@reventlessdev/reventless-postgres 3.0.0-alpha.15 → 3.0.0-alpha.151
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 +1093 -0
- package/README.md +83 -0
- package/lib/bs/.compiler.log +2 -2
- package/lib/bs/ReventlessPostgres.cmt +0 -0
- package/lib/bs/ReventlessPostgres.mlmap +0 -2
- package/lib/bs/compiler-info.json +4 -4
- package/lib/bs/src/DcbEventLogStorage_Postgres-ReventlessPostgres.cmi +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 +1 -1
- package/lib/bs/src/DcbEventLogStorage_Postgres_Ops-ReventlessPostgres.cmi +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 +43 -42
- package/lib/bs/src/DcbEventLogStorage_Postgres_Ops.res.mjs +4 -4
- 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 +15 -6
- 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.cmt +0 -0
- package/lib/bs/src/EventLogStorage_Postgres.ast +0 -0
- package/lib/bs/src/EventLogStorage_Postgres.res +1 -1
- package/lib/bs/src/EventLogStorage_Postgres_Ops-ReventlessPostgres.cmi +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 +24 -14
- 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 +21 -9
- 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/PgDriver.res +1 -2
- 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 +7 -2
- package/lib/bs/src/QueryDbStorage_Postgres.res.mjs +1 -1
- package/lib/bs/src/QueryDbStorage_Postgres_Ops-ReventlessPostgres.cmi +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 +14 -14
- 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 +141 -42
- package/lib/bs/src/QueryEnginePostgres.res.mjs +53 -30
- 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/PostgresIntegrationTest.res +157 -104
- 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/bs/tests/QueryEnginePostgresListPageTest.res +29 -6
- package/lib/bs/tests/QueryEnginePostgresListPageTest.res.mjs +4 -4
- package/lib/ocaml/.compiler.log +2 -2
- package/lib/ocaml/DcbEventLogStorage_Postgres-ReventlessPostgres.cmi +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 +1 -1
- package/lib/ocaml/DcbEventLogStorage_Postgres_Ops-ReventlessPostgres.cmi +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 +43 -42
- 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 +15 -6
- package/lib/ocaml/EventLogStorage_Postgres-ReventlessPostgres.cmi +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 +1 -1
- package/lib/ocaml/EventLogStorage_Postgres_Ops-ReventlessPostgres.cmi +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 +24 -14
- 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 +21 -9
- 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/PgDriver.res +1 -2
- 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/PostgresIntegrationTest.res +157 -104
- 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 +7 -2
- package/lib/ocaml/QueryDbStorage_Postgres_Ops-ReventlessPostgres.cmi +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 +14 -14
- 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 +141 -42
- package/lib/ocaml/QueryEnginePostgresListPageTest.res +29 -6
- package/lib/ocaml/ReventlessPostgres.cmt +0 -0
- package/package.json +13 -13
- package/rescript.json +2 -1
- package/src/DcbEventLogStorage_Postgres.res +1 -1
- package/src/DcbEventLogStorage_Postgres_Ops.res +43 -42
- package/src/DcbEventLogStorage_Postgres_Ops.res.mjs +4 -4
- package/src/EventLogChangeFeed.res +15 -6
- package/src/EventLogChangeFeed.res.mjs +3 -3
- package/src/EventLogStorage_Postgres.res +1 -1
- package/src/EventLogStorage_Postgres_Ops.res +24 -14
- package/src/PgChangeFeed.res +21 -9
- package/src/PgChangeFeed.res.mjs +6 -6
- package/src/PgDriver.res +1 -2
- package/src/QueryDbStorage_Postgres.res +7 -2
- package/src/QueryDbStorage_Postgres.res.mjs +1 -1
- package/src/QueryDbStorage_Postgres_Ops.res +14 -14
- package/src/QueryEnginePostgres.res +141 -42
- package/src/QueryEnginePostgres.res.mjs +53 -30
- package/tests/PostgresIntegrationTest.res +157 -104
- package/tests/QueryEnginePostgresListPageTest.res +29 -6
- 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
|
@@ -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,45 @@ 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
|
-
let
|
|
174
|
-
let
|
|
172
|
+
let notRetiredC = scope => {
|
|
173
|
+
let key = scope.field.replaceAll("'", "''");
|
|
174
|
+
let states = scope.values;
|
|
175
|
+
if (states !== undefined) {
|
|
176
|
+
if (states.length !== 0) {
|
|
177
|
+
return "(" + states.map(state => {
|
|
178
|
+
let lit = `'"` + state.replaceAll("'", "''") + `"'::jsonb`;
|
|
179
|
+
return `(item->'` + key + `') IS DISTINCT FROM ` + lit;
|
|
180
|
+
}).join(" AND ") + ")";
|
|
181
|
+
} else {
|
|
182
|
+
return "TRUE";
|
|
183
|
+
}
|
|
184
|
+
} else {
|
|
185
|
+
return `(item->'` + key + `') IS DISTINCT FROM ` + "'true'::jsonb";
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
let listPage = async (readModelName, argsDict, capability, param$1, ownerScope, retiredScope) => {
|
|
189
|
+
let table = QueryDbStorage_Postgres_Ops$ReventlessPostgres.tableName(readModelName);
|
|
175
190
|
let filterDict = Stdlib_Option.getOr(Stdlib_Option.flatMap(argsDict["filter"], Stdlib_JSON.Decode.object), {});
|
|
176
191
|
let strNonEmpty = k => Stdlib_Option.mapOr(Stdlib_Option.flatMap(filterDict[k], Stdlib_JSON.Decode.string), false, s => s.length > 0);
|
|
177
192
|
let hasIds = Stdlib_Option.mapOr(Stdlib_Option.flatMap(filterDict["ids"], Stdlib_JSON.Decode.array), false, a => a.length !== 0);
|
|
@@ -183,7 +198,13 @@ function Make(P) {
|
|
|
183
198
|
let b = {
|
|
184
199
|
params: []
|
|
185
200
|
};
|
|
186
|
-
let whereParts = [
|
|
201
|
+
let whereParts = [QueryDbStorage_Postgres_Ops$ReventlessPostgres.notExpiredClause];
|
|
202
|
+
if (ownerScope !== undefined) {
|
|
203
|
+
whereParts.push(jsonTextC(ownerScope[0]) + ` = ` + param(b, ownerScope[1]));
|
|
204
|
+
}
|
|
205
|
+
if (retiredScope !== undefined) {
|
|
206
|
+
whereParts.push(notRetiredC(retiredScope));
|
|
207
|
+
}
|
|
187
208
|
let valString = v => {
|
|
188
209
|
let s = Stdlib_JSON.Decode.string(v);
|
|
189
210
|
if (s !== undefined) {
|
|
@@ -214,11 +235,11 @@ function Make(P) {
|
|
|
214
235
|
let orderByField = Stdlib_Option.flatMap(Stdlib_Option.flatMap(orderByDict, ob => ob["field"]), Stdlib_JSON.Decode.string);
|
|
215
236
|
let isDesc = Stdlib_Option.getOr(Stdlib_Option.flatMap(Stdlib_Option.flatMap(orderByDict, ob => ob["direction"]), Stdlib_JSON.Decode.string), "ASC") === "DESC";
|
|
216
237
|
let cursorExpr = orderByField !== undefined ? jsonTextC(orderByField) : idExprC;
|
|
217
|
-
let
|
|
218
|
-
if (
|
|
238
|
+
let afterCursor = Stdlib_Option.flatMap(argsDict["after"], Stdlib_JSON.Decode.string);
|
|
239
|
+
if (afterCursor !== undefined) {
|
|
219
240
|
whereParts.push(cursorExpr + ` ` + (
|
|
220
241
|
isDesc ? "<" : ">"
|
|
221
|
-
) + ` ` + param(b, QueryDbListQuery$ReventlessCore.decodeCursor(
|
|
242
|
+
) + ` ` + param(b, QueryDbListQuery$ReventlessCore.decodeCursor(afterCursor)));
|
|
222
243
|
}
|
|
223
244
|
let orderClause = orderByField !== undefined ? jsonTextC(orderByField) + ` ` + (
|
|
224
245
|
isDesc ? "DESC" : "ASC"
|
|
@@ -230,10 +251,10 @@ function Make(P) {
|
|
|
230
251
|
let pageItems = rows.slice(0, pageSize);
|
|
231
252
|
let cursorField = Stdlib_Option.getOr(orderByField, "id");
|
|
232
253
|
let cursorValueOf = item => Stdlib_Option.getOr(QueryDbListQuery$ReventlessCore.getFieldString(item, cursorField), QueryDbListQuery$ReventlessCore.getId(item));
|
|
233
|
-
return QueryDbListQuery$ReventlessCore.buildConnection(pageItems, hasMore,
|
|
254
|
+
return QueryDbListQuery$ReventlessCore.buildConnection(pageItems, hasMore, Stdlib_Option.isSome(afterCursor), cursorValueOf);
|
|
234
255
|
};
|
|
235
|
-
let itemsPage = async (readModelName, param$1, id, argsDict) => {
|
|
236
|
-
let table =
|
|
256
|
+
let itemsPage = async (readModelName, param$1, id, argsDict, ownerScope, retiredScope) => {
|
|
257
|
+
let table = QueryDbStorage_Postgres_Ops$ReventlessPostgres.tableName(readModelName);
|
|
237
258
|
let filterDict = Stdlib_Option.getOr(Stdlib_Option.flatMap(argsDict["filter"], Stdlib_JSON.Decode.object), {});
|
|
238
259
|
let fstr = k => Stdlib_Option.flatMap(filterDict[k], Stdlib_JSON.Decode.string);
|
|
239
260
|
let orderDesc = Stdlib_Option.mapOr(fstr("order"), false, o => o === "DESC");
|
|
@@ -248,8 +269,14 @@ function Make(P) {
|
|
|
248
269
|
};
|
|
249
270
|
let where = [
|
|
250
271
|
`partition_key = ` + param(b, id),
|
|
251
|
-
|
|
272
|
+
QueryDbStorage_Postgres_Ops$ReventlessPostgres.notExpiredClause
|
|
252
273
|
];
|
|
274
|
+
if (ownerScope !== undefined) {
|
|
275
|
+
where.push(jsonTextC(ownerScope[0]) + ` = ` + param(b, ownerScope[1]));
|
|
276
|
+
}
|
|
277
|
+
if (retiredScope !== undefined) {
|
|
278
|
+
where.push(notRetiredC(retiredScope));
|
|
279
|
+
}
|
|
253
280
|
Stdlib_Option.forEach(fstr("prefix"), p => {
|
|
254
281
|
where.push(`starts_with(sub_key, ` + param(b, p) + `)`);
|
|
255
282
|
});
|
|
@@ -304,10 +331,6 @@ function Make(P) {
|
|
|
304
331
|
}
|
|
305
332
|
};
|
|
306
333
|
};
|
|
307
|
-
let make = _allQueryDbs => Pulumi.output({
|
|
308
|
-
scan: scan,
|
|
309
|
-
query: query
|
|
310
|
-
});
|
|
311
334
|
return {
|
|
312
335
|
query: query,
|
|
313
336
|
scan: scan,
|
|
@@ -315,13 +338,13 @@ function Make(P) {
|
|
|
315
338
|
byIds: byIds,
|
|
316
339
|
idExprC: idExprC,
|
|
317
340
|
jsonTextC: jsonTextC,
|
|
341
|
+
notRetiredC: notRetiredC,
|
|
318
342
|
listPage: listPage,
|
|
319
|
-
itemsPage: itemsPage
|
|
320
|
-
make: make
|
|
343
|
+
itemsPage: itemsPage
|
|
321
344
|
};
|
|
322
345
|
}
|
|
323
346
|
|
|
324
|
-
let notExpired =
|
|
347
|
+
let notExpired = QueryDbStorage_Postgres_Ops$ReventlessPostgres.notExpiredClause;
|
|
325
348
|
|
|
326
349
|
export {
|
|
327
350
|
valueToText,
|
|
@@ -334,4 +357,4 @@ export {
|
|
|
334
357
|
decodeRow,
|
|
335
358
|
Make,
|
|
336
359
|
}
|
|
337
|
-
/*
|
|
360
|
+
/* PgDriver-ReventlessPostgres Not a pure module */
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -100,7 +100,11 @@ switch processEnv->Dict.get("PG_URL") {
|
|
|
100
100
|
|
|
101
101
|
testPromise("append + read round-trips events with tags", async () => {
|
|
102
102
|
let (_n, ops, _s) = makeLog("dcb-rt")
|
|
103
|
-
let e1 = stored(
|
|
103
|
+
let e1 = stored(
|
|
104
|
+
"ItemAdded",
|
|
105
|
+
[{key: "itemId", value: "x1"}],
|
|
106
|
+
jsonObj([("n", JSON.Encode.string("w"))]),
|
|
107
|
+
)
|
|
104
108
|
let r = await ops.append([e1])
|
|
105
109
|
switch r {
|
|
106
110
|
| Ok(_) => expect(true)->toBe(true)
|
|
@@ -116,7 +120,12 @@ switch processEnv->Dict.get("PG_URL") {
|
|
|
116
120
|
|
|
117
121
|
testPromise("conditional append conflicts when the boundary already has an event", async () => {
|
|
118
122
|
let (_n, ops, _s) = makeLog("dcb-cond")
|
|
119
|
-
let mk = who =>
|
|
123
|
+
let mk = who =>
|
|
124
|
+
stored(
|
|
125
|
+
"Reserved",
|
|
126
|
+
[{key: "seatId", value: "s1"}],
|
|
127
|
+
jsonObj([("who", JSON.Encode.string(who))]),
|
|
128
|
+
)
|
|
120
129
|
let r1 = await ops.append([mk("a")])
|
|
121
130
|
switch r1 {
|
|
122
131
|
| Ok(_) => expect(true)->toBe(true)
|
|
@@ -134,37 +143,46 @@ switch processEnv->Dict.get("PG_URL") {
|
|
|
134
143
|
})
|
|
135
144
|
|
|
136
145
|
let writeSkew = (strategy, logName) =>
|
|
137
|
-
testPromise(
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
146
|
+
testPromise(
|
|
147
|
+
`write-skew: exactly one of two concurrent appends wins (${logName})`,
|
|
148
|
+
async () => {
|
|
149
|
+
let (_n, ops, _s) = DcbEventLogStorage_Postgres.makeStorage(
|
|
150
|
+
~pool,
|
|
151
|
+
~name=logName,
|
|
152
|
+
~indexes=[],
|
|
153
|
+
~partitionTag=DcbTag.Simple({key: "k"}),
|
|
154
|
+
~opts,
|
|
155
|
+
~lockStrategy=strategy,
|
|
156
|
+
)
|
|
157
|
+
let cond: DcbTag.appendCondition = {
|
|
158
|
+
query: [{eventTypes: ["Reserved"], tags: [{key: "seatId", value: "hot"}]}],
|
|
159
|
+
}
|
|
160
|
+
let mk = who =>
|
|
161
|
+
stored(
|
|
162
|
+
"Reserved",
|
|
163
|
+
[{key: "seatId", value: "hot"}],
|
|
164
|
+
jsonObj([("who", JSON.Encode.string(who))]),
|
|
165
|
+
)
|
|
166
|
+
// Dispatch BOTH before awaiting either — genuinely concurrent on the pool.
|
|
167
|
+
let p1 = ops.append([mk("a")], ~condition=cond)
|
|
168
|
+
let p2 = ops.append([mk("b")], ~condition=cond)
|
|
169
|
+
let r1 = await p1
|
|
170
|
+
let r2 = await p2
|
|
171
|
+
let isOk = r =>
|
|
172
|
+
switch r {
|
|
173
|
+
| Ok(_) => true
|
|
174
|
+
| _ => false
|
|
175
|
+
}
|
|
176
|
+
let isConflict = r => r == Error(ReventlessInfra.DcbEventLog.Conflict)
|
|
177
|
+
let oks = [r1, r2]->Array.filter(isOk)->Array.length
|
|
178
|
+
let conflicts = [r1, r2]->Array.filter(isConflict)->Array.length
|
|
179
|
+
expect(oks)->toBe(1)
|
|
180
|
+
expect(conflicts)->toBe(1)
|
|
181
|
+
// And only one event actually landed on the boundary.
|
|
182
|
+
let read = await ops.read(~query=[{tags: [{key: "seatId", value: "hot"}]}])
|
|
183
|
+
expect(read.events->Array.length)->toBe(1)
|
|
184
|
+
},
|
|
185
|
+
)
|
|
168
186
|
|
|
169
187
|
writeSkew(#AdvisoryLocks, "dcb-skew-advisory")
|
|
170
188
|
writeSkew(#RowLocks, "dcb-skew-rows")
|
|
@@ -176,17 +194,31 @@ switch processEnv->Dict.get("PG_URL") {
|
|
|
176
194
|
}
|
|
177
195
|
let n = 12
|
|
178
196
|
// Dispatch all N before awaiting any — genuinely concurrent on the pool.
|
|
179
|
-
let promises =
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
197
|
+
let promises =
|
|
198
|
+
Array.make(~length=n, 0)->Array.mapWithIndex(
|
|
199
|
+
(_, i) =>
|
|
200
|
+
ops.append(
|
|
201
|
+
[
|
|
202
|
+
stored(
|
|
203
|
+
"Claimed",
|
|
204
|
+
[{key: "prizeId", value: "p1"}],
|
|
205
|
+
jsonObj([("who", JSON.Encode.int(i))]),
|
|
206
|
+
),
|
|
207
|
+
],
|
|
208
|
+
~condition=cond,
|
|
209
|
+
),
|
|
183
210
|
)
|
|
184
|
-
)
|
|
185
211
|
let results = await Promise.all(promises)
|
|
186
|
-
let oks =
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
212
|
+
let oks =
|
|
213
|
+
results
|
|
214
|
+
->Array.filter(
|
|
215
|
+
r =>
|
|
216
|
+
switch r {
|
|
217
|
+
| Ok(_) => true
|
|
218
|
+
| _ => false
|
|
219
|
+
},
|
|
220
|
+
)
|
|
221
|
+
->Array.length
|
|
190
222
|
expect(oks)->toBe(1)
|
|
191
223
|
// No lost updates: exactly one Claimed landed on the boundary.
|
|
192
224
|
let read = await ops.read(~query=[{tags: [{key: "prizeId", value: "p1"}]}])
|
|
@@ -195,7 +227,8 @@ switch processEnv->Dict.get("PG_URL") {
|
|
|
195
227
|
|
|
196
228
|
testPromise("cursors are monotonic and usable as `after`", async () => {
|
|
197
229
|
let (_n, ops, _s) = makeLog("dcb-cursor")
|
|
198
|
-
let mk = i =>
|
|
230
|
+
let mk = i =>
|
|
231
|
+
stored("Tick", [{key: "streamId", value: "c1"}], jsonObj([("i", JSON.Encode.int(i))]))
|
|
199
232
|
let _ = await ops.append([mk(0)])
|
|
200
233
|
let mid = switch await ops.append([mk(1)]) {
|
|
201
234
|
| Ok(pos) => pos
|
|
@@ -222,83 +255,103 @@ switch processEnv->Dict.get("PG_URL") {
|
|
|
222
255
|
let _ = await ops.append([mk(0), mk(1), mk(2)])
|
|
223
256
|
|
|
224
257
|
let collected = ref(0)
|
|
225
|
-
let processed = await PgChangeFeed.drain(
|
|
226
|
-
|
|
227
|
-
|
|
258
|
+
let processed = await PgChangeFeed.drain(
|
|
259
|
+
pool,
|
|
260
|
+
~logName="feed-log",
|
|
261
|
+
~subscriber="sub-1",
|
|
262
|
+
~handle=async evs => {
|
|
263
|
+
collected := collected.contents + evs->Array.length
|
|
264
|
+
},
|
|
265
|
+
)
|
|
228
266
|
expect(processed)->toBe(3)
|
|
229
267
|
expect(collected.contents)->toBe(3)
|
|
230
268
|
|
|
231
269
|
// A second drain from the saved checkpoint sees nothing new.
|
|
232
|
-
let again = await PgChangeFeed.drain(
|
|
270
|
+
let again = await PgChangeFeed.drain(
|
|
271
|
+
pool,
|
|
272
|
+
~logName="feed-log",
|
|
273
|
+
~subscriber="sub-1",
|
|
274
|
+
~handle=async _ => (),
|
|
275
|
+
)
|
|
233
276
|
expect(again)->toBe(0)
|
|
234
277
|
})
|
|
235
278
|
})
|
|
236
279
|
|
|
237
280
|
describe("classic change feed (event_log, B2.5)", () => {
|
|
238
|
-
testPromise(
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
281
|
+
testPromise(
|
|
282
|
+
"drains classic events in commit order, with fields, then checkpoints",
|
|
283
|
+
async () => {
|
|
284
|
+
let (_n, ops, _s) = EventLogStorage_Postgres.makeStorage(~pool, ~name="cf-orders", ~opts)
|
|
285
|
+
let _ = await ops.append(0, "agg-1", [evJson("m0", 1), evJson("m1", 2)])
|
|
286
|
+
let _ = await ops.append(0, "agg-2", [evJson("m2", 3)])
|
|
242
287
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
288
|
+
let collected = ref([])
|
|
289
|
+
let processed = await EventLogChangeFeed.drain(
|
|
290
|
+
pool,
|
|
291
|
+
~logName="cf-orders",
|
|
292
|
+
~subscriber="cf-sub",
|
|
293
|
+
~handle=async evs => collected := collected.contents->Array.concat(evs),
|
|
294
|
+
)
|
|
295
|
+
expect(processed)->toBe(3)
|
|
296
|
+
expect(collected.contents->Array.length)->toBe(3)
|
|
252
297
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
298
|
+
// Fields round-trip from the stored row.
|
|
299
|
+
let first = collected.contents->Array.getUnsafe(0)
|
|
300
|
+
expect(first.aggregateId)->toBe("agg-1")
|
|
301
|
+
expect(first.seqNr)->toBe(0)
|
|
302
|
+
expect(first.msgId)->toEqual(Some("m0"))
|
|
258
303
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
304
|
+
// Cursors are strictly increasing in drain order.
|
|
305
|
+
let cursors = collected.contents->Array.map(e => e.cursor)
|
|
306
|
+
let increasing = ref(true)
|
|
307
|
+
for i in 1 to cursors->Array.length - 1 {
|
|
308
|
+
if cursors->Array.getUnsafe(i) <= cursors->Array.getUnsafe(i - 1) {
|
|
309
|
+
increasing := false
|
|
310
|
+
}
|
|
265
311
|
}
|
|
266
|
-
|
|
267
|
-
expect(increasing.contents)->toBe(true)
|
|
312
|
+
expect(increasing.contents)->toBe(true)
|
|
268
313
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
314
|
+
// Second drain from the saved checkpoint sees nothing new.
|
|
315
|
+
let again = await EventLogChangeFeed.drain(
|
|
316
|
+
pool,
|
|
317
|
+
~logName="cf-orders",
|
|
318
|
+
~subscriber="cf-sub",
|
|
319
|
+
~handle=async _ => (),
|
|
320
|
+
)
|
|
321
|
+
expect(again)->toBe(0)
|
|
322
|
+
},
|
|
323
|
+
)
|
|
278
324
|
|
|
279
|
-
testPromise(
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
Array.make(~length=n, 0)->Array.mapWithIndex((_, i) =>
|
|
287
|
-
ops.append(0, "agg-" ++ Int.toString(i), [evJson("m" ++ Int.toString(i), i)])
|
|
325
|
+
testPromise(
|
|
326
|
+
"concurrent appends across aggregates: every event drained exactly once",
|
|
327
|
+
async () => {
|
|
328
|
+
let (_n, ops, _s) = EventLogStorage_Postgres.makeStorage(
|
|
329
|
+
~pool,
|
|
330
|
+
~name="cf-concurrent",
|
|
331
|
+
~opts,
|
|
288
332
|
)
|
|
289
|
-
|
|
333
|
+
let n = 20
|
|
334
|
+
// One event per aggregate, all dispatched before awaiting — genuinely
|
|
335
|
+
// concurrent on the pool, so global_seq is assigned in interleaved/undefined
|
|
336
|
+
// commit order. The xmin fence must still drain every event exactly once.
|
|
337
|
+
let promises =
|
|
338
|
+
Array.make(~length=n, 0)->Array.mapWithIndex(
|
|
339
|
+
(_, i) => ops.append(0, "agg-" ++ Int.toString(i), [evJson("m" ++ Int.toString(i), i)]),
|
|
340
|
+
)
|
|
341
|
+
let _ = await Promise.all(promises)
|
|
290
342
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
343
|
+
let collected = ref([])
|
|
344
|
+
let _ = await EventLogChangeFeed.drain(
|
|
345
|
+
pool,
|
|
346
|
+
~logName="cf-concurrent",
|
|
347
|
+
~subscriber="cf-conc-sub",
|
|
348
|
+
~handle=async evs => collected := collected.contents->Array.concat(evs),
|
|
349
|
+
)
|
|
350
|
+
// No skips: all N events present. No dupes: N distinct cursors.
|
|
351
|
+
expect(collected.contents->Array.length)->toBe(n)
|
|
352
|
+
let distinctCursors = collected.contents->Array.map(e => e.cursor)->Set.fromArray
|
|
353
|
+
expect(distinctCursors->Set.size)->toBe(n)
|
|
354
|
+
},
|
|
355
|
+
)
|
|
303
356
|
})
|
|
304
357
|
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -135,7 +135,12 @@ switch processEnv->Dict.get("PG_URL") {
|
|
|
135
135
|
|
|
136
136
|
// Assert the push-down declines this shape (resolver falls back to the spec).
|
|
137
137
|
let checkFallback = async args => {
|
|
138
|
-
let r = await Eng.listPage(
|
|
138
|
+
let r = await Eng.listPage(
|
|
139
|
+
~readModelName=name,
|
|
140
|
+
~argsDict=argsOf(args),
|
|
141
|
+
~capability,
|
|
142
|
+
~labelField="name",
|
|
143
|
+
)
|
|
139
144
|
expect(r->Option.isSome)->toBe(false)
|
|
140
145
|
}
|
|
141
146
|
|
|
@@ -204,7 +209,9 @@ switch processEnv->Dict.get("PG_URL") {
|
|
|
204
209
|
checkFallback([("filter", filterOf([("searchPrefix", JSON.Encode.string("A"))]))])
|
|
205
210
|
)
|
|
206
211
|
testPromise("ids → fallback", () =>
|
|
207
|
-
checkFallback([
|
|
212
|
+
checkFallback([
|
|
213
|
+
("filter", filterOf([("ids", JSON.Encode.array([JSON.Encode.string("p-1")]))])),
|
|
214
|
+
])
|
|
208
215
|
)
|
|
209
216
|
testPromise("backward (last/before) → fallback", () =>
|
|
210
217
|
checkFallback([("last", JSON.Encode.int(2)), ("before", JSON.Encode.string(cur("p-4")))])
|
|
@@ -265,10 +272,20 @@ switch processEnv->Dict.get("PG_URL") {
|
|
|
265
272
|
->Array.filterMap(e => e->field("node")->Option.flatMap(n => n->str("seq")))
|
|
266
273
|
|
|
267
274
|
let pageInfoBool = (conn, key) =>
|
|
268
|
-
conn
|
|
275
|
+
conn
|
|
276
|
+
->field("pageInfo")
|
|
277
|
+
->Option.getOr(JSON.Encode.null)
|
|
278
|
+
->field(key)
|
|
279
|
+
->Option.flatMap(JSON.Decode.bool)
|
|
280
|
+
->Option.getOr(false)
|
|
269
281
|
|
|
270
282
|
let itemsPage = args =>
|
|
271
|
-
Eng.itemsPage(
|
|
283
|
+
Eng.itemsPage(
|
|
284
|
+
~readModelName=itemsName,
|
|
285
|
+
~subIdField="seq",
|
|
286
|
+
~id="order-1",
|
|
287
|
+
~argsDict=argsOf(args),
|
|
288
|
+
)
|
|
272
289
|
|
|
273
290
|
describe("QueryEnginePostgres itemsPage (sub-id keyset)", () => {
|
|
274
291
|
testPromise("bare → all lines ASC, no next page", async () => {
|
|
@@ -282,7 +299,10 @@ switch processEnv->Dict.get("PG_URL") {
|
|
|
282
299
|
expect(pageInfoBool(r, "hasNextPage"))->toBe(true)
|
|
283
300
|
})
|
|
284
301
|
testPromise("first:2 after b → [c,d]", async () => {
|
|
285
|
-
let r = await itemsPage([
|
|
302
|
+
let r = await itemsPage([
|
|
303
|
+
("first", JSON.Encode.int(2)),
|
|
304
|
+
("after", JSON.Encode.string(cur("b"))),
|
|
305
|
+
])
|
|
286
306
|
expect(r->itemSeqs)->toEqual(["c", "d"])
|
|
287
307
|
})
|
|
288
308
|
testPromise("order DESC → [e..a]", async () => {
|
|
@@ -304,7 +324,10 @@ switch processEnv->Dict.get("PG_URL") {
|
|
|
304
324
|
expect(r->itemSeqs)->toEqual(["c"])
|
|
305
325
|
})
|
|
306
326
|
testPromise("backward last:2 before d → [b,c] (logical ASC)", async () => {
|
|
307
|
-
let r = await itemsPage([
|
|
327
|
+
let r = await itemsPage([
|
|
328
|
+
("last", JSON.Encode.int(2)),
|
|
329
|
+
("before", JSON.Encode.string(cur("d"))),
|
|
330
|
+
])
|
|
308
331
|
expect(r->itemSeqs)->toEqual(["b", "c"])
|
|
309
332
|
expect(pageInfoBool(r, "hasPreviousPage"))->toBe(true)
|
|
310
333
|
})
|
|
@@ -122,7 +122,7 @@ function orderBy(f, dir) {
|
|
|
122
122
|
}
|
|
123
123
|
|
|
124
124
|
function expectedFor(argsDict) {
|
|
125
|
-
return norm(QueryDbListQuery$ReventlessCore.run(seededItems, argsDict, capability, "name", param => {}));
|
|
125
|
+
return norm(QueryDbListQuery$ReventlessCore.run(seededItems, argsDict, capability, "name", param => {}, undefined, undefined));
|
|
126
126
|
}
|
|
127
127
|
|
|
128
128
|
let url = process.env["PG_URL"];
|
|
@@ -148,7 +148,7 @@ if (url !== undefined) {
|
|
|
148
148
|
});
|
|
149
149
|
let checkPushed = async (label, args) => {
|
|
150
150
|
let argsDict = Object.fromEntries(args);
|
|
151
|
-
let actual = await Eng.listPage(name, argsDict, capability, "name");
|
|
151
|
+
let actual = await Eng.listPage(name, argsDict, capability, "name", undefined, undefined);
|
|
152
152
|
if (actual !== undefined) {
|
|
153
153
|
globalThis.expect(norm(actual)).toEqual(expectedFor(argsDict));
|
|
154
154
|
} else {
|
|
@@ -156,7 +156,7 @@ if (url !== undefined) {
|
|
|
156
156
|
}
|
|
157
157
|
};
|
|
158
158
|
let checkFallback = async args => {
|
|
159
|
-
let r = await Eng.listPage(name, Object.fromEntries(args), capability, "name");
|
|
159
|
+
let r = await Eng.listPage(name, Object.fromEntries(args), capability, "name", undefined, undefined);
|
|
160
160
|
globalThis.expect(Stdlib_Option.isSome(r)).toBe(false);
|
|
161
161
|
};
|
|
162
162
|
globalThis.describe("QueryDb list push-down parity (Postgres ≡ QueryDbListQuery spec)", () => {
|
|
@@ -322,7 +322,7 @@ if (url !== undefined) {
|
|
|
322
322
|
});
|
|
323
323
|
let itemSeqs = conn => Stdlib_Array.filterMap(Stdlib_Option.getOr(Stdlib_Option.flatMap(field(conn, "edges"), Stdlib_JSON.Decode.array), []), e => Stdlib_Option.flatMap(field(e, "node"), n => str(n, "seq")));
|
|
324
324
|
let pageInfoBool = (conn, key) => Stdlib_Option.getOr(Stdlib_Option.flatMap(field(Stdlib_Option.getOr(field(conn, "pageInfo"), null), key), Stdlib_JSON.Decode.bool), false);
|
|
325
|
-
let itemsPage = args => Eng.itemsPage(itemsName, "seq", "order-1", Object.fromEntries(args));
|
|
325
|
+
let itemsPage = args => Eng.itemsPage(itemsName, "seq", "order-1", Object.fromEntries(args), undefined, undefined);
|
|
326
326
|
globalThis.describe("QueryEnginePostgres itemsPage (sub-id keyset)", () => {
|
|
327
327
|
globalThis.test("bare → all lines ASC, no next page", async () => {
|
|
328
328
|
let r = await itemsPage([]);
|
package/lib/ocaml/.compiler.log
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
#Start(
|
|
2
|
-
#Done(
|
|
1
|
+
#Start(1790864278382)
|
|
2
|
+
#Done(1790864279610)
|
|
Binary file
|