Skip to content

[BUG]: migrate command creates tables in the wrong postgres schema #5889

@lmgraf

Description

@lmgraf

Report hasn't been filed before.

  • I have verified that the bug I'm about to report hasn't been filed before.

What version of drizzle-orm are you using?

1.0.0@beta.22

What version of drizzle-kit are you using?

1.0.0@beta.22

Other packages

No response

Describe the Bug

Affected Setups

  • Drizzle ORM connecting to any PostgreSQL database
  • I only tested it using the node-postgres (pg) driver

What is the undesired behavior?

  • The Problem: When migrations.schema inside drizzle.config.ts matches the postgres db username, drizzle-kit migrate creates all user defined tables on the "$user" schema, instead of the expected "public" schema. (EDITED)
  • This does NOT happen, when migrations.schema is set to something other than the db username "$user".
  • Side Effect: The schema field inside snapshot.json still points to "public", even though the tables were actually created on the "drizzle" schema.

What are the steps to reproduce it?

  1. Setup a postgres Database with the owner drizzle
  2. Set migrations.schema in drizzle.config.ts to the same value as the db username that owns the db ("drizzle"):
import { config } from "dotenv";
import { defineConfig } from "drizzle-kit";

config({ path: ".env" });

export default defineConfig({
  schema: "./src/db/schema.ts",
  out: "./src/db/migrations",
  dialect: "postgresql",
  dbCredentials: { url: process.env.DATABASE_URL! },
  migrations: { schema: "drizzle" }, // Or just set it to what the db username is, they just have to be exactly the same
});
  1. Define a standard table in schema.ts without using pgSchema:
import { pgTable as table, text } from "drizzle-orm/pg-core";

export const user = table("user", {
  id: text("id").primaryKey(),
  name: text("name").notNull(),
  email: text("email").notNull().unique(),
});
  1. Run drizzle-kit generate. Notice how the generated sql is correct: It's "user", and NOT "drizzle"."user"

Generated SQL src/db/migrations/[timestamp]/migration.sql:

CREATE TABLE "user" (
	"id" text PRIMARY KEY,
	"name" text NOT NULL,
	"email" text NOT NULL UNIQUE,
);

Snapshot src/db/migrations/[timestamp]/snapshot.json:

{
  "version": "8",
  "dialect": "postgres",
  "id": "a03e228c-9e0f-4469-adfe-9692249ef1f9",
  "prevIds": [
    "00000000-0000-0000-0000-000000000000"
  ],
  "ddl": [
    {
      "isRlsEnabled": false,
      "name": "user",
      "entityType": "tables",
      "schema": "public", // <- notice EXPECTED schema
    },
    {
      "type": "text",
    /* [...] */
      "name": "id",
      "entityType": "columns",
      "schema": "public", // <- notice EXPECTED schema
      "table": "user"
    },
    {
      "type": "text",
    /* [...] */
      "name": "name",
      "entityType": "columns",
      "schema": "public", // <- notice EXPECTED schema
      "table": "user"
    },
    {
      "type": "text",
    /* [...] */
      "name": "email",
      "entityType": "columns",
      "schema": "public", // <- notice EXPECTED schema
      "table": "user"
    }
    /* [... ETC ...] */
  ],
  "renames": []
}
  1. Now run drizzle-kit migrate.
  2. Check the database relations using \d in psql. The user table will be defined on the drizzle schema, entirely contradicting the snapshot.json which defines it under public.

DATABASE REALITY:

                     List of relations
 Schema  |            Name             |   Type   |  Owner
---------+-----------------------------+----------+---------
 drizzle | __drizzle_migrations        | table    | drizzle
 drizzle | __drizzle_migrations_id_seq | sequence | drizzle
 drizzle | user                        | table    | drizzle
    ^ 
INCORRECT
  1. Optional: To prove that this only happens when migrations.schema is set to "drizzle", execute DROP DATABASE example; and start again at step 1. But now set migrations.schema to something other than the db username or "public" and observe how the issue goes away. BEWARE: If you do not drop the database, the bug persists. Meaning, if you simply drop all the tables or the "drizzle" schema, and then re-run the migrations using drizzle-kit migrate, then migrations.schema will keep controlling the schema of all user defined tables.

What is the desired result?

DESIRED RESULT:

                     List of relations
 Schema  |            Name             |   Type   |  Owner
---------+-----------------------------+----------+---------
 drizzle | __drizzle_migrations        | table    | drizzle
 drizzle | __drizzle_migrations_id_seq | sequence | drizzle
 public  | user                        | table    | drizzle
    ^ 
 CORRECT
  1. The migrations.schema configuration property should only ever dictate the schema for Drizzle's internal migration tables and sequences, namely: the __drizzle_migrations table and the __drizzle_migrations_id_seq sequence

  2. Application tables defined without an explicit pgSchema layout should ALWAYS respect the database driver's native environment or fallback to public, instead of the schema specified in config.migrations.schema.

  3. The generated snapshot.json should always be in sync with what gets actually created in the database (only the schema property is wrong in this case).

Workarounds

Workaround 1

Add the following code to the top of the generated migration.sql file:

CREATE SCHEMA IF NOT EXISTS public;
SET search_path TO public;

Workaround 2

(if you don't want to manually edit migration.sql files)
Set config.migrations.schema to something other than "drizzle" (e.g. "public"), to create all tables on the public schema, and thus remove the schema mismatch between the database reality and the snapshot.json file.

Related issues

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions