Skip to content

Releases: drizzle-team/drizzle-orm

[email protected]

04 Dec 09:13
fc7f280
Compare
Choose a tag to compare
  • Fix SingleStore generate migrations command

0.37.0

03 Dec 14:06
9cf0ed2
Compare
Choose a tag to compare

New Dialects

🎉 SingleStore dialect is now available in Drizzle

Thanks to the SingleStore team for creating a PR with all the necessary changes to support the MySQL-compatible part of SingleStore. You can already start using it with Drizzle. The SingleStore team will also help us iterate through updates and make more SingleStore-specific features available in Drizzle

import { int, singlestoreTable, varchar } from 'drizzle-orm/singlestore-core';
import { drizzle } from 'drizzle-orm/singlestore';

export const usersTable = singlestoreTable('users_table', {
  id: int().primaryKey(),
  name: varchar({ length: 255 }).notNull(),
  age: int().notNull(),
  email: varchar({ length: 255 }).notNull().unique(),
});

...

const db = drizzle(process.env.DATABASE_URL!);

db.select()...

You can check out our Getting started guides to try SingleStore!

New Drivers

🎉 SQLite Durable Objects driver is now available in Drizzle

You can now query SQLite Durable Objects in Drizzle!

For the full example, please check our Get Started Section

/// <reference types="@cloudflare/workers-types" />
import { drizzle, DrizzleSqliteDODatabase } from 'drizzle-orm/durable-sqlite';
import { DurableObject } from 'cloudflare:workers'
import { migrate } from 'drizzle-orm/durable-sqlite/migrator';
import migrations from '../drizzle/migrations';
import { usersTable } from './db/schema';

export class MyDurableObject1 extends DurableObject {
  storage: DurableObjectStorage;
  db: DrizzleSqliteDODatabase<any>;

  constructor(ctx: DurableObjectState, env: Env) {
    super(ctx, env);
    this.storage = ctx.storage;
    this.db = drizzle(this.storage, { logger: false });
  }

    async migrate() {
        migrate(this.db, migrations);
    }

  async insert(user: typeof usersTable.$inferInsert) {
        await this.db.insert(usersTable).values(user);
    }

  async select() {
        return this.db.select().from(usersTable);
    }
}

export default {
  /**
   * This is the standard fetch handler for a Cloudflare Worker
   *
   * @param request - The request submitted to the Worker from the client
   * @param env - The interface to reference bindings declared in wrangler.toml
   * @param ctx - The execution context of the Worker
   * @returns The response to be sent back to the client
   */
  async fetch(request: Request, env: Env): Promise<Response> {
    const id: DurableObjectId = env.MY_DURABLE_OBJECT1.idFromName('durable-object');
    const stub = env.MY_DURABLE_OBJECT1.get(id);
    await stub.migrate();

    await stub.insert({
      name: 'John',
      age: 30,
      email: '[email protected]',
      })
    console.log('New user created!')
  
    const users = await stub.select();
    console.log('Getting all users from the database: ', users)

        return new Response();
    }
}

Bug fixes

[email protected]

03 Dec 13:14
9cf0ed2
Compare
Choose a tag to compare

New Dialects

🎉 SingleStore dialect is now available in Drizzle

Thanks to the SingleStore team for creating a PR with all the necessary changes to support the MySQL-compatible part of SingleStore. You can already start using it with Drizzle. The SingleStore team will also help us iterate through updates and make more SingleStore-specific features available in Drizzle

import 'dotenv/config';
import { defineConfig } from 'drizzle-kit';

export default defineConfig({
  dialect: 'singlestore',
  out: './drizzle',
  schema: './src/db/schema.ts',
  dbCredentials: {
    url: process.env.DATABASE_URL!,
  },
});

You can check out our Getting started guides to try SingleStore!

New Drivers

🎉 SQLite Durable Objects driver is now available in Drizzle

You can now query SQLite Durable Objects in Drizzle!

For the full example, please check our Get Started Section

import 'dotenv/config';
import { defineConfig } from 'drizzle-kit';
export default defineConfig({
  out: './drizzle',
  schema: './src/db/schema.ts',
  dialect: 'sqlite',
  driver: 'durable-sqlite',
});

0.36.4

22 Nov 11:34
03f6239
Compare
Choose a tag to compare

New Package: drizzle-seed

Note

drizzle-seed can only be used with [email protected] or higher. Versions lower than this may work at runtime but could have type issues and identity column issues, as this patch was introduced in [email protected]

Full Reference

The full API reference and package overview can be found in our official documentation

Basic Usage

In this example we will create 10 users with random names and ids

import { pgTable, integer, text } from "drizzle-orm/pg-core";
import { drizzle } from "drizzle-orm/node-postgres";
import { seed } from "drizzle-seed";

const users = pgTable("users", {
  id: integer().primaryKey(),
  name: text().notNull(),
});

async function main() {
  const db = drizzle(process.env.DATABASE_URL!);
  await seed(db, { users });
}

main();

Options

count

By default, the seed function will create 10 entities.
However, if you need more for your tests, you can specify this in the seed options object

await seed(db, schema, { count: 1000 });

seed

If you need a seed to generate a different set of values for all subsequent runs, you can define a different number
in the seed option. Any new number will generate a unique set of values

await seed(db, schema, { seed: 12345 });

The full API reference and package overview can be found in our official documentation

Features

Added OVERRIDING SYSTEM VALUE api to db.insert()

If you want to force you own values for GENERATED ALWAYS AS IDENTITY columns, you can use OVERRIDING SYSTEM VALUE

As PostgreSQL docs mentions

