@mikro-orm/sql 7.2.0-dev.1 → 7.2.0-dev.10

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.
@@ -308,22 +308,6 @@ export class SqlSchemaGenerator extends AbstractSchemaGenerator {
308
308
  for (const newTable of Object.values(schemaDiff.newTables)) {
309
309
  this.append(ret, this.helper.createTable(newTable, true), true);
310
310
  }
311
- if (this.helper.supportsSchemaConstraints()) {
312
- for (const newTable of Object.values(schemaDiff.newTables)) {
313
- const sql = [];
314
- if (this.options.createForeignKeyConstraints) {
315
- const fks = Object.values(newTable.getForeignKeys()).map(fk => this.helper.createForeignKey(newTable, fk));
316
- this.append(sql, fks);
317
- }
318
- for (const check of newTable.getChecks()) {
319
- this.append(sql, this.helper.createCheck(newTable, check));
320
- }
321
- for (const trigger of newTable.getTriggers()) {
322
- this.append(sql, this.helper.createTrigger(newTable, trigger));
323
- }
324
- this.append(ret, sql, true);
325
- }
326
- }
327
311
  if (options.dropTables && !options.safe) {
328
312
  for (const table of Object.values(schemaDiff.removedTables)) {
329
313
  // Drop triggers before the table so driver-specific cleanup runs (e.g. PostgreSQL function removal)
@@ -353,6 +337,23 @@ export class SqlSchemaGenerator extends AbstractSchemaGenerator {
353
337
  for (const changedTable of alteredTables) {
354
338
  this.append(ret, this.helper.getPostAlterTable(changedTable, options.safe), true);
355
339
  }
340
+ // after the alters, so a new table's FK can reference a unique constraint an existing table gains in the same diff
341
+ if (this.helper.supportsSchemaConstraints()) {
342
+ for (const newTable of Object.values(schemaDiff.newTables)) {
343
+ const sql = [];
344
+ if (this.options.createForeignKeyConstraints) {
345
+ const fks = Object.values(newTable.getForeignKeys()).map(fk => this.helper.createForeignKey(newTable, fk));
346
+ this.append(sql, fks);
347
+ }
348
+ for (const check of newTable.getChecks()) {
349
+ this.append(sql, this.helper.createCheck(newTable, check));
350
+ }
351
+ for (const trigger of newTable.getTriggers()) {
352
+ this.append(sql, this.helper.createTrigger(newTable, trigger));
353
+ }
354
+ this.append(ret, sql, true);
355
+ }
356
+ }
356
357
  if (!options.safe && this.platform.supportsNativeEnums()) {
357
358
  for (const removedNativeEnum of schemaDiff.removedNativeEnums) {
358
359
  this.append(ret, this.helper.getDropNativeEnumSQL(removedNativeEnum.name, removedNativeEnum.schema));
@@ -439,18 +440,23 @@ export class SqlSchemaGenerator extends AbstractSchemaGenerator {
439
440
  }
440
441
  async execute(sql, options = {}) {
441
442
  options.wrap ??= false;
442
- const lines = this.wrapSchema(sql, options).split('\n');
443
+ const lines = this.splitOutsideLiterals(this.wrapSchema(sql, options), '\n');
443
444
  const groups = [];
444
445
  let i = 0;
445
446
  for (const line of lines) {
446
- if (line.trim() === '') {
447
+ const stmt = line.trim();
448
+ if (stmt === '') {
447
449
  if (groups[i]?.length > 0) {
448
450
  i++;
449
451
  }
450
452
  continue;
451
453
  }
454
+ // same boundary an empty line creates, for statements that have to start their own batch
455
+ if (groups[i]?.length > 0 && this.startsBatch(stmt)) {
456
+ i++;
457
+ }
452
458
  groups[i] ??= [];
453
- groups[i].push(line.trim());
459
+ groups[i].push(stmt);
454
460
  }
455
461
  if (groups.length === 0) {
456
462
  return;
@@ -463,14 +469,37 @@ export class SqlSchemaGenerator extends AbstractSchemaGenerator {
463
469
  return;
464
470
  }
465
471
  const statements = groups.flatMap(group => {
466
- return group
467
- .join('\n')
468
- .split(';\n')
472
+ return this.splitOutsideLiterals(group.join('\n'), ';\n')
469
473
  .map(s => s.trim())
470
474
  .filter(s => s);
471
475
  });
472
476
  await Utils.runSerial(statements, stmt => this.driver.execute(stmt));
473
477
  }
478
+ /** Splits the SQL on the separator, keeping the separators that fall inside a string literal. */
479
+ splitOutsideLiterals(sql, separator) {
480
+ const [idOpen, idClose] = this.platform.quoteIdentifier('');
481
+ // mysql escapes quotes as `\'`, the other dialects double them, which pairs up on its own
482
+ const esc = this.platform.quoteValue(`'`).includes(`\\'`) ? '\\\\.|' : '';
483
+ // complete literals, quoted identifiers and `--` comments, so that an apostrophe inside an
484
+ // identifier or a comment is not mistaken for one opening a literal
485
+ const tokens = new RegExp(`'(?:${esc}[^'])*'|\\${idOpen}[^\\${idClose}]*\\${idClose}|--[^\n]*`, 'g');
486
+ const parts = [];
487
+ for (const chunk of sql.split(separator)) {
488
+ const prev = parts.at(-1);
489
+ // whatever quote is left once the complete tokens are gone opened a literal we are still inside of
490
+ if (prev?.replace(tokens, '').includes(`'`)) {
491
+ parts[parts.length - 1] = prev + separator + chunk;
492
+ }
493
+ else {
494
+ parts.push(chunk);
495
+ }
496
+ }
497
+ return parts;
498
+ }
499
+ /** Whether the statement has to be the first one in a query batch, e.g. `create trigger` on MSSQL. */
500
+ startsBatch(_statement) {
501
+ return false;
502
+ }
474
503
  async dropTableIfExists(name, schema) {
475
504
  const sql = this.helper.dropTableIfExists(name, schema);
476
505
  return this.execute(sql);
package/typings.d.ts CHANGED
@@ -368,9 +368,9 @@ type MaybeGenerated<TValue, TOptions, TProcessOnCreate extends boolean> = TOptio
368
368
  } ? TValue | null : TOptions extends {
369
369
  autoincrement: true;
370
370
  } ? Generated<TValue> : TOptions extends {
371
- default: true;
371
+ default: unknown;
372
372
  } ? Generated<TValue> : TOptions extends {
373
- defaultRaw: true;
373
+ defaultRaw: unknown;
374
374
  } ? Generated<TValue> : TProcessOnCreate extends false ? TValue : TOptions extends {
375
375
  onCreate: Function;
376
376
  } ? Generated<TValue> : TValue;