@antelopejs/postgres 0.2.1 → 0.2.3
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/README.md +6 -5
- package/dist/config.d.ts +1 -0
- package/dist/config.js +7 -3
- package/dist/config.js.map +1 -1
- package/dist/connect-failure.d.ts +1 -0
- package/dist/connect-failure.js +39 -0
- package/dist/connect-failure.js.map +1 -0
- package/dist/connection.d.ts +2 -1
- package/dist/connection.js +19 -2
- package/dist/connection.js.map +1 -1
- package/dist/implementations/catalog/index.js +3 -6
- package/dist/implementations/catalog/index.js.map +1 -1
- package/dist/implementations/database/coerce.js +20 -20
- package/dist/implementations/database/coerce.js.map +1 -1
- package/dist/implementations/database/context.d.ts +1 -0
- package/dist/implementations/database/context.js +4 -0
- package/dist/implementations/database/context.js.map +1 -1
- package/dist/implementations/database/convergence.d.ts +22 -0
- package/dist/implementations/database/convergence.js +183 -0
- package/dist/implementations/database/convergence.js.map +1 -0
- package/dist/implementations/database/cursors.js +3 -0
- package/dist/implementations/database/cursors.js.map +1 -1
- package/dist/implementations/database/ddl.d.ts +6 -26
- package/dist/implementations/database/ddl.js +28 -195
- package/dist/implementations/database/ddl.js.map +1 -1
- package/dist/implementations/database/duplicate-key.d.ts +2 -0
- package/dist/implementations/database/duplicate-key.js +49 -0
- package/dist/implementations/database/duplicate-key.js.map +1 -0
- package/dist/implementations/database/external-column-profile.js +6 -1
- package/dist/implementations/database/external-column-profile.js.map +1 -1
- package/dist/implementations/database/external-discovery.js +5 -5
- package/dist/implementations/database/external-discovery.js.map +1 -1
- package/dist/implementations/database/external-measures.js.map +1 -1
- package/dist/implementations/database/external-payload.d.ts +2 -2
- package/dist/implementations/database/external-payload.js +23 -13
- package/dist/implementations/database/external-payload.js.map +1 -1
- package/dist/implementations/database/external-schema.d.ts +2 -2
- package/dist/implementations/database/external-schema.js +3 -3
- package/dist/implementations/database/external-schema.js.map +1 -1
- package/dist/implementations/database/external-types.js +23 -16
- package/dist/implementations/database/external-types.js.map +1 -1
- package/dist/implementations/database/external-writes.d.ts +7 -1
- package/dist/implementations/database/external-writes.js +22 -21
- package/dist/implementations/database/external-writes.js.map +1 -1
- package/dist/implementations/database/feed-pipeline.js +3 -2
- package/dist/implementations/database/feed-pipeline.js.map +1 -1
- package/dist/implementations/database/feeds.d.ts +1 -1
- package/dist/implementations/database/feeds.js +36 -45
- package/dist/implementations/database/feeds.js.map +1 -1
- package/dist/implementations/database/fields.d.ts +9 -13
- package/dist/implementations/database/fields.js +25 -21
- package/dist/implementations/database/fields.js.map +1 -1
- package/dist/implementations/database/guards.d.ts +5 -0
- package/dist/implementations/database/guards.js +23 -0
- package/dist/implementations/database/guards.js.map +1 -0
- package/dist/implementations/database/introspect.d.ts +1 -1
- package/dist/implementations/database/listener.js +9 -3
- package/dist/implementations/database/listener.js.map +1 -1
- package/dist/implementations/database/migrate.d.ts +2 -2
- package/dist/implementations/database/migrate.js +10 -10
- package/dist/implementations/database/migrate.js.map +1 -1
- package/dist/implementations/database/payload.d.ts +3 -3
- package/dist/implementations/database/payload.js +4 -4
- package/dist/implementations/database/pipeline.d.ts +6 -2
- package/dist/implementations/database/pipeline.js +4 -1
- package/dist/implementations/database/pipeline.js.map +1 -1
- package/dist/implementations/database/query.js +27 -12
- package/dist/implementations/database/query.js.map +1 -1
- package/dist/implementations/database/reaper.js +6 -4
- package/dist/implementations/database/reaper.js.map +1 -1
- package/dist/implementations/database/relation.d.ts +2 -12
- package/dist/implementations/database/relation.js +5 -141
- package/dist/implementations/database/relation.js.map +1 -1
- package/dist/implementations/database/render.d.ts +11 -0
- package/dist/implementations/database/render.js +147 -0
- package/dist/implementations/database/render.js.map +1 -0
- package/dist/implementations/database/result.d.ts +2 -2
- package/dist/implementations/database/result.js +18 -19
- package/dist/implementations/database/result.js.map +1 -1
- package/dist/implementations/database/row-source.d.ts +10 -10
- package/dist/implementations/database/row-source.js +22 -19
- package/dist/implementations/database/row-source.js.map +1 -1
- package/dist/implementations/database/schema.d.ts +3 -2
- package/dist/implementations/database/schema.js +35 -19
- package/dist/implementations/database/schema.js.map +1 -1
- package/dist/implementations/database/selection.js +13 -7
- package/dist/implementations/database/selection.js.map +1 -1
- package/dist/implementations/database/sql.d.ts +7 -3
- package/dist/implementations/database/sql.js.map +1 -1
- package/dist/implementations/database/stage.js +3 -2
- package/dist/implementations/database/stage.js.map +1 -1
- package/dist/implementations/database/stages-aggregate.js +7 -5
- package/dist/implementations/database/stages-aggregate.js.map +1 -1
- package/dist/implementations/database/stages-array.js.map +1 -1
- package/dist/implementations/database/stages-core.js +2 -1
- package/dist/implementations/database/stages-core.js.map +1 -1
- package/dist/implementations/database/stages-date.js +2 -1
- package/dist/implementations/database/stages-date.js.map +1 -1
- package/dist/implementations/database/stages-group.js +11 -6
- package/dist/implementations/database/stages-group.js.map +1 -1
- package/dist/implementations/database/stages-join.js +13 -11
- package/dist/implementations/database/stages-join.js.map +1 -1
- package/dist/implementations/database/stages-numeric.js.map +1 -1
- package/dist/implementations/database/stages-object.js +1 -1
- package/dist/implementations/database/stages-object.js.map +1 -1
- package/dist/implementations/database/stages-projection.js +9 -8
- package/dist/implementations/database/stages-projection.js.map +1 -1
- package/dist/implementations/database/stages-rows.js +10 -8
- package/dist/implementations/database/stages-rows.js.map +1 -1
- package/dist/implementations/database/stages-selection.js +6 -4
- package/dist/implementations/database/stages-selection.js.map +1 -1
- package/dist/implementations/database/stages-string.js +7 -6
- package/dist/implementations/database/stages-string.js.map +1 -1
- package/dist/implementations/database/subquery.d.ts +1 -1
- package/dist/implementations/database/subquery.js +7 -5
- package/dist/implementations/database/subquery.js.map +1 -1
- package/dist/implementations/database/types.d.ts +5 -5
- package/dist/implementations/database/types.js +11 -11
- package/dist/implementations/database/types.js.map +1 -1
- package/dist/implementations/database/utils.js +2 -1
- package/dist/implementations/database/utils.js.map +1 -1
- package/dist/implementations/database/value.d.ts +1 -1
- package/dist/implementations/database/value.js +34 -33
- package/dist/implementations/database/value.js.map +1 -1
- package/dist/implementations/database/writes-atomic.js +6 -5
- package/dist/implementations/database/writes-atomic.js.map +1 -1
- package/dist/implementations/database/writes-identity.js +18 -19
- package/dist/implementations/database/writes-identity.js.map +1 -1
- package/dist/implementations/database/writes-insert.js +16 -22
- package/dist/implementations/database/writes-insert.js.map +1 -1
- package/dist/implementations/database/writes-shared.d.ts +1 -1
- package/dist/implementations/database/writes-shared.js +11 -7
- package/dist/implementations/database/writes-shared.js.map +1 -1
- package/dist/implementations/database/writes.d.ts +22 -1
- package/dist/implementations/database/writes.js +6 -3
- package/dist/implementations/database/writes.js.map +1 -1
- package/dist/test/catalog-owned.test.js +2 -0
- package/dist/test/catalog-owned.test.js.map +1 -1
- package/dist/test/contention.test.js.map +1 -1
- package/dist/test/duplicate-key.test.d.ts +1 -0
- package/dist/test/duplicate-key.test.js +103 -0
- package/dist/test/duplicate-key.test.js.map +1 -0
- package/dist/test/indexes.test.js +7 -7
- package/dist/test/indexes.test.js.map +1 -1
- package/dist/test/unit/coerce.spec.js +7 -7
- package/dist/test/unit/coerce.spec.js.map +1 -1
- package/dist/test/unit/config.spec.js +3 -1
- package/dist/test/unit/config.spec.js.map +1 -1
- package/dist/test/unit/connect-failure.spec.d.ts +1 -0
- package/dist/test/unit/connect-failure.spec.js +50 -0
- package/dist/test/unit/connect-failure.spec.js.map +1 -0
- package/dist/test/unit/connection.spec.js +16 -18
- package/dist/test/unit/connection.spec.js.map +1 -1
- package/dist/test/unit/convergence.spec.d.ts +1 -0
- package/dist/test/unit/convergence.spec.js +347 -0
- package/dist/test/unit/convergence.spec.js.map +1 -0
- package/dist/test/unit/cursors-fixture.d.ts +79 -0
- package/dist/test/unit/cursors-fixture.js +245 -0
- package/dist/test/unit/cursors-fixture.js.map +1 -0
- package/dist/test/unit/cursors.spec.js +138 -718
- package/dist/test/unit/cursors.spec.js.map +1 -1
- package/dist/test/unit/cursors.teardown.spec.d.ts +1 -0
- package/dist/test/unit/cursors.teardown.spec.js +322 -0
- package/dist/test/unit/cursors.teardown.spec.js.map +1 -0
- package/dist/test/unit/cursors.window.spec.d.ts +1 -0
- package/dist/test/unit/cursors.window.spec.js +78 -0
- package/dist/test/unit/cursors.window.spec.js.map +1 -0
- package/dist/test/unit/ddl-fixture.d.ts +5 -0
- package/dist/test/unit/ddl-fixture.js +19 -0
- package/dist/test/unit/ddl-fixture.js.map +1 -0
- package/dist/test/unit/ddl.spec.js +64 -366
- package/dist/test/unit/ddl.spec.js.map +1 -1
- package/dist/test/unit/expression-array-fixture.d.ts +17 -0
- package/dist/test/unit/expression-array-fixture.js +63 -0
- package/dist/test/unit/expression-array-fixture.js.map +1 -0
- package/dist/test/unit/expression-array-walk.spec.d.ts +1 -0
- package/dist/test/unit/expression-array-walk.spec.js +235 -0
- package/dist/test/unit/expression-array-walk.spec.js.map +1 -0
- package/dist/test/unit/expression-array.spec.js +48 -322
- package/dist/test/unit/expression-array.spec.js.map +1 -1
- package/dist/test/unit/expression-date.spec.js +4 -3
- package/dist/test/unit/expression-date.spec.js.map +1 -1
- package/dist/test/unit/expression-fixture.d.ts +15 -0
- package/dist/test/unit/expression-fixture.js +40 -0
- package/dist/test/unit/expression-fixture.js.map +1 -0
- package/dist/test/unit/expression-numeric.spec.js +10 -8
- package/dist/test/unit/expression-numeric.spec.js.map +1 -1
- package/dist/test/unit/expression-object.spec.js +3 -4
- package/dist/test/unit/expression-object.spec.js.map +1 -1
- package/dist/test/unit/expression-predicate.spec.d.ts +1 -0
- package/dist/test/unit/expression-predicate.spec.js +231 -0
- package/dist/test/unit/expression-predicate.spec.js.map +1 -0
- package/dist/test/unit/expression-stages.spec.js +0 -5
- package/dist/test/unit/expression-stages.spec.js.map +1 -1
- package/dist/test/unit/expression-string.spec.js +2 -5
- package/dist/test/unit/expression-string.spec.js.map +1 -1
- package/dist/test/unit/expression.spec.js +44 -292
- package/dist/test/unit/expression.spec.js.map +1 -1
- package/dist/test/unit/external-comparisons.spec.js +5 -5
- package/dist/test/unit/external-comparisons.spec.js.map +1 -1
- package/dist/test/unit/external-types.spec.js +2 -3
- package/dist/test/unit/external-types.spec.js.map +1 -1
- package/dist/test/unit/feeds.spec.js +40 -23
- package/dist/test/unit/feeds.spec.js.map +1 -1
- package/dist/test/unit/fields.spec.js +15 -9
- package/dist/test/unit/fields.spec.js.map +1 -1
- package/dist/test/unit/invalid-fixture.d.ts +3 -0
- package/dist/test/unit/invalid-fixture.js +11 -0
- package/dist/test/unit/invalid-fixture.js.map +1 -0
- package/dist/test/unit/payload.spec.js.map +1 -1
- package/dist/test/unit/pipeline-aggregate.spec.js +14 -14
- package/dist/test/unit/pipeline-aggregate.spec.js.map +1 -1
- package/dist/test/unit/pipeline-fixture.d.ts +25 -6
- package/dist/test/unit/pipeline-fixture.js +21 -11
- package/dist/test/unit/pipeline-fixture.js.map +1 -1
- package/dist/test/unit/pipeline-group-fixture.d.ts +2 -0
- package/dist/test/unit/pipeline-group-fixture.js +6 -0
- package/dist/test/unit/pipeline-group-fixture.js.map +1 -0
- package/dist/test/unit/pipeline-group.spec.js +15 -248
- package/dist/test/unit/pipeline-group.spec.js.map +1 -1
- package/dist/test/unit/pipeline-lookup.spec.js +13 -10
- package/dist/test/unit/pipeline-lookup.spec.js.map +1 -1
- package/dist/test/unit/pipeline-projection.spec.js +12 -13
- package/dist/test/unit/pipeline-projection.spec.js.map +1 -1
- package/dist/test/unit/pipeline-rows.spec.js +21 -18
- package/dist/test/unit/pipeline-rows.spec.js.map +1 -1
- package/dist/test/unit/pipeline-selection.spec.js +6 -4
- package/dist/test/unit/pipeline-selection.spec.js.map +1 -1
- package/dist/test/unit/pipeline-stages.spec.js +23 -35
- package/dist/test/unit/pipeline-stages.spec.js.map +1 -1
- package/dist/test/unit/pipeline-substream.spec.d.ts +1 -0
- package/dist/test/unit/pipeline-substream.spec.js +246 -0
- package/dist/test/unit/pipeline-substream.spec.js.map +1 -0
- package/dist/test/unit/pipeline.spec.js +1 -1
- package/dist/test/unit/query.spec.js +6 -2
- package/dist/test/unit/query.spec.js.map +1 -1
- package/dist/test/unit/reaper.spec.js +4 -3
- package/dist/test/unit/reaper.spec.js.map +1 -1
- package/dist/test/unit/relation.spec.js +37 -36
- package/dist/test/unit/relation.spec.js.map +1 -1
- package/dist/test/unit/result.spec.js +13 -11
- package/dist/test/unit/result.spec.js.map +1 -1
- package/dist/test/unit/row-source.spec.js +1 -1
- package/dist/test/unit/row-source.spec.js.map +1 -1
- package/dist/test/unit/schema.spec.js +5 -2
- package/dist/test/unit/schema.spec.js.map +1 -1
- package/dist/test/unit/selection.spec.js +7 -3
- package/dist/test/unit/selection.spec.js.map +1 -1
- package/dist/test/unit/types.spec.js +6 -6
- package/dist/test/unit/types.spec.js.map +1 -1
- package/dist/test/unit/writes-atomic.spec.js +2 -2
- package/dist/test/unit/writes-atomic.spec.js.map +1 -1
- package/dist/test/unit/writes-insert.spec.js +5 -4
- package/dist/test/unit/writes-insert.spec.js.map +1 -1
- package/dist/test/unit/writes-replace.spec.js +6 -6
- package/dist/test/unit/writes-replace.spec.js.map +1 -1
- package/dist/test/unit/writes-target.spec.js +3 -3
- package/dist/test/unit/writes-target.spec.js.map +1 -1
- package/dist/test/unit/writes-update-fixture.d.ts +9 -0
- package/dist/test/unit/writes-update-fixture.js +20 -0
- package/dist/test/unit/writes-update-fixture.js.map +1 -0
- package/dist/test/unit/writes-update-mapper.spec.d.ts +1 -0
- package/dist/test/unit/writes-update-mapper.spec.js +123 -0
- package/dist/test/unit/writes-update-mapper.spec.js.map +1 -0
- package/dist/test/unit/writes-update.spec.js +42 -171
- package/dist/test/unit/writes-update.spec.js.map +1 -1
- package/dist/test-external/catalog.test.js +11 -1
- package/dist/test-external/catalog.test.js.map +1 -1
- package/dist/test-external/native.test.js +8 -6
- package/dist/test-external/native.test.js.map +1 -1
- package/dist/test-external/reads.test.js +20 -22
- package/dist/test-external/reads.test.js.map +1 -1
- package/dist/test-external/refusals.test.js +45 -24
- package/dist/test-external/refusals.test.js.map +1 -1
- package/dist/test-external/registration.test.js +4 -2
- package/dist/test-external/registration.test.js.map +1 -1
- package/dist/test-external/sales.d.ts +9 -2
- package/dist/test-external/sales.js.map +1 -1
- package/dist/test-external/unreachable.test.d.ts +1 -0
- package/dist/test-external/unreachable.test.js +83 -0
- package/dist/test-external/unreachable.test.js.map +1 -0
- package/dist/test-external/writes.test.js +71 -37
- package/dist/test-external/writes.test.js.map +1 -1
- package/package.json +19 -6
|
@@ -5,15 +5,7 @@ const types_1 = require("../../implementations/database/types");
|
|
|
5
5
|
const fields_1 = require("../../implementations/database/fields");
|
|
6
6
|
const identifier_1 = require("../../implementations/database/identifier");
|
|
7
7
|
const ddl_1 = require("../../implementations/database/ddl");
|
|
8
|
-
const
|
|
9
|
-
fields: { car: "string", price: "number", tags: "string[]" },
|
|
10
|
-
indexes: {
|
|
11
|
-
price: {},
|
|
12
|
-
tags: { multi: true },
|
|
13
|
-
byCar: { fields: ["car", "price"] },
|
|
14
|
-
},
|
|
15
|
-
};
|
|
16
|
-
const VEHICLES_PLAN = (0, ddl_1.BuildTablePlan)("vehicles", vehicles, (0, fields_1.ParseTable)(vehicles, "s.vehicles"));
|
|
8
|
+
const ddl_fixture_1 = require("./ddl-fixture");
|
|
17
9
|
const TABLE_PREFIX = "t_";
|
|
18
10
|
const ESCAPED_LITERAL_PREFIX = "E'";
|
|
19
11
|
const COMMENT_PATTERN = /^COMMENT ON INDEX "shop"\."[^"]+" IS (E?'.*')$/;
|
|
@@ -24,11 +16,8 @@ function FindIndex(plan, name) {
|
|
|
24
16
|
}
|
|
25
17
|
return found;
|
|
26
18
|
}
|
|
27
|
-
function PlanFor(tableId, definition) {
|
|
28
|
-
return (0, ddl_1.BuildTablePlan)(tableId, definition, (0, fields_1.ParseTable)(definition, `s.${tableId}`));
|
|
29
|
-
}
|
|
30
19
|
function BuildOne(definition) {
|
|
31
|
-
return PlanFor("t", definition).indexes[0];
|
|
20
|
+
return (0, ddl_fixture_1.PlanFor)("t", definition).indexes[0];
|
|
32
21
|
}
|
|
33
22
|
function DecodeLiteral(literal) {
|
|
34
23
|
const isEscaped = literal.startsWith(ESCAPED_LITERAL_PREFIX);
|
|
@@ -38,7 +27,7 @@ function DecodeLiteral(literal) {
|
|
|
38
27
|
}
|
|
39
28
|
describe("BuildTablePlan", () => {
|
|
40
29
|
it("orders the reserved columns around the declared ones", () => {
|
|
41
|
-
(0, chai_1.expect)(VEHICLES_PLAN.columns.map((column) => column.name)).to.deep.equal([
|
|
30
|
+
(0, chai_1.expect)(ddl_fixture_1.VEHICLES_PLAN.columns.map((column) => column.name)).to.deep.equal([
|
|
42
31
|
"_id",
|
|
43
32
|
"_instance",
|
|
44
33
|
"car",
|
|
@@ -48,39 +37,39 @@ describe("BuildTablePlan", () => {
|
|
|
48
37
|
]);
|
|
49
38
|
});
|
|
50
39
|
it("maps declared fields to their physical types", () => {
|
|
51
|
-
(0, chai_1.expect)(VEHICLES_PLAN.columns[3]).to.deep.equal({
|
|
40
|
+
(0, chai_1.expect)(ddl_fixture_1.VEHICLES_PLAN.columns[3]).to.deep.equal({
|
|
52
41
|
name: "price",
|
|
53
42
|
type: "double precision",
|
|
54
43
|
declared: { field: "price", type: types_1.FLOAT },
|
|
55
44
|
});
|
|
56
45
|
});
|
|
57
46
|
it("leaves the reserved columns undeclared, since no field is stored in them", () => {
|
|
58
|
-
const reserved = [0, 1, VEHICLES_PLAN.columns.length - 1];
|
|
47
|
+
const reserved = [0, 1, ddl_fixture_1.VEHICLES_PLAN.columns.length - 1];
|
|
59
48
|
for (const at of reserved) {
|
|
60
|
-
(0, chai_1.expect)(VEHICLES_PLAN.columns[at].declared).to.equal(undefined);
|
|
49
|
+
(0, chai_1.expect)(ddl_fixture_1.VEHICLES_PLAN.columns[at].declared).to.equal(undefined);
|
|
61
50
|
}
|
|
62
51
|
});
|
|
63
52
|
it("gives the reserved columns their constraints", () => {
|
|
64
|
-
(0, chai_1.expect)((0, ddl_1.ColumnDdl)(VEHICLES_PLAN.columns[1])).to.equal(`"_instance" text NOT NULL DEFAULT ''`);
|
|
65
|
-
(0, chai_1.expect)((0, ddl_1.ColumnDdl)(VEHICLES_PLAN.columns[5])).to.equal(`"_extra" jsonb NOT NULL DEFAULT '{}'::jsonb`);
|
|
66
|
-
(0, chai_1.expect)((0, ddl_1.ColumnDdl)(VEHICLES_PLAN.columns[3])).to.equal(`"price" double precision`);
|
|
53
|
+
(0, chai_1.expect)((0, ddl_1.ColumnDdl)(ddl_fixture_1.VEHICLES_PLAN.columns[1])).to.equal(`"_instance" text NOT NULL DEFAULT ''`);
|
|
54
|
+
(0, chai_1.expect)((0, ddl_1.ColumnDdl)(ddl_fixture_1.VEHICLES_PLAN.columns[5])).to.equal(`"_extra" jsonb NOT NULL DEFAULT '{}'::jsonb`);
|
|
55
|
+
(0, chai_1.expect)((0, ddl_1.ColumnDdl)(ddl_fixture_1.VEHICLES_PLAN.columns[3])).to.equal(`"price" double precision`);
|
|
67
56
|
});
|
|
68
57
|
it("leads a btree index with _instance", () => {
|
|
69
|
-
const index = FindIndex(VEHICLES_PLAN, "vehicles_price");
|
|
58
|
+
const index = FindIndex(ddl_fixture_1.VEHICLES_PLAN, "vehicles_price");
|
|
70
59
|
(0, chai_1.expect)(index.method).to.equal("btree");
|
|
71
60
|
(0, chai_1.expect)(index.keys).to.deep.equal([`"_instance"`, `"price"`]);
|
|
72
61
|
});
|
|
73
62
|
it("uses a bare gin index for a multi index over a jsonb field", () => {
|
|
74
|
-
const index = FindIndex(VEHICLES_PLAN, "vehicles_tags");
|
|
63
|
+
const index = FindIndex(ddl_fixture_1.VEHICLES_PLAN, "vehicles_tags");
|
|
75
64
|
(0, chai_1.expect)(index.method).to.equal("gin");
|
|
76
65
|
(0, chai_1.expect)(index.keys).to.deep.equal([`"tags"`]);
|
|
77
66
|
});
|
|
78
67
|
it("expands a compound index in declaration order", () => {
|
|
79
|
-
const index = FindIndex(VEHICLES_PLAN, "vehicles_byCar");
|
|
68
|
+
const index = FindIndex(ddl_fixture_1.VEHICLES_PLAN, "vehicles_byCar");
|
|
80
69
|
(0, chai_1.expect)(index.keys).to.deep.equal([`"_instance"`, `"car"`, `"price"`]);
|
|
81
70
|
});
|
|
82
71
|
it("indexes an undeclared field through _extra", () => {
|
|
83
|
-
const out = PlanFor("t", { fields: {}, indexes: { ref: {} } });
|
|
72
|
+
const out = (0, ddl_fixture_1.PlanFor)("t", { fields: {}, indexes: { ref: {} } });
|
|
84
73
|
(0, chai_1.expect)(out.indexes[0].keys).to.deep.equal([
|
|
85
74
|
`"_instance"`,
|
|
86
75
|
`("_extra" -> 'ref')`,
|
|
@@ -117,8 +106,10 @@ describe("BuildTablePlan", () => {
|
|
|
117
106
|
(0, chai_1.expect)(index.method).to.equal("btree");
|
|
118
107
|
(0, chai_1.expect)(index.keys).to.deep.equal([`"_instance"`, `("_extra" -> 'ref')`]);
|
|
119
108
|
});
|
|
109
|
+
});
|
|
110
|
+
describe("BuildTablePlan", () => {
|
|
120
111
|
it("adds an unprefixed __g twin to a crossInstance btree index", () => {
|
|
121
|
-
const plan = PlanFor("t", {
|
|
112
|
+
const plan = (0, ddl_fixture_1.PlanFor)("t", {
|
|
122
113
|
fields: { car: "string", price: "number" },
|
|
123
114
|
indexes: { byCar: { fields: ["car", "price"], crossInstance: true } },
|
|
124
115
|
});
|
|
@@ -133,7 +124,7 @@ describe("BuildTablePlan", () => {
|
|
|
133
124
|
(0, chai_1.expect)(unscoped.signature).to.not.equal(scoped.signature);
|
|
134
125
|
});
|
|
135
126
|
it("keeps a crossInstance gin index as one bare index", () => {
|
|
136
|
-
const plan = PlanFor("t", {
|
|
127
|
+
const plan = (0, ddl_fixture_1.PlanFor)("t", {
|
|
137
128
|
fields: { tags: "string[]" },
|
|
138
129
|
indexes: { tags: { multi: true, crossInstance: true } },
|
|
139
130
|
});
|
|
@@ -142,7 +133,7 @@ describe("BuildTablePlan", () => {
|
|
|
142
133
|
});
|
|
143
134
|
it("fits the __g name into the identifier limit", () => {
|
|
144
135
|
const longId = "x".repeat(70);
|
|
145
|
-
const plan = PlanFor("t", {
|
|
136
|
+
const plan = (0, ddl_fixture_1.PlanFor)("t", {
|
|
146
137
|
fields: {},
|
|
147
138
|
indexes: { [longId]: { crossInstance: true } },
|
|
148
139
|
});
|
|
@@ -152,44 +143,73 @@ describe("BuildTablePlan", () => {
|
|
|
152
143
|
(0, chai_1.expect)(Buffer.byteLength(names[1])).to.be.at.most(63);
|
|
153
144
|
});
|
|
154
145
|
it("signs an index with its method and keys", () => {
|
|
155
|
-
const index = FindIndex(VEHICLES_PLAN, "vehicles_price");
|
|
146
|
+
const index = FindIndex(ddl_fixture_1.VEHICLES_PLAN, "vehicles_price");
|
|
156
147
|
(0, chai_1.expect)(index.signature).to.equal(`antelopejs:1:btree:"_instance","price"`);
|
|
157
148
|
});
|
|
158
149
|
it("emits a create table statement with the composite primary key", () => {
|
|
159
|
-
const sql = (0, ddl_1.CreateTableSql)("shop", VEHICLES_PLAN);
|
|
150
|
+
const sql = (0, ddl_1.CreateTableSql)("shop", ddl_fixture_1.VEHICLES_PLAN);
|
|
160
151
|
(0, chai_1.expect)(sql).to.contain(`CREATE TABLE IF NOT EXISTS "shop"."vehicles" (`);
|
|
161
152
|
(0, chai_1.expect)(sql).to.contain(`PRIMARY KEY ("_instance", "_id")`);
|
|
162
153
|
});
|
|
163
154
|
it("emits a concurrent create index statement and its signature comment", () => {
|
|
164
|
-
const index = FindIndex(VEHICLES_PLAN, "vehicles_price");
|
|
165
|
-
(0, chai_1.expect)((0, ddl_1.CreateIndexSql)("shop", VEHICLES_PLAN, index)).to.deep.equal([
|
|
155
|
+
const index = FindIndex(ddl_fixture_1.VEHICLES_PLAN, "vehicles_price");
|
|
156
|
+
(0, chai_1.expect)((0, ddl_1.CreateIndexSql)("shop", ddl_fixture_1.VEHICLES_PLAN, index)).to.deep.equal([
|
|
166
157
|
`CREATE INDEX CONCURRENTLY "vehicles_price" ON "shop"."vehicles" USING btree ("_instance", "price")`,
|
|
167
158
|
`COMMENT ON INDEX "shop"."vehicles_price" IS 'antelopejs:1:btree:"_instance","price"'`,
|
|
168
159
|
]);
|
|
169
160
|
});
|
|
170
161
|
it("round-trips a signature over a hostile field name", () => {
|
|
171
162
|
const hostile = "it's\\bad";
|
|
172
|
-
const hostilePlan = PlanFor("t", {
|
|
163
|
+
const hostilePlan = (0, ddl_fixture_1.PlanFor)("t", {
|
|
173
164
|
fields: {},
|
|
174
165
|
indexes: { [hostile]: {} },
|
|
175
166
|
});
|
|
176
167
|
const index = hostilePlan.indexes[0];
|
|
177
168
|
const comment = (0, ddl_1.CreateIndexSql)("shop", hostilePlan, index)[1];
|
|
178
169
|
const matched = COMMENT_PATTERN.exec(comment);
|
|
179
|
-
|
|
170
|
+
if (matched === null) {
|
|
171
|
+
chai_1.expect.fail(comment);
|
|
172
|
+
}
|
|
180
173
|
(0, chai_1.expect)(DecodeLiteral(matched[1])).to.equal(index.signature);
|
|
181
174
|
});
|
|
175
|
+
it("builds a unique index keyed by instance, with a marked signature", () => {
|
|
176
|
+
const plan = (0, ddl_fixture_1.PlanFor)("t", {
|
|
177
|
+
fields: { email: "string" },
|
|
178
|
+
indexes: { email: { unique: true } },
|
|
179
|
+
});
|
|
180
|
+
const [index] = plan.indexes;
|
|
181
|
+
(0, chai_1.expect)(index.isUnique).to.equal(true);
|
|
182
|
+
(0, chai_1.expect)(index.signature).to.equal(`antelopejs:1:btree:unique:"_instance","email"`);
|
|
183
|
+
(0, chai_1.expect)((0, ddl_1.CreateIndexSql)("shop", plan, index)[0]).to.equal(`CREATE UNIQUE INDEX CONCURRENTLY "t_email" ON "shop"."t" USING btree ("_instance", "email")`);
|
|
184
|
+
});
|
|
185
|
+
it("keeps the __g twin of a unique index non-unique", () => {
|
|
186
|
+
const plan = (0, ddl_fixture_1.PlanFor)("t", {
|
|
187
|
+
fields: { email: "string" },
|
|
188
|
+
indexes: { email: { unique: true, crossInstance: true } },
|
|
189
|
+
});
|
|
190
|
+
const [scoped, unscoped] = plan.indexes;
|
|
191
|
+
(0, chai_1.expect)(scoped.isUnique).to.equal(true);
|
|
192
|
+
(0, chai_1.expect)(unscoped.name).to.equal("t_email__g");
|
|
193
|
+
(0, chai_1.expect)(unscoped.isUnique).to.equal(false);
|
|
194
|
+
(0, chai_1.expect)((0, ddl_1.CreateIndexSql)("shop", plan, unscoped)[0]).to.match(/^CREATE INDEX CONCURRENTLY/);
|
|
195
|
+
});
|
|
196
|
+
it("refuses a unique index over an array field's elements", () => {
|
|
197
|
+
(0, chai_1.expect)(() => BuildOne({
|
|
198
|
+
fields: { tags: "string[]" },
|
|
199
|
+
indexes: { tags: { multi: true, unique: true } },
|
|
200
|
+
})).to.throw(/unique and multi over an array field/);
|
|
201
|
+
});
|
|
182
202
|
});
|
|
183
203
|
describe("ServesCrossInstance", () => {
|
|
184
|
-
const
|
|
204
|
+
const model = (0, fields_1.ParseTable)(ddl_fixture_1.vehicles, "s.vehicles");
|
|
185
205
|
it("is true for a declared crossInstance index", () => {
|
|
186
|
-
(0, chai_1.expect)((0, ddl_1.ServesCrossInstance)("price", { crossInstance: true },
|
|
206
|
+
(0, chai_1.expect)((0, ddl_1.ServesCrossInstance)("price", { crossInstance: true }, model)).to.equal(true);
|
|
187
207
|
});
|
|
188
208
|
it("is false for a btree index that is not crossInstance", () => {
|
|
189
|
-
(0, chai_1.expect)((0, ddl_1.ServesCrossInstance)("price", {},
|
|
209
|
+
(0, chai_1.expect)((0, ddl_1.ServesCrossInstance)("price", {}, model)).to.equal(false);
|
|
190
210
|
});
|
|
191
211
|
it("is true for a gin index, which carries no instance prefix", () => {
|
|
192
|
-
(0, chai_1.expect)((0, ddl_1.ServesCrossInstance)("tags", { multi: true },
|
|
212
|
+
(0, chai_1.expect)((0, ddl_1.ServesCrossInstance)("tags", { multi: true }, model)).to.equal(true);
|
|
193
213
|
});
|
|
194
214
|
});
|
|
195
215
|
describe("IsAdapterIndex", () => {
|
|
@@ -208,15 +228,15 @@ describe("IsAdapterIndex", () => {
|
|
|
208
228
|
describe("AssertDistinctNames", () => {
|
|
209
229
|
it("accepts a schema whose generated names are all distinct", () => {
|
|
210
230
|
const plans = [
|
|
211
|
-
VEHICLES_PLAN,
|
|
212
|
-
PlanFor("owners", { fields: { name: "string" }, indexes: { name: {} } }),
|
|
231
|
+
ddl_fixture_1.VEHICLES_PLAN,
|
|
232
|
+
(0, ddl_fixture_1.PlanFor)("owners", { fields: { name: "string" }, indexes: { name: {} } }),
|
|
213
233
|
];
|
|
214
234
|
(0, chai_1.expect)(() => (0, ddl_1.AssertDistinctNames)(plans)).to.not.throw();
|
|
215
235
|
});
|
|
216
236
|
it("rejects two indexes on one table that collide on one name", () => {
|
|
217
237
|
const long = "i".repeat(100);
|
|
218
238
|
const truncated = (0, identifier_1.PgIdentifier)(`${TABLE_PREFIX}${long}`).slice(TABLE_PREFIX.length);
|
|
219
|
-
const plan = PlanFor("t", {
|
|
239
|
+
const plan = (0, ddl_fixture_1.PlanFor)("t", {
|
|
220
240
|
fields: {},
|
|
221
241
|
indexes: { [long]: {}, [truncated]: {} },
|
|
222
242
|
});
|
|
@@ -227,8 +247,8 @@ describe("AssertDistinctNames", () => {
|
|
|
227
247
|
});
|
|
228
248
|
it("rejects two tables whose indexes map to one name", () => {
|
|
229
249
|
const plans = [
|
|
230
|
-
PlanFor("a", { fields: {}, indexes: { b_c: {} } }),
|
|
231
|
-
PlanFor("a_b", { fields: {}, indexes: { c: {} } }),
|
|
250
|
+
(0, ddl_fixture_1.PlanFor)("a", { fields: {}, indexes: { b_c: {} } }),
|
|
251
|
+
(0, ddl_fixture_1.PlanFor)("a_b", { fields: {}, indexes: { c: {} } }),
|
|
232
252
|
];
|
|
233
253
|
const check = () => (0, ddl_1.AssertDistinctNames)(plans);
|
|
234
254
|
(0, chai_1.expect)(check).to.throw("a_b_c");
|
|
@@ -237,8 +257,8 @@ describe("AssertDistinctNames", () => {
|
|
|
237
257
|
});
|
|
238
258
|
it("rejects an index that collides with a sibling table", () => {
|
|
239
259
|
const plans = [
|
|
240
|
-
VEHICLES_PLAN,
|
|
241
|
-
PlanFor("vehicles_price", { fields: {}, indexes: {} }),
|
|
260
|
+
ddl_fixture_1.VEHICLES_PLAN,
|
|
261
|
+
(0, ddl_fixture_1.PlanFor)("vehicles_price", { fields: {}, indexes: {} }),
|
|
242
262
|
];
|
|
243
263
|
const check = () => (0, ddl_1.AssertDistinctNames)(plans);
|
|
244
264
|
(0, chai_1.expect)(check).to.throw("vehicles_price");
|
|
@@ -246,326 +266,4 @@ describe("AssertDistinctNames", () => {
|
|
|
246
266
|
(0, chai_1.expect)(check).to.throw(/table 'vehicles_price'/);
|
|
247
267
|
});
|
|
248
268
|
});
|
|
249
|
-
const SAFE = "safe";
|
|
250
|
-
const DESTRUCTIVE = "destructive";
|
|
251
|
-
const SCHEMA = "shop";
|
|
252
|
-
const VEHICLES_TARGET = `"shop"."vehicles"`;
|
|
253
|
-
const DECLARED_INDEX_COUNT = 3;
|
|
254
|
-
const dated = {
|
|
255
|
-
fields: { manufactured: "date" },
|
|
256
|
-
indexes: {},
|
|
257
|
-
};
|
|
258
|
-
const everyType = {
|
|
259
|
-
fields: {
|
|
260
|
-
label: "string",
|
|
261
|
-
amount: "number",
|
|
262
|
-
active: "boolean",
|
|
263
|
-
at: "date",
|
|
264
|
-
payload: "object",
|
|
265
|
-
tags: "string[]",
|
|
266
|
-
},
|
|
267
|
-
indexes: {},
|
|
268
|
-
};
|
|
269
|
-
const CATALOG_TYPES = {
|
|
270
|
-
text: "text",
|
|
271
|
-
"double precision": "double precision",
|
|
272
|
-
boolean: "boolean",
|
|
273
|
-
timestamptz: "timestamp with time zone",
|
|
274
|
-
jsonb: "jsonb",
|
|
275
|
-
};
|
|
276
|
-
const EMPTY = { columns: [], indexes: [] };
|
|
277
|
-
const FULL_COLUMNS = [
|
|
278
|
-
{ name: "_id", type: "text" },
|
|
279
|
-
{ name: "_instance", type: "text" },
|
|
280
|
-
{ name: "car", type: "text" },
|
|
281
|
-
{ name: "price", type: "double precision" },
|
|
282
|
-
{ name: "tags", type: "jsonb" },
|
|
283
|
-
{ name: "_extra", type: "jsonb" },
|
|
284
|
-
];
|
|
285
|
-
const RETYPED_COLUMNS = FULL_COLUMNS.map((column) => column.name === "price" ? { name: column.name, type: "text" } : column);
|
|
286
|
-
const RETIRED_COLUMNS = [
|
|
287
|
-
...FULL_COLUMNS,
|
|
288
|
-
{ name: "retired", type: "text" },
|
|
289
|
-
];
|
|
290
|
-
const UNCASTABLE_COLUMNS = FULL_COLUMNS.map((column) => column.name === "price" ? { name: column.name, type: "boolean" } : column);
|
|
291
|
-
const DRIFTED_TAGS_INDEX = {
|
|
292
|
-
name: "vehicles_tags",
|
|
293
|
-
signature: `antelopejs:1:gin:"outdated"`,
|
|
294
|
-
valid: true,
|
|
295
|
-
};
|
|
296
|
-
const PRICE_SIGNATURE = `antelopejs:1:btree:"_instance","price"`;
|
|
297
|
-
const DRIFTED_PRICE_INDEX = {
|
|
298
|
-
name: "vehicles_price",
|
|
299
|
-
signature: `antelopejs:1:btree:"price"`,
|
|
300
|
-
valid: true,
|
|
301
|
-
};
|
|
302
|
-
const DROP_PRICE = `DROP INDEX CONCURRENTLY IF EXISTS "shop"."vehicles_price"`;
|
|
303
|
-
const DROP_PRICE_REPLACEMENT = `DROP INDEX CONCURRENTLY IF EXISTS "shop"."vehicles_price__next"`;
|
|
304
|
-
const CREATE_PRICE = `CREATE INDEX CONCURRENTLY "vehicles_price"`;
|
|
305
|
-
const CREATE_PRICE_REPLACEMENT = `CREATE INDEX CONCURRENTLY "vehicles_price__next"`;
|
|
306
|
-
const RENAME_PRICE_REPLACEMENT = `ALTER INDEX "shop"."vehicles_price__next" RENAME TO "vehicles_price"`;
|
|
307
|
-
function OtherIndexes(plan, name) {
|
|
308
|
-
return SignedIndexes(plan).filter((index) => index.name !== name);
|
|
309
|
-
}
|
|
310
|
-
function StartsAt(statements, prefix) {
|
|
311
|
-
return statements.findIndex((sql) => sql.startsWith(prefix));
|
|
312
|
-
}
|
|
313
|
-
function Existing(columns, indexes = []) {
|
|
314
|
-
return { columns, indexes };
|
|
315
|
-
}
|
|
316
|
-
function SignedIndexes(plan) {
|
|
317
|
-
return plan.indexes.map((index) => ({
|
|
318
|
-
name: index.name,
|
|
319
|
-
signature: index.signature,
|
|
320
|
-
valid: true,
|
|
321
|
-
}));
|
|
322
|
-
}
|
|
323
|
-
function CatalogType(type) {
|
|
324
|
-
if (!Object.hasOwn(CATALOG_TYPES, type)) {
|
|
325
|
-
throw new Error(`No catalog spelling recorded for physical type '${type}'`);
|
|
326
|
-
}
|
|
327
|
-
return CATALOG_TYPES[type];
|
|
328
|
-
}
|
|
329
|
-
function CatalogColumns(plan) {
|
|
330
|
-
return plan.columns.map((column) => ({
|
|
331
|
-
name: column.name,
|
|
332
|
-
type: CatalogType(column.type),
|
|
333
|
-
}));
|
|
334
|
-
}
|
|
335
|
-
const IsIndexDrop = (sql) => sql.startsWith("DROP INDEX");
|
|
336
|
-
const IsColumnChange = (sql) => sql.startsWith("ALTER TABLE");
|
|
337
|
-
function FirstAt(statements, matches) {
|
|
338
|
-
const position = statements.findIndex(matches);
|
|
339
|
-
if (position < 0) {
|
|
340
|
-
throw new Error(`No statement matched: ${statements.join(" | ")}`);
|
|
341
|
-
}
|
|
342
|
-
return position;
|
|
343
|
-
}
|
|
344
|
-
function LastAt(statements, matches) {
|
|
345
|
-
return statements.reduce((found, sql, position) => (matches(sql) ? position : found), FirstAt(statements, matches));
|
|
346
|
-
}
|
|
347
|
-
describe("PlanTable", () => {
|
|
348
|
-
it("creates everything when the table is absent", () => {
|
|
349
|
-
const out = (0, ddl_1.PlanTable)(SCHEMA, VEHICLES_PLAN, EMPTY, SAFE);
|
|
350
|
-
(0, chai_1.expect)(out.statements).to.have.lengthOf(1);
|
|
351
|
-
(0, chai_1.expect)(out.statements[0]).to.contain("CREATE TABLE IF NOT EXISTS");
|
|
352
|
-
(0, chai_1.expect)(out.indexStatements.filter((sql) => sql.startsWith("CREATE INDEX CONCURRENTLY"))).to.have.lengthOf(DECLARED_INDEX_COUNT);
|
|
353
|
-
(0, chai_1.expect)(out.warnings).to.deep.equal([]);
|
|
354
|
-
});
|
|
355
|
-
it("adds only the missing columns", () => {
|
|
356
|
-
const actual = Existing([
|
|
357
|
-
{ name: "_id", type: "text" },
|
|
358
|
-
{ name: "_instance", type: "text" },
|
|
359
|
-
{ name: "car", type: "text" },
|
|
360
|
-
{ name: "_extra", type: "jsonb" },
|
|
361
|
-
]);
|
|
362
|
-
const out = (0, ddl_1.PlanTable)(SCHEMA, VEHICLES_PLAN, actual, SAFE);
|
|
363
|
-
const added = out.statements.filter((sql) => sql.includes("ADD COLUMN"));
|
|
364
|
-
(0, chai_1.expect)(added).to.deep.equal([
|
|
365
|
-
`ALTER TABLE ${VEHICLES_TARGET} ADD COLUMN IF NOT EXISTS "price" double precision`,
|
|
366
|
-
`ALTER TABLE ${VEHICLES_TARGET} ADD COLUMN IF NOT EXISTS "tags" jsonb`,
|
|
367
|
-
]);
|
|
368
|
-
});
|
|
369
|
-
it("moves each added column's field out of the overflow document, in the same transaction", () => {
|
|
370
|
-
const actual = Existing([
|
|
371
|
-
{ name: "_id", type: "text" },
|
|
372
|
-
{ name: "_instance", type: "text" },
|
|
373
|
-
{ name: "car", type: "text" },
|
|
374
|
-
{ name: "_extra", type: "jsonb" },
|
|
375
|
-
]);
|
|
376
|
-
const out = (0, ddl_1.PlanTable)(SCHEMA, VEHICLES_PLAN, actual, SAFE);
|
|
377
|
-
const filled = out.statements.filter((sql) => sql.startsWith("UPDATE"));
|
|
378
|
-
(0, chai_1.expect)(filled).to.have.lengthOf(2);
|
|
379
|
-
(0, chai_1.expect)(filled[0]).to.contain(`UPDATE ${VEHICLES_TARGET} SET "price" =`);
|
|
380
|
-
(0, chai_1.expect)(filled[0]).to.contain(`"_extra" = "_extra" - 'price'`);
|
|
381
|
-
(0, chai_1.expect)(filled[0]).to.contain(`WHERE "price" IS NULL`);
|
|
382
|
-
const added = out.statements.indexOf(out.statements.filter((sql) => sql.includes(`"price"`))[0]);
|
|
383
|
-
(0, chai_1.expect)(out.statements[added + 1]).to.equal(filled[0]);
|
|
384
|
-
});
|
|
385
|
-
it("reads the stored value as the column's type, so a mistyped one stays put", () => {
|
|
386
|
-
const actual = Existing([
|
|
387
|
-
{ name: "_id", type: "text" },
|
|
388
|
-
{ name: "_instance", type: "text" },
|
|
389
|
-
{ name: "car", type: "text" },
|
|
390
|
-
{ name: "tags", type: "jsonb" },
|
|
391
|
-
{ name: "_extra", type: "jsonb" },
|
|
392
|
-
]);
|
|
393
|
-
const out = (0, ddl_1.PlanTable)(SCHEMA, VEHICLES_PLAN, actual, SAFE);
|
|
394
|
-
const filled = out.statements.filter((sql) => sql.startsWith("UPDATE"));
|
|
395
|
-
(0, chai_1.expect)(filled).to.have.lengthOf(1);
|
|
396
|
-
(0, chai_1.expect)(filled[0]).to.contain("jsonb_typeof");
|
|
397
|
-
(0, chai_1.expect)(filled[0]).to.contain("IS NOT NULL");
|
|
398
|
-
(0, chai_1.expect)(filled[0]).to.contain("'null'::jsonb");
|
|
399
|
-
});
|
|
400
|
-
it("plans no backfill where nothing was added", () => {
|
|
401
|
-
const actual = Existing([
|
|
402
|
-
{ name: "_id", type: "text" },
|
|
403
|
-
{ name: "_instance", type: "text" },
|
|
404
|
-
{ name: "car", type: "text" },
|
|
405
|
-
{ name: "price", type: "double precision" },
|
|
406
|
-
{ name: "tags", type: "jsonb" },
|
|
407
|
-
{ name: "_extra", type: "jsonb" },
|
|
408
|
-
]);
|
|
409
|
-
const out = (0, ddl_1.PlanTable)(SCHEMA, VEHICLES_PLAN, actual, SAFE);
|
|
410
|
-
(0, chai_1.expect)(out.statements.filter((sql) => sql.startsWith("UPDATE"))).to.deep.equal([]);
|
|
411
|
-
});
|
|
412
|
-
it("accepts the catalog spelling of a timestamp column", () => {
|
|
413
|
-
const plan = (0, ddl_1.BuildTablePlan)("v", dated, (0, fields_1.ParseTable)(dated, "s.v"));
|
|
414
|
-
const actual = Existing([
|
|
415
|
-
{ name: "_id", type: "text" },
|
|
416
|
-
{ name: "_instance", type: "text" },
|
|
417
|
-
{ name: "manufactured", type: "timestamp with time zone" },
|
|
418
|
-
{ name: "_extra", type: "jsonb" },
|
|
419
|
-
]);
|
|
420
|
-
(0, chai_1.expect)((0, ddl_1.PlanTable)(SCHEMA, plan, actual, SAFE).statements).to.deep.equal([]);
|
|
421
|
-
});
|
|
422
|
-
it("accepts the catalog spelling of every physical type", () => {
|
|
423
|
-
const plan = (0, ddl_1.BuildTablePlan)("v", everyType, (0, fields_1.ParseTable)(everyType, "s.v"));
|
|
424
|
-
const actual = Existing(CatalogColumns(plan));
|
|
425
|
-
(0, chai_1.expect)((0, ddl_1.PlanTable)(SCHEMA, plan, actual, SAFE).statements).to.deep.equal([]);
|
|
426
|
-
});
|
|
427
|
-
it("refuses a type change in safe mode, naming the field", () => {
|
|
428
|
-
const actual = Existing(RETYPED_COLUMNS);
|
|
429
|
-
const converge = () => (0, ddl_1.PlanTable)(SCHEMA, VEHICLES_PLAN, actual, SAFE);
|
|
430
|
-
(0, chai_1.expect)(converge).to.throw(/price/);
|
|
431
|
-
(0, chai_1.expect)(converge).to.throw(/destructive/);
|
|
432
|
-
});
|
|
433
|
-
it("alters a changed type in destructive mode", () => {
|
|
434
|
-
const actual = Existing(RETYPED_COLUMNS);
|
|
435
|
-
const out = (0, ddl_1.PlanTable)(SCHEMA, VEHICLES_PLAN, actual, DESTRUCTIVE);
|
|
436
|
-
(0, chai_1.expect)(out.statements).to.contain(`ALTER TABLE ${VEHICLES_TARGET} ALTER COLUMN "price" TYPE double precision USING ("price"::text::double precision)`);
|
|
437
|
-
});
|
|
438
|
-
it("routes the destructive cast through text when no direct cast exists", () => {
|
|
439
|
-
const actual = Existing(UNCASTABLE_COLUMNS);
|
|
440
|
-
const out = (0, ddl_1.PlanTable)(SCHEMA, VEHICLES_PLAN, actual, DESTRUCTIVE);
|
|
441
|
-
(0, chai_1.expect)(out.statements).to.contain(`ALTER TABLE ${VEHICLES_TARGET} ALTER COLUMN "price" TYPE double precision USING ("price"::text::double precision)`);
|
|
442
|
-
});
|
|
443
|
-
it("refuses to add a not-null column with no default to a live table", () => {
|
|
444
|
-
const actual = Existing(FULL_COLUMNS.filter((column) => column.name !== "_id"));
|
|
445
|
-
const converge = () => (0, ddl_1.PlanTable)(SCHEMA, VEHICLES_PLAN, actual, DESTRUCTIVE);
|
|
446
|
-
(0, chai_1.expect)(converge).to.throw(/_id/);
|
|
447
|
-
(0, chai_1.expect)(converge).to.throw(/not created by this adapter/);
|
|
448
|
-
});
|
|
449
|
-
it("warns about an undeclared column in safe mode and keeps it", () => {
|
|
450
|
-
const actual = Existing(RETIRED_COLUMNS, SignedIndexes(VEHICLES_PLAN));
|
|
451
|
-
const out = (0, ddl_1.PlanTable)(SCHEMA, VEHICLES_PLAN, actual, SAFE);
|
|
452
|
-
(0, chai_1.expect)(out.statements).to.deep.equal([]);
|
|
453
|
-
(0, chai_1.expect)(out.warnings[0]).to.match(/retired/);
|
|
454
|
-
});
|
|
455
|
-
it("drops an undeclared column in destructive mode", () => {
|
|
456
|
-
const actual = Existing(RETIRED_COLUMNS, SignedIndexes(VEHICLES_PLAN));
|
|
457
|
-
const out = (0, ddl_1.PlanTable)(SCHEMA, VEHICLES_PLAN, actual, DESTRUCTIVE);
|
|
458
|
-
(0, chai_1.expect)(out.statements).to.contain(`ALTER TABLE ${VEHICLES_TARGET} DROP COLUMN "retired"`);
|
|
459
|
-
});
|
|
460
|
-
it("leaves a matching index alone", () => {
|
|
461
|
-
const actual = Existing(FULL_COLUMNS, SignedIndexes(VEHICLES_PLAN));
|
|
462
|
-
const out = (0, ddl_1.PlanTable)(SCHEMA, VEHICLES_PLAN, actual, SAFE);
|
|
463
|
-
(0, chai_1.expect)(out.indexStatements).to.deep.equal([]);
|
|
464
|
-
});
|
|
465
|
-
it("builds indexes outside the transaction", () => {
|
|
466
|
-
const actual = Existing(FULL_COLUMNS);
|
|
467
|
-
const out = (0, ddl_1.PlanTable)(SCHEMA, VEHICLES_PLAN, actual, SAFE);
|
|
468
|
-
(0, chai_1.expect)(out.statements).to.deep.equal([]);
|
|
469
|
-
(0, chai_1.expect)(out.indexStatements).to.have.lengthOf(DECLARED_INDEX_COUNT * 2);
|
|
470
|
-
});
|
|
471
|
-
it("builds a drifted index's replacement before it drops the index", () => {
|
|
472
|
-
const actual = Existing(FULL_COLUMNS, [
|
|
473
|
-
...OtherIndexes(VEHICLES_PLAN, "vehicles_price"),
|
|
474
|
-
DRIFTED_PRICE_INDEX,
|
|
475
|
-
]);
|
|
476
|
-
const out = (0, ddl_1.PlanTable)(SCHEMA, VEHICLES_PLAN, actual, SAFE);
|
|
477
|
-
(0, chai_1.expect)(out.statements).to.deep.equal([]);
|
|
478
|
-
(0, chai_1.expect)(out.indexStatements).to.deep.equal([
|
|
479
|
-
`${CREATE_PRICE_REPLACEMENT} ON ${VEHICLES_TARGET} USING btree ("_instance", "price")`,
|
|
480
|
-
`COMMENT ON INDEX "shop"."vehicles_price__next" IS '${PRICE_SIGNATURE}'`,
|
|
481
|
-
DROP_PRICE,
|
|
482
|
-
RENAME_PRICE_REPLACEMENT,
|
|
483
|
-
]);
|
|
484
|
-
});
|
|
485
|
-
it("replaces an index we own but never signed", () => {
|
|
486
|
-
const actual = Existing(FULL_COLUMNS, [
|
|
487
|
-
...OtherIndexes(VEHICLES_PLAN, "vehicles_price"),
|
|
488
|
-
{ name: "vehicles_price", valid: true },
|
|
489
|
-
]);
|
|
490
|
-
const out = (0, ddl_1.PlanTable)(SCHEMA, VEHICLES_PLAN, actual, SAFE);
|
|
491
|
-
(0, chai_1.expect)(StartsAt(out.indexStatements, CREATE_PRICE_REPLACEMENT)).to.equal(0);
|
|
492
|
-
(0, chai_1.expect)(out.indexStatements).to.contain(RENAME_PRICE_REPLACEMENT);
|
|
493
|
-
});
|
|
494
|
-
it("drops and rebuilds an index a failed concurrent build left invalid", () => {
|
|
495
|
-
const actual = Existing(FULL_COLUMNS, [
|
|
496
|
-
...OtherIndexes(VEHICLES_PLAN, "vehicles_price"),
|
|
497
|
-
{ name: "vehicles_price", signature: PRICE_SIGNATURE, valid: false },
|
|
498
|
-
]);
|
|
499
|
-
const out = (0, ddl_1.PlanTable)(SCHEMA, VEHICLES_PLAN, actual, SAFE);
|
|
500
|
-
(0, chai_1.expect)(out.indexStatements[0]).to.equal(DROP_PRICE);
|
|
501
|
-
(0, chai_1.expect)(StartsAt(out.indexStatements, CREATE_PRICE)).to.equal(1);
|
|
502
|
-
});
|
|
503
|
-
it("clears a replacement a failed rebuild left behind", () => {
|
|
504
|
-
const actual = Existing(FULL_COLUMNS, [
|
|
505
|
-
...SignedIndexes(VEHICLES_PLAN),
|
|
506
|
-
{ name: "vehicles_price__next", valid: false },
|
|
507
|
-
]);
|
|
508
|
-
const out = (0, ddl_1.PlanTable)(SCHEMA, VEHICLES_PLAN, actual, SAFE);
|
|
509
|
-
(0, chai_1.expect)(out.indexStatements).to.deep.equal([DROP_PRICE_REPLACEMENT]);
|
|
510
|
-
});
|
|
511
|
-
it("swaps in a ready replacement when a crash left the index missing", () => {
|
|
512
|
-
const actual = Existing(FULL_COLUMNS, [
|
|
513
|
-
...OtherIndexes(VEHICLES_PLAN, "vehicles_price"),
|
|
514
|
-
{ name: "vehicles_price__next", signature: PRICE_SIGNATURE, valid: true },
|
|
515
|
-
]);
|
|
516
|
-
const out = (0, ddl_1.PlanTable)(SCHEMA, VEHICLES_PLAN, actual, SAFE);
|
|
517
|
-
(0, chai_1.expect)(out.indexStatements).to.deep.equal([RENAME_PRICE_REPLACEMENT]);
|
|
518
|
-
});
|
|
519
|
-
it("drops an adapter index whose declaration is gone, after every build", () => {
|
|
520
|
-
const actual = Existing(FULL_COLUMNS, [
|
|
521
|
-
{
|
|
522
|
-
name: "vehicles_retired",
|
|
523
|
-
signature: `antelopejs:1:btree:"_instance","retired"`,
|
|
524
|
-
valid: true,
|
|
525
|
-
},
|
|
526
|
-
]);
|
|
527
|
-
const out = (0, ddl_1.PlanTable)(SCHEMA, VEHICLES_PLAN, actual, SAFE);
|
|
528
|
-
(0, chai_1.expect)(out.indexStatements.at(-1)).to.equal(`DROP INDEX CONCURRENTLY IF EXISTS "shop"."vehicles_retired"`);
|
|
529
|
-
});
|
|
530
|
-
it("drops the __g twin once an index is no longer crossInstance", () => {
|
|
531
|
-
const shared = PlanFor("vehicles", {
|
|
532
|
-
fields: vehicles.fields,
|
|
533
|
-
indexes: { ...vehicles.indexes, price: { crossInstance: true } },
|
|
534
|
-
});
|
|
535
|
-
const actual = Existing(FULL_COLUMNS, SignedIndexes(shared));
|
|
536
|
-
const out = (0, ddl_1.PlanTable)(SCHEMA, VEHICLES_PLAN, actual, SAFE);
|
|
537
|
-
(0, chai_1.expect)(out.indexStatements).to.deep.equal([
|
|
538
|
-
`DROP INDEX CONCURRENTLY IF EXISTS "shop"."vehicles_price__g"`,
|
|
539
|
-
]);
|
|
540
|
-
});
|
|
541
|
-
it("leaves a hand-made index alone", () => {
|
|
542
|
-
const actual = Existing(FULL_COLUMNS, [
|
|
543
|
-
...SignedIndexes(VEHICLES_PLAN),
|
|
544
|
-
{ name: "operator_hunch", valid: true },
|
|
545
|
-
{ name: "operator_broken", valid: false },
|
|
546
|
-
]);
|
|
547
|
-
const out = (0, ddl_1.PlanTable)(SCHEMA, VEHICLES_PLAN, actual, SAFE);
|
|
548
|
-
(0, chai_1.expect)(out.statements).to.deep.equal([]);
|
|
549
|
-
(0, chai_1.expect)(out.indexStatements).to.deep.equal([]);
|
|
550
|
-
});
|
|
551
|
-
it("drops obsolete indexes inside the transaction before a column retype", () => {
|
|
552
|
-
const actual = Existing(RETYPED_COLUMNS, [
|
|
553
|
-
...OtherIndexes(VEHICLES_PLAN, "vehicles_tags"),
|
|
554
|
-
DRIFTED_TAGS_INDEX,
|
|
555
|
-
]);
|
|
556
|
-
const out = (0, ddl_1.PlanTable)(SCHEMA, VEHICLES_PLAN, actual, DESTRUCTIVE);
|
|
557
|
-
(0, chai_1.expect)(LastAt(out.statements, IsIndexDrop)).to.be.lessThan(FirstAt(out.statements, IsColumnChange));
|
|
558
|
-
(0, chai_1.expect)(out.statements[0]).to.equal(`DROP INDEX IF EXISTS "shop"."vehicles_tags"`);
|
|
559
|
-
(0, chai_1.expect)(out.indexStatements).to.have.lengthOf(2);
|
|
560
|
-
(0, chai_1.expect)(out.indexStatements[0]).to.match(/^CREATE INDEX CONCURRENTLY "vehicles_tags"/);
|
|
561
|
-
});
|
|
562
|
-
it("emits nothing against the state its own creation produces", () => {
|
|
563
|
-
const actual = Existing(CatalogColumns(VEHICLES_PLAN), SignedIndexes(VEHICLES_PLAN));
|
|
564
|
-
(0, chai_1.expect)((0, ddl_1.PlanTable)(SCHEMA, VEHICLES_PLAN, actual, SAFE)).to.deep.equal({
|
|
565
|
-
statements: [],
|
|
566
|
-
indexStatements: [],
|
|
567
|
-
warnings: [],
|
|
568
|
-
});
|
|
569
|
-
});
|
|
570
|
-
});
|
|
571
269
|
//# sourceMappingURL=ddl.spec.js.map
|