bun-query-builder 0.2.17 → 0.2.19

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.
@@ -18,6 +18,8 @@ export declare function sqlTypeToNormalized(rawType: string, dialect: SupportedD
18
18
  * details carried only by COLUMN_TYPE (for example TINYINT(1) and VARCHAR(n)).
19
19
  */
20
20
  export declare function mysqlColumnType(dataType: unknown, columnType: unknown, enumValues?: string[]): NormalizedColumnType;
21
+ /** Preserve the physical bound of a MySQL VARCHAR column for round-trip diffs. */
22
+ export declare function mysqlColumnMaxLength(columnType: unknown): number | undefined;
21
23
  /**
22
24
  * The plan type for one Postgres column, given what the catalogue knows.
23
25
  *
package/dist/bin/cli.js CHANGED
@@ -17740,6 +17740,8 @@ function sqlTypeToNormalized(rawType, dialect, ctx) {
17740
17740
  if (/^(?:varchar|character varying|nvarchar|nchar|char|character|bpchar)/.test(base)) {
17741
17741
  const m = t.match(/\((\d+)\)/);
17742
17742
  const len = m ? Number(m[1]) : undefined;
17743
+ if (isMysqlLike(dialect))
17744
+ return "string";
17743
17745
  return len !== undefined && len > 255 ? "text" : "string";
17744
17746
  }
17745
17747
  if (/text|clob/.test(base))
@@ -17767,6 +17769,13 @@ function sqlTypeToNormalized(rawType, dialect, ctx) {
17767
17769
  function mysqlColumnType(dataType, columnType, enumValues) {
17768
17770
  return sqlTypeToNormalized(String(columnType || dataType || ""), "mysql", { enumValues });
17769
17771
  }
17772
+ function mysqlColumnMaxLength(columnType) {
17773
+ const match = String(columnType || "").trim().match(/^varchar\((\d+)\)/i);
17774
+ if (!match)
17775
+ return;
17776
+ const length = Number(match[1]);
17777
+ return Number.isSafeInteger(length) && length > 0 ? length : undefined;
17778
+ }
17770
17779
  function asAction(raw2) {
17771
17780
  const v = String(raw2 ?? "").toLowerCase().trim();
17772
17781
  if (v === "cascade" || v === "restrict" || v === "set null")
@@ -17969,6 +17978,7 @@ async function buildMysqlTable(qb, table) {
17969
17978
  hasDefault,
17970
17979
  defaultValue: hasDefault ? normalizeRawDefault(rawDefault) : undefined,
17971
17980
  enumValues,
17981
+ maxLength: mysqlColumnMaxLength(columnType),
17972
17982
  references: fkByColumn.get(name)
17973
17983
  };
17974
17984
  });
@@ -18210,7 +18220,42 @@ class MySQLDriver {
18210
18220
  sql += ` ON DELETE ${onDelete.toUpperCase()}`;
18211
18221
  if (onUpdate)
18212
18222
  sql += ` ON UPDATE ${onUpdate.toUpperCase()}`;
18213
- return `${sql};`;
18223
+ return `${this.dropForeignKeysOn(tableName, columnName)}
18224
+ ${sql};`;
18225
+ }
18226
+ dropForeignKeysOn(tableName, columnName) {
18227
+ const table = this.quoteLiteral(tableName);
18228
+ const column = this.quoteLiteral(columnName);
18229
+ return `SET @drop_fks := (
18230
+ SELECT CONCAT(
18231
+ 'ALTER TABLE \`', ${table}, '\` DROP FOREIGN KEY \`',
18232
+ GROUP_CONCAT(kcu.CONSTRAINT_NAME SEPARATOR '\`, DROP FOREIGN KEY \`'),
18233
+ '\`'
18234
+ )
18235
+ FROM information_schema.KEY_COLUMN_USAGE kcu
18236
+ WHERE kcu.TABLE_SCHEMA = DATABASE()
18237
+ AND kcu.TABLE_NAME = ${table}
18238
+ AND kcu.COLUMN_NAME = ${column}
18239
+ AND kcu.REFERENCED_TABLE_NAME IS NOT NULL
18240
+ AND kcu.CONSTRAINT_NAME IN (
18241
+ SELECT single.CONSTRAINT_NAME FROM (
18242
+ SELECT inner_kcu.CONSTRAINT_NAME
18243
+ FROM information_schema.KEY_COLUMN_USAGE inner_kcu
18244
+ WHERE inner_kcu.TABLE_SCHEMA = DATABASE()
18245
+ AND inner_kcu.TABLE_NAME = ${table}
18246
+ AND inner_kcu.REFERENCED_TABLE_NAME IS NOT NULL
18247
+ GROUP BY inner_kcu.CONSTRAINT_NAME
18248
+ HAVING COUNT(*) = 1
18249
+ ) AS single
18250
+ )
18251
+ );
18252
+ SET @drop_fks := IFNULL(@drop_fks, 'SELECT 1');
18253
+ PREPARE drop_fks_stmt FROM @drop_fks;
18254
+ EXECUTE drop_fks_stmt;
18255
+ DEALLOCATE PREPARE drop_fks_stmt;`;
18256
+ }
18257
+ quoteLiteral(value) {
18258
+ return `'${value.replace(/'/g, "''")}'`;
18214
18259
  }
18215
18260
  addColumn(tableName, column) {
18216
18261
  const typeSql = this.getColumnType(column);
@@ -18400,7 +18445,34 @@ class PostgresDriver {
18400
18445
  sql += ` ON DELETE ${onDelete.toUpperCase()}`;
18401
18446
  if (onUpdate)
18402
18447
  sql += ` ON UPDATE ${onUpdate.toUpperCase()}`;
18403
- return `${sql};`;
18448
+ return `${this.dropForeignKeysOn(tableName, columnName)}
18449
+ ${sql};`;
18450
+ }
18451
+ dropForeignKeysOn(tableName, columnName) {
18452
+ const table = this.quoteLiteral(tableName);
18453
+ const column = this.quoteLiteral(columnName);
18454
+ return `DO $$
18455
+ DECLARE existing_name text;
18456
+ BEGIN
18457
+ FOR existing_name IN
18458
+ SELECT con.conname
18459
+ FROM pg_constraint con
18460
+ JOIN pg_class rel ON rel.oid = con.conrelid
18461
+ JOIN pg_namespace nsp ON nsp.oid = rel.relnamespace
18462
+ WHERE con.contype = 'f'
18463
+ AND rel.relname = ${table}
18464
+ AND nsp.nspname = current_schema()
18465
+ AND con.conkey = ARRAY[(
18466
+ SELECT att.attnum FROM pg_attribute att
18467
+ WHERE att.attrelid = rel.oid AND att.attname = ${column} AND att.attnum > 0
18468
+ )]::smallint[]
18469
+ LOOP
18470
+ EXECUTE format('ALTER TABLE %I DROP CONSTRAINT %I', ${table}, existing_name);
18471
+ END LOOP;
18472
+ END $$;`;
18473
+ }
18474
+ quoteLiteral(value) {
18475
+ return `'${value.replace(/'/g, "''")}'`;
18404
18476
  }
18405
18477
  addColumn(tableName, column) {
18406
18478
  const typeSql = this.getColumnType(column);
@@ -29062,6 +29134,37 @@ function canonicalStorageType(col, dialect) {
29062
29134
  return "TEXT";
29063
29135
  }
29064
29136
  }
29137
+ if (dialect === "mysql" || dialect === "vitess" || dialect === "singlestore") {
29138
+ switch (col.type) {
29139
+ case "string":
29140
+ return `VARCHAR(${col.maxLength ?? 255})`;
29141
+ case "text":
29142
+ return "TEXT";
29143
+ case "boolean":
29144
+ return "TINYINT(1)";
29145
+ case "integer":
29146
+ return "INTEGER";
29147
+ case "bigint":
29148
+ return "BIGINT";
29149
+ case "float":
29150
+ return "REAL";
29151
+ case "double":
29152
+ return "DOUBLE";
29153
+ case "decimal":
29154
+ return "DECIMAL";
29155
+ case "date":
29156
+ return "DATE";
29157
+ case "datetime":
29158
+ case "timestamptz":
29159
+ return "DATETIME";
29160
+ case "json":
29161
+ return "JSON";
29162
+ case "enum":
29163
+ return "ENUM";
29164
+ default:
29165
+ return col.type;
29166
+ }
29167
+ }
29065
29168
  return col.type;
29066
29169
  }
29067
29170
  function canonicalizeDefault(col) {
@@ -31565,7 +31668,7 @@ function getPrefix() {
31565
31668
  }
31566
31669
  var prefix = getPrefix();
31567
31670
  // package.json
31568
- var version2 = "0.2.17";
31671
+ var version2 = "0.2.19";
31569
31672
 
31570
31673
  // bin/cli.ts
31571
31674
  init_actions();
package/dist/src/index.js CHANGED
@@ -17739,6 +17739,8 @@ function sqlTypeToNormalized(rawType, dialect, ctx) {
17739
17739
  if (/^(?:varchar|character varying|nvarchar|nchar|char|character|bpchar)/.test(base)) {
17740
17740
  const m = t.match(/\((\d+)\)/);
17741
17741
  const len = m ? Number(m[1]) : undefined;
17742
+ if (isMysqlLike(dialect))
17743
+ return "string";
17742
17744
  return len !== undefined && len > 255 ? "text" : "string";
17743
17745
  }
17744
17746
  if (/text|clob/.test(base))
@@ -17766,6 +17768,13 @@ function sqlTypeToNormalized(rawType, dialect, ctx) {
17766
17768
  function mysqlColumnType(dataType, columnType, enumValues) {
17767
17769
  return sqlTypeToNormalized(String(columnType || dataType || ""), "mysql", { enumValues });
17768
17770
  }
17771
+ function mysqlColumnMaxLength(columnType) {
17772
+ const match = String(columnType || "").trim().match(/^varchar\((\d+)\)/i);
17773
+ if (!match)
17774
+ return;
17775
+ const length = Number(match[1]);
17776
+ return Number.isSafeInteger(length) && length > 0 ? length : undefined;
17777
+ }
17769
17778
  function asAction(raw2) {
17770
17779
  const v = String(raw2 ?? "").toLowerCase().trim();
17771
17780
  if (v === "cascade" || v === "restrict" || v === "set null")
@@ -17968,6 +17977,7 @@ async function buildMysqlTable(qb, table) {
17968
17977
  hasDefault,
17969
17978
  defaultValue: hasDefault ? normalizeRawDefault(rawDefault) : undefined,
17970
17979
  enumValues,
17980
+ maxLength: mysqlColumnMaxLength(columnType),
17971
17981
  references: fkByColumn.get(name)
17972
17982
  };
17973
17983
  });
@@ -18209,7 +18219,42 @@ class MySQLDriver {
18209
18219
  sql += ` ON DELETE ${onDelete.toUpperCase()}`;
18210
18220
  if (onUpdate)
18211
18221
  sql += ` ON UPDATE ${onUpdate.toUpperCase()}`;
18212
- return `${sql};`;
18222
+ return `${this.dropForeignKeysOn(tableName, columnName)}
18223
+ ${sql};`;
18224
+ }
18225
+ dropForeignKeysOn(tableName, columnName) {
18226
+ const table = this.quoteLiteral(tableName);
18227
+ const column = this.quoteLiteral(columnName);
18228
+ return `SET @drop_fks := (
18229
+ SELECT CONCAT(
18230
+ 'ALTER TABLE \`', ${table}, '\` DROP FOREIGN KEY \`',
18231
+ GROUP_CONCAT(kcu.CONSTRAINT_NAME SEPARATOR '\`, DROP FOREIGN KEY \`'),
18232
+ '\`'
18233
+ )
18234
+ FROM information_schema.KEY_COLUMN_USAGE kcu
18235
+ WHERE kcu.TABLE_SCHEMA = DATABASE()
18236
+ AND kcu.TABLE_NAME = ${table}
18237
+ AND kcu.COLUMN_NAME = ${column}
18238
+ AND kcu.REFERENCED_TABLE_NAME IS NOT NULL
18239
+ AND kcu.CONSTRAINT_NAME IN (
18240
+ SELECT single.CONSTRAINT_NAME FROM (
18241
+ SELECT inner_kcu.CONSTRAINT_NAME
18242
+ FROM information_schema.KEY_COLUMN_USAGE inner_kcu
18243
+ WHERE inner_kcu.TABLE_SCHEMA = DATABASE()
18244
+ AND inner_kcu.TABLE_NAME = ${table}
18245
+ AND inner_kcu.REFERENCED_TABLE_NAME IS NOT NULL
18246
+ GROUP BY inner_kcu.CONSTRAINT_NAME
18247
+ HAVING COUNT(*) = 1
18248
+ ) AS single
18249
+ )
18250
+ );
18251
+ SET @drop_fks := IFNULL(@drop_fks, 'SELECT 1');
18252
+ PREPARE drop_fks_stmt FROM @drop_fks;
18253
+ EXECUTE drop_fks_stmt;
18254
+ DEALLOCATE PREPARE drop_fks_stmt;`;
18255
+ }
18256
+ quoteLiteral(value) {
18257
+ return `'${value.replace(/'/g, "''")}'`;
18213
18258
  }
18214
18259
  addColumn(tableName, column) {
18215
18260
  const typeSql = this.getColumnType(column);
@@ -18399,7 +18444,34 @@ class PostgresDriver {
18399
18444
  sql += ` ON DELETE ${onDelete.toUpperCase()}`;
18400
18445
  if (onUpdate)
18401
18446
  sql += ` ON UPDATE ${onUpdate.toUpperCase()}`;
18402
- return `${sql};`;
18447
+ return `${this.dropForeignKeysOn(tableName, columnName)}
18448
+ ${sql};`;
18449
+ }
18450
+ dropForeignKeysOn(tableName, columnName) {
18451
+ const table = this.quoteLiteral(tableName);
18452
+ const column = this.quoteLiteral(columnName);
18453
+ return `DO $$
18454
+ DECLARE existing_name text;
18455
+ BEGIN
18456
+ FOR existing_name IN
18457
+ SELECT con.conname
18458
+ FROM pg_constraint con
18459
+ JOIN pg_class rel ON rel.oid = con.conrelid
18460
+ JOIN pg_namespace nsp ON nsp.oid = rel.relnamespace
18461
+ WHERE con.contype = 'f'
18462
+ AND rel.relname = ${table}
18463
+ AND nsp.nspname = current_schema()
18464
+ AND con.conkey = ARRAY[(
18465
+ SELECT att.attnum FROM pg_attribute att
18466
+ WHERE att.attrelid = rel.oid AND att.attname = ${column} AND att.attnum > 0
18467
+ )]::smallint[]
18468
+ LOOP
18469
+ EXECUTE format('ALTER TABLE %I DROP CONSTRAINT %I', ${table}, existing_name);
18470
+ END LOOP;
18471
+ END $$;`;
18472
+ }
18473
+ quoteLiteral(value) {
18474
+ return `'${value.replace(/'/g, "''")}'`;
18403
18475
  }
18404
18476
  addColumn(tableName, column) {
18405
18477
  const typeSql = this.getColumnType(column);
@@ -29061,6 +29133,37 @@ function canonicalStorageType(col, dialect) {
29061
29133
  return "TEXT";
29062
29134
  }
29063
29135
  }
29136
+ if (dialect === "mysql" || dialect === "vitess" || dialect === "singlestore") {
29137
+ switch (col.type) {
29138
+ case "string":
29139
+ return `VARCHAR(${col.maxLength ?? 255})`;
29140
+ case "text":
29141
+ return "TEXT";
29142
+ case "boolean":
29143
+ return "TINYINT(1)";
29144
+ case "integer":
29145
+ return "INTEGER";
29146
+ case "bigint":
29147
+ return "BIGINT";
29148
+ case "float":
29149
+ return "REAL";
29150
+ case "double":
29151
+ return "DOUBLE";
29152
+ case "decimal":
29153
+ return "DECIMAL";
29154
+ case "date":
29155
+ return "DATE";
29156
+ case "datetime":
29157
+ case "timestamptz":
29158
+ return "DATETIME";
29159
+ case "json":
29160
+ return "JSON";
29161
+ case "enum":
29162
+ return "ENUM";
29163
+ default:
29164
+ return col.type;
29165
+ }
29166
+ }
29064
29167
  return col.type;
29065
29168
  }
29066
29169
  function canonicalizeDefault(col) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "bun-query-builder",
3
3
  "type": "module",
4
- "version": "0.2.17",
4
+ "version": "0.2.19",
5
5
  "description": "A simple yet performant query builder for TypeScript. Built with Bun.",
6
6
  "author": "Chris Breuer <chris@stacksjs.org>",
7
7
  "license": "MIT",