drizzle-team/drizzle-orm

[BUG]: Getting error when running migrations with LibSQL

Closed this issue · 1 comments

What version of drizzle-orm are you using?

0.30.10

What version of drizzle-kit are you using?

0.20.17

Describe the Bug

Hey Drizzle team, thanks for all your hard work and this awesome lib! I'm having an issue when using Drizzle kit with libsql. I get an error when trying to run migrations. It's probably just ignorance on my end and I just misconfigured something lol

Here is the error:

file:///Users/gvqz/dev/github/dinki/node_modules/.pnpm/@libsql+client@0.6.0/node_modules/@libsql/client/lib-esm/sqlite3.js:312
        return new LibsqlError(e.message, e.code, e.rawCode, e);
               ^

LibsqlError: SQLITE_ERROR: near "(": syntax error
    at mapSqliteError (file:///Users/gvqz/dev/github/dinki/node_modules/.pnpm/@libsql+client@0.6.0/node_modules/@libsql/client/lib-esm/sqlite3.js:312:16)
    at executeStmt (file:///Users/gvqz/dev/github/dinki/node_modules/.pnpm/@libsql+client@0.6.0/node_modules/@libsql/client/lib-esm/sqlite3.js:222:15)
    at file:///Users/gvqz/dev/github/dinki/node_modules/.pnpm/@libsql+client@0.6.0/node_modules/@libsql/client/lib-esm/sqlite3.js:72:24
    ... 4 lines matching cause stack trace ...
    at <anonymous> (/Users/gvqz/dev/github/dinki/scripts/migrate.ts:7:1) {
  code: 'SQLITE_ERROR',
  rawCode: 1,
  [cause]: SqliteError: near "(": syntax error
      at convertError (/Users/gvqz/dev/github/dinki/node_modules/.pnpm/libsql@0.3.18/node_modules/libsql/index.js:48:12)
      at Database.prepare (/Users/gvqz/dev/github/dinki/node_modules/.pnpm/libsql@0.3.18/node_modules/libsql/index.js:111:13)
      at executeStmt (file:///Users/gvqz/dev/github/dinki/node_modules/.pnpm/@libsql+client@0.6.0/node_modules/@libsql/client/lib-esm/sqlite3.js:193:28)
      at file:///Users/gvqz/dev/github/dinki/node_modules/.pnpm/@libsql+client@0.6.0/node_modules/@libsql/client/lib-esm/sqlite3.js:72:24
      at Array.map (<anonymous>)
      at Sqlite3Client.batch (file:///Users/gvqz/dev/github/dinki/node_modules/.pnpm/@libsql+client@0.6.0/node_modules/@libsql/client/lib-esm/sqlite3.js:68:38)
      at LibSQLSession.batch (/Users/gvqz/dev/github/dinki/node_modules/.pnpm/drizzle-orm@0.30.10_@libsql+client@0.6.0_@types+react@18.3.1_react@18.3.1/node_modules/src/libsql/session.ts:75:42)
      at migrate (/Users/gvqz/dev/github/dinki/node_modules/.pnpm/drizzle-orm@0.30.10_@libsql+client@0.6.0_@types+react@18.3.1_react@18.3.1/node_modules/src/libsql/migrator.ts:50:19)
      at <anonymous> (/Users/gvqz/dev/github/dinki/scripts/migrate.ts:7:1) {
    code: 'SQLITE_ERROR',
    rawCode: 1
  }
}

For reference here are my schemas:

import { relations, sql } from "drizzle-orm";
import {
  sqliteTable,
  text,
  integer,
  real,
  uniqueIndex,
} from "drizzle-orm/sqlite-core";
import { paddles } from "./paddle";
export const users = sqliteTable(
  "users",
  {
    id: integer("id").primaryKey(),
    fullName: text("full_name"),
    email: text("email").notNull().unique(),
    postalCode: text("postal_code"),
    dupr: real("dupr"),
    joinDate: integer("join_date", { mode: "timestamp" }).default(
      sql`unixepoch()`
    ),
  },
  (users) => ({ userEmailIdx: uniqueIndex("user_email_idx").on(users.email) })
);

export const usersRelations = relations(users, ({ many }) => ({
  paddles: many(paddles),
}));

export type User = typeof users.$inferSelect;
export type InsertUser = typeof users.$inferInsert;
import { sqliteTable, integer, uniqueIndex } from "drizzle-orm/sqlite-core";
import { relations } from "drizzle-orm";
import { User, users } from "./user";

export const paddles = sqliteTable(
  "paddles",
  {
    id: integer("id").primaryKey(),
    ownerId: integer("owner_id").references(() => users.id),
  },
  (paddles) => ({
    paddleOwnerIdx: uniqueIndex("paddle_owner_idx").on(paddles.ownerId),
  })
);

export const paddlesRelations = relations(paddles, ({ one }) => ({
  owner: one(users, {
    references: [users.id],
    fields: [paddles.ownerId],
  }),
}));

export type Paddle = typeof paddles.$inferSelect;
export type InsertPaddle = typeof paddles.$inferInsert;
export type PaddleWithOwner = Paddle & { owner: User };

And here is my migration:

import "dotenv/config";
import { migrate } from "drizzle-orm/libsql/migrator";
import { getClient, getDB } from "../app/.server/db/db";
const client = getClient();
const db = getDB(client);
// This will run migrations on the database, skipping the ones already applied
await migrate(db, { migrationsFolder: "./drizzle" });
// Don't forget to close the connection, otherwise the script will hang
client.close();

And the resulting migration after running pnpm drizzle-kit generate:sqlite:

CREATE TABLE `paddles` (
	`id` integer PRIMARY KEY NOT NULL,
	`owner_id` integer,
	FOREIGN KEY (`owner_id`) REFERENCES `users`(`id`) ON UPDATE no action ON DELETE no action
);
--> statement-breakpoint
CREATE TABLE `users` (
	`id` integer PRIMARY KEY NOT NULL,
	`full_name` text,
	`email` text NOT NULL,
	`postal_code` text,
	`dupr` real,
	`join_date` integer DEFAULT unixepoch()
);
--> statement-breakpoint
CREATE UNIQUE INDEX `paddle_owner_idx` ON `paddles` (`owner_id`);--> statement-breakpoint
CREATE UNIQUE INDEX `users_email_unique` ON `users` (`email`);--> statement-breakpoint
CREATE UNIQUE INDEX `user_email_idx` ON `users` (`email`);

Expected behavior

For it to apply migrations without crashing I hope haha.

Environment & setup

NodeJS v21.5.0
tsx v4.9.3
typescript v5.4.5

drizzle.config.ts:

import type { Config } from "drizzle-kit";
import { env } from "~/.server/env";
export default {
  schema: "./app/.server/db/schema/*",
  out: "./drizzle",
  driver: "turso", // 'pg' | 'mysql2' | 'better-sqlite' | 'libsql' | 'turso'
  dbCredentials: {
    url: env.DATABASE_URL,
    authToken: env.DATABASE_AUTH_TOKEN,
  },
} satisfies Config;

Lol I forgot the surrounding parens on my call to unixepoch in the default value on user.join_date.

Thanks for this awesome tool btw!