In an INSERT command, if ALWAYS is selected, a user-specified value is only accepted if the INSERT statement specifies OVERRIDING SYSTEM VALUE. If BY DEFAULT is selected, then the user-specified value takes precedence

await db.insert(identityColumnsTable).overridingSystemValue().values([
  { alwaysAsIdentity: 2 },
]);

Added .$withAuth() API for Neon HTTP driver

Using this API, Drizzle will send you an auth token to authorize your query. It can be used with any query available in Drizzle by simply adding .$withAuth() before it. This token will be used for a specific query

Examples

const token = 'HdncFj1Nm'

await db.$withAuth(token).select().from(usersTable);
await db.$withAuth(token).update(usersTable).set({ name: 'CHANGED' }).where(eq(usersTable.name, 'TARGET'))

Bug Fixes

0.36.3

15 Nov 14:43
30e5347
Compare
Choose a tag to compare

New Features

Support for UPDATE ... FROM in PostgreSQL and SQLite

As the SQLite documentation mentions:

Note

The UPDATE-FROM idea is an extension to SQL that allows an UPDATE statement to be driven by other tables in the database.
The "target" table is the specific table that is being updated. With UPDATE-FROM you can join the target table
against other tables in the database in order to help compute which rows need updating and what
the new values should be on those rows

Similarly, the PostgreSQL documentation states:

Note

A table expression allowing columns from other tables to appear in the WHERE condition and update expressions

Drizzle also supports this feature starting from this version

For example, current query:

await db
  .update(users)
  .set({ cityId: cities.id })
  .from(cities)
  .where(and(eq(cities.name, 'Seattle'), eq(users.name, 'John')))

Will generate this sql

update "users" set "city_id" = "cities"."id" 
from "cities" 
where ("cities"."name" = $1 and "users"."name" = $2)

-- params: [ 'Seattle', 'John' ]

You can also alias tables that are joined (in PG, you can also alias the updating table too).

const c = alias(cities, 'c');
await db
  .update(users)
  .set({ cityId: c.id })
  .from(c);

Will generate this sql

update "users" set "city_id" = "c"."id" 
from "cities" "c"

In PostgreSQL, you can also return columns from the joined tables.

const updatedUsers = await db
  .update(users)
  .set({ cityId: cities.id })
  .from(cities)
  .returning({ id: users.id, cityName: cities.name });

Will generate this sql

update "users" set "city_id" = "cities"."id" 
from "cities" 
returning "users"."id", "cities"."name"

Support for INSERT INTO ... SELECT in all dialects

As the SQLite documentation mentions:

Note

The second form of the INSERT statement contains a SELECT statement instead of a VALUES clause.
A new entry is inserted into the table for each row of data returned by executing the SELECT statement.
If a column-list is specified, the number of columns in the result of the SELECT must be the same as
the number of items in the column-list. Otherwise, if no column-list is specified, the number of
columns in the result of the SELECT must be the same as the number of columns in the table.
Any SELECT statement, including compound SELECTs and SELECT statements with ORDER BY and/or LIMIT clauses,
may be used in an INSERT statement of this form.

Caution

To avoid a parsing ambiguity, the SELECT statement should always contain a WHERE clause, even if that clause is simply "WHERE true", if the upsert-clause is present. Without the WHERE clause, the parser does not know if the token "ON" is part of a join constraint on the SELECT, or the beginning of the upsert-clause.

As the PostgreSQL documentation mentions:

Note

A query (SELECT statement) that supplies the rows to be inserted

And as the MySQL documentation mentions:

Note

With INSERT ... SELECT, you can quickly insert many rows into a table from the result of a SELECT statement, which can select from one or many tables

Drizzle supports the current syntax for all dialects, and all of them share the same syntax. Let's review some common scenarios and API usage.
There are several ways to use select inside insert statements, allowing you to choose your preferred approach:

  • You can pass a query builder inside the select function.
  • You can use a query builder inside a callback.
  • You can pass an SQL template tag with any custom select query you want to use

Query Builder

const insertedEmployees = await db
  .insert(employees)
  .select(
    db.select({ name: users.name }).from(users).where(eq(users.role, 'employee'))
  )
  .returning({
    id: employees.id,
    name: employees.name
  });
const qb = new QueryBuilder();
await db.insert(employees).select(
    qb.select({ name: users.name }).from(users).where(eq(users.role, 'employee'))
);

Callback

await db.insert(employees).select(
    () => db.select({ name: users.name }).from(users).where(eq(users.role, 'employee'))
);
await db.insert(employees).select(
    (qb) => qb.select({ name: users.name }).from(users).where(eq(users.role, 'employee'))
);

SQL template tag

await db.insert(employees).select(
    sql`select "users"."name" as "name" from "users" where "users"."role" = 'employee'`
);
await db.insert(employees).select(
    () => sql`select "users"."name" as "name" from "users" where "users"."role" = 'employee'`
);

0.36.2

14 Nov 10:57
2677718
Compare
Choose a tag to compare

[email protected]

14 Nov 10:24
2677718
Compare
Choose a tag to compare

0.36.1

06 Nov 20:10
83daf2d
Compare
Choose a tag to compare

[email protected]

06 Nov 19:33
83daf2d
Compare
Choose a tag to compare

Improvements

  • Added an OHM static imports checker to identify unexpected imports within a chain of imports in the drizzle-kit repo. For example, it checks if drizzle-orm is imported before drizzle-kit and verifies if the drizzle-orm import is available in your project.
  • Adding more columns to Supabase auth.users table schema - thanks @nicholasdly

Bug Fixes

[email protected]

06 Nov 13:32
8e98201
Compare
Choose a tag to compare