metal-orm 1.0.10 → 1.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/README.md +17 -15
  2. package/dist/decorators/index.cjs +15 -2
  3. package/dist/decorators/index.cjs.map +1 -1
  4. package/dist/decorators/index.d.cts +1 -1
  5. package/dist/decorators/index.d.ts +1 -1
  6. package/dist/decorators/index.js +15 -2
  7. package/dist/decorators/index.js.map +1 -1
  8. package/dist/index.cjs +1394 -149
  9. package/dist/index.cjs.map +1 -1
  10. package/dist/index.d.cts +257 -23
  11. package/dist/index.d.ts +257 -23
  12. package/dist/index.js +1376 -149
  13. package/dist/index.js.map +1 -1
  14. package/dist/{select-654m4qy8.d.cts → select-BKlr2ivY.d.cts} +141 -4
  15. package/dist/{select-654m4qy8.d.ts → select-BKlr2ivY.d.ts} +141 -4
  16. package/package.json +1 -1
  17. package/src/core/ddl/dialects/base-schema-dialect.ts +48 -0
  18. package/src/core/ddl/dialects/index.ts +5 -0
  19. package/src/core/ddl/dialects/mssql-schema-dialect.ts +97 -0
  20. package/src/core/ddl/dialects/mysql-schema-dialect.ts +109 -0
  21. package/src/core/ddl/dialects/postgres-schema-dialect.ts +99 -0
  22. package/src/core/ddl/dialects/sqlite-schema-dialect.ts +103 -0
  23. package/src/core/ddl/introspect/mssql.ts +149 -0
  24. package/src/core/ddl/introspect/mysql.ts +99 -0
  25. package/src/core/ddl/introspect/postgres.ts +154 -0
  26. package/src/core/ddl/introspect/sqlite.ts +66 -0
  27. package/src/core/ddl/introspect/types.ts +19 -0
  28. package/src/core/ddl/introspect/utils.ts +27 -0
  29. package/src/core/ddl/schema-diff.ts +179 -0
  30. package/src/core/ddl/schema-generator.ts +229 -0
  31. package/src/core/ddl/schema-introspect.ts +32 -0
  32. package/src/core/ddl/schema-types.ts +39 -0
  33. package/src/core/dialect/base/sql-dialect.ts +161 -0
  34. package/src/core/dialect/mysql/index.ts +18 -112
  35. package/src/core/dialect/postgres/index.ts +30 -126
  36. package/src/core/dialect/sqlite/index.ts +29 -129
  37. package/src/index.ts +15 -10
  38. package/src/schema/column.ts +206 -27
  39. package/src/schema/table.ts +89 -32
  40. package/src/schema/types.ts +8 -5
