orez 0.4.46 → 0.4.48
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/pg-proxy-do-backend.d.ts +3 -0
- package/dist/pg-proxy-do-backend.d.ts.map +1 -1
- package/dist/pg-proxy-do-backend.js +120 -14
- package/dist/pg-proxy-do-backend.js.map +1 -1
- package/dist/worker/zero-sql-write-circuit.d.ts.map +1 -1
- package/dist/worker/zero-sql-write-circuit.js +10 -2
- package/dist/worker/zero-sql-write-circuit.js.map +1 -1
- package/package.json +2 -2
|
@@ -49,7 +49,9 @@ export declare class DoBackend {
|
|
|
49
49
|
private ensureMetadataTable;
|
|
50
50
|
private publicationToJSON;
|
|
51
51
|
private publicationFromJSON;
|
|
52
|
+
private hydrateSchemaMetadataRow;
|
|
52
53
|
private loadDurableMetadata;
|
|
54
|
+
private reloadSchemaMetadataIfEmpty;
|
|
53
55
|
private reloadPublicationsIfEmpty;
|
|
54
56
|
private repairShardMetadataPublications;
|
|
55
57
|
private persistDurableMetadata;
|
|
@@ -129,6 +131,7 @@ export declare class DoBackend {
|
|
|
129
131
|
private generatedIndexName;
|
|
130
132
|
private uniqueIndexName;
|
|
131
133
|
private sqliteIndexColumnsFromRows;
|
|
134
|
+
private promotedUniqueIndexKey;
|
|
132
135
|
private tableIndexInfos;
|
|
133
136
|
private publicationContainsTable;
|
|
134
137
|
private publicationsForTable;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pg-proxy-do-backend.d.ts","sourceRoot":"","sources":["../src/pg-proxy-do-backend.ts"],"names":[],"mappings":"AAq/HA,wBAAsB,+BAA+B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CACzE,KAAK,CAAC;IACJ,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;IACjB,kBAAkB,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;IACtD,mBAAmB,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;CACxD,CAAC,CACH,CAkDA;AAwkCD,qBAAa,SAAS;IACpB,KAAK,UAAQ;IACb,MAAM,UAAQ;IACd,OAAO,CAAC,KAAK,CAAQ;IACrB,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,UAAU,CAAY;IAC9B,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,oBAAoB,CAAa;IACzC,OAAO,CAAC,gBAAgB,CAAwC;IAChE,OAAO,CAAC,cAAc,CAAgB;IACtC,OAAO,CAAC,YAAY,CAAoC;IAGxD,OAAO,CAAC,4BAA4B,CAAoB;IACxD,OAAO,CAAC,YAAY,CAAmC;IACvD,OAAO,CAAC,kBAAkB,CAAuC;IACjE,OAAO,CAAC,OAAO,CAAiC;IAOhD,OAAO,CAAC,yBAAyB,CAAsC;IACvE,OAAO,CAAC,YAAY,CAA6B;IACjD,OAAO,CAAC,cAAc,CAAc;IAQpC,OAAO,CAAC,aAAa,CAAQ;IAC7B,OAAO,CAAC,IAAI,CAAsB;IAClC,OAAO,CAAC,UAAU,CAA2C;IAC7D,OAAO,CAAC,eAAe,CAAmC;IAC1D,OAAO,CAAC,iBAAiB,CAAI;IAM7B,OAAO,CAAC,yBAAyB,CAAQ;IAGzC,OAAO,CAAC,eAAe,CAAQ;IAC/B,OAAO,CAAC,iBAAiB,CAAQ;IAQjC,OAAO,CAAC,qBAAqB,CAAmC;IAOhE,OAAO,CAAC,OAAO,CAAQ;gBAGrB,KAAK,EAAE,MAAM,EACb,MAAM,GAAE,MAAmB,EAC3B,SAAS,SAAY,EACrB,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE;IAenD,IAAI,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAE7B;IAED,OAAO,CAAC,WAAW;YAWL,IAAI;YAUJ,0BAA0B;YAwB1B,mBAAmB;IAIjC,OAAO,CAAC,iBAAiB;IASzB,OAAO,CAAC,mBAAmB;
|
|
1
|
+
{"version":3,"file":"pg-proxy-do-backend.d.ts","sourceRoot":"","sources":["../src/pg-proxy-do-backend.ts"],"names":[],"mappings":"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"}
|
|
@@ -4859,6 +4859,17 @@ export class DoBackend {
|
|
|
4859
4859
|
return null;
|
|
4860
4860
|
}
|
|
4861
4861
|
}
|
|
4862
|
+
hydrateSchemaMetadataRow(tableName, columnName, value) {
|
|
4863
|
+
const metadata = JSON.parse(value);
|
|
4864
|
+
let table = this.schemaMetadata.get(tableName);
|
|
4865
|
+
if (!table) {
|
|
4866
|
+
table = new Map();
|
|
4867
|
+
this.schemaMetadata.set(tableName, table);
|
|
4868
|
+
}
|
|
4869
|
+
const changed = JSON.stringify(table.get(columnName)) !== value;
|
|
4870
|
+
table.set(columnName, metadata);
|
|
4871
|
+
return changed;
|
|
4872
|
+
}
|
|
4862
4873
|
async loadDurableMetadata() {
|
|
4863
4874
|
try {
|
|
4864
4875
|
await this.ensureMetadataTable();
|
|
@@ -4871,13 +4882,7 @@ export class DoBackend {
|
|
|
4871
4882
|
const value = String(row.value ?? '');
|
|
4872
4883
|
this.lastPersistedMetadata.set(`${kind}\u0000${key}\u0000${subkey}`, value);
|
|
4873
4884
|
if (kind === 'schema-column') {
|
|
4874
|
-
|
|
4875
|
-
let table = this.schemaMetadata.get(key);
|
|
4876
|
-
if (!table) {
|
|
4877
|
-
table = new Map();
|
|
4878
|
-
this.schemaMetadata.set(key, table);
|
|
4879
|
-
}
|
|
4880
|
-
table.set(subkey, metadata);
|
|
4885
|
+
this.hydrateSchemaMetadataRow(key, subkey, value);
|
|
4881
4886
|
}
|
|
4882
4887
|
else if (kind === 'publication') {
|
|
4883
4888
|
const publication = this.publicationFromJSON(value);
|
|
@@ -4894,6 +4899,42 @@ export class DoBackend {
|
|
|
4894
4899
|
}
|
|
4895
4900
|
catch { }
|
|
4896
4901
|
}
|
|
4902
|
+
// Schema migrations persist PostgreSQL type metadata directly into the
|
|
4903
|
+
// shared SQL DO, outside this backend instance. If this backend initialized
|
|
4904
|
+
// first, its one-time load cached an empty schema and requests then exposed
|
|
4905
|
+
// physical SQLite INTEGER/TEXT types to zero forever. Refresh before parsing
|
|
4906
|
+
// any request so prepared statements also get semantic parameter types. Do
|
|
4907
|
+
// not negative-cache an empty read: the migration may commit immediately
|
|
4908
|
+
// after it, which is the race this self-heal exists to close.
|
|
4909
|
+
async reloadSchemaMetadataIfEmpty() {
|
|
4910
|
+
if (this.dbName !== 'postgres' || this.schemaMetadata.size > 0)
|
|
4911
|
+
return;
|
|
4912
|
+
try {
|
|
4913
|
+
await this.ensureMetadataTable();
|
|
4914
|
+
const result = await this.doExecResult(`SELECT kind, key, subkey, value FROM ${quoteIdentifier(METADATA_TABLE)} WHERE kind = 'schema-column'`);
|
|
4915
|
+
let changed = false;
|
|
4916
|
+
const persisted = this.lastPersistedMetadata ?? new Map();
|
|
4917
|
+
this.lastPersistedMetadata = persisted;
|
|
4918
|
+
for (const row of result.rows) {
|
|
4919
|
+
const key = String(row.key ?? '');
|
|
4920
|
+
const subkey = String(row.subkey ?? '');
|
|
4921
|
+
const value = String(row.value ?? '');
|
|
4922
|
+
changed = this.hydrateSchemaMetadataRow(key, subkey, value) || changed;
|
|
4923
|
+
persisted.set(`schema-column\u0000${key}\u0000${subkey}`, value);
|
|
4924
|
+
}
|
|
4925
|
+
if (changed) {
|
|
4926
|
+
if (this.txSnapshot) {
|
|
4927
|
+
// The rows were committed out-of-band, not by this transaction. A
|
|
4928
|
+
// later ROLLBACK must preserve them rather than restoring the stale
|
|
4929
|
+
// empty snapshot captured before the migration finished.
|
|
4930
|
+
this.txSnapshot.schemaMetadata = this.cloneSchemaMetadata(this.schemaMetadata);
|
|
4931
|
+
}
|
|
4932
|
+
this.rewriteCache.clear();
|
|
4933
|
+
this.publicationTableInfoCache = null;
|
|
4934
|
+
}
|
|
4935
|
+
}
|
|
4936
|
+
catch { }
|
|
4937
|
+
}
|
|
4897
4938
|
// self-heal a stale-empty publication cache. publications are durable
|
|
4898
4939
|
// (_orez_pg_metadata) and SHARED across every DoBackend instance pointed at
|
|
4899
4940
|
// one DO, but each instance only loads them once at init(). when this
|
|
@@ -5206,8 +5247,10 @@ export class DoBackend {
|
|
|
5206
5247
|
try {
|
|
5207
5248
|
switch (msgType) {
|
|
5208
5249
|
case FT_QUERY:
|
|
5250
|
+
await this.reloadSchemaMetadataIfEmpty();
|
|
5209
5251
|
return this.handleSimpleQuery(message);
|
|
5210
5252
|
case FT_PARSE:
|
|
5253
|
+
await this.reloadSchemaMetadataIfEmpty();
|
|
5211
5254
|
return this.handleParse(message);
|
|
5212
5255
|
case FT_BIND:
|
|
5213
5256
|
return this.handleBind(message);
|
|
@@ -5706,6 +5749,7 @@ export class DoBackend {
|
|
|
5706
5749
|
async execLocked(sql) {
|
|
5707
5750
|
if (!this.ready)
|
|
5708
5751
|
await this.waitReady;
|
|
5752
|
+
await this.reloadSchemaMetadataIfEmpty();
|
|
5709
5753
|
if (await this.handleTransactionControl(sql))
|
|
5710
5754
|
return [];
|
|
5711
5755
|
const statements = this.rewriteSQLStatements(sql);
|
|
@@ -5761,6 +5805,7 @@ export class DoBackend {
|
|
|
5761
5805
|
async queryLocked(sql, params) {
|
|
5762
5806
|
if (!this.ready)
|
|
5763
5807
|
await this.waitReady;
|
|
5808
|
+
await this.reloadSchemaMetadataIfEmpty();
|
|
5764
5809
|
if (await this.handleTransactionControl(sql))
|
|
5765
5810
|
return { rows: [] };
|
|
5766
5811
|
const statements = this.rewriteSQLStatements(sql);
|
|
@@ -6262,6 +6307,54 @@ export class DoBackend {
|
|
|
6262
6307
|
columns[row.name] = row.desc === 1 ? 'DESC' : 'ASC';
|
|
6263
6308
|
return columns;
|
|
6264
6309
|
}
|
|
6310
|
+
// a table with no PRIMARY KEY but a full, non-partial UNIQUE index is keyed
|
|
6311
|
+
// by that index — the shape soot's DDL generator emits for composite drizzle
|
|
6312
|
+
// primaryKey() tables (CREATE TABLE without a PK + CREATE UNIQUE INDEX
|
|
6313
|
+
// <table>_pkey), because a PK cannot be retrofitted onto an existing sqlite
|
|
6314
|
+
// table. real pg conveys this key via replica identity; without promoting it
|
|
6315
|
+
// here, zero's initial sync builds a keyless replica spec and its change
|
|
6316
|
+
// processor throws "Cannot replicate table without a PRIMARY KEY or UNIQUE
|
|
6317
|
+
// INDEX" on the first UPDATE (2026-07-10 soot prod outage).
|
|
6318
|
+
//
|
|
6319
|
+
// the <table>_pkey name IS the generator's primary-key convention, so it is
|
|
6320
|
+
// trusted outright: legacy tables created before NOT NULL reached their DDL
|
|
6321
|
+
// have nullable physical columns (and possibly no durable metadata), yet the
|
|
6322
|
+
// index still represents the app-level composite PK — requiring NOT NULL
|
|
6323
|
+
// there would silently skip exactly the tables this promotion exists to
|
|
6324
|
+
// heal. any OTHER unique index must cover only NOT NULL columns (a unique
|
|
6325
|
+
// index over nullable columns permits duplicate NULL rows and is not a row
|
|
6326
|
+
// identity); among those, narrowest wins, name as the tiebreak.
|
|
6327
|
+
promotedUniqueIndexKey(sqliteTableName, columns, indexListRows, indexColumnsByName) {
|
|
6328
|
+
const columnNames = new Set(columns.map((column) => column.name));
|
|
6329
|
+
const notNull = new Set(columns
|
|
6330
|
+
.filter((column) => {
|
|
6331
|
+
const metadata = this.schemaMetadata.get(sqliteTableName)?.get(column.name);
|
|
6332
|
+
return metadata?.notNull || metadata?.primaryKey || column.notnull || column.pk;
|
|
6333
|
+
})
|
|
6334
|
+
.map((column) => column.name));
|
|
6335
|
+
const ref = this.tableRefForSqliteTable(sqliteTableName);
|
|
6336
|
+
const pkeyName = `${ref.tableName}_pkey`;
|
|
6337
|
+
const candidates = [];
|
|
6338
|
+
for (const row of indexListRows) {
|
|
6339
|
+
const name = String(row.name ?? '');
|
|
6340
|
+
if (!name || !Number(row.unique ?? 0) || Number(row.partial ?? 0))
|
|
6341
|
+
continue;
|
|
6342
|
+
const indexColumns = Object.keys(indexColumnsByName.get(name) ?? {});
|
|
6343
|
+
if (indexColumns.length === 0)
|
|
6344
|
+
continue;
|
|
6345
|
+
if (!indexColumns.every((column) => columnNames.has(column)))
|
|
6346
|
+
continue;
|
|
6347
|
+
if (name === pkeyName)
|
|
6348
|
+
return indexColumns;
|
|
6349
|
+
if (!indexColumns.every((column) => notNull.has(column)))
|
|
6350
|
+
continue;
|
|
6351
|
+
candidates.push({ name, columns: indexColumns });
|
|
6352
|
+
}
|
|
6353
|
+
if (candidates.length === 0)
|
|
6354
|
+
return [];
|
|
6355
|
+
candidates.sort((a, b) => a.columns.length - b.columns.length || a.name.localeCompare(b.name));
|
|
6356
|
+
return candidates[0].columns;
|
|
6357
|
+
}
|
|
6265
6358
|
tableIndexInfos(table, columns, primaryKey, indexListRows, indexColumnsByName) {
|
|
6266
6359
|
const usedNames = new Set();
|
|
6267
6360
|
const seenSignatures = new Set();
|
|
@@ -6387,17 +6480,21 @@ export class DoBackend {
|
|
|
6387
6480
|
const metadataPrimaryKey = columns
|
|
6388
6481
|
.filter((column) => this.schemaMetadata.get(table.name)?.get(column.name)?.primaryKey)
|
|
6389
6482
|
.map((column) => column.name);
|
|
6483
|
+
const sqlitePrimaryKey = columns
|
|
6484
|
+
.filter((column) => column.pk > 0)
|
|
6485
|
+
.sort((a, b) => a.pk - b.pk)
|
|
6486
|
+
.map((column) => column.name);
|
|
6487
|
+
const primaryKey = metadataPrimaryKey.length > 0
|
|
6488
|
+
? metadataPrimaryKey
|
|
6489
|
+
: sqlitePrimaryKey.length > 0
|
|
6490
|
+
? sqlitePrimaryKey
|
|
6491
|
+
: this.promotedUniqueIndexKey(table.name, columns, pragmaResults[i * 2 + 1]?.rows ?? [], indexColumnsByName);
|
|
6390
6492
|
const info = {
|
|
6391
6493
|
name: table.name,
|
|
6392
6494
|
schema: ref.schema,
|
|
6393
6495
|
tableName: ref.tableName,
|
|
6394
6496
|
columns,
|
|
6395
|
-
primaryKey
|
|
6396
|
-
? metadataPrimaryKey
|
|
6397
|
-
: columns
|
|
6398
|
-
.filter((column) => column.pk > 0)
|
|
6399
|
-
.sort((a, b) => a.pk - b.pk)
|
|
6400
|
-
.map((column) => column.name),
|
|
6497
|
+
primaryKey,
|
|
6401
6498
|
indexes: [],
|
|
6402
6499
|
};
|
|
6403
6500
|
info.indexes = this.tableIndexInfos(ref, columns, info.primaryKey, pragmaResults[i * 2 + 1]?.rows ?? [], indexColumnsByName);
|
|
@@ -6606,7 +6703,16 @@ export class DoBackend {
|
|
|
6606
6703
|
elemPgTypeClass: metadata?.elemTyptype ?? null,
|
|
6607
6704
|
typeOID: metadata?.typeOid ?? pgTypeOid(dataType),
|
|
6608
6705
|
characterMaximumLength: metadata?.characterMaximumLength ?? null,
|
|
6609
|
-
|
|
6706
|
+
// primary-key columns are never-null by definition; legacy
|
|
6707
|
+
// tables whose key was promoted from a <table>_pkey unique
|
|
6708
|
+
// index carry nullable physical columns, and zero's
|
|
6709
|
+
// view-syncer refuses to sync a table whose key columns are
|
|
6710
|
+
// nullable on the replica (checkClientSchema).
|
|
6711
|
+
notNull: Boolean(metadata?.notNull ||
|
|
6712
|
+
metadata?.primaryKey ||
|
|
6713
|
+
column.notnull ||
|
|
6714
|
+
column.pk ||
|
|
6715
|
+
info.primaryKey.includes(column.name)),
|
|
6610
6716
|
dflt: null,
|
|
6611
6717
|
},
|
|
6612
6718
|
];
|