diff --git a/changelogs/drizzle-kit/0.24.1.md b/changelogs/drizzle-kit/0.24.1.md new file mode 100644 index 000000000..d70f6ebbe --- /dev/null +++ b/changelogs/drizzle-kit/0.24.1.md @@ -0,0 +1,32 @@ +## Bug fixes + +> Big thanks to @L-Mario564 for his [PR](https://github.com/drizzle-team/drizzle-orm/pull/2804). It conflicted in most cases with a PR that was merged, but we incorporated some of his logic. Merging it would have caused more problems and taken more time to resolve, so we just took a few things from his PR, like removing "::" mappings in introspect and some array type default handlers + +### What was fixed + +1. The Drizzle Kit CLI was not working properly for the `introspect` command. +2. Added the ability to use column names with special characters for all dialects. +3. Included PostgreSQL sequences in the introspection process. +4. Reworked array type introspection and added all test cases. +5. Fixed all (we hope) default issues in PostgreSQL, where `::` was included in the introspected output. +6. `preserve` casing option was broken + +### Tickets that were closed + +- [[BUG]: invalid schema generation with drizzle-kit introspect:pg](https://github.com/drizzle-team/drizzle-orm/issues/1210) +- [[BUG][mysql introspection]: TS error when introspect column including colon](https://github.com/drizzle-team/drizzle-orm/issues/1928) +- [[BUG]: Unhandled defaults when introspecting postgres db](https://github.com/drizzle-team/drizzle-orm/issues/1625) +- [[BUG]: PostgreSQL Enum Naming and Schema Typing Issue](https://github.com/drizzle-team/drizzle-orm/issues/2315) +- [[BUG]: drizzle-kit instrospect command generates syntax error on varchar column types](https://github.com/drizzle-team/drizzle-orm/issues/2714) +- [[BUG]: Introspecting varchar[] type produces syntactically invalid schema.ts](https://github.com/drizzle-team/drizzle-orm/issues/1633) +- [[BUG]: introspect:pg column not using generated enum name](https://github.com/drizzle-team/drizzle-orm/issues/1648) +- [[BUG]: drizzle-kit introspect casing "preserve" config not working](https://github.com/drizzle-team/drizzle-orm/issues/2773) +- [[BUG]: drizzle-kit introspect fails on required param that is defined](https://github.com/drizzle-team/drizzle-orm/issues/2719) +- [[BUG]: Error when running npx drizzle-kit introspect: "Expected object, received string"](https://github.com/drizzle-team/drizzle-orm/issues/2657) +- [[BUG]: Missing index names when running introspect command [MYSQL]](https://github.com/drizzle-team/drizzle-orm/issues/2525) +- [[BUG]: drizzle-kit introspect TypeError: Cannot read properties of undefined (reading 'toLowerCase')](https://github.com/drizzle-team/drizzle-orm/issues/2338) +- [[BUG]: Wrong column name when using PgEnum.array()](https://github.com/drizzle-team/drizzle-orm/issues/2100) +- [[BUG]: Incorrect Schema Generated when introspecting extisting pg database](https://github.com/drizzle-team/drizzle-orm/issues/1985) +- [[⚠️🐞BUG]: index() missing argument after introspection, causes tsc error that fails the build](https://github.com/drizzle-team/drizzle-orm/issues/1870) +- [[BUG]: drizzle-kit introspect small errors](https://github.com/drizzle-team/drizzle-orm/issues/1738) +- [[BUG]: Missing bigint import in drizzle-kit introspect](https://github.com/drizzle-team/drizzle-orm/issues/1020) \ No newline at end of file diff --git a/drizzle-kit/package.json b/drizzle-kit/package.json index 25297e5b9..b2e780e1a 100644 --- a/drizzle-kit/package.json +++ b/drizzle-kit/package.json @@ -1,6 +1,6 @@ { "name": "drizzle-kit", - "version": "0.24.0", + "version": "0.24.1", "homepage": "https://orm.drizzle.team", "keywords": [ "drizzle", @@ -42,7 +42,7 @@ "publish": "npm publish package.tgz" }, "dependencies": { - "@drizzle-team/brocli": "^0.8.2", + "@drizzle-team/brocli": "^0.10.1", "@esbuild-kit/esm-loader": "^2.5.5", "esbuild": "^0.19.7", "esbuild-register": "^3.5.0" @@ -92,7 +92,7 @@ "hono": "^4.1.5", "json-diff": "1.0.6", "minimatch": "^7.4.3", - "mysql2": "2.3.3", + "mysql2": "3.3.3", "node-fetch": "^3.3.2", "pg": "^8.11.5", "pluralize": "^8.0.0", diff --git a/drizzle-kit/src/cli/commands/utils.ts b/drizzle-kit/src/cli/commands/utils.ts index 9f65318a6..7cf503248 100644 --- a/drizzle-kit/src/cli/commands/utils.ts +++ b/drizzle-kit/src/cli/commands/utils.ts @@ -408,11 +408,11 @@ export const preparePullConfig = async ( dialect: 'postgresql', out: config.out, breakpoints: config.breakpoints, - casing: config.introspectCasing, + casing: config.casing, credentials: parsed.data, tablesFilter, schemasFilter, - prefix: config.database?.prefix || 'index', + prefix: config.migrations?.prefix || 'index', }; } @@ -426,11 +426,11 @@ export const preparePullConfig = async ( dialect: 'mysql', out: config.out, breakpoints: config.breakpoints, - casing: config.introspectCasing, + casing: config.casing, credentials: parsed.data, tablesFilter, schemasFilter, - prefix: config.database?.prefix || 'index', + prefix: config.migrations?.prefix || 'index', }; } @@ -444,11 +444,11 @@ export const preparePullConfig = async ( dialect: 'sqlite', out: config.out, breakpoints: config.breakpoints, - casing: config.introspectCasing, + casing: config.casing, credentials: parsed.data, tablesFilter, schemasFilter, - prefix: config.database?.prefix || 'index', + prefix: config.migrations?.prefix || 'index', }; } diff --git a/drizzle-kit/src/cli/index.ts b/drizzle-kit/src/cli/index.ts index a7272ffef..86bffdf3d 100644 --- a/drizzle-kit/src/cli/index.ts +++ b/drizzle-kit/src/cli/index.ts @@ -43,5 +43,6 @@ const legacy = [ ]; run([generate, migrate, pull, push, studio, up, check, drop, ...legacy], { + name: 'drizzle-kit', version: version, }); diff --git a/drizzle-kit/src/cli/validations/cli.ts b/drizzle-kit/src/cli/validations/cli.ts index 67e118a98..c4bbbe530 100644 --- a/drizzle-kit/src/cli/validations/cli.ts +++ b/drizzle-kit/src/cli/validations/cli.ts @@ -38,9 +38,9 @@ export const pullParams = object({ .optional() .default(['public']), extensionsFilters: literal('postgis').array().optional(), - introspectCasing: casing, + casing, breakpoints: boolean().optional().default(true), - database: object({ + migrations: object({ prefix: prefix.optional().default('index'), }).optional(), }).passthrough(); diff --git a/drizzle-kit/src/introspect-mysql.ts b/drizzle-kit/src/introspect-mysql.ts index 21be79654..f206935a3 100644 --- a/drizzle-kit/src/introspect-mysql.ts +++ b/drizzle-kit/src/introspect-mysql.ts @@ -101,15 +101,22 @@ const importsPatch = { const relations = new Set(); +const escapeColumnKey = (value: string) => { + if (/^(?![a-zA-Z_$][a-zA-Z0-9_$]*$).+$/.test(value)) { + return `"${value}"`; + } + return value; +}; + const prepareCasing = (casing?: Casing) => (value: string) => { - if (typeof casing === 'undefined') { - return value; + if (casing === 'preserve') { + return escapeColumnKey(value); } if (casing === 'camel') { - return value.camelCase(); + return escapeColumnKey(value.camelCase()); } - return value; + return escapeColumnKey(value); }; export const schemaToTypeScript = ( diff --git a/drizzle-kit/src/introspect-pg.ts b/drizzle-kit/src/introspect-pg.ts index d20a96562..b7a52b735 100644 --- a/drizzle-kit/src/introspect-pg.ts +++ b/drizzle-kit/src/introspect-pg.ts @@ -140,6 +140,14 @@ const intervalConfig = (str: string) => { return statement; }; +const mapColumnDefault = (defaultValue: any, isExpression?: boolean) => { + if (isExpression) { + return `sql\`${defaultValue}\``; + } + + return defaultValue; +}; + const importsPatch = { 'double precision': 'doublePrecision', 'timestamp without time zone': 'timestamp', @@ -150,12 +158,19 @@ const importsPatch = { const relations = new Set(); +const escapeColumnKey = (value: string) => { + if (/^(?![a-zA-Z_$][a-zA-Z0-9_$]*$).+$/.test(value)) { + return `"${value}"`; + } + return value; +}; + const withCasing = (value: string, casing: Casing) => { if (casing === 'preserve') { - return value; + return escapeColumnKey(value); } if (casing === 'camel') { - return value.camelCase(); + return escapeColumnKey(value.camelCase()); } assertUnreachable(casing); @@ -267,6 +282,33 @@ export const relationsToTypeScriptForStudio = ( return result; }; +function generateIdentityParams(identity: Column['identity']) { + let paramsObj = `{ name: "${identity!.name}"`; + if (identity?.startWith) { + paramsObj += `, startWith: ${identity.startWith}`; + } + if (identity?.increment) { + paramsObj += `, increment: ${identity.increment}`; + } + if (identity?.minValue) { + paramsObj += `, minValue: ${identity.minValue}`; + } + if (identity?.maxValue) { + paramsObj += `, maxValue: ${identity.maxValue}`; + } + if (identity?.cache) { + paramsObj += `, cache: ${identity.cache}`; + } + if (identity?.cycle) { + paramsObj += `, cycle: true`; + } + paramsObj += ' }'; + if (identity?.type === 'always') { + return `.generatedAlwaysAsIdentity(${paramsObj})`; + } + return `.generatedByDefaultAsIdentity(${paramsObj})`; +} + export const paramNameFor = (name: string, schema?: string) => { const schemaSuffix = schema && schema !== 'public' ? `In${schema.capitalise()}` : ''; return `${name}${schemaSuffix}`; @@ -290,7 +332,13 @@ export const schemaToTypeScript = ( }), ); - const enumTypes = new Set(Object.values(schema.enums).map((it) => it.name)); + const enumTypes = Object.values(schema.enums).reduce( + (acc, cur) => { + acc.add(`${cur.schema}.${cur.name}`); + return acc; + }, + new Set(), + ); const imports = Object.values(schema.tables).reduce( (res, it) => { @@ -317,13 +365,10 @@ export const schemaToTypeScript = ( res.pg.push(...pkImports); res.pg.push(...uniqueImports); - if (enumTypes.size > 0) { - res.pg.push('pgEnum'); - } - const columnImports = Object.values(it.columns) .map((col) => { - let patched: string = importsPatch[col.type] || col.type; + let patched: string = (importsPatch[col.type] || col.type).replace('[]', ''); + patched = patched === 'double precision' ? 'doublePrecision' : patched; patched = patched.startsWith('varchar(') ? 'varchar' : patched; patched = patched.startsWith('char(') ? 'char' : patched; patched = patched.startsWith('numeric(') ? 'numeric' : patched; @@ -343,6 +388,22 @@ export const schemaToTypeScript = ( { pg: [] as string[] }, ); + Object.values(schema.sequences).forEach((it) => { + if (it.schema && it.schema !== 'public' && it.schema !== '') { + imports.pg.push('pgSchema'); + } else if (it.schema === 'public') { + imports.pg.push('pgSequence'); + } + }); + + Object.values(schema.enums).forEach((it) => { + if (it.schema && it.schema !== 'public' && it.schema !== '') { + imports.pg.push('pgSchema'); + } else if (it.schema === 'public') { + imports.pg.push('pgEnum'); + } + }); + const enumStatements = Object.values(schema.enums) .map((it) => { const enumSchema = schemas[it.schema]; @@ -359,6 +420,43 @@ export const schemaToTypeScript = ( .join('') .concat('\n'); + const sequencesStatements = Object.values(schema.sequences) + .map((it) => { + const seqSchema = schemas[it.schema]; + const paramName = paramNameFor(it.name, seqSchema); + + const func = seqSchema ? `${seqSchema}.sequence` : 'pgSequence'; + + let params = ''; + + if (it.startWith) { + params += `, startWith: "${it.startWith}"`; + } + if (it.increment) { + params += `, increment: "${it.increment}"`; + } + if (it.minValue) { + params += `, minValue: "${it.minValue}"`; + } + if (it.maxValue) { + params += `, maxValue: "${it.maxValue}"`; + } + if (it.cache) { + params += `, cache: "${it.cache}"`; + } + if (it.cycle) { + params += `, cycle: true`; + } else { + params += `, cycle: false`; + } + + return `export const ${withCasing(paramName, casing)} = ${func}("${it.name}"${ + params ? `, { ${params.trimChar(',')} }` : '' + })\n`; + }) + .join('') + .concat('\n'); + const schemaStatements = Object.entries(schemas) // .filter((it) => it[0] !== "public") .map((it) => { @@ -384,13 +482,14 @@ export const schemaToTypeScript = ( statement += '}'; // more than 2 fields or self reference or cyclic - const filteredFKs = Object.values(table.foreignKeys).filter((it) => { - return it.columnsFrom.length > 1 || isSelf(it); - }); + // Andrii: I switched this one off until we will get custom names in .references() + // const filteredFKs = Object.values(table.foreignKeys).filter((it) => { + // return it.columnsFrom.length > 1 || isSelf(it); + // }); if ( Object.keys(table.indexes).length > 0 - || filteredFKs.length > 0 + || Object.values(table.foreignKeys).length > 0 || Object.keys(table.compositePrimaryKeys).length > 0 || Object.keys(table.uniqueConstraints).length > 0 ) { @@ -402,7 +501,7 @@ export const schemaToTypeScript = ( Object.values(table.indexes), casing, ); - statement += createTableFKs(Object.values(filteredFKs), schemas, casing); + statement += createTableFKs(Object.values(table.foreignKeys), schemas, casing); statement += createTablePKs( Object.values(table.compositePrimaryKeys), casing, @@ -430,6 +529,7 @@ export const schemaToTypeScript = ( let decalrations = schemaStatements; decalrations += enumStatements; + decalrations += sequencesStatements; decalrations += '\n'; decalrations += tableStatements.join('\n\n'); @@ -459,16 +559,211 @@ const isSelf = (fk: ForeignKey) => { return fk.tableFrom === fk.tableTo; }; +const buildArrayDefault = (defaultValue: string, typeName: string): string => { + if (typeof defaultValue === 'string' && !(defaultValue.startsWith('{') || defaultValue.startsWith("'{"))) { + return `sql\`${defaultValue}\``; + } + defaultValue = defaultValue.substring(2, defaultValue.length - 2); + return `[${ + defaultValue + .split(/\s*,\s*/g) + .map((value) => { + // if (['integer', 'smallint', 'bigint', 'double precision', 'real'].includes(typeName)) { + // return value; + // } else if (typeName === 'interval') { + // return value.replaceAll('"', "'"); + // } else if (typeName === 'boolean') { + // return value === 't' ? 'true' : 'false'; + if (typeName === 'json' || typeName === 'jsonb') { + return value + .substring(1, value.length - 1) + .replaceAll('\\', ''); + } + return value; + // } + }) + .join(', ') + }]`; +}; + +const mapDefault = ( + tableName: string, + type: string, + name: string, + enumTypes: Set, + typeSchema: string, + defaultValue?: any, + internals?: PgKitInternals, +) => { + const isExpression = internals?.tables[tableName]?.columns[name]?.isDefaultAnExpression ?? false; + const isArray = internals?.tables[tableName]?.columns[name]?.isArray ?? false; + const lowered = type.toLowerCase().replace('[]', ''); + + if (isArray) { + return typeof defaultValue !== 'undefined' ? `.default(${buildArrayDefault(defaultValue, lowered)})` : ''; + } + + if (enumTypes.has(`${typeSchema}.${type.replace('[]', '')}`)) { + return typeof defaultValue !== 'undefined' ? `.default(${mapColumnDefault(defaultValue, isExpression)})` : ''; + } + + if (lowered.startsWith('integer')) { + return typeof defaultValue !== 'undefined' ? `.default(${mapColumnDefault(defaultValue, isExpression)})` : ''; + } + + if (lowered.startsWith('smallint')) { + return typeof defaultValue !== 'undefined' ? `.default(${mapColumnDefault(defaultValue, isExpression)})` : ''; + } + + if (lowered.startsWith('bigint')) { + return typeof defaultValue !== 'undefined' ? `.default(${mapColumnDefault(defaultValue, isExpression)})` : ''; + } + + if (lowered.startsWith('boolean')) { + return typeof defaultValue !== 'undefined' ? `.default(${mapColumnDefault(defaultValue, isExpression)})` : ''; + } + + if (lowered.startsWith('double precision')) { + return typeof defaultValue !== 'undefined' ? `.default(${mapColumnDefault(defaultValue, isExpression)})` : ''; + } + + if (lowered.startsWith('real')) { + return typeof defaultValue !== 'undefined' ? `.default(${mapColumnDefault(defaultValue, isExpression)})` : ''; + } + + if (lowered.startsWith('uuid')) { + return defaultValue === 'gen_random_uuid()' + ? '.defaultRandom()' + : defaultValue + ? `.default(sql\`${defaultValue}\`)` + : ''; + } + + if (lowered.startsWith('numeric')) { + defaultValue = defaultValue + ? defaultValue.startsWith(`'`) && defaultValue.endsWith(`'`) + ? defaultValue.substring(1, defaultValue.length - 1) + : defaultValue + : undefined; + return defaultValue ? `.default('${mapColumnDefault(defaultValue, isExpression)}')` : ''; + } + + if (lowered.startsWith('timestamp')) { + return defaultValue === 'now()' + ? '.defaultNow()' + : defaultValue === 'CURRENT_TIMESTAMP' + ? '.default(sql\`CURRENT_TIMESTAMP\`)' + : defaultValue + ? `.default(${mapColumnDefault(defaultValue, isExpression)})` + : ''; + } + + if (lowered.startsWith('time')) { + return defaultValue === 'now()' + ? '.defaultNow()' + : defaultValue + ? `.default(${mapColumnDefault(defaultValue, isExpression)})` + : ''; + } + + if (lowered.startsWith('interval')) { + return defaultValue ? `.default(${mapColumnDefault(defaultValue, isExpression)})` : ''; + } + + if (lowered === 'date') { + return defaultValue === 'now()' + ? '.defaultNow()' + : defaultValue === 'CURRENT_DATE' + ? `.default(sql\`${defaultValue}\`)` + : defaultValue + ? `.default(${defaultValue})` + : ''; + } + + if (lowered.startsWith('text')) { + return typeof defaultValue !== 'undefined' ? `.default(${mapColumnDefault(defaultValue, isExpression)})` : ''; + } + + if (lowered.startsWith('jsonb')) { + const def = typeof defaultValue !== 'undefined' + ? defaultValue.replace(/::(.*?)(?, + typeSchema: string, casing: Casing, defaultValue?: any, internals?: PgKitInternals, ) => { - const lowered = type.toLowerCase(); + const isExpression = internals?.tables[tableName]?.columns[name]?.isDefaultAnExpression ?? false; + const lowered = type.toLowerCase().replace('[]', ''); + + if (enumTypes.has(`${typeSchema}.${type.replace('[]', '')}`)) { + let out = `${withCasing(name, casing)}: ${ + withCasing( + paramNameFor(type.replace('[]', ''), typeSchema), + casing, + ) + }("${name}")`; + return out; + } + if (lowered.startsWith('serial')) { return `${withCasing(name, casing)}: serial("${name}")`; } @@ -488,49 +783,38 @@ const column = ( if (lowered.startsWith('integer')) { let out = `${withCasing(name, casing)}: integer("${name}")`; - out += typeof defaultValue !== 'undefined' ? `.default(${defaultValue})` : ''; return out; } if (lowered.startsWith('smallint')) { let out = `${withCasing(name, casing)}: smallint("${name}")`; - out += typeof defaultValue !== 'undefined' ? `.default(${defaultValue})` : ''; return out; } if (lowered.startsWith('bigint')) { let out = `// You can use { mode: "bigint" } if numbers are exceeding js number limitations\n\t`; out += `${withCasing(name, casing)}: bigint("${name}", { mode: "number" })`; - out += typeof defaultValue !== 'undefined' ? `.default(${defaultValue})` : ''; return out; } if (lowered.startsWith('boolean')) { let out = `${withCasing(name, casing)}: boolean("${name}")`; - out += typeof defaultValue !== 'undefined' ? `.default(${defaultValue})` : ''; return out; } if (lowered.startsWith('double precision')) { let out = `${withCasing(name, casing)}: doublePrecision("${name}")`; - out += defaultValue ? `.default(${defaultValue})` : ''; return out; } if (lowered.startsWith('real')) { let out = `${withCasing(name, casing)}: real("${name}")`; - out += defaultValue ? `.default(${defaultValue})` : ''; return out; } if (lowered.startsWith('uuid')) { let out = `${withCasing(name, casing)}: uuid("${name}")`; - out += defaultValue === 'gen_random_uuid()' - ? '.defaultRandom()' - : defaultValue - ? `.default(sql\`${defaultValue}\`)` - : ''; return out; } @@ -550,13 +834,6 @@ const column = ( ? `${withCasing(name, casing)}: numeric("${name}", ${timeConfig(params)})` : `${withCasing(name, casing)}: numeric("${name}")`; - defaultValue = defaultValue - ? defaultValue.startsWith(`'`) && defaultValue.endsWith(`'`) - ? defaultValue.substring(1, defaultValue.length - 1) - : defaultValue - : undefined; - out += defaultValue ? `.default('${defaultValue}')` : ''; - return out; } @@ -582,21 +859,6 @@ const column = ( ? `${withCasing(name, casing)}: timestamp("${name}", ${params})` : `${withCasing(name, casing)}: timestamp("${name}")`; - // defaultValue = defaultValue?.endsWith("::timestamp without time zone") - // ? defaultValue.substring(0, defaultValue.length - 29) - // : defaultValue; - - // defaultValue = defaultValue?.endsWith("::timestamp with time zone") - // ? defaultValue.substring(0, defaultValue.length - 26) - // : defaultValue; - - defaultValue = defaultValue === 'now()' || defaultValue === 'CURRENT_TIMESTAMP' - ? '.defaultNow()' - : defaultValue - ? `.default(${defaultValue})` - : ''; - - out += defaultValue; return out; } @@ -618,13 +880,6 @@ const column = ( ? `${withCasing(name, casing)}: time("${name}", ${params})` : `${withCasing(name, casing)}: time("${name}")`; - defaultValue = defaultValue === 'now()' - ? '.defaultNow()' - : defaultValue - ? `.default(${defaultValue})` - : ''; - - out += defaultValue; return out; } @@ -640,105 +895,51 @@ const column = ( ? `${withCasing(name, casing)}: interval("${name}", ${params})` : `${withCasing(name, casing)}: interval("${name}")`; - out += defaultValue ? `.default(${defaultValue})` : ''; return out; } if (lowered === 'date') { let out = `${withCasing(name, casing)}: date("${name}")`; - defaultValue = defaultValue === 'now()' - ? '.defaultNow()' - : defaultValue === 'CURRENT_DATE' - ? `.default(sql\`${defaultValue}\`)` - : defaultValue - ? `.default(${defaultValue})` - : ''; - - out += defaultValue; return out; } if (lowered.startsWith('text')) { let out = `${withCasing(name, casing)}: text("${name}")`; - out += typeof defaultValue !== 'undefined' ? `.default(${defaultValue})` : ''; return out; } - if (lowered === 'json') { - let out = `${withCasing(name, casing)}: json("${name}")`; - // defaultValue = defaultValue?.replace("::json", ""); - - defaultValue = defaultValue?.endsWith('::json') - ? defaultValue.substring(1, defaultValue.length - 7) - : defaultValue; - // const def = defaultValue ? objToStatement(JSON.parse(defaultValue)) : null; - const def = defaultValue ? defaultValue : null; - - out += typeof defaultValue !== 'undefined' ? `.default(${def})` : ''; + if (lowered.startsWith('jsonb')) { + let out = `${withCasing(name, casing)}: jsonb("${name}")`; return out; } - if (lowered === 'jsonb') { - let out = `${withCasing(name, casing)}: jsonb("${name}")`; - - defaultValue = defaultValue?.endsWith('::jsonb') - ? defaultValue.substring(1, defaultValue.length - 8) - : defaultValue; - // const def = defaultValue ? objToStatement(JSON.parse(defaultValue)) : null; - const def = typeof defaultValue !== 'undefined' ? defaultValue : null; - - out += defaultValue ? `.default(${def})` : ''; + if (lowered.startsWith('json')) { + let out = `${withCasing(name, casing)}: json("${name}")`; return out; } if (lowered.startsWith('inet')) { let out = `${withCasing(name, casing)}: inet("${name}")`; - - // defaultValue = defaultValue?.endsWith("::inet") - // ? defaultValue.substring(0, defaultValue.length - 6) - // : defaultValue; - - out += typeof defaultValue !== 'undefined' ? `.default(${defaultValue})` : ''; return out; } if (lowered.startsWith('cidr')) { let out = `${withCasing(name, casing)}: cidr("${name}")`; - - // defaultValue = defaultValue?.endsWith("::cidr") - // ? defaultValue.substring(0, defaultValue.length - 6) - // : defaultValue; - - out += typeof defaultValue !== 'undefined' ? `.default(${defaultValue})` : ''; - return out; - } - - if (lowered.startsWith('macaddr')) { - let out = `${withCasing(name, casing)}: macaddr("${name}")`; - - // defaultValue = defaultValue?.endsWith("::macaddr") - // ? defaultValue.substring(0, defaultValue.length - 9) - // : defaultValue; - - out += typeof defaultValue !== 'undefined' ? `.default(${defaultValue})` : ''; return out; } if (lowered.startsWith('macaddr8')) { let out = `${withCasing(name, casing)}: macaddr8("${name}")`; + return out; + } - // defaultValue = defaultValue?.endsWith("::macaddr8") - // ? defaultValue.substring(0, defaultValue.length - 10) - // : defaultValue; - - out += typeof defaultValue !== 'undefined' ? `.default(${defaultValue})` : ''; + if (lowered.startsWith('macaddr')) { + let out = `${withCasing(name, casing)}: macaddr("${name}")`; return out; } if (lowered.startsWith('varchar')) { - const split = lowered.split(' '); - let out: string; if (lowered.length !== 7) { out = `${ @@ -756,25 +957,16 @@ const column = ( out = `${withCasing(name, casing)}: varchar("${name}")`; } - // defaultValue = defaultValue?.endsWith("::character varying") - // ? defaultValue.substring(0, defaultValue.length - 19) - // : defaultValue; - - out += typeof defaultValue !== 'undefined' ? `.default(${defaultValue})` : ''; return out; } if (lowered.startsWith('point')) { let out: string = `${withCasing(name, casing)}: point("${name}")`; - - out += typeof defaultValue !== 'undefined' ? `.default(${defaultValue})` : ''; return out; } if (lowered.startsWith('line')) { let out: string = `${withCasing(name, casing)}: point("${name}")`; - - out += typeof defaultValue !== 'undefined' ? `.default(${defaultValue})` : ''; return out; } @@ -798,8 +990,6 @@ const column = ( out = `${withCasing(name, casing)}: geometry("${name}")`; } - out += typeof defaultValue !== 'undefined' ? `.default(${defaultValue})` : ''; - if (isGeoUnknown) { let unknown = `// TODO: failed to parse geometry type because found more than 2 options inside geometry function '${type}'\n// Introspect is currently supporting only type and srid options\n`; @@ -810,8 +1000,6 @@ const column = ( } if (lowered.startsWith('vector')) { - const split = lowered.split(' '); - let out: string; if (lowered.length !== 6) { out = `${ @@ -829,13 +1017,10 @@ const column = ( out = `${withCasing(name, casing)}: vector("${name}")`; } - out += typeof defaultValue !== 'undefined' ? `.default(${defaultValue})` : ''; return out; } if (lowered.startsWith('char')) { - // const split = lowered.split(" "); - let out: string; if (lowered.length !== 4) { out = `${ @@ -853,42 +1038,6 @@ const column = ( out = `${withCasing(name, casing)}: char("${name}")`; } - // defaultValue = defaultValue?.endsWith("::bpchar") - // ? defaultValue.substring(0, defaultValue.length - 8) - // : defaultValue; - - out += typeof defaultValue !== 'undefined' ? `.default(${defaultValue})` : ''; - return out; - } - - // if internal has this column - use it - const columnInternals = internals?.tables[tableName]?.columns[name]; - if (typeof columnInternals !== 'undefined') { - // it means there is enum as array case - if ( - columnInternals.isArray - && columnInternals.rawType - && enumTypes.has(columnInternals.rawType) - ) { - let out = `${withCasing(columnInternals.rawType, casing)}: ${ - withCasing( - columnInternals.rawType, - casing, - ) - }("${name}")`; - out += typeof defaultValue !== 'undefined' ? `.default(${defaultValue})` : ''; - return out; - } - } - - if (enumTypes.has(type)) { - let out = `${withCasing(name, casing)}: ${ - withCasing( - type, - casing, - ) - }("${name}")`; - out += typeof defaultValue !== 'undefined' ? `.default(${defaultValue})` : ''; return out; } @@ -937,6 +1086,7 @@ const createTableColumns = ( it.type, it.name, enumTypes, + it.typeSchema ?? 'public', casing, it.default, internals, @@ -949,73 +1099,56 @@ const createTableColumns = ( internals?.tables[tableName]?.columns[it.name]?.dimensions, ); } + statement += mapDefault( + tableName, + it.type, + it.name, + enumTypes, + it.typeSchema ?? 'public', + it.default, + internals, + ); statement += it.primaryKey ? '.primaryKey()' : ''; statement += it.notNull && !it.identity ? '.notNull()' : ''; - function generateIdentityParams(identity: Column['identity']) { - let paramsObj = `{ name: "${identity!.name}"`; - if (identity?.startWith) { - paramsObj += `, startWith: ${identity.startWith}`; - } - if (identity?.increment) { - paramsObj += `, increment: ${identity.increment}`; - } - if (identity?.minValue) { - paramsObj += `, minValue: ${identity.minValue}`; - } - if (identity?.maxValue) { - paramsObj += `, maxValue: ${identity.maxValue}`; - } - if (identity?.cache) { - paramsObj += `, cache: ${identity.cache}`; - } - if (identity?.cycle) { - paramsObj += `, cycle: true`; - } - paramsObj += ' }'; - if (identity?.type === 'always') { - return `.generatedAlwaysAsIdentity(${paramsObj})`; - } - return `.generatedByDefaultAsIdentity(${paramsObj})`; - } - statement += it.identity ? generateIdentityParams(it.identity) : ''; statement += it.generated ? `.generatedAlwaysAs(sql\`${it.generated.as}\`)` : ''; - const fks = fkByColumnName[it.name]; - if (fks) { - const fksStatement = fks - .map((it) => { - const onDelete = it.onDelete && it.onDelete !== 'no action' ? it.onDelete : null; - const onUpdate = it.onUpdate && it.onUpdate !== 'no action' ? it.onUpdate : null; - const params = { onDelete, onUpdate }; - - const typeSuffix = isCyclic(it) ? ': AnyPgColumn' : ''; - - const paramsStr = objToStatement2(params); - const tableSchema = schemas[it.schemaTo || '']; - const paramName = paramNameFor(it.tableTo, tableSchema); - if (paramsStr) { - return `.references(()${typeSuffix} => ${ - withCasing( - paramName, - casing, - ) - }.${withCasing(it.columnsTo[0], casing)}, ${paramsStr} )`; - } - return `.references(()${typeSuffix} => ${ - withCasing( - paramName, - casing, - ) - }.${withCasing(it.columnsTo[0], casing)})`; - }) - .join(''); - statement += fksStatement; - } + // const fks = fkByColumnName[it.name]; + // Andrii: I switched it off until we will get a custom naem setting in references + // if (fks) { + // const fksStatement = fks + // .map((it) => { + // const onDelete = it.onDelete && it.onDelete !== 'no action' ? it.onDelete : null; + // const onUpdate = it.onUpdate && it.onUpdate !== 'no action' ? it.onUpdate : null; + // const params = { onDelete, onUpdate }; + + // const typeSuffix = isCyclic(it) ? ': AnyPgColumn' : ''; + + // const paramsStr = objToStatement2(params); + // const tableSchema = schemas[it.schemaTo || '']; + // const paramName = paramNameFor(it.tableTo, tableSchema); + // if (paramsStr) { + // return `.references(()${typeSuffix} => ${ + // withCasing( + // paramName, + // casing, + // ) + // }.${withCasing(it.columnsTo[0], casing)}, ${paramsStr} )`; + // } + // return `.references(()${typeSuffix} => ${ + // withCasing( + // paramName, + // casing, + // ) + // }.${withCasing(it.columnsTo[0], casing)})`; + // }) + // .join(''); + // statement += fksStatement; + // } statement += ',\n'; }); @@ -1058,7 +1191,9 @@ const createTableIndexes = ( if (it.isExpression) { return `sql\`${it.expression}\``; } else { - return `table.${withCasing(it.expression, casing)}${ + return `table.${withCasing(it.expression, casing)}${it.asc ? '.asc()' : '.desc()'}${ + it.nulls === 'first' ? '.nullsFirst()' : '.nullsLast()' + }${ it.opclass && vectorOps.includes(it.opclass) ? `.op("${it.opclass}")` : '' diff --git a/drizzle-kit/src/introspect-sqlite.ts b/drizzle-kit/src/introspect-sqlite.ts index 9ff119ce6..b4a729f4c 100644 --- a/drizzle-kit/src/introspect-sqlite.ts +++ b/drizzle-kit/src/introspect-sqlite.ts @@ -38,12 +38,19 @@ const objToStatement2 = (json: any) => { const relations = new Set(); +const escapeColumnKey = (value: string) => { + if (/^(?![a-zA-Z_$][a-zA-Z0-9_$]*$).+$/.test(value)) { + return `"${value}"`; + } + return value; +}; + const withCasing = (value: string, casing?: Casing) => { - if (typeof casing === 'undefined') { - return value; + if (casing === 'preserve') { + return escapeColumnKey(value); } if (casing === 'camel') { - return value.camelCase(); + return escapeColumnKey(value.camelCase()); } return value; diff --git a/drizzle-kit/src/serializer/pgSchema.ts b/drizzle-kit/src/serializer/pgSchema.ts index 7e4a55afd..5860a6fef 100644 --- a/drizzle-kit/src/serializer/pgSchema.ts +++ b/drizzle-kit/src/serializer/pgSchema.ts @@ -1,3 +1,4 @@ +import { vectorOps } from 'src/extensions/vector'; import { mapValues, originUUID, snapshotVersion } from '../global'; import { any, array, boolean, enum as enumType, literal, number, object, record, string, TypeOf, union } from 'zod'; @@ -282,6 +283,7 @@ export const kitInternals = object({ isArray: boolean().optional(), dimensions: number().optional(), rawType: string().optional(), + isDefaultAnExpression: boolean().optional(), }).optional(), ), }).optional(), @@ -464,7 +466,10 @@ export const PgSquasher = { return `${idx.name};${ idx.columns .map( - (c) => `${c.expression}--${c.isExpression}--${c.asc}--${c.nulls}--${c.opclass}`, + (c) => + `${c.expression}--${c.isExpression}--${c.asc}--${c.nulls}--${ + c.opclass && vectorOps.includes(c.opclass) ? c.opclass : '' + }`, ) .join(',,') };${idx.isUnique};${idx.concurrently};${idx.method};${idx.where};${JSON.stringify(idx.with)}`; diff --git a/drizzle-kit/src/serializer/pgSerializer.ts b/drizzle-kit/src/serializer/pgSerializer.ts index 6470cf1ff..b479e59e2 100644 --- a/drizzle-kit/src/serializer/pgSerializer.ts +++ b/drizzle-kit/src/serializer/pgSerializer.ts @@ -269,7 +269,7 @@ export const generatePgSnapshot = ( column.default, sqlTypeLowered, ) - }'::${sqlTypeLowered}`; + }'`; } else { // Should do for all types // columnToSet.default = `'${column.default}'::${sqlTypeLowered}`; @@ -739,7 +739,7 @@ export const fromDatabase = async ( WHEN 'int2'::regtype THEN 'smallserial' END ELSE format_type(a.atttypid, a.atttypmod) - END AS data_type, INFORMATION_SCHEMA.COLUMNS.table_name, + END AS data_type, INFORMATION_SCHEMA.COLUMNS.table_name, ns.nspname as type_schema, pg_get_serial_sequence('"${tableSchema}"."${tableName}"', a.attname)::regclass as seq_name, INFORMATION_SCHEMA.COLUMNS.column_name, INFORMATION_SCHEMA.COLUMNS.column_default, INFORMATION_SCHEMA.COLUMNS.data_type as additional_dt, INFORMATION_SCHEMA.COLUMNS.udt_name as enum_name, @@ -750,6 +750,7 @@ export const fromDatabase = async ( INFORMATION_SCHEMA.COLUMNS.identity_cycle FROM pg_attribute a JOIN INFORMATION_SCHEMA.COLUMNS ON INFORMATION_SCHEMA.COLUMNS.column_name = a.attname + JOIN pg_type t ON t.oid = a.atttypid LEFT JOIN pg_namespace ns ON ns.oid = t.typnamespace WHERE a.attrelid = '"${tableSchema}"."${tableName}"'::regclass and INFORMATION_SCHEMA.COLUMNS.table_name = '${tableName}' and INFORMATION_SCHEMA.COLUMNS.table_schema = '${tableSchema}' AND a.attnum > 0 AND NOT a.attisdropped @@ -772,30 +773,42 @@ export const fromDatabase = async ( const tableForeignKeys = await db.query( `SELECT - tc.table_schema, - tc.constraint_name, - tc.table_name, - kcu.column_name, - ( - SELECT ccu.table_schema - FROM information_schema.constraint_column_usage ccu - WHERE ccu.constraint_name = tc.constraint_name - LIMIT 1 - ) AS foreign_table_schema, - ccu.table_name AS foreign_table_name, - ccu.column_name AS foreign_column_name, - rc.delete_rule, - rc.update_rule - FROM - information_schema.table_constraints AS tc - JOIN information_schema.key_column_usage AS kcu - ON tc.constraint_name = kcu.constraint_name - AND tc.table_schema = kcu.table_schema - JOIN information_schema.constraint_column_usage AS ccu - ON ccu.constraint_name = tc.constraint_name - JOIN information_schema.referential_constraints AS rc - ON ccu.constraint_name = rc.constraint_name - WHERE tc.constraint_type = 'FOREIGN KEY' AND tc.table_name='${tableName}' and tc.table_schema='${tableSchema}';`, + con.contype AS constraint_type, + nsp.nspname AS constraint_schema, + con.conname AS constraint_name, + rel.relname AS table_name, + att.attname AS column_name, + fnsp.nspname AS foreign_table_schema, + frel.relname AS foreign_table_name, + fatt.attname AS foreign_column_name, + CASE con.confupdtype + WHEN 'a' THEN 'NO ACTION' + WHEN 'r' THEN 'RESTRICT' + WHEN 'n' THEN 'SET NULL' + WHEN 'c' THEN 'CASCADE' + WHEN 'd' THEN 'SET DEFAULT' + END AS update_rule, + CASE con.confdeltype + WHEN 'a' THEN 'NO ACTION' + WHEN 'r' THEN 'RESTRICT' + WHEN 'n' THEN 'SET NULL' + WHEN 'c' THEN 'CASCADE' + WHEN 'd' THEN 'SET DEFAULT' + END AS delete_rule + FROM + pg_catalog.pg_constraint con + JOIN pg_catalog.pg_class rel ON rel.oid = con.conrelid + JOIN pg_catalog.pg_namespace nsp ON nsp.oid = con.connamespace + LEFT JOIN pg_catalog.pg_attribute att ON att.attnum = ANY (con.conkey) + AND att.attrelid = con.conrelid + LEFT JOIN pg_catalog.pg_class frel ON frel.oid = con.confrelid + LEFT JOIN pg_catalog.pg_namespace fnsp ON fnsp.oid = frel.relnamespace + LEFT JOIN pg_catalog.pg_attribute fatt ON fatt.attnum = ANY (con.confkey) + AND fatt.attrelid = con.confrelid + WHERE + nsp.nspname = '${tableSchema}' + AND rel.relname = '${tableName}' + AND con.contype IN ('f');`, ); foreignKeysCount += tableForeignKeys.length; @@ -809,8 +822,8 @@ export const fromDatabase = async ( const columnTo: string = fk.foreign_column_name; const schemaTo: string = fk.foreign_table_schema; const foreignKeyName = fk.constraint_name; - const onUpdate = fk.update_rule.toLowerCase(); - const onDelete = fk.delete_rule.toLowerCase(); + const onUpdate = fk.update_rule?.toLowerCase(); + const onDelete = fk.delete_rule?.toLowerCase(); if (typeof foreignKeysToReturn[foreignKeyName] !== 'undefined') { foreignKeysToReturn[foreignKeyName].columnsFrom.push(columnFrom); @@ -863,6 +876,8 @@ export const fromDatabase = async ( const columnDimensions = columnResponse.array_dimensions; const enumType: string = columnResponse.enum_name; let columnType: string = columnResponse.data_type; + const typeSchema = columnResponse.type_schema; + const defaultValueRes: string = columnResponse.column_default; const isGenerated = columnResponse.is_generated === 'ALWAYS'; const generationExpression = columnResponse.generation_expression; @@ -902,16 +917,8 @@ export const fromDatabase = async ( }; } - const defaultValue = defaultForColumn(columnResponse); - - const isSerial = columnType === 'serial'; - let columnTypeMapped = columnType; - if (columnTypeMapped.startsWith('numeric(')) { - columnTypeMapped = columnTypeMapped.replace(',', ', '); - } - // Set default to internal object if (columnAdditionalDT === 'ARRAY') { if (typeof internals.tables[tableName] === 'undefined') { @@ -944,6 +951,45 @@ export const fromDatabase = async ( } } + const defaultValue = defaultForColumn( + columnResponse, + internals, + tableName, + ); + if ( + defaultValue === 'NULL' + || (defaultValueRes && defaultValueRes.startsWith('(') && defaultValueRes.endsWith(')')) + ) { + if (typeof internals!.tables![tableName] === 'undefined') { + internals!.tables![tableName] = { + columns: { + [columnName]: { + isDefaultAnExpression: true, + }, + }, + }; + } else { + if ( + typeof internals!.tables![tableName]!.columns[columnName] + === 'undefined' + ) { + internals!.tables![tableName]!.columns[columnName] = { + isDefaultAnExpression: true, + }; + } else { + internals!.tables![tableName]!.columns[ + columnName + ]!.isDefaultAnExpression = true; + } + } + } + + const isSerial = columnType === 'serial'; + + if (columnTypeMapped.startsWith('numeric(')) { + columnTypeMapped = columnTypeMapped.replace(',', ', '); + } + if (columnAdditionalDT === 'ARRAY') { for (let i = 1; i < Number(columnDimensions); i++) { columnTypeMapped += '[]'; @@ -966,8 +1012,8 @@ export const fromDatabase = async ( && !['vector', 'geometry'].includes(enumType) ? enumType : columnTypeMapped, - typeSchema: enumsToReturn[`${tableSchema}.${enumType}`] !== undefined - ? enumsToReturn[`${tableSchema}.${enumType}`].schema + typeSchema: enumsToReturn[`${typeSchema}.${enumType}`] !== undefined + ? enumsToReturn[`${typeSchema}.${enumType}`].schema : undefined, primaryKey: primaryKey.length === 1 && cprimaryKey.length < 2, // default: isSerial ? undefined : defaultValue, @@ -995,7 +1041,12 @@ export const fromDatabase = async ( }; if (identityName) { - delete sequencesToReturn[`${tableSchema}.${identityName}`]; + // remove "" from sequence name + delete sequencesToReturn[ + `${tableSchema}.${ + identityName.startsWith('"') && identityName.endsWith('"') ? identityName.slice(1, -1) : identityName + }` + ]; delete sequencesToReturn[identityName]; } @@ -1170,29 +1221,10 @@ export const fromDatabase = async ( }; }; -const columnToDefault: Record = { - 'numeric(': '::numeric', - // text: "::text", - // "character varying": "::character varying", - // "double precision": "::double precision", - // "time with time zone": "::time with time zone", - 'time without time zone': '::time without time zone', - // "timestamp with time zone": "::timestamp with time zone", - 'timestamp without time zone': '::timestamp without time zone', - 'timestamp(': '::timestamp without time zone', - // date: "::date", - // interval: "::interval", - // character: "::bpchar", - // macaddr8: "::macaddr8", - // macaddr: "::macaddr", - // inet: "::inet", - // cidr: "::cidr", - // jsonb: "::jsonb", - // json: "::json", - 'character(': '::bpchar', -}; +const defaultForColumn = (column: any, internals: PgKitInternals, tableName: string) => { + const columnName = column.attname; + const isArray = internals?.tables[tableName]?.columns[columnName]?.isArray ?? false; -const defaultForColumn = (column: any) => { if (column.column_default === null) { return undefined; } @@ -1205,54 +1237,81 @@ const defaultForColumn = (column: any) => { return undefined; } - const hasDifferentDefaultCast = Object.keys(columnToDefault).find((it) => column.data_type.startsWith(it)); + if (column.column_default.endsWith('[]')) { + column.column_default = column.column_default.slice(0, -2); + } + + // if ( + // !['integer', 'smallint', 'bigint', 'double precision', 'real'].includes(column.data_type) + // ) { + column.column_default = column.column_default.replace(/::(.*?)(? { + if (['integer', 'smallint', 'bigint', 'double precision', 'real'].includes(column.data_type.slice(0, -2))) { + return value; + } else if (column.data_type.startsWith('timestamp')) { + return `${value}`; + } else if (column.data_type.slice(0, -2) === 'interval') { + return value.replaceAll('"', `\"`); + } else if (column.data_type.slice(0, -2) === 'boolean') { + return value === 't' ? 'true' : 'false'; + } else if (['json', 'jsonb'].includes(column.data_type.slice(0, -2))) { + return JSON.stringify(JSON.stringify(JSON.parse(JSON.parse(value)), null, 0)); + } else { + return `\"${value}\"`; + } + }) + .join(',') + }}'`; + } + if ( - columnDefaultAsString.endsWith( - hasDifferentDefaultCast - ? columnToDefault[hasDifferentDefaultCast] - : (column.data_type as string), - ) + ['integer', 'smallint', 'bigint', 'double precision', 'real'].includes(column.data_type) ) { - const nonPrefixPart = column.column_default.length - - (hasDifferentDefaultCast - ? columnToDefault[hasDifferentDefaultCast] - : `::${column.data_type as string}`).length - - 1; - - const rt = column.column_default - .toString() - .substring(1, nonPrefixPart) as string; - - if ( - /^-?[\d.]+(?:e-?\d+)?$/.test(rt) - && !column.data_type.startsWith('numeric') - ) { - return Number(rt); - } else if (column.data_type === 'json' || column.data_type === 'jsonb') { - const jsonWithoutSpaces = JSON.stringify(JSON.parse(rt)); - return `'${jsonWithoutSpaces}'${ - hasDifferentDefaultCast - ? columnToDefault[hasDifferentDefaultCast] - : `::${column.data_type as string}` - }`; - } else if (column.data_type === 'boolean') { - return column.column_default === 'true'; - } else { - return `'${rt}'`; - } - } else { - if ( - /^-?[\d.]+(?:e-?\d+)?$/.test(columnDefaultAsString) - && !column.data_type.startsWith('numeric') - ) { + if (/^-?[\d.]+(?:e-?\d+)?$/.test(columnDefaultAsString)) { return Number(columnDefaultAsString); - } else if (column.data_type === 'boolean') { - return column.column_default === 'true'; } else { - return `${columnDefaultAsString}`; + if (typeof internals!.tables![tableName] === 'undefined') { + internals!.tables![tableName] = { + columns: { + [columnName]: { + isDefaultAnExpression: true, + }, + }, + }; + } else { + if ( + typeof internals!.tables![tableName]!.columns[columnName] + === 'undefined' + ) { + internals!.tables![tableName]!.columns[columnName] = { + isDefaultAnExpression: true, + }; + } else { + internals!.tables![tableName]!.columns[ + columnName + ]!.isDefaultAnExpression = true; + } + } + return columnDefaultAsString; } + } else if (column.data_type === 'json' || column.data_type === 'jsonb') { + const jsonWithoutSpaces = JSON.stringify(JSON.parse(columnDefaultAsString.slice(1, -1))); + return `'${jsonWithoutSpaces}'::${column.data_type}`; + } else if (column.data_type === 'boolean') { + return column.column_default === 'true'; + } else if (columnDefaultAsString === 'NULL') { + return `NULL`; + } else if (columnDefaultAsString.startsWith("'") && columnDefaultAsString.endsWith("'")) { + return columnDefaultAsString; + } else { + return `${columnDefaultAsString.replace(/\\/g, '\`\\')}`; } }; diff --git a/drizzle-kit/src/sqlgenerator.ts b/drizzle-kit/src/sqlgenerator.ts index 769da7c5a..30517d0f2 100644 --- a/drizzle-kit/src/sqlgenerator.ts +++ b/drizzle-kit/src/sqlgenerator.ts @@ -106,6 +106,7 @@ const isPgNativeType = (it: string) => { || toCheck.startsWith('char(') || toCheck.startsWith('numeric(') || toCheck.startsWith('timestamp(') + || toCheck.startsWith('doubleprecision[') || toCheck.startsWith('intervalyear(') || toCheck.startsWith('intervalmonth(') || toCheck.startsWith('intervalday(') diff --git a/drizzle-kit/tests/indexes/pg.test.ts b/drizzle-kit/tests/indexes/pg.test.ts index 8419fd765..9958a2356 100644 --- a/drizzle-kit/tests/indexes/pg.test.ts +++ b/drizzle-kit/tests/indexes/pg.test.ts @@ -125,12 +125,12 @@ const pgSuite: DialectSuite = { expect(sqlStatements).toStrictEqual([ 'DROP INDEX IF EXISTS "indx";', 'DROP INDEX IF EXISTS "indx1";', - 'DROP INDEX IF EXISTS "indx2";', + // 'DROP INDEX IF EXISTS "indx2";', 'DROP INDEX IF EXISTS "indx3";', 'CREATE INDEX IF NOT EXISTS "indx4" ON "users" USING btree (lower(id)) WHERE true;', 'CREATE INDEX IF NOT EXISTS "indx" ON "users" USING btree ("name" DESC NULLS LAST);', 'CREATE INDEX IF NOT EXISTS "indx1" ON "users" USING btree ("name" DESC NULLS LAST) WHERE false;', - 'CREATE INDEX IF NOT EXISTS "indx2" ON "users" USING btree ("name" test) WHERE true;', + // 'CREATE INDEX IF NOT EXISTS "indx2" ON "users" USING btree ("name" test) WHERE true;', 'CREATE INDEX IF NOT EXISTS "indx3" ON "users" USING btree (lower("id")) WHERE true;', ]); }, @@ -180,14 +180,14 @@ const pgSuite: DialectSuite = { expression: 'name', isExpression: false, nulls: 'last', - opclass: undefined, + opclass: '', }, { asc: true, expression: 'id', isExpression: false, nulls: 'last', - opclass: undefined, + opclass: '', }, ], concurrently: false, @@ -212,14 +212,14 @@ const pgSuite: DialectSuite = { expression: 'name', isExpression: false, nulls: 'last', - opclass: undefined, + opclass: '', }, { asc: true, expression: '"name"', isExpression: true, nulls: 'last', - opclass: undefined, + opclass: '', }, ], concurrently: false, diff --git a/drizzle-kit/tests/introspect/pg.test.ts b/drizzle-kit/tests/introspect/pg.test.ts index 40b06187f..3efb57d7e 100644 --- a/drizzle-kit/tests/introspect/pg.test.ts +++ b/drizzle-kit/tests/introspect/pg.test.ts @@ -1,6 +1,34 @@ import { PGlite } from '@electric-sql/pglite'; import { SQL, sql } from 'drizzle-orm'; -import { integer, pgTable, text } from 'drizzle-orm/pg-core'; +import { + bigint, + bigserial, + boolean, + char, + cidr, + date, + doublePrecision, + inet, + integer, + interval, + json, + jsonb, + macaddr, + macaddr8, + numeric, + pgEnum, + pgSchema, + pgTable, + real, + serial, + smallint, + smallserial, + text, + time, + timestamp, + uuid, + varchar, +} from 'drizzle-orm/pg-core'; import { introspectPgToFile } from 'tests/schemaDiffer'; import { expect, test } from 'vitest'; @@ -186,3 +214,194 @@ test('generated column: link to another column', async () => { expect(statements.length).toBe(0); expect(sqlStatements.length).toBe(0); }); + +test('instrospect all column types', async () => { + const client = new PGlite(); + + const myEnum = pgEnum('my_enum', ['a', 'b', 'c']); + const schema = { + enum_: myEnum, + // NOTE: Types from extensions aren't tested due to PGLite not supporting at the moment + columns: pgTable('columns', { + enum: myEnum('my_enum').default('a'), + smallint: smallint('smallint').default(10), + integer: integer('integer').default(10), + numeric: numeric('numeric', { precision: 3, scale: 1 }).default('99.9'), + bigint: bigint('bigint', { mode: 'number' }).default(100), + boolean: boolean('boolean').default(true), + text: text('test').default('abc'), + varchar: varchar('varchar', { length: 25 }).default('abc'), + char: char('char', { length: 3 }).default('abc'), + serial: serial('serial'), + bigserial: bigserial('bigserial', { mode: 'number' }), + smallserial: smallserial('smallserial'), + doublePrecision: doublePrecision('doublePrecision').default(100), + real: real('real').default(100), + json: json('json').$type<{ attr: string }>().default({ attr: 'value' }), + jsonb: jsonb('jsonb').$type<{ attr: string }>().default({ attr: 'value' }), + time1: time('time1').default('00:00:00'), + time2: time('time2').defaultNow(), + timestamp1: timestamp('timestamp1', { withTimezone: true, precision: 6 }).default(new Date()), + timestamp2: timestamp('timestamp2', { withTimezone: true, precision: 6 }).defaultNow(), + date1: date('date1').default('2024-01-01'), + date2: date('date2').defaultNow(), + uuid1: uuid('uuid1').default('a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11'), + uuid2: uuid('uuid2').defaultRandom(), + inet: inet('inet').default('127.0.0.1'), + cidr: cidr('cidr').default('127.0.0.1/32'), + macaddr: macaddr('macaddr').default('00:00:00:00:00:00'), + macaddr8: macaddr8('macaddr8').default('00:00:00:ff:fe:00:00:00'), + interval: interval('interval').default('1 day 01:00:00'), + }), + }; + + const { statements, sqlStatements } = await introspectPgToFile( + client, + schema, + 'introspect-all-columns-types', + ); + + expect(statements.length).toBe(0); + expect(sqlStatements.length).toBe(0); +}); + +test('instrospect all column array types', async () => { + const client = new PGlite(); + + const myEnum = pgEnum('my_enum', ['a', 'b', 'c']); + const schema = { + enum_: myEnum, + // NOTE: Types from extensions aren't tested due to PGLite not supporting at the moment + columns: pgTable('columns', { + enum: myEnum('my_enum').array().default(['a', 'b']), + smallint: smallint('smallint').array().default([10, 20]), + integer: integer('integer').array().default([10, 20]), + numeric: numeric('numeric', { precision: 3, scale: 1 }).array().default(['99.9', '88.8']), + bigint: bigint('bigint', { mode: 'number' }).array().default([100, 200]), + boolean: boolean('boolean').array().default([true, false]), + text: text('test').array().default(['abc', 'def']), + varchar: varchar('varchar', { length: 25 }).array().default(['abc', 'def']), + char: char('char', { length: 3 }).array().default(['abc', 'def']), + doublePrecision: doublePrecision('doublePrecision').array().default([100, 200]), + real: real('real').array().default([100, 200]), + json: json('json').$type<{ attr: string }>().array().default([{ attr: 'value1' }, { attr: 'value2' }]), + jsonb: jsonb('jsonb').$type<{ attr: string }>().array().default([{ attr: 'value1' }, { attr: 'value2' }]), + time: time('time').array().default(['00:00:00', '01:00:00']), + timestamp: timestamp('timestamp', { withTimezone: true, precision: 6 }) + .array() + .default([new Date(), new Date()]), + date: date('date').array().default(['2024-01-01', '2024-01-02']), + uuid: uuid('uuid').array().default([ + 'a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11', + 'a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a12', + ]), + inet: inet('inet').array().default(['127.0.0.1', '127.0.0.2']), + cidr: cidr('cidr').array().default(['127.0.0.1/32', '127.0.0.2/32']), + macaddr: macaddr('macaddr').array().default(['00:00:00:00:00:00', '00:00:00:00:00:01']), + macaddr8: macaddr8('macaddr8').array().default(['00:00:00:ff:fe:00:00:00', '00:00:00:ff:fe:00:00:01']), + interval: interval('interval').array().default(['1 day 01:00:00', '1 day 02:00:00']), + }), + }; + + const { statements, sqlStatements } = await introspectPgToFile( + client, + schema, + 'introspect-all-columns-array-types', + ); + + expect(statements.length).toBe(0); + expect(sqlStatements.length).toBe(0); +}); + +test('introspect columns with name with non-alphanumeric characters', async () => { + const client = new PGlite(); + const schema = { + users: pgTable('users', { + 'not:allowed': integer('not:allowed'), + 'nuh--uh': integer('nuh-uh'), + '1_nope': integer('1_nope'), + valid: integer('valid'), + }), + }; + + const { statements, sqlStatements } = await introspectPgToFile( + client, + schema, + 'introspect-column-with-name-with-non-alphanumeric-characters', + ); + + expect(statements.length).toBe(0); + expect(sqlStatements.length).toBe(0); +}); + +test('introspect enum from different schema', async () => { + const client = new PGlite(); + + const schema2 = pgSchema('schema2'); + const myEnumInSchema2 = schema2.enum('my_enum', ['a', 'b', 'c']); + const schema = { + schema2, + myEnumInSchema2, + users: pgTable('users', { + col: myEnumInSchema2('col'), + }), + }; + + const { statements, sqlStatements } = await introspectPgToFile( + client, + schema, + 'introspect-enum-from-different-schema', + ['public', 'schema2'], + ); + + expect(statements.length).toBe(0); + expect(sqlStatements.length).toBe(0); +}); + +test('introspect enum with same names across different schema', async () => { + const client = new PGlite(); + + const schema2 = pgSchema('schema2'); + const myEnumInSchema2 = schema2.enum('my_enum', ['a', 'b', 'c']); + const myEnum = pgEnum('my_enum', ['a', 'b', 'c']); + const schema = { + schema2, + myEnumInSchema2, + myEnum, + users: pgTable('users', { + col1: myEnumInSchema2('col1'), + col2: myEnum('col2'), + }), + }; + + const { statements, sqlStatements } = await introspectPgToFile( + client, + schema, + 'introspect-enum-with-same-names-across-different-schema', + ['public', 'schema2'], + ); + + expect(statements.length).toBe(0); + expect(sqlStatements.length).toBe(0); +}); + +test('introspect enum with similar name to native type', async () => { + const client = new PGlite(); + + const timeLeft = pgEnum('time_left', ['short', 'medium', 'long']); + const schema = { + timeLeft, + auction: pgTable('auction', { + col: timeLeft('col1'), + }), + }; + + const { statements, sqlStatements } = await introspectPgToFile( + client, + schema, + 'introspect-enum-with-similar-name-to-native-type', + ); + + expect(statements.length).toBe(0); + expect(sqlStatements.length).toBe(0); +}); diff --git a/drizzle-kit/tests/pg-array.test.ts b/drizzle-kit/tests/pg-array.test.ts index a35411adb..e6c06d535 100644 --- a/drizzle-kit/tests/pg-array.test.ts +++ b/drizzle-kit/tests/pg-array.test.ts @@ -34,7 +34,7 @@ test('array #1: empty array default', async (t) => { type: 'alter_table_add_column', tableName: 'test', schema: '', - column: { name: 'values', type: 'integer[]', primaryKey: false, notNull: false, default: "'{}'::integer[]" }, + column: { name: 'values', type: 'integer[]', primaryKey: false, notNull: false, default: "'{}'" }, }); }); @@ -58,7 +58,7 @@ test('array #2: integer array default', async (t) => { type: 'alter_table_add_column', tableName: 'test', schema: '', - column: { name: 'values', type: 'integer[]', primaryKey: false, notNull: false, default: "'{1,2,3}'::integer[]" }, + column: { name: 'values', type: 'integer[]', primaryKey: false, notNull: false, default: "'{1,2,3}'" }, }); }); @@ -82,7 +82,7 @@ test('array #3: bigint array default', async (t) => { type: 'alter_table_add_column', tableName: 'test', schema: '', - column: { name: 'values', type: 'bigint[]', primaryKey: false, notNull: false, default: "'{1,2,3}'::bigint[]" }, + column: { name: 'values', type: 'bigint[]', primaryKey: false, notNull: false, default: "'{1,2,3}'" }, }); }); @@ -111,7 +111,7 @@ test('array #4: boolean array default', async (t) => { type: 'boolean[]', primaryKey: false, notNull: false, - default: "'{true,false,true}'::boolean[]", + default: "'{true,false,true}'", }, }); }); @@ -141,7 +141,7 @@ test('array #5: multi-dimensional array default', async (t) => { type: 'integer[][]', primaryKey: false, notNull: false, - default: "'{{1,2},{3,4}}'::integer[][]", + default: "'{{1,2},{3,4}}'", }, }); }); @@ -171,7 +171,7 @@ test('array #6: date array default', async (t) => { type: 'date[]', primaryKey: false, notNull: false, - default: '\'{"2024-08-06","2024-08-07"}\'::date[]', + default: '\'{"2024-08-06","2024-08-07"}\'', }, }); }); @@ -201,7 +201,7 @@ test('array #7: timestamp array default', async (t) => { type: 'timestamp[]', primaryKey: false, notNull: false, - default: '\'{"2024-08-06 00:00:00.000","2024-08-07 00:00:00.000"}\'::timestamp[]', + default: '\'{"2024-08-06 00:00:00.000","2024-08-07 00:00:00.000"}\'', }, }); }); @@ -231,7 +231,7 @@ test('array #8: json array default', async (t) => { type: 'json[]', primaryKey: false, notNull: false, - default: '\'{"{\\"a\\":1}","{\\"b\\":2}"}\'::json[]', + default: '\'{"{\\"a\\":1}","{\\"b\\":2}"}\'', }, }); }); @@ -261,7 +261,7 @@ test('array #9: text array default', async (t) => { type: 'text[]', primaryKey: false, notNull: false, - default: '\'{"abc","def"}\'::text[]', + default: '\'{"abc","def"}\'', }, }); }); @@ -294,7 +294,7 @@ test('array #10: uuid array default', async (t) => { type: 'uuid[]', primaryKey: false, notNull: false, - default: '\'{"a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11","b0eebc99-9c0b-4ef8-bb6d-cbb9bd380a11"}\'::uuid[]', + default: '\'{"a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11","b0eebc99-9c0b-4ef8-bb6d-cbb9bd380a11"}\'', }, }); }); @@ -328,7 +328,7 @@ test('array #11: enum array default', async (t) => { type: 'test_enum[]', primaryKey: false, notNull: false, - default: '\'{"a","b","c"}\'::test_enum[]', + default: '\'{"a","b","c"}\'', }, }); }); @@ -362,7 +362,7 @@ test('array #12: enum empty array default', async (t) => { type: 'test_enum[]', primaryKey: false, notNull: false, - default: "'{}'::test_enum[]", + default: "'{}'", }, }); }); diff --git a/drizzle-kit/tests/push/pg.test.ts b/drizzle-kit/tests/push/pg.test.ts index cd5908bad..cb1a97122 100644 --- a/drizzle-kit/tests/push/pg.test.ts +++ b/drizzle-kit/tests/push/pg.test.ts @@ -2192,11 +2192,11 @@ test('add array column - empty array default', async () => { type: 'alter_table_add_column', tableName: 'test', schema: '', - column: { name: 'values', type: 'integer[]', primaryKey: false, notNull: false, default: "'{}'::integer[]" }, + column: { name: 'values', type: 'integer[]', primaryKey: false, notNull: false, default: "'{}'" }, }, ]); expect(sqlStatements).toStrictEqual([ - 'ALTER TABLE "test" ADD COLUMN "values" integer[] DEFAULT \'{}\'::integer[];', + 'ALTER TABLE "test" ADD COLUMN "values" integer[] DEFAULT \'{}\';', ]); }); @@ -2229,10 +2229,10 @@ test('add array column - default', async () => { type: 'alter_table_add_column', tableName: 'test', schema: '', - column: { name: 'values', type: 'integer[]', primaryKey: false, notNull: false, default: "'{1,2,3}'::integer[]" }, + column: { name: 'values', type: 'integer[]', primaryKey: false, notNull: false, default: "'{1,2,3}'" }, }, ]); expect(sqlStatements).toStrictEqual([ - 'ALTER TABLE "test" ADD COLUMN "values" integer[] DEFAULT \'{1,2,3}\'::integer[];', + 'ALTER TABLE "test" ADD COLUMN "values" integer[] DEFAULT \'{1,2,3}\';', ]); }); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2fb00d93d..d2d091ad6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -45,7 +45,7 @@ importers: version: link:drizzle-orm/dist drizzle-orm-old: specifier: npm:drizzle-orm@^0.27.2 - version: drizzle-orm@0.27.2(@aws-sdk/client-rds-data@3.583.0)(@cloudflare/workers-types@4.20240524.0)(@libsql/client@0.6.0)(@neondatabase/serverless@0.9.3)(@opentelemetry/api@1.8.0)(@planetscale/database@1.18.0)(@types/better-sqlite3@7.6.10)(@types/pg@8.11.6)(@types/sql.js@1.4.9)(@vercel/postgres@0.8.0)(better-sqlite3@10.0.0)(bun-types@1.0.3)(knex@3.1.0(better-sqlite3@10.0.0)(mysql2@3.9.8)(pg@8.11.5)(sqlite3@5.1.7))(kysely@0.27.3)(mysql2@3.9.8)(pg@8.11.5)(postgres@3.4.4)(sql.js@1.10.3)(sqlite3@5.1.7) + version: drizzle-orm@0.27.2(@aws-sdk/client-rds-data@3.583.0)(@cloudflare/workers-types@4.20240524.0)(@libsql/client@0.5.6)(@neondatabase/serverless@0.9.3)(@opentelemetry/api@1.8.0)(@planetscale/database@1.18.0)(@types/better-sqlite3@7.6.10)(@types/pg@8.11.6)(@types/sql.js@1.4.9)(@vercel/postgres@0.8.0)(better-sqlite3@9.6.0)(bun-types@1.0.3)(knex@2.5.1(better-sqlite3@9.6.0)(mysql2@3.11.0)(pg@8.11.5)(sqlite3@5.1.7))(kysely@0.25.0)(mysql2@3.11.0)(pg@8.11.5)(postgres@3.4.4)(sql.js@1.10.3)(sqlite3@5.1.7) eslint: specifier: ^8.50.0 version: 8.50.0 @@ -92,8 +92,8 @@ importers: drizzle-kit: dependencies: '@drizzle-team/brocli': - specifier: ^0.8.2 - version: 0.8.2 + specifier: ^0.10.1 + version: 0.10.1 '@esbuild-kit/esm-loader': specifier: ^2.5.5 version: 2.5.5 @@ -237,8 +237,8 @@ importers: specifier: ^7.4.3 version: 7.4.6 mysql2: - specifier: 2.3.3 - version: 2.3.3 + specifier: 3.3.3 + version: 3.3.3 node-fetch: specifier: ^3.3.2 version: 3.3.2 @@ -1974,8 +1974,8 @@ packages: cpu: [x64] os: [win32] - '@drizzle-team/brocli@0.8.2': - resolution: {integrity: sha512-zTrFENsqGvOkBOuHDC1pXCkDXNd2UhP4lI3gYGhQ1R1SPeAAfqzPsV1dcpMy4uNU6kB5VpU5NGhvwxVNETR02A==} + '@drizzle-team/brocli@0.10.1': + resolution: {integrity: sha512-AHy0vjc+n/4w/8Mif+w86qpppHuF3AyXbcWW+R/W7GNA3F5/p2nuhlkCJaTXSLZheB4l1rtHzOfr9A7NwoR/Zg==} '@drizzle-team/studio@0.0.5': resolution: {integrity: sha512-ps5qF0tMxWRVu+V5gvCRrQNqlY92aTnIKdq27gm9LZMSdaKYZt6AVvSK1dlUMzs6Rt0Jm80b+eWct6xShBKhIw==} @@ -3084,18 +3084,12 @@ packages: '@libsql/client@0.5.6': resolution: {integrity: sha512-UBjmDoxz75Z2sHdP+ETCROpeLA/77VMesiff8R4UWK1rnaWbh6/YoCLDILMJL3Rh0udQeKxjL8MjXthqohax+g==} - '@libsql/client@0.6.0': - resolution: {integrity: sha512-qhQzTG/y2IEVbL3+9PULDvlQFWJ/RnjFXECr/Nc3nRngGiiMysDaOV5VUzYk7DulUX98EA4wi+z3FspKrUplUA==} - '@libsql/core@0.4.3': resolution: {integrity: sha512-r28iYBtaLBW9RRgXPFh6cGCsVI/rwRlOzSOpAu/1PVTm6EJ3t233pUf97jETVHU0vjdr1d8VvV6fKAvJkokqCw==} '@libsql/core@0.5.6': resolution: {integrity: sha512-3vicUAydq6jPth410n4AsHHm1n2psTwvkSf94nfJlSXutGSZsl0updn2N/mJBgqUHkbuFoWZtlMifF0SwBj1xQ==} - '@libsql/core@0.6.0': - resolution: {integrity: sha512-affAB8vSqQwqI9NBDJ5uJCVaHoOAS2pOpbv1kWConh1SBbmJBnHHd4KG73RAJ2sgd2+NbT9WA+XJBqxgp28YSw==} - '@libsql/darwin-arm64@0.2.0': resolution: {integrity: sha512-+qyT2W/n5CFH1YZWv2mxW4Fsoo4dX9Z9M/nvbQqZ7H84J8hVegvVAsIGYzcK8xAeMEcpU5yGKB1Y9NoDY4hOSQ==} cpu: [arm64] @@ -3119,15 +3113,9 @@ packages: '@libsql/hrana-client@0.5.6': resolution: {integrity: sha512-mjQoAmejZ1atG+M3YR2ZW+rg6ceBByH/S/h17ZoYZkqbWrvohFhXyz2LFxj++ARMoY9m6w3RJJIRdJdmnEUlFg==} - '@libsql/hrana-client@0.6.0': - resolution: {integrity: sha512-k+fqzdjqg3IvWfKmVJK5StsbjeTcyNAXFelUbXbGNz3yH1gEVT9mZ6kmhsIXP30ZSyVV0AE1Gi25p82mxC9hwg==} - '@libsql/isomorphic-fetch@0.1.12': resolution: {integrity: sha512-MRo4UcmjAGAa3ac56LoD5OE13m2p0lu0VEtZC2NZMcogM/jc5fU9YtMQ3qbPjFJ+u2BBjFZgMPkQaLS1dlMhpg==} - '@libsql/isomorphic-fetch@0.2.1': - resolution: {integrity: sha512-Sv07QP1Aw8A5OOrmKgRUBKe2fFhF2hpGJhtHe3d1aRnTESZCGkn//0zDycMKTGamVWb3oLYRroOsCV8Ukes9GA==} - '@libsql/isomorphic-ws@0.1.5': resolution: {integrity: sha512-DtLWIH29onUYR00i0GlQ3UdcTRC6EP4u9w/h9LxpUZJWRMARk6dQwZ6Jkd+QdwVpuAOrdxt18v0K2uIYR3fwFg==} @@ -4642,6 +4630,10 @@ packages: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} + aws-ssl-profiles@1.1.1: + resolution: {integrity: sha512-+H+kuK34PfMaI9PNU/NSjBKL5hh/KDM9J72kwYeYEm0A8B1AC4fuCy3qsjnA7lxklgyXsB68yn8Z2xoZEjgwCQ==} + engines: {node: '>= 6.0.0'} + axios@1.6.8: resolution: {integrity: sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==} @@ -4687,9 +4679,6 @@ packages: resolution: {integrity: sha512-aVNobHnJqLiUelTaHat9DZ1qM2w0C0Eym4LPI/3JxOnSokGVdsl1T1kN7TFvsEAD8G47A6VKQ0TVHqbBnYMJlQ==} engines: {node: '>=12.0.0'} - better-sqlite3@10.0.0: - resolution: {integrity: sha512-rOz0JY8bt9oMgrFssP7GnvA5R3yln73y/NizzWqy3WlFth8Ux8+g4r/N9fjX97nn4X1YX6MTER2doNpTu5pqiA==} - better-sqlite3@8.7.0: resolution: {integrity: sha512-99jZU4le+f3G6aIl6PmmV0cxUIWqKieHxsiF7G34CVFiE+/UabpYqkU0NJIkY/96mQKikHeBjtR27vFfs5JpEw==} @@ -7091,42 +7080,10 @@ packages: tedious: optional: true - knex@3.1.0: - resolution: {integrity: sha512-GLoII6hR0c4ti243gMs5/1Rb3B+AjwMOfjYm97pu0FOQa7JH56hgBxYf5WK2525ceSbBY1cjeZ9yk99GPMB6Kw==} - engines: {node: '>=16'} - hasBin: true - peerDependencies: - better-sqlite3: '*' - mysql: '*' - mysql2: '*' - pg: '*' - pg-native: '*' - sqlite3: '*' - tedious: '*' - peerDependenciesMeta: - better-sqlite3: - optional: true - mysql: - optional: true - mysql2: - optional: true - pg: - optional: true - pg-native: - optional: true - sqlite3: - optional: true - tedious: - optional: true - kysely@0.25.0: resolution: {integrity: sha512-srn0efIMu5IoEBk0tBmtGnoUss4uwvxtbFQWG/U2MosfqIace1l43IFP1PmEpHRDp+Z79xIcKEqmHH3dAvQdQA==} engines: {node: '>=14.0.0'} - kysely@0.27.3: - resolution: {integrity: sha512-lG03Ru+XyOJFsjH3OMY6R/9U38IjDPfnOfDgO3ynhbDr+Dz8fak+X6L62vqu3iybQnj+lG84OttBuU9KY3L9kA==} - engines: {node: '>=14.0.0'} - leven@3.1.0: resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} engines: {node: '>=6'} @@ -7323,9 +7280,6 @@ packages: resolution: {integrity: sha512-/3ER20CTTbahrCrpYfPn7Xavv9diBROZpoXGVZDWMw4b/X4uuUwAC0ki85tgsdMRONURyIJbcOvS94QsUBYPbQ==} hasBin: true - long@4.0.0: - resolution: {integrity: sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==} - long@5.2.3: resolution: {integrity: sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==} @@ -7672,18 +7626,14 @@ packages: resolution: {integrity: sha512-at/ZndSy3xEGJ8i0ygALh8ru9qy7gWW1cmkaqBN29JmMlIvM//MEO9y1sk/avxuwnPcfhkejkLsuPxH81BrkSg==} engines: {node: '>=0.8.0'} - mysql2@2.3.3: - resolution: {integrity: sha512-wxJUev6LgMSgACDkb/InIFxDprRa6T95+VEoR+xPvtngtccNH2dGjEB/fVZ8yg1gWv1510c9CvXuJHi5zUm0ZA==} + mysql2@3.11.0: + resolution: {integrity: sha512-J9phbsXGvTOcRVPR95YedzVSxJecpW5A5+cQ57rhHIFXteTP10HCs+VBjS7DHIKfEaI1zQ5tlVrquCd64A6YvA==} engines: {node: '>= 8.0'} mysql2@3.3.3: resolution: {integrity: sha512-MxDQJztArk4JFX1PKVjDhIXRzAmVJfuqZrVU+my6NeYBAA/XZRaDw5q7vga8TNvgyy3Lv3rivBFBBuJFbsdjaw==} engines: {node: '>= 8.0'} - mysql2@3.9.8: - resolution: {integrity: sha512-+5JKNjPuks1FNMoy9TYpl77f+5frbTklz7eb3XDwbpsERRLEeXiW2PDEkakYF50UuKU2qwfGnyXpKYvukv8mGA==} - engines: {node: '>= 8.0'} - mz@2.7.0: resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} @@ -8118,9 +8068,6 @@ packages: pg-connection-string@2.6.1: resolution: {integrity: sha512-w6ZzNu6oMmIzEAYVw+RLK0+nqHPt8K3ZnknKi+g48Ak2pr3dtljJW3o+D/n2zzCG07Zoe9VOX3aiKpj+BN0pjg==} - pg-connection-string@2.6.2: - resolution: {integrity: sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==} - pg-connection-string@2.6.4: resolution: {integrity: sha512-v+Z7W/0EO707aNMaAEfiGnGL9sxxumwLl2fJvCQtMn9Fxsg+lPpPkdcyBSv/KFgpGdYkMfn+EI1Or2EHjpgLCA==} @@ -10263,7 +10210,7 @@ snapshots: '@aws-sdk/client-sso-oidc': 3.583.0(@aws-sdk/client-sts@3.583.0) '@aws-sdk/client-sts': 3.583.0 '@aws-sdk/core': 3.582.0 - '@aws-sdk/credential-provider-node': 3.583.0(@aws-sdk/client-sso-oidc@3.583.0)(@aws-sdk/client-sts@3.583.0) + '@aws-sdk/credential-provider-node': 3.583.0(@aws-sdk/client-sso-oidc@3.583.0(@aws-sdk/client-sts@3.583.0))(@aws-sdk/client-sts@3.583.0) '@aws-sdk/middleware-host-header': 3.577.0 '@aws-sdk/middleware-logger': 3.577.0 '@aws-sdk/middleware-recursion-detection': 3.577.0 @@ -10353,7 +10300,7 @@ snapshots: '@aws-crypto/sha256-js': 3.0.0 '@aws-sdk/client-sts': 3.583.0 '@aws-sdk/core': 3.582.0 - '@aws-sdk/credential-provider-node': 3.583.0(@aws-sdk/client-sso-oidc@3.583.0)(@aws-sdk/client-sts@3.583.0) + '@aws-sdk/credential-provider-node': 3.583.0(@aws-sdk/client-sso-oidc@3.583.0(@aws-sdk/client-sts@3.583.0))(@aws-sdk/client-sts@3.583.0) '@aws-sdk/middleware-host-header': 3.577.0 '@aws-sdk/middleware-logger': 3.577.0 '@aws-sdk/middleware-recursion-detection': 3.577.0 @@ -10663,7 +10610,7 @@ snapshots: '@aws-crypto/sha256-js': 3.0.0 '@aws-sdk/client-sso-oidc': 3.583.0(@aws-sdk/client-sts@3.583.0) '@aws-sdk/core': 3.582.0 - '@aws-sdk/credential-provider-node': 3.583.0(@aws-sdk/client-sso-oidc@3.583.0)(@aws-sdk/client-sts@3.583.0) + '@aws-sdk/credential-provider-node': 3.583.0(@aws-sdk/client-sso-oidc@3.583.0(@aws-sdk/client-sts@3.583.0))(@aws-sdk/client-sts@3.583.0) '@aws-sdk/middleware-host-header': 3.577.0 '@aws-sdk/middleware-logger': 3.577.0 '@aws-sdk/middleware-recursion-detection': 3.577.0 @@ -10852,12 +10799,12 @@ snapshots: - '@aws-sdk/client-sso-oidc' - aws-crt - '@aws-sdk/credential-provider-ini@3.583.0(@aws-sdk/client-sso-oidc@3.583.0)(@aws-sdk/client-sts@3.583.0)': + '@aws-sdk/credential-provider-ini@3.583.0(@aws-sdk/client-sso-oidc@3.583.0(@aws-sdk/client-sts@3.583.0))(@aws-sdk/client-sts@3.583.0)': dependencies: '@aws-sdk/client-sts': 3.583.0 '@aws-sdk/credential-provider-env': 3.577.0 '@aws-sdk/credential-provider-process': 3.577.0 - '@aws-sdk/credential-provider-sso': 3.583.0(@aws-sdk/client-sso-oidc@3.583.0) + '@aws-sdk/credential-provider-sso': 3.583.0(@aws-sdk/client-sso-oidc@3.583.0(@aws-sdk/client-sts@3.583.0)) '@aws-sdk/credential-provider-web-identity': 3.577.0(@aws-sdk/client-sts@3.583.0) '@aws-sdk/types': 3.577.0 '@smithy/credential-provider-imds': 3.0.0 @@ -10942,13 +10889,13 @@ snapshots: - '@aws-sdk/client-sts' - aws-crt - '@aws-sdk/credential-provider-node@3.583.0(@aws-sdk/client-sso-oidc@3.583.0)(@aws-sdk/client-sts@3.583.0)': + '@aws-sdk/credential-provider-node@3.583.0(@aws-sdk/client-sso-oidc@3.583.0(@aws-sdk/client-sts@3.583.0))(@aws-sdk/client-sts@3.583.0)': dependencies: '@aws-sdk/credential-provider-env': 3.577.0 '@aws-sdk/credential-provider-http': 3.582.0 - '@aws-sdk/credential-provider-ini': 3.583.0(@aws-sdk/client-sso-oidc@3.583.0)(@aws-sdk/client-sts@3.583.0) + '@aws-sdk/credential-provider-ini': 3.583.0(@aws-sdk/client-sso-oidc@3.583.0(@aws-sdk/client-sts@3.583.0))(@aws-sdk/client-sts@3.583.0) '@aws-sdk/credential-provider-process': 3.577.0 - '@aws-sdk/credential-provider-sso': 3.583.0(@aws-sdk/client-sso-oidc@3.583.0) + '@aws-sdk/credential-provider-sso': 3.583.0(@aws-sdk/client-sso-oidc@3.583.0(@aws-sdk/client-sts@3.583.0)) '@aws-sdk/credential-provider-web-identity': 3.577.0(@aws-sdk/client-sts@3.583.0) '@aws-sdk/types': 3.577.0 '@smithy/credential-provider-imds': 3.0.0 @@ -11023,10 +10970,10 @@ snapshots: - '@aws-sdk/client-sso-oidc' - aws-crt - '@aws-sdk/credential-provider-sso@3.583.0(@aws-sdk/client-sso-oidc@3.583.0)': + '@aws-sdk/credential-provider-sso@3.583.0(@aws-sdk/client-sso-oidc@3.583.0(@aws-sdk/client-sts@3.583.0))': dependencies: '@aws-sdk/client-sso': 3.583.0 - '@aws-sdk/token-providers': 3.577.0(@aws-sdk/client-sso-oidc@3.583.0) + '@aws-sdk/token-providers': 3.577.0(@aws-sdk/client-sso-oidc@3.583.0(@aws-sdk/client-sts@3.583.0)) '@aws-sdk/types': 3.577.0 '@smithy/property-provider': 3.0.0 '@smithy/shared-ini-file-loader': 3.0.0 @@ -11269,7 +11216,7 @@ snapshots: '@smithy/types': 2.12.0 tslib: 2.6.2 - '@aws-sdk/token-providers@3.577.0(@aws-sdk/client-sso-oidc@3.583.0)': + '@aws-sdk/token-providers@3.577.0(@aws-sdk/client-sso-oidc@3.583.0(@aws-sdk/client-sts@3.583.0))': dependencies: '@aws-sdk/client-sso-oidc': 3.583.0(@aws-sdk/client-sts@3.583.0) '@aws-sdk/types': 3.577.0 @@ -12411,7 +12358,7 @@ snapshots: '@dprint/win32-x64@0.46.3': optional: true - '@drizzle-team/brocli@0.8.2': {} + '@drizzle-team/brocli@0.10.1': {} '@drizzle-team/studio@0.0.5': {} @@ -13404,17 +13351,6 @@ snapshots: - encoding - utf-8-validate - '@libsql/client@0.6.0': - dependencies: - '@libsql/core': 0.6.0 - '@libsql/hrana-client': 0.6.0 - js-base64: 3.7.7 - libsql: 0.3.18 - transitivePeerDependencies: - - bufferutil - - utf-8-validate - optional: true - '@libsql/core@0.4.3': dependencies: js-base64: 3.7.7 @@ -13423,11 +13359,6 @@ snapshots: dependencies: js-base64: 3.7.7 - '@libsql/core@0.6.0': - dependencies: - js-base64: 3.7.7 - optional: true - '@libsql/darwin-arm64@0.2.0': optional: true @@ -13451,17 +13382,6 @@ snapshots: - encoding - utf-8-validate - '@libsql/hrana-client@0.6.0': - dependencies: - '@libsql/isomorphic-fetch': 0.2.1 - '@libsql/isomorphic-ws': 0.1.5(bufferutil@4.0.8)(utf-8-validate@6.0.3) - js-base64: 3.7.7 - node-fetch: 3.3.2 - transitivePeerDependencies: - - bufferutil - - utf-8-validate - optional: true - '@libsql/isomorphic-fetch@0.1.12(encoding@0.1.13)': dependencies: '@types/node-fetch': 2.6.11 @@ -13469,9 +13389,6 @@ snapshots: transitivePeerDependencies: - encoding - '@libsql/isomorphic-fetch@0.2.1': - optional: true - '@libsql/isomorphic-ws@0.1.5(bufferutil@4.0.8)(utf-8-validate@6.0.3)': dependencies: '@types/ws': 8.5.11 @@ -15508,6 +15425,9 @@ snapshots: dependencies: possible-typed-array-names: 1.0.0 + aws-ssl-profiles@1.1.1: + optional: true + axios@1.6.8: dependencies: follow-redirects: 1.15.6 @@ -15580,12 +15500,6 @@ snapshots: dependencies: open: 8.4.2 - better-sqlite3@10.0.0: - dependencies: - bindings: 1.5.0 - prebuild-install: 7.1.2 - optional: true - better-sqlite3@8.7.0: dependencies: bindings: 1.5.0 @@ -16399,11 +16313,11 @@ snapshots: transitivePeerDependencies: - supports-color - drizzle-orm@0.27.2(@aws-sdk/client-rds-data@3.583.0)(@cloudflare/workers-types@4.20240524.0)(@libsql/client@0.6.0)(@neondatabase/serverless@0.9.3)(@opentelemetry/api@1.8.0)(@planetscale/database@1.18.0)(@types/better-sqlite3@7.6.10)(@types/pg@8.11.6)(@types/sql.js@1.4.9)(@vercel/postgres@0.8.0)(better-sqlite3@10.0.0)(bun-types@1.0.3)(knex@3.1.0(better-sqlite3@10.0.0)(mysql2@3.9.8)(pg@8.11.5)(sqlite3@5.1.7))(kysely@0.27.3)(mysql2@3.9.8)(pg@8.11.5)(postgres@3.4.4)(sql.js@1.10.3)(sqlite3@5.1.7): + drizzle-orm@0.27.2(@aws-sdk/client-rds-data@3.583.0)(@cloudflare/workers-types@4.20240524.0)(@libsql/client@0.5.6)(@neondatabase/serverless@0.9.3)(@opentelemetry/api@1.8.0)(@planetscale/database@1.18.0)(@types/better-sqlite3@7.6.10)(@types/pg@8.11.6)(@types/sql.js@1.4.9)(@vercel/postgres@0.8.0)(better-sqlite3@9.6.0)(bun-types@1.0.3)(knex@2.5.1(better-sqlite3@9.6.0)(mysql2@3.11.0)(pg@8.11.5)(sqlite3@5.1.7))(kysely@0.25.0)(mysql2@3.11.0)(pg@8.11.5)(postgres@3.4.4)(sql.js@1.10.3)(sqlite3@5.1.7): optionalDependencies: '@aws-sdk/client-rds-data': 3.583.0 '@cloudflare/workers-types': 4.20240524.0 - '@libsql/client': 0.6.0 + '@libsql/client': 0.5.6(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@6.0.3) '@neondatabase/serverless': 0.9.3 '@opentelemetry/api': 1.8.0 '@planetscale/database': 1.18.0 @@ -16411,11 +16325,11 @@ snapshots: '@types/pg': 8.11.6 '@types/sql.js': 1.4.9 '@vercel/postgres': 0.8.0 - better-sqlite3: 10.0.0 + better-sqlite3: 9.6.0 bun-types: 1.0.3 - knex: 3.1.0(better-sqlite3@10.0.0)(mysql2@3.9.8)(pg@8.11.5)(sqlite3@5.1.7) - kysely: 0.27.3 - mysql2: 3.9.8 + knex: 2.5.1(better-sqlite3@9.6.0)(mysql2@3.11.0)(pg@8.11.5)(sqlite3@5.1.7) + kysely: 0.25.0 + mysql2: 3.11.0 pg: 8.11.5 postgres: 3.4.4 sql.js: 1.10.3 @@ -18406,7 +18320,7 @@ snapshots: transitivePeerDependencies: - supports-color - knex@3.1.0(better-sqlite3@10.0.0)(mysql2@3.9.8)(pg@8.11.5)(sqlite3@5.1.7): + knex@2.5.1(better-sqlite3@9.6.0)(mysql2@3.11.0)(pg@8.11.5)(sqlite3@5.1.7): dependencies: colorette: 2.0.19 commander: 10.0.1 @@ -18417,14 +18331,14 @@ snapshots: getopts: 2.3.0 interpret: 2.2.0 lodash: 4.17.21 - pg-connection-string: 2.6.2 + pg-connection-string: 2.6.1 rechoir: 0.8.0 resolve-from: 5.0.0 tarn: 3.0.2 tildify: 2.0.0 optionalDependencies: - better-sqlite3: 10.0.0 - mysql2: 3.9.8 + better-sqlite3: 9.6.0 + mysql2: 3.11.0 pg: 8.11.5 sqlite3: 5.1.7 transitivePeerDependencies: @@ -18433,9 +18347,6 @@ snapshots: kysely@0.25.0: {} - kysely@0.27.3: - optional: true - leven@3.1.0: {} levn@0.4.1: @@ -18613,8 +18524,6 @@ snapshots: dayjs: 1.11.11 yargs: 15.4.1 - long@4.0.0: {} - long@5.2.3: {} loose-envify@1.4.0: @@ -19079,19 +18988,9 @@ snapshots: rimraf: 2.4.5 optional: true - mysql2@2.3.3: - dependencies: - denque: 2.1.0 - generate-function: 2.3.1 - iconv-lite: 0.6.3 - long: 4.0.0 - lru-cache: 6.0.0 - named-placeholders: 1.1.3 - seq-queue: 0.0.5 - sqlstring: 2.3.3 - - mysql2@3.3.3: + mysql2@3.11.0: dependencies: + aws-ssl-profiles: 1.1.1 denque: 2.1.0 generate-function: 2.3.1 iconv-lite: 0.6.3 @@ -19100,8 +18999,9 @@ snapshots: named-placeholders: 1.1.3 seq-queue: 0.0.5 sqlstring: 2.3.3 + optional: true - mysql2@3.9.8: + mysql2@3.3.3: dependencies: denque: 2.1.0 generate-function: 2.3.1 @@ -19111,7 +19011,6 @@ snapshots: named-placeholders: 1.1.3 seq-queue: 0.0.5 sqlstring: 2.3.3 - optional: true mz@2.7.0: dependencies: @@ -19541,9 +19440,6 @@ snapshots: pg-connection-string@2.6.1: {} - pg-connection-string@2.6.2: - optional: true - pg-connection-string@2.6.4: {} pg-int8@1.0.1: {}