@mikro-orm/knex 6.4.6-dev.9 → 7.0.0-dev.0

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 (101) hide show
  1. package/AbstractSqlConnection.d.ts +15 -25
  2. package/AbstractSqlConnection.js +98 -126
  3. package/AbstractSqlDriver.d.ts +20 -13
  4. package/AbstractSqlDriver.js +73 -54
  5. package/AbstractSqlPlatform.d.ts +15 -3
  6. package/AbstractSqlPlatform.js +32 -11
  7. package/README.md +0 -2
  8. package/SqlEntityManager.d.ts +5 -6
  9. package/SqlEntityManager.js +5 -5
  10. package/SqlEntityRepository.d.ts +1 -6
  11. package/SqlEntityRepository.js +0 -6
  12. package/dialects/mssql/MsSqlNativeQueryBuilder.d.ts +12 -0
  13. package/dialects/mssql/MsSqlNativeQueryBuilder.js +161 -0
  14. package/dialects/mssql/index.d.ts +1 -1
  15. package/dialects/mssql/index.js +1 -1
  16. package/dialects/mysql/MySqlExceptionConverter.js +1 -0
  17. package/dialects/mysql/MySqlNativeQueryBuilder.d.ts +7 -0
  18. package/dialects/mysql/MySqlNativeQueryBuilder.js +81 -0
  19. package/dialects/mysql/MySqlPlatform.d.ts +5 -1
  20. package/dialects/mysql/MySqlPlatform.js +9 -1
  21. package/dialects/mysql/MySqlSchemaHelper.d.ts +6 -12
  22. package/dialects/mysql/MySqlSchemaHelper.js +42 -75
  23. package/dialects/mysql/index.d.ts +1 -3
  24. package/dialects/mysql/index.js +1 -3
  25. package/dialects/postgresql/PostgreSqlNativeQueryBuilder.d.ts +5 -0
  26. package/dialects/postgresql/PostgreSqlNativeQueryBuilder.js +12 -0
  27. package/dialects/postgresql/index.d.ts +1 -1
  28. package/dialects/postgresql/index.js +1 -1
  29. package/dialects/sqlite/BaseSqliteConnection.d.ts +0 -5
  30. package/dialects/sqlite/BaseSqliteConnection.js +4 -42
  31. package/dialects/sqlite/BaseSqlitePlatform.d.ts +15 -3
  32. package/dialects/sqlite/BaseSqlitePlatform.js +20 -4
  33. package/dialects/sqlite/SqliteExceptionConverter.d.ts +9 -0
  34. package/dialects/sqlite/SqliteExceptionConverter.js +55 -0
  35. package/dialects/sqlite/SqliteNativeQueryBuilder.d.ts +6 -0
  36. package/dialects/sqlite/SqliteNativeQueryBuilder.js +15 -0
  37. package/dialects/sqlite/SqliteSchemaHelper.d.ts +38 -0
  38. package/dialects/sqlite/SqliteSchemaHelper.js +384 -0
  39. package/dialects/sqlite/index.d.ts +3 -5
  40. package/dialects/sqlite/index.js +3 -5
  41. package/index.d.ts +1 -2
  42. package/index.js +3 -5
  43. package/index.mjs +10 -13
  44. package/package.json +4 -18
  45. package/query/CriteriaNodeFactory.js +5 -5
  46. package/query/NativeQueryBuilder.d.ts +108 -0
  47. package/query/NativeQueryBuilder.js +429 -0
  48. package/query/ObjectCriteriaNode.js +3 -3
  49. package/query/QueryBuilder.d.ts +30 -34
  50. package/query/QueryBuilder.js +112 -123
  51. package/query/QueryBuilderHelper.d.ts +27 -23
  52. package/query/QueryBuilderHelper.js +174 -168
  53. package/query/ScalarCriteriaNode.js +4 -0
  54. package/query/index.d.ts +1 -0
  55. package/query/index.js +1 -0
  56. package/schema/DatabaseSchema.js +9 -6
  57. package/schema/DatabaseTable.d.ts +2 -1
  58. package/schema/DatabaseTable.js +9 -5
  59. package/schema/SchemaComparator.d.ts +1 -2
  60. package/schema/SchemaComparator.js +31 -18
  61. package/schema/SchemaHelper.d.ts +27 -33
  62. package/schema/SchemaHelper.js +294 -184
  63. package/schema/SqlSchemaGenerator.d.ts +3 -9
  64. package/schema/SqlSchemaGenerator.js +105 -229
  65. package/typings.d.ts +7 -17
  66. package/MonkeyPatchable.d.ts +0 -18
  67. package/MonkeyPatchable.js +0 -60
  68. package/dialects/mssql/MsSqlColumnCompiler.d.ts +0 -4
  69. package/dialects/mssql/MsSqlColumnCompiler.js +0 -10
  70. package/dialects/mssql/MsSqlKnexDialect.d.ts +0 -6
  71. package/dialects/mssql/MsSqlKnexDialect.js +0 -22
  72. package/dialects/mssql/MsSqlQueryCompiler.d.ts +0 -12
  73. package/dialects/mssql/MsSqlQueryCompiler.js +0 -94
  74. package/dialects/mssql/MsSqlTableCompiler.d.ts +0 -9
  75. package/dialects/mssql/MsSqlTableCompiler.js +0 -40
  76. package/dialects/mysql/MariaDbKnexDialect.d.ts +0 -6
  77. package/dialects/mysql/MariaDbKnexDialect.js +0 -16
  78. package/dialects/mysql/MySqlColumnCompiler.d.ts +0 -7
  79. package/dialects/mysql/MySqlColumnCompiler.js +0 -26
  80. package/dialects/mysql/MySqlConnection.d.ts +0 -8
  81. package/dialects/mysql/MySqlConnection.js +0 -43
  82. package/dialects/mysql/MySqlKnexDialect.d.ts +0 -5
  83. package/dialects/mysql/MySqlKnexDialect.js +0 -17
  84. package/dialects/mysql/MySqlQueryCompiler.d.ts +0 -5
  85. package/dialects/mysql/MySqlQueryCompiler.js +0 -23
  86. package/dialects/postgresql/PostgreSqlKnexDialect.d.ts +0 -7
  87. package/dialects/postgresql/PostgreSqlKnexDialect.js +0 -20
  88. package/dialects/postgresql/PostgreSqlQueryCompiler.d.ts +0 -4
  89. package/dialects/postgresql/PostgreSqlQueryCompiler.js +0 -13
  90. package/dialects/postgresql/PostgreSqlTableCompiler.d.ts +0 -11
  91. package/dialects/postgresql/PostgreSqlTableCompiler.js +0 -89
  92. package/dialects/sqlite/BaseSqliteSchemaHelper.d.ts +0 -28
  93. package/dialects/sqlite/BaseSqliteSchemaHelper.js +0 -200
  94. package/dialects/sqlite/BetterSqliteKnexDialect.d.ts +0 -5
  95. package/dialects/sqlite/BetterSqliteKnexDialect.js +0 -15
  96. package/dialects/sqlite/LibSqlKnexDialect.d.ts +0 -11
  97. package/dialects/sqlite/LibSqlKnexDialect.js +0 -85
  98. package/dialects/sqlite/SqliteKnexDialect.d.ts +0 -8
  99. package/dialects/sqlite/SqliteKnexDialect.js +0 -67
  100. package/dialects/sqlite/SqliteTableCompiler.d.ts +0 -6
  101. package/dialects/sqlite/SqliteTableCompiler.js +0 -71
