feat(core): introduce typed ClickHouse table API, query builder, and result handling; enhance HTTP client and add schema evolution, batch inserts and mutations; update docs/tests and bump deps
This commit is contained in:
134
ts/smartclickhouse.types.ts
Normal file
134
ts/smartclickhouse.types.ts
Normal file
@@ -0,0 +1,134 @@
|
||||
// ============================================================
|
||||
// Column Data Types
|
||||
// ============================================================
|
||||
export type TClickhouseColumnType =
|
||||
| 'String'
|
||||
| 'UInt8' | 'UInt16' | 'UInt32' | 'UInt64'
|
||||
| 'Int8' | 'Int16' | 'Int32' | 'Int64'
|
||||
| 'Float32' | 'Float64'
|
||||
| 'Bool'
|
||||
| 'Date' | 'Date32'
|
||||
| 'DateTime' | 'DateTime64'
|
||||
| 'UUID'
|
||||
| 'IPv4' | 'IPv6'
|
||||
| (string & {}); // allow arbitrary ClickHouse types like "DateTime64(3, 'Europe/Berlin')"
|
||||
|
||||
// ============================================================
|
||||
// Engine Configuration
|
||||
// ============================================================
|
||||
export type TClickhouseEngine =
|
||||
| 'MergeTree'
|
||||
| 'ReplacingMergeTree'
|
||||
| 'SummingMergeTree'
|
||||
| 'AggregatingMergeTree'
|
||||
| 'CollapsingMergeTree'
|
||||
| 'VersionedCollapsingMergeTree';
|
||||
|
||||
export interface IEngineConfig {
|
||||
engine: TClickhouseEngine;
|
||||
/** For ReplacingMergeTree: the version column name */
|
||||
versionColumn?: string;
|
||||
/** For CollapsingMergeTree: the sign column name */
|
||||
signColumn?: string;
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// Column Definition
|
||||
// ============================================================
|
||||
export interface IColumnDefinition {
|
||||
name: string;
|
||||
type: TClickhouseColumnType;
|
||||
defaultExpression?: string;
|
||||
codec?: string;
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// Table Options
|
||||
// ============================================================
|
||||
export interface IClickhouseTableOptions<T = any> {
|
||||
tableName: string;
|
||||
database?: string;
|
||||
engine?: IEngineConfig;
|
||||
orderBy: (keyof T & string) | (keyof T & string)[];
|
||||
partitionBy?: string;
|
||||
primaryKey?: (keyof T & string) | (keyof T & string)[];
|
||||
ttl?: {
|
||||
column: keyof T & string;
|
||||
interval: string; // e.g., '30 DAY', '1 MONTH'
|
||||
};
|
||||
columns?: IColumnDefinition[];
|
||||
/** Enable auto-schema evolution (add columns from data). Default: true */
|
||||
autoSchemaEvolution?: boolean;
|
||||
/** Data retention in days (shorthand for ttl). If ttl is set, this is ignored. */
|
||||
retainDataForDays?: number;
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// Column Info from system.columns
|
||||
// ============================================================
|
||||
export interface IColumnInfo {
|
||||
database: string;
|
||||
table: string;
|
||||
name: string;
|
||||
type: string;
|
||||
position: string;
|
||||
default_kind: string;
|
||||
default_expression: string;
|
||||
data_compressed_bytes: string;
|
||||
data_uncompressed_bytes: string;
|
||||
marks_bytes: string;
|
||||
comment: string;
|
||||
is_in_partition_key: 0 | 1;
|
||||
is_in_sorting_key: 0 | 1;
|
||||
is_in_primary_key: 0 | 1;
|
||||
is_in_sampling_key: 0 | 1;
|
||||
compression_codec: string;
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// Comparison Operators for Query Builder
|
||||
// ============================================================
|
||||
export type TComparisonOperator =
|
||||
| '='
|
||||
| '!='
|
||||
| '>'
|
||||
| '>='
|
||||
| '<'
|
||||
| '<='
|
||||
| 'LIKE'
|
||||
| 'NOT LIKE'
|
||||
| 'IN'
|
||||
| 'NOT IN'
|
||||
| 'BETWEEN';
|
||||
|
||||
// ============================================================
|
||||
// Value Escaping (SQL Injection Prevention)
|
||||
// ============================================================
|
||||
export function escapeClickhouseValue(value: any): string {
|
||||
if (value === null || value === undefined) return 'NULL';
|
||||
if (typeof value === 'number') return String(value);
|
||||
if (typeof value === 'boolean') return value ? '1' : '0';
|
||||
if (value instanceof Date) return `'${value.toISOString().replace('T', ' ').replace('Z', '')}'`;
|
||||
if (Array.isArray(value)) {
|
||||
return `(${value.map(escapeClickhouseValue).join(', ')})`;
|
||||
}
|
||||
// String: escape single quotes and backslashes
|
||||
return `'${String(value).replace(/\\/g, '\\\\').replace(/'/g, "\\'")}'`;
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// ClickHouse Type Detection from JS Values
|
||||
// ============================================================
|
||||
export function detectClickhouseType(value: any): TClickhouseColumnType | null {
|
||||
if (value === null || value === undefined) return null;
|
||||
if (typeof value === 'string') return 'String';
|
||||
if (typeof value === 'number') return 'Float64';
|
||||
if (typeof value === 'boolean') return 'UInt8';
|
||||
if (value instanceof Array) {
|
||||
if (value.length === 0) return null;
|
||||
const elementType = detectClickhouseType(value[0]);
|
||||
if (!elementType) return null;
|
||||
return `Array(${elementType})` as TClickhouseColumnType;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
Reference in New Issue
Block a user