@lossless.org/client 0.1.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/.smartconfig.json +37 -0
- package/dist_ts/00_commitinfo_data.d.ts +8 -0
- package/dist_ts/00_commitinfo_data.js +9 -0
- package/dist_ts/classes.losslessorgclient.d.ts +32 -0
- package/dist_ts/classes.losslessorgclient.js +103 -0
- package/dist_ts/core/classes.error.d.ts +16 -0
- package/dist_ts/core/classes.error.js +29 -0
- package/dist_ts/core/classes.operation.d.ts +17 -0
- package/dist_ts/core/classes.operation.js +70 -0
- package/dist_ts/core/interfaces.d.ts +18 -0
- package/dist_ts/core/interfaces.js +2 -0
- package/dist_ts/index.d.ts +4 -0
- package/dist_ts/index.js +3 -0
- package/dist_ts/nosqldb/classes.atomicdelete.d.ts +26 -0
- package/dist_ts/nosqldb/classes.atomicdelete.js +44 -0
- package/dist_ts/nosqldb/classes.atomicfindoneandupdate.d.ts +27 -0
- package/dist_ts/nosqldb/classes.atomicfindoneandupdate.js +86 -0
- package/dist_ts/nosqldb/classes.atomicupdate.d.ts +26 -0
- package/dist_ts/nosqldb/classes.atomicupdate.js +55 -0
- package/dist_ts/nosqldb/classes.bootstraprecord.d.ts +14 -0
- package/dist_ts/nosqldb/classes.bootstraprecord.js +80 -0
- package/dist_ts/nosqldb/classes.bsonassertion.d.ts +2 -0
- package/dist_ts/nosqldb/classes.bsonassertion.js +29 -0
- package/dist_ts/nosqldb/classes.bsonobjectid.d.ts +2 -0
- package/dist_ts/nosqldb/classes.bsonobjectid.js +50 -0
- package/dist_ts/nosqldb/classes.bsonsnapshot.d.ts +3 -0
- package/dist_ts/nosqldb/classes.bsonsnapshot.js +126 -0
- package/dist_ts/nosqldb/classes.cached-document.d.ts +27 -0
- package/dist_ts/nosqldb/classes.cached-document.js +112 -0
- package/dist_ts/nosqldb/classes.collection.d.ts +302 -0
- package/dist_ts/nosqldb/classes.collection.js +1568 -0
- package/dist_ts/nosqldb/classes.collectionfactory.d.ts +30 -0
- package/dist_ts/nosqldb/classes.collectionfactory.js +65 -0
- package/dist_ts/nosqldb/classes.collectionlifecycle.d.ts +4 -0
- package/dist_ts/nosqldb/classes.collectionlifecycle.js +15 -0
- package/dist_ts/nosqldb/classes.collectionpreparation.d.ts +34 -0
- package/dist_ts/nosqldb/classes.collectionpreparation.js +134 -0
- package/dist_ts/nosqldb/classes.collectiontopology.d.ts +47 -0
- package/dist_ts/nosqldb/classes.collectiontopology.js +388 -0
- package/dist_ts/nosqldb/classes.connection.d.ts +18 -0
- package/dist_ts/nosqldb/classes.connection.js +23 -0
- package/dist_ts/nosqldb/classes.convenience.d.ts +1 -0
- package/dist_ts/nosqldb/classes.convenience.js +5 -0
- package/dist_ts/nosqldb/classes.cursor.d.ts +15 -0
- package/dist_ts/nosqldb/classes.cursor.js +82 -0
- package/dist_ts/nosqldb/classes.cursoroperation.d.ts +7 -0
- package/dist_ts/nosqldb/classes.cursoroperation.js +36 -0
- package/dist_ts/nosqldb/classes.db.d.ts +98 -0
- package/dist_ts/nosqldb/classes.db.js +434 -0
- package/dist_ts/nosqldb/classes.distributedcoordinator.d.ts +52 -0
- package/dist_ts/nosqldb/classes.distributedcoordinator.js +314 -0
- package/dist_ts/nosqldb/classes.doc.d.ts +722 -0
- package/dist_ts/nosqldb/classes.doc.js +2976 -0
- package/dist_ts/nosqldb/classes.easystore.d.ts +42 -0
- package/dist_ts/nosqldb/classes.easystore.js +199 -0
- package/dist_ts/nosqldb/classes.exactpersistence.d.ts +141 -0
- package/dist_ts/nosqldb/classes.exactpersistence.js +1110 -0
- package/dist_ts/nosqldb/classes.lucene.adapter.d.ts +173 -0
- package/dist_ts/nosqldb/classes.lucene.adapter.js +623 -0
- package/dist_ts/nosqldb/classes.mongoadministration.d.ts +73 -0
- package/dist_ts/nosqldb/classes.mongoadministration.js +497 -0
- package/dist_ts/nosqldb/classes.namespaceinspection.d.ts +42 -0
- package/dist_ts/nosqldb/classes.namespaceinspection.js +138 -0
- package/dist_ts/nosqldb/classes.operationbudget.d.ts +22 -0
- package/dist_ts/nosqldb/classes.operationbudget.js +65 -0
- package/dist_ts/nosqldb/classes.ordinarypersistence.d.ts +18 -0
- package/dist_ts/nosqldb/classes.ordinarypersistence.js +71 -0
- package/dist_ts/nosqldb/classes.persistence.d.ts +14 -0
- package/dist_ts/nosqldb/classes.persistence.js +34 -0
- package/dist_ts/nosqldb/classes.session.d.ts +28 -0
- package/dist_ts/nosqldb/classes.session.js +246 -0
- package/dist_ts/nosqldb/classes.storedinspection.d.ts +44 -0
- package/dist_ts/nosqldb/classes.storedinspection.js +100 -0
- package/dist_ts/nosqldb/classes.testdatabase.d.ts +56 -0
- package/dist_ts/nosqldb/classes.testdatabase.js +250 -0
- package/dist_ts/nosqldb/classes.watcher.d.ts +37 -0
- package/dist_ts/nosqldb/classes.watcher.js +98 -0
- package/dist_ts/nosqldb/index.d.ts +27 -0
- package/dist_ts/nosqldb/index.js +18 -0
- package/dist_ts/nosqldb/logging.d.ts +2 -0
- package/dist_ts/nosqldb/logging.js +3 -0
- package/dist_ts/nosqldb/plugins.d.ts +17 -0
- package/dist_ts/nosqldb/plugins.js +20 -0
- package/dist_ts/nosqldb/shim.d.ts +1 -0
- package/dist_ts/nosqldb/shim.js +8 -0
- package/dist_ts/nosqldb/testsupport.d.ts +3 -0
- package/dist_ts/nosqldb/testsupport.js +3 -0
- package/dist_ts/objectstorage/classes.bucket.d.ts +227 -0
- package/dist_ts/objectstorage/classes.bucket.js +939 -0
- package/dist_ts/objectstorage/classes.connection.d.ts +21 -0
- package/dist_ts/objectstorage/classes.connection.js +27 -0
- package/dist_ts/objectstorage/classes.directory.d.ts +124 -0
- package/dist_ts/objectstorage/classes.directory.js +335 -0
- package/dist_ts/objectstorage/classes.exactpathpurgeerror.d.ts +5 -0
- package/dist_ts/objectstorage/classes.exactpathpurgeerror.js +18 -0
- package/dist_ts/objectstorage/classes.exactuploaderror.d.ts +5 -0
- package/dist_ts/objectstorage/classes.exactuploaderror.js +19 -0
- package/dist_ts/objectstorage/classes.file.d.ts +91 -0
- package/dist_ts/objectstorage/classes.file.js +255 -0
- package/dist_ts/objectstorage/classes.listcursor.d.ts +41 -0
- package/dist_ts/objectstorage/classes.listcursor.js +67 -0
- package/dist_ts/objectstorage/classes.metadata.d.ts +57 -0
- package/dist_ts/objectstorage/classes.metadata.js +113 -0
- package/dist_ts/objectstorage/classes.smartbucket.d.ts +57 -0
- package/dist_ts/objectstorage/classes.smartbucket.js +357 -0
- package/dist_ts/objectstorage/classes.trash.d.ts +11 -0
- package/dist_ts/objectstorage/classes.trash.js +22 -0
- package/dist_ts/objectstorage/classes.watcher.d.ts +79 -0
- package/dist_ts/objectstorage/classes.watcher.js +249 -0
- package/dist_ts/objectstorage/helpers.d.ts +25 -0
- package/dist_ts/objectstorage/helpers.js +215 -0
- package/dist_ts/objectstorage/index.d.ts +13 -0
- package/dist_ts/objectstorage/index.js +13 -0
- package/dist_ts/objectstorage/interfaces.d.ts +276 -0
- package/dist_ts/objectstorage/interfaces.js +2 -0
- package/dist_ts/objectstorage/internal.exactpathpurge.operations.d.ts +11 -0
- package/dist_ts/objectstorage/internal.exactpathpurge.operations.js +1069 -0
- package/dist_ts/objectstorage/internal.exactupload.capability.d.ts +40 -0
- package/dist_ts/objectstorage/internal.exactupload.capability.js +382 -0
- package/dist_ts/objectstorage/internal.exactupload.operations.d.ts +11 -0
- package/dist_ts/objectstorage/internal.exactupload.operations.js +1104 -0
- package/dist_ts/objectstorage/internal.multipart.planner.d.ts +8 -0
- package/dist_ts/objectstorage/internal.multipart.planner.js +63 -0
- package/dist_ts/objectstorage/internal.multipart.stream.d.ts +17 -0
- package/dist_ts/objectstorage/internal.multipart.stream.js +440 -0
- package/dist_ts/objectstorage/internal.multipart.types.d.ts +82 -0
- package/dist_ts/objectstorage/internal.multipart.types.js +2 -0
- package/dist_ts/objectstorage/plugins.d.ts +17 -0
- package/dist_ts/objectstorage/plugins.js +23 -0
- package/dist_ts/plugins.d.ts +4 -0
- package/dist_ts/plugins.js +5 -0
- package/dist_ts/sqldb/classes.clickhouseconnection.d.ts +39 -0
- package/dist_ts/sqldb/classes.clickhouseconnection.js +225 -0
- package/dist_ts/sqldb/classes.sqlconnection.d.ts +50 -0
- package/dist_ts/sqldb/classes.sqlconnection.js +376 -0
- package/dist_ts/sqldb/classes.sqltable.d.ts +29 -0
- package/dist_ts/sqldb/classes.sqltable.js +70 -0
- package/dist_ts/sqldb/clickhouse/classes.metricwriter.d.ts +27 -0
- package/dist_ts/sqldb/clickhouse/classes.metricwriter.js +89 -0
- package/dist_ts/sqldb/clickhouse/index.d.ts +9 -0
- package/dist_ts/sqldb/clickhouse/index.js +13 -0
- package/dist_ts/sqldb/clickhouse/smartclickhouse.classes.clickhousetable.d.ts +88 -0
- package/dist_ts/sqldb/clickhouse/smartclickhouse.classes.clickhousetable.js +304 -0
- package/dist_ts/sqldb/clickhouse/smartclickhouse.classes.httpclient.d.ts +28 -0
- package/dist_ts/sqldb/clickhouse/smartclickhouse.classes.httpclient.js +46 -0
- package/dist_ts/sqldb/clickhouse/smartclickhouse.classes.querybuilder.d.ts +43 -0
- package/dist_ts/sqldb/clickhouse/smartclickhouse.classes.querybuilder.js +155 -0
- package/dist_ts/sqldb/clickhouse/smartclickhouse.classes.resultset.d.ts +13 -0
- package/dist_ts/sqldb/clickhouse/smartclickhouse.classes.resultset.js +36 -0
- package/dist_ts/sqldb/clickhouse/smartclickhouse.classes.smartclickhouse.d.ts +49 -0
- package/dist_ts/sqldb/clickhouse/smartclickhouse.classes.smartclickhouse.js +106 -0
- package/dist_ts/sqldb/clickhouse/smartclickhouse.classes.timedatatable.d.ts +51 -0
- package/dist_ts/sqldb/clickhouse/smartclickhouse.classes.timedatatable.js +96 -0
- package/dist_ts/sqldb/clickhouse/smartclickhouse.plugins.d.ts +5 -0
- package/dist_ts/sqldb/clickhouse/smartclickhouse.plugins.js +6 -0
- package/dist_ts/sqldb/clickhouse/smartclickhouse.types.d.ts +53 -0
- package/dist_ts/sqldb/clickhouse/smartclickhouse.types.js +41 -0
- package/dist_ts/sqldb/index.d.ts +6 -0
- package/dist_ts/sqldb/index.js +6 -0
- package/dist_ts/sqldb/interfaces.d.ts +53 -0
- package/dist_ts/sqldb/interfaces.js +19 -0
- package/dist_ts/sqldb/internal.sqlpool.d.ts +51 -0
- package/dist_ts/sqldb/internal.sqlpool.js +214 -0
- package/dist_ts/sqldb/plugins.clickhouse.d.ts +4 -0
- package/dist_ts/sqldb/plugins.clickhouse.js +5 -0
- package/dist_ts/sqldb/plugins.mariadb.d.ts +4 -0
- package/dist_ts/sqldb/plugins.mariadb.js +5 -0
- package/docs/source/smartbucket/license.md +19 -0
- package/docs/source/smartclickhouse/license.md +19 -0
- package/license.md +21 -0
- package/package.json +101 -0
- package/readme.md +157 -0
- package/ts/00_commitinfo_data.ts +8 -0
- package/ts/classes.losslessorgclient.ts +104 -0
- package/ts/core/classes.error.ts +31 -0
- package/ts/core/classes.operation.ts +60 -0
- package/ts/core/interfaces.ts +24 -0
- package/ts/index.ts +4 -0
- package/ts/nosqldb/classes.atomicdelete.ts +81 -0
- package/ts/nosqldb/classes.atomicfindoneandupdate.ts +152 -0
- package/ts/nosqldb/classes.atomicupdate.ts +99 -0
- package/ts/nosqldb/classes.bootstraprecord.ts +107 -0
- package/ts/nosqldb/classes.bsonassertion.ts +25 -0
- package/ts/nosqldb/classes.bsonobjectid.ts +45 -0
- package/ts/nosqldb/classes.bsonsnapshot.ts +105 -0
- package/ts/nosqldb/classes.cached-document.ts +67 -0
- package/ts/nosqldb/classes.collection.ts +2399 -0
- package/ts/nosqldb/classes.collectionfactory.ts +87 -0
- package/ts/nosqldb/classes.collectionlifecycle.ts +24 -0
- package/ts/nosqldb/classes.collectionpreparation.ts +164 -0
- package/ts/nosqldb/classes.collectiontopology.ts +645 -0
- package/ts/nosqldb/classes.connection.ts +31 -0
- package/ts/nosqldb/classes.convenience.ts +5 -0
- package/ts/nosqldb/classes.cursor.ts +88 -0
- package/ts/nosqldb/classes.cursoroperation.ts +38 -0
- package/ts/nosqldb/classes.db.ts +637 -0
- package/ts/nosqldb/classes.distributedcoordinator.ts +305 -0
- package/ts/nosqldb/classes.doc.ts +4928 -0
- package/ts/nosqldb/classes.easystore.ts +154 -0
- package/ts/nosqldb/classes.exactpersistence.ts +1974 -0
- package/ts/nosqldb/classes.lucene.adapter.ts +780 -0
- package/ts/nosqldb/classes.mongoadministration.ts +867 -0
- package/ts/nosqldb/classes.namespaceinspection.ts +199 -0
- package/ts/nosqldb/classes.operationbudget.ts +75 -0
- package/ts/nosqldb/classes.ordinarypersistence.ts +84 -0
- package/ts/nosqldb/classes.persistence.ts +62 -0
- package/ts/nosqldb/classes.session.ts +389 -0
- package/ts/nosqldb/classes.storedinspection.ts +151 -0
- package/ts/nosqldb/classes.testdatabase.ts +272 -0
- package/ts/nosqldb/classes.watcher.ts +96 -0
- package/ts/nosqldb/index.ts +51 -0
- package/ts/nosqldb/logging.ts +3 -0
- package/ts/nosqldb/plugins.ts +37 -0
- package/ts/nosqldb/shim.ts +6 -0
- package/ts/nosqldb/testsupport.ts +13 -0
- package/ts/objectstorage/classes.bucket.ts +1114 -0
- package/ts/objectstorage/classes.connection.ts +36 -0
- package/ts/objectstorage/classes.directory.ts +425 -0
- package/ts/objectstorage/classes.exactpathpurgeerror.ts +24 -0
- package/ts/objectstorage/classes.exactuploaderror.ts +25 -0
- package/ts/objectstorage/classes.file.ts +303 -0
- package/ts/objectstorage/classes.listcursor.ts +89 -0
- package/ts/objectstorage/classes.metadata.ts +134 -0
- package/ts/objectstorage/classes.smartbucket.ts +445 -0
- package/ts/objectstorage/classes.trash.ts +30 -0
- package/ts/objectstorage/classes.watcher.ts +289 -0
- package/ts/objectstorage/helpers.ts +254 -0
- package/ts/objectstorage/index.ts +13 -0
- package/ts/objectstorage/interfaces.ts +389 -0
- package/ts/objectstorage/internal.exactpathpurge.operations.ts +1936 -0
- package/ts/objectstorage/internal.exactupload.capability.ts +580 -0
- package/ts/objectstorage/internal.exactupload.operations.ts +1715 -0
- package/ts/objectstorage/internal.multipart.planner.ts +90 -0
- package/ts/objectstorage/internal.multipart.stream.ts +606 -0
- package/ts/objectstorage/internal.multipart.types.ts +106 -0
- package/ts/objectstorage/plugins.ts +35 -0
- package/ts/plugins.ts +4 -0
- package/ts/sqldb/classes.clickhouseconnection.ts +189 -0
- package/ts/sqldb/classes.sqlconnection.ts +350 -0
- package/ts/sqldb/classes.sqltable.ts +70 -0
- package/ts/sqldb/clickhouse/classes.metricwriter.ts +72 -0
- package/ts/sqldb/clickhouse/index.ts +16 -0
- package/ts/sqldb/clickhouse/smartclickhouse.classes.clickhousetable.ts +372 -0
- package/ts/sqldb/clickhouse/smartclickhouse.classes.httpclient.ts +52 -0
- package/ts/sqldb/clickhouse/smartclickhouse.classes.querybuilder.ts +120 -0
- package/ts/sqldb/clickhouse/smartclickhouse.classes.resultset.ts +44 -0
- package/ts/sqldb/clickhouse/smartclickhouse.classes.smartclickhouse.ts +123 -0
- package/ts/sqldb/clickhouse/smartclickhouse.classes.timedatatable.ts +114 -0
- package/ts/sqldb/clickhouse/smartclickhouse.plugins.ts +5 -0
- package/ts/sqldb/clickhouse/smartclickhouse.types.ts +134 -0
- package/ts/sqldb/index.ts +6 -0
- package/ts/sqldb/interfaces.ts +61 -0
- package/ts/sqldb/internal.sqlpool.ts +179 -0
- package/ts/sqldb/plugins.clickhouse.ts +4 -0
- package/ts/sqldb/plugins.mariadb.ts +4 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// Core
|
|
2
|
+
export * from './smartclickhouse.classes.smartclickhouse.js';
|
|
3
|
+
export * from './smartclickhouse.classes.clickhousetable.js';
|
|
4
|
+
export * from './smartclickhouse.classes.httpclient.js';
|
|
5
|
+
// Query & Results
|
|
6
|
+
export * from './smartclickhouse.classes.querybuilder.js';
|
|
7
|
+
export * from './smartclickhouse.classes.resultset.js';
|
|
8
|
+
// Time Data Table (backward compat)
|
|
9
|
+
export * from './smartclickhouse.classes.timedatatable.js';
|
|
10
|
+
// Types
|
|
11
|
+
export * from './smartclickhouse.types.js';
|
|
12
|
+
export { MetricWriter } from './classes.metricwriter.js';
|
|
13
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy9zcWxkYi9jbGlja2hvdXNlL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU87QUFDUCxjQUFjLDhDQUE4QyxDQUFDO0FBQzdELGNBQWMsOENBQThDLENBQUM7QUFDN0QsY0FBYyx5Q0FBeUMsQ0FBQztBQUV4RCxrQkFBa0I7QUFDbEIsY0FBYywyQ0FBMkMsQ0FBQztBQUMxRCxjQUFjLHdDQUF3QyxDQUFDO0FBRXZELG9DQUFvQztBQUNwQyxjQUFjLDRDQUE0QyxDQUFDO0FBRTNELFFBQVE7QUFDUixjQUFjLDRCQUE0QixDQUFDO0FBQzNDLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQyJ9
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import * as plugins from './smartclickhouse.plugins.js';
|
|
2
|
+
import type { SmartClickHouseDb } from './smartclickhouse.classes.smartclickhouse.js';
|
|
3
|
+
import { ClickhouseQueryBuilder } from './smartclickhouse.classes.querybuilder.js';
|
|
4
|
+
import type { IClickhouseTableOptions, IColumnInfo, IEngineConfig } from './smartclickhouse.types.js';
|
|
5
|
+
import { MetricWriter, type IMetricWriterOptions } from './classes.metricwriter.js';
|
|
6
|
+
import type { IOperationOptions } from '../../core/interfaces.js';
|
|
7
|
+
export declare class ClickhouseTable<T extends Record<string, any>> {
|
|
8
|
+
static create<T extends Record<string, any>>(db: SmartClickHouseDb, options: IClickhouseTableOptions<T>): Promise<ClickhouseTable<T>>;
|
|
9
|
+
db: SmartClickHouseDb;
|
|
10
|
+
options: IClickhouseTableOptions<T> & {
|
|
11
|
+
database: string;
|
|
12
|
+
engine: IEngineConfig;
|
|
13
|
+
};
|
|
14
|
+
columns: IColumnInfo[];
|
|
15
|
+
constructor(db: SmartClickHouseDb, options: IClickhouseTableOptions<T>);
|
|
16
|
+
protected get qualifiedName(): string;
|
|
17
|
+
private interval;
|
|
18
|
+
/**
|
|
19
|
+
* Creates the table if it doesn't exist and refreshes column metadata
|
|
20
|
+
*/
|
|
21
|
+
setup(): Promise<void>;
|
|
22
|
+
/**
|
|
23
|
+
* Refresh column metadata from system.columns
|
|
24
|
+
*/
|
|
25
|
+
updateColumns(): Promise<IColumnInfo[]>;
|
|
26
|
+
/**
|
|
27
|
+
* Auto-schema evolution: detect new columns from data and add them
|
|
28
|
+
*/
|
|
29
|
+
syncSchema(data: Record<string, any>): Promise<void>;
|
|
30
|
+
/**
|
|
31
|
+
* Insert a single row
|
|
32
|
+
*/
|
|
33
|
+
insert(data: Partial<T>): Promise<void>;
|
|
34
|
+
/**
|
|
35
|
+
* Insert multiple rows
|
|
36
|
+
*/
|
|
37
|
+
insertMany(data: Partial<T>[]): Promise<void>;
|
|
38
|
+
/**
|
|
39
|
+
* Insert in batches of configurable size
|
|
40
|
+
*/
|
|
41
|
+
insertBatch(data: Partial<T>[], options?: {
|
|
42
|
+
batchSize?: number;
|
|
43
|
+
}): Promise<void>;
|
|
44
|
+
/** Await write() for backpressure and close() for the final acknowledged flush. */
|
|
45
|
+
createInsertStream(options?: IMetricWriterOptions): MetricWriter<Partial<T>>;
|
|
46
|
+
/**
|
|
47
|
+
* Returns a fluent query builder for this table
|
|
48
|
+
*/
|
|
49
|
+
query(): ClickhouseQueryBuilder<T>;
|
|
50
|
+
/**
|
|
51
|
+
* Update rows matching a where condition (ClickHouse mutation - use sparingly)
|
|
52
|
+
*/
|
|
53
|
+
update(set: Partial<T>, whereFn: (q: ClickhouseQueryBuilder<T>) => ClickhouseQueryBuilder<T>): Promise<void>;
|
|
54
|
+
/**
|
|
55
|
+
* Delete rows matching a where condition (ClickHouse mutation)
|
|
56
|
+
*/
|
|
57
|
+
deleteWhere(whereFn: (q: ClickhouseQueryBuilder<T>) => ClickhouseQueryBuilder<T>): Promise<void>;
|
|
58
|
+
/**
|
|
59
|
+
* Delete entries older than a given interval on a column
|
|
60
|
+
*/
|
|
61
|
+
deleteOlderThan(column: keyof T & string, interval: string): Promise<void>;
|
|
62
|
+
/**
|
|
63
|
+
* Drop the entire table
|
|
64
|
+
*/
|
|
65
|
+
drop(): Promise<void>;
|
|
66
|
+
/**
|
|
67
|
+
* Wait for all pending mutations on this table to complete
|
|
68
|
+
*/
|
|
69
|
+
waitForMutations(options?: IOperationOptions): Promise<void>;
|
|
70
|
+
/**
|
|
71
|
+
* Get the total row count
|
|
72
|
+
*/
|
|
73
|
+
getRowCount(): Promise<number>;
|
|
74
|
+
/**
|
|
75
|
+
* Optimize table (useful for ReplacingMergeTree deduplication)
|
|
76
|
+
*/
|
|
77
|
+
optimize(final?: boolean): Promise<void>;
|
|
78
|
+
/**
|
|
79
|
+
* Watch for new entries via polling. Returns an RxJS Observable.
|
|
80
|
+
*/
|
|
81
|
+
watch(_options?: {
|
|
82
|
+
pollInterval?: number;
|
|
83
|
+
}): plugins.smartrx.rxjs.Observable<T>;
|
|
84
|
+
private ensureColumn;
|
|
85
|
+
private flattenDocument;
|
|
86
|
+
private prepareDocument;
|
|
87
|
+
private executeInsert;
|
|
88
|
+
}
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
import * as plugins from './smartclickhouse.plugins.js';
|
|
2
|
+
import { ClickhouseQueryBuilder } from './smartclickhouse.classes.querybuilder.js';
|
|
3
|
+
import { detectClickhouseType } from './smartclickhouse.types.js';
|
|
4
|
+
import { quoteClickHouseIdentifier as quoteIdentifier } from '../interfaces.js';
|
|
5
|
+
import { MetricWriter } from './classes.metricwriter.js';
|
|
6
|
+
import { Operation } from '../../core/classes.operation.js';
|
|
7
|
+
import { LosslessClientError } from '../../core/classes.error.js';
|
|
8
|
+
export class ClickhouseTable {
|
|
9
|
+
// ---- STATIC FACTORY ----
|
|
10
|
+
static async create(db, options) {
|
|
11
|
+
const table = new ClickhouseTable(db, options);
|
|
12
|
+
await table.setup();
|
|
13
|
+
return table;
|
|
14
|
+
}
|
|
15
|
+
// ---- INSTANCE ----
|
|
16
|
+
db;
|
|
17
|
+
options;
|
|
18
|
+
columns = [];
|
|
19
|
+
constructor(db, options) {
|
|
20
|
+
this.db = db;
|
|
21
|
+
this.options = {
|
|
22
|
+
autoSchemaEvolution: true,
|
|
23
|
+
...options,
|
|
24
|
+
database: options.database || db.options.database,
|
|
25
|
+
engine: options.engine || { engine: 'MergeTree' },
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
get qualifiedName() {
|
|
29
|
+
return quoteIdentifier(this.options.database) + '.' + quoteIdentifier(this.options.tableName);
|
|
30
|
+
}
|
|
31
|
+
interval(value) {
|
|
32
|
+
if (!/^[1-9][0-9]* (SECOND|MINUTE|HOUR|DAY|WEEK|MONTH|QUARTER|YEAR)$/i.test(value)) {
|
|
33
|
+
throw new RangeError('An interval must be a positive integer and a supported unit.');
|
|
34
|
+
}
|
|
35
|
+
return value;
|
|
36
|
+
}
|
|
37
|
+
// ---- SCHEMA MANAGEMENT ----
|
|
38
|
+
/**
|
|
39
|
+
* Creates the table if it doesn't exist and refreshes column metadata
|
|
40
|
+
*/
|
|
41
|
+
async setup() {
|
|
42
|
+
const { database, tableName, engine, orderBy, partitionBy, primaryKey, ttl, retainDataForDays, columns } = this.options;
|
|
43
|
+
// Build column definitions
|
|
44
|
+
let columnDefs;
|
|
45
|
+
if (columns && columns.length > 0) {
|
|
46
|
+
columnDefs = columns.map((col) => {
|
|
47
|
+
let def = `${quoteIdentifier(col.name)} ${col.type}`;
|
|
48
|
+
if (col.defaultExpression)
|
|
49
|
+
def += ` DEFAULT ${col.defaultExpression}`;
|
|
50
|
+
if (col.codec)
|
|
51
|
+
def += ` CODEC(${col.codec})`;
|
|
52
|
+
return def;
|
|
53
|
+
}).join(',\n ');
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
// Default minimal schema — downstream code can add columns via auto-schema evolution
|
|
57
|
+
columnDefs = `timestamp DateTime64(3, 'Europe/Berlin'),\n message String`;
|
|
58
|
+
}
|
|
59
|
+
// Build engine clause
|
|
60
|
+
if (!['MergeTree', 'ReplacingMergeTree', 'SummingMergeTree', 'AggregatingMergeTree',
|
|
61
|
+
'CollapsingMergeTree', 'VersionedCollapsingMergeTree'].includes(engine.engine)) {
|
|
62
|
+
throw new RangeError('Unsupported table engine.');
|
|
63
|
+
}
|
|
64
|
+
let engineClause = engine.engine;
|
|
65
|
+
if (engine.engine === 'ReplacingMergeTree' && engine.versionColumn) {
|
|
66
|
+
engineClause = `ReplacingMergeTree(${quoteIdentifier(engine.versionColumn)})`;
|
|
67
|
+
}
|
|
68
|
+
else if (engine.engine === 'CollapsingMergeTree' && engine.signColumn) {
|
|
69
|
+
engineClause = `CollapsingMergeTree(${quoteIdentifier(engine.signColumn)})`;
|
|
70
|
+
}
|
|
71
|
+
else if (engine.engine === 'VersionedCollapsingMergeTree' && engine.signColumn && engine.versionColumn) {
|
|
72
|
+
engineClause = `VersionedCollapsingMergeTree(${quoteIdentifier(engine.signColumn)}, ${quoteIdentifier(engine.versionColumn)})`;
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
engineClause = `${engine.engine}()`;
|
|
76
|
+
}
|
|
77
|
+
// Build ORDER BY
|
|
78
|
+
const orderByStr = Array.isArray(orderBy) ? orderBy.map(quoteIdentifier).join(', ') : quoteIdentifier(orderBy);
|
|
79
|
+
let createSQL = `
|
|
80
|
+
CREATE TABLE IF NOT EXISTS ${this.qualifiedName} (
|
|
81
|
+
${columnDefs}
|
|
82
|
+
) ENGINE = ${engineClause}`;
|
|
83
|
+
if (partitionBy) {
|
|
84
|
+
createSQL += `\n PARTITION BY ${partitionBy}`;
|
|
85
|
+
}
|
|
86
|
+
createSQL += `\n ORDER BY (${orderByStr})`;
|
|
87
|
+
if (primaryKey) {
|
|
88
|
+
const primaryKeyStr = Array.isArray(primaryKey) ? primaryKey.map(quoteIdentifier).join(', ') : quoteIdentifier(primaryKey);
|
|
89
|
+
createSQL += `\n PRIMARY KEY (${primaryKeyStr})`;
|
|
90
|
+
}
|
|
91
|
+
await this.db.clickhouseHttpClient.queryPromise(createSQL);
|
|
92
|
+
// Apply TTL if configured
|
|
93
|
+
if (ttl) {
|
|
94
|
+
await this.db.clickhouseHttpClient.queryPromise(`
|
|
95
|
+
ALTER TABLE ${this.qualifiedName}
|
|
96
|
+
MODIFY TTL toDateTime(${quoteIdentifier(String(ttl.column))}) + INTERVAL ${this.interval(ttl.interval)}
|
|
97
|
+
`);
|
|
98
|
+
}
|
|
99
|
+
else if (retainDataForDays && retainDataForDays > 0) {
|
|
100
|
+
// Legacy shorthand
|
|
101
|
+
await this.db.clickhouseHttpClient.queryPromise(`
|
|
102
|
+
ALTER TABLE ${this.qualifiedName}
|
|
103
|
+
MODIFY TTL toDateTime(timestamp) + INTERVAL ${this.interval(retainDataForDays + ' DAY')}
|
|
104
|
+
`);
|
|
105
|
+
}
|
|
106
|
+
await this.updateColumns();
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Refresh column metadata from system.columns
|
|
110
|
+
*/
|
|
111
|
+
async updateColumns() {
|
|
112
|
+
this.columns = await this.db.clickhouseHttpClient.queryPromise(`
|
|
113
|
+
SELECT * FROM system.columns
|
|
114
|
+
WHERE database = {database:String}
|
|
115
|
+
AND table = {table:String}
|
|
116
|
+
`, { database: this.options.database, table: this.options.tableName });
|
|
117
|
+
return this.columns;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Auto-schema evolution: detect new columns from data and add them
|
|
121
|
+
*/
|
|
122
|
+
async syncSchema(data) {
|
|
123
|
+
const flatData = plugins.smartobject.toFlatObject(data);
|
|
124
|
+
for (const key of Object.keys(flatData)) {
|
|
125
|
+
if (key === 'timestamp')
|
|
126
|
+
continue;
|
|
127
|
+
const value = flatData[key];
|
|
128
|
+
const clickhouseType = detectClickhouseType(value);
|
|
129
|
+
if (!clickhouseType)
|
|
130
|
+
continue;
|
|
131
|
+
await this.ensureColumn(key, clickhouseType);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
// ---- INSERT ----
|
|
135
|
+
/**
|
|
136
|
+
* Insert a single row
|
|
137
|
+
*/
|
|
138
|
+
async insert(data) {
|
|
139
|
+
const storageDoc = await this.prepareDocument(data);
|
|
140
|
+
await this.executeInsert([storageDoc]);
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Insert multiple rows
|
|
144
|
+
*/
|
|
145
|
+
async insertMany(data) {
|
|
146
|
+
if (data.length === 0)
|
|
147
|
+
return;
|
|
148
|
+
// Schema sync across all documents
|
|
149
|
+
if (this.options.autoSchemaEvolution) {
|
|
150
|
+
const allKeys = new Set();
|
|
151
|
+
const sampleValues = {};
|
|
152
|
+
for (const doc of data) {
|
|
153
|
+
const flat = plugins.smartobject.toFlatObject(doc);
|
|
154
|
+
for (const [key, value] of Object.entries(flat)) {
|
|
155
|
+
if (!allKeys.has(key)) {
|
|
156
|
+
allKeys.add(key);
|
|
157
|
+
sampleValues[key] = value;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
await this.syncSchema(sampleValues);
|
|
162
|
+
}
|
|
163
|
+
const storageDocs = data.map((doc) => this.flattenDocument(doc));
|
|
164
|
+
await this.executeInsert(storageDocs);
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Insert in batches of configurable size
|
|
168
|
+
*/
|
|
169
|
+
async insertBatch(data, options) {
|
|
170
|
+
const size = options?.batchSize ?? 500;
|
|
171
|
+
if (!Number.isSafeInteger(size) || size < 1)
|
|
172
|
+
throw new RangeError('batchSize must be positive.');
|
|
173
|
+
for (let offset = 0; offset < data.length; offset += size) {
|
|
174
|
+
await this.insertMany(data.slice(offset, offset + size));
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
/** Await write() for backpressure and close() for the final acknowledged flush. */
|
|
178
|
+
createInsertStream(options = {}) {
|
|
179
|
+
return this.db.ownWriter(new MetricWriter(rows => this.insertMany(rows), options));
|
|
180
|
+
}
|
|
181
|
+
// ---- QUERY ----
|
|
182
|
+
/**
|
|
183
|
+
* Returns a fluent query builder for this table
|
|
184
|
+
*/
|
|
185
|
+
query() {
|
|
186
|
+
return new ClickhouseQueryBuilder(this.options.tableName, this.options.database, this.db.clickhouseHttpClient);
|
|
187
|
+
}
|
|
188
|
+
// ---- UPDATE ----
|
|
189
|
+
/**
|
|
190
|
+
* Update rows matching a where condition (ClickHouse mutation - use sparingly)
|
|
191
|
+
*/
|
|
192
|
+
async update(set, whereFn) {
|
|
193
|
+
const qb = whereFn(new ClickhouseQueryBuilder(this.options.tableName, this.options.database, this.db.clickhouseHttpClient));
|
|
194
|
+
const whereClause = qb.buildWhereClause();
|
|
195
|
+
if (!whereClause) {
|
|
196
|
+
throw new Error('UPDATE requires a WHERE clause. Use a where condition to target specific rows.');
|
|
197
|
+
}
|
|
198
|
+
const setClauses = Object.entries(set)
|
|
199
|
+
.map(([key, value]) => `${quoteIdentifier(key)} = ${qb.bind(value)}`)
|
|
200
|
+
.join(', ');
|
|
201
|
+
await this.db.clickhouseHttpClient.mutatePromise(`ALTER TABLE ${this.qualifiedName} UPDATE ${setClauses} WHERE ${whereClause}`, qb.parameters);
|
|
202
|
+
await this.waitForMutations();
|
|
203
|
+
}
|
|
204
|
+
// ---- DELETE ----
|
|
205
|
+
/**
|
|
206
|
+
* Delete rows matching a where condition (ClickHouse mutation)
|
|
207
|
+
*/
|
|
208
|
+
async deleteWhere(whereFn) {
|
|
209
|
+
const qb = whereFn(new ClickhouseQueryBuilder(this.options.tableName, this.options.database, this.db.clickhouseHttpClient));
|
|
210
|
+
const whereClause = qb.buildWhereClause();
|
|
211
|
+
if (!whereClause) {
|
|
212
|
+
throw new Error('DELETE requires a WHERE clause.');
|
|
213
|
+
}
|
|
214
|
+
await this.db.clickhouseHttpClient.mutatePromise(`ALTER TABLE ${this.qualifiedName} DELETE WHERE ${whereClause}`, qb.parameters);
|
|
215
|
+
await this.waitForMutations();
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Delete entries older than a given interval on a column
|
|
219
|
+
*/
|
|
220
|
+
async deleteOlderThan(column, interval) {
|
|
221
|
+
await this.db.clickhouseHttpClient.mutatePromise(`ALTER TABLE ${this.qualifiedName} DELETE WHERE ${quoteIdentifier(String(column))} < now() - INTERVAL ${this.interval(interval)}`);
|
|
222
|
+
await this.waitForMutations();
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Drop the entire table
|
|
226
|
+
*/
|
|
227
|
+
async drop() {
|
|
228
|
+
await this.db.clickhouseHttpClient.queryPromise(`DROP TABLE IF EXISTS ${this.qualifiedName}`);
|
|
229
|
+
this.columns = [];
|
|
230
|
+
}
|
|
231
|
+
// ---- UTILITIES ----
|
|
232
|
+
/**
|
|
233
|
+
* Wait for all pending mutations on this table to complete
|
|
234
|
+
*/
|
|
235
|
+
async waitForMutations(options = {}) {
|
|
236
|
+
const operation = new Operation(options, this.db.options.timeoutMs);
|
|
237
|
+
try {
|
|
238
|
+
while (true) {
|
|
239
|
+
operation.check();
|
|
240
|
+
const rows = await this.db.clickhouseHttpClient.queryPromise('SELECT count() AS cnt FROM system.mutations WHERE is_done = 0 AND database = {database:String} AND table = {table:String}', { database: this.options.database, table: this.options.tableName }, { signal: operation.signal });
|
|
241
|
+
if (BigInt(rows[0]?.cnt ?? 0) === 0n)
|
|
242
|
+
return;
|
|
243
|
+
await plugins.smartdelay.delayFor(100);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
finally {
|
|
247
|
+
operation.dispose();
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Get the total row count
|
|
252
|
+
*/
|
|
253
|
+
async getRowCount() {
|
|
254
|
+
const result = await this.db.clickhouseHttpClient.queryPromise(`
|
|
255
|
+
SELECT count() AS cnt FROM ${this.qualifiedName} FORMAT JSONEachRow
|
|
256
|
+
`);
|
|
257
|
+
const count = Number(result[0]?.cnt ?? 0);
|
|
258
|
+
if (!Number.isSafeInteger(count))
|
|
259
|
+
throw new RangeError('Count exceeds a safe JavaScript integer.');
|
|
260
|
+
return count;
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Optimize table (useful for ReplacingMergeTree deduplication)
|
|
264
|
+
*/
|
|
265
|
+
async optimize(final = false) {
|
|
266
|
+
const finalClause = final ? ' FINAL' : '';
|
|
267
|
+
await this.db.clickhouseHttpClient.queryPromise(`OPTIMIZE TABLE ${this.qualifiedName}${finalClause}`);
|
|
268
|
+
}
|
|
269
|
+
// ---- OBSERVATION ----
|
|
270
|
+
/**
|
|
271
|
+
* Watch for new entries via polling. Returns an RxJS Observable.
|
|
272
|
+
*/
|
|
273
|
+
watch(_options) {
|
|
274
|
+
return new plugins.smartrx.rxjs.Observable(observer => observer.error(new LosslessClientError('unsupported_capability', 'Timestamp polling cannot guarantee delivery of equal-timestamp or late rows. Use an explicit stable ingestion cursor before enabling a watch.')));
|
|
275
|
+
}
|
|
276
|
+
// ---- PRIVATE HELPERS ----
|
|
277
|
+
async ensureColumn(name, type) {
|
|
278
|
+
if (this.columns.some(column => column.name === name))
|
|
279
|
+
return;
|
|
280
|
+
await this.db.clickhouseHttpClient.queryPromise(`ALTER TABLE ${this.qualifiedName} ADD COLUMN IF NOT EXISTS ${quoteIdentifier(name)} ${type}`);
|
|
281
|
+
await this.updateColumns();
|
|
282
|
+
}
|
|
283
|
+
flattenDocument(data) {
|
|
284
|
+
const flat = plugins.smartobject.toFlatObject(data);
|
|
285
|
+
const storageDoc = {};
|
|
286
|
+
for (const [key, value] of Object.entries(flat)) {
|
|
287
|
+
const type = detectClickhouseType(value);
|
|
288
|
+
if (type || key === 'timestamp') {
|
|
289
|
+
storageDoc[key] = value;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
return storageDoc;
|
|
293
|
+
}
|
|
294
|
+
async prepareDocument(data) {
|
|
295
|
+
if (this.options.autoSchemaEvolution) {
|
|
296
|
+
await this.syncSchema(data);
|
|
297
|
+
}
|
|
298
|
+
return this.flattenDocument(data);
|
|
299
|
+
}
|
|
300
|
+
async executeInsert(docs) {
|
|
301
|
+
await this.db.clickhouseHttpClient.insertPromise(this.options.database, this.options.tableName, docs);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRjbGlja2hvdXNlLmNsYXNzZXMuY2xpY2tob3VzZXRhYmxlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vdHMvc3FsZGIvY2xpY2tob3VzZS9zbWFydGNsaWNraG91c2UuY2xhc3Nlcy5jbGlja2hvdXNldGFibGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSw4QkFBOEIsQ0FBQztBQUV4RCxPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSwyQ0FBMkMsQ0FBQztBQU9uRixPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUNsRSxPQUFPLEVBQUUseUJBQXlCLElBQUksZUFBZSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDaEYsT0FBTyxFQUFFLFlBQVksRUFBNkIsTUFBTSwyQkFBMkIsQ0FBQztBQUNwRixPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDNUQsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFHbEUsTUFBTSxPQUFPLGVBQWU7SUFDMUIsMkJBQTJCO0lBRXBCLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUN4QixFQUFxQixFQUNyQixPQUFtQztRQUVuQyxNQUFNLEtBQUssR0FBRyxJQUFJLGVBQWUsQ0FBSSxFQUFFLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDbEQsTUFBTSxLQUFLLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDcEIsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0lBRUQscUJBQXFCO0lBRWQsRUFBRSxDQUFvQjtJQUN0QixPQUFPLENBQTJFO0lBQ2xGLE9BQU8sR0FBa0IsRUFBRSxDQUFDO0lBR25DLFlBQVksRUFBcUIsRUFBRSxPQUFtQztRQUNwRSxJQUFJLENBQUMsRUFBRSxHQUFHLEVBQUUsQ0FBQztRQUNiLElBQUksQ0FBQyxPQUFPLEdBQUc7WUFDYixtQkFBbUIsRUFBRSxJ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
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { ClickHouseConnection } from '../classes.clickhouseconnection.js';
|
|
2
|
+
import type { IOperationOptions } from '../../core/interfaces.js';
|
|
3
|
+
import type { IQueryOptions } from '../interfaces.js';
|
|
4
|
+
export interface IClickhouseHttpClientOptions {
|
|
5
|
+
username?: string;
|
|
6
|
+
password?: string;
|
|
7
|
+
url: string;
|
|
8
|
+
timeoutMs?: number;
|
|
9
|
+
}
|
|
10
|
+
/** Migrated public transport API, using the official streaming ClickHouse connector. */
|
|
11
|
+
export declare class ClickhouseHttpClient {
|
|
12
|
+
options: IClickhouseHttpClientOptions;
|
|
13
|
+
readonly connection: ClickHouseConnection;
|
|
14
|
+
private readonly ownsConnection;
|
|
15
|
+
constructor(options: IClickhouseHttpClientOptions, connection?: ClickHouseConnection);
|
|
16
|
+
static createAndStart(options: IClickhouseHttpClientOptions): Promise<ClickhouseHttpClient>;
|
|
17
|
+
start(): Promise<void>;
|
|
18
|
+
close(): Promise<void>;
|
|
19
|
+
ping(options?: IOperationOptions): Promise<boolean>;
|
|
20
|
+
queryPromise(query: string, values?: Record<string, unknown>, options?: IQueryOptions): Promise<any[]>;
|
|
21
|
+
queryTyped<T>(query: string, values?: Record<string, unknown>, options?: IQueryOptions): Promise<T[]>;
|
|
22
|
+
insertPromise(database: string, table: string, documents: Record<string, unknown>[]): Promise<{
|
|
23
|
+
queryId: string;
|
|
24
|
+
completion: "acknowledged";
|
|
25
|
+
}>;
|
|
26
|
+
insertBatch(database: string, table: string, documents: Record<string, unknown>[], batchSize?: number): Promise<void>;
|
|
27
|
+
mutatePromise(query: string, values?: Record<string, unknown>, options?: IOperationOptions): Promise<void>;
|
|
28
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { ClickHouseConnection } from '../classes.clickhouseconnection.js';
|
|
2
|
+
/** Migrated public transport API, using the official streaming ClickHouse connector. */
|
|
3
|
+
export class ClickhouseHttpClient {
|
|
4
|
+
options;
|
|
5
|
+
connection;
|
|
6
|
+
ownsConnection;
|
|
7
|
+
constructor(options, connection) {
|
|
8
|
+
this.options = options;
|
|
9
|
+
this.ownsConnection = !connection;
|
|
10
|
+
this.connection = connection ?? new ClickHouseConnection({ ...options, backend: 'clickhouse', database: 'default' });
|
|
11
|
+
}
|
|
12
|
+
static async createAndStart(options) {
|
|
13
|
+
const instance = new ClickhouseHttpClient(options);
|
|
14
|
+
await instance.start();
|
|
15
|
+
return instance;
|
|
16
|
+
}
|
|
17
|
+
async start() { await this.connection.connect(); }
|
|
18
|
+
async close() { if (this.ownsConnection)
|
|
19
|
+
await this.connection.close(); }
|
|
20
|
+
async ping(options = {}) { return (await this.connection.ready(options)).ready; }
|
|
21
|
+
async queryPromise(query, values, options = {}) {
|
|
22
|
+
const sql = query.trim().replace(/\s+FORMAT\s+JSONEachRow\s*;?$/i, '');
|
|
23
|
+
if (/^(SELECT|WITH|SHOW|DESCRIBE|DESC|EXISTS|EXPLAIN)\b/i.test(sql)) {
|
|
24
|
+
return this.connection.query({ sql, values }, options);
|
|
25
|
+
}
|
|
26
|
+
await this.connection.execute({ sql, values }, options);
|
|
27
|
+
return [];
|
|
28
|
+
}
|
|
29
|
+
async queryTyped(query, values, options = {}) {
|
|
30
|
+
return this.queryPromise(query, values, options);
|
|
31
|
+
}
|
|
32
|
+
async insertPromise(database, table, documents) {
|
|
33
|
+
return this.connection.insertQualified(database, table, documents);
|
|
34
|
+
}
|
|
35
|
+
async insertBatch(database, table, documents, batchSize = 10_000) {
|
|
36
|
+
if (!Number.isSafeInteger(batchSize) || batchSize < 1)
|
|
37
|
+
throw new RangeError('batchSize must be positive.');
|
|
38
|
+
for (let i = 0; i < documents.length; i += batchSize) {
|
|
39
|
+
await this.insertPromise(database, table, documents.slice(i, i + batchSize));
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
async mutatePromise(query, values, options = {}) {
|
|
43
|
+
await this.connection.execute({ sql: query, values }, options);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRjbGlja2hvdXNlLmNsYXNzZXMuaHR0cGNsaWVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3RzL3NxbGRiL2NsaWNraG91c2Uvc21hcnRjbGlja2hvdXNlLmNsYXNzZXMuaHR0cGNsaWVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxvQ0FBb0MsQ0FBQztBQVcxRSx3RkFBd0Y7QUFDeEYsTUFBTSxPQUFPLG9CQUFvQjtJQUdaO0lBRkgsVUFBVSxDQUF1QjtJQUNoQyxjQUFjLENBQVU7SUFDekMsWUFBbUIsT0FBcUMsRUFBRSxVQUFpQztRQUF4RSxZQUFPLEdBQVAsT0FBTyxDQUE4QjtRQUN0RCxJQUFJLENBQUMsY0FBYyxHQUFHLENBQUMsVUFBVSxDQUFDO1FBQ2xDLElBQUksQ0FBQyxVQUFVLEdBQUcsVUFBVSxJQUFJLElBQUksb0JBQW9CLENBQUMsRUFBRSxHQUFHLE9BQU8sRUFBRSxPQUFPLEVBQUUsWUFBWSxFQUFFLFFBQVEsRUFBRSxTQUFTLEVBQUUsQ0FBQyxDQUFDO0lBQ3ZILENBQUM7SUFDTSxNQUFNLENBQUMsS0FBSyxDQUFDLGNBQWMsQ0FBQyxPQUFxQztRQUN0RSxNQUFNLFFBQVEsR0FBRyxJQUFJLG9CQUFvQixDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ25ELE1BQU0sUUFBUSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ3ZCLE9BQU8sUUFBUSxDQUFDO0lBQ2xCLENBQUM7SUFDTSxLQUFLLENBQUMsS0FBSyxLQUFvQixNQUFNLElBQUksQ0FBQyxVQUFVLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ2pFLEtBQUssQ0FBQyxLQUFLLEtBQW9CLElBQUksSUFBSSxDQUFDLGNBQWM7UUFBRSxNQUFNLElBQUksQ0FBQyxVQUFVLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ3hGLEtBQUssQ0FBQyxJQUFJLENBQUMsVUFBNkIsRUFBRSxJQUFzQixPQUFPLENBQUMsTUFBTSxJQUFJLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7SUFFdEgsS0FBSyxDQUFDLFlBQVksQ0FBQyxLQUFhLEVBQUUsTUFBZ0MsRUFBRSxVQUF5QixFQUFFO1FBQ3BHLE1BQU0sR0FBRyxHQUFHLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQyxPQUFPLENBQUMsZ0NBQWdDLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDdkUsSUFBSSxxREFBcUQsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUNwRSxPQUFPLElBQUksQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQ3pELENBQUM7UUFDRCxNQUFNLElBQUksQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQ3hELE9BQU8sRUFBRSxDQUFDO0lBQ1osQ0FBQztJQUNNLEtBQUssQ0FBQyxVQUFVLENBQUksS0FBYSxFQUFFLE1BQWdDLEVBQUUsVUFBeUIsRUFBRTtRQUNyRyxPQUFPLElBQUksQ0FBQyxZQUFZLENBQUMsS0FBSyxFQUFFLE1BQU0sRUFBRSxPQUFPLENBQWlCLENBQUM7SUFDbkUsQ0FBQztJQUNNLEtBQUssQ0FBQyxhQUFhLENBQUMsUUFBZ0IsRUFBRSxLQUFhLEVBQUUsU0FBb0M7UUFDOUYsT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFDLGVBQWUsQ0FBQyxRQUFRLEVBQUUsS0FBSyxFQUFFLFNBQVMsQ0FBQyxDQUFDO0lBQ3JFLENBQUM7SUFDTSxLQUFLLENBQUMsV0FBVyxDQUFDLFFBQWdCLEVBQUUsS0FBYSxFQUFFLFNBQW9DLEVBQUUsU0FBUyxHQUFHLE1BQU07UUFDaEgsSUFBSSxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsU0FBUyxDQUFDLElBQUksU0FBUyxHQUFHLENBQUM7WUFBRSxNQUFNLElBQUksVUFBVSxDQUFDLDZCQUE2QixDQUFDLENBQUM7UUFDM0csS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLFNBQVMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxJQUFJLFNBQVMsRUFBRSxDQUFDO1lBQ3JELE1BQU0sSUFBSSxDQUFDLGFBQWEsQ0FBQyxRQUFRLEVBQUUsS0FBSyxFQUFFLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLENBQUMsR0FBRyxTQUFTLENBQUMsQ0FBQyxDQUFDO1FBQy9FLENBQUM7SUFDSCxDQUFDO0lBQ00sS0FBSyxDQUFDLGFBQWEsQ0FBQyxLQUFhLEVBQUUsTUFBZ0MsRUFBRSxVQUE2QixFQUFFO1FBQ3pHLE1BQU0sSUFBSSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsRUFBRSxHQUFHLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBQ2pFLENBQUM7Q0FDRiJ9
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { ClickhouseHttpClient } from './smartclickhouse.classes.httpclient.js';
|
|
2
|
+
import { ClickhouseResultSet } from './smartclickhouse.classes.resultset.js';
|
|
3
|
+
import type { TComparisonOperator } from './smartclickhouse.types.js';
|
|
4
|
+
import type { IClickHouseStatement, IQueryOptions } from '../interfaces.js';
|
|
5
|
+
/** Identifier methods quote names. Methods ending in Raw and having() accept trusted SQL expressions. */
|
|
6
|
+
export declare class ClickhouseQueryBuilder<T extends Record<string, any>> {
|
|
7
|
+
private tableName;
|
|
8
|
+
private database;
|
|
9
|
+
private httpClient;
|
|
10
|
+
private selectColumns;
|
|
11
|
+
private whereClauses;
|
|
12
|
+
private orderByClauses;
|
|
13
|
+
private groupByClauses;
|
|
14
|
+
private havingClauses;
|
|
15
|
+
private limitValue;
|
|
16
|
+
private offsetValue;
|
|
17
|
+
private readonly values;
|
|
18
|
+
constructor(tableName: string, database: string, httpClient: ClickhouseHttpClient);
|
|
19
|
+
select<K extends keyof T & string>(...columns: K[]): this;
|
|
20
|
+
selectRaw(...expressions: string[]): this;
|
|
21
|
+
where<K extends keyof T & string>(column: K, operator: TComparisonOperator, value: unknown): this;
|
|
22
|
+
and<K extends keyof T & string>(column: K, operator: TComparisonOperator, value: unknown): this;
|
|
23
|
+
or<K extends keyof T & string>(column: K, operator: TComparisonOperator, value: unknown): this;
|
|
24
|
+
whereRaw(expression: string): this;
|
|
25
|
+
orderBy(column: (keyof T & string) | string, direction?: 'ASC' | 'DESC'): this;
|
|
26
|
+
groupBy<K extends keyof T & string>(...columns: K[]): this;
|
|
27
|
+
having(expression: string): this;
|
|
28
|
+
limit(count: number): this;
|
|
29
|
+
offset(count: number): this;
|
|
30
|
+
private validateCount;
|
|
31
|
+
execute(options?: IQueryOptions): Promise<ClickhouseResultSet<T>>;
|
|
32
|
+
first(): Promise<T | null>;
|
|
33
|
+
count(): Promise<number>;
|
|
34
|
+
toArray(options?: IQueryOptions): Promise<T[]>;
|
|
35
|
+
/** SQL contains typed placeholders. Pass parameters alongside it, or use toStatement(). */
|
|
36
|
+
toSQL(): string;
|
|
37
|
+
get parameters(): Record<string, unknown>;
|
|
38
|
+
toStatement(): IClickHouseStatement;
|
|
39
|
+
buildWhereClause(): string;
|
|
40
|
+
/** Bind a scalar for table mutations as well as predicates. */
|
|
41
|
+
bind(value: unknown): string;
|
|
42
|
+
private buildCondition;
|
|
43
|
+
}
|