Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Snyk] Upgrade drizzle-orm from 0.30.1 to 0.32.0 #1

Merged
merged 1 commit into from
Aug 15, 2024

Conversation

zntb
Copy link
Owner

@zntb zntb commented Aug 2, 2024

snyk-top-banner

Snyk has created this PR to upgrade drizzle-orm from 0.30.1 to 0.32.0.

ℹ️ Keep your dependencies up-to-date. This makes it easier to fix existing vulnerabilities and to more quickly identify and fix newly disclosed vulnerabilities when they affect your project.


  • The recommended version is 95 versions ahead of your current version.

  • The recommended version was released on 23 days ago.

Release notes
Package name: drizzle-orm
  • 0.32.0 - 2024-07-10

    Release notes for drizzle-orm@0.32.0 and drizzle-kit@0.23.0

    It's not mandatory to upgrade both packages, but if you want to use the new features in both queries and migrations, you will need to upgrade both packages

    New Features

    🎉 MySQL $returningId() function

    MySQL itself doesn't have native support for RETURNING after using INSERT. There is only one way to do it for primary keys with autoincrement (or serial) types, where you can access insertId and affectedRows fields. We've prepared an automatic way for you to handle such cases with Drizzle and automatically receive all inserted IDs as separate objects

    import { boolean, int, text, mysqlTable } from 'drizzle-orm/mysql-core';

    const usersTable = mysqlTable('users', {
    id: int('id').primaryKey(),
    name: text('name').notNull(),
    verified: boolean('verified').notNull().default(false),
    });

    const result = await db.insert(usersTable).values([{ name: 'John' }, { name: 'John1' }]).$returningId();
    // ^? { id: number }[]

    Also with Drizzle, you can specify a primary key with $default function that will generate custom primary keys at runtime. We will also return those generated keys for you in the $returningId() call

    import { varchar, text, mysqlTable } from 'drizzle-orm/mysql-core';
    import { createId } from '@ paralleldrive/cuid2';

    const usersTableDefFn = mysqlTable('users_default_fn', {
    customId: varchar('id', { length: 256 }).primaryKey().$defaultFn(createId),
    name: text('name').notNull(),
    });

    const result = await db.insert(usersTableDefFn).values([{ name: 'John' }, { name: 'John1' }]).$returningId();
    // ^? { customId: string }[]

    If there is no primary keys -> type will be {}[] for such queries

    🎉 PostgreSQL Sequences

    You can now specify sequences in Postgres within any schema you need and define all the available properties

    Example
    import { pgSchema, pgSequence } from "drizzle-orm/pg-core";

    // No params specified
    export const customSequence = pgSequence("name");

    // Sequence with params
    export const customSequence = pgSequence("name", {
    startWith: 100,
    maxValue: 10000,
    minValue: 100,
    cycle: true,
    cache: 10,
    increment: 2
    });

    // Sequence in custom schema
    export const customSchema = pgSchema('custom_schema');

    export const customSequence = customSchema.sequence("name");

    🎉 PostgreSQL Identity Columns

    Source: As mentioned, the serial type in Postgres is outdated and should be deprecated. Ideally, you should not use it. Identity columns are the recommended way to specify sequences in your schema, which is why we are introducing the identity columns feature

    Example
    import { pgTable, integer, text } from 'drizzle-orm/pg-core'

    export const ingredients = pgTable("ingredients", {
    id: integer("id").primaryKey().generatedAlwaysAsIdentity({ startWith: 1000 }),
    name: text("name").notNull(),
    description: text("description"),
    });

    You can specify all properties available for sequences in the .generatedAlwaysAsIdentity() function. Additionally, you can specify custom names for these sequences

    PostgreSQL docs reference.

    🎉 PostgreSQL Generated Columns

    You can now specify generated columns on any column supported by PostgreSQL to use with generated columns

    Example with generated column for tsvector

    Note: we will add tsVector column type before latest release

    import { SQL, sql } from "drizzle-orm";
    import { customType, index, integer, pgTable, text } from "drizzle-orm/pg-core";

    const tsVector = customType<{ data: string }>({
    dataType() {
    return "tsvector";
    },
    });

    export const test = pgTable(
    "test",
    {
    id: integer("id").primaryKey().generatedAlwaysAsIdentity(),
    content: text("content"),
    contentSearch: tsVector("content_search", {
    dimensions: 3,
    }).generatedAlwaysAs(
    (): SQL => sqlto_tsvector('english', <span class="pl-s1"><span class="pl-kos">${</span><span class="pl-s1">test</span><span class="pl-kos">.</span><span class="pl-c1">content</span><span class="pl-kos">}</span></span>)
    ),
    },
    (t) => ({
    idx: index("idx_content_search").using("gin", t.contentSearch),
    })
    );

    In case you don't need to reference any columns from your table, you can use just sql template or a string

    export const users = pgTable("users", {
      id: integer("id"),
      name: text("name"),
      generatedName: text("gen_name").generatedAlwaysAs(sql`hello world!`),
      generatedName1: text("gen_name1").generatedAlwaysAs("hello world!"),
    }),

    🎉 MySQL Generated Columns

    You can now specify generated columns on any column supported by MySQL to use with generated columns

    You can specify both stored and virtual options, for more info you can check MySQL docs

    Also MySQL has a few limitation for such columns usage, which is described here

    Drizzle Kit will also have limitations for push command:

    1. You can't change the generated constraint expression and type using push. Drizzle-kit will ignore this change. To make it work, you would need to drop the column, push, and then add a column with a new expression. This was done due to the complex mapping from the database side, where the schema expression will be modified on the database side and, on introspection, we will get a different string. We can't be sure if you changed this expression or if it was changed and formatted by the database. As long as these are generated columns and push is mostly used for prototyping on a local database, it should be fast to drop and create generated columns. Since these columns are generated, all the data will be restored

    2. generate should have no limitations

    Example
    export const users = mysqlTable("users", {
      id: int("id"),
      id2: int("id2"),
      name: text("name"),
      generatedName: text("gen_name").generatedAlwaysAs(
        (): SQL => sql`${schema2.users.name} || 'hello'`,
        { mode: "stored" }
      ),
      generatedName1: text("gen_name1").generatedAlwaysAs(
        (): SQL => sql`${schema2.users.name} || 'hello'`,
        { mode: "virtual" }
      ),
    }),

    In case you don't need to reference any columns from your table, you can use just sql template or a string in .generatedAlwaysAs()

    🎉 SQLite Generated Columns

    You can now specify generated columns on any column supported by SQLite to use with generated columns

    You can specify both stored and virtual options, for more info you can check SQLite docs

    Also SQLite has a few limitation for such columns usage, which is described here

    Drizzle Kit will also have limitations for push and generate command:

    1. You can't change the generated constraint expression with the stored type in an existing table. You would need to delete this table and create it again. This is due to SQLite limitations for such actions. We will handle this case in future releases (it will involve the creation of a new table with data migration).

    2. You can't add a stored generated expression to an existing column for the same reason as above. However, you can add a virtual expression to an existing column.

    3. You can't change a stored generated expression in an existing column for the same reason as above. However, you can change a virtual expression.

    4. You can't change the generated constraint type from virtual to stored for the same reason as above. However, you can change from stored to virtual.

    New Drizzle Kit features

    🎉 Migrations support for all the new orm features

    PostgreSQL sequences, identity columns and generated columns for all dialects

    🎉 New flag --force for drizzle-kit push

    You can auto-accept all data-loss statements using the push command. It's only available in CLI parameters. Make sure you always use it if you are fine with running data-loss statements on your database

    🎉 New migrations flag prefix

    You can now customize migration file prefixes to make the format suitable for your migration tools:

    • index is the default type and will result in 0001_name.sql file names;
    • supabase and timestamp are equal and will result in 20240627123900_name.sql file names;
    • unix will result in unix seconds prefixes 1719481298_name.sql file names;
    • none will omit the prefix completely;
    Example: Supabase migrations format
    import { defineConfig } from "drizzle-kit";

    export default defineConfig({
    dialect: "postgresql",
    migrations: {
    prefix: 'supabase'
    }
    });




  • 0.32.0-e7cf338 - 2024-06-25


  • 0.32.0-d0d6436 - 2024-06-27


  • 0.32.0-af7ce99 - 2024-06-17


  • 0.32.0-aaf764c - 2024-07-09


  • 0.32.0-85c8008 - 2024-06-24


  • 0.32.0-857ba54 - 2024-06-11


  • 0.32.0-81cb794 - 2024-06-22


  • 0.32.0-7721c7c - 2024-06-22


  • 0.32.0-7612dda - 2024-07-09


  • 0.32.0-5cc2ae0 - 2024-06-27


  • 0.32.0-4ed01aa - 2024-06-12


  • 0.32.0-0fdaa9e - 2024-06-25


  • 0.32.0-0d48b64 - 2024-06-07


  • 0.32.0-0a6885d - 2024-06-13


  • 0.32.0-55471 - 2024-06-12


  • 0.31.4 - 2024-07-08

    • Mark prisma clients package as optional - thanks @ Cherry
  • 0.31.3 - 2024-07-08

    Bug fixed

    • 🛠️ Fixed RQB behavior for tables with same names in different schemas
    • 🛠️ Fixed [BUG]: Mismatched type hints when using RDS Data API - #2097

    New Prisma-Drizzle extension

    import { PrismaClient } from '@ prisma/client';
    import { drizzle } from 'drizzle-orm/prisma/pg';
    import { User } from './drizzle';

    const prisma = new PrismaClient().$extends(drizzle());
    const users = await prisma.$drizzle.select().from(User);

    For more info, check docs: https://orm.drizzle.team/docs/prisma

  • 0.31.3-a90773c - 2024-07-08
  • 0.31.2 - 2024-06-07
    • 🎉 Added support for TiDB Cloud Serverless driver:

      import { connect } from '@ tidbcloud/serverless';
      import { drizzle } from 'drizzle-orm/tidb-serverless';

      const client = connect({ url: '...' });
      const db = drizzle(client);
      await db.select().from(...);

  • 0.31.2-f9f4c2e - 2024-06-09
  • 0.31.2-ee089d9 - 2024-07-06
  • 0.31.2-c59440c - 2024-06-09
  • 0.31.2-bd14b3f - 2024-06-07
  • 0.31.2-b59e0a5 - 2024-06-11
  • 0.31.2-b59b8f5 - 2024-07-08
  • 0.31.2-b1c8d15 - 2024-06-09
  • 0.31.2-aaea9bd - 2024-06-27
  • 0.31.2-86ec973 - 2024-06-07
  • 0.31.2-5b29cb4 - 2024-06-06
  • 0.31.1 - 2024-06-04

    New Features

    Live Queries 🎉

    For a full explanation about Drizzle + Expo welcome to discussions

    As of v0.31.1 Drizzle ORM now has native support for Expo SQLite Live Queries!
    We've implemented a native useLiveQuery React Hook which observes necessary database changes and automatically re-runs database queries. It works with both SQL-like and Drizzle Queries:

    import { useLiveQuery, drizzle } from 'drizzle-orm/expo-sqlite';
    import { openDatabaseSync } from 'expo-sqlite/next';
    import { users } from './schema';
    import { Text } from 'react-native';

    const expo = openDatabaseSync('db.db', { enableChangeListener: true }); // <-- enable change listeners
    const db = drizzle(expo);

    const App = () => {
    // Re-renders automatically when data changes
    const { data } = useLiveQuery(db.select().from(users));

    // const { data, error, updatedAt } = useLiveQuery(db.query.users.findFirst());
    // const { data, error, updatedAt } = useLiveQuery(db.query.users.findMany());

    return <Text>{JSON.stringify(data)}</Text>;
    };

    export default App;

    We've intentionally not changed the API of ORM itself to stay with conventional React Hook API, so we have useLiveQuery(databaseQuery) as opposed to db.select().from(users).useLive() or db.query.users.useFindMany()

    We've also decided to provide data, error and updatedAt fields as a result of hook for concise explicit error handling following practices of React Query and Electric SQL

  • 0.31.1-7a4cc2d - 2024-06-04
  • 0.31.1-26a7171 - 2024-05-30
  • 0.31.0 - 2024-05-31

    Breaking changes

    Note: drizzle-orm@0.31.0 can be used with drizzle-kit@0.22.0 or higher. The same applies to Drizzle Kit. If you run a Drizzle Kit command, it will check and prompt you for an upgrade (if needed). You can check for Drizzle Kit updates. below

    PostgreSQL indexes API was changed

    The previous Drizzle+PostgreSQL indexes API was incorrect and was not aligned with the PostgreSQL documentation. The good thing is that it was not used in queries, and drizzle-kit didn't support all properties for indexes. This means we can now change the API to the correct one and provide full support for it in drizzle-kit

    Previous API

    • No way to define SQL expressions inside .on.
    • .using and .on in our case are the same thing, so the API is incorrect here.
    • .asc(), .desc(), .nullsFirst(), and .nullsLast() should be specified for each column or expression on indexes, but not on an index itself.
    // Index declaration reference
    index('name')
      .on(table.column1, table.column2, ...) or .onOnly(table.column1, table.column2, ...)
      .concurrently()
      .using(sql``) // sql expression
      .asc() or .desc()
      .nullsFirst() or .nullsLast()
      .where(sql``) // sql expression

    Current API

    )
    .with({ fillfactor: '70' })

    // Second Example, with .using()
    index('name')
    .using('btree', table.column1.asc(), sqllower(<span class="pl-s1"><span class="pl-kos">${</span><span class="pl-s1">table</span><span class="pl-kos">.</span><span class="pl-c1">column2</span><span class="pl-kos">}</span></span>), table.column1.op('text_ops'))
    .where(sql``) // sql expression
    .with({ fillfactor: '70' })

    New Features

    🎉 "pg_vector" extension support

    There is no specific code to create an extension inside the Drizzle schema. We assume that if you are using vector types, indexes, and queries, you have a PostgreSQL database with the pg_vector extension installed.

    You can now specify indexes for pg_vector and utilize pg_vector functions for querying, ordering, etc.

    Let's take a few examples of pg_vector indexes from the pg_vector docs and translate them to Drizzle

    L2 distance, Inner product and Cosine distance

    // CREATE INDEX ON items USING hnsw (embedding vector_l2_ops);
    // CREATE INDEX ON items USING hnsw (embedding vector_ip_ops);
    // CREATE INDEX ON items USING hnsw (embedding vector_cosine_ops);

    const table = pgTable('items', {
    embedding: vector('embedding', { dimensions: 3 })
    }, (table) => ({
    l2: index('l2_index').using('hnsw', table.embedding.op('vector_l2_ops'))
    ip: index('ip_index').using('hnsw', table.embedding.op('vector_ip_ops'))
    cosine: index('cosine_index').using('hnsw', table.embedding.op('vector_cosine_ops'))
    }))

    L1 distance, Hamming distance and Jaccard distance - added in pg_vector 0.7.0 version

    // CREATE INDEX ON items USING hnsw (embedding vector_l1_ops);
    // CREATE INDEX ON items USING hnsw (embedding bit_hamming_ops);
    // CREATE INDEX ON items USING hnsw (embedding bit_jaccard_ops);

    const table = pgTable('table', {
    embedding: vector('embedding', { dimensions: 3 })
    }, (table) => ({
    l1: index('l1_index').using('hnsw', table.embedding.op('vector_l1_ops'))
    hamming: index('hamming_index').using('hnsw', table.embedding.op('bit_hamming_ops'))
    bit: index('bit_jaccard_index').using('hnsw', table.embedding.op('bit_jaccard_ops'))
    }))

    For queries, you can use predefined functions for vectors or create custom ones using the SQL template operator.

    You can also use the following helpers:

    import { l2Distance, l1Distance, innerProduct,
    cosineDistance, hammingDistance, jaccardDistance } from 'drizzle-orm'

    l2Distance(table.column, [3, 1, 2]) // table.column <-> '[3, 1, 2]'
    l1Distance(table.column, [3, 1, 2]) // table.column <+> '[3, 1, 2]'

    innerProduct(table.column, [3, 1, 2]) // table.column <#> '[3, 1, 2]'
    cosineDistance(table.column, [3, 1, 2]) // table.column <=> '[3, 1, 2]'

    hammingDistance(table.column, '101') // table.column <~> '101'
    jaccardDistance(table.column, '101') // table.column <%> '101'

    If pg_vector has some other functions to use, you can replicate implimentation from existing one we have. Here is how it can be done

    export function l2Distance(
      column: SQLWrapper | AnyColumn,
      value: number[] | 

Snyk has created this PR to upgrade drizzle-orm from 0.30.1 to 0.32.0.

See this package in npm:
drizzle-orm

See this project in Snyk:
https://app.snyk.io/org/zntb/project/d308268f-afda-4966-85d9-095070fc0bd9?utm_source=github&utm_medium=referral&page=upgrade-pr
@zntb zntb merged commit b1b4d38 into main Aug 15, 2024
1 check passed
@zntb zntb deleted the snyk-upgrade-7aed2a96bc3ede75ee640a7e44a97a7b branch August 15, 2024 15:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants