Skip to content

Commit

Permalink
feat: JS connectors integration (#4097)
Browse files Browse the repository at this point in the history
* Renames and restructure

* Use proxy in `JsQueryable::is_healthy`

* Change neon and planetscale drivers to  use a promise for the version

The promise executes aynchrounsly on constructor, but it's awaited whenever the version is required, particularly to provide consistent health information. Otherwise isHealthy would be returning false, while the promise hasn't resolved yet.

* feat: add child parent relation migration

* feat(js-connectors): add support for transactions in PlanetScale, without touching Rust

* chore: apply renames as in #4085

* chore: use switch case syntax

* chore: add hard error if we detect intertwine transaction

* feat(js-connectors): adopt Rust's "performIO" pattern to simplify isHealthy() and version()

* feat(js-connectors): implement "is_healthy()"

* feat(js-connectors): add data conversions for neon

* feat(js-connector): add common ConnectorConfig for PlanetScale and Neon

* feat(js-connector): update type mapping in neon, use common ConnectorConfig

* feat(js-connector): use common ConnectorConfig

* test(js-connector): split + centralise tests for PlanetScale and Neon, enable "@withFlavor" test decorator

* chore: update README.md

* chore: fix typo

* chore: fix typo

* chore: restore PlanetScale transactions

* fix: address review comments

* feat: simplify neon/planetscale data-type conversions

---------

Co-authored-by: Miguel Fernandez <[email protected]>
  • Loading branch information
jkomyno and miguelff authored Aug 3, 2023
1 parent 4ff176d commit 8f598f6
Show file tree
Hide file tree
Showing 19 changed files with 1,485 additions and 897 deletions.
31 changes: 18 additions & 13 deletions query-engine/js-connectors/smoke-test-js/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# @prisma/smoke-test-js

This is a playground for testing the `libquery` client with the experimental Node.js drivers.
It contains a subset of `@prisma/client`, plus a handy [`index.ts`](./src/index.ts) file with a `main` function.
It contains a subset of `@prisma/client`, plus some handy executable smoke tests:
- [`./src/planetscale.ts`](./src/planetscale.ts)
- [`./src/neon.ts`](./src/neon.ts)

## How to setup

Expand All @@ -10,7 +12,7 @@ We assume Node.js `v18.16.1`+ is installed.
- Create a `.envrc` starting from `.envrc.example`, and fill in the missing values following the given template
- Install Node.js dependencies via
```bash
npm i
pnpm i
```

### PlanetScale
Expand All @@ -20,9 +22,10 @@ We assume Node.js `v18.16.1`+ is installed.
- Create a new `shadow` database branch. Repeat the steps above (selecting the `shadow` branch instead of `main`), and paste the generated URL in the `JS_PLANETSCALE_SHADOW_DATABASE_URL` environment variable in `.envrc`.

In the current directory:
- Run `cp prisma/mysql/schema.prisma prisma/` to use the MySQL schema. Change the provider to `mysql`.
- Run `prisma migrate reset` to populate the remote PlanetScale database with the "smoke test" data.
- Change the `provider` name in [./prisma/schema.prisma](./prisma/schema.prisma) from `mysql` to `@prisma/planetscale`.
- Set the provider in [./prisma/mysql-planetscale/schema.prisma](./prisma/mysql-planetscale/schema.prisma) to `mysql`.
- Run `npx prisma db push --schema ./prisma/mysql-planetscale/schema.prisma`
- Run `npx prisma migrate deploy --schema ./prisma/mysql-planetscale/schema.prisma`
- Set the provider in [./prisma/mysql-planetscale/schema.prisma](./prisma/mysql-planetscale/schema.prisma) to `@prisma/planetscale`.

Note: you used to be able to run these Prisma commands without changing the provider name, but [#4074](https://github.com/prisma/prisma-engines/pull/4074) changed that (see https://github.com/prisma/prisma-engines/pull/4074#issuecomment-1649942475).

Expand All @@ -32,28 +35,30 @@ Note: you used to be able to run these Prisma commands without changing the prov
- Paste the connection string to `JS_NEON_DATABASE_URL`. Create a shadow branch and repeat the step above, paste the connection string to `JS_NEON_SHADOW_DATABASE_URL`.

In the current directory:
- Run `cp prisma/postgresql/schema.prisma prisma/` to use the PostgreSQL schema. Change the provider to `postgresql`.
- Run `prisma migrate reset` to populate the remote PlanetScale database with the "smoke test" data.
- Change the `provider` name in [./prisma/schema.prisma](./prisma/schema.prisma) from `postgresql` to `@prisma/neon`.
- Set the provider in [./prisma/postgres-neon/schema.prisma](./prisma/postgres-neon/schema.prisma) to `postgres`.
- Run `npx prisma db push --schema ./prisma/postgres-neon/schema.prisma`
- Run `npx prisma migrate deploy --schema ./prisma/postgres-neon/schema.prisma`
- Set the provider in [./prisma/postgres-neon/schema.prisma](./prisma/postgres-neon/schema.prisma) to `@prisma/neon`.

## How to use

In the current directory:
- Run `cargo build -p query-engine-node-api` to compile the `libquery` Query Engine
- Run `npm run planetscale` to run smoke tests against the PlanetScale database
- Run `pnpm planetscale` to run smoke tests against the PlanetScale database
- Run `pnpm neon` to run smoke tests against the PlanetScale database

## How to test

There is no automatic test. However, [./src/index.ts](./src/index.ts) includes a pipeline you can use to interactively experiment with the new Query Engine.
There is no automatic test. However, [./src/planetscale.ts](./src/planetscale.ts) includes a pipeline you can use to interactively experiment with the new Query Engine.

In particular, the pipeline steps are currently the following:
In particular, the pipeline steps are currently the following (in the case of PlanetScale):

- Define `db`, a class instance wrapper around the `@planetscale/database` JS driver for PlanetScale
- Define `db`, a class instance wrapper around the `@planetscale/database` serverless driver for PlanetScale
- Define `nodejsFnCtx`, an object exposing (a)sync "Queryable" functions that can be safely passed to Rust, so that it can interact with `db`'s class methods
- Load the *debug* version of `libquery`, i.e., the compilation artifact of the `query-engine-node-api` crate
- Define `engine` via the `QueryEngine` constructor exposed by Rust
- Initialize the connector via `engine.connect()`
- Run a Prisma `findMany` query via the JSON protocol, according to the Prisma schema in [./prisma/schema.prisma](./prisma/schema.prisma), storing the result in `resultSet`
- Run a Prisma `findMany` query via the JSON protocol, according to the Prisma schema in [./prisma/mysql-planetscale/schema.prisma](./prisma/mysql-planetscale/schema.prisma), storing the result in `resultSet`
- Release the connector via `engine.disconnect()`
- Attempt a reconnection (useful to catch possible panics in the implementation)
- Close the database connection via `nodejsFnCtx`
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
INSERT INTO type_test (
tinyint_column,
smallint_column,
mediumint_column,
int_column,
bigint_column,
float_column,
double_column,
decimal_column,
boolean_column,
bit_column,
char_column,
varchar_column,
text_column,
date_column,
time_column,
year_column,
datetime_column,
timestamp_column,
json_column,
enum_column,
binary_column,
varbinary_column,
blob_column,
set_column
) VALUES (
127, -- tinyint
32767, -- smallint
8388607, -- mediumint
2147483647, -- int
9223372036854775807, -- bigint
3.402823466, -- float
1.7976931348623157, -- double
99999999.99, -- decimal
TRUE, -- boolean
1, -- bit
'c', -- char
'Sample varchar', -- varchar
'This is a long text...', -- text
'2023-07-24', -- date
'23:59:59', -- time
2023, -- year
'2023-07-24 23:59:59', -- datetime
'2023-07-24 23:59:59', -- timestamp
'{"key": "value"}', -- json
'value3', -- enum
0x4D7953514C, -- binary
0x48656C6C6F20, -- varbinary
_binary 'binary', -- blob
'option1,option3' -- set
);
Original file line number Diff line number Diff line change
@@ -1,20 +1,14 @@
generator client {
provider = "prisma-client-js"
// previewFeatures = ["jsConnectors"]
}

datasource db {
provider = "@prisma/planetscale"
// provider = "mysql"
url = env("JS_PLANETSCALE_DATABASE_URL")
shadowDatabaseUrl = env("JS_PLANETSCALE_SHADOW_DATABASE_URL")
}

model some_users {
id Int @id @default(autoincrement())
firstname String @db.VarChar(32)
lastname String @db.VarChar(32)
}

model type_test {
id Int @id @default(autoincrement())
tinyint_column Int @db.TinyInt
Expand Down Expand Up @@ -78,3 +72,22 @@ enum type_test_enum_column_null {
value2
value3
}

model Child {
c String @unique
c_1 String
c_2 String
parentId String? @unique
non_unique String?
id String @id
@@unique([c_1, c_2])
}

model Parent {
p String @unique
p_1 String
p_2 String
non_unique String?
id String @id
@@unique([p_1, p_2])
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
INSERT INTO type_test (
smallint_column,
int_column,
bigint_column,
float_column,
double_column,
decimal_column,
boolean_column,
char_column,
varchar_column,
text_column,
date_column,
time_column,
datetime_column,
timestamp_column,
json_column,
enum_column
) VALUES (
32767, -- smallint
2147483647, -- int
9223372036854775807, -- bigint
3.402823466, -- float
1.7976931348623157, -- double
99999999.99, -- decimal
TRUE, -- boolean
'c', -- char
'Sample varchar', -- varchar
'This is a long text...', -- text
'2023-07-24', -- date
'23:59:59', -- time
'2023-07-24 23:59:59', -- datetime
'2023-07-24 23:59:59', -- timestamp
'{"key": "value"}', -- json
'value3' -- enum
);
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,11 @@ generator client {

datasource db {
provider = "@prisma/neon"
// provider = "postgres"
url = env("JS_NEON_DATABASE_URL")
shadowDatabaseUrl = env("JS_NEON_SHADOW_DATABASE_URL")
}

model some_users {
id Int @id @default(autoincrement())
firstname String @db.VarChar(32)
lastname String @db.VarChar(32)
}

model type_test {
id Int @id @default(autoincrement())
smallint_column Int @db.SmallInt
Expand Down Expand Up @@ -62,3 +57,22 @@ enum type_test_enum_column_null {
value2
value3
}

model Child {
c String @unique
c_1 String
c_2 String
parentId String? @unique
non_unique String?
id String @id
@@unique([c_1, c_2])
}

model Parent {
p String @unique
p_1 String
p_2 String
non_unique String?
id String @id
@@unique([p_1, p_2])
}
64 changes: 0 additions & 64 deletions query-engine/js-connectors/smoke-test-js/prisma/schema.prisma

This file was deleted.

Loading

0 comments on commit 8f598f6

Please sign in to comment.