Part of #630.
Depends on: #634
Goal
Move the reusable pure ClickHouse language helpers already maintained by SQL Browser into @altinity/clickhouse-http:
- SQL string-literal and identifier quoting;
- generic ClickHouse type-expression AST parsing, wrapper analysis, canonicalization, and enum inspection.
This is a pure-code ownership move. Do not move SQL Browser formatting, parameter-control UX, result-view policy, or product-specific SQL helpers.
SQL quoting API
Move the behavior currently implemented by src/core/format.ts's ClickHouse-specific quoting helpers into the package and expose public equivalents:
export function quoteStringLiteral(value: unknown): string;
export function quoteIdentifier(name: unknown): string;
export function qualifyIdentifier(...parts: unknown[]): string;
Required behavior is the current SQL Browser behavior:
String literals
- convert input with
String(...);
- escape
\ first using ClickHouse backslash escaping;
- escape
' so the result cannot break out of the string literal;
- wrap in single quotes;
- preserve Unicode and empty strings.
Identifiers
- bare identifier regex remains
[A-Za-z_][A-Za-z0-9_]*;
- bare names remain unquoted for readability;
- every other name is backtick-quoted;
\ and backticks are escaped using the current ClickHouse identifier rules;
- dots inside one identifier part are data and must not be treated as qualification separators.
Qualification
- take already-separated identifier parts;
- drop nullish/empty parts exactly as today;
- quote each retained part independently;
- join with
..
Reconcile #634's private query-id quoting so killQuery() uses the new public string-literal helper. There must be one quoting implementation after this PR.
SQL Browser may keep temporary named re-exports (sqlString, quoteIdent, qualifyIdent) from src/core/format.ts for compatibility, but those names must delegate to package functions rather than retain code.
Do not move unrelated src/core/format.ts behavior such as row/byte display formatting, detectSqlFormat, prepareExportSql, withTrailingFormat, schema-mutating classification, query naming, or editor-specific helpers.
ClickHouse type-expression package API
Move the generic AST/parser implementation currently in src/core/clickhouse-type.ts into the package.
The package must own the canonical types representing:
- type nodes;
- literal string/number arguments;
- Tuple members;
- Enum members;
- wrapper/modifier analysis.
Expose the current generic capabilities, at minimum:
parseClickHouseType(input): TypeNode | null
analyzeTypeModifiers(node): TypeModifiers
canonicalType(input): string
enumMembers(node): EnumMember[] | null
unwrapNullable(node)
unwrapLowCardinality(node)
unwrapValueTransparentWrappers(node)
If the current module exports additional generic predicates used by multiple consumers, move them only when their semantics describe ClickHouse types rather than a SQL Browser UI/product decision. Keep the package public surface minimal and document every moved export.
Grammar/behavior to preserve
The move must preserve the existing parser's tested semantics, including:
- nested type expressions;
- whitespace handling;
- argument lists;
- numeric literal arguments;
- quoted string literal arguments;
- backtick/double-quote/single-quote token handling where currently supported;
- ClickHouse backslash and doubled-delimiter decoding;
$tag$...$tag$ heredoc handling already supported by the parser;
Array;
Nullable;
LowCardinality;
Tuple, including named and positional members and the current mixed-member rejection;
Enum8 / Enum16, explicit and implicit codes;
- nested wrapper analysis and wrapper-order validity;
- the current
LowCardinality(Enum*) invalidity rule;
- malformed/unbalanced input returning
null or the current fail-closed result rather than throwing;
- canonicalization preserving quoted-content meaning while normalizing syntax as currently tested.
Do not broaden the grammar speculatively in this issue. The extraction contract is current behavior plus current tests.
SQL Browser integration
Repoint existing consumers to package exports while preserving their own policy layers:
src/core/param-type.ts continues to own parameter compatibility/policy projection, but consumes the package AST/parser;
- KPI, dashboard-variable, and other current type consumers use the same package parser rather than a compatibility copy;
src/core/clickhouse-type.ts may be a short compatibility re-export during the PR if needed to keep migration atomic, but the final state of this unit must have no independent parser implementation under SQL Browser source;
- SQL Browser-specific functions such as
multiSelectElementType, field/control decisions, recent-value behavior, or feature-specific supported-type policy stay in SQL Browser unless they are already demonstrably generic ClickHouse type semantics.
The package must not import sql-spans.ts, quoted-span.ts, or other SQL Browser files. If the type parser depends on generic lexical helpers currently under src/core, move the smallest reusable lexical primitives it needs into the package in this PR and repoint SQL Browser consumers to that single implementation. Do not duplicate the scanner to satisfy the boundary.
Tests
SQL quoting
Port/retain tests for:
- empty string;
';
\;
- trailing backslash;
- backslash + quote combinations;
- Unicode;
- bare identifiers;
- identifiers with spaces, dots, dashes, backticks, and backslashes;
- qualification with empty/nullish parts;
killQuery() using the same quoting implementation.
Type parser
The complete existing clickhouse-type test corpus must remain green after migration and should execute against package exports directly.
Add package-boundary tests proving no SQL Browser source import is required.
Run affected param-type, KPI, variable-option, serializer, and any other type-consumer tests to catch a projection drift.
Run the full repository gate:
npm run check:types
npm run check:arch
npm run check:schemas
npm run check:examples
npm test
npm run build
No browser e2e is required solely for this pure move unless the implementation changes package/workspace runtime wiring in a way not already covered by #632.
Acceptance criteria
Non-goals
- Moving
detectSqlFormat, stripTrailingTrivia, withTrailingFormat, prepareExportSql, query-name inference, display formatting, or schema-mutating classification.
- Moving parameter field/control policy or Dashboard variable UX.
- Adding a SQL parser, formatter, query builder, or AST for full SQL statements.
- Expanding type grammar beyond behavior already required/tested by SQL Browser.
- Changing persisted parameter/type representations.
- Rewriting authentication/application services.
Agent execution notes
Before planning, read #630–#634, src/core/format.ts, src/core/clickhouse-type.ts, src/core/param-type.ts, the parser/format tests, and every import of the helpers being moved. This is a subtractive unit: move implementation and tests to the package, repoint all real consumers, then delete the former implementation. Do not leave two scanners/parsers/quoters behind a compatibility facade.
Part of #630.
Depends on: #634
Goal
Move the reusable pure ClickHouse language helpers already maintained by SQL Browser into
@altinity/clickhouse-http:This is a pure-code ownership move. Do not move SQL Browser formatting, parameter-control UX, result-view policy, or product-specific SQL helpers.
SQL quoting API
Move the behavior currently implemented by
src/core/format.ts's ClickHouse-specific quoting helpers into the package and expose public equivalents:Required behavior is the current SQL Browser behavior:
String literals
String(...);\first using ClickHouse backslash escaping;'so the result cannot break out of the string literal;Identifiers
[A-Za-z_][A-Za-z0-9_]*;\and backticks are escaped using the current ClickHouse identifier rules;Qualification
..Reconcile #634's private query-id quoting so
killQuery()uses the new public string-literal helper. There must be one quoting implementation after this PR.SQL Browser may keep temporary named re-exports (
sqlString,quoteIdent,qualifyIdent) fromsrc/core/format.tsfor compatibility, but those names must delegate to package functions rather than retain code.Do not move unrelated
src/core/format.tsbehavior such as row/byte display formatting,detectSqlFormat,prepareExportSql,withTrailingFormat, schema-mutating classification, query naming, or editor-specific helpers.ClickHouse type-expression package API
Move the generic AST/parser implementation currently in
src/core/clickhouse-type.tsinto the package.The package must own the canonical types representing:
Expose the current generic capabilities, at minimum:
If the current module exports additional generic predicates used by multiple consumers, move them only when their semantics describe ClickHouse types rather than a SQL Browser UI/product decision. Keep the package public surface minimal and document every moved export.
Grammar/behavior to preserve
The move must preserve the existing parser's tested semantics, including:
$tag$...$tag$heredoc handling already supported by the parser;Array;Nullable;LowCardinality;Tuple, including named and positional members and the current mixed-member rejection;Enum8/Enum16, explicit and implicit codes;LowCardinality(Enum*)invalidity rule;nullor the current fail-closed result rather than throwing;Do not broaden the grammar speculatively in this issue. The extraction contract is current behavior plus current tests.
SQL Browser integration
Repoint existing consumers to package exports while preserving their own policy layers:
src/core/param-type.tscontinues to own parameter compatibility/policy projection, but consumes the package AST/parser;src/core/clickhouse-type.tsmay be a short compatibility re-export during the PR if needed to keep migration atomic, but the final state of this unit must have no independent parser implementation under SQL Browser source;multiSelectElementType, field/control decisions, recent-value behavior, or feature-specific supported-type policy stay in SQL Browser unless they are already demonstrably generic ClickHouse type semantics.The package must not import
sql-spans.ts,quoted-span.ts, or other SQL Browser files. If the type parser depends on generic lexical helpers currently undersrc/core, move the smallest reusable lexical primitives it needs into the package in this PR and repoint SQL Browser consumers to that single implementation. Do not duplicate the scanner to satisfy the boundary.Tests
SQL quoting
Port/retain tests for:
';\;killQuery()using the same quoting implementation.Type parser
The complete existing
clickhouse-typetest corpus must remain green after migration and should execute against package exports directly.Add package-boundary tests proving no SQL Browser source import is required.
Run affected
param-type, KPI, variable-option, serializer, and any other type-consumer tests to catch a projection drift.Run the full repository gate:
npm run check:types npm run check:arch npm run check:schemas npm run check:examples npm test npm run buildNo browser e2e is required solely for this pure move unless the implementation changes package/workspace runtime wiring in a way not already covered by #632.
Acceptance criteria
@altinity/clickhouse-http.killQuery()uses the shared public quoting helper.param-typeand UI/product policy remain SQL Browser-owned but use package type primitives.src/core/format.tsretains only SQL Browser formatting/policy plus compatibility delegates where temporarily necessary.src/core/clickhouse-type.tscontains no independent parser implementation at completion of this unit.Non-goals
detectSqlFormat,stripTrailingTrivia,withTrailingFormat,prepareExportSql, query-name inference, display formatting, or schema-mutating classification.Agent execution notes
Before planning, read #630–#634,
src/core/format.ts,src/core/clickhouse-type.ts,src/core/param-type.ts, the parser/format tests, and every import of the helpers being moved. This is a subtractive unit: move implementation and tests to the package, repoint all real consumers, then delete the former implementation. Do not leave two scanners/parsers/quoters behind a compatibility facade.