@dbsp/adapter-pgsql 3.4.0 → 3.5.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 -1
- package/dist/index.js +283 -18
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -960,6 +960,10 @@ declare class PgsqlTransactionTimeoutError extends Error {
|
|
|
960
960
|
/**
|
|
961
961
|
* Options for PgsqlAdapter.
|
|
962
962
|
*/
|
|
963
|
+
interface PgsqlPreparedStatementsOptions {
|
|
964
|
+
/** Maximum distinct compiled statements admitted per executor (default: 500). */
|
|
965
|
+
readonly maxStatements?: number;
|
|
966
|
+
}
|
|
963
967
|
interface PgsqlAdapterOptions {
|
|
964
968
|
/** Schema name for multi-tenant queries */
|
|
965
969
|
readonly schemaName?: string;
|
|
@@ -978,6 +982,11 @@ interface PgsqlAdapterOptions {
|
|
|
978
982
|
readonly defaultPkColumnName?: string;
|
|
979
983
|
/** Convention for deriving FK column names: (tableName, pkName) => fkColumnName */
|
|
980
984
|
readonly deriveFkColumnName?: FkColumnDerivation;
|
|
985
|
+
/**
|
|
986
|
+
* Opt in to node-postgres named prepared statements for compiled queries with
|
|
987
|
+
* parameters. `true` uses the default statement cap; an object overrides it.
|
|
988
|
+
*/
|
|
989
|
+
readonly preparedStatements?: boolean | PgsqlPreparedStatementsOptions;
|
|
981
990
|
}
|
|
982
991
|
interface PgsqlPoolAdapterOptions extends PgsqlAdapterOptions {
|
|
983
992
|
readonly borrowedClient?: false;
|
|
@@ -1042,6 +1051,8 @@ declare class PgsqlAdapter<DB = unknown> implements Adapter<DB> {
|
|
|
1042
1051
|
private readonly naming;
|
|
1043
1052
|
private readonly model;
|
|
1044
1053
|
private readonly logger;
|
|
1054
|
+
private readonly preparedStatements;
|
|
1055
|
+
private readonly preparedStatementRegistry;
|
|
1045
1056
|
private readonly _capabilities;
|
|
1046
1057
|
private readonly defaultPk;
|
|
1047
1058
|
private readonly deriveFk;
|
|
@@ -3585,4 +3596,4 @@ declare function escapeDiagnosticText(value: string): string;
|
|
|
3585
3596
|
*/
|
|
3586
3597
|
declare function validateSqlExpression(sql: string, context: string): void;
|
|
3587
3598
|
|
|
3588
|
-
export { ADD_CHECK_RULE_ID, ALTER_AUTHORITY_OBSERVATION, ALTER_COLUMN_SET_NOT_NULL_OPERATION_KIND, ALTER_TYPE_ADD_VALUE_OPERATION_KIND, ATTACH_LOGICAL_IDENTITY_OPERATION_KIND, type AddedEnumValue, type AlterColumnSetNotNullPayload, type AlterTypeAddValuePayload, type AttachLogicalIdentityPayload, type BatchValuesJoinDecision, COLUMN_EXISTS_OBSERVATION, CamelCaseNamingPlugin, type CanonicalizeCheckConstraintsOptions, type ChangeKind, CheckConstraintCanonicalizationError, type CheckConstraintCanonicalizationWarning, CheckConstraintNewEnumValueError, ColumnDefaultCanonicalizationError, type ColumnDefaultCanonicalizationWarning, type ComparePgsqlDatabaseSchemaOptions, type CompareSchemataOptions, type CompiledResult, type CompilerContext, type CompilerOptions, type CompilerState, type ConflictAction, type ConflictTarget, type CursorHoldOption, type CursorOptions, type CursorScrollOption, DBSP_LOGICAL_IDENTITY_TABLE, DBSP_META_SCHEMA, DBSP_TRANSITION_JOURNAL_TABLE, DBSP_TRANSITION_RUN_PLAN_TABLE, DBSP_TRANSITION_RUN_TABLE, DEFAULT_PK_COLUMN, DEFAULT_REDACTION_PATTERNS, type Decision, type DeleteConfig, type DetectedHierarchy, type DiffSummary, ENGINE_VERSION_OBSERVATION, ENUM_ADD_VALUE_RULE_ID, ENUM_LABEL_VISIBLE_OBSERVATION, ENUM_TYPE_EXISTS_OBSERVATION, type EnumAddValueMatch, type EnumAddValueRuleOptions, type ExplainFormat, type ExplainOptions, type ExplainPlan, ExpressionCanonicalizationUnavailableError, type ExpressionCanonicalizationWarning, type ExpressionHandler, type FetchDirection, type FetchOptions, type FkColumnDerivation, type GenerateDDLOptions, type IdentityAdoptionAsserter, IdentityNamingPlugin, type IncludeHandler, type IncludeResult, type IndexCapabilityContext, IndexFeatureUnsupportedError, type IndexRenderSpec, type InsertConfig, type IntrospectedModelIR, type IntrospectionOptions, InvalidIdentifierError, type JoinDecision, LOGICAL_IDENTITY_ADOPTION_RULE_ID, LOGICAL_IDENTITY_CARRIER_OBSERVATION, type LeafCompileFn, type LogicalIdentityAdoptionMatch, type LogicalIdentityAdoptionRuleOptions, MANUAL_SQL_OPERATION_KIND, type ManualSqlPayload, type MigrationRecord, type MigrationSQLOptions, NO_NULLS_GUARD, type NamingPlugin, NonConvergentSchemaDiffError, type NonConvergentSchemaDiffSurface, PG_INTROSPECTION_ARTIFACT, PG_OPERATION_PACK_ARTIFACT, PG_RULE_PACK_ARTIFACT, type ParamRefValidationResult, type ParsedMigrationFile, type PgAdvisoryLockKey, type PgAdvisoryLockResult, PgExecutionContractDerivationError, type PgTransitionClientLease, type PgTransitionPackOptions, PgsqlAdapter, type PgsqlAdapterOptions, PgsqlAdvisoryLockOptionsError, type PgsqlBorrowedClientAdapterOptions, PgsqlPinnedConnectionAbortSignalError, type PgsqlPoolAdapterOptions, PgsqlRawSqlTransactionControlError, PgsqlTransactionAbortSignalError, PgsqlTransactionAbortedCommitError, PgsqlTransactionAbortedError, PgsqlTransactionOptionsError, PgsqlTransactionTimeoutError, PlanCompiler, type PlanDecision, type PrecompiledJoinDecision, type RedactionConfig, type RedactionPattern, type RollbackOnlyPgsqlScope, SET_NOT_NULL_RULE_ID, type SchemaChange, type SchemaDiff, type SchemaScopeOptions, type SetNotNullMatch, type SetNotNullRuleOptions, type SetOperationResult, type SimplifiedPlanReport, type StreamConfig, type UpdateConfig, type UpsertConfig, type WhereDispatcher, type WhereHandler, acquirePgTransitionClient, assertCreateIndexSupported, assertCreateIndexesSupported, assertNoRepeatedExpressionSurfaceDrift, bm25Search, booleanSearch, boost, buildCloseCursor, buildDeclareCursor, buildExplain, buildExplainAnalyzeJson, buildExplainPlan, buildExplainVerbose, buildFetch, buildFetchAll, buildFetchFirst, buildFetchForward, buildFetchNext, buildOnConflictClause, buildStreamingStatements, camelCaseNaming, canGenerateCreateIndex, canonicalizeCheckConstraints, collectAndValidateParamRefs, comparePgsqlDatabaseSchema, compareSchemata, compileDelete, compileInsert, compileMutation, compilePlan, compileSetOperation, compileUpdate, compileUpsert, conditionalUpdate, cosineDistance, createAlterColumnSetNotNullOperationRuntime, createAlterTypeAddValueOperationRuntime, createAnyExpr, createAttachLogicalIdentityOperationRuntime, createEnumAddValueRule, createEqualityExpr, createLeafCompileFn, createLogicalIdentityAdoptionRule, createManualSqlOperationRuntime, createParamRef, createPgExecutionContract, createPgObservationIssuer, createPgTransitionLessor, createPgTransitionPack, createPgTransitionRunPersister, createPgsqlAdapter, createPgsqlCompileOnlyAdapter, createSetNotNullRule, createTypeCastParamRef, defaultFkDerivation, derivePostgresqlCapabilitiesForVersion, ensureMigrationsTable, ensureTransitionJournal, escapeDiagnosticText, evaluatePgExecutionContract, excludedRef, executePgObservationFromLessor, generateCreateIndex, generateCursorName, generateDDL, generateDownSQL, generateMigrationFile, generateMigrationSQL, generateSeries, getAppliedMigrations, getNamingPluginForDbCasing, getNextSchemaVersion, getRowEstimates, getTotalExecutionTime, identityNaming, innerProduct, introspect, isBatchValuesJoinDecision, isDestructiveDown, isJoinDecision, isMigrationApplied, isPrecompiledJoinDecision, isReservedKeyword, l2Distance, mapColumnType, mapOnDeleteAction, nextval, normalizeManualSqlPayload, parse, parseExplainJson, parseMigrationFile, pgTargetIdentityMismatch, rawDistance, readPgExecutionTargetFromClient, readPgObservationContextFromLessor, readTransitionJournal, recordMigration, redactParams, removeMigrationRecord, renderAlterColumnSetNotNullSql, renderAlterTypeAddValueSql, renderAttachLogicalIdentityLockSql, renderCreateDbspMetaSchemaSql, renderCreateIndex, renderCreateLogicalIdentityIndexesSql, renderCreateLogicalIdentitySideTableSql, renderCreateTransitionJournalTableSql, renderCreateTransitionRunPlanTableSql, renderCreateTransitionRunTableSql, renderInsertLogicalIdentitySql, renderNoNullsCheckSql, renderSetNotNullLockSql, resolveLogicalName, sanitizeForDisplay, score, validateIdentifier, validateIdentifiers, validateParamRef, validateQualifiedIdentifier, validateSqlExpression, vectorDims, withMigrationLock };
|
|
3599
|
+
export { ADD_CHECK_RULE_ID, ALTER_AUTHORITY_OBSERVATION, ALTER_COLUMN_SET_NOT_NULL_OPERATION_KIND, ALTER_TYPE_ADD_VALUE_OPERATION_KIND, ATTACH_LOGICAL_IDENTITY_OPERATION_KIND, type AddedEnumValue, type AlterColumnSetNotNullPayload, type AlterTypeAddValuePayload, type AttachLogicalIdentityPayload, type BatchValuesJoinDecision, COLUMN_EXISTS_OBSERVATION, CamelCaseNamingPlugin, type CanonicalizeCheckConstraintsOptions, type ChangeKind, CheckConstraintCanonicalizationError, type CheckConstraintCanonicalizationWarning, CheckConstraintNewEnumValueError, ColumnDefaultCanonicalizationError, type ColumnDefaultCanonicalizationWarning, type ComparePgsqlDatabaseSchemaOptions, type CompareSchemataOptions, type CompiledResult, type CompilerContext, type CompilerOptions, type CompilerState, type ConflictAction, type ConflictTarget, type CursorHoldOption, type CursorOptions, type CursorScrollOption, DBSP_LOGICAL_IDENTITY_TABLE, DBSP_META_SCHEMA, DBSP_TRANSITION_JOURNAL_TABLE, DBSP_TRANSITION_RUN_PLAN_TABLE, DBSP_TRANSITION_RUN_TABLE, DEFAULT_PK_COLUMN, DEFAULT_REDACTION_PATTERNS, type Decision, type DeleteConfig, type DetectedHierarchy, type DiffSummary, ENGINE_VERSION_OBSERVATION, ENUM_ADD_VALUE_RULE_ID, ENUM_LABEL_VISIBLE_OBSERVATION, ENUM_TYPE_EXISTS_OBSERVATION, type EnumAddValueMatch, type EnumAddValueRuleOptions, type ExplainFormat, type ExplainOptions, type ExplainPlan, ExpressionCanonicalizationUnavailableError, type ExpressionCanonicalizationWarning, type ExpressionHandler, type FetchDirection, type FetchOptions, type FkColumnDerivation, type GenerateDDLOptions, type IdentityAdoptionAsserter, IdentityNamingPlugin, type IncludeHandler, type IncludeResult, type IndexCapabilityContext, IndexFeatureUnsupportedError, type IndexRenderSpec, type InsertConfig, type IntrospectedModelIR, type IntrospectionOptions, InvalidIdentifierError, type JoinDecision, LOGICAL_IDENTITY_ADOPTION_RULE_ID, LOGICAL_IDENTITY_CARRIER_OBSERVATION, type LeafCompileFn, type LogicalIdentityAdoptionMatch, type LogicalIdentityAdoptionRuleOptions, MANUAL_SQL_OPERATION_KIND, type ManualSqlPayload, type MigrationRecord, type MigrationSQLOptions, NO_NULLS_GUARD, type NamingPlugin, NonConvergentSchemaDiffError, type NonConvergentSchemaDiffSurface, PG_INTROSPECTION_ARTIFACT, PG_OPERATION_PACK_ARTIFACT, PG_RULE_PACK_ARTIFACT, type ParamRefValidationResult, type ParsedMigrationFile, type PgAdvisoryLockKey, type PgAdvisoryLockResult, PgExecutionContractDerivationError, type PgTransitionClientLease, type PgTransitionPackOptions, PgsqlAdapter, type PgsqlAdapterOptions, PgsqlAdvisoryLockOptionsError, type PgsqlBorrowedClientAdapterOptions, PgsqlPinnedConnectionAbortSignalError, type PgsqlPoolAdapterOptions, type PgsqlPreparedStatementsOptions, PgsqlRawSqlTransactionControlError, PgsqlTransactionAbortSignalError, PgsqlTransactionAbortedCommitError, PgsqlTransactionAbortedError, PgsqlTransactionOptionsError, PgsqlTransactionTimeoutError, PlanCompiler, type PlanDecision, type PrecompiledJoinDecision, type RedactionConfig, type RedactionPattern, type RollbackOnlyPgsqlScope, SET_NOT_NULL_RULE_ID, type SchemaChange, type SchemaDiff, type SchemaScopeOptions, type SetNotNullMatch, type SetNotNullRuleOptions, type SetOperationResult, type SimplifiedPlanReport, type StreamConfig, type UpdateConfig, type UpsertConfig, type WhereDispatcher, type WhereHandler, acquirePgTransitionClient, assertCreateIndexSupported, assertCreateIndexesSupported, assertNoRepeatedExpressionSurfaceDrift, bm25Search, booleanSearch, boost, buildCloseCursor, buildDeclareCursor, buildExplain, buildExplainAnalyzeJson, buildExplainPlan, buildExplainVerbose, buildFetch, buildFetchAll, buildFetchFirst, buildFetchForward, buildFetchNext, buildOnConflictClause, buildStreamingStatements, camelCaseNaming, canGenerateCreateIndex, canonicalizeCheckConstraints, collectAndValidateParamRefs, comparePgsqlDatabaseSchema, compareSchemata, compileDelete, compileInsert, compileMutation, compilePlan, compileSetOperation, compileUpdate, compileUpsert, conditionalUpdate, cosineDistance, createAlterColumnSetNotNullOperationRuntime, createAlterTypeAddValueOperationRuntime, createAnyExpr, createAttachLogicalIdentityOperationRuntime, createEnumAddValueRule, createEqualityExpr, createLeafCompileFn, createLogicalIdentityAdoptionRule, createManualSqlOperationRuntime, createParamRef, createPgExecutionContract, createPgObservationIssuer, createPgTransitionLessor, createPgTransitionPack, createPgTransitionRunPersister, createPgsqlAdapter, createPgsqlCompileOnlyAdapter, createSetNotNullRule, createTypeCastParamRef, defaultFkDerivation, derivePostgresqlCapabilitiesForVersion, ensureMigrationsTable, ensureTransitionJournal, escapeDiagnosticText, evaluatePgExecutionContract, excludedRef, executePgObservationFromLessor, generateCreateIndex, generateCursorName, generateDDL, generateDownSQL, generateMigrationFile, generateMigrationSQL, generateSeries, getAppliedMigrations, getNamingPluginForDbCasing, getNextSchemaVersion, getRowEstimates, getTotalExecutionTime, identityNaming, innerProduct, introspect, isBatchValuesJoinDecision, isDestructiveDown, isJoinDecision, isMigrationApplied, isPrecompiledJoinDecision, isReservedKeyword, l2Distance, mapColumnType, mapOnDeleteAction, nextval, normalizeManualSqlPayload, parse, parseExplainJson, parseMigrationFile, pgTargetIdentityMismatch, rawDistance, readPgExecutionTargetFromClient, readPgObservationContextFromLessor, readTransitionJournal, recordMigration, redactParams, removeMigrationRecord, renderAlterColumnSetNotNullSql, renderAlterTypeAddValueSql, renderAttachLogicalIdentityLockSql, renderCreateDbspMetaSchemaSql, renderCreateIndex, renderCreateLogicalIdentityIndexesSql, renderCreateLogicalIdentitySideTableSql, renderCreateTransitionJournalTableSql, renderCreateTransitionRunPlanTableSql, renderCreateTransitionRunTableSql, renderInsertLogicalIdentitySql, renderNoNullsCheckSql, renderSetNotNullLockSql, resolveLogicalName, sanitizeForDisplay, score, validateIdentifier, validateIdentifiers, validateParamRef, validateQualifiedIdentifier, validateSqlExpression, vectorDims, withMigrationLock };
|
package/dist/index.js
CHANGED
|
@@ -23010,6 +23010,123 @@ function matchGlob(pattern, value) {
|
|
|
23010
23010
|
|
|
23011
23011
|
// src/pgsql-adapter.ts
|
|
23012
23012
|
init_naming_plugin();
|
|
23013
|
+
|
|
23014
|
+
// src/prepared-statements.ts
|
|
23015
|
+
import { createHash as createHash2 } from "crypto";
|
|
23016
|
+
var DEFAULT_MAX_PREPARED_STATEMENTS = 500;
|
|
23017
|
+
var PREPARED_STATEMENT_NAMESPACE = "dbsp_ps_";
|
|
23018
|
+
function derivePreparedStatementFingerprint(sql) {
|
|
23019
|
+
return createHash2("sha256").update(sql).digest("hex");
|
|
23020
|
+
}
|
|
23021
|
+
function derivePreparedStatementName(sql) {
|
|
23022
|
+
return `${PREPARED_STATEMENT_NAMESPACE}${derivePreparedStatementFingerprint(sql).slice(0, 32)}`;
|
|
23023
|
+
}
|
|
23024
|
+
var PreparedStatementRegistry = class {
|
|
23025
|
+
constructor(maxStatements, hashName = derivePreparedStatementName) {
|
|
23026
|
+
this.maxStatements = maxStatements;
|
|
23027
|
+
this.hashName = hashName;
|
|
23028
|
+
}
|
|
23029
|
+
maxStatements;
|
|
23030
|
+
hashName;
|
|
23031
|
+
candidates = /* @__PURE__ */ new Set();
|
|
23032
|
+
namesByFingerprint = /* @__PURE__ */ new Map();
|
|
23033
|
+
fingerprintsByName = /* @__PURE__ */ new Map();
|
|
23034
|
+
pendingByFingerprint = /* @__PURE__ */ new Map();
|
|
23035
|
+
collisionRejectedFingerprints = /* @__PURE__ */ new Set();
|
|
23036
|
+
nextGeneration = 0;
|
|
23037
|
+
/**
|
|
23038
|
+
* Reserves a name only from the second sighting onward. Call confirm after
|
|
23039
|
+
* successful named execution, or abort when that execution fails.
|
|
23040
|
+
*/
|
|
23041
|
+
admit(sql) {
|
|
23042
|
+
const fingerprint = derivePreparedStatementFingerprint(sql);
|
|
23043
|
+
if (this.collisionRejectedFingerprints.has(fingerprint)) return void 0;
|
|
23044
|
+
const knownName = this.namesByFingerprint.get(fingerprint);
|
|
23045
|
+
if (knownName !== void 0) return { name: knownName };
|
|
23046
|
+
const pending = this.pendingByFingerprint.get(fingerprint);
|
|
23047
|
+
if (pending !== void 0) {
|
|
23048
|
+
return this.reserveAttempt(fingerprint, pending);
|
|
23049
|
+
}
|
|
23050
|
+
if (!this.candidates.delete(fingerprint)) {
|
|
23051
|
+
if (this.atCapacity()) return void 0;
|
|
23052
|
+
if (this.candidates.size >= this.maxStatements) {
|
|
23053
|
+
const oldest = this.candidates.values().next().value;
|
|
23054
|
+
if (oldest !== void 0) this.candidates.delete(oldest);
|
|
23055
|
+
}
|
|
23056
|
+
this.candidates.add(fingerprint);
|
|
23057
|
+
return void 0;
|
|
23058
|
+
}
|
|
23059
|
+
if (this.atCapacity()) return void 0;
|
|
23060
|
+
const name = this.hashName(sql);
|
|
23061
|
+
const existingFingerprint = this.fingerprintsByName.get(name);
|
|
23062
|
+
if (existingFingerprint !== void 0 && existingFingerprint !== fingerprint) {
|
|
23063
|
+
this.rejectHashCollision(fingerprint);
|
|
23064
|
+
return void 0;
|
|
23065
|
+
}
|
|
23066
|
+
this.fingerprintsByName.set(name, fingerprint);
|
|
23067
|
+
const reservation = this.reserveAttempt(fingerprint, {
|
|
23068
|
+
name,
|
|
23069
|
+
generations: /* @__PURE__ */ new Set()
|
|
23070
|
+
});
|
|
23071
|
+
if (this.atCapacity()) this.candidates.clear();
|
|
23072
|
+
return reservation;
|
|
23073
|
+
}
|
|
23074
|
+
/** Confirms a reservation only after PostgreSQL accepted its named execution. */
|
|
23075
|
+
confirm(reservation) {
|
|
23076
|
+
const pending = this.pendingByFingerprint.get(reservation.fingerprint);
|
|
23077
|
+
if (pending === void 0 || pending.name !== reservation.name || !pending.generations.has(reservation.generation))
|
|
23078
|
+
return;
|
|
23079
|
+
this.pendingByFingerprint.delete(reservation.fingerprint);
|
|
23080
|
+
this.namesByFingerprint.set(reservation.fingerprint, reservation.name);
|
|
23081
|
+
}
|
|
23082
|
+
/** Aborts only this still-pending attempt, never a later confirmation. */
|
|
23083
|
+
abort(reservation) {
|
|
23084
|
+
const pending = this.pendingByFingerprint.get(reservation.fingerprint);
|
|
23085
|
+
if (pending === void 0 || pending.name !== reservation.name || !pending.generations.delete(reservation.generation))
|
|
23086
|
+
return;
|
|
23087
|
+
if (pending.generations.size !== 0) return;
|
|
23088
|
+
this.pendingByFingerprint.delete(reservation.fingerprint);
|
|
23089
|
+
if (this.fingerprintsByName.get(reservation.name) === reservation.fingerprint) {
|
|
23090
|
+
this.fingerprintsByName.delete(reservation.name);
|
|
23091
|
+
}
|
|
23092
|
+
}
|
|
23093
|
+
atCapacity() {
|
|
23094
|
+
return this.namesByFingerprint.size + this.pendingByFingerprint.size >= this.maxStatements;
|
|
23095
|
+
}
|
|
23096
|
+
reserveAttempt(fingerprint, pending) {
|
|
23097
|
+
this.pendingByFingerprint.set(fingerprint, pending);
|
|
23098
|
+
const reservation = {
|
|
23099
|
+
fingerprint,
|
|
23100
|
+
name: pending.name,
|
|
23101
|
+
generation: this.nextGeneration++
|
|
23102
|
+
};
|
|
23103
|
+
pending.generations.add(reservation.generation);
|
|
23104
|
+
return { name: pending.name, reservation };
|
|
23105
|
+
}
|
|
23106
|
+
/** Keeps a colliding full fingerprint unnamed within a bounded registry. */
|
|
23107
|
+
rejectHashCollision(fingerprint) {
|
|
23108
|
+
if (this.collisionRejectedFingerprints.size >= this.maxStatements) {
|
|
23109
|
+
const oldest = this.collisionRejectedFingerprints.values().next().value;
|
|
23110
|
+
if (oldest !== void 0)
|
|
23111
|
+
this.collisionRejectedFingerprints.delete(oldest);
|
|
23112
|
+
}
|
|
23113
|
+
this.collisionRejectedFingerprints.add(fingerprint);
|
|
23114
|
+
this.candidates.delete(fingerprint);
|
|
23115
|
+
}
|
|
23116
|
+
};
|
|
23117
|
+
function normalizeMaxPreparedStatements(maxStatements) {
|
|
23118
|
+
const resolved = maxStatements === void 0 ? DEFAULT_MAX_PREPARED_STATEMENTS : maxStatements;
|
|
23119
|
+
if (!Number.isSafeInteger(resolved))
|
|
23120
|
+
throw new Error("preparedStatements.maxStatements must be a safe integer.");
|
|
23121
|
+
const normalized = resolved;
|
|
23122
|
+
if (normalized < 1)
|
|
23123
|
+
throw new Error(
|
|
23124
|
+
"preparedStatements.maxStatements must be greater than zero."
|
|
23125
|
+
);
|
|
23126
|
+
return normalized;
|
|
23127
|
+
}
|
|
23128
|
+
|
|
23129
|
+
// src/pgsql-adapter.ts
|
|
23013
23130
|
init_cte_compiler();
|
|
23014
23131
|
|
|
23015
23132
|
// src/set-operation.ts
|
|
@@ -23264,6 +23381,8 @@ var pgsqlAdapterInternalOptionsKey = /* @__PURE__ */ Symbol(
|
|
|
23264
23381
|
"dbsp-pgsql-adapter-internal-options"
|
|
23265
23382
|
);
|
|
23266
23383
|
var activeClientScopes = /* @__PURE__ */ new WeakMap();
|
|
23384
|
+
var preparedStatementRegistries = /* @__PURE__ */ new WeakMap();
|
|
23385
|
+
var preparedStatementQuarantines = /* @__PURE__ */ new WeakMap();
|
|
23267
23386
|
var PgsqlRawSqlTransactionControlError = class extends Error {
|
|
23268
23387
|
dbspRawSqlTransactionControl = true;
|
|
23269
23388
|
constructor(cause) {
|
|
@@ -23334,6 +23453,57 @@ function poolClientTransactionOpen(client) {
|
|
|
23334
23453
|
function isPgErrorWithCode(error, code) {
|
|
23335
23454
|
return typeof error === "object" && error !== null && "code" in error && error.code === code;
|
|
23336
23455
|
}
|
|
23456
|
+
function isDriverLocalPreparedStatementNameCollision(error, attemptedName) {
|
|
23457
|
+
const message = `Prepared statements must be unique - '${attemptedName}' was used for a different statement`;
|
|
23458
|
+
return error instanceof Error && !("code" in error) && error.message === message;
|
|
23459
|
+
}
|
|
23460
|
+
function isVerifiedPreparedStatementInfrastructureError(error) {
|
|
23461
|
+
if (typeof error !== "object" || error === null) return false;
|
|
23462
|
+
const { code, routine } = error;
|
|
23463
|
+
return code === "0A000" && routine === "RevalidateCachedQuery" || code === "26000" && routine === "FetchPreparedStatement" || code === "42P05" && routine === "StorePreparedStatement";
|
|
23464
|
+
}
|
|
23465
|
+
function didNamedExecutionReachExecution(error) {
|
|
23466
|
+
if (typeof error !== "object" || error === null) return false;
|
|
23467
|
+
const { code, position } = error;
|
|
23468
|
+
return typeof code === "string" && /^[0-9A-Z]{5}$/.test(code) && position === void 0 && !isVerifiedPreparedStatementInfrastructureError(error);
|
|
23469
|
+
}
|
|
23470
|
+
function shouldAbortPreparedStatementReservation(error, executor, attemptedName) {
|
|
23471
|
+
if (typeof error === "object" && error !== null && "position" in error && error.position !== void 0)
|
|
23472
|
+
return true;
|
|
23473
|
+
if (isDriverLocalPreparedStatementNameCollision(error, attemptedName))
|
|
23474
|
+
return true;
|
|
23475
|
+
if (!isPoolClientLike(executor)) return false;
|
|
23476
|
+
if (didNamedExecutionReachExecution(error)) return false;
|
|
23477
|
+
return !(error instanceof Error && error.message.startsWith("Prepared statements must be unique - '"));
|
|
23478
|
+
}
|
|
23479
|
+
function isVerifiedClientWidePreparedStatementLoss(error) {
|
|
23480
|
+
if (typeof error !== "object" || error === null) return false;
|
|
23481
|
+
const { code, routine } = error;
|
|
23482
|
+
return code === "26000" && routine === "FetchPreparedStatement";
|
|
23483
|
+
}
|
|
23484
|
+
function isPreparedStatementQuarantined(client, sql) {
|
|
23485
|
+
const quarantine = preparedStatementQuarantines.get(client);
|
|
23486
|
+
return quarantine?.allStatements === true || quarantine?.fingerprints.has(derivePreparedStatementFingerprint(sql)) === true;
|
|
23487
|
+
}
|
|
23488
|
+
function hasPreparedStatementQuarantine(client) {
|
|
23489
|
+
return preparedStatementQuarantines.has(client);
|
|
23490
|
+
}
|
|
23491
|
+
function quarantinePreparedStatement(client, sql, clientWide) {
|
|
23492
|
+
const quarantine = preparedStatementQuarantines.get(client);
|
|
23493
|
+
if (quarantine !== void 0) {
|
|
23494
|
+
if (clientWide) {
|
|
23495
|
+
quarantine.allStatements = true;
|
|
23496
|
+
quarantine.fingerprints.clear();
|
|
23497
|
+
} else if (!quarantine.allStatements) {
|
|
23498
|
+
quarantine.fingerprints.add(derivePreparedStatementFingerprint(sql));
|
|
23499
|
+
}
|
|
23500
|
+
return;
|
|
23501
|
+
}
|
|
23502
|
+
preparedStatementQuarantines.set(client, {
|
|
23503
|
+
allStatements: clientWide,
|
|
23504
|
+
fingerprints: clientWide ? /* @__PURE__ */ new Set() : /* @__PURE__ */ new Set([derivePreparedStatementFingerprint(sql)])
|
|
23505
|
+
});
|
|
23506
|
+
}
|
|
23337
23507
|
function describeTransactionOptionValue(value) {
|
|
23338
23508
|
if (value === null) return "null";
|
|
23339
23509
|
if (typeof value === "string") return `string ${JSON.stringify(value)}`;
|
|
@@ -24357,6 +24527,45 @@ function getDbspScopeTokenOption(options) {
|
|
|
24357
24527
|
function getDbspScopeStateOption(options) {
|
|
24358
24528
|
return isPgsqlAdapterInternalOptions(options) ? options.dbspScopeState : void 0;
|
|
24359
24529
|
}
|
|
24530
|
+
function getPreparedStatementRegistryOption(options) {
|
|
24531
|
+
return isPgsqlAdapterInternalOptions(options) ? options.preparedStatementRegistry : void 0;
|
|
24532
|
+
}
|
|
24533
|
+
function getOrCreatePreparedStatementRegistry(executor, maxStatements) {
|
|
24534
|
+
const configured = preparedStatementRegistries.get(executor);
|
|
24535
|
+
if (configured === void 0) {
|
|
24536
|
+
const registry = new PreparedStatementRegistry(maxStatements);
|
|
24537
|
+
preparedStatementRegistries.set(executor, { maxStatements, registry });
|
|
24538
|
+
return registry;
|
|
24539
|
+
}
|
|
24540
|
+
if (configured.maxStatements !== maxStatements) {
|
|
24541
|
+
const executorKind = isPoolClientLike(executor) ? "borrowed client" : "pool";
|
|
24542
|
+
throw new Error(
|
|
24543
|
+
`preparedStatements.maxStatements is configured ${executorKind}-wide: expected ${configured.maxStatements}, received ${maxStatements}.`
|
|
24544
|
+
);
|
|
24545
|
+
}
|
|
24546
|
+
return configured.registry;
|
|
24547
|
+
}
|
|
24548
|
+
function normalizePreparedStatements(value) {
|
|
24549
|
+
if (value === void 0 || value === false) return false;
|
|
24550
|
+
if (value === true) {
|
|
24551
|
+
return Object.freeze({
|
|
24552
|
+
maxStatements: normalizeMaxPreparedStatements(void 0)
|
|
24553
|
+
});
|
|
24554
|
+
}
|
|
24555
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
24556
|
+
throw new Error(
|
|
24557
|
+
"preparedStatements must be true, false, or a non-null options object."
|
|
24558
|
+
);
|
|
24559
|
+
}
|
|
24560
|
+
return Object.freeze({
|
|
24561
|
+
maxStatements: normalizeMaxPreparedStatements(
|
|
24562
|
+
value.maxStatements
|
|
24563
|
+
)
|
|
24564
|
+
});
|
|
24565
|
+
}
|
|
24566
|
+
function clonePreparedStatements(config) {
|
|
24567
|
+
return config === false ? false : { maxStatements: config.maxStatements };
|
|
24568
|
+
}
|
|
24360
24569
|
function createPgsqlAdapterFromConstructionOptions(connection, options) {
|
|
24361
24570
|
return new PgsqlAdapter(
|
|
24362
24571
|
connection,
|
|
@@ -24378,6 +24587,8 @@ var PgsqlAdapter = class {
|
|
|
24378
24587
|
naming;
|
|
24379
24588
|
model;
|
|
24380
24589
|
logger;
|
|
24590
|
+
preparedStatements;
|
|
24591
|
+
preparedStatementRegistry;
|
|
24381
24592
|
_capabilities;
|
|
24382
24593
|
defaultPk;
|
|
24383
24594
|
deriveFk;
|
|
@@ -24424,6 +24635,15 @@ var PgsqlAdapter = class {
|
|
|
24424
24635
|
this.naming = getNamingPluginForDbCasing(this._dbCasing);
|
|
24425
24636
|
this.model = options?.model;
|
|
24426
24637
|
this.logger = options?.logger;
|
|
24638
|
+
this.preparedStatements = normalizePreparedStatements(
|
|
24639
|
+
options?.preparedStatements
|
|
24640
|
+
);
|
|
24641
|
+
if (this.preparedStatements !== false) {
|
|
24642
|
+
const { maxStatements } = this.preparedStatements;
|
|
24643
|
+
this.preparedStatementRegistry = getPreparedStatementRegistryOption(options) ?? (this.pool !== void 0 ? getOrCreatePreparedStatementRegistry(this.pool, maxStatements) : this.client !== void 0 ? getOrCreatePreparedStatementRegistry(this.client, maxStatements) : void 0);
|
|
24644
|
+
} else {
|
|
24645
|
+
this.preparedStatementRegistry = void 0;
|
|
24646
|
+
}
|
|
24427
24647
|
this.defaultPk = options?.defaultPkColumnName ?? DEFAULT_PK_COLUMN;
|
|
24428
24648
|
this.deriveFk = options?.deriveFkColumnName ?? defaultFkDerivation;
|
|
24429
24649
|
const supportsManagedTransactions = this.pool != null || this.client != null && this.managedTransactions;
|
|
@@ -24454,7 +24674,8 @@ var PgsqlAdapter = class {
|
|
|
24454
24674
|
const scopeToken = overrides.dbspScopeToken ?? this.scopeToken;
|
|
24455
24675
|
const scopeState = overrides.dbspScopeState ?? this.scopeState;
|
|
24456
24676
|
const rollbackOnlyScope = overrides.rollbackOnlyScope ?? this.rollbackOnlyScope ? true : void 0;
|
|
24457
|
-
const
|
|
24677
|
+
const preparedStatementRegistry = this.preparedStatementRegistry;
|
|
24678
|
+
const hasInternalOptions = adapterManagedTransaction === true || adapterManagedPinnedConnection === true || rollbackOnlyScope === true || scopeToken !== void 0 || scopeState !== void 0 || preparedStatementRegistry !== void 0;
|
|
24458
24679
|
return {
|
|
24459
24680
|
...hasInternalOptions && {
|
|
24460
24681
|
[pgsqlAdapterInternalOptionsKey]: true
|
|
@@ -24463,6 +24684,9 @@ var PgsqlAdapter = class {
|
|
|
24463
24684
|
...this._dbCasing !== void 0 && { dbCasing: this._dbCasing },
|
|
24464
24685
|
...this.model !== void 0 && { model: this.model },
|
|
24465
24686
|
...this.logger !== void 0 && { logger: this.logger },
|
|
24687
|
+
...this.preparedStatements !== false && {
|
|
24688
|
+
preparedStatements: clonePreparedStatements(this.preparedStatements)
|
|
24689
|
+
},
|
|
24466
24690
|
defaultPkColumnName: this.defaultPk,
|
|
24467
24691
|
deriveFkColumnName: this.deriveFk,
|
|
24468
24692
|
...this.borrowedClient && { borrowedClient: true },
|
|
@@ -24474,6 +24698,9 @@ var PgsqlAdapter = class {
|
|
|
24474
24698
|
...rollbackOnlyScope === true && { rollbackOnlyScope },
|
|
24475
24699
|
...scopeToken !== void 0 && { dbspScopeToken: scopeToken },
|
|
24476
24700
|
...scopeState !== void 0 && { dbspScopeState: scopeState },
|
|
24701
|
+
...preparedStatementRegistry !== void 0 && {
|
|
24702
|
+
preparedStatementRegistry
|
|
24703
|
+
},
|
|
24477
24704
|
...overrides
|
|
24478
24705
|
};
|
|
24479
24706
|
}
|
|
@@ -25058,7 +25285,7 @@ var PgsqlAdapter = class {
|
|
|
25058
25285
|
async executeWithMeta(query) {
|
|
25059
25286
|
this.requireConnection("execute");
|
|
25060
25287
|
const guardedQuery = guardCompiledQuery(query, "execute");
|
|
25061
|
-
const result = await this.executeQueryProtectingOpenTransaction(guardedQuery.sql, guardedQuery.parameters);
|
|
25288
|
+
const result = await this.executeQueryProtectingOpenTransaction(guardedQuery.sql, guardedQuery.parameters, { prepareEligible: true });
|
|
25062
25289
|
const metadata = queryResultMetadata(result);
|
|
25063
25290
|
const rows = this.transformResultRows(result.rows, guardedQuery);
|
|
25064
25291
|
return {
|
|
@@ -26559,11 +26786,11 @@ var PgsqlAdapter = class {
|
|
|
26559
26786
|
}
|
|
26560
26787
|
}
|
|
26561
26788
|
releaseClient(client, error) {
|
|
26562
|
-
if (error === void 0) {
|
|
26789
|
+
if (error === void 0 && !hasPreparedStatementQuarantine(client)) {
|
|
26563
26790
|
client.release();
|
|
26564
26791
|
return;
|
|
26565
26792
|
}
|
|
26566
|
-
client.release(error);
|
|
26793
|
+
client.release(error ?? true);
|
|
26567
26794
|
}
|
|
26568
26795
|
async rollbackAndReleaseSavepoint(client, savepointName, allowedScopeToken, scopeState, options) {
|
|
26569
26796
|
const rolledBack = await this.rollbackSavepoint(
|
|
@@ -27260,7 +27487,8 @@ var PgsqlAdapter = class {
|
|
|
27260
27487
|
const rawResult = await this.issueConnectionQuery(
|
|
27261
27488
|
executor,
|
|
27262
27489
|
sql,
|
|
27263
|
-
parameters
|
|
27490
|
+
parameters,
|
|
27491
|
+
options.prepareEligible ?? false
|
|
27264
27492
|
);
|
|
27265
27493
|
if (options.inspectTransactionControl !== false) {
|
|
27266
27494
|
await this.assertNoTransactionControlCommand(
|
|
@@ -27401,7 +27629,44 @@ var PgsqlAdapter = class {
|
|
|
27401
27629
|
}
|
|
27402
27630
|
return result;
|
|
27403
27631
|
}
|
|
27404
|
-
async issueConnectionQuery(executor, sql, parameters) {
|
|
27632
|
+
async issueConnectionQuery(executor, sql, parameters, prepareEligible) {
|
|
27633
|
+
if (this.preparedStatementRegistry !== void 0 && prepareEligible && parameters !== void 0 && parameters.length > 0) {
|
|
27634
|
+
if (isPoolClientLike(executor) && isPreparedStatementQuarantined(executor, sql)) {
|
|
27635
|
+
return executor.query(sql, [...parameters]);
|
|
27636
|
+
}
|
|
27637
|
+
const admission = this.preparedStatementRegistry.admit(sql);
|
|
27638
|
+
if (admission === void 0) {
|
|
27639
|
+
return executor.query(sql, [...parameters]);
|
|
27640
|
+
}
|
|
27641
|
+
try {
|
|
27642
|
+
const result = await executor.query({
|
|
27643
|
+
name: admission.name,
|
|
27644
|
+
text: sql,
|
|
27645
|
+
values: [...parameters]
|
|
27646
|
+
});
|
|
27647
|
+
if (admission.reservation !== void 0)
|
|
27648
|
+
this.preparedStatementRegistry.confirm(admission.reservation);
|
|
27649
|
+
return result;
|
|
27650
|
+
} catch (error) {
|
|
27651
|
+
if (admission.reservation !== void 0) {
|
|
27652
|
+
if (shouldAbortPreparedStatementReservation(
|
|
27653
|
+
error,
|
|
27654
|
+
executor,
|
|
27655
|
+
admission.name
|
|
27656
|
+
)) {
|
|
27657
|
+
this.preparedStatementRegistry.abort(admission.reservation);
|
|
27658
|
+
} else this.preparedStatementRegistry.confirm(admission.reservation);
|
|
27659
|
+
}
|
|
27660
|
+
if (isPoolClientLike(executor) && (isVerifiedPreparedStatementInfrastructureError(error) || isDriverLocalPreparedStatementNameCollision(error, admission.name))) {
|
|
27661
|
+
quarantinePreparedStatement(
|
|
27662
|
+
executor,
|
|
27663
|
+
sql,
|
|
27664
|
+
isVerifiedClientWidePreparedStatementLoss(error)
|
|
27665
|
+
);
|
|
27666
|
+
}
|
|
27667
|
+
throw error;
|
|
27668
|
+
}
|
|
27669
|
+
}
|
|
27405
27670
|
if (parameters === void 0) {
|
|
27406
27671
|
return executor.query(sql);
|
|
27407
27672
|
}
|
|
@@ -30596,7 +30861,7 @@ function createPgObservationIssuer() {
|
|
|
30596
30861
|
}
|
|
30597
30862
|
|
|
30598
30863
|
// src/transition/operations/alter-column-set-not-null.ts
|
|
30599
|
-
import { createHash as
|
|
30864
|
+
import { createHash as createHash3 } from "crypto";
|
|
30600
30865
|
import { createEvidenceView } from "@dbsp/core";
|
|
30601
30866
|
init_validate();
|
|
30602
30867
|
|
|
@@ -31869,7 +32134,7 @@ function operationPackSemanticsAssumption(payload, context) {
|
|
|
31869
32134
|
};
|
|
31870
32135
|
}
|
|
31871
32136
|
function digest(value) {
|
|
31872
|
-
return
|
|
32137
|
+
return createHash3("sha256").update(stableJson(value)).digest("hex");
|
|
31873
32138
|
}
|
|
31874
32139
|
function fact(key, value) {
|
|
31875
32140
|
return {
|
|
@@ -32541,7 +32806,7 @@ function createAlterColumnSetNotNullOperationRuntime() {
|
|
|
32541
32806
|
}
|
|
32542
32807
|
|
|
32543
32808
|
// src/transition/operations/alter-table-add-check.ts
|
|
32544
|
-
import { createHash as
|
|
32809
|
+
import { createHash as createHash4 } from "crypto";
|
|
32545
32810
|
init_validate();
|
|
32546
32811
|
var GUARD_STATEMENT_TIMEOUT_MS2 = 5e3;
|
|
32547
32812
|
var RENDERER_SESSION_REQUIREMENTS = [
|
|
@@ -32772,7 +33037,7 @@ function operationPackSemanticsAssumption2(payload, context) {
|
|
|
32772
33037
|
};
|
|
32773
33038
|
}
|
|
32774
33039
|
function digest2(value) {
|
|
32775
|
-
return
|
|
33040
|
+
return createHash4("sha256").update(stableJson(value)).digest("hex");
|
|
32776
33041
|
}
|
|
32777
33042
|
function fact2(key, value) {
|
|
32778
33043
|
return {
|
|
@@ -33246,7 +33511,7 @@ function createAlterTableAddCheckOperationRuntime() {
|
|
|
33246
33511
|
}
|
|
33247
33512
|
|
|
33248
33513
|
// src/transition/operations/alter-type-add-value.ts
|
|
33249
|
-
import { createHash as
|
|
33514
|
+
import { createHash as createHash5 } from "crypto";
|
|
33250
33515
|
init_validate();
|
|
33251
33516
|
var MAX_PG_ENUM_LABEL_BYTES = 63;
|
|
33252
33517
|
var RENDERER_SESSION_REQUIREMENTS2 = [
|
|
@@ -33414,7 +33679,7 @@ function operationPackSemanticsAssumption3(payload, context) {
|
|
|
33414
33679
|
};
|
|
33415
33680
|
}
|
|
33416
33681
|
function digest3(value) {
|
|
33417
|
-
return
|
|
33682
|
+
return createHash5("sha256").update(stableJson(value)).digest("hex");
|
|
33418
33683
|
}
|
|
33419
33684
|
function fact3(key, value) {
|
|
33420
33685
|
return {
|
|
@@ -33814,7 +34079,7 @@ function createAlterTypeAddValueOperationRuntime() {
|
|
|
33814
34079
|
}
|
|
33815
34080
|
|
|
33816
34081
|
// src/transition/operations/attach-logical-identity.ts
|
|
33817
|
-
import { createHash as
|
|
34082
|
+
import { createHash as createHash6 } from "crypto";
|
|
33818
34083
|
init_validate();
|
|
33819
34084
|
function isRecord11(value) {
|
|
33820
34085
|
return value != null && typeof value === "object" && !Array.isArray(value);
|
|
@@ -33957,7 +34222,7 @@ function renderInsertLogicalIdentitySql(_schema) {
|
|
|
33957
34222
|
return `INSERT INTO ${qualifiedSideTable()} (logical_id, schema_name, table_name, column_name, carrier_kind) VALUES ($1, $2, $3, $4, $5)`;
|
|
33958
34223
|
}
|
|
33959
34224
|
function digest4(value) {
|
|
33960
|
-
return
|
|
34225
|
+
return createHash6("sha256").update(stableJson(value)).digest("hex");
|
|
33961
34226
|
}
|
|
33962
34227
|
function fact4(key, value) {
|
|
33963
34228
|
return {
|
|
@@ -34360,7 +34625,7 @@ function createAttachLogicalIdentityOperationRuntime() {
|
|
|
34360
34625
|
}
|
|
34361
34626
|
|
|
34362
34627
|
// src/transition/operations/create-unique-index-concurrently.ts
|
|
34363
|
-
import { createHash as
|
|
34628
|
+
import { createHash as createHash7 } from "crypto";
|
|
34364
34629
|
init_validate();
|
|
34365
34630
|
var DEFAULT_LOCK_TIMEOUT_MS = 5e3;
|
|
34366
34631
|
function isRecord12(value) {
|
|
@@ -34472,7 +34737,7 @@ function operationPackSemanticsAssumption5(payload, context) {
|
|
|
34472
34737
|
};
|
|
34473
34738
|
}
|
|
34474
34739
|
function digest5(value) {
|
|
34475
|
-
return
|
|
34740
|
+
return createHash7("sha256").update(stableJson(value)).digest("hex");
|
|
34476
34741
|
}
|
|
34477
34742
|
function fact5(key, value) {
|
|
34478
34743
|
return {
|
|
@@ -35151,7 +35416,7 @@ function createCreateUniqueIndexConcurrentlyOperationRuntime() {
|
|
|
35151
35416
|
}
|
|
35152
35417
|
|
|
35153
35418
|
// src/transition/operations/manual-sql.ts
|
|
35154
|
-
import { createHash as
|
|
35419
|
+
import { createHash as createHash8 } from "crypto";
|
|
35155
35420
|
import { resourceScopeCovers } from "@dbsp/core";
|
|
35156
35421
|
function isRecord13(value) {
|
|
35157
35422
|
return value != null && typeof value === "object" && !Array.isArray(value);
|
|
@@ -35168,7 +35433,7 @@ function clientQuery6(client) {
|
|
|
35168
35433
|
return queryable7(client.opaqueClient);
|
|
35169
35434
|
}
|
|
35170
35435
|
function digest6(value) {
|
|
35171
|
-
return
|
|
35436
|
+
return createHash8("sha256").update(stableJson(value)).digest("hex");
|
|
35172
35437
|
}
|
|
35173
35438
|
function fact6(key, value) {
|
|
35174
35439
|
return {
|