@mikro-orm/sql 7.1.13-dev.15 → 7.1.13-dev.16

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mikro-orm/sql",
3
- "version": "7.1.13-dev.15",
3
+ "version": "7.1.13-dev.16",
4
4
  "description": "TypeScript ORM for Node.js based on Data Mapper, Unit of Work and Identity Map patterns. Supports MongoDB, MySQL, PostgreSQL and SQLite databases as well as usage with vanilla JavaScript.",
5
5
  "keywords": [
6
6
  "data-mapper",
@@ -53,7 +53,7 @@
53
53
  "@mikro-orm/core": "^7.1.12"
54
54
  },
55
55
  "peerDependencies": {
56
- "@mikro-orm/core": "7.1.13-dev.15"
56
+ "@mikro-orm/core": "7.1.13-dev.16"
57
57
  },
58
58
  "engines": {
59
59
  "node": ">= 22.17.0"
@@ -1,5 +1,5 @@
1
1
  import { type EntityMetadata, type EntityProperty, type Type } from '@mikro-orm/core';
2
- import { type CommonTableExpressionNameNode, type DeleteQueryNode, type InsertQueryNode, type JoinNode, type MergeQueryNode, type OperationNode, type QueryId, type SelectQueryNode, type UpdateQueryNode, type WithNode, ColumnNode, IdentifierNode, OperationNodeTransformer, SelectionNode, TableNode, ValueNode } from 'kysely';
2
+ import { type BinaryOperationNode, type CommonTableExpressionNameNode, type DeleteQueryNode, type InsertQueryNode, type JoinNode, type MergeQueryNode, type OperationNode, type QueryId, type SelectQueryNode, type UpdateQueryNode, type WithNode, ColumnNode, IdentifierNode, OperationNodeTransformer, SelectionNode, TableNode, ValueNode } from 'kysely';
3
3
  import type { MikroKyselyPluginOptions } from './index.js';
4
4
  import type { SqlEntityManager } from '../SqlEntityManager.js';
5
5
  export declare class MikroTransformer extends OperationNodeTransformer {
@@ -28,6 +28,12 @@ export declare class MikroTransformer extends OperationNodeTransformer {
28
28
  processOnUpdateHooks(node: UpdateQueryNode, meta: EntityMetadata): UpdateQueryNode;
29
29
  processInsertValues(node: InsertQueryNode, meta: EntityMetadata): InsertQueryNode;
30
30
  processUpdateValues(node: UpdateQueryNode, meta: EntityMetadata): UpdateQueryNode;
31
+ transformBinaryOperation(node: BinaryOperationNode, queryId: QueryId): BinaryOperationNode;
32
+ /** Resolve the entity property a comparison's left operand refers to, so its value operand can be converted. */
33
+ resolveOperandProperty(operand: OperationNode): {
34
+ prop: EntityProperty;
35
+ fieldName: string;
36
+ } | undefined;
31
37
  processInputValueNode(prop: EntityProperty | undefined, fieldName: string | undefined, valueNode: ValueNode): OperationNode;
32
38
  expandSelections(selections: readonly SelectionNode[]): readonly SelectionNode[];
33
39
  expandSelection(sel: SelectionNode): SelectionNode[] | null;
@@ -455,6 +455,60 @@ export class MikroTransformer extends OperationNodeTransformer {
455
455
  updates,
456
456
  };
457
457
  }
458
+ transformBinaryOperation(node, queryId) {
459
+ const transformed = super.transformBinaryOperation(node, queryId);
460
+ if (!this.#options.convertValues) {
461
+ return transformed;
462
+ }
463
+ const resolved = this.resolveOperandProperty(transformed.leftOperand);
464
+ if (!resolved) {
465
+ return transformed;
466
+ }
467
+ const { prop, fieldName } = resolved;
468
+ const right = transformed.rightOperand;
469
+ if (ValueNode.is(right)) {
470
+ const converted = this.processInputValueNode(prop, fieldName, right);
471
+ return converted === right ? transformed : { ...transformed, rightOperand: converted };
472
+ }
473
+ if (PrimitiveValueListNode.is(right)) {
474
+ // upgrade to ValueListNode when the type needs SQL-side wrapping, since
475
+ // PrimitiveValueListNode can only hold primitives
476
+ if (prop.hasConvertToDatabaseValueSQL) {
477
+ const values = right.values.map(value => this.processInputValueNode(prop, fieldName, ValueNode.create(value)));
478
+ return { ...transformed, rightOperand: ValueListNode.create(values) };
479
+ }
480
+ const values = right.values.map(value => this.prepareInputValue(prop, value, true));
481
+ return values.every((value, idx) => value === right.values[idx])
482
+ ? transformed
483
+ : { ...transformed, rightOperand: PrimitiveValueListNode.create(values) };
484
+ }
485
+ if (ValueListNode.is(right)) {
486
+ let changed = false;
487
+ const values = right.values.map(valueNode => {
488
+ if (!ValueNode.is(valueNode)) {
489
+ return valueNode;
490
+ }
491
+ const converted = this.processInputValueNode(prop, fieldName, valueNode);
492
+ if (converted !== valueNode) {
493
+ changed = true;
494
+ }
495
+ return converted;
496
+ });
497
+ return changed ? { ...transformed, rightOperand: ValueListNode.create(values) } : transformed;
498
+ }
499
+ return transformed;
500
+ }
501
+ /** Resolve the entity property a comparison's left operand refers to, so its value operand can be converted. */
502
+ resolveOperandProperty(operand) {
503
+ if (!ReferenceNode.is(operand) || !ColumnNode.is(operand.column)) {
504
+ return undefined;
505
+ }
506
+ const tableName = operand.table ? this.getTableName(operand.table) : undefined;
507
+ const meta = this.findOwnerMeta(tableName);
508
+ const fieldName = this.normalizeColumnName(operand.column.column);
509
+ const prop = this.findProperty(meta, fieldName);
510
+ return prop ? { prop, fieldName } : undefined;
511
+ }
458
512
  processInputValueNode(prop, fieldName, valueNode) {
459
513
  const converted = this.prepareInputValue(prop, valueNode.value, true);
460
514
  const newValueNode = converted === valueNode.value
@@ -543,8 +597,13 @@ export class MikroTransformer extends OperationNodeTransformer {
543
597
  if (name) {
544
598
  return this.lookupInContextStack(name) ?? this.#subqueryAliasMap.get(name) ?? this.findEntityMetadata(name);
545
599
  }
600
+ // the stack can be empty when transforming a raw root node with embedded expressions
601
+ const context = this.#contextStack[this.#contextStack.length - 1];
602
+ if (!context) {
603
+ return undefined;
604
+ }
546
605
  let single;
547
- for (const meta of this.#contextStack[this.#contextStack.length - 1].values()) {
606
+ for (const meta of context.values()) {
548
607
  if (!meta) {
549
608
  continue;
550
609
  }