chore(deps): update dependency drizzle-orm to 0.33 || 0.36
This MR contains the following updates:
Package | Type | Update | Change |
---|---|---|---|
drizzle-orm (source) | peerDependencies | minor | 0.33 -> 0.33 || 0.36 |
Release Notes
drizzle-team/drizzle-orm (drizzle-orm)
v0.36.0
This version of
drizzle-orm
requiresdrizzle-kit@0.27.0
to enable all new features
New Features
The third parameter in Drizzle ORM becomes an array
The object API is still available but deprecated
Instead of this
pgTable('users', {
id: integer().primaryKey(),
}, (t) => ({
index: index('test').on(t.id),
}));
You can now do this
pgTable('users', {
id: integer().primaryKey(),
}, (t) => [index('test').on(t.id)]);
Row-Level Security (RLS)
With Drizzle, you can enable Row-Level Security (RLS) for any Postgres table, create policies with various options, and define and manage the roles those policies apply to.
Drizzle supports a raw representation of Postgres policies and roles that can be used in any way you want. This works with popular Postgres database providers such as Neon
and Supabase
.
In Drizzle, we have specific predefined RLS roles and functions for RLS with both database providers, but you can also define your own logic.
Enable RLS
If you just want to enable RLS on a table without adding policies, you can use .enableRLS()
As mentioned in the PostgreSQL documentation:
If no policy exists for the table, a default-deny policy is used, meaning that no rows are visible or can be modified. Operations that apply to the whole table, such as TRUNCATE and REFERENCES, are not subject to row security.
import { integer, pgTable } from 'drizzle-orm/pg-core';
export const users = pgTable('users', {
id: integer(),
}).enableRLS();
If you add a policy to a table, RLS will be enabled automatically. So, there’s no need to explicitly enable RLS when adding policies to a table.
Roles
Currently, Drizzle supports defining roles with a few different options, as shown below. Support for more options will be added in a future release.
import { pgRole } from 'drizzle-orm/pg-core';
export const admin = pgRole('admin', { createRole: true, createDb: true, inherit: true });
If a role already exists in your database, and you don’t want drizzle-kit to ‘see’ it or include it in migrations, you can mark the role as existing.
import { pgRole } from 'drizzle-orm/pg-core';
export const admin = pgRole('admin').existing();
Policies
To fully leverage RLS, you can define policies within a Drizzle table.
In PostgreSQL, policies should be linked to an existing table. Since policies are always associated with a specific table, we decided that policy definitions should be defined as a parameter of
pgTable
Example of pgPolicy with all available properties
import { sql } from 'drizzle-orm';
import { integer, pgPolicy, pgRole, pgTable } from 'drizzle-orm/pg-core';
export const admin = pgRole('admin');
export const users = pgTable('users', {
id: integer(),
}, (t) => [
pgPolicy('policy', {
as: 'permissive',
to: admin,
for: 'delete',
using: sql``,
withCheck: sql``,
}),
]);
Link Policy to an existing table
There are situations where you need to link a policy to an existing table in your database.
The most common use case is with database providers like Neon
or Supabase
, where you need to add a policy
to their existing tables. In this case, you can use the .link()
API
import { sql } from "drizzle-orm";
import { pgPolicy } from "drizzle-orm/pg-core";
import { authenticatedRole, realtimeMessages } from "drizzle-orm/supabase";
export const policy = pgPolicy("authenticated role insert policy", {
for: "insert",
to: authenticatedRole,
using: sql``,
}).link(realtimeMessages);
Migrations
If you are using drizzle-kit to manage your schema and roles, there may be situations where you want to refer to roles that are not defined in your Drizzle schema. In such cases, you may want drizzle-kit to skip managing these roles without having to define each role in your drizzle schema and marking it with .existing()
.
In these cases, you can use entities.roles
in drizzle.config.ts
. For a complete reference, refer to the the drizzle.config.ts
documentation.
By default, drizzle-kit
does not manage roles for you, so you will need to enable this feature in drizzle.config.ts
.
// drizzle.config.ts
import { defineConfig } from "drizzle-kit";
export default defineConfig({
dialect: 'postgresql',
schema: "./drizzle/schema.ts",
dbCredentials: {
url: process.env.DATABASE_URL!
},
verbose: true,
strict: true,
entities: {
roles: true
}
});
In case you need additional configuration options, let's take a look at a few more examples.
You have an admin
role and want to exclude it from the list of manageable roles
// drizzle.config.ts
import { defineConfig } from "drizzle-kit";
export default defineConfig({
...
entities: {
roles: {
exclude: ['admin']
}
}
});
You have an admin
role and want to include it in the list of manageable roles
// drizzle.config.ts
import { defineConfig } from "drizzle-kit";
export default defineConfig({
...
entities: {
roles: {
include: ['admin']
}
}
});
If you are using Neon
and want to exclude Neon-defined roles, you can use the provider option
// drizzle.config.ts
import { defineConfig } from "drizzle-kit";
export default defineConfig({
...
entities: {
roles: {
provider: 'neon'
}
}
});
If you are using Supabase
and want to exclude Supabase-defined roles, you can use the provider option
// drizzle.config.ts
import { defineConfig } from "drizzle-kit";
export default defineConfig({
...
entities: {
roles: {
provider: 'supabase'
}
}
});
You may encounter situations where Drizzle is slightly outdated compared to new roles specified by your database provider. In such cases, you can use the
provider
option andexclude
additional roles:
// drizzle.config.ts
import { defineConfig } from "drizzle-kit";
export default defineConfig({
...
entities: {
roles: {
provider: 'supabase',
exclude: ['new_supabase_role']
}
}
});
RLS on views
With Drizzle, you can also specify RLS policies on views. For this, you need to use security_invoker
in the view's WITH options. Here is a small example:
...
export const roomsUsersProfiles = pgView("rooms_users_profiles")
.with({
securityInvoker: true,
})
.as((qb) =>
qb
.select({
...getTableColumns(roomsUsers),
email: profiles.email,
})
.from(roomsUsers)
.innerJoin(profiles, eq(roomsUsers.userId, profiles.id))
);
Using with Neon
The Neon Team helped us implement their vision of a wrapper on top of our raw policies API. We defined a specific
/neon
import with the crudPolicy
function that includes predefined functions and Neon's default roles.
Here's an example of how to use the crudPolicy
function:
import { crudPolicy } from 'drizzle-orm/neon';
import { integer, pgRole, pgTable } from 'drizzle-orm/pg-core';
export const admin = pgRole('admin');
export const users = pgTable('users', {
id: integer(),
}, (t) => [
crudPolicy({ role: admin, read: true, modify: false }),
]);
This policy is equivalent to:
import { sql } from 'drizzle-orm';
import { integer, pgPolicy, pgRole, pgTable } from 'drizzle-orm/pg-core';
export const admin = pgRole('admin');
export const users = pgTable('users', {
id: integer(),
}, (t) => [
pgPolicy(`crud-${admin.name}-policy-insert`, {
for: 'insert',
to: admin,
withCheck: sql`false`,
}),
pgPolicy(`crud-${admin.name}-policy-update`, {
for: 'update',
to: admin,
using: sql`false`,
withCheck: sql`false`,
}),
pgPolicy(`crud-${admin.name}-policy-delete`, {
for: 'delete',
to: admin,
using: sql`false`,
}),
pgPolicy(`crud-${admin.name}-policy-select`, {
for: 'select',
to: admin,
using: sql`true`,
}),
]);
Neon
exposes predefined authenticated
and anaonymous
roles and related functions. If you are using Neon
for RLS, you can use these roles, which are marked as existing, and the related functions in your RLS queries.
// drizzle-orm/neon
export const authenticatedRole = pgRole('authenticated').existing();
export const anonymousRole = pgRole('anonymous').existing();
export const authUid = (userIdColumn: AnyPgColumn) => sql`(select auth.user_id() = ${userIdColumn})`;
For example, you can use the Neon
predefined roles and functions like this:
import { sql } from 'drizzle-orm';
import { authenticatedRole } from 'drizzle-orm/neon';
import { integer, pgPolicy, pgRole, pgTable } from 'drizzle-orm/pg-core';
export const admin = pgRole('admin');
export const users = pgTable('users', {
id: integer(),
}, (t) => [
pgPolicy(`policy-insert`, {
for: 'insert',
to: authenticatedRole,
withCheck: sql`false`,
}),
]);
Using with Supabase
We also have a /supabase
import with a set of predefined roles marked as existing, which you can use in your schema.
This import will be extended in a future release with more functions and helpers to make using RLS and Supabase
simpler.
// drizzle-orm/supabase
export const anonRole = pgRole('anon').existing();
export const authenticatedRole = pgRole('authenticated').existing();
export const serviceRole = pgRole('service_role').existing();
export const postgresRole = pgRole('postgres_role').existing();
export const supabaseAuthAdminRole = pgRole('supabase_auth_admin').existing();
For example, you can use the Supabase
predefined roles like this:
import { sql } from 'drizzle-orm';
import { serviceRole } from 'drizzle-orm/supabase';
import { integer, pgPolicy, pgRole, pgTable } from 'drizzle-orm/pg-core';
export const admin = pgRole('admin');
export const users = pgTable('users', {
id: integer(),
}, (t) => [
pgPolicy(`policy-insert`, {
for: 'insert',
to: serviceRole,
withCheck: sql`false`,
}),
]);
The /supabase
import also includes predefined tables and functions that you can use in your application
// drizzle-orm/supabase
const auth = pgSchema('auth');
export const authUsers = auth.table('users', {
id: uuid().primaryKey().notNull(),
});
const realtime = pgSchema('realtime');
export const realtimeMessages = realtime.table(
'messages',
{
id: bigserial({ mode: 'bigint' }).primaryKey(),
topic: text().notNull(),
extension: text({
enum: ['presence', 'broadcast', 'postgres_changes'],
}).notNull(),
},
);
export const authUid = sql`(select auth.uid())`;
export const realtimeTopic = sql`realtime.topic()`;
This allows you to use it in your code, and Drizzle Kit will treat them as existing databases, using them only as information to connect to other entities
import { foreignKey, pgPolicy, pgTable, text, uuid } from "drizzle-orm/pg-core";
import { sql } from "drizzle-orm/sql";
import { authenticatedRole, authUsers } from "drizzle-orm/supabase";
export const profiles = pgTable(
"profiles",
{
id: uuid().primaryKey().notNull(),
email: text().notNull(),
},
(table) => [
foreignKey({
columns: [table.id],
// reference to the auth table from Supabase
foreignColumns: [authUsers.id],
name: "profiles_id_fk",
}).onDelete("cascade"),
pgPolicy("authenticated can view all profiles", {
for: "select",
// using predefined role from Supabase
to: authenticatedRole,
using: sql`true`,
}),
]
);
Let's check an example of adding a policy to a table that exists in Supabase
import { sql } from "drizzle-orm";
import { pgPolicy } from "drizzle-orm/pg-core";
import { authenticatedRole, realtimeMessages } from "drizzle-orm/supabase";
export const policy = pgPolicy("authenticated role insert policy", {
for: "insert",
to: authenticatedRole,
using: sql``,
}).link(realtimeMessages);
Bug fixes
v0.35.3
New LibSQL driver modules
Drizzle now has native support for all @libsql/client
driver variations:
-
@libsql/client
- defaults to node import, automatically changes to web if target or platform is set for bundler, e.g.esbuild --platform=browser
import { drizzle } from 'drizzle-orm/libsql';
const db = drizzle({ connection: {
url: process.env.DATABASE_URL,
authToken: process.env.DATABASE_AUTH_TOKEN
}});
-
@libsql/client/node
node compatible module, supports :memory:, file, wss, http and turso connection protocols
import { drizzle } from 'drizzle-orm/libsql/node';
const db = drizzle({ connection: {
url: process.env.DATABASE_URL,
authToken: process.env.DATABASE_AUTH_TOKEN
}});
-
@libsql/client/web
module for fullstack web frameworks like next, nuxt, astro, etc.
import { drizzle } from 'drizzle-orm/libsql/web';
const db = drizzle({ connection: {
url: process.env.DATABASE_URL,
authToken: process.env.DATABASE_AUTH_TOKEN
}});
-
@libsql/client/http
module for http and https connection protocols
import { drizzle } from 'drizzle-orm/libsql/http';
const db = drizzle({ connection: {
url: process.env.DATABASE_URL,
authToken: process.env.DATABASE_AUTH_TOKEN
}});
-
@libsql/client/ws
module for ws and wss connection protocols
import { drizzle } from 'drizzle-orm/libsql/ws';
const db = drizzle({ connection: {
url: process.env.DATABASE_URL,
authToken: process.env.DATABASE_AUTH_TOKEN
}});
-
@libsql/client/sqlite3
module for :memory: and file connection protocols
import { drizzle } from 'drizzle-orm/libsql/wasm';
const db = drizzle({ connection: {
url: process.env.DATABASE_URL,
authToken: process.env.DATABASE_AUTH_TOKEN
}});
-
@libsql/client-wasm
Separate experimental package for WASM
import { drizzle } from 'drizzle-orm/libsql';
const db = drizzle({ connection: {
url: process.env.DATABASE_URL,
authToken: process.env.DATABASE_AUTH_TOKEN
}});
v0.35.2
- Fix issues with importing in several environments after updating the Drizzle driver implementation
We've added approximately 240 tests to check the ESM and CJS builds for all the drivers we have. You can check them here
- Fixed [BUG]: Type Error in PgTransaction Missing $client Property After Upgrading to drizzle-orm@0.35.1
- Fixed [BUG]: New critical Build error drizzle 0.35.0 deploying on Cloudflare
v0.35.1
- Updated internal versions for the drizzle-kit and drizzle-orm packages. Changes were introduced in the last minor release, and you are required to upgrade both packages to ensure they work as expected
v0.35.0
Important change after 0.34.0 release
Updated the init Drizzle database API
The API from version 0.34.0 turned out to be unusable and needs to be changed. You can read more about our decisions in this discussion
If you still want to use the new API introduced in 0.34.0, which can create driver clients for you under the hood, you can now do so
import { drizzle } from "drizzle-orm/node-postgres";
const db = drizzle(process.env.DATABASE_URL);
// or
const db = drizzle({
connection: process.env.DATABASE_URL
});
const db = drizzle({
connection: {
user: "...",
password: "...",
host: "...",
port: 4321,
db: "...",
},
});
// if you need to pass logger or schema
const db = drizzle({
connection: process.env.DATABASE_URL,
logger: true,
schema: schema,
});
in order to not introduce breaking change - we will still leave support for deprecated API until V1 release.
It will degrade autocomplete performance in connection params due to DatabaseDriver
| ConnectionParams
types collision,
but that's a decent compromise against breaking changes
import { drizzle } from "drizzle-orm/node-postgres";
import { Pool } from "pg";
const client = new Pool({ connectionString: process.env.DATABASE_URL });
const db = drizzle(client); // deprecated but available
// new version
const db = drizzle({
client: client,
});
New Features
New .orderBy() and .limit() functions in update and delete statements SQLite and MySQL
You now have more options for the update
and delete
query builders in MySQL and SQLite
Example
await db.update(usersTable).set({ verified: true }).limit(2).orderBy(asc(usersTable.name));
await db.delete(usersTable).where(eq(usersTable.verified, false)).limit(1).orderBy(asc(usersTable.name));
drizzle.mock()
function
New There were cases where you didn't need to provide a driver to the Drizzle object, and this served as a workaround
const db = drizzle({} as any)
Now you can do this using a mock function
const db = drizzle.mock()
There is no valid production use case for this, but we used it in situations where we needed to check types, etc., without making actual database calls or dealing with driver creation. If anyone was using it, please switch to using mocks now
Internal updates
- Upgraded TS in codebase to the version 5.6.3
Bug fixes
v0.34.1
- Fixed dynamic imports for CJS and MJS in the
/connect
module
v0.34.0
Breaking changes and migrate guide for Turso users
If you are using Turso and libsql, you will need to upgrade your drizzle.config
and @libsql/client
package.
- This version of drizzle-orm will only work with
@libsql/client@0.10.0
or higher if you are using themigrate
function. For other use cases, you can continue using previous versions(But the suggestion is to upgrade) To install the latest version, use the command:
npm i @​libsql/client@latest
- Previously, we had a common
drizzle.config
for SQLite and Turso users, which allowed a shared strategy for both dialects. Starting with this release, we are introducing the turso dialect in drizzle-kit. We will evolve and improve Turso as a separate dialect with its own migration strategies.
Before
import { defineConfig } from "drizzle-kit";
export default defineConfig({
dialect: "sqlite",
schema: "./schema.ts",
out: "./drizzle",
dbCredentials: {
url: "database.db",
},
breakpoints: true,
verbose: true,
strict: true,
});
After
import { defineConfig } from "drizzle-kit";
export default defineConfig({
dialect: "turso",
schema: "./schema.ts",
out: "./drizzle",
dbCredentials: {
url: "database.db",
},
breakpoints: true,
verbose: true,
strict: true,
});
If you are using only SQLite, you can use dialect: "sqlite"
LibSQL/Turso and Sqlite migration updates
SQLite "generate" and "push" statements updates
Starting from this release, we will no longer generate comments like this:
'/*\n SQLite does not support "Changing existing column type" out of the box, we do not generate automatic migration for that, so it has to be done manually'
+ '\n Please refer to: https://www.techonthenet.com/sqlite/tables/alter_table.php'
+ '\n https://www.sqlite.org/lang_altertable.html'
+ '\n https://stackoverflow.com/questions/2083543/modify-a-columns-type-in-sqlite3'
+ "\n\n Due to that we don't generate migration automatically and it has to be done manually"
+ '\n*/'
We will generate a set of statements, and you can decide if it's appropriate to create data-moving statements instead. Here is an example of the SQL file you'll receive now:
PRAGMA foreign_keys=OFF;
--> statement-breakpoint
CREATE TABLE `__new_worker` (
`id` integer PRIMARY KEY NOT NULL,
`name` text NOT NULL,
`salary` text NOT NULL,
`job_id` integer,
FOREIGN KEY (`job_id`) REFERENCES `job`(`id`) ON UPDATE no action ON DELETE no action
);
--> statement-breakpoint
INSERT INTO `__new_worker`("id", "name", "salary", "job_id") SELECT "id", "name", "salary", "job_id" FROM `worker`;
--> statement-breakpoint
DROP TABLE `worker`;
--> statement-breakpoint
ALTER TABLE `__new_worker` RENAME TO `worker`;
--> statement-breakpoint
PRAGMA foreign_keys=ON;
LibSQL/Turso "generate" and "push" statements updates
Since LibSQL supports more ALTER statements than SQLite, we can generate more statements without recreating your schema and moving all the data, which can be potentially dangerous for production environments.
LibSQL and Turso will now have a separate dialect in the Drizzle config file, meaning that we will evolve Turso and LibSQL independently from SQLite and will aim to support as many features as Turso/LibSQL offer.
With the updated LibSQL migration strategy, you will have the ability to:
- Change Data Type: Set a new data type for existing columns.
- Set and Drop Default Values: Add or remove default values for existing columns.
- Set and Drop NOT NULL: Add or remove the NOT NULL constraint on existing columns.
- Add References to Existing Columns: Add foreign key references to existing columns
You can find more information in the LibSQL documentation
LIMITATIONS
- Dropping foreign key will cause table recreation.
This is because LibSQL/Turso does not support dropping this type of foreign key.
CREATE TABLE `users` (
`id` integer NOT NULL,
`name` integer,
`age` integer PRIMARY KEY NOT NULL
FOREIGN KEY (`name`) REFERENCES `users1`("id") ON UPDATE no action ON DELETE no action
);
-
If the table has indexes, altering columns will cause index recreation: Drizzle-Kit will drop the indexes, modify the columns, and then create the indexes.
-
Adding or dropping composite foreign keys is not supported and will cause table recreation.
-
Primary key columns can not be altered and will cause table recreation.
-
Altering columns that are part of foreign key will cause table recreation.
NOTES
- You can create a reference on any column type, but if you want to insert values, the referenced column must have a unique index or primary key.
CREATE TABLE parent(a PRIMARY KEY, b UNIQUE, c, d, e, f);
CREATE UNIQUE INDEX i1 ON parent(c, d);
CREATE INDEX i2 ON parent(e);
CREATE UNIQUE INDEX i3 ON parent(f COLLATE nocase);
CREATE TABLE child1(f, g REFERENCES parent(a)); -- Ok
CREATE TABLE child2(h, i REFERENCES parent(b)); -- Ok
CREATE TABLE child3(j, k, FOREIGN KEY(j, k) REFERENCES parent(c, d)); -- Ok
CREATE TABLE child4(l, m REFERENCES parent(e)); -- Error!
CREATE TABLE child5(n, o REFERENCES parent(f)); -- Error!
CREATE TABLE child6(p, q, FOREIGN KEY(p, q) REFERENCES parent(b, c)); -- Error!
CREATE TABLE child7(r REFERENCES parent(c)); -- Error!
NOTE: The foreign key for the table child5 is an error because, although the parent key column has a unique index, the index uses a different collating sequence.
See more: https://www.sqlite.org/foreignkeys.html
A new and easy way to start using drizzle
Current and the only way to do, is to define client yourself and pass it to drizzle
const client = new Pool({ url: '' });
drizzle(client, { logger: true });
But we want to introduce you to a new API, which is a simplified method in addition to the existing one.
Most clients will have a few options to connect, starting with the easiest and most common one, and allowing you to control your client connection as needed.
Let's use node-postgres
as an example, but the same pattern can be applied to all other clients
// Finally, one import for all available clients and dialects!
import { drizzle } from 'drizzle-orm/connect'
// Choose a client and use a connection URL — nothing else is needed!
const db1 = await drizzle("node-postgres", process.env.POSTGRES_URL);
// If you need to pass a logger, schema, or other configurations, you can use an object and specify the client-specific URL in the connection
const db2 = await drizzle("node-postgres", {
connection: process.env.POSTGRES_URL,
logger: true
});
// And finally, if you need to use full client/driver-specific types in connections, you can use a URL or host/port/etc. as an object inferred from the underlying client connection types
const db3 = await drizzle("node-postgres", {
connection: {
connectionString: process.env.POSTGRES_URL,
},
});
const db4 = await drizzle("node-postgres", {
connection: {
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
host: process.env.DB_HOST,
port: process.env.DB_PORT,
database: process.env.DB_NAME,
ssl: true,
},
});
A few clients will have a slightly different API due to their specific behavior. Let's take a look at them:
For aws-data-api-pg
, Drizzle will require resourceArn
, database
, and secretArn
, along with any other AWS Data API client types for the connection, such as credentials, region, etc.
drizzle("aws-data-api-pg", {
connection: {
resourceArn: "",
database: "",
secretArn: "",
},
});
For d1
, the CloudFlare Worker types as described in the documentation here will be required.
drizzle("d1", {
connection: env.DB // CloudFlare Worker Types
})
For vercel-postgres
, nothing is needed since Vercel automatically retrieves the POSTGRES_URL
from the .env
file. You can check this documentation for more info
drizzle("vercel-postgres")
Note that the first example with the client is still available and not deprecated. You can use it if you don't want to await the drizzle object. The new way of defining drizzle is designed to make it easier to import from one place and get autocomplete for all the available clients
Optional names for columns and callback in drizzle table
We believe that schema definition in Drizzle is extremely powerful and aims to be as close to SQL as possible while adding more helper functions for JS runtime values.
However, there are a few areas that could be improved, which we addressed in this release. These include:
- Unnecessary database column names when TypeScript keys are essentially just copies of them
- A callback that provides all column types available for a specific table.
Let's look at an example with PostgreSQL (this applies to all the dialects supported by Drizzle)
Previously
import { boolean, pgTable, text, uuid } from "drizzle-orm/pg-core";
export const ingredients = pgTable("ingredients", {
id: uuid("id").defaultRandom().primaryKey(),
name: text("name").notNull(),
description: text("description"),
inStock: boolean("in_stock").default(true),
});
The previous table definition will still be valid in the new release, but it can be replaced with this instead
import { pgTable } from "drizzle-orm/pg-core";
export const ingredients = pgTable("ingredients", (t) => ({
id: t.uuid().defaultRandom().primaryKey(),
name: t.text().notNull(),
description: t.text(),
inStock: t.boolean("in_stock").default(true),
}));
casing
param in drizzle-orm
and drizzle-kit
New There are more improvements you can make to your schema definition. The most common way to name your variables in a database and in TypeScript code is usually snake_case
in the database and camelCase
in the code. For this case, in Drizzle, you can now define a naming strategy in your database to help Drizzle map column keys automatically. Let's take a table from the previous example and make it work with the new casing API in Drizzle
Table can now become:
import { pgTable } from "drizzle-orm/pg-core";
export const ingredients = pgTable("ingredients", (t) => ({
id: t.uuid().defaultRandom().primaryKey(),
name: t.text().notNull(),
description: t.text(),
inStock: t.boolean().default(true),
}));
As you can see, inStock
doesn't have a database name alias, but by defining the casing configuration at the connection level, all queries will automatically map it to snake_case
const db = await drizzle('node-postgres', { connection: '', casing: 'snake_case' })
For drizzle-kit
migrations generation you should also specify casing
param in drizzle config, so you can be sure you casing strategy will be applied to drizzle-kit as well
import { defineConfig } from "drizzle-kit";
export default defineConfig({
dialect: "postgresql",
schema: "./schema.ts",
dbCredentials: {
url: "postgresql://postgres:password@localhost:5432/db",
},
casing: "snake_case",
});
New "count" API
Before this release to count entities in a table, you would need to do this:
const res = await db.select({ count: sql`count(*)` }).from(users);
const count = res[0].count;
The new API will look like this:
// how many users are in the database
const count: number = await db.$count(users);
// how many users with the name "Dan" are in the database
const count: number = await db.$count(users, eq(name, "Dan"));
This can also work as a subquery and within relational queries
const users = await db.select({
...users,
postsCount: db.$count(posts, eq(posts.authorId, users.id))
});
const users = await db.query.users.findMany({
extras: {
postsCount: db.$count(posts, eq(posts.authorId, users.id))
}
})
Ability to execute raw strings instead of using SQL templates for raw queries
Previously, you would have needed to do this to execute a raw query with Drizzle
import { sql } from 'drizzle-orm'
db.execute(sql`select * from ${users}`);
// or
db.execute(sql.raw(`select * from ${users}`));
You can now do this as well
db.execute('select * from users')
You can now access the driver client from Drizzle db instance
const client = db.$client;
Configuration
-
If you want to rebase/retry this MR, check this box
This MR has been generated by Renovate Bot.