udbx4ts 0.3.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.
- package/README.md +250 -0
- package/dist/UdbxDataSource-dOqTLN6v.d.cts +387 -0
- package/dist/UdbxDataSource-dOqTLN6v.d.ts +387 -0
- package/dist/index.cjs +3101 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +151 -0
- package/dist/index.d.ts +151 -0
- package/dist/index.js +3009 -0
- package/dist/index.js.map +1 -0
- package/dist/runtime-browser/index.cjs +4101 -0
- package/dist/runtime-browser/index.cjs.map +1 -0
- package/dist/runtime-browser/index.d.cts +242 -0
- package/dist/runtime-browser/index.d.ts +242 -0
- package/dist/runtime-browser/index.js +4047 -0
- package/dist/runtime-browser/index.js.map +1 -0
- package/dist/runtime-electron/index.cjs +2962 -0
- package/dist/runtime-electron/index.cjs.map +1 -0
- package/dist/runtime-electron/index.d.cts +20 -0
- package/dist/runtime-electron/index.d.ts +20 -0
- package/dist/runtime-electron/index.js +2926 -0
- package/dist/runtime-electron/index.js.map +1 -0
- package/package.json +64 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,3101 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
9
|
+
var __export = (target, all) => {
|
|
10
|
+
for (var name in all)
|
|
11
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
12
|
+
};
|
|
13
|
+
var __copyProps = (to, from, except, desc) => {
|
|
14
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
15
|
+
for (let key of __getOwnPropNames(from))
|
|
16
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
17
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
18
|
+
}
|
|
19
|
+
return to;
|
|
20
|
+
};
|
|
21
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
22
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
23
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
24
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
25
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
26
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
27
|
+
mod
|
|
28
|
+
));
|
|
29
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
30
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
31
|
+
|
|
32
|
+
// src/index.ts
|
|
33
|
+
var src_exports = {};
|
|
34
|
+
__export(src_exports, {
|
|
35
|
+
BaseDataset: () => BaseDataset,
|
|
36
|
+
BinaryCursor: () => BinaryCursor,
|
|
37
|
+
BinaryWriter: () => BinaryWriter,
|
|
38
|
+
CadDataset: () => CadDataset,
|
|
39
|
+
GAIA_BYTE_ORDER_LE: () => GAIA_BYTE_ORDER_LE,
|
|
40
|
+
GAIA_END: () => GAIA_END,
|
|
41
|
+
GAIA_GEOMETRY_DATA_OFFSET: () => GAIA_GEOMETRY_DATA_OFFSET,
|
|
42
|
+
GAIA_MBR: () => GAIA_MBR,
|
|
43
|
+
GAIA_START: () => GAIA_START,
|
|
44
|
+
GEO_TYPE_MULTILINESTRING: () => GEO_TYPE_MULTILINESTRING,
|
|
45
|
+
GEO_TYPE_MULTILINESTRINGZ: () => GEO_TYPE_MULTILINESTRINGZ,
|
|
46
|
+
GEO_TYPE_MULTIPOLYGON: () => GEO_TYPE_MULTIPOLYGON,
|
|
47
|
+
GEO_TYPE_MULTIPOLYGONZ: () => GEO_TYPE_MULTIPOLYGONZ,
|
|
48
|
+
GEO_TYPE_POINT: () => GEO_TYPE_POINT,
|
|
49
|
+
GEO_TYPE_POINTZ: () => GEO_TYPE_POINTZ,
|
|
50
|
+
GaiaError: () => GaiaError,
|
|
51
|
+
GaiaFormatError: () => GaiaFormatError,
|
|
52
|
+
GaiaGeoTypeMismatchError: () => GaiaGeoTypeMismatchError,
|
|
53
|
+
GaiaGeometryCodec: () => GaiaGeometryCodec,
|
|
54
|
+
GaiaLineCodec: () => GaiaLineCodec,
|
|
55
|
+
GaiaPointCodec: () => GaiaPointCodec,
|
|
56
|
+
GaiaPolygonCodec: () => GaiaPolygonCodec,
|
|
57
|
+
GaiaUnsupportedGeoTypeError: () => GaiaUnsupportedGeoTypeError,
|
|
58
|
+
JstsGeometryCodec: () => JstsGeometryCodec,
|
|
59
|
+
LineDataset: () => LineDataset,
|
|
60
|
+
LineZDataset: () => LineZDataset,
|
|
61
|
+
NotImplementedError: () => NotImplementedError,
|
|
62
|
+
PointDataset: () => PointDataset,
|
|
63
|
+
PointZDataset: () => PointZDataset,
|
|
64
|
+
RegionDataset: () => RegionDataset,
|
|
65
|
+
RegionZDataset: () => RegionZDataset,
|
|
66
|
+
SmFieldInfoRepository: () => SmFieldInfoRepository,
|
|
67
|
+
SmRegisterRepository: () => SmRegisterRepository,
|
|
68
|
+
TabularDataset: () => TabularDataset,
|
|
69
|
+
TextDataset: () => TextDataset,
|
|
70
|
+
UDBX_SCHEMA_STATEMENTS: () => UDBX_SCHEMA_STATEMENTS,
|
|
71
|
+
UDBX_SYSTEM_TABLES: () => UDBX_SYSTEM_TABLES,
|
|
72
|
+
UdbxConstraintError: () => UdbxConstraintError,
|
|
73
|
+
UdbxDataSource: () => UdbxDataSource,
|
|
74
|
+
UdbxError: () => UdbxError,
|
|
75
|
+
UdbxFormatError: () => UdbxFormatError,
|
|
76
|
+
UdbxIOError: () => UdbxIOError,
|
|
77
|
+
UdbxNotFoundError: () => UdbxNotFoundError,
|
|
78
|
+
UdbxSchemaInitializer: () => UdbxSchemaInitializer,
|
|
79
|
+
UdbxUnsupportedError: () => UdbxUnsupportedError,
|
|
80
|
+
createNotImplementedError: () => createNotImplementedError,
|
|
81
|
+
datasetKindToValue: () => datasetKindToValue,
|
|
82
|
+
datasetValueToKind: () => datasetValueToKind,
|
|
83
|
+
fieldTypeToValue: () => fieldTypeToValue,
|
|
84
|
+
fieldValueToType: () => fieldValueToType,
|
|
85
|
+
fromJsts: () => fromJsts,
|
|
86
|
+
readGaiaHeader: () => readGaiaHeader,
|
|
87
|
+
toJsts: () => toJsts,
|
|
88
|
+
toJstsMultiLineString: () => toJstsMultiLineString,
|
|
89
|
+
toJstsMultiPolygon: () => toJstsMultiPolygon,
|
|
90
|
+
toJstsPoint: () => toJstsPoint,
|
|
91
|
+
validateGaiaEnd: () => validateGaiaEnd,
|
|
92
|
+
writeGaiaHeader: () => writeGaiaHeader
|
|
93
|
+
});
|
|
94
|
+
module.exports = __toCommonJS(src_exports);
|
|
95
|
+
|
|
96
|
+
// src/core/sql/SqlHelpers.ts
|
|
97
|
+
async function queryAll(driver, sql, params) {
|
|
98
|
+
const statement = await driver.prepare(sql);
|
|
99
|
+
try {
|
|
100
|
+
if (params) {
|
|
101
|
+
await statement.bind(params);
|
|
102
|
+
}
|
|
103
|
+
const rows = [];
|
|
104
|
+
while (await statement.step()) {
|
|
105
|
+
rows.push(await statement.getRow());
|
|
106
|
+
}
|
|
107
|
+
return rows;
|
|
108
|
+
} finally {
|
|
109
|
+
await statement.finalize();
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
async function queryOne(driver, sql, params) {
|
|
113
|
+
const rows = await queryAll(driver, sql, params);
|
|
114
|
+
return rows[0] ?? null;
|
|
115
|
+
}
|
|
116
|
+
async function executeStatement(statement, params) {
|
|
117
|
+
try {
|
|
118
|
+
if (params) {
|
|
119
|
+
await statement.bind(params);
|
|
120
|
+
}
|
|
121
|
+
await statement.step();
|
|
122
|
+
} finally {
|
|
123
|
+
await statement.finalize();
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
async function executeSql(driver, sql, params) {
|
|
127
|
+
const statement = await driver.prepare(sql);
|
|
128
|
+
await executeStatement(statement, params);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// src/core/schema/UdbxTypeMappings.ts
|
|
132
|
+
var datasetKindToValueMap = {
|
|
133
|
+
tabular: 0,
|
|
134
|
+
point: 1,
|
|
135
|
+
line: 3,
|
|
136
|
+
region: 5,
|
|
137
|
+
pointZ: 101,
|
|
138
|
+
lineZ: 103,
|
|
139
|
+
regionZ: 105,
|
|
140
|
+
text: 7,
|
|
141
|
+
cad: 149
|
|
142
|
+
};
|
|
143
|
+
var datasetValueToKindMap = new Map(
|
|
144
|
+
Object.entries(datasetKindToValueMap).map(([kind, value]) => [
|
|
145
|
+
value,
|
|
146
|
+
kind
|
|
147
|
+
])
|
|
148
|
+
);
|
|
149
|
+
var fieldTypeToValueMap = {
|
|
150
|
+
boolean: 1,
|
|
151
|
+
byte: 2,
|
|
152
|
+
int16: 3,
|
|
153
|
+
int32: 4,
|
|
154
|
+
int64: 5,
|
|
155
|
+
single: 6,
|
|
156
|
+
double: 7,
|
|
157
|
+
date: 8,
|
|
158
|
+
binary: 9,
|
|
159
|
+
geometry: 10,
|
|
160
|
+
char: 11,
|
|
161
|
+
ntext: 127,
|
|
162
|
+
text: 128,
|
|
163
|
+
time: 16
|
|
164
|
+
};
|
|
165
|
+
var fieldValueToTypeMap = /* @__PURE__ */ new Map([
|
|
166
|
+
[1, "boolean"],
|
|
167
|
+
[2, "byte"],
|
|
168
|
+
[3, "int16"],
|
|
169
|
+
[4, "int32"],
|
|
170
|
+
[5, "int64"],
|
|
171
|
+
[6, "single"],
|
|
172
|
+
[7, "double"],
|
|
173
|
+
[8, "date"],
|
|
174
|
+
[9, "binary"],
|
|
175
|
+
[10, "geometry"],
|
|
176
|
+
[11, "char"],
|
|
177
|
+
[16, "time"],
|
|
178
|
+
[127, "ntext"],
|
|
179
|
+
[128, "text"]
|
|
180
|
+
]);
|
|
181
|
+
function datasetKindToValue(kind) {
|
|
182
|
+
return datasetKindToValueMap[kind];
|
|
183
|
+
}
|
|
184
|
+
function datasetValueToKind(value) {
|
|
185
|
+
const kind = datasetValueToKindMap.get(value);
|
|
186
|
+
if (!kind) {
|
|
187
|
+
throw new Error(`Unsupported SmDatasetType value: ${value}.`);
|
|
188
|
+
}
|
|
189
|
+
return kind;
|
|
190
|
+
}
|
|
191
|
+
function fieldTypeToValue(type) {
|
|
192
|
+
return fieldTypeToValueMap[type];
|
|
193
|
+
}
|
|
194
|
+
function fieldValueToType(value) {
|
|
195
|
+
const type = fieldValueToTypeMap.get(value);
|
|
196
|
+
if (!type) {
|
|
197
|
+
throw new Error(`Unsupported SmFieldType value: ${value}.`);
|
|
198
|
+
}
|
|
199
|
+
return type;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// src/core/schema/SmFieldInfoRepository.ts
|
|
203
|
+
function mapRow(row) {
|
|
204
|
+
return {
|
|
205
|
+
name: row.SmFieldName,
|
|
206
|
+
fieldType: fieldValueToType(row.SmFieldType),
|
|
207
|
+
nullable: row.SmFieldbRequired !== 1,
|
|
208
|
+
defaultValue: row.SmFieldDefaultValue ?? void 0
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
var SmFieldInfoRepository = class {
|
|
212
|
+
constructor(driver) {
|
|
213
|
+
this.driver = driver;
|
|
214
|
+
}
|
|
215
|
+
async findByDatasetId(datasetId) {
|
|
216
|
+
const rows = await queryAll(
|
|
217
|
+
this.driver,
|
|
218
|
+
`SELECT
|
|
219
|
+
SmFieldName,
|
|
220
|
+
SmFieldType,
|
|
221
|
+
SmFieldbRequired,
|
|
222
|
+
SmFieldDefaultValue
|
|
223
|
+
FROM SmFieldInfo
|
|
224
|
+
WHERE SmDatasetID = ?
|
|
225
|
+
ORDER BY SmID`,
|
|
226
|
+
[datasetId]
|
|
227
|
+
);
|
|
228
|
+
return rows.map(mapRow);
|
|
229
|
+
}
|
|
230
|
+
async insertAll(datasetId, fields) {
|
|
231
|
+
for (const field of fields) {
|
|
232
|
+
const statement = await this.driver.prepare(
|
|
233
|
+
`INSERT INTO SmFieldInfo (
|
|
234
|
+
SmDatasetID,
|
|
235
|
+
SmFieldName,
|
|
236
|
+
SmFieldType,
|
|
237
|
+
SmFieldCaption,
|
|
238
|
+
SmFieldbRequired,
|
|
239
|
+
SmFieldDefaultValue
|
|
240
|
+
) VALUES (?, ?, ?, ?, ?, ?)`
|
|
241
|
+
);
|
|
242
|
+
await executeStatement(statement, [
|
|
243
|
+
datasetId,
|
|
244
|
+
field.name,
|
|
245
|
+
fieldTypeToValue(field.fieldType),
|
|
246
|
+
field.name,
|
|
247
|
+
field.nullable ? 0 : 1,
|
|
248
|
+
field.defaultValue == null ? null : String(field.defaultValue)
|
|
249
|
+
]);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
// src/core/dataset/BaseDataset.ts
|
|
255
|
+
var BaseDataset = class {
|
|
256
|
+
constructor(driver, info) {
|
|
257
|
+
this.driver = driver;
|
|
258
|
+
this.info = info;
|
|
259
|
+
__publicField(this, "fieldInfoRepository");
|
|
260
|
+
this.fieldInfoRepository = new SmFieldInfoRepository(driver);
|
|
261
|
+
}
|
|
262
|
+
getFields() {
|
|
263
|
+
return this.fieldInfoRepository.findByDatasetId(this.info.id);
|
|
264
|
+
}
|
|
265
|
+
};
|
|
266
|
+
|
|
267
|
+
// src/core/utils/errors.ts
|
|
268
|
+
var NotImplementedError = class extends Error {
|
|
269
|
+
constructor(message) {
|
|
270
|
+
super(message);
|
|
271
|
+
this.name = "NotImplementedError";
|
|
272
|
+
}
|
|
273
|
+
};
|
|
274
|
+
function createNotImplementedError(scope) {
|
|
275
|
+
return new NotImplementedError(`${scope} is not implemented yet.`);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// src/core/dataset/CadDataset.ts
|
|
279
|
+
var CadDataset = class extends BaseDataset {
|
|
280
|
+
async getById() {
|
|
281
|
+
throw createNotImplementedError("CadDataset.getById");
|
|
282
|
+
}
|
|
283
|
+
async list() {
|
|
284
|
+
throw createNotImplementedError("CadDataset.list");
|
|
285
|
+
}
|
|
286
|
+
async *iterate() {
|
|
287
|
+
throw createNotImplementedError("CadDataset.iterate");
|
|
288
|
+
}
|
|
289
|
+
async count() {
|
|
290
|
+
throw createNotImplementedError("CadDataset.count");
|
|
291
|
+
}
|
|
292
|
+
async insert() {
|
|
293
|
+
throw createNotImplementedError("CadDataset.insert");
|
|
294
|
+
}
|
|
295
|
+
async insertMany() {
|
|
296
|
+
throw createNotImplementedError("CadDataset.insertMany");
|
|
297
|
+
}
|
|
298
|
+
async update() {
|
|
299
|
+
throw createNotImplementedError("CadDataset.update");
|
|
300
|
+
}
|
|
301
|
+
async delete() {
|
|
302
|
+
throw createNotImplementedError("CadDataset.delete");
|
|
303
|
+
}
|
|
304
|
+
};
|
|
305
|
+
|
|
306
|
+
// src/core/utils/BinaryCursor.ts
|
|
307
|
+
function toUint8Array(input) {
|
|
308
|
+
if (input instanceof Uint8Array) {
|
|
309
|
+
return input;
|
|
310
|
+
}
|
|
311
|
+
if (ArrayBuffer.isView(input)) {
|
|
312
|
+
return new Uint8Array(input.buffer, input.byteOffset, input.byteLength);
|
|
313
|
+
}
|
|
314
|
+
return new Uint8Array(input);
|
|
315
|
+
}
|
|
316
|
+
var BinaryCursor = class {
|
|
317
|
+
constructor(input) {
|
|
318
|
+
__publicField(this, "bytes");
|
|
319
|
+
__publicField(this, "view");
|
|
320
|
+
__publicField(this, "offset", 0);
|
|
321
|
+
this.bytes = toUint8Array(input);
|
|
322
|
+
this.view = new DataView(
|
|
323
|
+
this.bytes.buffer,
|
|
324
|
+
this.bytes.byteOffset,
|
|
325
|
+
this.bytes.byteLength
|
|
326
|
+
);
|
|
327
|
+
}
|
|
328
|
+
get length() {
|
|
329
|
+
return this.bytes.byteLength;
|
|
330
|
+
}
|
|
331
|
+
get position() {
|
|
332
|
+
return this.offset;
|
|
333
|
+
}
|
|
334
|
+
get remaining() {
|
|
335
|
+
return this.length - this.offset;
|
|
336
|
+
}
|
|
337
|
+
seek(position) {
|
|
338
|
+
if (position < 0 || position > this.length) {
|
|
339
|
+
throw new RangeError(
|
|
340
|
+
`Cannot seek to ${position}; valid range is 0..${this.length}.`
|
|
341
|
+
);
|
|
342
|
+
}
|
|
343
|
+
this.offset = position;
|
|
344
|
+
}
|
|
345
|
+
skip(length) {
|
|
346
|
+
this.seek(this.offset + length);
|
|
347
|
+
}
|
|
348
|
+
readUint8() {
|
|
349
|
+
this.ensureAvailable(1);
|
|
350
|
+
const value = this.view.getUint8(this.offset);
|
|
351
|
+
this.offset += 1;
|
|
352
|
+
return value;
|
|
353
|
+
}
|
|
354
|
+
readInt32(littleEndian = true) {
|
|
355
|
+
this.ensureAvailable(4);
|
|
356
|
+
const value = this.view.getInt32(this.offset, littleEndian);
|
|
357
|
+
this.offset += 4;
|
|
358
|
+
return value;
|
|
359
|
+
}
|
|
360
|
+
readFloat64(littleEndian = true) {
|
|
361
|
+
this.ensureAvailable(8);
|
|
362
|
+
const value = this.view.getFloat64(this.offset, littleEndian);
|
|
363
|
+
this.offset += 8;
|
|
364
|
+
return value;
|
|
365
|
+
}
|
|
366
|
+
readBytes(length) {
|
|
367
|
+
this.ensureAvailable(length);
|
|
368
|
+
const value = this.bytes.slice(this.offset, this.offset + length);
|
|
369
|
+
this.offset += length;
|
|
370
|
+
return value;
|
|
371
|
+
}
|
|
372
|
+
peekUint8() {
|
|
373
|
+
this.ensureAvailable(1);
|
|
374
|
+
return this.view.getUint8(this.offset);
|
|
375
|
+
}
|
|
376
|
+
ensureAvailable(length) {
|
|
377
|
+
if (length < 0) {
|
|
378
|
+
throw new RangeError("Length must be non-negative.");
|
|
379
|
+
}
|
|
380
|
+
if (this.offset + length > this.length) {
|
|
381
|
+
throw new RangeError(
|
|
382
|
+
`Cannot read ${length} byte(s) from offset ${this.offset}; only ${this.remaining} byte(s) remain.`
|
|
383
|
+
);
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
};
|
|
387
|
+
|
|
388
|
+
// src/core/utils/BinaryWriter.ts
|
|
389
|
+
var BinaryWriter = class {
|
|
390
|
+
constructor(initialCapacity = 64) {
|
|
391
|
+
__publicField(this, "buffer");
|
|
392
|
+
__publicField(this, "view");
|
|
393
|
+
__publicField(this, "bytes");
|
|
394
|
+
__publicField(this, "offset", 0);
|
|
395
|
+
if (initialCapacity <= 0) {
|
|
396
|
+
throw new RangeError("Initial capacity must be greater than 0.");
|
|
397
|
+
}
|
|
398
|
+
this.buffer = new ArrayBuffer(initialCapacity);
|
|
399
|
+
this.view = new DataView(this.buffer);
|
|
400
|
+
this.bytes = new Uint8Array(this.buffer);
|
|
401
|
+
}
|
|
402
|
+
get length() {
|
|
403
|
+
return this.offset;
|
|
404
|
+
}
|
|
405
|
+
writeUint8(value) {
|
|
406
|
+
this.ensureCapacity(1);
|
|
407
|
+
this.view.setUint8(this.offset, value);
|
|
408
|
+
this.offset += 1;
|
|
409
|
+
}
|
|
410
|
+
writeInt32(value, littleEndian = true) {
|
|
411
|
+
this.ensureCapacity(4);
|
|
412
|
+
this.view.setInt32(this.offset, value, littleEndian);
|
|
413
|
+
this.offset += 4;
|
|
414
|
+
}
|
|
415
|
+
writeFloat64(value, littleEndian = true) {
|
|
416
|
+
this.ensureCapacity(8);
|
|
417
|
+
this.view.setFloat64(this.offset, value, littleEndian);
|
|
418
|
+
this.offset += 8;
|
|
419
|
+
}
|
|
420
|
+
writeBytes(value) {
|
|
421
|
+
const bytes = value instanceof Uint8Array ? value : ArrayBuffer.isView(value) ? new Uint8Array(value.buffer, value.byteOffset, value.byteLength) : new Uint8Array(value);
|
|
422
|
+
this.ensureCapacity(bytes.byteLength);
|
|
423
|
+
this.bytes.set(bytes, this.offset);
|
|
424
|
+
this.offset += bytes.byteLength;
|
|
425
|
+
}
|
|
426
|
+
toUint8Array() {
|
|
427
|
+
return this.bytes.slice(0, this.offset);
|
|
428
|
+
}
|
|
429
|
+
ensureCapacity(required) {
|
|
430
|
+
if (this.offset + required <= this.buffer.byteLength) {
|
|
431
|
+
return;
|
|
432
|
+
}
|
|
433
|
+
let nextCapacity = this.buffer.byteLength;
|
|
434
|
+
while (this.offset + required > nextCapacity) {
|
|
435
|
+
nextCapacity *= 2;
|
|
436
|
+
}
|
|
437
|
+
const nextBuffer = new ArrayBuffer(nextCapacity);
|
|
438
|
+
const nextBytes = new Uint8Array(nextBuffer);
|
|
439
|
+
nextBytes.set(this.bytes.subarray(0, this.offset));
|
|
440
|
+
this.buffer = nextBuffer;
|
|
441
|
+
this.view = new DataView(this.buffer);
|
|
442
|
+
this.bytes = nextBytes;
|
|
443
|
+
}
|
|
444
|
+
};
|
|
445
|
+
|
|
446
|
+
// src/core/geometry/gaia/GaiaConstants.ts
|
|
447
|
+
var GAIA_START = 0;
|
|
448
|
+
var GAIA_BYTE_ORDER_LE = 1;
|
|
449
|
+
var GAIA_MBR = 124;
|
|
450
|
+
var GAIA_END = 254;
|
|
451
|
+
var GAIA_GEOMETRY_DATA_OFFSET = 43;
|
|
452
|
+
var GEO_TYPE_POINT = 1;
|
|
453
|
+
var GEO_TYPE_POINTZ = 1001;
|
|
454
|
+
var GEO_TYPE_MULTILINESTRING = 5;
|
|
455
|
+
var GEO_TYPE_MULTILINESTRINGZ = 1005;
|
|
456
|
+
var GEO_TYPE_MULTIPOLYGON = 6;
|
|
457
|
+
var GEO_TYPE_MULTIPOLYGONZ = 1006;
|
|
458
|
+
|
|
459
|
+
// src/core/geometry/gaia/GaiaErrors.ts
|
|
460
|
+
var GaiaError = class extends Error {
|
|
461
|
+
constructor(message) {
|
|
462
|
+
super(message);
|
|
463
|
+
this.name = "GaiaError";
|
|
464
|
+
}
|
|
465
|
+
};
|
|
466
|
+
var GaiaFormatError = class extends GaiaError {
|
|
467
|
+
constructor(message) {
|
|
468
|
+
super(message);
|
|
469
|
+
this.name = "GaiaFormatError";
|
|
470
|
+
}
|
|
471
|
+
};
|
|
472
|
+
var GaiaGeoTypeMismatchError = class extends GaiaError {
|
|
473
|
+
constructor(expected, actual) {
|
|
474
|
+
super(`Expected geoType=${expected}, got ${actual}.`);
|
|
475
|
+
this.name = "GaiaGeoTypeMismatchError";
|
|
476
|
+
}
|
|
477
|
+
};
|
|
478
|
+
var GaiaUnsupportedGeoTypeError = class extends GaiaError {
|
|
479
|
+
constructor(geoType) {
|
|
480
|
+
super(`Unsupported GAIA geoType: ${geoType}.`);
|
|
481
|
+
this.name = "GaiaUnsupportedGeoTypeError";
|
|
482
|
+
}
|
|
483
|
+
};
|
|
484
|
+
|
|
485
|
+
// src/core/geometry/gaia/GaiaHeader.ts
|
|
486
|
+
function readGaiaHeader(cursor, expectedGeoType) {
|
|
487
|
+
cursor.seek(0);
|
|
488
|
+
const gaiaStart = cursor.readUint8();
|
|
489
|
+
if (gaiaStart !== GAIA_START) {
|
|
490
|
+
throw new GaiaFormatError(
|
|
491
|
+
`Invalid GAIA start marker: expected 0x${GAIA_START.toString(16)}, got 0x${gaiaStart.toString(16)}.`
|
|
492
|
+
);
|
|
493
|
+
}
|
|
494
|
+
const byteOrder = cursor.readUint8();
|
|
495
|
+
if (byteOrder !== GAIA_BYTE_ORDER_LE) {
|
|
496
|
+
throw new GaiaFormatError(
|
|
497
|
+
`Unsupported byte order: expected 0x${GAIA_BYTE_ORDER_LE.toString(16)}, got 0x${byteOrder.toString(16)}.`
|
|
498
|
+
);
|
|
499
|
+
}
|
|
500
|
+
const srid = cursor.readInt32(true);
|
|
501
|
+
const minX = cursor.readFloat64(true);
|
|
502
|
+
const minY = cursor.readFloat64(true);
|
|
503
|
+
const maxX = cursor.readFloat64(true);
|
|
504
|
+
const maxY = cursor.readFloat64(true);
|
|
505
|
+
const gaiaMbr = cursor.readUint8();
|
|
506
|
+
if (gaiaMbr !== GAIA_MBR) {
|
|
507
|
+
throw new GaiaFormatError(
|
|
508
|
+
`Invalid GAIA MBR marker: expected 0x${GAIA_MBR.toString(16)}, got 0x${gaiaMbr.toString(16)}.`
|
|
509
|
+
);
|
|
510
|
+
}
|
|
511
|
+
const geoType = cursor.readInt32(true);
|
|
512
|
+
if (expectedGeoType !== void 0 && geoType !== expectedGeoType) {
|
|
513
|
+
throw new GaiaGeoTypeMismatchError(expectedGeoType, geoType);
|
|
514
|
+
}
|
|
515
|
+
return {
|
|
516
|
+
byteOrder,
|
|
517
|
+
srid,
|
|
518
|
+
mbr: [minX, minY, maxX, maxY],
|
|
519
|
+
geoType,
|
|
520
|
+
geometryDataOffset: GAIA_GEOMETRY_DATA_OFFSET
|
|
521
|
+
};
|
|
522
|
+
}
|
|
523
|
+
function validateGaiaEnd(cursor) {
|
|
524
|
+
const gaiaEnd = cursor.readUint8();
|
|
525
|
+
if (gaiaEnd !== GAIA_END) {
|
|
526
|
+
throw new GaiaFormatError(
|
|
527
|
+
`Invalid GAIA end marker: expected 0x${GAIA_END.toString(16)}, got 0x${gaiaEnd.toString(16)}.`
|
|
528
|
+
);
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
// src/core/geometry/gaia/GaiaPointCodec.ts
|
|
533
|
+
function isPoint3D(geometry) {
|
|
534
|
+
return geometry.coordinates.length === 3;
|
|
535
|
+
}
|
|
536
|
+
function createPointMbr(coordinates) {
|
|
537
|
+
return [coordinates[0], coordinates[1], coordinates[0], coordinates[1]];
|
|
538
|
+
}
|
|
539
|
+
function writeGaiaHeader(writer2, srid, mbr, geoType) {
|
|
540
|
+
writer2.writeUint8(GAIA_START);
|
|
541
|
+
writer2.writeUint8(GAIA_BYTE_ORDER_LE);
|
|
542
|
+
writer2.writeInt32(srid, true);
|
|
543
|
+
writer2.writeFloat64(mbr[0], true);
|
|
544
|
+
writer2.writeFloat64(mbr[1], true);
|
|
545
|
+
writer2.writeFloat64(mbr[2], true);
|
|
546
|
+
writer2.writeFloat64(mbr[3], true);
|
|
547
|
+
writer2.writeUint8(GAIA_MBR);
|
|
548
|
+
writer2.writeInt32(geoType, true);
|
|
549
|
+
}
|
|
550
|
+
var GaiaPointCodec = class {
|
|
551
|
+
static readPoint(input) {
|
|
552
|
+
const cursor = new BinaryCursor(input);
|
|
553
|
+
const header = readGaiaHeader(cursor, GEO_TYPE_POINT);
|
|
554
|
+
const x = cursor.readFloat64(true);
|
|
555
|
+
const y = cursor.readFloat64(true);
|
|
556
|
+
validateGaiaEnd(cursor);
|
|
557
|
+
return {
|
|
558
|
+
type: "Point",
|
|
559
|
+
coordinates: [x, y],
|
|
560
|
+
srid: header.srid,
|
|
561
|
+
bbox: header.mbr,
|
|
562
|
+
hasZ: false,
|
|
563
|
+
geoType: header.geoType
|
|
564
|
+
};
|
|
565
|
+
}
|
|
566
|
+
static readPointZ(input) {
|
|
567
|
+
const cursor = new BinaryCursor(input);
|
|
568
|
+
const header = readGaiaHeader(cursor, GEO_TYPE_POINTZ);
|
|
569
|
+
const x = cursor.readFloat64(true);
|
|
570
|
+
const y = cursor.readFloat64(true);
|
|
571
|
+
const z = cursor.readFloat64(true);
|
|
572
|
+
validateGaiaEnd(cursor);
|
|
573
|
+
return {
|
|
574
|
+
type: "Point",
|
|
575
|
+
coordinates: [x, y, z],
|
|
576
|
+
srid: header.srid,
|
|
577
|
+
bbox: header.mbr,
|
|
578
|
+
hasZ: true,
|
|
579
|
+
geoType: header.geoType
|
|
580
|
+
};
|
|
581
|
+
}
|
|
582
|
+
static writePoint(geometry, srid) {
|
|
583
|
+
if (isPoint3D(geometry)) {
|
|
584
|
+
throw new GaiaFormatError("writePoint expects a 2D Point geometry.");
|
|
585
|
+
}
|
|
586
|
+
const writer2 = new BinaryWriter(60);
|
|
587
|
+
const mbr = createPointMbr(geometry.coordinates);
|
|
588
|
+
writeGaiaHeader(writer2, srid, mbr, GEO_TYPE_POINT);
|
|
589
|
+
writer2.writeFloat64(geometry.coordinates[0], true);
|
|
590
|
+
writer2.writeFloat64(geometry.coordinates[1], true);
|
|
591
|
+
writer2.writeUint8(GAIA_END);
|
|
592
|
+
return writer2.toUint8Array();
|
|
593
|
+
}
|
|
594
|
+
static writePointZ(geometry, srid) {
|
|
595
|
+
if (!isPoint3D(geometry)) {
|
|
596
|
+
throw new GaiaFormatError("writePointZ expects a 3D Point geometry.");
|
|
597
|
+
}
|
|
598
|
+
const writer2 = new BinaryWriter(68);
|
|
599
|
+
const mbr = createPointMbr(geometry.coordinates);
|
|
600
|
+
writeGaiaHeader(writer2, srid, mbr, GEO_TYPE_POINTZ);
|
|
601
|
+
writer2.writeFloat64(geometry.coordinates[0], true);
|
|
602
|
+
writer2.writeFloat64(geometry.coordinates[1], true);
|
|
603
|
+
writer2.writeFloat64(geometry.coordinates[2], true);
|
|
604
|
+
writer2.writeUint8(GAIA_END);
|
|
605
|
+
return writer2.toUint8Array();
|
|
606
|
+
}
|
|
607
|
+
};
|
|
608
|
+
|
|
609
|
+
// src/core/geometry/gaia/GaiaLineCodec.ts
|
|
610
|
+
var GAIA_ENTITY_MARK = 105;
|
|
611
|
+
var GEO_TYPE_LINESTRING = 2;
|
|
612
|
+
var GEO_TYPE_LINESTRINGZ = 1002;
|
|
613
|
+
function is3DCoordinates(coordinates) {
|
|
614
|
+
return coordinates[0]?.[0]?.length === 3;
|
|
615
|
+
}
|
|
616
|
+
function createLineMbr(coordinates) {
|
|
617
|
+
const xs = [];
|
|
618
|
+
const ys = [];
|
|
619
|
+
for (const line of coordinates) {
|
|
620
|
+
for (const point of line) {
|
|
621
|
+
xs.push(point[0]);
|
|
622
|
+
ys.push(point[1]);
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
if (xs.length === 0) {
|
|
626
|
+
throw new GaiaFormatError("MultiLineString must contain at least one point.");
|
|
627
|
+
}
|
|
628
|
+
return [
|
|
629
|
+
Math.min(...xs),
|
|
630
|
+
Math.min(...ys),
|
|
631
|
+
Math.max(...xs),
|
|
632
|
+
Math.max(...ys)
|
|
633
|
+
];
|
|
634
|
+
}
|
|
635
|
+
var GaiaLineCodec = class {
|
|
636
|
+
static readMultiLineString(input) {
|
|
637
|
+
const cursor = new BinaryCursor(input);
|
|
638
|
+
const header = readGaiaHeader(cursor, GEO_TYPE_MULTILINESTRING);
|
|
639
|
+
const lineCount = cursor.readInt32(true);
|
|
640
|
+
const coordinates = [];
|
|
641
|
+
for (let lineIndex = 0; lineIndex < lineCount; lineIndex += 1) {
|
|
642
|
+
const entityMark = cursor.readUint8();
|
|
643
|
+
if (entityMark !== GAIA_ENTITY_MARK) {
|
|
644
|
+
throw new GaiaFormatError(
|
|
645
|
+
`Invalid LineString entity mark: expected 0x${GAIA_ENTITY_MARK.toString(16)}, got 0x${entityMark.toString(16)}.`
|
|
646
|
+
);
|
|
647
|
+
}
|
|
648
|
+
const lineGeoType = cursor.readInt32(true);
|
|
649
|
+
if (lineGeoType !== GEO_TYPE_LINESTRING) {
|
|
650
|
+
throw new GaiaFormatError(
|
|
651
|
+
`Invalid LineString geoType: expected ${GEO_TYPE_LINESTRING}, got ${lineGeoType}.`
|
|
652
|
+
);
|
|
653
|
+
}
|
|
654
|
+
const pointCount = cursor.readInt32(true);
|
|
655
|
+
const line = [];
|
|
656
|
+
for (let pointIndex = 0; pointIndex < pointCount; pointIndex += 1) {
|
|
657
|
+
line.push([cursor.readFloat64(true), cursor.readFloat64(true)]);
|
|
658
|
+
}
|
|
659
|
+
coordinates.push(line);
|
|
660
|
+
}
|
|
661
|
+
validateGaiaEnd(cursor);
|
|
662
|
+
return {
|
|
663
|
+
type: "MultiLineString",
|
|
664
|
+
coordinates,
|
|
665
|
+
srid: header.srid,
|
|
666
|
+
bbox: header.mbr,
|
|
667
|
+
hasZ: false,
|
|
668
|
+
geoType: header.geoType
|
|
669
|
+
};
|
|
670
|
+
}
|
|
671
|
+
static readMultiLineStringZ(input) {
|
|
672
|
+
const cursor = new BinaryCursor(input);
|
|
673
|
+
const header = readGaiaHeader(cursor, GEO_TYPE_MULTILINESTRINGZ);
|
|
674
|
+
const lineCount = cursor.readInt32(true);
|
|
675
|
+
const coordinates = [];
|
|
676
|
+
for (let lineIndex = 0; lineIndex < lineCount; lineIndex += 1) {
|
|
677
|
+
const entityMark = cursor.readUint8();
|
|
678
|
+
if (entityMark !== GAIA_ENTITY_MARK) {
|
|
679
|
+
throw new GaiaFormatError(
|
|
680
|
+
`Invalid LineString entity mark: expected 0x${GAIA_ENTITY_MARK.toString(16)}, got 0x${entityMark.toString(16)}.`
|
|
681
|
+
);
|
|
682
|
+
}
|
|
683
|
+
const lineGeoType = cursor.readInt32(true);
|
|
684
|
+
if (lineGeoType !== GEO_TYPE_LINESTRINGZ) {
|
|
685
|
+
throw new GaiaFormatError(
|
|
686
|
+
`Invalid LineStringZ geoType: expected ${GEO_TYPE_LINESTRINGZ}, got ${lineGeoType}.`
|
|
687
|
+
);
|
|
688
|
+
}
|
|
689
|
+
const pointCount = cursor.readInt32(true);
|
|
690
|
+
const line = [];
|
|
691
|
+
for (let pointIndex = 0; pointIndex < pointCount; pointIndex += 1) {
|
|
692
|
+
line.push([
|
|
693
|
+
cursor.readFloat64(true),
|
|
694
|
+
cursor.readFloat64(true),
|
|
695
|
+
cursor.readFloat64(true)
|
|
696
|
+
]);
|
|
697
|
+
}
|
|
698
|
+
coordinates.push(line);
|
|
699
|
+
}
|
|
700
|
+
validateGaiaEnd(cursor);
|
|
701
|
+
return {
|
|
702
|
+
type: "MultiLineString",
|
|
703
|
+
coordinates,
|
|
704
|
+
srid: header.srid,
|
|
705
|
+
bbox: header.mbr,
|
|
706
|
+
hasZ: true,
|
|
707
|
+
geoType: header.geoType
|
|
708
|
+
};
|
|
709
|
+
}
|
|
710
|
+
static writeMultiLineString(geometry, srid) {
|
|
711
|
+
if (is3DCoordinates(geometry.coordinates)) {
|
|
712
|
+
throw new GaiaFormatError(
|
|
713
|
+
"writeMultiLineString expects 2D coordinates."
|
|
714
|
+
);
|
|
715
|
+
}
|
|
716
|
+
const writer2 = new BinaryWriter();
|
|
717
|
+
writeGaiaHeader(
|
|
718
|
+
writer2,
|
|
719
|
+
srid,
|
|
720
|
+
createLineMbr(geometry.coordinates),
|
|
721
|
+
GEO_TYPE_MULTILINESTRING
|
|
722
|
+
);
|
|
723
|
+
writer2.writeInt32(geometry.coordinates.length, true);
|
|
724
|
+
for (const line of geometry.coordinates) {
|
|
725
|
+
writer2.writeUint8(GAIA_ENTITY_MARK);
|
|
726
|
+
writer2.writeInt32(GEO_TYPE_LINESTRING, true);
|
|
727
|
+
writer2.writeInt32(line.length, true);
|
|
728
|
+
for (const point of line) {
|
|
729
|
+
writer2.writeFloat64(point[0], true);
|
|
730
|
+
writer2.writeFloat64(point[1], true);
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
writer2.writeUint8(GAIA_END);
|
|
734
|
+
return writer2.toUint8Array();
|
|
735
|
+
}
|
|
736
|
+
static writeMultiLineStringZ(geometry, srid) {
|
|
737
|
+
if (!is3DCoordinates(geometry.coordinates)) {
|
|
738
|
+
throw new GaiaFormatError(
|
|
739
|
+
"writeMultiLineStringZ expects 3D coordinates."
|
|
740
|
+
);
|
|
741
|
+
}
|
|
742
|
+
const writer2 = new BinaryWriter();
|
|
743
|
+
writeGaiaHeader(
|
|
744
|
+
writer2,
|
|
745
|
+
srid,
|
|
746
|
+
createLineMbr(geometry.coordinates),
|
|
747
|
+
GEO_TYPE_MULTILINESTRINGZ
|
|
748
|
+
);
|
|
749
|
+
writer2.writeInt32(geometry.coordinates.length, true);
|
|
750
|
+
for (const line of geometry.coordinates) {
|
|
751
|
+
writer2.writeUint8(GAIA_ENTITY_MARK);
|
|
752
|
+
writer2.writeInt32(GEO_TYPE_LINESTRINGZ, true);
|
|
753
|
+
writer2.writeInt32(line.length, true);
|
|
754
|
+
for (const point of line) {
|
|
755
|
+
writer2.writeFloat64(point[0], true);
|
|
756
|
+
writer2.writeFloat64(point[1], true);
|
|
757
|
+
writer2.writeFloat64(point[2], true);
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
writer2.writeUint8(GAIA_END);
|
|
761
|
+
return writer2.toUint8Array();
|
|
762
|
+
}
|
|
763
|
+
};
|
|
764
|
+
|
|
765
|
+
// src/core/schema/SmRegisterRepository.ts
|
|
766
|
+
function mapRow2(row) {
|
|
767
|
+
return {
|
|
768
|
+
id: row.SmDatasetID,
|
|
769
|
+
name: row.SmDatasetName,
|
|
770
|
+
kind: datasetValueToKind(row.SmDatasetType),
|
|
771
|
+
tableName: row.SmTableName,
|
|
772
|
+
srid: row.SmSRID ?? null,
|
|
773
|
+
objectCount: row.SmObjectCount,
|
|
774
|
+
geometryType: row.geometryType ?? null
|
|
775
|
+
};
|
|
776
|
+
}
|
|
777
|
+
var SmRegisterRepository = class {
|
|
778
|
+
constructor(driver) {
|
|
779
|
+
this.driver = driver;
|
|
780
|
+
}
|
|
781
|
+
async findAll() {
|
|
782
|
+
const rows = await queryAll(
|
|
783
|
+
this.driver,
|
|
784
|
+
`SELECT
|
|
785
|
+
SmDatasetID,
|
|
786
|
+
SmDatasetName,
|
|
787
|
+
SmTableName,
|
|
788
|
+
SmDatasetType,
|
|
789
|
+
SmObjectCount,
|
|
790
|
+
SmSRID
|
|
791
|
+
FROM SmRegister
|
|
792
|
+
ORDER BY SmDatasetID`
|
|
793
|
+
);
|
|
794
|
+
return rows.map(mapRow2);
|
|
795
|
+
}
|
|
796
|
+
async findByName(name) {
|
|
797
|
+
const row = await queryOne(
|
|
798
|
+
this.driver,
|
|
799
|
+
`SELECT
|
|
800
|
+
SmDatasetID,
|
|
801
|
+
SmDatasetName,
|
|
802
|
+
SmTableName,
|
|
803
|
+
SmDatasetType,
|
|
804
|
+
SmObjectCount,
|
|
805
|
+
SmSRID
|
|
806
|
+
FROM SmRegister
|
|
807
|
+
WHERE SmDatasetName = ?`,
|
|
808
|
+
[name]
|
|
809
|
+
);
|
|
810
|
+
return row ? mapRow2(row) : null;
|
|
811
|
+
}
|
|
812
|
+
async nextDatasetId() {
|
|
813
|
+
const row = await queryOne(
|
|
814
|
+
this.driver,
|
|
815
|
+
"SELECT COALESCE(MAX(SmDatasetID), 0) + 1 AS nextId FROM SmRegister"
|
|
816
|
+
);
|
|
817
|
+
return row?.nextId ?? 1;
|
|
818
|
+
}
|
|
819
|
+
async insert(params) {
|
|
820
|
+
const datasetId = await this.nextDatasetId();
|
|
821
|
+
const statement = await this.driver.prepare(
|
|
822
|
+
`INSERT INTO SmRegister (
|
|
823
|
+
SmDatasetID,
|
|
824
|
+
SmDatasetName,
|
|
825
|
+
SmTableName,
|
|
826
|
+
SmDatasetType,
|
|
827
|
+
SmObjectCount,
|
|
828
|
+
SmSRID,
|
|
829
|
+
SmIDColName,
|
|
830
|
+
SmGeoColName,
|
|
831
|
+
SmMaxGeometrySize,
|
|
832
|
+
SmCreateTime,
|
|
833
|
+
SmLastUpdateTime
|
|
834
|
+
) VALUES (?, ?, ?, ?, 0, ?, ?, ?, 0, datetime('now'), datetime('now'))`
|
|
835
|
+
);
|
|
836
|
+
await executeStatement(statement, [
|
|
837
|
+
datasetId,
|
|
838
|
+
params.name,
|
|
839
|
+
params.name,
|
|
840
|
+
datasetKindToValue(params.kind),
|
|
841
|
+
params.srid,
|
|
842
|
+
params.idColumnName,
|
|
843
|
+
params.geometryColumnName
|
|
844
|
+
]);
|
|
845
|
+
return datasetId;
|
|
846
|
+
}
|
|
847
|
+
async incrementObjectCount(datasetId, geometrySize) {
|
|
848
|
+
if (geometrySize === void 0) {
|
|
849
|
+
const statement2 = await this.driver.prepare(
|
|
850
|
+
"UPDATE SmRegister SET SmObjectCount = SmObjectCount + 1 WHERE SmDatasetID = ?"
|
|
851
|
+
);
|
|
852
|
+
await executeStatement(statement2, [datasetId]);
|
|
853
|
+
return;
|
|
854
|
+
}
|
|
855
|
+
const statement = await this.driver.prepare(
|
|
856
|
+
`UPDATE SmRegister
|
|
857
|
+
SET SmObjectCount = SmObjectCount + 1,
|
|
858
|
+
SmMaxGeometrySize = CASE
|
|
859
|
+
WHEN SmMaxGeometrySize < ? THEN ?
|
|
860
|
+
ELSE SmMaxGeometrySize
|
|
861
|
+
END
|
|
862
|
+
WHERE SmDatasetID = ?`
|
|
863
|
+
);
|
|
864
|
+
await executeStatement(statement, [geometrySize, geometrySize, datasetId]);
|
|
865
|
+
}
|
|
866
|
+
async incrementObjectCountBatch(datasetId, count, maxGeometrySize) {
|
|
867
|
+
const statement = await this.driver.prepare(
|
|
868
|
+
`UPDATE SmRegister
|
|
869
|
+
SET SmObjectCount = SmObjectCount + ?,
|
|
870
|
+
SmMaxGeometrySize = CASE
|
|
871
|
+
WHEN SmMaxGeometrySize < ? THEN ?
|
|
872
|
+
ELSE SmMaxGeometrySize
|
|
873
|
+
END
|
|
874
|
+
WHERE SmDatasetID = ?`
|
|
875
|
+
);
|
|
876
|
+
await executeStatement(statement, [
|
|
877
|
+
count,
|
|
878
|
+
maxGeometrySize,
|
|
879
|
+
maxGeometrySize,
|
|
880
|
+
datasetId
|
|
881
|
+
]);
|
|
882
|
+
}
|
|
883
|
+
async decrementObjectCount(datasetId) {
|
|
884
|
+
const statement = await this.driver.prepare(
|
|
885
|
+
"UPDATE SmRegister SET SmObjectCount = SmObjectCount - 1 WHERE SmDatasetID = ? AND SmObjectCount > 0"
|
|
886
|
+
);
|
|
887
|
+
await executeStatement(statement, [datasetId]);
|
|
888
|
+
}
|
|
889
|
+
};
|
|
890
|
+
|
|
891
|
+
// src/core/dataset/vectorDatasetShared.ts
|
|
892
|
+
function normalizeGeometryBlob(value) {
|
|
893
|
+
return value instanceof Uint8Array ? value : new Uint8Array(value);
|
|
894
|
+
}
|
|
895
|
+
function buildListSql(tableName, options) {
|
|
896
|
+
const params = [];
|
|
897
|
+
const clauses = [];
|
|
898
|
+
if (options?.ids?.length) {
|
|
899
|
+
const placeholders = options.ids.map(() => "?").join(", ");
|
|
900
|
+
clauses.push(`SmID IN (${placeholders})`);
|
|
901
|
+
params.push(...options.ids);
|
|
902
|
+
}
|
|
903
|
+
const whereClause = clauses.length > 0 ? ` WHERE ${clauses.join(" AND ")}` : "";
|
|
904
|
+
let sql = `SELECT * FROM "${tableName}"${whereClause} ORDER BY SmID`;
|
|
905
|
+
if (options?.limit !== void 0) {
|
|
906
|
+
sql += " LIMIT ?";
|
|
907
|
+
params.push(options.limit);
|
|
908
|
+
}
|
|
909
|
+
if (options?.offset !== void 0) {
|
|
910
|
+
if (options.limit === void 0) {
|
|
911
|
+
sql += " LIMIT -1";
|
|
912
|
+
}
|
|
913
|
+
sql += " OFFSET ?";
|
|
914
|
+
params.push(options.offset);
|
|
915
|
+
}
|
|
916
|
+
return { sql, params };
|
|
917
|
+
}
|
|
918
|
+
function sqliteColumnType(field) {
|
|
919
|
+
switch (field.fieldType) {
|
|
920
|
+
case "boolean":
|
|
921
|
+
case "byte":
|
|
922
|
+
case "int16":
|
|
923
|
+
case "int32":
|
|
924
|
+
case "int64":
|
|
925
|
+
return "INTEGER";
|
|
926
|
+
case "single":
|
|
927
|
+
case "double":
|
|
928
|
+
return "REAL";
|
|
929
|
+
case "binary":
|
|
930
|
+
case "geometry":
|
|
931
|
+
return "BLOB";
|
|
932
|
+
case "date":
|
|
933
|
+
case "char":
|
|
934
|
+
case "ntext":
|
|
935
|
+
case "text":
|
|
936
|
+
case "time":
|
|
937
|
+
default:
|
|
938
|
+
return "TEXT";
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
// src/core/dataset/LineDataset.ts
|
|
943
|
+
function mapLineRow(row) {
|
|
944
|
+
const { SmID, SmGeometry, ...attributes } = row;
|
|
945
|
+
return {
|
|
946
|
+
id: SmID,
|
|
947
|
+
geometry: GaiaLineCodec.readMultiLineString(normalizeGeometryBlob(SmGeometry)),
|
|
948
|
+
attributes
|
|
949
|
+
};
|
|
950
|
+
}
|
|
951
|
+
var LineDataset = class _LineDataset extends BaseDataset {
|
|
952
|
+
constructor(driver, info) {
|
|
953
|
+
super(driver, info);
|
|
954
|
+
__publicField(this, "registerRepository");
|
|
955
|
+
this.registerRepository = new SmRegisterRepository(driver);
|
|
956
|
+
}
|
|
957
|
+
async getById(id) {
|
|
958
|
+
const row = await queryOne(
|
|
959
|
+
this.driver,
|
|
960
|
+
`SELECT * FROM "${this.info.tableName}" WHERE SmID = ?`,
|
|
961
|
+
[id]
|
|
962
|
+
);
|
|
963
|
+
return row ? mapLineRow(row) : null;
|
|
964
|
+
}
|
|
965
|
+
async list(options) {
|
|
966
|
+
const { sql, params } = buildListSql(this.info.tableName, options);
|
|
967
|
+
const rows = await queryAll(this.driver, sql, params);
|
|
968
|
+
return rows.map((row) => mapLineRow(row));
|
|
969
|
+
}
|
|
970
|
+
async *iterate(options) {
|
|
971
|
+
const { sql, params } = buildListSql(this.info.tableName, options);
|
|
972
|
+
const statement = await this.driver.prepare(sql);
|
|
973
|
+
try {
|
|
974
|
+
if (params.length > 0) {
|
|
975
|
+
await statement.bind(params);
|
|
976
|
+
}
|
|
977
|
+
while (await statement.step()) {
|
|
978
|
+
yield mapLineRow(await statement.getRow());
|
|
979
|
+
}
|
|
980
|
+
} finally {
|
|
981
|
+
await statement.finalize();
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
async insert(feature) {
|
|
985
|
+
const userFields = await this.getFields();
|
|
986
|
+
const columnNames = ["SmID", "SmUserID", "SmGeometry", ...userFields.map((field) => field.name)];
|
|
987
|
+
const placeholders = columnNames.map(() => "?").join(", ");
|
|
988
|
+
const geometry = GaiaLineCodec.writeMultiLineString(
|
|
989
|
+
feature.geometry,
|
|
990
|
+
feature.geometry.srid ?? this.info.srid ?? 0
|
|
991
|
+
);
|
|
992
|
+
const sql = `INSERT INTO "${this.info.tableName}" (${columnNames.map((column) => `"${column}"`).join(", ")}) VALUES (${placeholders})`;
|
|
993
|
+
const params = [
|
|
994
|
+
feature.id,
|
|
995
|
+
0,
|
|
996
|
+
geometry,
|
|
997
|
+
...userFields.map((field) => feature.attributes[field.name] ?? null)
|
|
998
|
+
];
|
|
999
|
+
await this.driver.transaction(async () => {
|
|
1000
|
+
await executeSql(this.driver, sql, params);
|
|
1001
|
+
await this.registerRepository.incrementObjectCount(this.info.id, geometry.byteLength);
|
|
1002
|
+
});
|
|
1003
|
+
}
|
|
1004
|
+
async insertMany(features) {
|
|
1005
|
+
const userFields = await this.getFields();
|
|
1006
|
+
const columnNames = ["SmID", "SmUserID", "SmGeometry", ...userFields.map((field) => field.name)];
|
|
1007
|
+
const placeholders = columnNames.map(() => "?").join(", ");
|
|
1008
|
+
const sql = `INSERT INTO "${this.info.tableName}" (${columnNames.map((column) => `"${column}"`).join(", ")}) VALUES (${placeholders})`;
|
|
1009
|
+
await this.driver.transaction(async () => {
|
|
1010
|
+
const statement = await this.driver.prepare(sql);
|
|
1011
|
+
try {
|
|
1012
|
+
let count = 0;
|
|
1013
|
+
let maxGeometrySize = 0;
|
|
1014
|
+
for await (const feature of features) {
|
|
1015
|
+
const geometry = GaiaLineCodec.writeMultiLineString(
|
|
1016
|
+
feature.geometry,
|
|
1017
|
+
feature.geometry.srid ?? this.info.srid ?? 0
|
|
1018
|
+
);
|
|
1019
|
+
maxGeometrySize = Math.max(maxGeometrySize, geometry.byteLength);
|
|
1020
|
+
const params = [
|
|
1021
|
+
feature.id,
|
|
1022
|
+
0,
|
|
1023
|
+
geometry,
|
|
1024
|
+
...userFields.map(
|
|
1025
|
+
(field) => feature.attributes[field.name] ?? null
|
|
1026
|
+
)
|
|
1027
|
+
];
|
|
1028
|
+
await statement.bind(params);
|
|
1029
|
+
await statement.step();
|
|
1030
|
+
await statement.reset();
|
|
1031
|
+
count++;
|
|
1032
|
+
}
|
|
1033
|
+
if (count > 0) {
|
|
1034
|
+
await this.registerRepository.incrementObjectCountBatch(
|
|
1035
|
+
this.info.id,
|
|
1036
|
+
count,
|
|
1037
|
+
maxGeometrySize
|
|
1038
|
+
);
|
|
1039
|
+
}
|
|
1040
|
+
} finally {
|
|
1041
|
+
await statement.finalize();
|
|
1042
|
+
}
|
|
1043
|
+
});
|
|
1044
|
+
}
|
|
1045
|
+
async count() {
|
|
1046
|
+
const row = await queryOne(
|
|
1047
|
+
this.driver,
|
|
1048
|
+
`SELECT COUNT(*) AS count FROM "${this.info.tableName}"`,
|
|
1049
|
+
[]
|
|
1050
|
+
);
|
|
1051
|
+
return row?.count ?? 0;
|
|
1052
|
+
}
|
|
1053
|
+
async update(id, changes) {
|
|
1054
|
+
if (!changes.geometry && !changes.attributes) {
|
|
1055
|
+
return;
|
|
1056
|
+
}
|
|
1057
|
+
const setClauses = [];
|
|
1058
|
+
const params = [];
|
|
1059
|
+
if (changes.geometry) {
|
|
1060
|
+
const geometry = GaiaLineCodec.writeMultiLineString(
|
|
1061
|
+
changes.geometry,
|
|
1062
|
+
changes.geometry.srid ?? this.info.srid ?? 0
|
|
1063
|
+
);
|
|
1064
|
+
setClauses.push('"SmGeometry" = ?');
|
|
1065
|
+
params.push(geometry);
|
|
1066
|
+
}
|
|
1067
|
+
if (changes.attributes) {
|
|
1068
|
+
const userFields = await this.getFields();
|
|
1069
|
+
const fieldNames = new Set(userFields.map((f) => f.name));
|
|
1070
|
+
const validEntries = Object.entries(changes.attributes).filter(
|
|
1071
|
+
([key]) => fieldNames.has(key)
|
|
1072
|
+
);
|
|
1073
|
+
for (const [key, value] of validEntries) {
|
|
1074
|
+
setClauses.push(`"${key}" = ?`);
|
|
1075
|
+
params.push(value);
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1078
|
+
if (setClauses.length === 0) {
|
|
1079
|
+
return;
|
|
1080
|
+
}
|
|
1081
|
+
const sql = `UPDATE "${this.info.tableName}" SET ${setClauses.join(", ")} WHERE SmID = ?`;
|
|
1082
|
+
params.push(id);
|
|
1083
|
+
await this.driver.transaction(async () => {
|
|
1084
|
+
await executeSql(this.driver, sql, params);
|
|
1085
|
+
});
|
|
1086
|
+
}
|
|
1087
|
+
async delete(id) {
|
|
1088
|
+
await this.driver.transaction(async () => {
|
|
1089
|
+
await executeSql(
|
|
1090
|
+
this.driver,
|
|
1091
|
+
`DELETE FROM "${this.info.tableName}" WHERE SmID = ?`,
|
|
1092
|
+
[id]
|
|
1093
|
+
);
|
|
1094
|
+
await this.registerRepository.decrementObjectCount(this.info.id);
|
|
1095
|
+
});
|
|
1096
|
+
}
|
|
1097
|
+
static async create(driver, registerRepository, params) {
|
|
1098
|
+
const fields = params.fields ?? [];
|
|
1099
|
+
const datasetId = await registerRepository.insert({
|
|
1100
|
+
name: params.name,
|
|
1101
|
+
kind: "line",
|
|
1102
|
+
srid: params.srid,
|
|
1103
|
+
idColumnName: "SmID",
|
|
1104
|
+
geometryColumnName: "SmGeometry"
|
|
1105
|
+
});
|
|
1106
|
+
const userColumnDefinitions = fields.map((field) => {
|
|
1107
|
+
const nullability = field.nullable ? "" : " NOT NULL";
|
|
1108
|
+
return `"${field.name}" ${sqliteColumnType(field)}${nullability}`;
|
|
1109
|
+
});
|
|
1110
|
+
const createTableParts = [
|
|
1111
|
+
`"SmID" INTEGER NOT NULL PRIMARY KEY`,
|
|
1112
|
+
`"SmUserID" INTEGER DEFAULT 0 NOT NULL`,
|
|
1113
|
+
`"SmGeometry" BLOB NOT NULL`,
|
|
1114
|
+
...userColumnDefinitions
|
|
1115
|
+
];
|
|
1116
|
+
await driver.exec(
|
|
1117
|
+
`CREATE TABLE "${params.name}" (${createTableParts.join(", ")})`
|
|
1118
|
+
);
|
|
1119
|
+
await executeSql(
|
|
1120
|
+
driver,
|
|
1121
|
+
`INSERT INTO geometry_columns (
|
|
1122
|
+
f_table_name,
|
|
1123
|
+
f_geometry_column,
|
|
1124
|
+
geometry_type,
|
|
1125
|
+
coord_dimension,
|
|
1126
|
+
srid,
|
|
1127
|
+
spatial_index_enabled
|
|
1128
|
+
) VALUES (?, ?, ?, ?, ?, ?)`,
|
|
1129
|
+
[params.name, "SmGeometry", 5, 2, params.srid, 0]
|
|
1130
|
+
);
|
|
1131
|
+
if (fields.length > 0) {
|
|
1132
|
+
const fieldInfoRepository = new SmFieldInfoRepository(driver);
|
|
1133
|
+
await fieldInfoRepository.insertAll(datasetId, fields);
|
|
1134
|
+
}
|
|
1135
|
+
return new _LineDataset(driver, {
|
|
1136
|
+
id: datasetId,
|
|
1137
|
+
name: params.name,
|
|
1138
|
+
kind: "line",
|
|
1139
|
+
tableName: params.name,
|
|
1140
|
+
srid: params.srid,
|
|
1141
|
+
objectCount: 0,
|
|
1142
|
+
geometryType: 5
|
|
1143
|
+
});
|
|
1144
|
+
}
|
|
1145
|
+
};
|
|
1146
|
+
|
|
1147
|
+
// src/core/dataset/LineZDataset.ts
|
|
1148
|
+
function mapLineZRow(row) {
|
|
1149
|
+
const { SmID, SmGeometry, ...attributes } = row;
|
|
1150
|
+
return {
|
|
1151
|
+
id: SmID,
|
|
1152
|
+
geometry: GaiaLineCodec.readMultiLineStringZ(normalizeGeometryBlob(SmGeometry)),
|
|
1153
|
+
attributes
|
|
1154
|
+
};
|
|
1155
|
+
}
|
|
1156
|
+
var LineZDataset = class _LineZDataset extends BaseDataset {
|
|
1157
|
+
constructor(driver, info) {
|
|
1158
|
+
super(driver, info);
|
|
1159
|
+
__publicField(this, "registerRepository");
|
|
1160
|
+
this.registerRepository = new SmRegisterRepository(driver);
|
|
1161
|
+
}
|
|
1162
|
+
async getById(id) {
|
|
1163
|
+
const row = await queryOne(
|
|
1164
|
+
this.driver,
|
|
1165
|
+
`SELECT * FROM "${this.info.tableName}" WHERE SmID = ?`,
|
|
1166
|
+
[id]
|
|
1167
|
+
);
|
|
1168
|
+
return row ? mapLineZRow(row) : null;
|
|
1169
|
+
}
|
|
1170
|
+
async list(options) {
|
|
1171
|
+
const { sql, params } = buildListSql(this.info.tableName, options);
|
|
1172
|
+
const rows = await queryAll(this.driver, sql, params);
|
|
1173
|
+
return rows.map((row) => mapLineZRow(row));
|
|
1174
|
+
}
|
|
1175
|
+
async *iterate(options) {
|
|
1176
|
+
const { sql, params } = buildListSql(this.info.tableName, options);
|
|
1177
|
+
const statement = await this.driver.prepare(sql);
|
|
1178
|
+
try {
|
|
1179
|
+
if (params.length > 0) {
|
|
1180
|
+
await statement.bind(params);
|
|
1181
|
+
}
|
|
1182
|
+
while (await statement.step()) {
|
|
1183
|
+
yield mapLineZRow(await statement.getRow());
|
|
1184
|
+
}
|
|
1185
|
+
} finally {
|
|
1186
|
+
await statement.finalize();
|
|
1187
|
+
}
|
|
1188
|
+
}
|
|
1189
|
+
async count() {
|
|
1190
|
+
const row = await queryOne(
|
|
1191
|
+
this.driver,
|
|
1192
|
+
`SELECT COUNT(*) AS count FROM "${this.info.tableName}"`,
|
|
1193
|
+
[]
|
|
1194
|
+
);
|
|
1195
|
+
return row?.count ?? 0;
|
|
1196
|
+
}
|
|
1197
|
+
async insert(feature) {
|
|
1198
|
+
const userFields = await this.getFields();
|
|
1199
|
+
const columnNames = ["SmID", "SmUserID", "SmGeometry", ...userFields.map((field) => field.name)];
|
|
1200
|
+
const placeholders = columnNames.map(() => "?").join(", ");
|
|
1201
|
+
const geometry = GaiaLineCodec.writeMultiLineStringZ(
|
|
1202
|
+
feature.geometry,
|
|
1203
|
+
feature.geometry.srid ?? this.info.srid ?? 0
|
|
1204
|
+
);
|
|
1205
|
+
const sql = `INSERT INTO "${this.info.tableName}" (${columnNames.map((column) => `"${column}"`).join(", ")}) VALUES (${placeholders})`;
|
|
1206
|
+
const params = [
|
|
1207
|
+
feature.id,
|
|
1208
|
+
0,
|
|
1209
|
+
geometry,
|
|
1210
|
+
...userFields.map((field) => feature.attributes[field.name] ?? null)
|
|
1211
|
+
];
|
|
1212
|
+
await this.driver.transaction(async () => {
|
|
1213
|
+
await executeSql(this.driver, sql, params);
|
|
1214
|
+
await this.registerRepository.incrementObjectCount(this.info.id, geometry.byteLength);
|
|
1215
|
+
});
|
|
1216
|
+
}
|
|
1217
|
+
async insertMany(features) {
|
|
1218
|
+
const userFields = await this.getFields();
|
|
1219
|
+
const columnNames = ["SmID", "SmUserID", "SmGeometry", ...userFields.map((field) => field.name)];
|
|
1220
|
+
const placeholders = columnNames.map(() => "?").join(", ");
|
|
1221
|
+
const sql = `INSERT INTO "${this.info.tableName}" (${columnNames.map((column) => `"${column}"`).join(", ")}) VALUES (${placeholders})`;
|
|
1222
|
+
await this.driver.transaction(async () => {
|
|
1223
|
+
const statement = await this.driver.prepare(sql);
|
|
1224
|
+
try {
|
|
1225
|
+
let count = 0;
|
|
1226
|
+
let maxGeometrySize = 0;
|
|
1227
|
+
for await (const feature of features) {
|
|
1228
|
+
const geometry = GaiaLineCodec.writeMultiLineStringZ(
|
|
1229
|
+
feature.geometry,
|
|
1230
|
+
feature.geometry.srid ?? this.info.srid ?? 0
|
|
1231
|
+
);
|
|
1232
|
+
maxGeometrySize = Math.max(maxGeometrySize, geometry.byteLength);
|
|
1233
|
+
const params = [
|
|
1234
|
+
feature.id,
|
|
1235
|
+
0,
|
|
1236
|
+
geometry,
|
|
1237
|
+
...userFields.map(
|
|
1238
|
+
(field) => feature.attributes[field.name] ?? null
|
|
1239
|
+
)
|
|
1240
|
+
];
|
|
1241
|
+
await statement.bind(params);
|
|
1242
|
+
await statement.step();
|
|
1243
|
+
await statement.reset();
|
|
1244
|
+
count++;
|
|
1245
|
+
}
|
|
1246
|
+
if (count > 0) {
|
|
1247
|
+
await this.registerRepository.incrementObjectCountBatch(
|
|
1248
|
+
this.info.id,
|
|
1249
|
+
count,
|
|
1250
|
+
maxGeometrySize
|
|
1251
|
+
);
|
|
1252
|
+
}
|
|
1253
|
+
} finally {
|
|
1254
|
+
await statement.finalize();
|
|
1255
|
+
}
|
|
1256
|
+
});
|
|
1257
|
+
}
|
|
1258
|
+
async update(id, changes) {
|
|
1259
|
+
if (!changes.geometry && !changes.attributes) {
|
|
1260
|
+
return;
|
|
1261
|
+
}
|
|
1262
|
+
const setClauses = [];
|
|
1263
|
+
const params = [];
|
|
1264
|
+
if (changes.geometry) {
|
|
1265
|
+
const geometry = GaiaLineCodec.writeMultiLineStringZ(
|
|
1266
|
+
changes.geometry,
|
|
1267
|
+
changes.geometry.srid ?? this.info.srid ?? 0
|
|
1268
|
+
);
|
|
1269
|
+
setClauses.push('"SmGeometry" = ?');
|
|
1270
|
+
params.push(geometry);
|
|
1271
|
+
}
|
|
1272
|
+
if (changes.attributes) {
|
|
1273
|
+
const userFields = await this.getFields();
|
|
1274
|
+
const fieldNames = new Set(userFields.map((f) => f.name));
|
|
1275
|
+
const validEntries = Object.entries(changes.attributes).filter(
|
|
1276
|
+
([key]) => fieldNames.has(key)
|
|
1277
|
+
);
|
|
1278
|
+
for (const [key, value] of validEntries) {
|
|
1279
|
+
setClauses.push(`"${key}" = ?`);
|
|
1280
|
+
params.push(value);
|
|
1281
|
+
}
|
|
1282
|
+
}
|
|
1283
|
+
if (setClauses.length === 0) {
|
|
1284
|
+
return;
|
|
1285
|
+
}
|
|
1286
|
+
const sql = `UPDATE "${this.info.tableName}" SET ${setClauses.join(", ")} WHERE SmID = ?`;
|
|
1287
|
+
params.push(id);
|
|
1288
|
+
await this.driver.transaction(async () => {
|
|
1289
|
+
await executeSql(this.driver, sql, params);
|
|
1290
|
+
});
|
|
1291
|
+
}
|
|
1292
|
+
async delete(id) {
|
|
1293
|
+
await this.driver.transaction(async () => {
|
|
1294
|
+
await executeSql(
|
|
1295
|
+
this.driver,
|
|
1296
|
+
`DELETE FROM "${this.info.tableName}" WHERE SmID = ?`,
|
|
1297
|
+
[id]
|
|
1298
|
+
);
|
|
1299
|
+
await this.registerRepository.decrementObjectCount(this.info.id);
|
|
1300
|
+
});
|
|
1301
|
+
}
|
|
1302
|
+
static async create(driver, registerRepository, params) {
|
|
1303
|
+
const fields = params.fields ?? [];
|
|
1304
|
+
const datasetId = await registerRepository.insert({
|
|
1305
|
+
name: params.name,
|
|
1306
|
+
kind: "lineZ",
|
|
1307
|
+
srid: params.srid,
|
|
1308
|
+
idColumnName: "SmID",
|
|
1309
|
+
geometryColumnName: "SmGeometry"
|
|
1310
|
+
});
|
|
1311
|
+
const userColumnDefinitions = fields.map((field) => {
|
|
1312
|
+
const nullability = field.nullable ? "" : " NOT NULL";
|
|
1313
|
+
return `"${field.name}" ${sqliteColumnType(field)}${nullability}`;
|
|
1314
|
+
});
|
|
1315
|
+
const createTableParts = [
|
|
1316
|
+
`"SmID" INTEGER NOT NULL PRIMARY KEY`,
|
|
1317
|
+
`"SmUserID" INTEGER DEFAULT 0 NOT NULL`,
|
|
1318
|
+
`"SmGeometry" BLOB NOT NULL`,
|
|
1319
|
+
...userColumnDefinitions
|
|
1320
|
+
];
|
|
1321
|
+
await driver.exec(
|
|
1322
|
+
`CREATE TABLE "${params.name}" (${createTableParts.join(", ")})`
|
|
1323
|
+
);
|
|
1324
|
+
await executeSql(
|
|
1325
|
+
driver,
|
|
1326
|
+
`INSERT INTO geometry_columns (
|
|
1327
|
+
f_table_name,
|
|
1328
|
+
f_geometry_column,
|
|
1329
|
+
geometry_type,
|
|
1330
|
+
coord_dimension,
|
|
1331
|
+
srid,
|
|
1332
|
+
spatial_index_enabled
|
|
1333
|
+
) VALUES (?, ?, ?, ?, ?, ?)`,
|
|
1334
|
+
[params.name, "SmGeometry", 1005, 3, params.srid, 0]
|
|
1335
|
+
);
|
|
1336
|
+
if (fields.length > 0) {
|
|
1337
|
+
const fieldInfoRepository = new SmFieldInfoRepository(driver);
|
|
1338
|
+
await fieldInfoRepository.insertAll(datasetId, fields);
|
|
1339
|
+
}
|
|
1340
|
+
return new _LineZDataset(driver, {
|
|
1341
|
+
id: datasetId,
|
|
1342
|
+
name: params.name,
|
|
1343
|
+
kind: "lineZ",
|
|
1344
|
+
tableName: params.name,
|
|
1345
|
+
srid: params.srid,
|
|
1346
|
+
objectCount: 0,
|
|
1347
|
+
geometryType: 1005
|
|
1348
|
+
});
|
|
1349
|
+
}
|
|
1350
|
+
};
|
|
1351
|
+
|
|
1352
|
+
// src/core/dataset/PointDataset.ts
|
|
1353
|
+
function mapPointRow(row) {
|
|
1354
|
+
const { SmID, SmGeometry, ...attributes } = row;
|
|
1355
|
+
return {
|
|
1356
|
+
id: SmID,
|
|
1357
|
+
geometry: GaiaPointCodec.readPoint(normalizeGeometryBlob(SmGeometry)),
|
|
1358
|
+
attributes
|
|
1359
|
+
};
|
|
1360
|
+
}
|
|
1361
|
+
var PointDataset = class _PointDataset extends BaseDataset {
|
|
1362
|
+
constructor(driver, info) {
|
|
1363
|
+
super(driver, info);
|
|
1364
|
+
__publicField(this, "registerRepository");
|
|
1365
|
+
this.registerRepository = new SmRegisterRepository(driver);
|
|
1366
|
+
}
|
|
1367
|
+
async getById(id) {
|
|
1368
|
+
const row = await queryOne(
|
|
1369
|
+
this.driver,
|
|
1370
|
+
`SELECT * FROM "${this.info.tableName}" WHERE SmID = ?`,
|
|
1371
|
+
[id]
|
|
1372
|
+
);
|
|
1373
|
+
return row ? mapPointRow(row) : null;
|
|
1374
|
+
}
|
|
1375
|
+
async list(options) {
|
|
1376
|
+
const { sql, params } = buildListSql(this.info.tableName, options);
|
|
1377
|
+
const rows = await queryAll(this.driver, sql, params);
|
|
1378
|
+
return rows.map((row) => mapPointRow(row));
|
|
1379
|
+
}
|
|
1380
|
+
async *iterate(options) {
|
|
1381
|
+
const { sql, params } = buildListSql(this.info.tableName, options);
|
|
1382
|
+
const statement = await this.driver.prepare(sql);
|
|
1383
|
+
try {
|
|
1384
|
+
if (params.length > 0) {
|
|
1385
|
+
await statement.bind(params);
|
|
1386
|
+
}
|
|
1387
|
+
while (await statement.step()) {
|
|
1388
|
+
yield mapPointRow(await statement.getRow());
|
|
1389
|
+
}
|
|
1390
|
+
} finally {
|
|
1391
|
+
await statement.finalize();
|
|
1392
|
+
}
|
|
1393
|
+
}
|
|
1394
|
+
async insert(feature) {
|
|
1395
|
+
const userFields = await this.getFields();
|
|
1396
|
+
const columnNames = ["SmID", "SmUserID", "SmGeometry", ...userFields.map((field) => field.name)];
|
|
1397
|
+
const placeholders = columnNames.map(() => "?").join(", ");
|
|
1398
|
+
const geometry = GaiaPointCodec.writePoint(feature.geometry, feature.geometry.srid ?? this.info.srid ?? 0);
|
|
1399
|
+
const sql = `INSERT INTO "${this.info.tableName}" (${columnNames.map((column) => `"${column}"`).join(", ")}) VALUES (${placeholders})`;
|
|
1400
|
+
const params = [
|
|
1401
|
+
feature.id,
|
|
1402
|
+
0,
|
|
1403
|
+
geometry,
|
|
1404
|
+
...userFields.map((field) => feature.attributes[field.name] ?? null)
|
|
1405
|
+
];
|
|
1406
|
+
await this.driver.transaction(async () => {
|
|
1407
|
+
await executeSql(this.driver, sql, params);
|
|
1408
|
+
await this.registerRepository.incrementObjectCount(this.info.id, geometry.byteLength);
|
|
1409
|
+
});
|
|
1410
|
+
}
|
|
1411
|
+
async insertMany(features) {
|
|
1412
|
+
const userFields = await this.getFields();
|
|
1413
|
+
const columnNames = ["SmID", "SmUserID", "SmGeometry", ...userFields.map((field) => field.name)];
|
|
1414
|
+
const placeholders = columnNames.map(() => "?").join(", ");
|
|
1415
|
+
const sql = `INSERT INTO "${this.info.tableName}" (${columnNames.map((column) => `"${column}"`).join(", ")}) VALUES (${placeholders})`;
|
|
1416
|
+
await this.driver.transaction(async () => {
|
|
1417
|
+
const statement = await this.driver.prepare(sql);
|
|
1418
|
+
try {
|
|
1419
|
+
let count = 0;
|
|
1420
|
+
let maxGeometrySize = 0;
|
|
1421
|
+
for await (const feature of features) {
|
|
1422
|
+
const geometry = GaiaPointCodec.writePoint(
|
|
1423
|
+
feature.geometry,
|
|
1424
|
+
feature.geometry.srid ?? this.info.srid ?? 0
|
|
1425
|
+
);
|
|
1426
|
+
maxGeometrySize = Math.max(maxGeometrySize, geometry.byteLength);
|
|
1427
|
+
const params = [
|
|
1428
|
+
feature.id,
|
|
1429
|
+
0,
|
|
1430
|
+
geometry,
|
|
1431
|
+
...userFields.map(
|
|
1432
|
+
(field) => feature.attributes[field.name] ?? null
|
|
1433
|
+
)
|
|
1434
|
+
];
|
|
1435
|
+
await statement.bind(params);
|
|
1436
|
+
await statement.step();
|
|
1437
|
+
await statement.reset();
|
|
1438
|
+
count++;
|
|
1439
|
+
}
|
|
1440
|
+
if (count > 0) {
|
|
1441
|
+
await this.registerRepository.incrementObjectCountBatch(
|
|
1442
|
+
this.info.id,
|
|
1443
|
+
count,
|
|
1444
|
+
maxGeometrySize
|
|
1445
|
+
);
|
|
1446
|
+
}
|
|
1447
|
+
} finally {
|
|
1448
|
+
await statement.finalize();
|
|
1449
|
+
}
|
|
1450
|
+
});
|
|
1451
|
+
}
|
|
1452
|
+
async count() {
|
|
1453
|
+
const row = await queryOne(
|
|
1454
|
+
this.driver,
|
|
1455
|
+
`SELECT COUNT(*) AS count FROM "${this.info.tableName}"`,
|
|
1456
|
+
[]
|
|
1457
|
+
);
|
|
1458
|
+
return row?.count ?? 0;
|
|
1459
|
+
}
|
|
1460
|
+
async update(id, changes) {
|
|
1461
|
+
if (!changes.geometry && !changes.attributes) {
|
|
1462
|
+
return;
|
|
1463
|
+
}
|
|
1464
|
+
const setClauses = [];
|
|
1465
|
+
const params = [];
|
|
1466
|
+
if (changes.geometry) {
|
|
1467
|
+
const geometry = GaiaPointCodec.writePoint(
|
|
1468
|
+
changes.geometry,
|
|
1469
|
+
changes.geometry.srid ?? this.info.srid ?? 0
|
|
1470
|
+
);
|
|
1471
|
+
setClauses.push('"SmGeometry" = ?');
|
|
1472
|
+
params.push(geometry);
|
|
1473
|
+
}
|
|
1474
|
+
if (changes.attributes) {
|
|
1475
|
+
const userFields = await this.getFields();
|
|
1476
|
+
const fieldNames = new Set(userFields.map((f) => f.name));
|
|
1477
|
+
const validEntries = Object.entries(changes.attributes).filter(
|
|
1478
|
+
([key]) => fieldNames.has(key)
|
|
1479
|
+
);
|
|
1480
|
+
for (const [key, value] of validEntries) {
|
|
1481
|
+
setClauses.push(`"${key}" = ?`);
|
|
1482
|
+
params.push(value);
|
|
1483
|
+
}
|
|
1484
|
+
}
|
|
1485
|
+
if (setClauses.length === 0) {
|
|
1486
|
+
return;
|
|
1487
|
+
}
|
|
1488
|
+
const sql = `UPDATE "${this.info.tableName}" SET ${setClauses.join(", ")} WHERE SmID = ?`;
|
|
1489
|
+
params.push(id);
|
|
1490
|
+
await this.driver.transaction(async () => {
|
|
1491
|
+
await executeSql(this.driver, sql, params);
|
|
1492
|
+
});
|
|
1493
|
+
}
|
|
1494
|
+
async delete(id) {
|
|
1495
|
+
await this.driver.transaction(async () => {
|
|
1496
|
+
await executeSql(
|
|
1497
|
+
this.driver,
|
|
1498
|
+
`DELETE FROM "${this.info.tableName}" WHERE SmID = ?`,
|
|
1499
|
+
[id]
|
|
1500
|
+
);
|
|
1501
|
+
await this.registerRepository.decrementObjectCount(this.info.id);
|
|
1502
|
+
});
|
|
1503
|
+
}
|
|
1504
|
+
static async create(driver, registerRepository, params) {
|
|
1505
|
+
const fields = params.fields ?? [];
|
|
1506
|
+
const datasetId = await registerRepository.insert({
|
|
1507
|
+
name: params.name,
|
|
1508
|
+
kind: "point",
|
|
1509
|
+
srid: params.srid,
|
|
1510
|
+
idColumnName: "SmID",
|
|
1511
|
+
geometryColumnName: "SmGeometry"
|
|
1512
|
+
});
|
|
1513
|
+
const userColumnDefinitions = fields.map((field) => {
|
|
1514
|
+
const nullability = field.nullable ? "" : " NOT NULL";
|
|
1515
|
+
return `"${field.name}" ${sqliteColumnType(field)}${nullability}`;
|
|
1516
|
+
});
|
|
1517
|
+
const createTableParts = [
|
|
1518
|
+
`"SmID" INTEGER NOT NULL PRIMARY KEY`,
|
|
1519
|
+
`"SmUserID" INTEGER DEFAULT 0 NOT NULL`,
|
|
1520
|
+
`"SmGeometry" BLOB NOT NULL`,
|
|
1521
|
+
...userColumnDefinitions
|
|
1522
|
+
];
|
|
1523
|
+
await driver.exec(
|
|
1524
|
+
`CREATE TABLE "${params.name}" (${createTableParts.join(", ")})`
|
|
1525
|
+
);
|
|
1526
|
+
await executeSql(
|
|
1527
|
+
driver,
|
|
1528
|
+
`INSERT INTO geometry_columns (
|
|
1529
|
+
f_table_name,
|
|
1530
|
+
f_geometry_column,
|
|
1531
|
+
geometry_type,
|
|
1532
|
+
coord_dimension,
|
|
1533
|
+
srid,
|
|
1534
|
+
spatial_index_enabled
|
|
1535
|
+
) VALUES (?, ?, ?, ?, ?, ?)`,
|
|
1536
|
+
[params.name, "SmGeometry", 1, 2, params.srid, 0]
|
|
1537
|
+
);
|
|
1538
|
+
if (fields.length > 0) {
|
|
1539
|
+
const fieldInfoRepository = new SmFieldInfoRepository(driver);
|
|
1540
|
+
await fieldInfoRepository.insertAll(datasetId, fields);
|
|
1541
|
+
}
|
|
1542
|
+
return new _PointDataset(driver, {
|
|
1543
|
+
id: datasetId,
|
|
1544
|
+
name: params.name,
|
|
1545
|
+
kind: "point",
|
|
1546
|
+
tableName: params.name,
|
|
1547
|
+
srid: params.srid,
|
|
1548
|
+
objectCount: 0,
|
|
1549
|
+
geometryType: 1
|
|
1550
|
+
});
|
|
1551
|
+
}
|
|
1552
|
+
};
|
|
1553
|
+
|
|
1554
|
+
// src/core/dataset/PointZDataset.ts
|
|
1555
|
+
function mapPointZRow(row) {
|
|
1556
|
+
const { SmID, SmGeometry, ...attributes } = row;
|
|
1557
|
+
return {
|
|
1558
|
+
id: SmID,
|
|
1559
|
+
geometry: GaiaPointCodec.readPointZ(normalizeGeometryBlob(SmGeometry)),
|
|
1560
|
+
attributes
|
|
1561
|
+
};
|
|
1562
|
+
}
|
|
1563
|
+
var PointZDataset = class _PointZDataset extends BaseDataset {
|
|
1564
|
+
constructor(driver, info) {
|
|
1565
|
+
super(driver, info);
|
|
1566
|
+
__publicField(this, "registerRepository");
|
|
1567
|
+
this.registerRepository = new SmRegisterRepository(driver);
|
|
1568
|
+
}
|
|
1569
|
+
async getById(id) {
|
|
1570
|
+
const row = await queryOne(
|
|
1571
|
+
this.driver,
|
|
1572
|
+
`SELECT * FROM "${this.info.tableName}" WHERE SmID = ?`,
|
|
1573
|
+
[id]
|
|
1574
|
+
);
|
|
1575
|
+
return row ? mapPointZRow(row) : null;
|
|
1576
|
+
}
|
|
1577
|
+
async list(options) {
|
|
1578
|
+
const { sql, params } = buildListSql(this.info.tableName, options);
|
|
1579
|
+
const rows = await queryAll(this.driver, sql, params);
|
|
1580
|
+
return rows.map((row) => mapPointZRow(row));
|
|
1581
|
+
}
|
|
1582
|
+
async *iterate(options) {
|
|
1583
|
+
const { sql, params } = buildListSql(this.info.tableName, options);
|
|
1584
|
+
const statement = await this.driver.prepare(sql);
|
|
1585
|
+
try {
|
|
1586
|
+
if (params.length > 0) {
|
|
1587
|
+
await statement.bind(params);
|
|
1588
|
+
}
|
|
1589
|
+
while (await statement.step()) {
|
|
1590
|
+
yield mapPointZRow(await statement.getRow());
|
|
1591
|
+
}
|
|
1592
|
+
} finally {
|
|
1593
|
+
await statement.finalize();
|
|
1594
|
+
}
|
|
1595
|
+
}
|
|
1596
|
+
async count() {
|
|
1597
|
+
const row = await queryOne(
|
|
1598
|
+
this.driver,
|
|
1599
|
+
`SELECT COUNT(*) AS count FROM "${this.info.tableName}"`,
|
|
1600
|
+
[]
|
|
1601
|
+
);
|
|
1602
|
+
return row?.count ?? 0;
|
|
1603
|
+
}
|
|
1604
|
+
async insert(feature) {
|
|
1605
|
+
const userFields = await this.getFields();
|
|
1606
|
+
const columnNames = ["SmID", "SmUserID", "SmGeometry", ...userFields.map((field) => field.name)];
|
|
1607
|
+
const placeholders = columnNames.map(() => "?").join(", ");
|
|
1608
|
+
const geometry = GaiaPointCodec.writePointZ(
|
|
1609
|
+
feature.geometry,
|
|
1610
|
+
feature.geometry.srid ?? this.info.srid ?? 0
|
|
1611
|
+
);
|
|
1612
|
+
const sql = `INSERT INTO "${this.info.tableName}" (${columnNames.map((column) => `"${column}"`).join(", ")}) VALUES (${placeholders})`;
|
|
1613
|
+
const params = [
|
|
1614
|
+
feature.id,
|
|
1615
|
+
0,
|
|
1616
|
+
geometry,
|
|
1617
|
+
...userFields.map((field) => feature.attributes[field.name] ?? null)
|
|
1618
|
+
];
|
|
1619
|
+
await this.driver.transaction(async () => {
|
|
1620
|
+
await executeSql(this.driver, sql, params);
|
|
1621
|
+
await this.registerRepository.incrementObjectCount(this.info.id, geometry.byteLength);
|
|
1622
|
+
});
|
|
1623
|
+
}
|
|
1624
|
+
async insertMany(features) {
|
|
1625
|
+
const userFields = await this.getFields();
|
|
1626
|
+
const columnNames = ["SmID", "SmUserID", "SmGeometry", ...userFields.map((field) => field.name)];
|
|
1627
|
+
const placeholders = columnNames.map(() => "?").join(", ");
|
|
1628
|
+
const sql = `INSERT INTO "${this.info.tableName}" (${columnNames.map((column) => `"${column}"`).join(", ")}) VALUES (${placeholders})`;
|
|
1629
|
+
await this.driver.transaction(async () => {
|
|
1630
|
+
const statement = await this.driver.prepare(sql);
|
|
1631
|
+
try {
|
|
1632
|
+
let count = 0;
|
|
1633
|
+
let maxGeometrySize = 0;
|
|
1634
|
+
for await (const feature of features) {
|
|
1635
|
+
const geometry = GaiaPointCodec.writePointZ(
|
|
1636
|
+
feature.geometry,
|
|
1637
|
+
feature.geometry.srid ?? this.info.srid ?? 0
|
|
1638
|
+
);
|
|
1639
|
+
maxGeometrySize = Math.max(maxGeometrySize, geometry.byteLength);
|
|
1640
|
+
const params = [
|
|
1641
|
+
feature.id,
|
|
1642
|
+
0,
|
|
1643
|
+
geometry,
|
|
1644
|
+
...userFields.map(
|
|
1645
|
+
(field) => feature.attributes[field.name] ?? null
|
|
1646
|
+
)
|
|
1647
|
+
];
|
|
1648
|
+
await statement.bind(params);
|
|
1649
|
+
await statement.step();
|
|
1650
|
+
await statement.reset();
|
|
1651
|
+
count++;
|
|
1652
|
+
}
|
|
1653
|
+
if (count > 0) {
|
|
1654
|
+
await this.registerRepository.incrementObjectCountBatch(
|
|
1655
|
+
this.info.id,
|
|
1656
|
+
count,
|
|
1657
|
+
maxGeometrySize
|
|
1658
|
+
);
|
|
1659
|
+
}
|
|
1660
|
+
} finally {
|
|
1661
|
+
await statement.finalize();
|
|
1662
|
+
}
|
|
1663
|
+
});
|
|
1664
|
+
}
|
|
1665
|
+
async update(id, changes) {
|
|
1666
|
+
if (!changes.geometry && !changes.attributes) {
|
|
1667
|
+
return;
|
|
1668
|
+
}
|
|
1669
|
+
const setClauses = [];
|
|
1670
|
+
const params = [];
|
|
1671
|
+
if (changes.geometry) {
|
|
1672
|
+
const geometry = GaiaPointCodec.writePointZ(
|
|
1673
|
+
changes.geometry,
|
|
1674
|
+
changes.geometry.srid ?? this.info.srid ?? 0
|
|
1675
|
+
);
|
|
1676
|
+
setClauses.push('"SmGeometry" = ?');
|
|
1677
|
+
params.push(geometry);
|
|
1678
|
+
}
|
|
1679
|
+
if (changes.attributes) {
|
|
1680
|
+
const userFields = await this.getFields();
|
|
1681
|
+
const fieldNames = new Set(userFields.map((f) => f.name));
|
|
1682
|
+
const validEntries = Object.entries(changes.attributes).filter(
|
|
1683
|
+
([key]) => fieldNames.has(key)
|
|
1684
|
+
);
|
|
1685
|
+
for (const [key, value] of validEntries) {
|
|
1686
|
+
setClauses.push(`"${key}" = ?`);
|
|
1687
|
+
params.push(value);
|
|
1688
|
+
}
|
|
1689
|
+
}
|
|
1690
|
+
if (setClauses.length === 0) {
|
|
1691
|
+
return;
|
|
1692
|
+
}
|
|
1693
|
+
const sql = `UPDATE "${this.info.tableName}" SET ${setClauses.join(", ")} WHERE SmID = ?`;
|
|
1694
|
+
params.push(id);
|
|
1695
|
+
await this.driver.transaction(async () => {
|
|
1696
|
+
await executeSql(this.driver, sql, params);
|
|
1697
|
+
});
|
|
1698
|
+
}
|
|
1699
|
+
async delete(id) {
|
|
1700
|
+
await this.driver.transaction(async () => {
|
|
1701
|
+
await executeSql(
|
|
1702
|
+
this.driver,
|
|
1703
|
+
`DELETE FROM "${this.info.tableName}" WHERE SmID = ?`,
|
|
1704
|
+
[id]
|
|
1705
|
+
);
|
|
1706
|
+
await this.registerRepository.decrementObjectCount(this.info.id);
|
|
1707
|
+
});
|
|
1708
|
+
}
|
|
1709
|
+
static async create(driver, registerRepository, params) {
|
|
1710
|
+
const fields = params.fields ?? [];
|
|
1711
|
+
const datasetId = await registerRepository.insert({
|
|
1712
|
+
name: params.name,
|
|
1713
|
+
kind: "pointZ",
|
|
1714
|
+
srid: params.srid,
|
|
1715
|
+
idColumnName: "SmID",
|
|
1716
|
+
geometryColumnName: "SmGeometry"
|
|
1717
|
+
});
|
|
1718
|
+
const userColumnDefinitions = fields.map((field) => {
|
|
1719
|
+
const nullability = field.nullable ? "" : " NOT NULL";
|
|
1720
|
+
return `"${field.name}" ${sqliteColumnType(field)}${nullability}`;
|
|
1721
|
+
});
|
|
1722
|
+
const createTableParts = [
|
|
1723
|
+
`"SmID" INTEGER NOT NULL PRIMARY KEY`,
|
|
1724
|
+
`"SmUserID" INTEGER DEFAULT 0 NOT NULL`,
|
|
1725
|
+
`"SmGeometry" BLOB NOT NULL`,
|
|
1726
|
+
...userColumnDefinitions
|
|
1727
|
+
];
|
|
1728
|
+
await driver.exec(
|
|
1729
|
+
`CREATE TABLE "${params.name}" (${createTableParts.join(", ")})`
|
|
1730
|
+
);
|
|
1731
|
+
await executeSql(
|
|
1732
|
+
driver,
|
|
1733
|
+
`INSERT INTO geometry_columns (
|
|
1734
|
+
f_table_name,
|
|
1735
|
+
f_geometry_column,
|
|
1736
|
+
geometry_type,
|
|
1737
|
+
coord_dimension,
|
|
1738
|
+
srid,
|
|
1739
|
+
spatial_index_enabled
|
|
1740
|
+
) VALUES (?, ?, ?, ?, ?, ?)`,
|
|
1741
|
+
[params.name, "SmGeometry", 1001, 3, params.srid, 0]
|
|
1742
|
+
);
|
|
1743
|
+
if (fields.length > 0) {
|
|
1744
|
+
const fieldInfoRepository = new SmFieldInfoRepository(driver);
|
|
1745
|
+
await fieldInfoRepository.insertAll(datasetId, fields);
|
|
1746
|
+
}
|
|
1747
|
+
return new _PointZDataset(driver, {
|
|
1748
|
+
id: datasetId,
|
|
1749
|
+
name: params.name,
|
|
1750
|
+
kind: "pointZ",
|
|
1751
|
+
tableName: params.name,
|
|
1752
|
+
srid: params.srid,
|
|
1753
|
+
objectCount: 0,
|
|
1754
|
+
geometryType: 1001
|
|
1755
|
+
});
|
|
1756
|
+
}
|
|
1757
|
+
};
|
|
1758
|
+
|
|
1759
|
+
// src/core/geometry/gaia/GaiaPolygonCodec.ts
|
|
1760
|
+
var GAIA_ENTITY_MARK2 = 105;
|
|
1761
|
+
var GEO_TYPE_POLYGON = 3;
|
|
1762
|
+
var GEO_TYPE_POLYGONZ = 1003;
|
|
1763
|
+
function is3DCoordinates2(coordinates) {
|
|
1764
|
+
return coordinates[0]?.[0]?.[0]?.length === 3;
|
|
1765
|
+
}
|
|
1766
|
+
function createPolygonMbr(coordinates) {
|
|
1767
|
+
const xs = [];
|
|
1768
|
+
const ys = [];
|
|
1769
|
+
for (const polygon of coordinates) {
|
|
1770
|
+
for (const ring of polygon) {
|
|
1771
|
+
for (const point of ring) {
|
|
1772
|
+
xs.push(point[0]);
|
|
1773
|
+
ys.push(point[1]);
|
|
1774
|
+
}
|
|
1775
|
+
}
|
|
1776
|
+
}
|
|
1777
|
+
if (xs.length === 0) {
|
|
1778
|
+
throw new GaiaFormatError("MultiPolygon must contain at least one point.");
|
|
1779
|
+
}
|
|
1780
|
+
return [
|
|
1781
|
+
Math.min(...xs),
|
|
1782
|
+
Math.min(...ys),
|
|
1783
|
+
Math.max(...xs),
|
|
1784
|
+
Math.max(...ys)
|
|
1785
|
+
];
|
|
1786
|
+
}
|
|
1787
|
+
function writeRing2D(writer2, ring) {
|
|
1788
|
+
writer2.writeInt32(ring.length, true);
|
|
1789
|
+
for (const point of ring) {
|
|
1790
|
+
writer2.writeFloat64(point[0], true);
|
|
1791
|
+
writer2.writeFloat64(point[1], true);
|
|
1792
|
+
}
|
|
1793
|
+
}
|
|
1794
|
+
function writeRing3D(writer2, ring) {
|
|
1795
|
+
writer2.writeInt32(ring.length, true);
|
|
1796
|
+
for (const point of ring) {
|
|
1797
|
+
writer2.writeFloat64(point[0], true);
|
|
1798
|
+
writer2.writeFloat64(point[1], true);
|
|
1799
|
+
writer2.writeFloat64(point[2], true);
|
|
1800
|
+
}
|
|
1801
|
+
}
|
|
1802
|
+
function readRing2D(cursor) {
|
|
1803
|
+
const pointCount = cursor.readInt32(true);
|
|
1804
|
+
const ring = [];
|
|
1805
|
+
for (let pointIndex = 0; pointIndex < pointCount; pointIndex += 1) {
|
|
1806
|
+
ring.push([cursor.readFloat64(true), cursor.readFloat64(true)]);
|
|
1807
|
+
}
|
|
1808
|
+
return ring;
|
|
1809
|
+
}
|
|
1810
|
+
function readRing3D(cursor) {
|
|
1811
|
+
const pointCount = cursor.readInt32(true);
|
|
1812
|
+
const ring = [];
|
|
1813
|
+
for (let pointIndex = 0; pointIndex < pointCount; pointIndex += 1) {
|
|
1814
|
+
ring.push([
|
|
1815
|
+
cursor.readFloat64(true),
|
|
1816
|
+
cursor.readFloat64(true),
|
|
1817
|
+
cursor.readFloat64(true)
|
|
1818
|
+
]);
|
|
1819
|
+
}
|
|
1820
|
+
return ring;
|
|
1821
|
+
}
|
|
1822
|
+
var GaiaPolygonCodec = class {
|
|
1823
|
+
static readMultiPolygon(input) {
|
|
1824
|
+
const cursor = new BinaryCursor(input);
|
|
1825
|
+
const header = readGaiaHeader(cursor, GEO_TYPE_MULTIPOLYGON);
|
|
1826
|
+
const polygonCount = cursor.readInt32(true);
|
|
1827
|
+
const coordinates = [];
|
|
1828
|
+
for (let polygonIndex = 0; polygonIndex < polygonCount; polygonIndex += 1) {
|
|
1829
|
+
const entityMark = cursor.readUint8();
|
|
1830
|
+
if (entityMark !== GAIA_ENTITY_MARK2) {
|
|
1831
|
+
throw new GaiaFormatError(
|
|
1832
|
+
`Invalid Polygon entity mark: expected 0x${GAIA_ENTITY_MARK2.toString(16)}, got 0x${entityMark.toString(16)}.`
|
|
1833
|
+
);
|
|
1834
|
+
}
|
|
1835
|
+
const polygonGeoType = cursor.readInt32(true);
|
|
1836
|
+
if (polygonGeoType !== GEO_TYPE_POLYGON) {
|
|
1837
|
+
throw new GaiaFormatError(
|
|
1838
|
+
`Invalid Polygon geoType: expected ${GEO_TYPE_POLYGON}, got ${polygonGeoType}.`
|
|
1839
|
+
);
|
|
1840
|
+
}
|
|
1841
|
+
const ringCount = cursor.readInt32(true);
|
|
1842
|
+
if (ringCount < 1) {
|
|
1843
|
+
throw new GaiaFormatError(
|
|
1844
|
+
`Polygon must contain at least one ring, got ${ringCount}.`
|
|
1845
|
+
);
|
|
1846
|
+
}
|
|
1847
|
+
const polygon = [];
|
|
1848
|
+
for (let ringIndex = 0; ringIndex < ringCount; ringIndex += 1) {
|
|
1849
|
+
polygon.push(readRing2D(cursor));
|
|
1850
|
+
}
|
|
1851
|
+
coordinates.push(polygon);
|
|
1852
|
+
}
|
|
1853
|
+
validateGaiaEnd(cursor);
|
|
1854
|
+
return {
|
|
1855
|
+
type: "MultiPolygon",
|
|
1856
|
+
coordinates,
|
|
1857
|
+
srid: header.srid,
|
|
1858
|
+
bbox: header.mbr,
|
|
1859
|
+
hasZ: false,
|
|
1860
|
+
geoType: header.geoType
|
|
1861
|
+
};
|
|
1862
|
+
}
|
|
1863
|
+
static readMultiPolygonZ(input) {
|
|
1864
|
+
const cursor = new BinaryCursor(input);
|
|
1865
|
+
const header = readGaiaHeader(cursor, GEO_TYPE_MULTIPOLYGONZ);
|
|
1866
|
+
const polygonCount = cursor.readInt32(true);
|
|
1867
|
+
const coordinates = [];
|
|
1868
|
+
for (let polygonIndex = 0; polygonIndex < polygonCount; polygonIndex += 1) {
|
|
1869
|
+
const entityMark = cursor.readUint8();
|
|
1870
|
+
if (entityMark !== GAIA_ENTITY_MARK2) {
|
|
1871
|
+
throw new GaiaFormatError(
|
|
1872
|
+
`Invalid Polygon entity mark: expected 0x${GAIA_ENTITY_MARK2.toString(16)}, got 0x${entityMark.toString(16)}.`
|
|
1873
|
+
);
|
|
1874
|
+
}
|
|
1875
|
+
const polygonGeoType = cursor.readInt32(true);
|
|
1876
|
+
if (polygonGeoType !== GEO_TYPE_POLYGONZ) {
|
|
1877
|
+
throw new GaiaFormatError(
|
|
1878
|
+
`Invalid PolygonZ geoType: expected ${GEO_TYPE_POLYGONZ}, got ${polygonGeoType}.`
|
|
1879
|
+
);
|
|
1880
|
+
}
|
|
1881
|
+
const ringCount = cursor.readInt32(true);
|
|
1882
|
+
if (ringCount < 1) {
|
|
1883
|
+
throw new GaiaFormatError(
|
|
1884
|
+
`Polygon must contain at least one ring, got ${ringCount}.`
|
|
1885
|
+
);
|
|
1886
|
+
}
|
|
1887
|
+
const polygon = [];
|
|
1888
|
+
for (let ringIndex = 0; ringIndex < ringCount; ringIndex += 1) {
|
|
1889
|
+
polygon.push(readRing3D(cursor));
|
|
1890
|
+
}
|
|
1891
|
+
coordinates.push(polygon);
|
|
1892
|
+
}
|
|
1893
|
+
validateGaiaEnd(cursor);
|
|
1894
|
+
return {
|
|
1895
|
+
type: "MultiPolygon",
|
|
1896
|
+
coordinates,
|
|
1897
|
+
srid: header.srid,
|
|
1898
|
+
bbox: header.mbr,
|
|
1899
|
+
hasZ: true,
|
|
1900
|
+
geoType: header.geoType
|
|
1901
|
+
};
|
|
1902
|
+
}
|
|
1903
|
+
static writeMultiPolygon(geometry, srid) {
|
|
1904
|
+
if (is3DCoordinates2(geometry.coordinates)) {
|
|
1905
|
+
throw new GaiaFormatError("writeMultiPolygon expects 2D coordinates.");
|
|
1906
|
+
}
|
|
1907
|
+
const writer2 = new BinaryWriter();
|
|
1908
|
+
writeGaiaHeader(
|
|
1909
|
+
writer2,
|
|
1910
|
+
srid,
|
|
1911
|
+
createPolygonMbr(geometry.coordinates),
|
|
1912
|
+
GEO_TYPE_MULTIPOLYGON
|
|
1913
|
+
);
|
|
1914
|
+
writer2.writeInt32(geometry.coordinates.length, true);
|
|
1915
|
+
for (const polygon of geometry.coordinates) {
|
|
1916
|
+
writer2.writeUint8(GAIA_ENTITY_MARK2);
|
|
1917
|
+
writer2.writeInt32(GEO_TYPE_POLYGON, true);
|
|
1918
|
+
writer2.writeInt32(polygon.length, true);
|
|
1919
|
+
for (const ring of polygon) {
|
|
1920
|
+
writeRing2D(writer2, ring);
|
|
1921
|
+
}
|
|
1922
|
+
}
|
|
1923
|
+
writer2.writeUint8(GAIA_END);
|
|
1924
|
+
return writer2.toUint8Array();
|
|
1925
|
+
}
|
|
1926
|
+
static writeMultiPolygonZ(geometry, srid) {
|
|
1927
|
+
if (!is3DCoordinates2(geometry.coordinates)) {
|
|
1928
|
+
throw new GaiaFormatError("writeMultiPolygonZ expects 3D coordinates.");
|
|
1929
|
+
}
|
|
1930
|
+
const writer2 = new BinaryWriter();
|
|
1931
|
+
writeGaiaHeader(
|
|
1932
|
+
writer2,
|
|
1933
|
+
srid,
|
|
1934
|
+
createPolygonMbr(geometry.coordinates),
|
|
1935
|
+
GEO_TYPE_MULTIPOLYGONZ
|
|
1936
|
+
);
|
|
1937
|
+
writer2.writeInt32(geometry.coordinates.length, true);
|
|
1938
|
+
for (const polygon of geometry.coordinates) {
|
|
1939
|
+
writer2.writeUint8(GAIA_ENTITY_MARK2);
|
|
1940
|
+
writer2.writeInt32(GEO_TYPE_POLYGONZ, true);
|
|
1941
|
+
writer2.writeInt32(polygon.length, true);
|
|
1942
|
+
for (const ring of polygon) {
|
|
1943
|
+
writeRing3D(writer2, ring);
|
|
1944
|
+
}
|
|
1945
|
+
}
|
|
1946
|
+
writer2.writeUint8(GAIA_END);
|
|
1947
|
+
return writer2.toUint8Array();
|
|
1948
|
+
}
|
|
1949
|
+
};
|
|
1950
|
+
|
|
1951
|
+
// src/core/dataset/RegionDataset.ts
|
|
1952
|
+
function mapRegionRow(row) {
|
|
1953
|
+
const { SmID, SmGeometry, ...attributes } = row;
|
|
1954
|
+
return {
|
|
1955
|
+
id: SmID,
|
|
1956
|
+
geometry: GaiaPolygonCodec.readMultiPolygon(normalizeGeometryBlob(SmGeometry)),
|
|
1957
|
+
attributes
|
|
1958
|
+
};
|
|
1959
|
+
}
|
|
1960
|
+
var RegionDataset = class _RegionDataset extends BaseDataset {
|
|
1961
|
+
constructor(driver, info) {
|
|
1962
|
+
super(driver, info);
|
|
1963
|
+
__publicField(this, "registerRepository");
|
|
1964
|
+
this.registerRepository = new SmRegisterRepository(driver);
|
|
1965
|
+
}
|
|
1966
|
+
async getById(id) {
|
|
1967
|
+
const row = await queryOne(
|
|
1968
|
+
this.driver,
|
|
1969
|
+
`SELECT * FROM "${this.info.tableName}" WHERE SmID = ?`,
|
|
1970
|
+
[id]
|
|
1971
|
+
);
|
|
1972
|
+
return row ? mapRegionRow(row) : null;
|
|
1973
|
+
}
|
|
1974
|
+
async list(options) {
|
|
1975
|
+
const { sql, params } = buildListSql(this.info.tableName, options);
|
|
1976
|
+
const rows = await queryAll(this.driver, sql, params);
|
|
1977
|
+
return rows.map((row) => mapRegionRow(row));
|
|
1978
|
+
}
|
|
1979
|
+
async *iterate(options) {
|
|
1980
|
+
const { sql, params } = buildListSql(this.info.tableName, options);
|
|
1981
|
+
const statement = await this.driver.prepare(sql);
|
|
1982
|
+
try {
|
|
1983
|
+
if (params.length > 0) {
|
|
1984
|
+
await statement.bind(params);
|
|
1985
|
+
}
|
|
1986
|
+
while (await statement.step()) {
|
|
1987
|
+
yield mapRegionRow(
|
|
1988
|
+
await statement.getRow()
|
|
1989
|
+
);
|
|
1990
|
+
}
|
|
1991
|
+
} finally {
|
|
1992
|
+
await statement.finalize();
|
|
1993
|
+
}
|
|
1994
|
+
}
|
|
1995
|
+
async insert(feature) {
|
|
1996
|
+
const userFields = await this.getFields();
|
|
1997
|
+
const columnNames = ["SmID", "SmUserID", "SmGeometry", ...userFields.map((field) => field.name)];
|
|
1998
|
+
const placeholders = columnNames.map(() => "?").join(", ");
|
|
1999
|
+
const geometry = GaiaPolygonCodec.writeMultiPolygon(
|
|
2000
|
+
feature.geometry,
|
|
2001
|
+
feature.geometry.srid ?? this.info.srid ?? 0
|
|
2002
|
+
);
|
|
2003
|
+
const sql = `INSERT INTO "${this.info.tableName}" (${columnNames.map((column) => `"${column}"`).join(", ")}) VALUES (${placeholders})`;
|
|
2004
|
+
const params = [
|
|
2005
|
+
feature.id,
|
|
2006
|
+
0,
|
|
2007
|
+
geometry,
|
|
2008
|
+
...userFields.map((field) => feature.attributes[field.name] ?? null)
|
|
2009
|
+
];
|
|
2010
|
+
await this.driver.transaction(async () => {
|
|
2011
|
+
await executeSql(this.driver, sql, params);
|
|
2012
|
+
await this.registerRepository.incrementObjectCount(this.info.id, geometry.byteLength);
|
|
2013
|
+
});
|
|
2014
|
+
}
|
|
2015
|
+
async insertMany(features) {
|
|
2016
|
+
const userFields = await this.getFields();
|
|
2017
|
+
const columnNames = ["SmID", "SmUserID", "SmGeometry", ...userFields.map((field) => field.name)];
|
|
2018
|
+
const placeholders = columnNames.map(() => "?").join(", ");
|
|
2019
|
+
const sql = `INSERT INTO "${this.info.tableName}" (${columnNames.map((column) => `"${column}"`).join(", ")}) VALUES (${placeholders})`;
|
|
2020
|
+
await this.driver.transaction(async () => {
|
|
2021
|
+
const statement = await this.driver.prepare(sql);
|
|
2022
|
+
try {
|
|
2023
|
+
let count = 0;
|
|
2024
|
+
let maxGeometrySize = 0;
|
|
2025
|
+
for await (const feature of features) {
|
|
2026
|
+
const geometry = GaiaPolygonCodec.writeMultiPolygon(
|
|
2027
|
+
feature.geometry,
|
|
2028
|
+
feature.geometry.srid ?? this.info.srid ?? 0
|
|
2029
|
+
);
|
|
2030
|
+
maxGeometrySize = Math.max(maxGeometrySize, geometry.byteLength);
|
|
2031
|
+
const params = [
|
|
2032
|
+
feature.id,
|
|
2033
|
+
0,
|
|
2034
|
+
geometry,
|
|
2035
|
+
...userFields.map(
|
|
2036
|
+
(field) => feature.attributes[field.name] ?? null
|
|
2037
|
+
)
|
|
2038
|
+
];
|
|
2039
|
+
await statement.bind(params);
|
|
2040
|
+
await statement.step();
|
|
2041
|
+
await statement.reset();
|
|
2042
|
+
count++;
|
|
2043
|
+
}
|
|
2044
|
+
if (count > 0) {
|
|
2045
|
+
await this.registerRepository.incrementObjectCountBatch(
|
|
2046
|
+
this.info.id,
|
|
2047
|
+
count,
|
|
2048
|
+
maxGeometrySize
|
|
2049
|
+
);
|
|
2050
|
+
}
|
|
2051
|
+
} finally {
|
|
2052
|
+
await statement.finalize();
|
|
2053
|
+
}
|
|
2054
|
+
});
|
|
2055
|
+
}
|
|
2056
|
+
async count() {
|
|
2057
|
+
const row = await queryOne(
|
|
2058
|
+
this.driver,
|
|
2059
|
+
`SELECT COUNT(*) AS count FROM "${this.info.tableName}"`,
|
|
2060
|
+
[]
|
|
2061
|
+
);
|
|
2062
|
+
return row?.count ?? 0;
|
|
2063
|
+
}
|
|
2064
|
+
async update(id, changes) {
|
|
2065
|
+
if (!changes.geometry && !changes.attributes) {
|
|
2066
|
+
return;
|
|
2067
|
+
}
|
|
2068
|
+
const setClauses = [];
|
|
2069
|
+
const params = [];
|
|
2070
|
+
if (changes.geometry) {
|
|
2071
|
+
const geometry = GaiaPolygonCodec.writeMultiPolygon(
|
|
2072
|
+
changes.geometry,
|
|
2073
|
+
changes.geometry.srid ?? this.info.srid ?? 0
|
|
2074
|
+
);
|
|
2075
|
+
setClauses.push('"SmGeometry" = ?');
|
|
2076
|
+
params.push(geometry);
|
|
2077
|
+
}
|
|
2078
|
+
if (changes.attributes) {
|
|
2079
|
+
const userFields = await this.getFields();
|
|
2080
|
+
const fieldNames = new Set(userFields.map((f) => f.name));
|
|
2081
|
+
const validEntries = Object.entries(changes.attributes).filter(
|
|
2082
|
+
([key]) => fieldNames.has(key)
|
|
2083
|
+
);
|
|
2084
|
+
for (const [key, value] of validEntries) {
|
|
2085
|
+
setClauses.push(`"${key}" = ?`);
|
|
2086
|
+
params.push(value);
|
|
2087
|
+
}
|
|
2088
|
+
}
|
|
2089
|
+
if (setClauses.length === 0) {
|
|
2090
|
+
return;
|
|
2091
|
+
}
|
|
2092
|
+
const sql = `UPDATE "${this.info.tableName}" SET ${setClauses.join(", ")} WHERE SmID = ?`;
|
|
2093
|
+
params.push(id);
|
|
2094
|
+
await this.driver.transaction(async () => {
|
|
2095
|
+
await executeSql(this.driver, sql, params);
|
|
2096
|
+
});
|
|
2097
|
+
}
|
|
2098
|
+
async delete(id) {
|
|
2099
|
+
await this.driver.transaction(async () => {
|
|
2100
|
+
await executeSql(
|
|
2101
|
+
this.driver,
|
|
2102
|
+
`DELETE FROM "${this.info.tableName}" WHERE SmID = ?`,
|
|
2103
|
+
[id]
|
|
2104
|
+
);
|
|
2105
|
+
await this.registerRepository.decrementObjectCount(this.info.id);
|
|
2106
|
+
});
|
|
2107
|
+
}
|
|
2108
|
+
static async create(driver, registerRepository, params) {
|
|
2109
|
+
const fields = params.fields ?? [];
|
|
2110
|
+
const datasetId = await registerRepository.insert({
|
|
2111
|
+
name: params.name,
|
|
2112
|
+
kind: "region",
|
|
2113
|
+
srid: params.srid,
|
|
2114
|
+
idColumnName: "SmID",
|
|
2115
|
+
geometryColumnName: "SmGeometry"
|
|
2116
|
+
});
|
|
2117
|
+
const userColumnDefinitions = fields.map((field) => {
|
|
2118
|
+
const nullability = field.nullable ? "" : " NOT NULL";
|
|
2119
|
+
return `"${field.name}" ${sqliteColumnType(field)}${nullability}`;
|
|
2120
|
+
});
|
|
2121
|
+
const createTableParts = [
|
|
2122
|
+
`"SmID" INTEGER NOT NULL PRIMARY KEY`,
|
|
2123
|
+
`"SmUserID" INTEGER DEFAULT 0 NOT NULL`,
|
|
2124
|
+
`"SmGeometry" BLOB NOT NULL`,
|
|
2125
|
+
...userColumnDefinitions
|
|
2126
|
+
];
|
|
2127
|
+
await driver.exec(
|
|
2128
|
+
`CREATE TABLE "${params.name}" (${createTableParts.join(", ")})`
|
|
2129
|
+
);
|
|
2130
|
+
await executeSql(
|
|
2131
|
+
driver,
|
|
2132
|
+
`INSERT INTO geometry_columns (
|
|
2133
|
+
f_table_name,
|
|
2134
|
+
f_geometry_column,
|
|
2135
|
+
geometry_type,
|
|
2136
|
+
coord_dimension,
|
|
2137
|
+
srid,
|
|
2138
|
+
spatial_index_enabled
|
|
2139
|
+
) VALUES (?, ?, ?, ?, ?, ?)`,
|
|
2140
|
+
[params.name, "SmGeometry", 6, 2, params.srid, 0]
|
|
2141
|
+
);
|
|
2142
|
+
if (fields.length > 0) {
|
|
2143
|
+
const fieldInfoRepository = new SmFieldInfoRepository(driver);
|
|
2144
|
+
await fieldInfoRepository.insertAll(datasetId, fields);
|
|
2145
|
+
}
|
|
2146
|
+
return new _RegionDataset(driver, {
|
|
2147
|
+
id: datasetId,
|
|
2148
|
+
name: params.name,
|
|
2149
|
+
kind: "region",
|
|
2150
|
+
tableName: params.name,
|
|
2151
|
+
srid: params.srid,
|
|
2152
|
+
objectCount: 0,
|
|
2153
|
+
geometryType: 6
|
|
2154
|
+
});
|
|
2155
|
+
}
|
|
2156
|
+
};
|
|
2157
|
+
|
|
2158
|
+
// src/core/dataset/RegionZDataset.ts
|
|
2159
|
+
function mapRegionZRow(row) {
|
|
2160
|
+
const { SmID, SmGeometry, ...attributes } = row;
|
|
2161
|
+
return {
|
|
2162
|
+
id: SmID,
|
|
2163
|
+
geometry: GaiaPolygonCodec.readMultiPolygonZ(normalizeGeometryBlob(SmGeometry)),
|
|
2164
|
+
attributes
|
|
2165
|
+
};
|
|
2166
|
+
}
|
|
2167
|
+
var RegionZDataset = class _RegionZDataset extends BaseDataset {
|
|
2168
|
+
constructor(driver, info) {
|
|
2169
|
+
super(driver, info);
|
|
2170
|
+
__publicField(this, "registerRepository");
|
|
2171
|
+
this.registerRepository = new SmRegisterRepository(driver);
|
|
2172
|
+
}
|
|
2173
|
+
async getById(id) {
|
|
2174
|
+
const row = await queryOne(
|
|
2175
|
+
this.driver,
|
|
2176
|
+
`SELECT * FROM "${this.info.tableName}" WHERE SmID = ?`,
|
|
2177
|
+
[id]
|
|
2178
|
+
);
|
|
2179
|
+
return row ? mapRegionZRow(row) : null;
|
|
2180
|
+
}
|
|
2181
|
+
async list(options) {
|
|
2182
|
+
const { sql, params } = buildListSql(this.info.tableName, options);
|
|
2183
|
+
const rows = await queryAll(this.driver, sql, params);
|
|
2184
|
+
return rows.map((row) => mapRegionZRow(row));
|
|
2185
|
+
}
|
|
2186
|
+
async *iterate(options) {
|
|
2187
|
+
const { sql, params } = buildListSql(this.info.tableName, options);
|
|
2188
|
+
const statement = await this.driver.prepare(sql);
|
|
2189
|
+
try {
|
|
2190
|
+
if (params.length > 0) {
|
|
2191
|
+
await statement.bind(params);
|
|
2192
|
+
}
|
|
2193
|
+
while (await statement.step()) {
|
|
2194
|
+
yield mapRegionZRow(
|
|
2195
|
+
await statement.getRow()
|
|
2196
|
+
);
|
|
2197
|
+
}
|
|
2198
|
+
} finally {
|
|
2199
|
+
await statement.finalize();
|
|
2200
|
+
}
|
|
2201
|
+
}
|
|
2202
|
+
async count() {
|
|
2203
|
+
const row = await queryOne(
|
|
2204
|
+
this.driver,
|
|
2205
|
+
`SELECT COUNT(*) AS count FROM "${this.info.tableName}"`,
|
|
2206
|
+
[]
|
|
2207
|
+
);
|
|
2208
|
+
return row?.count ?? 0;
|
|
2209
|
+
}
|
|
2210
|
+
async insert(feature) {
|
|
2211
|
+
const userFields = await this.getFields();
|
|
2212
|
+
const columnNames = ["SmID", "SmUserID", "SmGeometry", ...userFields.map((field) => field.name)];
|
|
2213
|
+
const placeholders = columnNames.map(() => "?").join(", ");
|
|
2214
|
+
const geometry = GaiaPolygonCodec.writeMultiPolygonZ(
|
|
2215
|
+
feature.geometry,
|
|
2216
|
+
feature.geometry.srid ?? this.info.srid ?? 0
|
|
2217
|
+
);
|
|
2218
|
+
const sql = `INSERT INTO "${this.info.tableName}" (${columnNames.map((column) => `"${column}"`).join(", ")}) VALUES (${placeholders})`;
|
|
2219
|
+
const params = [
|
|
2220
|
+
feature.id,
|
|
2221
|
+
0,
|
|
2222
|
+
geometry,
|
|
2223
|
+
...userFields.map((field) => feature.attributes[field.name] ?? null)
|
|
2224
|
+
];
|
|
2225
|
+
await this.driver.transaction(async () => {
|
|
2226
|
+
await executeSql(this.driver, sql, params);
|
|
2227
|
+
await this.registerRepository.incrementObjectCount(this.info.id, geometry.byteLength);
|
|
2228
|
+
});
|
|
2229
|
+
}
|
|
2230
|
+
async insertMany(features) {
|
|
2231
|
+
const userFields = await this.getFields();
|
|
2232
|
+
const columnNames = ["SmID", "SmUserID", "SmGeometry", ...userFields.map((field) => field.name)];
|
|
2233
|
+
const placeholders = columnNames.map(() => "?").join(", ");
|
|
2234
|
+
const sql = `INSERT INTO "${this.info.tableName}" (${columnNames.map((column) => `"${column}"`).join(", ")}) VALUES (${placeholders})`;
|
|
2235
|
+
await this.driver.transaction(async () => {
|
|
2236
|
+
const statement = await this.driver.prepare(sql);
|
|
2237
|
+
try {
|
|
2238
|
+
let count = 0;
|
|
2239
|
+
let maxGeometrySize = 0;
|
|
2240
|
+
for await (const feature of features) {
|
|
2241
|
+
const geometry = GaiaPolygonCodec.writeMultiPolygonZ(
|
|
2242
|
+
feature.geometry,
|
|
2243
|
+
feature.geometry.srid ?? this.info.srid ?? 0
|
|
2244
|
+
);
|
|
2245
|
+
maxGeometrySize = Math.max(maxGeometrySize, geometry.byteLength);
|
|
2246
|
+
const params = [
|
|
2247
|
+
feature.id,
|
|
2248
|
+
0,
|
|
2249
|
+
geometry,
|
|
2250
|
+
...userFields.map(
|
|
2251
|
+
(field) => feature.attributes[field.name] ?? null
|
|
2252
|
+
)
|
|
2253
|
+
];
|
|
2254
|
+
await statement.bind(params);
|
|
2255
|
+
await statement.step();
|
|
2256
|
+
await statement.reset();
|
|
2257
|
+
count++;
|
|
2258
|
+
}
|
|
2259
|
+
if (count > 0) {
|
|
2260
|
+
await this.registerRepository.incrementObjectCountBatch(
|
|
2261
|
+
this.info.id,
|
|
2262
|
+
count,
|
|
2263
|
+
maxGeometrySize
|
|
2264
|
+
);
|
|
2265
|
+
}
|
|
2266
|
+
} finally {
|
|
2267
|
+
await statement.finalize();
|
|
2268
|
+
}
|
|
2269
|
+
});
|
|
2270
|
+
}
|
|
2271
|
+
async update(id, changes) {
|
|
2272
|
+
if (!changes.geometry && !changes.attributes) {
|
|
2273
|
+
return;
|
|
2274
|
+
}
|
|
2275
|
+
const setClauses = [];
|
|
2276
|
+
const params = [];
|
|
2277
|
+
if (changes.geometry) {
|
|
2278
|
+
const geometry = GaiaPolygonCodec.writeMultiPolygonZ(
|
|
2279
|
+
changes.geometry,
|
|
2280
|
+
changes.geometry.srid ?? this.info.srid ?? 0
|
|
2281
|
+
);
|
|
2282
|
+
setClauses.push('"SmGeometry" = ?');
|
|
2283
|
+
params.push(geometry);
|
|
2284
|
+
}
|
|
2285
|
+
if (changes.attributes) {
|
|
2286
|
+
const userFields = await this.getFields();
|
|
2287
|
+
const fieldNames = new Set(userFields.map((f) => f.name));
|
|
2288
|
+
const validEntries = Object.entries(changes.attributes).filter(
|
|
2289
|
+
([key]) => fieldNames.has(key)
|
|
2290
|
+
);
|
|
2291
|
+
for (const [key, value] of validEntries) {
|
|
2292
|
+
setClauses.push(`"${key}" = ?`);
|
|
2293
|
+
params.push(value);
|
|
2294
|
+
}
|
|
2295
|
+
}
|
|
2296
|
+
if (setClauses.length === 0) {
|
|
2297
|
+
return;
|
|
2298
|
+
}
|
|
2299
|
+
const sql = `UPDATE "${this.info.tableName}" SET ${setClauses.join(", ")} WHERE SmID = ?`;
|
|
2300
|
+
params.push(id);
|
|
2301
|
+
await this.driver.transaction(async () => {
|
|
2302
|
+
await executeSql(this.driver, sql, params);
|
|
2303
|
+
});
|
|
2304
|
+
}
|
|
2305
|
+
async delete(id) {
|
|
2306
|
+
await this.driver.transaction(async () => {
|
|
2307
|
+
await executeSql(
|
|
2308
|
+
this.driver,
|
|
2309
|
+
`DELETE FROM "${this.info.tableName}" WHERE SmID = ?`,
|
|
2310
|
+
[id]
|
|
2311
|
+
);
|
|
2312
|
+
await this.registerRepository.decrementObjectCount(this.info.id);
|
|
2313
|
+
});
|
|
2314
|
+
}
|
|
2315
|
+
static async create(driver, registerRepository, params) {
|
|
2316
|
+
const fields = params.fields ?? [];
|
|
2317
|
+
const datasetId = await registerRepository.insert({
|
|
2318
|
+
name: params.name,
|
|
2319
|
+
kind: "regionZ",
|
|
2320
|
+
srid: params.srid,
|
|
2321
|
+
idColumnName: "SmID",
|
|
2322
|
+
geometryColumnName: "SmGeometry"
|
|
2323
|
+
});
|
|
2324
|
+
const userColumnDefinitions = fields.map((field) => {
|
|
2325
|
+
const nullability = field.nullable ? "" : " NOT NULL";
|
|
2326
|
+
return `"${field.name}" ${sqliteColumnType(field)}${nullability}`;
|
|
2327
|
+
});
|
|
2328
|
+
const createTableParts = [
|
|
2329
|
+
`"SmID" INTEGER NOT NULL PRIMARY KEY`,
|
|
2330
|
+
`"SmUserID" INTEGER DEFAULT 0 NOT NULL`,
|
|
2331
|
+
`"SmGeometry" BLOB NOT NULL`,
|
|
2332
|
+
...userColumnDefinitions
|
|
2333
|
+
];
|
|
2334
|
+
await driver.exec(
|
|
2335
|
+
`CREATE TABLE "${params.name}" (${createTableParts.join(", ")})`
|
|
2336
|
+
);
|
|
2337
|
+
await executeSql(
|
|
2338
|
+
driver,
|
|
2339
|
+
`INSERT INTO geometry_columns (
|
|
2340
|
+
f_table_name,
|
|
2341
|
+
f_geometry_column,
|
|
2342
|
+
geometry_type,
|
|
2343
|
+
coord_dimension,
|
|
2344
|
+
srid,
|
|
2345
|
+
spatial_index_enabled
|
|
2346
|
+
) VALUES (?, ?, ?, ?, ?, ?)`,
|
|
2347
|
+
[params.name, "SmGeometry", 1006, 3, params.srid, 0]
|
|
2348
|
+
);
|
|
2349
|
+
if (fields.length > 0) {
|
|
2350
|
+
const fieldInfoRepository = new SmFieldInfoRepository(driver);
|
|
2351
|
+
await fieldInfoRepository.insertAll(datasetId, fields);
|
|
2352
|
+
}
|
|
2353
|
+
return new _RegionZDataset(driver, {
|
|
2354
|
+
id: datasetId,
|
|
2355
|
+
name: params.name,
|
|
2356
|
+
kind: "regionZ",
|
|
2357
|
+
tableName: params.name,
|
|
2358
|
+
srid: params.srid,
|
|
2359
|
+
objectCount: 0,
|
|
2360
|
+
geometryType: 1006
|
|
2361
|
+
});
|
|
2362
|
+
}
|
|
2363
|
+
};
|
|
2364
|
+
|
|
2365
|
+
// src/core/dataset/TabularDataset.ts
|
|
2366
|
+
var SYSTEM_COLUMN_PREFIX = "Sm";
|
|
2367
|
+
function mapTabularRow(row) {
|
|
2368
|
+
const { SmID, ...rest } = row;
|
|
2369
|
+
const attributes = {};
|
|
2370
|
+
for (const [key, value] of Object.entries(rest)) {
|
|
2371
|
+
if (!key.startsWith(SYSTEM_COLUMN_PREFIX)) {
|
|
2372
|
+
attributes[key] = value;
|
|
2373
|
+
}
|
|
2374
|
+
}
|
|
2375
|
+
return {
|
|
2376
|
+
id: SmID,
|
|
2377
|
+
attributes
|
|
2378
|
+
};
|
|
2379
|
+
}
|
|
2380
|
+
var TabularDataset = class _TabularDataset extends BaseDataset {
|
|
2381
|
+
constructor(driver, info) {
|
|
2382
|
+
super(driver, info);
|
|
2383
|
+
__publicField(this, "registerRepository");
|
|
2384
|
+
this.registerRepository = new SmRegisterRepository(driver);
|
|
2385
|
+
}
|
|
2386
|
+
async getById(id) {
|
|
2387
|
+
const row = await queryOne(
|
|
2388
|
+
this.driver,
|
|
2389
|
+
`SELECT * FROM "${this.info.tableName}" WHERE SmID = ?`,
|
|
2390
|
+
[id]
|
|
2391
|
+
);
|
|
2392
|
+
return row ? mapTabularRow(row) : null;
|
|
2393
|
+
}
|
|
2394
|
+
async list(options) {
|
|
2395
|
+
const { sql, params } = buildListSql(this.info.tableName, options);
|
|
2396
|
+
const rows = await queryAll(this.driver, sql, params);
|
|
2397
|
+
return rows.map((row) => mapTabularRow(row));
|
|
2398
|
+
}
|
|
2399
|
+
async *iterate(options) {
|
|
2400
|
+
const { sql, params } = buildListSql(this.info.tableName, options);
|
|
2401
|
+
const statement = await this.driver.prepare(sql);
|
|
2402
|
+
try {
|
|
2403
|
+
if (params.length > 0) {
|
|
2404
|
+
await statement.bind(params);
|
|
2405
|
+
}
|
|
2406
|
+
while (await statement.step()) {
|
|
2407
|
+
yield mapTabularRow(
|
|
2408
|
+
await statement.getRow()
|
|
2409
|
+
);
|
|
2410
|
+
}
|
|
2411
|
+
} finally {
|
|
2412
|
+
await statement.finalize();
|
|
2413
|
+
}
|
|
2414
|
+
}
|
|
2415
|
+
async count() {
|
|
2416
|
+
const row = await queryOne(
|
|
2417
|
+
this.driver,
|
|
2418
|
+
`SELECT COUNT(*) AS count FROM "${this.info.tableName}"`,
|
|
2419
|
+
[]
|
|
2420
|
+
);
|
|
2421
|
+
return row?.count ?? 0;
|
|
2422
|
+
}
|
|
2423
|
+
async insert(record) {
|
|
2424
|
+
const userFields = await this.getFields();
|
|
2425
|
+
const columnNames = [
|
|
2426
|
+
"SmID",
|
|
2427
|
+
"SmUserID",
|
|
2428
|
+
...userFields.map((field) => field.name)
|
|
2429
|
+
];
|
|
2430
|
+
const placeholders = columnNames.map(() => "?").join(", ");
|
|
2431
|
+
const sql = `INSERT INTO "${this.info.tableName}" (${columnNames.map((column) => `"${column}"`).join(", ")}) VALUES (${placeholders})`;
|
|
2432
|
+
const params = [
|
|
2433
|
+
record.id,
|
|
2434
|
+
0,
|
|
2435
|
+
...userFields.map(
|
|
2436
|
+
(field) => record.attributes[field.name] ?? null
|
|
2437
|
+
)
|
|
2438
|
+
];
|
|
2439
|
+
await this.driver.transaction(async () => {
|
|
2440
|
+
await executeSql(this.driver, sql, params);
|
|
2441
|
+
await this.registerRepository.incrementObjectCount(this.info.id);
|
|
2442
|
+
});
|
|
2443
|
+
}
|
|
2444
|
+
async insertMany(records) {
|
|
2445
|
+
const userFields = await this.getFields();
|
|
2446
|
+
const columnNames = [
|
|
2447
|
+
"SmID",
|
|
2448
|
+
"SmUserID",
|
|
2449
|
+
...userFields.map((field) => field.name)
|
|
2450
|
+
];
|
|
2451
|
+
const placeholders = columnNames.map(() => "?").join(", ");
|
|
2452
|
+
const sql = `INSERT INTO "${this.info.tableName}" (${columnNames.map((column) => `"${column}"`).join(", ")}) VALUES (${placeholders})`;
|
|
2453
|
+
await this.driver.transaction(async () => {
|
|
2454
|
+
const statement = await this.driver.prepare(sql);
|
|
2455
|
+
try {
|
|
2456
|
+
let count = 0;
|
|
2457
|
+
for await (const record of records) {
|
|
2458
|
+
const params = [
|
|
2459
|
+
record.id,
|
|
2460
|
+
0,
|
|
2461
|
+
...userFields.map(
|
|
2462
|
+
(field) => record.attributes[field.name] ?? null
|
|
2463
|
+
)
|
|
2464
|
+
];
|
|
2465
|
+
await statement.bind(params);
|
|
2466
|
+
await statement.step();
|
|
2467
|
+
await statement.reset();
|
|
2468
|
+
count++;
|
|
2469
|
+
}
|
|
2470
|
+
if (count > 0) {
|
|
2471
|
+
await this.registerRepository.incrementObjectCountBatch(
|
|
2472
|
+
this.info.id,
|
|
2473
|
+
count,
|
|
2474
|
+
0
|
|
2475
|
+
);
|
|
2476
|
+
}
|
|
2477
|
+
} finally {
|
|
2478
|
+
await statement.finalize();
|
|
2479
|
+
}
|
|
2480
|
+
});
|
|
2481
|
+
}
|
|
2482
|
+
async update(id, attributes) {
|
|
2483
|
+
const userFields = await this.getFields();
|
|
2484
|
+
const fieldNames = new Set(userFields.map((f) => f.name));
|
|
2485
|
+
const validEntries = Object.entries(attributes).filter(
|
|
2486
|
+
([key]) => fieldNames.has(key)
|
|
2487
|
+
);
|
|
2488
|
+
if (validEntries.length === 0) return;
|
|
2489
|
+
const keys = validEntries.map(([key]) => key);
|
|
2490
|
+
const setClauses = keys.map((key) => `"${key}" = ?`).join(", ");
|
|
2491
|
+
const sql = `UPDATE "${this.info.tableName}" SET ${setClauses} WHERE SmID = ?`;
|
|
2492
|
+
const params = [
|
|
2493
|
+
...keys.map((key) => attributes[key]),
|
|
2494
|
+
id
|
|
2495
|
+
];
|
|
2496
|
+
await this.driver.transaction(async () => {
|
|
2497
|
+
await executeSql(this.driver, sql, params);
|
|
2498
|
+
});
|
|
2499
|
+
}
|
|
2500
|
+
async delete(id) {
|
|
2501
|
+
await this.driver.transaction(async () => {
|
|
2502
|
+
await executeSql(
|
|
2503
|
+
this.driver,
|
|
2504
|
+
`DELETE FROM "${this.info.tableName}" WHERE SmID = ?`,
|
|
2505
|
+
[id]
|
|
2506
|
+
);
|
|
2507
|
+
await this.registerRepository.decrementObjectCount(this.info.id);
|
|
2508
|
+
});
|
|
2509
|
+
}
|
|
2510
|
+
static async create(driver, registerRepository, params) {
|
|
2511
|
+
const fields = params.fields ?? [];
|
|
2512
|
+
const datasetId = await registerRepository.insert({
|
|
2513
|
+
name: params.name,
|
|
2514
|
+
kind: "tabular",
|
|
2515
|
+
srid: 0,
|
|
2516
|
+
idColumnName: "SmID",
|
|
2517
|
+
geometryColumnName: null
|
|
2518
|
+
});
|
|
2519
|
+
const userColumnDefinitions = fields.map((field) => {
|
|
2520
|
+
const nullability = field.nullable ? "" : " NOT NULL";
|
|
2521
|
+
return `"${field.name}" ${sqliteColumnType(field)}${nullability}`;
|
|
2522
|
+
});
|
|
2523
|
+
const createTableParts = [
|
|
2524
|
+
`"SmID" INTEGER NOT NULL PRIMARY KEY`,
|
|
2525
|
+
`"SmUserID" INTEGER DEFAULT 0 NOT NULL`,
|
|
2526
|
+
...userColumnDefinitions
|
|
2527
|
+
];
|
|
2528
|
+
await driver.exec(
|
|
2529
|
+
`CREATE TABLE "${params.name}" (${createTableParts.join(", ")})`
|
|
2530
|
+
);
|
|
2531
|
+
if (fields.length > 0) {
|
|
2532
|
+
const fieldInfoRepository = new SmFieldInfoRepository(driver);
|
|
2533
|
+
await fieldInfoRepository.insertAll(datasetId, fields);
|
|
2534
|
+
}
|
|
2535
|
+
return new _TabularDataset(driver, {
|
|
2536
|
+
id: datasetId,
|
|
2537
|
+
name: params.name,
|
|
2538
|
+
kind: "tabular",
|
|
2539
|
+
tableName: params.name,
|
|
2540
|
+
srid: 0,
|
|
2541
|
+
objectCount: 0,
|
|
2542
|
+
geometryType: null
|
|
2543
|
+
});
|
|
2544
|
+
}
|
|
2545
|
+
};
|
|
2546
|
+
|
|
2547
|
+
// src/core/dataset/TextDataset.ts
|
|
2548
|
+
var TextDataset = class extends BaseDataset {
|
|
2549
|
+
async getById() {
|
|
2550
|
+
throw createNotImplementedError("TextDataset.getById");
|
|
2551
|
+
}
|
|
2552
|
+
async list(_options) {
|
|
2553
|
+
throw createNotImplementedError("TextDataset.list");
|
|
2554
|
+
}
|
|
2555
|
+
async *iterate(_options) {
|
|
2556
|
+
throw createNotImplementedError("TextDataset.iterate");
|
|
2557
|
+
}
|
|
2558
|
+
async count() {
|
|
2559
|
+
throw createNotImplementedError("TextDataset.count");
|
|
2560
|
+
}
|
|
2561
|
+
async insert() {
|
|
2562
|
+
throw createNotImplementedError("TextDataset.insert");
|
|
2563
|
+
}
|
|
2564
|
+
async insertMany() {
|
|
2565
|
+
throw createNotImplementedError("TextDataset.insertMany");
|
|
2566
|
+
}
|
|
2567
|
+
async update() {
|
|
2568
|
+
throw createNotImplementedError("TextDataset.update");
|
|
2569
|
+
}
|
|
2570
|
+
async delete() {
|
|
2571
|
+
throw createNotImplementedError("TextDataset.delete");
|
|
2572
|
+
}
|
|
2573
|
+
};
|
|
2574
|
+
|
|
2575
|
+
// src/core/schema/UdbxSchemaInitializer.ts
|
|
2576
|
+
var UDBX_SYSTEM_TABLES = [
|
|
2577
|
+
"spatial_ref_sys",
|
|
2578
|
+
"geometry_columns",
|
|
2579
|
+
"SmDataSourceInfo",
|
|
2580
|
+
"SmRegister",
|
|
2581
|
+
"SmFieldInfo"
|
|
2582
|
+
];
|
|
2583
|
+
var UDBX_SCHEMA_STATEMENTS = [
|
|
2584
|
+
`CREATE TABLE spatial_ref_sys (
|
|
2585
|
+
srid INTEGER NOT NULL PRIMARY KEY,
|
|
2586
|
+
auth_name TEXT NOT NULL,
|
|
2587
|
+
auth_srid INTEGER NOT NULL,
|
|
2588
|
+
ref_sys_name TEXT NOT NULL DEFAULT 'Unknown',
|
|
2589
|
+
proj4text TEXT NOT NULL,
|
|
2590
|
+
srtext TEXT NOT NULL DEFAULT 'Undefined'
|
|
2591
|
+
)`,
|
|
2592
|
+
`CREATE TABLE geometry_columns (
|
|
2593
|
+
f_table_name TEXT NOT NULL,
|
|
2594
|
+
f_geometry_column TEXT NOT NULL,
|
|
2595
|
+
geometry_type INTEGER NOT NULL,
|
|
2596
|
+
coord_dimension INTEGER NOT NULL,
|
|
2597
|
+
srid INTEGER NOT NULL,
|
|
2598
|
+
spatial_index_enabled INTEGER NOT NULL,
|
|
2599
|
+
CONSTRAINT pk_geom_cols PRIMARY KEY (f_table_name, f_geometry_column)
|
|
2600
|
+
)`,
|
|
2601
|
+
`CREATE TABLE SmDataSourceInfo (
|
|
2602
|
+
SmFlag INTEGER DEFAULT 0 NOT NULL PRIMARY KEY AUTOINCREMENT,
|
|
2603
|
+
SmVersion INTEGER,
|
|
2604
|
+
SmDsDescription TEXT,
|
|
2605
|
+
SmProjectInfo BLOB,
|
|
2606
|
+
SmLastUpdateTime DATE DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
|
2607
|
+
SmDataFormat INTEGER DEFAULT 0 NOT NULL
|
|
2608
|
+
)`,
|
|
2609
|
+
`CREATE TABLE SmRegister (
|
|
2610
|
+
SmDatasetID INTEGER DEFAULT 0 NOT NULL PRIMARY KEY,
|
|
2611
|
+
SmDatasetName TEXT,
|
|
2612
|
+
SmTableName TEXT,
|
|
2613
|
+
SmOption INTEGER,
|
|
2614
|
+
SmEncType INTEGER,
|
|
2615
|
+
SmParentDTID INTEGER DEFAULT 0 NOT NULL,
|
|
2616
|
+
SmDatasetType INTEGER,
|
|
2617
|
+
SmObjectCount INTEGER DEFAULT 0 NOT NULL,
|
|
2618
|
+
SmLeft REAL,
|
|
2619
|
+
SmRight REAL,
|
|
2620
|
+
SmTop REAL,
|
|
2621
|
+
SmBottom REAL,
|
|
2622
|
+
SmIDColName TEXT,
|
|
2623
|
+
SmGeoColName TEXT,
|
|
2624
|
+
SmMinZ REAL,
|
|
2625
|
+
SmMaxZ REAL,
|
|
2626
|
+
SmSRID INTEGER DEFAULT 0,
|
|
2627
|
+
SmIndexType INTEGER DEFAULT 1,
|
|
2628
|
+
SmToleRanceFuzzy REAL,
|
|
2629
|
+
SmToleranceDAngle REAL,
|
|
2630
|
+
SmToleranceNodeSnap REAL,
|
|
2631
|
+
SmToleranceSmallPolygon REAL,
|
|
2632
|
+
SmToleranceGrain REAL,
|
|
2633
|
+
SmMaxGeometrySize INTEGER DEFAULT 0 NOT NULL,
|
|
2634
|
+
SmOptimizeCount INTEGER DEFAULT 0 NOT NULL,
|
|
2635
|
+
SmOptimizeRatio REAL,
|
|
2636
|
+
SmDescription TEXT,
|
|
2637
|
+
SmExtInfo TEXT,
|
|
2638
|
+
SmCreateTime TEXT,
|
|
2639
|
+
SmLastUpdateTime TEXT,
|
|
2640
|
+
SmProjectInfo BLOB
|
|
2641
|
+
)`,
|
|
2642
|
+
`CREATE TABLE SmFieldInfo (
|
|
2643
|
+
SmID INTEGER DEFAULT 0 NOT NULL PRIMARY KEY AUTOINCREMENT,
|
|
2644
|
+
SmDatasetID INTEGER,
|
|
2645
|
+
SmFieldName TEXT,
|
|
2646
|
+
SmFieldCaption TEXT,
|
|
2647
|
+
SmFieldType INTEGER,
|
|
2648
|
+
SmFieldFormat TEXT,
|
|
2649
|
+
SmFieldSign INTEGER,
|
|
2650
|
+
SmFieldDomain TEXT,
|
|
2651
|
+
SmFieldUpdatable INTEGER,
|
|
2652
|
+
SmFieldbRequired INTEGER,
|
|
2653
|
+
SmFieldDefaultValue TEXT,
|
|
2654
|
+
SmFieldSize INTEGER
|
|
2655
|
+
)`,
|
|
2656
|
+
"INSERT INTO SmDataSourceInfo (SmVersion, SmDataFormat) VALUES (0, 1)",
|
|
2657
|
+
"INSERT INTO spatial_ref_sys (srid, auth_name, auth_srid, ref_sys_name, proj4text, srtext) VALUES (0, 'none', 0, 'Undefined', '', 'Undefined')",
|
|
2658
|
+
`INSERT INTO spatial_ref_sys (srid, auth_name, auth_srid, ref_sys_name, proj4text, srtext)
|
|
2659
|
+
VALUES (
|
|
2660
|
+
4326,
|
|
2661
|
+
'epsg',
|
|
2662
|
+
4326,
|
|
2663
|
+
'WGS 84',
|
|
2664
|
+
'+proj=longlat +datum=WGS84 +no_defs',
|
|
2665
|
+
'GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["degree",0.0174532925199433],AUTHORITY["EPSG","4326"]]'
|
|
2666
|
+
)`
|
|
2667
|
+
];
|
|
2668
|
+
var UdbxSchemaInitializer = class {
|
|
2669
|
+
static async isInitialized(driver) {
|
|
2670
|
+
const statement = await driver.prepare(
|
|
2671
|
+
"SELECT name FROM sqlite_master WHERE type = 'table' AND name = ? LIMIT 1"
|
|
2672
|
+
);
|
|
2673
|
+
try {
|
|
2674
|
+
await statement.bind(["SmDataSourceInfo"]);
|
|
2675
|
+
return statement.step();
|
|
2676
|
+
} finally {
|
|
2677
|
+
await statement.finalize();
|
|
2678
|
+
}
|
|
2679
|
+
}
|
|
2680
|
+
static async ensureInitialized(driver) {
|
|
2681
|
+
const initialized = await this.isInitialized(driver);
|
|
2682
|
+
if (initialized) {
|
|
2683
|
+
return false;
|
|
2684
|
+
}
|
|
2685
|
+
await this.initialize(driver);
|
|
2686
|
+
return true;
|
|
2687
|
+
}
|
|
2688
|
+
static async initialize(driver) {
|
|
2689
|
+
await driver.exec("PRAGMA journal_mode = WAL");
|
|
2690
|
+
await driver.transaction(async () => {
|
|
2691
|
+
for (const statement of UDBX_SCHEMA_STATEMENTS) {
|
|
2692
|
+
await driver.exec(statement);
|
|
2693
|
+
}
|
|
2694
|
+
});
|
|
2695
|
+
}
|
|
2696
|
+
};
|
|
2697
|
+
|
|
2698
|
+
// src/core/datasource/UdbxDataSource.ts
|
|
2699
|
+
var UdbxDataSource = class _UdbxDataSource {
|
|
2700
|
+
constructor(driver, runtime = "unknown") {
|
|
2701
|
+
this.driver = driver;
|
|
2702
|
+
this.runtime = runtime;
|
|
2703
|
+
__publicField(this, "registerRepository");
|
|
2704
|
+
this.registerRepository = new SmRegisterRepository(driver);
|
|
2705
|
+
}
|
|
2706
|
+
static async open(params) {
|
|
2707
|
+
await params.driver.open(params.target);
|
|
2708
|
+
return new _UdbxDataSource(params.driver, params.runtime ?? "unknown");
|
|
2709
|
+
}
|
|
2710
|
+
static async create(params) {
|
|
2711
|
+
await params.driver.open(params.target);
|
|
2712
|
+
await UdbxSchemaInitializer.initialize(params.driver);
|
|
2713
|
+
return new _UdbxDataSource(params.driver, params.runtime ?? "unknown");
|
|
2714
|
+
}
|
|
2715
|
+
async listDatasets() {
|
|
2716
|
+
return this.registerRepository.findAll();
|
|
2717
|
+
}
|
|
2718
|
+
async getDataset(name) {
|
|
2719
|
+
const info = await this.registerRepository.findByName(name);
|
|
2720
|
+
if (!info) {
|
|
2721
|
+
return null;
|
|
2722
|
+
}
|
|
2723
|
+
switch (info.kind) {
|
|
2724
|
+
case "point":
|
|
2725
|
+
return new PointDataset(this.driver, info);
|
|
2726
|
+
case "pointZ":
|
|
2727
|
+
return new PointZDataset(this.driver, info);
|
|
2728
|
+
case "line":
|
|
2729
|
+
return new LineDataset(this.driver, info);
|
|
2730
|
+
case "lineZ":
|
|
2731
|
+
return new LineZDataset(this.driver, info);
|
|
2732
|
+
case "region":
|
|
2733
|
+
return new RegionDataset(this.driver, info);
|
|
2734
|
+
case "regionZ":
|
|
2735
|
+
return new RegionZDataset(this.driver, info);
|
|
2736
|
+
case "tabular":
|
|
2737
|
+
return new TabularDataset(this.driver, info);
|
|
2738
|
+
case "text":
|
|
2739
|
+
return new TextDataset(this.driver, info);
|
|
2740
|
+
case "cad":
|
|
2741
|
+
return new CadDataset(this.driver, info);
|
|
2742
|
+
default:
|
|
2743
|
+
return null;
|
|
2744
|
+
}
|
|
2745
|
+
}
|
|
2746
|
+
async createPointDataset(name, srid, fields) {
|
|
2747
|
+
return this.driver.transaction(async () => {
|
|
2748
|
+
const params = fields === void 0 ? { name, srid } : { name, srid, fields };
|
|
2749
|
+
return PointDataset.create(this.driver, this.registerRepository, params);
|
|
2750
|
+
});
|
|
2751
|
+
}
|
|
2752
|
+
async createLineDataset(name, srid, fields) {
|
|
2753
|
+
return this.driver.transaction(async () => {
|
|
2754
|
+
const params = fields === void 0 ? { name, srid } : { name, srid, fields };
|
|
2755
|
+
return LineDataset.create(this.driver, this.registerRepository, params);
|
|
2756
|
+
});
|
|
2757
|
+
}
|
|
2758
|
+
async createRegionDataset(name, srid, fields) {
|
|
2759
|
+
return this.driver.transaction(async () => {
|
|
2760
|
+
const params = fields === void 0 ? { name, srid } : { name, srid, fields };
|
|
2761
|
+
return RegionDataset.create(this.driver, this.registerRepository, params);
|
|
2762
|
+
});
|
|
2763
|
+
}
|
|
2764
|
+
async createPointZDataset(name, srid, fields) {
|
|
2765
|
+
return this.driver.transaction(async () => {
|
|
2766
|
+
const params = fields === void 0 ? { name, srid } : { name, srid, fields };
|
|
2767
|
+
return PointZDataset.create(this.driver, this.registerRepository, params);
|
|
2768
|
+
});
|
|
2769
|
+
}
|
|
2770
|
+
async createLineZDataset(name, srid, fields) {
|
|
2771
|
+
return this.driver.transaction(async () => {
|
|
2772
|
+
const params = fields === void 0 ? { name, srid } : { name, srid, fields };
|
|
2773
|
+
return LineZDataset.create(this.driver, this.registerRepository, params);
|
|
2774
|
+
});
|
|
2775
|
+
}
|
|
2776
|
+
async createRegionZDataset(name, srid, fields) {
|
|
2777
|
+
return this.driver.transaction(async () => {
|
|
2778
|
+
const params = fields === void 0 ? { name, srid } : { name, srid, fields };
|
|
2779
|
+
return RegionZDataset.create(this.driver, this.registerRepository, params);
|
|
2780
|
+
});
|
|
2781
|
+
}
|
|
2782
|
+
async createTabularDataset(name, fields) {
|
|
2783
|
+
return this.driver.transaction(async () => {
|
|
2784
|
+
const params = fields === void 0 ? { name } : { name, fields };
|
|
2785
|
+
return TabularDataset.create(this.driver, this.registerRepository, params);
|
|
2786
|
+
});
|
|
2787
|
+
}
|
|
2788
|
+
async createTextDataset(name, srid, fields) {
|
|
2789
|
+
return this.driver.transaction(async () => {
|
|
2790
|
+
const fieldList = fields ?? [];
|
|
2791
|
+
const datasetId = await this.registerRepository.insert({
|
|
2792
|
+
name,
|
|
2793
|
+
kind: "text",
|
|
2794
|
+
srid,
|
|
2795
|
+
idColumnName: "SmID",
|
|
2796
|
+
geometryColumnName: "SmGeometry"
|
|
2797
|
+
});
|
|
2798
|
+
const userColumnDefinitions = fieldList.map((field) => {
|
|
2799
|
+
const nullability = field.nullable ? "" : " NOT NULL";
|
|
2800
|
+
return `"${field.name}" TEXT${nullability}`;
|
|
2801
|
+
});
|
|
2802
|
+
const createTableParts = [
|
|
2803
|
+
`"SmID" INTEGER NOT NULL PRIMARY KEY`,
|
|
2804
|
+
`"SmUserID" INTEGER DEFAULT 0 NOT NULL`,
|
|
2805
|
+
`"SmGeometry" BLOB`,
|
|
2806
|
+
`"SmIndexKey" POLYGON`,
|
|
2807
|
+
...userColumnDefinitions
|
|
2808
|
+
];
|
|
2809
|
+
await this.driver.exec(
|
|
2810
|
+
`CREATE TABLE "${name}" (${createTableParts.join(", ")})`
|
|
2811
|
+
);
|
|
2812
|
+
if (fieldList.length > 0) {
|
|
2813
|
+
const fieldInfoRepository = new SmFieldInfoRepository(this.driver);
|
|
2814
|
+
await fieldInfoRepository.insertAll(datasetId, fieldList);
|
|
2815
|
+
}
|
|
2816
|
+
return new TextDataset(this.driver, {
|
|
2817
|
+
id: datasetId,
|
|
2818
|
+
name,
|
|
2819
|
+
kind: "text",
|
|
2820
|
+
tableName: name,
|
|
2821
|
+
srid,
|
|
2822
|
+
objectCount: 0,
|
|
2823
|
+
geometryType: null
|
|
2824
|
+
});
|
|
2825
|
+
});
|
|
2826
|
+
}
|
|
2827
|
+
async createCadDataset(name, fields) {
|
|
2828
|
+
return this.driver.transaction(async () => {
|
|
2829
|
+
const fieldList = fields ?? [];
|
|
2830
|
+
const datasetId = await this.registerRepository.insert({
|
|
2831
|
+
name,
|
|
2832
|
+
kind: "cad",
|
|
2833
|
+
srid: 0,
|
|
2834
|
+
idColumnName: "SmID",
|
|
2835
|
+
geometryColumnName: "SmGeometry"
|
|
2836
|
+
});
|
|
2837
|
+
const userColumnDefinitions = fieldList.map((field) => {
|
|
2838
|
+
const nullability = field.nullable ? "" : " NOT NULL";
|
|
2839
|
+
return `"${field.name}" TEXT${nullability}`;
|
|
2840
|
+
});
|
|
2841
|
+
const createTableParts = [
|
|
2842
|
+
`"SmID" INTEGER NOT NULL PRIMARY KEY`,
|
|
2843
|
+
`"SmUserID" INTEGER DEFAULT 0 NOT NULL`,
|
|
2844
|
+
`"SmGeometry" BLOB`,
|
|
2845
|
+
...userColumnDefinitions
|
|
2846
|
+
];
|
|
2847
|
+
await this.driver.exec(
|
|
2848
|
+
`CREATE TABLE "${name}" (${createTableParts.join(", ")})`
|
|
2849
|
+
);
|
|
2850
|
+
if (fieldList.length > 0) {
|
|
2851
|
+
const fieldInfoRepository = new SmFieldInfoRepository(this.driver);
|
|
2852
|
+
await fieldInfoRepository.insertAll(datasetId, fieldList);
|
|
2853
|
+
}
|
|
2854
|
+
return new CadDataset(this.driver, {
|
|
2855
|
+
id: datasetId,
|
|
2856
|
+
name,
|
|
2857
|
+
kind: "cad",
|
|
2858
|
+
tableName: name,
|
|
2859
|
+
srid: 0,
|
|
2860
|
+
objectCount: 0,
|
|
2861
|
+
geometryType: null
|
|
2862
|
+
});
|
|
2863
|
+
});
|
|
2864
|
+
}
|
|
2865
|
+
async close() {
|
|
2866
|
+
await this.driver.close();
|
|
2867
|
+
}
|
|
2868
|
+
};
|
|
2869
|
+
|
|
2870
|
+
// src/core/errors.ts
|
|
2871
|
+
var UdbxError = class extends Error {
|
|
2872
|
+
constructor(message) {
|
|
2873
|
+
super(message);
|
|
2874
|
+
this.name = "UdbxError";
|
|
2875
|
+
}
|
|
2876
|
+
};
|
|
2877
|
+
var UdbxFormatError = class extends UdbxError {
|
|
2878
|
+
constructor(message) {
|
|
2879
|
+
super(message);
|
|
2880
|
+
this.name = "UdbxFormatError";
|
|
2881
|
+
}
|
|
2882
|
+
};
|
|
2883
|
+
var UdbxNotFoundError = class extends UdbxError {
|
|
2884
|
+
constructor(what, id) {
|
|
2885
|
+
super(id !== void 0 ? `${what} not found (id=${id})` : `${what} not found`);
|
|
2886
|
+
this.name = "UdbxNotFoundError";
|
|
2887
|
+
}
|
|
2888
|
+
};
|
|
2889
|
+
var UdbxUnsupportedError = class extends UdbxError {
|
|
2890
|
+
constructor(what) {
|
|
2891
|
+
super(`Unsupported: ${what}`);
|
|
2892
|
+
this.name = "UdbxUnsupportedError";
|
|
2893
|
+
}
|
|
2894
|
+
};
|
|
2895
|
+
var UdbxConstraintError = class extends UdbxError {
|
|
2896
|
+
constructor(what) {
|
|
2897
|
+
super(`Constraint violation: ${what}`);
|
|
2898
|
+
this.name = "UdbxConstraintError";
|
|
2899
|
+
}
|
|
2900
|
+
};
|
|
2901
|
+
var UdbxIOError = class extends UdbxError {
|
|
2902
|
+
constructor(cause) {
|
|
2903
|
+
super(cause ? `IO error: ${cause.message}` : "IO error");
|
|
2904
|
+
this.name = "UdbxIOError";
|
|
2905
|
+
}
|
|
2906
|
+
};
|
|
2907
|
+
|
|
2908
|
+
// src/core/geometry/gaia/GaiaGeometryCodec.ts
|
|
2909
|
+
var decodeByGeoType = /* @__PURE__ */ new Map([
|
|
2910
|
+
[GEO_TYPE_POINT, GaiaPointCodec.readPoint],
|
|
2911
|
+
[GEO_TYPE_POINTZ, GaiaPointCodec.readPointZ],
|
|
2912
|
+
[GEO_TYPE_MULTILINESTRING, GaiaLineCodec.readMultiLineString],
|
|
2913
|
+
[GEO_TYPE_MULTILINESTRINGZ, GaiaLineCodec.readMultiLineStringZ],
|
|
2914
|
+
[GEO_TYPE_MULTIPOLYGON, GaiaPolygonCodec.readMultiPolygon],
|
|
2915
|
+
[GEO_TYPE_MULTIPOLYGONZ, GaiaPolygonCodec.readMultiPolygonZ]
|
|
2916
|
+
]);
|
|
2917
|
+
var pointCodecs = {
|
|
2918
|
+
[GEO_TYPE_POINT]: {
|
|
2919
|
+
geoType: GEO_TYPE_POINT,
|
|
2920
|
+
decode: GaiaPointCodec.readPoint
|
|
2921
|
+
},
|
|
2922
|
+
[GEO_TYPE_POINTZ]: {
|
|
2923
|
+
geoType: GEO_TYPE_POINTZ,
|
|
2924
|
+
decode: GaiaPointCodec.readPointZ
|
|
2925
|
+
}
|
|
2926
|
+
};
|
|
2927
|
+
var lineCodecs = {
|
|
2928
|
+
[GEO_TYPE_MULTILINESTRING]: {
|
|
2929
|
+
geoType: GEO_TYPE_MULTILINESTRING,
|
|
2930
|
+
decode: GaiaLineCodec.readMultiLineString
|
|
2931
|
+
},
|
|
2932
|
+
[GEO_TYPE_MULTILINESTRINGZ]: {
|
|
2933
|
+
geoType: GEO_TYPE_MULTILINESTRINGZ,
|
|
2934
|
+
decode: GaiaLineCodec.readMultiLineStringZ
|
|
2935
|
+
}
|
|
2936
|
+
};
|
|
2937
|
+
var polygonCodecs = {
|
|
2938
|
+
[GEO_TYPE_MULTIPOLYGON]: {
|
|
2939
|
+
geoType: GEO_TYPE_MULTIPOLYGON,
|
|
2940
|
+
decode: GaiaPolygonCodec.readMultiPolygon
|
|
2941
|
+
},
|
|
2942
|
+
[GEO_TYPE_MULTIPOLYGONZ]: {
|
|
2943
|
+
geoType: GEO_TYPE_MULTIPOLYGONZ,
|
|
2944
|
+
decode: GaiaPolygonCodec.readMultiPolygonZ
|
|
2945
|
+
}
|
|
2946
|
+
};
|
|
2947
|
+
function geometryHasZ(geometry) {
|
|
2948
|
+
switch (geometry.type) {
|
|
2949
|
+
case "Point":
|
|
2950
|
+
return geometry.coordinates.length === 3;
|
|
2951
|
+
case "MultiLineString":
|
|
2952
|
+
return geometry.coordinates[0]?.[0]?.length === 3;
|
|
2953
|
+
case "MultiPolygon":
|
|
2954
|
+
return geometry.coordinates[0]?.[0]?.[0]?.length === 3;
|
|
2955
|
+
case "Cad":
|
|
2956
|
+
case "Text":
|
|
2957
|
+
return false;
|
|
2958
|
+
default:
|
|
2959
|
+
return false;
|
|
2960
|
+
}
|
|
2961
|
+
}
|
|
2962
|
+
function encodeGeometry(geometry, srid) {
|
|
2963
|
+
switch (geometry.type) {
|
|
2964
|
+
case "Point":
|
|
2965
|
+
return geometryHasZ(geometry) ? GaiaPointCodec.writePointZ(geometry, srid) : GaiaPointCodec.writePoint(geometry, srid);
|
|
2966
|
+
case "MultiLineString":
|
|
2967
|
+
return geometryHasZ(geometry) ? GaiaLineCodec.writeMultiLineStringZ(geometry, srid) : GaiaLineCodec.writeMultiLineString(geometry, srid);
|
|
2968
|
+
case "MultiPolygon":
|
|
2969
|
+
return geometryHasZ(geometry) ? GaiaPolygonCodec.writeMultiPolygonZ(geometry, srid) : GaiaPolygonCodec.writeMultiPolygon(geometry, srid);
|
|
2970
|
+
case "Cad":
|
|
2971
|
+
throw new Error("CAD geometry is not supported by GaiaGeometryCodec.");
|
|
2972
|
+
case "Text":
|
|
2973
|
+
throw new Error("Text geometry is not supported by GaiaGeometryCodec.");
|
|
2974
|
+
default:
|
|
2975
|
+
throw new Error(`Unsupported geometry type: ${geometry.type}`);
|
|
2976
|
+
}
|
|
2977
|
+
}
|
|
2978
|
+
var GaiaGeometryCodec = class {
|
|
2979
|
+
static decode(input) {
|
|
2980
|
+
const header = readGaiaHeader(new BinaryCursor(input));
|
|
2981
|
+
const decoder = decodeByGeoType.get(header.geoType);
|
|
2982
|
+
if (!decoder) {
|
|
2983
|
+
throw new GaiaUnsupportedGeoTypeError(header.geoType);
|
|
2984
|
+
}
|
|
2985
|
+
return decoder(input);
|
|
2986
|
+
}
|
|
2987
|
+
static encode(geometry, srid) {
|
|
2988
|
+
return encodeGeometry(geometry, srid);
|
|
2989
|
+
}
|
|
2990
|
+
};
|
|
2991
|
+
|
|
2992
|
+
// src/core/geometry/jsts/JstsGeometryAdapter.ts
|
|
2993
|
+
var reader = null;
|
|
2994
|
+
var writer = null;
|
|
2995
|
+
async function getReader() {
|
|
2996
|
+
if (!reader) {
|
|
2997
|
+
const { default: GeoJSONReader } = await import("jsts/org/locationtech/jts/io/GeoJSONReader");
|
|
2998
|
+
const { default: GeometryFactory } = await import("jsts/org/locationtech/jts/geom/GeometryFactory");
|
|
2999
|
+
reader = new GeoJSONReader(new GeometryFactory());
|
|
3000
|
+
}
|
|
3001
|
+
return reader;
|
|
3002
|
+
}
|
|
3003
|
+
async function getWriter() {
|
|
3004
|
+
if (!writer) {
|
|
3005
|
+
const { default: GeoJSONWriter } = await import("jsts/org/locationtech/jts/io/GeoJSONWriter");
|
|
3006
|
+
writer = new GeoJSONWriter();
|
|
3007
|
+
}
|
|
3008
|
+
return writer;
|
|
3009
|
+
}
|
|
3010
|
+
async function toJsts(geometry) {
|
|
3011
|
+
const r = await getReader();
|
|
3012
|
+
return r.read(geometry);
|
|
3013
|
+
}
|
|
3014
|
+
async function fromJsts(jtsGeom) {
|
|
3015
|
+
const w = await getWriter();
|
|
3016
|
+
return w.write(jtsGeom);
|
|
3017
|
+
}
|
|
3018
|
+
async function toJstsPoint(geometry) {
|
|
3019
|
+
const r = await getReader();
|
|
3020
|
+
return r.read(geometry);
|
|
3021
|
+
}
|
|
3022
|
+
async function toJstsMultiLineString(geometry) {
|
|
3023
|
+
const r = await getReader();
|
|
3024
|
+
return r.read(geometry);
|
|
3025
|
+
}
|
|
3026
|
+
async function toJstsMultiPolygon(geometry) {
|
|
3027
|
+
const r = await getReader();
|
|
3028
|
+
return r.read(geometry);
|
|
3029
|
+
}
|
|
3030
|
+
var JstsGeometryCodec = class {
|
|
3031
|
+
static async decode(input) {
|
|
3032
|
+
const geojson = GaiaGeometryCodec.decode(input);
|
|
3033
|
+
return toJsts(geojson);
|
|
3034
|
+
}
|
|
3035
|
+
static async encode(jtsGeom, srid) {
|
|
3036
|
+
const geojson = await fromJsts(jtsGeom);
|
|
3037
|
+
return GaiaGeometryCodec.encode(geojson, srid);
|
|
3038
|
+
}
|
|
3039
|
+
};
|
|
3040
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
3041
|
+
0 && (module.exports = {
|
|
3042
|
+
BaseDataset,
|
|
3043
|
+
BinaryCursor,
|
|
3044
|
+
BinaryWriter,
|
|
3045
|
+
CadDataset,
|
|
3046
|
+
GAIA_BYTE_ORDER_LE,
|
|
3047
|
+
GAIA_END,
|
|
3048
|
+
GAIA_GEOMETRY_DATA_OFFSET,
|
|
3049
|
+
GAIA_MBR,
|
|
3050
|
+
GAIA_START,
|
|
3051
|
+
GEO_TYPE_MULTILINESTRING,
|
|
3052
|
+
GEO_TYPE_MULTILINESTRINGZ,
|
|
3053
|
+
GEO_TYPE_MULTIPOLYGON,
|
|
3054
|
+
GEO_TYPE_MULTIPOLYGONZ,
|
|
3055
|
+
GEO_TYPE_POINT,
|
|
3056
|
+
GEO_TYPE_POINTZ,
|
|
3057
|
+
GaiaError,
|
|
3058
|
+
GaiaFormatError,
|
|
3059
|
+
GaiaGeoTypeMismatchError,
|
|
3060
|
+
GaiaGeometryCodec,
|
|
3061
|
+
GaiaLineCodec,
|
|
3062
|
+
GaiaPointCodec,
|
|
3063
|
+
GaiaPolygonCodec,
|
|
3064
|
+
GaiaUnsupportedGeoTypeError,
|
|
3065
|
+
JstsGeometryCodec,
|
|
3066
|
+
LineDataset,
|
|
3067
|
+
LineZDataset,
|
|
3068
|
+
NotImplementedError,
|
|
3069
|
+
PointDataset,
|
|
3070
|
+
PointZDataset,
|
|
3071
|
+
RegionDataset,
|
|
3072
|
+
RegionZDataset,
|
|
3073
|
+
SmFieldInfoRepository,
|
|
3074
|
+
SmRegisterRepository,
|
|
3075
|
+
TabularDataset,
|
|
3076
|
+
TextDataset,
|
|
3077
|
+
UDBX_SCHEMA_STATEMENTS,
|
|
3078
|
+
UDBX_SYSTEM_TABLES,
|
|
3079
|
+
UdbxConstraintError,
|
|
3080
|
+
UdbxDataSource,
|
|
3081
|
+
UdbxError,
|
|
3082
|
+
UdbxFormatError,
|
|
3083
|
+
UdbxIOError,
|
|
3084
|
+
UdbxNotFoundError,
|
|
3085
|
+
UdbxSchemaInitializer,
|
|
3086
|
+
UdbxUnsupportedError,
|
|
3087
|
+
createNotImplementedError,
|
|
3088
|
+
datasetKindToValue,
|
|
3089
|
+
datasetValueToKind,
|
|
3090
|
+
fieldTypeToValue,
|
|
3091
|
+
fieldValueToType,
|
|
3092
|
+
fromJsts,
|
|
3093
|
+
readGaiaHeader,
|
|
3094
|
+
toJsts,
|
|
3095
|
+
toJstsMultiLineString,
|
|
3096
|
+
toJstsMultiPolygon,
|
|
3097
|
+
toJstsPoint,
|
|
3098
|
+
validateGaiaEnd,
|
|
3099
|
+
writeGaiaHeader
|
|
3100
|
+
});
|
|
3101
|
+
//# sourceMappingURL=index.cjs.map
|