package/dist/index.cjs CHANGED
@@ -20,15 +20,21 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  var index_exports = {};
21
21
  __export(index_exports, {
22
22
  AsyncLocalStorage: () => AsyncLocalStorage,
23
+ BaseSchemaDialect: () => BaseSchemaDialect,
23
24
  DefaultBelongsToReference: () => DefaultBelongsToReference,
24
25
  DefaultHasManyCollection: () => DefaultHasManyCollection,
25
26
  DefaultManyToManyCollection: () => DefaultManyToManyCollection,
26
27
  DeleteQueryBuilder: () => DeleteQueryBuilder,
27
28
  EntityStatus: () => EntityStatus,
28
29
  InsertQueryBuilder: () => InsertQueryBuilder,
30
+ MSSqlSchemaDialect: () => MSSqlSchemaDialect,
29
31
  MySqlDialect: () => MySqlDialect,
32
+ MySqlSchemaDialect: () => MySqlSchemaDialect,
30
33
  OrmContext: () => OrmContext,
34
+ PostgresDialect: () => PostgresDialect,
35
+ PostgresSchemaDialect: () => PostgresSchemaDialect,
31
36
  RelationKinds: () => RelationKinds,
37
+ SQLiteSchemaDialect: () => SQLiteSchemaDialect,
32
38
  SelectQueryBuilder: () => SelectQueryBuilder,
33
39
  SqlServerDialect: () => SqlServerDialect,
34
40
  SqliteDialect: () => SqliteDialect,
@@ -50,15 +56,22 @@ __export(index_exports, {
50
56
  createLiteral: () => createLiteral,
51
57
  defineTable: () => defineTable,
52
58
  denseRank: () => denseRank,
59
+ deriveIndexName: () => deriveIndexName,
60
+ diffSchema: () => diffSchema,
53
61
  eq: () => eq,
62
+ escapeLiteral: () => escapeLiteral,
54
63
  executeHydrated: () => executeHydrated,
55
64
  exists: () => exists,
56
65
  firstValue: () => firstValue,
66
+ formatLiteral: () => formatLiteral,
67
+ generateCreateTableSql: () => generateCreateTableSql,
68
+ generateSchemaSql: () => generateSchemaSql,
57
69
  gt: () => gt,
58
70
  gte: () => gte,
59
71
  hasMany: () => hasMany,
60
72
  hydrateRows: () => hydrateRows,
61
73
  inList: () => inList,
74
+ introspectSchema: () => introspectSchema,
62
75
  isCaseExpressionNode: () => isCaseExpressionNode,
63
76
  isExpressionSelectionNode: () => isExpressionSelectionNode,
64
77
  isFunctionNode: () => isFunctionNode,
@@ -83,9 +96,14 @@ __export(index_exports, {
83
96
  notLike: () => notLike,
84
97
  ntile: () => ntile,
85
98
  or: () => or,
99
+ quoteQualified: () => quoteQualified,
86
100
  rank: () => rank,
101
+ renderColumnDefinition: () => renderColumnDefinition,
102
+ renderIndexColumns: () => renderIndexColumns,
103
+ resolvePrimaryKey: () => resolvePrimaryKey,
87
104
  rowNumber: () => rowNumber,
88
105
  sum: () => sum,
106
+ synchronizeSchema: () => synchronizeSchema,
89
107
  valueToOperand: () => valueToOperand,
90
108
  visitExpression: () => visitExpression,
91
109
  visitOperand: () => visitOperand,
@@ -94,12 +112,25 @@ __export(index_exports, {
94
112
  module.exports = __toCommonJS(index_exports);
95
113
 
96
114
  // src/schema/table.ts
97
- var defineTable = (name, columns, relations = {}, hooks) => {
115
+ var defineTable = (name, columns, relations = {}, hooks, options = {}) => {
98
116
  const colsWithNames = Object.entries(columns).reduce((acc, [key, def]) => {
99
117
  acc[key] = { ...def, name: key, table: name };
100
118
  return acc;
101
119
  }, {});
102
- return { name, columns: colsWithNames, relations, hooks };
120
+ return {
121
+ name,
122
+ schema: options.schema,
123
+ columns: colsWithNames,
124
+ relations,
125
+ hooks,
126
+ primaryKey: options.primaryKey,
127
+ indexes: options.indexes,
128
+ checks: options.checks,
129
+ comment: options.comment,
130
+ engine: options.engine,
131
+ charset: options.charset,
132
+ collation: options.collation
133
+ };
103
134
  };
104
135
 
105
136
  // src/schema/column.ts
@@ -109,12 +140,52 @@ var col = {
109
140
  * @returns ColumnDef with INT type
110
141
  */
111
142
  int: () => ({ name: "", type: "INT" }),
143
+ /**
144
+ * Creates a big integer column definition
145
+ */
146
+ bigint: () => ({ name: "", type: "BIGINT" }),
112
147
  /**
113
148
  * Creates a variable character column definition
114
149
  * @param length - Maximum length of the string
115
150
  * @returns ColumnDef with VARCHAR type
116
151
  */
117
152
  varchar: (length) => ({ name: "", type: "VARCHAR", args: [length] }),
153
+ /**
154
+ * Creates a fixed precision decimal column definition
155
+ */
156
+ decimal: (precision, scale = 0) => ({
157
+ name: "",
158
+ type: "DECIMAL",
159
+ args: [precision, scale]
160
+ }),
161
+ /**
162
+ * Creates a floating point column definition
163
+ */
164
+ float: (precision) => ({
165
+ name: "",
166
+ type: "FLOAT",
167
+ args: precision !== void 0 ? [precision] : void 0
168
+ }),
169
+ /**
170
+ * Creates a UUID column definition
171
+ */
172
+ uuid: () => ({ name: "", type: "UUID" }),
173
+ /**
174
+ * Creates a timestamp column definition
175
+ */
176
+ timestamp: () => ({ name: "", type: "TIMESTAMP" }),
177
+ /**
178
+ * Creates a timestamptz column definition
179
+ */
180
+ timestamptz: () => ({ name: "", type: "TIMESTAMPTZ" }),
181
+ /**
182
+ * Creates a date column definition
183
+ */
184
+ date: () => ({ name: "", type: "DATE" }),
185
+ /**
186
+ * Creates a datetime column definition
187
+ */
188
+ datetime: () => ({ name: "", type: "DATETIME" }),
118
189
  /**
119
190
  * Creates a JSON column definition
120
191
  * @returns ColumnDef with JSON type
@@ -125,12 +196,64 @@ var col = {
125
196
  * @returns ColumnDef with BOOLEAN type
126
197
  */
127
198
  boolean: () => ({ name: "", type: "BOOLEAN" }),
199
+ /**
200
+ * Creates an enum column definition
201
+ * @param values - Enum values
202
+ */
203
+ enum: (values) => ({ name: "", type: "ENUM", args: values }),
128
204
  /**
129
205
  * Marks a column definition as a primary key
130
206
  * @param def - Column definition to modify
131
207
  * @returns Modified ColumnDef with primary: true
132
208
  */
133
- primaryKey: (def) => ({ ...def, primary: true })
209
+ primaryKey: (def) => ({ ...def, primary: true }),
210
+ /**
211
+ * Marks a column as NOT NULL
212
+ */
213
+ notNull: (def) => ({ ...def, notNull: true }),
214
+ /**
215
+ * Marks a column as UNIQUE
216
+ */
217
+ unique: (def, name) => ({
218
+ ...def,
219
+ unique: name ?? true
220
+ }),
221
+ /**
222
+ * Sets a default value for the column
223
+ */
224
+ default: (def, value) => ({
225
+ ...def,
226
+ default: value
227
+ }),
228
+ /**
229
+ * Sets a raw SQL default value for the column
230
+ */
231
+ defaultRaw: (def, expression) => ({
232
+ ...def,
233
+ default: { raw: expression }
234
+ }),
235
+ /**
236
+ * Marks a column as auto-increment / identity
237
+ */
238
+ autoIncrement: (def, strategy = "byDefault") => ({
239
+ ...def,
240
+ autoIncrement: true,
241
+ generated: strategy
242
+ }),
243
+ /**
244
+ * Adds a foreign key reference
245
+ */
246
+ references: (def, ref) => ({
247
+ ...def,
248
+ references: ref
249
+ }),
250
+ /**
251
+ * Adds a check constraint to the column
252
+ */
253
+ check: (def, expression) => ({
254
+ ...def,
255
+ check: expression
256
+ })
134
257
  };
135
258
 
136
259
  // src/schema/relation.ts
@@ -2994,8 +3117,132 @@ var Dialect = class {
2994
3117
  }
2995
3118
  };
2996
3119
 
3120
+ // src/core/dialect/base/sql-dialect.ts
3121
+ var SqlDialectBase = class extends Dialect {
3122
+ /**
3123
+ * Compiles SELECT query AST to SQL using common rules.
3124
+ */
3125
+ compileSelectAst(ast, ctx) {
3126
+ const ctes = this.compileCtes(ast, ctx);
3127
+ const columns = this.compileSelectColumns(ast, ctx);
3128
+ const from = this.compileFrom(ast.from);
3129
+ const joins = this.compileJoins(ast, ctx);
3130
+ const whereClause = this.compileWhere(ast.where, ctx);
3131
+ const groupBy = this.compileGroupBy(ast);
3132
+ const having = this.compileHaving(ast, ctx);
3133
+ const orderBy = this.compileOrderBy(ast);
3134
+ const pagination = this.compilePagination(ast, orderBy);
3135
+ return `${ctes}SELECT ${this.compileDistinct(ast)}${columns} FROM ${from}${joins}${whereClause}${groupBy}${having}${orderBy}${pagination}`;
3136
+ }
3137
+ compileInsertAst(ast, ctx) {
3138
+ const table = this.compileTableName(ast.into);
3139
+ const columnList = ast.columns.map((column) => `${this.quoteIdentifier(column.table)}.${this.quoteIdentifier(column.name)}`).join(", ");
3140
+ const values = ast.values.map((row) => `(${row.map((value) => this.compileOperand(value, ctx)).join(", ")})`).join(", ");
3141
+ const returning = this.compileReturning(ast.returning, ctx);
3142
+ return `INSERT INTO ${table} (${columnList}) VALUES ${values}${returning}`;
3143
+ }
3144
+ compileUpdateAst(ast, ctx) {
3145
+ const table = this.compileTableName(ast.table);
3146
+ const assignments = ast.set.map((assignment) => {
3147
+ const col2 = assignment.column;
3148
+ const target = `${this.quoteIdentifier(col2.table)}.${this.quoteIdentifier(col2.name)}`;
3149
+ const value = this.compileOperand(assignment.value, ctx);
3150
+ return `${target} = ${value}`;
3151
+ }).join(", ");
3152
+ const whereClause = this.compileWhere(ast.where, ctx);
3153
+ const returning = this.compileReturning(ast.returning, ctx);
3154
+ return `UPDATE ${table} SET ${assignments}${whereClause}${returning}`;
3155
+ }
3156
+ compileDeleteAst(ast, ctx) {
3157
+ const table = this.compileTableName(ast.from);
3158
+ const whereClause = this.compileWhere(ast.where, ctx);
3159
+ const returning = this.compileReturning(ast.returning, ctx);
3160
+ return `DELETE FROM ${table}${whereClause}${returning}`;
3161
+ }
3162
+ /**
3163
+ * Default RETURNING compilation: no support.
3164
+ */
3165
+ compileReturning(returning, _ctx) {
3166
+ if (!returning || returning.length === 0) return "";
3167
+ throw new Error("RETURNING is not supported by this dialect.");
3168
+ }
3169
+ /**
3170
+ * DISTINCT clause. Override for DISTINCT ON support.
3171
+ */
3172
+ compileDistinct(ast) {
3173
+ return ast.distinct ? "DISTINCT " : "";
3174
+ }
3175
+ compileSelectColumns(ast, ctx) {
3176
+ return ast.columns.map((c) => {
3177
+ const expr = this.compileOperand(c, ctx);
3178
+ if (c.alias) {
3179
+ if (c.alias.includes("(")) return c.alias;
3180
+ return `${expr} AS ${this.quoteIdentifier(c.alias)}`;
3181
+ }
3182
+ return expr;
3183
+ }).join(", ");
3184
+ }
3185
+ compileFrom(ast) {
3186
+ const base = this.compileTableName(ast);
3187
+ return ast.alias ? `${base} AS ${this.quoteIdentifier(ast.alias)}` : base;
3188
+ }
3189
+ compileTableName(table) {
3190
+ if (table.schema) {
3191
+ return `${this.quoteIdentifier(table.schema)}.${this.quoteIdentifier(table.name)}`;
3192
+ }
3193
+ return this.quoteIdentifier(table.name);
3194
+ }
3195
+ compileJoins(ast, ctx) {
3196
+ if (!ast.joins || ast.joins.length === 0) return "";
3197
+ const parts = ast.joins.map((j) => {
3198
+ const table = this.compileFrom(j.table);
3199
+ const cond = this.compileExpression(j.condition, ctx);
3200
+ return `${j.kind} JOIN ${table} ON ${cond}`;
3201
+ });
3202
+ return ` ${parts.join(" ")}`;
3203
+ }
3204
+ compileGroupBy(ast) {
3205
+ if (!ast.groupBy || ast.groupBy.length === 0) return "";
3206
+ const cols = ast.groupBy.map((c) => `${this.quoteIdentifier(c.table)}.${this.quoteIdentifier(c.name)}`).join(", ");
3207
+ return ` GROUP BY ${cols}`;
3208
+ }
3209
+ compileHaving(ast, ctx) {
3210
+ if (!ast.having) return "";
3211
+ return ` HAVING ${this.compileExpression(ast.having, ctx)}`;
3212
+ }
3213
+ compileOrderBy(ast) {
3214
+ if (!ast.orderBy || ast.orderBy.length === 0) return "";
3215
+ const parts = ast.orderBy.map((o) => `${this.quoteIdentifier(o.column.table)}.${this.quoteIdentifier(o.column.name)} ${o.direction}`).join(", ");
3216
+ return ` ORDER BY ${parts}`;
3217
+ }
3218
+ /**
3219
+ * Default LIMIT/OFFSET pagination clause.
3220
+ */
3221
+ compilePagination(ast, _orderByClause) {
3222
+ const parts = [];
3223
+ if (ast.limit !== void 0) parts.push(`LIMIT ${ast.limit}`);
3224
+ if (ast.offset !== void 0) parts.push(`OFFSET ${ast.offset}`);
3225
+ return parts.length ? ` ${parts.join(" ")}` : "";
3226
+ }
3227
+ compileCtes(ast, ctx) {
3228
+ if (!ast.ctes || ast.ctes.length === 0) return "";
3229
+ const hasRecursive = ast.ctes.some((cte) => cte.recursive);
3230
+ const prefix = hasRecursive ? "WITH RECURSIVE " : "WITH ";
3231
+ const cteDefs = ast.ctes.map((cte) => {
3232
+ const name = this.quoteIdentifier(cte.name);
3233
+ const cols = cte.columns && cte.columns.length ? `(${cte.columns.map((c) => this.quoteIdentifier(c)).join(", ")})` : "";
3234
+ const query = this.stripTrailingSemicolon(this.compileSelectAst(cte.query, ctx));
3235
+ return `${name}${cols} AS (${query})`;
3236
+ }).join(", ");
3237
+ return `${prefix}${cteDefs} `;
3238
+ }
3239
+ stripTrailingSemicolon(sql) {
3240
+ return sql.trim().replace(/;$/, "");
3241
+ }
3242
+ };
3243
+
2997
3244
  // src/core/dialect/mysql/index.ts
2998
- var MySqlDialect = class extends Dialect {
3245
+ var MySqlDialect = class extends SqlDialectBase {
2999
3246
  /**
3000
3247
  * Creates a new MySqlDialect instance
3001
3248
  */
@@ -3019,78 +3266,6 @@ var MySqlDialect = class extends Dialect {
3019
3266
  const col2 = `${this.quoteIdentifier(node.column.table)}.${this.quoteIdentifier(node.column.name)}`;
3020
3267
  return `${col2}->'${node.path}'`;
3021
3268
  }
3022
- /**
3023
- * Compiles SELECT query AST to MySQL SQL
3024
- * @param ast - Query AST
3025
- * @param ctx - Compiler context
3026
- * @returns MySQL SQL string
3027
- */
3028
- compileSelectAst(ast, ctx) {
3029
- const columns = ast.columns.map((c) => {
3030
- let expr = "";
3031
- if (c.type === "Function") {
3032
- expr = this.compileOperand(c, ctx);
3033
- } else if (c.type === "Column") {
3034
- expr = `${this.quoteIdentifier(c.table)}.${this.quoteIdentifier(c.name)}`;
3035
- } else if (c.type === "ScalarSubquery") {
3036
- expr = this.compileOperand(c, ctx);
3037
- } else if (c.type === "WindowFunction") {
3038
- expr = this.compileOperand(c, ctx);
3039
- }
3040
- if (c.alias) {
3041
- if (c.alias.includes("(")) return c.alias;
3042
- return `${expr} AS ${this.quoteIdentifier(c.alias)}`;
3043
- }
3044
- return expr;
3045
- }).join(", ");
3046
- const distinct = ast.distinct ? "DISTINCT " : "";
3047
- const from = `${this.quoteIdentifier(ast.from.name)}`;
3048
- const joins = ast.joins.map((j) => {
3049
- const table = this.quoteIdentifier(j.table.name);
3050
- const cond = this.compileExpression(j.condition, ctx);
3051
- return `${j.kind} JOIN ${table} ON ${cond}`;
3052
- }).join(" ");
3053
- const whereClause = this.compileWhere(ast.where, ctx);
3054
- const groupBy = ast.groupBy && ast.groupBy.length > 0 ? " GROUP BY " + ast.groupBy.map((c) => `${this.quoteIdentifier(c.table)}.${this.quoteIdentifier(c.name)}`).join(", ") : "";
3055
- const having = ast.having ? ` HAVING ${this.compileExpression(ast.having, ctx)}` : "";
3056
- const orderBy = ast.orderBy && ast.orderBy.length > 0 ? " ORDER BY " + ast.orderBy.map((o) => `${this.quoteIdentifier(o.column.table)}.${this.quoteIdentifier(o.column.name)} ${o.direction}`).join(", ") : "";
3057
- const limit = ast.limit ? ` LIMIT ${ast.limit}` : "";
3058
- const offset = ast.offset ? ` OFFSET ${ast.offset}` : "";
3059
- const ctes = ast.ctes && ast.ctes.length > 0 ? (() => {
3060
- const hasRecursive = ast.ctes.some((cte) => cte.recursive);
3061
- const prefix = hasRecursive ? "WITH RECURSIVE " : "WITH ";
3062
- const cteDefs = ast.ctes.map((cte) => {
3063
- const name = this.quoteIdentifier(cte.name);
3064
- const cols = cte.columns ? `(${cte.columns.map((c) => this.quoteIdentifier(c)).join(", ")})` : "";
3065
- const query = this.compileSelectAst(cte.query, ctx).trim().replace(/;$/, "");
3066
- return `${name}${cols} AS (${query})`;
3067
- }).join(", ");
3068
- return prefix + cteDefs + " ";
3069
- })() : "";
3070
- return `${ctes}SELECT ${distinct}${columns} FROM ${from}${joins ? " " + joins : ""}${whereClause}${groupBy}${having}${orderBy}${limit}${offset};`;
3071
- }
3072
- compileInsertAst(ast, ctx) {
3073
- const table = this.quoteIdentifier(ast.into.name);
3074
- const columnList = ast.columns.map((column) => `${this.quoteIdentifier(column.table)}.${this.quoteIdentifier(column.name)}`).join(", ");
3075
- const values = ast.values.map((row) => `(${row.map((value) => this.compileOperand(value, ctx)).join(", ")})`).join(", ");
3076
- return `INSERT INTO ${table} (${columnList}) VALUES ${values};`;
3077
- }
3078
- compileUpdateAst(ast, ctx) {
3079
- const table = this.quoteIdentifier(ast.table.name);
3080
- const assignments = ast.set.map((assignment) => {
3081
- const col2 = assignment.column;
3082
- const target = `${this.quoteIdentifier(col2.table)}.${this.quoteIdentifier(col2.name)}`;
3083
- const value = this.compileOperand(assignment.value, ctx);
3084
- return `${target} = ${value}`;
3085
- }).join(", ");
3086
- const whereClause = this.compileWhere(ast.where, ctx);
3087
- return `UPDATE ${table} SET ${assignments}${whereClause};`;
3088
- }
3089
- compileDeleteAst(ast, ctx) {
3090
- const table = this.quoteIdentifier(ast.from.name);
3091
- const whereClause = this.compileWhere(ast.where, ctx);
3092
- return `DELETE FROM ${table}${whereClause};`;
3093
- }
3094
3269
  };
3095
3270
 
3096
3271
  // src/core/dialect/mssql/index.ts
@@ -3204,7 +3379,7 @@ var SqlServerDialect = class extends Dialect {
3204
3379
  };
3205
3380
 
3206
3381
  // src/core/dialect/sqlite/index.ts
3207
- var SqliteDialect = class extends Dialect {
3382
+ var SqliteDialect = class extends SqlDialectBase {
3208
3383
  /**
3209
3384
  * Creates a new SqliteDialect instance
3210
3385
  */
@@ -3228,82 +3403,40 @@ var SqliteDialect = class extends Dialect {
3228
3403
  const col2 = `${this.quoteIdentifier(node.column.table)}.${this.quoteIdentifier(node.column.name)}`;
3229
3404
  return `json_extract(${col2}, '${node.path}')`;
3230
3405
  }
3231
- /**
3232
- * Compiles SELECT query AST to SQLite SQL
3233
- * @param ast - Query AST
3234
- * @param ctx - Compiler context
3235
- * @returns SQLite SQL string
3236
- */
3237
- compileSelectAst(ast, ctx) {
3238
- const columns = ast.columns.map((c) => {
3239
- let expr = "";
3240
- if (c.type === "Function") {
3241
- expr = this.compileOperand(c, ctx);
3242
- } else if (c.type === "Column") {
3243
- expr = `${this.quoteIdentifier(c.table)}.${this.quoteIdentifier(c.name)}`;
3244
- } else if (c.type === "ScalarSubquery") {
3245
- expr = this.compileOperand(c, ctx);
3246
- } else if (c.type === "CaseExpression") {
3247
- expr = this.compileOperand(c, ctx);
3248
- } else if (c.type === "WindowFunction") {
3249
- expr = this.compileOperand(c, ctx);
3250
- }
3251
- if (c.alias) {
3252
- if (c.alias.includes("(")) return c.alias;
3253
- return `${expr} AS ${this.quoteIdentifier(c.alias)}`;
3254
- }
3255
- return expr;
3406
+ compileReturning(returning, ctx) {
3407
+ if (!returning || returning.length === 0) return "";
3408
+ const columns = returning.map((column) => {
3409
+ const tablePart = column.table ? `${this.quoteIdentifier(column.table)}.` : "";
3410
+ return `${tablePart}${this.quoteIdentifier(column.name)}`;
3256
3411
  }).join(", ");
3257
- const distinct = ast.distinct ? "DISTINCT " : "";
3258
- const from = `${this.quoteIdentifier(ast.from.name)}`;
3259
- const joins = ast.joins.map((j) => {
3260
- const table = this.quoteIdentifier(j.table.name);
3261
- const cond = this.compileExpression(j.condition, ctx);
3262
- return `${j.kind} JOIN ${table} ON ${cond}`;
3263
- }).join(" ");
3264
- const whereClause = this.compileWhere(ast.where, ctx);
3265
- const groupBy = ast.groupBy && ast.groupBy.length > 0 ? " GROUP BY " + ast.groupBy.map((c) => `${this.quoteIdentifier(c.table)}.${this.quoteIdentifier(c.name)}`).join(", ") : "";
3266
- const having = ast.having ? ` HAVING ${this.compileExpression(ast.having, ctx)}` : "";
3267
- const orderBy = ast.orderBy && ast.orderBy.length > 0 ? " ORDER BY " + ast.orderBy.map((o) => `${this.quoteIdentifier(o.column.table)}.${this.quoteIdentifier(o.column.name)} ${o.direction}`).join(", ") : "";
3268
- const limit = ast.limit ? ` LIMIT ${ast.limit}` : "";
3269
- const offset = ast.offset ? ` OFFSET ${ast.offset}` : "";
3270
- const ctes = ast.ctes && ast.ctes.length > 0 ? (() => {
3271
- const hasRecursive = ast.ctes.some((cte) => cte.recursive);
3272
- const prefix = hasRecursive ? "WITH RECURSIVE " : "WITH ";
3273
- const cteDefs = ast.ctes.map((cte) => {
3274
- const name = this.quoteIdentifier(cte.name);
3275
- const cols = cte.columns ? `(${cte.columns.map((c) => this.quoteIdentifier(c)).join(", ")})` : "";
3276
- const query = this.compileSelectAst(cte.query, ctx).trim().replace(/;$/, "");
3277
- return `${name}${cols} AS (${query})`;
3278
- }).join(", ");
3279
- return prefix + cteDefs + " ";
3280
- })() : "";
3281
- return `${ctes}SELECT ${distinct}${columns} FROM ${from}${joins ? " " + joins : ""}${whereClause}${groupBy}${having}${orderBy}${limit}${offset};`;
3412
+ return ` RETURNING ${columns}`;
3282
3413
  }
3283
- compileInsertAst(ast, ctx) {
3284
- const table = this.quoteIdentifier(ast.into.name);
3285
- const columnList = ast.columns.map((column) => `${this.quoteIdentifier(column.table)}.${this.quoteIdentifier(column.name)}`).join(", ");
3286
- const values = ast.values.map((row) => `(${row.map((value) => this.compileOperand(value, ctx)).join(", ")})`).join(", ");
3287
- const returning = this.compileReturning(ast.returning, ctx);
3288
- return `INSERT INTO ${table} (${columnList}) VALUES ${values}${returning};`;
3414
+ };
3415
+
3416
+ // src/core/dialect/postgres/index.ts
3417
+ var PostgresDialect = class extends SqlDialectBase {
3418
+ /**
3419
+ * Creates a new PostgresDialect instance
3420
+ */
3421
+ constructor() {
3422
+ super();
3289
3423
  }
3290
- compileUpdateAst(ast, ctx) {
3291
- const table = this.quoteIdentifier(ast.table.name);
3292
- const assignments = ast.set.map((assignment) => {
3293
- const col2 = assignment.column;
3294
- const target = `${this.quoteIdentifier(col2.table)}.${this.quoteIdentifier(col2.name)}`;
3295
- const value = this.compileOperand(assignment.value, ctx);
3296
- return `${target} = ${value}`;
3297
- }).join(", ");
3298
- const whereClause = this.compileWhere(ast.where, ctx);
3299
- const returning = this.compileReturning(ast.returning, ctx);
3300
- return `UPDATE ${table} SET ${assignments}${whereClause}${returning};`;
3424
+ /**
3425
+ * Quotes an identifier using PostgreSQL double-quote syntax
3426
+ * @param id - Identifier to quote
3427
+ * @returns Quoted identifier
3428
+ */
3429
+ quoteIdentifier(id) {
3430
+ return `"${id}"`;
3301
3431
  }
3302
- compileDeleteAst(ast, ctx) {
3303
- const table = this.quoteIdentifier(ast.from.name);
3304
- const whereClause = this.compileWhere(ast.where, ctx);
3305
- const returning = this.compileReturning(ast.returning, ctx);
3306
- return `DELETE FROM ${table}${whereClause}${returning};`;
3432
+ /**
3433
+ * Compiles JSON path expression using PostgreSQL syntax
3434
+ * @param node - JSON path node
3435
+ * @returns PostgreSQL JSON path expression
3436
+ */
3437
+ compileJsonPath(node) {
3438
+ const col2 = `${this.quoteIdentifier(node.column.table)}.${this.quoteIdentifier(node.column.name)}`;
3439
+ return `${col2}->>'${node.path}'`;
3307
3440
  }
3308
3441
  compileReturning(returning, ctx) {
3309
3442
  if (!returning || returning.length === 0) return "";
@@ -3315,6 +3448,1100 @@ var SqliteDialect = class extends Dialect {
3315
3448
  }
3316
3449
  };
3317
3450
 
3451
+ // src/core/ddl/dialects/base-schema-dialect.ts
3452
+ var BaseSchemaDialect = class {
3453
+ supportsPartialIndexes() {
3454
+ return false;
3455
+ }
3456
+ formatTableName(table) {
3457
+ if (table.schema) {
3458
+ return `${this.quoteIdentifier(table.schema)}.${this.quoteIdentifier(table.name)}`;
3459
+ }
3460
+ return this.quoteIdentifier(table.name);
3461
+ }
3462
+ renderDefault(value, _column) {
3463
+ return formatLiteral(value, this.name);
3464
+ }
3465
+ renderReference(ref, _table) {
3466
+ const parts = ["REFERENCES", quoteQualified(this, ref.table), `(${this.quoteIdentifier(ref.column)})`];
3467
+ if (ref.onDelete) parts.push("ON DELETE", ref.onDelete);
3468
+ if (ref.onUpdate) parts.push("ON UPDATE", ref.onUpdate);
3469
+ if (ref.deferrable && this.name === "postgres") parts.push("DEFERRABLE INITIALLY DEFERRED");
3470
+ return parts.join(" ");
3471
+ }
3472
+ renderTableOptions(_table) {
3473
+ return void 0;
3474
+ }
3475
+ dropTableSql(table) {
3476
+ return [`DROP TABLE IF EXISTS ${this.formatTableName(table)};`];
3477
+ }
3478
+ warnDropColumn(_table, _column) {
3479
+ return void 0;
3480
+ }
3481
+ };
3482
+
3483
+ // src/core/ddl/dialects/postgres-schema-dialect.ts
3484
+ var PostgresSchemaDialect = class extends BaseSchemaDialect {
3485
+ constructor() {
3486
+ super(...arguments);
3487
+ this.name = "postgres";
3488
+ }
3489
+ quoteIdentifier(id) {
3490
+ return `"${id}"`;
3491
+ }
3492
+ renderColumnType(column) {
3493
+ switch (column.type) {
3494
+ case "INT":
3495
+ case "INTEGER":
3496
+ case "int":
3497
+ case "integer":
3498
+ return "integer";
3499
+ case "BIGINT":
3500
+ case "bigint":
3501
+ return "bigint";
3502
+ case "UUID":
3503
+ case "uuid":
3504
+ return "uuid";
3505
+ case "BOOLEAN":
3506
+ case "boolean":
3507
+ return "boolean";
3508
+ case "JSON":
3509
+ case "json":
3510
+ return "jsonb";
3511
+ case "DECIMAL":
3512
+ case "decimal":
3513
+ return column.args?.length ? `numeric(${column.args[0]}, ${column.args[1] ?? 0})` : "numeric";
3514
+ case "FLOAT":
3515
+ case "float":
3516
+ case "DOUBLE":
3517
+ case "double":
3518
+ return "double precision";
3519
+ case "TIMESTAMPTZ":
3520
+ case "timestamptz":
3521
+ return "timestamptz";
3522
+ case "TIMESTAMP":
3523
+ case "timestamp":
3524
+ return "timestamp";
3525
+ case "DATE":
3526
+ case "date":
3527
+ return "date";
3528
+ case "DATETIME":
3529
+ case "datetime":
3530
+ return "timestamp";
3531
+ case "VARCHAR":
3532
+ case "varchar":
3533
+ return column.args?.length ? `varchar(${column.args[0]})` : "varchar";
3534
+ case "TEXT":
3535
+ case "text":
3536
+ return "text";
3537
+ case "ENUM":
3538
+ case "enum":
3539
+ return "text";
3540
+ default:
3541
+ return String(column.type).toLowerCase();
3542
+ }
3543
+ }
3544
+ renderAutoIncrement(column) {
3545
+ if (!column.autoIncrement) return void 0;
3546
+ const strategy = column.generated === "always" ? "GENERATED ALWAYS" : "GENERATED BY DEFAULT";
3547
+ return `${strategy} AS IDENTITY`;
3548
+ }
3549
+ renderIndex(table, index) {
3550
+ const name = index.name || deriveIndexName(table, index);
3551
+ const cols = renderIndexColumns(this, index.columns);
3552
+ const unique = index.unique ? "UNIQUE " : "";
3553
+ const where = index.where ? ` WHERE ${index.where}` : "";
3554
+ return `CREATE ${unique}INDEX IF NOT EXISTS ${this.quoteIdentifier(name)} ON ${this.formatTableName(table)} (${cols})${where};`;
3555
+ }
3556
+ supportsPartialIndexes() {
3557
+ return true;
3558
+ }
3559
+ dropColumnSql(table, column) {
3560
+ return [`ALTER TABLE ${this.formatTableName(table)} DROP COLUMN ${this.quoteIdentifier(column)};`];
3561
+ }
3562
+ dropIndexSql(table, index) {
3563
+ const qualified = table.schema ? `${this.quoteIdentifier(table.schema)}.${this.quoteIdentifier(index)}` : this.quoteIdentifier(index);
3564
+ return [`DROP INDEX IF EXISTS ${qualified};`];
3565
+ }
3566
+ };
3567
+
3568
+ // src/core/ddl/dialects/mysql-schema-dialect.ts
3569
+ var MySqlSchemaDialect = class extends BaseSchemaDialect {
3570
+ constructor() {
3571
+ super(...arguments);
3572
+ this.name = "mysql";
3573
+ }
3574
+ quoteIdentifier(id) {
3575
+ return `\`${id}\``;
3576
+ }
3577
+ renderColumnType(column) {
3578
+ switch (column.type) {
3579
+ case "INT":
3580
+ case "INTEGER":
3581
+ case "int":
3582
+ case "integer":
3583
+ return "INT";
3584
+ case "BIGINT":
3585
+ case "bigint":
3586
+ return "BIGINT";
3587
+ case "UUID":
3588
+ case "uuid":
3589
+ return "CHAR(36)";
3590
+ case "BOOLEAN":
3591
+ case "boolean":
3592
+ return "TINYINT(1)";
3593
+ case "JSON":
3594
+ case "json":
3595
+ return "JSON";
3596
+ case "DECIMAL":
3597
+ case "decimal":
3598
+ return column.args?.length ? `DECIMAL(${column.args[0]},${column.args[1] ?? 0})` : "DECIMAL";
3599
+ case "FLOAT":
3600
+ case "float":
3601
+ return column.args?.length ? `FLOAT(${column.args[0]})` : "FLOAT";
3602
+ case "DOUBLE":
3603
+ case "double":
3604
+ return "DOUBLE";
3605
+ case "TIMESTAMPTZ":
3606
+ case "timestamptz":
3607
+ return "TIMESTAMP";
3608
+ case "TIMESTAMP":
3609
+ case "timestamp":
3610
+ return "TIMESTAMP";
3611
+ case "DATETIME":
3612
+ case "datetime":
3613
+ return "DATETIME";
3614
+ case "DATE":
3615
+ case "date":
3616
+ return "DATE";
3617
+ case "VARCHAR":
3618
+ case "varchar":
3619
+ return column.args?.length ? `VARCHAR(${column.args[0]})` : "VARCHAR(255)";
3620
+ case "TEXT":
3621
+ case "text":
3622
+ return "TEXT";
3623
+ case "ENUM":
3624
+ case "enum":
3625
+ return column.args && Array.isArray(column.args) && column.args.length ? `ENUM(${column.args.map((v) => `'${escapeLiteral(v)}'`).join(",")})` : "ENUM";
3626
+ default:
3627
+ return String(column.type).toUpperCase();
3628
+ }
3629
+ }
3630
+ renderDefault(value) {
3631
+ return formatLiteral(value, this.name);
3632
+ }
3633
+ renderAutoIncrement(column) {
3634
+ return column.autoIncrement ? "AUTO_INCREMENT" : void 0;
3635
+ }
3636
+ renderIndex(table, index) {
3637
+ if (index.where) {
3638
+ throw new Error("MySQL does not support partial/filtered indexes");
3639
+ }
3640
+ const name = index.name || deriveIndexName(table, index);
3641
+ const cols = renderIndexColumns(this, index.columns);
3642
+ const unique = index.unique ? "UNIQUE " : "";
3643
+ return `CREATE ${unique}INDEX ${this.quoteIdentifier(name)} ON ${this.formatTableName(table)} (${cols});`;
3644
+ }
3645
+ renderTableOptions(table) {
3646
+ const parts = [];
3647
+ if (table.engine) parts.push(`ENGINE=${table.engine}`);
3648
+ if (table.charset) parts.push(`DEFAULT CHARSET=${table.charset}`);
3649
+ if (table.collation) parts.push(`COLLATE=${table.collation}`);
3650
+ return parts.length ? parts.join(" ") : void 0;
3651
+ }
3652
+ dropColumnSql(table, column) {
3653
+ return [`ALTER TABLE ${this.formatTableName(table)} DROP COLUMN ${this.quoteIdentifier(column)};`];
3654
+ }
3655
+ dropIndexSql(table, index) {
3656
+ return [`DROP INDEX ${this.quoteIdentifier(index)} ON ${this.formatTableName(table)};`];
3657
+ }
3658
+ };
3659
+
3660
+ // src/core/ddl/dialects/sqlite-schema-dialect.ts
3661
+ var SQLiteSchemaDialect = class extends BaseSchemaDialect {
3662
+ constructor() {
3663
+ super(...arguments);
3664
+ this.name = "sqlite";
3665
+ }
3666
+ quoteIdentifier(id) {
3667
+ return `"${id}"`;
3668
+ }
3669
+ renderColumnType(column) {
3670
+ switch (column.type) {
3671
+ case "INT":
3672
+ case "INTEGER":
3673
+ case "int":
3674
+ case "integer":
3675
+ case "BIGINT":
3676
+ case "bigint":
3677
+ return "INTEGER";
3678
+ case "BOOLEAN":
3679
+ case "boolean":
3680
+ return "INTEGER";
3681
+ case "DECIMAL":
3682
+ case "decimal":
3683
+ case "FLOAT":
3684
+ case "float":
3685
+ case "DOUBLE":
3686
+ case "double":
3687
+ return "REAL";
3688
+ case "DATE":
3689
+ case "date":
3690
+ case "DATETIME":
3691
+ case "datetime":
3692
+ case "TIMESTAMP":
3693
+ case "timestamp":
3694
+ case "TIMESTAMPTZ":
3695
+ case "timestamptz":
3696
+ return "TEXT";
3697
+ case "VARCHAR":
3698
+ case "varchar":
3699
+ case "TEXT":
3700
+ case "text":
3701
+ case "JSON":
3702
+ case "json":
3703
+ case "UUID":
3704
+ case "uuid":
3705
+ return "TEXT";
3706
+ case "ENUM":
3707
+ case "enum":
3708
+ return "TEXT";
3709
+ default:
3710
+ return "TEXT";
3711
+ }
3712
+ }
3713
+ renderAutoIncrement(column, table) {
3714
+ const pk = resolvePrimaryKey(table);
3715
+ if (column.autoIncrement && pk.length === 1 && pk[0] === column.name) {
3716
+ return "PRIMARY KEY AUTOINCREMENT";
3717
+ }
3718
+ return void 0;
3719
+ }
3720
+ preferInlinePkAutoincrement(column, table, pk) {
3721
+ return !!(column.autoIncrement && pk.length === 1 && pk[0] === column.name);
3722
+ }
3723
+ renderDefault(value) {
3724
+ return formatLiteral(value, this.name);
3725
+ }
3726
+ renderIndex(table, index) {
3727
+ if (index.where) {
3728
+ throw new Error("SQLite does not support partial/filtered indexes");
3729
+ }
3730
+ const name = index.name || deriveIndexName(table, index);
3731
+ const cols = renderIndexColumns(this, index.columns);
3732
+ const unique = index.unique ? "UNIQUE " : "";
3733
+ return `CREATE ${unique}INDEX IF NOT EXISTS ${this.quoteIdentifier(name)} ON ${this.formatTableName(table)} (${cols});`;
3734
+ }
3735
+ dropColumnSql(_table, _column) {
3736
+ return [];
3737
+ }
3738
+ dropIndexSql(_table, index) {
3739
+ return [`DROP INDEX IF EXISTS ${this.quoteIdentifier(index)};`];
3740
+ }
3741
+ warnDropColumn(table, column) {
3742
+ const key = table.schema ? `${table.schema}.${table.name}` : table.name;
3743
+ return `Dropping columns on SQLite requires table rebuild (column ${column} on ${key}).`;
3744
+ }
3745
+ };
3746
+
3747
+ // src/core/ddl/dialects/mssql-schema-dialect.ts
3748
+ var MSSqlSchemaDialect = class extends BaseSchemaDialect {
3749
+ constructor() {
3750
+ super(...arguments);
3751
+ this.name = "mssql";
3752
+ }
3753
+ quoteIdentifier(id) {
3754
+ return `[${id.replace(/]/g, "]]")}]`;
3755
+ }
3756
+ renderColumnType(column) {
3757
+ switch (column.type) {
3758
+ case "INT":
3759
+ case "INTEGER":
3760
+ case "int":
3761
+ case "integer":
3762
+ return "INT";
3763
+ case "BIGINT":
3764
+ case "bigint":
3765
+ return "BIGINT";
3766
+ case "UUID":
3767
+ case "uuid":
3768
+ return "UNIQUEIDENTIFIER";
3769
+ case "BOOLEAN":
3770
+ case "boolean":
3771
+ return "BIT";
3772
+ case "JSON":
3773
+ case "json":
3774
+ return "NVARCHAR(MAX)";
3775
+ case "DECIMAL":
3776
+ case "decimal":
3777
+ return column.args?.length ? `DECIMAL(${column.args[0]},${column.args[1] ?? 0})` : "DECIMAL(18,0)";
3778
+ case "FLOAT":
3779
+ case "float":
3780
+ case "DOUBLE":
3781
+ case "double":
3782
+ return "FLOAT";
3783
+ case "TIMESTAMPTZ":
3784
+ case "timestamptz":
3785
+ case "TIMESTAMP":
3786
+ case "timestamp":
3787
+ case "DATETIME":
3788
+ case "datetime":
3789
+ return "DATETIME2";
3790
+ case "DATE":
3791
+ case "date":
3792
+ return "DATE";
3793
+ case "VARCHAR":
3794
+ case "varchar":
3795
+ return column.args?.length ? `NVARCHAR(${column.args[0]})` : "NVARCHAR(255)";
3796
+ case "TEXT":
3797
+ case "text":
3798
+ return "NVARCHAR(MAX)";
3799
+ case "ENUM":
3800
+ case "enum":
3801
+ return "NVARCHAR(255)";
3802
+ default:
3803
+ return String(column.type).toUpperCase();
3804
+ }
3805
+ }
3806
+ renderDefault(value) {
3807
+ return formatLiteral(value, this.name);
3808
+ }
3809
+ renderAutoIncrement(column) {
3810
+ return column.autoIncrement ? "IDENTITY(1,1)" : void 0;
3811
+ }
3812
+ renderIndex(table, index) {
3813
+ const name = index.name || deriveIndexName(table, index);
3814
+ const cols = renderIndexColumns(this, index.columns);
3815
+ const unique = index.unique ? "UNIQUE " : "";
3816
+ const where = index.where ? ` WHERE ${index.where}` : "";
3817
+ return `CREATE ${unique}INDEX ${this.quoteIdentifier(name)} ON ${this.formatTableName(table)} (${cols})${where};`;
3818
+ }
3819
+ supportsPartialIndexes() {
3820
+ return true;
3821
+ }
3822
+ dropColumnSql(table, column) {
3823
+ return [`ALTER TABLE ${this.formatTableName(table)} DROP COLUMN ${this.quoteIdentifier(column)};`];
3824
+ }
3825
+ dropIndexSql(table, index) {
3826
+ return [`DROP INDEX ${this.quoteIdentifier(index)} ON ${this.formatTableName(table)};`];
3827
+ }
3828
+ };
3829
+
3830
+ // src/core/ddl/schema-generator.ts
3831
+ var escapeLiteral = (value) => value.replace(/'/g, "''");
3832
+ var isRawDefault = (value) => {
3833
+ return !!value && typeof value === "object" && "raw" in value && typeof value.raw === "string";
3834
+ };
3835
+ var formatLiteral = (value, dialect) => {
3836
+ if (isRawDefault(value)) return value.raw;
3837
+ if (value === null) return "NULL";
3838
+ if (typeof value === "number") return Number.isFinite(value) ? String(value) : "NULL";
3839
+ if (typeof value === "boolean") {
3840
+ if (dialect === "mysql" || dialect === "sqlite" || dialect === "mssql") {
3841
+ return value ? "1" : "0";
3842
+ }
3843
+ return value ? "TRUE" : "FALSE";
3844
+ }
3845
+ if (value instanceof Date) return `'${escapeLiteral(value.toISOString())}'`;
3846
+ if (typeof value === "string") return `'${escapeLiteral(value)}'`;
3847
+ return `'${escapeLiteral(JSON.stringify(value))}'`;
3848
+ };
3849
+ var resolvePrimaryKey = (table) => {
3850
+ if (table.primaryKey && table.primaryKey.length > 0) {
3851
+ return table.primaryKey;
3852
+ }
3853
+ const cols = Object.values(table.columns);
3854
+ return cols.filter((c) => c.primary).map((c) => c.name);
3855
+ };
3856
+ var quoteQualified = (dialect, identifier) => {
3857
+ if (identifier.includes(".")) {
3858
+ return identifier.split(".").map((part) => dialect.quoteIdentifier(part)).join(".");
3859
+ }
3860
+ return dialect.quoteIdentifier(identifier);
3861
+ };
3862
+ var renderIndexColumns = (dialect, columns) => {
3863
+ return columns.map((col2) => {
3864
+ if (typeof col2 === "string") return dialect.quoteIdentifier(col2);
3865
+ const parts = [dialect.quoteIdentifier(col2.column)];
3866
+ if (col2.order) parts.push(col2.order);
3867
+ if (col2.nulls) parts.push(`NULLS ${col2.nulls}`);
3868
+ return parts.join(" ");
3869
+ }).join(", ");
3870
+ };
3871
+ var deriveIndexName = (table, index) => {
3872
+ const base = (index.columns || []).map((col2) => typeof col2 === "string" ? col2 : col2.column).join("_");
3873
+ const suffix = index.unique ? "uniq" : "idx";
3874
+ return `${table.name}_${base}_${suffix}`;
3875
+ };
3876
+ var renderColumnDefinition = (table, col2, dialect, options = {}) => {
3877
+ const parts = [];
3878
+ parts.push(dialect.quoteIdentifier(col2.name));
3879
+ parts.push(dialect.renderColumnType(col2));
3880
+ const autoInc = dialect.renderAutoIncrement(col2, table);
3881
+ if (autoInc) parts.push(autoInc);
3882
+ if (col2.notNull) parts.push("NOT NULL");
3883
+ if (col2.unique) parts.push("UNIQUE");
3884
+ if (col2.default !== void 0) {
3885
+ parts.push(`DEFAULT ${dialect.renderDefault(col2.default, col2)}`);
3886
+ }
3887
+ if (options.includePrimary && col2.primary) {
3888
+ parts.push("PRIMARY KEY");
3889
+ }
3890
+ if (col2.check) {
3891
+ parts.push(`CHECK (${col2.check})`);
3892
+ }
3893
+ if (col2.references) {
3894
+ parts.push(dialect.renderReference(col2.references, table));
3895
+ }
3896
+ return { sql: parts.join(" "), inlinePrimary: !!(options.includePrimary && col2.primary) };
3897
+ };
3898
+ var generateCreateTableSql = (table, dialect) => {
3899
+ const pk = resolvePrimaryKey(table);
3900
+ const inlinePkColumns = /* @__PURE__ */ new Set();
3901
+ const columnLines = Object.values(table.columns).map((col2) => {
3902
+ const includePk = dialect.preferInlinePkAutoincrement?.(col2, table, pk) && pk.includes(col2.name);
3903
+ if (includePk) {
3904
+ inlinePkColumns.add(col2.name);
3905
+ }
3906
+ return renderColumnDefinition(table, col2, dialect, { includePrimary: includePk }).sql;
3907
+ });
3908
+ const constraintLines = [];
3909
+ if (pk.length > 0 && !(pk.length === 1 && inlinePkColumns.has(pk[0]))) {
3910
+ const cols = pk.map((c) => dialect.quoteIdentifier(c)).join(", ");
3911
+ constraintLines.push(`PRIMARY KEY (${cols})`);
3912
+ }
3913
+ if (table.checks) {
3914
+ table.checks.forEach((check) => {
3915
+ const name = check.name ? `${dialect.quoteIdentifier(check.name)} ` : "";
3916
+ constraintLines.push(`CONSTRAINT ${name}CHECK (${check.expression})`);
3917
+ });
3918
+ }
3919
+ const allLines = [...columnLines, ...constraintLines];
3920
+ const body = allLines.map((line) => ` ${line}`).join(",\n");
3921
+ const tableOptions = dialect.renderTableOptions(table);
3922
+ const tableSql = `CREATE TABLE ${dialect.formatTableName(table)} (
3923
+ ${body}
3924
+ )${tableOptions ? " " + tableOptions : ""};`;
3925
+ const indexSql = [];
3926
+ if (table.indexes && table.indexes.length > 0) {
3927
+ for (const idx of table.indexes) {
3928
+ if (idx.where && !dialect.supportsPartialIndexes()) {
3929
+ throw new Error(`Dialect ${dialect.name} does not support partial/filtered indexes (${idx.name || idx.columns.join("_")}).`);
3930
+ }
3931
+ indexSql.push(dialect.renderIndex(table, idx));
3932
+ }
3933
+ }
3934
+ return { tableSql, indexSql };
3935
+ };
3936
+ var generateSchemaSql = (tables, dialect) => {
3937
+ const ordered = orderTablesByDependencies(tables);
3938
+ const statements = [];
3939
+ ordered.forEach((table) => {
3940
+ const { tableSql, indexSql } = generateCreateTableSql(table, dialect);
3941
+ statements.push(tableSql, ...indexSql);
3942
+ });
3943
+ return statements;
3944
+ };
3945
+ var orderTablesByDependencies = (tables) => {
3946
+ const map = /* @__PURE__ */ new Map();
3947
+ tables.forEach((t) => map.set(t.name, t));
3948
+ const deps = /* @__PURE__ */ new Map();
3949
+ for (const table of tables) {
3950
+ const refTables = /* @__PURE__ */ new Set();
3951
+ Object.values(table.columns).forEach((col2) => {
3952
+ if (col2.references?.table) {
3953
+ refTables.add(col2.references.table);
3954
+ }
3955
+ });
3956
+ deps.set(table.name, refTables);
3957
+ }
3958
+ const visited = /* @__PURE__ */ new Set();
3959
+ const ordered = [];
3960
+ const visit = (name, stack) => {
3961
+ if (visited.has(name)) return;
3962
+ const table = map.get(name);
3963
+ if (!table) return;
3964
+ if (stack.has(name)) {
3965
+ ordered.push(table);
3966
+ visited.add(name);
3967
+ return;
3968
+ }
3969
+ stack.add(name);
3970
+ for (const dep of deps.get(name) || []) {
3971
+ visit(dep, stack);
3972
+ }
3973
+ stack.delete(name);
3974
+ visited.add(name);
3975
+ ordered.push(table);
3976
+ };
3977
+ tables.forEach((t) => visit(t.name, /* @__PURE__ */ new Set()));
3978
+ return ordered;
3979
+ };
3980
+
3981
+ // src/core/ddl/schema-diff.ts
3982
+ var tableKey = (name, schema) => schema ? `${schema}.${name}` : name;
3983
+ var mapTables = (schema) => {
3984
+ const map = /* @__PURE__ */ new Map();
3985
+ for (const table of schema.tables) {
3986
+ map.set(tableKey(table.name, table.schema), table);
3987
+ }
3988
+ return map;
3989
+ };
3990
+ var buildAddColumnSql = (table, colName, dialect) => {
3991
+ const column = table.columns[colName];
3992
+ const rendered = renderColumnDefinition(table, column, dialect);
3993
+ return `ALTER TABLE ${dialect.formatTableName(table)} ADD ${rendered.sql};`;
3994
+ };
3995
+ var diffSchema = (expectedTables, actualSchema, dialect, options = {}) => {
3996
+ const allowDestructive = options.allowDestructive ?? false;
3997
+ const plan = { changes: [], warnings: [] };
3998
+ const actualMap = mapTables(actualSchema);
3999
+ for (const table of expectedTables) {
4000
+ const key = tableKey(table.name, table.schema);
4001
+ const actual = actualMap.get(key);
4002
+ if (!actual) {
4003
+ const { tableSql, indexSql } = generateCreateTableSql(table, dialect);
4004
+ plan.changes.push({
4005
+ kind: "createTable",
4006
+ table: key,
4007
+ description: `Create table ${key}`,
4008
+ statements: [tableSql, ...indexSql],
4009
+ safe: true
4010
+ });
4011
+ continue;
4012
+ }
4013
+ const actualCols = new Map(actual.columns.map((c) => [c.name, c]));
4014
+ for (const colName of Object.keys(table.columns)) {
4015
+ if (!actualCols.has(colName)) {
4016
+ plan.changes.push({
4017
+ kind: "addColumn",
4018
+ table: key,
4019
+ description: `Add column ${colName} to ${key}`,
4020
+ statements: [buildAddColumnSql(table, colName, dialect)],
4021
+ safe: true
4022
+ });
4023
+ }
4024
+ }
4025
+ for (const colName of actualCols.keys()) {
4026
+ if (!table.columns[colName]) {
4027
+ plan.changes.push({
4028
+ kind: "dropColumn",
4029
+ table: key,
4030
+ description: `Drop column ${colName} from ${key}`,
4031
+ statements: allowDestructive ? dialect.dropColumnSql(actual, colName) : [],
4032
+ safe: false
4033
+ });
4034
+ const warning = dialect.warnDropColumn?.(actual, colName);
4035
+ if (warning) plan.warnings.push(warning);
4036
+ }
4037
+ }
4038
+ const expectedIndexes = table.indexes ?? [];
4039
+ const actualIndexes = actual.indexes ?? [];
4040
+ const actualIndexMap = new Map(actualIndexes.map((idx) => [idx.name, idx]));
4041
+ for (const idx of expectedIndexes) {
4042
+ const name = idx.name || deriveIndexName(table, idx);
4043
+ if (!actualIndexMap.has(name)) {
4044
+ plan.changes.push({
4045
+ kind: "addIndex",
4046
+ table: key,
4047
+ description: `Create index ${name} on ${key}`,
4048
+ statements: [dialect.renderIndex(table, { ...idx, name })],
4049
+ safe: true
4050
+ });
4051
+ }
4052
+ }
4053
+ for (const idx of actualIndexes) {
4054
+ if (idx.name && !expectedIndexes.find((expected) => (expected.name || deriveIndexName(table, expected)) === idx.name)) {
4055
+ plan.changes.push({
4056
+ kind: "dropIndex",
4057
+ table: key,
4058
+ description: `Drop index ${idx.name} on ${key}`,
4059
+ statements: allowDestructive ? dialect.dropIndexSql(actual, idx.name) : [],
4060
+ safe: false
4061
+ });
4062
+ }
4063
+ }
4064
+ }
4065
+ for (const actual of actualSchema.tables) {
4066
+ const key = tableKey(actual.name, actual.schema);
4067
+ if (!expectedTables.find((t) => tableKey(t.name, t.schema) === key)) {
4068
+ plan.changes.push({
4069
+ kind: "dropTable",
4070
+ table: key,
4071
+ description: `Drop table ${key}`,
4072
+ statements: allowDestructive ? dialect.dropTableSql(actual) : [],
4073
+ safe: false
4074
+ });
4075
+ }
4076
+ }
4077
+ return plan;
4078
+ };
4079
+ var synchronizeSchema = async (expectedTables, actualSchema, dialect, executor, options = {}) => {
4080
+ const plan = diffSchema(expectedTables, actualSchema, dialect, options);
4081
+ if (options.dryRun) return plan;
4082
+ for (const change of plan.changes) {
4083
+ if (!change.statements.length) continue;
4084
+ if (!change.safe && !options.allowDestructive) continue;
4085
+ for (const stmt of change.statements) {
4086
+ if (!stmt.trim()) continue;
4087
+ await executor.executeSql(stmt);
4088
+ }
4089
+ }
4090
+ return plan;
4091
+ };
4092
+
4093
+ // src/core/ddl/introspect/utils.ts
4094
+ var toRows = (result) => {
4095
+ if (!result) return [];
4096
+ return result.values.map(
4097
+ (row) => result.columns.reduce((acc, col2, idx) => {
4098
+ acc[col2] = row[idx];
4099
+ return acc;
4100
+ }, {})
4101
+ );
4102
+ };
4103
+ var queryRows = async (executor, sql, params = []) => {
4104
+ const [first] = await executor.executeSql(sql, params);
4105
+ return toRows(first);
4106
+ };
4107
+ var shouldIncludeTable = (name, options) => {
4108
+ if (options.includeTables && !options.includeTables.includes(name)) return false;
4109
+ if (options.excludeTables && options.excludeTables.includes(name)) return false;
4110
+ return true;
4111
+ };
4112
+
4113
+ // src/core/ddl/introspect/postgres.ts
4114
+ var postgresIntrospector = {
4115
+ async introspect(executor, options) {
4116
+ const schema = options.schema || "public";
4117
+ const tables = [];
4118
+ const columnRows = await queryRows(
4119
+ executor,
4120
+ `
4121
+ SELECT table_schema, table_name, column_name, data_type, is_nullable, column_default
4122
+ FROM information_schema.columns
4123
+ WHERE table_schema = $1
4124
+ ORDER BY table_name, ordinal_position
4125
+ `,
4126
+ [schema]
4127
+ );
4128
+ const pkRows = await queryRows(
4129
+ executor,
4130
+ `
4131
+ SELECT
4132
+ ns.nspname AS table_schema,
4133
+ tbl.relname AS table_name,
4134
+ array_agg(att.attname ORDER BY arr.idx) AS pk_columns
4135
+ FROM pg_index i
4136
+ JOIN pg_class tbl ON tbl.oid = i.indrelid
4137
+ JOIN pg_namespace ns ON ns.oid = tbl.relnamespace
4138
+ JOIN LATERAL unnest(i.indkey) WITH ORDINALITY AS arr(attnum, idx) ON TRUE
4139
+ LEFT JOIN pg_attribute att ON att.attrelid = tbl.oid AND att.attnum = arr.attnum
4140
+ WHERE i.indisprimary AND ns.nspname = $1
4141
+ GROUP BY ns.nspname, tbl.relname
4142
+ `,
4143
+ [schema]
4144
+ );
4145
+ const pkMap = /* @__PURE__ */ new Map();
4146
+ pkRows.forEach((r) => {
4147
+ pkMap.set(`${r.table_schema}.${r.table_name}`, r.pk_columns || []);
4148
+ });
4149
+ const fkRows = await queryRows(
4150
+ executor,
4151
+ `
4152
+ SELECT
4153
+ tc.table_schema,
4154
+ tc.table_name,
4155
+ kcu.column_name,
4156
+ ccu.table_schema AS foreign_table_schema,
4157
+ ccu.table_name AS foreign_table_name,
4158
+ ccu.column_name AS foreign_column_name,
4159
+ rc.update_rule AS on_update,
4160
+ rc.delete_rule AS on_delete
4161
+ FROM information_schema.table_constraints AS tc
4162
+ JOIN information_schema.key_column_usage AS kcu
4163
+ ON tc.constraint_name = kcu.constraint_name AND tc.table_schema = kcu.table_schema
4164
+ JOIN information_schema.constraint_column_usage AS ccu
4165
+ ON ccu.constraint_name = tc.constraint_name AND ccu.table_schema = tc.table_schema
4166
+ JOIN information_schema.referential_constraints rc
4167
+ ON rc.constraint_name = tc.constraint_name AND rc.constraint_schema = tc.table_schema
4168
+ WHERE tc.constraint_type = 'FOREIGN KEY' AND tc.table_schema = $1
4169
+ `,
4170
+ [schema]
4171
+ );
4172
+ const fkMap = /* @__PURE__ */ new Map();
4173
+ fkRows.forEach((r) => {
4174
+ const key = `${r.table_schema}.${r.table_name}.${r.column_name}`;
4175
+ fkMap.set(key, [{
4176
+ table: `${r.foreign_table_schema}.${r.foreign_table_name}`,
4177
+ column: r.foreign_column_name,
4178
+ onDelete: r.on_delete?.toUpperCase(),
4179
+ onUpdate: r.on_update?.toUpperCase()
4180
+ }]);
4181
+ });
4182
+ const indexRows = await queryRows(
4183
+ executor,
4184
+ `
4185
+ SELECT
4186
+ ns.nspname AS table_schema,
4187
+ tbl.relname AS table_name,
4188
+ idx.relname AS index_name,
4189
+ i.indisunique AS is_unique,
4190
+ pg_get_expr(i.indpred, i.indrelid) AS predicate,
4191
+ array_agg(att.attname ORDER BY arr.idx) AS column_names
4192
+ FROM pg_index i
4193
+ JOIN pg_class tbl ON tbl.oid = i.indrelid
4194
+ JOIN pg_namespace ns ON ns.oid = tbl.relnamespace
4195
+ JOIN pg_class idx ON idx.oid = i.indexrelid
4196
+ JOIN LATERAL unnest(i.indkey) WITH ORDINALITY AS arr(attnum, idx) ON TRUE
4197
+ LEFT JOIN pg_attribute att ON att.attrelid = tbl.oid AND att.attnum = arr.attnum
4198
+ WHERE ns.nspname = $1 AND NOT i.indisprimary
4199
+ GROUP BY ns.nspname, tbl.relname, idx.relname, i.indisunique, i.indpred
4200
+ `,
4201
+ [schema]
4202
+ );
4203
+ const tablesByKey = /* @__PURE__ */ new Map();
4204
+ columnRows.forEach((r) => {
4205
+ const key = `${r.table_schema}.${r.table_name}`;
4206
+ if (!shouldIncludeTable(r.table_name, options)) {
4207
+ return;
4208
+ }
4209
+ if (!tablesByKey.has(key)) {
4210
+ tablesByKey.set(key, {
4211
+ name: r.table_name,
4212
+ schema: r.table_schema,
4213
+ columns: [],
4214
+ primaryKey: pkMap.get(key) || [],
4215
+ indexes: []
4216
+ });
4217
+ }
4218
+ const cols = tablesByKey.get(key);
4219
+ const fk = fkMap.get(`${r.table_schema}.${r.table_name}.${r.column_name}`)?.[0];
4220
+ const column = {
4221
+ name: r.column_name,
4222
+ type: r.data_type,
4223
+ notNull: r.is_nullable === "NO",
4224
+ default: r.column_default ?? void 0,
4225
+ references: fk ? {
4226
+ table: fk.table,
4227
+ column: fk.column,
4228
+ onDelete: fk.onDelete,
4229
+ onUpdate: fk.onUpdate
4230
+ } : void 0
4231
+ };
4232
+ cols.columns.push(column);
4233
+ });
4234
+ indexRows.forEach((r) => {
4235
+ const key = `${r.table_schema}.${r.table_name}`;
4236
+ const table = tablesByKey.get(key);
4237
+ if (!table) return;
4238
+ const idx = {
4239
+ name: r.index_name,
4240
+ columns: (r.column_names || []).map((c) => ({ column: c })),
4241
+ unique: !!r.is_unique,
4242
+ where: r.predicate || void 0
4243
+ };
4244
+ table.indexes = table.indexes || [];
4245
+ table.indexes.push(idx);
4246
+ });
4247
+ tables.push(...tablesByKey.values());
4248
+ return { tables };
4249
+ }
4250
+ };
4251
+
4252
+ // src/core/ddl/introspect/mysql.ts
4253
+ var mysqlIntrospector = {
4254
+ async introspect(executor, options) {
4255
+ const schema = options.schema;
4256
+ const filterClause = schema ? "table_schema = ?" : "table_schema = database()";
4257
+ const params = schema ? [schema] : [];
4258
+ const columnRows = await queryRows(
4259
+ executor,
4260
+ `
4261
+ SELECT table_schema, table_name, column_name, data_type, is_nullable, column_default, extra
4262
+ FROM information_schema.columns
4263
+ WHERE ${filterClause}
4264
+ ORDER BY table_name, ordinal_position
4265
+ `,
4266
+ params
4267
+ );
4268
+ const pkRows = await queryRows(
4269
+ executor,
4270
+ `
4271
+ SELECT table_schema, table_name, column_name
4272
+ FROM information_schema.key_column_usage
4273
+ WHERE constraint_name = 'PRIMARY' AND ${filterClause}
4274
+ ORDER BY ordinal_position
4275
+ `,
4276
+ params
4277
+ );
4278
+ const pkMap = /* @__PURE__ */ new Map();
4279
+ pkRows.forEach((r) => {
4280
+ const key = `${r.table_schema}.${r.table_name}`;
4281
+ const list = pkMap.get(key) || [];
4282
+ list.push(r.column_name);
4283
+ pkMap.set(key, list);
4284
+ });
4285
+ const indexRows = await queryRows(
4286
+ executor,
4287
+ `
4288
+ SELECT
4289
+ table_schema,
4290
+ table_name,
4291
+ index_name,
4292
+ non_unique,
4293
+ GROUP_CONCAT(column_name ORDER BY seq_in_index) AS cols
4294
+ FROM information_schema.statistics
4295
+ WHERE ${filterClause} AND index_name <> 'PRIMARY'
4296
+ GROUP BY table_schema, table_name, index_name, non_unique
4297
+ `,
4298
+ params
4299
+ );
4300
+ const tablesByKey = /* @__PURE__ */ new Map();
4301
+ columnRows.forEach((r) => {
4302
+ const key = `${r.table_schema}.${r.table_name}`;
4303
+ if (!shouldIncludeTable(r.table_name, options)) return;
4304
+ if (!tablesByKey.has(key)) {
4305
+ tablesByKey.set(key, {
4306
+ name: r.table_name,
4307
+ schema: r.table_schema,
4308
+ columns: [],
4309
+ primaryKey: pkMap.get(key) || [],
4310
+ indexes: []
4311
+ });
4312
+ }
4313
+ const cols = tablesByKey.get(key);
4314
+ const column = {
4315
+ name: r.column_name,
4316
+ type: r.data_type,
4317
+ notNull: r.is_nullable === "NO",
4318
+ default: r.column_default ?? void 0,
4319
+ autoIncrement: typeof r.extra === "string" && r.extra.includes("auto_increment")
4320
+ };
4321
+ cols.columns.push(column);
4322
+ });
4323
+ indexRows.forEach((r) => {
4324
+ const key = `${r.table_schema}.${r.table_name}`;
4325
+ const table = tablesByKey.get(key);
4326
+ if (!table) return;
4327
+ const cols = (typeof r.cols === "string" ? r.cols.split(",") : []).map((c) => ({ column: c.trim() }));
4328
+ const idx = {
4329
+ name: r.index_name,
4330
+ columns: cols,
4331
+ unique: r.non_unique === 0
4332
+ };
4333
+ table.indexes = table.indexes || [];
4334
+ table.indexes.push(idx);
4335
+ });
4336
+ return { tables: Array.from(tablesByKey.values()) };
4337
+ }
4338
+ };
4339
+
4340
+ // src/core/ddl/introspect/sqlite.ts
4341
+ var escapeSingleQuotes = (name) => name.replace(/'/g, "''");
4342
+ var sqliteIntrospector = {
4343
+ async introspect(executor, options) {
4344
+ const tables = [];
4345
+ const tableRows = await queryRows(
4346
+ executor,
4347
+ `SELECT name FROM sqlite_master WHERE type = 'table' AND name NOT LIKE 'sqlite_%';`
4348
+ );
4349
+ for (const row of tableRows) {
4350
+ const name = row.name;
4351
+ if (!shouldIncludeTable(name, options)) continue;
4352
+ const table = { name, columns: [], primaryKey: [], indexes: [] };
4353
+ const cols = await queryRows(executor, `PRAGMA table_info('${escapeSingleQuotes(name)}');`);
4354
+ cols.forEach((c) => {
4355
+ table.columns.push({
4356
+ name: c.name,
4357
+ type: c.type,
4358
+ notNull: c.notnull === 1,
4359
+ default: c.dflt_value ?? void 0,
4360
+ autoIncrement: false
4361
+ });
4362
+ if (c.pk && c.pk > 0) {
4363
+ table.primaryKey = table.primaryKey || [];
4364
+ table.primaryKey.push(c.name);
4365
+ }
4366
+ });
4367
+ const fkRows = await queryRows(executor, `PRAGMA foreign_key_list('${escapeSingleQuotes(name)}');`);
4368
+ fkRows.forEach((fk) => {
4369
+ const col2 = table.columns.find((c) => c.name === fk.from);
4370
+ if (col2) {
4371
+ col2.references = {
4372
+ table: fk.table,
4373
+ column: fk.to,
4374
+ onDelete: fk.on_delete?.toUpperCase(),
4375
+ onUpdate: fk.on_update?.toUpperCase()
4376
+ };
4377
+ }
4378
+ });
4379
+ const idxList = await queryRows(executor, `PRAGMA index_list('${escapeSingleQuotes(name)}');`);
4380
+ for (const idx of idxList) {
4381
+ const idxName = idx.name;
4382
+ const columnsInfo = await queryRows(executor, `PRAGMA index_info('${escapeSingleQuotes(idxName)}');`);
4383
+ const idxEntry = {
4384
+ name: idxName,
4385
+ columns: columnsInfo.map((ci) => ({ column: ci.name })),
4386
+ unique: idx.unique === 1
4387
+ };
4388
+ table.indexes.push(idxEntry);
4389
+ }
4390
+ tables.push(table);
4391
+ }
4392
+ return { tables };
4393
+ }
4394
+ };
4395
+
4396
+ // src/core/ddl/introspect/mssql.ts
4397
+ var mssqlIntrospector = {
4398
+ async introspect(executor, options) {
4399
+ const schema = options.schema;
4400
+ const filterSchema = schema ? "sch.name = @p1" : "1=1";
4401
+ const params = schema ? [schema] : [];
4402
+ const columnRows = await queryRows(
4403
+ executor,
4404
+ `
4405
+ SELECT
4406
+ sch.name AS table_schema,
4407
+ t.name AS table_name,
4408
+ c.name AS column_name,
4409
+ ty.name AS data_type,
4410
+ c.is_nullable,
4411
+ c.is_identity,
4412
+ object_definition(c.default_object_id) AS column_default
4413
+ FROM sys.columns c
4414
+ JOIN sys.tables t ON t.object_id = c.object_id
4415
+ JOIN sys.schemas sch ON sch.schema_id = t.schema_id
4416
+ JOIN sys.types ty ON ty.user_type_id = c.user_type_id
4417
+ WHERE t.is_ms_shipped = 0 AND ${filterSchema}
4418
+ `,
4419
+ params
4420
+ );
4421
+ const pkRows = await queryRows(
4422
+ executor,
4423
+ `
4424
+ SELECT
4425
+ sch.name AS table_schema,
4426
+ t.name AS table_name,
4427
+ c.name AS column_name,
4428
+ ic.key_ordinal
4429
+ FROM sys.indexes i
4430
+ JOIN sys.index_columns ic ON ic.object_id = i.object_id AND ic.index_id = i.index_id
4431
+ JOIN sys.columns c ON c.object_id = ic.object_id AND c.column_id = ic.column_id
4432
+ JOIN sys.tables t ON t.object_id = i.object_id
4433
+ JOIN sys.schemas sch ON sch.schema_id = t.schema_id
4434
+ WHERE i.is_primary_key = 1 AND ${filterSchema}
4435
+ ORDER BY ic.key_ordinal
4436
+ `,
4437
+ params
4438
+ );
4439
+ const pkMap = /* @__PURE__ */ new Map();
4440
+ pkRows.forEach((r) => {
4441
+ const key = `${r.table_schema}.${r.table_name}`;
4442
+ const list = pkMap.get(key) || [];
4443
+ list.push(r.column_name);
4444
+ pkMap.set(key, list);
4445
+ });
4446
+ const indexRows = await queryRows(
4447
+ executor,
4448
+ `
4449
+ SELECT
4450
+ sch.name AS table_schema,
4451
+ t.name AS table_name,
4452
+ i.name AS index_name,
4453
+ i.is_unique,
4454
+ i.has_filter,
4455
+ i.filter_definition
4456
+ FROM sys.indexes i
4457
+ JOIN sys.tables t ON t.object_id = i.object_id
4458
+ JOIN sys.schemas sch ON sch.schema_id = t.schema_id
4459
+ WHERE i.is_primary_key = 0 AND i.is_hypothetical = 0 AND ${filterSchema}
4460
+ `,
4461
+ params
4462
+ );
4463
+ const indexColsRows = await queryRows(
4464
+ executor,
4465
+ `
4466
+ SELECT
4467
+ sch.name AS table_schema,
4468
+ t.name AS table_name,
4469
+ i.name AS index_name,
4470
+ c.name AS column_name,
4471
+ ic.key_ordinal
4472
+ FROM sys.index_columns ic
4473
+ JOIN sys.indexes i ON i.object_id = ic.object_id AND i.index_id = ic.index_id
4474
+ JOIN sys.columns c ON c.object_id = ic.object_id AND c.column_id = ic.column_id
4475
+ JOIN sys.tables t ON t.object_id = i.object_id
4476
+ JOIN sys.schemas sch ON sch.schema_id = t.schema_id
4477
+ WHERE i.is_primary_key = 0 AND ${filterSchema}
4478
+ ORDER BY ic.key_ordinal
4479
+ `,
4480
+ params
4481
+ );
4482
+ const indexColumnsMap = /* @__PURE__ */ new Map();
4483
+ indexColsRows.forEach((r) => {
4484
+ const key = `${r.table_schema}.${r.table_name}.${r.index_name}`;
4485
+ const list = indexColumnsMap.get(key) || [];
4486
+ list.push({ column: r.column_name, order: r.key_ordinal });
4487
+ indexColumnsMap.set(key, list);
4488
+ });
4489
+ const tablesByKey = /* @__PURE__ */ new Map();
4490
+ columnRows.forEach((r) => {
4491
+ if (!shouldIncludeTable(r.table_name, options)) return;
4492
+ const key = `${r.table_schema}.${r.table_name}`;
4493
+ if (!tablesByKey.has(key)) {
4494
+ tablesByKey.set(key, {
4495
+ name: r.table_name,
4496
+ schema: r.table_schema,
4497
+ columns: [],
4498
+ primaryKey: pkMap.get(key) || [],
4499
+ indexes: []
4500
+ });
4501
+ }
4502
+ const t = tablesByKey.get(key);
4503
+ const column = {
4504
+ name: r.column_name,
4505
+ type: r.data_type,
4506
+ notNull: r.is_nullable === false || r.is_nullable === 0,
4507
+ default: r.column_default ?? void 0,
4508
+ autoIncrement: !!r.is_identity
4509
+ };
4510
+ t.columns.push(column);
4511
+ });
4512
+ indexRows.forEach((r) => {
4513
+ const key = `${r.table_schema}.${r.table_name}`;
4514
+ const table = tablesByKey.get(key);
4515
+ if (!table) return;
4516
+ const cols = (indexColumnsMap.get(`${r.table_schema}.${r.table_name}.${r.index_name}`) || []).sort((a, b) => a.order - b.order).map((c) => ({ column: c.column }));
4517
+ const idx = {
4518
+ name: r.index_name,
4519
+ columns: cols,
4520
+ unique: !!r.is_unique,
4521
+ where: r.has_filter ? r.filter_definition : void 0
4522
+ };
4523
+ table.indexes = table.indexes || [];
4524
+ table.indexes.push(idx);
4525
+ });
4526
+ return { tables: Array.from(tablesByKey.values()) };
4527
+ }
4528
+ };
4529
+
4530
+ // src/core/ddl/schema-introspect.ts
4531
+ var INTROSPECTORS = {
4532
+ postgres: postgresIntrospector,
4533
+ mysql: mysqlIntrospector,
4534
+ sqlite: sqliteIntrospector,
4535
+ mssql: mssqlIntrospector
4536
+ };
4537
+ var introspectSchema = async (executor, dialect, options = {}) => {
4538
+ const handler = INTROSPECTORS[dialect];
4539
+ if (!handler) {
4540
+ throw new Error(`Unsupported dialect for introspection: ${dialect}`);
4541
+ }
4542
+ return handler.introspect(executor, options);
4543
+ };
4544
+
3318
4545
  // src/orm/als.ts
3319
4546
  var AsyncLocalStorage = class {
3320
4547
  /**
@@ -4153,15 +5380,21 @@ var OrmContext = class {
4153
5380
  // Annotate the CommonJS export names for ESM import in node:
4154
5381
  0 && (module.exports = {
4155
5382
  AsyncLocalStorage,
5383
+ BaseSchemaDialect,
4156
5384
  DefaultBelongsToReference,
4157
5385
  DefaultHasManyCollection,
4158
5386
  DefaultManyToManyCollection,
4159
5387
  DeleteQueryBuilder,
4160
5388
  EntityStatus,
4161
5389
  InsertQueryBuilder,
5390
+ MSSqlSchemaDialect,
4162
5391
  MySqlDialect,
5392
+ MySqlSchemaDialect,
4163
5393
  OrmContext,
5394
+ PostgresDialect,
5395
+ PostgresSchemaDialect,
4164
5396
  RelationKinds,
5397
+ SQLiteSchemaDialect,
4165
5398
  SelectQueryBuilder,
4166
5399
  SqlServerDialect,
4167
5400
  SqliteDialect,
@@ -4183,15 +5416,22 @@ var OrmContext = class {
4183
5416
  createLiteral,
4184
5417
  defineTable,
4185
5418
  denseRank,
5419
+ deriveIndexName,
5420
+ diffSchema,
4186
5421
  eq,
5422
+ escapeLiteral,
4187
5423
  executeHydrated,
4188
5424
  exists,
4189
5425
  firstValue,
5426
+ formatLiteral,
5427
+ generateCreateTableSql,
5428
+ generateSchemaSql,
4190
5429
  gt,
4191
5430
  gte,
4192
5431
  hasMany,
4193
5432
  hydrateRows,
4194
5433
  inList,
5434
+ introspectSchema,
4195
5435
  isCaseExpressionNode,
4196
5436
  isExpressionSelectionNode,
4197
5437
  isFunctionNode,
@@ -4216,9 +5456,14 @@ var OrmContext = class {
4216
5456
  notLike,
4217
5457
  ntile,
4218
5458
  or,
5459
+ quoteQualified,
4219
5460
  rank,
5461
+ renderColumnDefinition,
5462
+ renderIndexColumns,
5463
+ resolvePrimaryKey,
4220
5464
  rowNumber,
4221
5465
  sum,
5466
+ synchronizeSchema,
4222
5467
  valueToOperand,
4223
5468
  visitExpression,
4224
5469
  visitOperand,