@dbsp/core 3.1.0 → 3.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 CHANGED
@@ -1,6 +1,6 @@
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, ColumnJsReadType as ColumnJsReadType$1, WhereIntent, OnDeleteAction, ModelIR, DbCasing, QueryIntent, PlanOptions, PlanReport, RecursiveIntent, RecursivePlanOptions, RecursivePlanReport, ObservationContext, TransitionConnectionPool, IssuedObservation, RecoveryArtefact, FingerprintManifest, OperationSemantics, OperationKindRef, PhysicalOperation, EvidenceObservation, DurableIntentRecord, OperationEffectAssessment, ObservationIssuer, ApplyGuard, OperationExecutionOutcome, TransactionalCompletionRecord, StepJournal, TransitionRule, EquivalenceCapability, CapabilityDescriptor, TransitionCompositionFact, RuleRef, SemanticArtifactRef, CheckConstraintIR, Comparator, EnumIR, ObservationRequest, EvidenceView, AdvisoryObservationId, AssumptionId, ClaimId, EvidenceId, SemanticArtifactId, IndexIR, ResourceAddress, ResourceSelector, ApplyPolicy, ApplyResult, TransitionCandidate, TransitionFragmentComposition, PlanAssessment, CompareOutcome, TransitionFragment, ProofClaim, Assumption, ProvenPlanShape, ApplicableAssessment, TransitionRunJournal, InapplicableAssessment, TableIR, SequenceIR, AmbiguityCheckResult, DialectCapabilities, DDLFeature, DDLFeatureVersionRange, 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, DumpSequenceStep, UpsertConflictTarget, UpsertConflictAction, RawCteIntent, TruncateOptions, VacuumOptions, AlterColumnOptions, CreateIndexOptions, DropIndexOptions, IndexInfo, ExpressionIntent, ComparisonOperator, WhereSubqueryIntent, SubqueryRefIntent, WhereAndIntent, WhereAnyIntent, WhereComparisonIntent, WhereRelationFilterIntent, RecursiveExistsOptions, WhereExistsIntent, WhereInIntent, WhereNullIntent, WhereLikeIntent, WhereNotIntent, WhereNotExistsIntent, WhereOrIntent, WhereRawExistsIntent, WhereRawNotExistsIntent, WhereExpressionIntent, AggOrderByArg, RelationType as RelationType$1, Cardinality, FeatureWarning, UnsupportedFeatureBehavior, FeatureBehaviorConfig, RangeValue, WhereRangeIntent, SubqueryIncludeInfo } from '@dbsp/types';
3
- export { Adapter, AdapterCapabilities, AdapterLogger, AdapterStreamOptions, AdjacencyTraversal, AggregateExpressionIntent, AggregateFunction, AggregateIntent, AggregateWindowFunction, AliasIncludedColumnsMode, AlterColumnOptions, AmbiguityCheckResult, ApplicableAssessment, ApplicableEvaluation, ApplyPolicy, ArrayOperator, Assumption, BaseAdapter, CTEDefinition, CapabilityDescriptor, Cardinality, CaseExpressionIntent, CoalesceExpressionIntent, ColumnAliasIntent, ColumnExpressionIntent, ColumnIR, ColumnJsReadType, ColumnType, CommonColumnType, Comparator, CompareOutcome, ComparisonExpressionIntent, ComparisonOperator, CompileOnlyAdapter, CompileOptions, CompileResultWithIncludes, CompiledQuery, CompilingAdapter, CreateIndexOptions, CustomTraversal, DDLGeneratingAdapter, DbCasing, DecisionType, DeleteIntent, DialectCapabilities, DialectName, DropIndexOptions, DuckDBColumnType, Dump, DumpMeta, DurableIntentRecord, EdgeTableTraversal, EmitJoinClause, ExecutingAdapter, ExpressionIntent, FilterStrategy, FingerprintManifest, ForeignKeyIR, InapplicableAssessment, IncludeIntent, IncludeStrategy, IndexColumnDef, IndexIR, IndexInfo, IndexMethod, InsertFromIntent, InsertIntent, IntrospectingAdapter, IsTypeSupported, JoinDefault, JoinIntent, LiteralExpressionIntent, LogicalIdentity, LogicalIdentityCarrier, LogicalOperator, MSSQLColumnType, ModelIR, MutationIntent, MySQLColumnType, NullOperator, NullsPosition, ObservationContext, ObservationIssuer, ObservationRequest, OffsetWindowFunction, OnDeleteAction, OperationEffectAssessment, OperationSemantics, Optionality, OrderByIntent, PartitionIR, PhysicalOperation, PlanDecision, PlanOptions, PlanReport, PlanWarning, PlanWarningCode, PostgresColumnType, PostgresOnlyColumnType, ProvenApplyGuard, ProvenGuardProtocol, ProvenPlanShape, ProvenPlanStep, PseudoColumnExpressionIntent, PseudoColumnMetadata, PseudoColumnTraversal, QueryIntent, RangeOperator, RangeValue, RankingWindowFunction, RawExpressionIntent, RawSqlAdapter, RecognitionResult, RecursiveAdvancedOptions, RecursiveDedupe, RecursiveDirection, RecursiveEmitOptions, RecursiveExistsOptions, RecursiveIntent, RecursiveMetadata, RecursiveNodeIdExpr, RecursivePlanOptions, RecursivePlanReport, RecursiveTrackOptions, RecursiveTraversal, RelationColumnIntent, RelationIR, RelationKind, RelationOperator, RelationType, RequiredEnumLabelIR, ResolvedIncludeStrategy, ResourceAddress, RuleEvaluation, RuleSupport, SQLiteColumnType, SelectAggregateIntent, SelectAllIntent, SelectFieldsIntent, SelectIntent, SelectWithExpressionsIntent, SerializedProvenPlan, SortDirection, StepJournal, StreamingAdapter, StringOperator, SubqueryIncludeInfo, SubqueryRefIntent, SupportedColumnTypes, TableIR, TransactionalAdapter, TransactionalCompletionRecord, TransitionCandidate, TransitionConnectionPool, TransitionQueryClient, TransitionRule, TransitionRunMetadata, 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';
2
+ import { PseudoColumnMetadata, RecursiveMetadata, RelationIR, RelationKind, AdapterCapabilities, Adapter, BaseAdapter, DDLGeneratingAdapter, ExecutingAdapter, IntrospectingAdapter, RawSqlAdapter, StreamingAdapter, TransactionalAdapter, ColumnType, ColumnJsReadType as ColumnJsReadType$1, WhereIntent, OnDeleteAction, ModelIR, DbCasing, QueryIntent, PlanOptions, PlanReport, RecursiveIntent, RecursivePlanOptions, RecursivePlanReport, ObservationContext, TransitionConnectionPool, IssuedObservation, RecoveryArtefact, FingerprintManifest, OperationSemantics, OperationKindRef, PhysicalOperation, EvidenceObservation, DurableIntentRecord, OperationEffectAssessment, ObservationIssuer, ApplyGuard, OperationExecutionOutcome, TransactionalCompletionRecord, StepJournal, TransitionRule, EquivalenceCapability, CapabilityDescriptor, TransitionCompositionFact, RuleRef, SemanticArtifactRef, CheckConstraintIR, Comparator, EnumIR, ObservationRequest, EvidenceView, AdvisoryObservationId, AssumptionId, ClaimId, EvidenceId, SemanticArtifactId, IndexIR, ResourceAddress, ResourceSelector, ApplyPolicy, ApplyResult, TransitionCandidate, TransitionFragmentComposition, PlanAssessment, CompareOutcome, TransitionFragment, ProofClaim, Assumption, ProvenPlanShape, ApplicableAssessment, TransitionRunJournal, InapplicableAssessment, TableIR, SequenceIR, AmbiguityCheckResult, DialectCapabilities, DDLFeature, DDLFeatureVersionRange, SelectIntent, IncludeIntent, AggregateIntent, OrderByIntent, SortDirection, InsertIntent, InsertFromIntent, UpdateIntent, BatchUpdateIntent, DeleteIntent, UpsertIntent, UpsertFromIntent, TransactionBeginOptions, Dump, SetOperationIntent, LockStrength, LockWaitPolicy, DumpMeta, JoinIntent, UnnestCteIntent, CteQueryIntent, CompileOptions, CompiledQuery, MutationIntent as MutationIntent$1, DumpSequenceStep, UpsertConflictTarget, UpsertConflictAction, RawCteIntent, TruncateOptions, VacuumOptions, AlterColumnOptions, CreateIndexOptions, DropIndexOptions, IndexInfo, TransactionOptions, PinnedConnectionOptions, ExpressionIntent, ComparisonOperator, WhereSubqueryIntent, SubqueryRefIntent, WhereAndIntent, WhereAnyIntent, WhereComparisonIntent, WhereRelationFilterIntent, RecursiveExistsOptions, WhereExistsIntent, WhereInIntent, WhereNullIntent, WhereLikeIntent, WhereNotIntent, WhereNotExistsIntent, WhereOrIntent, WhereRawExistsIntent, WhereRawNotExistsIntent, WhereExpressionIntent, AggOrderByArg, RelationType as RelationType$1, Cardinality, FeatureWarning, UnsupportedFeatureBehavior, FeatureBehaviorConfig, RangeValue, WhereRangeIntent, SubqueryIncludeInfo } from '@dbsp/types';
3
+ export { Adapter, AdapterCapabilities, AdapterLogger, AdapterStreamOptions, AdjacencyTraversal, AggregateExpressionIntent, AggregateFunction, AggregateIntent, AggregateWindowFunction, AliasIncludedColumnsMode, AlterColumnOptions, AmbiguityCheckResult, ApplicableAssessment, ApplicableEvaluation, ApplyPolicy, ArrayOperator, Assumption, BaseAdapter, CTEDefinition, CapabilityDescriptor, Cardinality, CaseExpressionIntent, CoalesceExpressionIntent, ColumnAliasIntent, ColumnExpressionIntent, ColumnIR, ColumnJsReadType, ColumnType, CommonColumnType, Comparator, CompareOutcome, ComparisonExpressionIntent, ComparisonOperator, CompileOnlyAdapter, CompileOptions, CompileResultWithIncludes, CompiledQuery, CompilingAdapter, CreateIndexOptions, CustomTraversal, DDLGeneratingAdapter, DbCasing, DecisionType, DeleteIntent, DialectCapabilities, DialectName, DropIndexOptions, DuckDBColumnType, Dump, DumpMeta, DurableIntentRecord, EdgeTableTraversal, EmitJoinClause, ExecutingAdapter, ExpressionIntent, FilterStrategy, FingerprintManifest, ForeignKeyIR, InapplicableAssessment, IncludeIntent, IncludeStrategy, IndexColumnDef, IndexIR, IndexInfo, IndexMethod, InsertFromIntent, InsertIntent, IntrospectingAdapter, IsTypeSupported, JoinDefault, JoinIntent, LiteralExpressionIntent, LogicalIdentity, LogicalIdentityCarrier, LogicalOperator, MSSQLColumnType, ModelIR, MutationIntent, MySQLColumnType, NullOperator, NullsPosition, ObservationContext, ObservationIssuer, ObservationRequest, OffsetWindowFunction, OnDeleteAction, OperationEffectAssessment, OperationSemantics, Optionality, OrderByIntent, PartitionIR, PhysicalOperation, PlanDecision, PlanOptions, PlanReport, PlanWarning, PlanWarningCode, PostgresColumnType, PostgresOnlyColumnType, ProvenApplyGuard, ProvenGuardProtocol, ProvenPlanShape, ProvenPlanStep, PseudoColumnExpressionIntent, PseudoColumnMetadata, PseudoColumnTraversal, QueryIntent, RangeOperator, RangeValue, RankingWindowFunction, RawExpressionIntent, RawSqlAdapter, RecognitionResult, RecursiveAdvancedOptions, RecursiveDedupe, RecursiveDirection, RecursiveEmitOptions, RecursiveExistsOptions, RecursiveIntent, RecursiveMetadata, RecursiveNodeIdExpr, RecursivePlanOptions, RecursivePlanReport, RecursiveTrackOptions, RecursiveTraversal, RelationColumnIntent, RelationIR, RelationKind, RelationOperator, RelationType, RequiredEnumLabelIR, ResolvedIncludeStrategy, ResourceAddress, RuleEvaluation, RuleSupport, SQLiteColumnType, SelectAggregateIntent, SelectAllIntent, SelectFieldsIntent, SelectIntent, SelectWithExpressionsIntent, SerializedProvenPlan, SortDirection, StepJournal, StreamingAdapter, StringOperator, SubqueryIncludeInfo, SubqueryRefIntent, SupportedColumnTypes, TableIR, TransactionOptions, TransactionalAdapter, TransactionalCompletionRecord, TransitionCandidate, TransitionConnectionPool, TransitionQueryClient, TransitionRule, TransitionRunMetadata, 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
 
6
6
  /**
@@ -2426,7 +2426,7 @@ interface QueryBuilderContext {
2426
2426
  * Options for streaming query execution.
2427
2427
  * Options for configuring streaming behavior.
2428
2428
  */
2429
- interface StreamOptions {
2429
+ interface StreamOptions extends TransactionBeginOptions {
2430
2430
  /**
2431
2431
  * Number of rows to fetch per batch from the database.
2432
2432
  * Only affects PostgreSQL with pg-cursor configured.
@@ -2438,6 +2438,8 @@ interface StreamOptions {
2438
2438
  * Receives the query dump for observability/logging.
2439
2439
  */
2440
2440
  readonly onStart?: (dump: Dump) => void;
2441
+ /** AbortSignal is intentionally unsupported by stream-owned transactions. */
2442
+ readonly signal?: never;
2441
2443
  }
2442
2444
  /**
2443
2445
  * Options for offset-based pagination.
@@ -3851,6 +3853,7 @@ declare abstract class MutationBuilderBase<T, TIntent extends InsertIntent | Upd
3851
3853
  protected requireAdapter(operation: string): Adapter;
3852
3854
  dump(extraOptions?: CompileOptions): MutationDump;
3853
3855
  execute(): Promise<T>;
3856
+ affectedRows(): Promise<number>;
3854
3857
  private prepareMutationExecution;
3855
3858
  }
3856
3859
  /**
@@ -4475,6 +4478,13 @@ interface SelectExpressionResult {
4475
4478
  */
4476
4479
  execute<T = Record<string, unknown>>(): Promise<T[]>;
4477
4480
  }
4481
+ interface RawReadOptions {
4482
+ /**
4483
+ * Map of output-key -> JS read type, applied to bigint columns read via raw SQL.
4484
+ * The caller declares provenance explicitly; dbsp does not infer it for arbitrary SQL.
4485
+ */
4486
+ readonly bigintReads?: Readonly<Record<string, ColumnJsReadType$1>>;
4487
+ }
4478
4488
  interface OrmInstance<DB = Record<string, unknown>> {
4479
4489
  /**
4480
4490
  * Type-safe table references for query building.
@@ -4624,6 +4634,26 @@ interface OrmInstance<DB = Record<string, unknown>> {
4624
4634
  * The strict mode setting for this ORM instance.
4625
4635
  */
4626
4636
  readonly strictMode: boolean;
4637
+ /**
4638
+ * Whether the connection backing this ORM instance is inside a transaction.
4639
+ *
4640
+ * Reflects the backing adapter's real transaction state: `true` inside a
4641
+ * {@link OrmInstance.transaction} callback, and also `true` for a top-level
4642
+ * instance built on an adapter that is ALREADY inside a caller-owned
4643
+ * transaction (e.g. a borrowed pg client mid-`BEGIN`); `false` otherwise.
4644
+ *
4645
+ * Callers use this to enforce a top-level precondition: an operation whose
4646
+ * effects a caller's outer rollback must not silently undo — DDL that cannot
4647
+ * be nested, or a process-level cache that would go stale if the surrounding
4648
+ * transaction rolls back — can fail closed when the connection is already in a
4649
+ * transaction instead of assuming it owns the top-level transaction.
4650
+ *
4651
+ * Optional for backward compatibility: instances produced by `createOrm`
4652
+ * always populate it, but a pre-existing hand-built `OrmInstance` double may
4653
+ * omit it (reads as `undefined`), so a fail-closed caller should treat a
4654
+ * non-`true` value it cannot confirm accordingly.
4655
+ */
4656
+ readonly inTransaction?: boolean;
4627
4657
  /**
4628
4658
  * Create a schema-scoped ORM instance.
4629
4659
  * All queries from the returned instance will include the schema prefix.
@@ -4731,7 +4761,17 @@ interface OrmInstance<DB = Record<string, unknown>> {
4731
4761
  * });
4732
4762
  * ```
4733
4763
  */
4734
- transaction<T>(fn: (tx: OrmInstance<DB>) => Promise<T>): Promise<T>;
4764
+ transaction<T>(fn: (tx: OrmInstance<DB>) => Promise<T>, options?: TransactionOptions): Promise<T>;
4765
+ /**
4766
+ * Execute a callback with all ORM work pinned to one physical database
4767
+ * connection for the callback lifetime, without opening a transaction.
4768
+ *
4769
+ * @typeParam T - The return type of the callback
4770
+ * @param fn - Async callback that receives a connection-pinned ORM instance
4771
+ * @param options - Optional pinned connection controls
4772
+ * @returns Promise resolving to the callback's return value
4773
+ */
4774
+ withPinnedConnection<T>(fn: (pinned: OrmInstance<DB>) => Promise<T>, options?: PinnedConnectionOptions): Promise<T>;
4735
4775
  /**
4736
4776
  * NQL template tag for writing queries in Natural Query Language.
4737
4777
  *
@@ -4755,9 +4795,10 @@ interface OrmInstance<DB = Record<string, unknown>> {
4755
4795
  * @typeParam T - Expected result type (defaults to unknown)
4756
4796
  * @param sql - Raw SQL string with parameter placeholders
4757
4797
  * @param parameters - Parameter values for placeholders
4798
+ * @param options - Explicit raw read coercion options
4758
4799
  * @returns Promise resolving to array of results
4759
4800
  */
4760
- raw<T = unknown>(sql: string, parameters?: readonly unknown[]): Promise<T[]>;
4801
+ raw<T = unknown>(sql: string, parameters?: readonly unknown[], options?: RawReadOptions): Promise<T[]>;
4761
4802
  /**
4762
4803
  * Create a CTE (Common Table Expression) backed by unnest() arrays.
4763
4804
  *
package/dist/index.js CHANGED
@@ -11788,7 +11788,7 @@ function createStagedTransitionOrchestrator(registry) {
11788
11788
 
11789
11789
  // src/adapter.ts
11790
11790
  function supportsExecution(adapter) {
11791
- return "execute" in adapter && "executeOne" in adapter && typeof adapter.execute === "function";
11791
+ return typeof adapter.execute === "function" && typeof adapter.executeOne === "function" && typeof adapter.executeOneOrThrow === "function";
11792
11792
  }
11793
11793
  function supportsStreaming(adapter) {
11794
11794
  return adapter.capabilities?.supportsStreaming === true && "stream" in adapter && typeof adapter.stream === "function";
@@ -14325,6 +14325,10 @@ function compileMutationIntent(adapter, intent, options) {
14325
14325
  );
14326
14326
  }
14327
14327
  async function runMutationWithHooks(opts) {
14328
+ const execution = await runMutationWithHooksMeta(opts);
14329
+ return execution.result;
14330
+ }
14331
+ async function runMutationWithHooksMeta(opts) {
14328
14332
  if (!opts.hookStore || !hasHooks(opts.hookStore)) {
14329
14333
  const prepared = opts.prepare(opts.intent);
14330
14334
  return prepared.execute();
@@ -14358,25 +14362,30 @@ async function runMutationWithHooksInner(opts, store) {
14358
14362
  }
14359
14363
  const prepared = opts.prepare(intent);
14360
14364
  const duration = Date.now() - startTime;
14361
- const result = await prepared.execute();
14365
+ const execution = await prepared.execute();
14366
+ let result = execution.result;
14362
14367
  if (store.afterMutation.length > 0) {
14363
14368
  const afterCtx = Object.freeze({
14364
14369
  ...ctx,
14365
14370
  sql: prepared.sql,
14366
14371
  parameters: prepared.parameters,
14367
- duration
14372
+ duration,
14373
+ ...execution.affectedRows !== void 0 ? { affectedRows: execution.affectedRows } : {}
14368
14374
  });
14369
14375
  const transformed = await runAfterMutationHooks(
14370
14376
  store.afterMutation,
14371
14377
  afterCtx,
14372
- [...prepared.getAfterMutationResult?.(result) ?? []],
14378
+ [...prepared.getAfterMutationResult?.(execution.result) ?? []],
14373
14379
  opts.onHookError
14374
14380
  );
14375
14381
  if (prepared.returnAfterMutationResult) {
14376
- return prepared.mapAfterMutationResult?.(result, transformed) ?? transformed;
14382
+ result = prepared.mapAfterMutationResult?.(result, transformed) ?? transformed;
14377
14383
  }
14378
14384
  }
14379
- return result;
14385
+ return {
14386
+ result,
14387
+ ...execution.affectedRows !== void 0 ? { affectedRows: execution.affectedRows } : {}
14388
+ };
14380
14389
  } catch (error) {
14381
14390
  if (store.onError.length > 0) {
14382
14391
  const errorCtx = {
@@ -14502,6 +14511,34 @@ var MutationBuilderBase = class {
14502
14511
  prepare: (preparedIntent) => this.prepareMutationExecution(adapter, preparedIntent)
14503
14512
  });
14504
14513
  }
14514
+ async affectedRows() {
14515
+ const adapter = this.requireAdapter(this.operationName);
14516
+ const intent = this.buildIntent();
14517
+ if (typeof adapter.executeWithMeta !== "function") {
14518
+ throw new ExecutionError({
14519
+ operation: `${this.operationName}.affectedRows`,
14520
+ reason: "this adapter does not support affectedRows(); it does not implement executeWithMeta",
14521
+ fix: "Use an adapter that implements executeWithMeta, or call execute() when row count metadata is not required."
14522
+ });
14523
+ }
14524
+ const execution = await runMutationWithHooksMeta({
14525
+ table: this.table,
14526
+ intent,
14527
+ hookStore: this.hookStore,
14528
+ onHookError: this.onHookError,
14529
+ schemaName: this.schemaName,
14530
+ inTransaction: this.inTransaction,
14531
+ prepare: (preparedIntent) => this.prepareMutationExecution(adapter, preparedIntent)
14532
+ });
14533
+ if (execution.affectedRows === void 0) {
14534
+ throw new ExecutionError({
14535
+ operation: `${this.operationName}.affectedRows`,
14536
+ reason: "this adapter does not support affectedRows(); it did not return executeWithMeta metadata",
14537
+ fix: "Use an adapter that implements executeWithMeta and returns rowCount metadata."
14538
+ });
14539
+ }
14540
+ return execution.affectedRows;
14541
+ }
14505
14542
  prepareMutationExecution(adapter, intent) {
14506
14543
  const compileOptions = {
14507
14544
  model: this.model,
@@ -14512,7 +14549,19 @@ var MutationBuilderBase = class {
14512
14549
  return {
14513
14550
  sql: compiled.sql,
14514
14551
  parameters: compiled.parameters,
14515
- execute: () => adapter.execute(compiled),
14552
+ execute: async () => {
14553
+ if (typeof adapter.executeWithMeta === "function") {
14554
+ const result2 = await adapter.executeWithMeta(compiled);
14555
+ return {
14556
+ result: result2.rows,
14557
+ affectedRows: result2.rowCount
14558
+ };
14559
+ }
14560
+ const result = await adapter.execute(compiled);
14561
+ return {
14562
+ result
14563
+ };
14564
+ },
14516
14565
  getAfterMutationResult: (result) => result,
14517
14566
  returnAfterMutationResult: true
14518
14567
  };
@@ -14521,8 +14570,17 @@ var MutationBuilderBase = class {
14521
14570
  sql: compiled.sql,
14522
14571
  parameters: compiled.parameters,
14523
14572
  execute: async () => {
14573
+ if (typeof adapter.executeWithMeta === "function") {
14574
+ const result = await adapter.executeWithMeta(compiled);
14575
+ return {
14576
+ result: void 0,
14577
+ affectedRows: result.rowCount
14578
+ };
14579
+ }
14524
14580
  await adapter.execute(compiled);
14525
- return void 0;
14581
+ return {
14582
+ result: void 0
14583
+ };
14526
14584
  },
14527
14585
  getAfterMutationResult: () => []
14528
14586
  };
@@ -16355,12 +16413,27 @@ var NqlBuilderImpl = class {
16355
16413
  sql: compiled.sql,
16356
16414
  parameters: compiled.parameters,
16357
16415
  execute: async () => {
16416
+ if (typeof adapter.executeWithMeta === "function") {
16417
+ const metadata = await adapter.executeWithMeta(compiled);
16418
+ const hookRows2 = metadata.rows;
16419
+ const rawRows2 = snapshotMutationRows(hookRows2);
16420
+ return {
16421
+ result: {
16422
+ rawRows: rawRows2,
16423
+ hookRows: hookRows2,
16424
+ transformedRows: hookRows2
16425
+ },
16426
+ affectedRows: metadata.rowCount
16427
+ };
16428
+ }
16358
16429
  const hookRows = await adapter.execute(compiled);
16359
16430
  const rawRows = snapshotMutationRows(hookRows);
16360
16431
  return {
16361
- rawRows,
16362
- hookRows,
16363
- transformedRows: hookRows
16432
+ result: {
16433
+ rawRows,
16434
+ hookRows,
16435
+ transformedRows: hookRows
16436
+ }
16364
16437
  };
16365
16438
  },
16366
16439
  getAfterMutationResult: (result) => hasReturning ? result.hookRows : [],
@@ -16704,6 +16777,11 @@ function extractPseudoColumnKeywords(model) {
16704
16777
  };
16705
16778
  }
16706
16779
 
16780
+ // src/dx/orm-instance.ts
16781
+ import {
16782
+ convertBigintJsReadValue as convertBigintJsReadValue2
16783
+ } from "@dbsp/types";
16784
+
16707
16785
  // src/dx/hierarchy-helpers.ts
16708
16786
  function extractRecursiveField(result, field) {
16709
16787
  if (result == null) return [];
@@ -17600,9 +17678,35 @@ function createUnsupportedStreamingError() {
17600
17678
  fix: "Use an adapter configuration that supports streaming."
17601
17679
  });
17602
17680
  }
17681
+ function hasStreamTransactionBeginOptions(options) {
17682
+ return options != null && (options.isolationLevel !== void 0 || options.readOnly !== void 0 || options.lockTimeoutMs !== void 0 || options.statementTimeoutMs !== void 0);
17683
+ }
17684
+ function hasRuntimeStreamSignalOption(options) {
17685
+ return typeof options === "object" && options !== null && "signal" in options;
17686
+ }
17687
+ function createAdapterStreamOptions(options) {
17688
+ if (options === void 0 || options.chunkSize === void 0 && !hasStreamTransactionBeginOptions(options)) {
17689
+ return void 0;
17690
+ }
17691
+ return {
17692
+ ...options.chunkSize !== void 0 && { chunkSize: options.chunkSize },
17693
+ ...options.isolationLevel !== void 0 && {
17694
+ isolationLevel: options.isolationLevel
17695
+ },
17696
+ ...options.readOnly !== void 0 && { readOnly: options.readOnly },
17697
+ ...options.lockTimeoutMs !== void 0 && {
17698
+ lockTimeoutMs: options.lockTimeoutMs
17699
+ },
17700
+ ...options.statementTimeoutMs !== void 0 && {
17701
+ statementTimeoutMs: options.statementTimeoutMs
17702
+ }
17703
+ };
17704
+ }
17603
17705
  function stream(builder, options) {
17604
17706
  const adapter = builder.getConfiguredAdapter();
17605
- const adapterOptions = options?.chunkSize !== void 0 ? { chunkSize: options.chunkSize } : void 0;
17707
+ const hasBeginOptions = hasStreamTransactionBeginOptions(options);
17708
+ const hasSignalOption = hasRuntimeStreamSignalOption(options);
17709
+ const adapterOptions = createAdapterStreamOptions(options);
17606
17710
  const hookStore = builder.ctx.hookStore;
17607
17711
  const onHookError = builder.ctx.onHookError;
17608
17712
  const table = builder.from;
@@ -17622,6 +17726,16 @@ function stream(builder, options) {
17622
17726
  if (!supportsStreaming(adapter)) {
17623
17727
  throw createUnsupportedStreamingError();
17624
17728
  }
17729
+ if (hasSignalOption) {
17730
+ throw new Error(
17731
+ "stream() does not support signal; AbortSignal is only supported by transaction()."
17732
+ );
17733
+ }
17734
+ if (hasBeginOptions && adapter.capabilities.supportsTransactionOptions !== true) {
17735
+ throw new Error(
17736
+ "This adapter does not support stream transaction options (isolationLevel/readOnly/lockTimeoutMs/statementTimeoutMs); it does not declare supportsTransactionOptions."
17737
+ );
17738
+ }
17625
17739
  if (!hooksFired) {
17626
17740
  hooksFired = true;
17627
17741
  if (hookStore && hasHooks(hookStore)) {
@@ -19175,8 +19289,21 @@ function createRawCteBuilder(cteName, options, adapter, schemaName, model) {
19175
19289
  function quoteIdent(name) {
19176
19290
  return `"${name.replace(/"/g, '""')}"`;
19177
19291
  }
19292
+ var DEFAULT_DDL_SCHEMA_NAME = "public";
19293
+ function resolveDDLSchemaName(schemaName) {
19294
+ const resolved = schemaName ?? DEFAULT_DDL_SCHEMA_NAME;
19295
+ validateIdentifier(resolved, "schema");
19296
+ return resolved;
19297
+ }
19298
+ function sanitizeDropIndexOptions(options) {
19299
+ if (options === void 0 || !("schema" in options)) {
19300
+ return options;
19301
+ }
19302
+ const { schema: _schema, ...rest } = options;
19303
+ return Object.keys(rest).length > 0 ? rest : void 0;
19304
+ }
19178
19305
  function buildQualifiedTable(tableName, schemaName) {
19179
- return schemaName ? `${quoteIdent(schemaName)}.${quoteIdent(tableName)}` : quoteIdent(tableName);
19306
+ return `${quoteIdent(schemaName)}.${quoteIdent(tableName)}`;
19180
19307
  }
19181
19308
  function generateTruncateSQL(tableName, schemaName, options) {
19182
19309
  const parts = [`TRUNCATE ${buildQualifiedTable(tableName, schemaName)}`];
@@ -19198,6 +19325,33 @@ function createUnsupportedTransactionError() {
19198
19325
  fix: "Use an adapter that implements transaction() and withSchema(), and declare adapter.capabilities.supportsTransactions: true."
19199
19326
  });
19200
19327
  }
19328
+ function createUnsupportedPinnedConnectionError() {
19329
+ return new ExecutionError({
19330
+ operation: "withPinnedConnection()",
19331
+ reason: "The adapter does not declare capabilities.supportsPinnedConnections: true and implement withPinnedConnection() for this ORM instance.",
19332
+ fix: "Use an adapter that implements withPinnedConnection(), and declare adapter.capabilities.supportsPinnedConnections: true."
19333
+ });
19334
+ }
19335
+ function hasTransactionOptions(options) {
19336
+ return options != null && (options.isolationLevel !== void 0 || options.readOnly !== void 0 || options.lockTimeoutMs !== void 0 || options.statementTimeoutMs !== void 0 || options.signal !== void 0);
19337
+ }
19338
+ function supportsPinnedConnections(adapter) {
19339
+ return adapter.capabilities.supportsPinnedConnections === true && typeof adapter.withPinnedConnection === "function";
19340
+ }
19341
+ function applyBigintReads(row, bigintReads) {
19342
+ if (row === null || typeof row !== "object") return row;
19343
+ const rowRecord = row;
19344
+ const converted = { ...rowRecord };
19345
+ for (const [outputKey, js] of Object.entries(bigintReads)) {
19346
+ if (!(outputKey in rowRecord)) continue;
19347
+ converted[outputKey] = convertBigintJsReadValue2(rowRecord[outputKey], js, {
19348
+ table: "(raw)",
19349
+ column: outputKey,
19350
+ outputKey
19351
+ });
19352
+ }
19353
+ return converted;
19354
+ }
19201
19355
  function adapterTransactionState(adapter, operation, statement) {
19202
19356
  const inTransaction = adapter.inTransaction;
19203
19357
  if (typeof inTransaction !== "boolean") {
@@ -19216,8 +19370,8 @@ function assertOutsideTransaction(adapter, operation, statement) {
19216
19370
  );
19217
19371
  }
19218
19372
  }
19219
- function generateAlterColumnSQL(tableName, column, schemaName, options) {
19220
- const tbl = buildQualifiedTable(tableName, schemaName);
19373
+ function generateAlterColumnSQL(tableName, schemaName, column, options) {
19374
+ const tbl = buildQualifiedTable(tableName, resolveDDLSchemaName(schemaName));
19221
19375
  const col2 = quoteIdent(column);
19222
19376
  const clauses = [];
19223
19377
  if (options.type !== void 0) {
@@ -19249,8 +19403,7 @@ function generateDropIndexSQL(name, schemaName, options) {
19249
19403
  const parts = ["DROP INDEX"];
19250
19404
  if (options?.concurrently) parts.push("CONCURRENTLY");
19251
19405
  if (options?.ifExists) parts.push("IF EXISTS");
19252
- const sc = options?.schema ?? schemaName;
19253
- parts.push(sc ? `${quoteIdent(sc)}.${quoteIdent(name)}` : quoteIdent(name));
19406
+ parts.push(`${quoteIdent(schemaName)}.${quoteIdent(name)}`);
19254
19407
  if (options?.cascade) parts.push("CASCADE");
19255
19408
  return parts.join(" ");
19256
19409
  }
@@ -19261,7 +19414,8 @@ function buildIndexAPI(tableName, schemaName, adapter, requireAdapter2) {
19261
19414
  if (opts.concurrently) {
19262
19415
  assertOutsideTransaction(a, "createIndex", "CREATE INDEX CONCURRENTLY");
19263
19416
  }
19264
- const sql2 = a.generateCreateIndex(tableName, opts, schemaName);
19417
+ const ddlSchemaName = resolveDDLSchemaName(schemaName);
19418
+ const sql2 = a.generateCreateIndex(tableName, ddlSchemaName, opts);
19265
19419
  await a.executeDDL?.(sql2);
19266
19420
  },
19267
19421
  async drop(name, options) {
@@ -19269,8 +19423,9 @@ function buildIndexAPI(tableName, schemaName, adapter, requireAdapter2) {
19269
19423
  if (options?.concurrently) {
19270
19424
  assertOutsideTransaction(a, "dropIndex", "DROP INDEX CONCURRENTLY");
19271
19425
  }
19272
- const scopedOptions = schemaName ? { ...options, schema: options?.schema ?? schemaName } : options;
19273
- const sql2 = a.generateDropIndex ? a.generateDropIndex(name, scopedOptions) : generateDropIndexSQL(name, schemaName, options);
19426
+ const ddlSchemaName = resolveDDLSchemaName(schemaName);
19427
+ const sanitizedOptions = sanitizeDropIndexOptions(options);
19428
+ const sql2 = a.generateDropIndex ? a.generateDropIndex(name, ddlSchemaName, sanitizedOptions) : generateDropIndexSQL(name, ddlSchemaName, sanitizedOptions);
19274
19429
  await a.executeDDL?.(sql2);
19275
19430
  },
19276
19431
  async list(options) {
@@ -19318,20 +19473,23 @@ function buildTableDDL(tableName, schemaName, adapter) {
19318
19473
  return {
19319
19474
  async truncate(options) {
19320
19475
  const a = requireAdapter2();
19321
- const sql2 = a.generateTruncate ? a.generateTruncate(tableName, schemaName, options) : generateTruncateSQL(tableName, schemaName, options);
19476
+ const ddlSchemaName = resolveDDLSchemaName(schemaName);
19477
+ const sql2 = a.generateTruncate ? a.generateTruncate(tableName, ddlSchemaName, options) : generateTruncateSQL(tableName, ddlSchemaName, options);
19322
19478
  await a.executeDDL?.(sql2);
19323
19479
  },
19324
19480
  async vacuum(options) {
19325
19481
  const a = requireAdapter2();
19326
19482
  assertOutsideTransaction(a, "vacuum", "VACUUM");
19327
- const sql2 = a.generateVacuum ? a.generateVacuum(tableName, schemaName, options) : generateVacuumSQL(tableName, schemaName, options);
19483
+ const ddlSchemaName = resolveDDLSchemaName(schemaName);
19484
+ const sql2 = a.generateVacuum ? a.generateVacuum(tableName, ddlSchemaName, options) : generateVacuumSQL(tableName, ddlSchemaName, options);
19328
19485
  await a.executeDDL?.(sql2);
19329
19486
  },
19330
19487
  async alterColumn(column, options) {
19331
19488
  validateIdentifier(tableName, "table");
19332
19489
  validateIdentifier(column, "column");
19333
19490
  const a = requireAdapter2();
19334
- const sql2 = a.generateAlterColumn ? a.generateAlterColumn(tableName, column, options, schemaName) : generateAlterColumnSQL(tableName, column, schemaName, options);
19491
+ const ddlSchemaName = resolveDDLSchemaName(schemaName);
19492
+ const sql2 = a.generateAlterColumn ? a.generateAlterColumn(tableName, ddlSchemaName, column, options) : generateAlterColumnSQL(tableName, ddlSchemaName, column, options);
19335
19493
  await a.executeDDL?.(sql2);
19336
19494
  },
19337
19495
  indexes: buildIndexAPI(tableName, schemaName, adapter, requireAdapter2),
@@ -19410,6 +19568,18 @@ function createOrmInstance(model, strictMode, relationHints, adapter, schemaName
19410
19568
  );
19411
19569
  return {
19412
19570
  strictMode,
19571
+ // Reflect the REAL transaction state of the backing adapter so callers can
19572
+ // enforce a top-level precondition. This is authoritative even when the ORM
19573
+ // was handed an adapter ALREADY inside a caller-owned transaction (e.g. a
19574
+ // borrowed pg client mid-BEGIN): the adapter tracks the connection's actual
19575
+ // state, which dbsp's construction-time nesting flag alone cannot see. Falls
19576
+ // back to that flag only when no adapter exposes the state (e.g. a compile-only
19577
+ // ORM). withSchema/transaction() re-derive it from their own (scoped/tx)
19578
+ // adapter, so every instance reports the state of the connection it uses.
19579
+ get inTransaction() {
19580
+ const adapterState = adapter?.inTransaction;
19581
+ return typeof adapterState === "boolean" ? adapterState : inTransaction ?? false;
19582
+ },
19413
19583
  nql,
19414
19584
  tables: tablesDDLProxy,
19415
19585
  // biome-ignore lint/suspicious/noExplicitAny: polymorphic constraint — TTable is inferred by callers; TableRef generics are statically erased in this implementation signature
@@ -19662,7 +19832,7 @@ function createOrmInstance(model, strictMode, relationHints, adapter, schemaName
19662
19832
  // as awaited, by core, before the caller ever touched it. So the adapter's
19663
19833
  // promise is passed through untouched. The guards still reject rather than
19664
19834
  // throwing synchronously, because that is what callers already rely on.
19665
- transaction(fn2) {
19835
+ transaction(fn2, options) {
19666
19836
  if (!adapter) {
19667
19837
  return Promise.reject(
19668
19838
  new Error(
@@ -19673,6 +19843,13 @@ function createOrmInstance(model, strictMode, relationHints, adapter, schemaName
19673
19843
  if (!supportsTransactions(adapter)) {
19674
19844
  return Promise.reject(createUnsupportedTransactionError());
19675
19845
  }
19846
+ if (hasTransactionOptions(options) && adapter.capabilities.supportsTransactionOptions !== true) {
19847
+ return Promise.reject(
19848
+ new Error(
19849
+ "This adapter does not support transaction options (isolationLevel/readOnly/lockTimeoutMs/statementTimeoutMs/signal); it does not declare supportsTransactionOptions."
19850
+ )
19851
+ );
19852
+ }
19676
19853
  try {
19677
19854
  return adapter.transaction(async (txAdapter) => {
19678
19855
  const txOrm = createOrmInstance(
@@ -19692,7 +19869,41 @@ function createOrmInstance(model, strictMode, relationHints, adapter, schemaName
19692
19869
  tablesProxy
19693
19870
  );
19694
19871
  return fn2(txOrm);
19695
- });
19872
+ }, options);
19873
+ } catch (error) {
19874
+ return Promise.reject(error);
19875
+ }
19876
+ },
19877
+ withPinnedConnection(fn2, options) {
19878
+ if (!adapter) {
19879
+ return Promise.reject(
19880
+ new Error(
19881
+ "withPinnedConnection() requires an adapter. Pass an adapter when creating the ORM."
19882
+ )
19883
+ );
19884
+ }
19885
+ if (!supportsPinnedConnections(adapter)) {
19886
+ return Promise.reject(createUnsupportedPinnedConnectionError());
19887
+ }
19888
+ try {
19889
+ return adapter.withPinnedConnection(async (pinnedAdapter) => {
19890
+ const pinnedOrm = createOrmInstance(
19891
+ model,
19892
+ strictMode,
19893
+ relationHints,
19894
+ pinnedAdapter,
19895
+ schemaName,
19896
+ dialectCapabilities,
19897
+ schemaDefinition,
19898
+ globalPlanOptions,
19899
+ defaultFilters,
19900
+ hookStore,
19901
+ onHookError,
19902
+ pinnedAdapter.inTransaction,
19903
+ tablesProxy
19904
+ );
19905
+ return fn2(pinnedOrm);
19906
+ }, options);
19696
19907
  } catch (error) {
19697
19908
  return Promise.reject(error);
19698
19909
  }
@@ -19725,13 +19936,18 @@ function createOrmInstance(model, strictMode, relationHints, adapter, schemaName
19725
19936
  *
19726
19937
  * @see {@link https://owasp.org/www-community/attacks/SQL_Injection | OWASP SQL Injection}
19727
19938
  */
19728
- async raw(sqlString, parameters = []) {
19939
+ async raw(sqlString, parameters = [], options) {
19729
19940
  if (!adapter) {
19730
19941
  throw new Error(
19731
19942
  "raw() requires an adapter. Pass an adapter when creating the ORM."
19732
19943
  );
19733
19944
  }
19734
- return adapter.executeRaw(sqlString, parameters);
19945
+ const rows = await adapter.executeRaw(sqlString, parameters);
19946
+ const bigintReads = options?.bigintReads;
19947
+ if (!bigintReads || Object.keys(bigintReads).length === 0) {
19948
+ return rows;
19949
+ }
19950
+ return rows.map((row) => applyBigintReads(row, bigintReads));
19735
19951
  },
19736
19952
  batchValues(data, columns, types, opts) {
19737
19953
  return batchValues(data, columns, types, opts);
@@ -19788,19 +20004,16 @@ function createOrmInstance(model, strictMode, relationHints, adapter, schemaName
19788
20004
  );
19789
20005
  }
19790
20006
  validateIdentifier(name, "index");
19791
- const sc = options?.schema ?? schemaName;
19792
- if (sc) {
19793
- validateIdentifier(sc, "schema");
19794
- }
19795
- const scopedOptions = sc ? { ...options, schema: sc } : options;
19796
- const sql2 = adapter.generateDropIndex ? adapter.generateDropIndex(name, scopedOptions) : (() => {
20007
+ const ddlSchemaName = resolveDDLSchemaName(schemaName);
20008
+ const sanitizedOptions = sanitizeDropIndexOptions(options);
20009
+ const sql2 = adapter.generateDropIndex ? adapter.generateDropIndex(name, ddlSchemaName, sanitizedOptions) : (() => {
19797
20010
  const parts = ["DROP INDEX"];
19798
- if (options?.concurrently) parts.push("CONCURRENTLY");
19799
- if (options?.ifExists) parts.push("IF EXISTS");
20011
+ if (sanitizedOptions?.concurrently) parts.push("CONCURRENTLY");
20012
+ if (sanitizedOptions?.ifExists) parts.push("IF EXISTS");
19800
20013
  parts.push(
19801
- sc ? `"${sc.replace(/"/g, '""')}"."${name.replace(/"/g, '""')}"` : `"${name.replace(/"/g, '""')}"`
20014
+ `"${ddlSchemaName.replace(/"/g, '""')}"."${name.replace(/"/g, '""')}"`
19802
20015
  );
19803
- if (options?.cascade) parts.push("CASCADE");
20016
+ if (sanitizedOptions?.cascade) parts.push("CASCADE");
19804
20017
  return parts.join(" ");
19805
20018
  })();
19806
20019
  await adapter.executeDDL(sql2);