@lunarhue/expo-wa-sqlite 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +9 -0
- package/.lovely-docs.yaml +11 -0
- package/LICENSE +21 -0
- package/demo/next.config.mjs +17 -0
- package/demo/package.json +26 -0
- package/demo/scripts/copy-wasm.mjs +14 -0
- package/demo/src/app/layout.tsx +16 -0
- package/demo/src/app/page.tsx +16 -0
- package/demo/src/app/todos.tsx +118 -0
- package/demo/src/db/schema.ts +7 -0
- package/demo/tsconfig.json +18 -0
- package/lovely-docs/drizzle-orm/arktype.md +113 -0
- package/lovely-docs/drizzle-orm/batch-api.md +35 -0
- package/lovely-docs/drizzle-orm/cache.md +145 -0
- package/lovely-docs/drizzle-orm/check-migrations.md +52 -0
- package/lovely-docs/drizzle-orm/column_types/mysql-column-types.md +76 -0
- package/lovely-docs/drizzle-orm/column_types/postgresql_column_types.md +314 -0
- package/lovely-docs/drizzle-orm/column_types/singlestore-column-types.md +171 -0
- package/lovely-docs/drizzle-orm/column_types/sqlite_column_types.md +132 -0
- package/lovely-docs/drizzle-orm/column_types.md +76 -0
- package/lovely-docs/drizzle-orm/common_patterns_&_recipes/case-insensitive-unique-email.md +113 -0
- package/lovely-docs/drizzle-orm/common_patterns_&_recipes/conditional-filters-in-query.md +69 -0
- package/lovely-docs/drizzle-orm/common_patterns_&_recipes/count-rows.md +76 -0
- package/lovely-docs/drizzle-orm/common_patterns_&_recipes/cursor-based-pagination.md +142 -0
- package/lovely-docs/drizzle-orm/common_patterns_&_recipes/d1_http_api_configuration.md +49 -0
- package/lovely-docs/drizzle-orm/common_patterns_&_recipes/decrementing-a-value.md +36 -0
- package/lovely-docs/drizzle-orm/common_patterns_&_recipes/empty-array-default-value.md +43 -0
- package/lovely-docs/drizzle-orm/common_patterns_&_recipes/full-text-search-with-generated-columns.md +73 -0
- package/lovely-docs/drizzle-orm/common_patterns_&_recipes/gel-auth-extension.md +89 -0
- package/lovely-docs/drizzle-orm/common_patterns_&_recipes/include-or-exclude-columns.md +51 -0
- package/lovely-docs/drizzle-orm/common_patterns_&_recipes/incrementing-a-value.md +36 -0
- package/lovely-docs/drizzle-orm/common_patterns_&_recipes/limit-offset-pagination.md +104 -0
- package/lovely-docs/drizzle-orm/common_patterns_&_recipes/mysql-local-setup.md +55 -0
- package/lovely-docs/drizzle-orm/common_patterns_&_recipes/point-datatype-psql.md +79 -0
- package/lovely-docs/drizzle-orm/common_patterns_&_recipes/postgis-geometry-point.md +115 -0
- package/lovely-docs/drizzle-orm/common_patterns_&_recipes/postgresql-full-text-search.md +150 -0
- package/lovely-docs/drizzle-orm/common_patterns_&_recipes/postgresql-local-setup.md +55 -0
- package/lovely-docs/drizzle-orm/common_patterns_&_recipes/seeding-with-option.md +69 -0
- package/lovely-docs/drizzle-orm/common_patterns_&_recipes/seeding-with-partially-exposed-schema.md +60 -0
- package/lovely-docs/drizzle-orm/common_patterns_&_recipes/select-parent-rows-with-at-least-one-related-child-row.md +74 -0
- package/lovely-docs/drizzle-orm/common_patterns_&_recipes/timestamp-default-value.md +93 -0
- package/lovely-docs/drizzle-orm/common_patterns_&_recipes/toggling-a-boolean-field.md +20 -0
- package/lovely-docs/drizzle-orm/common_patterns_&_recipes/update-many-with-different-values.md +50 -0
- package/lovely-docs/drizzle-orm/common_patterns_&_recipes/upsert.md +169 -0
- package/lovely-docs/drizzle-orm/common_patterns_&_recipes/vector-similarity-search.md +79 -0
- package/lovely-docs/drizzle-orm/common_patterns_&_recipes.md +787 -0
- package/lovely-docs/drizzle-orm/connect-aws-data-api-pg.md +47 -0
- package/lovely-docs/drizzle-orm/connect-bun-sql.md +35 -0
- package/lovely-docs/drizzle-orm/connect-bun-sqlite.md +42 -0
- package/lovely-docs/drizzle-orm/connect-cloudflare-d1.md +61 -0
- package/lovely-docs/drizzle-orm/connect-cloudflare-do.md +86 -0
- package/lovely-docs/drizzle-orm/connect-neon.md +72 -0
- package/lovely-docs/drizzle-orm/connect-nile.md +84 -0
- package/lovely-docs/drizzle-orm/connect-pglite.md +39 -0
- package/lovely-docs/drizzle-orm/connect-planetscale.md +37 -0
- package/lovely-docs/drizzle-orm/connect-prisma-postgres.md +48 -0
- package/lovely-docs/drizzle-orm/connect-sqlite-cloud.md +29 -0
- package/lovely-docs/drizzle-orm/connect-supabase.md +45 -0
- package/lovely-docs/drizzle-orm/connect-tidb-serverless.md +35 -0
- package/lovely-docs/drizzle-orm/connect-turso-database.md +28 -0
- package/lovely-docs/drizzle-orm/connect-turso.md +60 -0
- package/lovely-docs/drizzle-orm/connect-vercel-postgres.md +37 -0
- package/lovely-docs/drizzle-orm/connect-xata.md +29 -0
- package/lovely-docs/drizzle-orm/custom-migrations.md +40 -0
- package/lovely-docs/drizzle-orm/custom-types.md +137 -0
- package/lovely-docs/drizzle-orm/database-connection-overview.md +89 -0
- package/lovely-docs/drizzle-orm/database_setup_guides/bun-sql-existing.md +59 -0
- package/lovely-docs/drizzle-orm/database_setup_guides/bun-sqlite-existing.md +48 -0
- package/lovely-docs/drizzle-orm/database_setup_guides/bun-sqlite-new.md +34 -0
- package/lovely-docs/drizzle-orm/database_setup_guides/d1-new.md +74 -0
- package/lovely-docs/drizzle-orm/database_setup_guides/expo-sqlite-setup.md +169 -0
- package/lovely-docs/drizzle-orm/database_setup_guides/gel-existing-project.md +81 -0
- package/lovely-docs/drizzle-orm/database_setup_guides/get-started-bun-sql.md +29 -0
- package/lovely-docs/drizzle-orm/database_setup_guides/getting_started_with_gel.md +85 -0
- package/lovely-docs/drizzle-orm/database_setup_guides/mysql-existing-project.md +32 -0
- package/lovely-docs/drizzle-orm/database_setup_guides/mysql-setup.md +43 -0
- package/lovely-docs/drizzle-orm/database_setup_guides/neon-existing-project.md +39 -0
- package/lovely-docs/drizzle-orm/database_setup_guides/neon-setup.md +45 -0
- package/lovely-docs/drizzle-orm/database_setup_guides/nile-existing-project.md +66 -0
- package/lovely-docs/drizzle-orm/database_setup_guides/nile-setup.md +59 -0
- package/lovely-docs/drizzle-orm/database_setup_guides/op-sqlite_setup_guide.md +135 -0
- package/lovely-docs/drizzle-orm/database_setup_guides/pglite-existing-project.md +67 -0
- package/lovely-docs/drizzle-orm/database_setup_guides/pglite-setup.md +33 -0
- package/lovely-docs/drizzle-orm/database_setup_guides/planetscale-existing-project.md +70 -0
- package/lovely-docs/drizzle-orm/database_setup_guides/planetscale-setup.md +46 -0
- package/lovely-docs/drizzle-orm/database_setup_guides/postgresql-existing-project.md +57 -0
- package/lovely-docs/drizzle-orm/database_setup_guides/postgresql-setup.md +44 -0
- package/lovely-docs/drizzle-orm/database_setup_guides/singlestore-existing-project.md +22 -0
- package/lovely-docs/drizzle-orm/database_setup_guides/singlestore-setup.md +37 -0
- package/lovely-docs/drizzle-orm/database_setup_guides/sqlite-cloud-existing-project.md +52 -0
- package/lovely-docs/drizzle-orm/database_setup_guides/sqlite-cloud-setup.md +53 -0
- package/lovely-docs/drizzle-orm/database_setup_guides/sqlite-durable-objects-setup.md +163 -0
- package/lovely-docs/drizzle-orm/database_setup_guides/sqlite-existing-project.md +36 -0
- package/lovely-docs/drizzle-orm/database_setup_guides/sqlite-new.md +28 -0
- package/lovely-docs/drizzle-orm/database_setup_guides/supabase-existing-project.md +32 -0
- package/lovely-docs/drizzle-orm/database_setup_guides/tidb-existing-project.md +25 -0
- package/lovely-docs/drizzle-orm/database_setup_guides/tidb-serverless-setup.md +41 -0
- package/lovely-docs/drizzle-orm/database_setup_guides/turso-database-existing.md +61 -0
- package/lovely-docs/drizzle-orm/database_setup_guides/turso-database-setup.md +60 -0
- package/lovely-docs/drizzle-orm/database_setup_guides/turso-existing.md +74 -0
- package/lovely-docs/drizzle-orm/database_setup_guides/turso-new.md +78 -0
- package/lovely-docs/drizzle-orm/database_setup_guides/vercel-postgres-existing-project.md +71 -0
- package/lovely-docs/drizzle-orm/database_setup_guides/vercel-postgres-setup.md +46 -0
- package/lovely-docs/drizzle-orm/database_setup_guides/xata-existing-project.md +32 -0
- package/lovely-docs/drizzle-orm/database_setup_guides/xata-new.md +30 -0
- package/lovely-docs/drizzle-orm/database_setup_guides.md +144 -0
- package/lovely-docs/drizzle-orm/delete.md +57 -0
- package/lovely-docs/drizzle-orm/drizzle-config-file.md +252 -0
- package/lovely-docs/drizzle-orm/drizzle-kit-up.md +43 -0
- package/lovely-docs/drizzle-orm/dynamic-query-building.md +68 -0
- package/lovely-docs/drizzle-orm/eslint-plugin.md +76 -0
- package/lovely-docs/drizzle-orm/expo-sqlite.md +101 -0
- package/lovely-docs/drizzle-orm/export.md +88 -0
- package/lovely-docs/drizzle-orm/faq.md +28 -0
- package/lovely-docs/drizzle-orm/filter-and-conditional-operators.md +169 -0
- package/lovely-docs/drizzle-orm/gel-setup.md +37 -0
- package/lovely-docs/drizzle-orm/generate.md +119 -0
- package/lovely-docs/drizzle-orm/generated-columns.md +128 -0
- package/lovely-docs/drizzle-orm/getting_started/database_integrations/drizzle-with-turso.md +159 -0
- package/lovely-docs/drizzle-orm/getting_started/database_integrations/drizzle_with_nile_database.md +195 -0
- package/lovely-docs/drizzle-orm/getting_started/database_integrations/neon_postgres_integration.md +157 -0
- package/lovely-docs/drizzle-orm/getting_started/database_integrations/supabase_integration.md +150 -0
- package/lovely-docs/drizzle-orm/getting_started/database_integrations/vercel-postgres-setup.md +152 -0
- package/lovely-docs/drizzle-orm/getting_started/database_integrations/xata_integration.md +143 -0
- package/lovely-docs/drizzle-orm/getting_started/database_integrations.md +117 -0
- package/lovely-docs/drizzle-orm/getting_started/edge_functions_integration/drizzle_with_vercel_edge_functions.md +220 -0
- package/lovely-docs/drizzle-orm/getting_started/edge_functions_integration/netlify_edge_functions_with_neon_postgres.md +120 -0
- package/lovely-docs/drizzle-orm/getting_started/edge_functions_integration/netlify_edge_functions_with_supabase.md +94 -0
- package/lovely-docs/drizzle-orm/getting_started/edge_functions_integration/supabase_edge_functions_integration.md +116 -0
- package/lovely-docs/drizzle-orm/getting_started/edge_functions_integration.md +63 -0
- package/lovely-docs/drizzle-orm/getting_started/todo_app_with_neon_postgres.md +323 -0
- package/lovely-docs/drizzle-orm/getting_started.md +443 -0
- package/lovely-docs/drizzle-orm/graphql.md +107 -0
- package/lovely-docs/drizzle-orm/http-proxy-driver.md +138 -0
- package/lovely-docs/drizzle-orm/indexes-constraints.md +135 -0
- package/lovely-docs/drizzle-orm/insert.mdx.md +118 -0
- package/lovely-docs/drizzle-orm/joins.md +145 -0
- package/lovely-docs/drizzle-orm/kit-overview.md +81 -0
- package/lovely-docs/drizzle-orm/migrate.md +54 -0
- package/lovely-docs/drizzle-orm/migration_guides/migrate-from-sequelize.md +335 -0
- package/lovely-docs/drizzle-orm/migration_guides/migrate-from-typeorm.md +317 -0
- package/lovely-docs/drizzle-orm/migration_guides/migrate_from_prisma_to_drizzle.md +258 -0
- package/lovely-docs/drizzle-orm/migration_guides.md +201 -0
- package/lovely-docs/drizzle-orm/migrations.md +50 -0
- package/lovely-docs/drizzle-orm/mysql-setup.md +51 -0
- package/lovely-docs/drizzle-orm/op-sqlite-setup.md +80 -0
- package/lovely-docs/drizzle-orm/overview.md +69 -0
- package/lovely-docs/drizzle-orm/postgresql-setup.md +71 -0
- package/lovely-docs/drizzle-orm/postgresql_extensions.md +93 -0
- package/lovely-docs/drizzle-orm/prepared-statements.md +77 -0
- package/lovely-docs/drizzle-orm/prisma-extension.md +46 -0
- package/lovely-docs/drizzle-orm/pull.md +134 -0
- package/lovely-docs/drizzle-orm/push.md +129 -0
- package/lovely-docs/drizzle-orm/queries-and-crud.md +72 -0
- package/lovely-docs/drizzle-orm/quick-start.md +63 -0
- package/lovely-docs/drizzle-orm/react-native-sqlite-setup.md +1 -0
- package/lovely-docs/drizzle-orm/read-replicas.md +66 -0
- package/lovely-docs/drizzle-orm/relational-queries.md +271 -0
- package/lovely-docs/drizzle-orm/relations.md +194 -0
- package/lovely-docs/drizzle-orm/release_notes/live-queries.md +27 -0
- package/lovely-docs/drizzle-orm/release_notes/pglite_driver_support.md +14 -0
- package/lovely-docs/drizzle-orm/release_notes/v0.11.0_release.md +139 -0
- package/lovely-docs/drizzle-orm/release_notes/v0.16.2_release_notes.md +86 -0
- package/lovely-docs/drizzle-orm/release_notes/v0.23.2_release.md +5 -0
- package/lovely-docs/drizzle-orm/release_notes/v0.27.2_-_unique_constraints_support.md +66 -0
- package/lovely-docs/drizzle-orm/release_notes/v0.28.0_release_notes.md +80 -0
- package/lovely-docs/drizzle-orm/release_notes/v0.28.1_release.md +7 -0
- package/lovely-docs/drizzle-orm/release_notes/v0.28.2_release_notes.md +18 -0
- package/lovely-docs/drizzle-orm/release_notes/v0.28.3_release_notes.md +48 -0
- package/lovely-docs/drizzle-orm/release_notes/v0.28.4_release.md +8 -0
- package/lovely-docs/drizzle-orm/release_notes/v0.28.5_release_notes.md +7 -0
- package/lovely-docs/drizzle-orm/release_notes/v0.28.6_release_notes.md +54 -0
- package/lovely-docs/drizzle-orm/release_notes/v0.29.0_release_notes.md +143 -0
- package/lovely-docs/drizzle-orm/release_notes/v0.29.1_release_notes.md +72 -0
- package/lovely-docs/drizzle-orm/release_notes/v0.29.2_release_notes.md +95 -0
- package/lovely-docs/drizzle-orm/release_notes/v0.29.3_release.md +7 -0
- package/lovely-docs/drizzle-orm/release_notes/v0.29.4_release_notes.md +40 -0
- package/lovely-docs/drizzle-orm/release_notes/v0.29.5_release_notes.md +69 -0
- package/lovely-docs/drizzle-orm/release_notes/v0.30.0_release_notes.md +31 -0
- package/lovely-docs/drizzle-orm/release_notes/v0.30.10_release.md +18 -0
- package/lovely-docs/drizzle-orm/release_notes/v0.30.1_release_notes.md +16 -0
- package/lovely-docs/drizzle-orm/release_notes/v0.30.2_release_notes.md +7 -0
- package/lovely-docs/drizzle-orm/release_notes/v0.30.3_release_notes.md +8 -0
- package/lovely-docs/drizzle-orm/release_notes/v0.30.5_release_notes.md +20 -0
- package/lovely-docs/drizzle-orm/release_notes/v0.30.7_release.md +5 -0
- package/lovely-docs/drizzle-orm/release_notes/v0.30.8_release_notes.md +36 -0
- package/lovely-docs/drizzle-orm/release_notes/v0.30.9_release.md +29 -0
- package/lovely-docs/drizzle-orm/release_notes/v0.31.0_release_notes.md +186 -0
- package/lovely-docs/drizzle-orm/release_notes/v0.31.2_tidb_cloud_serverless_support.md +16 -0
- package/lovely-docs/drizzle-orm/release_notes/v0.31.3_release.md +19 -0
- package/lovely-docs/drizzle-orm/release_notes/v0.31.4_release.md +1 -0
- package/lovely-docs/drizzle-orm/release_notes/v0.32.0_release_notes.md +136 -0
- package/lovely-docs/drizzle-orm/release_notes/v0.32.1_release_notes.md +15 -0
- package/lovely-docs/drizzle-orm/release_notes/v0.32.2_release.md +13 -0
- package/lovely-docs/drizzle-orm/release_notes/xata-http-driver-support.md +27 -0
- package/lovely-docs/drizzle-orm/release_notes.md +25 -0
- package/lovely-docs/drizzle-orm/rls.mdx.md +385 -0
- package/lovely-docs/drizzle-orm/schema-declaration.md +239 -0
- package/lovely-docs/drizzle-orm/schemas.md +63 -0
- package/lovely-docs/drizzle-orm/seed-generators.md +220 -0
- package/lovely-docs/drizzle-orm/seed-limitations.md +3 -0
- package/lovely-docs/drizzle-orm/seed-overview.md +155 -0
- package/lovely-docs/drizzle-orm/seed-versioning.md +85 -0
- package/lovely-docs/drizzle-orm/select.md +411 -0
- package/lovely-docs/drizzle-orm/sequences.md +62 -0
- package/lovely-docs/drizzle-orm/serverless-performance.md +21 -0
- package/lovely-docs/drizzle-orm/set-operations.md +127 -0
- package/lovely-docs/drizzle-orm/singlestore-setup.md +57 -0
- package/lovely-docs/drizzle-orm/sql-template.md +127 -0
- package/lovely-docs/drizzle-orm/sqlite-setup.md +65 -0
- package/lovely-docs/drizzle-orm/studio.md +47 -0
- package/lovely-docs/drizzle-orm/transactions.md +83 -0
- package/lovely-docs/drizzle-orm/type-helpers-and-utilities.md +160 -0
- package/lovely-docs/drizzle-orm/typebox.md +110 -0
- package/lovely-docs/drizzle-orm/update.md +79 -0
- package/lovely-docs/drizzle-orm/upgrade-to-0.21.0.md +40 -0
- package/lovely-docs/drizzle-orm/valibot.md +115 -0
- package/lovely-docs/drizzle-orm/views.md +135 -0
- package/lovely-docs/drizzle-orm/why-drizzle.md +66 -0
- package/lovely-docs/drizzle-orm/zod.md +113 -0
- package/lovely-docs/drizzle-orm.md +60 -0
- package/package.json +24 -0
- package/src/index.ts +186 -0
- package/tsconfig.json +14 -0
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
## Overview
|
|
2
|
+
Open source TypeScript ORM with fully typed SQL schema in-code. Supports PostgreSQL with MySQL and SQLite coming soon.
|
|
3
|
+
|
|
4
|
+
## Schema Definition
|
|
5
|
+
Define tables as classes extending `PgTable` with typed columns:
|
|
6
|
+
```ts
|
|
7
|
+
export const popularityEnum = createEnum({ alias: 'popularity', values: ['unknown', 'known', 'popular'] });
|
|
8
|
+
|
|
9
|
+
export class CountriesTable extends PgTable<CountriesTable> {
|
|
10
|
+
id = this.serial("id").primaryKey();
|
|
11
|
+
name = this.varchar("name", { size: 256 })
|
|
12
|
+
nameIndex = this.uniqueIndex(this.name)
|
|
13
|
+
public tableName(): string { return 'countries'; }
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export class CitiesTable extends PgTable<CitiesTable> {
|
|
17
|
+
id = this.serial("id").primaryKey();
|
|
18
|
+
name = this.varchar("name", { size: 256 })
|
|
19
|
+
countryId = this.int("country_id").foreignKey(CountriesTable, (country) => country.id)
|
|
20
|
+
popularity = this.type(popularityEnum, "popularity")
|
|
21
|
+
public tableName(): string { return 'cities'; }
|
|
22
|
+
}
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Connection & Basic Queries
|
|
26
|
+
```ts
|
|
27
|
+
import { drizzle } from 'drizzle-orm'
|
|
28
|
+
|
|
29
|
+
export class UsersTable extends PgTable<UsersTable> {
|
|
30
|
+
public id = this.serial('id').primaryKey();
|
|
31
|
+
public fullName = this.text('full_name');
|
|
32
|
+
public phone = this.varchar('phone', { size: 256 });
|
|
33
|
+
public tableName(): string { return 'users'; }
|
|
34
|
+
}
|
|
35
|
+
export type User = InferType<UsersTable>
|
|
36
|
+
|
|
37
|
+
const db = await drizzle.connect("postgres://user:password@host:port/db");
|
|
38
|
+
const usersTable = new UsersTable(db);
|
|
39
|
+
const users: User[] = await usersTable.select().execute();
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Filtering & Selection
|
|
43
|
+
```ts
|
|
44
|
+
// WHERE with filters
|
|
45
|
+
await table.select().where(eq(table.id, 42)).execute();
|
|
46
|
+
await table.select().where(and([eq(table.id, 42), eq(table.name, "Dan")])).execute();
|
|
47
|
+
await table.select().where(or([eq(table.id, 42), eq(table.id, 1)])).execute();
|
|
48
|
+
|
|
49
|
+
// Partial select
|
|
50
|
+
const result = await table.select({
|
|
51
|
+
mapped1: table.id,
|
|
52
|
+
mapped2: table.name,
|
|
53
|
+
}).execute();
|
|
54
|
+
|
|
55
|
+
// Pagination & ordering
|
|
56
|
+
await table.select().limit(10).offset(10).execute()
|
|
57
|
+
await table.select().orderBy((table) => table.name, Order.ASC).execute()
|
|
58
|
+
await table.select().orderBy((table) => table.name, Order.DESC).execute()
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Insert, Update, Delete
|
|
62
|
+
```ts
|
|
63
|
+
await usersTable.insert({ name: "Andrew", createdAt: new Date() }).execute();
|
|
64
|
+
await usersTable.insertMany([
|
|
65
|
+
{ name: "Andrew", createdAt: new Date() },
|
|
66
|
+
{ name: "Dan", createdAt: new Date() }
|
|
67
|
+
]).execute();
|
|
68
|
+
await usersTable.update().where(eq(usersTable.name, 'Dan')).set({ name: 'Mr. Dan' }).execute();
|
|
69
|
+
await usersTable.delete().where(eq(usersTable.name, 'Dan')).execute();
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Joins
|
|
73
|
+
Fully typed joins prevent mistakes at compile time:
|
|
74
|
+
```ts
|
|
75
|
+
const result = await citiesTable.select()
|
|
76
|
+
.leftJoin(usersTable, (cities, users) => eq(cities.userId, users.id))
|
|
77
|
+
.where((cities, users) => eq(cities.id, 1))
|
|
78
|
+
.execute();
|
|
79
|
+
const citiesWithUsers: { city: City, user: User }[] = result.map((city, user) => ({ city, user }));
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Many-to-Many Relationships
|
|
83
|
+
```ts
|
|
84
|
+
export class UsersTable extends PgTable<UsersTable> {
|
|
85
|
+
id = this.serial("id").primaryKey();
|
|
86
|
+
name = this.varchar("name");
|
|
87
|
+
}
|
|
88
|
+
export class ChatGroupsTable extends PgTable<ChatGroupsTable> {
|
|
89
|
+
id = this.serial("id").primaryKey();
|
|
90
|
+
}
|
|
91
|
+
export class ManyToManyTable extends PgTable<ManyToManyTable> {
|
|
92
|
+
userId = this.int('user_id').foreignKey(UsersTable, (table) => table.id, { onDelete: 'CASCADE' });
|
|
93
|
+
groupId = this.int('group_id').foreignKey(ChatGroupsTable, (table) => table.id, { onDelete: 'CASCADE' });
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const usersWithUserGroups = await manyToManyTable.select()
|
|
97
|
+
.leftJoin(usersTable, (manyToMany, users) => eq(manyToManyTable.userId, users.id))
|
|
98
|
+
.leftJoin(chatGroupsTable, (manyToMany, _users, chatGroups) => eq(manyToManyTable.groupId, chatGroups.id))
|
|
99
|
+
.where((manyToMany, _users, userGroups) => eq(userGroups.id, 1))
|
|
100
|
+
.execute();
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Migrations
|
|
104
|
+
CLI tool generates migrations automatically from TypeScript schema, handling renames and deletes with prompts.
|
|
105
|
+
|
|
106
|
+
Schema:
|
|
107
|
+
```ts
|
|
108
|
+
export class UsersTable extends PgTable<UsersTable> {
|
|
109
|
+
public id = this.serial("id").primaryKey();
|
|
110
|
+
public fullName = this.varchar("full_name", { size: 256 });
|
|
111
|
+
public fullNameIndex = this.index(this.fullName);
|
|
112
|
+
public tableName(): string { return "users"; }
|
|
113
|
+
}
|
|
114
|
+
export class AuthOtpTable extends PgTable<AuthOtpTable> {
|
|
115
|
+
public id = this.serial("id").primaryKey();
|
|
116
|
+
public phone = this.varchar("phone", { size: 256 });
|
|
117
|
+
public userId = this.int("user_id").foreignKey(UsersTable, (t) => t.id);
|
|
118
|
+
public tableName(): string { return "auth_otp"; }
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Generated SQL:
|
|
123
|
+
```sql
|
|
124
|
+
CREATE TABLE IF NOT EXISTS auth_otp (
|
|
125
|
+
"id" SERIAL PRIMARY KEY,
|
|
126
|
+
"phone" character varying(256),
|
|
127
|
+
"user_id" INT
|
|
128
|
+
);
|
|
129
|
+
CREATE TABLE IF NOT EXISTS users (
|
|
130
|
+
"id" SERIAL PRIMARY KEY,
|
|
131
|
+
"full_name" character varying(256)
|
|
132
|
+
);
|
|
133
|
+
DO $$ BEGIN
|
|
134
|
+
ALTER TABLE auth_otp ADD CONSTRAINT auth_otp_user_id_fkey FOREIGN KEY ("user_id") REFERENCES users(id);
|
|
135
|
+
EXCEPTION
|
|
136
|
+
WHEN duplicate_object THEN null;
|
|
137
|
+
END $$;
|
|
138
|
+
CREATE INDEX IF NOT EXISTS users_full_name_index ON users (full_name);
|
|
139
|
+
```
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
## PostgreSQL Schemas
|
|
2
|
+
Declare PostgreSQL schemas and create tables within them:
|
|
3
|
+
```ts
|
|
4
|
+
import { pgSchema } from "drizzle-orm-pg";
|
|
5
|
+
export const mySchema = pgSchema("my_schema");
|
|
6
|
+
export const users = mySchema("users", {
|
|
7
|
+
id: serial("id").primaryKey(),
|
|
8
|
+
name: text("name"),
|
|
9
|
+
email: text("email"),
|
|
10
|
+
});
|
|
11
|
+
```
|
|
12
|
+
Generates:
|
|
13
|
+
```sql
|
|
14
|
+
CREATE SCHEMA "my_schema";
|
|
15
|
+
CREATE TABLE IF NOT EXISTS "my_schema"."users" (
|
|
16
|
+
"id" serial PRIMARY KEY NOT NULL,
|
|
17
|
+
"name" text,
|
|
18
|
+
"email" text
|
|
19
|
+
);
|
|
20
|
+
```
|
|
21
|
+
drizzle-kit auto-generates migrations: `drizzle-kit generate:pg --schema=src/schema.ts --out=migrations/`
|
|
22
|
+
|
|
23
|
+
## MySQL Databases/Schemas
|
|
24
|
+
Similar schema support for MySQL:
|
|
25
|
+
```ts
|
|
26
|
+
import { mysqlSchema } from "drizzle-orm-mysql";
|
|
27
|
+
const mySchema = mysqlSchema("my_schema");
|
|
28
|
+
const users = mySchema("users", {
|
|
29
|
+
id: serial("id").primaryKey(),
|
|
30
|
+
name: text("name"),
|
|
31
|
+
email: text("email"),
|
|
32
|
+
});
|
|
33
|
+
```
|
|
34
|
+
Generates:
|
|
35
|
+
```sql
|
|
36
|
+
CREATE DATABASE `my_schema`;
|
|
37
|
+
CREATE TABLE `my_schema`.`users` (
|
|
38
|
+
`id` serial PRIMARY KEY NOT NULL,
|
|
39
|
+
`name` text,
|
|
40
|
+
`email` text
|
|
41
|
+
);
|
|
42
|
+
```
|
|
43
|
+
Command: `drizzle-kit generate:mysql --schema=src/schema.ts --out=migrations/`
|
|
44
|
+
|
|
45
|
+
## PostgreSQL Introspection
|
|
46
|
+
Pull existing PostgreSQL database schema automatically with drizzle-kit. Supports enums, tables with native/non-native columns, indexes, foreign keys, self-references, cyclic foreign keys, and schemas:
|
|
47
|
+
```shell
|
|
48
|
+
drizzle-kit introspect:pg --out=migrations/ --connectionString=postgresql://user:pass@host:port/db_name
|
|
49
|
+
```
|
|
50
|
+
Generates complete `schema.ts` with all detected types, enums, tables, columns, defaults, and relationships including cyclic references and self-references.
|
|
51
|
+
|
|
52
|
+
## Postgres.js Driver Support
|
|
53
|
+
Full support for postgres.js driver:
|
|
54
|
+
```ts
|
|
55
|
+
import { pgTable, serial, text, varchar } from "drizzle-orm-pg";
|
|
56
|
+
import { drizzle } from "drizzle-orm-pg/postgres.js";
|
|
57
|
+
import postgres from "postgres";
|
|
58
|
+
|
|
59
|
+
export const users = pgTable("users", {
|
|
60
|
+
id: serial("id").primaryKey(),
|
|
61
|
+
fullName: text("full_name"),
|
|
62
|
+
phone: varchar("phone", { length: 256 }),
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
const client = postgres(connectionString);
|
|
66
|
+
const db = drizzle(client);
|
|
67
|
+
const allUsers = await db.select(users);
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Custom Types
|
|
71
|
+
Create non-native PostgreSQL or MySQL types:
|
|
72
|
+
```ts
|
|
73
|
+
const customText = customType<{ data: string }>({
|
|
74
|
+
dataType() { return "text"; }
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
// PostgreSQL
|
|
78
|
+
const pgUsersTable = pgTable("users", {
|
|
79
|
+
name: customText("name").notNull(),
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
// MySQL
|
|
83
|
+
const mysqlUsersTable = mysqlTable("users", {
|
|
84
|
+
name: customText("name").notNull(),
|
|
85
|
+
});
|
|
86
|
+
```
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
## Bug Fixes
|
|
2
|
+
|
|
3
|
+
**PostgreSQL schemaFilter bug**: Fixed an issue where the `schemaFilter` object in push and introspect commands was incorrectly detecting enums in schemas that were not defined in the filter.
|
|
4
|
+
|
|
5
|
+
**drizzle-kit up command**: Fixed the `drizzle-kit up` command to work correctly starting from the sequences release.
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
## UNIQUE Constraints Support Added
|
|
2
|
+
|
|
3
|
+
Support for `UNIQUE` constraints across PostgreSQL, MySQL, and SQLite databases.
|
|
4
|
+
|
|
5
|
+
### PostgreSQL
|
|
6
|
+
Single-column constraints defined at column level with optional custom name:
|
|
7
|
+
```ts
|
|
8
|
+
const table = pgTable('table', {
|
|
9
|
+
id: serial('id').primaryKey(),
|
|
10
|
+
name: text('name').notNull().unique(),
|
|
11
|
+
state: char('state', { length: 2 }).unique('custom'),
|
|
12
|
+
field: char('field', { length: 2 }).unique('custom_field', { nulls: 'not distinct' }),
|
|
13
|
+
});
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Multi-column constraints defined in table config with `nullsNotDistinct()` option:
|
|
17
|
+
```ts
|
|
18
|
+
const table = pgTable('table', {
|
|
19
|
+
id: serial('id').primaryKey(),
|
|
20
|
+
name: text('name').notNull(),
|
|
21
|
+
state: char('state', { length: 2 }),
|
|
22
|
+
}, (t) => ({
|
|
23
|
+
first: unique('custom_name').on(t.name, t.state).nullsNotDistinct(),
|
|
24
|
+
second: unique('custom_name1').on(t.name, t.state),
|
|
25
|
+
}));
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
PostgreSQL supports `NULLS NOT DISTINCT` option to restrict multiple NULL values.
|
|
29
|
+
|
|
30
|
+
### MySQL
|
|
31
|
+
Same syntax as PostgreSQL but without `NULLS NOT DISTINCT` support:
|
|
32
|
+
```ts
|
|
33
|
+
const table = mysqlTable('table', {
|
|
34
|
+
id: serial('id').primaryKey(),
|
|
35
|
+
name: text('name').notNull().unique(),
|
|
36
|
+
state: text('state').unique('custom'),
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const table = mysqlTable('cities1', {
|
|
40
|
+
id: serial('id').primaryKey(),
|
|
41
|
+
name: text('name').notNull(),
|
|
42
|
+
state: text('state'),
|
|
43
|
+
}, (t) => ({
|
|
44
|
+
first: unique().on(t.name, t.state),
|
|
45
|
+
second: unique('custom_name1').on(t.name, t.state),
|
|
46
|
+
}));
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### SQLite
|
|
50
|
+
Unique constraints implemented as unique indexes. Supports optional naming:
|
|
51
|
+
```ts
|
|
52
|
+
const table = sqliteTable('table', {
|
|
53
|
+
id: int('id').primaryKey(),
|
|
54
|
+
name: text('name').notNull().unique(),
|
|
55
|
+
state: text('state').unique('custom'),
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
const table = sqliteTable('table', {
|
|
59
|
+
id: int('id').primaryKey(),
|
|
60
|
+
name: text('name').notNull(),
|
|
61
|
+
state: text('state'),
|
|
62
|
+
}, (t) => ({
|
|
63
|
+
first: unique().on(t.name, t.state),
|
|
64
|
+
second: unique('custom').on(t.name, t.state),
|
|
65
|
+
}));
|
|
66
|
+
```
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
## Breaking Changes
|
|
2
|
+
|
|
3
|
+
### Removed support for filtering by nested relations
|
|
4
|
+
The `table` object in the `where` callback no longer includes fields from `with` and `extras`. This change improves relational query efficiency.
|
|
5
|
+
|
|
6
|
+
```ts
|
|
7
|
+
// This no longer works:
|
|
8
|
+
const usersWithPosts = await db.query.users.findMany({
|
|
9
|
+
where: (table, { sql }) => (sql`json_array_length(${table.posts}) > 0`),
|
|
10
|
+
with: { posts: true },
|
|
11
|
+
});
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Workarounds: apply filters manually after fetching, or use the core API.
|
|
15
|
+
|
|
16
|
+
### Added Relational Queries `mode` config for `mysql2` driver
|
|
17
|
+
Relational queries use lateral joins which PlanetScale doesn't support. Specify the mode when creating the connection:
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
const db = drizzle({ client, schema, mode: 'planetscale' });
|
|
21
|
+
// or
|
|
22
|
+
const db = drizzle({ client, schema, mode: 'default' }); // for regular MySQL
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Performance Improvements
|
|
26
|
+
|
|
27
|
+
### IntelliSense performance for large schemas
|
|
28
|
+
Optimized internal types resulting in **430% speed up** for IntelliSense on schemas with 85 tables, 666 columns, 26 enums, 172 indexes, and 133 foreign keys.
|
|
29
|
+
|
|
30
|
+
### Relational Queries Performance and Read Usage
|
|
31
|
+
Completely rewrote query generation strategy:
|
|
32
|
+
1. **Lateral Joins**: Uses "LEFT JOIN LATERAL" for efficient data retrieval; MySQL PlanetScale and SQLite use simple subquery selects
|
|
33
|
+
2. **Selective Data Retrieval**: Only fetches necessary columns, reducing dataset size
|
|
34
|
+
3. **Reduced Aggregations**: Uses `json_build_array` directly within lateral joins instead of multiple aggregation functions
|
|
35
|
+
4. **Simplified Grouping**: Removed GROUP BY clause as lateral joins handle aggregation more efficiently
|
|
36
|
+
|
|
37
|
+
Example query transformation:
|
|
38
|
+
|
|
39
|
+
```ts
|
|
40
|
+
const items = await db.query.comments.findMany({
|
|
41
|
+
limit,
|
|
42
|
+
orderBy: comments.id,
|
|
43
|
+
with: {
|
|
44
|
+
user: { columns: { name: true } },
|
|
45
|
+
post: {
|
|
46
|
+
columns: { title: true },
|
|
47
|
+
with: { user: { columns: { name: true } } },
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
**New query** (with lateral joins):
|
|
54
|
+
```sql
|
|
55
|
+
select "comments"."id", "comments"."user_id", "comments"."post_id", "comments"."content",
|
|
56
|
+
"comments_user"."data" as "user", "comments_post"."data" as "post"
|
|
57
|
+
from "comments"
|
|
58
|
+
left join lateral (select json_build_array("comments_user"."name") as "data"
|
|
59
|
+
from (select * from "users" "comments_user"
|
|
60
|
+
where "comments_user"."id" = "comments"."user_id" limit 1) "comments_user") "comments_user" on true
|
|
61
|
+
left join lateral (select json_build_array("comments_post"."title", "comments_post_user"."data") as "data"
|
|
62
|
+
from (select * from "posts" "comments_post"
|
|
63
|
+
where "comments_post"."id" = "comments"."post_id" limit 1) "comments_post"
|
|
64
|
+
left join lateral (select json_build_array("comments_post_user"."name") as "data"
|
|
65
|
+
from (select * from "users" "comments_post_user"
|
|
66
|
+
where "comments_post_user"."id" = "comments_post"."user_id" limit 1) "comments_post_user") "comments_post_user" on true) "comments_post" on true
|
|
67
|
+
order by "comments"."id" limit 1
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
**Old query** (with GROUP BY and aggregations) - significantly more complex with multiple CASE statements and json_agg calls.
|
|
71
|
+
|
|
72
|
+
## New Features
|
|
73
|
+
|
|
74
|
+
### Insert rows with default values for all columns
|
|
75
|
+
Provide empty objects to insert rows with all default values:
|
|
76
|
+
|
|
77
|
+
```ts
|
|
78
|
+
await db.insert(usersTable).values({}); // Insert 1 row with all defaults
|
|
79
|
+
await db.insert(usersTable).values([{}, {}]); // Insert 2 rows with all defaults
|
|
80
|
+
```
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
## v0.28.2 Release
|
|
2
|
+
|
|
3
|
+
### Community Contributions
|
|
4
|
+
This release includes contributions from the community.
|
|
5
|
+
|
|
6
|
+
### Internal Changes
|
|
7
|
+
- Added comprehensive test suite for d1
|
|
8
|
+
- Fixed documentation issues
|
|
9
|
+
|
|
10
|
+
### Bug Fixes
|
|
11
|
+
- **MySQL timestamp milliseconds**: Fixed truncation issue where milliseconds were being lost in timestamp values
|
|
12
|
+
- **SQLite `.get()` method**: Corrected type signature for sqlite-based dialects (issue #565)
|
|
13
|
+
- **SQLite proxy**: Fixed bug causing queries to execute twice
|
|
14
|
+
|
|
15
|
+
### New Features
|
|
16
|
+
- **Typebox support**: Added official support for Typebox package integration via new `drizzle-typebox` package
|
|
17
|
+
- Enables type-safe schema validation using Typebox
|
|
18
|
+
- See `/docs/typebox` for usage examples and documentation
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
## Fixes
|
|
2
|
+
- Fixed sqlite-proxy and SQL.js `.get()` response when result is empty
|
|
3
|
+
|
|
4
|
+
## New Features
|
|
5
|
+
|
|
6
|
+
### SQLite Simplified Query API
|
|
7
|
+
Added simplified query API for SQLite.
|
|
8
|
+
|
|
9
|
+
### Column Builder Methods: `.$defaultFn()` / `.$default()`
|
|
10
|
+
Define runtime default values for columns with custom logic. Available for PostgreSQL, MySQL, and SQLite.
|
|
11
|
+
|
|
12
|
+
```ts
|
|
13
|
+
import { varchar, mysqlTable } from "drizzle-orm/mysql-core";
|
|
14
|
+
import { createId } from '@paralleldrive/cuid2';
|
|
15
|
+
|
|
16
|
+
const table = mysqlTable('table', {
|
|
17
|
+
id: varchar('id', { length: 128 }).$defaultFn(() => createId()),
|
|
18
|
+
});
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Note: Runtime defaults only affect drizzle-orm behavior, not drizzle-kit.
|
|
22
|
+
|
|
23
|
+
### Table Model Type Inference: `$inferSelect` / `$inferInsert`
|
|
24
|
+
Convenient methods for inferring table types. Replaces deprecated `InferModel`.
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
import { InferSelectModel, InferInsertModel } from 'drizzle-orm'
|
|
28
|
+
|
|
29
|
+
const usersTable = pgTable('users', {
|
|
30
|
+
id: serial('id').primaryKey(),
|
|
31
|
+
name: text('name').notNull(),
|
|
32
|
+
verified: boolean('verified').notNull().default(false),
|
|
33
|
+
jsonb: jsonb('jsonb').$type<string[]>(),
|
|
34
|
+
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
// New approach
|
|
38
|
+
type SelectUser = typeof usersTable.$inferSelect;
|
|
39
|
+
type InsertUser = typeof usersTable.$inferInsert;
|
|
40
|
+
|
|
41
|
+
// Legacy approach (deprecated)
|
|
42
|
+
type SelectUser2 = InferSelectModel<typeof usersTable>;
|
|
43
|
+
type InsertUser2 = InferInsertModel<typeof usersTable>;
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Other Changes
|
|
47
|
+
- Deprecated `InferModel` type in favor of `InferSelectModel` and `InferInsertModel`
|
|
48
|
+
- Disabled `.d.ts` files bundling
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
## v0.28.4 Release (2023-08-24)
|
|
2
|
+
|
|
3
|
+
### Fixes
|
|
4
|
+
- Fixed imports in ESM-based projects (issue #1088)
|
|
5
|
+
- Fixed type error on Postgres table definitions (issue #1089)
|
|
6
|
+
|
|
7
|
+
### Note
|
|
8
|
+
If you encounter a `Cannot find package '@opentelemetry/api'` error, update to v0.28.5 where this is resolved.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
## v0.28.5 Release
|
|
2
|
+
|
|
3
|
+
**Fix:** Corrected incorrect OpenTelemetry type import that caused a runtime error.
|
|
4
|
+
|
|
5
|
+
**Details:** The issue was caused by using `import { type ... }` syntax instead of `import type { ... }` on the tracing.ts file, which caused the `import '@opentelemetry/api'` line to leak into runtime code.
|
|
6
|
+
|
|
7
|
+
**Context:** OpenTelemetry integration in drizzle-orm is currently disabled and does nothing. It was an experimental feature designed to allow users to collect query statistics and send them to their own telemetry consumers. The ORM itself never collects or sends any stats. OpenTelemetry is simply a protocol that the library provides hooks for, but the feature is not active in current versions.
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
## Changes
|
|
2
|
+
MySQL `datetime` with `mode: 'date'` now stores and retrieves dates in UTC strings. Use `mode: 'string'` or custom types for different behavior.
|
|
3
|
+
|
|
4
|
+
## New Features
|
|
5
|
+
|
|
6
|
+
**LibSQL batch API support**
|
|
7
|
+
Execute multiple queries in a single batch call:
|
|
8
|
+
```ts
|
|
9
|
+
const batchResponse = await db.batch([
|
|
10
|
+
db.insert(usersTable).values({ id: 1, name: 'John' }).returning({ id: usersTable.id }),
|
|
11
|
+
db.update(usersTable).set({ name: 'Dan' }).where(eq(usersTable.id, 1)),
|
|
12
|
+
db.query.usersTable.findMany({}),
|
|
13
|
+
db.select().from(usersTable).where(eq(usersTable.id, 1)),
|
|
14
|
+
]);
|
|
15
|
+
// Returns: [{ id: number }[], ResultSet, User[], User[]]
|
|
16
|
+
```
|
|
17
|
+
Supported builders: `db.all()`, `db.get()`, `db.values()`, `db.run()`, `db.query.<table>.findMany()`, `db.query.<table>.findFirst()`, `db.select()...`, `db.update()...`, `db.delete()...`, `db.insert()...`
|
|
18
|
+
|
|
19
|
+
**JSON mode for SQLite text columns**
|
|
20
|
+
```ts
|
|
21
|
+
const test = sqliteTable('test', {
|
|
22
|
+
dataTyped: text('data_typed', { mode: 'json' }).$type<{ a: 1 }>().notNull(),
|
|
23
|
+
});
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
**`.toSQL()` on Relational Query API**
|
|
27
|
+
```ts
|
|
28
|
+
const query = db.query.usersTable.findFirst().toSQL();
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
**PostgreSQL array operators**
|
|
32
|
+
```ts
|
|
33
|
+
const contains = await db.select({ id: posts.id }).from(posts)
|
|
34
|
+
.where(arrayContains(posts.tags, ['Typescript', 'ORM']));
|
|
35
|
+
const contained = await db.select({ id: posts.id }).from(posts)
|
|
36
|
+
.where(arrayContained(posts.tags, ['Typescript', 'ORM']));
|
|
37
|
+
const overlaps = await db.select({ id: posts.id }).from(posts)
|
|
38
|
+
.where(arrayOverlaps(posts.tags, ['Typescript', 'ORM']));
|
|
39
|
+
const withSubQuery = await db.select({ id: posts.id }).from(posts)
|
|
40
|
+
.where(arrayContains(posts.tags, db.select({ tags: posts.tags }).from(posts).where(eq(posts.id, 1))));
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**More SQL operators in Relational Query where filters**
|
|
44
|
+
```ts
|
|
45
|
+
// Before: import { inArray } from "drizzle-orm/pg-core"; await db.users.findFirst({ where: (table, _) => inArray(table.id, [...]) })
|
|
46
|
+
// After: await db.users.findFirst({ where: (table, { inArray }) => inArray(table.id, [...]) })
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Fixes
|
|
50
|
+
- Correct where in on conflict in SQLite
|
|
51
|
+
- Fix libsql/client type import
|
|
52
|
+
- Fix raw SQL query mapping on RDS
|
|
53
|
+
- Fix datetime mapping for MySQL
|
|
54
|
+
- Fix smallserial generating as serial
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
## MySQL unsigned bigint
|
|
2
|
+
```ts
|
|
3
|
+
const table = mysqlTable('table', {
|
|
4
|
+
id: bigint('id', { mode: 'number', unsigned: true }),
|
|
5
|
+
});
|
|
6
|
+
```
|
|
7
|
+
|
|
8
|
+
## Improved query builder types
|
|
9
|
+
By default, query builder methods can only be invoked once (e.g., `.where()` once per query) to match SQL semantics. Use `.$dynamic()` to enable multiple invocations for dynamic query building:
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
function withPagination<T extends PgSelect>(qb: T, page: number, pageSize: number = 10) {
|
|
13
|
+
return qb.limit(pageSize).offset(page * pageSize);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const query = db.select().from(users).where(eq(users.id, 1)).$dynamic();
|
|
17
|
+
withPagination(query, 1); // ✅ OK
|
|
18
|
+
|
|
19
|
+
function withFriends<T extends PgSelect>(qb: T) {
|
|
20
|
+
return qb.leftJoin(friends, eq(friends.userId, users.id));
|
|
21
|
+
}
|
|
22
|
+
query = withFriends(query);
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Custom names for primary and foreign keys
|
|
26
|
+
```ts
|
|
27
|
+
const table = pgTable('table', {
|
|
28
|
+
id: integer('id'),
|
|
29
|
+
name: text('name'),
|
|
30
|
+
}, (table) => ({
|
|
31
|
+
cpk: primaryKey({ name: 'composite_key', columns: [table.id, table.name] }),
|
|
32
|
+
cfk: foreignKey({
|
|
33
|
+
name: 'fkName',
|
|
34
|
+
columns: [table.id],
|
|
35
|
+
foreignColumns: [table.name],
|
|
36
|
+
}),
|
|
37
|
+
}));
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Read replicas support
|
|
41
|
+
```ts
|
|
42
|
+
const primaryDb = drizzle({ client });
|
|
43
|
+
const read1 = drizzle({ client });
|
|
44
|
+
const read2 = drizzle({ client });
|
|
45
|
+
const db = withReplicas(primaryDb, [read1, read2]);
|
|
46
|
+
|
|
47
|
+
db.$primary.select().from(usersTable); // read from primary
|
|
48
|
+
db.select().from(usersTable); // read from replica
|
|
49
|
+
db.delete(usersTable).where(eq(usersTable.id, 1)); // write to primary
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Custom replica selection with weighted probability:
|
|
53
|
+
```ts
|
|
54
|
+
const db = withReplicas(primaryDb, [read1, read2], (replicas) => {
|
|
55
|
+
const weight = [0.7, 0.3];
|
|
56
|
+
let cumulativeProbability = 0;
|
|
57
|
+
const rand = Math.random();
|
|
58
|
+
for (const [i, replica] of replicas.entries()) {
|
|
59
|
+
cumulativeProbability += weight[i]!;
|
|
60
|
+
if (rand < cumulativeProbability) return replica;
|
|
61
|
+
}
|
|
62
|
+
return replicas[0]!
|
|
63
|
+
});
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Set operators (UNION, UNION ALL, INTERSECT, INTERSECT ALL, EXCEPT, EXCEPT ALL)
|
|
67
|
+
```ts
|
|
68
|
+
// Import approach
|
|
69
|
+
import { union } from 'drizzle-orm/pg-core'
|
|
70
|
+
const result = await union(
|
|
71
|
+
db.select().from(users),
|
|
72
|
+
db.select().from(customers)
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
// Builder approach
|
|
76
|
+
const result = await db.select().from(users).union(db.select().from(customers));
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## MySQL proxy driver
|
|
80
|
+
Implement HTTP endpoints for queries and migrations. Driver example:
|
|
81
|
+
```ts
|
|
82
|
+
import { drizzle } from 'drizzle-orm/mysql-proxy';
|
|
83
|
+
import { migrate } from 'drizzle-orm/mysql-proxy/migrator';
|
|
84
|
+
|
|
85
|
+
const db = drizzle(async (sql, params, method) => {
|
|
86
|
+
const rows = await axios.post(`${process.env.REMOTE_DRIVER}/query`, { sql, params, method });
|
|
87
|
+
return { rows: rows.data };
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
await migrate(db, async (queries) => {
|
|
91
|
+
await axios.post(`${process.env.REMOTE_DRIVER}/migrate`, { queries });
|
|
92
|
+
}, { migrationsFolder: 'drizzle' });
|
|
93
|
+
|
|
94
|
+
await db.insert(cities).values({ id: 1, name: 'name' });
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## PostgreSQL proxy driver
|
|
98
|
+
Same as MySQL proxy driver:
|
|
99
|
+
```ts
|
|
100
|
+
import { drizzle } from 'drizzle-orm/pg-proxy';
|
|
101
|
+
import { migrate } from 'drizzle-orm/pg-proxy/migrator';
|
|
102
|
+
|
|
103
|
+
const db = drizzle(async (sql, params, method) => {
|
|
104
|
+
const rows = await axios.post(`${process.env.REMOTE_DRIVER}/query`, { sql, params, method });
|
|
105
|
+
return { rows: rows.data };
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
await migrate(db, async (queries) => {
|
|
109
|
+
await axios.post(`${process.env.REMOTE_DRIVER}/query`, { queries });
|
|
110
|
+
}, { migrationsFolder: 'drizzle' });
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## D1 Batch API support
|
|
114
|
+
```ts
|
|
115
|
+
const batchResponse = await db.batch([
|
|
116
|
+
db.insert(usersTable).values({ id: 1, name: 'John' }).returning({ id: usersTable.id }),
|
|
117
|
+
db.update(usersTable).set({ name: 'Dan' }).where(eq(usersTable.id, 1)),
|
|
118
|
+
db.query.usersTable.findMany({}),
|
|
119
|
+
db.select().from(usersTable).where(eq(usersTable.id, 1)),
|
|
120
|
+
db.select({ id: usersTable.id, invitedBy: usersTable.invitedBy }).from(usersTable),
|
|
121
|
+
]);
|
|
122
|
+
|
|
123
|
+
type BatchResponse = [
|
|
124
|
+
{ id: number }[],
|
|
125
|
+
D1Result,
|
|
126
|
+
{ id: number; name: string; verified: number; invitedBy: number | null }[],
|
|
127
|
+
{ id: number; name: string; verified: number; invitedBy: number | null }[],
|
|
128
|
+
{ id: number; invitedBy: number | null }[],
|
|
129
|
+
];
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Supported builders: `db.all()`, `db.get()`, `db.values()`, `db.run()`, `db.query.<table>.findMany()`, `db.query.<table>.findFirst()`, `db.select()...`, `db.update()...`, `db.delete()...`, `db.insert()...`
|
|
133
|
+
|
|
134
|
+
## Drizzle Kit 0.20.0
|
|
135
|
+
- `defineConfig` function for config definition
|
|
136
|
+
- Cloudflare D1 access in Drizzle Studio via wrangler.toml
|
|
137
|
+
- Drizzle Studio migrated to https://local.drizzle.studio/
|
|
138
|
+
- `bigint unsigned` support
|
|
139
|
+
- Custom names for `primaryKeys` and `foreignKeys`
|
|
140
|
+
- Automatic environment variable fetching
|
|
141
|
+
- Bug fixes and improvements
|
|
142
|
+
|
|
143
|
+
**Note:** v0.29.0 requires minimum Drizzle Kit v0.20.0 and vice versa.
|