envio 3.5.0-alpha.3 → 3.5.0-rc.0

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.
Files changed (127) hide show
  1. package/package.json +6 -6
  2. package/src/Batch.res +8 -8
  3. package/src/Batch.res.mjs +4 -3
  4. package/src/BatchProcessing.res +17 -7
  5. package/src/BatchProcessing.res.mjs +8 -4
  6. package/src/ChainFetching.res +20 -19
  7. package/src/ChainFetching.res.mjs +14 -14
  8. package/src/ChainId.res +58 -0
  9. package/src/ChainId.res.mjs +49 -0
  10. package/src/ChainId.resi +27 -0
  11. package/src/ChainMap.res +12 -26
  12. package/src/ChainMap.res.mjs +5 -41
  13. package/src/ChainMap.resi +5 -20
  14. package/src/ChainMetadata.res +1 -1
  15. package/src/ChainMetadata.res.mjs +3 -2
  16. package/src/ChainState.res +35 -20
  17. package/src/ChainState.res.mjs +34 -11
  18. package/src/ChainState.resi +2 -0
  19. package/src/Config.res +41 -24
  20. package/src/Config.res.mjs +17 -14
  21. package/src/ContractRegisterContext.res +1 -1
  22. package/src/ContractRegisterContext.res.mjs +1 -1
  23. package/src/Core.res +1 -0
  24. package/src/CrossChainState.res +61 -16
  25. package/src/CrossChainState.res.mjs +37 -13
  26. package/src/CrossChainState.resi +3 -2
  27. package/src/Env.res +0 -3
  28. package/src/Env.res.mjs +0 -3
  29. package/src/EventConfigBuilder.res +1 -1
  30. package/src/EventProcessing.res +4 -4
  31. package/src/EventProcessing.res.mjs +5 -5
  32. package/src/FetchState.res +261 -89
  33. package/src/FetchState.res.mjs +187 -63
  34. package/src/FinalizeBackfill.res +33 -6
  35. package/src/FinalizeBackfill.res.mjs +19 -1
  36. package/src/HandlerRegister.res +8 -8
  37. package/src/HandlerRegister.res.mjs +5 -4
  38. package/src/HandlerRegister.resi +1 -1
  39. package/src/InMemoryStore.res +4 -0
  40. package/src/InMemoryStore.res.mjs +1 -1
  41. package/src/IndexerLoop.res +9 -2
  42. package/src/IndexerLoop.res.mjs +8 -1
  43. package/src/IndexerState.res +41 -24
  44. package/src/IndexerState.res.mjs +36 -17
  45. package/src/IndexerState.resi +9 -7
  46. package/src/Internal.res +19 -17
  47. package/src/Internal.res.mjs +18 -9
  48. package/src/LoadLayer.res +1 -1
  49. package/src/LoadLayer.res.mjs +2 -1
  50. package/src/LogSelection.res +2 -2
  51. package/src/Main.res +7 -11
  52. package/src/Main.res.mjs +4 -6
  53. package/src/Metrics.res +6 -6
  54. package/src/Metrics.res.mjs +4 -3
  55. package/src/Persistence.res +15 -7
  56. package/src/PgStorage.res +284 -258
  57. package/src/PgStorage.res.mjs +181 -208
  58. package/src/RawEvent.res +1 -2
  59. package/src/RawEvent.res.mjs +1 -1
  60. package/src/Rollback.res +18 -20
  61. package/src/Rollback.res.mjs +9 -9
  62. package/src/RollbackCommit.res +2 -2
  63. package/src/RollbackCommit.res.mjs +3 -3
  64. package/src/SafeCheckpointTracking.res +2 -2
  65. package/src/SimulateDeadInputTracker.res +17 -21
  66. package/src/SimulateDeadInputTracker.res.mjs +9 -8
  67. package/src/SimulateItems.res +8 -10
  68. package/src/SimulateItems.res.mjs +9 -10
  69. package/src/Sink.res +2 -2
  70. package/src/Sink.res.mjs +3 -2
  71. package/src/TestIndexer.res +11 -14
  72. package/src/TestIndexer.res.mjs +14 -10
  73. package/src/UserContext.res +2 -2
  74. package/src/UserContext.res.mjs +2 -1
  75. package/src/Utils.res +0 -4
  76. package/src/Utils.res.mjs +1 -6
  77. package/src/bindings/ClickHouse.res +20 -2
  78. package/src/bindings/ClickHouse.res.mjs +25 -14
  79. package/src/db/EntityHistory.res +1 -1
  80. package/src/db/IndexCatalog.res +248 -0
  81. package/src/db/IndexCatalog.res.mjs +222 -0
  82. package/src/db/IndexDefinition.res +131 -0
  83. package/src/db/IndexDefinition.res.mjs +138 -0
  84. package/src/db/IndexManager.res +145 -0
  85. package/src/db/IndexManager.res.mjs +130 -0
  86. package/src/db/InternalTable.res +50 -26
  87. package/src/db/InternalTable.res.mjs +32 -24
  88. package/src/db/Table.res +11 -1
  89. package/src/db/Table.res.mjs +9 -4
  90. package/src/sources/AddressSet.res +5 -4
  91. package/src/sources/AddressStore.res +25 -14
  92. package/src/sources/AddressStore.res.mjs +10 -12
  93. package/src/sources/Evm.res +2 -2
  94. package/src/sources/Evm.res.mjs +1 -1
  95. package/src/sources/EvmChain.res +3 -3
  96. package/src/sources/EvmChain.res.mjs +3 -3
  97. package/src/sources/EvmHyperSyncSource.res +7 -7
  98. package/src/sources/EvmHyperSyncSource.res.mjs +6 -6
  99. package/src/sources/Fuel.res +2 -2
  100. package/src/sources/Fuel.res.mjs +1 -1
  101. package/src/sources/FuelHyperSyncClient.res +3 -0
  102. package/src/sources/FuelHyperSyncClient.res.mjs +1 -0
  103. package/src/sources/FuelHyperSyncSource.res +5 -7
  104. package/src/sources/FuelHyperSyncSource.res.mjs +5 -5
  105. package/src/sources/HyperSync.resi +2 -2
  106. package/src/sources/HyperSyncClient.res +5 -0
  107. package/src/sources/HyperSyncClient.res.mjs +1 -0
  108. package/src/sources/RpcSource.res +13 -14
  109. package/src/sources/RpcSource.res.mjs +13 -12
  110. package/src/sources/SimulateSource.res +42 -15
  111. package/src/sources/SimulateSource.res.mjs +27 -9
  112. package/src/sources/Source.res +1 -5
  113. package/src/sources/SourceManager.res +12 -12
  114. package/src/sources/SourceManager.res.mjs +11 -10
  115. package/src/sources/SourceManager.resi +2 -2
  116. package/src/sources/Svm.res +4 -5
  117. package/src/sources/Svm.res.mjs +5 -4
  118. package/src/sources/SvmHyperSyncClient.res +3 -0
  119. package/src/sources/SvmHyperSyncClient.res.mjs +1 -0
  120. package/src/sources/SvmHyperSyncSource.res +4 -4
  121. package/src/sources/SvmHyperSyncSource.res.mjs +3 -3
  122. package/src/tui/Tui.res +1 -1
  123. package/src/tui/Tui.res.mjs +2 -1
  124. package/src/tui/components/CustomHooks.res +5 -4
  125. package/src/tui/components/CustomHooks.res.mjs +4 -2
  126. package/src/db/IndexRegistry.res +0 -219
  127. package/src/db/IndexRegistry.res.mjs +0 -195
