orez 0.2.26 → 0.2.29
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/cf-do/worker.d.ts.map +1 -1
- package/dist/cf-do/worker.js +9 -1
- package/dist/cf-do/worker.js.map +1 -1
- package/dist/pg-proxy-do-backend.d.ts +2 -0
- package/dist/pg-proxy-do-backend.d.ts.map +1 -1
- package/dist/pg-proxy-do-backend.js +49 -7
- package/dist/pg-proxy-do-backend.js.map +1 -1
- package/dist/pg-sqlite-compiler/catalog/seed.d.ts +67 -0
- package/dist/pg-sqlite-compiler/catalog/seed.d.ts.map +1 -0
- package/dist/pg-sqlite-compiler/catalog/seed.js +436 -0
- package/dist/pg-sqlite-compiler/catalog/seed.js.map +1 -0
- package/dist/pg-sqlite-compiler/index.d.ts +12 -0
- package/dist/pg-sqlite-compiler/index.d.ts.map +1 -0
- package/dist/pg-sqlite-compiler/index.js +59 -0
- package/dist/pg-sqlite-compiler/index.js.map +1 -0
- package/dist/pg-sqlite-compiler/passes/ast-utils.d.ts +48 -0
- package/dist/pg-sqlite-compiler/passes/ast-utils.d.ts.map +1 -0
- package/dist/pg-sqlite-compiler/passes/ast-utils.js +93 -0
- package/dist/pg-sqlite-compiler/passes/ast-utils.js.map +1 -0
- package/dist/pg-sqlite-compiler/passes/catalog.d.ts +34 -0
- package/dist/pg-sqlite-compiler/passes/catalog.d.ts.map +1 -0
- package/dist/pg-sqlite-compiler/passes/catalog.js +30 -0
- package/dist/pg-sqlite-compiler/passes/catalog.js.map +1 -0
- package/dist/pg-sqlite-compiler/passes/datetime.d.ts +21 -0
- package/dist/pg-sqlite-compiler/passes/datetime.d.ts.map +1 -0
- package/dist/pg-sqlite-compiler/passes/datetime.js +53 -0
- package/dist/pg-sqlite-compiler/passes/datetime.js.map +1 -0
- package/dist/pg-sqlite-compiler/passes/index.d.ts +21 -0
- package/dist/pg-sqlite-compiler/passes/index.d.ts.map +1 -0
- package/dist/pg-sqlite-compiler/passes/index.js +39 -0
- package/dist/pg-sqlite-compiler/passes/index.js.map +1 -0
- package/dist/pg-sqlite-compiler/passes/types.d.ts +41 -0
- package/dist/pg-sqlite-compiler/passes/types.d.ts.map +1 -0
- package/dist/pg-sqlite-compiler/passes/types.js +103 -0
- package/dist/pg-sqlite-compiler/passes/types.js.map +1 -0
- package/dist/pg-sqlite-compiler/test/oracle.d.ts +34 -0
- package/dist/pg-sqlite-compiler/test/oracle.d.ts.map +1 -0
- package/dist/pg-sqlite-compiler/test/oracle.js +204 -0
- package/dist/pg-sqlite-compiler/test/oracle.js.map +1 -0
- package/dist/pg-sqlite-compiler/types.d.ts +55 -0
- package/dist/pg-sqlite-compiler/types.d.ts.map +1 -0
- package/dist/pg-sqlite-compiler/types.js +2 -0
- package/dist/pg-sqlite-compiler/types.js.map +1 -0
- package/package.json +8 -4
- package/src/admin/admin-data.test.ts +0 -348
- package/src/admin/http-proxy.ts +0 -252
- package/src/admin/log-store.ts +0 -192
- package/src/admin/server.ts +0 -471
- package/src/admin/ui.ts +0 -1322
- package/src/bench/proxy-throughput.bench.ts +0 -343
- package/src/bench/serial-mutations.bench.ts +0 -270
- package/src/browser.ts +0 -203
- package/src/cf-do/.wrangler/cache/cf.json +0 -1
- package/src/cf-do/.wrangler/state/v3/cache/miniflare-CacheObject/metadata.sqlite +0 -0
- package/src/cf-do/.wrangler/state/v3/cache/miniflare-CacheObject/metadata.sqlite-shm +0 -0
- package/src/cf-do/.wrangler/state/v3/cache/miniflare-CacheObject/metadata.sqlite-wal +0 -0
- package/src/cf-do/.wrangler/state/v3/do/zero-do-ZeroDO/0f0f3bdf0abda097eb6f1246db4657d9fc622081362d894d82c1a1ce067b05b6.sqlite +0 -0
- package/src/cf-do/.wrangler/state/v3/do/zero-do-ZeroDO/1ddd3a4a48a11b51658444f5458a1fb175194b1d5b6a5bda20ef3fe3205b900c.sqlite +0 -0
- package/src/cf-do/.wrangler/state/v3/do/zero-do-ZeroDO/204a39120310d37e972c5914cfd71ad55c151bdb9e8ed289a5f8c5b052dd60e4.sqlite +0 -0
- package/src/cf-do/.wrangler/state/v3/do/zero-do-ZeroDO/3835f242df9728adba3d127a238793fd054ed3e51df3f60749ee744c469bf2a2.sqlite +0 -0
- package/src/cf-do/.wrangler/state/v3/do/zero-do-ZeroDO/4aa9c80eb716cf55b8995ccf7afab0b36c683e6da07d7c37a3f9c570136036df.sqlite +0 -0
- package/src/cf-do/.wrangler/state/v3/do/zero-do-ZeroDO/533e2fd1d6ea46e7a9a0017916ef341802d438d72583462755f2c1f8225e9bf2.sqlite +0 -0
- package/src/cf-do/.wrangler/state/v3/do/zero-do-ZeroDO/5ffa1aced1225ecaeac6366f7586aa3de92761cdff8711d81fbd81f248076abd.sqlite +0 -0
- package/src/cf-do/.wrangler/state/v3/do/zero-do-ZeroDO/686c3a9f0d7e59ed2ab607efd4b76d779c97cafeb3818380033bf7c7eb86c819.sqlite +0 -0
- package/src/cf-do/.wrangler/state/v3/do/zero-do-ZeroDO/6e8214e8dcfadd0deb52d64e5e9ca85c6b329ace11193909845995396914c473.sqlite +0 -0
- package/src/cf-do/.wrangler/state/v3/do/zero-do-ZeroDO/78d9ec9ff873d3fe3507ff53c2a6f6dfc408b4268eb0db3f2a146c0678965366.sqlite +0 -0
- package/src/cf-do/.wrangler/state/v3/do/zero-do-ZeroDO/7eff9f0ed7e27ad0d3f9d923de0682fab1928591172c1ba336c5f79a134a5d85.sqlite +0 -0
- package/src/cf-do/.wrangler/state/v3/do/zero-do-ZeroDO/836cda5b995b25867d722ed4f4c2292167e80351a3c6038db626648eb247dd8b.sqlite +0 -0
- package/src/cf-do/.wrangler/state/v3/do/zero-do-ZeroDO/91ef63b112209ab30172763acd8a0935106c248f7f1bcae5545ce37a9f201551.sqlite +0 -0
- package/src/cf-do/.wrangler/state/v3/do/zero-do-ZeroDO/a66ea4293a5f5938bc6d116edfa2522bb85bc37aea3541fbc09c3b613b9b32c0.sqlite +0 -0
- package/src/cf-do/.wrangler/state/v3/do/zero-do-ZeroDO/ceb2ab26b80590840b65651deb6e948d3bf81565c6751f3a58752cf4bf4aecae.sqlite +0 -0
- package/src/cf-do/.wrangler/state/v3/do/zero-do-ZeroDO/metadata.sqlite +0 -0
- package/src/cf-do/.wrangler/state/v3/do/zero-do-ZeroDO/metadata.sqlite-shm +0 -0
- package/src/cf-do/.wrangler/state/v3/do/zero-do-ZeroDO/metadata.sqlite-wal +0 -0
- package/src/cf-do/ARCHITECTURE.md +0 -83
- package/src/cf-do/watermark.test.ts +0 -103
- package/src/cf-do/watermark.ts +0 -118
- package/src/cf-do/worker.ts +0 -1033
- package/src/cf-do/wrangler.toml +0 -11
- package/src/cf-pglite/README.md +0 -19
- package/src/change-tracking.ts +0 -25
- package/src/child-process.test.ts +0 -147
- package/src/child-process.ts +0 -90
- package/src/cli-entry.ts +0 -72
- package/src/cli.test.ts +0 -38
- package/src/cli.ts +0 -1214
- package/src/config.ts +0 -150
- package/src/do-sql-tracking.test.ts +0 -19
- package/src/do-sql-tracking.ts +0 -19
- package/src/index.ts +0 -1215
- package/src/integration/integration.test.ts +0 -517
- package/src/integration/native-binary.guard.test.ts +0 -13
- package/src/integration/native-startup.test.ts +0 -44
- package/src/integration/replication-latency.test.ts +0 -428
- package/src/integration/restore-live-stress.test.ts +0 -433
- package/src/integration/restore-reset.test.ts +0 -400
- package/src/integration/restore.test.ts +0 -274
- package/src/integration/test-permissions.ts +0 -147
- package/src/load-config.ts +0 -46
- package/src/log.ts +0 -96
- package/src/mutex.ts +0 -47
- package/src/pg-proxy-browser.singledb.test.ts +0 -233
- package/src/pg-proxy-browser.ts +0 -2022
- package/src/pg-proxy-do-backend.test.ts +0 -3890
- package/src/pg-proxy-do-backend.ts +0 -7157
- package/src/pg-proxy.ts +0 -1087
- package/src/pglite-ipc.test.ts +0 -116
- package/src/pglite-ipc.ts +0 -266
- package/src/pglite-manager.ts +0 -557
- package/src/pglite-web-proxy.test.ts +0 -57
- package/src/pglite-web-proxy.ts +0 -221
- package/src/pglite-web-worker.ts +0 -152
- package/src/pglite-worker-thread.ts +0 -253
- package/src/port.ts +0 -25
- package/src/process-title.ts +0 -9
- package/src/recovery.ts +0 -155
- package/src/replication/change-tracker.test.ts +0 -357
- package/src/replication/change-tracker.ts +0 -279
- package/src/replication/handler.test.ts +0 -511
- package/src/replication/handler.ts +0 -1190
- package/src/replication/pgoutput-encoder.test.ts +0 -697
- package/src/replication/pgoutput-encoder.ts +0 -373
- package/src/replication/tcp-replication.test.ts +0 -876
- package/src/replication/zero-compat.test.ts +0 -1150
- package/src/restore-stress.test.ts +0 -188
- package/src/s3-local.ts +0 -203
- package/src/shim/hooks.mjs +0 -120
- package/src/shim/register.mjs +0 -4
- package/src/sqlite-mode/apply-mode.ts +0 -224
- package/src/sqlite-mode/index.ts +0 -15
- package/src/sqlite-mode/native-binary.ts +0 -89
- package/src/sqlite-mode/package-resolve.ts +0 -17
- package/src/sqlite-mode/resolve-mode.ts +0 -80
- package/src/sqlite-mode/shim-template.ts +0 -159
- package/src/sqlite-mode/sqlite-mode.test.ts +0 -427
- package/src/sqlite-mode/types.ts +0 -30
- package/src/vite-plugin.ts +0 -67
- package/src/wasm-sqlite.test.ts +0 -537
- package/src/worker/browser-admin.ts +0 -52
- package/src/worker/browser-build-config.test.ts +0 -71
- package/src/worker/browser-build-config.ts +0 -109
- package/src/worker/browser-embed-admin.test.ts +0 -75
- package/src/worker/browser-embed.ts +0 -345
- package/src/worker/cf-patches.ts +0 -384
- package/src/worker/embed-integration.test.ts +0 -321
- package/src/worker/index.ts +0 -138
- package/src/worker/shims/fastify.test.ts +0 -255
- package/src/worker/shims/fastify.ts +0 -306
- package/src/worker/shims/http-service.test.ts +0 -355
- package/src/worker/shims/http-service.ts +0 -293
- package/src/worker/shims/node-stub.ts +0 -290
- package/src/worker/shims/oxfmt.ts +0 -3
- package/src/worker/shims/postgres-browser.ts +0 -59
- package/src/worker/shims/postgres-socket.test.ts +0 -576
- package/src/worker/shims/postgres-socket.ts +0 -310
- package/src/worker/shims/postgres.test.ts +0 -364
- package/src/worker/shims/postgres.ts +0 -1454
- package/src/worker/shims/sqlite-browser.test.ts +0 -233
- package/src/worker/shims/sqlite-browser.ts +0 -175
- package/src/worker/shims/sqlite.test.ts +0 -786
- package/src/worker/shims/sqlite.ts +0 -978
- package/src/worker/shims/stream-browser.ts +0 -15
- package/src/worker/shims/ws-browser.test.ts +0 -205
- package/src/worker/shims/ws-browser.ts +0 -248
- package/src/worker/shims/ws.test.ts +0 -288
- package/src/worker/shims/ws.ts +0 -467
- package/src/worker/shims/zero-process-env.ts +0 -11
- package/src/worker/types.ts +0 -75
- package/src/worker/worker-integration.test.ts +0 -223
- package/src/worker/worker.test.ts +0 -136
- package/src/worker/zero-cache-embed-cf.ts +0 -463
- package/src/worker/zero-cache-embed.ts +0 -277
|
@@ -1,373 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* pgoutput binary protocol encoder.
|
|
3
|
-
*
|
|
4
|
-
* encodes change records into the binary format that postgres uses
|
|
5
|
-
* for logical replication (pgoutput plugin).
|
|
6
|
-
*
|
|
7
|
-
* all functions return Uint8Array for cross-platform compatibility.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
// postgres epoch: 2000-01-01 in microseconds from unix epoch
|
|
11
|
-
const PG_EPOCH_MICROS = 946684800000000n
|
|
12
|
-
const PG_TYPE_BOOL = 16
|
|
13
|
-
const PG_TYPE_TIMESTAMP = 1114
|
|
14
|
-
const PG_TYPE_TIMESTAMPTZ = 1184
|
|
15
|
-
|
|
16
|
-
// shared encoder instance - avoids per-call allocation
|
|
17
|
-
const encoder = new TextEncoder()
|
|
18
|
-
|
|
19
|
-
function flattenRelationName(tableName: string): string {
|
|
20
|
-
const dot = tableName.indexOf('.')
|
|
21
|
-
if (dot < 0) return tableName
|
|
22
|
-
const schema = tableName.slice(0, dot)
|
|
23
|
-
const name = tableName.slice(dot + 1)
|
|
24
|
-
if (schema === 'public') return name
|
|
25
|
-
if (schema === '_orez' && name === '_zero_changes') return '_zero_changes'
|
|
26
|
-
if (schema === '_orez' && name === '_zero_replication_slots')
|
|
27
|
-
return '_orez__zero_replication_slots'
|
|
28
|
-
if (schema === '_orez') return `_orez__${name}`
|
|
29
|
-
if (schema === '_zero') return `_zero_${name}`
|
|
30
|
-
return `${schema}_${name}`
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
function getTableOid(tableName: string): number {
|
|
34
|
-
let hash = 0
|
|
35
|
-
const key = `table:${flattenRelationName(tableName)}`
|
|
36
|
-
for (let i = 0; i < key.length; i++) hash = (hash * 33 + key.charCodeAt(i)) >>> 0
|
|
37
|
-
return 50_000 + (hash % 10_000_000)
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export interface ColumnInfo {
|
|
41
|
-
name: string
|
|
42
|
-
typeOid: number
|
|
43
|
-
typeMod: number
|
|
44
|
-
isKey?: boolean
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
// infer columns from a jsonb row
|
|
48
|
-
export function inferColumns(row: Record<string, unknown>): ColumnInfo[] {
|
|
49
|
-
return Object.keys(row).map((name) => ({
|
|
50
|
-
name,
|
|
51
|
-
typeOid: 25, // text oid - safe default, zero-cache re-maps types
|
|
52
|
-
typeMod: -1,
|
|
53
|
-
}))
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
function postgresBooleanText(value: unknown): string | null {
|
|
57
|
-
if (typeof value === 'boolean') return value ? 't' : 'f'
|
|
58
|
-
if (typeof value === 'number') return value === 0 ? 'f' : 't'
|
|
59
|
-
if (typeof value === 'bigint') return value === 0n ? 'f' : 't'
|
|
60
|
-
if (typeof value !== 'string') return null
|
|
61
|
-
switch (value.trim().toLowerCase()) {
|
|
62
|
-
case 't':
|
|
63
|
-
case 'true':
|
|
64
|
-
case '1':
|
|
65
|
-
return 't'
|
|
66
|
-
case 'f':
|
|
67
|
-
case 'false':
|
|
68
|
-
case '0':
|
|
69
|
-
return 'f'
|
|
70
|
-
default:
|
|
71
|
-
return null
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
function postgresTupleTextValue(value: unknown, column: ColumnInfo): string {
|
|
76
|
-
if (column.typeOid === PG_TYPE_BOOL) {
|
|
77
|
-
const booleanText = postgresBooleanText(value)
|
|
78
|
-
if (booleanText !== null) return booleanText
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
if (typeof value === 'boolean') return value ? 't' : 'f'
|
|
82
|
-
if (typeof value === 'object') return JSON.stringify(value)
|
|
83
|
-
|
|
84
|
-
let strVal = String(value)
|
|
85
|
-
// normalize ISO timestamps to postgres text format.
|
|
86
|
-
// to_jsonb() produces "2026-03-19T07:20:11.643" but postgres
|
|
87
|
-
// pgoutput sends "2026-03-19 07:20:11.643" (space, no T).
|
|
88
|
-
// mismatch causes zero-cache to see different values during
|
|
89
|
-
// mutation reconciliation, triggering unnecessary rebases.
|
|
90
|
-
if (
|
|
91
|
-
(column.typeOid === PG_TYPE_TIMESTAMP || column.typeOid === PG_TYPE_TIMESTAMPTZ) &&
|
|
92
|
-
typeof value === 'string' &&
|
|
93
|
-
value.length >= 19
|
|
94
|
-
) {
|
|
95
|
-
strVal = strVal.replace('T', ' ')
|
|
96
|
-
}
|
|
97
|
-
return strVal
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// reusable scratch buffer for building messages (64KB, grows if needed)
|
|
101
|
-
let scratch = new Uint8Array(65536)
|
|
102
|
-
let scratchView = new DataView(scratch.buffer)
|
|
103
|
-
|
|
104
|
-
function ensureScratch(size: number): void {
|
|
105
|
-
if (scratch.length < size) {
|
|
106
|
-
const newSize = Math.max(size, scratch.length * 2)
|
|
107
|
-
const newScratch = new Uint8Array(newSize)
|
|
108
|
-
newScratch.set(scratch)
|
|
109
|
-
scratch = newScratch
|
|
110
|
-
scratchView = new DataView(scratch.buffer)
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
function writeInt16At(offset: number, val: number): void {
|
|
115
|
-
scratchView.setInt16(offset, val)
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
function writeInt32At(offset: number, val: number): void {
|
|
119
|
-
scratchView.setInt32(offset, val)
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
// legacy helpers for standalone buffers
|
|
123
|
-
function writeInt16(buf: Uint8Array, offset: number, val: number): void {
|
|
124
|
-
new DataView(buf.buffer, buf.byteOffset).setInt16(offset, val)
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
function writeInt32(buf: Uint8Array, offset: number, val: number): void {
|
|
128
|
-
new DataView(buf.buffer, buf.byteOffset).setInt32(offset, val)
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
function writeInt64(buf: Uint8Array, offset: number, val: bigint): void {
|
|
132
|
-
new DataView(buf.buffer, buf.byteOffset).setBigInt64(offset, val)
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
// encode a BEGIN message
|
|
136
|
-
export function encodeBegin(lsn: bigint, timestamp: bigint, xid: number): Uint8Array {
|
|
137
|
-
const buf = new Uint8Array(1 + 8 + 8 + 4)
|
|
138
|
-
buf[0] = 0x42 // 'B'
|
|
139
|
-
writeInt64(buf, 1, lsn)
|
|
140
|
-
writeInt64(buf, 9, timestamp - PG_EPOCH_MICROS)
|
|
141
|
-
writeInt32(buf, 17, xid)
|
|
142
|
-
return buf
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
// encode a COMMIT message
|
|
146
|
-
export function encodeCommit(
|
|
147
|
-
flags: number,
|
|
148
|
-
lsn: bigint,
|
|
149
|
-
endLsn: bigint,
|
|
150
|
-
timestamp: bigint
|
|
151
|
-
): Uint8Array {
|
|
152
|
-
const buf = new Uint8Array(1 + 1 + 8 + 8 + 8)
|
|
153
|
-
buf[0] = 0x43 // 'C'
|
|
154
|
-
buf[1] = flags
|
|
155
|
-
writeInt64(buf, 2, lsn)
|
|
156
|
-
writeInt64(buf, 10, endLsn)
|
|
157
|
-
writeInt64(buf, 18, timestamp - PG_EPOCH_MICROS)
|
|
158
|
-
return buf
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
// encode a RELATION message
|
|
162
|
-
export function encodeRelation(
|
|
163
|
-
tableOid: number,
|
|
164
|
-
schema: string,
|
|
165
|
-
tableName: string,
|
|
166
|
-
replicaIdentity: number,
|
|
167
|
-
columns: ColumnInfo[]
|
|
168
|
-
): Uint8Array {
|
|
169
|
-
const schemaBytes = encoder.encode(schema)
|
|
170
|
-
const nameBytes = encoder.encode(tableName)
|
|
171
|
-
|
|
172
|
-
// calculate column sizes
|
|
173
|
-
let columnsSize = 0
|
|
174
|
-
const colNameBytes: Uint8Array[] = []
|
|
175
|
-
for (const col of columns) {
|
|
176
|
-
const nb = encoder.encode(col.name)
|
|
177
|
-
colNameBytes.push(nb)
|
|
178
|
-
columnsSize += 1 + nb.length + 1 + 4 + 4 // flags + name + null + typeOid + typeMod
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
const total =
|
|
182
|
-
1 + 4 + schemaBytes.length + 1 + nameBytes.length + 1 + 1 + 2 + columnsSize
|
|
183
|
-
const buf = new Uint8Array(total)
|
|
184
|
-
let pos = 0
|
|
185
|
-
|
|
186
|
-
buf[pos++] = 0x52 // 'R'
|
|
187
|
-
writeInt32(buf, pos, tableOid)
|
|
188
|
-
pos += 4
|
|
189
|
-
buf.set(schemaBytes, pos)
|
|
190
|
-
pos += schemaBytes.length
|
|
191
|
-
buf[pos++] = 0
|
|
192
|
-
buf.set(nameBytes, pos)
|
|
193
|
-
pos += nameBytes.length
|
|
194
|
-
buf[pos++] = 0
|
|
195
|
-
buf[pos++] = replicaIdentity
|
|
196
|
-
writeInt16(buf, pos, columns.length)
|
|
197
|
-
pos += 2
|
|
198
|
-
|
|
199
|
-
for (let i = 0; i < columns.length; i++) {
|
|
200
|
-
buf[pos++] = columns[i].isKey ? 1 : 0 // flags: 1 = part of replica identity key
|
|
201
|
-
buf.set(colNameBytes[i], pos)
|
|
202
|
-
pos += colNameBytes[i].length
|
|
203
|
-
buf[pos++] = 0
|
|
204
|
-
writeInt32(buf, pos, columns[i].typeOid)
|
|
205
|
-
pos += 4
|
|
206
|
-
writeInt32(buf, pos, columns[i].typeMod)
|
|
207
|
-
pos += 4
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
return buf
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
// encode tuple data directly into scratch buffer starting at given offset.
|
|
214
|
-
// returns the number of bytes written.
|
|
215
|
-
function encodeTupleDataInto(
|
|
216
|
-
row: Record<string, unknown>,
|
|
217
|
-
columns: ColumnInfo[],
|
|
218
|
-
startOffset: number
|
|
219
|
-
): number {
|
|
220
|
-
let pos = startOffset
|
|
221
|
-
|
|
222
|
-
// reserve space for ncolumns
|
|
223
|
-
ensureScratch(pos + 2 + columns.length * 32)
|
|
224
|
-
writeInt16At(pos, columns.length)
|
|
225
|
-
pos += 2
|
|
226
|
-
|
|
227
|
-
for (const col of columns) {
|
|
228
|
-
const val = row[col.name]
|
|
229
|
-
if (val === null || val === undefined) {
|
|
230
|
-
ensureScratch(pos + 1)
|
|
231
|
-
scratch[pos++] = 0x6e // 'n' for null
|
|
232
|
-
} else {
|
|
233
|
-
const strVal = postgresTupleTextValue(val, col)
|
|
234
|
-
const bytes = encoder.encode(strVal)
|
|
235
|
-
ensureScratch(pos + 1 + 4 + bytes.length)
|
|
236
|
-
scratch[pos++] = 0x74 // 't' for text
|
|
237
|
-
writeInt32At(pos, bytes.length)
|
|
238
|
-
pos += 4
|
|
239
|
-
scratch.set(bytes, pos)
|
|
240
|
-
pos += bytes.length
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
return pos - startOffset
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
/**
|
|
248
|
-
* encode a complete change message wrapped in CopyData(XLogData(...)).
|
|
249
|
-
* avoids intermediate buffer allocations by writing directly into one buffer.
|
|
250
|
-
*/
|
|
251
|
-
export function encodeWrappedChange(
|
|
252
|
-
walStart: bigint,
|
|
253
|
-
walEnd: bigint,
|
|
254
|
-
timestamp: bigint,
|
|
255
|
-
changeData: Uint8Array
|
|
256
|
-
): Uint8Array {
|
|
257
|
-
// CopyData header: 'd' + int32 len
|
|
258
|
-
// XLogData header: 'w' + int64 walStart + int64 walEnd + int64 timestamp
|
|
259
|
-
// then changeData
|
|
260
|
-
const xlogSize = 1 + 8 + 8 + 8 + changeData.length
|
|
261
|
-
const totalSize = 1 + 4 + xlogSize
|
|
262
|
-
const buf = new Uint8Array(totalSize)
|
|
263
|
-
|
|
264
|
-
// CopyData
|
|
265
|
-
buf[0] = 0x64 // 'd'
|
|
266
|
-
writeInt32(buf, 1, 4 + xlogSize)
|
|
267
|
-
|
|
268
|
-
// XLogData
|
|
269
|
-
buf[5] = 0x77 // 'w'
|
|
270
|
-
writeInt64(buf, 6, walStart)
|
|
271
|
-
writeInt64(buf, 14, walEnd)
|
|
272
|
-
writeInt64(buf, 22, timestamp - PG_EPOCH_MICROS)
|
|
273
|
-
|
|
274
|
-
// change payload
|
|
275
|
-
buf.set(changeData, 30)
|
|
276
|
-
|
|
277
|
-
return buf
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
// encode an INSERT message
|
|
281
|
-
export function encodeInsert(
|
|
282
|
-
tableOid: number,
|
|
283
|
-
row: Record<string, unknown>,
|
|
284
|
-
columns: ColumnInfo[]
|
|
285
|
-
): Uint8Array {
|
|
286
|
-
// write header + tuple directly into scratch
|
|
287
|
-
const headerSize = 1 + 4 + 1 // 'I' + oid + 'N'
|
|
288
|
-
ensureScratch(headerSize + 2 + columns.length * 64)
|
|
289
|
-
scratch[0] = 0x49 // 'I'
|
|
290
|
-
writeInt32At(1, tableOid)
|
|
291
|
-
scratch[5] = 0x4e // 'N' for new tuple
|
|
292
|
-
const tupleLen = encodeTupleDataInto(row, columns, 6)
|
|
293
|
-
return scratch.slice(0, 6 + tupleLen)
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
// encode an UPDATE message
|
|
297
|
-
export function encodeUpdate(
|
|
298
|
-
tableOid: number,
|
|
299
|
-
row: Record<string, unknown>,
|
|
300
|
-
oldRow: Record<string, unknown> | null,
|
|
301
|
-
columns: ColumnInfo[]
|
|
302
|
-
): Uint8Array {
|
|
303
|
-
ensureScratch(1 + 4 + 1 + columns.length * 128)
|
|
304
|
-
scratch[0] = 0x55 // 'U'
|
|
305
|
-
writeInt32At(1, tableOid)
|
|
306
|
-
|
|
307
|
-
if (oldRow) {
|
|
308
|
-
scratch[5] = 0x4f // 'O' for old tuple
|
|
309
|
-
const oldLen = encodeTupleDataInto(oldRow, columns, 6)
|
|
310
|
-
scratch[6 + oldLen] = 0x4e // 'N' for new tuple
|
|
311
|
-
const newLen = encodeTupleDataInto(row, columns, 7 + oldLen)
|
|
312
|
-
return scratch.slice(0, 7 + oldLen + newLen)
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
scratch[5] = 0x4e // 'N'
|
|
316
|
-
const newLen = encodeTupleDataInto(row, columns, 6)
|
|
317
|
-
return scratch.slice(0, 6 + newLen)
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
// encode a DELETE message
|
|
321
|
-
export function encodeDelete(
|
|
322
|
-
tableOid: number,
|
|
323
|
-
oldRow: Record<string, unknown>,
|
|
324
|
-
columns: ColumnInfo[]
|
|
325
|
-
): Uint8Array {
|
|
326
|
-
ensureScratch(1 + 4 + 1 + columns.length * 64)
|
|
327
|
-
scratch[0] = 0x44 // 'D'
|
|
328
|
-
writeInt32At(1, tableOid)
|
|
329
|
-
scratch[5] = 0x4b // 'K' for key tuple
|
|
330
|
-
const tupleLen = encodeTupleDataInto(oldRow, columns, 6)
|
|
331
|
-
return scratch.slice(0, 6 + tupleLen)
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
// wrap a pgoutput message in XLogData format
|
|
335
|
-
export function wrapXLogData(
|
|
336
|
-
walStart: bigint,
|
|
337
|
-
walEnd: bigint,
|
|
338
|
-
timestamp: bigint,
|
|
339
|
-
data: Uint8Array
|
|
340
|
-
): Uint8Array {
|
|
341
|
-
const buf = new Uint8Array(1 + 8 + 8 + 8 + data.length)
|
|
342
|
-
buf[0] = 0x77 // 'w' XLogData
|
|
343
|
-
writeInt64(buf, 1, walStart)
|
|
344
|
-
writeInt64(buf, 9, walEnd)
|
|
345
|
-
writeInt64(buf, 17, timestamp - PG_EPOCH_MICROS)
|
|
346
|
-
buf.set(data, 25)
|
|
347
|
-
return buf
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
// wrap in CopyData format
|
|
351
|
-
export function wrapCopyData(data: Uint8Array): Uint8Array {
|
|
352
|
-
const buf = new Uint8Array(1 + 4 + data.length)
|
|
353
|
-
buf[0] = 0x64 // 'd' CopyData
|
|
354
|
-
writeInt32(buf, 1, 4 + data.length)
|
|
355
|
-
buf.set(data, 5)
|
|
356
|
-
return buf
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
// encode a primary keepalive message
|
|
360
|
-
export function encodeKeepalive(
|
|
361
|
-
walEnd: bigint,
|
|
362
|
-
timestamp: bigint,
|
|
363
|
-
replyRequested: boolean
|
|
364
|
-
): Uint8Array {
|
|
365
|
-
const inner = new Uint8Array(1 + 8 + 8 + 1)
|
|
366
|
-
inner[0] = 0x6b // 'k' keepalive
|
|
367
|
-
writeInt64(inner, 1, walEnd)
|
|
368
|
-
writeInt64(inner, 9, timestamp - PG_EPOCH_MICROS)
|
|
369
|
-
inner[17] = replyRequested ? 1 : 0
|
|
370
|
-
return wrapCopyData(inner)
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
export { getTableOid }
|