From 66cba8c3e281a06eedbdede7272b733c01170757 Mon Sep 17 00:00:00 2001 From: Aolin Date: Thu, 29 Feb 2024 17:48:31 +0800 Subject: [PATCH] This is an automated cherry-pick of #16612 Signed-off-by: ti-chi-bot --- ...-guide-sample-application-nodejs-prisma.md | 8 +- ...dev-guide-sample-application-ruby-rails.md | 6 +- .../serverless-driver-kysely-example.md | 299 ++++++++++++++++++ .../serverless-driver-prisma-example.md | 219 +++++++++++++ 4 files changed, 527 insertions(+), 5 deletions(-) create mode 100644 tidb-cloud/serverless-driver-kysely-example.md create mode 100644 tidb-cloud/serverless-driver-prisma-example.md diff --git a/develop/dev-guide-sample-application-nodejs-prisma.md b/develop/dev-guide-sample-application-nodejs-prisma.md index 1c482f8167989..06bc0cfe6ce07 100644 --- a/develop/dev-guide-sample-application-nodejs-prisma.md +++ b/develop/dev-guide-sample-application-nodejs-prisma.md @@ -100,7 +100,11 @@ Connect to your TiDB cluster depending on the TiDB deployment option you've sele 6. Edit the `.env` file, set up the environment variable `DATABASE_URL` as follows, replace the corresponding placeholders `{}` with connection parameters on the connection dialog: ```dotenv +<<<<<<< HEAD DATABASE_URL=mysql://{user}:{password}@{host}:4000/test?sslaccept=strict +======= + DATABASE_URL='{connection_string}' +>>>>>>> 528dc73dc2 (develop: update env file code examples (#16612)) ``` > **Note** @@ -137,7 +141,7 @@ Connect to your TiDB cluster depending on the TiDB deployment option you've sele 5. Edit the `.env` file, set up the environment variable `DATABASE_URL` as follows, replace the corresponding placeholders `{}` with connection parameters on the connection dialog: ```dotenv - DATABASE_URL=mysql://{user}:{password}@{host}:4000/test?sslaccept=strict&sslcert={downloaded_ssl_ca_path} + DATABASE_URL='mysql://{user}:{password}@{host}:4000/test?sslaccept=strict&sslcert={downloaded_ssl_ca_path}' ``` > **Note** @@ -166,7 +170,7 @@ Connect to your TiDB cluster depending on the TiDB deployment option you've sele 2. Edit the `.env` file, set up the environment variable `DATABASE_URL` as follows, replace the corresponding placeholders `{}` with connection parameters of your TiDB cluster: ```dotenv - DATABASE_URL=mysql://{user}:{password}@{host}:4000/test + DATABASE_URL='mysql://{user}:{password}@{host}:4000/test' ``` If you are running TiDB locally, the default host address is `127.0.0.1`, and the password is empty. diff --git a/develop/dev-guide-sample-application-ruby-rails.md b/develop/dev-guide-sample-application-ruby-rails.md index 4ae72881f2b18..841ab79239ba4 100644 --- a/develop/dev-guide-sample-application-ruby-rails.md +++ b/develop/dev-guide-sample-application-ruby-rails.md @@ -97,7 +97,7 @@ Connect to your TiDB cluster depending on the TiDB deployment option you've sele 6. Edit the `.env` file, set up the `DATABASE_URL` environment variable as follows, and copy the connection string from the connection dialog as the variable value. ```dotenv - DATABASE_URL=mysql2://{user}:{password}@{host}:{port}/{database_name}?ssl_mode=verify_identity + DATABASE_URL='mysql2://{user}:{password}@{host}:{port}/{database_name}?ssl_mode=verify_identity' ``` > **Note** @@ -126,7 +126,7 @@ Connect to your TiDB cluster depending on the TiDB deployment option you've sele 5. Edit the `.env` file, set up the `DATABASE_URL` environment variable as follows, copy the connection string from the connection dialog as the variable value, and set the `sslca` query parameter to the file path of the CA certificate downloaded from the connection dialog: ```dotenv - DATABASE_URL=mysql2://{user}:{password}@{host}:{port}/{database}?ssl_mode=verify_identity&sslca=/path/to/ca.pem + DATABASE_URL='mysql2://{user}:{password}@{host}:{port}/{database}?ssl_mode=verify_identity&sslca=/path/to/ca.pem' ``` > **Note** @@ -149,7 +149,7 @@ Connect to your TiDB cluster depending on the TiDB deployment option you've sele 2. Edit the `.env` file, set up the `DATABASE_URL` environment variable as follows, and replace the `{user}`, `{password}`, `{host}`, `{port}`, and `{database}` with your own TiDB connection information: ```dotenv - DATABASE_URL=mysql2://{user}:{password}@{host}:{port}/{database} + DATABASE_URL='mysql2://{user}:{password}@{host}:{port}/{database}' ``` If you are running TiDB locally, the default host address is `127.0.0.1`, and the password is empty. diff --git a/tidb-cloud/serverless-driver-kysely-example.md b/tidb-cloud/serverless-driver-kysely-example.md new file mode 100644 index 0000000000000..ded6989ccf6af --- /dev/null +++ b/tidb-cloud/serverless-driver-kysely-example.md @@ -0,0 +1,299 @@ +--- +title: TiDB Cloud Serverless Driver Kysely Tutorial +summary: Learn how to use TiDB Cloud serverless driver with Kysely. +--- + +# TiDB Cloud Serverless Driver Kysely Tutorial + +[Kysely](https://kysely.dev/docs/intro) is a type-safe and autocompletion-friendly TypeScript SQL query builder. TiDB Cloud offers [@tidbcloud/kysely](https://github.com/tidbcloud/kysely), enabling you to use Kysely over HTTPS with [TiDB Cloud serverless driver](/tidb-cloud/serverless-driver.md). Compared with the traditional TCP way, [@tidbcloud/kysely](https://github.com/tidbcloud/kysely) brings the following benefits: + +- Better performance in serverless environments. +- Ability to use Kysely in edge environments. + +This tutorial describes how to use TiDB Cloud serverless driver with Kysely in Node.js environments and edge environments. + +## Use TiDB Cloud Kysely dialect in Node.js environments + +This section describes how to use TiDB Cloud serverless driver with Kysely in Node.js environments. + +### Before you begin + +To complete this tutorial, you need the following: + +- [Node.js](https://nodejs.org/en) >= 18.0.0. +- [npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) or your preferred package manager. +- A TiDB Serverless cluster. If you don't have any, you can [create a TiDB Serverless cluster](/develop/dev-guide-build-cluster-in-cloud.md). + +### Step 1. Create a project + +1. Create a project named `kysely-node-example`: + + ``` + mkdir kysely-node-example + cd kysely-node-example + ``` + +2. Install the `kysely`, `@tidbcloud/kysely`, and `@tidbcloud/serverless` packages: + + ``` + npm install kysely @tidbcloud/kysely @tidbcloud/serverless + ``` + +3. In the root directory of your project, locate the `package.json` file, and then specify the ES module by adding `type: "module"` to the file: + + ```json + { + "type": "module", + "dependencies": { + "@tidbcloud/kysely": "^0.0.4", + "@tidbcloud/serverless": "^0.0.7", + "kysely": "^0.26.3", + } + } + ``` + +4. In the root directory of your project, add a `tsconfig.json` file to define the TypeScript compiler options. Here is an example file: + + ```json + { + "compilerOptions": { + "module": "ES2022", + "target": "ES2022", + "moduleResolution": "node", + "strict": false, + "declaration": true, + "outDir": "dist", + "removeComments": true, + "allowJs": true, + "esModuleInterop": true, + "resolveJsonModule": true + } + } + ``` + +### Step 2. Set the environment + +1. On the overview page of your TiDB Serverless cluster, click **Connect** in the upper-right corner, and then get the connection string for your database from the displayed dialog. The connection string looks like this: + + ``` + mysql://[username]:[password]@[host]/[database] + ``` + +2. Set the environment variable `DATABASE_URL` in your local environment. For example, in Linux or macOS, you can run the following command: + + ```bash + export DATABASE_URL='mysql://[username]:[password]@[host]/[database]' + ``` + +### Step 3. Use Kysely to query data + +1. Create a table in your TiDB Serverless cluster and insert some data. + + You can use [Chat2Query in the TiDB Cloud console](/tidb-cloud/explore-data-with-chat2query.md) to execute SQL statements. Here is an example: + + ```sql + CREATE TABLE `test`.`person` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `name` varchar(255) NULL DEFAULT NULL, + `gender` enum('male','female') NULL DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE + ); + + insert into test.person values (1,'pingcap','male') + ``` + +2. In the root directory of your project, create a file named `hello-word.ts` and add the following code: + + ```ts + import { Kysely,GeneratedAlways,Selectable } from 'kysely' + import { TiDBServerlessDialect } from '@tidbcloud/kysely' + + // Types + interface Database { + person: PersonTable + } + + interface PersonTable { + id: GeneratedAlways + name: string + gender: "male" | "female" + } + + // Dialect + const db = new Kysely({ + dialect: new TiDBServerlessDialect({ + url: process.env.DATABASE_URL + }), + }) + + // Simple Querying + type Person = Selectable + export async function findPeople(criteria: Partial = {}) { + let query = db.selectFrom('person') + + if (criteria.name){ + query = query.where('name', '=', criteria.name) + } + + return await query.selectAll().execute() + } + + console.log(await findPeople()) + ``` + +### Step 4. Run the Typescript code + +1. Install `ts-node` to transform TypeScript into JavaScript, and then install `@types/node` to provide TypeScript type definitions for Node.js. + + ``` + npm install -g ts-node + npm i --save-dev @types/node + ``` + +2. Run the Typescript code with the following command: + + ``` + ts-node --esm hello-world.ts + ``` + +## Use TiDB Cloud Kysely dialect in edge environments + +This section takes the TiDB Cloud Kysely dialect in Vercel Edge Function as an example. + +### Before you begin + +To complete this tutorial, you need the following: + +- A [Vercel](https://vercel.com/docs) account that provides edge environment. +- [npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) or your preferred package manager. +- A TiDB Serverless cluster. If you don't have any, you can [create a TiDB Serverless cluster](/develop/dev-guide-build-cluster-in-cloud.md). + +### Step 1. Create a project + +1. Install the Vercel CLI: + + ``` + npm i -g vercel@latest + ``` + +2. Create a [Next.js](https://nextjs.org/) project called `kysely-example` using the following terminal commands: + + ``` + npx create-next-app@latest kysely-example --ts --no-eslint --tailwind --no-src-dir --app --import-alias "@/*" + cd kysely-example + ``` + +3. Install the `kysely`, `@tidbcloud/kysely`, and `@tidbcloud/serverless` packages: + + ``` + npm install kysely @tidbcloud/kysely @tidbcloud/serverless + ``` + +### Step 2. Set the environment + +On the overview page of your TiDB Serverless cluster, click **Connect** in the upper-right corner, and then get the connection string for your database from the displayed dialog. The connection string looks like this: + +``` +mysql://[username]:[password]@[host]/[database] +``` + +### Step 3. Create an edge function + +1. Create a table in your TiDB Serverless cluster and insert some data. + + You can use [Chat2Query in the TiDB Cloud console](/tidb-cloud/explore-data-with-chat2query.md) to execute SQL statements. Here is an example: + + ```sql + CREATE TABLE `test`.`person` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `name` varchar(255) NULL DEFAULT NULL, + `gender` enum('male','female') NULL DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE + ); + + insert into test.person values (1,'pingcap','male') + ``` + +2. In the `app` directory of your project, create a file `/api/edge-function-example/route.ts` and add the following code: + + ```ts + import { NextResponse } from 'next/server'; + import type { NextRequest } from 'next/server'; + import { Kysely,GeneratedAlways,Selectable } from 'kysely' + import { TiDBServerlessDialect } from '@tidbcloud/kysely' + + export const runtime = 'edge'; + + // Types + interface Database { + person: PersonTable + } + + interface PersonTable { + id: GeneratedAlways + name: string + gender: "male" | "female" | "other" + } + + // Dialect + const db = new Kysely({ + dialect: new TiDBServerlessDialect({ + url: process.env.DATABASE_URL + }), + }) + + // Query + type Person = Selectable + async function findPeople(criteria: Partial = {}) { + let query = db.selectFrom('person') + + if (criteria.name){ + query = query.where('name', '=', criteria.name) + } + + return await query.selectAll().execute() + } + + export async function GET(request: NextRequest) { + + const searchParams = request.nextUrl.searchParams + const query = searchParams.get('query') + + let response = null; + if (query) { + response = await findPeople({name: query}) + } else { + response = await findPeople() + } + + return NextResponse.json(response); + } + ``` + + The preceding code accepts a query parameter `query` and returns the result of the query. If the query parameter is not provided, it returns all records in the `person` table. + +3. Test your code locally: + + ``` + export DATABASE_URL='mysql://[username]:[password]@[host]/[database]' + next dev + ``` + +4. Navigate to `http://localhost:3000/api/edge-function-example` to get the response from your route. + +### Step 4. Deploy your code to Vercel + +1. Deploy your code to Vercel with the `DATABASE_URL` environment variable: + + ``` + vercel -e DATABASE_URL='mysql://[username]:[password]@[host]/[database]' --prod + ``` + + After the deployment is complete, you will get the URL of your project. + +2. Navigate to the `${Your-URL}/api/edge-function-example` page to get the response from your route. + +## What's next + +- Learn more about [Kysely](https://kysely.dev/docs/intro) and [@tidbcloud/kysely](https://github.com/tidbcloud/kysely) +- Learn how to [integrate TiDB Cloud with Vercel](/tidb-cloud/integrate-tidbcloud-with-vercel.md) \ No newline at end of file diff --git a/tidb-cloud/serverless-driver-prisma-example.md b/tidb-cloud/serverless-driver-prisma-example.md new file mode 100644 index 0000000000000..49b3ffd9a7c88 --- /dev/null +++ b/tidb-cloud/serverless-driver-prisma-example.md @@ -0,0 +1,219 @@ +--- +title: TiDB Cloud Serverless Driver Prisma Tutorial +summary: Learn how to use TiDB Cloud serverless driver with Prisma ORM. +--- + +# TiDB Cloud Serverless Driver Prisma Tutorial + +[Prisma](https://www.prisma.io/docs) is an open source next-generation ORM (Object-Relational Mapping) that helps developers interact with their database in an intuitive, efficient, and safe way. TiDB Cloud offers [@tidbcloud/prisma-adapter](https://github.com/tidbcloud/prisma-adapter), enabling you to use [Prisma Client](https://www.prisma.io/docs/concepts/components/prisma-client) over HTTPS with [TiDB Cloud serverless driver](/tidb-cloud/serverless-driver.md). Compared with the traditional TCP way, [@tidbcloud/prisma-adapter](https://github.com/tidbcloud/prisma-adapter) brings the following benefits: + +- Better performance in serverless environments +- Possibility of using Prisma client in the edge environments (see [#21394](https://github.com/prisma/prisma/issues/21394) for more information) + +This tutorial describes how to use TiDB Cloud serverless driver with the Prisma adapter. + +## Use the Prisma adapter in Node.js environments + +### Before you begin + +To complete this tutorial, you need the following: + +- [Node.js](https://nodejs.org/en) >= 18.0.0. +- [npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) or your preferred package manager. +- A TiDB Serverless cluster. If you don't have any, you can [create a TiDB Serverless cluster](/develop/dev-guide-build-cluster-in-cloud.md). + +### Step 1. Create a project + +1. Create a project named `prisma-example`: + + ``` + mkdir prisma-example + cd prisma-example + ``` + +2. Install the `@tidbcloud/prisma-adapter` driver adapter, the `@tidbcloud/serverless` serverless driver, and the Prisma CLI. + + The following commands use npm as the package manager. Executing `npm install @tidbcloud/serverless` will create a `node_modules` directory and a `package.json` file in your project directory. + + ``` + npm install @tidbcloud/prisma-adapter + npm install @tidbcloud/serverless + npm install prisma --save-dev + ``` + +3. In the `package.json` file, specify the ES module by adding `type: "module"`: + + ```json + { + "type": "module", + "dependencies": { + "@prisma/client": "^5.5.2", + "@tidbcloud/prisma-adapter": "^5.5.2", + "@tidbcloud/serverless": "^0.0.7" + }, + "devDependencies": { + "prisma": "^5.5.2" + } + } + ``` + +### Step 2. Set the environment + +1. On the overview page of your TiDB Serverless cluster, click **Connect** in the upper-right corner, and then get the connection string for your database from the displayed dialog. The connection string looks like this: + + ``` + mysql://[username]:[password]@[host]:4000/[database]?sslaccept=strict + ``` + +2. In the root directory of your project, create a file named `.env`, define an environment variable named `DATABASE_URL` as follows, and then replace the placeholders `[]` in this variable with the corresponding parameters in the connection string. + + ```dotenv + DATABASE_URL='mysql://[username]:[password]@[host]:4000/[database]?sslaccept=strict' + ``` + + > **Note:** + > + > `@tidbcloud/prisma-adapter` only supports the use of Prisma Client over HTTPS. For [Prisma Migrate](https://www.prisma.io/docs/concepts/components/prisma-migrate) and [Prisma Introspection](https://www.prisma.io/docs/concepts/components/introspection), the traditional TCP connection is still used. If you only need to use Prisma Client, you can simplify `DATABASE_URL` to the `mysql://[username]:[password]@[host]/[database]` format. + +3. Install `dotenv` to load the environment variable from the `.env` file: + + ``` + npm install dotenv + ``` + +### Step 3. Define your schema + +1. Create a file named `schema.prisma`. In this file, include the `driverAdapters` preview feature and reference the `DATABASE_URL` environment variable. Here is an example file: + + ``` + // schema.prisma + generator client { + provider = "prisma-client-js" + previewFeatures = ["driverAdapters"] + } + + datasource db { + provider = "mysql" + url = env("DATABASE_URL") + } + ``` + +2. In the `schema.prisma` file, define a data model for your database table. In the following example, a data model named `user` is defined. + + ``` + // schema.prisma + generator client { + provider = "prisma-client-js" + previewFeatures = ["driverAdapters"] + } + + datasource db { + provider = "mysql" + url = env("DATABASE_URL") + } + + // define a data model according to your database table + model user { + id Int @id @default(autoincrement()) + email String? @unique(map: "uniq_email") @db.VarChar(255) + name String? @db.VarChar(255) + } + ``` + +3. Synchronize your database with the Prisma schema. You can either manually create the database tables in your TiDB Serverless cluster or use the Prisma CLI to create them automatically as follows: + + ``` + npx prisma db push + ``` + + This command will create the `user` table in your TiDB Serverless cluster through the traditional TCP connection, rather than through the HTTPS connection using `@tidbcloud/prisma-adapter`. This is because it uses the same engine as Prisma Migrate. For more information about this command, see [Prototype your schema](https://www.prisma.io/docs/concepts/components/prisma-migrate/db-push). + +4. Generate Prisma Client: + + ``` + npx prisma generate + ``` + + This command will generate Prisma Client based on the Prisma schema. + +### Step 4. Execute CRUD operations + +1. Create a file named `hello-word.js` and add the following code to initialize Prisma Client: + + ```js + import { connect } from '@tidbcloud/serverless'; + import { PrismaTiDBCloud } from '@tidbcloud/prisma-adapter'; + import { PrismaClient } from '@prisma/client'; + import dotenv from 'dotenv'; + + // setup + dotenv.config(); + const connectionString = `${process.env.DATABASE_URL}`; + + // Initialize Prisma Client + const connection = connect({ url: connectionString }); + const adapter = new PrismaTiDBCloud(connection); + const prisma = new PrismaClient({ adapter }); + ``` + +2. Execute some CRUD operations with Prisma Client. For example: + + ```js + // Insert + const user = await prisma.user.create({ + data: { + email: 'test@pingcap.com', + name: 'test', + }, + }) + console.log(user) + + // Query + console.log(await prisma.user.findMany()) + + // Delete + await prisma.user.delete({ + where: { + id: user.id, + }, + }) + ``` + +3. Execute some transaction operations with Prisma Client. For example: + + ```js + const createUser1 = prisma.user.create({ + data: { + email: 'test1@pingcap.com', + name: 'test1', + }, + }) + const createUser2 = prisma.user.create({ + data: { + email: 'test1@pingcap.com', + name: 'test1', + }, + }) + const createUser3 = prisma.user.create({ + data: { + email: 'test2@pingcap.com', + name: 'test2', + }, + }) + + try { + await prisma.$transaction([createUser1, createUser2]) // Operations fail because the email address is duplicated + } catch (e) { + console.log(e) + } + + try { + await prisma.$transaction([createUser2, createUser3]) // Operations success because the email address is unique + } catch (e) { + console.log(e) + } + ``` + +## Use the Prisma adapter in edge environments + +Currently, `@tidbcloud/prisma-adapter` is not compatible with edge environments such as Vercel Edge Function and Cloudflare Workers. However, there are plans to support these environments. For more information, see [#21394](https://github.com/prisma/prisma/issues/21394). \ No newline at end of file