@@ -1,219 +0,0 @@
1
- // An in-memory mirror of the indexes PostgreSQL holds for the indexer schema.
2
- // Postgres stays authoritative: the registry is loaded from pg_catalog at
3
- // startup/resume and afterwards only grows — optimistically, right after a
4
- // CREATE INDEX we issued succeeds. Only one Indexer instance writes to the
5
- // schema, so no catalog refresh is needed between those two points.
6
-
7
- let btree = "btree"
8
-
9
- type column = {
10
- name: string,
11
- direction: Table.indexFieldDirection,
12
- }
13
-
14
- let fromIndexFields = (indexFields: array<Table.compositeIndexField>) =>
15
- indexFields->Array.map(({fieldName, direction}) => {name: fieldName, direction})
16
-
17
- // Identity of an index is table + ordered columns + direction + method. Names
18
- // are deliberately not part of it: the catalog is matched on what the index
19
- // actually covers, not on how it was spelled.
20
- let makeKey = (~tableName, ~columns: array<column>, ~method) =>
21
- `${tableName}|${method}|${columns
22
- ->Array.map(({name, direction}) =>
23
- switch direction {
24
- | Table.Asc => name
25
- | Desc => name ++ " DESC"
26
- }
27
- )
28
- ->Array.joinUnsafe(",")}`
29
-
30
- type catalogRow = {
31
- tableName: string,
32
- indexName: string,
33
- method: string,
34
- // 1/0 rather than a bool: postgres.js hands booleans back inconsistently
35
- // depending on the driver's type resolution, so the query casts it.
36
- isValid: int,
37
- // 1 only for an index the indexer could have created: plain btree over plain
38
- // columns. A unique or partial index carries a definition our key doesn't
39
- // capture, so it can never be one of ours to rebuild.
40
- isPlain: int,
41
- columns: array<string>,
42
- // "ASC"/"DESC" per column, in the same order as `columns`.
43
- directions: array<string>,
44
- }
45
-
46
- let catalogRowsSchema = S.array(
47
- S.object((s): catalogRow => {
48
- tableName: s.field("tableName", S.string),
49
- indexName: s.field("indexName", S.string),
50
- method: s.field("method", S.string),
51
- isValid: s.field("isValid", S.int),
52
- isPlain: s.field("isPlain", S.int),
53
- columns: s.field("columns", S.array(S.string)),
54
- directions: s.field("directions", S.array(S.string)),
55
- }),
56
- )
57
-
58
- // One row per index, with its key columns aggregated in ordinal order.
59
- // INCLUDE columns are excluded (they don't affect what the index can serve),
60
- // and expression columns come back as their printed definition so an
61
- // expression index can never be mistaken for a plain-column one.
62
- let makeCatalogQuery = (~pgSchema) =>
63
- `SELECT
64
- t.relname AS "tableName",
65
- i.relname AS "indexName",
66
- am.amname AS "method",
67
- CASE WHEN ix.indisvalid AND ix.indisready THEN 1 ELSE 0 END AS "isValid",
68
- CASE
69
- WHEN ix.indisunique OR ix.indpred IS NOT NULL OR ix.indexprs IS NOT NULL THEN 0
70
- ELSE 1
71
- END AS "isPlain",
72
- array_agg(
73
- CASE WHEN k.attnum = 0
74
- THEN pg_get_indexdef(ix.indexrelid, k.ord::int, true)
75
- ELSE a.attname
76
- END ORDER BY k.ord
77
- ) AS "columns",
78
- array_agg(
79
- CASE WHEN (ix.indoption[k.ord - 1] & 1) = 1 THEN 'DESC' ELSE 'ASC' END ORDER BY k.ord
80
- ) AS "directions"
81
- FROM pg_index ix
82
- JOIN pg_class i ON i.oid = ix.indexrelid
83
- JOIN pg_class t ON t.oid = ix.indrelid
84
- JOIN pg_namespace n ON n.oid = t.relnamespace
85
- JOIN pg_am am ON am.oid = i.relam
86
- JOIN LATERAL unnest(ix.indkey) WITH ORDINALITY AS k(attnum, ord) ON k.ord <= ix.indnkeyatts
87
- LEFT JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = k.attnum
88
- WHERE n.nspname = '${pgSchema}'
89
- GROUP BY t.relname, i.relname, am.amname, ix.indisvalid, ix.indisready,
90
- ix.indisunique, ix.indpred, ix.indexprs;`
91
-
92
- // What we know about an index that came back invalid, enough to decide whether
93
- // rebuilding it would produce the index we actually wanted.
94
- type invalidIndex = {
95
- key: string,
96
- isRepairable: bool,
97
- }
98
-
99
- type t = {
100
- keys: Utils.Set.t<string>,
101
- // Every index Postgres reports as invalid, by name. Kept because
102
- // `CREATE INDEX IF NOT EXISTS` matches on name: with an invalid index already
103
- // under the name we want, the DDL is a silent no-op and we'd register a key
104
- // for something the planner refuses to use.
105
- invalidByName: dict<invalidIndex>,
106
- // Keyed by index key so identical concurrent requests await one build.
107
- inflight: dict<promise<unit>>,
108
- // Tail of the build chain per table, so two different indexes on the same
109
- // table are built one after the other rather than at once.
110
- tableQueue: dict<promise<unit>>,
111
- }
112
-
113
- let make = () => {
114
- keys: Utils.Set.make(),
115
- invalidByName: Dict.make(),
116
- inflight: Dict.make(),
117
- tableQueue: Dict.make(),
118
- }
119
-
120
- let has = (registry, key) => registry.keys->Utils.Set.has(key)
121
-
122
- let add = (registry, key) => registry.keys->Utils.Set.add(key)->ignore
123
-
124
- let size = registry => registry.keys->Utils.Set.size
125
-
126
- let toArray = registry => registry.keys->Utils.Set.toArray->Array.toSorted(String.compare)
127
-
128
- // A plain CREATE INDEX either commits or leaves nothing behind, so an index can
129
- // only be invalid because something before us left it that way — the startup
130
- // snapshot stays accurate until the next restart.
131
- let getInvalid = (registry, name) => registry.invalidByName->Utils.Dict.dangerouslyGetNonOption(name)
132
-
133
- let clearInvalidName = (registry, name) => registry.invalidByName->Utils.Dict.deleteInPlace(name)
134
-
135
- // Replaces the whole registry with what the catalog reports. Returns the names
136
- // of indexes Postgres flagged invalid (eg a CREATE INDEX CONCURRENTLY that died
137
- // midway). They stay out of the registry, so the next request that needs one
138
- // repairs it.
139
- let reload = (registry, ~rows: array<catalogRow>) => {
140
- registry.keys->Utils.Set.clear
141
- registry.invalidByName
142
- ->Dict.keysToArray
143
- ->Array.forEach(name => registry.invalidByName->Utils.Dict.deleteInPlace(name))
144
- let invalidIndexNames = []
145
- rows->Array.forEach(row => {
146
- let key = makeKey(
147
- ~tableName=row.tableName,
148
- ~columns=row.columns->Array.mapWithIndex((name, idx) => {
149
- name,
150
- direction: switch row.directions->Array.get(idx) {
151
- | Some("DESC") => Table.Desc
152
- | _ => Asc
153
- },
154
- }),
155
- ~method=row.method,
156
- )
157
- if row.isValid === 0 {
158
- invalidIndexNames->Array.push(row.indexName)->ignore
159
- registry.invalidByName->Dict.set(row.indexName, {key, isRepairable: row.isPlain === 1})
160
- } else {
161
- registry->add(key)
162
- }
163
- })
164
- invalidIndexNames
165
- }
166
-
167
- // Runs `build` unless the index is already registered. The key is added only
168
- // after `build` resolves, so a failed build leaves the registry untouched and
169
- // the next request retries.
170
- let ensure = (registry, ~key, ~tableName, ~build) =>
171
- if registry->has(key) {
172
- Promise.resolve()
173
- } else {
174
- switch registry.inflight->Utils.Dict.dangerouslyGetNonOption(key) {
175
- | Some(promise) => promise
176
- | None =>
177
- let tail = switch registry.tableQueue->Utils.Dict.dangerouslyGetNonOption(tableName) {
178
- | Some(tail) => tail
179
- | None => Promise.resolve()
180
- }
181
- let promise =
182
- tail
183
- // The queued build may have been satisfied while waiting behind another
184
- // one on the same table (eg a finalize pass created it).
185
- ->Promise.then(() => registry->has(key) ? Promise.resolve() : build())
186
- ->Promise.thenResolve(() => registry->add(key))
187
- registry.inflight->Dict.set(key, promise)
188
- registry.tableQueue->Dict.set(tableName, promise->Utils.Promise.silentCatch)
189
- promise->Promise.finally(() => registry.inflight->Utils.Dict.deleteInPlace(key))
190
- }
191
- }
192
-
193
- let pgMaxIdentifierLength = 63
194
-
195
- // Postgres truncates identifiers past 63 characters on its own. Doing it here
196
- // instead keeps the name we emit, log and read back from the catalog identical
197
- // to the one it stores. Descriptions are ASCII (GraphQL names are), so
198
- // characters and Postgres' byte limit line up.
199
- let truncateIndexName = description =>
200
- description->String.length > pgMaxIdentifierLength
201
- ? description->String.slice(~start=0, ~end=pgMaxIdentifierLength)
202
- : description
203
-
204
- // Two distinct descriptions can collapse onto one truncated name — and the
205
- // second `CREATE INDEX IF NOT EXISTS` would then be skipped without a trace,
206
- // leaving the registry claiming an index that doesn't exist.
207
- let validateIndexNamesOrThrow = (descriptions: array<string>) => {
208
- let byName = Dict.make()
209
- descriptions->Array.forEach(description => {
210
- let name = description->truncateIndexName
211
- switch byName->Utils.Dict.dangerouslyGetNonOption(name) {
212
- | Some(existing) if existing !== description =>
213
- JsError.throwWithMessage(
214
- `Index names "${existing}" and "${description}" both truncate to "${name}" at PostgreSQL's ${pgMaxIdentifierLength->Int.toString}-character identifier limit. Rename a field or an entity so the generated index names stay distinct.`,
215
- )
216
- | _ => byName->Dict.set(name, description)
217
- }
218
- })
219
- }
@@ -1,195 +0,0 @@
1
- // Generated by ReScript, PLEASE EDIT WITH CARE
2
-
3
- import * as Utils from "../Utils.res.mjs";
4
- import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
5
- import * as Primitive_string from "@rescript/runtime/lib/es6/Primitive_string.js";
6
- import * as S$RescriptSchema from "rescript-schema/src/S.res.mjs";
7
-
8
- function fromIndexFields(indexFields) {
9
- return indexFields.map(param => ({
10
- name: param.fieldName,
11
- direction: param.direction
12
- }));
13
- }
14
-
15
- function makeKey(tableName, columns, method) {
16
- return tableName + `|` + method + `|` + columns.map(param => {
17
- let name = param.name;
18
- if (param.direction === "Asc") {
19
- return name;
20
- } else {
21
- return name + " DESC";
22
- }
23
- }).join(",");
24
- }
25
-
26
- let catalogRowsSchema = S$RescriptSchema.array(S$RescriptSchema.object(s => ({
27
- tableName: s.f("tableName", S$RescriptSchema.string),
28
- indexName: s.f("indexName", S$RescriptSchema.string),
29
- method: s.f("method", S$RescriptSchema.string),
30
- isValid: s.f("isValid", S$RescriptSchema.int),
31
- isPlain: s.f("isPlain", S$RescriptSchema.int),
32
- columns: s.f("columns", S$RescriptSchema.array(S$RescriptSchema.string)),
33
- directions: s.f("directions", S$RescriptSchema.array(S$RescriptSchema.string))
34
- })));
35
-
36
- function makeCatalogQuery(pgSchema) {
37
- return `SELECT
38
- t.relname AS "tableName",
39
- i.relname AS "indexName",
40
- am.amname AS "method",
41
- CASE WHEN ix.indisvalid AND ix.indisready THEN 1 ELSE 0 END AS "isValid",
42
- CASE
43
- WHEN ix.indisunique OR ix.indpred IS NOT NULL OR ix.indexprs IS NOT NULL THEN 0
44
- ELSE 1
45
- END AS "isPlain",
46
- array_agg(
47
- CASE WHEN k.attnum = 0
48
- THEN pg_get_indexdef(ix.indexrelid, k.ord::int, true)
49
- ELSE a.attname
50
- END ORDER BY k.ord
51
- ) AS "columns",
52
- array_agg(
53
- CASE WHEN (ix.indoption[k.ord - 1] & 1) = 1 THEN 'DESC' ELSE 'ASC' END ORDER BY k.ord
54
- ) AS "directions"
55
- FROM pg_index ix
56
- JOIN pg_class i ON i.oid = ix.indexrelid
57
- JOIN pg_class t ON t.oid = ix.indrelid
58
- JOIN pg_namespace n ON n.oid = t.relnamespace
59
- JOIN pg_am am ON am.oid = i.relam
60
- JOIN LATERAL unnest(ix.indkey) WITH ORDINALITY AS k(attnum, ord) ON k.ord <= ix.indnkeyatts
61
- LEFT JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = k.attnum
62
- WHERE n.nspname = '` + pgSchema + `'
63
- GROUP BY t.relname, i.relname, am.amname, ix.indisvalid, ix.indisready,
64
- ix.indisunique, ix.indpred, ix.indexprs;`;
65
- }
66
-
67
- function make() {
68
- return {
69
- keys: new Set(),
70
- invalidByName: {},
71
- inflight: {},
72
- tableQueue: {}
73
- };
74
- }
75
-
76
- function has(registry, key) {
77
- return registry.keys.has(key);
78
- }
79
-
80
- function add(registry, key) {
81
- registry.keys.add(key);
82
- }
83
-
84
- function size(registry) {
85
- return registry.keys.size;
86
- }
87
-
88
- function toArray(registry) {
89
- return Array.from(registry.keys).toSorted(Primitive_string.compare);
90
- }
91
-
92
- function getInvalid(registry, name) {
93
- return registry.invalidByName[name];
94
- }
95
-
96
- function clearInvalidName(registry, name) {
97
- Utils.Dict.deleteInPlace(registry.invalidByName, name);
98
- }
99
-
100
- function reload(registry, rows) {
101
- registry.keys.clear();
102
- Object.keys(registry.invalidByName).forEach(name => Utils.Dict.deleteInPlace(registry.invalidByName, name));
103
- let invalidIndexNames = [];
104
- rows.forEach(row => {
105
- let key = makeKey(row.tableName, row.columns.map((name, idx) => {
106
- let match = row.directions[idx];
107
- let tmp;
108
- tmp = match === "DESC" ? "Desc" : "Asc";
109
- return {
110
- name: name,
111
- direction: tmp
112
- };
113
- }), row.method);
114
- if (row.isValid === 0) {
115
- invalidIndexNames.push(row.indexName);
116
- registry.invalidByName[row.indexName] = {
117
- key: key,
118
- isRepairable: row.isPlain === 1
119
- };
120
- return;
121
- } else {
122
- return add(registry, key);
123
- }
124
- });
125
- return invalidIndexNames;
126
- }
127
-
128
- function ensure(registry, key, tableName, build) {
129
- if (registry.keys.has(key)) {
130
- return Promise.resolve();
131
- }
132
- let promise = registry.inflight[key];
133
- if (promise !== undefined) {
134
- return promise;
135
- }
136
- let tail = registry.tableQueue[tableName];
137
- let tail$1 = tail !== undefined ? tail : Promise.resolve();
138
- let promise$1 = tail$1.then(() => {
139
- if (registry.keys.has(key)) {
140
- return Promise.resolve();
141
- } else {
142
- return build();
143
- }
144
- }).then(() => add(registry, key));
145
- registry.inflight[key] = promise$1;
146
- registry.tableQueue[tableName] = Utils.$$Promise.silentCatch(promise$1);
147
- return promise$1.finally(() => Utils.Dict.deleteInPlace(registry.inflight, key));
148
- }
149
-
150
- function truncateIndexName(description) {
151
- if (description.length > 63) {
152
- return description.slice(0, 63);
153
- } else {
154
- return description;
155
- }
156
- }
157
-
158
- function validateIndexNamesOrThrow(descriptions) {
159
- let byName = {};
160
- descriptions.forEach(description => {
161
- let name = truncateIndexName(description);
162
- let existing = byName[name];
163
- if (existing !== undefined && existing !== description) {
164
- return Stdlib_JsError.throwWithMessage(`Index names "` + existing + `" and "` + description + `" both truncate to "` + name + `" at PostgreSQL's ` + (63).toString() + `-character identifier limit. Rename a field or an entity so the generated index names stay distinct.`);
165
- } else {
166
- byName[name] = description;
167
- return;
168
- }
169
- });
170
- }
171
-
172
- let btree = "btree";
173
-
174
- let pgMaxIdentifierLength = 63;
175
-
176
- export {
177
- btree,
178
- fromIndexFields,
179
- makeKey,
180
- catalogRowsSchema,
181
- makeCatalogQuery,
182
- make,
183
- has,
184
- add,
185
- size,
186
- toArray,
187
- getInvalid,
188
- clearInvalidName,
189
- reload,
190
- ensure,
191
- pgMaxIdentifierLength,
192
- truncateIndexName,
193
- validateIndexNamesOrThrow,
194
- }
195
- /* catalogRowsSchema Not a pure module */