Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 27 additions & 4 deletions drizzle-kit/src/cli/commands/up-sqlite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ import { join } from 'path';
import { transformOnUpdateDelete } from 'src/dialects/sqlite/grammar';
import { nameForPk } from 'src/dialects/sqlite/grammar';
import { prepareOutFolder, validateWithReport } from 'src/utils/utils-node';
import { createDDL } from '../../dialects/sqlite/ddl';
import { createDDL, type SqliteEntity, type Table } from '../../dialects/sqlite/ddl';
import {
snapshotValidator,
sqliteSchemaV5,
type SQLiteSchemaV6,
sqliteSchemaV6,
Expand All @@ -32,9 +33,11 @@ export const upSqliteHandler = (out: string) => {

let result: SqliteSnapshot;
if (it.raw['version'] === '5') {
result = updateToV7(updateUpToV6(it.raw));
result = updateToV8(updateToV7(updateUpToV6(it.raw)));
} else if (it.raw['version'] === '6') {
result = updateToV7(sqliteSchemaV6.parse(it.raw));
result = updateToV8(updateToV7(sqliteSchemaV6.parse(it.raw)));
} else if (it.raw['version'] === '7') {
result = updateToV8(it.raw as SqliteSnapshotV7);
} else {
throw new Error(`unexpected version of SQLite snapshot: ${it.raw['version']}`);
}
Expand All @@ -51,11 +54,19 @@ export const upSqliteHandler = (out: string) => {
console.log("Everything's fine 🐶🔥");
};

export const updateToV7 = (snapshot: SQLiteSchemaV6): SqliteSnapshot => {
type SqliteEntityV7 = Exclude<SqliteEntity, { entityType: 'tables' }> | Omit<Table, 'isStrict'>;

export type SqliteSnapshotV7 = Omit<SqliteSnapshot, 'version' | 'ddl'> & {
version: '7';
ddl: SqliteEntityV7[];
};

export const updateToV7 = (snapshot: SQLiteSchemaV6): SqliteSnapshotV7 => {
const ddl = createDDL();
for (const table of Object.values(snapshot.tables)) {
ddl.tables.push({
name: table.name,
isStrict: false,
});

for (const column of Object.values(table.columns)) {
Expand Down Expand Up @@ -162,6 +173,18 @@ export const updateToV7 = (snapshot: SQLiteSchemaV6): SqliteSnapshot => {
};
};

export const updateToV8 = (snapshot: SqliteSnapshotV7): SqliteSnapshot => {
return snapshotValidator.strict({
...snapshot,
version: '8',
ddl: snapshot.ddl.map((entity) =>
entity.entityType === 'tables'
? { ...entity, isStrict: false }
: entity
),
});
};

const updateUpToV6 = (json: object): SQLiteSchemaV6 => {
const schema = sqliteSchemaV5.parse(json);

Expand Down
4 changes: 4 additions & 0 deletions drizzle-kit/src/cli/views.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@ export const sqliteSchemaError = (error: SqliteSchemaError): string => {
return `'${error.table}' table has no columns`;
}

if (error.type === 'invalid_strict_column_type') {
return `'${error.column}' column in STRICT table '${error.table}' has unsupported type '${error.columnType}'. Allowed types: INT, INTEGER, REAL, TEXT, BLOB, ANY`;
}

assertUnreachable(error);
};

Expand Down
7 changes: 5 additions & 2 deletions drizzle-kit/src/dialects/sqlite/convertor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ const createTable = convertor('create_table', (st) => {
statement += `CREATE TABLE \`${tableName}\` (\n`;
for (let i = 0; i < columns.length; i++) {
const column = columns[i];
const columnType = st.table.isStrict && /^text\(\d+\)$/i.test(column.type)
? 'text'
: column.type;

/*
https://www.sqlite.org/lang_createtable.html#the_generated_always_as_clause
Expand Down Expand Up @@ -71,7 +74,7 @@ const createTable = convertor('create_table', (st) => {

statement += '\t';
statement +=
`\`${column.name}\` ${column.type}${primaryKeyStatement}${autoincrementStatement}${defaultStatement}${generatedStatement}${notNullStatement}${unqiueConstraintPrefix}`;
`\`${column.name}\` ${columnType}${primaryKeyStatement}${autoincrementStatement}${defaultStatement}${generatedStatement}${notNullStatement}${unqiueConstraintPrefix}`;

statement += i === columns.length - 1 ? '' : ',\n';
}
Expand Down Expand Up @@ -118,7 +121,7 @@ const createTable = convertor('create_table', (st) => {
}

statement += `\n`;
statement += `);`;
statement += `)${st.table.isStrict ? ' STRICT' : ''};`;
statement += `\n`;
return statement;
});
Expand Down
39 changes: 29 additions & 10 deletions drizzle-kit/src/dialects/sqlite/ddl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import { nameForPk, nameForUnique } from './grammar';

export const createDDL = () => {
return create({
tables: {},
tables: {
isStrict: 'boolean',
},
columns: {
table: 'required',
type: 'string',
Expand Down Expand Up @@ -99,6 +101,7 @@ export type ViewColumn = { view: string; name: string; type: string; notNull: bo

export type TableFull = {
name: string;
isStrict: boolean;
columns: Column[];
indexes: Index[];
checks: CheckConstraint[];
Expand All @@ -109,6 +112,7 @@ export type TableFull = {

export const tableFromDDL = (name: string, ddl: SQLiteDDL): TableFull => {
const filter = { table: name } as const;
const table = ddl.tables.one({ name });
const columns = ddl.columns.list(filter);
const pk = ddl.pks.one(filter);
const fks = ddl.fks.list(filter);
Expand All @@ -117,6 +121,7 @@ export const tableFromDDL = (name: string, ddl: SQLiteDDL): TableFull => {
const indexes = ddl.indexes.list(filter);
return {
name,
isStrict: table?.isStrict ?? false,
columns,
pk,
fks,
Expand Down Expand Up @@ -169,6 +174,13 @@ export type ConflictCheck = {
name: string;
};

export type InvalidStrictColumnType = {
type: 'invalid_strict_column_type';
table: string;
column: string;
columnType: string;
};

export type SchemaError =
| ConflictTable
| ConflictView
Expand All @@ -178,16 +190,9 @@ export type SchemaError =
| ConflictUnique
| ConflictCheck
| ConflictIndex
| InvalidStrictColumnType
| TableNoColumns;

const count = <T>(arr: T[], predicate: (it: T) => boolean) => {
let count = 0;
for (const it of arr) {
if (predicate(it)) count += 1;
}
return count;
};

export type InterimColumn = Column & {
pk: boolean;
pkName: string | null;
Expand Down Expand Up @@ -217,10 +222,24 @@ export const interimToDDL = (schema: InterimSchema): { ddl: SQLiteDDL; errors: S
const errors: SchemaError[] = [];

for (const table of schema.tables) {
if (count(schema.columns, (it) => it.table === table.name) === 0) {
const columns = schema.columns.filter((it) => it.table === table.name);
if (columns.length === 0) {
errors.push({ type: 'table_no_columns', table: table.name });
continue;
}
if (table.isStrict) {
const allowed = new Set(['int', 'integer', 'real', 'text', 'blob', 'any']);
for (const column of columns) {
if (!allowed.has(column.type.toLowerCase())) {
errors.push({
type: 'invalid_strict_column_type',
table: table.name,
column: column.name,
columnType: column.type,
});
}
}
}
const res = ddl.tables.push(table);
if (res.status === 'CONFLICT') {
errors.push({ type: 'conflict_table', table: res.data.name });
Expand Down
7 changes: 7 additions & 0 deletions drizzle-kit/src/dialects/sqlite/diff.ts
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,13 @@ export const ddlDiff = async (
].map((it) => it.table),
);

for (const table of ddl2.tables.list()) {
const previous = ddl1.tables.one({ name: table.name });
if (previous && previous.isStrict !== table.isStrict) {
setOfTablesToRecereate.add(table.name);
}
}

for (const it of createdTables) {
setOfTablesToRecereate.delete(it.name);
}
Expand Down
6 changes: 5 additions & 1 deletion drizzle-kit/src/dialects/sqlite/drizzle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export const fromDrizzleSchema = (
return {
entityType: 'tables',
name: it.config.name,
isStrict: it.config.isStrict ?? false,
} satisfies Table;
});

Expand All @@ -44,6 +45,7 @@ export const fromDrizzleSchema = (
const { name } = column;
const primaryKey: boolean = column.primary;
const generated = column.generated;
const sqlType = column.getSQLType();

const generatedObj: {
as: string;
Expand Down Expand Up @@ -77,7 +79,9 @@ export const fromDrizzleSchema = (
entityType: 'columns',
table: it.config.name,
name,
type: column.getSQLType(),
type: it.config.isStrict && /^text\(\d+\)$/i.test(sqlType)
? 'text'
: sqlType,
default: defalutValue,
notNull: column.notNull && !primaryKey,
pk: primaryKey,
Expand Down
6 changes: 6 additions & 0 deletions drizzle-kit/src/dialects/sqlite/introspect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -361,11 +361,17 @@ export const fromDatabase = async (
return acc;
}, {} as Record<string, string>) || {};

const isStrictTable = (sql: string): boolean => {
const options = sql.slice(sql.lastIndexOf(')') + 1);
return /\bSTRICT\b/i.test(options);
};

const tables: SqliteEntities['tables'][] = [
...new Set(dbTableColumns.filter((it) => it.type === 'table').map((it) => it.table)),
].map((it) => ({
entityType: 'tables',
name: it,
isStrict: isStrictTable(tablesToSQL[it]),
}));

const pks: PrimaryKey[] = [];
Expand Down
5 changes: 3 additions & 2 deletions drizzle-kit/src/dialects/sqlite/serializer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export const prepareSqliteSnapshot = async (
: findLeafSnapshotIds(snapshots);

const snapshot = {
version: '7',
version: '8',
dialect: 'sqlite',
id,
prevIds,
Expand Down Expand Up @@ -146,14 +146,15 @@ export function generateLatestSnapshot(

const insertTableFull = (table: {
name: string;
isStrict: boolean;
columns: Column[];
indexes: Index[];
pk: PrimaryKey | null;
fks: ForeignKey[];
uniques: UniqueConstraint[];
checks: { table: string; value: string; name?: string }[];
}) => {
ddl.tables.push({ name: table.name });
ddl.tables.push({ name: table.name, isStrict: table.isStrict });
for (const column of table.columns) push(ddl.columns, column);
for (const index of table.indexes) push(ddl.indexes, index);
if (table.pk) push(ddl.pks, table.pk);
Expand Down
8 changes: 4 additions & 4 deletions drizzle-kit/src/dialects/sqlite/snapshot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ export const schemaInternalV5 = object({
}),
}).strict();

const latestVersion = literal('7');
const latestVersion = literal('8');
export const schemaInternalV6 = object({
version: literal('6'),
dialect: dialect,
Expand Down Expand Up @@ -164,15 +164,15 @@ export const toJsonSnapshot = (
dialect: 'sqlite',
id,
prevIds,
version: '7',
version: '8',
ddl: ddl.entities.list(),
renames,
};
};

const ddl = createDDL();
export const snapshotValidator = validator({
version: ['7'],
version: ['8'],
dialect: ['sqlite'],
id: 'string',
prevIds: array<string>((_) => true),
Expand All @@ -182,7 +182,7 @@ export const snapshotValidator = validator({

export type SqliteSnapshot = typeof snapshotValidator.shape;
export const drySqliteSnapshot = snapshotValidator.strict({
version: '7',
version: '8',
dialect: 'sqlite',
id: originUUID,
prevIds: [],
Expand Down
4 changes: 3 additions & 1 deletion drizzle-kit/src/dialects/sqlite/typescript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,9 @@ export const ddlToTypeScript = (
const uniqies = schema.uniques.list({ table: table.name });
const checks = schema.checks.list({ table: table.name });

let statement = `export const ${withCasing(table.name, casing)} = sqliteTable("${table.name}", {\n`;
let statement = `export const ${withCasing(table.name, casing)} = sqliteTable${
table.isStrict ? '.strict' : ''
}("${table.name}", {\n`;

statement += createTableColumns(columns, fks, pk, casing);
statement += '}';
Expand Down
2 changes: 1 addition & 1 deletion drizzle-kit/src/utils/utils-node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ const mssqlSnapshotValidator = (snapshot: object): ValidationResult => {
};

const sqliteValidator = (snapshot: object): ValidationResult => {
const versionError = assertVersion(snapshot, 7);
const versionError = assertVersion(snapshot, 8);
if (versionError) return { status: versionError };

const { success } = sqliteStapshotValidator.parse(snapshot);
Expand Down
2 changes: 1 addition & 1 deletion drizzle-kit/tests/sqlite/commutativity.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ function makeSnapshot(
schema: SqliteSchema,
): SqliteSnapshot {
return {
version: '7',
version: '8',
dialect: 'sqlite',
id,
prevIds,
Expand Down
6 changes: 3 additions & 3 deletions drizzle-kit/tests/sqlite/generate-flow.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ function makeSnapshot(
schema: SqliteSchema,
): SqliteSnapshot {
return {
version: '7',
version: '8',
dialect: 'sqlite',
id,
prevIds,
Expand Down Expand Up @@ -175,7 +175,7 @@ describe('generateLatestSnapshot (sqlite)', () => {
const fromDDL = drizzleToDDL(from).ddl;
const toDDL = drizzleToDDL(to).ddl;
const base: SqliteSnapshot = {
version: '7',
version: '8',
dialect: 'sqlite',
id: 'snapshot-id',
prevIds: [ORIGIN],
Expand Down Expand Up @@ -238,7 +238,7 @@ describe('generateLatestSnapshot (sqlite)', () => {
const combined: JsonStatement[] = [...stmtsA, ...stmtsB];

const base: SqliteSnapshot = {
version: '7',
version: '8',
dialect: 'sqlite',
id: 'parent-id',
prevIds: [ORIGIN],
Expand Down
4 changes: 2 additions & 2 deletions drizzle-kit/tests/sqlite/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { SQLiteDB } from 'src/utils';
import { mockResolver } from 'src/utils/mocks';
import { tsc } from 'tests/utils';
import 'zx/globals';
import { updateToV7 } from 'src/cli/commands/up-sqlite';
import { updateToV7, updateToV8 } from 'src/cli/commands/up-sqlite';
import { serializeSQLite } from 'src/legacy/sqlite-v6/serializer';
import { diff as legacyDiff } from 'src/legacy/sqlite-v6/sqliteDiff';

Expand Down Expand Up @@ -396,7 +396,7 @@ export const diffSnapshotV6 = async (
await db.run(st);
}

const snapshot = updateToV7(res);
const snapshot = updateToV8(updateToV7(res));

const ddl = fromEntities(snapshot.ddl);

Expand Down
Loading