@@ -122,10 +122,9 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
122
122
  if (res instanceof query_1.QueryBuilder) {
123
123
  return this.wrapVirtualExpressionInSubquery(meta, res.getFormattedQuery(), where, options, type);
124
124
  }
125
- if (!(res instanceof Promise) && core_1.Utils.isObject(res)) {
126
- const { sql, bindings } = res.toSQL();
127
- const query = this.platform.formatQuery(sql, bindings);
128
- return this.wrapVirtualExpressionInSubquery(meta, query, where, options, type);
125
+ if (res instanceof core_1.RawQueryFragment) {
126
+ const expr = this.platform.formatQuery(res.sql, res.params);
127
+ return this.wrapVirtualExpressionInSubquery(meta, expr, where, options, type);
129
128
  }
130
129
  /* istanbul ignore next */
131
130
  return res;
@@ -150,15 +149,16 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
150
149
  }
151
150
  qb.limit(options?.limit, options?.offset);
152
151
  }
153
- const kqb = qb.getKnexQuery(false).clear('select');
152
+ const native = qb.getNativeQuery(false).clear('select');
154
153
  if (type === query_1.QueryType.COUNT) {
155
- kqb.select(this.connection.getKnex().raw('count(*) as count'));
154
+ native.count();
156
155
  }
157
156
  else { // select
158
- kqb.select('*');
157
+ native.select('*');
159
158
  }
160
- kqb.fromRaw(`(${expression}) as ${this.platform.quoteIdentifier(qb.alias)}`);
161
- const res = await this.execute(kqb);
159
+ native.from((0, core_1.raw)(`(${expression}) as ${this.platform.quoteIdentifier(qb.alias)}`));
160
+ const query = native.compile();
161
+ const res = await this.execute(query.sql, query.params, 'all', options.ctx);
162
162
  if (type === query_1.QueryType.COUNT) {
163
163
  return res[0].count;
164
164
  }
@@ -371,7 +371,7 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
371
371
  if (meta && this.platform.usesOutputStatement()) {
372
372
  const returningProps = meta.props
373
373
  .filter(prop => prop.persist !== false && prop.defaultRaw || prop.autoincrement || prop.generated)
374
- .filter(prop => !(prop.name in data[0]) || core_1.Utils.isRawSql(data[0][prop.name]));
374
+ .filter(prop => !(prop.name in data[0]) || (0, core_1.isRaw)(data[0][prop.name]));
375
375
  const returningFields = core_1.Utils.flatten(returningProps.map(prop => prop.fieldNames));
376
376
  sql += returningFields.length > 0 ? ` output ${returningFields.map(field => 'inserted.' + this.platform.quoteIdentifier(field)).join(', ')}` : '';
377
377
  }
