@dbsp/core 1.1.0 → 1.2.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.
- package/dist/index.d.ts +12 -17
- package/dist/index.js +300 -149
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _dbsp_types from '@dbsp/types';
|
|
2
|
-
import { PseudoColumnMetadata, RecursiveMetadata, RelationIR, RelationKind, AdapterCapabilities, Adapter, BaseAdapter, DDLGeneratingAdapter, ExecutingAdapter, IntrospectingAdapter, RawSqlAdapter, StreamingAdapter, TransactionalAdapter, ColumnType, WhereIntent, OnDeleteAction, ModelIR, DbCasing, QueryIntent, PlanOptions, PlanReport, RecursiveIntent, RecursivePlanOptions, RecursivePlanReport, TableIR, EnumIR, SequenceIR, AmbiguityCheckResult, DialectCapabilities, DDLFeature, DDLFeatureVersionRange, ComparisonOperator, WhereSubqueryIntent, SubqueryRefIntent, WhereAndIntent, WhereAnyIntent, WhereComparisonIntent, WhereRelationFilterIntent, RecursiveExistsOptions, WhereExistsIntent, WhereInIntent, WhereNullIntent, WhereLikeIntent, WhereNotIntent, WhereNotExistsIntent, WhereOrIntent, WhereRawExistsIntent, WhereRawNotExistsIntent, SelectIntent, IncludeIntent, AggregateIntent, OrderByIntent, SortDirection, InsertIntent, UpdateIntent, BatchUpdateIntent, DeleteIntent, UpsertIntent, Dump, SetOperationIntent, LockStrength, LockWaitPolicy, DumpMeta, JoinIntent, UnnestCteIntent, CteQueryIntent, CompileOptions, CompiledQuery, UpsertConflictTarget, UpsertConflictAction, RawCteIntent, TruncateOptions, VacuumOptions, AlterColumnOptions, CreateIndexOptions, DropIndexOptions, IndexInfo, ExpressionIntent, WhereExpressionIntent, AggOrderByArg, RelationType as RelationType$1, Cardinality, FeatureWarning, UnsupportedFeatureBehavior, FeatureBehaviorConfig, RangeValue, WhereRangeIntent, SubqueryIncludeInfo } from '@dbsp/types';
|
|
2
|
+
import { PseudoColumnMetadata, RecursiveMetadata, RelationIR, RelationKind, AdapterCapabilities, Adapter, BaseAdapter, DDLGeneratingAdapter, ExecutingAdapter, IntrospectingAdapter, RawSqlAdapter, StreamingAdapter, TransactionalAdapter, ColumnType, WhereIntent, OnDeleteAction, ModelIR, DbCasing, QueryIntent, PlanOptions, PlanReport, RecursiveIntent, RecursivePlanOptions, RecursivePlanReport, TableIR, EnumIR, SequenceIR, AmbiguityCheckResult, DialectCapabilities, DDLFeature, DDLFeatureVersionRange, ComparisonOperator, WhereSubqueryIntent, SubqueryRefIntent, WhereAndIntent, WhereAnyIntent, WhereComparisonIntent, WhereRelationFilterIntent, RecursiveExistsOptions, WhereExistsIntent, WhereInIntent, WhereNullIntent, WhereLikeIntent, WhereNotIntent, WhereNotExistsIntent, WhereOrIntent, WhereRawExistsIntent, WhereRawNotExistsIntent, SelectIntent, IncludeIntent, AggregateIntent, OrderByIntent, SortDirection, InsertIntent, InsertFromIntent, UpdateIntent, BatchUpdateIntent, DeleteIntent, UpsertIntent, UpsertFromIntent, Dump, SetOperationIntent, LockStrength, LockWaitPolicy, DumpMeta, JoinIntent, UnnestCteIntent, CteQueryIntent, CompileOptions, CompiledQuery, MutationIntent as MutationIntent$1, UpsertConflictTarget, UpsertConflictAction, RawCteIntent, TruncateOptions, VacuumOptions, AlterColumnOptions, CreateIndexOptions, DropIndexOptions, IndexInfo, ExpressionIntent, WhereExpressionIntent, AggOrderByArg, RelationType as RelationType$1, Cardinality, FeatureWarning, UnsupportedFeatureBehavior, FeatureBehaviorConfig, RangeValue, WhereRangeIntent, SubqueryIncludeInfo } from '@dbsp/types';
|
|
3
3
|
export { Adapter, AdapterCapabilities, AdapterLogger, AdapterStreamOptions, AdjacencyTraversal, AggregateExpressionIntent, AggregateFunction, AggregateIntent, AggregateWindowFunction, AliasIncludedColumnsMode, AlterColumnOptions, AmbiguityCheckResult, ArrayOperator, BaseAdapter, CTEDefinition, Cardinality, CaseExpressionIntent, CoalesceExpressionIntent, ColumnAliasIntent, ColumnExpressionIntent, ColumnIR, ColumnType, CommonColumnType, ComparisonExpressionIntent, ComparisonOperator, CompileOnlyAdapter, CompileOptions, CompileResultWithIncludes, CompiledQuery, CompilingAdapter, CreateIndexOptions, CustomTraversal, DDLGeneratingAdapter, DbCasing, DecisionType, DeleteIntent, DialectCapabilities, DialectName, DropIndexOptions, DuckDBColumnType, Dump, DumpMeta, EdgeTableTraversal, EmitJoinClause, ExecutingAdapter, ExpressionIntent, FilterStrategy, ForeignKeyIR, IncludeIntent, IncludeStrategy, IndexColumnDef, IndexIR, IndexInfo, IndexMethod, InsertFromIntent, InsertIntent, IntrospectingAdapter, IsTypeSupported, JoinDefault, JoinIntent, LiteralExpressionIntent, LogicalOperator, MSSQLColumnType, ModelIR, MutationIntent, MySQLColumnType, NullOperator, NullsPosition, OffsetWindowFunction, OnDeleteAction, Optionality, OrderByIntent, PartitionIR, PlanDecision, PlanOptions, PlanReport, PlanWarning, PlanWarningCode, PostgresColumnType, PostgresOnlyColumnType, PseudoColumnExpressionIntent, PseudoColumnMetadata, PseudoColumnTraversal, QueryIntent, RangeOperator, RangeValue, RankingWindowFunction, RawExpressionIntent, RawSqlAdapter, RecursiveAdvancedOptions, RecursiveDedupe, RecursiveDirection, RecursiveEmitOptions, RecursiveExistsOptions, RecursiveIntent, RecursiveMetadata, RecursiveNodeIdExpr, RecursivePlanOptions, RecursivePlanReport, RecursiveTrackOptions, RecursiveTraversal, RelationColumnIntent, RelationIR, RelationKind, RelationOperator, RelationType, ResolvedIncludeStrategy, SQLiteColumnType, ScalarSubqueryIntent, SelectAggregateIntent, SelectAllIntent, SelectFieldsIntent, SelectIntent, SelectWithExpressionsIntent, SortDirection, StreamingAdapter, StringOperator, SubqueryIncludeInfo, SubqueryRefIntent, SupportedColumnTypes, TableIR, TransactionalAdapter, TruncateOptions, UpdateIntent, UpsertConflictAction, UpsertConflictTarget, UpsertFromIntent, UpsertIntent, VacuumOptions, WhereAndIntent, WhereAnyIntent, WhereComparisonIntent, WhereExistsIntent, WhereInIntent, WhereIntent, WhereLikeIntent, WhereNotExistsIntent, WhereNotIntent, WhereNullIntent, WhereOrIntent, WhereRangeIntent, WhereRelationFilterIntent, WhereSubqueryIntent, WindowFunction, WindowIntent, WindowOrderBy, getNodeIdAlias, isAdjacencyTraversal, isAggregateWindowFunction, isCoalesceExpression, isColumnAliasExpression, isCustomTraversal, isDeleteIntent, isEdgeTableTraversal, isInsertIntent, isMutationIntent, isRankingWindowFunction, isRawExpression, isRecursiveIntent, isRelationColumnExpression, isSelectAggregate, isSelectAll, isSelectFields, isSelectWithExpressions, isSubqueryRef, isUpdateIntent, isUpsertIntent, isWhereAnd, isWhereAny, isWhereComparison, isWhereExists, isWhereIn, isWhereLike, isWhereLogical, isWhereNot, isWhereNotExists, isWhereNull, isWhereOr, isWhereRange, isWhereRelationBased, isWhereRelationFilter, isWhereSubquery, isWindowIntent } from '@dbsp/types';
|
|
4
4
|
import { NqlCompilerOptions } from '@dbsp/nql';
|
|
5
5
|
import * as v from 'valibot';
|
|
@@ -3153,9 +3153,9 @@ type QueryHookContext = {
|
|
|
3153
3153
|
};
|
|
3154
3154
|
/** Union of all mutation intent types */
|
|
3155
3155
|
/** Union of all mutation intent types */
|
|
3156
|
-
type MutationIntent = InsertIntent | UpdateIntent | BatchUpdateIntent | DeleteIntent | UpsertIntent;
|
|
3156
|
+
type MutationIntent = InsertIntent | InsertFromIntent | UpdateIntent | BatchUpdateIntent | DeleteIntent | UpsertIntent | UpsertFromIntent;
|
|
3157
3157
|
/** Mutation operation types */
|
|
3158
|
-
type MutationOperation = 'insert' | 'update' | 'batchUpdate' | 'delete' | 'upsert';
|
|
3158
|
+
type MutationOperation = 'insert' | 'insert_from' | 'update' | 'batchUpdate' | 'delete' | 'upsert' | 'upsert_from';
|
|
3159
3159
|
/**
|
|
3160
3160
|
* Context passed to mutation hooks (beforeMutation/afterMutation).
|
|
3161
3161
|
* Frozen via Object.freeze — hooks must return new objects to modify.
|
|
@@ -4635,12 +4635,9 @@ interface MutationDump {
|
|
|
4635
4635
|
/** Bound parameter values */
|
|
4636
4636
|
readonly parameters: readonly unknown[];
|
|
4637
4637
|
/** The mutation intent */
|
|
4638
|
-
readonly intent:
|
|
4638
|
+
readonly intent: MutationIntent$1;
|
|
4639
4639
|
/** Optional metadata */
|
|
4640
|
-
readonly meta?:
|
|
4641
|
-
readonly schema?: string;
|
|
4642
|
-
readonly compiledAt?: Date;
|
|
4643
|
-
};
|
|
4640
|
+
readonly meta?: DumpMeta;
|
|
4644
4641
|
}
|
|
4645
4642
|
/** Shared base options for all mutation builders */
|
|
4646
4643
|
type MutationBaseOpts = {
|
|
@@ -4684,11 +4681,7 @@ declare abstract class MutationBuilderBase<T, TIntent extends InsertIntent | Upd
|
|
|
4684
4681
|
protected requireAdapter(operation: string): Adapter;
|
|
4685
4682
|
dump(extraOptions?: CompileOptions): MutationDump;
|
|
4686
4683
|
execute(): Promise<T>;
|
|
4687
|
-
private
|
|
4688
|
-
private executeWithHooks;
|
|
4689
|
-
private executeWithHooksInner;
|
|
4690
|
-
/** Extract cardinality and data from mutation intent */
|
|
4691
|
-
private extractIntentData;
|
|
4684
|
+
private prepareMutationExecution;
|
|
4692
4685
|
}
|
|
4693
4686
|
/**
|
|
4694
4687
|
* Builder for INSERT operations.
|
|
@@ -4933,14 +4926,16 @@ declare class UpsertBuilder<T = void> extends MutationBuilderBase<T, UpsertInten
|
|
|
4933
4926
|
interface NqlBuilder<T> {
|
|
4934
4927
|
/** Execute query and return all results */
|
|
4935
4928
|
all(): Promise<T[]>;
|
|
4929
|
+
/** Execute query or mutation and discard any returned rows */
|
|
4930
|
+
run(): Promise<void>;
|
|
4936
4931
|
/** Execute query and return first result or null */
|
|
4937
4932
|
first(): Promise<T | null>;
|
|
4938
4933
|
/** Get the IntentIR for debugging */
|
|
4939
|
-
toIntentIR(): QueryIntent;
|
|
4934
|
+
toIntentIR(): QueryIntent | MutationIntent$1;
|
|
4940
4935
|
/** Get the execution plan */
|
|
4941
4936
|
plan(): PlanReport;
|
|
4942
|
-
/** Get full dump
|
|
4943
|
-
dump(meta?: DumpMetaInput): Dump;
|
|
4937
|
+
/** Get full dump. Mutations return MutationDump without a plan. */
|
|
4938
|
+
dump(meta?: DumpMetaInput): Dump | MutationDump;
|
|
4944
4939
|
}
|
|
4945
4940
|
/**
|
|
4946
4941
|
* NQL template tag function type.
|
|
@@ -4984,7 +4979,7 @@ declare function nqlRaw(fragment: string): NqlRawFragment;
|
|
|
4984
4979
|
* @param schemaName - Optional schema name for multi-tenant queries
|
|
4985
4980
|
* @returns NQL template tag function
|
|
4986
4981
|
*/
|
|
4987
|
-
declare function createNqlTag(schemaDefinition: unknown, model: ModelIR, adapter?: Adapter<unknown>, schemaName?: string): NqlTag;
|
|
4982
|
+
declare function createNqlTag(schemaDefinition: unknown, model: ModelIR, adapter?: Adapter<unknown>, schemaName?: string, hookStore?: HookStore, onHookError?: HookErrorHandler, inTransaction?: boolean): NqlTag;
|
|
4988
4983
|
/**
|
|
4989
4984
|
* Extract pseudo-column keywords from model configuration.
|
|
4990
4985
|
* Collects all configured roles and recursive keywords from all tables'
|
package/dist/index.js
CHANGED
|
@@ -5453,6 +5453,122 @@ var LightweightModelIR = class {
|
|
|
5453
5453
|
};
|
|
5454
5454
|
|
|
5455
5455
|
// src/dx/mutation-builders.ts
|
|
5456
|
+
function compileMutationIntent(adapter, intent, options) {
|
|
5457
|
+
switch (intent.type) {
|
|
5458
|
+
case "insert":
|
|
5459
|
+
return adapter.compileInsert(intent, options);
|
|
5460
|
+
case "insert_from":
|
|
5461
|
+
return adapter.compileInsertFrom(intent, options);
|
|
5462
|
+
case "update":
|
|
5463
|
+
return adapter.compileUpdate(intent, options);
|
|
5464
|
+
case "batchUpdate":
|
|
5465
|
+
return adapter.compileBatchUpdate(intent, options);
|
|
5466
|
+
case "delete":
|
|
5467
|
+
return adapter.compileDelete(intent, options);
|
|
5468
|
+
case "upsert":
|
|
5469
|
+
return adapter.compileUpsert(intent, options);
|
|
5470
|
+
case "upsert_from":
|
|
5471
|
+
return adapter.compileUpsertFrom(intent, options);
|
|
5472
|
+
}
|
|
5473
|
+
const _exhaustive = intent;
|
|
5474
|
+
throw new Error(
|
|
5475
|
+
`Unsupported mutation type: ${_exhaustive.type}`
|
|
5476
|
+
);
|
|
5477
|
+
}
|
|
5478
|
+
async function runMutationWithHooks(opts) {
|
|
5479
|
+
if (!opts.hookStore || !hasHooks(opts.hookStore)) {
|
|
5480
|
+
const prepared = opts.prepare(opts.intent);
|
|
5481
|
+
return prepared.execute();
|
|
5482
|
+
}
|
|
5483
|
+
return withReentrancyGuard(
|
|
5484
|
+
opts.hookStore,
|
|
5485
|
+
(store) => runMutationWithHooksInner(opts, store)
|
|
5486
|
+
);
|
|
5487
|
+
}
|
|
5488
|
+
async function runMutationWithHooksInner(opts, store) {
|
|
5489
|
+
const { intent } = opts;
|
|
5490
|
+
const operation = intent.type;
|
|
5491
|
+
const startTime = Date.now();
|
|
5492
|
+
const { cardinality, data } = extractMutationIntentData(intent);
|
|
5493
|
+
let ctx = Object.freeze({
|
|
5494
|
+
table: opts.table,
|
|
5495
|
+
operation,
|
|
5496
|
+
intent,
|
|
5497
|
+
cardinality,
|
|
5498
|
+
data,
|
|
5499
|
+
...opts.schemaName !== void 0 ? { schemaName: opts.schemaName } : {},
|
|
5500
|
+
...opts.inTransaction ? { inTransaction: true } : {}
|
|
5501
|
+
});
|
|
5502
|
+
try {
|
|
5503
|
+
if (store.beforeMutation.length > 0) {
|
|
5504
|
+
ctx = await runBeforeMutationHooks(
|
|
5505
|
+
store.beforeMutation,
|
|
5506
|
+
ctx,
|
|
5507
|
+
opts.onHookError
|
|
5508
|
+
);
|
|
5509
|
+
}
|
|
5510
|
+
const prepared = opts.prepare(intent);
|
|
5511
|
+
const duration = Date.now() - startTime;
|
|
5512
|
+
const result = await prepared.execute();
|
|
5513
|
+
if (store.afterMutation.length > 0) {
|
|
5514
|
+
const afterCtx = Object.freeze({
|
|
5515
|
+
...ctx,
|
|
5516
|
+
sql: prepared.sql,
|
|
5517
|
+
parameters: prepared.parameters,
|
|
5518
|
+
duration
|
|
5519
|
+
});
|
|
5520
|
+
const transformed = await runAfterMutationHooks(
|
|
5521
|
+
store.afterMutation,
|
|
5522
|
+
afterCtx,
|
|
5523
|
+
[...prepared.getAfterMutationResult?.(result) ?? []],
|
|
5524
|
+
opts.onHookError
|
|
5525
|
+
);
|
|
5526
|
+
if (prepared.returnAfterMutationResult) {
|
|
5527
|
+
return transformed;
|
|
5528
|
+
}
|
|
5529
|
+
}
|
|
5530
|
+
return result;
|
|
5531
|
+
} catch (error) {
|
|
5532
|
+
if (store.onError.length > 0) {
|
|
5533
|
+
const errorCtx = {
|
|
5534
|
+
table: opts.table,
|
|
5535
|
+
operation,
|
|
5536
|
+
error,
|
|
5537
|
+
intent,
|
|
5538
|
+
phase: "beforeMutation",
|
|
5539
|
+
...opts.schemaName !== void 0 ? { schemaName: opts.schemaName } : {}
|
|
5540
|
+
};
|
|
5541
|
+
const transformed = await runOnErrorHooks(store.onError, errorCtx);
|
|
5542
|
+
throw transformed;
|
|
5543
|
+
}
|
|
5544
|
+
throw error;
|
|
5545
|
+
}
|
|
5546
|
+
}
|
|
5547
|
+
function extractMutationIntentData(intent) {
|
|
5548
|
+
if (intent.type === "insert" || intent.type === "upsert") {
|
|
5549
|
+
const values = intent.values;
|
|
5550
|
+
return {
|
|
5551
|
+
cardinality: values.length > 1 ? "bulk" : "single",
|
|
5552
|
+
data: values.length > 1 ? values : values[0]
|
|
5553
|
+
};
|
|
5554
|
+
}
|
|
5555
|
+
if (intent.type === "update") {
|
|
5556
|
+
return {
|
|
5557
|
+
cardinality: "single",
|
|
5558
|
+
data: intent.set
|
|
5559
|
+
};
|
|
5560
|
+
}
|
|
5561
|
+
if (intent.type === "batchUpdate") {
|
|
5562
|
+
return {
|
|
5563
|
+
cardinality: "bulk",
|
|
5564
|
+
data: intent.updates
|
|
5565
|
+
};
|
|
5566
|
+
}
|
|
5567
|
+
if (intent.type === "insert_from" || intent.type === "upsert_from") {
|
|
5568
|
+
return { cardinality: "bulk", data: void 0 };
|
|
5569
|
+
}
|
|
5570
|
+
return { cardinality: "single", data: void 0 };
|
|
5571
|
+
}
|
|
5456
5572
|
var MutationBuilderBase = class {
|
|
5457
5573
|
table;
|
|
5458
5574
|
model;
|
|
@@ -5507,11 +5623,15 @@ var MutationBuilderBase = class {
|
|
|
5507
5623
|
Object.keys(compileOptions).length > 0 ? compileOptions : void 0
|
|
5508
5624
|
);
|
|
5509
5625
|
const meta = {
|
|
5510
|
-
compiledAt: /* @__PURE__ */ new Date()
|
|
5626
|
+
compiledAt: /* @__PURE__ */ new Date(),
|
|
5627
|
+
...this.schemaName !== void 0 && { schema: this.schemaName },
|
|
5628
|
+
...extraOptions?.queryName !== void 0 && {
|
|
5629
|
+
queryName: extraOptions.queryName
|
|
5630
|
+
},
|
|
5631
|
+
...extraOptions?.correlationId !== void 0 && {
|
|
5632
|
+
correlationId: extraOptions.correlationId
|
|
5633
|
+
}
|
|
5511
5634
|
};
|
|
5512
|
-
if (this.schemaName !== void 0) {
|
|
5513
|
-
meta.schema = this.schemaName;
|
|
5514
|
-
}
|
|
5515
5635
|
return {
|
|
5516
5636
|
sql: compiled.sql,
|
|
5517
5637
|
parameters: compiled.parameters,
|
|
@@ -5521,129 +5641,38 @@ var MutationBuilderBase = class {
|
|
|
5521
5641
|
}
|
|
5522
5642
|
async execute() {
|
|
5523
5643
|
const adapter = this.requireAdapter(this.operationName);
|
|
5524
|
-
if (!this.hookStore || !hasHooks(this.hookStore)) {
|
|
5525
|
-
return this.executeWithoutHooks(adapter);
|
|
5526
|
-
}
|
|
5527
|
-
return this.executeWithHooks(adapter);
|
|
5528
|
-
}
|
|
5529
|
-
async executeWithoutHooks(adapter) {
|
|
5530
5644
|
const intent = this.buildIntent();
|
|
5531
|
-
|
|
5532
|
-
const compiled = this.compileIntent(adapter, intent, compileOptions);
|
|
5533
|
-
if (this.returningColumns && this.returningColumns.length > 0) {
|
|
5534
|
-
const result = await adapter.execute(compiled);
|
|
5535
|
-
return result;
|
|
5536
|
-
}
|
|
5537
|
-
await adapter.execute(compiled);
|
|
5538
|
-
return void 0;
|
|
5539
|
-
}
|
|
5540
|
-
async executeWithHooks(adapter) {
|
|
5541
|
-
const store = this.hookStore;
|
|
5542
|
-
if (!store) throw new Error("executeWithHooks called without hookStore");
|
|
5543
|
-
return withReentrancyGuard(
|
|
5544
|
-
store,
|
|
5545
|
-
(s) => this.executeWithHooksInner(adapter, s)
|
|
5546
|
-
);
|
|
5547
|
-
}
|
|
5548
|
-
async executeWithHooksInner(adapter, store) {
|
|
5549
|
-
const intent = this.buildIntent();
|
|
5550
|
-
const operation = intent.type;
|
|
5551
|
-
const startTime = Date.now();
|
|
5552
|
-
const { cardinality, data } = this.extractIntentData(intent);
|
|
5553
|
-
let ctx = Object.freeze({
|
|
5645
|
+
return runMutationWithHooks({
|
|
5554
5646
|
table: this.table,
|
|
5555
|
-
operation,
|
|
5556
5647
|
intent,
|
|
5557
|
-
|
|
5558
|
-
|
|
5559
|
-
|
|
5560
|
-
|
|
5648
|
+
hookStore: this.hookStore,
|
|
5649
|
+
onHookError: this.onHookError,
|
|
5650
|
+
schemaName: this.schemaName,
|
|
5651
|
+
inTransaction: this.inTransaction,
|
|
5652
|
+
prepare: (preparedIntent) => this.prepareMutationExecution(adapter, preparedIntent)
|
|
5561
5653
|
});
|
|
5562
|
-
try {
|
|
5563
|
-
if (store.beforeMutation.length > 0) {
|
|
5564
|
-
ctx = await runBeforeMutationHooks(
|
|
5565
|
-
store.beforeMutation,
|
|
5566
|
-
ctx,
|
|
5567
|
-
this.onHookError
|
|
5568
|
-
);
|
|
5569
|
-
}
|
|
5570
|
-
const compileOptions = this.schemaName ? { schemaName: this.schemaName } : void 0;
|
|
5571
|
-
const compiled = this.compileIntent(adapter, intent, compileOptions);
|
|
5572
|
-
const duration = Date.now() - startTime;
|
|
5573
|
-
if (this.returningColumns && this.returningColumns.length > 0) {
|
|
5574
|
-
const result = await adapter.execute(compiled);
|
|
5575
|
-
const afterCtx = Object.freeze({
|
|
5576
|
-
...ctx,
|
|
5577
|
-
sql: compiled.sql,
|
|
5578
|
-
parameters: compiled.parameters,
|
|
5579
|
-
duration
|
|
5580
|
-
});
|
|
5581
|
-
if (store.afterMutation.length > 0) {
|
|
5582
|
-
const transformed = await runAfterMutationHooks(
|
|
5583
|
-
store.afterMutation,
|
|
5584
|
-
afterCtx,
|
|
5585
|
-
result,
|
|
5586
|
-
this.onHookError
|
|
5587
|
-
);
|
|
5588
|
-
return transformed;
|
|
5589
|
-
}
|
|
5590
|
-
return result;
|
|
5591
|
-
}
|
|
5592
|
-
await adapter.execute(compiled);
|
|
5593
|
-
if (store.afterMutation.length > 0) {
|
|
5594
|
-
const afterCtx = Object.freeze({
|
|
5595
|
-
...ctx,
|
|
5596
|
-
sql: compiled.sql,
|
|
5597
|
-
parameters: compiled.parameters,
|
|
5598
|
-
duration
|
|
5599
|
-
});
|
|
5600
|
-
await runAfterMutationHooks(
|
|
5601
|
-
store.afterMutation,
|
|
5602
|
-
afterCtx,
|
|
5603
|
-
[],
|
|
5604
|
-
this.onHookError
|
|
5605
|
-
);
|
|
5606
|
-
}
|
|
5607
|
-
return void 0;
|
|
5608
|
-
} catch (error) {
|
|
5609
|
-
if (store.onError.length > 0) {
|
|
5610
|
-
const errorCtx = {
|
|
5611
|
-
table: this.table,
|
|
5612
|
-
operation,
|
|
5613
|
-
error,
|
|
5614
|
-
intent,
|
|
5615
|
-
phase: "beforeMutation",
|
|
5616
|
-
...this.schemaName !== void 0 ? { schemaName: this.schemaName } : {}
|
|
5617
|
-
};
|
|
5618
|
-
const transformed = await runOnErrorHooks(store.onError, errorCtx);
|
|
5619
|
-
throw transformed;
|
|
5620
|
-
}
|
|
5621
|
-
throw error;
|
|
5622
|
-
}
|
|
5623
5654
|
}
|
|
5624
|
-
|
|
5625
|
-
|
|
5626
|
-
|
|
5627
|
-
|
|
5628
|
-
return {
|
|
5629
|
-
cardinality: values.length > 1 ? "bulk" : "single",
|
|
5630
|
-
data: values.length > 1 ? values : values[0]
|
|
5631
|
-
};
|
|
5632
|
-
}
|
|
5633
|
-
if (intent.type === "update") {
|
|
5634
|
-
return {
|
|
5635
|
-
cardinality: "single",
|
|
5636
|
-
data: intent.set
|
|
5637
|
-
};
|
|
5638
|
-
}
|
|
5639
|
-
if (intent.type === "batchUpdate") {
|
|
5640
|
-
const updates = intent.updates;
|
|
5655
|
+
prepareMutationExecution(adapter, intent) {
|
|
5656
|
+
const compileOptions = this.schemaName ? { schemaName: this.schemaName } : void 0;
|
|
5657
|
+
const compiled = this.compileIntent(adapter, intent, compileOptions);
|
|
5658
|
+
if (this.returningColumns && this.returningColumns.length > 0) {
|
|
5641
5659
|
return {
|
|
5642
|
-
|
|
5643
|
-
|
|
5660
|
+
sql: compiled.sql,
|
|
5661
|
+
parameters: compiled.parameters,
|
|
5662
|
+
execute: () => adapter.execute(compiled),
|
|
5663
|
+
getAfterMutationResult: (result) => result,
|
|
5664
|
+
returnAfterMutationResult: true
|
|
5644
5665
|
};
|
|
5645
5666
|
}
|
|
5646
|
-
return {
|
|
5667
|
+
return {
|
|
5668
|
+
sql: compiled.sql,
|
|
5669
|
+
parameters: compiled.parameters,
|
|
5670
|
+
execute: async () => {
|
|
5671
|
+
await adapter.execute(compiled);
|
|
5672
|
+
return void 0;
|
|
5673
|
+
},
|
|
5674
|
+
getAfterMutationResult: () => []
|
|
5675
|
+
};
|
|
5647
5676
|
}
|
|
5648
5677
|
};
|
|
5649
5678
|
var InsertBuilder = class _InsertBuilder extends MutationBuilderBase {
|
|
@@ -5703,7 +5732,7 @@ var InsertBuilder = class _InsertBuilder extends MutationBuilderBase {
|
|
|
5703
5732
|
return intent;
|
|
5704
5733
|
}
|
|
5705
5734
|
compileIntent(adapter, intent, options) {
|
|
5706
|
-
return adapter
|
|
5735
|
+
return compileMutationIntent(adapter, intent, options);
|
|
5707
5736
|
}
|
|
5708
5737
|
};
|
|
5709
5738
|
var UpdateBuilder = class _UpdateBuilder extends MutationBuilderBase {
|
|
@@ -5858,10 +5887,7 @@ var UpdateBuilder = class _UpdateBuilder extends MutationBuilderBase {
|
|
|
5858
5887
|
return intent;
|
|
5859
5888
|
}
|
|
5860
5889
|
compileIntent(adapter, intent, options) {
|
|
5861
|
-
|
|
5862
|
-
return adapter.compileBatchUpdate(intent, options);
|
|
5863
|
-
}
|
|
5864
|
-
return adapter.compileUpdate(intent, options);
|
|
5890
|
+
return compileMutationIntent(adapter, intent, options);
|
|
5865
5891
|
}
|
|
5866
5892
|
};
|
|
5867
5893
|
var DeleteBuilder = class _DeleteBuilder extends MutationBuilderBase {
|
|
@@ -5948,7 +5974,7 @@ var DeleteBuilder = class _DeleteBuilder extends MutationBuilderBase {
|
|
|
5948
5974
|
return intent;
|
|
5949
5975
|
}
|
|
5950
5976
|
compileIntent(adapter, intent, options) {
|
|
5951
|
-
return adapter
|
|
5977
|
+
return compileMutationIntent(adapter, intent, options);
|
|
5952
5978
|
}
|
|
5953
5979
|
};
|
|
5954
5980
|
var UpsertBuilder = class _UpsertBuilder extends MutationBuilderBase {
|
|
@@ -6080,7 +6106,7 @@ var UpsertBuilder = class _UpsertBuilder extends MutationBuilderBase {
|
|
|
6080
6106
|
return intent;
|
|
6081
6107
|
}
|
|
6082
6108
|
compileIntent(adapter, intent, options) {
|
|
6083
|
-
return adapter
|
|
6109
|
+
return compileMutationIntent(adapter, intent, options);
|
|
6084
6110
|
}
|
|
6085
6111
|
};
|
|
6086
6112
|
|
|
@@ -6139,6 +6165,19 @@ import {
|
|
|
6139
6165
|
} from "@dbsp/nql";
|
|
6140
6166
|
import { NQL_INTERNAL_COMPILER_OPTIONS } from "@dbsp/types/internal";
|
|
6141
6167
|
var NQL_RAW_FRAGMENT = /* @__PURE__ */ Symbol("NqlRawFragment");
|
|
6168
|
+
function hasNqlBindings(bundle) {
|
|
6169
|
+
return (bundle.bindings?.size ?? 0) > 0;
|
|
6170
|
+
}
|
|
6171
|
+
function assertNoMutationBindingBodies(bundle) {
|
|
6172
|
+
const mutationBindings = bundle.mutationBindings;
|
|
6173
|
+
if (!mutationBindings || mutationBindings.size === 0) {
|
|
6174
|
+
return;
|
|
6175
|
+
}
|
|
6176
|
+
const bindNames = [...mutationBindings.keys()].map((name) => `'${name}'`).join(", ");
|
|
6177
|
+
throw new Error(
|
|
6178
|
+
`NQL tag programs cannot use mutation bodies in | bind clauses (${bindNames}); writable binding CTEs are disabled for tag execution (#173). Use a read-only bind before a single final mutation, or execute the mutation explicitly.`
|
|
6179
|
+
);
|
|
6180
|
+
}
|
|
6142
6181
|
function nqlRaw(fragment) {
|
|
6143
6182
|
if (typeof fragment !== "string") {
|
|
6144
6183
|
throw new TypeError("nqlRaw() expects a string fragment");
|
|
@@ -6250,7 +6289,7 @@ function assembleNqlTemplate(strings, values) {
|
|
|
6250
6289
|
sourceError: findInternalParamSourceError(query, generatedRanges)
|
|
6251
6290
|
};
|
|
6252
6291
|
}
|
|
6253
|
-
function createNqlTag(schemaDefinition, model, adapter, schemaName) {
|
|
6292
|
+
function createNqlTag(schemaDefinition, model, adapter, schemaName, hookStore, onHookError, inTransaction) {
|
|
6254
6293
|
return function nql(strings, ...values) {
|
|
6255
6294
|
const assembled = assembleNqlTemplate(strings, values);
|
|
6256
6295
|
return new NqlBuilderImpl(
|
|
@@ -6261,22 +6300,27 @@ function createNqlTag(schemaDefinition, model, adapter, schemaName) {
|
|
|
6261
6300
|
schemaDefinition,
|
|
6262
6301
|
model,
|
|
6263
6302
|
adapter,
|
|
6264
|
-
schemaName
|
|
6303
|
+
schemaName,
|
|
6304
|
+
hookStore,
|
|
6305
|
+
onHookError,
|
|
6306
|
+
inTransaction
|
|
6265
6307
|
);
|
|
6266
6308
|
};
|
|
6267
6309
|
}
|
|
6268
6310
|
var NqlBuilderImpl = class {
|
|
6269
|
-
|
|
6311
|
+
_compiled;
|
|
6270
6312
|
query;
|
|
6271
6313
|
params;
|
|
6272
6314
|
hasBoundParams;
|
|
6273
6315
|
sourceError;
|
|
6274
6316
|
schemaDefinition;
|
|
6275
6317
|
model;
|
|
6276
|
-
// biome-ignore lint/correctness/noUnusedPrivateClassMembers: Reserved for future schema-scoping support
|
|
6277
6318
|
_schemaName;
|
|
6278
6319
|
adapter;
|
|
6279
|
-
|
|
6320
|
+
hookStore;
|
|
6321
|
+
onHookError;
|
|
6322
|
+
inTransaction;
|
|
6323
|
+
constructor(query, params, hasBoundParams, sourceError, schemaDefinition, model, adapter, schemaName, hookStore, onHookError, inTransaction) {
|
|
6280
6324
|
this.query = query;
|
|
6281
6325
|
this.params = params;
|
|
6282
6326
|
this.hasBoundParams = hasBoundParams;
|
|
@@ -6285,10 +6329,13 @@ var NqlBuilderImpl = class {
|
|
|
6285
6329
|
this.model = model;
|
|
6286
6330
|
this.adapter = adapter;
|
|
6287
6331
|
this._schemaName = schemaName;
|
|
6332
|
+
this.hookStore = hookStore;
|
|
6333
|
+
this.onHookError = onHookError;
|
|
6334
|
+
this.inTransaction = inTransaction;
|
|
6288
6335
|
}
|
|
6289
6336
|
compile() {
|
|
6290
|
-
if (this.
|
|
6291
|
-
return this.
|
|
6337
|
+
if (this._compiled) {
|
|
6338
|
+
return this._compiled;
|
|
6292
6339
|
}
|
|
6293
6340
|
if (this.sourceError !== void 0) {
|
|
6294
6341
|
throw new Error(`NQL compilation failed: ${this.sourceError}`);
|
|
@@ -6309,28 +6356,53 @@ var NqlBuilderImpl = class {
|
|
|
6309
6356
|
const rawHint = this.hasBoundParams ? " If an interpolation was intended as NQL structure, wrap a trusted fragment with nqlRaw()." : "";
|
|
6310
6357
|
throw new Error(`NQL compilation failed: ${errors}${rawHint}`);
|
|
6311
6358
|
}
|
|
6312
|
-
|
|
6313
|
-
|
|
6314
|
-
"INSERT/UPDATE/DELETE/UPSERT not yet supported via the nql`...` tagged template. Use orm.insert(table, data) / orm.update(table, set) / orm.delete(table) / orm.upsert(table, data) instead. Tracking: https://github.com/oorabona/db-semantic-planner/issues/113"
|
|
6315
|
-
);
|
|
6316
|
-
}
|
|
6317
|
-
if (!result.ast?.query) {
|
|
6359
|
+
const bundle = result.ast;
|
|
6360
|
+
if (!bundle) {
|
|
6318
6361
|
throw new Error("NQL compilation failed: no query AST produced");
|
|
6319
6362
|
}
|
|
6320
|
-
|
|
6321
|
-
|
|
6363
|
+
assertNoMutationBindingBodies(bundle);
|
|
6364
|
+
if (bundle.query) {
|
|
6365
|
+
this._compiled = {
|
|
6366
|
+
kind: "query",
|
|
6367
|
+
bundle,
|
|
6368
|
+
intent: bundle.query
|
|
6369
|
+
};
|
|
6370
|
+
return this._compiled;
|
|
6371
|
+
}
|
|
6372
|
+
if (bundle.mutation) {
|
|
6373
|
+
this._compiled = {
|
|
6374
|
+
kind: "mutation",
|
|
6375
|
+
bundle,
|
|
6376
|
+
intent: bundle.mutation
|
|
6377
|
+
};
|
|
6378
|
+
return this._compiled;
|
|
6379
|
+
}
|
|
6380
|
+
throw new Error("NQL compilation failed: no query AST produced");
|
|
6322
6381
|
}
|
|
6323
6382
|
toIntentIR() {
|
|
6324
|
-
return this.compile();
|
|
6383
|
+
return this.compile().intent;
|
|
6325
6384
|
}
|
|
6326
6385
|
planInternal() {
|
|
6327
|
-
const
|
|
6328
|
-
|
|
6386
|
+
const compiled = this.compile();
|
|
6387
|
+
if (compiled.kind === "mutation") {
|
|
6388
|
+
throw new Error(
|
|
6389
|
+
"NQL mutations do not have execution plans; use dump() for SQL and parameters."
|
|
6390
|
+
);
|
|
6391
|
+
}
|
|
6392
|
+
return plan(compiled.intent, this.model);
|
|
6329
6393
|
}
|
|
6330
6394
|
plan() {
|
|
6331
6395
|
return this.planInternal();
|
|
6332
6396
|
}
|
|
6333
6397
|
dump(meta) {
|
|
6398
|
+
const compiledIntent = this.compile();
|
|
6399
|
+
if (compiledIntent.kind === "mutation") {
|
|
6400
|
+
return this.dumpMutation(
|
|
6401
|
+
compiledIntent.bundle,
|
|
6402
|
+
compiledIntent.intent,
|
|
6403
|
+
meta
|
|
6404
|
+
);
|
|
6405
|
+
}
|
|
6334
6406
|
const planReport = this.planInternal();
|
|
6335
6407
|
if (!this.adapter) {
|
|
6336
6408
|
return {
|
|
@@ -6340,7 +6412,10 @@ var NqlBuilderImpl = class {
|
|
|
6340
6412
|
...meta !== void 0 && { meta }
|
|
6341
6413
|
};
|
|
6342
6414
|
}
|
|
6343
|
-
const compiled = this.adapter.compile(
|
|
6415
|
+
const compiled = hasNqlBindings(compiledIntent.bundle) ? this.adapter.compile(
|
|
6416
|
+
compiledIntent.bundle,
|
|
6417
|
+
this.nqlBundleCompileOptions()
|
|
6418
|
+
) : this.adapter.compile(planReport);
|
|
6344
6419
|
try {
|
|
6345
6420
|
return this.adapter.createDump(planReport, compiled, meta);
|
|
6346
6421
|
} catch (err) {
|
|
@@ -6368,15 +6443,88 @@ var NqlBuilderImpl = class {
|
|
|
6368
6443
|
throw err;
|
|
6369
6444
|
}
|
|
6370
6445
|
}
|
|
6371
|
-
|
|
6446
|
+
requireAdapter(operation) {
|
|
6372
6447
|
if (!this.adapter) {
|
|
6448
|
+
throw new ExecutionError({
|
|
6449
|
+
operation,
|
|
6450
|
+
reason: "Adapter not configured",
|
|
6451
|
+
fix: "Pass adapter option when creating ORM: createOrm({ model, adapter })"
|
|
6452
|
+
});
|
|
6453
|
+
}
|
|
6454
|
+
return this.adapter;
|
|
6455
|
+
}
|
|
6456
|
+
mutationCompileOptions(extraOptions) {
|
|
6457
|
+
return {
|
|
6458
|
+
model: this.model,
|
|
6459
|
+
...this._schemaName !== void 0 && { schemaName: this._schemaName },
|
|
6460
|
+
...extraOptions
|
|
6461
|
+
};
|
|
6462
|
+
}
|
|
6463
|
+
nqlBundleCompileOptions() {
|
|
6464
|
+
return {
|
|
6465
|
+
model: this.model,
|
|
6466
|
+
...this._schemaName !== void 0 && { schemaName: this._schemaName }
|
|
6467
|
+
};
|
|
6468
|
+
}
|
|
6469
|
+
dumpMutation(bundle, intent, meta) {
|
|
6470
|
+
const adapter = this.requireAdapter("dump");
|
|
6471
|
+
const compiled = adapter.compile(bundle, this.mutationCompileOptions(meta));
|
|
6472
|
+
const dumpMeta = {
|
|
6473
|
+
compiledAt: /* @__PURE__ */ new Date(),
|
|
6474
|
+
...this._schemaName !== void 0 && { schema: this._schemaName },
|
|
6475
|
+
...meta?.queryName !== void 0 && { queryName: meta.queryName },
|
|
6476
|
+
...meta?.correlationId !== void 0 && {
|
|
6477
|
+
correlationId: meta.correlationId
|
|
6478
|
+
}
|
|
6479
|
+
};
|
|
6480
|
+
return {
|
|
6481
|
+
sql: compiled.sql,
|
|
6482
|
+
parameters: compiled.parameters,
|
|
6483
|
+
intent,
|
|
6484
|
+
meta: dumpMeta
|
|
6485
|
+
};
|
|
6486
|
+
}
|
|
6487
|
+
async all() {
|
|
6488
|
+
const adapter = this.adapter;
|
|
6489
|
+
if (!adapter) {
|
|
6373
6490
|
throw new Error(
|
|
6374
6491
|
"Cannot execute query: no adapter configured. Pass an adapter to createOrm() or use .toIntentIR() / .plan() for debugging."
|
|
6375
6492
|
);
|
|
6376
6493
|
}
|
|
6494
|
+
const compiledIntent = this.compile();
|
|
6495
|
+
if (compiledIntent.kind === "mutation") {
|
|
6496
|
+
const hasReturning = (compiledIntent.intent.returning?.length ?? 0) > 0;
|
|
6497
|
+
return runMutationWithHooks({
|
|
6498
|
+
table: compiledIntent.intent.table,
|
|
6499
|
+
intent: compiledIntent.intent,
|
|
6500
|
+
hookStore: this.hookStore,
|
|
6501
|
+
onHookError: this.onHookError,
|
|
6502
|
+
schemaName: this._schemaName,
|
|
6503
|
+
inTransaction: this.inTransaction,
|
|
6504
|
+
prepare: () => {
|
|
6505
|
+
const compiled2 = adapter.compile(
|
|
6506
|
+
compiledIntent.bundle,
|
|
6507
|
+
this.mutationCompileOptions()
|
|
6508
|
+
);
|
|
6509
|
+
return {
|
|
6510
|
+
sql: compiled2.sql,
|
|
6511
|
+
parameters: compiled2.parameters,
|
|
6512
|
+
execute: () => adapter.execute(compiled2),
|
|
6513
|
+
getAfterMutationResult: (result) => hasReturning ? result : [],
|
|
6514
|
+
returnAfterMutationResult: hasReturning
|
|
6515
|
+
};
|
|
6516
|
+
}
|
|
6517
|
+
});
|
|
6518
|
+
}
|
|
6377
6519
|
const planReport = this.planInternal();
|
|
6378
|
-
const compiled =
|
|
6379
|
-
|
|
6520
|
+
const compiled = hasNqlBindings(compiledIntent.bundle) ? adapter.compile(
|
|
6521
|
+
compiledIntent.bundle,
|
|
6522
|
+
this.nqlBundleCompileOptions()
|
|
6523
|
+
) : adapter.compile(planReport);
|
|
6524
|
+
return adapter.execute(compiled);
|
|
6525
|
+
}
|
|
6526
|
+
async run() {
|
|
6527
|
+
await this.all();
|
|
6380
6528
|
}
|
|
6381
6529
|
async first() {
|
|
6382
6530
|
const rows = await this.all();
|
|
@@ -9151,7 +9299,10 @@ function createOrmInstance(model, strictMode, relationHints, adapter, schemaName
|
|
|
9151
9299
|
schemaDefinition,
|
|
9152
9300
|
model,
|
|
9153
9301
|
adapter,
|
|
9154
|
-
schemaName
|
|
9302
|
+
schemaName,
|
|
9303
|
+
hookStore,
|
|
9304
|
+
onHookError,
|
|
9305
|
+
inTransaction
|
|
9155
9306
|
);
|
|
9156
9307
|
const mutationOpts = {
|
|
9157
9308
|
model,
|