metal-orm 1.1.24 → 1.1.26

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 (35) hide show
  1. package/dist/index.cjs +770 -710
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.d.cts +294 -318
  4. package/dist/index.d.ts +294 -318
  5. package/dist/index.js +745 -709
  6. package/dist/index.js.map +1 -1
  7. package/package.json +1 -1
  8. package/src/core/dialect/abstract.ts +7 -229
  9. package/src/core/dialect/base/returning-strategy.ts +40 -39
  10. package/src/core/dialect/base/sql-compiler-set.ts +33 -0
  11. package/src/core/dialect/base/sql-dialect-composer.ts +294 -0
  12. package/src/core/dialect/base/standard-sql-services.ts +2 -6
  13. package/src/core/dialect/base/upsert-strategy.ts +44 -0
  14. package/src/core/dialect/capabilities/procedure-compiler.ts +10 -8
  15. package/src/core/dialect/dialect-factory.ts +17 -49
  16. package/src/core/dialect/mssql/compiler-factory.ts +12 -0
  17. package/src/core/dialect/mssql/delete-compiler.ts +40 -0
  18. package/src/core/dialect/mssql/index.ts +52 -370
  19. package/src/core/dialect/mssql/insert-compiler.ts +112 -0
  20. package/src/core/dialect/mssql/output.ts +46 -0
  21. package/src/core/dialect/mssql/procedure-compiler.ts +81 -0
  22. package/src/core/dialect/mssql/select-compiler.ts +116 -0
  23. package/src/core/dialect/mssql/update-compiler.ts +37 -0
  24. package/src/core/dialect/mysql/index.ts +66 -126
  25. package/src/core/dialect/mysql/procedure-compiler.ts +67 -0
  26. package/src/core/dialect/mysql/upsert.ts +42 -0
  27. package/src/core/dialect/postgres/index.ts +75 -114
  28. package/src/core/dialect/postgres/procedure-compiler.ts +41 -0
  29. package/src/core/dialect/postgres/returning.ts +4 -0
  30. package/src/core/dialect/postgres/upsert.ts +43 -0
  31. package/src/core/dialect/sqlite/index.ts +65 -90
  32. package/src/core/dialect/sqlite/returning.ts +30 -0
  33. package/src/core/dialect/sqlite/upsert.ts +43 -0
  34. package/src/index.ts +22 -10
  35. package/src/core/dialect/base/sql-dialect.ts +0 -176
@@ -1,135 +1,96 @@
1
- import { CompilerContext } from '../abstract.js';
1
+ import type { ProcedureCallNode } from '../../ast/procedure.js';
2
+ import type { BitwiseExpressionNode, ColumnNode, JsonPathNode } from '../../ast/expression.js';
3
+ import type {
4
+ DeleteQueryNode,
5
+ InsertQueryNode,
6
+ SelectQueryNode,
7
+ TableNode,
8
+ UpdateQueryNode
9
+ } from '../../ast/query.js';
10
+ import type { CompiledQuery, Dialect } from '../abstract.js';
2
11
  import type { CompiledProcedureCall, ProcedureCompiler } from '../capabilities/procedure-compiler.js';
3
- import { JsonPathNode, ColumnNode, BitwiseExpressionNode } from '../../ast/expression.js';
4
- import { InsertQueryNode, TableNode } from '../../ast/query.js';
5
- import { SqlDialectBase } from '../base/sql-dialect.js';
12
+ import { composeSqlDialect } from '../base/sql-dialect-composer.js';
6
13
  import { PostgresFunctionStrategy } from './functions.js';
7
14
  import { PostgresTableFunctionStrategy } from './table-functions.js';