@@ -436,7 +436,7 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
436
436
  else {
437
437
  const field = prop.fieldNames[0];
438
438
  if (!duplicates.includes(field) || !usedDups.includes(field)) {
439
- if (prop.customType && !prop.object && 'convertToDatabaseValueSQL' in prop.customType && !this.platform.isRaw(row[prop.name])) {
439
+ if (prop.customType && !prop.object && 'convertToDatabaseValueSQL' in prop.customType && !(0, core_1.isRaw)(row[prop.name])) {
440
440
  keys.push(prop.customType.convertToDatabaseValueSQL('?', this.platform));
441
441
  }
442
442
  else {
@@ -453,7 +453,7 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
453
453
  if (meta && this.platform.usesReturningStatement()) {
454
454
  const returningProps = meta.props
455
455
  .filter(prop => prop.persist !== false && prop.defaultRaw || prop.autoincrement || prop.generated)
456
- .filter(prop => !(prop.name in data[0]) || core_1.Utils.isRawSql(data[0][prop.name]));
456
+ .filter(prop => !(prop.name in data[0]) || (0, core_1.isRaw)(data[0][prop.name]));
457
457
  const returningFields = core_1.Utils.flatten(returningProps.map(prop => prop.fieldNames));
458
458
  /* istanbul ignore next */
459
459
  sql += returningFields.length > 0 ? ` returning ${returningFields.map(field => this.platform.quoteIdentifier(field)).join(', ')}` : '';
@@ -549,7 +549,7 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
549
549
  for (const row of data) {
550
550
  for (const k of core_1.Utils.keys(row)) {
551
551
  keys.add(k);
552
- if (core_1.Utils.isRawSql(row[k])) {
552
+ if ((0, core_1.isRaw)(row[k])) {
553
553
  returning.add(k);
554
554
  }
555
555
  }
@@ -587,7 +587,7 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
587
587
  if (key in data[idx]) {
588
588
  const pks = core_1.Utils.getOrderedPrimaryKeys(cond, meta);
589
589
  sql += ` when (${pkCond}) then `;
590
- if (prop.customType && !prop.object && 'convertToDatabaseValueSQL' in prop.customType && !this.platform.isRaw(data[idx][key])) {
590
+ if (prop.customType && !prop.object && 'convertToDatabaseValueSQL' in prop.customType && !(0, core_1.isRaw)(data[idx][key])) {
591
591
  sql += prop.customType.convertToDatabaseValueSQL('?', this.platform);
592
592
  }
593
593
  else {
@@ -706,24 +706,24 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
706
706
  .withSchema(this.getSchemaName(meta, options));
707
707
  if (coll.getSnapshot() === undefined) {
708
708
  if (coll.property.orphanRemoval) {
709
- const kqb = qb.delete({ [coll.property.mappedBy]: pks })
710
- .getKnexQuery()
711
- .whereNotIn(cols, insertDiff);
712
- await this.rethrow(this.execute(kqb));
709
+ const query = qb.delete({ [coll.property.mappedBy]: pks })
710
+ .andWhere({ [cols.join(core_1.Utils.PK_SEPARATOR)]: { $nin: insertDiff } });
711
+ await this.rethrow(query.execute());
713
712
  continue;
714
713
  }
715
- const kqb = qb.update({ [coll.property.mappedBy]: null })
714
+ const query = qb.update({ [coll.property.mappedBy]: null })
716
715
  .where({ [coll.property.mappedBy]: pks })
717
- .getKnexQuery()
718
- .andWhere(qb => qb.whereNotIn(cols, insertDiff));
719
- await this.rethrow(this.execute(kqb));
716
+ .andWhere({ [cols.join(core_1.Utils.PK_SEPARATOR)]: { $nin: insertDiff } });
717
+ await this.rethrow(query.execute());
718
+ continue;
719
+ }
720
+ /* istanbul ignore next */
721
+ {
722
+ const query = qb.update({ [coll.property.mappedBy]: pks })
723
+ .where({ [cols.join(core_1.Utils.PK_SEPARATOR)]: { $in: insertDiff } });
724
+ await this.rethrow(query.execute());
720
725
  continue;
721
726
  }
722
- const kqb = qb.update({ [coll.property.mappedBy]: pks })
723
- .getKnexQuery()
724
- .whereIn(cols, insertDiff);
725
- await this.rethrow(this.execute(kqb));
726
- continue;
727
727
  }
728
728
  /* istanbul ignore next */
729
729
  const pivotMeta = this.metadata.find(coll.property.pivotEntity);
@@ -851,8 +851,8 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
851
851
  }
852
852
  return [];
853
853
  }
854
- async execute(queryOrKnex, params = [], method = 'all', ctx, loggerContext) {
855
- return this.rethrow(this.connection.execute(queryOrKnex, params, method, ctx, loggerContext));
854
+ async execute(query, params = [], method = 'all', ctx, loggerContext) {
855
+ return this.rethrow(this.connection.execute(query, params, method, ctx, loggerContext));
856
856
  }
857
857
  /**
858
858
  * 1:1 owner side needs to be marked for population so QB auto-joins the owner id
@@ -927,11 +927,12 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
927
927
  }
928
928
  return res;
929
929
  }
930
- getFieldsForJoinedLoad(qb, meta, explicitFields, exclude, populate = [], options, parentTableAlias, parentJoinPath, count) {
930
+ getFieldsForJoinedLoad(qb, meta, options) {
931
931
  const fields = [];
932
+ const populate = options.populate ?? [];
932
933
  const joinedProps = this.joinedProps(meta, populate, options);
933
934
  const shouldHaveColumn = (prop, populate, fields) => {
934
- if (!this.platform.shouldHaveColumn(prop, populate, exclude)) {
935
+ if (!this.platform.shouldHaveColumn(prop, populate, options.exclude)) {
935
936
  return false;
936
937
  }
937
938
  if (!fields || fields.includes('*') || prop.primary) {
@@ -941,11 +942,11 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
941
942
  };
942
943
  const populateWhereAll = options?._populateWhere === 'all' || core_1.Utils.isEmpty(options?._populateWhere);
943
944
  // root entity is already handled, skip that
944
- if (parentJoinPath) {
945
+ if (options.parentJoinPath) {
945
946
  // alias all fields in the primary table
946
947
  meta.props
947
- .filter(prop => shouldHaveColumn(prop, populate, explicitFields))
948
- .forEach(prop => fields.push(...this.mapPropToFieldNames(qb, prop, parentTableAlias)));
948
+ .filter(prop => shouldHaveColumn(prop, populate, options.explicitFields))
949
+ .forEach(prop => fields.push(...this.mapPropToFieldNames(qb, prop, options.parentTableAlias)));
949
950
  }
950
951
  for (const hint of joinedProps) {
951
952
  const [propName, ref] = hint.field.split(':', 2);
@@ -954,15 +955,15 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
954
955
  if (ref && !hint.filter && (prop.kind === core_1.ReferenceKind.MANY_TO_ONE || (prop.kind === core_1.ReferenceKind.ONE_TO_ONE && !prop.owner))) {
955
956
  continue;
956
957
  }
957
- if (count && (!options?.populateFilter || !options.populateFilter[prop.name])) {
958
+ if (options.count && (!options?.populateFilter || !options.populateFilter[prop.name])) {
958
959
  continue;
959
960
  }
960
961
  const meta2 = this.metadata.find(prop.type);
961
962
  const pivotRefJoin = prop.kind === core_1.ReferenceKind.MANY_TO_MANY && ref;
962
963
  const tableAlias = qb.getNextAlias(prop.name);
963
- const field = parentTableAlias ? `${parentTableAlias}.${prop.name}` : prop.name;
964
- let path = parentJoinPath ? `${parentJoinPath}.${prop.name}` : `${meta.name}.${prop.name}`;
965
- if (!parentJoinPath && populateWhereAll && !hint.filter && !path.startsWith('[populate]')) {
964
+ const field = `${options.parentTableAlias}.${prop.name}`;
965
+ let path = options.parentJoinPath ? `${options.parentJoinPath}.${prop.name}` : `${meta.name}.${prop.name}`;
966
+ if (!options.parentJoinPath && populateWhereAll && !hint.filter && !path.startsWith('[populate]')) {
966
967
  path = '[populate]' + path;
967
968
  }
968
969
  const joinType = pivotRefJoin
@@ -975,17 +976,31 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
975
976
  fields.push(...prop.joinColumns.map(col => qb.helper.mapper(`${tableAlias}.${col}`, qb.type, undefined, `${tableAlias}__${col}`)), ...prop.inverseJoinColumns.map(col => qb.helper.mapper(`${tableAlias}.${col}`, qb.type, undefined, `${tableAlias}__${col}`)));
976
977
  }
977
978
  if (prop.kind === core_1.ReferenceKind.ONE_TO_MANY && ref) {
978
- fields.push(...this.getFieldsForJoinedLoad(qb, meta2, prop.referencedColumnNames, undefined, hint.children, options, tableAlias, path, count));
979
+ fields.push(...this.getFieldsForJoinedLoad(qb, meta2, {
980
+ ...options,
981
+ explicitFields: prop.referencedColumnNames,
982
+ exclude: undefined,
983
+ populate: hint.children,
984
+ parentTableAlias: tableAlias,
985
+ parentJoinPath: path,
986
+ }));
979
987
  }
980
- const childExplicitFields = explicitFields?.filter(f => core_1.Utils.isPlainObject(f)).map(o => o[prop.name])[0] || [];
981
- explicitFields?.forEach(f => {
988
+ const childExplicitFields = options.explicitFields?.filter(f => core_1.Utils.isPlainObject(f)).map(o => o[prop.name])[0] || [];
989
+ options.explicitFields?.forEach(f => {
982
990
  if (typeof f === 'string' && f.startsWith(`${prop.name}.`)) {
983
991
  childExplicitFields.push(f.substring(prop.name.length + 1));
984
992
  }
985
993
  });
986
- const childExclude = exclude ? core_1.Utils.extractChildElements(exclude, prop.name) : exclude;
994
+ const childExclude = options.exclude ? core_1.Utils.extractChildElements(options.exclude, prop.name) : options.exclude;
987
995
  if (!ref && !prop.mapToPk) {
988
- fields.push(...this.getFieldsForJoinedLoad(qb, meta2, childExplicitFields.length === 0 ? undefined : childExplicitFields, childExclude, hint.children, options, tableAlias, path, count));
996
+ fields.push(...this.getFieldsForJoinedLoad(qb, meta2, {
997
+ ...options,
998
+ explicitFields: childExplicitFields.length === 0 ? undefined : childExplicitFields,
999
+ exclude: childExclude,
1000
+ populate: hint.children,
1001
+ parentTableAlias: tableAlias,
1002
+ parentJoinPath: path,
1003
+ }));
989
1004
  }
990
1005
  else if (hint.filter || prop.mapToPk) {
991
1006
  fields.push(...prop.referencedColumnNames.map(col => qb.helper.mapper(`${tableAlias}.${col}`, qb.type, undefined, `${tableAlias}__${col}`)));
@@ -997,8 +1012,8 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
997
1012
  * @internal
998
1013
  */
999
1014
  mapPropToFieldNames(qb, prop, tableAlias) {
1000
- const aliased = this.platform.quoteIdentifier(tableAlias ? `${tableAlias}__${prop.fieldNames[0]}` : prop.fieldNames[0]);
1001
- if (tableAlias && prop.customTypes?.some(type => type?.convertToJSValueSQL)) {
1015
+ const aliased = this.platform.quoteIdentifier(`${tableAlias}__${prop.fieldNames[0]}`);
1016
+ if (prop.customTypes?.some(type => type?.convertToJSValueSQL)) {
1002
1017
  return prop.fieldNames.map((col, idx) => {
1003
1018
  if (!prop.customTypes[idx]?.convertToJSValueSQL) {
1004
1019
  return col;
@@ -1008,20 +1023,17 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
1008
1023
  return (0, core_1.raw)(`${prop.customTypes[idx].convertToJSValueSQL(prefixed, this.platform)} as ${aliased}`);
1009
1024
  });
1010
1025
  }
1011
- if (tableAlias && prop.customType?.convertToJSValueSQL) {
1026
+ if (prop.customType?.convertToJSValueSQL) {
1012
1027
  const prefixed = this.platform.quoteIdentifier(`${tableAlias}.${prop.fieldNames[0]}`);
1013
1028
  return [(0, core_1.raw)(`${prop.customType.convertToJSValueSQL(prefixed, this.platform)} as ${aliased}`)];
1014
1029
  }
1015
1030
  if (prop.formula) {
1016
- const alias = this.platform.quoteIdentifier(tableAlias ?? qb.alias);
1031
+ const alias = this.platform.quoteIdentifier(tableAlias);
1017
1032
  return [(0, core_1.raw)(`${prop.formula(alias)} as ${aliased}`)];
1018
1033
  }
1019
- if (tableAlias) {
1020
- return prop.fieldNames.map(fieldName => {
1021
- return `${tableAlias}.${fieldName} as ${tableAlias}__${fieldName}`;
1022
- });
1023
- }
1024
- return prop.fieldNames;
1034
+ return prop.fieldNames.map(fieldName => {
1035
+ return `${tableAlias}.${fieldName} as ${tableAlias}__${fieldName}`;
1036
+ });
1025
1037
  }
1026
1038
  /** @internal */
1027
1039
  createQueryBuilder(entityName, ctx, preferredConnectionType, convertCustomTypes, loggerContext, alias, em) {
@@ -1308,7 +1320,14 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
1308
1320
  }
1309
1321
  // add joined relations after the root entity fields
1310
1322
  if (joinedProps.length > 0) {
1311
- ret.push(...this.getFieldsForJoinedLoad(qb, meta, options.fields, options.exclude, populate, options, alias, undefined, count));
1323
+ ret.push(...this.getFieldsForJoinedLoad(qb, meta, {
1324
+ explicitFields: options.fields,
1325
+ exclude: options.exclude,
1326
+ populate,
1327
+ parentTableAlias: alias,
1328
+ count,
1329
+ ...options,
1330
+ }));
1312
1331
  }
1313
1332
  return core_1.Utils.unique(ret);
1314
1333
  }
@@ -1,6 +1,8 @@
1
- import { Platform, type Constructor, type EntityManager, type EntityRepository, type IDatabaseDriver, type MikroORM } from '@mikro-orm/core';
2
- import { SqlSchemaGenerator, type SchemaHelper } from './schema';
1
+ import { type Constructor, type EntityManager, type EntityRepository, type IDatabaseDriver, type IsolationLevel, type MikroORM, Platform } from '@mikro-orm/core';
2
+ import { SqlSchemaGenerator } from './schema/SqlSchemaGenerator';
3
+ import { type SchemaHelper } from './schema/SchemaHelper';
3
4
  import type { IndexDef } from './typings';
5
+ import { NativeQueryBuilder } from './query/NativeQueryBuilder';
4
6
  export declare abstract class AbstractSqlPlatform extends Platform {
5
7
  protected readonly schemaHelper?: SchemaHelper;
6
8
  usesPivotTable(): boolean;
@@ -10,12 +12,22 @@ export declare abstract class AbstractSqlPlatform extends Platform {
10
12
  /** @inheritDoc */
11
13
  lookupExtensions(orm: MikroORM): void;
12
14
  getSchemaGenerator(driver: IDatabaseDriver, em?: EntityManager): SqlSchemaGenerator;
15
+ /** @internal */
16
+ createNativeQueryBuilder(): NativeQueryBuilder;
17
+ getBeginTransactionSQL(options?: {
18
+ isolationLevel?: IsolationLevel;
19
+ readOnly?: boolean;
20
+ }): string[];
21
+ getCommitTransactionSQL(): string;
22
+ getRollbackTransactionSQL(): string;
23
+ getSavepointSQL(savepointName: string): string;
24
+ getRollbackToSavepointSQL(savepointName: string): string;
25
+ getReleaseSavepointSQL(savepointName: string): string;
13
26
  quoteValue(value: any): string;
14
27
  escape(value: any): string;
15
28
  getSearchJsonPropertySQL(path: string, type: string, aliased: boolean): string;
16
29
  getSearchJsonPropertyKey(path: string[], type: string, aliased: boolean, value?: unknown): string;
17
30
  getJsonIndexDefinition(index: IndexDef): string[];
18
- isRaw(value: any): boolean;
19
31
  supportsSchemas(): boolean;
20
32
  /** @inheritDoc */
21
33
  generateCustomOrder(escapedColumn: string, values: unknown[]): string;
@@ -4,7 +4,8 @@ exports.AbstractSqlPlatform = void 0;
4
4
  const sqlstring_1 = require("sqlstring");
5
5
  const core_1 = require("@mikro-orm/core");
6
6
  const SqlEntityRepository_1 = require("./SqlEntityRepository");
7
- const schema_1 = require("./schema");
7
+ const SqlSchemaGenerator_1 = require("./schema/SqlSchemaGenerator");
8
+ const NativeQueryBuilder_1 = require("./query/NativeQueryBuilder");
8
9
  class AbstractSqlPlatform extends core_1.Platform {
9
10
  schemaHelper;
10
11
  usesPivotTable() {
@@ -21,18 +22,41 @@ class AbstractSqlPlatform extends core_1.Platform {
21
22
  }
22
23
  /** @inheritDoc */
23
24
  lookupExtensions(orm) {
24
- schema_1.SqlSchemaGenerator.register(orm);
25
+ SqlSchemaGenerator_1.SqlSchemaGenerator.register(orm);
25
26
  }
26
27
  /* istanbul ignore next: kept for type inference only */
27
28
  getSchemaGenerator(driver, em) {
28
- return new schema_1.SqlSchemaGenerator(em ?? driver);
29
+ return new SqlSchemaGenerator_1.SqlSchemaGenerator(em ?? driver);
29
30
  }
30
- quoteValue(value) {
31
- if (core_1.Utils.isRawSql(value)) {
32
- return this.formatQuery(value.sql, value.params ?? []);
31
+ /* istanbul ignore next */
32
+ /** @internal */
33
+ createNativeQueryBuilder() {
34
+ return new NativeQueryBuilder_1.NativeQueryBuilder(this);
35
+ }
36
+ getBeginTransactionSQL(options) {
37
+ if (options?.isolationLevel) {
38
+ return [`set transaction isolation level ${options.isolationLevel}`, 'begin'];
33
39
  }
34
- if (this.isRaw(value)) {
35
- return value;
40
+ return ['begin'];
41
+ }
42
+ getCommitTransactionSQL() {
43
+ return 'commit';
44
+ }
45
+ getRollbackTransactionSQL() {
46
+ return 'rollback';
47
+ }
48
+ getSavepointSQL(savepointName) {
49
+ return `savepoint ${savepointName}`;
50
+ }
51
+ getRollbackToSavepointSQL(savepointName) {
52
+ return `rollback to savepoint ${savepointName}`;
53
+ }
54
+ getReleaseSavepointSQL(savepointName) {
55
+ return `release savepoint ${savepointName}`;
56
+ }
57
+ quoteValue(value) {
58
+ if ((0, core_1.isRaw)(value)) {
59
+ return this.formatQuery(value.sql, value.params);
36
60
  }
37
61
  if (core_1.Utils.isPlainObject(value) || value?.[core_1.JsonProperty]) {
38
62
  return this.escape(JSON.stringify(value));
@@ -63,9 +87,6 @@ class AbstractSqlPlatform extends core_1.Platform {
63
87
  return `(json_extract(${root}, '$.${path.join('.')}'))`;
64
88
  });
65
89
  }
66
- isRaw(value) {
67
- return super.isRaw(value) || (typeof value === 'object' && value !== null && value.client && ['Ref', 'Raw'].includes(value.constructor.name));
68
- }
69
90
  supportsSchemas() {
70
91
  return false;
71
92
  }
package/README.md CHANGED
@@ -183,7 +183,6 @@ yarn add @mikro-orm/core @mikro-orm/mariadb # for mysql/mariadb
183
183
  yarn add @mikro-orm/core @mikro-orm/postgresql # for postgresql
184
184
  yarn add @mikro-orm/core @mikro-orm/mssql # for mssql
185
185
  yarn add @mikro-orm/core @mikro-orm/sqlite # for sqlite
186
- yarn add @mikro-orm/core @mikro-orm/better-sqlite # for better-sqlite
187
186
  yarn add @mikro-orm/core @mikro-orm/libsql # for libsql
188
187
  ```
189
188
 
@@ -196,7 +195,6 @@ npm i -s @mikro-orm/core @mikro-orm/mariadb # for mysql/mariadb
196
195
  npm i -s @mikro-orm/core @mikro-orm/postgresql # for postgresql
197
196
  npm i -s @mikro-orm/core @mikro-orm/mssql # for mssql
198
197
  npm i -s @mikro-orm/core @mikro-orm/sqlite # for sqlite
199
- npm i -s @mikro-orm/core @mikro-orm/better-sqlite # for better-sqlite
200
198
  npm i -s @mikro-orm/core @mikro-orm/libsql # for libsql
201
199
  ```
202
200
 
@@ -1,7 +1,6 @@
1
- import type { Knex } from 'knex';
2
- import { EntityManager, type AnyEntity, type ConnectionType, type EntityData, type EntityName, type EntityRepository, type GetRepository, type QueryResult, type FilterQuery, type LoggingOptions } from '@mikro-orm/core';
1
+ import { EntityManager, type AnyEntity, type ConnectionType, type EntityData, type EntityName, type EntityRepository, type GetRepository, type QueryResult, type FilterQuery, type LoggingOptions, type RawQueryFragment } from '@mikro-orm/core';
3
2
  import type { AbstractSqlDriver } from './AbstractSqlDriver';
4
- import type { QueryBuilder } from './query';
3
+ import type { NativeQueryBuilder, QueryBuilder } from './query';
5
4
  import type { SqlEntityRepository } from './SqlEntityRepository';
6
5
  /**
7
6
  * @inheritDoc
@@ -16,10 +15,10 @@ export declare class SqlEntityManager<Driver extends AbstractSqlDriver = Abstrac
16
15
  */
17
16
  qb<Entity extends object, RootAlias extends string = never>(entityName: EntityName<Entity>, alias?: RootAlias, type?: ConnectionType, loggerContext?: LoggingOptions): QueryBuilder<Entity, RootAlias, never, never>;
18
17
  /**
19
- * Returns configured knex instance.
18
+ * Returns configured Kysely instance.
20
19
  */
21
- getKnex(type?: ConnectionType): Knex<any, any[]>;
22
- execute<T extends QueryResult | EntityData<AnyEntity> | EntityData<AnyEntity>[] = EntityData<AnyEntity>[]>(queryOrKnex: string | Knex.QueryBuilder | Knex.Raw, params?: any[], method?: 'all' | 'get' | 'run', loggerContext?: LoggingOptions): Promise<T>;
20
+ getKysely(type?: ConnectionType): import("kysely").Kysely<any>;
21
+ execute<T extends QueryResult | EntityData<AnyEntity> | EntityData<AnyEntity>[] = EntityData<AnyEntity>[]>(query: string | NativeQueryBuilder | RawQueryFragment, params?: any[], method?: 'all' | 'get' | 'run', loggerContext?: LoggingOptions): Promise<T>;
23
22
  getRepository<T extends object, U extends EntityRepository<T> = SqlEntityRepository<T>>(entityName: EntityName<T>): GetRepository<T, U>;
24
23
  protected applyDiscriminatorCondition<Entity extends object>(entityName: string, where: FilterQuery<Entity>): FilterQuery<Entity>;
25
24
  }
@@ -20,13 +20,13 @@ class SqlEntityManager extends core_1.EntityManager {
20
20
  return this.createQueryBuilder(entityName, alias, type, loggerContext);
21
21
  }
22
22
  /**
23
- * Returns configured knex instance.
23
+ * Returns configured Kysely instance.
24
24
  */
25
- getKnex(type) {
26
- return this.getConnection(type).getKnex();
25
+ getKysely(type) {
26
+ return this.getConnection(type).getClient();
27
27
  }
28
- async execute(queryOrKnex, params = [], method = 'all', loggerContext) {
29
- return this.getDriver().execute(queryOrKnex, params, method, this.getContext(false).getTransactionContext(), loggerContext);
28
+ async execute(query, params = [], method = 'all', loggerContext) {
29
+ return this.getDriver().execute(query, params, method, this.getContext(false).getTransactionContext(), loggerContext);
30
30
  }
31
31
  getRepository(entityName) {
32
32
  return super.getRepository(entityName);
@@ -1,5 +1,4 @@
1
- import type { Knex } from 'knex';
2
- import { EntityRepository, type ConnectionType, type EntityName } from '@mikro-orm/core';
1
+ import { EntityRepository, type EntityName } from '@mikro-orm/core';
3
2
  import type { SqlEntityManager } from './SqlEntityManager';
4
3
  import type { QueryBuilder } from './query';
5
4
  export declare class SqlEntityRepository<Entity extends object> extends EntityRepository<Entity> {
@@ -13,10 +12,6 @@ export declare class SqlEntityRepository<Entity extends object> extends EntityRe
13
12
  * Shortcut for `createQueryBuilder()`
14
13
  */
15
14
  qb<RootAlias extends string = never>(alias?: RootAlias): QueryBuilder<Entity, RootAlias>;
16
- /**
17
- * Returns configured knex instance.
18
- */
19
- getKnex(type?: ConnectionType): Knex;
20
15
  /**
21
16
  * @inheritDoc
22
17
  */
@@ -20,12 +20,6 @@ class SqlEntityRepository extends core_1.EntityRepository {
20
20
  qb(alias) {
21
21
  return this.createQueryBuilder(alias);
22
22
  }
23
- /**
24
- * Returns configured knex instance.
25
- */
26
- getKnex(type) {
27
- return this.getEntityManager().getKnex(type);
28
- }
29
23
  /**
30
24
  * @inheritDoc
31
25
  */
@@ -0,0 +1,12 @@
1
+ import { NativeQueryBuilder } from '../../query/NativeQueryBuilder';
2
+ /** @internal */
3
+ export declare class MsSqlNativeQueryBuilder extends NativeQueryBuilder {
4
+ compile(): {
5
+ sql: string;
6
+ params: unknown[];
7
+ };
8
+ private compileUpsert;
9
+ protected compileSelect(): void;
10
+ protected addLockClause(): void;
11
+ protected compileTruncate(): void;
12
+ }
@@ -0,0 +1,161 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MsSqlNativeQueryBuilder = void 0;
4
+ const core_1 = require("@mikro-orm/core");
5
+ const NativeQueryBuilder_1 = require("../../query/NativeQueryBuilder");
6
+ const enums_1 = require("../../query/enums");
7
+ /** @internal */
8
+ class MsSqlNativeQueryBuilder extends NativeQueryBuilder_1.NativeQueryBuilder {
9
+ compile() {
10
+ if (!this.type) {
11
+ throw new Error('No query type provided');
12
+ }
13
+ this.parts.length = 0;
14
+ this.params.length = 0;
15
+ if (this.options.flags?.has(core_1.QueryFlag.IDENTITY_INSERT)) {
16
+ this.parts.push(`set identity_insert ${this.getTableName()} on;`);
17
+ }
18
+ if (this.options.comment) {
19
+ this.parts.push(...this.options.comment.map(comment => `/* ${comment} */`));
20
+ }
21
+ if (this.options.onConflict && !core_1.Utils.isEmpty(core_1.Utils.asArray(this.options.data)[0])) {
22
+ this.compileUpsert();
23
+ }
24
+ else {
25
+ switch (this.type) {
26
+ case enums_1.QueryType.SELECT:
27
+ case enums_1.QueryType.COUNT:
28
+ this.compileSelect();
29
+ break;
30
+ case enums_1.QueryType.INSERT:
31
+ this.compileInsert();
32
+ break;
33
+ case enums_1.QueryType.UPDATE:
34
+ this.compileUpdate();
35
+ break;
36
+ case enums_1.QueryType.DELETE:
37
+ this.compileDelete();
38
+ break;
39
+ case enums_1.QueryType.TRUNCATE:
40
+ this.compileTruncate();
41
+ break;
42
+ }
43
+ if ([enums_1.QueryType.INSERT, enums_1.QueryType.UPDATE, enums_1.QueryType.DELETE].includes(this.type)) {
44
+ this.parts[this.parts.length - 1] += '; select @@rowcount;';
45
+ }
46
+ }
47
+ if (this.options.flags?.has(core_1.QueryFlag.IDENTITY_INSERT)) {
48
+ this.parts.push(`set identity_insert ${this.getTableName()} off;`);
49
+ }
50
+ return this.combineParts();
51
+ }
52
+ compileUpsert() {
53
+ const clause = this.options.onConflict;
54
+ const dataAsArray = core_1.Utils.asArray(this.options.data);
55
+ const keys = Object.keys(dataAsArray[0]);
56
+ const values = keys.map(() => '?');
57
+ const parts = [];
58
+ for (const data of dataAsArray) {
59
+ for (const key of keys) {
60
+ this.params.push(data[key]);
61
+ }
62
+ parts.push(`(${values.join(', ')})`);
63
+ }
64
+ this.parts.push(`merge into ${this.getTableName()}`);
65
+ this.parts.push(`using (values ${parts.join(', ')}) as tsource(${keys.map(key => this.quote(key)).join(', ')})`);
66
+ if (clause.fields instanceof core_1.RawQueryFragment) {
67
+ this.parts.push(clause.fields.sql);
68
+ this.params.push(...clause.fields.params);
69
+ }
70
+ else if (clause.fields.length > 0) {
71
+ // const fields = clause.fields.map(field => this.quote(field));
72
+ const conflictColumn = this.quote(clause.fields[0]);
73
+ this.parts.push(`on ${this.getTableName()}.${conflictColumn} = tsource.${conflictColumn}`);
74
+ }
75
+ const sourceColumns = keys.map(field => `tsource.${this.quote(field)}`).join(', ');
76
+ const destinationColumns = keys.map(field => this.quote(field)).join(', ');
77
+ this.parts.push(`when not matched then insert (${destinationColumns}) values (${sourceColumns})`);
78
+ if (!clause.ignore) {
79
+ this.parts.push('when matched');
80
+ if (clause.where) {
81
+ this.parts.push(`and ${clause.where.sql}`);
82
+ this.params.push(...clause.where.params);
83
+ }
84
+ this.parts.push('then update set');
85
+ if (!clause.merge || Array.isArray(clause.merge)) {
86
+ const parts = keys.map((column) => `${this.quote(column)} = tsource.${this.quote(column)}`);
87
+ this.parts.push(parts.join(', '));
88
+ }
89
+ else if (typeof clause.merge === 'object') {
90
+ const parts = Object.entries(clause.merge).map(([key, value]) => {
91
+ this.params.push(value);
92
+ return `${this.getTableName()}.${this.quote(key)} = ?`;
93
+ });
94
+ this.parts.push(parts.join(', '));
95
+ }
96
+ }
97
+ this.addOutputClause('inserted');
98
+ this.parts[this.parts.length - 1] += ';';
99
+ }
100
+ compileSelect() {
101
+ this.parts.push('select');
102
+ if (this.options.limit != null && this.options.offset == null) {
103
+ this.parts.push(`top (?)`);
104
+ this.params.push(this.options.limit);
105
+ }
106
+ this.addHintComment();
107
+ this.parts.push(`${this.getFields()} from ${this.getTableName()}`);
108
+ this.addLockClause();
109
+ if (this.options.joins) {
110
+ for (const join of this.options.joins) {
111
+ this.parts.push(join.sql);
112
+ this.params.push(...join.params);
113
+ }
114
+ }
115
+ if (this.options.where?.sql.trim()) {
116
+ this.parts.push(`where ${this.options.where.sql}`);
117
+ this.params.push(...this.options.where.params);
118
+ }
119
+ if (this.options.groupBy) {
120
+ const fields = this.options.groupBy.map(field => this.quote(field));
121
+ this.parts.push(`group by ${fields.join(', ')}`);
122
+ }
123
+ if (this.options.having) {
124
+ this.parts.push(`having ${this.options.having.sql}`);
125
+ this.params.push(...this.options.having.params);
126
+ }
127
+ if (this.options.orderBy) {
128
+ this.parts.push(`order by ${this.options.orderBy}`);
129
+ }
130
+ if (this.options.offset != null) {
131
+ /* istanbul ignore next */
132
+ if (!this.options.orderBy) {
133
+ throw new Error('Order by clause is required for pagination');
134
+ }
135
+ this.parts.push(`offset ? rows`);
136
+ this.params.push(this.options.offset);
137
+ if (this.options.limit != null) {
138
+ this.parts.push(`fetch next ? rows only`);
139
+ this.params.push(this.options.limit);
140
+ }
141
+ }
142
+ }
143
+ addLockClause() {
144
+ if (!this.options.lockMode || ![core_1.LockMode.PESSIMISTIC_READ, core_1.LockMode.PESSIMISTIC_WRITE].includes(this.options.lockMode)) {
145
+ return;
146
+ }
147
+ const map = {
148
+ [core_1.LockMode.PESSIMISTIC_READ]: 'with (holdlock)',
149
+ [core_1.LockMode.PESSIMISTIC_WRITE]: 'with (updlock)',
150
+ };
151
+ if (this.options.lockMode !== core_1.LockMode.OPTIMISTIC) {
152
+ this.parts.push(map[this.options.lockMode]);
153
+ }
154
+ }
155
+ compileTruncate() {
156
+ const tableName = this.getTableName();
157
+ const sql = `delete from ${tableName}; declare @count int = case @@rowcount when 0 then 1 else 0 end; dbcc checkident ('${tableName.replace(/[[\]]/g, '')}', reseed, @count)`;
158
+ this.parts.push(sql);
159
+ }
160
+ }
161
+ exports.MsSqlNativeQueryBuilder = MsSqlNativeQueryBuilder;
@@ -1 +1 @@
1
- export * from './MsSqlKnexDialect';
1
+ export * from './MsSqlNativeQueryBuilder';
@@ -14,4 +14,4 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./MsSqlKnexDialect"), exports);
17
+ __exportStar(require("./MsSqlNativeQueryBuilder"), exports);