@reventlessdev/reventless-postgres 3.0.0-alpha.6 → 3.0.0-alpha.60
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/CHANGELOG.md +434 -0
- package/README.md +83 -0
- package/lib/bs/.compiler.log +2 -2
- package/lib/bs/ReventlessPostgres.cmi +0 -0
- package/lib/bs/ReventlessPostgres.cmt +0 -0
- package/lib/bs/ReventlessPostgres.mlmap +3 -2
- package/lib/bs/compiler-info.json +2 -2
- package/lib/bs/src/DcbEventLogStorage_Postgres-ReventlessPostgres.cmi +0 -0
- package/lib/bs/src/DcbEventLogStorage_Postgres-ReventlessPostgres.cmj +0 -0
- package/lib/bs/src/DcbEventLogStorage_Postgres-ReventlessPostgres.cmt +0 -0
- package/lib/bs/src/DcbEventLogStorage_Postgres.ast +0 -0
- package/lib/bs/src/DcbEventLogStorage_Postgres.res +25 -340
- package/lib/bs/src/DcbEventLogStorage_Postgres.res.mjs +32 -348
- package/lib/bs/src/DcbEventLogStorage_Postgres_Ops-ReventlessPostgres.cmi +0 -0
- package/lib/bs/src/DcbEventLogStorage_Postgres_Ops-ReventlessPostgres.cmj +0 -0
- package/lib/bs/src/DcbEventLogStorage_Postgres_Ops-ReventlessPostgres.cmt +0 -0
- package/lib/bs/src/DcbEventLogStorage_Postgres_Ops.ast +0 -0
- package/lib/bs/src/DcbEventLogStorage_Postgres_Ops.res +350 -0
- package/lib/bs/src/DcbEventLogStorage_Postgres_Ops.res.mjs +380 -0
- package/lib/bs/src/EventLogChangeFeed-ReventlessPostgres.cmi +0 -0
- package/lib/bs/src/EventLogChangeFeed-ReventlessPostgres.cmt +0 -0
- package/lib/bs/src/EventLogChangeFeed.ast +0 -0
- package/lib/bs/src/EventLogChangeFeed.res +5 -2
- package/lib/bs/src/EventLogChangeFeed.res.mjs +3 -3
- package/lib/bs/src/EventLogStorage_Postgres-ReventlessPostgres.cmi +0 -0
- package/lib/bs/src/EventLogStorage_Postgres-ReventlessPostgres.cmj +0 -0
- package/lib/bs/src/EventLogStorage_Postgres-ReventlessPostgres.cmt +0 -0
- package/lib/bs/src/EventLogStorage_Postgres.ast +0 -0
- package/lib/bs/src/EventLogStorage_Postgres.res +12 -170
- package/lib/bs/src/EventLogStorage_Postgres.res.mjs +20 -186
- package/lib/bs/src/EventLogStorage_Postgres_Ops-ReventlessPostgres.cmi +0 -0
- package/lib/bs/src/EventLogStorage_Postgres_Ops-ReventlessPostgres.cmj +0 -0
- package/lib/bs/src/EventLogStorage_Postgres_Ops-ReventlessPostgres.cmt +0 -0
- package/lib/bs/src/EventLogStorage_Postgres_Ops.ast +0 -0
- package/lib/bs/src/EventLogStorage_Postgres_Ops.res +180 -0
- package/lib/bs/src/EventLogStorage_Postgres_Ops.res.mjs +202 -0
- package/lib/bs/src/PgChangeFeed-ReventlessPostgres.cmi +0 -0
- package/lib/bs/src/PgChangeFeed-ReventlessPostgres.cmt +0 -0
- package/lib/bs/src/PgChangeFeed.ast +0 -0
- package/lib/bs/src/PgChangeFeed.res +6 -1
- package/lib/bs/src/PgChangeFeed.res.mjs +6 -6
- package/lib/bs/src/PgDriver-ReventlessPostgres.cmi +0 -0
- package/lib/bs/src/PgDriver-ReventlessPostgres.cmt +0 -0
- package/lib/bs/src/PgDriver-ReventlessPostgres.cmti +0 -0
- package/lib/bs/src/PgDriver.ast +0 -0
- package/lib/bs/src/PgDriver.iast +0 -0
- package/lib/bs/src/PgSchema-ReventlessPostgres.cmi +0 -0
- package/lib/bs/src/PgSchema-ReventlessPostgres.cmt +0 -0
- package/lib/bs/src/PgSchema.ast +0 -0
- package/lib/bs/src/QueryDbStorage_Postgres-ReventlessPostgres.cmi +0 -0
- package/lib/bs/src/QueryDbStorage_Postgres-ReventlessPostgres.cmt +0 -0
- package/lib/bs/src/QueryDbStorage_Postgres.ast +0 -0
- package/lib/bs/src/QueryDbStorage_Postgres.res +10 -233
- package/lib/bs/src/QueryDbStorage_Postgres.res.mjs +25 -204
- package/lib/bs/src/QueryDbStorage_Postgres_Ops-ReventlessPostgres.cmi +0 -0
- package/lib/bs/src/QueryDbStorage_Postgres_Ops-ReventlessPostgres.cmj +0 -0
- package/lib/bs/src/QueryDbStorage_Postgres_Ops-ReventlessPostgres.cmt +0 -0
- package/lib/bs/src/QueryDbStorage_Postgres_Ops.ast +0 -0
- package/lib/bs/src/QueryDbStorage_Postgres_Ops.res +229 -0
- package/lib/bs/src/QueryDbStorage_Postgres_Ops.res.mjs +222 -0
- package/lib/bs/src/QueryEnginePostgres-ReventlessPostgres.cmi +0 -0
- package/lib/bs/src/QueryEnginePostgres-ReventlessPostgres.cmt +0 -0
- package/lib/bs/src/QueryEnginePostgres.ast +0 -0
- package/lib/bs/src/QueryEnginePostgres.res +9 -12
- package/lib/bs/src/QueryEnginePostgres.res.mjs +18 -24
- package/lib/bs/tests/PostgresIntegrationTest-ReventlessPostgres.cmi +0 -0
- package/lib/bs/tests/PostgresIntegrationTest-ReventlessPostgres.cmt +0 -0
- package/lib/bs/tests/PostgresIntegrationTest.ast +0 -0
- package/lib/bs/tests/QueryEnginePostgresListPageTest-ReventlessPostgres.cmi +0 -0
- package/lib/bs/tests/QueryEnginePostgresListPageTest-ReventlessPostgres.cmt +0 -0
- package/lib/bs/tests/QueryEnginePostgresListPageTest.ast +0 -0
- package/lib/ocaml/.compiler.log +2 -2
- package/lib/ocaml/DcbEventLogStorage_Postgres-ReventlessPostgres.cmi +0 -0
- package/lib/ocaml/DcbEventLogStorage_Postgres-ReventlessPostgres.cmj +0 -0
- package/lib/ocaml/DcbEventLogStorage_Postgres-ReventlessPostgres.cmt +0 -0
- package/lib/ocaml/DcbEventLogStorage_Postgres.ast +0 -0
- package/lib/ocaml/DcbEventLogStorage_Postgres.res +25 -340
- package/lib/ocaml/DcbEventLogStorage_Postgres_Ops-ReventlessPostgres.cmi +0 -0
- package/lib/ocaml/DcbEventLogStorage_Postgres_Ops-ReventlessPostgres.cmj +0 -0
- package/lib/ocaml/DcbEventLogStorage_Postgres_Ops-ReventlessPostgres.cmt +0 -0
- package/lib/ocaml/DcbEventLogStorage_Postgres_Ops.ast +0 -0
- package/lib/ocaml/DcbEventLogStorage_Postgres_Ops.res +350 -0
- package/lib/ocaml/EventLogChangeFeed-ReventlessPostgres.cmi +0 -0
- package/lib/ocaml/EventLogChangeFeed-ReventlessPostgres.cmt +0 -0
- package/lib/ocaml/EventLogChangeFeed.ast +0 -0
- package/lib/ocaml/EventLogChangeFeed.res +5 -2
- package/lib/ocaml/EventLogStorage_Postgres-ReventlessPostgres.cmi +0 -0
- package/lib/ocaml/EventLogStorage_Postgres-ReventlessPostgres.cmj +0 -0
- package/lib/ocaml/EventLogStorage_Postgres-ReventlessPostgres.cmt +0 -0
- package/lib/ocaml/EventLogStorage_Postgres.ast +0 -0
- package/lib/ocaml/EventLogStorage_Postgres.res +12 -170
- package/lib/ocaml/EventLogStorage_Postgres_Ops-ReventlessPostgres.cmi +0 -0
- package/lib/ocaml/EventLogStorage_Postgres_Ops-ReventlessPostgres.cmj +0 -0
- package/lib/ocaml/EventLogStorage_Postgres_Ops-ReventlessPostgres.cmt +0 -0
- package/lib/ocaml/EventLogStorage_Postgres_Ops.ast +0 -0
- package/lib/ocaml/EventLogStorage_Postgres_Ops.res +180 -0
- package/lib/ocaml/PgChangeFeed-ReventlessPostgres.cmi +0 -0
- package/lib/ocaml/PgChangeFeed-ReventlessPostgres.cmt +0 -0
- package/lib/ocaml/PgChangeFeed.ast +0 -0
- package/lib/ocaml/PgChangeFeed.res +6 -1
- package/lib/ocaml/PgDriver-ReventlessPostgres.cmi +0 -0
- package/lib/ocaml/PgDriver-ReventlessPostgres.cmt +0 -0
- package/lib/ocaml/PgDriver-ReventlessPostgres.cmti +0 -0
- package/lib/ocaml/PgDriver.ast +0 -0
- package/lib/ocaml/PgDriver.iast +0 -0
- package/lib/ocaml/PgSchema-ReventlessPostgres.cmi +0 -0
- package/lib/ocaml/PgSchema-ReventlessPostgres.cmt +0 -0
- package/lib/ocaml/PgSchema.ast +0 -0
- package/lib/ocaml/QueryDbStorage_Postgres-ReventlessPostgres.cmi +0 -0
- package/lib/ocaml/QueryDbStorage_Postgres-ReventlessPostgres.cmt +0 -0
- package/lib/ocaml/QueryDbStorage_Postgres.ast +0 -0
- package/lib/ocaml/QueryDbStorage_Postgres.res +10 -233
- package/lib/ocaml/QueryDbStorage_Postgres_Ops-ReventlessPostgres.cmi +0 -0
- package/lib/ocaml/QueryDbStorage_Postgres_Ops-ReventlessPostgres.cmj +0 -0
- package/lib/ocaml/QueryDbStorage_Postgres_Ops-ReventlessPostgres.cmt +0 -0
- package/lib/ocaml/QueryDbStorage_Postgres_Ops.ast +0 -0
- package/lib/ocaml/QueryDbStorage_Postgres_Ops.res +229 -0
- package/lib/ocaml/QueryEnginePostgres-ReventlessPostgres.cmi +0 -0
- package/lib/ocaml/QueryEnginePostgres-ReventlessPostgres.cmt +0 -0
- package/lib/ocaml/QueryEnginePostgres.ast +0 -0
- package/lib/ocaml/QueryEnginePostgres.res +9 -12
- package/lib/ocaml/ReventlessPostgres.cmi +0 -0
- package/lib/ocaml/ReventlessPostgres.cmt +0 -0
- package/lib/ocaml/ReventlessPostgres.mlmap +3 -0
- package/package.json +11 -11
- package/rescript.json +2 -1
- package/src/DcbEventLogStorage_Postgres.res +25 -340
- package/src/DcbEventLogStorage_Postgres.res.mjs +32 -348
- package/src/DcbEventLogStorage_Postgres_Ops.res +350 -0
- package/src/DcbEventLogStorage_Postgres_Ops.res.mjs +380 -0
- package/src/EventLogChangeFeed.res +5 -2
- package/src/EventLogChangeFeed.res.mjs +3 -3
- package/src/EventLogStorage_Postgres.res +12 -170
- package/src/EventLogStorage_Postgres.res.mjs +20 -186
- package/src/EventLogStorage_Postgres_Ops.res +180 -0
- package/src/EventLogStorage_Postgres_Ops.res.mjs +202 -0
- package/src/PgChangeFeed.res +6 -1
- package/src/PgChangeFeed.res.mjs +6 -6
- package/src/QueryDbStorage_Postgres.res +10 -233
- package/src/QueryDbStorage_Postgres.res.mjs +25 -204
- package/src/QueryDbStorage_Postgres_Ops.res +229 -0
- package/src/QueryDbStorage_Postgres_Ops.res.mjs +222 -0
- package/src/QueryEnginePostgres.res +9 -12
- package/src/QueryEnginePostgres.res.mjs +18 -24
- package/lib/ocaml/PostgresIntegrationTest-ReventlessPostgres.cmi +0 -0
- package/lib/ocaml/PostgresIntegrationTest-ReventlessPostgres.cmj +0 -0
- package/lib/ocaml/PostgresIntegrationTest-ReventlessPostgres.cmt +0 -0
- package/lib/ocaml/PostgresIntegrationTest.ast +0 -0
- package/lib/ocaml/QueryEnginePostgresListPageTest-ReventlessPostgres.cmi +0 -0
- package/lib/ocaml/QueryEnginePostgresListPageTest-ReventlessPostgres.cmj +0 -0
- package/lib/ocaml/QueryEnginePostgresListPageTest-ReventlessPostgres.cmt +0 -0
- package/lib/ocaml/QueryEnginePostgresListPageTest.ast +0 -0
- package/tests/PostgresIntegrationTest.res.mjs +0 -377
- package/tests/QueryEnginePostgresListPageTest.res.mjs +0 -461
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
// Runtime-pure QueryDb operations for the Postgres backend — JSONB document
|
|
2
|
+
// tables, one per read model.
|
|
3
|
+
//
|
|
4
|
+
// Holds the operation set + all SQL helpers and imports NO `@pulumi/pulumi`
|
|
5
|
+
// (deploy-time only), so the deployed-Lambda runtime can bind ops without dragging
|
|
6
|
+
// a deploy-time dep into its ESM import graph (which fails resolution on real
|
|
7
|
+
// Lambda). The thin `QueryDbStorage_Postgres` wrapper `include`s this and adds the
|
|
8
|
+
// deploy-time `Pulumi.Output`-shaped `storage` record + the `Make` functor.
|
|
9
|
+
// See docs/plans/deployed-lambda-esm-self-containment.md (Rung-3 finding).
|
|
10
|
+
|
|
11
|
+
open ReventlessCore
|
|
12
|
+
open Reventless.ReadModel
|
|
13
|
+
|
|
14
|
+
let tableName = (name: string): string => "qdb_" ++ name->String.replaceAll("-", "_")
|
|
15
|
+
|
|
16
|
+
// Collapse anything outside [A-Za-z0-9_] to _ — predictable, injection-safe idents.
|
|
17
|
+
let sanitizeIdent = (s: string): string =>
|
|
18
|
+
s->String.replaceRegExp(%re("/[^A-Za-z0-9_]/g"), "_")
|
|
19
|
+
|
|
20
|
+
let notExpiredClause = "(expires_at IS NULL OR expires_at > extract(epoch from now()))"
|
|
21
|
+
|
|
22
|
+
// JSONB text extraction for a single top-level field.
|
|
23
|
+
let jsonField = (field: string): string =>
|
|
24
|
+
`(item->>'${field->String.replaceAll("'", "''")}')`
|
|
25
|
+
|
|
26
|
+
let compositeExpr = (fields: array<string>, sep: string): string => {
|
|
27
|
+
let escapedSep = sep->String.replaceAll("'", "''")
|
|
28
|
+
fields->Array.map(jsonField)->Array.join(` || '${escapedSep}' || `)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
let indexExpressions = (idx: indexConfig): (string, option<string>) => {
|
|
32
|
+
let pkExpr = switch idx.pkFields {
|
|
33
|
+
| Some(fields) if fields->Array.length > 0 => compositeExpr(fields, idx.pkSep->Option.getOr("/"))
|
|
34
|
+
| _ =>
|
|
35
|
+
switch idx.idField {
|
|
36
|
+
| Some(field) => jsonField(field)
|
|
37
|
+
| None => jsonField(idx.index)
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
let skExpr = switch idx.skFields {
|
|
41
|
+
| Some(fields) if fields->Array.length > 0 =>
|
|
42
|
+
Some(compositeExpr(fields, idx.skSep->Option.getOr("/")))
|
|
43
|
+
| _ =>
|
|
44
|
+
switch idx.subIdField {
|
|
45
|
+
| Some(field) => Some(jsonField(field))
|
|
46
|
+
| None => None
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
(pkExpr, skExpr)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
let ensureTable = async (~pool, ~table) => {
|
|
53
|
+
await pool->PgDriver.exec(
|
|
54
|
+
`CREATE TABLE IF NOT EXISTS ${table} (partition_key text NOT NULL, sub_key text NOT NULL DEFAULT '', item jsonb NOT NULL, expires_at double precision, PRIMARY KEY (partition_key, sub_key))`,
|
|
55
|
+
)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
let ensureIndexes = async (~pool, ~table, ~indexes: array<indexConfig>) => {
|
|
59
|
+
for i in 0 to indexes->Array.length - 1 {
|
|
60
|
+
let idx = indexes->Array.getUnsafe(i)
|
|
61
|
+
let (pkExpr, skExprOpt) = indexExpressions(idx)
|
|
62
|
+
let indexName = `idx_${table}_${sanitizeIdent(idx.index)}`
|
|
63
|
+
let cols = switch skExprOpt {
|
|
64
|
+
| Some(skExpr) => `${pkExpr}, ${skExpr}`
|
|
65
|
+
| None => pkExpr
|
|
66
|
+
}
|
|
67
|
+
await pool->PgDriver.exec(`CREATE INDEX IF NOT EXISTS ${indexName} ON ${table} (${cols})`)
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
let decodeItem = (row: dict<JSON.t>): JSON.t =>
|
|
72
|
+
row->Dict.get("item")->Option.getOr(JSON.Encode.null)
|
|
73
|
+
|
|
74
|
+
let computeSubKey = (item: JSON.t, subIdField: option<string>): string =>
|
|
75
|
+
switch subIdField {
|
|
76
|
+
| None => ""
|
|
77
|
+
| Some(field) =>
|
|
78
|
+
switch item->JSON.Decode.object->Option.flatMap(o => o->Dict.get(field)) {
|
|
79
|
+
| Some(JSON.String(s)) => s
|
|
80
|
+
| _ => ""
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
let withId = (item: JSON.t, partitionKey: string): JSON.t =>
|
|
85
|
+
switch item->JSON.Decode.object {
|
|
86
|
+
| Some(obj) if obj->Dict.get("id")->Option.isNone =>
|
|
87
|
+
let copy = Dict.copy(obj)
|
|
88
|
+
copy->Dict.set("id", JSON.Encode.string(partitionKey))
|
|
89
|
+
JSON.Encode.object(copy)
|
|
90
|
+
| _ => item
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Plain operation set for a read model's qdb table. Exposed separately from
|
|
94
|
+
// `makeStorage` so the deployed-Lambda runtime (reventless-aws) can bind ops
|
|
95
|
+
// without touching the Pulumi-shaped `storage` record.
|
|
96
|
+
let makeOperations = (
|
|
97
|
+
~pool: PgDriver.pool,
|
|
98
|
+
~name: string,
|
|
99
|
+
~indexes: array<indexConfig>,
|
|
100
|
+
~subIdField: option<string>,
|
|
101
|
+
): QueryDb_Adapter.operations => {
|
|
102
|
+
let table = tableName(name)
|
|
103
|
+
// Schema setup is async and LAZY: kicked off by the first operation, not at
|
|
104
|
+
// construction. A deploy-time caller may build the ops on a machine that
|
|
105
|
+
// cannot reach the database (VPC-private RDS) — only the runtime, which
|
|
106
|
+
// actually calls an operation, may open a connection. Subsequent operations
|
|
107
|
+
// await the same promise (table + index creation runs exactly once).
|
|
108
|
+
let readyRef: ref<option<promise<unit>>> = ref(None)
|
|
109
|
+
let ready = () =>
|
|
110
|
+
switch readyRef.contents {
|
|
111
|
+
| Some(p) => p
|
|
112
|
+
| None =>
|
|
113
|
+
let p = {
|
|
114
|
+
open Promise
|
|
115
|
+
ensureTable(~pool, ~table)->then(() => ensureIndexes(~pool, ~table, ~indexes))
|
|
116
|
+
}
|
|
117
|
+
readyRef := Some(p)
|
|
118
|
+
p
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
let rowsFor = async (id: string): array<JSON.t> => {
|
|
122
|
+
await ready()
|
|
123
|
+
(await pool->PgDriver.query(
|
|
124
|
+
`SELECT item FROM ${table} WHERE partition_key = $1 AND ${notExpiredClause} ORDER BY sub_key ASC`,
|
|
125
|
+
[JSON.Encode.string(id)],
|
|
126
|
+
))->Array.map(decodeItem)
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
let saveOne = async (id: string, state: JSON.t, ttl: option<int>) => {
|
|
130
|
+
await ready()
|
|
131
|
+
let subKey = computeSubKey(state, subIdField)
|
|
132
|
+
let expiresAt = switch ttl {
|
|
133
|
+
| Some(t) => JSON.Encode.int(t)
|
|
134
|
+
| None => JSON.Encode.null
|
|
135
|
+
}
|
|
136
|
+
let _ = await pool->PgDriver.query(
|
|
137
|
+
`INSERT INTO ${table}(partition_key, sub_key, item, expires_at)
|
|
138
|
+
VALUES ($1, $2, $3::jsonb, $4)
|
|
139
|
+
ON CONFLICT (partition_key, sub_key)
|
|
140
|
+
DO UPDATE SET item = EXCLUDED.item, expires_at = EXCLUDED.expires_at`,
|
|
141
|
+
[
|
|
142
|
+
JSON.Encode.string(id),
|
|
143
|
+
JSON.Encode.string(subKey),
|
|
144
|
+
JSON.Encode.string(JSON.stringify(state)),
|
|
145
|
+
expiresAt,
|
|
146
|
+
],
|
|
147
|
+
)
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
let load: QueryDb.load<string, JSON.t> = async id => Ok(await rowsFor(id))
|
|
151
|
+
|
|
152
|
+
let loadStream: QueryDb.loadStream<string, JSON.t> =
|
|
153
|
+
id =>
|
|
154
|
+
Effect.promise(() => rowsFor(id))
|
|
155
|
+
->Stream.fromEffect
|
|
156
|
+
->Stream.flatMap(arr => Stream.fromIterable(arr))
|
|
157
|
+
|
|
158
|
+
let save: QueryDb.save<string, JSON.t> = async (id, state, _saveMode, ttl) => {
|
|
159
|
+
await saveOne(id, state, ttl)
|
|
160
|
+
Ok()
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
let saveBatch: QueryDb.saveBatch<string, JSON.t> = async batch => {
|
|
164
|
+
// pg has no synchronous multi-statement transaction helper here; the upserts
|
|
165
|
+
// are independent (distinct keys) so a sequential apply is equivalent.
|
|
166
|
+
for i in 0 to batch->Array.length - 1 {
|
|
167
|
+
let (id, state, ttl) = batch->Array.getUnsafe(i)
|
|
168
|
+
await saveOne(id, state, ttl)
|
|
169
|
+
}
|
|
170
|
+
Ok()
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Mirror DynamoDB's `ADD #field :inc`: read the counter on the partition item
|
|
174
|
+
// (counters are single-state, sub_key=""), add inc, upsert, return NEW total.
|
|
175
|
+
let count: QueryDb.count<string> = async (id, fieldName, inc) => {
|
|
176
|
+
await ready()
|
|
177
|
+
let existing = (await rowsFor(id))->Array.get(0)->Option.flatMap(JSON.Decode.object)
|
|
178
|
+
let current =
|
|
179
|
+
existing
|
|
180
|
+
->Option.flatMap(o => o->Dict.get(fieldName))
|
|
181
|
+
->Option.flatMap(JSON.Decode.float)
|
|
182
|
+
->Option.mapOr(0, Float.toInt)
|
|
183
|
+
let next = current + inc
|
|
184
|
+
let obj = switch existing {
|
|
185
|
+
| Some(o) => Dict.copy(o)
|
|
186
|
+
| None => Dict.make()
|
|
187
|
+
}
|
|
188
|
+
obj->Dict.set("id", JSON.Encode.string(id))
|
|
189
|
+
obj->Dict.set(fieldName, JSON.Encode.int(next))
|
|
190
|
+
await saveOne(id, JSON.Encode.object(obj), None)
|
|
191
|
+
Ok(next)
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
let delete: QueryDb.delete<string> = async (id, subIdOpt) => {
|
|
195
|
+
await ready()
|
|
196
|
+
let _ = switch subIdOpt {
|
|
197
|
+
| None =>
|
|
198
|
+
await pool->PgDriver.query(
|
|
199
|
+
`DELETE FROM ${table} WHERE partition_key = $1`,
|
|
200
|
+
[JSON.Encode.string(id)],
|
|
201
|
+
)
|
|
202
|
+
| Some((_, subValue)) =>
|
|
203
|
+
await pool->PgDriver.query(
|
|
204
|
+
`DELETE FROM ${table} WHERE partition_key = $1 AND sub_key = $2`,
|
|
205
|
+
[JSON.Encode.string(id), JSON.Encode.string(subValue)],
|
|
206
|
+
)
|
|
207
|
+
}
|
|
208
|
+
Ok()
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
let deleteBatch: QueryDb.deleteBatch<string> = async ids => {
|
|
212
|
+
for i in 0 to ids->Array.length - 1 {
|
|
213
|
+
let (id, subIdOpt) = ids->Array.getUnsafe(i)
|
|
214
|
+
let _ = await delete(id, subIdOpt)
|
|
215
|
+
}
|
|
216
|
+
Ok()
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
let ops: QueryDb_Adapter.operations = {
|
|
220
|
+
load,
|
|
221
|
+
loadStream,
|
|
222
|
+
save,
|
|
223
|
+
saveBatch,
|
|
224
|
+
count,
|
|
225
|
+
delete,
|
|
226
|
+
deleteBatch,
|
|
227
|
+
}
|
|
228
|
+
ops
|
|
229
|
+
}
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as Stdlib_JSON from "@rescript/runtime/lib/es6/Stdlib_JSON.js";
|
|
4
|
+
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
5
|
+
import * as Effect from "effect/Effect";
|
|
6
|
+
import * as Stream from "effect/Stream";
|
|
7
|
+
import * as PgDriver$ReventlessPostgres from "./PgDriver.res.mjs";
|
|
8
|
+
|
|
9
|
+
function tableName(name) {
|
|
10
|
+
return "qdb_" + name.replaceAll("-", "_");
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function sanitizeIdent(s) {
|
|
14
|
+
return s.replace(/[^A-Za-z0-9_]/g, "_");
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
let notExpiredClause = "(expires_at IS NULL OR expires_at > extract(epoch from now()))";
|
|
18
|
+
|
|
19
|
+
function jsonField(field) {
|
|
20
|
+
return `(item->>'` + field.replaceAll("'", "''") + `')`;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function compositeExpr(fields, sep) {
|
|
24
|
+
let escapedSep = sep.replaceAll("'", "''");
|
|
25
|
+
return fields.map(jsonField).join(` || '` + escapedSep + `' || `);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function indexExpressions(idx) {
|
|
29
|
+
let fields = idx.pkFields;
|
|
30
|
+
let pkExpr;
|
|
31
|
+
let exit = 0;
|
|
32
|
+
if (fields !== undefined && fields.length !== 0) {
|
|
33
|
+
pkExpr = compositeExpr(fields, Stdlib_Option.getOr(idx.pkSep, "/"));
|
|
34
|
+
} else {
|
|
35
|
+
exit = 1;
|
|
36
|
+
}
|
|
37
|
+
if (exit === 1) {
|
|
38
|
+
let field = idx.idField;
|
|
39
|
+
pkExpr = field !== undefined ? jsonField(field) : jsonField(idx.index);
|
|
40
|
+
}
|
|
41
|
+
let fields$1 = idx.skFields;
|
|
42
|
+
let skExpr;
|
|
43
|
+
let exit$1 = 0;
|
|
44
|
+
if (fields$1 !== undefined && fields$1.length !== 0) {
|
|
45
|
+
skExpr = compositeExpr(fields$1, Stdlib_Option.getOr(idx.skSep, "/"));
|
|
46
|
+
} else {
|
|
47
|
+
exit$1 = 1;
|
|
48
|
+
}
|
|
49
|
+
if (exit$1 === 1) {
|
|
50
|
+
let field$1 = idx.subIdField;
|
|
51
|
+
skExpr = field$1 !== undefined ? jsonField(field$1) : undefined;
|
|
52
|
+
}
|
|
53
|
+
return [
|
|
54
|
+
pkExpr,
|
|
55
|
+
skExpr
|
|
56
|
+
];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async function ensureTable(pool, table) {
|
|
60
|
+
return await PgDriver$ReventlessPostgres.exec(pool, `CREATE TABLE IF NOT EXISTS ` + table + ` (partition_key text NOT NULL, sub_key text NOT NULL DEFAULT '', item jsonb NOT NULL, expires_at double precision, PRIMARY KEY (partition_key, sub_key))`);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async function ensureIndexes(pool, table, indexes) {
|
|
64
|
+
for (let i = 0, i_finish = indexes.length; i < i_finish; ++i) {
|
|
65
|
+
let idx = indexes[i];
|
|
66
|
+
let match = indexExpressions(idx);
|
|
67
|
+
let skExprOpt = match[1];
|
|
68
|
+
let pkExpr = match[0];
|
|
69
|
+
let indexName = `idx_` + table + `_` + sanitizeIdent(idx.index);
|
|
70
|
+
let cols = skExprOpt !== undefined ? pkExpr + `, ` + skExprOpt : pkExpr;
|
|
71
|
+
await PgDriver$ReventlessPostgres.exec(pool, `CREATE INDEX IF NOT EXISTS ` + indexName + ` ON ` + table + ` (` + cols + `)`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function decodeItem(row) {
|
|
76
|
+
return Stdlib_Option.getOr(row["item"], null);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function computeSubKey(item, subIdField) {
|
|
80
|
+
if (subIdField === undefined) {
|
|
81
|
+
return "";
|
|
82
|
+
}
|
|
83
|
+
let match = Stdlib_Option.flatMap(Stdlib_JSON.Decode.object(item), o => o[subIdField]);
|
|
84
|
+
if (typeof match === "string") {
|
|
85
|
+
return match;
|
|
86
|
+
} else {
|
|
87
|
+
return "";
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function withId(item, partitionKey) {
|
|
92
|
+
let obj = Stdlib_JSON.Decode.object(item);
|
|
93
|
+
if (obj === undefined) {
|
|
94
|
+
return item;
|
|
95
|
+
}
|
|
96
|
+
if (!Stdlib_Option.isNone(obj["id"])) {
|
|
97
|
+
return item;
|
|
98
|
+
}
|
|
99
|
+
let copy = Object.assign({}, obj);
|
|
100
|
+
copy["id"] = partitionKey;
|
|
101
|
+
return copy;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function makeOperations(pool, name, indexes, subIdField) {
|
|
105
|
+
let table = tableName(name);
|
|
106
|
+
let readyRef = {
|
|
107
|
+
contents: undefined
|
|
108
|
+
};
|
|
109
|
+
let ready = () => {
|
|
110
|
+
let p = readyRef.contents;
|
|
111
|
+
if (p !== undefined) {
|
|
112
|
+
return p;
|
|
113
|
+
}
|
|
114
|
+
let p$1 = ensureTable(pool, table).then(() => ensureIndexes(pool, table, indexes));
|
|
115
|
+
readyRef.contents = p$1;
|
|
116
|
+
return p$1;
|
|
117
|
+
};
|
|
118
|
+
let rowsFor = async id => {
|
|
119
|
+
await ready();
|
|
120
|
+
return (await PgDriver$ReventlessPostgres.query(pool, `SELECT item FROM ` + table + ` WHERE partition_key = $1 AND ` + notExpiredClause + ` ORDER BY sub_key ASC`, [id])).map(decodeItem);
|
|
121
|
+
};
|
|
122
|
+
let saveOne = async (id, state, ttl) => {
|
|
123
|
+
await ready();
|
|
124
|
+
let subKey = computeSubKey(state, subIdField);
|
|
125
|
+
let expiresAt = ttl !== undefined ? ttl : null;
|
|
126
|
+
await PgDriver$ReventlessPostgres.query(pool, `INSERT INTO ` + table + `(partition_key, sub_key, item, expires_at)
|
|
127
|
+
VALUES ($1, $2, $3::jsonb, $4)
|
|
128
|
+
ON CONFLICT (partition_key, sub_key)
|
|
129
|
+
DO UPDATE SET item = EXCLUDED.item, expires_at = EXCLUDED.expires_at`, [
|
|
130
|
+
id,
|
|
131
|
+
subKey,
|
|
132
|
+
JSON.stringify(state),
|
|
133
|
+
expiresAt
|
|
134
|
+
]);
|
|
135
|
+
};
|
|
136
|
+
let load = async id => ({
|
|
137
|
+
TAG: "Ok",
|
|
138
|
+
_0: await rowsFor(id)
|
|
139
|
+
});
|
|
140
|
+
let loadStream = id => Stream.flatMap(Stream.fromEffect(Effect.promise(() => rowsFor(id))), arr => Stream.fromIterable(arr));
|
|
141
|
+
let save = async (id, state, _saveMode, ttl) => {
|
|
142
|
+
await saveOne(id, state, ttl);
|
|
143
|
+
return {
|
|
144
|
+
TAG: "Ok",
|
|
145
|
+
_0: undefined
|
|
146
|
+
};
|
|
147
|
+
};
|
|
148
|
+
let saveBatch = async batch => {
|
|
149
|
+
for (let i = 0, i_finish = batch.length; i < i_finish; ++i) {
|
|
150
|
+
let match = batch[i];
|
|
151
|
+
await saveOne(match[0], match[1], match[2]);
|
|
152
|
+
}
|
|
153
|
+
return {
|
|
154
|
+
TAG: "Ok",
|
|
155
|
+
_0: undefined
|
|
156
|
+
};
|
|
157
|
+
};
|
|
158
|
+
let count = async (id, fieldName, inc) => {
|
|
159
|
+
await ready();
|
|
160
|
+
let existing = Stdlib_Option.flatMap((await rowsFor(id))[0], Stdlib_JSON.Decode.object);
|
|
161
|
+
let current = Stdlib_Option.mapOr(Stdlib_Option.flatMap(Stdlib_Option.flatMap(existing, o => o[fieldName]), Stdlib_JSON.Decode.float), 0, prim => prim | 0);
|
|
162
|
+
let next = current + inc | 0;
|
|
163
|
+
let obj = existing !== undefined ? Object.assign({}, existing) : ({});
|
|
164
|
+
obj["id"] = id;
|
|
165
|
+
obj[fieldName] = next;
|
|
166
|
+
await saveOne(id, obj, undefined);
|
|
167
|
+
return {
|
|
168
|
+
TAG: "Ok",
|
|
169
|
+
_0: next
|
|
170
|
+
};
|
|
171
|
+
};
|
|
172
|
+
let $$delete = async (id, subIdOpt) => {
|
|
173
|
+
await ready();
|
|
174
|
+
if (subIdOpt !== undefined) {
|
|
175
|
+
await PgDriver$ReventlessPostgres.query(pool, `DELETE FROM ` + table + ` WHERE partition_key = $1 AND sub_key = $2`, [
|
|
176
|
+
id,
|
|
177
|
+
subIdOpt[1]
|
|
178
|
+
]);
|
|
179
|
+
} else {
|
|
180
|
+
await PgDriver$ReventlessPostgres.query(pool, `DELETE FROM ` + table + ` WHERE partition_key = $1`, [id]);
|
|
181
|
+
}
|
|
182
|
+
return {
|
|
183
|
+
TAG: "Ok",
|
|
184
|
+
_0: undefined
|
|
185
|
+
};
|
|
186
|
+
};
|
|
187
|
+
let deleteBatch = async ids => {
|
|
188
|
+
for (let i = 0, i_finish = ids.length; i < i_finish; ++i) {
|
|
189
|
+
let match = ids[i];
|
|
190
|
+
await $$delete(match[0], match[1]);
|
|
191
|
+
}
|
|
192
|
+
return {
|
|
193
|
+
TAG: "Ok",
|
|
194
|
+
_0: undefined
|
|
195
|
+
};
|
|
196
|
+
};
|
|
197
|
+
return {
|
|
198
|
+
load: load,
|
|
199
|
+
loadStream: loadStream,
|
|
200
|
+
save: save,
|
|
201
|
+
saveBatch: saveBatch,
|
|
202
|
+
count: count,
|
|
203
|
+
delete: $$delete,
|
|
204
|
+
deleteBatch: deleteBatch
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
export {
|
|
209
|
+
tableName,
|
|
210
|
+
sanitizeIdent,
|
|
211
|
+
notExpiredClause,
|
|
212
|
+
jsonField,
|
|
213
|
+
compositeExpr,
|
|
214
|
+
indexExpressions,
|
|
215
|
+
ensureTable,
|
|
216
|
+
ensureIndexes,
|
|
217
|
+
decodeItem,
|
|
218
|
+
computeSubKey,
|
|
219
|
+
withId,
|
|
220
|
+
makeOperations,
|
|
221
|
+
}
|
|
222
|
+
/* effect/Effect Not a pure module */
|
|
@@ -63,18 +63,18 @@ let subIdSql = (b: paramBuilder, field: string, cmp: QueryEngine.SubId.comparato
|
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
let notExpired =
|
|
66
|
+
let notExpired = QueryDbStorage_Postgres_Ops.notExpiredClause
|
|
67
67
|
|
|
68
68
|
// Add `id` (from partition_key) when absent — matches allRows/scan in the SQLite
|
|
69
69
|
// engine; partition-key queries return items as stored.
|
|
70
70
|
let decodeRow = (~withId, row: dict<JSON.t>): JSON.t => {
|
|
71
|
-
let item =
|
|
71
|
+
let item = QueryDbStorage_Postgres_Ops.decodeItem(row)
|
|
72
72
|
if withId {
|
|
73
73
|
let pk = switch row->Dict.get("partition_key") {
|
|
74
74
|
| Some(JSON.String(s)) => s
|
|
75
75
|
| _ => ""
|
|
76
76
|
}
|
|
77
|
-
|
|
77
|
+
QueryDbStorage_Postgres_Ops.withId(item, pk)
|
|
78
78
|
} else {
|
|
79
79
|
item
|
|
80
80
|
}
|
|
@@ -90,7 +90,7 @@ module Make = (P: {let pool: PgDriver.pool}) => {
|
|
|
90
90
|
~ascending=?,
|
|
91
91
|
~limit=?,
|
|
92
92
|
): array<JSON.t> => {
|
|
93
|
-
let table =
|
|
93
|
+
let table = QueryDbStorage_Postgres_Ops.tableName(readModelName)
|
|
94
94
|
let keyStr = switch key {
|
|
95
95
|
| Some(k) => k
|
|
96
96
|
| None => valueToText(id)
|
|
@@ -114,7 +114,7 @@ module Make = (P: {let pool: PgDriver.pool}) => {
|
|
|
114
114
|
}
|
|
115
115
|
|
|
116
116
|
let scan = async (~readModelName, ~filterConfigs, ~limit): array<JSON.t> => {
|
|
117
|
-
let table =
|
|
117
|
+
let table = QueryDbStorage_Postgres_Ops.tableName(readModelName)
|
|
118
118
|
let b = {params: []}
|
|
119
119
|
let where = [notExpired]
|
|
120
120
|
filterConfigs->Array.forEach(((field, cmp, v)) => where->Array.push(filterSql(b, field, cmp, v)))
|
|
@@ -138,7 +138,7 @@ module Make = (P: {let pool: PgDriver.pool}) => {
|
|
|
138
138
|
// (`ensureIndexes`) instead of scanning. String comparison mirrors the
|
|
139
139
|
// resolver's JS path (which only matched string-typed fields).
|
|
140
140
|
let indexLookup = async (~readModelName, field: string, value: string): array<JSON.t> => {
|
|
141
|
-
let table =
|
|
141
|
+
let table = QueryDbStorage_Postgres_Ops.tableName(readModelName)
|
|
142
142
|
let b = {params: []}
|
|
143
143
|
let sql = `SELECT partition_key, item FROM ${table} WHERE ${col(field)} = ${b->param(
|
|
144
144
|
JSON.Encode.string(value),
|
|
@@ -154,7 +154,7 @@ module Make = (P: {let pool: PgDriver.pool}) => {
|
|
|
154
154
|
if ids->Array.length == 0 {
|
|
155
155
|
[]
|
|
156
156
|
} else {
|
|
157
|
-
let table =
|
|
157
|
+
let table = QueryDbStorage_Postgres_Ops.tableName(readModelName)
|
|
158
158
|
let b = {params: []}
|
|
159
159
|
let idsJson = JSON.Encode.array(ids->Array.map(JSON.Encode.string))
|
|
160
160
|
let sql = `SELECT partition_key, item FROM ${table} WHERE partition_key = ANY(${b->param(
|
|
@@ -184,7 +184,7 @@ module Make = (P: {let pool: PgDriver.pool}) => {
|
|
|
184
184
|
~capability: GraphQL_FragmentGenerator.serverCapability,
|
|
185
185
|
~labelField as _,
|
|
186
186
|
): option<JSON.t> => {
|
|
187
|
-
let table =
|
|
187
|
+
let table = QueryDbStorage_Postgres_Ops.tableName(readModelName)
|
|
188
188
|
let filterDict =
|
|
189
189
|
argsDict->Dict.get("filter")->Option.flatMap(JSON.Decode.object)->Option.getOr(Dict.make())
|
|
190
190
|
let strNonEmpty = k =>
|
|
@@ -310,7 +310,7 @@ module Make = (P: {let pool: PgDriver.pool}) => {
|
|
|
310
310
|
~id: string,
|
|
311
311
|
~argsDict: dict<JSON.t>,
|
|
312
312
|
): JSON.t => {
|
|
313
|
-
let table =
|
|
313
|
+
let table = QueryDbStorage_Postgres_Ops.tableName(readModelName)
|
|
314
314
|
let filterDict =
|
|
315
315
|
argsDict->Dict.get("filter")->Option.flatMap(JSON.Decode.object)->Option.getOr(Dict.make())
|
|
316
316
|
let fstr = k => filterDict->Dict.get(k)->Option.flatMap(JSON.Decode.string)
|
|
@@ -380,7 +380,4 @@ module Make = (P: {let pool: PgDriver.pool}) => {
|
|
|
380
380
|
},
|
|
381
381
|
})
|
|
382
382
|
}
|
|
383
|
-
|
|
384
|
-
let make: QueryDb_Adapter.queryEngineMaker = _allQueryDbs =>
|
|
385
|
-
Pulumi.Output.make({QueryEngine.scan, query})
|
|
386
383
|
}
|
|
@@ -2,11 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
import * as Stdlib_JSON from "@rescript/runtime/lib/es6/Stdlib_JSON.js";
|
|
4
4
|
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
5
|
-
import * as Pulumi from "@pulumi/pulumi";
|
|
6
5
|
import * as Stdlib_Nullable from "@rescript/runtime/lib/es6/Stdlib_Nullable.js";
|
|
7
6
|
import * as PgDriver$ReventlessPostgres from "./PgDriver.res.mjs";
|
|
8
7
|
import * as QueryDbListQuery$ReventlessCore from "@reventlessdev/reventless-core/src/components/Api/QueryDbListQuery.res.mjs";
|
|
9
|
-
import * as
|
|
8
|
+
import * as QueryDbStorage_Postgres_Ops$ReventlessPostgres from "./QueryDbStorage_Postgres_Ops.res.mjs";
|
|
10
9
|
|
|
11
10
|
function valueToText(v) {
|
|
12
11
|
switch (v.TAG) {
|
|
@@ -105,25 +104,25 @@ function subIdSql(b, field, cmp, v) {
|
|
|
105
104
|
}
|
|
106
105
|
|
|
107
106
|
function decodeRow(withId, row) {
|
|
108
|
-
let item =
|
|
107
|
+
let item = QueryDbStorage_Postgres_Ops$ReventlessPostgres.decodeItem(row);
|
|
109
108
|
if (!withId) {
|
|
110
109
|
return item;
|
|
111
110
|
}
|
|
112
111
|
let match = row["partition_key"];
|
|
113
112
|
let pk = typeof match === "string" ? match : "";
|
|
114
|
-
return
|
|
113
|
+
return QueryDbStorage_Postgres_Ops$ReventlessPostgres.withId(item, pk);
|
|
115
114
|
}
|
|
116
115
|
|
|
117
116
|
function Make(P) {
|
|
118
117
|
let query = async (readModelName, key, id, subIdConfig, filterConfigs, ascending, limit) => {
|
|
119
|
-
let table =
|
|
118
|
+
let table = QueryDbStorage_Postgres_Ops$ReventlessPostgres.tableName(readModelName);
|
|
120
119
|
let keyStr = key !== undefined ? key : valueToText(id);
|
|
121
120
|
let b = {
|
|
122
121
|
params: []
|
|
123
122
|
};
|
|
124
123
|
let where = [
|
|
125
124
|
`partition_key = ` + param(b, keyStr),
|
|
126
|
-
|
|
125
|
+
QueryDbStorage_Postgres_Ops$ReventlessPostgres.notExpiredClause
|
|
127
126
|
];
|
|
128
127
|
if (subIdConfig !== undefined) {
|
|
129
128
|
where.push(subIdSql(b, subIdConfig[0], subIdConfig[1], subIdConfig[2]));
|
|
@@ -137,11 +136,11 @@ function Make(P) {
|
|
|
137
136
|
return (await PgDriver$ReventlessPostgres.query(P.pool, sql, b.params)).map(extra => decodeRow(false, extra));
|
|
138
137
|
};
|
|
139
138
|
let scan = async (readModelName, filterConfigs, limit) => {
|
|
140
|
-
let table =
|
|
139
|
+
let table = QueryDbStorage_Postgres_Ops$ReventlessPostgres.tableName(readModelName);
|
|
141
140
|
let b = {
|
|
142
141
|
params: []
|
|
143
142
|
};
|
|
144
|
-
let where = [
|
|
143
|
+
let where = [QueryDbStorage_Postgres_Ops$ReventlessPostgres.notExpiredClause];
|
|
145
144
|
filterConfigs.forEach(param => {
|
|
146
145
|
where.push(filterSql(b, param[0], param[1], param[2]));
|
|
147
146
|
});
|
|
@@ -149,29 +148,29 @@ function Make(P) {
|
|
|
149
148
|
return (await PgDriver$ReventlessPostgres.query(P.pool, sql, b.params)).map(extra => decodeRow(true, extra));
|
|
150
149
|
};
|
|
151
150
|
let indexLookup = async (readModelName, field, value) => {
|
|
152
|
-
let table =
|
|
151
|
+
let table = QueryDbStorage_Postgres_Ops$ReventlessPostgres.tableName(readModelName);
|
|
153
152
|
let b = {
|
|
154
153
|
params: []
|
|
155
154
|
};
|
|
156
|
-
let sql = `SELECT partition_key, item FROM ` + table + ` WHERE ` + col(field) + ` = ` + param(b, value) + ` AND ` +
|
|
155
|
+
let sql = `SELECT partition_key, item FROM ` + table + ` WHERE ` + col(field) + ` = ` + param(b, value) + ` AND ` + QueryDbStorage_Postgres_Ops$ReventlessPostgres.notExpiredClause;
|
|
157
156
|
return (await PgDriver$ReventlessPostgres.query(P.pool, sql, b.params)).map(extra => decodeRow(true, extra));
|
|
158
157
|
};
|
|
159
158
|
let byIds = async (readModelName, ids) => {
|
|
160
159
|
if (ids.length === 0) {
|
|
161
160
|
return [];
|
|
162
161
|
}
|
|
163
|
-
let table =
|
|
162
|
+
let table = QueryDbStorage_Postgres_Ops$ReventlessPostgres.tableName(readModelName);
|
|
164
163
|
let b = {
|
|
165
164
|
params: []
|
|
166
165
|
};
|
|
167
166
|
let idsJson = ids.map(prim => prim);
|
|
168
|
-
let sql = `SELECT partition_key, item FROM ` + table + ` WHERE partition_key = ANY(` + param(b, idsJson) + `::text[]) AND ` +
|
|
167
|
+
let sql = `SELECT partition_key, item FROM ` + table + ` WHERE partition_key = ANY(` + param(b, idsJson) + `::text[]) AND ` + QueryDbStorage_Postgres_Ops$ReventlessPostgres.notExpiredClause;
|
|
169
168
|
return (await PgDriver$ReventlessPostgres.query(P.pool, sql, b.params)).map(extra => decodeRow(true, extra));
|
|
170
169
|
};
|
|
171
170
|
let idExprC = `COALESCE(item->>'id', partition_key) COLLATE "C"`;
|
|
172
171
|
let jsonTextC = field => col(field) + ` COLLATE "C"`;
|
|
173
172
|
let listPage = async (readModelName, argsDict, capability, param$1) => {
|
|
174
|
-
let table =
|
|
173
|
+
let table = QueryDbStorage_Postgres_Ops$ReventlessPostgres.tableName(readModelName);
|
|
175
174
|
let filterDict = Stdlib_Option.getOr(Stdlib_Option.flatMap(argsDict["filter"], Stdlib_JSON.Decode.object), {});
|
|
176
175
|
let strNonEmpty = k => Stdlib_Option.mapOr(Stdlib_Option.flatMap(filterDict[k], Stdlib_JSON.Decode.string), false, s => s.length > 0);
|
|
177
176
|
let hasIds = Stdlib_Option.mapOr(Stdlib_Option.flatMap(filterDict["ids"], Stdlib_JSON.Decode.array), false, a => a.length !== 0);
|
|
@@ -183,7 +182,7 @@ function Make(P) {
|
|
|
183
182
|
let b = {
|
|
184
183
|
params: []
|
|
185
184
|
};
|
|
186
|
-
let whereParts = [
|
|
185
|
+
let whereParts = [QueryDbStorage_Postgres_Ops$ReventlessPostgres.notExpiredClause];
|
|
187
186
|
let valString = v => {
|
|
188
187
|
let s = Stdlib_JSON.Decode.string(v);
|
|
189
188
|
if (s !== undefined) {
|
|
@@ -233,7 +232,7 @@ function Make(P) {
|
|
|
233
232
|
return QueryDbListQuery$ReventlessCore.buildConnection(pageItems, hasMore, false, cursorValueOf);
|
|
234
233
|
};
|
|
235
234
|
let itemsPage = async (readModelName, param$1, id, argsDict) => {
|
|
236
|
-
let table =
|
|
235
|
+
let table = QueryDbStorage_Postgres_Ops$ReventlessPostgres.tableName(readModelName);
|
|
237
236
|
let filterDict = Stdlib_Option.getOr(Stdlib_Option.flatMap(argsDict["filter"], Stdlib_JSON.Decode.object), {});
|
|
238
237
|
let fstr = k => Stdlib_Option.flatMap(filterDict[k], Stdlib_JSON.Decode.string);
|
|
239
238
|
let orderDesc = Stdlib_Option.mapOr(fstr("order"), false, o => o === "DESC");
|
|
@@ -248,7 +247,7 @@ function Make(P) {
|
|
|
248
247
|
};
|
|
249
248
|
let where = [
|
|
250
249
|
`partition_key = ` + param(b, id),
|
|
251
|
-
|
|
250
|
+
QueryDbStorage_Postgres_Ops$ReventlessPostgres.notExpiredClause
|
|
252
251
|
];
|
|
253
252
|
Stdlib_Option.forEach(fstr("prefix"), p => {
|
|
254
253
|
where.push(`starts_with(sub_key, ` + param(b, p) + `)`);
|
|
@@ -304,10 +303,6 @@ function Make(P) {
|
|
|
304
303
|
}
|
|
305
304
|
};
|
|
306
305
|
};
|
|
307
|
-
let make = _allQueryDbs => Pulumi.output({
|
|
308
|
-
scan: scan,
|
|
309
|
-
query: query
|
|
310
|
-
});
|
|
311
306
|
return {
|
|
312
307
|
query: query,
|
|
313
308
|
scan: scan,
|
|
@@ -316,12 +311,11 @@ function Make(P) {
|
|
|
316
311
|
idExprC: idExprC,
|
|
317
312
|
jsonTextC: jsonTextC,
|
|
318
313
|
listPage: listPage,
|
|
319
|
-
itemsPage: itemsPage
|
|
320
|
-
make: make
|
|
314
|
+
itemsPage: itemsPage
|
|
321
315
|
};
|
|
322
316
|
}
|
|
323
317
|
|
|
324
|
-
let notExpired =
|
|
318
|
+
let notExpired = QueryDbStorage_Postgres_Ops$ReventlessPostgres.notExpiredClause;
|
|
325
319
|
|
|
326
320
|
export {
|
|
327
321
|
valueToText,
|
|
@@ -334,4 +328,4 @@ export {
|
|
|
334
328
|
decodeRow,
|
|
335
329
|
Make,
|
|
336
330
|
}
|
|
337
|
-
/*
|
|
331
|
+
/* PgDriver-ReventlessPostgres Not a pure module */
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|