8
- import { ProcedureCallNode } from '../../ast/procedure.js';
15
+ import { PostgresProcedureCompiler } from './procedure-compiler.js';
16
+ import { PostgresReturningStrategy } from './returning.js';
17
+ import { PostgresUpsertStrategy } from './upsert.js';
18
+
19
+ const quoteIdentifier = (id: string): string => `"${id}"`;
20
+
21
+ export type PostgresDialectImplementation = Dialect & ProcedureCompiler;
22
+
23
+ /** Creates the PostgreSQL dialect entirely from composable compiler components. */
24
+ export const createPostgresDialect = (): PostgresDialectImplementation => {
25
+ const composition = composeSqlDialect({
26
+ name: 'postgres',
27
+ quoteIdentifier,
28
+ formatPlaceholder: index => `$${index}`,
29
+ functionStrategy: new PostgresFunctionStrategy(),
30
+ tableFunctionStrategy: new PostgresTableFunctionStrategy(),
31
+ returningStrategy: new PostgresReturningStrategy(),
32
+ upsertStrategy: new PostgresUpsertStrategy(),
33
+ supportsDmlReturning: true,
34
+ compileSetTarget: (column: ColumnNode, _table: TableNode) => {
35
+ void _table;
36
+ return quoteIdentifier(column.name);
37
+ },
38
+ compileJsonPath(node: JsonPathNode): string {
39
+ const column = `${quoteIdentifier(node.column.table)}.${quoteIdentifier(node.column.name)}`;
40
+ return `${column}->>'${node.path}'`;
41
+ },
42
+ configureExpressions(api) {
43
+ api.registerExpressionCompiler('BitwiseExpression', (node: BitwiseExpressionNode, ctx) => {
44
+ const left = api.compileOperand(node.left, ctx);
45
+ const right = api.compileOperand(node.right, ctx);
46
+ const operator = node.operator === '^' ? '#' : node.operator;
47
+ return `${left} ${operator} ${right}`;
48
+ });
49
+ api.registerOperandCompiler('BitwiseExpression', (node: BitwiseExpressionNode, ctx) => {
50
+ const left = api.compileOperand(node.left, ctx);
51
+ const right = api.compileOperand(node.right, ctx);
52
+ const operator = node.operator === '^' ? '#' : node.operator;
53
+ return `(${left} ${operator} ${right})`;
54
+ });
55
+ }
56
+ });
9
57
 
10
- /**
11
- * PostgreSQL dialect implementation
12
- */
13
- export class PostgresDialect extends SqlDialectBase implements ProcedureCompiler {
14
- protected readonly dialect = 'postgres';
15
- /**
16
- * Creates a new PostgresDialect instance
17
- */
18
- public constructor() {
19
- super(new PostgresFunctionStrategy(), new PostgresTableFunctionStrategy());
20
- this.registerExpressionCompiler('BitwiseExpression', (node: BitwiseExpressionNode, ctx) => {
21
- const left = this.compileOperand(node.left, ctx);
22
- const right = this.compileOperand(node.right, ctx);
23
- const op = node.operator === '^' ? '#' : node.operator;
24
- return `${left} ${op} ${right}`;
25
- });
26
- this.registerOperandCompiler('BitwiseExpression', (node: BitwiseExpressionNode, ctx) => {
27
- const left = this.compileOperand(node.left, ctx);
28
- const right = this.compileOperand(node.right, ctx);
29
- const op = node.operator === '^' ? '#' : node.operator;
30
- return `(${left} ${op} ${right})`;
31
- });
32
- }
58
+ const procedures = new PostgresProcedureCompiler(composition.runtime);
59
+ return {
60
+ ...composition.dialect,
61
+ compileProcedureCall: ast => procedures.compileProcedureCall(ast)
62
+ };
63
+ };
64
+
65
+ /** Ergonomic constructor facade over the composed PostgreSQL dialect. */
66
+ export class PostgresDialect implements Dialect, ProcedureCompiler {
67
+ private readonly impl: PostgresDialectImplementation = createPostgresDialect();
33
68
 
34
- /**
35
- * Quotes an identifier using PostgreSQL double-quote syntax
36
- * @param id - Identifier to quote
37
- * @returns Quoted identifier
38
- */
39
69
  quoteIdentifier(id: string): string {
40
- return `"${id}"`;
70
+ return this.impl.quoteIdentifier(id);
41
71
  }
42
72
 
43
- protected formatPlaceholder(index: number): string {
44
- return `$${index}`;
73
+ supportsDmlReturningClause(): boolean {
74
+ return this.impl.supportsDmlReturningClause();
45
75
  }
46
76
 
47
- /**
48
- * Compiles JSON path expression using PostgreSQL syntax
49
- * @param node - JSON path node
50
- * @returns PostgreSQL JSON path expression
51
- */
52
- protected compileJsonPath(node: JsonPathNode): string {
53
- const col = `${this.quoteIdentifier(node.column.table)}.${this.quoteIdentifier(node.column.name)}`;
54
- // Postgres uses col->>'path' for text extraction
55
- return `${col}->>'${node.path}'`;
77
+ compileSelect(ast: SelectQueryNode): CompiledQuery {
78
+ return this.impl.compileSelect(ast);
56
79
  }
57
80
 
58
- protected compileReturning(returning: ColumnNode[] | undefined, ctx: CompilerContext): string {
59
- void ctx;
60
- if (!returning || returning.length === 0) return '';
61
- const columns = this.formatReturningColumns(returning);
62
- return ` RETURNING ${columns}`;
81
+ compileInsert(ast: InsertQueryNode): CompiledQuery {
82
+ return this.impl.compileInsert(ast);
63
83
  }
64
84
 
65
- protected compileUpsertClause(ast: InsertQueryNode, ctx: CompilerContext): string {
66
- if (!ast.onConflict) return '';
67
-
68
- const clause = ast.onConflict;
69
- const target = clause.target.constraint
70
- ? ` ON CONFLICT ON CONSTRAINT ${this.quoteIdentifier(clause.target.constraint)}`
71
- : (() => {
72
- this.ensureConflictColumns(
73
- clause,
74
- 'PostgreSQL ON CONFLICT requires conflict columns or a constraint name.'
75
- );
76
- const cols = clause.target.columns.map(col => this.quoteIdentifier(col.name)).join(', ');
77
- return ` ON CONFLICT (${cols})`;
78
- })();
79
-
80
- if (clause.action.type === 'DoNothing') {
81
- return `${target} DO NOTHING`;
82
- }
83
-
84
- if (!clause.action.set.length) {
85
- throw new Error('PostgreSQL ON CONFLICT DO UPDATE requires at least one assignment.');
86
- }
87
-
88
- const assignments = this.compileUpdateAssignments(clause.action.set, ast.into, ctx);
89
- const where = clause.action.where
90
- ? ` WHERE ${this.compileExpression(clause.action.where, ctx)}`
91
- : '';
92
- return `${target} DO UPDATE SET ${assignments}${where}`;
85
+ compileUpdate(ast: UpdateQueryNode): CompiledQuery {
86
+ return this.impl.compileUpdate(ast);
93
87
  }
94
88
 
95
- supportsDmlReturningClause(): boolean {
96
- return true;
89
+ compileDelete(ast: DeleteQueryNode): CompiledQuery {
90
+ return this.impl.compileDelete(ast);
97
91
  }
98
92
 
99
93
  compileProcedureCall(ast: ProcedureCallNode): CompiledProcedureCall {
100
- const ctx = this.createCompilerContext();
101
- const qualifiedName = ast.ref.schema
102
- ? `${this.quoteIdentifier(ast.ref.schema)}.${this.quoteIdentifier(ast.ref.name)}`
103
- : this.quoteIdentifier(ast.ref.name);
104
-
105
- const args: string[] = [];
106
- for (const param of ast.params) {
107
- if (param.direction === 'out') continue;
108
- if (!param.value) {
109
- throw new Error(`Procedure parameter "${param.name}" requires a value for direction "${param.direction}".`);
110
- }
111
- args.push(this.compileOperand(param.value, ctx));
112
- }
113
-
114
- const outNames = ast.params
115
- .filter(param => param.direction === 'out' || param.direction === 'inout')
116
- .map(param => param.name);
117
-
118
- const rawSql = `CALL ${qualifiedName}(${args.join(', ')})`;
119
- return {
120
- sql: `${rawSql};`,
121
- params: [...ctx.params],
122
- outParams: {
123
- source: outNames.length ? 'firstResultSet' : 'none',
124
- names: outNames
125
- }
126
- };
127
- }
128
-
129
- /**
130
- * PostgreSQL requires unqualified column names in SET clause
131
- */
132
- protected compileSetTarget(column: ColumnNode, _table: TableNode): string {
133
- return this.quoteIdentifier(column.name);
94
+ return this.impl.compileProcedureCall(ast);
134
95
  }
135
96
  }
@@ -0,0 +1,41 @@
1
+ import type { ProcedureCallNode } from '../../ast/procedure.js';
2
+ import type {
3
+ CompiledProcedureCall,
4
+ ProcedureCompiler,
5
+ ProcedureCompilerServices
6
+ } from '../capabilities/procedure-compiler.js';
7
+
8
+ export class PostgresProcedureCompiler implements ProcedureCompiler {
9
+ constructor(private readonly services: ProcedureCompilerServices) {}
10
+
11
+ compileProcedureCall(ast: ProcedureCallNode): CompiledProcedureCall {
12
+ const ctx = this.services.createCompilerContext();
13
+ const qualifiedName = ast.ref.schema
14
+ ? `${this.services.quoteIdentifier(ast.ref.schema)}.${this.services.quoteIdentifier(ast.ref.name)}`
15
+ : this.services.quoteIdentifier(ast.ref.name);
16
+
17
+ const args: string[] = [];
18
+ for (const param of ast.params) {
19
+ if (param.direction === 'out') continue;
20
+ if (!param.value) {
21
+ throw new Error(
22
+ `Procedure parameter "${param.name}" requires a value for direction "${param.direction}".`
23
+ );
24
+ }
25
+ args.push(this.services.compileOperand(param.value, ctx));
26
+ }
27
+
28
+ const outNames = ast.params
29
+ .filter(param => param.direction === 'out' || param.direction === 'inout')
30
+ .map(param => param.name);
31
+
32
+ return {
33
+ sql: `CALL ${qualifiedName}(${args.join(', ')});`,
34
+ params: [...ctx.params],
35
+ outParams: {
36
+ source: outNames.length ? 'firstResultSet' : 'none',
37
+ names: outNames
38
+ }
39
+ };
40
+ }
41
+ }
@@ -0,0 +1,4 @@
1
+ import { StandardReturningStrategy } from '../base/returning-strategy.js';
2
+
3
+ /** PostgreSQL uses standard SQL RETURNING with qualified columns. */
4
+ export class PostgresReturningStrategy extends StandardReturningStrategy {}
@@ -0,0 +1,43 @@
1
+ import type { CompilerContext } from '../abstract.js';
2
+ import type { InsertQueryNode } from '../../ast/query.js';
3
+ import type {
4
+ UpsertCompilationServices,
5
+ UpsertStrategy
6
+ } from '../base/upsert-strategy.js';
7
+
8
+ export class PostgresUpsertStrategy implements UpsertStrategy {
9
+ compile(
10
+ ast: InsertQueryNode,
11
+ ctx: CompilerContext,
12
+ services: UpsertCompilationServices
13
+ ): string {
14
+ if (!ast.onConflict) return '';
15
+
16
+ const clause = ast.onConflict;
17
+ const target = clause.target.constraint
18
+ ? ` ON CONFLICT ON CONSTRAINT ${services.quoteIdentifier(clause.target.constraint)}`
19
+ : (() => {
20
+ if (!clause.target.columns.length) {
21
+ throw new Error('PostgreSQL ON CONFLICT requires conflict columns or a constraint name.');
22
+ }
23
+ const columns = clause.target.columns
24
+ .map(column => services.quoteIdentifier(column.name))
25
+ .join(', ');
26
+ return ` ON CONFLICT (${columns})`;
27
+ })();
28
+
29
+ if (clause.action.type === 'DoNothing') {
30
+ return `${target} DO NOTHING`;
31
+ }
32
+
33
+ if (!clause.action.set.length) {
34
+ throw new Error('PostgreSQL ON CONFLICT DO UPDATE requires at least one assignment.');
35
+ }
36
+
37
+ const assignments = services.compileUpdateAssignments(clause.action.set, ast.into, ctx);
38
+ const where = clause.action.where
39
+ ? ` WHERE ${services.compileExpression(clause.action.where, ctx)}`
40
+ : '';
41
+ return `${target} DO UPDATE SET ${assignments}${where}`;
42
+ }
43
+ }
@@ -1,106 +1,81 @@
1
- import { CompilerContext } from '../abstract.js';
2
- import { JsonPathNode, ColumnNode, BitwiseExpressionNode } from '../../ast/expression.js';
3
- import { InsertQueryNode, TableNode } from '../../ast/query.js';
4
- import { SqlDialectBase } from '../base/sql-dialect.js';
1
+ import type { BitwiseExpressionNode, ColumnNode, JsonPathNode } from '../../ast/expression.js';
2
+ import type {
3
+ DeleteQueryNode,
4
+ InsertQueryNode,
5
+ SelectQueryNode,
6
+ TableNode,
7
+ UpdateQueryNode
8
+ } from '../../ast/query.js';
9
+ import type { CompiledQuery, Dialect } from '../abstract.js';
10
+ import { composeSqlDialect } from '../base/sql-dialect-composer.js';
5
11
  import { SqliteFunctionStrategy } from './functions.js';
12
+ import { SqliteReturningStrategy } from './returning.js';
13
+ import { SqliteUpsertStrategy } from './upsert.js';
6
14
 
7
- /**
8
- * SQLite dialect implementation
9
- */
10
- export class SqliteDialect extends SqlDialectBase {
11
- protected readonly dialect = 'sqlite';
12
- /**
13
- * Creates a new SqliteDialect instance
14
- */
15
- public constructor() {
16
- super(new SqliteFunctionStrategy());
17
- this.registerExpressionCompiler('BitwiseExpression', (node: BitwiseExpressionNode, ctx) => {
18
- const left = this.compileOperand(node.left, ctx);
19
- const right = this.compileOperand(node.right, ctx);
20
- if (node.operator === '^') {
21
- return `(${left} | ${right}) & ~(${left} & ${right})`;
22
- }
23
- return `${left} ${node.operator} ${right}`;
24
- });
25
- this.registerOperandCompiler('BitwiseExpression', (node: BitwiseExpressionNode, ctx) => {
26
- const left = this.compileOperand(node.left, ctx);
27
- const right = this.compileOperand(node.right, ctx);
28
- if (node.operator === '^') {
29
- return `((${left} | ${right}) & ~(${left} & ${right}))`;
30
- }
31
- return `(${left} ${node.operator} ${right})`;
32
- });
33
- }
15
+ const quoteIdentifier = (id: string): string => `"${id}"`;
34
16
 
35
- /**
36
- * Quotes an identifier using SQLite double-quote syntax
37
- * @param id - Identifier to quote
38
- * @returns Quoted identifier
39
- */
40
- quoteIdentifier(id: string): string {
41
- return `"${id}"`;
42
- }
17
+ /** Creates the SQLite dialect entirely from composable compiler components. */
18
+ export const createSqliteDialect = (): Dialect =>
19
+ composeSqlDialect({
20
+ name: 'sqlite',
21
+ quoteIdentifier,
22
+ functionStrategy: new SqliteFunctionStrategy(),
23
+ returningStrategy: new SqliteReturningStrategy(),
24
+ upsertStrategy: new SqliteUpsertStrategy(),
25
+ supportsDmlReturning: true,
26
+ compileSetTarget: (column: ColumnNode, _table: TableNode) => {
27
+ void _table;
28
+ return quoteIdentifier(column.name);
29
+ },
30
+ compileJsonPath(node: JsonPathNode): string {
31
+ const column = `${quoteIdentifier(node.column.table)}.${quoteIdentifier(node.column.name)}`;
32
+ return `json_extract(${column}, '${node.path}')`;
33
+ },
34
+ configureExpressions(api) {
35
+ api.registerExpressionCompiler('BitwiseExpression', (node: BitwiseExpressionNode, ctx) => {
36
+ const left = api.compileOperand(node.left, ctx);
37
+ const right = api.compileOperand(node.right, ctx);
38
+ if (node.operator === '^') {
39
+ return `(${left} | ${right}) & ~(${left} & ${right})`;
40
+ }
41
+ return `${left} ${node.operator} ${right}`;
42
+ });
43
+ api.registerOperandCompiler('BitwiseExpression', (node: BitwiseExpressionNode, ctx) => {
44
+ const left = api.compileOperand(node.left, ctx);
45
+ const right = api.compileOperand(node.right, ctx);
46
+ if (node.operator === '^') {
47
+ return `((${left} | ${right}) & ~(${left} & ${right}))`;
48
+ }
49
+ return `(${left} ${node.operator} ${right})`;
50
+ });
51
+ }
52
+ }).dialect;
43
53
 
44
- /**
45
- * Compiles JSON path expression using SQLite syntax
46
- * @param node - JSON path node
47
- * @returns SQLite JSON path expression
48
- */
49
- protected compileJsonPath(node: JsonPathNode): string {
50
- const col = `${this.quoteIdentifier(node.column.table)}.${this.quoteIdentifier(node.column.name)}`;
51
- // SQLite uses json_extract(col, '$.path')
52
- return `json_extract(${col}, '${node.path}')`;
53
- }
54
+ /** Ergonomic constructor facade over the composed SQLite dialect. */
55
+ export class SqliteDialect implements Dialect {
56
+ private readonly impl: Dialect = createSqliteDialect();
54
57
 
55
- protected compileQualifiedColumn(column: ColumnNode, _table: TableNode): string {
56
- void _table;
57
- return this.quoteIdentifier(column.name);
58
+ quoteIdentifier(id: string): string {
59
+ return this.impl.quoteIdentifier(id);
58
60
  }
59
61
 
60
- protected compileReturning(returning: ColumnNode[] | undefined, ctx: CompilerContext): string {
61
- void ctx;
62
- if (!returning || returning.length === 0) return '';
63
- const columns = this.formatReturningColumns(returning);
64
- return ` RETURNING ${columns}`;
62
+ supportsDmlReturningClause(): boolean {
63
+ return this.impl.supportsDmlReturningClause();
65
64
  }
66
65
 
67
- protected formatReturningColumns(returning: ColumnNode[]): string {
68
- return returning
69
- .map(column => {
70
- const alias = column.alias ? ` AS ${this.quoteIdentifier(column.alias)}` : '';
71
- return `${this.quoteIdentifier(column.name)}${alias}`;
72
- })
73
- .join(', ');
66
+ compileSelect(ast: SelectQueryNode): CompiledQuery {
67
+ return this.impl.compileSelect(ast);
74
68
  }
75
69
 
76
- protected compileUpsertClause(ast: InsertQueryNode, ctx: CompilerContext): string {
77
- if (!ast.onConflict) return '';
78
-
79
- const clause = ast.onConflict;
80
- if (clause.target.constraint) {
81
- throw new Error('SQLite ON CONFLICT does not support named constraints.');
82
- }
83
- this.ensureConflictColumns(clause, 'SQLite ON CONFLICT requires conflict columns.');
84
-
85
- const cols = clause.target.columns.map(col => this.quoteIdentifier(col.name)).join(', ');
86
- const target = ` ON CONFLICT (${cols})`;
87
-
88
- if (clause.action.type === 'DoNothing') {
89
- return `${target} DO NOTHING`;
90
- }
91
-
92
- if (!clause.action.set.length) {
93
- throw new Error('SQLite ON CONFLICT DO UPDATE requires at least one assignment.');
94
- }
70
+ compileInsert(ast: InsertQueryNode): CompiledQuery {
71
+ return this.impl.compileInsert(ast);
72
+ }
95
73
 
96
- const assignments = this.compileUpdateAssignments(clause.action.set, ast.into, ctx);
97
- const where = clause.action.where
98
- ? ` WHERE ${this.compileExpression(clause.action.where, ctx)}`
99
- : '';
100
- return `${target} DO UPDATE SET ${assignments}${where}`;
74
+ compileUpdate(ast: UpdateQueryNode): CompiledQuery {
75
+ return this.impl.compileUpdate(ast);
101
76
  }
102
77
 
103
- supportsDmlReturningClause(): boolean {
104
- return true;
78
+ compileDelete(ast: DeleteQueryNode): CompiledQuery {
79
+ return this.impl.compileDelete(ast);
105
80
  }
106
81
  }
@@ -0,0 +1,30 @@
1
+ import type { ColumnNode } from '../../ast/expression.js';
2
+ import type { CompilerContext } from '../abstract.js';
3
+ import type {
4
+ QuoteIdentifier,
5
+ ReturningStrategy
6
+ } from '../base/returning-strategy.js';
7
+
8
+ export class SqliteReturningStrategy implements ReturningStrategy {
9
+ compileReturning(
10
+ returning: ColumnNode[] | undefined,
11
+ _ctx: CompilerContext,
12
+ quoteIdentifier: QuoteIdentifier
13
+ ): string {
14
+ void _ctx;
15
+ if (!returning || returning.length === 0) return '';
16
+ return ` RETURNING ${this.formatReturningColumns(returning, quoteIdentifier)}`;
17
+ }
18
+
19
+ formatReturningColumns(
20
+ returning: ColumnNode[],
21
+ quoteIdentifier: QuoteIdentifier
22
+ ): string {
23
+ return returning
24
+ .map(column => {
25
+ const alias = column.alias ? ` AS ${quoteIdentifier(column.alias)}` : '';
26
+ return `${quoteIdentifier(column.name)}${alias}`;
27
+ })
28
+ .join(', ');
29
+ }
30
+ }
@@ -0,0 +1,43 @@
1
+ import type { CompilerContext } from '../abstract.js';
2
+ import type { InsertQueryNode } from '../../ast/query.js';
3
+ import type {
4
+ UpsertCompilationServices,
5
+ UpsertStrategy
6
+ } from '../base/upsert-strategy.js';
7
+
8
+ export class SqliteUpsertStrategy implements UpsertStrategy {
9
+ compile(
10
+ ast: InsertQueryNode,
11
+ ctx: CompilerContext,
12
+ services: UpsertCompilationServices
13
+ ): string {
14
+ if (!ast.onConflict) return '';
15
+
16
+ const clause = ast.onConflict;
17
+ if (clause.target.constraint) {
18
+ throw new Error('SQLite ON CONFLICT does not support named constraints.');
19
+ }
20
+ if (!clause.target.columns.length) {
21
+ throw new Error('SQLite ON CONFLICT requires conflict columns.');
22
+ }
23
+
24
+ const columns = clause.target.columns
25
+ .map(column => services.quoteIdentifier(column.name))
26
+ .join(', ');
27
+ const target = ` ON CONFLICT (${columns})`;
28
+
29
+ if (clause.action.type === 'DoNothing') {
30
+ return `${target} DO NOTHING`;
31
+ }
32
+
33
+ if (!clause.action.set.length) {
34
+ throw new Error('SQLite ON CONFLICT DO UPDATE requires at least one assignment.');
35
+ }
36
+
37
+ const assignments = services.compileUpdateAssignments(clause.action.set, ast.into, ctx);
38
+ const where = clause.action.where
39
+ ? ` WHERE ${services.compileExpression(clause.action.where, ctx)}`
40
+ : '';
41
+ return `${target} DO UPDATE SET ${assignments}${where}`;
42
+ }
43
+ }
package/src/index.ts CHANGED
@@ -20,16 +20,37 @@ export * from './core/hydration/types.js';
20
20
  export * from './core/dialect/abstract.js';
21
21
  export * from './core/dialect/dialect-factory.js';
22
22
  export * from './core/dialect/capabilities/procedure-compiler.js';
23
+ export * from './core/dialect/base/sql-dialect-composer.js';
24
+ export * from './core/dialect/base/sql-compiler-set.js';
25
+ export * from './core/dialect/base/upsert-strategy.js';
26
+ export * from './core/dialect/base/returning-strategy.js';
27
+ export * from './core/dialect/base/pagination-strategy.js';
23
28
  export * from './core/dialect/base/standard-sql-services.js';
24
29
  export * from './core/dialect/base/standard-sql-source-compiler.js';
25
30
  export * from './core/dialect/base/standard-select-compiler.js';
26
31
  export * from './core/dialect/base/standard-insert-compiler.js';
27
32
  export * from './core/dialect/base/standard-update-compiler.js';
28
33
  export * from './core/dialect/base/standard-delete-compiler.js';
34
+ export * from './core/functions/table-types.js';
35
+ export * from './core/functions/standard-table-strategy.js';
29
36
  export * from './core/dialect/mysql/index.js';
37
+ export * from './core/dialect/mysql/upsert.js';
38
+ export * from './core/dialect/mysql/procedure-compiler.js';
30
39
  export * from './core/dialect/mssql/index.js';
40
+ export * from './core/dialect/mssql/compiler-factory.js';
41
+ export * from './core/dialect/mssql/select-compiler.js';
42
+ export * from './core/dialect/mssql/insert-compiler.js';
43
+ export * from './core/dialect/mssql/update-compiler.js';
44
+ export * from './core/dialect/mssql/delete-compiler.js';
45
+ export * from './core/dialect/mssql/output.js';
46
+ export * from './core/dialect/mssql/procedure-compiler.js';
31
47
  export * from './core/dialect/sqlite/index.js';
48
+ export * from './core/dialect/sqlite/upsert.js';
49
+ export * from './core/dialect/sqlite/returning.js';
32
50
  export * from './core/dialect/postgres/index.js';
51
+ export * from './core/dialect/postgres/upsert.js';
52
+ export * from './core/dialect/postgres/returning.js';
53
+ export * from './core/dialect/postgres/procedure-compiler.js';
33
54
  export * from './core/ddl/schema-generator.js';
34
55
  export * from './core/ddl/schema-types.js';
35
56
  export * from './core/ddl/schema-diff.js';
@@ -71,7 +92,7 @@ export * from './orm/jsonify.js';
71
92
  export * from './orm/save-graph-types.js';
72
93
  export * from './decorators/index.js';
73
94
 
74
- // NEW: execution abstraction + helpers
95
+ // Execution abstraction + helpers
75
96
  export * from './core/execution/db-executor.js';
76
97
  export * from './core/execution/pooling/pool-types.js';
77
98
  export * from './core/execution/pooling/pool.js';
@@ -81,17 +102,8 @@ export * from './core/execution/executors/sqlite-executor.js';
81
102
  export * from './core/execution/executors/better-sqlite3-executor.js';
82
103
  export * from './core/execution/executors/mssql-executor.js';
83
104
 
84
- // NEW: first-class pooling integration
85
105
  export * from './orm/pooled-executor-factory.js';
86
-
87
- // DTO module for REST API integration
88
106
  export * from './dto/index.js';
89
-
90
- // Tree behavior (Nested Set / MPTT)
91
107
  export * from './tree/index.js';
92
-
93
- // Cache module
94
108
  export * from './cache/index.js';
95
-
96
- // Bulk operations module
97
109
  export * from './bulk/index.js';