lakeql 0.1.2 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.js +205 -81
- package/dist/{chunk-MUTXXFOW.js → chunk-BFLGC6Y5.js} +382 -67
- package/dist/chunk-RZL45ZSN.js +11034 -0
- package/dist/chunk-TFD5RFKB.js +1152 -0
- package/dist/cloudflare.d.ts +2 -3
- package/dist/cloudflare.js +5 -4
- package/dist/geo-backend-TSQJWAAB.js +18 -0
- package/dist/index.d.ts +764 -230
- package/dist/index.js +3 -2
- package/dist/node.d.ts +2 -3
- package/dist/node.js +22 -18
- package/package.json +11 -10
- package/dist/chunk-D3A4VN3U.js +0 -5677
|
@@ -1,7 +1,316 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Lake, stableStringify, vectorValue, scalarVectorValue, batchFromColumns, withObjectStoreReadControls, throwIfAborted, readControlSignal, readParquetObjectBatches, readIcebergParquetDeletes } from './chunk-RZL45ZSN.js';
|
|
2
|
+
import { LakeqlError, jsonSafeValue, matches } from './chunk-TFD5RFKB.js';
|
|
3
|
+
|
|
4
|
+
// ../core/dist/in-memory.js
|
|
5
|
+
var InMemoryRowsScanner = class {
|
|
6
|
+
tables;
|
|
7
|
+
constructor(tables, options = {}) {
|
|
8
|
+
this.tables = normalizeInMemoryTables(tables, options);
|
|
9
|
+
}
|
|
10
|
+
async *scan(path, options) {
|
|
11
|
+
const table = this.table(path);
|
|
12
|
+
const batchSize = options.batchSize;
|
|
13
|
+
for (let start = 0; start < table.rows.length; start += batchSize) {
|
|
14
|
+
const out = [];
|
|
15
|
+
for (const row of table.rows.slice(start, start + batchSize)) {
|
|
16
|
+
out.push(projectPhysicalColumns(row, options.columns));
|
|
17
|
+
}
|
|
18
|
+
yield out;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
async planTask(path) {
|
|
22
|
+
return { rowGroupRanges: [{ start: 0, end: this.table(path).rows.length }] };
|
|
23
|
+
}
|
|
24
|
+
tableInfo(path) {
|
|
25
|
+
const table = this.table(path);
|
|
26
|
+
return {
|
|
27
|
+
path: table.path,
|
|
28
|
+
size: table.size,
|
|
29
|
+
etag: table.etag,
|
|
30
|
+
lastModified: table.lastModified
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
listTables(prefix, options = {}) {
|
|
34
|
+
const out = [];
|
|
35
|
+
for (const table of [...this.tables.values()].sort((left, right) => left.path.localeCompare(right.path))) {
|
|
36
|
+
if (!table.path.startsWith(prefix))
|
|
37
|
+
continue;
|
|
38
|
+
out.push({
|
|
39
|
+
path: table.path,
|
|
40
|
+
size: table.size,
|
|
41
|
+
etag: table.etag,
|
|
42
|
+
lastModified: table.lastModified
|
|
43
|
+
});
|
|
44
|
+
if (options.limit !== void 0 && out.length >= options.limit)
|
|
45
|
+
break;
|
|
46
|
+
}
|
|
47
|
+
return out;
|
|
48
|
+
}
|
|
49
|
+
table(path) {
|
|
50
|
+
const table = this.tables.get(path);
|
|
51
|
+
if (table === void 0) {
|
|
52
|
+
throw new LakeqlError("LAKEQL_UNKNOWN_TABLE", `No in-memory table named ${path}`, { path });
|
|
53
|
+
}
|
|
54
|
+
return table;
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
var InMemoryRowsStore = class {
|
|
58
|
+
scanner;
|
|
59
|
+
constructor(scanner) {
|
|
60
|
+
this.scanner = scanner;
|
|
61
|
+
}
|
|
62
|
+
async get(path) {
|
|
63
|
+
this.scanner.tableInfo(path);
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
async getRange(path) {
|
|
67
|
+
this.scanner.tableInfo(path);
|
|
68
|
+
return new Uint8Array();
|
|
69
|
+
}
|
|
70
|
+
async put() {
|
|
71
|
+
throw new LakeqlError("LAKEQL_TYPE_ERROR", "In-memory row stores are read-only");
|
|
72
|
+
}
|
|
73
|
+
async delete() {
|
|
74
|
+
throw new LakeqlError("LAKEQL_TYPE_ERROR", "In-memory row stores are read-only");
|
|
75
|
+
}
|
|
76
|
+
async *list(prefix, options) {
|
|
77
|
+
yield* this.scanner.listTables(prefix, options);
|
|
78
|
+
}
|
|
79
|
+
async head(path) {
|
|
80
|
+
try {
|
|
81
|
+
const table = this.scanner.tableInfo(path);
|
|
82
|
+
const head = {
|
|
83
|
+
size: table.size,
|
|
84
|
+
contentType: "application/vnd.lakeql.rows+json"
|
|
85
|
+
};
|
|
86
|
+
if (table.etag !== void 0)
|
|
87
|
+
head.etag = table.etag;
|
|
88
|
+
if (table.lastModified !== void 0)
|
|
89
|
+
head.lastModified = table.lastModified;
|
|
90
|
+
return head;
|
|
91
|
+
} catch (cause) {
|
|
92
|
+
if (cause instanceof LakeqlError && cause.code === "LAKEQL_UNKNOWN_TABLE")
|
|
93
|
+
return null;
|
|
94
|
+
throw cause;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
function inMemoryRowsScanner(tables, options = {}) {
|
|
99
|
+
return new InMemoryRowsScanner(tables, options);
|
|
100
|
+
}
|
|
101
|
+
function createInMemoryLake(tables, options = {}) {
|
|
102
|
+
const { maxRows, maxBytes, ...lakeOptions } = options;
|
|
103
|
+
const tableOptions = {};
|
|
104
|
+
if (maxRows !== void 0)
|
|
105
|
+
tableOptions.maxRows = maxRows;
|
|
106
|
+
if (maxBytes !== void 0)
|
|
107
|
+
tableOptions.maxBytes = maxBytes;
|
|
108
|
+
const scanner = inMemoryRowsScanner(tables, tableOptions);
|
|
109
|
+
return new Lake({
|
|
110
|
+
...lakeOptions,
|
|
111
|
+
store: new InMemoryRowsStore(scanner),
|
|
112
|
+
scanner
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
function normalizeInMemoryTables(tables, options) {
|
|
116
|
+
const normalized = /* @__PURE__ */ new Map();
|
|
117
|
+
let totalRows = 0;
|
|
118
|
+
let totalBytes = 0;
|
|
119
|
+
for (const [path, rows] of Object.entries(tables)) {
|
|
120
|
+
if (path.trim() === "") {
|
|
121
|
+
throw new LakeqlError("LAKEQL_TYPE_ERROR", "In-memory table names must be non-empty");
|
|
122
|
+
}
|
|
123
|
+
const copiedRows = rows.map((row) => ({ ...row }));
|
|
124
|
+
const size = estimateRowsBytes(copiedRows);
|
|
125
|
+
totalRows += copiedRows.length;
|
|
126
|
+
totalBytes += size;
|
|
127
|
+
enforceInMemoryTableBudget(options, totalRows, totalBytes);
|
|
128
|
+
normalized.set(path, {
|
|
129
|
+
path,
|
|
130
|
+
rows: copiedRows,
|
|
131
|
+
size,
|
|
132
|
+
etag: `memory-${stableStringify([path, copiedRows.length, size])}`,
|
|
133
|
+
lastModified: /* @__PURE__ */ new Date(0)
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
return normalized;
|
|
137
|
+
}
|
|
138
|
+
function enforceInMemoryTableBudget(options, rows, bytes) {
|
|
139
|
+
if (options.maxRows !== void 0 && rows > options.maxRows) {
|
|
140
|
+
throw new LakeqlError("LAKEQL_BUDGET_EXCEEDED", `In-memory ingest exceeded row budget (${rows} > ${options.maxRows})`, { metric: "ingest rows", limit: options.maxRows, actual: rows });
|
|
141
|
+
}
|
|
142
|
+
if (options.maxBytes !== void 0 && bytes > options.maxBytes) {
|
|
143
|
+
throw new LakeqlError("LAKEQL_BUDGET_EXCEEDED", `In-memory ingest exceeded byte budget (${bytes} > ${options.maxBytes})`, { metric: "ingest bytes", limit: options.maxBytes, actual: bytes });
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
function estimateRowsBytes(rows) {
|
|
147
|
+
return new TextEncoder().encode(stableStringify(jsonSafeValue(rows))).byteLength;
|
|
148
|
+
}
|
|
149
|
+
function projectPhysicalColumns(row, columns) {
|
|
150
|
+
if (columns === void 0)
|
|
151
|
+
return { ...row };
|
|
152
|
+
const out = {};
|
|
153
|
+
for (const column of columns) {
|
|
154
|
+
if (column in row)
|
|
155
|
+
out[column] = row[column];
|
|
156
|
+
}
|
|
157
|
+
return out;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// ../core/dist/vector-join.js
|
|
161
|
+
function vectorHashJoin(left, right, options) {
|
|
162
|
+
const normalized = validateVectorJoinOptions(left, right, options);
|
|
163
|
+
const rightIndices = selectedIndices(right.rowCount, options.rightSelection);
|
|
164
|
+
enforceMaxRightRows(rightIndices.length, options.maxRightRows);
|
|
165
|
+
const index = buildRightIndex(right, rightIndices, normalized.rightKeys);
|
|
166
|
+
const output = createOutputColumns(left, right, normalized);
|
|
167
|
+
for (const leftIndex of selectedIndices(left.rowCount, options.leftSelection)) {
|
|
168
|
+
const matches2 = index.get(joinKey(left, leftIndex, normalized.leftKeys));
|
|
169
|
+
if (normalized.type === "semi") {
|
|
170
|
+
if (matches2 !== void 0 && matches2.length > 0)
|
|
171
|
+
appendLeftOnly(output, left, leftIndex);
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
174
|
+
if (normalized.type === "anti") {
|
|
175
|
+
if (matches2 === void 0 || matches2.length === 0)
|
|
176
|
+
appendLeftOnly(output, left, leftIndex);
|
|
177
|
+
continue;
|
|
178
|
+
}
|
|
179
|
+
if (matches2 === void 0 || matches2.length === 0) {
|
|
180
|
+
if (normalized.type === "left")
|
|
181
|
+
appendLeftWithNullRight(output, left, right, leftIndex, normalized);
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
for (const rightIndex of matches2)
|
|
185
|
+
appendJoined(output, left, right, leftIndex, rightIndex, normalized);
|
|
186
|
+
}
|
|
187
|
+
return batchFromOutput(output);
|
|
188
|
+
}
|
|
189
|
+
function validateVectorJoinOptions(left, right, options) {
|
|
190
|
+
const leftKeys = normalizeJoinKeys(options.leftKey, "leftKey");
|
|
191
|
+
const rightKeys = normalizeJoinKeys(options.rightKey, "rightKey");
|
|
192
|
+
if (leftKeys.length !== rightKeys.length) {
|
|
193
|
+
throw new LakeqlError("LAKEQL_TYPE_ERROR", "Vector join key counts must match", {
|
|
194
|
+
leftKey: options.leftKey,
|
|
195
|
+
rightKey: options.rightKey
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
if (!Number.isInteger(options.maxRightRows) || options.maxRightRows < 1) {
|
|
199
|
+
throw new LakeqlError("LAKEQL_TYPE_ERROR", "Vector join maxRightRows must be a positive integer");
|
|
200
|
+
}
|
|
201
|
+
const type = options.type ?? "inner";
|
|
202
|
+
if (type !== "inner" && type !== "left" && type !== "semi" && type !== "anti") {
|
|
203
|
+
throw new LakeqlError("LAKEQL_TYPE_ERROR", "Vector join type is not supported", { type });
|
|
204
|
+
}
|
|
205
|
+
for (const key of leftKeys)
|
|
206
|
+
assertColumn(left, key);
|
|
207
|
+
for (const key of rightKeys)
|
|
208
|
+
assertColumn(right, key);
|
|
209
|
+
const rightPrefix = options.rightPrefix ?? "right.";
|
|
210
|
+
return {
|
|
211
|
+
leftKeys,
|
|
212
|
+
rightKeys,
|
|
213
|
+
type,
|
|
214
|
+
rightPrefix,
|
|
215
|
+
outputRightColumns: type === "semi" || type === "anti" ? [] : outputRightColumns(left, right, leftKeys, rightKeys, rightPrefix)
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
function buildRightIndex(right, rightIndices, rightKeys) {
|
|
219
|
+
const index = /* @__PURE__ */ new Map();
|
|
220
|
+
for (const rightIndex of rightIndices) {
|
|
221
|
+
const key = joinKey(right, rightIndex, rightKeys);
|
|
222
|
+
const bucket = index.get(key);
|
|
223
|
+
if (bucket === void 0)
|
|
224
|
+
index.set(key, [rightIndex]);
|
|
225
|
+
else
|
|
226
|
+
bucket.push(rightIndex);
|
|
227
|
+
}
|
|
228
|
+
return index;
|
|
229
|
+
}
|
|
230
|
+
function createOutputColumns(left, _right, options) {
|
|
231
|
+
const output = {};
|
|
232
|
+
for (const column of Object.keys(left.columns))
|
|
233
|
+
output[column] = [];
|
|
234
|
+
for (const { output: column } of options.outputRightColumns)
|
|
235
|
+
output[column] = [];
|
|
236
|
+
return output;
|
|
237
|
+
}
|
|
238
|
+
function appendJoined(output, left, right, leftIndex, rightIndex, options) {
|
|
239
|
+
appendLeft(output, left, leftIndex);
|
|
240
|
+
appendRight(output, right, rightIndex, options);
|
|
241
|
+
}
|
|
242
|
+
function appendLeftOnly(output, left, leftIndex) {
|
|
243
|
+
appendLeft(output, left, leftIndex);
|
|
244
|
+
}
|
|
245
|
+
function appendLeftWithNullRight(output, left, right, leftIndex, options) {
|
|
246
|
+
appendLeft(output, left, leftIndex);
|
|
247
|
+
for (const { output: column } of options.outputRightColumns)
|
|
248
|
+
output[column]?.push(null);
|
|
249
|
+
}
|
|
250
|
+
function appendLeft(output, left, leftIndex) {
|
|
251
|
+
for (const [column, vector] of Object.entries(left.columns)) {
|
|
252
|
+
output[column]?.push(vectorValue(vector, leftIndex));
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
function appendRight(output, right, rightIndex, options) {
|
|
256
|
+
for (const { input, output: column } of options.outputRightColumns) {
|
|
257
|
+
const vector = right.columns[input];
|
|
258
|
+
if (vector === void 0)
|
|
259
|
+
throw new LakeqlError("LAKEQL_UNKNOWN_COLUMN", `Unknown column ${input}`, { column: input });
|
|
260
|
+
output[column]?.push(vectorValue(vector, rightIndex));
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
function outputRightColumns(left, right, leftKeys, rightKeys, rightPrefix) {
|
|
264
|
+
return Object.keys(right.columns).flatMap((column) => {
|
|
265
|
+
if (rightKeys.includes(column) && leftKeys.includes(column))
|
|
266
|
+
return [];
|
|
267
|
+
return [{ input: column, output: column in left.columns ? `${rightPrefix}${column}` : column }];
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
function joinKey(batch, index, keys) {
|
|
271
|
+
const values = keys.map((key) => scalarJoinValue(batch, index, key));
|
|
272
|
+
return stableStringify(values.length === 1 ? values[0] : values);
|
|
273
|
+
}
|
|
274
|
+
function scalarJoinValue(batch, index, column) {
|
|
275
|
+
const vector = batch.columns[column];
|
|
276
|
+
if (vector === void 0)
|
|
277
|
+
throw new LakeqlError("LAKEQL_UNKNOWN_COLUMN", `Unknown join key ${column}`, { column });
|
|
278
|
+
return scalarVectorValue(vector, index);
|
|
279
|
+
}
|
|
280
|
+
function normalizeJoinKeys(key, label) {
|
|
281
|
+
const keys = Array.isArray(key) ? key : [key];
|
|
282
|
+
if (keys.length === 0 || keys.some((column) => typeof column !== "string" || column.length === 0)) {
|
|
283
|
+
throw new LakeqlError("LAKEQL_TYPE_ERROR", `Vector join ${label} must contain column names`, {
|
|
284
|
+
[label]: key
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
return keys;
|
|
288
|
+
}
|
|
289
|
+
function assertColumn(batch, column) {
|
|
290
|
+
if (batch.columns[column] === void 0) {
|
|
291
|
+
throw new LakeqlError("LAKEQL_UNKNOWN_COLUMN", `Unknown join key ${column}`, { column });
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
function selectedIndices(rowCount, selection) {
|
|
295
|
+
const indices = [];
|
|
296
|
+
for (let index = 0; index < rowCount; index += 1) {
|
|
297
|
+
if (selection !== void 0 && selection[index] !== 1)
|
|
298
|
+
continue;
|
|
299
|
+
indices.push(index);
|
|
300
|
+
}
|
|
301
|
+
return indices;
|
|
302
|
+
}
|
|
303
|
+
function enforceMaxRightRows(actual, limit) {
|
|
304
|
+
if (actual <= limit)
|
|
305
|
+
return;
|
|
306
|
+
throw new LakeqlError("LAKEQL_BUDGET_EXCEEDED", `Vector join exceeded maxRightRows (${actual} > ${limit})`, { metric: "maxRightRows", limit, actual });
|
|
307
|
+
}
|
|
308
|
+
function batchFromOutput(output) {
|
|
309
|
+
return batchFromColumns(output);
|
|
310
|
+
}
|
|
2
311
|
|
|
3
312
|
// ../iceberg/dist/index.js
|
|
4
|
-
var PACKAGE = "
|
|
313
|
+
var PACKAGE = "lakeql-iceberg";
|
|
5
314
|
var IcebergTable = class {
|
|
6
315
|
store;
|
|
7
316
|
metadataPath;
|
|
@@ -17,7 +326,7 @@ var IcebergTable = class {
|
|
|
17
326
|
if (options.ref !== void 0) {
|
|
18
327
|
const ref = this.metadata.refs?.[options.ref];
|
|
19
328
|
if (!ref) {
|
|
20
|
-
throw new
|
|
329
|
+
throw new LakeqlError("LAKEQL_CATALOG_ERROR", `Unknown Iceberg ref ${options.ref}`, {
|
|
21
330
|
ref: options.ref
|
|
22
331
|
});
|
|
23
332
|
}
|
|
@@ -26,7 +335,7 @@ var IcebergTable = class {
|
|
|
26
335
|
if (options.asOfTimestampMs !== void 0) {
|
|
27
336
|
const snapshot = [...this.metadata.snapshots].filter((candidate) => candidate["timestamp-ms"] <= options.asOfTimestampMs).sort((a, b) => b["timestamp-ms"] - a["timestamp-ms"])[0];
|
|
28
337
|
if (!snapshot) {
|
|
29
|
-
throw new
|
|
338
|
+
throw new LakeqlError("LAKEQL_CATALOG_ERROR", "No Iceberg snapshot at requested timestamp", {
|
|
30
339
|
asOfTimestampMs: options.asOfTimestampMs
|
|
31
340
|
});
|
|
32
341
|
}
|
|
@@ -37,7 +346,9 @@ var IcebergTable = class {
|
|
|
37
346
|
schema(schemaId) {
|
|
38
347
|
const schema = this.metadata.schemas.find((candidate) => candidate["schema-id"] === schemaId);
|
|
39
348
|
if (!schema) {
|
|
40
|
-
throw new
|
|
349
|
+
throw new LakeqlError("LAKEQL_CATALOG_ERROR", `Unknown Iceberg schema ${schemaId}`, {
|
|
350
|
+
schemaId
|
|
351
|
+
});
|
|
41
352
|
}
|
|
42
353
|
return schema.fields;
|
|
43
354
|
}
|
|
@@ -81,7 +392,7 @@ var IcebergTable = class {
|
|
|
81
392
|
const supportedDeleteFiles = supportedIcebergDeleteFiles(file.deleteFiles);
|
|
82
393
|
const unsupportedDeleteFiles = unsupportedIcebergDeleteFiles(file.deleteFiles);
|
|
83
394
|
if (unsupportedDeleteFiles.length > 0 && readMode === "strict") {
|
|
84
|
-
throw new
|
|
395
|
+
throw new LakeqlError("LAKEQL_UNSUPPORTED_DELETE_FILES", "Snapshot contains delete files unsupported by strict Iceberg planning", {
|
|
85
396
|
path: file.path,
|
|
86
397
|
deleteFiles: file.deleteFiles,
|
|
87
398
|
supportedDeleteFiles,
|
|
@@ -125,10 +436,10 @@ var IcebergTable = class {
|
|
|
125
436
|
}
|
|
126
437
|
async appendFiles(options) {
|
|
127
438
|
if (options.files.length === 0) {
|
|
128
|
-
throw new
|
|
439
|
+
throw new LakeqlError("LAKEQL_VALIDATION_ERROR", "Iceberg append requires at least one file");
|
|
129
440
|
}
|
|
130
441
|
if (this.metadata["format-version"] !== 2) {
|
|
131
|
-
throw new
|
|
442
|
+
throw new LakeqlError("LAKEQL_VALIDATION_ERROR", "Iceberg append requires format-version 2 metadata", { formatVersion: this.metadata["format-version"] });
|
|
132
443
|
}
|
|
133
444
|
const currentSnapshot = this.snapshot();
|
|
134
445
|
const nextSnapshotId = options.nextSnapshotId ?? randomSnapshotId(this.metadata.snapshots.map(snapshotIdOf));
|
|
@@ -172,7 +483,7 @@ var IcebergTable = class {
|
|
|
172
483
|
});
|
|
173
484
|
const committed = typeof commit === "boolean" ? commit : commit.committed;
|
|
174
485
|
if (!committed) {
|
|
175
|
-
throw new
|
|
486
|
+
throw new LakeqlError("LAKEQL_ICEBERG_COMMIT_CONFLICT", "Iceberg append commit conflict", {
|
|
176
487
|
metadataPath: this.metadataPath,
|
|
177
488
|
expectedSnapshotId: currentSnapshot["snapshot-id"],
|
|
178
489
|
nextSnapshotId
|
|
@@ -197,7 +508,7 @@ var IcebergTable = class {
|
|
|
197
508
|
async appendOutputManifest(options) {
|
|
198
509
|
const files = options.manifest.entries.map((entry) => {
|
|
199
510
|
if (entry.iceberg === void 0) {
|
|
200
|
-
throw new
|
|
511
|
+
throw new LakeqlError("LAKEQL_VALIDATION_ERROR", "Output manifest entry is missing Iceberg file metadata", {
|
|
201
512
|
taskId: entry.taskId,
|
|
202
513
|
outputPath: entry.outputPath
|
|
203
514
|
});
|
|
@@ -220,7 +531,7 @@ var IcebergTable = class {
|
|
|
220
531
|
snapshotById(snapshotId) {
|
|
221
532
|
const snapshot = this.metadata.snapshots.find((candidate) => candidate["snapshot-id"] === snapshotId);
|
|
222
533
|
if (!snapshot) {
|
|
223
|
-
throw new
|
|
534
|
+
throw new LakeqlError("LAKEQL_CATALOG_ERROR", `Unknown Iceberg snapshot ${snapshotId}`, {
|
|
224
535
|
snapshotId
|
|
225
536
|
});
|
|
226
537
|
}
|
|
@@ -241,11 +552,11 @@ function planFiles(table, options = {}) {
|
|
|
241
552
|
var ObjectStoreIcebergCommitCatalog = class {
|
|
242
553
|
async commitAppend(input) {
|
|
243
554
|
if (!supportsConditionalPut(input.store)) {
|
|
244
|
-
throw new
|
|
555
|
+
throw new LakeqlError("LAKEQL_CATALOG_ERROR", "Object-store Iceberg append requires conditional put support", { metadataPath: input.currentMetadataPath });
|
|
245
556
|
}
|
|
246
557
|
const currentBytes = await input.store.get(input.currentMetadataPath);
|
|
247
558
|
if (!currentBytes) {
|
|
248
|
-
throw new
|
|
559
|
+
throw new LakeqlError("LAKEQL_OBJECT_NOT_FOUND", `No object at ${input.currentMetadataPath}`, {
|
|
249
560
|
path: input.currentMetadataPath
|
|
250
561
|
});
|
|
251
562
|
}
|
|
@@ -284,7 +595,7 @@ var IcebergRestCatalog = class {
|
|
|
284
595
|
async loadTable(store) {
|
|
285
596
|
const response = await this.requestJson(this.tableUrl(), { method: "GET" });
|
|
286
597
|
if (!isRecord(response) || typeof response["metadata-location"] !== "string") {
|
|
287
|
-
throw new
|
|
598
|
+
throw new LakeqlError("LAKEQL_CATALOG_ERROR", "Invalid Iceberg REST load table response", {
|
|
288
599
|
url: this.tableUrl()
|
|
289
600
|
});
|
|
290
601
|
}
|
|
@@ -329,7 +640,7 @@ var IcebergRestCatalog = class {
|
|
|
329
640
|
if (response.status === 409)
|
|
330
641
|
return { committed: false };
|
|
331
642
|
if (!response.ok) {
|
|
332
|
-
throw new
|
|
643
|
+
throw new LakeqlError("LAKEQL_CATALOG_ERROR", "Iceberg REST table commit failed", {
|
|
333
644
|
url: this.tableUrl(),
|
|
334
645
|
status: response.status,
|
|
335
646
|
statusText: response.statusText
|
|
@@ -347,7 +658,7 @@ var IcebergRestCatalog = class {
|
|
|
347
658
|
headers: this.headers(init.body !== void 0)
|
|
348
659
|
});
|
|
349
660
|
if (!response.ok) {
|
|
350
|
-
throw new
|
|
661
|
+
throw new LakeqlError("LAKEQL_CATALOG_ERROR", "Iceberg REST catalog request failed", {
|
|
351
662
|
url,
|
|
352
663
|
status: response.status,
|
|
353
664
|
statusText: response.statusText
|
|
@@ -356,7 +667,7 @@ var IcebergRestCatalog = class {
|
|
|
356
667
|
try {
|
|
357
668
|
return await response.json();
|
|
358
669
|
} catch (cause) {
|
|
359
|
-
throw new
|
|
670
|
+
throw new LakeqlError("LAKEQL_CATALOG_ERROR", "Iceberg REST catalog response is not JSON", {
|
|
360
671
|
url,
|
|
361
672
|
cause
|
|
362
673
|
});
|
|
@@ -402,7 +713,7 @@ var IcebergUnsupportedCatalog = class {
|
|
|
402
713
|
throw this.unsupported("commitAppend");
|
|
403
714
|
}
|
|
404
715
|
unsupported(operation) {
|
|
405
|
-
return new
|
|
716
|
+
return new LakeqlError("LAKEQL_CATALOG_ERROR", `${this.catalog} Iceberg catalog is not implemented`, {
|
|
406
717
|
catalog: this.catalog,
|
|
407
718
|
namespace: this.namespace,
|
|
408
719
|
table: this.table,
|
|
@@ -425,7 +736,7 @@ async function loadIcebergTable(options) {
|
|
|
425
736
|
const store = withObjectStoreReadControls(options.store, readControls);
|
|
426
737
|
const bytes = await store.get(options.metadataPath);
|
|
427
738
|
if (!bytes) {
|
|
428
|
-
throw new
|
|
739
|
+
throw new LakeqlError("LAKEQL_OBJECT_NOT_FOUND", `No object at ${options.metadataPath}`, {
|
|
429
740
|
path: options.metadataPath
|
|
430
741
|
});
|
|
431
742
|
}
|
|
@@ -434,9 +745,9 @@ async function loadIcebergTable(options) {
|
|
|
434
745
|
try {
|
|
435
746
|
return new IcebergTable(store, options.metadataPath, await hydrateMetadataManifests(store, validateMetadata(JSON.parse(text)), readControls));
|
|
436
747
|
} catch (cause) {
|
|
437
|
-
if (cause instanceof
|
|
748
|
+
if (cause instanceof LakeqlError)
|
|
438
749
|
throw cause;
|
|
439
|
-
throw new
|
|
750
|
+
throw new LakeqlError("LAKEQL_CATALOG_ERROR", `Invalid Iceberg metadata at ${options.metadataPath}`, {
|
|
440
751
|
path: options.metadataPath,
|
|
441
752
|
cause
|
|
442
753
|
});
|
|
@@ -482,7 +793,7 @@ function applyIcebergDeletes(options) {
|
|
|
482
793
|
const equalityDeleteKeys = /* @__PURE__ */ new Map();
|
|
483
794
|
for (const deletion of options.equalityDeletes ?? []) {
|
|
484
795
|
if (deletion.columns.length === 0) {
|
|
485
|
-
throw new
|
|
796
|
+
throw new LakeqlError("LAKEQL_VALIDATION_ERROR", "Iceberg equality delete requires columns");
|
|
486
797
|
}
|
|
487
798
|
const columnsKey = stableStringify(deletion.columns);
|
|
488
799
|
let keys = equalityDeleteKeys.get(columnsKey);
|
|
@@ -566,7 +877,7 @@ function isAsyncIterable(value) {
|
|
|
566
877
|
}
|
|
567
878
|
function validateDeletePosition(position, path) {
|
|
568
879
|
if (!Number.isInteger(position) || position < 0) {
|
|
569
|
-
throw new
|
|
880
|
+
throw new LakeqlError("LAKEQL_VALIDATION_ERROR", "Iceberg delete position must be non-negative", {
|
|
570
881
|
path,
|
|
571
882
|
position
|
|
572
883
|
});
|
|
@@ -585,14 +896,14 @@ function randomSnapshotId(existingIds) {
|
|
|
585
896
|
if (!existing.has(id))
|
|
586
897
|
return id;
|
|
587
898
|
}
|
|
588
|
-
throw new
|
|
899
|
+
throw new LakeqlError("LAKEQL_CATALOG_ERROR", "Unable to allocate unique Iceberg snapshot id");
|
|
589
900
|
}
|
|
590
901
|
function validateNewSnapshotId(snapshotId, snapshots) {
|
|
591
902
|
if (!Number.isSafeInteger(snapshotId) || snapshotId <= 0) {
|
|
592
|
-
throw new
|
|
903
|
+
throw new LakeqlError("LAKEQL_VALIDATION_ERROR", "Iceberg snapshot id must be a positive safe integer", { snapshotId });
|
|
593
904
|
}
|
|
594
905
|
if (snapshots.some((snapshot) => snapshotIdOf(snapshot) === snapshotId)) {
|
|
595
|
-
throw new
|
|
906
|
+
throw new LakeqlError("LAKEQL_VALIDATION_ERROR", "Iceberg snapshot id already exists", {
|
|
596
907
|
snapshotId
|
|
597
908
|
});
|
|
598
909
|
}
|
|
@@ -656,14 +967,16 @@ function publicDeleteFile(deleteFile) {
|
|
|
656
967
|
async function readManifestList(store, path) {
|
|
657
968
|
const bytes = await store.get(path);
|
|
658
969
|
if (!bytes) {
|
|
659
|
-
throw new
|
|
970
|
+
throw new LakeqlError("LAKEQL_OBJECT_NOT_FOUND", `No Iceberg manifest list at ${path}`, {
|
|
971
|
+
path
|
|
972
|
+
});
|
|
660
973
|
}
|
|
661
974
|
try {
|
|
662
975
|
return avroObjectContainer(bytes) ? validateAvroManifestList(await decodeAvroObjectContainer(bytes), path) : validateManifestList(JSON.parse(new TextDecoder().decode(bytes)), path);
|
|
663
976
|
} catch (cause) {
|
|
664
|
-
if (cause instanceof
|
|
977
|
+
if (cause instanceof LakeqlError)
|
|
665
978
|
throw cause;
|
|
666
|
-
throw new
|
|
979
|
+
throw new LakeqlError("LAKEQL_CATALOG_ERROR", `Invalid Iceberg manifest list at ${path}`, {
|
|
667
980
|
path,
|
|
668
981
|
cause
|
|
669
982
|
});
|
|
@@ -672,15 +985,15 @@ async function readManifestList(store, path) {
|
|
|
672
985
|
async function readManifest(store, path, tablePrefix = "") {
|
|
673
986
|
const bytes = await store.get(path);
|
|
674
987
|
if (!bytes) {
|
|
675
|
-
throw new
|
|
988
|
+
throw new LakeqlError("LAKEQL_OBJECT_NOT_FOUND", `No Iceberg manifest at ${path}`, { path });
|
|
676
989
|
}
|
|
677
990
|
try {
|
|
678
991
|
const manifest = avroObjectContainer(bytes) ? validateAvroManifest(await decodeAvroObjectContainer(bytes), path) : validateManifest(JSON.parse(new TextDecoder().decode(bytes)), path);
|
|
679
992
|
return validateManifestPaths(manifest, path, tablePrefix);
|
|
680
993
|
} catch (cause) {
|
|
681
|
-
if (cause instanceof
|
|
994
|
+
if (cause instanceof LakeqlError)
|
|
682
995
|
throw cause;
|
|
683
|
-
throw new
|
|
996
|
+
throw new LakeqlError("LAKEQL_CATALOG_ERROR", `Invalid Iceberg manifest at ${path}`, {
|
|
684
997
|
path,
|
|
685
998
|
cause
|
|
686
999
|
});
|
|
@@ -689,7 +1002,7 @@ async function readManifest(store, path, tablePrefix = "") {
|
|
|
689
1002
|
function validateAvroManifestList(records, path) {
|
|
690
1003
|
return records.map((record) => {
|
|
691
1004
|
if (!isRecord(record) || typeof record.manifest_path !== "string") {
|
|
692
|
-
throw new
|
|
1005
|
+
throw new LakeqlError("LAKEQL_CATALOG_ERROR", "Iceberg Avro manifest list entry is invalid", {
|
|
693
1006
|
path
|
|
694
1007
|
});
|
|
695
1008
|
}
|
|
@@ -702,7 +1015,7 @@ function validateAvroManifest(records, path) {
|
|
|
702
1015
|
const deleteFiles = [];
|
|
703
1016
|
for (const record of records) {
|
|
704
1017
|
if (!isRecord(record)) {
|
|
705
|
-
throw new
|
|
1018
|
+
throw new LakeqlError("LAKEQL_CATALOG_ERROR", "Iceberg Avro manifest entry is invalid", {
|
|
706
1019
|
path
|
|
707
1020
|
});
|
|
708
1021
|
}
|
|
@@ -710,14 +1023,14 @@ function validateAvroManifest(records, path) {
|
|
|
710
1023
|
continue;
|
|
711
1024
|
const dataFile = record.data_file;
|
|
712
1025
|
if (!isRecord(dataFile)) {
|
|
713
|
-
throw new
|
|
1026
|
+
throw new LakeqlError("LAKEQL_CATALOG_ERROR", "Iceberg Avro manifest entry is missing data_file", {
|
|
714
1027
|
path
|
|
715
1028
|
});
|
|
716
1029
|
}
|
|
717
1030
|
const content = typeof dataFile.content === "number" ? dataFile.content : 0;
|
|
718
1031
|
const recordCount = safeAvroNumber(dataFile.record_count);
|
|
719
1032
|
if (typeof dataFile.file_path !== "string" || recordCount === void 0) {
|
|
720
|
-
throw new
|
|
1033
|
+
throw new LakeqlError("LAKEQL_CATALOG_ERROR", "Iceberg Avro data file has invalid fields", {
|
|
721
1034
|
path
|
|
722
1035
|
});
|
|
723
1036
|
}
|
|
@@ -819,7 +1132,7 @@ async function loadAvro() {
|
|
|
819
1132
|
function validateManifestList(value, path) {
|
|
820
1133
|
const manifests = Array.isArray(value) ? value : isRecord(value) && Array.isArray(value.manifests) ? value.manifests : void 0;
|
|
821
1134
|
if (manifests === void 0) {
|
|
822
|
-
throw new
|
|
1135
|
+
throw new LakeqlError("LAKEQL_CATALOG_ERROR", "Iceberg manifest list has invalid required fields", {
|
|
823
1136
|
path
|
|
824
1137
|
});
|
|
825
1138
|
}
|
|
@@ -827,7 +1140,7 @@ function validateManifestList(value, path) {
|
|
|
827
1140
|
}
|
|
828
1141
|
function validateManifest(value, path) {
|
|
829
1142
|
if (!isRecord(value) || typeof value.path !== "string" || !Array.isArray(value.files)) {
|
|
830
|
-
throw new
|
|
1143
|
+
throw new LakeqlError("LAKEQL_CATALOG_ERROR", "Iceberg manifest has invalid required fields", {
|
|
831
1144
|
path
|
|
832
1145
|
});
|
|
833
1146
|
}
|
|
@@ -835,7 +1148,9 @@ function validateManifest(value, path) {
|
|
|
835
1148
|
}
|
|
836
1149
|
function validateManifestReference(value, path) {
|
|
837
1150
|
if (!isRecord(value) || typeof value.path !== "string") {
|
|
838
|
-
throw new
|
|
1151
|
+
throw new LakeqlError("LAKEQL_CATALOG_ERROR", "Iceberg manifest list entry is invalid", {
|
|
1152
|
+
path
|
|
1153
|
+
});
|
|
839
1154
|
}
|
|
840
1155
|
validateManifestContent(value.content, path);
|
|
841
1156
|
if (Array.isArray(value.files))
|
|
@@ -847,7 +1162,7 @@ function validateManifestContent(content, path) {
|
|
|
847
1162
|
return;
|
|
848
1163
|
if (content === 0 || content === 1 || content === "data" || content === "deletes")
|
|
849
1164
|
return;
|
|
850
|
-
throw new
|
|
1165
|
+
throw new LakeqlError("LAKEQL_UNSUPPORTED_ICEBERG_FEATURE", "Iceberg manifest list contains an unsupported manifest content type", {
|
|
851
1166
|
path,
|
|
852
1167
|
content
|
|
853
1168
|
});
|
|
@@ -867,7 +1182,7 @@ function validateManifestPaths(manifest, path, tablePrefix = "") {
|
|
|
867
1182
|
}
|
|
868
1183
|
function validateManifestSourcedPath(path, tablePrefix = "") {
|
|
869
1184
|
if (/^(?:[a-z][a-z0-9+.-]*:)?\/\//iu.test(path) || path.startsWith("/")) {
|
|
870
|
-
throw new
|
|
1185
|
+
throw new LakeqlError("LAKEQL_VALIDATION_ERROR", `Iceberg manifest path must be relative: ${path}`, {
|
|
871
1186
|
path
|
|
872
1187
|
});
|
|
873
1188
|
}
|
|
@@ -876,18 +1191,18 @@ function validateManifestSourcedPath(path, tablePrefix = "") {
|
|
|
876
1191
|
try {
|
|
877
1192
|
decoded = decodeURIComponent(segment);
|
|
878
1193
|
} catch {
|
|
879
|
-
throw new
|
|
1194
|
+
throw new LakeqlError("LAKEQL_VALIDATION_ERROR", `Iceberg manifest path is invalid: ${path}`, {
|
|
880
1195
|
path
|
|
881
1196
|
});
|
|
882
1197
|
}
|
|
883
1198
|
if (decoded === "." || decoded === "..") {
|
|
884
|
-
throw new
|
|
1199
|
+
throw new LakeqlError("LAKEQL_VALIDATION_ERROR", `Iceberg manifest path contains traversal: ${path}`, {
|
|
885
1200
|
path
|
|
886
1201
|
});
|
|
887
1202
|
}
|
|
888
1203
|
}
|
|
889
1204
|
if (tablePrefix !== "" && path !== tablePrefix && !path.startsWith(`${tablePrefix}/`)) {
|
|
890
|
-
throw new
|
|
1205
|
+
throw new LakeqlError("LAKEQL_VALIDATION_ERROR", `Iceberg manifest path escapes table location: ${path}`, {
|
|
891
1206
|
path,
|
|
892
1207
|
tableLocation: tablePrefix
|
|
893
1208
|
});
|
|
@@ -915,7 +1230,7 @@ async function readVersionHint(store, path, controls = {}) {
|
|
|
915
1230
|
const text = new TextDecoder().decode(bytes).trim();
|
|
916
1231
|
const version = Number(text);
|
|
917
1232
|
if (!Number.isInteger(version) || version < 0) {
|
|
918
|
-
throw new
|
|
1233
|
+
throw new LakeqlError("LAKEQL_CATALOG_ERROR", "Invalid Iceberg version hint", {
|
|
919
1234
|
path,
|
|
920
1235
|
versionHint: text
|
|
921
1236
|
});
|
|
@@ -937,7 +1252,7 @@ async function latestMetadataPathFromList(store, metadataPrefix, controls = {})
|
|
|
937
1252
|
latest = { path: object.path, version };
|
|
938
1253
|
}
|
|
939
1254
|
if (latest === void 0) {
|
|
940
|
-
throw new
|
|
1255
|
+
throw new LakeqlError("LAKEQL_OBJECT_NOT_FOUND", "No Iceberg metadata files found", {
|
|
941
1256
|
prefix: metadataPrefix
|
|
942
1257
|
});
|
|
943
1258
|
}
|
|
@@ -957,7 +1272,7 @@ function namespaceParts(namespace) {
|
|
|
957
1272
|
const parts = Array.isArray(namespace) ? namespace : namespace.split(".");
|
|
958
1273
|
const out = parts.map((part) => requiredNonEmptyString(part, "namespace"));
|
|
959
1274
|
if (out.length === 0) {
|
|
960
|
-
throw new
|
|
1275
|
+
throw new LakeqlError("LAKEQL_VALIDATION_ERROR", "Iceberg REST namespace is required");
|
|
961
1276
|
}
|
|
962
1277
|
return out;
|
|
963
1278
|
}
|
|
@@ -969,7 +1284,7 @@ function catalogPrefixParts(prefix) {
|
|
|
969
1284
|
function requiredNonEmptyString(value, field) {
|
|
970
1285
|
const trimmed = value.trim();
|
|
971
1286
|
if (trimmed.length === 0) {
|
|
972
|
-
throw new
|
|
1287
|
+
throw new LakeqlError("LAKEQL_VALIDATION_ERROR", `Iceberg REST ${field} is required`);
|
|
973
1288
|
}
|
|
974
1289
|
return trimmed;
|
|
975
1290
|
}
|
|
@@ -989,7 +1304,7 @@ async function commitResponseMetadataPath(response) {
|
|
|
989
1304
|
function restAppendSnapshot(input) {
|
|
990
1305
|
const snapshot = input.metadata.snapshots.at(-1);
|
|
991
1306
|
if (snapshot === void 0) {
|
|
992
|
-
throw new
|
|
1307
|
+
throw new LakeqlError("LAKEQL_CATALOG_ERROR", "Iceberg append metadata is missing next snapshot");
|
|
993
1308
|
}
|
|
994
1309
|
return {
|
|
995
1310
|
"snapshot-id": snapshot["snapshot-id"],
|
|
@@ -1007,7 +1322,7 @@ function restAppendSnapshot(input) {
|
|
|
1007
1322
|
function equalityKey(row, columns) {
|
|
1008
1323
|
return stableStringify(columns.map((column) => {
|
|
1009
1324
|
if (!(column in row)) {
|
|
1010
|
-
throw new
|
|
1325
|
+
throw new LakeqlError("LAKEQL_UNKNOWN_COLUMN", `Unknown Iceberg equality delete column ${column}`, {
|
|
1011
1326
|
column
|
|
1012
1327
|
});
|
|
1013
1328
|
}
|
|
@@ -1129,28 +1444,28 @@ function sortStringRecord(record) {
|
|
|
1129
1444
|
}
|
|
1130
1445
|
function validateListTablesResponse(value) {
|
|
1131
1446
|
if (!isRecord(value) || !Array.isArray(value.identifiers)) {
|
|
1132
|
-
throw new
|
|
1447
|
+
throw new LakeqlError("LAKEQL_CATALOG_ERROR", "Invalid Iceberg REST list tables response");
|
|
1133
1448
|
}
|
|
1134
1449
|
return value.identifiers.map((identifier) => {
|
|
1135
1450
|
if (!isRecord(identifier) || !Array.isArray(identifier.namespace) || !identifier.namespace.every((part) => typeof part === "string") || typeof identifier.name !== "string") {
|
|
1136
|
-
throw new
|
|
1451
|
+
throw new LakeqlError("LAKEQL_CATALOG_ERROR", "Invalid Iceberg REST table identifier");
|
|
1137
1452
|
}
|
|
1138
1453
|
return { namespace: identifier.namespace, name: identifier.name };
|
|
1139
1454
|
});
|
|
1140
1455
|
}
|
|
1141
1456
|
function validateMetadata(value) {
|
|
1142
1457
|
if (!isRecord(value))
|
|
1143
|
-
throw new
|
|
1458
|
+
throw new LakeqlError("LAKEQL_CATALOG_ERROR", "Iceberg metadata must be an object");
|
|
1144
1459
|
if (value["format-version"] !== 1 && value["format-version"] !== 2) {
|
|
1145
|
-
throw new
|
|
1460
|
+
throw new LakeqlError("LAKEQL_CATALOG_ERROR", "Only Iceberg format-version 1 and 2 metadata is supported for reads", {
|
|
1146
1461
|
formatVersion: value["format-version"]
|
|
1147
1462
|
});
|
|
1148
1463
|
}
|
|
1149
1464
|
if (!Array.isArray(value.snapshots) || !Array.isArray(value.schemas)) {
|
|
1150
|
-
throw new
|
|
1465
|
+
throw new LakeqlError("LAKEQL_CATALOG_ERROR", "Iceberg metadata is missing snapshots or schemas");
|
|
1151
1466
|
}
|
|
1152
1467
|
if (!isMetadataFile(value)) {
|
|
1153
|
-
throw new
|
|
1468
|
+
throw new LakeqlError("LAKEQL_CATALOG_ERROR", "Iceberg metadata has invalid required fields");
|
|
1154
1469
|
}
|
|
1155
1470
|
rejectUnsupportedMetadataFeatures(value);
|
|
1156
1471
|
return value;
|
|
@@ -1165,7 +1480,7 @@ function rejectAdvertisedFeatureFlags(metadata) {
|
|
|
1165
1480
|
const features = metadata[key];
|
|
1166
1481
|
if (features === void 0 || Array.isArray(features) && features.length === 0)
|
|
1167
1482
|
continue;
|
|
1168
|
-
throw new
|
|
1483
|
+
throw new LakeqlError("LAKEQL_UNSUPPORTED_ICEBERG_FEATURE", "Iceberg metadata advertises unsupported table-format features", {
|
|
1169
1484
|
featureProperty: key,
|
|
1170
1485
|
features
|
|
1171
1486
|
});
|
|
@@ -1175,18 +1490,18 @@ function rejectUnsupportedPartitionTransforms(partitionSpecs) {
|
|
|
1175
1490
|
if (partitionSpecs === void 0)
|
|
1176
1491
|
return;
|
|
1177
1492
|
if (!Array.isArray(partitionSpecs)) {
|
|
1178
|
-
throw new
|
|
1493
|
+
throw new LakeqlError("LAKEQL_CATALOG_ERROR", "Iceberg partition-specs must be an array");
|
|
1179
1494
|
}
|
|
1180
1495
|
for (const spec of partitionSpecs) {
|
|
1181
1496
|
if (!isRecord(spec) || !Array.isArray(spec.fields)) {
|
|
1182
|
-
throw new
|
|
1497
|
+
throw new LakeqlError("LAKEQL_CATALOG_ERROR", "Iceberg partition spec is invalid");
|
|
1183
1498
|
}
|
|
1184
1499
|
for (const field of spec.fields) {
|
|
1185
1500
|
if (!isRecord(field) || typeof field.transform !== "string") {
|
|
1186
|
-
throw new
|
|
1501
|
+
throw new LakeqlError("LAKEQL_CATALOG_ERROR", "Iceberg partition field is invalid");
|
|
1187
1502
|
}
|
|
1188
1503
|
if (field.transform !== "identity" && field.transform !== "void") {
|
|
1189
|
-
throw new
|
|
1504
|
+
throw new LakeqlError("LAKEQL_UNSUPPORTED_ICEBERG_FEATURE", "Iceberg partition transform is not supported for strict planning", {
|
|
1190
1505
|
specId: spec["spec-id"],
|
|
1191
1506
|
fieldName: field.name,
|
|
1192
1507
|
transform: field.transform
|
|
@@ -1199,14 +1514,14 @@ function rejectUnsupportedSortOrders(sortOrders) {
|
|
|
1199
1514
|
if (sortOrders === void 0)
|
|
1200
1515
|
return;
|
|
1201
1516
|
if (!Array.isArray(sortOrders)) {
|
|
1202
|
-
throw new
|
|
1517
|
+
throw new LakeqlError("LAKEQL_CATALOG_ERROR", "Iceberg sort-orders must be an array");
|
|
1203
1518
|
}
|
|
1204
1519
|
for (const order of sortOrders) {
|
|
1205
1520
|
if (!isRecord(order) || !Array.isArray(order.fields)) {
|
|
1206
|
-
throw new
|
|
1521
|
+
throw new LakeqlError("LAKEQL_CATALOG_ERROR", "Iceberg sort order is invalid");
|
|
1207
1522
|
}
|
|
1208
1523
|
if (order.fields.length > 0) {
|
|
1209
|
-
throw new
|
|
1524
|
+
throw new LakeqlError("LAKEQL_UNSUPPORTED_ICEBERG_FEATURE", "Iceberg sorted table metadata is not supported for strict planning", {
|
|
1210
1525
|
orderId: order["order-id"],
|
|
1211
1526
|
fields: order.fields
|
|
1212
1527
|
});
|
|
@@ -1224,7 +1539,7 @@ function projectedIds(fields, select) {
|
|
|
1224
1539
|
return select.map((name) => {
|
|
1225
1540
|
const field = fields.find((candidate) => candidate.name === name);
|
|
1226
1541
|
if (!field) {
|
|
1227
|
-
throw new
|
|
1542
|
+
throw new LakeqlError("LAKEQL_UNKNOWN_COLUMN", `Unknown Iceberg column ${name}`, {
|
|
1228
1543
|
column: name
|
|
1229
1544
|
});
|
|
1230
1545
|
}
|
|
@@ -1241,7 +1556,7 @@ function partitionMayMatch(expr, partition) {
|
|
|
1241
1556
|
try {
|
|
1242
1557
|
return matches(expr, partition);
|
|
1243
1558
|
} catch (cause) {
|
|
1244
|
-
if (cause instanceof
|
|
1559
|
+
if (cause instanceof LakeqlError && cause.code === "LAKEQL_TYPE_ERROR")
|
|
1245
1560
|
return true;
|
|
1246
1561
|
throw cause;
|
|
1247
1562
|
}
|
|
@@ -1376,4 +1691,4 @@ async function* projectIcebergParquetBatches(store, table, path, partition, snap
|
|
|
1376
1691
|
}
|
|
1377
1692
|
}
|
|
1378
1693
|
|
|
1379
|
-
export { IcebergRestCatalog, IcebergTable, IcebergUnsupportedCatalog, ObjectStoreIcebergCommitCatalog, PACKAGE, applyIcebergDeletes, icebergGlueCatalog, icebergNessieCatalog, icebergRestCatalog, loadIcebergTable, loadIcebergTableFromObjectStore, loadIcebergTableFromRest, loadTable, planFiles2 as planFiles, scanBatches, scanPlannedIcebergRows, scanRows };
|
|
1694
|
+
export { IcebergRestCatalog, IcebergTable, IcebergUnsupportedCatalog, InMemoryRowsScanner, InMemoryRowsStore, ObjectStoreIcebergCommitCatalog, PACKAGE, applyIcebergDeletes, createInMemoryLake, icebergGlueCatalog, icebergNessieCatalog, icebergRestCatalog, inMemoryRowsScanner, loadIcebergTable, loadIcebergTableFromObjectStore, loadIcebergTableFromRest, loadTable, planFiles2 as planFiles, scanBatches, scanPlannedIcebergRows, scanRows, vectorHashJoin };
|