From a4a39d40066d60889bb74d34fb9518bf1185f385 Mon Sep 17 00:00:00 2001 From: Peter Leonov Date: Tue, 23 Jun 2026 14:00:33 +0200 Subject: [PATCH 1/9] mini-parser from https://github.com/peter-leonov-ch/ClickHouse/pull/1/changes/ad4410a151e95917debadf6110e99179051af4fa --- type-parser/mini-parser-extracted/.gitignore | 1 + .../mini-parser-extracted/CMakeLists.txt | 27 + type-parser/mini-parser-extracted/README.md | 107 ++++ .../mini-parser-extracted/include/chdt/ast.h | 87 +++ .../include/chdt/parser.h | 44 ++ .../mini-parser-extracted/src/json.cpp | 243 +++++++++ .../mini-parser-extracted/src/lexer.cpp | 200 +++++++ type-parser/mini-parser-extracted/src/lexer.h | 50 ++ .../mini-parser-extracted/src/parser.cpp | 509 ++++++++++++++++++ .../mini-parser-extracted/test/CMakeLists.txt | 24 + .../mini-parser-extracted/test/cases.txt | 72 +++ .../test/cases_unsupported.txt | 7 + .../test/check_unsupported.py | 40 ++ .../test/oracle_compare.py | 110 ++++ .../mini-parser-extracted/tool/main.cpp | 46 ++ 15 files changed, 1567 insertions(+) create mode 100644 type-parser/mini-parser-extracted/.gitignore create mode 100644 type-parser/mini-parser-extracted/CMakeLists.txt create mode 100644 type-parser/mini-parser-extracted/README.md create mode 100644 type-parser/mini-parser-extracted/include/chdt/ast.h create mode 100644 type-parser/mini-parser-extracted/include/chdt/parser.h create mode 100644 type-parser/mini-parser-extracted/src/json.cpp create mode 100644 type-parser/mini-parser-extracted/src/lexer.cpp create mode 100644 type-parser/mini-parser-extracted/src/lexer.h create mode 100644 type-parser/mini-parser-extracted/src/parser.cpp create mode 100644 type-parser/mini-parser-extracted/test/CMakeLists.txt create mode 100644 type-parser/mini-parser-extracted/test/cases.txt create mode 100644 type-parser/mini-parser-extracted/test/cases_unsupported.txt create mode 100644 type-parser/mini-parser-extracted/test/check_unsupported.py create mode 100644 type-parser/mini-parser-extracted/test/oracle_compare.py create mode 100644 type-parser/mini-parser-extracted/tool/main.cpp diff --git a/type-parser/mini-parser-extracted/.gitignore b/type-parser/mini-parser-extracted/.gitignore new file mode 100644 index 000000000..567609b12 --- /dev/null +++ b/type-parser/mini-parser-extracted/.gitignore @@ -0,0 +1 @@ +build/ diff --git a/type-parser/mini-parser-extracted/CMakeLists.txt b/type-parser/mini-parser-extracted/CMakeLists.txt new file mode 100644 index 000000000..5ff06511c --- /dev/null +++ b/type-parser/mini-parser-extracted/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.16) +project(chdt_datatype_parser CXX) + +# A self-contained library: no dependency on the ClickHouse source tree. +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Release) +endif() + +add_compile_options(-Wall -Wextra) + +add_library(chdt_datatype_parser + src/lexer.cpp + src/parser.cpp + src/json.cpp +) +target_include_directories(chdt_datatype_parser PUBLIC include) + +# CLI: read a data-type string, print its JSON AST. Exit non-zero on error. +add_executable(chdt-parse tool/main.cpp) +target_link_libraries(chdt-parse PRIVATE chdt_datatype_parser) + +enable_testing() +add_subdirectory(test) diff --git a/type-parser/mini-parser-extracted/README.md b/type-parser/mini-parser-extracted/README.md new file mode 100644 index 000000000..9e480404e --- /dev/null +++ b/type-parser/mini-parser-extracted/README.md @@ -0,0 +1,107 @@ +# chdt — standalone ClickHouse data-type parser + +A small, self-contained C++ library that parses a ClickHouse **data-type +string** (the kind sent in the types row of `RowBinaryWithNamesAndTypes`, e.g. +`Array(Nullable(UInt64))`, `Tuple(a UInt8, b String)`, `Enum8('a' = 1)`, +`Decimal(10, 2)`) into a JSON AST. + +It is extracted from the server's `ParserDataType` +(`src/Parsers/ParserDataType.cpp`) but has **no dependency on the ClickHouse +source tree** — only the C++20 standard library. The JSON it emits mirrors the +data-type subtree of the frozen `EXPLAIN AST json = 1` document (format +**version 2**; see `AST.md` in the ClickHouse repo), so its output is a drop-in +match for what the server produces. + +## Why this exists + +The server's type parser is entangled with the lexer, the expression parsers, +and the `IAST` / `Field` machinery. Vendoring all of that verbatim would pull +in ~9–10k lines (`Field`, `ReadHelpers`, `Exception`, the formatting/hashing +layer). Instead, this reimplements just the type grammar on a minimal AST: + +- a purpose-built tokenizer (`src/lexer.*`) covering the slice of SQL that type + strings use, in place of the full `Lexer` and its `UTF8Helpers` / + `find_symbols` dependencies; +- a faithful port of `ParserDataType::parseImpl` (`src/parser.cpp`) — same + control flow: identifier + SQL-standard multi-word aliases, the Enum and + Tuple special cases, then the generic parametric-argument loop; +- plain structs for the AST (`include/chdt/ast.h`) instead of `IAST` + `Field`. + +## Building + +```bash +cmake -S . -B build -DCMAKE_BUILD_TYPE=Release +cmake --build build +``` + +This produces `libchdt_datatype_parser.a` and the `chdt-parse` CLI. + +## Usage + +Library: + +```cpp +#include "chdt/parser.h" + +chdt::ParseResult r = chdt::parseDataType("Tuple(a UInt8, b String)"); +if (r.ok()) + std::string json = chdt::toJSON(*r.ast); +else + /* r.error->message, r.error->position */; +``` + +CLI: + +```bash +./build/chdt-parse "Array(Nullable(UInt64))" +echo "Enum8('a' = 1, 'b' = 2)" | ./build/chdt-parse +``` + +## Output shape + +Node types and slots match the server (format v2): + +| `type` | slots | +|------------------|----------------------------------------------------------| +| `DataType` | `name`, `arguments?` (present iff the type had `(...)`) | +| `EnumDataType` | `name`, `values` (array of `{ name, value }`) | +| `TupleDataType` | `name`, `arguments?`, `element_names?` (named tuples) | +| `NameTypePair` | `name`, `data_type` (a `Nested(...)` element) | +| `Literal` | `value_type`, `value` (64-bit ints as JSON strings) | +| `Function` | `name`, `is_operator?`, `arguments` (e.g. `max_types=5`) | +| `Identifier` | `name`, `name_parts?` | + +`EnumDataType.values` and `TupleDataType.element_names` are carried here exactly +as the server emits them since format v2. + +## Coverage + +Supported: scalars, parametric types with literal args (`Decimal`, +`FixedString`, `DateTime64`, …), nested type args (`Array`, `Map`, `Nullable`, +`LowCardinality`, `Variant`, …), enums (explicit → `EnumDataType`; +auto-assigned → generic `DataType`), named/unnamed/mixed tuples, `Nested`, +`Dynamic(max_types = N)`, the legacy `Object('json')`, and the SQL-standard +multi-word aliases (`DOUBLE PRECISION`, `CHAR VARYING`, `INT SIGNED`, …). + +**Deliberately not supported yet** (the parser returns a clear error): + +- `AggregateFunction` / `SimpleAggregateFunction` — needs the function-expression + parser the server reaches for here. +- the new `JSON(...)` object-argument syntax (`JSON(a.b UInt32, SKIP x)`). Bare + `JSON` and legacy `Object('json')` parse fine. + +## Tests + +`ctest` runs two suites against the parser: + +- **oracle** (`test/oracle_compare.py`) — for each type in `test/cases.txt`, + compares the parser's JSON against the `data_type` subtree the real server + emits for `CREATE TABLE t (c ) ENGINE = Null`. Needs a `clickhouse` + binary (default: `../build/programs/clickhouse`; override with + `-DCLICKHOUSE_BINARY=...`). +- **unsupported** (`test/check_unsupported.py`) — asserts the deferred types in + `test/cases_unsupported.txt` are rejected. + +```bash +ctest --test-dir build --output-on-failure +``` diff --git a/type-parser/mini-parser-extracted/include/chdt/ast.h b/type-parser/mini-parser-extracted/include/chdt/ast.h new file mode 100644 index 000000000..948a1eccb --- /dev/null +++ b/type-parser/mini-parser-extracted/include/chdt/ast.h @@ -0,0 +1,87 @@ +#pragma once + +/// Minimal, self-contained AST for ClickHouse data-type strings. +/// +/// The node shapes mirror the frozen `EXPLAIN AST json = 1` document +/// (format version 2; see ClickHouse `AST.md`) so that JSON produced here is +/// a drop-in match for the data-type subtree the server emits — and a +/// superset of it: `EnumDataType.values` and `TupleDataType.element_names` +/// are carried here as they are in the server (since v2). +/// +/// This header has no dependency on the ClickHouse source tree. + +#include +#include +#include +#include + +namespace chdt +{ + +enum class NodeKind +{ + DataType, /// generic type: name + optional argument list + EnumDataType, /// Enum / Enum8 / Enum16 with fully explicit values + TupleDataType, /// Tuple, with optional element names + NameTypePair, /// `name Type` element of a Nested(...) + Literal, /// numeric / string argument (e.g. Decimal(10, 2)) + Function, /// operator/function argument (e.g. `max_types = 5`) + Identifier, /// bare identifier argument +}; + +struct Node; +using NodePtr = std::shared_ptr; + +struct EnumValue +{ + std::string name; + int64_t value = 0; +}; + +/// One node type for the whole tree. Only the fields relevant to `kind` are +/// populated; serialization emits exactly the slots the server would. +struct Node +{ + explicit Node(NodeKind kind_) : kind(kind_) {} + + NodeKind kind; + + /// DataType / EnumDataType / TupleDataType / Function / Identifier / NameTypePair + std::string name; + + /// DataType / TupleDataType / Function argument list (children inlined in JSON). + std::vector arguments; + /// DataType only: whether the type carried a parenthesised argument list at + /// all. `UInt8` omits the `arguments` slot; `Array(...)` emits it (possibly + /// empty). Tuple/Function always emit their list. + bool has_argument_list = false; + + /// EnumDataType: explicit `'name' = value` pairs. + std::vector values; + + /// TupleDataType: element names. Empty => unnamed tuple (slot omitted). + std::vector element_names; + + /// NameTypePair: the element's type. + NodePtr data_type; + + /// Literal: `value_type` is the Field type id ("UInt64", "Int64", + /// "Float64", "String"); `value` is the textual value. + std::string value_type; + std::string value; + + /// Function: set for operators such as `equals`. + bool is_operator = false; + + /// Identifier: populated when the identifier is compound (a.b). + std::vector name_parts; + + static NodePtr make(NodeKind kind_) { return std::make_shared(kind_); } +}; + +/// Serialize a node tree to JSON, matching the server's `formatASTAsJSON` +/// shape for data types. `indent` < 0 produces compact output; >= 0 produces +/// pretty output with that many spaces per level. +std::string toJSON(const Node & node, int indent = 2); + +} diff --git a/type-parser/mini-parser-extracted/include/chdt/parser.h b/type-parser/mini-parser-extracted/include/chdt/parser.h new file mode 100644 index 000000000..489a8c369 --- /dev/null +++ b/type-parser/mini-parser-extracted/include/chdt/parser.h @@ -0,0 +1,44 @@ +#pragma once + +/// Public entry point: parse a ClickHouse data-type string into the AST in +/// `ast.h`. Self-contained — no dependency on the ClickHouse source tree. +/// +/// Coverage mirrors the server's `ParserDataType` (`src/Parsers/ParserDataType.cpp`) +/// with two deliberate omissions, deferred for now: +/// * AggregateFunction / SimpleAggregateFunction — would pull in the full +/// function-expression parser; a clear error is returned instead. +/// * the new JSON/Object path-typed arguments (`JSON(a.b UInt32, SKIP x)`). +/// The bare `JSON` type and legacy `Object('json')` parse fine; the +/// object-argument syntax returns an error. +/// Everything else — nested types, parametric types, enums (explicit and +/// auto-assigned), named/unnamed tuples, Nested, Dynamic(max_types=N), and the +/// SQL-standard multi-word aliases — is supported. + +#include +#include + +#include "chdt/ast.h" + +namespace chdt + +{ + +struct ParseError +{ + std::string message; /// human-readable description + size_t position = 0; /// byte offset into the input where parsing stuck +}; + +struct ParseResult +{ + NodePtr ast; /// non-null on success + std::optional error; /// set on failure + + bool ok() const { return ast != nullptr; } +}; + +/// Parse the whole string as a single data type. Trailing tokens after a +/// complete type are an error (the entire input must be one type). +ParseResult parseDataType(const std::string & input); + +} diff --git a/type-parser/mini-parser-extracted/src/json.cpp b/type-parser/mini-parser-extracted/src/json.cpp new file mode 100644 index 000000000..40bf14c6c --- /dev/null +++ b/type-parser/mini-parser-extracted/src/json.cpp @@ -0,0 +1,243 @@ +#include "chdt/ast.h" + +#include + +namespace chdt +{ + +namespace +{ + +void escapeTo(std::string & out, const std::string & s) +{ + out.push_back('"'); + for (unsigned char c : s) + { + switch (c) + { + case '"': out += "\\\""; break; + case '\\': out += "\\\\"; break; + case '\b': out += "\\b"; break; + case '\f': out += "\\f"; break; + case '\n': out += "\\n"; break; + case '\r': out += "\\r"; break; + case '\t': out += "\\t"; break; + default: + if (c < 0x20) + { + char buf[8]; + std::snprintf(buf, sizeof(buf), "\\u%04x", c); + out += buf; + } + else + out.push_back(static_cast(c)); + } + } + out.push_back('"'); +} + +struct Writer +{ + std::string out; + int indent; /// spaces per level, or < 0 for compact + + void newlineIndent(int depth) + { + if (indent < 0) + return; + out.push_back('\n'); + out.append(static_cast(indent) * depth, ' '); + } + + void colon() { out += (indent < 0) ? ":" : ": "; } +}; + +/// Object emission is inline (each node writes its own members in order). +void writeNode(Writer & w, const Node & node, int depth); + +/// Emit `"key": ` prefix; returns whether a leading comma is needed next. +void writeKey(Writer & w, const char * key, bool & first, int depth) +{ + if (!first) + w.out.push_back(','); + first = false; + w.newlineIndent(depth + 1); + escapeTo(w.out, key); + w.colon(); +} + +void writeArray(Writer & w, const std::vector & items, int depth) +{ + if (items.empty()) + { + w.out += "[]"; + return; + } + w.out.push_back('['); + bool first = true; + for (const auto & item : items) + { + if (!first) + w.out.push_back(','); + first = false; + w.newlineIndent(depth + 1); + writeNode(w, *item, depth + 1); + } + w.newlineIndent(depth); + w.out.push_back(']'); +} + +void writeStringArray(Writer & w, const std::vector & items, int depth) +{ + if (items.empty()) + { + w.out += "[]"; + return; + } + w.out.push_back('['); + bool first = true; + for (const auto & item : items) + { + if (!first) + w.out.push_back(','); + first = false; + w.newlineIndent(depth + 1); + escapeTo(w.out, item); + } + w.newlineIndent(depth); + w.out.push_back(']'); +} + +void writeLiteralValue(Writer & w, const Node & node) +{ + /// 64-bit integers are emitted as JSON strings (the server's contract: + /// values above 2^53 lose precision under JS `JSON.parse`). Float64 is a + /// JSON number; String is a JSON string. + if (node.value_type == "Float64") + w.out += node.value; /// already a valid JSON number + else if (node.value_type == "String") + escapeTo(w.out, node.value); + else /// UInt64 / Int64 / fallback + escapeTo(w.out, node.value); +} + +void writeNode(Writer & w, const Node & node, int depth) +{ + w.out.push_back('{'); + bool first = true; + + auto key = [&](const char * k) { writeKey(w, k, first, depth); }; + + switch (node.kind) + { + case NodeKind::DataType: + key("type"); escapeTo(w.out, "DataType"); + key("name"); escapeTo(w.out, node.name); + if (node.has_argument_list) + { + key("arguments"); + writeArray(w, node.arguments, depth + 1); + } + break; + + case NodeKind::EnumDataType: + { + key("type"); escapeTo(w.out, "EnumDataType"); + key("name"); escapeTo(w.out, node.name); + key("values"); + if (node.values.empty()) + w.out += "[]"; + else + { + w.out.push_back('['); + bool vfirst = true; + for (const auto & v : node.values) + { + if (!vfirst) + w.out.push_back(','); + vfirst = false; + w.newlineIndent(depth + 2); + w.out.push_back('{'); + bool mfirst = true; + writeKey(w, "name", mfirst, depth + 2); + escapeTo(w.out, v.name); + writeKey(w, "value", mfirst, depth + 2); + w.out += std::to_string(v.value); + w.newlineIndent(depth + 2); + w.out.push_back('}'); + } + w.newlineIndent(depth + 1); + w.out.push_back(']'); + } + break; + } + + case NodeKind::TupleDataType: + key("type"); escapeTo(w.out, "TupleDataType"); + key("name"); escapeTo(w.out, node.name); + if (node.has_argument_list) + { + key("arguments"); + writeArray(w, node.arguments, depth + 1); + } + if (!node.element_names.empty()) + { + key("element_names"); + writeStringArray(w, node.element_names, depth + 1); + } + break; + + case NodeKind::NameTypePair: + key("type"); escapeTo(w.out, "NameTypePair"); + key("name"); escapeTo(w.out, node.name); + if (node.data_type) + { + key("data_type"); + writeNode(w, *node.data_type, depth + 1); + } + break; + + case NodeKind::Literal: + key("type"); escapeTo(w.out, "Literal"); + key("value_type"); escapeTo(w.out, node.value_type); + key("value"); writeLiteralValue(w, node); + break; + + case NodeKind::Function: + key("type"); escapeTo(w.out, "Function"); + key("name"); escapeTo(w.out, node.name); + if (node.is_operator) + { + key("is_operator"); + w.out += "true"; + } + key("arguments"); + writeArray(w, node.arguments, depth + 1); + break; + + case NodeKind::Identifier: + key("type"); escapeTo(w.out, "Identifier"); + key("name"); escapeTo(w.out, node.name); + if (!node.name_parts.empty()) + { + key("name_parts"); + writeStringArray(w, node.name_parts, depth + 1); + } + break; + } + + w.newlineIndent(depth); + w.out.push_back('}'); +} + +} /// namespace + +std::string toJSON(const Node & node, int indent) +{ + Writer w; + w.indent = indent; + writeNode(w, node, 0); + return w.out; +} + +} diff --git a/type-parser/mini-parser-extracted/src/lexer.cpp b/type-parser/mini-parser-extracted/src/lexer.cpp new file mode 100644 index 000000000..256abebbd --- /dev/null +++ b/type-parser/mini-parser-extracted/src/lexer.cpp @@ -0,0 +1,200 @@ +#include "lexer.h" + +namespace chdt +{ + +namespace +{ + +bool isSpace(char c) +{ + return c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f' || c == '\v'; +} + +bool isDigit(char c) +{ + return c >= '0' && c <= '9'; +} + +bool isWordFirst(char c) +{ + return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' || c == '$'; +} + +bool isWordChar(char c) +{ + return isWordFirst(c) || isDigit(c); +} + +/// Decode the body of a quoted token (string literal or quoted identifier). +/// `quote` is the surrounding quote character. Handles C-style backslash +/// escapes and the SQL doubled-quote escape (e.g. '' inside '...'). Mirrors +/// the relevant behaviour of `tryReadQuotedStringWithSQLStyle`. +bool decodeQuoted(const std::string & in, size_t & pos, char quote, std::string & out, std::string & error) +{ + /// pos points at the opening quote. + ++pos; + while (pos < in.size()) + { + char c = in[pos]; + if (c == quote) + { + /// Doubled quote -> literal quote. + if (pos + 1 < in.size() && in[pos + 1] == quote) + { + out.push_back(quote); + pos += 2; + continue; + } + ++pos; /// consume the closing quote + return true; + } + if (c == '\\') + { + if (pos + 1 >= in.size()) + { + error = "unterminated escape in quoted literal"; + return false; + } + char e = in[pos + 1]; + switch (e) + { + case 'b': out.push_back('\b'); break; + case 'f': out.push_back('\f'); break; + case 'n': out.push_back('\n'); break; + case 'r': out.push_back('\r'); break; + case 't': out.push_back('\t'); break; + case '0': out.push_back('\0'); break; + case 'a': out.push_back('\a'); break; + case 'v': out.push_back('\v'); break; + /// \\, \', \", \`, and any other char: keep the literal char. + default: out.push_back(e); break; + } + pos += 2; + continue; + } + out.push_back(c); + ++pos; + } + error = "unterminated quoted literal"; + return false; +} + +} /// namespace + +std::vector tokenize(const std::string & input) +{ + std::vector tokens; + size_t pos = 0; + const size_t n = input.size(); + + auto fail = [&](size_t at, const std::string & msg) + { + tokens.push_back(Token{TokenType::Error, msg, false, at}); + }; + + while (pos < n) + { + char c = input[pos]; + + if (isSpace(c)) + { + ++pos; + continue; + } + + const size_t start = pos; + + switch (c) + { + case '(': tokens.push_back({TokenType::OpeningParen, "(", false, start}); ++pos; continue; + case ')': tokens.push_back({TokenType::ClosingParen, ")", false, start}); ++pos; continue; + case ',': tokens.push_back({TokenType::Comma, ",", false, start}); ++pos; continue; + case '=': tokens.push_back({TokenType::Equals, "=", false, start}); ++pos; continue; + case '-': tokens.push_back({TokenType::Minus, "-", false, start}); ++pos; continue; + default: break; + } + + /// A dot may start a fractional number (.5) or be a standalone separator. + if (c == '.' && !(pos + 1 < n && isDigit(input[pos + 1]))) + { + tokens.push_back({TokenType::Dot, ".", false, start}); + ++pos; + continue; + } + + /// Quoted identifiers. + if (c == '`' || c == '"') + { + std::string decoded; + std::string error; + if (!decodeQuoted(input, pos, c, decoded, error)) + { + fail(start, error); + break; + } + tokens.push_back({TokenType::QuotedIdent, decoded, false, start}); + continue; + } + + /// String literal. + if (c == '\'') + { + std::string decoded; + std::string error; + if (!decodeQuoted(input, pos, c, decoded, error)) + { + fail(start, error); + break; + } + tokens.push_back({TokenType::String, decoded, false, start}); + continue; + } + + /// Number. + if (isDigit(c) || c == '.') + { + bool is_float = false; + /// integer part + while (pos < n && isDigit(input[pos])) + ++pos; + /// fraction + if (pos < n && input[pos] == '.') + { + is_float = true; + ++pos; + while (pos < n && isDigit(input[pos])) + ++pos; + } + /// exponent + if (pos < n && (input[pos] == 'e' || input[pos] == 'E')) + { + is_float = true; + ++pos; + if (pos < n && (input[pos] == '+' || input[pos] == '-')) + ++pos; + while (pos < n && isDigit(input[pos])) + ++pos; + } + tokens.push_back({TokenType::Number, input.substr(start, pos - start), is_float, start}); + continue; + } + + /// Bare word / identifier / keyword. + if (isWordFirst(c)) + { + while (pos < n && isWordChar(input[pos])) + ++pos; + tokens.push_back({TokenType::Word, input.substr(start, pos - start), false, start}); + continue; + } + + fail(start, std::string("unexpected character '") + c + "'"); + break; + } + + tokens.push_back({TokenType::End, "", false, pos}); + return tokens; +} + +} diff --git a/type-parser/mini-parser-extracted/src/lexer.h b/type-parser/mini-parser-extracted/src/lexer.h new file mode 100644 index 000000000..9edf36bb2 --- /dev/null +++ b/type-parser/mini-parser-extracted/src/lexer.h @@ -0,0 +1,50 @@ +#pragma once + +/// A small purpose-built tokenizer for ClickHouse data-type strings. +/// +/// Type strings use a tiny slice of the SQL grammar — identifiers (bare, +/// backtick- or double-quoted), single-quoted string literals, numbers, and a +/// handful of punctuation tokens. Rather than vendor the full ClickHouse +/// `Lexer` (and its `UTF8Helpers` / `find_symbols` dependencies), this covers +/// exactly that slice, keeping the library free of any ClickHouse headers. + +#include +#include +#include + +namespace chdt +{ + +enum class TokenType +{ + End, /// end of input + Word, /// bare identifier / keyword, e.g. UInt8, Array, SIGNED + QuotedIdent, /// `backtick` or "double"-quoted identifier (decoded) + Number, /// numeric literal (raw text, no sign) + String, /// single-quoted string literal (decoded) + OpeningParen, /// ( + ClosingParen, /// ) + Comma, /// , + Equals, /// = + Minus, /// - + Dot, /// . + Error, /// malformed token; `text` holds the message +}; + +struct Token +{ + TokenType type = TokenType::End; + /// Word/Number: raw source text. QuotedIdent/String: decoded content. + /// Error: the error message. + std::string text; + /// Number only: true when the literal has a fractional part or exponent. + bool is_float = false; + /// Byte offset of the token start in the input (for diagnostics). + size_t begin = 0; +}; + +/// Tokenize the whole input. The returned vector always ends with an `End` +/// token. A malformed token yields a single trailing `Error` token. +std::vector tokenize(const std::string & input); + +} diff --git a/type-parser/mini-parser-extracted/src/parser.cpp b/type-parser/mini-parser-extracted/src/parser.cpp new file mode 100644 index 000000000..08f370cb8 --- /dev/null +++ b/type-parser/mini-parser-extracted/src/parser.cpp @@ -0,0 +1,509 @@ +#include "chdt/parser.h" + +#include "lexer.h" + +#include +#include +#include +#include + +/// A faithful port of ClickHouse's `ParserDataType::parseImpl` +/// (src/Parsers/ParserDataType.cpp) onto the self-contained AST in `ast.h`. +/// The control flow deliberately tracks the original: identifier + SQL-standard +/// multi-word aliases, the Enum and Tuple special cases, then the generic +/// parametric-argument loop. AggregateFunction/SimpleAggregateFunction and the +/// JSON object-argument syntax are reported as unsupported (see parser.h). + +namespace chdt +{ + +namespace +{ + +std::string toUpper(const std::string & s) +{ + std::string r = s; + for (char & c : r) + if (c >= 'a' && c <= 'z') + c = static_cast(c - 'a' + 'A'); + return r; +} + +std::string toLower(const std::string & s) +{ + std::string r = s; + for (char & c : r) + if (c >= 'A' && c <= 'Z') + c = static_cast(c - 'A' + 'a'); + return r; +} + +bool isWordCharOrDollar(char c) +{ + return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_' || c == '$'; +} + +bool isEnumTypeUpper(const std::string & u) +{ + return u == "ENUM" || u == "ENUM8" || u == "ENUM16"; +} + +class Parser +{ +public: + explicit Parser(std::vector tokens_) : tokens(std::move(tokens_)) {} + + ParseResult run() + { + /// A lexing error surfaces as a trailing Error token. + for (const auto & tok : tokens) + if (tok.type == TokenType::Error) + return fail(tok.begin, tok.text); + + NodePtr node = parseType(); + if (!node) + { + if (hard_error) + return ParseResult{nullptr, hard_error}; + return fail(cur().begin, "expected a data type"); + } + + if (cur().type != TokenType::End) + return fail(cur().begin, "unexpected trailing input after the data type"); + + return ParseResult{node, std::nullopt}; + } + +private: + std::vector tokens; + size_t pos = 0; + std::optional hard_error; + + const Token & cur() const { return tokens[pos]; } + TokenType type() const { return tokens[pos].type; } + void advance() + { + if (tokens[pos].type != TokenType::End) + ++pos; + } + + static ParseResult fail(size_t at, const std::string & msg) { return ParseResult{nullptr, ParseError{msg, at}}; } + + void setHardError(size_t at, const std::string & msg) + { + if (!hard_error) + hard_error = ParseError{msg, at}; + } + + bool isIdentifier() const { return type() == TokenType::Word || type() == TokenType::QuotedIdent; } + + /// Consume `count` consecutive Word tokens iff they match `words` + /// (case-insensitive). Returns the original-cased joined match or "". + bool matchWords(std::initializer_list words) + { + size_t p = pos; + for (const char * w : words) + { + if (tokens[p].type != TokenType::Word || toUpper(tokens[p].text) != toUpper(std::string(w))) + return false; + ++p; + } + pos = p; + return true; + } + + /// Read a single identifier (bare or quoted) into `name`. + bool parseIdentifier(std::string & name) + { + if (!isIdentifier()) + return false; + name = cur().text; + advance(); + return true; + } + + NodePtr parseType() + { + std::string type_name; + if (!parseIdentifier(type_name)) + return nullptr; + + /// Reject quoted garbage that cannot be a type name (e.g. `x.y`, `Null`). + if (!std::all_of(type_name.begin(), type_name.end(), [](char c) { return isWordCharOrDollar(c); })) + return nullptr; + + const std::string type_name_upper = toUpper(type_name); + + /// Keywords that the column-declaration parser claims before the type. + if (type_name_upper == "NOT" || type_name_upper == "NULL" || type_name_upper == "DEFAULT" + || type_name_upper == "MATERIALIZED" || type_name_upper == "EPHEMERAL" || type_name_upper == "ALIAS" + || type_name_upper == "AUTO" || type_name_upper == "PRIMARY" || type_name_upper == "COMMENT" + || type_name_upper == "CODEC") + return nullptr; + + /// SQL-standard multi-word type names. + std::string suffix = parseTypeNameSuffix(type_name_upper); + if (!suffix.empty()) + type_name = type_name_upper + " " + suffix; + + skipTrailingComma(); + + /// Enum special case -> EnumDataType with explicit values. + if (isEnumTypeUpper(type_name_upper) && type() == TokenType::OpeningParen) + { + size_t saved = pos; + advance(); + std::vector values; + if (parseEnumValues(values) && type() == TokenType::ClosingParen) + { + advance(); + auto node = Node::make(NodeKind::EnumDataType); + node->name = type_name; + node->values = std::move(values); + return node; + } + pos = saved; + } + + /// Tuple special case -> TupleDataType with optional element names. + if (type_name == "Tuple" && type() == TokenType::OpeningParen) + { + if (NodePtr tuple = parseTuple(type_name)) + return tuple; + /// else: fall through to the generic path + } + + auto node = Node::make(NodeKind::DataType); + node->name = type_name; + + if (type() != TokenType::OpeningParen) + return node; + advance(); + + if (!parseArgumentList(type_name, node->arguments)) + return nullptr; + + if (type() != TokenType::ClosingParen) + return nullptr; + advance(); + + node->has_argument_list = true; + return node; + } + + /// Returns the suffix to append for SQL-standard multi-word names, or "". + std::string parseTypeNameSuffix(const std::string & u) + { + if (u == "NATIONAL") + { + if (matchWords({"CHARACTER", "LARGE", "OBJECT"})) return "CHARACTER LARGE OBJECT"; + if (matchWords({"CHARACTER", "VARYING"})) return "CHARACTER VARYING"; + if (matchWords({"CHAR", "VARYING"})) return "CHAR VARYING"; + if (matchWords({"CHARACTER"})) return "CHARACTER"; + if (matchWords({"CHAR"})) return "CHAR"; + } + else if (u == "BINARY" || u == "CHARACTER" || u == "CHAR" || u == "NCHAR") + { + if (matchWords({"LARGE", "OBJECT"})) return "LARGE OBJECT"; + if (matchWords({"VARYING"})) return "VARYING"; + } + else if (u == "DOUBLE") + { + if (matchWords({"PRECISION"})) return "PRECISION"; + } + else if (u.find("INT") != std::string::npos) + { + /// MySQL-compatible SIGNED / UNSIGNED, optionally after `(width)`. + if (matchWords({"SIGNED"})) return "SIGNED"; + if (matchWords({"UNSIGNED"})) return "UNSIGNED"; + if (type() == TokenType::OpeningParen) + { + size_t saved = pos; + advance(); + if (type() == TokenType::Number) + advance(); + if (type() == TokenType::ClosingParen) + { + advance(); + if (matchWords({"SIGNED"})) return "SIGNED"; + if (matchWords({"UNSIGNED"})) return "UNSIGNED"; + } + else + { + /// not the width form; leave the paren for generic args + pos = saved; + } + } + } + return ""; + } + + /// Skip a trailing comma right before a closing paren: `Tuple(Int, String,)`. + void skipTrailingComma() + { + if (type() == TokenType::Comma && tokens[pos + 1].type == TokenType::ClosingParen) + advance(); + } + + /// Explicit-only enum body: 'name' = value, ... . Returns false (caller + /// restores) for auto-assigned or otherwise non-trivial enums. + bool parseEnumValues(std::vector & values) + { + bool first = true; + while (true) + { + if (!first) + { + if (type() != TokenType::Comma) + break; + advance(); + } + first = false; + + if (type() != TokenType::String) + return false; + std::string name = cur().text; + advance(); + + if (type() != TokenType::Equals) + return false; + advance(); + + bool negative = false; + if (type() == TokenType::Minus) + { + negative = true; + advance(); + } + + if (type() != TokenType::Number || cur().is_float) + return false; + int64_t v = std::strtoll(cur().text.c_str(), nullptr, 10); + advance(); + + values.push_back(EnumValue{name, negative ? -v : v}); + } + return !values.empty(); + } + + /// Parse a Tuple body into element types + names. Returns null (with the + /// position restored) if it cannot, so the caller can try the generic path. + NodePtr parseTuple(const std::string & type_name) + { + size_t saved = pos; + advance(); /// consume '(' + + auto node = Node::make(NodeKind::TupleDataType); + node->name = type_name; + + std::vector names; + bool has_named = false; + bool first = true; + + while (true) + { + if (!first) + { + if (type() == TokenType::Comma) + advance(); + else + break; + } + first = false; + + size_t element_pos = pos; + std::string ident; + /// Try: identifier Type (named element) + if (parseIdentifier(ident)) + { + if (NodePtr t = parseType()) + { + names.push_back(ident); + node->arguments.push_back(t); + has_named = true; + continue; + } + } + /// Else: just Type (unnamed element) + pos = element_pos; + if (NodePtr t = parseType()) + { + names.emplace_back(""); + node->arguments.push_back(t); + } + else + { + break; + } + } + + if (type() == TokenType::ClosingParen && !node->arguments.empty()) + { + advance(); + node->has_argument_list = true; + if (has_named) + node->element_names = std::move(names); + return node; + } + + pos = saved; + return nullptr; + } + + /// The generic comma-separated argument list inside `Type(...)`. + bool parseArgumentList(const std::string & type_name, std::vector & out) + { + const std::string lower = toLower(type_name); + + if (type_name == "AggregateFunction" || type_name == "SimpleAggregateFunction") + { + setHardError(cur().begin, type_name + " is not supported by this parser yet"); + return false; + } + if (lower == "json") + { + setHardError(cur().begin, "JSON typed/object arguments are not supported by this parser yet"); + return false; + } + + size_t arg_num = 0; + while (true) + { + if (arg_num > 0) + { + if (type() == TokenType::Comma) + advance(); + else + break; + } + + NodePtr arg; + if (type_name == "Dynamic") + arg = parseEqualsArgument(); + else if (type_name == "Nested") + arg = parseNameTypePair(); + else if (type_name == "Tuple") + arg = parseNameTypePairOrType(); + else + arg = parseGenericArgument(); + + if (!arg) + break; + + out.push_back(arg); + ++arg_num; + } + return true; + } + + /// `identifier = number` -> Function equals(Identifier, Literal). + NodePtr parseEqualsArgument() + { + std::string ident; + if (!parseIdentifier(ident)) + return nullptr; + if (type() != TokenType::Equals) + return nullptr; + advance(); + NodePtr number = parseNumberLiteral(); + if (!number) + return nullptr; + + auto id = Node::make(NodeKind::Identifier); + id->name = ident; + auto fn = Node::make(NodeKind::Function); + fn->name = "equals"; + fn->is_operator = true; + fn->arguments = {id, number}; + return fn; + } + + /// `name Type` -> NameTypePair (Nested elements). + NodePtr parseNameTypePair() + { + std::string name; + if (!parseIdentifier(name)) + return nullptr; + NodePtr t = parseType(); + if (!t) + return nullptr; + auto node = Node::make(NodeKind::NameTypePair); + node->name = name; + node->data_type = t; + return node; + } + + NodePtr parseNameTypePairOrType() + { + size_t saved = pos; + if (NodePtr pair = parseNameTypePair()) + return pair; + pos = saved; + return parseType(); + } + + /// Generic argument: a scalar literal (optionally `lit = lit`), or a type. + NodePtr parseGenericArgument() + { + if (NodePtr lit = parseScalarLiteral()) + { + if (type() == TokenType::Equals) + { + advance(); + NodePtr rhs = parseScalarLiteral(); + if (!rhs) + return nullptr; + auto fn = Node::make(NodeKind::Function); + fn->name = "equals"; + fn->is_operator = true; + fn->arguments = {lit, rhs}; + return fn; + } + return lit; + } + return parseType(); + } + + NodePtr parseNumberLiteral() + { + bool negative = false; + if (type() == TokenType::Minus) + { + negative = true; + advance(); + } + if (type() != TokenType::Number) + return nullptr; + auto node = Node::make(NodeKind::Literal); + node->value_type = cur().is_float ? "Float64" : (negative ? "Int64" : "UInt64"); + node->value = (negative ? "-" : "") + cur().text; + advance(); + return node; + } + + /// A scalar literal: number (optionally signed) or string. + NodePtr parseScalarLiteral() + { + if (type() == TokenType::Number || type() == TokenType::Minus) + return parseNumberLiteral(); + if (type() == TokenType::String) + { + auto node = Node::make(NodeKind::Literal); + node->value_type = "String"; + node->value = cur().text; + advance(); + return node; + } + return nullptr; + } +}; + +} /// namespace + +ParseResult parseDataType(const std::string & input) +{ + Parser parser(tokenize(input)); + return parser.run(); +} + +} diff --git a/type-parser/mini-parser-extracted/test/CMakeLists.txt b/type-parser/mini-parser-extracted/test/CMakeLists.txt new file mode 100644 index 000000000..6c99f8bdc --- /dev/null +++ b/type-parser/mini-parser-extracted/test/CMakeLists.txt @@ -0,0 +1,24 @@ +# The oracle test needs a ClickHouse binary to produce expected output. +# Override with -DCLICKHOUSE_BINARY=/path/to/clickhouse at configure time. +set(CLICKHOUSE_BINARY "${CMAKE_SOURCE_DIR}/../build/programs/clickhouse" + CACHE FILEPATH "Path to the clickhouse binary used as the oracle") + +find_package(Python3 COMPONENTS Interpreter) + +if(Python3_Interpreter_FOUND) + add_test( + NAME oracle + COMMAND ${Python3_EXECUTABLE} + ${CMAKE_CURRENT_SOURCE_DIR}/oracle_compare.py + --clickhouse ${CLICKHOUSE_BINARY} + --tool $ + --cases ${CMAKE_CURRENT_SOURCE_DIR}/cases.txt + ) + add_test( + NAME unsupported + COMMAND ${Python3_EXECUTABLE} + ${CMAKE_CURRENT_SOURCE_DIR}/check_unsupported.py + --tool $ + --cases ${CMAKE_CURRENT_SOURCE_DIR}/cases_unsupported.txt + ) +endif() diff --git a/type-parser/mini-parser-extracted/test/cases.txt b/type-parser/mini-parser-extracted/test/cases.txt new file mode 100644 index 000000000..37844c31f --- /dev/null +++ b/type-parser/mini-parser-extracted/test/cases.txt @@ -0,0 +1,72 @@ +# Supported data types, one per line. Each is compared against the +# data_type subtree the ClickHouse server emits for +# EXPLAIN AST json = 1 CREATE TABLE t (c ) ENGINE = Null +# Blank lines and #-comments are ignored. + +# scalars +UInt8 +Int64 +Float64 +String +Date +DateTime +UUID +Bool +IPv4 +IPv6 + +# parametric with literal args +FixedString(16) +Decimal(10, 2) +Decimal(38, 10) +Decimal32(4) +DateTime64(3) +DateTime64(3, 'UTC') +DateTime('UTC') + +# nested type args +Nullable(UInt64) +Array(String) +Array(Array(Int32)) +Array(Nullable(UInt64)) +Map(String, UInt64) +Map(String, Array(UInt8)) +LowCardinality(String) +LowCardinality(Nullable(String)) +Array(Tuple(Float64, Float64)) + +# tuples +Tuple(UInt8, String) +Tuple(a UInt8, b String) +Tuple(a UInt8, String) +Tuple(Decimal(10, 2), Nullable(String)) + +# enums (explicit -> EnumDataType; auto-assigned -> generic DataType) +Enum8('a' = 1, 'b' = 2) +Enum16('x' = -1, 'y' = 100) +Enum('a' = 1, 'b' = 2) +Enum8('a', 'b') + +# nested table type +Nested(a UInt8, b String) +Nested(a Array(UInt8), b Tuple(x UInt8, y String)) + +# SQL-standard multi-word aliases +DOUBLE PRECISION +CHAR VARYING +INT SIGNED +INT UNSIGNED + +# legacy object + dynamic +Object('json') +Dynamic +Dynamic(max_types = 5) + +# misc families harvested from the fixture corpus +Variant(UInt8, String) +varchar +varchar(255) +BFloat16 +Time +int +Int diff --git a/type-parser/mini-parser-extracted/test/cases_unsupported.txt b/type-parser/mini-parser-extracted/test/cases_unsupported.txt new file mode 100644 index 000000000..cf6064272 --- /dev/null +++ b/type-parser/mini-parser-extracted/test/cases_unsupported.txt @@ -0,0 +1,7 @@ +# Types that the parser deliberately rejects (see parser.h). Each must make +# chdt-parse exit non-zero. Blank lines and #-comments are ignored. +AggregateFunction(sum, UInt64) +AggregateFunction(1, quantiles(0.5), Float64) +SimpleAggregateFunction(sum, UInt64) +JSON(max_dynamic_paths = 16) +JSON(a.b UInt32, SKIP x) diff --git a/type-parser/mini-parser-extracted/test/check_unsupported.py b/type-parser/mini-parser-extracted/test/check_unsupported.py new file mode 100644 index 000000000..062952fac --- /dev/null +++ b/type-parser/mini-parser-extracted/test/check_unsupported.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python3 +"""Assert that chdt-parse rejects the deliberately-unsupported types.""" + +import argparse +import subprocess +import sys + + +def read_cases(path): + cases = [] + with open(path) as f: + for line in f: + line = line.strip() + if line and not line.startswith("#"): + cases.append(line) + return cases + + +def main(): + ap = argparse.ArgumentParser() + ap.add_argument("--tool", required=True) + ap.add_argument("--cases", required=True) + args = ap.parse_args() + + cases = read_cases(args.cases) + failures = 0 + for type_str in cases: + out = subprocess.run([args.tool, type_str], capture_output=True, text=True) + if out.returncode != 0: + print(f" ok rejected: {type_str}") + else: + failures += 1 + print(f"FAIL unexpectedly accepted: {type_str}") + + print(f"\n{len(cases) - failures}/{len(cases)} correctly rejected") + return 1 if failures else 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/type-parser/mini-parser-extracted/test/oracle_compare.py b/type-parser/mini-parser-extracted/test/oracle_compare.py new file mode 100644 index 000000000..8a26ae35b --- /dev/null +++ b/type-parser/mini-parser-extracted/test/oracle_compare.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python3 +"""Compare the standalone parser's JSON AST against the ClickHouse server. + +For each data type in the cases file, the expected output is the `data_type` +subtree the server produces for + + EXPLAIN AST json = 1 CREATE TABLE t (c ) ENGINE = Null + +(version 2 of the format). The actual output is `chdt-parse `. The two +JSON trees are compared structurally (key order ignored). +""" + +import argparse +import json +import subprocess +import sys + + +def canon(value): + """Recursively sort dict keys so comparison ignores key order.""" + if isinstance(value, dict): + return {k: canon(value[k]) for k in sorted(value)} + if isinstance(value, list): + return [canon(v) for v in value] + return value + + +def find_column_data_type(node, column): + """Depth-first search for the ColumnDeclaration named `column`.""" + if isinstance(node, dict): + if node.get("type") == "ColumnDeclaration" and node.get("name") == column: + return node.get("data_type") + for v in node.values(): + found = find_column_data_type(v, column) + if found is not None: + return found + elif isinstance(node, list): + for v in node: + found = find_column_data_type(v, column) + if found is not None: + return found + return None + + +def server_data_type(clickhouse, type_str): + sql = f"EXPLAIN AST json = 1 CREATE TABLE t (c {type_str}) ENGINE = Null" + out = subprocess.run( + [clickhouse, "local", "--format", "TSVRaw", "-q", sql], + capture_output=True, text=True, + ) + if out.returncode != 0: + raise RuntimeError(f"server failed: {out.stderr.strip()}") + doc = json.loads(out.stdout) + if doc.get("version") != 2: + raise RuntimeError(f"unexpected format version {doc.get('version')}") + dt = find_column_data_type(doc["ast"], "c") + if dt is None: + raise RuntimeError("could not locate column data_type in server AST") + return dt + + +def tool_data_type(tool, type_str): + out = subprocess.run([tool, type_str], capture_output=True, text=True) + if out.returncode != 0: + raise RuntimeError(f"chdt-parse failed: {out.stderr.strip()}") + return json.loads(out.stdout) + + +def read_cases(path): + cases = [] + with open(path) as f: + for line in f: + line = line.strip() + if line and not line.startswith("#"): + cases.append(line) + return cases + + +def main(): + ap = argparse.ArgumentParser() + ap.add_argument("--clickhouse", required=True) + ap.add_argument("--tool", required=True) + ap.add_argument("--cases", required=True) + args = ap.parse_args() + + cases = read_cases(args.cases) + failures = 0 + for type_str in cases: + try: + expected = canon(server_data_type(args.clickhouse, type_str)) + actual = canon(tool_data_type(args.tool, type_str)) + except Exception as exc: # noqa: BLE001 + print(f"ERROR {type_str!r}: {exc}") + failures += 1 + continue + + if expected == actual: + print(f" ok {type_str}") + else: + failures += 1 + print(f"FAIL {type_str}") + print(" expected:", json.dumps(expected)) + print(" actual: ", json.dumps(actual)) + + print(f"\n{len(cases) - failures}/{len(cases)} passed") + return 1 if failures else 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/type-parser/mini-parser-extracted/tool/main.cpp b/type-parser/mini-parser-extracted/tool/main.cpp new file mode 100644 index 000000000..83ab686ea --- /dev/null +++ b/type-parser/mini-parser-extracted/tool/main.cpp @@ -0,0 +1,46 @@ +#include "chdt/parser.h" + +#include +#include +#include + +/// chdt-parse: read a ClickHouse data-type string and print its JSON AST. +/// +/// chdt-parse "Array(Nullable(UInt64))" # type from arguments +/// echo "Tuple(a UInt8, b String)" | chdt-parse # type from stdin +/// +/// Prints the JSON AST and exits 0 on success. On a parse error, prints +/// "error: (at byte N)" to stderr and exits 1. +int main(int argc, char ** argv) +{ + std::string input; + if (argc > 1) + { + for (int i = 1; i < argc; ++i) + { + if (i > 1) + input += ' '; + input += argv[i]; + } + } + else + { + std::ostringstream ss; + ss << std::cin.rdbuf(); + input = ss.str(); + } + + /// Trim trailing newline/whitespace from stdin. + while (!input.empty() && (input.back() == '\n' || input.back() == '\r' || input.back() == ' ' || input.back() == '\t')) + input.pop_back(); + + chdt::ParseResult result = chdt::parseDataType(input); + if (!result.ok()) + { + std::cerr << "error: " << result.error->message << " (at byte " << result.error->position << ")\n"; + return 1; + } + + std::cout << chdt::toJSON(*result.ast) << "\n"; + return 0; +} From 8f9693788ffa50efac29c06b4c998b8bdf9f1bac Mon Sep 17 00:00:00 2001 From: Peter Leonov Date: Tue, 23 Jun 2026 14:26:04 +0200 Subject: [PATCH 2/9] about tests --- type-parser/mini-parser-extracted/README.md | 27 ++++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/type-parser/mini-parser-extracted/README.md b/type-parser/mini-parser-extracted/README.md index 9e480404e..87011edfa 100644 --- a/type-parser/mini-parser-extracted/README.md +++ b/type-parser/mini-parser-extracted/README.md @@ -27,15 +27,14 @@ layer). Instead, this reimplements just the type grammar on a minimal AST: Tuple special cases, then the generic parametric-argument loop; - plain structs for the AST (`include/chdt/ast.h`) instead of `IAST` + `Field`. -## Building +## Build and test ```bash +rm -rf build # clean the build dir for a fresh run cmake -S . -B build -DCMAKE_BUILD_TYPE=Release cmake --build build ``` -This produces `libchdt_datatype_parser.a` and the `chdt-parse` CLI. - ## Usage Library: @@ -61,15 +60,15 @@ echo "Enum8('a' = 1, 'b' = 2)" | ./build/chdt-parse Node types and slots match the server (format v2): -| `type` | slots | -|------------------|----------------------------------------------------------| -| `DataType` | `name`, `arguments?` (present iff the type had `(...)`) | -| `EnumDataType` | `name`, `values` (array of `{ name, value }`) | -| `TupleDataType` | `name`, `arguments?`, `element_names?` (named tuples) | -| `NameTypePair` | `name`, `data_type` (a `Nested(...)` element) | -| `Literal` | `value_type`, `value` (64-bit ints as JSON strings) | -| `Function` | `name`, `is_operator?`, `arguments` (e.g. `max_types=5`) | -| `Identifier` | `name`, `name_parts?` | +| `type` | slots | +| --------------- | -------------------------------------------------------- | +| `DataType` | `name`, `arguments?` (present iff the type had `(...)`) | +| `EnumDataType` | `name`, `values` (array of `{ name, value }`) | +| `TupleDataType` | `name`, `arguments?`, `element_names?` (named tuples) | +| `NameTypePair` | `name`, `data_type` (a `Nested(...)` element) | +| `Literal` | `value_type`, `value` (64-bit ints as JSON strings) | +| `Function` | `name`, `is_operator?`, `arguments` (e.g. `max_types=5`) | +| `Identifier` | `name`, `name_parts?` | `EnumDataType.values` and `TupleDataType.element_names` are carried here exactly as the server emits them since format v2. @@ -103,5 +102,9 @@ multi-word aliases (`DOUBLE PRECISION`, `CHAR VARYING`, `INT SIGNED`, …). `test/cases_unsupported.txt` are rejected. ```bash +cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DCLICKHOUSE_BINARY=/work/ClickHouse/build/programs/clickhouse +cmake --build build ctest --test-dir build --output-on-failure ``` + +When the AST format changes get merged the special build `/work/ClickHouse/build/programs/clickhouse` wouldn't be needed. From 12e002225eda0161e2eeb4e06250d65a2e3945a2 Mon Sep 17 00:00:00 2001 From: Peter Leonov Date: Wed, 24 Jun 2026 12:10:11 +0200 Subject: [PATCH 3/9] example --- type-parser/mini-parser-extracted/README.md | 253 ++++++++++++++++++++ 1 file changed, 253 insertions(+) diff --git a/type-parser/mini-parser-extracted/README.md b/type-parser/mini-parser-extracted/README.md index 87011edfa..0d04b801b 100644 --- a/type-parser/mini-parser-extracted/README.md +++ b/type-parser/mini-parser-extracted/README.md @@ -1,5 +1,258 @@ # chdt — standalone ClickHouse data-type parser +## Examples + +```bash +./build/chdt-parse "Tuple(id UInt64, name LowCardinality(String), price Decimal(18, 4), ts DateTime64(9, 'UTC'), tags + Array(LowCardinality(Nullable(String))), attrs Map(String, Array(Nullable(Int32))), status Enum8('active' = 1, 'closed' = -2), coords + Array(Tuple(Float64, Float64)), meta Nested(k String, v UInt32), fixed FixedString(16), dyn Dynamic(max_types = 8), variant Variant(UInt64, String, + Array(UInt8)), raw Object('json'))" +``` + +```json +{ + "type": "TupleDataType", + "name": "Tuple", + "arguments": [ + { + "type": "DataType", + "name": "UInt64" + }, + { + "type": "DataType", + "name": "LowCardinality", + "arguments": [ + { + "type": "DataType", + "name": "String" + } + ] + }, + { + "type": "DataType", + "name": "Decimal", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "18" + }, + { + "type": "Literal", + "value_type": "UInt64", + "value": "4" + } + ] + }, + { + "type": "DataType", + "name": "DateTime64", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "9" + }, + { + "type": "Literal", + "value_type": "String", + "value": "UTC" + } + ] + }, + { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "LowCardinality", + "arguments": [ + { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "DataType", + "name": "String" + } + ] + } + ] + } + ] + }, + { + "type": "DataType", + "name": "Map", + "arguments": [ + { + "type": "DataType", + "name": "String" + }, + { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "DataType", + "name": "Int32" + } + ] + } + ] + } + ] + }, + { + "type": "EnumDataType", + "name": "Enum8", + "values": [ + { + "name": "active", + "value": 1 + }, + { + "name": "closed", + "value": -2 + } + ] + }, + { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "TupleDataType", + "name": "Tuple", + "arguments": [ + { + "type": "DataType", + "name": "Float64" + }, + { + "type": "DataType", + "name": "Float64" + } + ] + } + ] + }, + { + "type": "DataType", + "name": "Nested", + "arguments": [ + { + "type": "NameTypePair", + "name": "k", + "data_type": { + "type": "DataType", + "name": "String" + } + }, + { + "type": "NameTypePair", + "name": "v", + "data_type": { + "type": "DataType", + "name": "UInt32" + } + } + ] + }, + { + "type": "DataType", + "name": "FixedString", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "16" + } + ] + }, + { + "type": "DataType", + "name": "Dynamic", + "arguments": [ + { + "type": "Function", + "name": "equals", + "is_operator": true, + "arguments": [ + { + "type": "Identifier", + "name": "max_types" + }, + { + "type": "Literal", + "value_type": "UInt64", + "value": "8" + } + ] + } + ] + }, + { + "type": "DataType", + "name": "Variant", + "arguments": [ + { + "type": "DataType", + "name": "UInt64" + }, + { + "type": "DataType", + "name": "String" + }, + { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "UInt8" + } + ] + } + ] + }, + { + "type": "DataType", + "name": "Object", + "arguments": [ + { + "type": "Literal", + "value_type": "String", + "value": "json" + } + ] + } + ], + "element_names": [ + "id", + "name", + "price", + "ts", + "tags", + "attrs", + "status", + "coords", + "meta", + "fixed", + "dyn", + "variant", + "raw" + ] +} +``` + +## About + A small, self-contained C++ library that parses a ClickHouse **data-type string** (the kind sent in the types row of `RowBinaryWithNamesAndTypes`, e.g. `Array(Nullable(UInt64))`, `Tuple(a UInt8, b String)`, `Enum8('a' = 1)`, From 06b3f8766a917d18229f1c1492dc7e0c88963802 Mon Sep 17 00:00:00 2001 From: Peter Leonov Date: Wed, 24 Jun 2026 12:13:33 +0200 Subject: [PATCH 4/9] Add mini-parser-ts: TypeScript port of the chdt data-type parser A faithful TypeScript port of the standalone C++ ClickHouse data-type parser in type-parser/mini-parser-extracted. The module layout tracks the C++ sources one-to-one (ast/lexer/parser/json), preserving the original control flow, branch ordering, and pos save/restore points. Output is verified byte-identical to the C++ chdt-parse across the full corpus (50 supported + 5 unsupported + edge/error cases) and matches the real server's EXPLAIN AST json=1 data_type subtree (oracle: 50/50). Includes a tsx-based CLI, a dependency-free node:test unit suite, and TS ports of the oracle/unsupported test harnesses. Co-Authored-By: Claude Opus 4.8 (1M context) --- type-parser/mini-parser-ts/.gitignore | 2 + type-parser/mini-parser-ts/README.md | 116 ++++ type-parser/mini-parser-ts/package-lock.json | 551 ++++++++++++++++++ type-parser/mini-parser-ts/package.json | 23 + type-parser/mini-parser-ts/src/ast.ts | 82 +++ type-parser/mini-parser-ts/src/index.ts | 18 + type-parser/mini-parser-ts/src/json.ts | 267 +++++++++ type-parser/mini-parser-ts/src/lexer.ts | 240 ++++++++ type-parser/mini-parser-ts/src/parser.ts | 495 ++++++++++++++++ type-parser/mini-parser-ts/test/cases.ts | 31 + type-parser/mini-parser-ts/test/cases.txt | 72 +++ .../mini-parser-ts/test/cases_unsupported.txt | 7 + .../mini-parser-ts/test/check_unsupported.ts | 37 ++ .../mini-parser-ts/test/oracle_compare.ts | 121 ++++ .../mini-parser-ts/test/parser.test.ts | 122 ++++ type-parser/mini-parser-ts/tool/main.ts | 47 ++ type-parser/mini-parser-ts/tsconfig.json | 19 + 17 files changed, 2250 insertions(+) create mode 100644 type-parser/mini-parser-ts/.gitignore create mode 100644 type-parser/mini-parser-ts/README.md create mode 100644 type-parser/mini-parser-ts/package-lock.json create mode 100644 type-parser/mini-parser-ts/package.json create mode 100644 type-parser/mini-parser-ts/src/ast.ts create mode 100644 type-parser/mini-parser-ts/src/index.ts create mode 100644 type-parser/mini-parser-ts/src/json.ts create mode 100644 type-parser/mini-parser-ts/src/lexer.ts create mode 100644 type-parser/mini-parser-ts/src/parser.ts create mode 100644 type-parser/mini-parser-ts/test/cases.ts create mode 100644 type-parser/mini-parser-ts/test/cases.txt create mode 100644 type-parser/mini-parser-ts/test/cases_unsupported.txt create mode 100644 type-parser/mini-parser-ts/test/check_unsupported.ts create mode 100644 type-parser/mini-parser-ts/test/oracle_compare.ts create mode 100644 type-parser/mini-parser-ts/test/parser.test.ts create mode 100644 type-parser/mini-parser-ts/tool/main.ts create mode 100644 type-parser/mini-parser-ts/tsconfig.json diff --git a/type-parser/mini-parser-ts/.gitignore b/type-parser/mini-parser-ts/.gitignore new file mode 100644 index 000000000..b94707787 --- /dev/null +++ b/type-parser/mini-parser-ts/.gitignore @@ -0,0 +1,2 @@ +node_modules/ +dist/ diff --git a/type-parser/mini-parser-ts/README.md b/type-parser/mini-parser-ts/README.md new file mode 100644 index 000000000..67eb63a96 --- /dev/null +++ b/type-parser/mini-parser-ts/README.md @@ -0,0 +1,116 @@ +# chdt-ts — standalone ClickHouse data-type parser (TypeScript) + +A small, self-contained TypeScript library that parses a ClickHouse **data-type +string** (the kind sent in the types row of `RowBinaryWithNamesAndTypes`, e.g. +`Array(Nullable(UInt64))`, `Tuple(a UInt8, b String)`, `Enum8('a' = 1)`, +`Decimal(10, 2)`) into a JSON AST. + +It is a faithful port of the C++ `chdt` library (see `../mini-parser-extracted`), +which is itself extracted from the server's `ParserDataType` +(`src/Parsers/ParserDataType.cpp`). It has **no runtime dependencies** — only the +Node.js standard library. The JSON it emits mirrors the data-type subtree of the +frozen `EXPLAIN AST json = 1` document (format **version 2**), so its output is a +drop-in match for what the server produces — and is **byte-identical** to the C++ +parser's output across the full test corpus. + +## Layout + +The module structure tracks the C++ sources one-to-one: + +| TypeScript | ported from (C++) | role | +| ------------------- | -------------------------------- | --------------------------------------- | +| `src/ast.ts` | `include/chdt/ast.h` | the AST node shape + `makeNode` factory | +| `src/lexer.ts` | `src/lexer.{h,cpp}` | the purpose-built tokenizer | +| `src/parser.ts` | `src/parser.cpp` + `parser.h` | the `ParserDataType::parseImpl` port | +| `src/json.ts` | `src/json.cpp` | the byte-faithful JSON serializer | +| `src/index.ts` | — | public barrel | +| `tool/main.ts` | `tool/main.cpp` | the `chdt-parse` CLI | + +The lexer and parser deliberately preserve the original control flow, branch +ordering, helper names, and `pos` save/restore points. A few signatures changed +where C++ used out-parameters (`std::string &`): `parseIdentifier` and +`decodeQuoted` return small result objects instead. + +## Install & build + +```bash +npm install +npm run build # emits dist/ (JS + .d.ts) +npm run typecheck # tsc --noEmit +``` + +## Usage + +Library: + +```ts +import { parseDataType, toJSON } from "chdt-datatype-parser"; + +const r = parseDataType("Tuple(a UInt8, b String)"); +if (r.ok()) { + console.log(toJSON(r.ast!)); // pretty (2-space) JSON + console.log(toJSON(r.ast!, -1)); // compact JSON +} else { + console.error(r.error!.message, r.error!.position); +} +``` + +CLI (no build step needed — runs via `tsx`): + +```bash +npm run parse -- "Array(Nullable(UInt64))" +echo "Enum8('a' = 1, 'b' = 2)" | npm run parse + +# or, after `npm run build`: +node dist/tool/main.js "Tuple(a UInt8, b String)" +``` + +## Output shape + +Node types and slots match the server (format v2): + +| `type` | slots | +| --------------- | -------------------------------------------------------- | +| `DataType` | `name`, `arguments?` (present iff the type had `(...)`) | +| `EnumDataType` | `name`, `values` (array of `{ name, value }`) | +| `TupleDataType` | `name`, `arguments?`, `element_names?` (named tuples) | +| `NameTypePair` | `name`, `data_type` (a `Nested(...)` element) | +| `Literal` | `value_type`, `value` (64-bit ints as JSON strings) | +| `Function` | `name`, `is_operator?`, `arguments` (e.g. `max_types=5`) | +| `Identifier` | `name`, `name_parts?` | + +## Coverage + +Supported: scalars, parametric types with literal args (`Decimal`, +`FixedString`, `DateTime64`, …), nested type args (`Array`, `Map`, `Nullable`, +`LowCardinality`, `Variant`, …), enums (explicit → `EnumDataType`; +auto-assigned → generic `DataType`), named/unnamed/mixed tuples, `Nested`, +`Dynamic(max_types = N)`, the legacy `Object('json')`, and the SQL-standard +multi-word aliases (`DOUBLE PRECISION`, `CHAR VARYING`, `INT SIGNED`, …). + +**Deliberately not supported yet** (the parser returns a clear error): + +- `AggregateFunction` / `SimpleAggregateFunction` — needs the function-expression + parser the server reaches for here. +- the new `JSON(...)` object-argument syntax (`JSON(a.b UInt32, SKIP x)`). Bare + `JSON` and legacy `Object('json')` parse fine. + +## Tests + +```bash +npm test # node:test unit suite — no external dependencies +npm run test:unsupported # asserts the deferred types are rejected +npm run test:oracle -- --clickhouse /path/to/clickhouse +``` + +- **unit** (`test/parser.test.ts`) — pins representative AST shapes and all the + deliberate rejections; needs nothing but Node. +- **unsupported** (`test/check_unsupported.ts`) — asserts the types in + `test/cases_unsupported.txt` are rejected. +- **oracle** (`test/oracle_compare.ts`) — for each type in `test/cases.txt`, + compares the parser's JSON against the `data_type` subtree the real server + emits for `CREATE TABLE t (c ) ENGINE = Null`. Needs a `clickhouse` + binary built from + https://github.com/peter-leonov-ch/ClickHouse/pull/1 — the AST-format changes + this parser mirrors live in that PR, so a stock server build will not match. + diff --git a/type-parser/mini-parser-ts/package-lock.json b/type-parser/mini-parser-ts/package-lock.json new file mode 100644 index 000000000..d2ed1934d --- /dev/null +++ b/type-parser/mini-parser-ts/package-lock.json @@ -0,0 +1,551 @@ +{ + "name": "chdt-datatype-parser", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "chdt-datatype-parser", + "version": "0.1.0", + "bin": { + "chdt-parse": "dist/tool/main.js" + }, + "devDependencies": { + "tsx": "^4.22.4", + "typescript": "^5.6.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz", + "integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.1.tgz", + "integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz", + "integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.1.tgz", + "integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz", + "integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz", + "integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz", + "integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz", + "integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz", + "integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz", + "integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz", + "integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz", + "integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz", + "integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz", + "integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz", + "integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz", + "integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz", + "integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz", + "integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz", + "integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz", + "integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz", + "integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz", + "integrity": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz", + "integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz", + "integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz", + "integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz", + "integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/esbuild": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz", + "integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.28.1", + "@esbuild/android-arm": "0.28.1", + "@esbuild/android-arm64": "0.28.1", + "@esbuild/android-x64": "0.28.1", + "@esbuild/darwin-arm64": "0.28.1", + "@esbuild/darwin-x64": "0.28.1", + "@esbuild/freebsd-arm64": "0.28.1", + "@esbuild/freebsd-x64": "0.28.1", + "@esbuild/linux-arm": "0.28.1", + "@esbuild/linux-arm64": "0.28.1", + "@esbuild/linux-ia32": "0.28.1", + "@esbuild/linux-loong64": "0.28.1", + "@esbuild/linux-mips64el": "0.28.1", + "@esbuild/linux-ppc64": "0.28.1", + "@esbuild/linux-riscv64": "0.28.1", + "@esbuild/linux-s390x": "0.28.1", + "@esbuild/linux-x64": "0.28.1", + "@esbuild/netbsd-arm64": "0.28.1", + "@esbuild/netbsd-x64": "0.28.1", + "@esbuild/openbsd-arm64": "0.28.1", + "@esbuild/openbsd-x64": "0.28.1", + "@esbuild/openharmony-arm64": "0.28.1", + "@esbuild/sunos-x64": "0.28.1", + "@esbuild/win32-arm64": "0.28.1", + "@esbuild/win32-ia32": "0.28.1", + "@esbuild/win32-x64": "0.28.1" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/tsx": { + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.22.4.tgz", + "integrity": "sha512-X8EX+XV4QR5xCsrgxaED954zTDfY8KqlDtskKEL0cHhyS/P8b4IFOvGDQpsC9Q1XnLq915wEfwwY/zzskCtmhg==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "~0.28.0" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + } + } +} diff --git a/type-parser/mini-parser-ts/package.json b/type-parser/mini-parser-ts/package.json new file mode 100644 index 000000000..20b725788 --- /dev/null +++ b/type-parser/mini-parser-ts/package.json @@ -0,0 +1,23 @@ +{ + "name": "chdt-datatype-parser", + "version": "0.1.0", + "description": "Standalone ClickHouse data-type string parser — a TypeScript port of the chdt C++ library.", + "type": "module", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "bin": { + "chdt-parse": "dist/tool/main.js" + }, + "scripts": { + "build": "tsc -p tsconfig.json", + "typecheck": "tsc -p tsconfig.json --noEmit", + "parse": "tsx tool/main.ts", + "test": "node --import tsx --test test/*.test.ts", + "test:oracle": "tsx test/oracle_compare.ts", + "test:unsupported": "tsx test/check_unsupported.ts" + }, + "devDependencies": { + "tsx": "^4.22.4", + "typescript": "^5.6.0" + } +} diff --git a/type-parser/mini-parser-ts/src/ast.ts b/type-parser/mini-parser-ts/src/ast.ts new file mode 100644 index 000000000..62524bec0 --- /dev/null +++ b/type-parser/mini-parser-ts/src/ast.ts @@ -0,0 +1,82 @@ +/// Minimal, self-contained AST for ClickHouse data-type strings. +/// +/// The node shapes mirror the frozen `EXPLAIN AST json = 1` document +/// (format version 2; see ClickHouse `AST.md`) so that JSON produced here is +/// a drop-in match for the data-type subtree the server emits — and a +/// superset of it: `EnumDataType.values` and `TupleDataType.element_names` +/// are carried here as they are in the server (since v2). +/// +/// This is a TypeScript port of the C++ `chdt/ast.h`. The C++ side uses a +/// single "fat" struct with a `kind` discriminant and only the fields relevant +/// to that kind populated; we mirror that exactly (rather than a discriminated +/// union) so the parser port stays line-for-line faithful to the original. + +export enum NodeKind { + DataType = "DataType", /// generic type: name + optional argument list + EnumDataType = "EnumDataType", /// Enum / Enum8 / Enum16 with fully explicit values + TupleDataType = "TupleDataType", /// Tuple, with optional element names + NameTypePair = "NameTypePair", /// `name Type` element of a Nested(...) + Literal = "Literal", /// numeric / string argument (e.g. Decimal(10, 2)) + Function = "Function", /// operator/function argument (e.g. `max_types = 5`) + Identifier = "Identifier", /// bare identifier argument +} + +export interface EnumValue { + name: string; + /// int64 in the server; bigint here to avoid precision loss on serialization. + value: bigint; +} + +/// One node type for the whole tree. Only the fields relevant to `kind` are +/// populated; serialization emits exactly the slots the server would. +export interface Node { + kind: NodeKind; + + /// DataType / EnumDataType / TupleDataType / Function / Identifier / NameTypePair + name: string; + + /// DataType / TupleDataType / Function argument list (children inlined in JSON). + arguments: Node[]; + /// DataType only: whether the type carried a parenthesised argument list at + /// all. `UInt8` omits the `arguments` slot; `Array(...)` emits it (possibly + /// empty). Tuple/Function always emit their list. + has_argument_list: boolean; + + /// EnumDataType: explicit `'name' = value` pairs. + values: EnumValue[]; + + /// TupleDataType: element names. Empty => unnamed tuple (slot omitted). + element_names: string[]; + + /// NameTypePair: the element's type. + data_type: Node | null; + + /// Literal: `value_type` is the Field type id ("UInt64", "Int64", + /// "Float64", "String"); `value` is the textual value. + value_type: string; + value: string; + + /// Function: set for operators such as `equals`. + is_operator: boolean; + + /// Identifier: populated when the identifier is compound (a.b). + name_parts: string[]; +} + +/// Construct a node with all fields defaulted (mirrors the C++ struct's member +/// initializers), so the parser can set only the slots relevant to `kind`. +export function makeNode(kind: NodeKind): Node { + return { + kind, + name: "", + arguments: [], + has_argument_list: false, + values: [], + element_names: [], + data_type: null, + value_type: "", + value: "", + is_operator: false, + name_parts: [], + }; +} diff --git a/type-parser/mini-parser-ts/src/index.ts b/type-parser/mini-parser-ts/src/index.ts new file mode 100644 index 000000000..9b725d4fe --- /dev/null +++ b/type-parser/mini-parser-ts/src/index.ts @@ -0,0 +1,18 @@ +/// Public entry point for the standalone ClickHouse data-type parser. +/// +/// A TypeScript port of the C++ `chdt` library: parse a ClickHouse data-type +/// string (the kind sent in the types row of `RowBinaryWithNamesAndTypes`, e.g. +/// `Array(Nullable(UInt64))`, `Tuple(a UInt8, b String)`, `Enum8('a' = 1)`) +/// into a JSON-serializable AST that mirrors the server's `EXPLAIN AST json = 1` +/// data-type subtree (format version 2). + +export { parseDataType } from "./parser.js"; +export type { ParseError, ParseResult } from "./parser.js"; + +export { toJSON } from "./json.js"; + +export { NodeKind, makeNode } from "./ast.js"; +export type { Node, EnumValue } from "./ast.js"; + +export { tokenize, TokenType } from "./lexer.js"; +export type { Token } from "./lexer.js"; diff --git a/type-parser/mini-parser-ts/src/json.ts b/type-parser/mini-parser-ts/src/json.ts new file mode 100644 index 000000000..4b07402bc --- /dev/null +++ b/type-parser/mini-parser-ts/src/json.ts @@ -0,0 +1,267 @@ +/// Serialize a node tree to JSON, matching the server's `formatASTAsJSON` +/// shape for data types. This is a faithful TypeScript port of the C++ +/// `src/json.cpp`. `indent` < 0 produces compact output; >= 0 produces pretty +/// output with that many spaces per level. +/// +/// Byte-faithfulness: the C++ `escapeTo` iterates over the `unsigned char` +/// bytes of the input. To match it exactly for multibyte UTF-8 content we +/// accumulate the whole document into a byte buffer (`number[]` of byte +/// values): structural characters are ASCII, strings are encoded to their +/// UTF-8 bytes, and only bytes < 0x20 are special-cased (the ASCII escapes plus +/// the `\u%04x` fallback). All bytes >= 0x20 are pushed through verbatim. At +/// the end we decode the buffer back to a (byte-identical) JS string. + +import { NodeKind, type Node } from "./ast.js"; + +const encoder = new TextEncoder(); +const decoder = new TextDecoder("utf-8"); + +/// Mutable holder for the C++ `bool &` "first" flag (TS has no reference +/// parameters), threaded through `writeKey`. +interface FirstFlag { + first: boolean; +} + +function escapeTo(out: number[], s: string): void { + out.push(0x22 /* '"' */); + for (const c of encoder.encode(s)) { + switch (c) { + case 0x22 /* '"' */: + pushAscii(out, '\\"'); + break; + case 0x5c /* '\\' */: + pushAscii(out, "\\\\"); + break; + case 0x08 /* '\b' */: + pushAscii(out, "\\b"); + break; + case 0x0c /* '\f' */: + pushAscii(out, "\\f"); + break; + case 0x0a /* '\n' */: + pushAscii(out, "\\n"); + break; + case 0x0d /* '\r' */: + pushAscii(out, "\\r"); + break; + case 0x09 /* '\t' */: + pushAscii(out, "\\t"); + break; + default: + if (c < 0x20) { + /// \u%04x — lowercase hex, 4 digits. + pushAscii(out, "\\u" + c.toString(16).padStart(4, "0")); + } else { + out.push(c); + } + } + } + out.push(0x22 /* '"' */); +} + +/// Append the ASCII bytes of `s` (used only for structural/escape text, which +/// is always ASCII). +function pushAscii(out: number[], s: string): void { + for (let i = 0; i < s.length; i++) { + out.push(s.charCodeAt(i)); + } +} + +class Writer { + out: number[] = []; + indent: number; /// spaces per level, or < 0 for compact + + constructor(indent: number) { + this.indent = indent; + } + + newlineIndent(depth: number): void { + if (this.indent < 0) return; + this.out.push(0x0a /* '\n' */); + const spaces = this.indent * depth; + for (let i = 0; i < spaces; i++) { + this.out.push(0x20 /* ' ' */); + } + } + + colon(): void { + pushAscii(this.out, this.indent < 0 ? ":" : ": "); + } +} + +/// Emit `"key": ` prefix; flips `flag.first` to false (mirrors the C++ +/// `bool & first`). +function writeKey(w: Writer, key: string, flag: FirstFlag, depth: number): void { + if (!flag.first) w.out.push(0x2c /* ',' */); + flag.first = false; + w.newlineIndent(depth + 1); + escapeTo(w.out, key); + w.colon(); +} + +function writeArray(w: Writer, items: Node[], depth: number): void { + if (items.length === 0) { + pushAscii(w.out, "[]"); + return; + } + w.out.push(0x5b /* '[' */); + let first = true; + for (const item of items) { + if (!first) w.out.push(0x2c /* ',' */); + first = false; + w.newlineIndent(depth + 1); + writeNode(w, item, depth + 1); + } + w.newlineIndent(depth); + w.out.push(0x5d /* ']' */); +} + +function writeStringArray(w: Writer, items: string[], depth: number): void { + if (items.length === 0) { + pushAscii(w.out, "[]"); + return; + } + w.out.push(0x5b /* '[' */); + let first = true; + for (const item of items) { + if (!first) w.out.push(0x2c /* ',' */); + first = false; + w.newlineIndent(depth + 1); + escapeTo(w.out, item); + } + w.newlineIndent(depth); + w.out.push(0x5d /* ']' */); +} + +function writeLiteralValue(w: Writer, node: Node): void { + /// 64-bit integers are emitted as JSON strings (the server's contract: + /// values above 2^53 lose precision under JS `JSON.parse`). Float64 is a + /// JSON number; String is a JSON string. + if (node.value_type === "Float64") { + pushAscii(w.out, node.value); /// already a valid JSON number + } else if (node.value_type === "String") { + escapeTo(w.out, node.value); + } /// UInt64 / Int64 / fallback + else { + escapeTo(w.out, node.value); + } +} + +/// Object emission is inline (each node writes its own members in order). +function writeNode(w: Writer, node: Node, depth: number): void { + w.out.push(0x7b /* '{' */); + const flag: FirstFlag = { first: true }; + + const key = (k: string): void => writeKey(w, k, flag, depth); + + switch (node.kind) { + case NodeKind.DataType: + key("type"); + escapeTo(w.out, "DataType"); + key("name"); + escapeTo(w.out, node.name); + if (node.has_argument_list) { + key("arguments"); + writeArray(w, node.arguments, depth + 1); + } + break; + + case NodeKind.EnumDataType: { + key("type"); + escapeTo(w.out, "EnumDataType"); + key("name"); + escapeTo(w.out, node.name); + key("values"); + if (node.values.length === 0) { + pushAscii(w.out, "[]"); + } else { + w.out.push(0x5b /* '[' */); + let vfirst = true; + for (const v of node.values) { + if (!vfirst) w.out.push(0x2c /* ',' */); + vfirst = false; + w.newlineIndent(depth + 2); + w.out.push(0x7b /* '{' */); + const mflag: FirstFlag = { first: true }; + writeKey(w, "name", mflag, depth + 2); + escapeTo(w.out, v.name); + writeKey(w, "value", mflag, depth + 2); + pushAscii(w.out, v.value.toString()); + w.newlineIndent(depth + 2); + w.out.push(0x7d /* '}' */); + } + w.newlineIndent(depth + 1); + w.out.push(0x5d /* ']' */); + } + break; + } + + case NodeKind.TupleDataType: + key("type"); + escapeTo(w.out, "TupleDataType"); + key("name"); + escapeTo(w.out, node.name); + if (node.has_argument_list) { + key("arguments"); + writeArray(w, node.arguments, depth + 1); + } + if (node.element_names.length > 0) { + key("element_names"); + writeStringArray(w, node.element_names, depth + 1); + } + break; + + case NodeKind.NameTypePair: + key("type"); + escapeTo(w.out, "NameTypePair"); + key("name"); + escapeTo(w.out, node.name); + if (node.data_type) { + key("data_type"); + writeNode(w, node.data_type, depth + 1); + } + break; + + case NodeKind.Literal: + key("type"); + escapeTo(w.out, "Literal"); + key("value_type"); + escapeTo(w.out, node.value_type); + key("value"); + writeLiteralValue(w, node); + break; + + case NodeKind.Function: + key("type"); + escapeTo(w.out, "Function"); + key("name"); + escapeTo(w.out, node.name); + if (node.is_operator) { + key("is_operator"); + pushAscii(w.out, "true"); + } + key("arguments"); + writeArray(w, node.arguments, depth + 1); + break; + + case NodeKind.Identifier: + key("type"); + escapeTo(w.out, "Identifier"); + key("name"); + escapeTo(w.out, node.name); + if (node.name_parts.length > 0) { + key("name_parts"); + writeStringArray(w, node.name_parts, depth + 1); + } + break; + } + + w.newlineIndent(depth); + w.out.push(0x7d /* '}' */); +} + +export function toJSON(node: Node, indent = 2): string { + const w = new Writer(indent); + writeNode(w, node, 0); + return decoder.decode(Uint8Array.from(w.out)); +} diff --git a/type-parser/mini-parser-ts/src/lexer.ts b/type-parser/mini-parser-ts/src/lexer.ts new file mode 100644 index 000000000..00884e76b --- /dev/null +++ b/type-parser/mini-parser-ts/src/lexer.ts @@ -0,0 +1,240 @@ +/// A small purpose-built tokenizer for ClickHouse data-type strings. +/// +/// Type strings use a tiny slice of the SQL grammar — identifiers (bare, +/// backtick- or double-quoted), single-quoted string literals, numbers, and a +/// handful of punctuation tokens. Rather than vendor the full ClickHouse +/// `Lexer` (and its `UTF8Helpers` / `find_symbols` dependencies), this covers +/// exactly that slice, keeping the library free of any ClickHouse headers. +/// +/// This is a faithful TypeScript port of the original C++ lexer. + +export enum TokenType { + End = "End", /// end of input + Word = "Word", /// bare identifier / keyword, e.g. UInt8, Array, SIGNED + QuotedIdent = "QuotedIdent", /// `backtick` or "double"-quoted identifier (decoded) + Number = "Number", /// numeric literal (raw text, no sign) + String = "String", /// single-quoted string literal (decoded) + OpeningParen = "OpeningParen", /// ( + ClosingParen = "ClosingParen", /// ) + Comma = "Comma", /// , + Equals = "Equals", /// = + Minus = "Minus", /// - + Dot = "Dot", /// . + Error = "Error", /// malformed token; `text` holds the message +} + +export interface Token { + type: TokenType + /// Word/Number: raw source text. QuotedIdent/String: decoded content. + /// Error: the error message. + text: string + /// Number only: true when the literal has a fractional part or exponent. + is_float: boolean + /// Byte offset of the token start in the input (for diagnostics). + begin: number +} + +function isSpace(c: string): boolean { + return c === " " || c === "\t" || c === "\n" || c === "\r" || c === "\f" || c === "\v" +} + +function isDigit(c: string): boolean { + return c >= "0" && c <= "9" +} + +function isWordFirst(c: string): boolean { + return (c >= "a" && c <= "z") || (c >= "A" && c <= "Z") || c === "_" || c === "$" +} + +function isWordChar(c: string): boolean { + return isWordFirst(c) || isDigit(c) +} + +interface DecodeResult { + ok: boolean + /// Decoded content (valid when ok is true). + out: string + /// Error message (valid when ok is false). + error: string + /// Position after the token (in/out replacement for `size_t & pos`). + pos: number +} + +/// Decode the body of a quoted token (string literal or quoted identifier). +/// `quote` is the surrounding quote character. Handles C-style backslash +/// escapes and the SQL doubled-quote escape (e.g. '' inside '...'). Mirrors +/// the relevant behaviour of `tryReadQuotedStringWithSQLStyle`. +function decodeQuoted(input: string, pos: number, quote: string): DecodeResult { + const n = input.length + let out = "" + /// pos points at the opening quote. + ++pos + while (pos < n) { + const c = input[pos] as string + if (c === quote) { + /// Doubled quote -> literal quote. + if (pos + 1 < n && input[pos + 1] === quote) { + out += quote + pos += 2 + continue + } + ++pos /// consume the closing quote + return { ok: true, out, error: "", pos } + } + if (c === "\\") { + if (pos + 1 >= n) { + return { ok: false, out, error: "unterminated escape in quoted literal", pos } + } + const e = input[pos + 1] as string + switch (e) { + case "b": + out += "\b" + break + case "f": + out += "\f" + break + case "n": + out += "\n" + break + case "r": + out += "\r" + break + case "t": + out += "\t" + break + case "0": + out += "\0" + break + case "a": + out += "\x07" + break + case "v": + out += "\v" + break + /// \\, \', \", \`, and any other char: keep the literal char. + default: + out += e + break + } + pos += 2 + continue + } + out += c + ++pos + } + return { ok: false, out, error: "unterminated quoted literal", pos } +} + +/// Tokenize the whole input. The returned array always ends with an `End` +/// token. A malformed token yields a single trailing `Error` token. +export function tokenize(input: string): Token[] { + const tokens: Token[] = [] + let pos = 0 + const n = input.length + + const fail = (at: number, msg: string): void => { + tokens.push({ type: TokenType.Error, text: msg, is_float: false, begin: at }) + } + + while (pos < n) { + const c = input[pos] as string + + if (isSpace(c)) { + ++pos + continue + } + + const start = pos + + switch (c) { + case "(": + tokens.push({ type: TokenType.OpeningParen, text: "(", is_float: false, begin: start }) + ++pos + continue + case ")": + tokens.push({ type: TokenType.ClosingParen, text: ")", is_float: false, begin: start }) + ++pos + continue + case ",": + tokens.push({ type: TokenType.Comma, text: ",", is_float: false, begin: start }) + ++pos + continue + case "=": + tokens.push({ type: TokenType.Equals, text: "=", is_float: false, begin: start }) + ++pos + continue + case "-": + tokens.push({ type: TokenType.Minus, text: "-", is_float: false, begin: start }) + ++pos + continue + default: + break + } + + /// A dot may start a fractional number (.5) or be a standalone separator. + if (c === "." && !(pos + 1 < n && isDigit(input[pos + 1] as string))) { + tokens.push({ type: TokenType.Dot, text: ".", is_float: false, begin: start }) + ++pos + continue + } + + /// Quoted identifiers. + if (c === "`" || c === '"') { + const r = decodeQuoted(input, pos, c) + pos = r.pos + if (!r.ok) { + fail(start, r.error) + break + } + tokens.push({ type: TokenType.QuotedIdent, text: r.out, is_float: false, begin: start }) + continue + } + + /// String literal. + if (c === "'") { + const r = decodeQuoted(input, pos, c) + pos = r.pos + if (!r.ok) { + fail(start, r.error) + break + } + tokens.push({ type: TokenType.String, text: r.out, is_float: false, begin: start }) + continue + } + + /// Number. + if (isDigit(c) || c === ".") { + let is_float = false + /// integer part + while (pos < n && isDigit(input[pos] as string)) ++pos + /// fraction + if (pos < n && input[pos] === ".") { + is_float = true + ++pos + while (pos < n && isDigit(input[pos] as string)) ++pos + } + /// exponent + if (pos < n && (input[pos] === "e" || input[pos] === "E")) { + is_float = true + ++pos + if (pos < n && (input[pos] === "+" || input[pos] === "-")) ++pos + while (pos < n && isDigit(input[pos] as string)) ++pos + } + tokens.push({ type: TokenType.Number, text: input.substring(start, pos), is_float, begin: start }) + continue + } + + /// Bare word / identifier / keyword. + if (isWordFirst(c)) { + while (pos < n && isWordChar(input[pos] as string)) ++pos + tokens.push({ type: TokenType.Word, text: input.substring(start, pos), is_float: false, begin: start }) + continue + } + + fail(start, "unexpected character '" + c + "'") + break + } + + tokens.push({ type: TokenType.End, text: "", is_float: false, begin: pos }) + return tokens +} diff --git a/type-parser/mini-parser-ts/src/parser.ts b/type-parser/mini-parser-ts/src/parser.ts new file mode 100644 index 000000000..adcd9570a --- /dev/null +++ b/type-parser/mini-parser-ts/src/parser.ts @@ -0,0 +1,495 @@ +/// A faithful port of ClickHouse's `ParserDataType::parseImpl` +/// (src/Parsers/ParserDataType.cpp) onto the self-contained AST in `ast.ts`. +/// The control flow deliberately tracks the original: identifier + SQL-standard +/// multi-word aliases, the Enum and Tuple special cases, then the generic +/// parametric-argument loop. AggregateFunction/SimpleAggregateFunction and the +/// JSON object-argument syntax are reported as unsupported (see parser.h). +/// +/// This is the TypeScript port of the C++ `chdt/parser.cpp`. + +import { EnumValue, makeNode, Node, NodeKind } from "./ast.js" +import { Token, tokenize, TokenType } from "./lexer.js" + +/// Public entry point types (ported from parser.h). +export interface ParseError { + message: string /// human-readable description + position: number /// byte offset into the input where parsing stuck +} + +export interface ParseResult { + ast: Node | null /// non-null on success + error: ParseError | null /// set on failure + ok(): boolean +} + +function toUpper(s: string): string { + let r = "" + for (let i = 0; i < s.length; ++i) { + const c = s[i] as string + if (c >= "a" && c <= "z") + r += String.fromCharCode(c.charCodeAt(0) - "a".charCodeAt(0) + "A".charCodeAt(0)) + else + r += c + } + return r +} + +function toLower(s: string): string { + let r = "" + for (let i = 0; i < s.length; ++i) { + const c = s[i] as string + if (c >= "A" && c <= "Z") + r += String.fromCharCode(c.charCodeAt(0) - "A".charCodeAt(0) + "a".charCodeAt(0)) + else + r += c + } + return r +} + +function isWordCharOrDollar(c: string): boolean { + return (c >= "a" && c <= "z") || (c >= "A" && c <= "Z") || (c >= "0" && c <= "9") || c === "_" || c === "$" +} + +function isEnumTypeUpper(u: string): boolean { + return u === "ENUM" || u === "ENUM8" || u === "ENUM16" +} + +class Parser { + private tokens: Token[] + private pos = 0 + private hard_error: ParseError | null = null + + constructor(tokens: Token[]) { + this.tokens = tokens + } + + run(): ParseResult { + /// A lexing error surfaces as a trailing Error token. + for (const tok of this.tokens) + if (tok.type === TokenType.Error) + return Parser.fail(tok.begin, tok.text) + + const node = this.parseType() + if (!node) { + if (this.hard_error) + return makeResult(null, this.hard_error) + return Parser.fail(this.cur().begin, "expected a data type") + } + + if (this.cur().type !== TokenType.End) + return Parser.fail(this.cur().begin, "unexpected trailing input after the data type") + + return makeResult(node, null) + } + + private cur(): Token { + return this.tokens[this.pos] as Token + } + + private type(): TokenType { + return (this.tokens[this.pos] as Token).type + } + + private advance(): void { + if ((this.tokens[this.pos] as Token).type !== TokenType.End) + ++this.pos + } + + private static fail(at: number, msg: string): ParseResult { + return makeResult(null, { message: msg, position: at }) + } + + private setHardError(at: number, msg: string): void { + if (!this.hard_error) + this.hard_error = { message: msg, position: at } + } + + private isIdentifier(): boolean { + return this.type() === TokenType.Word || this.type() === TokenType.QuotedIdent + } + + /// Consume `count` consecutive Word tokens iff they match `words` + /// (case-insensitive). Returns the original-cased joined match or "". + private matchWords(words: string[]): boolean { + let p = this.pos + for (const w of words) { + const tok = this.tokens[p] as Token + if (tok.type !== TokenType.Word || toUpper(tok.text) !== toUpper(w)) + return false + ++p + } + this.pos = p + return true + } + + /// Read a single identifier (bare or quoted) into `name`. + private parseIdentifier(): { ok: boolean; name: string } { + if (!this.isIdentifier()) + return { ok: false, name: "" } + const name = this.cur().text + this.advance() + return { ok: true, name } + } + + private parseType(): Node | null { + const id = this.parseIdentifier() + if (!id.ok) + return null + let type_name = id.name + + /// Reject quoted garbage that cannot be a type name (e.g. `x.y`, `Null`). + { + let allWordChar = true + for (let i = 0; i < type_name.length; ++i) { + if (!isWordCharOrDollar(type_name[i] as string)) { + allWordChar = false + break + } + } + if (!allWordChar) + return null + } + + const type_name_upper = toUpper(type_name) + + /// Keywords that the column-declaration parser claims before the type. + if (type_name_upper === "NOT" || type_name_upper === "NULL" || type_name_upper === "DEFAULT" + || type_name_upper === "MATERIALIZED" || type_name_upper === "EPHEMERAL" || type_name_upper === "ALIAS" + || type_name_upper === "AUTO" || type_name_upper === "PRIMARY" || type_name_upper === "COMMENT" + || type_name_upper === "CODEC") + return null + + /// SQL-standard multi-word type names. + const suffix = this.parseTypeNameSuffix(type_name_upper) + if (suffix !== "") + type_name = type_name_upper + " " + suffix + + this.skipTrailingComma() + + /// Enum special case -> EnumDataType with explicit values. + if (isEnumTypeUpper(type_name_upper) && this.type() === TokenType.OpeningParen) { + const saved = this.pos + this.advance() + const values: EnumValue[] = [] + if (this.parseEnumValues(values) && this.type() === TokenType.ClosingParen) { + this.advance() + const node = makeNode(NodeKind.EnumDataType) + node.name = type_name + node.values = values + return node + } + this.pos = saved + } + + /// Tuple special case -> TupleDataType with optional element names. + if (type_name === "Tuple" && this.type() === TokenType.OpeningParen) { + const tuple = this.parseTuple(type_name) + if (tuple) + return tuple + /// else: fall through to the generic path + } + + const node = makeNode(NodeKind.DataType) + node.name = type_name + + if (this.type() !== TokenType.OpeningParen) + return node + this.advance() + + if (!this.parseArgumentList(type_name, node.arguments)) + return null + + if (this.type() !== TokenType.ClosingParen) + return null + this.advance() + + node.has_argument_list = true + return node + } + + /// Returns the suffix to append for SQL-standard multi-word names, or "". + private parseTypeNameSuffix(u: string): string { + if (u === "NATIONAL") { + if (this.matchWords(["CHARACTER", "LARGE", "OBJECT"])) return "CHARACTER LARGE OBJECT" + if (this.matchWords(["CHARACTER", "VARYING"])) return "CHARACTER VARYING" + if (this.matchWords(["CHAR", "VARYING"])) return "CHAR VARYING" + if (this.matchWords(["CHARACTER"])) return "CHARACTER" + if (this.matchWords(["CHAR"])) return "CHAR" + } else if (u === "BINARY" || u === "CHARACTER" || u === "CHAR" || u === "NCHAR") { + if (this.matchWords(["LARGE", "OBJECT"])) return "LARGE OBJECT" + if (this.matchWords(["VARYING"])) return "VARYING" + } else if (u === "DOUBLE") { + if (this.matchWords(["PRECISION"])) return "PRECISION" + } else if (u.indexOf("INT") !== -1) { + /// MySQL-compatible SIGNED / UNSIGNED, optionally after `(width)`. + if (this.matchWords(["SIGNED"])) return "SIGNED" + if (this.matchWords(["UNSIGNED"])) return "UNSIGNED" + if (this.type() === TokenType.OpeningParen) { + const saved = this.pos + this.advance() + if (this.type() === TokenType.Number) + this.advance() + if (this.type() === TokenType.ClosingParen) { + this.advance() + if (this.matchWords(["SIGNED"])) return "SIGNED" + if (this.matchWords(["UNSIGNED"])) return "UNSIGNED" + } else { + /// not the width form; leave the paren for generic args + this.pos = saved + } + } + } + return "" + } + + /// Skip a trailing comma right before a closing paren: `Tuple(Int, String,)`. + private skipTrailingComma(): void { + if (this.type() === TokenType.Comma && (this.tokens[this.pos + 1] as Token).type === TokenType.ClosingParen) + this.advance() + } + + /// Explicit-only enum body: 'name' = value, ... . Returns false (caller + /// restores) for auto-assigned or otherwise non-trivial enums. + private parseEnumValues(values: EnumValue[]): boolean { + let first = true + while (true) { + if (!first) { + if (this.type() !== TokenType.Comma) + break + this.advance() + } + first = false + + if (this.type() !== TokenType.String) + return false + const name = this.cur().text + this.advance() + + if (this.type() !== TokenType.Equals) + return false + this.advance() + + let negative = false + if (this.type() === TokenType.Minus) { + negative = true + this.advance() + } + + if (this.type() !== TokenType.Number || this.cur().is_float) + return false + const v = BigInt(this.cur().text) + this.advance() + + values.push({ name, value: negative ? -v : v }) + } + return values.length !== 0 + } + + /// Parse a Tuple body into element types + names. Returns null (with the + /// position restored) if it cannot, so the caller can try the generic path. + private parseTuple(type_name: string): Node | null { + const saved = this.pos + this.advance() /// consume '(' + + const node = makeNode(NodeKind.TupleDataType) + node.name = type_name + + const names: string[] = [] + let has_named = false + let first = true + + while (true) { + if (!first) { + if (this.type() === TokenType.Comma) + this.advance() + else + break + } + first = false + + const element_pos = this.pos + /// Try: identifier Type (named element) + const id = this.parseIdentifier() + if (id.ok) { + const t = this.parseType() + if (t) { + names.push(id.name) + node.arguments.push(t) + has_named = true + continue + } + } + /// Else: just Type (unnamed element) + this.pos = element_pos + const t = this.parseType() + if (t) { + names.push("") + node.arguments.push(t) + } else { + break + } + } + + if (this.type() === TokenType.ClosingParen && node.arguments.length !== 0) { + this.advance() + node.has_argument_list = true + if (has_named) + node.element_names = names + return node + } + + this.pos = saved + return null + } + + /// The generic comma-separated argument list inside `Type(...)`. + private parseArgumentList(type_name: string, out: Node[]): boolean { + const lower = toLower(type_name) + + if (type_name === "AggregateFunction" || type_name === "SimpleAggregateFunction") { + this.setHardError(this.cur().begin, type_name + " is not supported by this parser yet") + return false + } + if (lower === "json") { + this.setHardError(this.cur().begin, "JSON typed/object arguments are not supported by this parser yet") + return false + } + + let arg_num = 0 + while (true) { + if (arg_num > 0) { + if (this.type() === TokenType.Comma) + this.advance() + else + break + } + + let arg: Node | null + if (type_name === "Dynamic") + arg = this.parseEqualsArgument() + else if (type_name === "Nested") + arg = this.parseNameTypePair() + else if (type_name === "Tuple") + arg = this.parseNameTypePairOrType() + else + arg = this.parseGenericArgument() + + if (!arg) + break + + out.push(arg) + ++arg_num + } + return true + } + + /// `identifier = number` -> Function equals(Identifier, Literal). + private parseEqualsArgument(): Node | null { + const id = this.parseIdentifier() + if (!id.ok) + return null + if (this.type() !== TokenType.Equals) + return null + this.advance() + const number = this.parseNumberLiteral() + if (!number) + return null + + const idNode = makeNode(NodeKind.Identifier) + idNode.name = id.name + const fn = makeNode(NodeKind.Function) + fn.name = "equals" + fn.is_operator = true + fn.arguments = [idNode, number] + return fn + } + + /// `name Type` -> NameTypePair (Nested elements). + private parseNameTypePair(): Node | null { + const id = this.parseIdentifier() + if (!id.ok) + return null + const t = this.parseType() + if (!t) + return null + const node = makeNode(NodeKind.NameTypePair) + node.name = id.name + node.data_type = t + return node + } + + private parseNameTypePairOrType(): Node | null { + const saved = this.pos + const pair = this.parseNameTypePair() + if (pair) + return pair + this.pos = saved + return this.parseType() + } + + /// Generic argument: a scalar literal (optionally `lit = lit`), or a type. + private parseGenericArgument(): Node | null { + const lit = this.parseScalarLiteral() + if (lit) { + if (this.type() === TokenType.Equals) { + this.advance() + const rhs = this.parseScalarLiteral() + if (!rhs) + return null + const fn = makeNode(NodeKind.Function) + fn.name = "equals" + fn.is_operator = true + fn.arguments = [lit, rhs] + return fn + } + return lit + } + return this.parseType() + } + + private parseNumberLiteral(): Node | null { + let negative = false + if (this.type() === TokenType.Minus) { + negative = true + this.advance() + } + if (this.type() !== TokenType.Number) + return null + const node = makeNode(NodeKind.Literal) + node.value_type = this.cur().is_float ? "Float64" : (negative ? "Int64" : "UInt64") + node.value = (negative ? "-" : "") + this.cur().text + this.advance() + return node + } + + /// A scalar literal: number (optionally signed) or string. + private parseScalarLiteral(): Node | null { + if (this.type() === TokenType.Number || this.type() === TokenType.Minus) + return this.parseNumberLiteral() + if (this.type() === TokenType.String) { + const node = makeNode(NodeKind.Literal) + node.value_type = "String" + node.value = this.cur().text + this.advance() + return node + } + return null + } +} + +function makeResult(ast: Node | null, error: ParseError | null): ParseResult { + return { + ast, + error, + ok(): boolean { + return this.ast !== null + }, + } +} + +/// Parse the whole string as a single data type. Trailing tokens after a +/// complete type are an error (the entire input must be one type). +export function parseDataType(input: string): ParseResult { + const parser = new Parser(tokenize(input)) + return parser.run() +} diff --git a/type-parser/mini-parser-ts/test/cases.ts b/type-parser/mini-parser-ts/test/cases.ts new file mode 100644 index 000000000..00bd70c76 --- /dev/null +++ b/type-parser/mini-parser-ts/test/cases.ts @@ -0,0 +1,31 @@ +/// Shared helpers for the oracle / unsupported test harnesses. + +import { readFileSync } from "node:fs"; + +/// Read a cases file: one type per line, blank lines and #-comments ignored. +export function readCases(path: string): string[] { + const cases: string[] = []; + for (const raw of readFileSync(path, "utf8").split("\n")) { + const line = raw.trim(); + if (line && !line.startsWith("#")) cases.push(line); + } + return cases; +} + +/// Recursively sort object keys so comparison ignores key order (mirrors the +/// Python oracle's `canon`). +export function canon(value: unknown): unknown { + if (Array.isArray(value)) return value.map(canon); + if (value !== null && typeof value === "object") { + const out: Record = {}; + for (const k of Object.keys(value as Record).sort()) { + out[k] = canon((value as Record)[k]); + } + return out; + } + return value; +} + +export function deepEqual(a: unknown, b: unknown): boolean { + return JSON.stringify(canon(a)) === JSON.stringify(canon(b)); +} diff --git a/type-parser/mini-parser-ts/test/cases.txt b/type-parser/mini-parser-ts/test/cases.txt new file mode 100644 index 000000000..37844c31f --- /dev/null +++ b/type-parser/mini-parser-ts/test/cases.txt @@ -0,0 +1,72 @@ +# Supported data types, one per line. Each is compared against the +# data_type subtree the ClickHouse server emits for +# EXPLAIN AST json = 1 CREATE TABLE t (c ) ENGINE = Null +# Blank lines and #-comments are ignored. + +# scalars +UInt8 +Int64 +Float64 +String +Date +DateTime +UUID +Bool +IPv4 +IPv6 + +# parametric with literal args +FixedString(16) +Decimal(10, 2) +Decimal(38, 10) +Decimal32(4) +DateTime64(3) +DateTime64(3, 'UTC') +DateTime('UTC') + +# nested type args +Nullable(UInt64) +Array(String) +Array(Array(Int32)) +Array(Nullable(UInt64)) +Map(String, UInt64) +Map(String, Array(UInt8)) +LowCardinality(String) +LowCardinality(Nullable(String)) +Array(Tuple(Float64, Float64)) + +# tuples +Tuple(UInt8, String) +Tuple(a UInt8, b String) +Tuple(a UInt8, String) +Tuple(Decimal(10, 2), Nullable(String)) + +# enums (explicit -> EnumDataType; auto-assigned -> generic DataType) +Enum8('a' = 1, 'b' = 2) +Enum16('x' = -1, 'y' = 100) +Enum('a' = 1, 'b' = 2) +Enum8('a', 'b') + +# nested table type +Nested(a UInt8, b String) +Nested(a Array(UInt8), b Tuple(x UInt8, y String)) + +# SQL-standard multi-word aliases +DOUBLE PRECISION +CHAR VARYING +INT SIGNED +INT UNSIGNED + +# legacy object + dynamic +Object('json') +Dynamic +Dynamic(max_types = 5) + +# misc families harvested from the fixture corpus +Variant(UInt8, String) +varchar +varchar(255) +BFloat16 +Time +int +Int diff --git a/type-parser/mini-parser-ts/test/cases_unsupported.txt b/type-parser/mini-parser-ts/test/cases_unsupported.txt new file mode 100644 index 000000000..cf6064272 --- /dev/null +++ b/type-parser/mini-parser-ts/test/cases_unsupported.txt @@ -0,0 +1,7 @@ +# Types that the parser deliberately rejects (see parser.h). Each must make +# chdt-parse exit non-zero. Blank lines and #-comments are ignored. +AggregateFunction(sum, UInt64) +AggregateFunction(1, quantiles(0.5), Float64) +SimpleAggregateFunction(sum, UInt64) +JSON(max_dynamic_paths = 16) +JSON(a.b UInt32, SKIP x) diff --git a/type-parser/mini-parser-ts/test/check_unsupported.ts b/type-parser/mini-parser-ts/test/check_unsupported.ts new file mode 100644 index 000000000..891ac9201 --- /dev/null +++ b/type-parser/mini-parser-ts/test/check_unsupported.ts @@ -0,0 +1,37 @@ +#!/usr/bin/env node +/// Assert that the parser rejects the deliberately-unsupported types. +/// A TypeScript port of the Python `check_unsupported.py`. +/// +/// Usage: tsx test/check_unsupported.ts [--cases test/cases_unsupported.txt] + +import { fileURLToPath } from "node:url"; +import { dirname, join } from "node:path"; + +import { parseDataType } from "../src/index.js"; +import { readCases } from "./cases.js"; + +const here = dirname(fileURLToPath(import.meta.url)); + +function main(): number { + const argv = process.argv.slice(2); + let casesPath = join(here, "cases_unsupported.txt"); + for (let i = 0; i < argv.length; i++) { + if (argv[i] === "--cases") casesPath = argv[++i] ?? casesPath; + } + + const cases = readCases(casesPath); + let failures = 0; + for (const typeStr of cases) { + if (!parseDataType(typeStr).ok()) { + console.log(` ok rejected: ${typeStr}`); + } else { + failures++; + console.log(`FAIL unexpectedly accepted: ${typeStr}`); + } + } + + console.log(`\n${cases.length - failures}/${cases.length} correctly rejected`); + return failures ? 1 : 0; +} + +process.exit(main()); diff --git a/type-parser/mini-parser-ts/test/oracle_compare.ts b/type-parser/mini-parser-ts/test/oracle_compare.ts new file mode 100644 index 000000000..9879569fd --- /dev/null +++ b/type-parser/mini-parser-ts/test/oracle_compare.ts @@ -0,0 +1,121 @@ +#!/usr/bin/env node +/// Compare the standalone parser's JSON AST against the ClickHouse server. +/// +/// For each data type in the cases file, the expected output is the `data_type` +/// subtree the server produces for +/// +/// EXPLAIN AST json = 1 CREATE TABLE t (c ) ENGINE = Null +/// +/// (version 2 of the format). The actual output is what `parseDataType` + +/// `toJSON` produce. The two JSON trees are compared structurally (key order +/// ignored). A TypeScript port of the Python `oracle_compare.py`. +/// +/// Usage: +/// tsx test/oracle_compare.ts --clickhouse /path/to/clickhouse [--cases test/cases.txt] +/// +/// The clickhouse binary must be built from +/// https://github.com/peter-leonov-ch/ClickHouse/pull/1 (the AST-format changes +/// this parser mirrors live in that PR). + +import { spawnSync } from "node:child_process"; +import { fileURLToPath } from "node:url"; +import { dirname, join } from "node:path"; + +import { parseDataType, toJSON } from "../src/index.js"; +import { canon, deepEqual, readCases } from "./cases.js"; + +const here = dirname(fileURLToPath(import.meta.url)); + +function parseArgs(argv: string[]): { clickhouse: string; cases: string } { + let clickhouse = ""; + let cases = join(here, "cases.txt"); + for (let i = 0; i < argv.length; i++) { + if (argv[i] === "--clickhouse") clickhouse = argv[++i] ?? ""; + else if (argv[i] === "--cases") cases = argv[++i] ?? cases; + } + if (!clickhouse) { + console.error("error: --clickhouse is required"); + process.exit(2); + } + return { clickhouse, cases }; +} + +/// Depth-first search for the ColumnDeclaration named `column`. +function findColumnDataType(node: unknown, column: string): unknown { + if (Array.isArray(node)) { + for (const v of node) { + const found = findColumnDataType(v, column); + if (found !== undefined) return found; + } + } else if (node !== null && typeof node === "object") { + const obj = node as Record; + if (obj["type"] === "ColumnDeclaration" && obj["name"] === column) { + return obj["data_type"]; + } + for (const v of Object.values(obj)) { + const found = findColumnDataType(v, column); + if (found !== undefined) return found; + } + } + return undefined; +} + +function serverDataType(clickhouse: string, typeStr: string): unknown { + const sql = `EXPLAIN AST json = 1 CREATE TABLE t (c ${typeStr}) ENGINE = Null`; + const out = spawnSync(clickhouse, ["local", "--format", "TSVRaw", "-q", sql], { + encoding: "utf8", + }); + if (out.status !== 0) { + throw new Error(`server failed: ${(out.stderr ?? "").trim()}`); + } + const doc = JSON.parse(out.stdout) as { version?: number; ast: unknown }; + if (doc.version !== 2) { + throw new Error(`unexpected format version ${doc.version}`); + } + const dt = findColumnDataType(doc.ast, "c"); + if (dt === undefined) { + throw new Error("could not locate column data_type in server AST"); + } + return dt; +} + +function toolDataType(typeStr: string): unknown { + const result = parseDataType(typeStr); + if (!result.ok()) { + throw new Error(`parse failed: ${result.error!.message}`); + } + return JSON.parse(toJSON(result.ast!)); +} + +function main(): number { + const { clickhouse, cases: casesPath } = parseArgs(process.argv.slice(2)); + const cases = readCases(casesPath); + let failures = 0; + + for (const typeStr of cases) { + let expected: unknown; + let actual: unknown; + try { + expected = canon(serverDataType(clickhouse, typeStr)); + actual = canon(toolDataType(typeStr)); + } catch (exc) { + console.log(`ERROR ${JSON.stringify(typeStr)}: ${(exc as Error).message}`); + failures++; + continue; + } + + if (deepEqual(expected, actual)) { + console.log(` ok ${typeStr}`); + } else { + failures++; + console.log(`FAIL ${typeStr}`); + console.log(" expected:", JSON.stringify(expected)); + console.log(" actual: ", JSON.stringify(actual)); + } + } + + console.log(`\n${cases.length - failures}/${cases.length} passed`); + return failures ? 1 : 0; +} + +process.exit(main()); diff --git a/type-parser/mini-parser-ts/test/parser.test.ts b/type-parser/mini-parser-ts/test/parser.test.ts new file mode 100644 index 000000000..123d65c82 --- /dev/null +++ b/type-parser/mini-parser-ts/test/parser.test.ts @@ -0,0 +1,122 @@ +/// Dependency-free unit tests (no ClickHouse binary required). +/// Run with: npm test (node --import tsx --test test/*.test.ts) +/// +/// The exhaustive server-equivalence check lives in oracle_compare.ts; these +/// pin a few representative shapes and all the deliberate rejections so `npm +/// test` is meaningful on its own. + +import { strict as assert } from "node:assert"; +import { test } from "node:test"; +import { fileURLToPath } from "node:url"; +import { dirname, join } from "node:path"; + +import { parseDataType, toJSON } from "../src/index.js"; +import { readCases } from "./cases.js"; + +const here = dirname(fileURLToPath(import.meta.url)); + +function json(typeStr: string): unknown { + const r = parseDataType(typeStr); + assert.ok(r.ok(), `expected ${typeStr} to parse: ${r.error?.message}`); + return JSON.parse(toJSON(r.ast!)); +} + +test("scalar type omits the arguments slot", () => { + assert.deepEqual(json("UInt8"), { type: "DataType", name: "UInt8" }); +}); + +test("nested parametric type", () => { + assert.deepEqual(json("Array(Nullable(UInt64))"), { + type: "DataType", + name: "Array", + arguments: [ + { type: "DataType", name: "Nullable", arguments: [{ type: "DataType", name: "UInt64" }] }, + ], + }); +}); + +test("literal arguments: 64-bit ints are JSON strings, scale is a string too", () => { + assert.deepEqual(json("Decimal(10, 2)"), { + type: "DataType", + name: "Decimal", + arguments: [ + { type: "Literal", value_type: "UInt64", value: "10" }, + { type: "Literal", value_type: "UInt64", value: "2" }, + ], + }); +}); + +test("explicit enum becomes EnumDataType with numeric values", () => { + assert.deepEqual(json("Enum16('x' = -1, 'y' = 100)"), { + type: "EnumDataType", + name: "Enum16", + values: [ + { name: "x", value: -1 }, + { name: "y", value: 100 }, + ], + }); +}); + +test("auto-assigned enum falls back to a generic DataType (not EnumDataType)", () => { + const v = json("Enum8('a', 'b')") as { type: string }; + assert.equal(v.type, "DataType"); +}); + +test("named tuple carries element_names", () => { + assert.deepEqual(json("Tuple(a UInt8, b String)"), { + type: "TupleDataType", + name: "Tuple", + arguments: [ + { type: "DataType", name: "UInt8" }, + { type: "DataType", name: "String" }, + ], + element_names: ["a", "b"], + }); +}); + +test("unnamed tuple omits element_names", () => { + const v = json("Tuple(UInt8, String)") as Record; + assert.equal("element_names" in v, false); +}); + +test("Dynamic(max_types = 5) parses to an equals Function argument", () => { + assert.deepEqual(json("Dynamic(max_types = 5)"), { + type: "DataType", + name: "Dynamic", + arguments: [ + { + type: "Function", + name: "equals", + is_operator: true, + arguments: [ + { type: "Identifier", name: "max_types" }, + { type: "Literal", value_type: "UInt64", value: "5" }, + ], + }, + ], + }); +}); + +test("SQL-standard multi-word alias", () => { + assert.deepEqual(json("DOUBLE PRECISION"), { type: "DataType", name: "DOUBLE PRECISION" }); +}); + +test("compact output has no whitespace", () => { + const r = parseDataType("Array(String)"); + assert.ok(r.ok()); + assert.equal(toJSON(r.ast!, -1), '{"type":"DataType","name":"Array","arguments":[{"type":"DataType","name":"String"}]}'); +}); + +test("deliberately-unsupported types are rejected with a hard error", () => { + for (const typeStr of readCases(join(here, "cases_unsupported.txt"))) { + const r = parseDataType(typeStr); + assert.equal(r.ok(), false, `expected ${typeStr} to be rejected`); + assert.ok(r.error && r.error.message.length > 0); + } +}); + +test("trailing input after a complete type is an error", () => { + const r = parseDataType("UInt8 garbage"); + assert.equal(r.ok(), false); + assert.match(r.error!.message, /trailing input/); +}); diff --git a/type-parser/mini-parser-ts/tool/main.ts b/type-parser/mini-parser-ts/tool/main.ts new file mode 100644 index 000000000..3453bc7b4 --- /dev/null +++ b/type-parser/mini-parser-ts/tool/main.ts @@ -0,0 +1,47 @@ +#!/usr/bin/env node +/// chdt-parse: read a ClickHouse data-type string and print its JSON AST. +/// +/// chdt-parse "Array(Nullable(UInt64))" # type from arguments +/// echo "Tuple(a UInt8, b String)" | chdt-parse # type from stdin +/// +/// Prints the JSON AST and exits 0 on success. On a parse error, prints +/// "error: (at byte N)" to stderr and exits 1. +/// +/// A TypeScript port of the C++ `tool/main.cpp`. + +import { readFileSync } from "node:fs"; + +import { parseDataType, toJSON } from "../src/index.js"; + +function readStdin(): string { + try { + /// fd 0 = stdin. Read synchronously so the CLI behaves like the C++ one. + return readFileSync(0, "utf8"); + } catch { + return ""; + } +} + +function main(argv: string[]): number { + let input: string; + if (argv.length > 0) { + input = argv.join(" "); + } else { + input = readStdin(); + } + + /// Trim trailing newline/whitespace from stdin. + input = input.replace(/[\n\r \t]+$/, ""); + + const result = parseDataType(input); + if (!result.ok()) { + const err = result.error!; + process.stderr.write(`error: ${err.message} (at byte ${err.position})\n`); + return 1; + } + + process.stdout.write(toJSON(result.ast!) + "\n"); + return 0; +} + +process.exit(main(process.argv.slice(2))); diff --git a/type-parser/mini-parser-ts/tsconfig.json b/type-parser/mini-parser-ts/tsconfig.json new file mode 100644 index 000000000..eb23792e0 --- /dev/null +++ b/type-parser/mini-parser-ts/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "NodeNext", + "moduleResolution": "NodeNext", + "lib": ["ES2022"], + "declaration": true, + "outDir": "dist", + "rootDir": ".", + "strict": true, + "noUncheckedIndexedAccess": true, + "noImplicitOverride": true, + "noFallthroughCasesInSwitch": true, + "forceConsistentCasingInFileNames": true, + "esModuleInterop": true, + "skipLibCheck": true + }, + "include": ["src/**/*.ts", "tool/**/*.ts", "test/**/*.ts"] +} From 508176b170110bded9c8f53a7b2d8b79d5d32b76 Mon Sep 17 00:00:00 2001 From: Peter Leonov Date: Wed, 24 Jun 2026 19:21:33 +0200 Subject: [PATCH 5/9] test(mini-parser-ts): add a server-snapshot test corpus Grow test/cases.txt to 356 ClickHouse data types (scalars, parametric, deeply nested, enums, tuples, SQL/MySQL aliases, geo, interval, ...) and capture the server's data_type AST for each as a static snapshot under test/snapshots/ (one .json per query). The snapshot test then runs with no clickhouse binary, so `npm test` is fully self-contained. A snapshot is only written when the server accepts the type AND the parser matches it, so "parser == snapshot" means "parser == server". All 356 pass. Tooling: - update_snapshots.ts (npm run snapshot:update -- --clickhouse ): validates cases.txt + candidates.txt against the server, keeps only matching types, appends new keepers to cases.txt, writes/prunes snapshots, and reports rejected/divergent types. - oracle.ts: shared server-query + parser helpers, refactored out of oracle_compare.ts. - snapshot.test.ts: the CLI-free comparison against the static snapshots. - candidates.txt: the generated seed list of candidate types. Also seeds validate_types_live.ts, a live type-instantiation sanity check (refined in the follow-up commit). Co-Authored-By: Claude Opus 4.8 (1M context) --- type-parser/mini-parser-ts/.gitignore | 1 + type-parser/mini-parser-ts/README.md | 46 +- type-parser/mini-parser-ts/package.json | 3 +- .../mini-parser-ts/test/candidates.txt | 401 ++++++++++++++++++ type-parser/mini-parser-ts/test/cases.txt | 308 ++++++++++++++ type-parser/mini-parser-ts/test/oracle.ts | 60 +++ .../mini-parser-ts/test/oracle_compare.ts | 50 +-- .../mini-parser-ts/test/snapshot.test.ts | 40 ++ type-parser/mini-parser-ts/test/snapshots.ts | 30 ++ .../test/snapshots/00b95dd2fc4a3cb1.json | 53 +++ .../test/snapshots/00ce7d22d518eb3d.json | 19 + .../test/snapshots/01dc6abd5a2822d1.json | 55 +++ .../test/snapshots/0282a2e2726b5fdb.json | 7 + .../test/snapshots/02bdf07c09cc39a9.json | 31 ++ .../test/snapshots/03f2221a84fa9cb6.json | 14 + .../test/snapshots/05b87974a3b9b844.json | 49 +++ .../test/snapshots/06083c5d1e0fb4b0.json | 55 +++ .../test/snapshots/0630ca3355f050df.json | 19 + .../test/snapshots/069c4db0034b51e1.json | 35 ++ .../test/snapshots/07a4cee5695b7794.json | 13 + .../test/snapshots/07a608893061fe06.json | 21 + .../test/snapshots/08512f086f95145c.json | 14 + .../test/snapshots/097274c5c7abaa17.json | 7 + .../test/snapshots/0a450823c46ccbe3.json | 19 + .../test/snapshots/0aeb95282860cfdf.json | 25 ++ .../test/snapshots/0bed42cd6332cc16.json | 14 + .../test/snapshots/0db54c89682d17c4.json | 7 + .../test/snapshots/0dc646c154d2103e.json | 19 + .../test/snapshots/0ee669b87ea0b36a.json | 23 + .../test/snapshots/0ef4e25fc70c78ee.json | 13 + .../test/snapshots/0f07cff3e8006379.json | 14 + .../test/snapshots/0fe37e40e5dab3ac.json | 7 + .../test/snapshots/10997dcfa0b17169.json | 13 + .../test/snapshots/11d240952f22547e.json | 20 + .../test/snapshots/1269b7d5dc9faecd.json | 13 + .../test/snapshots/128519da85d4b5b8.json | 25 ++ .../test/snapshots/133ca8ecd29f3663.json | 14 + .../test/snapshots/156e367c7969e103.json | 14 + .../test/snapshots/15ac3a2fa148ab10.json | 17 + .../test/snapshots/16b2e8523343d5f3.json | 13 + .../test/snapshots/16d4d882e66fffc1.json | 19 + .../test/snapshots/174711b74c597654.json | 17 + .../test/snapshots/1800cfa6f2c5cb5c.json | 14 + .../test/snapshots/180fcbe698d0f2c4.json | 7 + .../test/snapshots/183de27e0bac77a1.json | 25 ++ .../test/snapshots/19c537c1c1730b4d.json | 13 + .../test/snapshots/19e4439f2f9c5c0d.json | 7 + .../test/snapshots/1a8c9516519ad655.json | 19 + .../test/snapshots/1ab3503a837a8b33.json | 19 + .../test/snapshots/1af429358d8dc4cc.json | 13 + .../test/snapshots/1b1855ddfe121c06.json | 13 + .../test/snapshots/1bd2dfcbd0545dd9.json | 17 + .../test/snapshots/1c0e4bc11b79399b.json | 14 + .../test/snapshots/1c6d137de6e9cce4.json | 14 + .../test/snapshots/1ce04f29dadb9973.json | 7 + .../test/snapshots/1d0146114b4a4362.json | 19 + .../test/snapshots/1d2e38577d2a158e.json | 19 + .../test/snapshots/1dc79a25ff699c42.json | 23 + .../test/snapshots/1e16f998c6447325.json | 21 + .../test/snapshots/20fd836cdfc11886.json | 19 + .../test/snapshots/21bf75a5255af008.json | 7 + .../test/snapshots/2208b0f5d5d2aea7.json | 7 + .../test/snapshots/22aaa82db55ed6cb.json | 13 + .../test/snapshots/22ecac851cfb07e9.json | 23 + .../test/snapshots/23b36b23f947874d.json | 19 + .../test/snapshots/2451237b00b13cd7.json | 19 + .../test/snapshots/261b6d70eaf74bf4.json | 7 + .../test/snapshots/26b32b5b966f2a05.json | 7 + .../test/snapshots/283e861dc1341e3c.json | 13 + .../test/snapshots/292209387fe87cb3.json | 20 + .../test/snapshots/292c7af4fff95bcd.json | 7 + .../test/snapshots/2a2dd538a651992b.json | 24 ++ .../test/snapshots/2a93a144ad9458ad.json | 14 + .../test/snapshots/2b759bb1ca791e18.json | 25 ++ .../test/snapshots/2b92c8c85daf51e6.json | 14 + .../test/snapshots/2bb1b10e295da6ba.json | 33 ++ .../test/snapshots/2cad1f5221666485.json | 20 + .../test/snapshots/2d0fe684054a5388.json | 7 + .../test/snapshots/2d50b2d54d49e844.json | 43 ++ .../test/snapshots/2ecf89a293cd698f.json | 23 + .../test/snapshots/2f058b0d7c8ff211.json | 21 + .../test/snapshots/2f446fedbc924375.json | 7 + .../test/snapshots/2f76fee2db93cfc2.json | 13 + .../test/snapshots/2ffb7489d68e87c9.json | 14 + .../test/snapshots/30a77c9b71a45749.json | 19 + .../test/snapshots/314040aa10c72b02.json | 17 + .../test/snapshots/33888e8184bce3d1.json | 7 + .../test/snapshots/343587b20a4bf691.json | 7 + .../test/snapshots/35d5fb175bed4093.json | 13 + .../test/snapshots/36af8609901f12c8.json | 7 + .../test/snapshots/36c3682fea89a80a.json | 19 + .../test/snapshots/3720deb1bdd5e553.json | 20 + .../test/snapshots/387bc74e5d2ed508.json | 13 + .../test/snapshots/388c0a082cfd7817.json | 37 ++ .../test/snapshots/3967d5ba8569635b.json | 19 + .../test/snapshots/3a8bb11d808ae810.json | 14 + .../test/snapshots/3ae9dd8952516f33.json | 14 + .../test/snapshots/3b330731a188b19f.json | 7 + .../test/snapshots/3b7f131c8d41638e.json | 13 + .../test/snapshots/3badd67bde55d4f2.json | 49 +++ .../test/snapshots/3c4d1905119c3883.json | 14 + .../test/snapshots/3ce40017fe0513c0.json | 51 +++ .../test/snapshots/3d0564f65e2951d7.json | 39 ++ .../test/snapshots/3d40c376159dc070.json | 26 ++ .../test/snapshots/3df63b7acb0522da.json | 7 + .../test/snapshots/3e2d739f398d42c7.json | 21 + .../test/snapshots/3eb94c999f391ca9.json | 14 + .../test/snapshots/401053f5f7236705.json | 13 + .../test/snapshots/406c62c428cea57a.json | 20 + .../test/snapshots/435de109befc994a.json | 20 + .../test/snapshots/44af40134bf9392d.json | 14 + .../test/snapshots/44b693037c5f8e61.json | 25 ++ .../test/snapshots/454656691c92b81b.json | 14 + .../test/snapshots/45e2c84f9ca77549.json | 19 + .../test/snapshots/46e27f45db2bf7c7.json | 33 ++ .../test/snapshots/46f8ab7c0cff9df7.json | 7 + .../test/snapshots/4736033ecebeb570.json | 19 + .../test/snapshots/49101d78947d3702.json | 14 + .../test/snapshots/49279edf04879138.json | 7 + .../test/snapshots/49718b649da090b8.json | 23 + .../test/snapshots/49f72ed44502ec22.json | 37 ++ .../test/snapshots/4b1c0b5b55c6eeae.json | 25 ++ .../test/snapshots/4b2e0d29c996e5d4.json | 14 + .../test/snapshots/4c5840cb7dad0940.json | 31 ++ .../test/snapshots/4c7aa27b65521bcf.json | 14 + .../test/snapshots/4d0c622ecdd58854.json | 35 ++ .../test/snapshots/4dc8e18720867887.json | 21 + .../test/snapshots/4e5e15828b576fc3.json | 62 +++ .../test/snapshots/4f2b2ad192957150.json | 19 + .../test/snapshots/4fe5a3682f802978.json | 7 + .../test/snapshots/501529315784089e.json | 13 + .../test/snapshots/503d0c06e75dd73f.json | 13 + .../test/snapshots/50876ef35975fe08.json | 7 + .../test/snapshots/508ec6552e77fe7d.json | 26 ++ .../test/snapshots/5094f81299f4d418.json | 14 + .../test/snapshots/51b1bf12f2eef86f.json | 14 + .../test/snapshots/51db33fb52b4c790.json | 7 + .../test/snapshots/52708f106b39ca6d.json | 13 + .../test/snapshots/54b047d7967410c4.json | 25 ++ .../test/snapshots/55042c80818a5432.json | 7 + .../test/snapshots/55c5d81017a30edf.json | 7 + .../test/snapshots/5913df984e01b049.json | 13 + .../test/snapshots/5a84a5824366cfdf.json | 14 + .../test/snapshots/5bee16b592d3087c.json | 26 ++ .../test/snapshots/5c52b39b56c50f56.json | 7 + .../test/snapshots/5c89edcac2811a6a.json | 7 + .../test/snapshots/5e990ab2800482f2.json | 14 + .../test/snapshots/6000a28977e029d9.json | 45 ++ .../test/snapshots/620e6c17af0fec3f.json | 17 + .../test/snapshots/625a100e21847dcf.json | 13 + .../test/snapshots/63a53953382e5a76.json | 21 + .../test/snapshots/64269f9bd268bf28.json | 7 + .../test/snapshots/648be8a9b20b4068.json | 13 + .../test/snapshots/64edc28811344047.json | 13 + .../test/snapshots/6529f695ef6bea2b.json | 7 + .../test/snapshots/65d2d849e33bbb9f.json | 19 + .../test/snapshots/663699edbe8d32d0.json | 14 + .../test/snapshots/663ad5af89c48643.json | 37 ++ .../test/snapshots/66c7fbd08eb194f8.json | 17 + .../test/snapshots/6760521bb1b6d98f.json | 13 + .../test/snapshots/67ab5f4c86e061d7.json | 19 + .../test/snapshots/6932c015a8c3a3ef.json | 56 +++ .../test/snapshots/69a99906f5a06ea1.json | 7 + .../test/snapshots/69ddba4964a41534.json | 17 + .../test/snapshots/6b09d0c1e764f23a.json | 19 + .../test/snapshots/6c43115b5c24bfa0.json | 25 ++ .../test/snapshots/6c82e6dd86807ee3.json | 7 + .../test/snapshots/6ddeb86eb863afac.json | 63 +++ .../test/snapshots/6e25d9b9f79612fd.json | 55 +++ .../test/snapshots/6e53b6c5a0f31021.json | 19 + .../test/snapshots/6e5f2d68fd260298.json | 35 ++ .../test/snapshots/6e823ebb2984559d.json | 13 + .../test/snapshots/6e85b5501433e087.json | 58 +++ .../test/snapshots/6f2851997db0584b.json | 13 + .../test/snapshots/707890c2d6dfa724.json | 31 ++ .../test/snapshots/707ef63b9e074824.json | 21 + .../test/snapshots/70b4bb2684c3f896.json | 7 + .../test/snapshots/710d7120fc63672d.json | 29 ++ .../test/snapshots/711cbcac68f895ff.json | 63 +++ .../test/snapshots/71bf56ec603bc142.json | 13 + .../test/snapshots/720b7e5e0ae2603c.json | 17 + .../test/snapshots/74219cbd9de3b122.json | 16 + .../test/snapshots/742ae2179d57f271.json | 7 + .../test/snapshots/7438a826f1a6e96c.json | 33 ++ .../test/snapshots/75233122af88843e.json | 14 + .../test/snapshots/7583403b47298bc7.json | 7 + .../test/snapshots/7588be2bc0c71c3a.json | 7 + .../test/snapshots/76a9f9e4cb330396.json | 13 + .../test/snapshots/76b87a32829da0e0.json | 7 + .../test/snapshots/76f142be038f6aaf.json | 37 ++ .../test/snapshots/77dac08f7a014269.json | 25 ++ .../test/snapshots/78de9c05192768a1.json | 25 ++ .../test/snapshots/793985cddb68d46e.json | 7 + .../test/snapshots/7982e8c08d84551a.json | 7 + .../test/snapshots/7b2d79ca937a8cbb.json | 7 + .../test/snapshots/7b35b7bce86754a4.json | 14 + .../test/snapshots/7b617dda062bb685.json | 25 ++ .../test/snapshots/7bb7347a7172ad9e.json | 14 + .../test/snapshots/7bd969148ace5e13.json | 29 ++ .../test/snapshots/7c42711aeccef61a.json | 20 + .../test/snapshots/7d144c8134ca1b4f.json | 20 + .../test/snapshots/7d4e42ef9d04a046.json | 7 + .../test/snapshots/7d6f05e0471d0acd.json | 7 + .../test/snapshots/7ee1ece2d69e227b.json | 13 + .../test/snapshots/820a070e69cbeff5.json | 19 + .../test/snapshots/84bafac21a924872.json | 37 ++ .../test/snapshots/84c79425e23a4926.json | 25 ++ .../test/snapshots/85066b2ca9c0c348.json | 7 + .../test/snapshots/857895ede54a4ad7.json | 47 ++ .../test/snapshots/85e93d199ff62047.json | 44 ++ .../test/snapshots/863545b36296dfca.json | 23 + .../test/snapshots/863c2dcdff8db25e.json | 17 + .../test/snapshots/8658478ee33a4992.json | 41 ++ .../test/snapshots/8659297c152d065c.json | 14 + .../test/snapshots/88228a7e519d90de.json | 57 +++ .../test/snapshots/88c06ce9a212e3c3.json | 19 + .../test/snapshots/8911b9163c7d34f3.json | 17 + .../test/snapshots/8969693adfe3e927.json | 7 + .../test/snapshots/89a8eec911b3dcd7.json | 29 ++ .../test/snapshots/8a4d871957c7159e.json | 7 + .../test/snapshots/8bad118235abbed4.json | 29 ++ .../test/snapshots/8d08253fa3dc6ea7.json | 13 + .../test/snapshots/8e194457987b0af1.json | 19 + .../test/snapshots/8e8232cd6a0e42ec.json | 27 ++ .../test/snapshots/8f1113085b02958c.json | 19 + .../test/snapshots/8f535b0aee7ff306.json | 7 + .../test/snapshots/8fe0c11dbe0aca49.json | 23 + .../test/snapshots/90885de55fed9053.json | 17 + .../test/snapshots/913001e7931e5222.json | 7 + .../test/snapshots/91b51f022dd84872.json | 7 + .../test/snapshots/92d47d12e6852d3f.json | 17 + .../test/snapshots/9430d1f0cb6846cf.json | 33 ++ .../test/snapshots/9434ca86a34b5ff2.json | 17 + .../test/snapshots/95bf560a0bb0375a.json | 28 ++ .../test/snapshots/96ddaccf581f483c.json | 7 + .../test/snapshots/98cc0e810e27c9bf.json | 7 + .../test/snapshots/998fe0ecccd6998c.json | 7 + .../test/snapshots/9993d2e1f4dbe182.json | 26 ++ .../test/snapshots/9a52f34a0fcbb1da.json | 21 + .../test/snapshots/9cbddfd4afa15219.json | 21 + .../test/snapshots/9d618df2b0f244f4.json | 17 + .../test/snapshots/9e170c7c7025a1a5.json | 7 + .../test/snapshots/9f561ebcb560c871.json | 7 + .../test/snapshots/9fbbc9c6e35de50d.json | 14 + .../test/snapshots/a148b5c78eff3afa.json | 19 + .../test/snapshots/a1b36e70b213ab9a.json | 13 + .../test/snapshots/a314e0179bfc11f0.json | 7 + .../test/snapshots/a3bd1284c7e4a6ab.json | 14 + .../test/snapshots/a5215edb17e53ed3.json | 17 + .../test/snapshots/a55e385aa7e8d7ec.json | 7 + .../test/snapshots/a8b536b58d6a8ca7.json | 17 + .../test/snapshots/a8dbffb1eb0d1d99.json | 17 + .../test/snapshots/a95e6ce38f4ca609.json | 24 ++ .../test/snapshots/a96d87d7c8b3dcfb.json | 7 + .../test/snapshots/aa7c18e52c6fe0c3.json | 13 + .../test/snapshots/ab56a84eb0f06b84.json | 26 ++ .../test/snapshots/ab68d8e893a82cff.json | 7 + .../test/snapshots/ab7266122e1f020a.json | 7 + .../test/snapshots/adcc2a14fead7cd8.json | 23 + .../test/snapshots/afc75d45f651500f.json | 25 ++ .../test/snapshots/b1017bf1dd9b0fe4.json | 35 ++ .../test/snapshots/b306956d40529bf3.json | 21 + .../test/snapshots/b321ed35f3d53336.json | 17 + .../test/snapshots/b4aa451e69c80088.json | 27 ++ .../test/snapshots/b4c5e2b4273fdc60.json | 13 + .../test/snapshots/b60cb032709a29a6.json | 19 + .../test/snapshots/b70cb7df11aa9094.json | 13 + .../test/snapshots/b734564dc378b7bd.json | 36 ++ .../test/snapshots/b8cee90b794bb4f1.json | 19 + .../test/snapshots/b96269387d602df2.json | 7 + .../test/snapshots/ba328c5fc345c0f2.json | 7 + .../test/snapshots/ba5c9413b0237a0c.json | 19 + .../test/snapshots/bad418ae7c592db2.json | 26 ++ .../test/snapshots/bb588ee05a3b285f.json | 21 + .../test/snapshots/bbaa27c010a10469.json | 27 ++ .../test/snapshots/bbdddd4971d19599.json | 14 + .../test/snapshots/bc45bad0c8791d60.json | 23 + .../test/snapshots/bd226d3d4f21c323.json | 33 ++ .../test/snapshots/bd92f5ce619c26da.json | 14 + .../test/snapshots/be25137f16c1f587.json | 17 + .../test/snapshots/bf23ba5bb47b8e4e.json | 29 ++ .../test/snapshots/c0e76a72cd8b87eb.json | 39 ++ .../test/snapshots/c0f0cadca0773416.json | 7 + .../test/snapshots/c1543d88719671aa.json | 7 + .../test/snapshots/c271016d67dd8d54.json | 19 + .../test/snapshots/c2ca3c43a16ca245.json | 14 + .../test/snapshots/c3dc913b07d28a5b.json | 14 + .../test/snapshots/c45aaac1573d8a07.json | 25 ++ .../test/snapshots/c4605abe1a663a47.json | 17 + .../test/snapshots/c4904982bc938507.json | 27 ++ .../test/snapshots/c5a8be2409ab2f1d.json | 25 ++ .../test/snapshots/c643b487ea6dfd72.json | 17 + .../test/snapshots/c78c17175a5c0e87.json | 7 + .../test/snapshots/c8093b3c6d44d486.json | 13 + .../test/snapshots/c861c5ff0886a0f9.json | 7 + .../test/snapshots/c86fdaa691b98f8b.json | 14 + .../test/snapshots/c901bde075754bb0.json | 13 + .../test/snapshots/c9f338bf38999cef.json | 14 + .../test/snapshots/ca7b55d1b3b969de.json | 17 + .../test/snapshots/cb3651f0a9fbe7c0.json | 27 ++ .../test/snapshots/cbad8c51a3e1d032.json | 19 + .../test/snapshots/cd98ae36981ee80a.json | 7 + .../test/snapshots/cda2841ab393e45d.json | 19 + .../test/snapshots/ce3bb6ac91e15082.json | 7 + .../test/snapshots/ceb02f409a78f4ef.json | 7 + .../test/snapshots/ceb739dfaa883916.json | 7 + .../test/snapshots/cf31903898d06426.json | 7 + .../test/snapshots/cf640c0ceb20ff34.json | 19 + .../test/snapshots/d05fb01e0b399387.json | 7 + .../test/snapshots/d3a3854ba98eb85d.json | 13 + .../test/snapshots/d3e90af2aefe399f.json | 13 + .../test/snapshots/d41324ffd6eed6b3.json | 14 + .../test/snapshots/d62cec53886ff651.json | 17 + .../test/snapshots/d64027e56b998e7c.json | 26 ++ .../test/snapshots/d669ea9cedaeb679.json | 25 ++ .../test/snapshots/d701a37b6e4cf4e9.json | 14 + .../test/snapshots/d712296f71e49233.json | 14 + .../test/snapshots/d773faf0b86ac88b.json | 14 + .../test/snapshots/d8367e8f5ce1f2ca.json | 14 + .../test/snapshots/d9c0ea6152fbf443.json | 13 + .../test/snapshots/da0fdc28c11b5812.json | 14 + .../test/snapshots/daf760a167a8047c.json | 7 + .../test/snapshots/db09a2734af421e6.json | 39 ++ .../test/snapshots/dc1e8f7f69dcbc15.json | 17 + .../test/snapshots/dd0748912e59ec25.json | 21 + .../test/snapshots/dd6fa4122e474566.json | 13 + .../test/snapshots/de785c721705dbba.json | 7 + .../test/snapshots/de86a870104fb0a5.json | 7 + .../test/snapshots/dec8ddb4c2e278d9.json | 17 + .../test/snapshots/df0e5006b34734de.json | 7 + .../test/snapshots/df6b4430f3a214bb.json | 21 + .../test/snapshots/e2102781550b6a87.json | 53 +++ .../test/snapshots/e2227d1f14c97584.json | 13 + .../test/snapshots/e227de9f1df532c1.json | 67 +++ .../test/snapshots/e3b6ce3dbb8f6886.json | 19 + .../test/snapshots/e56ae18058a93567.json | 37 ++ .../test/snapshots/e5fa045b9b25e6db.json | 14 + .../test/snapshots/e64cdc56ad4c4e02.json | 13 + .../test/snapshots/e71e7bc3fe9e9f3c.json | 7 + .../test/snapshots/e7eb51047d99b420.json | 13 + .../test/snapshots/e83319c6c4642871.json | 14 + .../test/snapshots/e89762d9c1f07a3d.json | 7 + .../test/snapshots/e927c2b90a4679c4.json | 14 + .../test/snapshots/e9ca4b2541b01556.json | 21 + .../test/snapshots/eb0071b65f67691e.json | 13 + .../test/snapshots/eb4afc85d92c38ea.json | 7 + .../test/snapshots/eb9a4bc1c0c153e4.json | 7 + .../test/snapshots/ed4a033a0e470779.json | 19 + .../test/snapshots/ed61428e81d608b3.json | 33 ++ .../test/snapshots/ef1ea9269b9833d2.json | 25 ++ .../test/snapshots/effc93c8668219e9.json | 26 ++ .../test/snapshots/f1124b0079db9585.json | 31 ++ .../test/snapshots/f161ebdfdf2494e6.json | 7 + .../test/snapshots/f1e5baf5ecc35896.json | 7 + .../test/snapshots/f4753a4dee54ee10.json | 7 + .../test/snapshots/f47ef5f8d16849a5.json | 41 ++ .../test/snapshots/f4f033a85ce688b6.json | 25 ++ .../test/snapshots/f79a28423ed1ae02.json | 7 + .../test/snapshots/f8a4e52fe170a6b8.json | 7 + .../test/snapshots/f9874bb3d8034d65.json | 17 + .../test/snapshots/fb533649ca2f9e73.json | 7 + .../test/snapshots/fca4d8d6e1593c6b.json | 7 + .../test/snapshots/fcb1a5ad1920b1d8.json | 13 + .../test/snapshots/fcf6d8ffa4297b9e.json | 26 ++ .../test/snapshots/fedf5fb1af8c725d.json | 14 + .../mini-parser-ts/test/update_snapshots.ts | 156 +++++++ .../test/validate_types_live.ts | 118 ++++++ 367 files changed, 7778 insertions(+), 61 deletions(-) create mode 100644 type-parser/mini-parser-ts/test/candidates.txt create mode 100644 type-parser/mini-parser-ts/test/oracle.ts create mode 100644 type-parser/mini-parser-ts/test/snapshot.test.ts create mode 100644 type-parser/mini-parser-ts/test/snapshots.ts create mode 100644 type-parser/mini-parser-ts/test/snapshots/00b95dd2fc4a3cb1.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/00ce7d22d518eb3d.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/01dc6abd5a2822d1.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/0282a2e2726b5fdb.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/02bdf07c09cc39a9.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/03f2221a84fa9cb6.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/05b87974a3b9b844.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/06083c5d1e0fb4b0.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/0630ca3355f050df.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/069c4db0034b51e1.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/07a4cee5695b7794.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/07a608893061fe06.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/08512f086f95145c.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/097274c5c7abaa17.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/0a450823c46ccbe3.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/0aeb95282860cfdf.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/0bed42cd6332cc16.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/0db54c89682d17c4.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/0dc646c154d2103e.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/0ee669b87ea0b36a.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/0ef4e25fc70c78ee.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/0f07cff3e8006379.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/0fe37e40e5dab3ac.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/10997dcfa0b17169.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/11d240952f22547e.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/1269b7d5dc9faecd.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/128519da85d4b5b8.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/133ca8ecd29f3663.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/156e367c7969e103.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/15ac3a2fa148ab10.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/16b2e8523343d5f3.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/16d4d882e66fffc1.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/174711b74c597654.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/1800cfa6f2c5cb5c.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/180fcbe698d0f2c4.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/183de27e0bac77a1.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/19c537c1c1730b4d.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/19e4439f2f9c5c0d.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/1a8c9516519ad655.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/1ab3503a837a8b33.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/1af429358d8dc4cc.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/1b1855ddfe121c06.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/1bd2dfcbd0545dd9.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/1c0e4bc11b79399b.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/1c6d137de6e9cce4.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/1ce04f29dadb9973.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/1d0146114b4a4362.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/1d2e38577d2a158e.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/1dc79a25ff699c42.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/1e16f998c6447325.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/20fd836cdfc11886.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/21bf75a5255af008.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/2208b0f5d5d2aea7.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/22aaa82db55ed6cb.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/22ecac851cfb07e9.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/23b36b23f947874d.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/2451237b00b13cd7.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/261b6d70eaf74bf4.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/26b32b5b966f2a05.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/283e861dc1341e3c.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/292209387fe87cb3.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/292c7af4fff95bcd.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/2a2dd538a651992b.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/2a93a144ad9458ad.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/2b759bb1ca791e18.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/2b92c8c85daf51e6.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/2bb1b10e295da6ba.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/2cad1f5221666485.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/2d0fe684054a5388.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/2d50b2d54d49e844.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/2ecf89a293cd698f.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/2f058b0d7c8ff211.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/2f446fedbc924375.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/2f76fee2db93cfc2.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/2ffb7489d68e87c9.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/30a77c9b71a45749.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/314040aa10c72b02.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/33888e8184bce3d1.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/343587b20a4bf691.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/35d5fb175bed4093.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/36af8609901f12c8.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/36c3682fea89a80a.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/3720deb1bdd5e553.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/387bc74e5d2ed508.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/388c0a082cfd7817.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/3967d5ba8569635b.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/3a8bb11d808ae810.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/3ae9dd8952516f33.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/3b330731a188b19f.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/3b7f131c8d41638e.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/3badd67bde55d4f2.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/3c4d1905119c3883.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/3ce40017fe0513c0.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/3d0564f65e2951d7.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/3d40c376159dc070.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/3df63b7acb0522da.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/3e2d739f398d42c7.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/3eb94c999f391ca9.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/401053f5f7236705.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/406c62c428cea57a.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/435de109befc994a.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/44af40134bf9392d.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/44b693037c5f8e61.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/454656691c92b81b.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/45e2c84f9ca77549.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/46e27f45db2bf7c7.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/46f8ab7c0cff9df7.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/4736033ecebeb570.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/49101d78947d3702.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/49279edf04879138.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/49718b649da090b8.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/49f72ed44502ec22.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/4b1c0b5b55c6eeae.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/4b2e0d29c996e5d4.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/4c5840cb7dad0940.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/4c7aa27b65521bcf.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/4d0c622ecdd58854.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/4dc8e18720867887.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/4e5e15828b576fc3.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/4f2b2ad192957150.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/4fe5a3682f802978.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/501529315784089e.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/503d0c06e75dd73f.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/50876ef35975fe08.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/508ec6552e77fe7d.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/5094f81299f4d418.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/51b1bf12f2eef86f.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/51db33fb52b4c790.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/52708f106b39ca6d.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/54b047d7967410c4.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/55042c80818a5432.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/55c5d81017a30edf.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/5913df984e01b049.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/5a84a5824366cfdf.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/5bee16b592d3087c.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/5c52b39b56c50f56.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/5c89edcac2811a6a.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/5e990ab2800482f2.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/6000a28977e029d9.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/620e6c17af0fec3f.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/625a100e21847dcf.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/63a53953382e5a76.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/64269f9bd268bf28.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/648be8a9b20b4068.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/64edc28811344047.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/6529f695ef6bea2b.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/65d2d849e33bbb9f.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/663699edbe8d32d0.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/663ad5af89c48643.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/66c7fbd08eb194f8.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/6760521bb1b6d98f.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/67ab5f4c86e061d7.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/6932c015a8c3a3ef.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/69a99906f5a06ea1.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/69ddba4964a41534.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/6b09d0c1e764f23a.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/6c43115b5c24bfa0.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/6c82e6dd86807ee3.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/6ddeb86eb863afac.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/6e25d9b9f79612fd.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/6e53b6c5a0f31021.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/6e5f2d68fd260298.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/6e823ebb2984559d.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/6e85b5501433e087.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/6f2851997db0584b.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/707890c2d6dfa724.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/707ef63b9e074824.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/70b4bb2684c3f896.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/710d7120fc63672d.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/711cbcac68f895ff.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/71bf56ec603bc142.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/720b7e5e0ae2603c.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/74219cbd9de3b122.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/742ae2179d57f271.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/7438a826f1a6e96c.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/75233122af88843e.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/7583403b47298bc7.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/7588be2bc0c71c3a.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/76a9f9e4cb330396.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/76b87a32829da0e0.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/76f142be038f6aaf.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/77dac08f7a014269.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/78de9c05192768a1.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/793985cddb68d46e.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/7982e8c08d84551a.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/7b2d79ca937a8cbb.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/7b35b7bce86754a4.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/7b617dda062bb685.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/7bb7347a7172ad9e.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/7bd969148ace5e13.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/7c42711aeccef61a.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/7d144c8134ca1b4f.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/7d4e42ef9d04a046.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/7d6f05e0471d0acd.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/7ee1ece2d69e227b.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/820a070e69cbeff5.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/84bafac21a924872.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/84c79425e23a4926.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/85066b2ca9c0c348.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/857895ede54a4ad7.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/85e93d199ff62047.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/863545b36296dfca.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/863c2dcdff8db25e.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/8658478ee33a4992.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/8659297c152d065c.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/88228a7e519d90de.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/88c06ce9a212e3c3.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/8911b9163c7d34f3.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/8969693adfe3e927.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/89a8eec911b3dcd7.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/8a4d871957c7159e.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/8bad118235abbed4.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/8d08253fa3dc6ea7.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/8e194457987b0af1.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/8e8232cd6a0e42ec.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/8f1113085b02958c.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/8f535b0aee7ff306.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/8fe0c11dbe0aca49.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/90885de55fed9053.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/913001e7931e5222.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/91b51f022dd84872.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/92d47d12e6852d3f.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/9430d1f0cb6846cf.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/9434ca86a34b5ff2.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/95bf560a0bb0375a.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/96ddaccf581f483c.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/98cc0e810e27c9bf.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/998fe0ecccd6998c.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/9993d2e1f4dbe182.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/9a52f34a0fcbb1da.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/9cbddfd4afa15219.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/9d618df2b0f244f4.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/9e170c7c7025a1a5.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/9f561ebcb560c871.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/9fbbc9c6e35de50d.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/a148b5c78eff3afa.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/a1b36e70b213ab9a.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/a314e0179bfc11f0.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/a3bd1284c7e4a6ab.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/a5215edb17e53ed3.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/a55e385aa7e8d7ec.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/a8b536b58d6a8ca7.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/a8dbffb1eb0d1d99.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/a95e6ce38f4ca609.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/a96d87d7c8b3dcfb.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/aa7c18e52c6fe0c3.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/ab56a84eb0f06b84.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/ab68d8e893a82cff.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/ab7266122e1f020a.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/adcc2a14fead7cd8.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/afc75d45f651500f.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/b1017bf1dd9b0fe4.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/b306956d40529bf3.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/b321ed35f3d53336.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/b4aa451e69c80088.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/b4c5e2b4273fdc60.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/b60cb032709a29a6.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/b70cb7df11aa9094.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/b734564dc378b7bd.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/b8cee90b794bb4f1.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/b96269387d602df2.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/ba328c5fc345c0f2.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/ba5c9413b0237a0c.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/bad418ae7c592db2.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/bb588ee05a3b285f.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/bbaa27c010a10469.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/bbdddd4971d19599.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/bc45bad0c8791d60.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/bd226d3d4f21c323.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/bd92f5ce619c26da.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/be25137f16c1f587.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/bf23ba5bb47b8e4e.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/c0e76a72cd8b87eb.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/c0f0cadca0773416.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/c1543d88719671aa.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/c271016d67dd8d54.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/c2ca3c43a16ca245.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/c3dc913b07d28a5b.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/c45aaac1573d8a07.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/c4605abe1a663a47.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/c4904982bc938507.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/c5a8be2409ab2f1d.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/c643b487ea6dfd72.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/c78c17175a5c0e87.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/c8093b3c6d44d486.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/c861c5ff0886a0f9.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/c86fdaa691b98f8b.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/c901bde075754bb0.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/c9f338bf38999cef.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/ca7b55d1b3b969de.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/cb3651f0a9fbe7c0.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/cbad8c51a3e1d032.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/cd98ae36981ee80a.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/cda2841ab393e45d.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/ce3bb6ac91e15082.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/ceb02f409a78f4ef.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/ceb739dfaa883916.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/cf31903898d06426.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/cf640c0ceb20ff34.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/d05fb01e0b399387.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/d3a3854ba98eb85d.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/d3e90af2aefe399f.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/d41324ffd6eed6b3.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/d62cec53886ff651.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/d64027e56b998e7c.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/d669ea9cedaeb679.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/d701a37b6e4cf4e9.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/d712296f71e49233.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/d773faf0b86ac88b.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/d8367e8f5ce1f2ca.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/d9c0ea6152fbf443.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/da0fdc28c11b5812.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/daf760a167a8047c.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/db09a2734af421e6.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/dc1e8f7f69dcbc15.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/dd0748912e59ec25.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/dd6fa4122e474566.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/de785c721705dbba.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/de86a870104fb0a5.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/dec8ddb4c2e278d9.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/df0e5006b34734de.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/df6b4430f3a214bb.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/e2102781550b6a87.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/e2227d1f14c97584.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/e227de9f1df532c1.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/e3b6ce3dbb8f6886.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/e56ae18058a93567.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/e5fa045b9b25e6db.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/e64cdc56ad4c4e02.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/e71e7bc3fe9e9f3c.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/e7eb51047d99b420.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/e83319c6c4642871.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/e89762d9c1f07a3d.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/e927c2b90a4679c4.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/e9ca4b2541b01556.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/eb0071b65f67691e.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/eb4afc85d92c38ea.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/eb9a4bc1c0c153e4.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/ed4a033a0e470779.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/ed61428e81d608b3.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/ef1ea9269b9833d2.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/effc93c8668219e9.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/f1124b0079db9585.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/f161ebdfdf2494e6.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/f1e5baf5ecc35896.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/f4753a4dee54ee10.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/f47ef5f8d16849a5.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/f4f033a85ce688b6.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/f79a28423ed1ae02.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/f8a4e52fe170a6b8.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/f9874bb3d8034d65.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/fb533649ca2f9e73.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/fca4d8d6e1593c6b.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/fcb1a5ad1920b1d8.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/fcf6d8ffa4297b9e.json create mode 100644 type-parser/mini-parser-ts/test/snapshots/fedf5fb1af8c725d.json create mode 100644 type-parser/mini-parser-ts/test/update_snapshots.ts create mode 100644 type-parser/mini-parser-ts/test/validate_types_live.ts diff --git a/type-parser/mini-parser-ts/.gitignore b/type-parser/mini-parser-ts/.gitignore index b94707787..756d26c74 100644 --- a/type-parser/mini-parser-ts/.gitignore +++ b/type-parser/mini-parser-ts/.gitignore @@ -1,2 +1,3 @@ node_modules/ dist/ +test/snapshots_report.txt diff --git a/type-parser/mini-parser-ts/README.md b/type-parser/mini-parser-ts/README.md index 67eb63a96..1f2518181 100644 --- a/type-parser/mini-parser-ts/README.md +++ b/type-parser/mini-parser-ts/README.md @@ -98,19 +98,43 @@ multi-word aliases (`DOUBLE PRECISION`, `CHAR VARYING`, `INT SIGNED`, …). ## Tests ```bash -npm test # node:test unit suite — no external dependencies +npm test # node:test: unit suite + snapshot corpus — NO clickhouse needed npm run test:unsupported # asserts the deferred types are rejected -npm run test:oracle -- --clickhouse /path/to/clickhouse ``` +`npm test` requires **no `clickhouse` binary** — it runs entirely against +checked-in fixtures: + - **unit** (`test/parser.test.ts`) — pins representative AST shapes and all the - deliberate rejections; needs nothing but Node. -- **unsupported** (`test/check_unsupported.ts`) — asserts the types in - `test/cases_unsupported.txt` are rejected. -- **oracle** (`test/oracle_compare.ts`) — for each type in `test/cases.txt`, - compares the parser's JSON against the `data_type` subtree the real server - emits for `CREATE TABLE t (c ) ENGINE = Null`. Needs a `clickhouse` - binary built from - https://github.com/peter-leonov-ch/ClickHouse/pull/1 — the AST-format changes - this parser mirrors live in that PR, so a stock server build will not match. + deliberate rejections. +- **snapshot** (`test/snapshot.test.ts`) — for every type in `test/cases.txt` + (356 and counting), compares the parser's JSON against a checked-in static + snapshot of the real server's `data_type` subtree, in `test/snapshots/` + (one `.json` per query). Because a snapshot is only written when the + server accepted the type **and** the parser matched it, "parser == snapshot" + means "parser == server". + +### Regenerating / extending the snapshot corpus + +The snapshots are captured from a real server by `update_snapshots.ts`, which +needs a `clickhouse` binary built from +https://github.com/peter-leonov-ch/ClickHouse/pull/1 (the AST-format changes +this parser mirrors live in that PR; a stock build will not match): + +```bash +npm run snapshot:update -- --clickhouse /path/to/clickhouse +``` + +It validates every type in `test/cases.txt` plus any in `test/candidates.txt` +(a seed list of additional types), keeps only those the server accepts and the +parser matches, appends new keepers to `cases.txt`, writes a snapshot per kept +query, and prunes orphans. Types the server rejects or where the parser diverges +are dropped and listed in `test/snapshots_report.txt` (never silently added). + +There is also a live comparison that skips the snapshots and queries the server +directly, useful while iterating: + +```bash +npm run test:oracle -- --clickhouse /path/to/clickhouse +``` diff --git a/type-parser/mini-parser-ts/package.json b/type-parser/mini-parser-ts/package.json index 20b725788..b34d979ed 100644 --- a/type-parser/mini-parser-ts/package.json +++ b/type-parser/mini-parser-ts/package.json @@ -14,7 +14,8 @@ "parse": "tsx tool/main.ts", "test": "node --import tsx --test test/*.test.ts", "test:oracle": "tsx test/oracle_compare.ts", - "test:unsupported": "tsx test/check_unsupported.ts" + "test:unsupported": "tsx test/check_unsupported.ts", + "snapshot:update": "tsx test/update_snapshots.ts" }, "devDependencies": { "tsx": "^4.22.4", diff --git a/type-parser/mini-parser-ts/test/candidates.txt b/type-parser/mini-parser-ts/test/candidates.txt new file mode 100644 index 000000000..843a29a4d --- /dev/null +++ b/type-parser/mini-parser-ts/test/candidates.txt @@ -0,0 +1,401 @@ +# ClickHouse data-type parser test corpus +# One type per line. Lines starting with # and blank lines are ignored. + +# ---- Integers ---- +UInt8 +UInt16 +UInt32 +UInt64 +UInt128 +UInt256 +Int8 +Int16 +Int32 +Int64 +Int128 +Int256 + +# ---- Floats ---- +Float32 +Float64 +BFloat16 + +# ---- Decimal ---- +Decimal(9, 0) +Decimal(10, 2) +Decimal(18, 4) +Decimal(38, 10) +Decimal(76, 20) +Decimal(1, 0) +Decimal(2, 1) +Decimal(38, 0) +Decimal(38, 38) +Decimal(76, 0) +Decimal(76, 76) +Decimal(20, 5) +Decimal(30, 15) +Decimal(50, 25) +Decimal32(0) +Decimal32(2) +Decimal32(9) +Decimal64(0) +Decimal64(4) +Decimal64(18) +Decimal128(0) +Decimal128(10) +Decimal128(38) +Decimal256(0) +Decimal256(20) +Decimal256(76) + +# ---- Date / Time ---- +Date +Date32 +DateTime +DateTime('UTC') +DateTime('Europe/Amsterdam') +DateTime('America/New_York') +DateTime('Asia/Tokyo') +DateTime64(0) +DateTime64(1) +DateTime64(2) +DateTime64(3) +DateTime64(4) +DateTime64(5) +DateTime64(6) +DateTime64(7) +DateTime64(8) +DateTime64(9) +DateTime64(3, 'UTC') +DateTime64(6, 'Europe/Amsterdam') +DateTime64(9, 'Asia/Tokyo') +DateTime64(0, 'America/Los_Angeles') +Time +Time64(0) +Time64(3) +Time64(6) +Time64(9) + +# ---- String / FixedString ---- +String +FixedString(1) +FixedString(2) +FixedString(4) +FixedString(8) +FixedString(16) +FixedString(32) +FixedString(64) +FixedString(128) +FixedString(255) +FixedString(256) +FixedString(1024) + +# ---- Misc scalars ---- +UUID +IPv4 +IPv6 +Bool + +# ---- Enum8 / Enum16 / Enum ---- +Enum8('a' = 1, 'b' = 2) +Enum8('a' = 1, 'b' = 2, 'c' = 3) +Enum8('red' = 0, 'green' = 1, 'blue' = 2) +Enum8('x' = -1, 'y' = 0, 'z' = 1) +Enum8('neg' = -128, 'pos' = 127) +Enum8('a') +Enum8('a', 'b', 'c') +Enum8('one', 'two', 'three', 'four') +Enum16('x' = -1, 'y' = 100, 'z' = 1000) +Enum16('small' = 1, 'big' = 30000) +Enum16('min' = -32768, 'max' = 32767) +Enum16('a' = 1, 'b' = 2, 'c' = 3, 'd' = 4, 'e' = 5) +Enum16('alpha', 'beta') +Enum('a' = 1, 'b' = 2) +Enum('hello world' = 1, 'foo bar' = 2) +Enum8('with space' = 1, 'another one' = 2) +Enum8('a.b.c' = 1, 'x.y.z' = 2) +Enum8('café' = 1, 'naïve' = 2) +Enum16('日本語' = 1, 'español' = 2, 'русский' = 3) +Enum8('' = 0, 'nonempty' = 1) +Enum8('UPPER' = 1, 'lower' = 2, 'MiXeD' = 3) +Enum16('a' = 1, 'b' = 2, 'c' = 3, 'd' = 4, 'e' = 5, 'f' = 6, 'g' = 7, 'h' = 8) + +# ---- Array over scalars ---- +Array(UInt8) +Array(Int64) +Array(Float64) +Array(String) +Array(UUID) +Array(Date) +Array(DateTime) +Array(Bool) +Array(IPv4) +Array(IPv6) +Array(FixedString(16)) +Array(Decimal(18, 4)) +Array(DateTime64(3, 'UTC')) +Array(Enum8('a' = 1, 'b' = 2)) + +# ---- Array nesting ---- +Array(Array(UInt8)) +Array(Array(String)) +Array(Array(Array(Int32))) +Array(Array(Array(Array(Float64)))) +Array(Nullable(UInt64)) +Array(Nullable(String)) +Array(LowCardinality(String)) +Array(Array(Nullable(Decimal(18, 4)))) + +# ---- Map ---- +Map(String, String) +Map(String, UInt64) +Map(String, Float64) +Map(Int32, String) +Map(UInt64, UInt64) +Map(UUID, String) +Map(FixedString(8), UInt32) +Map(Date, UInt64) +Map(LowCardinality(String), UInt32) +Map(Enum8('a' = 1, 'b' = 2), String) +Map(String, Array(UInt8)) +Map(String, Array(String)) +Map(UUID, Array(LowCardinality(String))) +Map(String, Map(String, UInt64)) +Map(String, Tuple(UInt8, String)) +Map(Int64, Nullable(Float64)) +Map(String, Array(Map(String, UInt64))) +Map(LowCardinality(String), Array(Nullable(Decimal(18, 4)))) + +# ---- Nullable ---- +Nullable(UInt8) +Nullable(UInt16) +Nullable(UInt32) +Nullable(UInt64) +Nullable(UInt128) +Nullable(UInt256) +Nullable(Int8) +Nullable(Int32) +Nullable(Int64) +Nullable(Float32) +Nullable(Float64) +Nullable(String) +Nullable(FixedString(16)) +Nullable(UUID) +Nullable(Date) +Nullable(Date32) +Nullable(DateTime) +Nullable(DateTime('UTC')) +Nullable(DateTime64(3)) +Nullable(DateTime64(3, 'UTC')) +Nullable(Decimal(18, 4)) +Nullable(Decimal64(4)) +Nullable(IPv4) +Nullable(IPv6) +Nullable(Bool) +Nullable(Enum8('a' = 1, 'b' = 2)) + +# ---- LowCardinality ---- +LowCardinality(String) +LowCardinality(FixedString(8)) +LowCardinality(FixedString(32)) +LowCardinality(Nullable(String)) +LowCardinality(Nullable(FixedString(16))) +LowCardinality(Date) +LowCardinality(Date32) +LowCardinality(DateTime) +LowCardinality(UInt8) +LowCardinality(UInt32) +LowCardinality(UInt64) +LowCardinality(Int32) +LowCardinality(Int64) +LowCardinality(Float64) +LowCardinality(Nullable(UInt32)) + +# ---- Variant ---- +Variant(UInt64, String) +Variant(Int32, Float64) +Variant(String, UInt64, Float64) +Variant(UInt8, Int16, UInt32) +Variant(String, Array(UInt8), Map(String, UInt64)) +Variant(Date, DateTime, DateTime64(3)) +Variant(UInt8, UInt16, UInt32, UInt64) +Variant(String, FixedString(16), UUID, IPv4, IPv6) +Variant(Int8, Int16, Int32, Int64, Int128, Int256) +Variant(Tuple(UInt8, String), Array(Float64)) +Variant(Nullable(UInt64), String) + +# ---- Tuple (unnamed) ---- +Tuple(UInt8) +Tuple(UInt8, String) +Tuple(String, UInt64, Float64) +Tuple(Int32, Int32, Int32) +Tuple(UInt8, UInt16, UInt32, UInt64) +Tuple(String, String, String, String, String) +Tuple(UInt8, String, Float64, Date, UUID, Bool) +Tuple(Int8, Int16, Int32, Int64, Int128, Int256, UInt8) +Tuple(UInt8, UInt16, UInt32, UInt64, Int8, Int16, Int32, Int64) + +# ---- Tuple (named) ---- +Tuple(a UInt8) +Tuple(a UInt8, b String) +Tuple(id UInt64, name String, score Float64) +Tuple(x Int32, y Int32, z Int32) +Tuple(first String, second String, third String) +Tuple(a UInt8, b UInt16, c UInt32, d UInt64) +Tuple(ts DateTime64(3, 'UTC'), val Nullable(Float64)) +Tuple(key String, payload Array(UInt8)) + +# ---- Tuple (mixed named/unnamed) ---- +Tuple(a UInt8, String) +Tuple(a UInt8, String, c Float64) +Tuple(UInt8, b String, Float64) +Tuple(id UInt64, String, flag Bool) + +# ---- Tuple nesting ---- +Tuple(Tuple(UInt8, String), Float64) +Tuple(a Tuple(x UInt8, y UInt8), b String) +Tuple(Array(Int32), Map(String, Float64), Nullable(DateTime64(3, 'UTC'))) +Tuple(a Array(UInt8), b Map(String, UInt64), c Tuple(p Int8, q Int8)) +Array(Tuple(UInt8, String)) +Array(Tuple(LowCardinality(String), Array(Nullable(Decimal(18, 4))))) + +# ---- Nested ---- +Nested(a UInt8, b String) +Nested(id UInt64, name String, score Float64) +Nested(x Int32, y Int32) +Nested(key String, value Array(UInt8)) +Nested(ts DateTime, vals Array(Float64)) +Nested(a UInt8, b Tuple(x Int8, y Int8)) +Nested(name String, tags Array(LowCardinality(String))) +Nested(outer UInt8, inner Nested(a UInt8, b String)) + +# ---- Dynamic ---- +Dynamic +Dynamic(max_types = 1) +Dynamic(max_types = 5) +Dynamic(max_types = 10) +Dynamic(max_types = 16) +Dynamic(max_types = 32) +Dynamic(max_types = 100) +Dynamic(max_types = 255) + +# ---- Geo ---- +Point +Ring +LineString +MultiLineString +Polygon +MultiPolygon + +# ---- Interval ---- +IntervalNanosecond +IntervalMicrosecond +IntervalMillisecond +IntervalSecond +IntervalMinute +IntervalHour +IntervalDay +IntervalWeek +IntervalMonth +IntervalQuarter +IntervalYear + +# ---- Legacy ---- +Object('json') + +# ---- SQL-standard / MySQL-compatible aliases ---- +DOUBLE PRECISION +CHAR +CHARACTER +CHAR VARYING +CHARACTER VARYING +NCHAR +NVARCHAR +varchar +varchar(255) +VARCHAR(64) +CHAR(10) +NATIONAL CHARACTER +NATIONAL CHAR VARYING +BINARY +BINARY VARYING +BINARY LARGE OBJECT +CHAR LARGE OBJECT +INT +INTEGER +INT SIGNED +INT UNSIGNED +INTEGER SIGNED +INT(11) +INT(10) UNSIGNED +TINYINT +SMALLINT +MEDIUMINT +BIGINT +TINYINT UNSIGNED +BIGINT SIGNED +FLOAT +REAL +DOUBLE +DEC(10, 2) +NUMERIC(10, 2) +FIXED(10, 2) +BLOB +TEXT +MEDIUMTEXT +LONGTEXT +BYTEA +BOOL +BOOLEAN +SET +YEAR +TIME +BIT + +# ---- Deep / wide nesting combos ---- +Array(Map(String, Tuple(a UInt8, b Array(Nullable(String))))) +Map(UUID, Array(LowCardinality(String))) +Tuple(Array(Int32), Map(String, Float64), Nullable(DateTime64(3, 'UTC'))) +Array(Tuple(LowCardinality(String), Array(Nullable(Decimal(18, 4))))) +Array(Array(Map(String, Array(UInt8)))) +Map(String, Array(Tuple(id UInt64, vals Array(Nullable(Float64))))) +Tuple(a Array(Map(String, UInt64)), b Tuple(x Array(Int8), y Nullable(String))) +Array(Nullable(Tuple(UInt8, String))) +Map(LowCardinality(String), Map(UUID, Array(Nullable(DateTime64(3, 'UTC'))))) +Array(Variant(UInt64, String, Array(Float64))) +Tuple(v Variant(Int32, String), arr Array(Map(String, Nullable(UInt64)))) +Map(FixedString(16), Tuple(a Decimal(38, 10), b Array(LowCardinality(String)))) +Array(Array(Array(Tuple(UInt8, Nullable(String), Map(String, Float64))))) +Nullable(Decimal256(40)) +Tuple(p Point, r Ring, poly Polygon) +Array(Point) +Array(Polygon) +Map(String, MultiPolygon) +Array(Map(LowCardinality(String), Array(Tuple(a UInt8, b Nullable(Decimal(18, 6)))))) +Tuple(meta Map(String, String), data Array(Tuple(ts DateTime64(9, 'UTC'), val Float64))) +Array(Tuple(a UInt8, b UInt16, c Tuple(d Int32, e Array(Nullable(String))))) +Map(Int64, Variant(String, UInt64, Array(Float64))) +LowCardinality(Nullable(FixedString(8))) +Array(LowCardinality(Nullable(String))) +Map(String, Nullable(Decimal(38, 18))) +Tuple(a Nullable(UUID), b Nullable(IPv6), c Nullable(Date32)) +Array(Tuple(Enum8('a' = 1, 'b' = 2), Array(UInt8))) +Nested(coords Tuple(lat Float64, lon Float64), labels Array(LowCardinality(String))) +Map(UUID, Tuple(created DateTime64(3, 'UTC'), tags Array(LowCardinality(String)))) +Array(Map(String, Variant(Int64, Float64, String))) + +# ---- Whitespace variety ---- +Array( Nullable( UInt64 ) ) +Tuple(a UInt8, b String) +Decimal(10,2) +Decimal( 10 , 2 ) +Map( String , UInt64 ) +Array( Array( Int32 ) ) +Nullable( Float64 ) +LowCardinality( String ) +DateTime64( 3 , 'UTC' ) +Tuple( id UInt64 , name String ) +Enum8( 'a' = 1 , 'b' = 2 ) +FixedString( 16 ) +Variant( UInt64 , String ) +Dynamic( max_types = 8 ) diff --git a/type-parser/mini-parser-ts/test/cases.txt b/type-parser/mini-parser-ts/test/cases.txt index 37844c31f..552359a7e 100644 --- a/type-parser/mini-parser-ts/test/cases.txt +++ b/type-parser/mini-parser-ts/test/cases.txt @@ -70,3 +70,311 @@ BFloat16 Time int Int + +# === generated cases (validated against the server oracle; see update_snapshots.ts) === +UInt16 +UInt32 +UInt64 +UInt128 +UInt256 +Int8 +Int16 +Int32 +Int128 +Int256 +Float32 +Decimal(9, 0) +Decimal(18, 4) +Decimal(76, 20) +Decimal(1, 0) +Decimal(2, 1) +Decimal(38, 0) +Decimal(38, 38) +Decimal(76, 0) +Decimal(76, 76) +Decimal(20, 5) +Decimal(30, 15) +Decimal(50, 25) +Decimal32(0) +Decimal32(2) +Decimal32(9) +Decimal64(0) +Decimal64(4) +Decimal64(18) +Decimal128(0) +Decimal128(10) +Decimal128(38) +Decimal256(0) +Decimal256(20) +Decimal256(76) +Date32 +DateTime('Europe/Amsterdam') +DateTime('America/New_York') +DateTime('Asia/Tokyo') +DateTime64(0) +DateTime64(1) +DateTime64(2) +DateTime64(4) +DateTime64(5) +DateTime64(6) +DateTime64(7) +DateTime64(8) +DateTime64(9) +DateTime64(6, 'Europe/Amsterdam') +DateTime64(9, 'Asia/Tokyo') +DateTime64(0, 'America/Los_Angeles') +Time64(0) +Time64(3) +Time64(6) +Time64(9) +FixedString(1) +FixedString(2) +FixedString(4) +FixedString(8) +FixedString(32) +FixedString(64) +FixedString(128) +FixedString(255) +FixedString(256) +FixedString(1024) +Enum8('a' = 1, 'b' = 2, 'c' = 3) +Enum8('red' = 0, 'green' = 1, 'blue' = 2) +Enum8('x' = -1, 'y' = 0, 'z' = 1) +Enum8('neg' = -128, 'pos' = 127) +Enum8('a') +Enum8('a', 'b', 'c') +Enum8('one', 'two', 'three', 'four') +Enum16('x' = -1, 'y' = 100, 'z' = 1000) +Enum16('small' = 1, 'big' = 30000) +Enum16('min' = -32768, 'max' = 32767) +Enum16('a' = 1, 'b' = 2, 'c' = 3, 'd' = 4, 'e' = 5) +Enum16('alpha', 'beta') +Enum('hello world' = 1, 'foo bar' = 2) +Enum8('with space' = 1, 'another one' = 2) +Enum8('a.b.c' = 1, 'x.y.z' = 2) +Enum8('café' = 1, 'naïve' = 2) +Enum16('日本語' = 1, 'español' = 2, 'русский' = 3) +Enum8('' = 0, 'nonempty' = 1) +Enum8('UPPER' = 1, 'lower' = 2, 'MiXeD' = 3) +Enum16('a' = 1, 'b' = 2, 'c' = 3, 'd' = 4, 'e' = 5, 'f' = 6, 'g' = 7, 'h' = 8) +Array(UInt8) +Array(Int64) +Array(Float64) +Array(UUID) +Array(Date) +Array(DateTime) +Array(Bool) +Array(IPv4) +Array(IPv6) +Array(FixedString(16)) +Array(Decimal(18, 4)) +Array(DateTime64(3, 'UTC')) +Array(Enum8('a' = 1, 'b' = 2)) +Array(Array(UInt8)) +Array(Array(String)) +Array(Array(Array(Int32))) +Array(Array(Array(Array(Float64)))) +Array(Nullable(String)) +Array(LowCardinality(String)) +Array(Array(Nullable(Decimal(18, 4)))) +Map(String, String) +Map(String, Float64) +Map(Int32, String) +Map(UInt64, UInt64) +Map(UUID, String) +Map(FixedString(8), UInt32) +Map(Date, UInt64) +Map(LowCardinality(String), UInt32) +Map(Enum8('a' = 1, 'b' = 2), String) +Map(String, Array(String)) +Map(UUID, Array(LowCardinality(String))) +Map(String, Map(String, UInt64)) +Map(String, Tuple(UInt8, String)) +Map(Int64, Nullable(Float64)) +Map(String, Array(Map(String, UInt64))) +Map(LowCardinality(String), Array(Nullable(Decimal(18, 4)))) +Nullable(UInt8) +Nullable(UInt16) +Nullable(UInt32) +Nullable(UInt128) +Nullable(UInt256) +Nullable(Int8) +Nullable(Int32) +Nullable(Int64) +Nullable(Float32) +Nullable(Float64) +Nullable(String) +Nullable(FixedString(16)) +Nullable(UUID) +Nullable(Date) +Nullable(Date32) +Nullable(DateTime) +Nullable(DateTime('UTC')) +Nullable(DateTime64(3)) +Nullable(DateTime64(3, 'UTC')) +Nullable(Decimal(18, 4)) +Nullable(Decimal64(4)) +Nullable(IPv4) +Nullable(IPv6) +Nullable(Bool) +Nullable(Enum8('a' = 1, 'b' = 2)) +LowCardinality(FixedString(8)) +LowCardinality(FixedString(32)) +LowCardinality(Nullable(FixedString(16))) +LowCardinality(Date) +LowCardinality(Date32) +LowCardinality(DateTime) +LowCardinality(UInt8) +LowCardinality(UInt32) +LowCardinality(UInt64) +LowCardinality(Int32) +LowCardinality(Int64) +LowCardinality(Float64) +LowCardinality(Nullable(UInt32)) +Variant(UInt64, String) +Variant(Int32, Float64) +Variant(String, UInt64, Float64) +Variant(UInt8, Int16, UInt32) +Variant(String, Array(UInt8), Map(String, UInt64)) +Variant(Date, DateTime, DateTime64(3)) +Variant(UInt8, UInt16, UInt32, UInt64) +Variant(String, FixedString(16), UUID, IPv4, IPv6) +Variant(Int8, Int16, Int32, Int64, Int128, Int256) +Variant(Tuple(UInt8, String), Array(Float64)) +Variant(Nullable(UInt64), String) +Tuple(UInt8) +Tuple(String, UInt64, Float64) +Tuple(Int32, Int32, Int32) +Tuple(UInt8, UInt16, UInt32, UInt64) +Tuple(String, String, String, String, String) +Tuple(UInt8, String, Float64, Date, UUID, Bool) +Tuple(Int8, Int16, Int32, Int64, Int128, Int256, UInt8) +Tuple(UInt8, UInt16, UInt32, UInt64, Int8, Int16, Int32, Int64) +Tuple(a UInt8) +Tuple(id UInt64, name String, score Float64) +Tuple(x Int32, y Int32, z Int32) +Tuple(first String, second String, third String) +Tuple(a UInt8, b UInt16, c UInt32, d UInt64) +Tuple(ts DateTime64(3, 'UTC'), val Nullable(Float64)) +Tuple(key String, payload Array(UInt8)) +Tuple(a UInt8, String, c Float64) +Tuple(UInt8, b String, Float64) +Tuple(id UInt64, String, flag Bool) +Tuple(Tuple(UInt8, String), Float64) +Tuple(a Tuple(x UInt8, y UInt8), b String) +Tuple(Array(Int32), Map(String, Float64), Nullable(DateTime64(3, 'UTC'))) +Tuple(a Array(UInt8), b Map(String, UInt64), c Tuple(p Int8, q Int8)) +Array(Tuple(UInt8, String)) +Array(Tuple(LowCardinality(String), Array(Nullable(Decimal(18, 4))))) +Nested(id UInt64, name String, score Float64) +Nested(x Int32, y Int32) +Nested(key String, value Array(UInt8)) +Nested(ts DateTime, vals Array(Float64)) +Nested(a UInt8, b Tuple(x Int8, y Int8)) +Nested(name String, tags Array(LowCardinality(String))) +Nested(outer UInt8, inner Nested(a UInt8, b String)) +Dynamic(max_types = 1) +Dynamic(max_types = 10) +Dynamic(max_types = 16) +Dynamic(max_types = 32) +Dynamic(max_types = 100) +Dynamic(max_types = 255) +Point +Ring +LineString +MultiLineString +Polygon +MultiPolygon +IntervalNanosecond +IntervalMicrosecond +IntervalMillisecond +IntervalSecond +IntervalMinute +IntervalHour +IntervalDay +IntervalWeek +IntervalMonth +IntervalQuarter +IntervalYear +CHAR +CHARACTER +CHARACTER VARYING +NCHAR +NVARCHAR +VARCHAR(64) +CHAR(10) +NATIONAL CHARACTER +NATIONAL CHAR VARYING +BINARY +BINARY VARYING +BINARY LARGE OBJECT +CHAR LARGE OBJECT +INT +INTEGER +INTEGER SIGNED +INT(11) +INT(10) UNSIGNED +TINYINT +SMALLINT +MEDIUMINT +BIGINT +TINYINT UNSIGNED +BIGINT SIGNED +FLOAT +REAL +DOUBLE +DEC(10, 2) +NUMERIC(10, 2) +FIXED(10, 2) +BLOB +TEXT +MEDIUMTEXT +LONGTEXT +BYTEA +BOOL +BOOLEAN +SET +YEAR +TIME +BIT +Array(Map(String, Tuple(a UInt8, b Array(Nullable(String))))) +Array(Array(Map(String, Array(UInt8)))) +Map(String, Array(Tuple(id UInt64, vals Array(Nullable(Float64))))) +Tuple(a Array(Map(String, UInt64)), b Tuple(x Array(Int8), y Nullable(String))) +Array(Nullable(Tuple(UInt8, String))) +Map(LowCardinality(String), Map(UUID, Array(Nullable(DateTime64(3, 'UTC'))))) +Array(Variant(UInt64, String, Array(Float64))) +Tuple(v Variant(Int32, String), arr Array(Map(String, Nullable(UInt64)))) +Map(FixedString(16), Tuple(a Decimal(38, 10), b Array(LowCardinality(String)))) +Array(Array(Array(Tuple(UInt8, Nullable(String), Map(String, Float64))))) +Nullable(Decimal256(40)) +Tuple(p Point, r Ring, poly Polygon) +Array(Point) +Array(Polygon) +Map(String, MultiPolygon) +Array(Map(LowCardinality(String), Array(Tuple(a UInt8, b Nullable(Decimal(18, 6)))))) +Tuple(meta Map(String, String), data Array(Tuple(ts DateTime64(9, 'UTC'), val Float64))) +Array(Tuple(a UInt8, b UInt16, c Tuple(d Int32, e Array(Nullable(String))))) +Map(Int64, Variant(String, UInt64, Array(Float64))) +LowCardinality(Nullable(FixedString(8))) +Array(LowCardinality(Nullable(String))) +Map(String, Nullable(Decimal(38, 18))) +Tuple(a Nullable(UUID), b Nullable(IPv6), c Nullable(Date32)) +Array(Tuple(Enum8('a' = 1, 'b' = 2), Array(UInt8))) +Nested(coords Tuple(lat Float64, lon Float64), labels Array(LowCardinality(String))) +Map(UUID, Tuple(created DateTime64(3, 'UTC'), tags Array(LowCardinality(String)))) +Array(Map(String, Variant(Int64, Float64, String))) +Array( Nullable( UInt64 ) ) +Tuple(a UInt8, b String) +Decimal(10,2) +Decimal( 10 , 2 ) +Map( String , UInt64 ) +Array( Array( Int32 ) ) +Nullable( Float64 ) +LowCardinality( String ) +DateTime64( 3 , 'UTC' ) +Tuple( id UInt64 , name String ) +Enum8( 'a' = 1 , 'b' = 2 ) +FixedString( 16 ) +Variant( UInt64 , String ) +Dynamic( max_types = 8 ) diff --git a/type-parser/mini-parser-ts/test/oracle.ts b/type-parser/mini-parser-ts/test/oracle.ts new file mode 100644 index 000000000..cc96f4293 --- /dev/null +++ b/type-parser/mini-parser-ts/test/oracle.ts @@ -0,0 +1,60 @@ +/// Shared oracle helpers: talk to a real ClickHouse server to obtain the +/// expected `data_type` subtree, and run the standalone parser. Used by the +/// live oracle comparison and by the snapshot updater. + +import { spawnSync } from "node:child_process"; + +import { parseDataType, toJSON } from "../src/index.js"; + +/// Depth-first search for the ColumnDeclaration named `column`. +export function findColumnDataType(node: unknown, column: string): unknown { + if (Array.isArray(node)) { + for (const v of node) { + const found = findColumnDataType(v, column); + if (found !== undefined) return found; + } + } else if (node !== null && typeof node === "object") { + const obj = node as Record; + if (obj["type"] === "ColumnDeclaration" && obj["name"] === column) { + return obj["data_type"]; + } + for (const v of Object.values(obj)) { + const found = findColumnDataType(v, column); + if (found !== undefined) return found; + } + } + return undefined; +} + +/// The `data_type` subtree the server produces for +/// `EXPLAIN AST json = 1 CREATE TABLE t (c ) ENGINE = Null`. Throws on a +/// server error (invalid type) or an unexpected AST shape. +export function serverDataType(clickhouse: string, typeStr: string): unknown { + const sql = `EXPLAIN AST json = 1 CREATE TABLE t (c ${typeStr}) ENGINE = Null`; + const out = spawnSync(clickhouse, ["local", "--format", "TSVRaw", "-q", sql], { + encoding: "utf8", + maxBuffer: 64 * 1024 * 1024, + }); + if (out.status !== 0) { + throw new Error(`server failed: ${(out.stderr ?? "").trim()}`); + } + const doc = JSON.parse(out.stdout) as { version?: number; ast: unknown }; + if (doc.version !== 2) { + throw new Error(`unexpected format version ${doc.version}`); + } + const dt = findColumnDataType(doc.ast, "c"); + if (dt === undefined) { + throw new Error("could not locate column data_type in server AST"); + } + return dt; +} + +/// The standalone parser's JSON AST for a type string. Throws if the parser +/// rejects the input. +export function toolDataType(typeStr: string): unknown { + const result = parseDataType(typeStr); + if (!result.ok()) { + throw new Error(`parse failed: ${result.error!.message}`); + } + return JSON.parse(toJSON(result.ast!)); +} diff --git a/type-parser/mini-parser-ts/test/oracle_compare.ts b/type-parser/mini-parser-ts/test/oracle_compare.ts index 9879569fd..33ffe48c9 100644 --- a/type-parser/mini-parser-ts/test/oracle_compare.ts +++ b/type-parser/mini-parser-ts/test/oracle_compare.ts @@ -17,12 +17,11 @@ /// https://github.com/peter-leonov-ch/ClickHouse/pull/1 (the AST-format changes /// this parser mirrors live in that PR). -import { spawnSync } from "node:child_process"; import { fileURLToPath } from "node:url"; import { dirname, join } from "node:path"; -import { parseDataType, toJSON } from "../src/index.js"; import { canon, deepEqual, readCases } from "./cases.js"; +import { serverDataType, toolDataType } from "./oracle.js"; const here = dirname(fileURLToPath(import.meta.url)); @@ -40,53 +39,6 @@ function parseArgs(argv: string[]): { clickhouse: string; cases: string } { return { clickhouse, cases }; } -/// Depth-first search for the ColumnDeclaration named `column`. -function findColumnDataType(node: unknown, column: string): unknown { - if (Array.isArray(node)) { - for (const v of node) { - const found = findColumnDataType(v, column); - if (found !== undefined) return found; - } - } else if (node !== null && typeof node === "object") { - const obj = node as Record; - if (obj["type"] === "ColumnDeclaration" && obj["name"] === column) { - return obj["data_type"]; - } - for (const v of Object.values(obj)) { - const found = findColumnDataType(v, column); - if (found !== undefined) return found; - } - } - return undefined; -} - -function serverDataType(clickhouse: string, typeStr: string): unknown { - const sql = `EXPLAIN AST json = 1 CREATE TABLE t (c ${typeStr}) ENGINE = Null`; - const out = spawnSync(clickhouse, ["local", "--format", "TSVRaw", "-q", sql], { - encoding: "utf8", - }); - if (out.status !== 0) { - throw new Error(`server failed: ${(out.stderr ?? "").trim()}`); - } - const doc = JSON.parse(out.stdout) as { version?: number; ast: unknown }; - if (doc.version !== 2) { - throw new Error(`unexpected format version ${doc.version}`); - } - const dt = findColumnDataType(doc.ast, "c"); - if (dt === undefined) { - throw new Error("could not locate column data_type in server AST"); - } - return dt; -} - -function toolDataType(typeStr: string): unknown { - const result = parseDataType(typeStr); - if (!result.ok()) { - throw new Error(`parse failed: ${result.error!.message}`); - } - return JSON.parse(toJSON(result.ast!)); -} - function main(): number { const { clickhouse, cases: casesPath } = parseArgs(process.argv.slice(2)); const cases = readCases(casesPath); diff --git a/type-parser/mini-parser-ts/test/snapshot.test.ts b/type-parser/mini-parser-ts/test/snapshot.test.ts new file mode 100644 index 000000000..83489d708 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshot.test.ts @@ -0,0 +1,40 @@ +/// Snapshot test: compare the standalone parser against the static oracle +/// snapshots in test/snapshots/ — NO `clickhouse` binary required. +/// +/// Each snapshot holds the `data_type` subtree the real server emitted for a +/// type in cases.txt (captured by update_snapshots.ts). Since a snapshot is +/// only written when the server accepted the type AND the parser matched it, +/// "parser output equals snapshot" is equivalent to "parser equals server". +/// +/// Run with: npm test (node --import tsx --test test/*.test.ts) + +import { strict as assert } from "node:assert"; +import { existsSync, readFileSync } from "node:fs"; +import { test } from "node:test"; +import { fileURLToPath } from "node:url"; +import { dirname, join } from "node:path"; + +import { canon, readCases } from "./cases.js"; +import { toolDataType } from "./oracle.js"; +import { snapshotPath, type Snapshot } from "./snapshots.js"; + +const here = dirname(fileURLToPath(import.meta.url)); +const cases = readCases(join(here, "cases.txt")); + +test(`snapshot corpus is non-empty`, () => { + assert.ok(cases.length > 0, "cases.txt has no cases"); +}); + +for (const typeStr of cases) { + test(`matches server snapshot: ${typeStr}`, () => { + const path = snapshotPath(typeStr); + assert.ok( + existsSync(path), + `missing snapshot for ${JSON.stringify(typeStr)} — run: npm run snapshot:update -- --clickhouse `, + ); + const snap = JSON.parse(readFileSync(path, "utf8")) as Snapshot; + const expected = canon(snap.data_type); + const actual = canon(toolDataType(typeStr)); + assert.deepEqual(actual, expected); + }); +} diff --git a/type-parser/mini-parser-ts/test/snapshots.ts b/type-parser/mini-parser-ts/test/snapshots.ts new file mode 100644 index 000000000..c53fd2fa7 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots.ts @@ -0,0 +1,30 @@ +/// Static oracle snapshots: one JSON file per data-type string, holding the +/// `data_type` subtree the ClickHouse server emits. These let the snapshot test +/// run with no `clickhouse` binary — the server is only needed to (re)generate +/// them via `update_snapshots.ts`. + +import { createHash } from "node:crypto"; +import { fileURLToPath } from "node:url"; +import { dirname, join } from "node:path"; + +const here = dirname(fileURLToPath(import.meta.url)); + +/// Directory holding the per-query snapshot files. +export const SNAPSHOT_DIR = join(here, "snapshots"); + +/// A stable filename for a type string (content-addressed, so reordering +/// cases.txt never churns filenames). +export function snapshotName(typeStr: string): string { + return createHash("sha1").update(typeStr, "utf8").digest("hex").slice(0, 16) + ".json"; +} + +export function snapshotPath(typeStr: string): string { + return join(SNAPSHOT_DIR, snapshotName(typeStr)); +} + +/// Self-describing snapshot payload (the `type` is stored so files are +/// readable / debuggable on their own). +export interface Snapshot { + type: string; + data_type: unknown; +} diff --git a/type-parser/mini-parser-ts/test/snapshots/00b95dd2fc4a3cb1.json b/type-parser/mini-parser-ts/test/snapshots/00b95dd2fc4a3cb1.json new file mode 100644 index 000000000..715dc4123 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/00b95dd2fc4a3cb1.json @@ -0,0 +1,53 @@ +{ + "type": "Array(Tuple(LowCardinality(String), Array(Nullable(Decimal(18, 4)))))", + "data_type": { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "TupleDataType", + "name": "Tuple", + "arguments": [ + { + "type": "DataType", + "name": "LowCardinality", + "arguments": [ + { + "type": "DataType", + "name": "String" + } + ] + }, + { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "DataType", + "name": "Decimal", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "18" + }, + { + "type": "Literal", + "value_type": "UInt64", + "value": "4" + } + ] + } + ] + } + ] + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/00ce7d22d518eb3d.json b/type-parser/mini-parser-ts/test/snapshots/00ce7d22d518eb3d.json new file mode 100644 index 000000000..e47784418 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/00ce7d22d518eb3d.json @@ -0,0 +1,19 @@ +{ + "type": "Array(Array(String))", + "data_type": { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "String" + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/01dc6abd5a2822d1.json b/type-parser/mini-parser-ts/test/snapshots/01dc6abd5a2822d1.json new file mode 100644 index 000000000..224761c8c --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/01dc6abd5a2822d1.json @@ -0,0 +1,55 @@ +{ + "type": "Array(Array(Array(Tuple(UInt8, Nullable(String), Map(String, Float64)))))", + "data_type": { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "TupleDataType", + "name": "Tuple", + "arguments": [ + { + "type": "DataType", + "name": "UInt8" + }, + { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "DataType", + "name": "String" + } + ] + }, + { + "type": "DataType", + "name": "Map", + "arguments": [ + { + "type": "DataType", + "name": "String" + }, + { + "type": "DataType", + "name": "Float64" + } + ] + } + ] + } + ] + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/0282a2e2726b5fdb.json b/type-parser/mini-parser-ts/test/snapshots/0282a2e2726b5fdb.json new file mode 100644 index 000000000..a62d233e2 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/0282a2e2726b5fdb.json @@ -0,0 +1,7 @@ +{ + "type": "DOUBLE PRECISION", + "data_type": { + "type": "DataType", + "name": "DOUBLE PRECISION" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/02bdf07c09cc39a9.json b/type-parser/mini-parser-ts/test/snapshots/02bdf07c09cc39a9.json new file mode 100644 index 000000000..8514028aa --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/02bdf07c09cc39a9.json @@ -0,0 +1,31 @@ +{ + "type": "Nested(key String, value Array(UInt8))", + "data_type": { + "type": "DataType", + "name": "Nested", + "arguments": [ + { + "type": "NameTypePair", + "name": "key", + "data_type": { + "type": "DataType", + "name": "String" + } + }, + { + "type": "NameTypePair", + "name": "value", + "data_type": { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "UInt8" + } + ] + } + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/03f2221a84fa9cb6.json b/type-parser/mini-parser-ts/test/snapshots/03f2221a84fa9cb6.json new file mode 100644 index 000000000..cd1b9ff44 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/03f2221a84fa9cb6.json @@ -0,0 +1,14 @@ +{ + "type": "FixedString(128)", + "data_type": { + "type": "DataType", + "name": "FixedString", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "128" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/05b87974a3b9b844.json b/type-parser/mini-parser-ts/test/snapshots/05b87974a3b9b844.json new file mode 100644 index 000000000..94cac05cb --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/05b87974a3b9b844.json @@ -0,0 +1,49 @@ +{ + "type": "Array(Map(String, Tuple(a UInt8, b Array(Nullable(String)))))", + "data_type": { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "Map", + "arguments": [ + { + "type": "DataType", + "name": "String" + }, + { + "type": "TupleDataType", + "name": "Tuple", + "arguments": [ + { + "type": "DataType", + "name": "UInt8" + }, + { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "DataType", + "name": "String" + } + ] + } + ] + } + ], + "element_names": [ + "a", + "b" + ] + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/06083c5d1e0fb4b0.json b/type-parser/mini-parser-ts/test/snapshots/06083c5d1e0fb4b0.json new file mode 100644 index 000000000..ce688c80a --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/06083c5d1e0fb4b0.json @@ -0,0 +1,55 @@ +{ + "type": "Tuple(Array(Int32), Map(String, Float64), Nullable(DateTime64(3, 'UTC')))", + "data_type": { + "type": "TupleDataType", + "name": "Tuple", + "arguments": [ + { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "Int32" + } + ] + }, + { + "type": "DataType", + "name": "Map", + "arguments": [ + { + "type": "DataType", + "name": "String" + }, + { + "type": "DataType", + "name": "Float64" + } + ] + }, + { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "DataType", + "name": "DateTime64", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "3" + }, + { + "type": "Literal", + "value_type": "String", + "value": "UTC" + } + ] + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/0630ca3355f050df.json b/type-parser/mini-parser-ts/test/snapshots/0630ca3355f050df.json new file mode 100644 index 000000000..9f3297b64 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/0630ca3355f050df.json @@ -0,0 +1,19 @@ +{ + "type": "DateTime64(0, 'America/Los_Angeles')", + "data_type": { + "type": "DataType", + "name": "DateTime64", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "0" + }, + { + "type": "Literal", + "value_type": "String", + "value": "America/Los_Angeles" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/069c4db0034b51e1.json b/type-parser/mini-parser-ts/test/snapshots/069c4db0034b51e1.json new file mode 100644 index 000000000..734d09b18 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/069c4db0034b51e1.json @@ -0,0 +1,35 @@ +{ + "type": "Map(String, Nullable(Decimal(38, 18)))", + "data_type": { + "type": "DataType", + "name": "Map", + "arguments": [ + { + "type": "DataType", + "name": "String" + }, + { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "DataType", + "name": "Decimal", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "38" + }, + { + "type": "Literal", + "value_type": "UInt64", + "value": "18" + } + ] + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/07a4cee5695b7794.json b/type-parser/mini-parser-ts/test/snapshots/07a4cee5695b7794.json new file mode 100644 index 000000000..9d0000031 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/07a4cee5695b7794.json @@ -0,0 +1,13 @@ +{ + "type": "Array(Float64)", + "data_type": { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "Float64" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/07a608893061fe06.json b/type-parser/mini-parser-ts/test/snapshots/07a608893061fe06.json new file mode 100644 index 000000000..7d8ea2713 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/07a608893061fe06.json @@ -0,0 +1,21 @@ +{ + "type": "Tuple(String, UInt64, Float64)", + "data_type": { + "type": "TupleDataType", + "name": "Tuple", + "arguments": [ + { + "type": "DataType", + "name": "String" + }, + { + "type": "DataType", + "name": "UInt64" + }, + { + "type": "DataType", + "name": "Float64" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/08512f086f95145c.json b/type-parser/mini-parser-ts/test/snapshots/08512f086f95145c.json new file mode 100644 index 000000000..577fa9382 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/08512f086f95145c.json @@ -0,0 +1,14 @@ +{ + "type": "FixedString(1)", + "data_type": { + "type": "DataType", + "name": "FixedString", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "1" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/097274c5c7abaa17.json b/type-parser/mini-parser-ts/test/snapshots/097274c5c7abaa17.json new file mode 100644 index 000000000..d3c541938 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/097274c5c7abaa17.json @@ -0,0 +1,7 @@ +{ + "type": "DOUBLE", + "data_type": { + "type": "DataType", + "name": "DOUBLE" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/0a450823c46ccbe3.json b/type-parser/mini-parser-ts/test/snapshots/0a450823c46ccbe3.json new file mode 100644 index 000000000..80a9e1e15 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/0a450823c46ccbe3.json @@ -0,0 +1,19 @@ +{ + "type": "Array(Nullable(String))", + "data_type": { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "DataType", + "name": "String" + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/0aeb95282860cfdf.json b/type-parser/mini-parser-ts/test/snapshots/0aeb95282860cfdf.json new file mode 100644 index 000000000..d4df4a49a --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/0aeb95282860cfdf.json @@ -0,0 +1,25 @@ +{ + "type": "Dynamic(max_types = 32)", + "data_type": { + "type": "DataType", + "name": "Dynamic", + "arguments": [ + { + "type": "Function", + "name": "equals", + "is_operator": true, + "arguments": [ + { + "type": "Identifier", + "name": "max_types" + }, + { + "type": "Literal", + "value_type": "UInt64", + "value": "32" + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/0bed42cd6332cc16.json b/type-parser/mini-parser-ts/test/snapshots/0bed42cd6332cc16.json new file mode 100644 index 000000000..fc5ccb18a --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/0bed42cd6332cc16.json @@ -0,0 +1,14 @@ +{ + "type": "Decimal32(4)", + "data_type": { + "type": "DataType", + "name": "Decimal32", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "4" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/0db54c89682d17c4.json b/type-parser/mini-parser-ts/test/snapshots/0db54c89682d17c4.json new file mode 100644 index 000000000..81025b8d8 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/0db54c89682d17c4.json @@ -0,0 +1,7 @@ +{ + "type": "IntervalDay", + "data_type": { + "type": "DataType", + "name": "IntervalDay" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/0dc646c154d2103e.json b/type-parser/mini-parser-ts/test/snapshots/0dc646c154d2103e.json new file mode 100644 index 000000000..009e3f303 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/0dc646c154d2103e.json @@ -0,0 +1,19 @@ +{ + "type": "Array(Nullable(UInt64))", + "data_type": { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "DataType", + "name": "UInt64" + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/0ee669b87ea0b36a.json b/type-parser/mini-parser-ts/test/snapshots/0ee669b87ea0b36a.json new file mode 100644 index 000000000..a4130c059 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/0ee669b87ea0b36a.json @@ -0,0 +1,23 @@ +{ + "type": "Nullable(Enum8('a' = 1, 'b' = 2))", + "data_type": { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "EnumDataType", + "name": "Enum8", + "values": [ + { + "name": "a", + "value": 1 + }, + { + "name": "b", + "value": 2 + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/0ef4e25fc70c78ee.json b/type-parser/mini-parser-ts/test/snapshots/0ef4e25fc70c78ee.json new file mode 100644 index 000000000..8f6b2a921 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/0ef4e25fc70c78ee.json @@ -0,0 +1,13 @@ +{ + "type": "Nullable(UUID)", + "data_type": { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "DataType", + "name": "UUID" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/0f07cff3e8006379.json b/type-parser/mini-parser-ts/test/snapshots/0f07cff3e8006379.json new file mode 100644 index 000000000..1a6e4abfd --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/0f07cff3e8006379.json @@ -0,0 +1,14 @@ +{ + "type": "DateTime64(2)", + "data_type": { + "type": "DataType", + "name": "DateTime64", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "2" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/0fe37e40e5dab3ac.json b/type-parser/mini-parser-ts/test/snapshots/0fe37e40e5dab3ac.json new file mode 100644 index 000000000..99efae5f2 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/0fe37e40e5dab3ac.json @@ -0,0 +1,7 @@ +{ + "type": "INTEGER", + "data_type": { + "type": "DataType", + "name": "INTEGER" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/10997dcfa0b17169.json b/type-parser/mini-parser-ts/test/snapshots/10997dcfa0b17169.json new file mode 100644 index 000000000..fbb828548 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/10997dcfa0b17169.json @@ -0,0 +1,13 @@ +{ + "type": "LowCardinality(Date32)", + "data_type": { + "type": "DataType", + "name": "LowCardinality", + "arguments": [ + { + "type": "DataType", + "name": "Date32" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/11d240952f22547e.json b/type-parser/mini-parser-ts/test/snapshots/11d240952f22547e.json new file mode 100644 index 000000000..ed4c1a282 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/11d240952f22547e.json @@ -0,0 +1,20 @@ +{ + "type": "LowCardinality(FixedString(32))", + "data_type": { + "type": "DataType", + "name": "LowCardinality", + "arguments": [ + { + "type": "DataType", + "name": "FixedString", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "32" + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/1269b7d5dc9faecd.json b/type-parser/mini-parser-ts/test/snapshots/1269b7d5dc9faecd.json new file mode 100644 index 000000000..cdd92ad14 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/1269b7d5dc9faecd.json @@ -0,0 +1,13 @@ +{ + "type": "Nullable(UInt16)", + "data_type": { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "DataType", + "name": "UInt16" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/128519da85d4b5b8.json b/type-parser/mini-parser-ts/test/snapshots/128519da85d4b5b8.json new file mode 100644 index 000000000..070336265 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/128519da85d4b5b8.json @@ -0,0 +1,25 @@ +{ + "type": "Dynamic(max_types = 5)", + "data_type": { + "type": "DataType", + "name": "Dynamic", + "arguments": [ + { + "type": "Function", + "name": "equals", + "is_operator": true, + "arguments": [ + { + "type": "Identifier", + "name": "max_types" + }, + { + "type": "Literal", + "value_type": "UInt64", + "value": "5" + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/133ca8ecd29f3663.json b/type-parser/mini-parser-ts/test/snapshots/133ca8ecd29f3663.json new file mode 100644 index 000000000..c7de609bc --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/133ca8ecd29f3663.json @@ -0,0 +1,14 @@ +{ + "type": "Decimal256(20)", + "data_type": { + "type": "DataType", + "name": "Decimal256", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "20" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/156e367c7969e103.json b/type-parser/mini-parser-ts/test/snapshots/156e367c7969e103.json new file mode 100644 index 000000000..c3728a1cd --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/156e367c7969e103.json @@ -0,0 +1,14 @@ +{ + "type": "FixedString(16)", + "data_type": { + "type": "DataType", + "name": "FixedString", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "16" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/15ac3a2fa148ab10.json b/type-parser/mini-parser-ts/test/snapshots/15ac3a2fa148ab10.json new file mode 100644 index 000000000..a42b7a5da --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/15ac3a2fa148ab10.json @@ -0,0 +1,17 @@ +{ + "type": "Map(Int32, String)", + "data_type": { + "type": "DataType", + "name": "Map", + "arguments": [ + { + "type": "DataType", + "name": "Int32" + }, + { + "type": "DataType", + "name": "String" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/16b2e8523343d5f3.json b/type-parser/mini-parser-ts/test/snapshots/16b2e8523343d5f3.json new file mode 100644 index 000000000..b54a71908 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/16b2e8523343d5f3.json @@ -0,0 +1,13 @@ +{ + "type": "Array(Polygon)", + "data_type": { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "Polygon" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/16d4d882e66fffc1.json b/type-parser/mini-parser-ts/test/snapshots/16d4d882e66fffc1.json new file mode 100644 index 000000000..cd2a27abd --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/16d4d882e66fffc1.json @@ -0,0 +1,19 @@ +{ + "type": "Decimal(76, 76)", + "data_type": { + "type": "DataType", + "name": "Decimal", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "76" + }, + { + "type": "Literal", + "value_type": "UInt64", + "value": "76" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/174711b74c597654.json b/type-parser/mini-parser-ts/test/snapshots/174711b74c597654.json new file mode 100644 index 000000000..d86f608cf --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/174711b74c597654.json @@ -0,0 +1,17 @@ +{ + "type": "Enum8('neg' = -128, 'pos' = 127)", + "data_type": { + "type": "EnumDataType", + "name": "Enum8", + "values": [ + { + "name": "neg", + "value": -128 + }, + { + "name": "pos", + "value": 127 + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/1800cfa6f2c5cb5c.json b/type-parser/mini-parser-ts/test/snapshots/1800cfa6f2c5cb5c.json new file mode 100644 index 000000000..80ce6ce19 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/1800cfa6f2c5cb5c.json @@ -0,0 +1,14 @@ +{ + "type": "FixedString(64)", + "data_type": { + "type": "DataType", + "name": "FixedString", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "64" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/180fcbe698d0f2c4.json b/type-parser/mini-parser-ts/test/snapshots/180fcbe698d0f2c4.json new file mode 100644 index 000000000..379404e47 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/180fcbe698d0f2c4.json @@ -0,0 +1,7 @@ +{ + "type": "Int64", + "data_type": { + "type": "DataType", + "name": "Int64" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/183de27e0bac77a1.json b/type-parser/mini-parser-ts/test/snapshots/183de27e0bac77a1.json new file mode 100644 index 000000000..24cee1206 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/183de27e0bac77a1.json @@ -0,0 +1,25 @@ +{ + "type": "Dynamic( max_types = 8 )", + "data_type": { + "type": "DataType", + "name": "Dynamic", + "arguments": [ + { + "type": "Function", + "name": "equals", + "is_operator": true, + "arguments": [ + { + "type": "Identifier", + "name": "max_types" + }, + { + "type": "Literal", + "value_type": "UInt64", + "value": "8" + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/19c537c1c1730b4d.json b/type-parser/mini-parser-ts/test/snapshots/19c537c1c1730b4d.json new file mode 100644 index 000000000..ad793ed6d --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/19c537c1c1730b4d.json @@ -0,0 +1,13 @@ +{ + "type": "Nullable(UInt128)", + "data_type": { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "DataType", + "name": "UInt128" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/19e4439f2f9c5c0d.json b/type-parser/mini-parser-ts/test/snapshots/19e4439f2f9c5c0d.json new file mode 100644 index 000000000..c147cf3d2 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/19e4439f2f9c5c0d.json @@ -0,0 +1,7 @@ +{ + "type": "IntervalYear", + "data_type": { + "type": "DataType", + "name": "IntervalYear" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/1a8c9516519ad655.json b/type-parser/mini-parser-ts/test/snapshots/1a8c9516519ad655.json new file mode 100644 index 000000000..c7f3cc218 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/1a8c9516519ad655.json @@ -0,0 +1,19 @@ +{ + "type": "DateTime64(9, 'Asia/Tokyo')", + "data_type": { + "type": "DataType", + "name": "DateTime64", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "9" + }, + { + "type": "Literal", + "value_type": "String", + "value": "Asia/Tokyo" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/1ab3503a837a8b33.json b/type-parser/mini-parser-ts/test/snapshots/1ab3503a837a8b33.json new file mode 100644 index 000000000..47804f599 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/1ab3503a837a8b33.json @@ -0,0 +1,19 @@ +{ + "type": "Decimal(76, 20)", + "data_type": { + "type": "DataType", + "name": "Decimal", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "76" + }, + { + "type": "Literal", + "value_type": "UInt64", + "value": "20" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/1af429358d8dc4cc.json b/type-parser/mini-parser-ts/test/snapshots/1af429358d8dc4cc.json new file mode 100644 index 000000000..03c4923d1 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/1af429358d8dc4cc.json @@ -0,0 +1,13 @@ +{ + "type": "Nullable(UInt256)", + "data_type": { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "DataType", + "name": "UInt256" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/1b1855ddfe121c06.json b/type-parser/mini-parser-ts/test/snapshots/1b1855ddfe121c06.json new file mode 100644 index 000000000..3ba8a444a --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/1b1855ddfe121c06.json @@ -0,0 +1,13 @@ +{ + "type": "Nullable(UInt64)", + "data_type": { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "DataType", + "name": "UInt64" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/1bd2dfcbd0545dd9.json b/type-parser/mini-parser-ts/test/snapshots/1bd2dfcbd0545dd9.json new file mode 100644 index 000000000..302a5adbe --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/1bd2dfcbd0545dd9.json @@ -0,0 +1,17 @@ +{ + "type": "Enum8('' = 0, 'nonempty' = 1)", + "data_type": { + "type": "EnumDataType", + "name": "Enum8", + "values": [ + { + "name": "", + "value": 0 + }, + { + "name": "nonempty", + "value": 1 + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/1c0e4bc11b79399b.json b/type-parser/mini-parser-ts/test/snapshots/1c0e4bc11b79399b.json new file mode 100644 index 000000000..e247d4b36 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/1c0e4bc11b79399b.json @@ -0,0 +1,14 @@ +{ + "type": "DateTime('UTC')", + "data_type": { + "type": "DataType", + "name": "DateTime", + "arguments": [ + { + "type": "Literal", + "value_type": "String", + "value": "UTC" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/1c6d137de6e9cce4.json b/type-parser/mini-parser-ts/test/snapshots/1c6d137de6e9cce4.json new file mode 100644 index 000000000..f9835a369 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/1c6d137de6e9cce4.json @@ -0,0 +1,14 @@ +{ + "type": "DateTime('Europe/Amsterdam')", + "data_type": { + "type": "DataType", + "name": "DateTime", + "arguments": [ + { + "type": "Literal", + "value_type": "String", + "value": "Europe/Amsterdam" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/1ce04f29dadb9973.json b/type-parser/mini-parser-ts/test/snapshots/1ce04f29dadb9973.json new file mode 100644 index 000000000..6670684ff --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/1ce04f29dadb9973.json @@ -0,0 +1,7 @@ +{ + "type": "BLOB", + "data_type": { + "type": "DataType", + "name": "BLOB" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/1d0146114b4a4362.json b/type-parser/mini-parser-ts/test/snapshots/1d0146114b4a4362.json new file mode 100644 index 000000000..2f3b2bc8b --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/1d0146114b4a4362.json @@ -0,0 +1,19 @@ +{ + "type": "DateTime64(3, 'UTC')", + "data_type": { + "type": "DataType", + "name": "DateTime64", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "3" + }, + { + "type": "Literal", + "value_type": "String", + "value": "UTC" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/1d2e38577d2a158e.json b/type-parser/mini-parser-ts/test/snapshots/1d2e38577d2a158e.json new file mode 100644 index 000000000..1431dc809 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/1d2e38577d2a158e.json @@ -0,0 +1,19 @@ +{ + "type": "Decimal(9, 0)", + "data_type": { + "type": "DataType", + "name": "Decimal", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "9" + }, + { + "type": "Literal", + "value_type": "UInt64", + "value": "0" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/1dc79a25ff699c42.json b/type-parser/mini-parser-ts/test/snapshots/1dc79a25ff699c42.json new file mode 100644 index 000000000..eada052a1 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/1dc79a25ff699c42.json @@ -0,0 +1,23 @@ +{ + "type": "Array(Tuple(UInt8, String))", + "data_type": { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "TupleDataType", + "name": "Tuple", + "arguments": [ + { + "type": "DataType", + "name": "UInt8" + }, + { + "type": "DataType", + "name": "String" + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/1e16f998c6447325.json b/type-parser/mini-parser-ts/test/snapshots/1e16f998c6447325.json new file mode 100644 index 000000000..68c0652e3 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/1e16f998c6447325.json @@ -0,0 +1,21 @@ +{ + "type": "Tuple(Int32, Int32, Int32)", + "data_type": { + "type": "TupleDataType", + "name": "Tuple", + "arguments": [ + { + "type": "DataType", + "name": "Int32" + }, + { + "type": "DataType", + "name": "Int32" + }, + { + "type": "DataType", + "name": "Int32" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/20fd836cdfc11886.json b/type-parser/mini-parser-ts/test/snapshots/20fd836cdfc11886.json new file mode 100644 index 000000000..bd43c573e --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/20fd836cdfc11886.json @@ -0,0 +1,19 @@ +{ + "type": "DateTime64( 3 , 'UTC' )", + "data_type": { + "type": "DataType", + "name": "DateTime64", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "3" + }, + { + "type": "Literal", + "value_type": "String", + "value": "UTC" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/21bf75a5255af008.json b/type-parser/mini-parser-ts/test/snapshots/21bf75a5255af008.json new file mode 100644 index 000000000..c2411b87e --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/21bf75a5255af008.json @@ -0,0 +1,7 @@ +{ + "type": "UUID", + "data_type": { + "type": "DataType", + "name": "UUID" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/2208b0f5d5d2aea7.json b/type-parser/mini-parser-ts/test/snapshots/2208b0f5d5d2aea7.json new file mode 100644 index 000000000..c529af56d --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/2208b0f5d5d2aea7.json @@ -0,0 +1,7 @@ +{ + "type": "INTEGER SIGNED", + "data_type": { + "type": "DataType", + "name": "INTEGER SIGNED" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/22aaa82db55ed6cb.json b/type-parser/mini-parser-ts/test/snapshots/22aaa82db55ed6cb.json new file mode 100644 index 000000000..7ac322435 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/22aaa82db55ed6cb.json @@ -0,0 +1,13 @@ +{ + "type": "LowCardinality(UInt64)", + "data_type": { + "type": "DataType", + "name": "LowCardinality", + "arguments": [ + { + "type": "DataType", + "name": "UInt64" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/22ecac851cfb07e9.json b/type-parser/mini-parser-ts/test/snapshots/22ecac851cfb07e9.json new file mode 100644 index 000000000..4064c04d2 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/22ecac851cfb07e9.json @@ -0,0 +1,23 @@ +{ + "type": "Array(Tuple(Float64, Float64))", + "data_type": { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "TupleDataType", + "name": "Tuple", + "arguments": [ + { + "type": "DataType", + "name": "Float64" + }, + { + "type": "DataType", + "name": "Float64" + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/23b36b23f947874d.json b/type-parser/mini-parser-ts/test/snapshots/23b36b23f947874d.json new file mode 100644 index 000000000..74545b4a2 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/23b36b23f947874d.json @@ -0,0 +1,19 @@ +{ + "type": "Decimal(10, 2)", + "data_type": { + "type": "DataType", + "name": "Decimal", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "10" + }, + { + "type": "Literal", + "value_type": "UInt64", + "value": "2" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/2451237b00b13cd7.json b/type-parser/mini-parser-ts/test/snapshots/2451237b00b13cd7.json new file mode 100644 index 000000000..b6b0b5b88 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/2451237b00b13cd7.json @@ -0,0 +1,19 @@ +{ + "type": "Enum8('a', 'b')", + "data_type": { + "type": "DataType", + "name": "Enum8", + "arguments": [ + { + "type": "Literal", + "value_type": "String", + "value": "a" + }, + { + "type": "Literal", + "value_type": "String", + "value": "b" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/261b6d70eaf74bf4.json b/type-parser/mini-parser-ts/test/snapshots/261b6d70eaf74bf4.json new file mode 100644 index 000000000..724d5958f --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/261b6d70eaf74bf4.json @@ -0,0 +1,7 @@ +{ + "type": "BIT", + "data_type": { + "type": "DataType", + "name": "BIT" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/26b32b5b966f2a05.json b/type-parser/mini-parser-ts/test/snapshots/26b32b5b966f2a05.json new file mode 100644 index 000000000..f3719cd85 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/26b32b5b966f2a05.json @@ -0,0 +1,7 @@ +{ + "type": "BINARY LARGE OBJECT", + "data_type": { + "type": "DataType", + "name": "BINARY LARGE OBJECT" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/283e861dc1341e3c.json b/type-parser/mini-parser-ts/test/snapshots/283e861dc1341e3c.json new file mode 100644 index 000000000..a072ea374 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/283e861dc1341e3c.json @@ -0,0 +1,13 @@ +{ + "type": "Array(DateTime)", + "data_type": { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "DateTime" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/292209387fe87cb3.json b/type-parser/mini-parser-ts/test/snapshots/292209387fe87cb3.json new file mode 100644 index 000000000..589704d32 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/292209387fe87cb3.json @@ -0,0 +1,20 @@ +{ + "type": "Nullable(FixedString(16))", + "data_type": { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "DataType", + "name": "FixedString", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "16" + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/292c7af4fff95bcd.json b/type-parser/mini-parser-ts/test/snapshots/292c7af4fff95bcd.json new file mode 100644 index 000000000..5723d591a --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/292c7af4fff95bcd.json @@ -0,0 +1,7 @@ +{ + "type": "BOOL", + "data_type": { + "type": "DataType", + "name": "BOOL" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/2a2dd538a651992b.json b/type-parser/mini-parser-ts/test/snapshots/2a2dd538a651992b.json new file mode 100644 index 000000000..cfcb21e01 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/2a2dd538a651992b.json @@ -0,0 +1,24 @@ +{ + "type": "Enum8('a', 'b', 'c')", + "data_type": { + "type": "DataType", + "name": "Enum8", + "arguments": [ + { + "type": "Literal", + "value_type": "String", + "value": "a" + }, + { + "type": "Literal", + "value_type": "String", + "value": "b" + }, + { + "type": "Literal", + "value_type": "String", + "value": "c" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/2a93a144ad9458ad.json b/type-parser/mini-parser-ts/test/snapshots/2a93a144ad9458ad.json new file mode 100644 index 000000000..e50f9f8aa --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/2a93a144ad9458ad.json @@ -0,0 +1,14 @@ +{ + "type": "FixedString(2)", + "data_type": { + "type": "DataType", + "name": "FixedString", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "2" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/2b759bb1ca791e18.json b/type-parser/mini-parser-ts/test/snapshots/2b759bb1ca791e18.json new file mode 100644 index 000000000..b82ac7b50 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/2b759bb1ca791e18.json @@ -0,0 +1,25 @@ +{ + "type": "Nested(x Int32, y Int32)", + "data_type": { + "type": "DataType", + "name": "Nested", + "arguments": [ + { + "type": "NameTypePair", + "name": "x", + "data_type": { + "type": "DataType", + "name": "Int32" + } + }, + { + "type": "NameTypePair", + "name": "y", + "data_type": { + "type": "DataType", + "name": "Int32" + } + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/2b92c8c85daf51e6.json b/type-parser/mini-parser-ts/test/snapshots/2b92c8c85daf51e6.json new file mode 100644 index 000000000..c9f76a46d --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/2b92c8c85daf51e6.json @@ -0,0 +1,14 @@ +{ + "type": "Decimal32(0)", + "data_type": { + "type": "DataType", + "name": "Decimal32", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "0" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/2bb1b10e295da6ba.json b/type-parser/mini-parser-ts/test/snapshots/2bb1b10e295da6ba.json new file mode 100644 index 000000000..3abdaeb1e --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/2bb1b10e295da6ba.json @@ -0,0 +1,33 @@ +{ + "type": "Tuple(UInt8, String, Float64, Date, UUID, Bool)", + "data_type": { + "type": "TupleDataType", + "name": "Tuple", + "arguments": [ + { + "type": "DataType", + "name": "UInt8" + }, + { + "type": "DataType", + "name": "String" + }, + { + "type": "DataType", + "name": "Float64" + }, + { + "type": "DataType", + "name": "Date" + }, + { + "type": "DataType", + "name": "UUID" + }, + { + "type": "DataType", + "name": "Bool" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/2cad1f5221666485.json b/type-parser/mini-parser-ts/test/snapshots/2cad1f5221666485.json new file mode 100644 index 000000000..ea00ef943 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/2cad1f5221666485.json @@ -0,0 +1,20 @@ +{ + "type": "LowCardinality(FixedString(8))", + "data_type": { + "type": "DataType", + "name": "LowCardinality", + "arguments": [ + { + "type": "DataType", + "name": "FixedString", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "8" + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/2d0fe684054a5388.json b/type-parser/mini-parser-ts/test/snapshots/2d0fe684054a5388.json new file mode 100644 index 000000000..7bdf44ee4 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/2d0fe684054a5388.json @@ -0,0 +1,7 @@ +{ + "type": "BIGINT", + "data_type": { + "type": "DataType", + "name": "BIGINT" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/2d50b2d54d49e844.json b/type-parser/mini-parser-ts/test/snapshots/2d50b2d54d49e844.json new file mode 100644 index 000000000..e4c48e675 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/2d50b2d54d49e844.json @@ -0,0 +1,43 @@ +{ + "type": "Nested(outer UInt8, inner Nested(a UInt8, b String))", + "data_type": { + "type": "DataType", + "name": "Nested", + "arguments": [ + { + "type": "NameTypePair", + "name": "outer", + "data_type": { + "type": "DataType", + "name": "UInt8" + } + }, + { + "type": "NameTypePair", + "name": "inner", + "data_type": { + "type": "DataType", + "name": "Nested", + "arguments": [ + { + "type": "NameTypePair", + "name": "a", + "data_type": { + "type": "DataType", + "name": "UInt8" + } + }, + { + "type": "NameTypePair", + "name": "b", + "data_type": { + "type": "DataType", + "name": "String" + } + } + ] + } + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/2ecf89a293cd698f.json b/type-parser/mini-parser-ts/test/snapshots/2ecf89a293cd698f.json new file mode 100644 index 000000000..3924dafdc --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/2ecf89a293cd698f.json @@ -0,0 +1,23 @@ +{ + "type": "Array(Enum8('a' = 1, 'b' = 2))", + "data_type": { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "EnumDataType", + "name": "Enum8", + "values": [ + { + "name": "a", + "value": 1 + }, + { + "name": "b", + "value": 2 + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/2f058b0d7c8ff211.json b/type-parser/mini-parser-ts/test/snapshots/2f058b0d7c8ff211.json new file mode 100644 index 000000000..5c149a845 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/2f058b0d7c8ff211.json @@ -0,0 +1,21 @@ +{ + "type": "Enum16('x' = -1, 'y' = 100, 'z' = 1000)", + "data_type": { + "type": "EnumDataType", + "name": "Enum16", + "values": [ + { + "name": "x", + "value": -1 + }, + { + "name": "y", + "value": 100 + }, + { + "name": "z", + "value": 1000 + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/2f446fedbc924375.json b/type-parser/mini-parser-ts/test/snapshots/2f446fedbc924375.json new file mode 100644 index 000000000..c167252f8 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/2f446fedbc924375.json @@ -0,0 +1,7 @@ +{ + "type": "INT(10) UNSIGNED", + "data_type": { + "type": "DataType", + "name": "INT UNSIGNED" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/2f76fee2db93cfc2.json b/type-parser/mini-parser-ts/test/snapshots/2f76fee2db93cfc2.json new file mode 100644 index 000000000..65b7c7a97 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/2f76fee2db93cfc2.json @@ -0,0 +1,13 @@ +{ + "type": "LowCardinality(UInt8)", + "data_type": { + "type": "DataType", + "name": "LowCardinality", + "arguments": [ + { + "type": "DataType", + "name": "UInt8" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/2ffb7489d68e87c9.json b/type-parser/mini-parser-ts/test/snapshots/2ffb7489d68e87c9.json new file mode 100644 index 000000000..97fbe1969 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/2ffb7489d68e87c9.json @@ -0,0 +1,14 @@ +{ + "type": "Decimal64(18)", + "data_type": { + "type": "DataType", + "name": "Decimal64", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "18" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/30a77c9b71a45749.json b/type-parser/mini-parser-ts/test/snapshots/30a77c9b71a45749.json new file mode 100644 index 000000000..2f324c0fb --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/30a77c9b71a45749.json @@ -0,0 +1,19 @@ +{ + "type": "Decimal(38, 10)", + "data_type": { + "type": "DataType", + "name": "Decimal", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "38" + }, + { + "type": "Literal", + "value_type": "UInt64", + "value": "10" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/314040aa10c72b02.json b/type-parser/mini-parser-ts/test/snapshots/314040aa10c72b02.json new file mode 100644 index 000000000..0da1ed2cd --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/314040aa10c72b02.json @@ -0,0 +1,17 @@ +{ + "type": "Variant(Int32, Float64)", + "data_type": { + "type": "DataType", + "name": "Variant", + "arguments": [ + { + "type": "DataType", + "name": "Int32" + }, + { + "type": "DataType", + "name": "Float64" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/33888e8184bce3d1.json b/type-parser/mini-parser-ts/test/snapshots/33888e8184bce3d1.json new file mode 100644 index 000000000..596d24a1c --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/33888e8184bce3d1.json @@ -0,0 +1,7 @@ +{ + "type": "MEDIUMTEXT", + "data_type": { + "type": "DataType", + "name": "MEDIUMTEXT" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/343587b20a4bf691.json b/type-parser/mini-parser-ts/test/snapshots/343587b20a4bf691.json new file mode 100644 index 000000000..7cdb06847 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/343587b20a4bf691.json @@ -0,0 +1,7 @@ +{ + "type": "NATIONAL CHARACTER", + "data_type": { + "type": "DataType", + "name": "NATIONAL CHARACTER" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/35d5fb175bed4093.json b/type-parser/mini-parser-ts/test/snapshots/35d5fb175bed4093.json new file mode 100644 index 000000000..6dd86839f --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/35d5fb175bed4093.json @@ -0,0 +1,13 @@ +{ + "type": "Array(String)", + "data_type": { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "String" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/36af8609901f12c8.json b/type-parser/mini-parser-ts/test/snapshots/36af8609901f12c8.json new file mode 100644 index 000000000..4698c9cfd --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/36af8609901f12c8.json @@ -0,0 +1,7 @@ +{ + "type": "IntervalMillisecond", + "data_type": { + "type": "DataType", + "name": "IntervalMillisecond" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/36c3682fea89a80a.json b/type-parser/mini-parser-ts/test/snapshots/36c3682fea89a80a.json new file mode 100644 index 000000000..d5427dbe5 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/36c3682fea89a80a.json @@ -0,0 +1,19 @@ +{ + "type": "DEC(10, 2)", + "data_type": { + "type": "DataType", + "name": "DEC", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "10" + }, + { + "type": "Literal", + "value_type": "UInt64", + "value": "2" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/3720deb1bdd5e553.json b/type-parser/mini-parser-ts/test/snapshots/3720deb1bdd5e553.json new file mode 100644 index 000000000..1985338c6 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/3720deb1bdd5e553.json @@ -0,0 +1,20 @@ +{ + "type": "Nullable(DateTime('UTC'))", + "data_type": { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "DataType", + "name": "DateTime", + "arguments": [ + { + "type": "Literal", + "value_type": "String", + "value": "UTC" + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/387bc74e5d2ed508.json b/type-parser/mini-parser-ts/test/snapshots/387bc74e5d2ed508.json new file mode 100644 index 000000000..838ce2c41 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/387bc74e5d2ed508.json @@ -0,0 +1,13 @@ +{ + "type": "Array(Bool)", + "data_type": { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "Bool" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/388c0a082cfd7817.json b/type-parser/mini-parser-ts/test/snapshots/388c0a082cfd7817.json new file mode 100644 index 000000000..0949926ff --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/388c0a082cfd7817.json @@ -0,0 +1,37 @@ +{ + "type": "Map(Int64, Variant(String, UInt64, Array(Float64)))", + "data_type": { + "type": "DataType", + "name": "Map", + "arguments": [ + { + "type": "DataType", + "name": "Int64" + }, + { + "type": "DataType", + "name": "Variant", + "arguments": [ + { + "type": "DataType", + "name": "String" + }, + { + "type": "DataType", + "name": "UInt64" + }, + { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "Float64" + } + ] + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/3967d5ba8569635b.json b/type-parser/mini-parser-ts/test/snapshots/3967d5ba8569635b.json new file mode 100644 index 000000000..7053d41b2 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/3967d5ba8569635b.json @@ -0,0 +1,19 @@ +{ + "type": "Decimal(18, 4)", + "data_type": { + "type": "DataType", + "name": "Decimal", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "18" + }, + { + "type": "Literal", + "value_type": "UInt64", + "value": "4" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/3a8bb11d808ae810.json b/type-parser/mini-parser-ts/test/snapshots/3a8bb11d808ae810.json new file mode 100644 index 000000000..2f2e6bb02 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/3a8bb11d808ae810.json @@ -0,0 +1,14 @@ +{ + "type": "DateTime64(9)", + "data_type": { + "type": "DataType", + "name": "DateTime64", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "9" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/3ae9dd8952516f33.json b/type-parser/mini-parser-ts/test/snapshots/3ae9dd8952516f33.json new file mode 100644 index 000000000..88f628ac5 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/3ae9dd8952516f33.json @@ -0,0 +1,14 @@ +{ + "type": "DateTime64(0)", + "data_type": { + "type": "DataType", + "name": "DateTime64", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "0" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/3b330731a188b19f.json b/type-parser/mini-parser-ts/test/snapshots/3b330731a188b19f.json new file mode 100644 index 000000000..9c963d6b7 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/3b330731a188b19f.json @@ -0,0 +1,7 @@ +{ + "type": "REAL", + "data_type": { + "type": "DataType", + "name": "REAL" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/3b7f131c8d41638e.json b/type-parser/mini-parser-ts/test/snapshots/3b7f131c8d41638e.json new file mode 100644 index 000000000..e08e64879 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/3b7f131c8d41638e.json @@ -0,0 +1,13 @@ +{ + "type": "Tuple(UInt8)", + "data_type": { + "type": "TupleDataType", + "name": "Tuple", + "arguments": [ + { + "type": "DataType", + "name": "UInt8" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/3badd67bde55d4f2.json b/type-parser/mini-parser-ts/test/snapshots/3badd67bde55d4f2.json new file mode 100644 index 000000000..ae186d592 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/3badd67bde55d4f2.json @@ -0,0 +1,49 @@ +{ + "type": "Map(String, Array(Tuple(id UInt64, vals Array(Nullable(Float64)))))", + "data_type": { + "type": "DataType", + "name": "Map", + "arguments": [ + { + "type": "DataType", + "name": "String" + }, + { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "TupleDataType", + "name": "Tuple", + "arguments": [ + { + "type": "DataType", + "name": "UInt64" + }, + { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "DataType", + "name": "Float64" + } + ] + } + ] + } + ], + "element_names": [ + "id", + "vals" + ] + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/3c4d1905119c3883.json b/type-parser/mini-parser-ts/test/snapshots/3c4d1905119c3883.json new file mode 100644 index 000000000..93a30f5c1 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/3c4d1905119c3883.json @@ -0,0 +1,14 @@ +{ + "type": "FixedString(8)", + "data_type": { + "type": "DataType", + "name": "FixedString", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "8" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/3ce40017fe0513c0.json b/type-parser/mini-parser-ts/test/snapshots/3ce40017fe0513c0.json new file mode 100644 index 000000000..d0d4c26b3 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/3ce40017fe0513c0.json @@ -0,0 +1,51 @@ +{ + "type": "Nested(coords Tuple(lat Float64, lon Float64), labels Array(LowCardinality(String)))", + "data_type": { + "type": "DataType", + "name": "Nested", + "arguments": [ + { + "type": "NameTypePair", + "name": "coords", + "data_type": { + "type": "TupleDataType", + "name": "Tuple", + "arguments": [ + { + "type": "DataType", + "name": "Float64" + }, + { + "type": "DataType", + "name": "Float64" + } + ], + "element_names": [ + "lat", + "lon" + ] + } + }, + { + "type": "NameTypePair", + "name": "labels", + "data_type": { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "LowCardinality", + "arguments": [ + { + "type": "DataType", + "name": "String" + } + ] + } + ] + } + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/3d0564f65e2951d7.json b/type-parser/mini-parser-ts/test/snapshots/3d0564f65e2951d7.json new file mode 100644 index 000000000..5fcedf904 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/3d0564f65e2951d7.json @@ -0,0 +1,39 @@ +{ + "type": "Nested(a UInt8, b Tuple(x Int8, y Int8))", + "data_type": { + "type": "DataType", + "name": "Nested", + "arguments": [ + { + "type": "NameTypePair", + "name": "a", + "data_type": { + "type": "DataType", + "name": "UInt8" + } + }, + { + "type": "NameTypePair", + "name": "b", + "data_type": { + "type": "TupleDataType", + "name": "Tuple", + "arguments": [ + { + "type": "DataType", + "name": "Int8" + }, + { + "type": "DataType", + "name": "Int8" + } + ], + "element_names": [ + "x", + "y" + ] + } + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/3d40c376159dc070.json b/type-parser/mini-parser-ts/test/snapshots/3d40c376159dc070.json new file mode 100644 index 000000000..7a0b2037f --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/3d40c376159dc070.json @@ -0,0 +1,26 @@ +{ + "type": "Tuple(first String, second String, third String)", + "data_type": { + "type": "TupleDataType", + "name": "Tuple", + "arguments": [ + { + "type": "DataType", + "name": "String" + }, + { + "type": "DataType", + "name": "String" + }, + { + "type": "DataType", + "name": "String" + } + ], + "element_names": [ + "first", + "second", + "third" + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/3df63b7acb0522da.json b/type-parser/mini-parser-ts/test/snapshots/3df63b7acb0522da.json new file mode 100644 index 000000000..e2c1caf69 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/3df63b7acb0522da.json @@ -0,0 +1,7 @@ +{ + "type": "String", + "data_type": { + "type": "DataType", + "name": "String" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/3e2d739f398d42c7.json b/type-parser/mini-parser-ts/test/snapshots/3e2d739f398d42c7.json new file mode 100644 index 000000000..a6bdaa28f --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/3e2d739f398d42c7.json @@ -0,0 +1,21 @@ +{ + "type": "Enum8('a' = 1, 'b' = 2, 'c' = 3)", + "data_type": { + "type": "EnumDataType", + "name": "Enum8", + "values": [ + { + "name": "a", + "value": 1 + }, + { + "name": "b", + "value": 2 + }, + { + "name": "c", + "value": 3 + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/3eb94c999f391ca9.json b/type-parser/mini-parser-ts/test/snapshots/3eb94c999f391ca9.json new file mode 100644 index 000000000..dd9e1fd0e --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/3eb94c999f391ca9.json @@ -0,0 +1,14 @@ +{ + "type": "DateTime64(8)", + "data_type": { + "type": "DataType", + "name": "DateTime64", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "8" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/401053f5f7236705.json b/type-parser/mini-parser-ts/test/snapshots/401053f5f7236705.json new file mode 100644 index 000000000..f4c496cd7 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/401053f5f7236705.json @@ -0,0 +1,13 @@ +{ + "type": "LowCardinality(Int32)", + "data_type": { + "type": "DataType", + "name": "LowCardinality", + "arguments": [ + { + "type": "DataType", + "name": "Int32" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/406c62c428cea57a.json b/type-parser/mini-parser-ts/test/snapshots/406c62c428cea57a.json new file mode 100644 index 000000000..404b8d1a8 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/406c62c428cea57a.json @@ -0,0 +1,20 @@ +{ + "type": "Nullable(Decimal256(40))", + "data_type": { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "DataType", + "name": "Decimal256", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "40" + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/435de109befc994a.json b/type-parser/mini-parser-ts/test/snapshots/435de109befc994a.json new file mode 100644 index 000000000..62e741ead --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/435de109befc994a.json @@ -0,0 +1,20 @@ +{ + "type": "Nullable(Decimal64(4))", + "data_type": { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "DataType", + "name": "Decimal64", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "4" + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/44af40134bf9392d.json b/type-parser/mini-parser-ts/test/snapshots/44af40134bf9392d.json new file mode 100644 index 000000000..ead222017 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/44af40134bf9392d.json @@ -0,0 +1,14 @@ +{ + "type": "Decimal256(0)", + "data_type": { + "type": "DataType", + "name": "Decimal256", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "0" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/44b693037c5f8e61.json b/type-parser/mini-parser-ts/test/snapshots/44b693037c5f8e61.json new file mode 100644 index 000000000..6a099da41 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/44b693037c5f8e61.json @@ -0,0 +1,25 @@ +{ + "type": "Tuple(UInt8, UInt16, UInt32, UInt64)", + "data_type": { + "type": "TupleDataType", + "name": "Tuple", + "arguments": [ + { + "type": "DataType", + "name": "UInt8" + }, + { + "type": "DataType", + "name": "UInt16" + }, + { + "type": "DataType", + "name": "UInt32" + }, + { + "type": "DataType", + "name": "UInt64" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/454656691c92b81b.json b/type-parser/mini-parser-ts/test/snapshots/454656691c92b81b.json new file mode 100644 index 000000000..7ba5b25a7 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/454656691c92b81b.json @@ -0,0 +1,14 @@ +{ + "type": "Decimal64(4)", + "data_type": { + "type": "DataType", + "name": "Decimal64", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "4" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/45e2c84f9ca77549.json b/type-parser/mini-parser-ts/test/snapshots/45e2c84f9ca77549.json new file mode 100644 index 000000000..756b6ff1e --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/45e2c84f9ca77549.json @@ -0,0 +1,19 @@ +{ + "type": "DateTime64(6, 'Europe/Amsterdam')", + "data_type": { + "type": "DataType", + "name": "DateTime64", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "6" + }, + { + "type": "Literal", + "value_type": "String", + "value": "Europe/Amsterdam" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/46e27f45db2bf7c7.json b/type-parser/mini-parser-ts/test/snapshots/46e27f45db2bf7c7.json new file mode 100644 index 000000000..aafab924a --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/46e27f45db2bf7c7.json @@ -0,0 +1,33 @@ +{ + "type": "Array(Variant(UInt64, String, Array(Float64)))", + "data_type": { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "Variant", + "arguments": [ + { + "type": "DataType", + "name": "UInt64" + }, + { + "type": "DataType", + "name": "String" + }, + { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "Float64" + } + ] + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/46f8ab7c0cff9df7.json b/type-parser/mini-parser-ts/test/snapshots/46f8ab7c0cff9df7.json new file mode 100644 index 000000000..6d18d21d4 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/46f8ab7c0cff9df7.json @@ -0,0 +1,7 @@ +{ + "type": "int", + "data_type": { + "type": "DataType", + "name": "int" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/4736033ecebeb570.json b/type-parser/mini-parser-ts/test/snapshots/4736033ecebeb570.json new file mode 100644 index 000000000..6d354254d --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/4736033ecebeb570.json @@ -0,0 +1,19 @@ +{ + "type": "Decimal(10,2)", + "data_type": { + "type": "DataType", + "name": "Decimal", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "10" + }, + { + "type": "Literal", + "value_type": "UInt64", + "value": "2" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/49101d78947d3702.json b/type-parser/mini-parser-ts/test/snapshots/49101d78947d3702.json new file mode 100644 index 000000000..c2f5300e7 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/49101d78947d3702.json @@ -0,0 +1,14 @@ +{ + "type": "FixedString(256)", + "data_type": { + "type": "DataType", + "name": "FixedString", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "256" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/49279edf04879138.json b/type-parser/mini-parser-ts/test/snapshots/49279edf04879138.json new file mode 100644 index 000000000..0a41c9f1d --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/49279edf04879138.json @@ -0,0 +1,7 @@ +{ + "type": "CHAR", + "data_type": { + "type": "DataType", + "name": "CHAR" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/49718b649da090b8.json b/type-parser/mini-parser-ts/test/snapshots/49718b649da090b8.json new file mode 100644 index 000000000..100bd4712 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/49718b649da090b8.json @@ -0,0 +1,23 @@ +{ + "type": "Map(LowCardinality(String), UInt32)", + "data_type": { + "type": "DataType", + "name": "Map", + "arguments": [ + { + "type": "DataType", + "name": "LowCardinality", + "arguments": [ + { + "type": "DataType", + "name": "String" + } + ] + }, + { + "type": "DataType", + "name": "UInt32" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/49f72ed44502ec22.json b/type-parser/mini-parser-ts/test/snapshots/49f72ed44502ec22.json new file mode 100644 index 000000000..97b2cf30d --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/49f72ed44502ec22.json @@ -0,0 +1,37 @@ +{ + "type": "Array(Array(Nullable(Decimal(18, 4))))", + "data_type": { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "DataType", + "name": "Decimal", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "18" + }, + { + "type": "Literal", + "value_type": "UInt64", + "value": "4" + } + ] + } + ] + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/4b1c0b5b55c6eeae.json b/type-parser/mini-parser-ts/test/snapshots/4b1c0b5b55c6eeae.json new file mode 100644 index 000000000..c89c7ae96 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/4b1c0b5b55c6eeae.json @@ -0,0 +1,25 @@ +{ + "type": "Nested(a UInt8, b String)", + "data_type": { + "type": "DataType", + "name": "Nested", + "arguments": [ + { + "type": "NameTypePair", + "name": "a", + "data_type": { + "type": "DataType", + "name": "UInt8" + } + }, + { + "type": "NameTypePair", + "name": "b", + "data_type": { + "type": "DataType", + "name": "String" + } + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/4b2e0d29c996e5d4.json b/type-parser/mini-parser-ts/test/snapshots/4b2e0d29c996e5d4.json new file mode 100644 index 000000000..91a93c179 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/4b2e0d29c996e5d4.json @@ -0,0 +1,14 @@ +{ + "type": "Time64(6)", + "data_type": { + "type": "DataType", + "name": "Time64", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "6" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/4c5840cb7dad0940.json b/type-parser/mini-parser-ts/test/snapshots/4c5840cb7dad0940.json new file mode 100644 index 000000000..965bdff7b --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/4c5840cb7dad0940.json @@ -0,0 +1,31 @@ +{ + "type": "Tuple(a UInt8, b UInt16, c UInt32, d UInt64)", + "data_type": { + "type": "TupleDataType", + "name": "Tuple", + "arguments": [ + { + "type": "DataType", + "name": "UInt8" + }, + { + "type": "DataType", + "name": "UInt16" + }, + { + "type": "DataType", + "name": "UInt32" + }, + { + "type": "DataType", + "name": "UInt64" + } + ], + "element_names": [ + "a", + "b", + "c", + "d" + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/4c7aa27b65521bcf.json b/type-parser/mini-parser-ts/test/snapshots/4c7aa27b65521bcf.json new file mode 100644 index 000000000..ff4d772a7 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/4c7aa27b65521bcf.json @@ -0,0 +1,14 @@ +{ + "type": "DateTime64(4)", + "data_type": { + "type": "DataType", + "name": "DateTime64", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "4" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/4d0c622ecdd58854.json b/type-parser/mini-parser-ts/test/snapshots/4d0c622ecdd58854.json new file mode 100644 index 000000000..c3acd218c --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/4d0c622ecdd58854.json @@ -0,0 +1,35 @@ +{ + "type": "Tuple(a Tuple(x UInt8, y UInt8), b String)", + "data_type": { + "type": "TupleDataType", + "name": "Tuple", + "arguments": [ + { + "type": "TupleDataType", + "name": "Tuple", + "arguments": [ + { + "type": "DataType", + "name": "UInt8" + }, + { + "type": "DataType", + "name": "UInt8" + } + ], + "element_names": [ + "x", + "y" + ] + }, + { + "type": "DataType", + "name": "String" + } + ], + "element_names": [ + "a", + "b" + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/4dc8e18720867887.json b/type-parser/mini-parser-ts/test/snapshots/4dc8e18720867887.json new file mode 100644 index 000000000..318978843 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/4dc8e18720867887.json @@ -0,0 +1,21 @@ +{ + "type": "Enum8('x' = -1, 'y' = 0, 'z' = 1)", + "data_type": { + "type": "EnumDataType", + "name": "Enum8", + "values": [ + { + "name": "x", + "value": -1 + }, + { + "name": "y", + "value": 0 + }, + { + "name": "z", + "value": 1 + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/4e5e15828b576fc3.json b/type-parser/mini-parser-ts/test/snapshots/4e5e15828b576fc3.json new file mode 100644 index 000000000..a86b3617d --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/4e5e15828b576fc3.json @@ -0,0 +1,62 @@ +{ + "type": "Map(FixedString(16), Tuple(a Decimal(38, 10), b Array(LowCardinality(String))))", + "data_type": { + "type": "DataType", + "name": "Map", + "arguments": [ + { + "type": "DataType", + "name": "FixedString", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "16" + } + ] + }, + { + "type": "TupleDataType", + "name": "Tuple", + "arguments": [ + { + "type": "DataType", + "name": "Decimal", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "38" + }, + { + "type": "Literal", + "value_type": "UInt64", + "value": "10" + } + ] + }, + { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "LowCardinality", + "arguments": [ + { + "type": "DataType", + "name": "String" + } + ] + } + ] + } + ], + "element_names": [ + "a", + "b" + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/4f2b2ad192957150.json b/type-parser/mini-parser-ts/test/snapshots/4f2b2ad192957150.json new file mode 100644 index 000000000..092c8746e --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/4f2b2ad192957150.json @@ -0,0 +1,19 @@ +{ + "type": "Decimal( 10 , 2 )", + "data_type": { + "type": "DataType", + "name": "Decimal", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "10" + }, + { + "type": "Literal", + "value_type": "UInt64", + "value": "2" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/4fe5a3682f802978.json b/type-parser/mini-parser-ts/test/snapshots/4fe5a3682f802978.json new file mode 100644 index 000000000..df7a6a24b --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/4fe5a3682f802978.json @@ -0,0 +1,7 @@ +{ + "type": "TINYINT", + "data_type": { + "type": "DataType", + "name": "TINYINT" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/501529315784089e.json b/type-parser/mini-parser-ts/test/snapshots/501529315784089e.json new file mode 100644 index 000000000..bbc44d77c --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/501529315784089e.json @@ -0,0 +1,13 @@ +{ + "type": "Array(UInt8)", + "data_type": { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "UInt8" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/503d0c06e75dd73f.json b/type-parser/mini-parser-ts/test/snapshots/503d0c06e75dd73f.json new file mode 100644 index 000000000..83675d6db --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/503d0c06e75dd73f.json @@ -0,0 +1,13 @@ +{ + "type": "Nullable(Float32)", + "data_type": { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "DataType", + "name": "Float32" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/50876ef35975fe08.json b/type-parser/mini-parser-ts/test/snapshots/50876ef35975fe08.json new file mode 100644 index 000000000..378a01cc8 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/50876ef35975fe08.json @@ -0,0 +1,7 @@ +{ + "type": "NCHAR", + "data_type": { + "type": "DataType", + "name": "NCHAR" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/508ec6552e77fe7d.json b/type-parser/mini-parser-ts/test/snapshots/508ec6552e77fe7d.json new file mode 100644 index 000000000..d5cd7124e --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/508ec6552e77fe7d.json @@ -0,0 +1,26 @@ +{ + "type": "LowCardinality(Nullable(FixedString(8)))", + "data_type": { + "type": "DataType", + "name": "LowCardinality", + "arguments": [ + { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "DataType", + "name": "FixedString", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "8" + } + ] + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/5094f81299f4d418.json b/type-parser/mini-parser-ts/test/snapshots/5094f81299f4d418.json new file mode 100644 index 000000000..30295ecc8 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/5094f81299f4d418.json @@ -0,0 +1,14 @@ +{ + "type": "Decimal128(0)", + "data_type": { + "type": "DataType", + "name": "Decimal128", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "0" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/51b1bf12f2eef86f.json b/type-parser/mini-parser-ts/test/snapshots/51b1bf12f2eef86f.json new file mode 100644 index 000000000..c7a2922b6 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/51b1bf12f2eef86f.json @@ -0,0 +1,14 @@ +{ + "type": "DateTime64(1)", + "data_type": { + "type": "DataType", + "name": "DateTime64", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "1" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/51db33fb52b4c790.json b/type-parser/mini-parser-ts/test/snapshots/51db33fb52b4c790.json new file mode 100644 index 000000000..8aaab9d1e --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/51db33fb52b4c790.json @@ -0,0 +1,7 @@ +{ + "type": "INT SIGNED", + "data_type": { + "type": "DataType", + "name": "INT SIGNED" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/52708f106b39ca6d.json b/type-parser/mini-parser-ts/test/snapshots/52708f106b39ca6d.json new file mode 100644 index 000000000..91cc0c3bb --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/52708f106b39ca6d.json @@ -0,0 +1,13 @@ +{ + "type": "Array(Date)", + "data_type": { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "Date" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/54b047d7967410c4.json b/type-parser/mini-parser-ts/test/snapshots/54b047d7967410c4.json new file mode 100644 index 000000000..1dce59da7 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/54b047d7967410c4.json @@ -0,0 +1,25 @@ +{ + "type": "Array(DateTime64(3, 'UTC'))", + "data_type": { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "DateTime64", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "3" + }, + { + "type": "Literal", + "value_type": "String", + "value": "UTC" + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/55042c80818a5432.json b/type-parser/mini-parser-ts/test/snapshots/55042c80818a5432.json new file mode 100644 index 000000000..1c46d499d --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/55042c80818a5432.json @@ -0,0 +1,7 @@ +{ + "type": "IntervalNanosecond", + "data_type": { + "type": "DataType", + "name": "IntervalNanosecond" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/55c5d81017a30edf.json b/type-parser/mini-parser-ts/test/snapshots/55c5d81017a30edf.json new file mode 100644 index 000000000..cf413b37b --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/55c5d81017a30edf.json @@ -0,0 +1,7 @@ +{ + "type": "SET", + "data_type": { + "type": "DataType", + "name": "SET" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/5913df984e01b049.json b/type-parser/mini-parser-ts/test/snapshots/5913df984e01b049.json new file mode 100644 index 000000000..36f29fa6b --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/5913df984e01b049.json @@ -0,0 +1,13 @@ +{ + "type": "LowCardinality(UInt32)", + "data_type": { + "type": "DataType", + "name": "LowCardinality", + "arguments": [ + { + "type": "DataType", + "name": "UInt32" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/5a84a5824366cfdf.json b/type-parser/mini-parser-ts/test/snapshots/5a84a5824366cfdf.json new file mode 100644 index 000000000..b1f366c7a --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/5a84a5824366cfdf.json @@ -0,0 +1,14 @@ +{ + "type": "Time64(0)", + "data_type": { + "type": "DataType", + "name": "Time64", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "0" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/5bee16b592d3087c.json b/type-parser/mini-parser-ts/test/snapshots/5bee16b592d3087c.json new file mode 100644 index 000000000..ff66f6fa1 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/5bee16b592d3087c.json @@ -0,0 +1,26 @@ +{ + "type": "Tuple(id UInt64, name String, score Float64)", + "data_type": { + "type": "TupleDataType", + "name": "Tuple", + "arguments": [ + { + "type": "DataType", + "name": "UInt64" + }, + { + "type": "DataType", + "name": "String" + }, + { + "type": "DataType", + "name": "Float64" + } + ], + "element_names": [ + "id", + "name", + "score" + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/5c52b39b56c50f56.json b/type-parser/mini-parser-ts/test/snapshots/5c52b39b56c50f56.json new file mode 100644 index 000000000..c03ac2e98 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/5c52b39b56c50f56.json @@ -0,0 +1,7 @@ +{ + "type": "Int256", + "data_type": { + "type": "DataType", + "name": "Int256" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/5c89edcac2811a6a.json b/type-parser/mini-parser-ts/test/snapshots/5c89edcac2811a6a.json new file mode 100644 index 000000000..25cbaa118 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/5c89edcac2811a6a.json @@ -0,0 +1,7 @@ +{ + "type": "Int", + "data_type": { + "type": "DataType", + "name": "Int" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/5e990ab2800482f2.json b/type-parser/mini-parser-ts/test/snapshots/5e990ab2800482f2.json new file mode 100644 index 000000000..304c0402f --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/5e990ab2800482f2.json @@ -0,0 +1,14 @@ +{ + "type": "DateTime64(5)", + "data_type": { + "type": "DataType", + "name": "DateTime64", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "5" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/6000a28977e029d9.json b/type-parser/mini-parser-ts/test/snapshots/6000a28977e029d9.json new file mode 100644 index 000000000..ca7665fac --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/6000a28977e029d9.json @@ -0,0 +1,45 @@ +{ + "type": "Nested(a Array(UInt8), b Tuple(x UInt8, y String))", + "data_type": { + "type": "DataType", + "name": "Nested", + "arguments": [ + { + "type": "NameTypePair", + "name": "a", + "data_type": { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "UInt8" + } + ] + } + }, + { + "type": "NameTypePair", + "name": "b", + "data_type": { + "type": "TupleDataType", + "name": "Tuple", + "arguments": [ + { + "type": "DataType", + "name": "UInt8" + }, + { + "type": "DataType", + "name": "String" + } + ], + "element_names": [ + "x", + "y" + ] + } + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/620e6c17af0fec3f.json b/type-parser/mini-parser-ts/test/snapshots/620e6c17af0fec3f.json new file mode 100644 index 000000000..0e910497a --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/620e6c17af0fec3f.json @@ -0,0 +1,17 @@ +{ + "type": "Map(String, MultiPolygon)", + "data_type": { + "type": "DataType", + "name": "Map", + "arguments": [ + { + "type": "DataType", + "name": "String" + }, + { + "type": "DataType", + "name": "MultiPolygon" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/625a100e21847dcf.json b/type-parser/mini-parser-ts/test/snapshots/625a100e21847dcf.json new file mode 100644 index 000000000..a2e8eb3b9 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/625a100e21847dcf.json @@ -0,0 +1,13 @@ +{ + "type": "Nullable(Int8)", + "data_type": { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "DataType", + "name": "Int8" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/63a53953382e5a76.json b/type-parser/mini-parser-ts/test/snapshots/63a53953382e5a76.json new file mode 100644 index 000000000..1234aa09f --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/63a53953382e5a76.json @@ -0,0 +1,21 @@ +{ + "type": "Tuple( id UInt64 , name String )", + "data_type": { + "type": "TupleDataType", + "name": "Tuple", + "arguments": [ + { + "type": "DataType", + "name": "UInt64" + }, + { + "type": "DataType", + "name": "String" + } + ], + "element_names": [ + "id", + "name" + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/64269f9bd268bf28.json b/type-parser/mini-parser-ts/test/snapshots/64269f9bd268bf28.json new file mode 100644 index 000000000..156829a6f --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/64269f9bd268bf28.json @@ -0,0 +1,7 @@ +{ + "type": "TIME", + "data_type": { + "type": "DataType", + "name": "TIME" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/648be8a9b20b4068.json b/type-parser/mini-parser-ts/test/snapshots/648be8a9b20b4068.json new file mode 100644 index 000000000..0b5dcb82c --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/648be8a9b20b4068.json @@ -0,0 +1,13 @@ +{ + "type": "Array(IPv6)", + "data_type": { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "IPv6" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/64edc28811344047.json b/type-parser/mini-parser-ts/test/snapshots/64edc28811344047.json new file mode 100644 index 000000000..9f463c805 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/64edc28811344047.json @@ -0,0 +1,13 @@ +{ + "type": "Nullable(UInt32)", + "data_type": { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "DataType", + "name": "UInt32" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/6529f695ef6bea2b.json b/type-parser/mini-parser-ts/test/snapshots/6529f695ef6bea2b.json new file mode 100644 index 000000000..de753e231 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/6529f695ef6bea2b.json @@ -0,0 +1,7 @@ +{ + "type": "CHARACTER", + "data_type": { + "type": "DataType", + "name": "CHARACTER" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/65d2d849e33bbb9f.json b/type-parser/mini-parser-ts/test/snapshots/65d2d849e33bbb9f.json new file mode 100644 index 000000000..f638d310c --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/65d2d849e33bbb9f.json @@ -0,0 +1,19 @@ +{ + "type": "Array(Array(Int32))", + "data_type": { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "Int32" + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/663699edbe8d32d0.json b/type-parser/mini-parser-ts/test/snapshots/663699edbe8d32d0.json new file mode 100644 index 000000000..c227a18c7 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/663699edbe8d32d0.json @@ -0,0 +1,14 @@ +{ + "type": "FixedString( 16 )", + "data_type": { + "type": "DataType", + "name": "FixedString", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "16" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/663ad5af89c48643.json b/type-parser/mini-parser-ts/test/snapshots/663ad5af89c48643.json new file mode 100644 index 000000000..5c62dfdeb --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/663ad5af89c48643.json @@ -0,0 +1,37 @@ +{ + "type": "Array(Map(String, Variant(Int64, Float64, String)))", + "data_type": { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "Map", + "arguments": [ + { + "type": "DataType", + "name": "String" + }, + { + "type": "DataType", + "name": "Variant", + "arguments": [ + { + "type": "DataType", + "name": "Int64" + }, + { + "type": "DataType", + "name": "Float64" + }, + { + "type": "DataType", + "name": "String" + } + ] + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/66c7fbd08eb194f8.json b/type-parser/mini-parser-ts/test/snapshots/66c7fbd08eb194f8.json new file mode 100644 index 000000000..1bec0c628 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/66c7fbd08eb194f8.json @@ -0,0 +1,17 @@ +{ + "type": "Enum('a' = 1, 'b' = 2)", + "data_type": { + "type": "EnumDataType", + "name": "Enum", + "values": [ + { + "name": "a", + "value": 1 + }, + { + "name": "b", + "value": 2 + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/6760521bb1b6d98f.json b/type-parser/mini-parser-ts/test/snapshots/6760521bb1b6d98f.json new file mode 100644 index 000000000..4446034e7 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/6760521bb1b6d98f.json @@ -0,0 +1,13 @@ +{ + "type": "Nullable(Bool)", + "data_type": { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "DataType", + "name": "Bool" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/67ab5f4c86e061d7.json b/type-parser/mini-parser-ts/test/snapshots/67ab5f4c86e061d7.json new file mode 100644 index 000000000..4925639d5 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/67ab5f4c86e061d7.json @@ -0,0 +1,19 @@ +{ + "type": "FIXED(10, 2)", + "data_type": { + "type": "DataType", + "name": "FIXED", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "10" + }, + { + "type": "Literal", + "value_type": "UInt64", + "value": "2" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/6932c015a8c3a3ef.json b/type-parser/mini-parser-ts/test/snapshots/6932c015a8c3a3ef.json new file mode 100644 index 000000000..4a0c40eec --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/6932c015a8c3a3ef.json @@ -0,0 +1,56 @@ +{ + "type": "Tuple(a Array(UInt8), b Map(String, UInt64), c Tuple(p Int8, q Int8))", + "data_type": { + "type": "TupleDataType", + "name": "Tuple", + "arguments": [ + { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "UInt8" + } + ] + }, + { + "type": "DataType", + "name": "Map", + "arguments": [ + { + "type": "DataType", + "name": "String" + }, + { + "type": "DataType", + "name": "UInt64" + } + ] + }, + { + "type": "TupleDataType", + "name": "Tuple", + "arguments": [ + { + "type": "DataType", + "name": "Int8" + }, + { + "type": "DataType", + "name": "Int8" + } + ], + "element_names": [ + "p", + "q" + ] + } + ], + "element_names": [ + "a", + "b", + "c" + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/69a99906f5a06ea1.json b/type-parser/mini-parser-ts/test/snapshots/69a99906f5a06ea1.json new file mode 100644 index 000000000..9fffdaf79 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/69a99906f5a06ea1.json @@ -0,0 +1,7 @@ +{ + "type": "UInt64", + "data_type": { + "type": "DataType", + "name": "UInt64" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/69ddba4964a41534.json b/type-parser/mini-parser-ts/test/snapshots/69ddba4964a41534.json new file mode 100644 index 000000000..1766e6d01 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/69ddba4964a41534.json @@ -0,0 +1,17 @@ +{ + "type": "Enum8('café' = 1, 'naïve' = 2)", + "data_type": { + "type": "EnumDataType", + "name": "Enum8", + "values": [ + { + "name": "café", + "value": 1 + }, + { + "name": "naïve", + "value": 2 + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/6b09d0c1e764f23a.json b/type-parser/mini-parser-ts/test/snapshots/6b09d0c1e764f23a.json new file mode 100644 index 000000000..741ea7110 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/6b09d0c1e764f23a.json @@ -0,0 +1,19 @@ +{ + "type": "LowCardinality(Nullable(UInt32))", + "data_type": { + "type": "DataType", + "name": "LowCardinality", + "arguments": [ + { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "DataType", + "name": "UInt32" + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/6c43115b5c24bfa0.json b/type-parser/mini-parser-ts/test/snapshots/6c43115b5c24bfa0.json new file mode 100644 index 000000000..c6dbad040 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/6c43115b5c24bfa0.json @@ -0,0 +1,25 @@ +{ + "type": "Dynamic(max_types = 1)", + "data_type": { + "type": "DataType", + "name": "Dynamic", + "arguments": [ + { + "type": "Function", + "name": "equals", + "is_operator": true, + "arguments": [ + { + "type": "Identifier", + "name": "max_types" + }, + { + "type": "Literal", + "value_type": "UInt64", + "value": "1" + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/6c82e6dd86807ee3.json b/type-parser/mini-parser-ts/test/snapshots/6c82e6dd86807ee3.json new file mode 100644 index 000000000..c0feba60e --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/6c82e6dd86807ee3.json @@ -0,0 +1,7 @@ +{ + "type": "Time", + "data_type": { + "type": "DataType", + "name": "Time" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/6ddeb86eb863afac.json b/type-parser/mini-parser-ts/test/snapshots/6ddeb86eb863afac.json new file mode 100644 index 000000000..ed10f860c --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/6ddeb86eb863afac.json @@ -0,0 +1,63 @@ +{ + "type": "Tuple(meta Map(String, String), data Array(Tuple(ts DateTime64(9, 'UTC'), val Float64)))", + "data_type": { + "type": "TupleDataType", + "name": "Tuple", + "arguments": [ + { + "type": "DataType", + "name": "Map", + "arguments": [ + { + "type": "DataType", + "name": "String" + }, + { + "type": "DataType", + "name": "String" + } + ] + }, + { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "TupleDataType", + "name": "Tuple", + "arguments": [ + { + "type": "DataType", + "name": "DateTime64", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "9" + }, + { + "type": "Literal", + "value_type": "String", + "value": "UTC" + } + ] + }, + { + "type": "DataType", + "name": "Float64" + } + ], + "element_names": [ + "ts", + "val" + ] + } + ] + } + ], + "element_names": [ + "meta", + "data" + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/6e25d9b9f79612fd.json b/type-parser/mini-parser-ts/test/snapshots/6e25d9b9f79612fd.json new file mode 100644 index 000000000..5898c6183 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/6e25d9b9f79612fd.json @@ -0,0 +1,55 @@ +{ + "type": "Map(UUID, Tuple(created DateTime64(3, 'UTC'), tags Array(LowCardinality(String))))", + "data_type": { + "type": "DataType", + "name": "Map", + "arguments": [ + { + "type": "DataType", + "name": "UUID" + }, + { + "type": "TupleDataType", + "name": "Tuple", + "arguments": [ + { + "type": "DataType", + "name": "DateTime64", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "3" + }, + { + "type": "Literal", + "value_type": "String", + "value": "UTC" + } + ] + }, + { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "LowCardinality", + "arguments": [ + { + "type": "DataType", + "name": "String" + } + ] + } + ] + } + ], + "element_names": [ + "created", + "tags" + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/6e53b6c5a0f31021.json b/type-parser/mini-parser-ts/test/snapshots/6e53b6c5a0f31021.json new file mode 100644 index 000000000..5db983cfd --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/6e53b6c5a0f31021.json @@ -0,0 +1,19 @@ +{ + "type": "Decimal(76, 0)", + "data_type": { + "type": "DataType", + "name": "Decimal", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "76" + }, + { + "type": "Literal", + "value_type": "UInt64", + "value": "0" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/6e5f2d68fd260298.json b/type-parser/mini-parser-ts/test/snapshots/6e5f2d68fd260298.json new file mode 100644 index 000000000..8f5237dbb --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/6e5f2d68fd260298.json @@ -0,0 +1,35 @@ +{ + "type": "Array(Array(Map(String, Array(UInt8))))", + "data_type": { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "Map", + "arguments": [ + { + "type": "DataType", + "name": "String" + }, + { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "UInt8" + } + ] + } + ] + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/6e823ebb2984559d.json b/type-parser/mini-parser-ts/test/snapshots/6e823ebb2984559d.json new file mode 100644 index 000000000..0accbb23f --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/6e823ebb2984559d.json @@ -0,0 +1,13 @@ +{ + "type": "Nullable( Float64 )", + "data_type": { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "DataType", + "name": "Float64" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/6e85b5501433e087.json b/type-parser/mini-parser-ts/test/snapshots/6e85b5501433e087.json new file mode 100644 index 000000000..b44848c8a --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/6e85b5501433e087.json @@ -0,0 +1,58 @@ +{ + "type": "Array(Tuple(a UInt8, b UInt16, c Tuple(d Int32, e Array(Nullable(String)))))", + "data_type": { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "TupleDataType", + "name": "Tuple", + "arguments": [ + { + "type": "DataType", + "name": "UInt8" + }, + { + "type": "DataType", + "name": "UInt16" + }, + { + "type": "TupleDataType", + "name": "Tuple", + "arguments": [ + { + "type": "DataType", + "name": "Int32" + }, + { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "DataType", + "name": "String" + } + ] + } + ] + } + ], + "element_names": [ + "d", + "e" + ] + } + ], + "element_names": [ + "a", + "b", + "c" + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/6f2851997db0584b.json b/type-parser/mini-parser-ts/test/snapshots/6f2851997db0584b.json new file mode 100644 index 000000000..2612a37d5 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/6f2851997db0584b.json @@ -0,0 +1,13 @@ +{ + "type": "Nullable(String)", + "data_type": { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "DataType", + "name": "String" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/707890c2d6dfa724.json b/type-parser/mini-parser-ts/test/snapshots/707890c2d6dfa724.json new file mode 100644 index 000000000..18c1473de --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/707890c2d6dfa724.json @@ -0,0 +1,31 @@ +{ + "type": "Nested(ts DateTime, vals Array(Float64))", + "data_type": { + "type": "DataType", + "name": "Nested", + "arguments": [ + { + "type": "NameTypePair", + "name": "ts", + "data_type": { + "type": "DataType", + "name": "DateTime" + } + }, + { + "type": "NameTypePair", + "name": "vals", + "data_type": { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "Float64" + } + ] + } + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/707ef63b9e074824.json b/type-parser/mini-parser-ts/test/snapshots/707ef63b9e074824.json new file mode 100644 index 000000000..9a940ef0c --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/707ef63b9e074824.json @@ -0,0 +1,21 @@ +{ + "type": "Enum8('UPPER' = 1, 'lower' = 2, 'MiXeD' = 3)", + "data_type": { + "type": "EnumDataType", + "name": "Enum8", + "values": [ + { + "name": "UPPER", + "value": 1 + }, + { + "name": "lower", + "value": 2 + }, + { + "name": "MiXeD", + "value": 3 + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/70b4bb2684c3f896.json b/type-parser/mini-parser-ts/test/snapshots/70b4bb2684c3f896.json new file mode 100644 index 000000000..2aab0a37d --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/70b4bb2684c3f896.json @@ -0,0 +1,7 @@ +{ + "type": "UInt16", + "data_type": { + "type": "DataType", + "name": "UInt16" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/710d7120fc63672d.json b/type-parser/mini-parser-ts/test/snapshots/710d7120fc63672d.json new file mode 100644 index 000000000..d232b0fec --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/710d7120fc63672d.json @@ -0,0 +1,29 @@ +{ + "type": "Map(UUID, Array(LowCardinality(String)))", + "data_type": { + "type": "DataType", + "name": "Map", + "arguments": [ + { + "type": "DataType", + "name": "UUID" + }, + { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "LowCardinality", + "arguments": [ + { + "type": "DataType", + "name": "String" + } + ] + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/711cbcac68f895ff.json b/type-parser/mini-parser-ts/test/snapshots/711cbcac68f895ff.json new file mode 100644 index 000000000..3906acb02 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/711cbcac68f895ff.json @@ -0,0 +1,63 @@ +{ + "type": "Tuple(a Array(Map(String, UInt64)), b Tuple(x Array(Int8), y Nullable(String)))", + "data_type": { + "type": "TupleDataType", + "name": "Tuple", + "arguments": [ + { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "Map", + "arguments": [ + { + "type": "DataType", + "name": "String" + }, + { + "type": "DataType", + "name": "UInt64" + } + ] + } + ] + }, + { + "type": "TupleDataType", + "name": "Tuple", + "arguments": [ + { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "Int8" + } + ] + }, + { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "DataType", + "name": "String" + } + ] + } + ], + "element_names": [ + "x", + "y" + ] + } + ], + "element_names": [ + "a", + "b" + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/71bf56ec603bc142.json b/type-parser/mini-parser-ts/test/snapshots/71bf56ec603bc142.json new file mode 100644 index 000000000..a2a8c3756 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/71bf56ec603bc142.json @@ -0,0 +1,13 @@ +{ + "type": "Nullable(Float64)", + "data_type": { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "DataType", + "name": "Float64" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/720b7e5e0ae2603c.json b/type-parser/mini-parser-ts/test/snapshots/720b7e5e0ae2603c.json new file mode 100644 index 000000000..9c4a6537f --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/720b7e5e0ae2603c.json @@ -0,0 +1,17 @@ +{ + "type": "Enum16('min' = -32768, 'max' = 32767)", + "data_type": { + "type": "EnumDataType", + "name": "Enum16", + "values": [ + { + "name": "min", + "value": -32768 + }, + { + "name": "max", + "value": 32767 + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/74219cbd9de3b122.json b/type-parser/mini-parser-ts/test/snapshots/74219cbd9de3b122.json new file mode 100644 index 000000000..d43290648 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/74219cbd9de3b122.json @@ -0,0 +1,16 @@ +{ + "type": "Tuple(a UInt8)", + "data_type": { + "type": "TupleDataType", + "name": "Tuple", + "arguments": [ + { + "type": "DataType", + "name": "UInt8" + } + ], + "element_names": [ + "a" + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/742ae2179d57f271.json b/type-parser/mini-parser-ts/test/snapshots/742ae2179d57f271.json new file mode 100644 index 000000000..6ad9987de --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/742ae2179d57f271.json @@ -0,0 +1,7 @@ +{ + "type": "INT UNSIGNED", + "data_type": { + "type": "DataType", + "name": "INT UNSIGNED" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/7438a826f1a6e96c.json b/type-parser/mini-parser-ts/test/snapshots/7438a826f1a6e96c.json new file mode 100644 index 000000000..f53d771c4 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/7438a826f1a6e96c.json @@ -0,0 +1,33 @@ +{ + "type": "Variant(Int8, Int16, Int32, Int64, Int128, Int256)", + "data_type": { + "type": "DataType", + "name": "Variant", + "arguments": [ + { + "type": "DataType", + "name": "Int8" + }, + { + "type": "DataType", + "name": "Int16" + }, + { + "type": "DataType", + "name": "Int32" + }, + { + "type": "DataType", + "name": "Int64" + }, + { + "type": "DataType", + "name": "Int128" + }, + { + "type": "DataType", + "name": "Int256" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/75233122af88843e.json b/type-parser/mini-parser-ts/test/snapshots/75233122af88843e.json new file mode 100644 index 000000000..db8c77734 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/75233122af88843e.json @@ -0,0 +1,14 @@ +{ + "type": "Decimal256(76)", + "data_type": { + "type": "DataType", + "name": "Decimal256", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "76" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/7583403b47298bc7.json b/type-parser/mini-parser-ts/test/snapshots/7583403b47298bc7.json new file mode 100644 index 000000000..6aecf5c37 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/7583403b47298bc7.json @@ -0,0 +1,7 @@ +{ + "type": "IntervalMinute", + "data_type": { + "type": "DataType", + "name": "IntervalMinute" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/7588be2bc0c71c3a.json b/type-parser/mini-parser-ts/test/snapshots/7588be2bc0c71c3a.json new file mode 100644 index 000000000..9867ff7a7 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/7588be2bc0c71c3a.json @@ -0,0 +1,7 @@ +{ + "type": "IntervalMonth", + "data_type": { + "type": "DataType", + "name": "IntervalMonth" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/76a9f9e4cb330396.json b/type-parser/mini-parser-ts/test/snapshots/76a9f9e4cb330396.json new file mode 100644 index 000000000..8665bc060 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/76a9f9e4cb330396.json @@ -0,0 +1,13 @@ +{ + "type": "Nullable(IPv4)", + "data_type": { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "DataType", + "name": "IPv4" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/76b87a32829da0e0.json b/type-parser/mini-parser-ts/test/snapshots/76b87a32829da0e0.json new file mode 100644 index 000000000..41d762675 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/76b87a32829da0e0.json @@ -0,0 +1,7 @@ +{ + "type": "IPv6", + "data_type": { + "type": "DataType", + "name": "IPv6" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/76f142be038f6aaf.json b/type-parser/mini-parser-ts/test/snapshots/76f142be038f6aaf.json new file mode 100644 index 000000000..cbcbba470 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/76f142be038f6aaf.json @@ -0,0 +1,37 @@ +{ + "type": "Tuple(Int8, Int16, Int32, Int64, Int128, Int256, UInt8)", + "data_type": { + "type": "TupleDataType", + "name": "Tuple", + "arguments": [ + { + "type": "DataType", + "name": "Int8" + }, + { + "type": "DataType", + "name": "Int16" + }, + { + "type": "DataType", + "name": "Int32" + }, + { + "type": "DataType", + "name": "Int64" + }, + { + "type": "DataType", + "name": "Int128" + }, + { + "type": "DataType", + "name": "Int256" + }, + { + "type": "DataType", + "name": "UInt8" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/77dac08f7a014269.json b/type-parser/mini-parser-ts/test/snapshots/77dac08f7a014269.json new file mode 100644 index 000000000..883226270 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/77dac08f7a014269.json @@ -0,0 +1,25 @@ +{ + "type": "Nullable(Decimal(18, 4))", + "data_type": { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "DataType", + "name": "Decimal", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "18" + }, + { + "type": "Literal", + "value_type": "UInt64", + "value": "4" + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/78de9c05192768a1.json b/type-parser/mini-parser-ts/test/snapshots/78de9c05192768a1.json new file mode 100644 index 000000000..2ef527458 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/78de9c05192768a1.json @@ -0,0 +1,25 @@ +{ + "type": "Array(Decimal(18, 4))", + "data_type": { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "Decimal", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "18" + }, + { + "type": "Literal", + "value_type": "UInt64", + "value": "4" + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/793985cddb68d46e.json b/type-parser/mini-parser-ts/test/snapshots/793985cddb68d46e.json new file mode 100644 index 000000000..e1d21446e --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/793985cddb68d46e.json @@ -0,0 +1,7 @@ +{ + "type": "INT", + "data_type": { + "type": "DataType", + "name": "INT" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/7982e8c08d84551a.json b/type-parser/mini-parser-ts/test/snapshots/7982e8c08d84551a.json new file mode 100644 index 000000000..ed9930a4e --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/7982e8c08d84551a.json @@ -0,0 +1,7 @@ +{ + "type": "Int16", + "data_type": { + "type": "DataType", + "name": "Int16" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/7b2d79ca937a8cbb.json b/type-parser/mini-parser-ts/test/snapshots/7b2d79ca937a8cbb.json new file mode 100644 index 000000000..f72e0ebb3 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/7b2d79ca937a8cbb.json @@ -0,0 +1,7 @@ +{ + "type": "LineString", + "data_type": { + "type": "DataType", + "name": "LineString" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/7b35b7bce86754a4.json b/type-parser/mini-parser-ts/test/snapshots/7b35b7bce86754a4.json new file mode 100644 index 000000000..97f352676 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/7b35b7bce86754a4.json @@ -0,0 +1,14 @@ +{ + "type": "DateTime64(6)", + "data_type": { + "type": "DataType", + "name": "DateTime64", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "6" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/7b617dda062bb685.json b/type-parser/mini-parser-ts/test/snapshots/7b617dda062bb685.json new file mode 100644 index 000000000..83abb782e --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/7b617dda062bb685.json @@ -0,0 +1,25 @@ +{ + "type": "Nullable(DateTime64(3, 'UTC'))", + "data_type": { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "DataType", + "name": "DateTime64", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "3" + }, + { + "type": "Literal", + "value_type": "String", + "value": "UTC" + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/7bb7347a7172ad9e.json b/type-parser/mini-parser-ts/test/snapshots/7bb7347a7172ad9e.json new file mode 100644 index 000000000..8dc36f06c --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/7bb7347a7172ad9e.json @@ -0,0 +1,14 @@ +{ + "type": "DateTime64(7)", + "data_type": { + "type": "DataType", + "name": "DateTime64", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "7" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/7bd969148ace5e13.json b/type-parser/mini-parser-ts/test/snapshots/7bd969148ace5e13.json new file mode 100644 index 000000000..581a75437 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/7bd969148ace5e13.json @@ -0,0 +1,29 @@ +{ + "type": "Enum8('one', 'two', 'three', 'four')", + "data_type": { + "type": "DataType", + "name": "Enum8", + "arguments": [ + { + "type": "Literal", + "value_type": "String", + "value": "one" + }, + { + "type": "Literal", + "value_type": "String", + "value": "two" + }, + { + "type": "Literal", + "value_type": "String", + "value": "three" + }, + { + "type": "Literal", + "value_type": "String", + "value": "four" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/7c42711aeccef61a.json b/type-parser/mini-parser-ts/test/snapshots/7c42711aeccef61a.json new file mode 100644 index 000000000..150ba7c64 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/7c42711aeccef61a.json @@ -0,0 +1,20 @@ +{ + "type": "Nullable(DateTime64(3))", + "data_type": { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "DataType", + "name": "DateTime64", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "3" + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/7d144c8134ca1b4f.json b/type-parser/mini-parser-ts/test/snapshots/7d144c8134ca1b4f.json new file mode 100644 index 000000000..424fc5bb4 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/7d144c8134ca1b4f.json @@ -0,0 +1,20 @@ +{ + "type": "Array(FixedString(16))", + "data_type": { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "FixedString", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "16" + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/7d4e42ef9d04a046.json b/type-parser/mini-parser-ts/test/snapshots/7d4e42ef9d04a046.json new file mode 100644 index 000000000..02bd4b961 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/7d4e42ef9d04a046.json @@ -0,0 +1,7 @@ +{ + "type": "TEXT", + "data_type": { + "type": "DataType", + "name": "TEXT" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/7d6f05e0471d0acd.json b/type-parser/mini-parser-ts/test/snapshots/7d6f05e0471d0acd.json new file mode 100644 index 000000000..22c787de1 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/7d6f05e0471d0acd.json @@ -0,0 +1,7 @@ +{ + "type": "IntervalMicrosecond", + "data_type": { + "type": "DataType", + "name": "IntervalMicrosecond" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/7ee1ece2d69e227b.json b/type-parser/mini-parser-ts/test/snapshots/7ee1ece2d69e227b.json new file mode 100644 index 000000000..9472d532f --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/7ee1ece2d69e227b.json @@ -0,0 +1,13 @@ +{ + "type": "LowCardinality(DateTime)", + "data_type": { + "type": "DataType", + "name": "LowCardinality", + "arguments": [ + { + "type": "DataType", + "name": "DateTime" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/820a070e69cbeff5.json b/type-parser/mini-parser-ts/test/snapshots/820a070e69cbeff5.json new file mode 100644 index 000000000..543e70ba4 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/820a070e69cbeff5.json @@ -0,0 +1,19 @@ +{ + "type": "Decimal(50, 25)", + "data_type": { + "type": "DataType", + "name": "Decimal", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "50" + }, + { + "type": "Literal", + "value_type": "UInt64", + "value": "25" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/84bafac21a924872.json b/type-parser/mini-parser-ts/test/snapshots/84bafac21a924872.json new file mode 100644 index 000000000..0c6ee660a --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/84bafac21a924872.json @@ -0,0 +1,37 @@ +{ + "type": "Variant(String, Array(UInt8), Map(String, UInt64))", + "data_type": { + "type": "DataType", + "name": "Variant", + "arguments": [ + { + "type": "DataType", + "name": "String" + }, + { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "UInt8" + } + ] + }, + { + "type": "DataType", + "name": "Map", + "arguments": [ + { + "type": "DataType", + "name": "String" + }, + { + "type": "DataType", + "name": "UInt64" + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/84c79425e23a4926.json b/type-parser/mini-parser-ts/test/snapshots/84c79425e23a4926.json new file mode 100644 index 000000000..6f6e9f8c9 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/84c79425e23a4926.json @@ -0,0 +1,25 @@ +{ + "type": "Dynamic(max_types = 16)", + "data_type": { + "type": "DataType", + "name": "Dynamic", + "arguments": [ + { + "type": "Function", + "name": "equals", + "is_operator": true, + "arguments": [ + { + "type": "Identifier", + "name": "max_types" + }, + { + "type": "Literal", + "value_type": "UInt64", + "value": "16" + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/85066b2ca9c0c348.json b/type-parser/mini-parser-ts/test/snapshots/85066b2ca9c0c348.json new file mode 100644 index 000000000..aa1ff2b34 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/85066b2ca9c0c348.json @@ -0,0 +1,7 @@ +{ + "type": "Polygon", + "data_type": { + "type": "DataType", + "name": "Polygon" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/857895ede54a4ad7.json b/type-parser/mini-parser-ts/test/snapshots/857895ede54a4ad7.json new file mode 100644 index 000000000..b543da026 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/857895ede54a4ad7.json @@ -0,0 +1,47 @@ +{ + "type": "Map(LowCardinality(String), Array(Nullable(Decimal(18, 4))))", + "data_type": { + "type": "DataType", + "name": "Map", + "arguments": [ + { + "type": "DataType", + "name": "LowCardinality", + "arguments": [ + { + "type": "DataType", + "name": "String" + } + ] + }, + { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "DataType", + "name": "Decimal", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "18" + }, + { + "type": "Literal", + "value_type": "UInt64", + "value": "4" + } + ] + } + ] + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/85e93d199ff62047.json b/type-parser/mini-parser-ts/test/snapshots/85e93d199ff62047.json new file mode 100644 index 000000000..b13e26f93 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/85e93d199ff62047.json @@ -0,0 +1,44 @@ +{ + "type": "Tuple(a Nullable(UUID), b Nullable(IPv6), c Nullable(Date32))", + "data_type": { + "type": "TupleDataType", + "name": "Tuple", + "arguments": [ + { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "DataType", + "name": "UUID" + } + ] + }, + { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "DataType", + "name": "IPv6" + } + ] + }, + { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "DataType", + "name": "Date32" + } + ] + } + ], + "element_names": [ + "a", + "b", + "c" + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/863545b36296dfca.json b/type-parser/mini-parser-ts/test/snapshots/863545b36296dfca.json new file mode 100644 index 000000000..1a39cdfa2 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/863545b36296dfca.json @@ -0,0 +1,23 @@ +{ + "type": "Map(String, Array(UInt8))", + "data_type": { + "type": "DataType", + "name": "Map", + "arguments": [ + { + "type": "DataType", + "name": "String" + }, + { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "UInt8" + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/863c2dcdff8db25e.json b/type-parser/mini-parser-ts/test/snapshots/863c2dcdff8db25e.json new file mode 100644 index 000000000..ad4c54844 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/863c2dcdff8db25e.json @@ -0,0 +1,17 @@ +{ + "type": "Enum16('small' = 1, 'big' = 30000)", + "data_type": { + "type": "EnumDataType", + "name": "Enum16", + "values": [ + { + "name": "small", + "value": 1 + }, + { + "name": "big", + "value": 30000 + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/8658478ee33a4992.json b/type-parser/mini-parser-ts/test/snapshots/8658478ee33a4992.json new file mode 100644 index 000000000..4f636a25c --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/8658478ee33a4992.json @@ -0,0 +1,41 @@ +{ + "type": "Enum16('a' = 1, 'b' = 2, 'c' = 3, 'd' = 4, 'e' = 5, 'f' = 6, 'g' = 7, 'h' = 8)", + "data_type": { + "type": "EnumDataType", + "name": "Enum16", + "values": [ + { + "name": "a", + "value": 1 + }, + { + "name": "b", + "value": 2 + }, + { + "name": "c", + "value": 3 + }, + { + "name": "d", + "value": 4 + }, + { + "name": "e", + "value": 5 + }, + { + "name": "f", + "value": 6 + }, + { + "name": "g", + "value": 7 + }, + { + "name": "h", + "value": 8 + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/8659297c152d065c.json b/type-parser/mini-parser-ts/test/snapshots/8659297c152d065c.json new file mode 100644 index 000000000..7f7e161d2 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/8659297c152d065c.json @@ -0,0 +1,14 @@ +{ + "type": "FixedString(4)", + "data_type": { + "type": "DataType", + "name": "FixedString", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "4" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/88228a7e519d90de.json b/type-parser/mini-parser-ts/test/snapshots/88228a7e519d90de.json new file mode 100644 index 000000000..663de2265 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/88228a7e519d90de.json @@ -0,0 +1,57 @@ +{ + "type": "Map(LowCardinality(String), Map(UUID, Array(Nullable(DateTime64(3, 'UTC')))))", + "data_type": { + "type": "DataType", + "name": "Map", + "arguments": [ + { + "type": "DataType", + "name": "LowCardinality", + "arguments": [ + { + "type": "DataType", + "name": "String" + } + ] + }, + { + "type": "DataType", + "name": "Map", + "arguments": [ + { + "type": "DataType", + "name": "UUID" + }, + { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "DataType", + "name": "DateTime64", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "3" + }, + { + "type": "Literal", + "value_type": "String", + "value": "UTC" + } + ] + } + ] + } + ] + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/88c06ce9a212e3c3.json b/type-parser/mini-parser-ts/test/snapshots/88c06ce9a212e3c3.json new file mode 100644 index 000000000..60f5f7291 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/88c06ce9a212e3c3.json @@ -0,0 +1,19 @@ +{ + "type": "Array( Array( Int32 ) )", + "data_type": { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "Int32" + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/8911b9163c7d34f3.json b/type-parser/mini-parser-ts/test/snapshots/8911b9163c7d34f3.json new file mode 100644 index 000000000..cc20c3463 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/8911b9163c7d34f3.json @@ -0,0 +1,17 @@ +{ + "type": "Map(Date, UInt64)", + "data_type": { + "type": "DataType", + "name": "Map", + "arguments": [ + { + "type": "DataType", + "name": "Date" + }, + { + "type": "DataType", + "name": "UInt64" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/8969693adfe3e927.json b/type-parser/mini-parser-ts/test/snapshots/8969693adfe3e927.json new file mode 100644 index 000000000..1f331f374 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/8969693adfe3e927.json @@ -0,0 +1,7 @@ +{ + "type": "BYTEA", + "data_type": { + "type": "DataType", + "name": "BYTEA" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/89a8eec911b3dcd7.json b/type-parser/mini-parser-ts/test/snapshots/89a8eec911b3dcd7.json new file mode 100644 index 000000000..2eb33838e --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/89a8eec911b3dcd7.json @@ -0,0 +1,29 @@ +{ + "type": "Array(Nullable(Tuple(UInt8, String)))", + "data_type": { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "TupleDataType", + "name": "Tuple", + "arguments": [ + { + "type": "DataType", + "name": "UInt8" + }, + { + "type": "DataType", + "name": "String" + } + ] + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/8a4d871957c7159e.json b/type-parser/mini-parser-ts/test/snapshots/8a4d871957c7159e.json new file mode 100644 index 000000000..95e31b752 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/8a4d871957c7159e.json @@ -0,0 +1,7 @@ +{ + "type": "BIGINT SIGNED", + "data_type": { + "type": "DataType", + "name": "BIGINT SIGNED" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/8bad118235abbed4.json b/type-parser/mini-parser-ts/test/snapshots/8bad118235abbed4.json new file mode 100644 index 000000000..f2540799e --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/8bad118235abbed4.json @@ -0,0 +1,29 @@ +{ + "type": "Tuple(String, String, String, String, String)", + "data_type": { + "type": "TupleDataType", + "name": "Tuple", + "arguments": [ + { + "type": "DataType", + "name": "String" + }, + { + "type": "DataType", + "name": "String" + }, + { + "type": "DataType", + "name": "String" + }, + { + "type": "DataType", + "name": "String" + }, + { + "type": "DataType", + "name": "String" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/8d08253fa3dc6ea7.json b/type-parser/mini-parser-ts/test/snapshots/8d08253fa3dc6ea7.json new file mode 100644 index 000000000..ef2380058 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/8d08253fa3dc6ea7.json @@ -0,0 +1,13 @@ +{ + "type": "LowCardinality(Int64)", + "data_type": { + "type": "DataType", + "name": "LowCardinality", + "arguments": [ + { + "type": "DataType", + "name": "Int64" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/8e194457987b0af1.json b/type-parser/mini-parser-ts/test/snapshots/8e194457987b0af1.json new file mode 100644 index 000000000..8965ec359 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/8e194457987b0af1.json @@ -0,0 +1,19 @@ +{ + "type": "NUMERIC(10, 2)", + "data_type": { + "type": "DataType", + "name": "NUMERIC", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "10" + }, + { + "type": "Literal", + "value_type": "UInt64", + "value": "2" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/8e8232cd6a0e42ec.json b/type-parser/mini-parser-ts/test/snapshots/8e8232cd6a0e42ec.json new file mode 100644 index 000000000..867eb979d --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/8e8232cd6a0e42ec.json @@ -0,0 +1,27 @@ +{ + "type": "Map(Enum8('a' = 1, 'b' = 2), String)", + "data_type": { + "type": "DataType", + "name": "Map", + "arguments": [ + { + "type": "EnumDataType", + "name": "Enum8", + "values": [ + { + "name": "a", + "value": 1 + }, + { + "name": "b", + "value": 2 + } + ] + }, + { + "type": "DataType", + "name": "String" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/8f1113085b02958c.json b/type-parser/mini-parser-ts/test/snapshots/8f1113085b02958c.json new file mode 100644 index 000000000..6f70d50df --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/8f1113085b02958c.json @@ -0,0 +1,19 @@ +{ + "type": "Array(Array(UInt8))", + "data_type": { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "UInt8" + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/8f535b0aee7ff306.json b/type-parser/mini-parser-ts/test/snapshots/8f535b0aee7ff306.json new file mode 100644 index 000000000..cb8941d2b --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/8f535b0aee7ff306.json @@ -0,0 +1,7 @@ +{ + "type": "BFloat16", + "data_type": { + "type": "DataType", + "name": "BFloat16" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/8fe0c11dbe0aca49.json b/type-parser/mini-parser-ts/test/snapshots/8fe0c11dbe0aca49.json new file mode 100644 index 000000000..dc29ce084 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/8fe0c11dbe0aca49.json @@ -0,0 +1,23 @@ +{ + "type": "Map(Int64, Nullable(Float64))", + "data_type": { + "type": "DataType", + "name": "Map", + "arguments": [ + { + "type": "DataType", + "name": "Int64" + }, + { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "DataType", + "name": "Float64" + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/90885de55fed9053.json b/type-parser/mini-parser-ts/test/snapshots/90885de55fed9053.json new file mode 100644 index 000000000..24b2603ab --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/90885de55fed9053.json @@ -0,0 +1,17 @@ +{ + "type": "Tuple(UInt8, String)", + "data_type": { + "type": "TupleDataType", + "name": "Tuple", + "arguments": [ + { + "type": "DataType", + "name": "UInt8" + }, + { + "type": "DataType", + "name": "String" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/913001e7931e5222.json b/type-parser/mini-parser-ts/test/snapshots/913001e7931e5222.json new file mode 100644 index 000000000..e351d76b6 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/913001e7931e5222.json @@ -0,0 +1,7 @@ +{ + "type": "CHAR VARYING", + "data_type": { + "type": "DataType", + "name": "CHAR VARYING" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/91b51f022dd84872.json b/type-parser/mini-parser-ts/test/snapshots/91b51f022dd84872.json new file mode 100644 index 000000000..51ec61954 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/91b51f022dd84872.json @@ -0,0 +1,7 @@ +{ + "type": "Date32", + "data_type": { + "type": "DataType", + "name": "Date32" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/92d47d12e6852d3f.json b/type-parser/mini-parser-ts/test/snapshots/92d47d12e6852d3f.json new file mode 100644 index 000000000..e92fbf33b --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/92d47d12e6852d3f.json @@ -0,0 +1,17 @@ +{ + "type": "Enum8('a.b.c' = 1, 'x.y.z' = 2)", + "data_type": { + "type": "EnumDataType", + "name": "Enum8", + "values": [ + { + "name": "a.b.c", + "value": 1 + }, + { + "name": "x.y.z", + "value": 2 + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/9430d1f0cb6846cf.json b/type-parser/mini-parser-ts/test/snapshots/9430d1f0cb6846cf.json new file mode 100644 index 000000000..6a938d672 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/9430d1f0cb6846cf.json @@ -0,0 +1,33 @@ +{ + "type": "Nested(id UInt64, name String, score Float64)", + "data_type": { + "type": "DataType", + "name": "Nested", + "arguments": [ + { + "type": "NameTypePair", + "name": "id", + "data_type": { + "type": "DataType", + "name": "UInt64" + } + }, + { + "type": "NameTypePair", + "name": "name", + "data_type": { + "type": "DataType", + "name": "String" + } + }, + { + "type": "NameTypePair", + "name": "score", + "data_type": { + "type": "DataType", + "name": "Float64" + } + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/9434ca86a34b5ff2.json b/type-parser/mini-parser-ts/test/snapshots/9434ca86a34b5ff2.json new file mode 100644 index 000000000..6ce857723 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/9434ca86a34b5ff2.json @@ -0,0 +1,17 @@ +{ + "type": "Map(String, Float64)", + "data_type": { + "type": "DataType", + "name": "Map", + "arguments": [ + { + "type": "DataType", + "name": "String" + }, + { + "type": "DataType", + "name": "Float64" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/95bf560a0bb0375a.json b/type-parser/mini-parser-ts/test/snapshots/95bf560a0bb0375a.json new file mode 100644 index 000000000..867e7395d --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/95bf560a0bb0375a.json @@ -0,0 +1,28 @@ +{ + "type": "Variant(Date, DateTime, DateTime64(3))", + "data_type": { + "type": "DataType", + "name": "Variant", + "arguments": [ + { + "type": "DataType", + "name": "Date" + }, + { + "type": "DataType", + "name": "DateTime" + }, + { + "type": "DataType", + "name": "DateTime64", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "3" + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/96ddaccf581f483c.json b/type-parser/mini-parser-ts/test/snapshots/96ddaccf581f483c.json new file mode 100644 index 000000000..a43d606cb --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/96ddaccf581f483c.json @@ -0,0 +1,7 @@ +{ + "type": "Ring", + "data_type": { + "type": "DataType", + "name": "Ring" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/98cc0e810e27c9bf.json b/type-parser/mini-parser-ts/test/snapshots/98cc0e810e27c9bf.json new file mode 100644 index 000000000..7edae203f --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/98cc0e810e27c9bf.json @@ -0,0 +1,7 @@ +{ + "type": "CHAR LARGE OBJECT", + "data_type": { + "type": "DataType", + "name": "CHAR LARGE OBJECT" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/998fe0ecccd6998c.json b/type-parser/mini-parser-ts/test/snapshots/998fe0ecccd6998c.json new file mode 100644 index 000000000..b060fc8e6 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/998fe0ecccd6998c.json @@ -0,0 +1,7 @@ +{ + "type": "Float32", + "data_type": { + "type": "DataType", + "name": "Float32" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/9993d2e1f4dbe182.json b/type-parser/mini-parser-ts/test/snapshots/9993d2e1f4dbe182.json new file mode 100644 index 000000000..a6242ec1f --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/9993d2e1f4dbe182.json @@ -0,0 +1,26 @@ +{ + "type": "LowCardinality(Nullable(FixedString(16)))", + "data_type": { + "type": "DataType", + "name": "LowCardinality", + "arguments": [ + { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "DataType", + "name": "FixedString", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "16" + } + ] + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/9a52f34a0fcbb1da.json b/type-parser/mini-parser-ts/test/snapshots/9a52f34a0fcbb1da.json new file mode 100644 index 000000000..caf8929f3 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/9a52f34a0fcbb1da.json @@ -0,0 +1,21 @@ +{ + "type": "Enum8('red' = 0, 'green' = 1, 'blue' = 2)", + "data_type": { + "type": "EnumDataType", + "name": "Enum8", + "values": [ + { + "name": "red", + "value": 0 + }, + { + "name": "green", + "value": 1 + }, + { + "name": "blue", + "value": 2 + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/9cbddfd4afa15219.json b/type-parser/mini-parser-ts/test/snapshots/9cbddfd4afa15219.json new file mode 100644 index 000000000..f8bc95592 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/9cbddfd4afa15219.json @@ -0,0 +1,21 @@ +{ + "type": "Variant(UInt8, Int16, UInt32)", + "data_type": { + "type": "DataType", + "name": "Variant", + "arguments": [ + { + "type": "DataType", + "name": "UInt8" + }, + { + "type": "DataType", + "name": "Int16" + }, + { + "type": "DataType", + "name": "UInt32" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/9d618df2b0f244f4.json b/type-parser/mini-parser-ts/test/snapshots/9d618df2b0f244f4.json new file mode 100644 index 000000000..4baf7eadc --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/9d618df2b0f244f4.json @@ -0,0 +1,17 @@ +{ + "type": "Variant( UInt64 , String )", + "data_type": { + "type": "DataType", + "name": "Variant", + "arguments": [ + { + "type": "DataType", + "name": "UInt64" + }, + { + "type": "DataType", + "name": "String" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/9e170c7c7025a1a5.json b/type-parser/mini-parser-ts/test/snapshots/9e170c7c7025a1a5.json new file mode 100644 index 000000000..aa28dca3c --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/9e170c7c7025a1a5.json @@ -0,0 +1,7 @@ +{ + "type": "SMALLINT", + "data_type": { + "type": "DataType", + "name": "SMALLINT" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/9f561ebcb560c871.json b/type-parser/mini-parser-ts/test/snapshots/9f561ebcb560c871.json new file mode 100644 index 000000000..0fb75c5af --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/9f561ebcb560c871.json @@ -0,0 +1,7 @@ +{ + "type": "TINYINT UNSIGNED", + "data_type": { + "type": "DataType", + "name": "TINYINT UNSIGNED" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/9fbbc9c6e35de50d.json b/type-parser/mini-parser-ts/test/snapshots/9fbbc9c6e35de50d.json new file mode 100644 index 000000000..1f1138009 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/9fbbc9c6e35de50d.json @@ -0,0 +1,14 @@ +{ + "type": "DateTime('America/New_York')", + "data_type": { + "type": "DataType", + "name": "DateTime", + "arguments": [ + { + "type": "Literal", + "value_type": "String", + "value": "America/New_York" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/a148b5c78eff3afa.json b/type-parser/mini-parser-ts/test/snapshots/a148b5c78eff3afa.json new file mode 100644 index 000000000..8668ff401 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/a148b5c78eff3afa.json @@ -0,0 +1,19 @@ +{ + "type": "Decimal(30, 15)", + "data_type": { + "type": "DataType", + "name": "Decimal", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "30" + }, + { + "type": "Literal", + "value_type": "UInt64", + "value": "15" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/a1b36e70b213ab9a.json b/type-parser/mini-parser-ts/test/snapshots/a1b36e70b213ab9a.json new file mode 100644 index 000000000..2aa1c0ea3 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/a1b36e70b213ab9a.json @@ -0,0 +1,13 @@ +{ + "type": "LowCardinality(String)", + "data_type": { + "type": "DataType", + "name": "LowCardinality", + "arguments": [ + { + "type": "DataType", + "name": "String" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/a314e0179bfc11f0.json b/type-parser/mini-parser-ts/test/snapshots/a314e0179bfc11f0.json new file mode 100644 index 000000000..9daa3e43b --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/a314e0179bfc11f0.json @@ -0,0 +1,7 @@ +{ + "type": "UInt128", + "data_type": { + "type": "DataType", + "name": "UInt128" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/a3bd1284c7e4a6ab.json b/type-parser/mini-parser-ts/test/snapshots/a3bd1284c7e4a6ab.json new file mode 100644 index 000000000..4b95239f0 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/a3bd1284c7e4a6ab.json @@ -0,0 +1,14 @@ +{ + "type": "Time64(9)", + "data_type": { + "type": "DataType", + "name": "Time64", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "9" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/a5215edb17e53ed3.json b/type-parser/mini-parser-ts/test/snapshots/a5215edb17e53ed3.json new file mode 100644 index 000000000..4bec7fc27 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/a5215edb17e53ed3.json @@ -0,0 +1,17 @@ +{ + "type": "Enum8('with space' = 1, 'another one' = 2)", + "data_type": { + "type": "EnumDataType", + "name": "Enum8", + "values": [ + { + "name": "with space", + "value": 1 + }, + { + "name": "another one", + "value": 2 + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/a55e385aa7e8d7ec.json b/type-parser/mini-parser-ts/test/snapshots/a55e385aa7e8d7ec.json new file mode 100644 index 000000000..7f4e6b21b --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/a55e385aa7e8d7ec.json @@ -0,0 +1,7 @@ +{ + "type": "NATIONAL CHAR VARYING", + "data_type": { + "type": "DataType", + "name": "NATIONAL CHAR VARYING" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/a8b536b58d6a8ca7.json b/type-parser/mini-parser-ts/test/snapshots/a8b536b58d6a8ca7.json new file mode 100644 index 000000000..0dcb6fb68 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/a8b536b58d6a8ca7.json @@ -0,0 +1,17 @@ +{ + "type": "Map(String, UInt64)", + "data_type": { + "type": "DataType", + "name": "Map", + "arguments": [ + { + "type": "DataType", + "name": "String" + }, + { + "type": "DataType", + "name": "UInt64" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/a8dbffb1eb0d1d99.json b/type-parser/mini-parser-ts/test/snapshots/a8dbffb1eb0d1d99.json new file mode 100644 index 000000000..37622b301 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/a8dbffb1eb0d1d99.json @@ -0,0 +1,17 @@ +{ + "type": "Enum16('x' = -1, 'y' = 100)", + "data_type": { + "type": "EnumDataType", + "name": "Enum16", + "values": [ + { + "name": "x", + "value": -1 + }, + { + "name": "y", + "value": 100 + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/a95e6ce38f4ca609.json b/type-parser/mini-parser-ts/test/snapshots/a95e6ce38f4ca609.json new file mode 100644 index 000000000..ebe88a841 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/a95e6ce38f4ca609.json @@ -0,0 +1,24 @@ +{ + "type": "Map(FixedString(8), UInt32)", + "data_type": { + "type": "DataType", + "name": "Map", + "arguments": [ + { + "type": "DataType", + "name": "FixedString", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "8" + } + ] + }, + { + "type": "DataType", + "name": "UInt32" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/a96d87d7c8b3dcfb.json b/type-parser/mini-parser-ts/test/snapshots/a96d87d7c8b3dcfb.json new file mode 100644 index 000000000..01422aed1 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/a96d87d7c8b3dcfb.json @@ -0,0 +1,7 @@ +{ + "type": "Int8", + "data_type": { + "type": "DataType", + "name": "Int8" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/aa7c18e52c6fe0c3.json b/type-parser/mini-parser-ts/test/snapshots/aa7c18e52c6fe0c3.json new file mode 100644 index 000000000..629154b69 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/aa7c18e52c6fe0c3.json @@ -0,0 +1,13 @@ +{ + "type": "LowCardinality(Date)", + "data_type": { + "type": "DataType", + "name": "LowCardinality", + "arguments": [ + { + "type": "DataType", + "name": "Date" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/ab56a84eb0f06b84.json b/type-parser/mini-parser-ts/test/snapshots/ab56a84eb0f06b84.json new file mode 100644 index 000000000..f82f93d6b --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/ab56a84eb0f06b84.json @@ -0,0 +1,26 @@ +{ + "type": "Tuple(id UInt64, String, flag Bool)", + "data_type": { + "type": "TupleDataType", + "name": "Tuple", + "arguments": [ + { + "type": "DataType", + "name": "UInt64" + }, + { + "type": "DataType", + "name": "String" + }, + { + "type": "DataType", + "name": "Bool" + } + ], + "element_names": [ + "id", + "", + "flag" + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/ab68d8e893a82cff.json b/type-parser/mini-parser-ts/test/snapshots/ab68d8e893a82cff.json new file mode 100644 index 000000000..4e8f502d8 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/ab68d8e893a82cff.json @@ -0,0 +1,7 @@ +{ + "type": "BOOLEAN", + "data_type": { + "type": "DataType", + "name": "BOOLEAN" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/ab7266122e1f020a.json b/type-parser/mini-parser-ts/test/snapshots/ab7266122e1f020a.json new file mode 100644 index 000000000..d47e477f1 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/ab7266122e1f020a.json @@ -0,0 +1,7 @@ +{ + "type": "NVARCHAR", + "data_type": { + "type": "DataType", + "name": "NVARCHAR" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/adcc2a14fead7cd8.json b/type-parser/mini-parser-ts/test/snapshots/adcc2a14fead7cd8.json new file mode 100644 index 000000000..b24731bf5 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/adcc2a14fead7cd8.json @@ -0,0 +1,23 @@ +{ + "type": "Map(String, Array(String))", + "data_type": { + "type": "DataType", + "name": "Map", + "arguments": [ + { + "type": "DataType", + "name": "String" + }, + { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "String" + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/afc75d45f651500f.json b/type-parser/mini-parser-ts/test/snapshots/afc75d45f651500f.json new file mode 100644 index 000000000..bea6bf55e --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/afc75d45f651500f.json @@ -0,0 +1,25 @@ +{ + "type": "Array(LowCardinality(Nullable(String)))", + "data_type": { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "LowCardinality", + "arguments": [ + { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "DataType", + "name": "String" + } + ] + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/b1017bf1dd9b0fe4.json b/type-parser/mini-parser-ts/test/snapshots/b1017bf1dd9b0fe4.json new file mode 100644 index 000000000..14a2d29de --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/b1017bf1dd9b0fe4.json @@ -0,0 +1,35 @@ +{ + "type": "Tuple(Decimal(10, 2), Nullable(String))", + "data_type": { + "type": "TupleDataType", + "name": "Tuple", + "arguments": [ + { + "type": "DataType", + "name": "Decimal", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "10" + }, + { + "type": "Literal", + "value_type": "UInt64", + "value": "2" + } + ] + }, + { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "DataType", + "name": "String" + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/b306956d40529bf3.json b/type-parser/mini-parser-ts/test/snapshots/b306956d40529bf3.json new file mode 100644 index 000000000..4bb010080 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/b306956d40529bf3.json @@ -0,0 +1,21 @@ +{ + "type": "Tuple(a UInt8, b String)", + "data_type": { + "type": "TupleDataType", + "name": "Tuple", + "arguments": [ + { + "type": "DataType", + "name": "UInt8" + }, + { + "type": "DataType", + "name": "String" + } + ], + "element_names": [ + "a", + "b" + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/b321ed35f3d53336.json b/type-parser/mini-parser-ts/test/snapshots/b321ed35f3d53336.json new file mode 100644 index 000000000..4e2126dab --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/b321ed35f3d53336.json @@ -0,0 +1,17 @@ +{ + "type": "Map(UInt64, UInt64)", + "data_type": { + "type": "DataType", + "name": "Map", + "arguments": [ + { + "type": "DataType", + "name": "UInt64" + }, + { + "type": "DataType", + "name": "UInt64" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/b4aa451e69c80088.json b/type-parser/mini-parser-ts/test/snapshots/b4aa451e69c80088.json new file mode 100644 index 000000000..12cb12bb2 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/b4aa451e69c80088.json @@ -0,0 +1,27 @@ +{ + "type": "Map(String, Map(String, UInt64))", + "data_type": { + "type": "DataType", + "name": "Map", + "arguments": [ + { + "type": "DataType", + "name": "String" + }, + { + "type": "DataType", + "name": "Map", + "arguments": [ + { + "type": "DataType", + "name": "String" + }, + { + "type": "DataType", + "name": "UInt64" + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/b4c5e2b4273fdc60.json b/type-parser/mini-parser-ts/test/snapshots/b4c5e2b4273fdc60.json new file mode 100644 index 000000000..64e163002 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/b4c5e2b4273fdc60.json @@ -0,0 +1,13 @@ +{ + "type": "LowCardinality( String )", + "data_type": { + "type": "DataType", + "name": "LowCardinality", + "arguments": [ + { + "type": "DataType", + "name": "String" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/b60cb032709a29a6.json b/type-parser/mini-parser-ts/test/snapshots/b60cb032709a29a6.json new file mode 100644 index 000000000..43ce190d1 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/b60cb032709a29a6.json @@ -0,0 +1,19 @@ +{ + "type": "Decimal(38, 38)", + "data_type": { + "type": "DataType", + "name": "Decimal", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "38" + }, + { + "type": "Literal", + "value_type": "UInt64", + "value": "38" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/b70cb7df11aa9094.json b/type-parser/mini-parser-ts/test/snapshots/b70cb7df11aa9094.json new file mode 100644 index 000000000..ac2e5a150 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/b70cb7df11aa9094.json @@ -0,0 +1,13 @@ +{ + "type": "Nullable(Int32)", + "data_type": { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "DataType", + "name": "Int32" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/b734564dc378b7bd.json b/type-parser/mini-parser-ts/test/snapshots/b734564dc378b7bd.json new file mode 100644 index 000000000..0781dbd2a --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/b734564dc378b7bd.json @@ -0,0 +1,36 @@ +{ + "type": "Variant(String, FixedString(16), UUID, IPv4, IPv6)", + "data_type": { + "type": "DataType", + "name": "Variant", + "arguments": [ + { + "type": "DataType", + "name": "String" + }, + { + "type": "DataType", + "name": "FixedString", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "16" + } + ] + }, + { + "type": "DataType", + "name": "UUID" + }, + { + "type": "DataType", + "name": "IPv4" + }, + { + "type": "DataType", + "name": "IPv6" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/b8cee90b794bb4f1.json b/type-parser/mini-parser-ts/test/snapshots/b8cee90b794bb4f1.json new file mode 100644 index 000000000..6fbc0f3e4 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/b8cee90b794bb4f1.json @@ -0,0 +1,19 @@ +{ + "type": "Decimal(38, 0)", + "data_type": { + "type": "DataType", + "name": "Decimal", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "38" + }, + { + "type": "Literal", + "value_type": "UInt64", + "value": "0" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/b96269387d602df2.json b/type-parser/mini-parser-ts/test/snapshots/b96269387d602df2.json new file mode 100644 index 000000000..fb375076b --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/b96269387d602df2.json @@ -0,0 +1,7 @@ +{ + "type": "MultiLineString", + "data_type": { + "type": "DataType", + "name": "MultiLineString" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/ba328c5fc345c0f2.json b/type-parser/mini-parser-ts/test/snapshots/ba328c5fc345c0f2.json new file mode 100644 index 000000000..63ca00d97 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/ba328c5fc345c0f2.json @@ -0,0 +1,7 @@ +{ + "type": "INT(11)", + "data_type": { + "type": "DataType", + "name": "INT" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/ba5c9413b0237a0c.json b/type-parser/mini-parser-ts/test/snapshots/ba5c9413b0237a0c.json new file mode 100644 index 000000000..095e4f193 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/ba5c9413b0237a0c.json @@ -0,0 +1,19 @@ +{ + "type": "Decimal(2, 1)", + "data_type": { + "type": "DataType", + "name": "Decimal", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "2" + }, + { + "type": "Literal", + "value_type": "UInt64", + "value": "1" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/bad418ae7c592db2.json b/type-parser/mini-parser-ts/test/snapshots/bad418ae7c592db2.json new file mode 100644 index 000000000..4cc5d8011 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/bad418ae7c592db2.json @@ -0,0 +1,26 @@ +{ + "type": "Tuple(x Int32, y Int32, z Int32)", + "data_type": { + "type": "TupleDataType", + "name": "Tuple", + "arguments": [ + { + "type": "DataType", + "name": "Int32" + }, + { + "type": "DataType", + "name": "Int32" + }, + { + "type": "DataType", + "name": "Int32" + } + ], + "element_names": [ + "x", + "y", + "z" + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/bb588ee05a3b285f.json b/type-parser/mini-parser-ts/test/snapshots/bb588ee05a3b285f.json new file mode 100644 index 000000000..428368467 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/bb588ee05a3b285f.json @@ -0,0 +1,21 @@ +{ + "type": "Variant(String, UInt64, Float64)", + "data_type": { + "type": "DataType", + "name": "Variant", + "arguments": [ + { + "type": "DataType", + "name": "String" + }, + { + "type": "DataType", + "name": "UInt64" + }, + { + "type": "DataType", + "name": "Float64" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/bbaa27c010a10469.json b/type-parser/mini-parser-ts/test/snapshots/bbaa27c010a10469.json new file mode 100644 index 000000000..b23d9fea3 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/bbaa27c010a10469.json @@ -0,0 +1,27 @@ +{ + "type": "Tuple(Tuple(UInt8, String), Float64)", + "data_type": { + "type": "TupleDataType", + "name": "Tuple", + "arguments": [ + { + "type": "TupleDataType", + "name": "Tuple", + "arguments": [ + { + "type": "DataType", + "name": "UInt8" + }, + { + "type": "DataType", + "name": "String" + } + ] + }, + { + "type": "DataType", + "name": "Float64" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/bbdddd4971d19599.json b/type-parser/mini-parser-ts/test/snapshots/bbdddd4971d19599.json new file mode 100644 index 000000000..5092461c7 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/bbdddd4971d19599.json @@ -0,0 +1,14 @@ +{ + "type": "CHAR(10)", + "data_type": { + "type": "DataType", + "name": "CHAR", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "10" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/bc45bad0c8791d60.json b/type-parser/mini-parser-ts/test/snapshots/bc45bad0c8791d60.json new file mode 100644 index 000000000..7f9a33860 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/bc45bad0c8791d60.json @@ -0,0 +1,23 @@ +{ + "type": "Variant(Nullable(UInt64), String)", + "data_type": { + "type": "DataType", + "name": "Variant", + "arguments": [ + { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "DataType", + "name": "UInt64" + } + ] + }, + { + "type": "DataType", + "name": "String" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/bd226d3d4f21c323.json b/type-parser/mini-parser-ts/test/snapshots/bd226d3d4f21c323.json new file mode 100644 index 000000000..b4e3a9aa2 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/bd226d3d4f21c323.json @@ -0,0 +1,33 @@ +{ + "type": "Variant(Tuple(UInt8, String), Array(Float64))", + "data_type": { + "type": "DataType", + "name": "Variant", + "arguments": [ + { + "type": "TupleDataType", + "name": "Tuple", + "arguments": [ + { + "type": "DataType", + "name": "UInt8" + }, + { + "type": "DataType", + "name": "String" + } + ] + }, + { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "Float64" + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/bd92f5ce619c26da.json b/type-parser/mini-parser-ts/test/snapshots/bd92f5ce619c26da.json new file mode 100644 index 000000000..ffcdfade8 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/bd92f5ce619c26da.json @@ -0,0 +1,14 @@ +{ + "type": "FixedString(32)", + "data_type": { + "type": "DataType", + "name": "FixedString", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "32" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/be25137f16c1f587.json b/type-parser/mini-parser-ts/test/snapshots/be25137f16c1f587.json new file mode 100644 index 000000000..97930af1a --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/be25137f16c1f587.json @@ -0,0 +1,17 @@ +{ + "type": "Variant(UInt64, String)", + "data_type": { + "type": "DataType", + "name": "Variant", + "arguments": [ + { + "type": "DataType", + "name": "UInt64" + }, + { + "type": "DataType", + "name": "String" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/bf23ba5bb47b8e4e.json b/type-parser/mini-parser-ts/test/snapshots/bf23ba5bb47b8e4e.json new file mode 100644 index 000000000..15fed0b35 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/bf23ba5bb47b8e4e.json @@ -0,0 +1,29 @@ +{ + "type": "Enum16('a' = 1, 'b' = 2, 'c' = 3, 'd' = 4, 'e' = 5)", + "data_type": { + "type": "EnumDataType", + "name": "Enum16", + "values": [ + { + "name": "a", + "value": 1 + }, + { + "name": "b", + "value": 2 + }, + { + "name": "c", + "value": 3 + }, + { + "name": "d", + "value": 4 + }, + { + "name": "e", + "value": 5 + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/c0e76a72cd8b87eb.json b/type-parser/mini-parser-ts/test/snapshots/c0e76a72cd8b87eb.json new file mode 100644 index 000000000..fe611a553 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/c0e76a72cd8b87eb.json @@ -0,0 +1,39 @@ +{ + "type": "Array(Tuple(Enum8('a' = 1, 'b' = 2), Array(UInt8)))", + "data_type": { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "TupleDataType", + "name": "Tuple", + "arguments": [ + { + "type": "EnumDataType", + "name": "Enum8", + "values": [ + { + "name": "a", + "value": 1 + }, + { + "name": "b", + "value": 2 + } + ] + }, + { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "UInt8" + } + ] + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/c0f0cadca0773416.json b/type-parser/mini-parser-ts/test/snapshots/c0f0cadca0773416.json new file mode 100644 index 000000000..fa301e73d --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/c0f0cadca0773416.json @@ -0,0 +1,7 @@ +{ + "type": "YEAR", + "data_type": { + "type": "DataType", + "name": "YEAR" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/c1543d88719671aa.json b/type-parser/mini-parser-ts/test/snapshots/c1543d88719671aa.json new file mode 100644 index 000000000..2b83233da --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/c1543d88719671aa.json @@ -0,0 +1,7 @@ +{ + "type": "LONGTEXT", + "data_type": { + "type": "DataType", + "name": "LONGTEXT" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/c271016d67dd8d54.json b/type-parser/mini-parser-ts/test/snapshots/c271016d67dd8d54.json new file mode 100644 index 000000000..74c2af8ed --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/c271016d67dd8d54.json @@ -0,0 +1,19 @@ +{ + "type": "Array( Nullable( UInt64 ) )", + "data_type": { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "DataType", + "name": "UInt64" + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/c2ca3c43a16ca245.json b/type-parser/mini-parser-ts/test/snapshots/c2ca3c43a16ca245.json new file mode 100644 index 000000000..f22d64e92 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/c2ca3c43a16ca245.json @@ -0,0 +1,14 @@ +{ + "type": "Enum8('a')", + "data_type": { + "type": "DataType", + "name": "Enum8", + "arguments": [ + { + "type": "Literal", + "value_type": "String", + "value": "a" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/c3dc913b07d28a5b.json b/type-parser/mini-parser-ts/test/snapshots/c3dc913b07d28a5b.json new file mode 100644 index 000000000..3dcb2999b --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/c3dc913b07d28a5b.json @@ -0,0 +1,14 @@ +{ + "type": "Decimal128(10)", + "data_type": { + "type": "DataType", + "name": "Decimal128", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "10" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/c45aaac1573d8a07.json b/type-parser/mini-parser-ts/test/snapshots/c45aaac1573d8a07.json new file mode 100644 index 000000000..6e994d5bc --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/c45aaac1573d8a07.json @@ -0,0 +1,25 @@ +{ + "type": "Dynamic(max_types = 255)", + "data_type": { + "type": "DataType", + "name": "Dynamic", + "arguments": [ + { + "type": "Function", + "name": "equals", + "is_operator": true, + "arguments": [ + { + "type": "Identifier", + "name": "max_types" + }, + { + "type": "Literal", + "value_type": "UInt64", + "value": "255" + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/c4605abe1a663a47.json b/type-parser/mini-parser-ts/test/snapshots/c4605abe1a663a47.json new file mode 100644 index 000000000..c6492d3c9 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/c4605abe1a663a47.json @@ -0,0 +1,17 @@ +{ + "type": "Enum8('a' = 1, 'b' = 2)", + "data_type": { + "type": "EnumDataType", + "name": "Enum8", + "values": [ + { + "name": "a", + "value": 1 + }, + { + "name": "b", + "value": 2 + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/c4904982bc938507.json b/type-parser/mini-parser-ts/test/snapshots/c4904982bc938507.json new file mode 100644 index 000000000..be447d409 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/c4904982bc938507.json @@ -0,0 +1,27 @@ +{ + "type": "Map(String, Tuple(UInt8, String))", + "data_type": { + "type": "DataType", + "name": "Map", + "arguments": [ + { + "type": "DataType", + "name": "String" + }, + { + "type": "TupleDataType", + "name": "Tuple", + "arguments": [ + { + "type": "DataType", + "name": "UInt8" + }, + { + "type": "DataType", + "name": "String" + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/c5a8be2409ab2f1d.json b/type-parser/mini-parser-ts/test/snapshots/c5a8be2409ab2f1d.json new file mode 100644 index 000000000..ff4a57729 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/c5a8be2409ab2f1d.json @@ -0,0 +1,25 @@ +{ + "type": "Dynamic(max_types = 10)", + "data_type": { + "type": "DataType", + "name": "Dynamic", + "arguments": [ + { + "type": "Function", + "name": "equals", + "is_operator": true, + "arguments": [ + { + "type": "Identifier", + "name": "max_types" + }, + { + "type": "Literal", + "value_type": "UInt64", + "value": "10" + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/c643b487ea6dfd72.json b/type-parser/mini-parser-ts/test/snapshots/c643b487ea6dfd72.json new file mode 100644 index 000000000..19b582aa5 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/c643b487ea6dfd72.json @@ -0,0 +1,17 @@ +{ + "type": "Map( String , UInt64 )", + "data_type": { + "type": "DataType", + "name": "Map", + "arguments": [ + { + "type": "DataType", + "name": "String" + }, + { + "type": "DataType", + "name": "UInt64" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/c78c17175a5c0e87.json b/type-parser/mini-parser-ts/test/snapshots/c78c17175a5c0e87.json new file mode 100644 index 000000000..6d6223453 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/c78c17175a5c0e87.json @@ -0,0 +1,7 @@ +{ + "type": "BINARY VARYING", + "data_type": { + "type": "DataType", + "name": "BINARY VARYING" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/c8093b3c6d44d486.json b/type-parser/mini-parser-ts/test/snapshots/c8093b3c6d44d486.json new file mode 100644 index 000000000..ecb2ffa6d --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/c8093b3c6d44d486.json @@ -0,0 +1,13 @@ +{ + "type": "Nullable(Date)", + "data_type": { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "DataType", + "name": "Date" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/c861c5ff0886a0f9.json b/type-parser/mini-parser-ts/test/snapshots/c861c5ff0886a0f9.json new file mode 100644 index 000000000..ff1b1fa35 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/c861c5ff0886a0f9.json @@ -0,0 +1,7 @@ +{ + "type": "IntervalHour", + "data_type": { + "type": "DataType", + "name": "IntervalHour" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/c86fdaa691b98f8b.json b/type-parser/mini-parser-ts/test/snapshots/c86fdaa691b98f8b.json new file mode 100644 index 000000000..754126637 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/c86fdaa691b98f8b.json @@ -0,0 +1,14 @@ +{ + "type": "FixedString(255)", + "data_type": { + "type": "DataType", + "name": "FixedString", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "255" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/c901bde075754bb0.json b/type-parser/mini-parser-ts/test/snapshots/c901bde075754bb0.json new file mode 100644 index 000000000..f7d9a7cad --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/c901bde075754bb0.json @@ -0,0 +1,13 @@ +{ + "type": "Array(Point)", + "data_type": { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "Point" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/c9f338bf38999cef.json b/type-parser/mini-parser-ts/test/snapshots/c9f338bf38999cef.json new file mode 100644 index 000000000..f42991326 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/c9f338bf38999cef.json @@ -0,0 +1,14 @@ +{ + "type": "varchar(255)", + "data_type": { + "type": "DataType", + "name": "varchar", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "255" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/ca7b55d1b3b969de.json b/type-parser/mini-parser-ts/test/snapshots/ca7b55d1b3b969de.json new file mode 100644 index 000000000..fbf2ece80 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/ca7b55d1b3b969de.json @@ -0,0 +1,17 @@ +{ + "type": "Enum8( 'a' = 1 , 'b' = 2 )", + "data_type": { + "type": "EnumDataType", + "name": "Enum8", + "values": [ + { + "name": "a", + "value": 1 + }, + { + "name": "b", + "value": 2 + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/cb3651f0a9fbe7c0.json b/type-parser/mini-parser-ts/test/snapshots/cb3651f0a9fbe7c0.json new file mode 100644 index 000000000..bd5840098 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/cb3651f0a9fbe7c0.json @@ -0,0 +1,27 @@ +{ + "type": "Tuple(key String, payload Array(UInt8))", + "data_type": { + "type": "TupleDataType", + "name": "Tuple", + "arguments": [ + { + "type": "DataType", + "name": "String" + }, + { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "UInt8" + } + ] + } + ], + "element_names": [ + "key", + "payload" + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/cbad8c51a3e1d032.json b/type-parser/mini-parser-ts/test/snapshots/cbad8c51a3e1d032.json new file mode 100644 index 000000000..ee5338001 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/cbad8c51a3e1d032.json @@ -0,0 +1,19 @@ +{ + "type": "LowCardinality(Nullable(String))", + "data_type": { + "type": "DataType", + "name": "LowCardinality", + "arguments": [ + { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "DataType", + "name": "String" + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/cd98ae36981ee80a.json b/type-parser/mini-parser-ts/test/snapshots/cd98ae36981ee80a.json new file mode 100644 index 000000000..e68ef90ff --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/cd98ae36981ee80a.json @@ -0,0 +1,7 @@ +{ + "type": "FLOAT", + "data_type": { + "type": "DataType", + "name": "FLOAT" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/cda2841ab393e45d.json b/type-parser/mini-parser-ts/test/snapshots/cda2841ab393e45d.json new file mode 100644 index 000000000..ddcc6f9c0 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/cda2841ab393e45d.json @@ -0,0 +1,19 @@ +{ + "type": "Array(LowCardinality(String))", + "data_type": { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "LowCardinality", + "arguments": [ + { + "type": "DataType", + "name": "String" + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/ce3bb6ac91e15082.json b/type-parser/mini-parser-ts/test/snapshots/ce3bb6ac91e15082.json new file mode 100644 index 000000000..9b402c004 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/ce3bb6ac91e15082.json @@ -0,0 +1,7 @@ +{ + "type": "MultiPolygon", + "data_type": { + "type": "DataType", + "name": "MultiPolygon" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/ceb02f409a78f4ef.json b/type-parser/mini-parser-ts/test/snapshots/ceb02f409a78f4ef.json new file mode 100644 index 000000000..6799b7126 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/ceb02f409a78f4ef.json @@ -0,0 +1,7 @@ +{ + "type": "Float64", + "data_type": { + "type": "DataType", + "name": "Float64" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/ceb739dfaa883916.json b/type-parser/mini-parser-ts/test/snapshots/ceb739dfaa883916.json new file mode 100644 index 000000000..13e37c9fc --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/ceb739dfaa883916.json @@ -0,0 +1,7 @@ +{ + "type": "Dynamic", + "data_type": { + "type": "DataType", + "name": "Dynamic" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/cf31903898d06426.json b/type-parser/mini-parser-ts/test/snapshots/cf31903898d06426.json new file mode 100644 index 000000000..97f78f2fb --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/cf31903898d06426.json @@ -0,0 +1,7 @@ +{ + "type": "UInt8", + "data_type": { + "type": "DataType", + "name": "UInt8" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/cf640c0ceb20ff34.json b/type-parser/mini-parser-ts/test/snapshots/cf640c0ceb20ff34.json new file mode 100644 index 000000000..79fedeb66 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/cf640c0ceb20ff34.json @@ -0,0 +1,19 @@ +{ + "type": "Decimal(1, 0)", + "data_type": { + "type": "DataType", + "name": "Decimal", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "1" + }, + { + "type": "Literal", + "value_type": "UInt64", + "value": "0" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/d05fb01e0b399387.json b/type-parser/mini-parser-ts/test/snapshots/d05fb01e0b399387.json new file mode 100644 index 000000000..ee656174c --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/d05fb01e0b399387.json @@ -0,0 +1,7 @@ +{ + "type": "BINARY", + "data_type": { + "type": "DataType", + "name": "BINARY" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/d3a3854ba98eb85d.json b/type-parser/mini-parser-ts/test/snapshots/d3a3854ba98eb85d.json new file mode 100644 index 000000000..fe0754dfd --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/d3a3854ba98eb85d.json @@ -0,0 +1,13 @@ +{ + "type": "Array(IPv4)", + "data_type": { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "IPv4" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/d3e90af2aefe399f.json b/type-parser/mini-parser-ts/test/snapshots/d3e90af2aefe399f.json new file mode 100644 index 000000000..b5d1d7d10 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/d3e90af2aefe399f.json @@ -0,0 +1,13 @@ +{ + "type": "Nullable(UInt8)", + "data_type": { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "DataType", + "name": "UInt8" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/d41324ffd6eed6b3.json b/type-parser/mini-parser-ts/test/snapshots/d41324ffd6eed6b3.json new file mode 100644 index 000000000..27524f9b6 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/d41324ffd6eed6b3.json @@ -0,0 +1,14 @@ +{ + "type": "Decimal64(0)", + "data_type": { + "type": "DataType", + "name": "Decimal64", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "0" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/d62cec53886ff651.json b/type-parser/mini-parser-ts/test/snapshots/d62cec53886ff651.json new file mode 100644 index 000000000..30d280e74 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/d62cec53886ff651.json @@ -0,0 +1,17 @@ +{ + "type": "Enum('hello world' = 1, 'foo bar' = 2)", + "data_type": { + "type": "EnumDataType", + "name": "Enum", + "values": [ + { + "name": "hello world", + "value": 1 + }, + { + "name": "foo bar", + "value": 2 + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/d64027e56b998e7c.json b/type-parser/mini-parser-ts/test/snapshots/d64027e56b998e7c.json new file mode 100644 index 000000000..5532da134 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/d64027e56b998e7c.json @@ -0,0 +1,26 @@ +{ + "type": "Tuple(UInt8, b String, Float64)", + "data_type": { + "type": "TupleDataType", + "name": "Tuple", + "arguments": [ + { + "type": "DataType", + "name": "UInt8" + }, + { + "type": "DataType", + "name": "String" + }, + { + "type": "DataType", + "name": "Float64" + } + ], + "element_names": [ + "", + "b", + "" + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/d669ea9cedaeb679.json b/type-parser/mini-parser-ts/test/snapshots/d669ea9cedaeb679.json new file mode 100644 index 000000000..e1bcb2360 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/d669ea9cedaeb679.json @@ -0,0 +1,25 @@ +{ + "type": "Dynamic(max_types = 100)", + "data_type": { + "type": "DataType", + "name": "Dynamic", + "arguments": [ + { + "type": "Function", + "name": "equals", + "is_operator": true, + "arguments": [ + { + "type": "Identifier", + "name": "max_types" + }, + { + "type": "Literal", + "value_type": "UInt64", + "value": "100" + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/d701a37b6e4cf4e9.json b/type-parser/mini-parser-ts/test/snapshots/d701a37b6e4cf4e9.json new file mode 100644 index 000000000..e374776cb --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/d701a37b6e4cf4e9.json @@ -0,0 +1,14 @@ +{ + "type": "Time64(3)", + "data_type": { + "type": "DataType", + "name": "Time64", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "3" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/d712296f71e49233.json b/type-parser/mini-parser-ts/test/snapshots/d712296f71e49233.json new file mode 100644 index 000000000..41af5888d --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/d712296f71e49233.json @@ -0,0 +1,14 @@ +{ + "type": "VARCHAR(64)", + "data_type": { + "type": "DataType", + "name": "VARCHAR", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "64" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/d773faf0b86ac88b.json b/type-parser/mini-parser-ts/test/snapshots/d773faf0b86ac88b.json new file mode 100644 index 000000000..d5ae65351 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/d773faf0b86ac88b.json @@ -0,0 +1,14 @@ +{ + "type": "Object('json')", + "data_type": { + "type": "DataType", + "name": "Object", + "arguments": [ + { + "type": "Literal", + "value_type": "String", + "value": "json" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/d8367e8f5ce1f2ca.json b/type-parser/mini-parser-ts/test/snapshots/d8367e8f5ce1f2ca.json new file mode 100644 index 000000000..49fbff885 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/d8367e8f5ce1f2ca.json @@ -0,0 +1,14 @@ +{ + "type": "Decimal32(2)", + "data_type": { + "type": "DataType", + "name": "Decimal32", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "2" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/d9c0ea6152fbf443.json b/type-parser/mini-parser-ts/test/snapshots/d9c0ea6152fbf443.json new file mode 100644 index 000000000..6b4b69c14 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/d9c0ea6152fbf443.json @@ -0,0 +1,13 @@ +{ + "type": "Array(UUID)", + "data_type": { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "UUID" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/da0fdc28c11b5812.json b/type-parser/mini-parser-ts/test/snapshots/da0fdc28c11b5812.json new file mode 100644 index 000000000..cafcd2fc1 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/da0fdc28c11b5812.json @@ -0,0 +1,14 @@ +{ + "type": "Decimal32(9)", + "data_type": { + "type": "DataType", + "name": "Decimal32", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "9" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/daf760a167a8047c.json b/type-parser/mini-parser-ts/test/snapshots/daf760a167a8047c.json new file mode 100644 index 000000000..19b194bf8 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/daf760a167a8047c.json @@ -0,0 +1,7 @@ +{ + "type": "Bool", + "data_type": { + "type": "DataType", + "name": "Bool" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/db09a2734af421e6.json b/type-parser/mini-parser-ts/test/snapshots/db09a2734af421e6.json new file mode 100644 index 000000000..7991eb0c5 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/db09a2734af421e6.json @@ -0,0 +1,39 @@ +{ + "type": "Tuple(ts DateTime64(3, 'UTC'), val Nullable(Float64))", + "data_type": { + "type": "TupleDataType", + "name": "Tuple", + "arguments": [ + { + "type": "DataType", + "name": "DateTime64", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "3" + }, + { + "type": "Literal", + "value_type": "String", + "value": "UTC" + } + ] + }, + { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "DataType", + "name": "Float64" + } + ] + } + ], + "element_names": [ + "ts", + "val" + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/dc1e8f7f69dcbc15.json b/type-parser/mini-parser-ts/test/snapshots/dc1e8f7f69dcbc15.json new file mode 100644 index 000000000..caac854e5 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/dc1e8f7f69dcbc15.json @@ -0,0 +1,17 @@ +{ + "type": "Map(String, String)", + "data_type": { + "type": "DataType", + "name": "Map", + "arguments": [ + { + "type": "DataType", + "name": "String" + }, + { + "type": "DataType", + "name": "String" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/dd0748912e59ec25.json b/type-parser/mini-parser-ts/test/snapshots/dd0748912e59ec25.json new file mode 100644 index 000000000..228022a01 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/dd0748912e59ec25.json @@ -0,0 +1,21 @@ +{ + "type": "Tuple(a UInt8, String)", + "data_type": { + "type": "TupleDataType", + "name": "Tuple", + "arguments": [ + { + "type": "DataType", + "name": "UInt8" + }, + { + "type": "DataType", + "name": "String" + } + ], + "element_names": [ + "a", + "" + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/dd6fa4122e474566.json b/type-parser/mini-parser-ts/test/snapshots/dd6fa4122e474566.json new file mode 100644 index 000000000..05c3d83bb --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/dd6fa4122e474566.json @@ -0,0 +1,13 @@ +{ + "type": "Nullable(Int64)", + "data_type": { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "DataType", + "name": "Int64" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/de785c721705dbba.json b/type-parser/mini-parser-ts/test/snapshots/de785c721705dbba.json new file mode 100644 index 000000000..1caefa87c --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/de785c721705dbba.json @@ -0,0 +1,7 @@ +{ + "type": "IntervalQuarter", + "data_type": { + "type": "DataType", + "name": "IntervalQuarter" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/de86a870104fb0a5.json b/type-parser/mini-parser-ts/test/snapshots/de86a870104fb0a5.json new file mode 100644 index 000000000..7f7cfe4df --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/de86a870104fb0a5.json @@ -0,0 +1,7 @@ +{ + "type": "Int128", + "data_type": { + "type": "DataType", + "name": "Int128" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/dec8ddb4c2e278d9.json b/type-parser/mini-parser-ts/test/snapshots/dec8ddb4c2e278d9.json new file mode 100644 index 000000000..6d229f09e --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/dec8ddb4c2e278d9.json @@ -0,0 +1,17 @@ +{ + "type": "Variant(UInt8, String)", + "data_type": { + "type": "DataType", + "name": "Variant", + "arguments": [ + { + "type": "DataType", + "name": "UInt8" + }, + { + "type": "DataType", + "name": "String" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/df0e5006b34734de.json b/type-parser/mini-parser-ts/test/snapshots/df0e5006b34734de.json new file mode 100644 index 000000000..82e5fd8f3 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/df0e5006b34734de.json @@ -0,0 +1,7 @@ +{ + "type": "varchar", + "data_type": { + "type": "DataType", + "name": "varchar" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/df6b4430f3a214bb.json b/type-parser/mini-parser-ts/test/snapshots/df6b4430f3a214bb.json new file mode 100644 index 000000000..1a659f0db --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/df6b4430f3a214bb.json @@ -0,0 +1,21 @@ +{ + "type": "Enum16('日本語' = 1, 'español' = 2, 'русский' = 3)", + "data_type": { + "type": "EnumDataType", + "name": "Enum16", + "values": [ + { + "name": "日本語", + "value": 1 + }, + { + "name": "español", + "value": 2 + }, + { + "name": "русский", + "value": 3 + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/e2102781550b6a87.json b/type-parser/mini-parser-ts/test/snapshots/e2102781550b6a87.json new file mode 100644 index 000000000..7ad1ceb4c --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/e2102781550b6a87.json @@ -0,0 +1,53 @@ +{ + "type": "Tuple(v Variant(Int32, String), arr Array(Map(String, Nullable(UInt64))))", + "data_type": { + "type": "TupleDataType", + "name": "Tuple", + "arguments": [ + { + "type": "DataType", + "name": "Variant", + "arguments": [ + { + "type": "DataType", + "name": "Int32" + }, + { + "type": "DataType", + "name": "String" + } + ] + }, + { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "Map", + "arguments": [ + { + "type": "DataType", + "name": "String" + }, + { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "DataType", + "name": "UInt64" + } + ] + } + ] + } + ] + } + ], + "element_names": [ + "v", + "arr" + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/e2227d1f14c97584.json b/type-parser/mini-parser-ts/test/snapshots/e2227d1f14c97584.json new file mode 100644 index 000000000..1c16f4a2f --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/e2227d1f14c97584.json @@ -0,0 +1,13 @@ +{ + "type": "Nullable(IPv6)", + "data_type": { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "DataType", + "name": "IPv6" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/e227de9f1df532c1.json b/type-parser/mini-parser-ts/test/snapshots/e227de9f1df532c1.json new file mode 100644 index 000000000..70c513b30 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/e227de9f1df532c1.json @@ -0,0 +1,67 @@ +{ + "type": "Array(Map(LowCardinality(String), Array(Tuple(a UInt8, b Nullable(Decimal(18, 6))))))", + "data_type": { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "Map", + "arguments": [ + { + "type": "DataType", + "name": "LowCardinality", + "arguments": [ + { + "type": "DataType", + "name": "String" + } + ] + }, + { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "TupleDataType", + "name": "Tuple", + "arguments": [ + { + "type": "DataType", + "name": "UInt8" + }, + { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "DataType", + "name": "Decimal", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "18" + }, + { + "type": "Literal", + "value_type": "UInt64", + "value": "6" + } + ] + } + ] + } + ], + "element_names": [ + "a", + "b" + ] + } + ] + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/e3b6ce3dbb8f6886.json b/type-parser/mini-parser-ts/test/snapshots/e3b6ce3dbb8f6886.json new file mode 100644 index 000000000..b7c4ab52c --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/e3b6ce3dbb8f6886.json @@ -0,0 +1,19 @@ +{ + "type": "Enum16('alpha', 'beta')", + "data_type": { + "type": "DataType", + "name": "Enum16", + "arguments": [ + { + "type": "Literal", + "value_type": "String", + "value": "alpha" + }, + { + "type": "Literal", + "value_type": "String", + "value": "beta" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/e56ae18058a93567.json b/type-parser/mini-parser-ts/test/snapshots/e56ae18058a93567.json new file mode 100644 index 000000000..f3c9f9381 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/e56ae18058a93567.json @@ -0,0 +1,37 @@ +{ + "type": "Nested(name String, tags Array(LowCardinality(String)))", + "data_type": { + "type": "DataType", + "name": "Nested", + "arguments": [ + { + "type": "NameTypePair", + "name": "name", + "data_type": { + "type": "DataType", + "name": "String" + } + }, + { + "type": "NameTypePair", + "name": "tags", + "data_type": { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "LowCardinality", + "arguments": [ + { + "type": "DataType", + "name": "String" + } + ] + } + ] + } + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/e5fa045b9b25e6db.json b/type-parser/mini-parser-ts/test/snapshots/e5fa045b9b25e6db.json new file mode 100644 index 000000000..df5ab3098 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/e5fa045b9b25e6db.json @@ -0,0 +1,14 @@ +{ + "type": "FixedString(1024)", + "data_type": { + "type": "DataType", + "name": "FixedString", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "1024" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/e64cdc56ad4c4e02.json b/type-parser/mini-parser-ts/test/snapshots/e64cdc56ad4c4e02.json new file mode 100644 index 000000000..f7a6f80b1 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/e64cdc56ad4c4e02.json @@ -0,0 +1,13 @@ +{ + "type": "Nullable(DateTime)", + "data_type": { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "DataType", + "name": "DateTime" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/e71e7bc3fe9e9f3c.json b/type-parser/mini-parser-ts/test/snapshots/e71e7bc3fe9e9f3c.json new file mode 100644 index 000000000..b7eda5d83 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/e71e7bc3fe9e9f3c.json @@ -0,0 +1,7 @@ +{ + "type": "UInt32", + "data_type": { + "type": "DataType", + "name": "UInt32" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/e7eb51047d99b420.json b/type-parser/mini-parser-ts/test/snapshots/e7eb51047d99b420.json new file mode 100644 index 000000000..8a2ab1718 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/e7eb51047d99b420.json @@ -0,0 +1,13 @@ +{ + "type": "LowCardinality(Float64)", + "data_type": { + "type": "DataType", + "name": "LowCardinality", + "arguments": [ + { + "type": "DataType", + "name": "Float64" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/e83319c6c4642871.json b/type-parser/mini-parser-ts/test/snapshots/e83319c6c4642871.json new file mode 100644 index 000000000..243b908bb --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/e83319c6c4642871.json @@ -0,0 +1,14 @@ +{ + "type": "Decimal128(38)", + "data_type": { + "type": "DataType", + "name": "Decimal128", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "38" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/e89762d9c1f07a3d.json b/type-parser/mini-parser-ts/test/snapshots/e89762d9c1f07a3d.json new file mode 100644 index 000000000..7c08c71e4 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/e89762d9c1f07a3d.json @@ -0,0 +1,7 @@ +{ + "type": "IntervalSecond", + "data_type": { + "type": "DataType", + "name": "IntervalSecond" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/e927c2b90a4679c4.json b/type-parser/mini-parser-ts/test/snapshots/e927c2b90a4679c4.json new file mode 100644 index 000000000..2d8dfbd8a --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/e927c2b90a4679c4.json @@ -0,0 +1,14 @@ +{ + "type": "DateTime('Asia/Tokyo')", + "data_type": { + "type": "DataType", + "name": "DateTime", + "arguments": [ + { + "type": "Literal", + "value_type": "String", + "value": "Asia/Tokyo" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/e9ca4b2541b01556.json b/type-parser/mini-parser-ts/test/snapshots/e9ca4b2541b01556.json new file mode 100644 index 000000000..ba53a3b02 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/e9ca4b2541b01556.json @@ -0,0 +1,21 @@ +{ + "type": "Tuple(a UInt8, b String)", + "data_type": { + "type": "TupleDataType", + "name": "Tuple", + "arguments": [ + { + "type": "DataType", + "name": "UInt8" + }, + { + "type": "DataType", + "name": "String" + } + ], + "element_names": [ + "a", + "b" + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/eb0071b65f67691e.json b/type-parser/mini-parser-ts/test/snapshots/eb0071b65f67691e.json new file mode 100644 index 000000000..da8dff5e4 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/eb0071b65f67691e.json @@ -0,0 +1,13 @@ +{ + "type": "Array(Int64)", + "data_type": { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "Int64" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/eb4afc85d92c38ea.json b/type-parser/mini-parser-ts/test/snapshots/eb4afc85d92c38ea.json new file mode 100644 index 000000000..c856c36d7 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/eb4afc85d92c38ea.json @@ -0,0 +1,7 @@ +{ + "type": "CHARACTER VARYING", + "data_type": { + "type": "DataType", + "name": "CHARACTER VARYING" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/eb9a4bc1c0c153e4.json b/type-parser/mini-parser-ts/test/snapshots/eb9a4bc1c0c153e4.json new file mode 100644 index 000000000..b792c6dfa --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/eb9a4bc1c0c153e4.json @@ -0,0 +1,7 @@ +{ + "type": "Date", + "data_type": { + "type": "DataType", + "name": "Date" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/ed4a033a0e470779.json b/type-parser/mini-parser-ts/test/snapshots/ed4a033a0e470779.json new file mode 100644 index 000000000..8b29a1b99 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/ed4a033a0e470779.json @@ -0,0 +1,19 @@ +{ + "type": "Decimal(20, 5)", + "data_type": { + "type": "DataType", + "name": "Decimal", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "20" + }, + { + "type": "Literal", + "value_type": "UInt64", + "value": "5" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/ed61428e81d608b3.json b/type-parser/mini-parser-ts/test/snapshots/ed61428e81d608b3.json new file mode 100644 index 000000000..6c0d23384 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/ed61428e81d608b3.json @@ -0,0 +1,33 @@ +{ + "type": "Map(String, Array(Map(String, UInt64)))", + "data_type": { + "type": "DataType", + "name": "Map", + "arguments": [ + { + "type": "DataType", + "name": "String" + }, + { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "Map", + "arguments": [ + { + "type": "DataType", + "name": "String" + }, + { + "type": "DataType", + "name": "UInt64" + } + ] + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/ef1ea9269b9833d2.json b/type-parser/mini-parser-ts/test/snapshots/ef1ea9269b9833d2.json new file mode 100644 index 000000000..203ea1000 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/ef1ea9269b9833d2.json @@ -0,0 +1,25 @@ +{ + "type": "Array(Array(Array(Int32)))", + "data_type": { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "Int32" + } + ] + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/effc93c8668219e9.json b/type-parser/mini-parser-ts/test/snapshots/effc93c8668219e9.json new file mode 100644 index 000000000..b96130a1a --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/effc93c8668219e9.json @@ -0,0 +1,26 @@ +{ + "type": "Tuple(p Point, r Ring, poly Polygon)", + "data_type": { + "type": "TupleDataType", + "name": "Tuple", + "arguments": [ + { + "type": "DataType", + "name": "Point" + }, + { + "type": "DataType", + "name": "Ring" + }, + { + "type": "DataType", + "name": "Polygon" + } + ], + "element_names": [ + "p", + "r", + "poly" + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/f1124b0079db9585.json b/type-parser/mini-parser-ts/test/snapshots/f1124b0079db9585.json new file mode 100644 index 000000000..1772e9aa1 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/f1124b0079db9585.json @@ -0,0 +1,31 @@ +{ + "type": "Array(Array(Array(Array(Float64))))", + "data_type": { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "Array", + "arguments": [ + { + "type": "DataType", + "name": "Float64" + } + ] + } + ] + } + ] + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/f161ebdfdf2494e6.json b/type-parser/mini-parser-ts/test/snapshots/f161ebdfdf2494e6.json new file mode 100644 index 000000000..acf712051 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/f161ebdfdf2494e6.json @@ -0,0 +1,7 @@ +{ + "type": "UInt256", + "data_type": { + "type": "DataType", + "name": "UInt256" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/f1e5baf5ecc35896.json b/type-parser/mini-parser-ts/test/snapshots/f1e5baf5ecc35896.json new file mode 100644 index 000000000..193aaa919 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/f1e5baf5ecc35896.json @@ -0,0 +1,7 @@ +{ + "type": "DateTime", + "data_type": { + "type": "DataType", + "name": "DateTime" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/f4753a4dee54ee10.json b/type-parser/mini-parser-ts/test/snapshots/f4753a4dee54ee10.json new file mode 100644 index 000000000..5b912578d --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/f4753a4dee54ee10.json @@ -0,0 +1,7 @@ +{ + "type": "Int32", + "data_type": { + "type": "DataType", + "name": "Int32" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/f47ef5f8d16849a5.json b/type-parser/mini-parser-ts/test/snapshots/f47ef5f8d16849a5.json new file mode 100644 index 000000000..d6c4ad458 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/f47ef5f8d16849a5.json @@ -0,0 +1,41 @@ +{ + "type": "Tuple(UInt8, UInt16, UInt32, UInt64, Int8, Int16, Int32, Int64)", + "data_type": { + "type": "TupleDataType", + "name": "Tuple", + "arguments": [ + { + "type": "DataType", + "name": "UInt8" + }, + { + "type": "DataType", + "name": "UInt16" + }, + { + "type": "DataType", + "name": "UInt32" + }, + { + "type": "DataType", + "name": "UInt64" + }, + { + "type": "DataType", + "name": "Int8" + }, + { + "type": "DataType", + "name": "Int16" + }, + { + "type": "DataType", + "name": "Int32" + }, + { + "type": "DataType", + "name": "Int64" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/f4f033a85ce688b6.json b/type-parser/mini-parser-ts/test/snapshots/f4f033a85ce688b6.json new file mode 100644 index 000000000..eae6a8cf5 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/f4f033a85ce688b6.json @@ -0,0 +1,25 @@ +{ + "type": "Variant(UInt8, UInt16, UInt32, UInt64)", + "data_type": { + "type": "DataType", + "name": "Variant", + "arguments": [ + { + "type": "DataType", + "name": "UInt8" + }, + { + "type": "DataType", + "name": "UInt16" + }, + { + "type": "DataType", + "name": "UInt32" + }, + { + "type": "DataType", + "name": "UInt64" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/f79a28423ed1ae02.json b/type-parser/mini-parser-ts/test/snapshots/f79a28423ed1ae02.json new file mode 100644 index 000000000..f2a6e6c89 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/f79a28423ed1ae02.json @@ -0,0 +1,7 @@ +{ + "type": "Point", + "data_type": { + "type": "DataType", + "name": "Point" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/f8a4e52fe170a6b8.json b/type-parser/mini-parser-ts/test/snapshots/f8a4e52fe170a6b8.json new file mode 100644 index 000000000..bdebde973 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/f8a4e52fe170a6b8.json @@ -0,0 +1,7 @@ +{ + "type": "IPv4", + "data_type": { + "type": "DataType", + "name": "IPv4" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/f9874bb3d8034d65.json b/type-parser/mini-parser-ts/test/snapshots/f9874bb3d8034d65.json new file mode 100644 index 000000000..fae099fdd --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/f9874bb3d8034d65.json @@ -0,0 +1,17 @@ +{ + "type": "Map(UUID, String)", + "data_type": { + "type": "DataType", + "name": "Map", + "arguments": [ + { + "type": "DataType", + "name": "UUID" + }, + { + "type": "DataType", + "name": "String" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/fb533649ca2f9e73.json b/type-parser/mini-parser-ts/test/snapshots/fb533649ca2f9e73.json new file mode 100644 index 000000000..0274dd3eb --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/fb533649ca2f9e73.json @@ -0,0 +1,7 @@ +{ + "type": "MEDIUMINT", + "data_type": { + "type": "DataType", + "name": "MEDIUMINT" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/fca4d8d6e1593c6b.json b/type-parser/mini-parser-ts/test/snapshots/fca4d8d6e1593c6b.json new file mode 100644 index 000000000..6b4a5b14f --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/fca4d8d6e1593c6b.json @@ -0,0 +1,7 @@ +{ + "type": "IntervalWeek", + "data_type": { + "type": "DataType", + "name": "IntervalWeek" + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/fcb1a5ad1920b1d8.json b/type-parser/mini-parser-ts/test/snapshots/fcb1a5ad1920b1d8.json new file mode 100644 index 000000000..8342e18f5 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/fcb1a5ad1920b1d8.json @@ -0,0 +1,13 @@ +{ + "type": "Nullable(Date32)", + "data_type": { + "type": "DataType", + "name": "Nullable", + "arguments": [ + { + "type": "DataType", + "name": "Date32" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/fcf6d8ffa4297b9e.json b/type-parser/mini-parser-ts/test/snapshots/fcf6d8ffa4297b9e.json new file mode 100644 index 000000000..11050eafb --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/fcf6d8ffa4297b9e.json @@ -0,0 +1,26 @@ +{ + "type": "Tuple(a UInt8, String, c Float64)", + "data_type": { + "type": "TupleDataType", + "name": "Tuple", + "arguments": [ + { + "type": "DataType", + "name": "UInt8" + }, + { + "type": "DataType", + "name": "String" + }, + { + "type": "DataType", + "name": "Float64" + } + ], + "element_names": [ + "a", + "", + "c" + ] + } +} diff --git a/type-parser/mini-parser-ts/test/snapshots/fedf5fb1af8c725d.json b/type-parser/mini-parser-ts/test/snapshots/fedf5fb1af8c725d.json new file mode 100644 index 000000000..d2b924f04 --- /dev/null +++ b/type-parser/mini-parser-ts/test/snapshots/fedf5fb1af8c725d.json @@ -0,0 +1,14 @@ +{ + "type": "DateTime64(3)", + "data_type": { + "type": "DataType", + "name": "DateTime64", + "arguments": [ + { + "type": "Literal", + "value_type": "UInt64", + "value": "3" + } + ] + } +} diff --git a/type-parser/mini-parser-ts/test/update_snapshots.ts b/type-parser/mini-parser-ts/test/update_snapshots.ts new file mode 100644 index 000000000..de3386e47 --- /dev/null +++ b/type-parser/mini-parser-ts/test/update_snapshots.ts @@ -0,0 +1,156 @@ +#!/usr/bin/env node +/// Regenerate the static oracle snapshots from a real ClickHouse server. +/// +/// For every candidate type (existing cases.txt entries + the candidates file) +/// this: +/// 1. asks the server for the `data_type` subtree, +/// 2. parses the same type with the standalone parser, +/// 3. compares them structurally. +/// Only types where the server ACCEPTS the type AND the parser MATCHES the +/// server are kept: new ones are appended to cases.txt, and a snapshot file is +/// written for every kept case. Types the server rejects, or where the parser +/// diverges, are dropped and listed in a report (never silently added). +/// +/// Usage: +/// tsx test/update_snapshots.ts --clickhouse /path/to/clickhouse \ +/// [--candidates test/candidates.txt] [--cases test/cases.txt] +/// +/// The clickhouse binary must be built from +/// https://github.com/peter-leonov-ch/ClickHouse/pull/1. + +import { existsSync, mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync, appendFileSync } from "node:fs"; +import { fileURLToPath } from "node:url"; +import { dirname, join } from "node:path"; + +import { canon, deepEqual, readCases } from "./cases.js"; +import { serverDataType, toolDataType } from "./oracle.js"; +import { SNAPSHOT_DIR, snapshotName, snapshotPath, type Snapshot } from "./snapshots.js"; + +const here = dirname(fileURLToPath(import.meta.url)); + +interface Args { + clickhouse: string; + cases: string; + candidates: string; +} + +function parseArgs(argv: string[]): Args { + let clickhouse = ""; + let cases = join(here, "cases.txt"); + let candidates = join(here, "candidates.txt"); + for (let i = 0; i < argv.length; i++) { + if (argv[i] === "--clickhouse") clickhouse = argv[++i] ?? ""; + else if (argv[i] === "--cases") cases = argv[++i] ?? cases; + else if (argv[i] === "--candidates") candidates = argv[++i] ?? candidates; + } + if (!clickhouse) { + console.error("error: --clickhouse is required"); + process.exit(2); + } + return { clickhouse, cases, candidates }; +} + +function main(): number { + const args = parseArgs(process.argv.slice(2)); + + /// Existing curated cases stay first and keep their order; new candidates are + /// appended. Dedup by exact (trimmed) string across both sources. + const existing = readCases(args.cases); + const existingSet = new Set(existing); + const candidates = existsSync(args.candidates) ? readCases(args.candidates) : []; + + const order: string[] = []; + const seen = new Set(); + for (const c of [...existing, ...candidates]) { + if (!seen.has(c)) { + seen.add(c); + order.push(c); + } + } + + mkdirSync(SNAPSHOT_DIR, { recursive: true }); + + const kept: string[] = []; + const rejected: { type: string; reason: string }[] = []; + const divergent: { type: string; expected: string; actual: string }[] = []; + + let i = 0; + for (const typeStr of order) { + i++; + if (i % 25 === 0) process.stderr.write(` ... ${i}/${order.length}\n`); + + let expected: unknown; + try { + expected = serverDataType(args.clickhouse, typeStr); + } catch (exc) { + rejected.push({ type: typeStr, reason: `server: ${(exc as Error).message}` }); + continue; + } + + let actual: unknown; + try { + actual = toolDataType(typeStr); + } catch (exc) { + divergent.push({ type: typeStr, expected: JSON.stringify(canon(expected)), actual: `(${(exc as Error).message})` }); + continue; + } + + if (!deepEqual(expected, actual)) { + divergent.push({ type: typeStr, expected: JSON.stringify(canon(expected)), actual: JSON.stringify(canon(actual)) }); + continue; + } + + /// Kept: write the snapshot holding the server's data_type subtree. + const snap: Snapshot = { type: typeStr, data_type: expected }; + writeFileSync(snapshotPath(typeStr), JSON.stringify(snap, null, 2) + "\n"); + kept.push(typeStr); + } + + /// Append newly-kept cases (not already present) to cases.txt. + const newKept = kept.filter((c) => !existingSet.has(c)); + if (newKept.length > 0) { + const block = + "\n# === generated cases (validated against the server oracle; see update_snapshots.ts) ===\n" + + newKept.join("\n") + + "\n"; + appendFileSync(args.cases, block); + } + + /// Prune snapshot files that no longer correspond to a kept case. + const keepFiles = new Set(kept.map(snapshotName)); + let pruned = 0; + for (const f of readdirSync(SNAPSHOT_DIR)) { + if (f.endsWith(".json") && !keepFiles.has(f)) { + rmSync(join(SNAPSHOT_DIR, f)); + pruned++; + } + } + + /// Write a human-readable report of what was dropped. + const reportLines: string[] = []; + reportLines.push(`# snapshot update report`); + reportLines.push(`candidates considered: ${order.length}`); + reportLines.push(`kept (snapshotted): ${kept.length} (new in cases.txt: ${newKept.length})`); + reportLines.push(`rejected by server: ${rejected.length}`); + reportLines.push(`divergent (server!=parser): ${divergent.length}`); + reportLines.push(`pruned stale snapshots: ${pruned}`); + if (rejected.length) { + reportLines.push(`\n## rejected by server (invalid type / not accepted)`); + for (const r of rejected) reportLines.push(`- ${r.type}\n ${r.reason}`); + } + if (divergent.length) { + reportLines.push(`\n## divergent (server accepted but parser output differs)`); + for (const d of divergent) { + reportLines.push(`- ${d.type}`); + reportLines.push(` expected: ${d.expected}`); + reportLines.push(` actual: ${d.actual}`); + } + } + writeFileSync(join(here, "snapshots_report.txt"), reportLines.join("\n") + "\n"); + + console.log(reportLines.slice(0, 6).join("\n")); + console.log(`\nreport: test/snapshots_report.txt`); + return 0; +} + +process.exit(main()); diff --git a/type-parser/mini-parser-ts/test/validate_types_live.ts b/type-parser/mini-parser-ts/test/validate_types_live.ts new file mode 100644 index 000000000..2aaa24e12 --- /dev/null +++ b/type-parser/mini-parser-ts/test/validate_types_live.ts @@ -0,0 +1,118 @@ +#!/usr/bin/env node +/// Sanity-check that every type in cases.txt is a REAL ClickHouse type — i.e. +/// that we did not invent any — against a stock running server (no AST-JSON +/// support needed). Unlike `EXPLAIN SYNTAX`/`EXPLAIN AST`, which only check +/// syntax (they happily accept `Bogus(UInt8)`), this instantiates the type via +/// +/// CREATE TEMPORARY TABLE _probe (c ) +/// +/// which forces the type factory to build the column and rejects unknown type +/// families with UNKNOWN_TYPE. Temporary tables are session-scoped (one per +/// HTTP request here), so nothing is persisted. +/// +/// Experimental/suspicious types (Variant, Dynamic, JSON/Object, big +/// FixedString, suspicious LowCardinality, Time) are real but gated behind +/// settings, so we enable those settings — a failure then means the type +/// genuinely does not exist. +/// +/// Usage: tsx test/validate_types_live.ts [--url http://localhost:8124/] + +import { fileURLToPath } from "node:url"; +import { dirname, join } from "node:path"; + +import { readCases } from "./cases.js"; + +const SETTINGS: Record = { + allow_experimental_object_type: "1", + allow_experimental_variant_type: "1", + allow_experimental_dynamic_type: "1", + allow_experimental_json_type: "1", + enable_json_type: "1", + allow_experimental_geo_types: "1", + allow_suspicious_low_cardinality_types: "1", + allow_suspicious_variant_types: "1", + allow_suspicious_fixed_string_types: "1", + enable_time_time64_type: "1", +}; + +const CONCURRENCY = 16; + +interface Failure { + type: string; + code: number | null; + message: string; + invented: boolean; +} + +/// A failure proves we "invented" a type only when the family is unknown or the +/// type string does not even parse. Everything else (a real type rejected for +/// some other reason) is not an invention. +function isInvented(code: number | null, message: string): boolean { + if (code === 50 /* UNKNOWN_TYPE */ || code === 62 /* SYNTAX_ERROR */) return true; + return /Unknown data type family|UNKNOWN_TYPE|SYNTAX_ERROR/i.test(message); +} + +async function probe(url: string, typeStr: string, i: number): Promise { + const sql = `CREATE TEMPORARY TABLE _chdt_probe_${i} (c ${typeStr})`; + const resp = await fetch(url, { method: "POST", body: sql }); + if (resp.ok) { + await resp.text(); + return null; + } + const body = (await resp.text()).trim(); + const m = body.match(/^Code:\s*(\d+)\./); + const code = m ? Number(m[1]) : null; + return { type: typeStr, code, message: body, invented: isInvented(code, body) }; +} + +async function main(): Promise { + const argv = process.argv.slice(2); + let base = "http://localhost:8124/"; + for (let i = 0; i < argv.length; i++) { + if (argv[i] === "--url") base = argv[++i] ?? base; + } + const url = base + "?" + new URLSearchParams(SETTINGS).toString(); + + const here = dirname(fileURLToPath(import.meta.url)); + const cases = readCases(join(here, "cases.txt")); + + /// Confirm reachability up front. + try { + const v = await fetch(base, { method: "POST", body: "SELECT version()" }); + console.log(`server: ${(await v.text()).trim()}`); + } catch (exc) { + console.error(`error: cannot reach ${base}: ${(exc as Error).message}`); + return 2; + } + + const failures: Failure[] = []; + let done = 0; + for (let start = 0; start < cases.length; start += CONCURRENCY) { + const batch = cases.slice(start, start + CONCURRENCY); + const results = await Promise.all(batch.map((t, k) => probe(url, t, start + k))); + for (const f of results) if (f) failures.push(f); + done += batch.length; + process.stderr.write(` ... ${done}/${cases.length}\n`); + } + + const invented = failures.filter((f) => f.invented); + const other = failures.filter((f) => !f.invented); + + console.log(`\nchecked ${cases.length} types`); + console.log(`instantiated OK: ${cases.length - failures.length}`); + console.log(`invented (UNKNOWN_TYPE / parse error): ${invented.length}`); + console.log(`other failures (real type, other constraint): ${other.length}`); + + if (other.length) { + console.log(`\n## other failures (NOT inventions — real types blocked by some constraint)`); + for (const f of other) console.log(`- ${f.type}\n Code ${f.code}: ${f.message.split("\n")[0]}`); + } + if (invented.length) { + console.log(`\n## INVENTED TYPES (do not exist on the server)`); + for (const f of invented) console.log(`- ${f.type}\n Code ${f.code}: ${f.message.split("\n")[0]}`); + } + + return invented.length ? 1 : 0; +} + +process.exit(await main()); From dbb6560610b9ebe0bb60286d0f039d3a76596024 Mon Sep 17 00:00:00 2001 From: Peter Leonov Date: Wed, 24 Jun 2026 19:23:45 +0200 Subject: [PATCH 6/9] test(mini-parser-ts): verify corpus types instantiate on a stock server MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit EXPLAIN SYNTAX/AST only checks parse syntax (it accepts Bogus(UInt8)), so it can't prove the corpus uses real types. Add validate_types_live.ts (npm run validate:live), which instantiates each cases.txt type via a session-scoped CREATE TEMPORARY TABLE over the HTTP interface — with the relevant experimental settings enabled — so an unknown family fails with UNKNOWN_TYPE. Against a stock v26.1 server: 347/356 instantiate, 0 unexpected. The 9 that don't are parser-valid but factory-invalid (partial tuple naming, Nullable in Variant, Nullable(Tuple), Dynamic max_types=255, BINARY alias without size, legacy Object('json')); they are allowlisted in non_instantiable.txt with reasons. This library mirrors ParserDataType, not the type factory, so these stay as intentional parser test inputs. The check exits non-zero only on an unexpected failure or a stale allowlist entry. Co-Authored-By: Claude Opus 4.8 (1M context) --- type-parser/mini-parser-ts/README.md | 26 +++++++++++ type-parser/mini-parser-ts/package.json | 3 +- .../mini-parser-ts/test/non_instantiable.txt | 29 ++++++++++++ .../test/validate_types_live.ts | 44 ++++++++++--------- 4 files changed, 80 insertions(+), 22 deletions(-) create mode 100644 type-parser/mini-parser-ts/test/non_instantiable.txt diff --git a/type-parser/mini-parser-ts/README.md b/type-parser/mini-parser-ts/README.md index 1f2518181..7b7a877ab 100644 --- a/type-parser/mini-parser-ts/README.md +++ b/type-parser/mini-parser-ts/README.md @@ -138,3 +138,29 @@ directly, useful while iterating: npm run test:oracle -- --clickhouse /path/to/clickhouse ``` +### Confirming the corpus is real (no invented types) + +The oracle compares against the server's **parser** (`ParserDataType`), which is +what this library mirrors. To additionally confirm that every type in the corpus +is a *real* ClickHouse type — not just syntactically well-formed — there is a +check that **instantiates** each type against any stock running server (no +AST-JSON support needed; over the HTTP interface): + +```bash +npm run validate:live -- --url http://localhost:8124/ +``` + +It runs `CREATE TEMPORARY TABLE _probe (c )` (session-scoped, nothing +persisted) with the relevant experimental settings enabled, so an unknown type +family fails with `UNKNOWN_TYPE`. As of the latest run, **347/356 instantiate +and 0 are unexpected**. + +The remaining 9 are listed in `test/non_instantiable.txt`: types the parser +accepts (and whose AST matches the server's parser) but that the server's **type +factory** later rejects — e.g. partial tuple naming (`Tuple(a UInt8, String)`), +`Nullable` inside `Variant`, `Nullable(Tuple(...))`, `Dynamic(max_types = 255)`, +the `BINARY` alias without a size, and the legacy `Object('json')` (removed in +recent servers). These are deliberate parser test inputs — this is a type-string +*parser*, not a type validator — so they are allowlisted, and `validate:live` +exits non-zero only on an *unexpected* failure. + diff --git a/type-parser/mini-parser-ts/package.json b/type-parser/mini-parser-ts/package.json index b34d979ed..5e802dbc8 100644 --- a/type-parser/mini-parser-ts/package.json +++ b/type-parser/mini-parser-ts/package.json @@ -15,7 +15,8 @@ "test": "node --import tsx --test test/*.test.ts", "test:oracle": "tsx test/oracle_compare.ts", "test:unsupported": "tsx test/check_unsupported.ts", - "snapshot:update": "tsx test/update_snapshots.ts" + "snapshot:update": "tsx test/update_snapshots.ts", + "validate:live": "tsx test/validate_types_live.ts" }, "devDependencies": { "tsx": "^4.22.4", diff --git a/type-parser/mini-parser-ts/test/non_instantiable.txt b/type-parser/mini-parser-ts/test/non_instantiable.txt new file mode 100644 index 000000000..277ce2ad5 --- /dev/null +++ b/type-parser/mini-parser-ts/test/non_instantiable.txt @@ -0,0 +1,29 @@ +# Cases that the server's PARSER accepts (and whose AST this library matches — +# see test/snapshots/) but that the server's TYPE FACTORY refuses to +# instantiate. This library mirrors ParserDataType, not the type factory, so +# these are valid, intentional parser test inputs. validate_types_live.ts +# treats a failed instantiation as OK only if the type is listed here. +# +# Each line notes why instantiation fails on a stock server. + +# legacy experimental object type — removed in newer servers (UNKNOWN_TYPE on v26+) +Object('json') + +# partial tuple naming: the parser accepts mixed named/unnamed elements, but the +# factory requires names for all elements or none. +Tuple(a UInt8, String) +Tuple(a UInt8, String, c Float64) +Tuple(UInt8, b String, Float64) +Tuple(id UInt64, String, flag Bool) + +# Nullable is not allowed inside Variant +Variant(Nullable(UInt64), String) + +# Nullable cannot wrap Tuple +Array(Nullable(Tuple(UInt8, String))) + +# Dynamic max_types must be in 0..254 +Dynamic(max_types = 255) + +# BINARY is an alias for FixedString, which needs a size argument +BINARY diff --git a/type-parser/mini-parser-ts/test/validate_types_live.ts b/type-parser/mini-parser-ts/test/validate_types_live.ts index 2aaa24e12..a462cb1e9 100644 --- a/type-parser/mini-parser-ts/test/validate_types_live.ts +++ b/type-parser/mini-parser-ts/test/validate_types_live.ts @@ -41,15 +41,6 @@ interface Failure { type: string; code: number | null; message: string; - invented: boolean; -} - -/// A failure proves we "invented" a type only when the family is unknown or the -/// type string does not even parse. Everything else (a real type rejected for -/// some other reason) is not an invention. -function isInvented(code: number | null, message: string): boolean { - if (code === 50 /* UNKNOWN_TYPE */ || code === 62 /* SYNTAX_ERROR */) return true; - return /Unknown data type family|UNKNOWN_TYPE|SYNTAX_ERROR/i.test(message); } async function probe(url: string, typeStr: string, i: number): Promise { @@ -62,7 +53,7 @@ async function probe(url: string, typeStr: string, i: number): Promise { @@ -75,6 +66,9 @@ async function main(): Promise { const here = dirname(fileURLToPath(import.meta.url)); const cases = readCases(join(here, "cases.txt")); + /// Types the parser handles (and whose AST matches the server) but that the + /// type factory refuses to instantiate — documented & expected, not bugs. + const expectedNonInstantiable = new Set(readCases(join(here, "non_instantiable.txt"))); /// Confirm reachability up front. try { @@ -95,24 +89,32 @@ async function main(): Promise { process.stderr.write(` ... ${done}/${cases.length}\n`); } - const invented = failures.filter((f) => f.invented); - const other = failures.filter((f) => !f.invented); + const expected = failures.filter((f) => expectedNonInstantiable.has(f.type)); + const unexpected = failures.filter((f) => !expectedNonInstantiable.has(f.type)); console.log(`\nchecked ${cases.length} types`); console.log(`instantiated OK: ${cases.length - failures.length}`); - console.log(`invented (UNKNOWN_TYPE / parse error): ${invented.length}`); - console.log(`other failures (real type, other constraint): ${other.length}`); + console.log(`expected non-instantiable (allowlisted, see non_instantiable.txt): ${expected.length}`); + console.log(`UNEXPECTED failures: ${unexpected.length}`); - if (other.length) { - console.log(`\n## other failures (NOT inventions — real types blocked by some constraint)`); - for (const f of other) console.log(`- ${f.type}\n Code ${f.code}: ${f.message.split("\n")[0]}`); + if (expected.length) { + console.log(`\n## expected non-instantiable (parser-valid by design — NOT inventions)`); + for (const f of expected) console.log(`- ${f.type}\n Code ${f.code}: ${f.message.split("\n")[0]}`); } - if (invented.length) { - console.log(`\n## INVENTED TYPES (do not exist on the server)`); - for (const f of invented) console.log(`- ${f.type}\n Code ${f.code}: ${f.message.split("\n")[0]}`); + if (unexpected.length) { + console.log(`\n## UNEXPECTED — server does not accept these (review!)`); + for (const f of unexpected) console.log(`- ${f.type}\n Code ${f.code}: ${f.message.split("\n")[0]}`); + } + + /// Also flag anything allowlisted that now DOES instantiate (stale entry). + const okSet = new Set(cases.filter((t) => !failures.some((f) => f.type === t))); + const stale = [...expectedNonInstantiable].filter((t) => okSet.has(t)); + if (stale.length) { + console.log(`\n## stale allowlist entries (now instantiate — remove from non_instantiable.txt)`); + for (const t of stale) console.log(`- ${t}`); } - return invented.length ? 1 : 0; + return unexpected.length ? 1 : 0; } process.exit(await main()); From 91f9a583d7f13b97a168d9d5d2813a0c3d278f43 Mon Sep 17 00:00:00 2001 From: Peter Leonov Date: Wed, 24 Jun 2026 19:46:02 +0200 Subject: [PATCH 7/9] build(mini-parser-ts): make the package publishable as @clickhouse/datatype-parser The package could not be published as-is: main/types pointed at dist/index.js (the real entry is dist/src/index.js), there was no files whitelist (npm would have shipped src/, the whole test harness, and 356 snapshot JSONs), and the test files were compiled into dist/. - Fix main/types and add an exports map (dist/src/index.*). - Add a files whitelist (dist, README.md, LICENSE). - Add tsconfig.build.json (src + tool only); `build` uses it so dist ships just the library and CLI. `typecheck` still covers tests. - Add publish metadata: scoped name, Apache-2.0 license, repository with directory, engines (node >=18), keywords, sideEffects:false, and publishConfig.access=public for the scoped package. - prepack runs the build so the tarball is always fresh. - Bundle LICENSE, point the README import at the scoped name, ignore *.tgz. Verified: npm pack ships 15 files (16.7 kB); installing the tarball into a fresh project resolves both `import { parseDataType, toJSON }` and the `chdt-parse` bin. Co-Authored-By: Claude Opus 4.8 (1M context) --- type-parser/mini-parser-ts/.gitignore | 1 + type-parser/mini-parser-ts/LICENSE | 203 ++++++++++++++++++ type-parser/mini-parser-ts/README.md | 2 +- type-parser/mini-parser-ts/package.json | 40 +++- .../mini-parser-ts/tsconfig.build.json | 5 + 5 files changed, 246 insertions(+), 5 deletions(-) create mode 100644 type-parser/mini-parser-ts/LICENSE create mode 100644 type-parser/mini-parser-ts/tsconfig.build.json diff --git a/type-parser/mini-parser-ts/.gitignore b/type-parser/mini-parser-ts/.gitignore index 756d26c74..cf7333f50 100644 --- a/type-parser/mini-parser-ts/.gitignore +++ b/type-parser/mini-parser-ts/.gitignore @@ -1,3 +1,4 @@ node_modules/ dist/ test/snapshots_report.txt +*.tgz diff --git a/type-parser/mini-parser-ts/LICENSE b/type-parser/mini-parser-ts/LICENSE new file mode 100644 index 000000000..c653e59a8 --- /dev/null +++ b/type-parser/mini-parser-ts/LICENSE @@ -0,0 +1,203 @@ +Copyright 2016-2024 ClickHouse, Inc. + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2016-2024 ClickHouse, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/type-parser/mini-parser-ts/README.md b/type-parser/mini-parser-ts/README.md index 7b7a877ab..d2da01169 100644 --- a/type-parser/mini-parser-ts/README.md +++ b/type-parser/mini-parser-ts/README.md @@ -44,7 +44,7 @@ npm run typecheck # tsc --noEmit Library: ```ts -import { parseDataType, toJSON } from "chdt-datatype-parser"; +import { parseDataType, toJSON } from "@clickhouse/datatype-parser"; const r = parseDataType("Tuple(a UInt8, b String)"); if (r.ok()) { diff --git a/type-parser/mini-parser-ts/package.json b/type-parser/mini-parser-ts/package.json index 5e802dbc8..a5186597a 100644 --- a/type-parser/mini-parser-ts/package.json +++ b/type-parser/mini-parser-ts/package.json @@ -1,16 +1,48 @@ { - "name": "chdt-datatype-parser", + "name": "@clickhouse/datatype-parser", "version": "0.1.0", "description": "Standalone ClickHouse data-type string parser — a TypeScript port of the chdt C++ library.", + "license": "Apache-2.0", "type": "module", - "main": "dist/index.js", - "types": "dist/index.d.ts", + "main": "dist/src/index.js", + "types": "dist/src/index.d.ts", + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + }, "bin": { "chdt-parse": "dist/tool/main.js" }, + "files": [ + "dist", + "README.md", + "LICENSE" + ], + "sideEffects": false, + "engines": { + "node": ">=18.0.0" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/ClickHouse/clickhouse-js.git", + "directory": "type-parser/mini-parser-ts" + }, + "keywords": [ + "clickhouse", + "data-type", + "parser", + "ast", + "rowbinary" + ], + "publishConfig": { + "access": "public" + }, "scripts": { - "build": "tsc -p tsconfig.json", + "build": "tsc -p tsconfig.build.json", "typecheck": "tsc -p tsconfig.json --noEmit", + "prepack": "npm run build", "parse": "tsx tool/main.ts", "test": "node --import tsx --test test/*.test.ts", "test:oracle": "tsx test/oracle_compare.ts", diff --git a/type-parser/mini-parser-ts/tsconfig.build.json b/type-parser/mini-parser-ts/tsconfig.build.json new file mode 100644 index 000000000..f41ec42b7 --- /dev/null +++ b/type-parser/mini-parser-ts/tsconfig.build.json @@ -0,0 +1,5 @@ +{ + "extends": "./tsconfig.json", + "comment": "Build config for publishing: emits only the library (src) + CLI (tool), never the test harness.", + "include": ["src/**/*.ts", "tool/**/*.ts"] +} From 7aafbc041704292d12f934d63d6788fee7a0a86c Mon Sep 17 00:00:00 2001 From: Peter Leonov Date: Wed, 24 Jun 2026 19:47:37 +0200 Subject: [PATCH 8/9] style(mini-parser-ts): format with prettier MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Apply the repo's prettier config across the package sources, tests, and docs. No behavior change — typecheck clean, 369/369 tests pass. Co-Authored-By: Claude Opus 4.8 (1M context) --- type-parser/mini-parser-ts/README.md | 27 +- type-parser/mini-parser-ts/src/json.ts | 7 +- type-parser/mini-parser-ts/src/lexer.ts | 277 +++++---- type-parser/mini-parser-ts/src/parser.ts | 544 +++++++++--------- .../mini-parser-ts/test/check_unsupported.ts | 4 +- type-parser/mini-parser-ts/test/oracle.ts | 12 +- .../mini-parser-ts/test/oracle_compare.ts | 4 +- .../mini-parser-ts/test/parser.test.ts | 16 +- type-parser/mini-parser-ts/test/snapshots.ts | 5 +- .../mini-parser-ts/test/update_snapshots.ts | 51 +- .../test/validate_types_live.ts | 44 +- 11 files changed, 578 insertions(+), 413 deletions(-) diff --git a/type-parser/mini-parser-ts/README.md b/type-parser/mini-parser-ts/README.md index d2da01169..1252772cc 100644 --- a/type-parser/mini-parser-ts/README.md +++ b/type-parser/mini-parser-ts/README.md @@ -17,14 +17,14 @@ parser's output across the full test corpus. The module structure tracks the C++ sources one-to-one: -| TypeScript | ported from (C++) | role | -| ------------------- | -------------------------------- | --------------------------------------- | -| `src/ast.ts` | `include/chdt/ast.h` | the AST node shape + `makeNode` factory | -| `src/lexer.ts` | `src/lexer.{h,cpp}` | the purpose-built tokenizer | -| `src/parser.ts` | `src/parser.cpp` + `parser.h` | the `ParserDataType::parseImpl` port | -| `src/json.ts` | `src/json.cpp` | the byte-faithful JSON serializer | -| `src/index.ts` | — | public barrel | -| `tool/main.ts` | `tool/main.cpp` | the `chdt-parse` CLI | +| TypeScript | ported from (C++) | role | +| --------------- | ----------------------------- | --------------------------------------- | +| `src/ast.ts` | `include/chdt/ast.h` | the AST node shape + `makeNode` factory | +| `src/lexer.ts` | `src/lexer.{h,cpp}` | the purpose-built tokenizer | +| `src/parser.ts` | `src/parser.cpp` + `parser.h` | the `ParserDataType::parseImpl` port | +| `src/json.ts` | `src/json.cpp` | the byte-faithful JSON serializer | +| `src/index.ts` | — | public barrel | +| `tool/main.ts` | `tool/main.cpp` | the `chdt-parse` CLI | The lexer and parser deliberately preserve the original control flow, branch ordering, helper names, and `pos` save/restore points. A few signatures changed @@ -48,8 +48,8 @@ import { parseDataType, toJSON } from "@clickhouse/datatype-parser"; const r = parseDataType("Tuple(a UInt8, b String)"); if (r.ok()) { - console.log(toJSON(r.ast!)); // pretty (2-space) JSON - console.log(toJSON(r.ast!, -1)); // compact JSON + console.log(toJSON(r.ast!)); // pretty (2-space) JSON + console.log(toJSON(r.ast!, -1)); // compact JSON } else { console.error(r.error!.message, r.error!.position); } @@ -142,7 +142,7 @@ npm run test:oracle -- --clickhouse /path/to/clickhouse The oracle compares against the server's **parser** (`ParserDataType`), which is what this library mirrors. To additionally confirm that every type in the corpus -is a *real* ClickHouse type — not just syntactically well-formed — there is a +is a _real_ ClickHouse type — not just syntactically well-formed — there is a check that **instantiates** each type against any stock running server (no AST-JSON support needed; over the HTTP interface): @@ -161,6 +161,5 @@ factory** later rejects — e.g. partial tuple naming (`Tuple(a UInt8, String)`) `Nullable` inside `Variant`, `Nullable(Tuple(...))`, `Dynamic(max_types = 255)`, the `BINARY` alias without a size, and the legacy `Object('json')` (removed in recent servers). These are deliberate parser test inputs — this is a type-string -*parser*, not a type validator — so they are allowlisted, and `validate:live` -exits non-zero only on an *unexpected* failure. - +_parser_, not a type validator — so they are allowlisted, and `validate:live` +exits non-zero only on an _unexpected_ failure. diff --git a/type-parser/mini-parser-ts/src/json.ts b/type-parser/mini-parser-ts/src/json.ts index 4b07402bc..e84e59e05 100644 --- a/type-parser/mini-parser-ts/src/json.ts +++ b/type-parser/mini-parser-ts/src/json.ts @@ -91,7 +91,12 @@ class Writer { /// Emit `"key": ` prefix; flips `flag.first` to false (mirrors the C++ /// `bool & first`). -function writeKey(w: Writer, key: string, flag: FirstFlag, depth: number): void { +function writeKey( + w: Writer, + key: string, + flag: FirstFlag, + depth: number, +): void { if (!flag.first) w.out.push(0x2c /* ',' */); flag.first = false; w.newlineIndent(depth + 1); diff --git a/type-parser/mini-parser-ts/src/lexer.ts b/type-parser/mini-parser-ts/src/lexer.ts index 00884e76b..60fd50118 100644 --- a/type-parser/mini-parser-ts/src/lexer.ts +++ b/type-parser/mini-parser-ts/src/lexer.ts @@ -24,40 +24,49 @@ export enum TokenType { } export interface Token { - type: TokenType + type: TokenType; /// Word/Number: raw source text. QuotedIdent/String: decoded content. /// Error: the error message. - text: string + text: string; /// Number only: true when the literal has a fractional part or exponent. - is_float: boolean + is_float: boolean; /// Byte offset of the token start in the input (for diagnostics). - begin: number + begin: number; } function isSpace(c: string): boolean { - return c === " " || c === "\t" || c === "\n" || c === "\r" || c === "\f" || c === "\v" + return ( + c === " " || + c === "\t" || + c === "\n" || + c === "\r" || + c === "\f" || + c === "\v" + ); } function isDigit(c: string): boolean { - return c >= "0" && c <= "9" + return c >= "0" && c <= "9"; } function isWordFirst(c: string): boolean { - return (c >= "a" && c <= "z") || (c >= "A" && c <= "Z") || c === "_" || c === "$" + return ( + (c >= "a" && c <= "z") || (c >= "A" && c <= "Z") || c === "_" || c === "$" + ); } function isWordChar(c: string): boolean { - return isWordFirst(c) || isDigit(c) + return isWordFirst(c) || isDigit(c); } interface DecodeResult { - ok: boolean + ok: boolean; /// Decoded content (valid when ok is true). - out: string + out: string; /// Error message (valid when ok is false). - error: string + error: string; /// Position after the token (in/out replacement for `size_t & pos`). - pos: number + pos: number; } /// Decode the body of a quoted token (string literal or quoted identifier). @@ -65,176 +74,236 @@ interface DecodeResult { /// escapes and the SQL doubled-quote escape (e.g. '' inside '...'). Mirrors /// the relevant behaviour of `tryReadQuotedStringWithSQLStyle`. function decodeQuoted(input: string, pos: number, quote: string): DecodeResult { - const n = input.length - let out = "" + const n = input.length; + let out = ""; /// pos points at the opening quote. - ++pos + ++pos; while (pos < n) { - const c = input[pos] as string + const c = input[pos] as string; if (c === quote) { /// Doubled quote -> literal quote. if (pos + 1 < n && input[pos + 1] === quote) { - out += quote - pos += 2 - continue + out += quote; + pos += 2; + continue; } - ++pos /// consume the closing quote - return { ok: true, out, error: "", pos } + ++pos; /// consume the closing quote + return { ok: true, out, error: "", pos }; } if (c === "\\") { if (pos + 1 >= n) { - return { ok: false, out, error: "unterminated escape in quoted literal", pos } + return { + ok: false, + out, + error: "unterminated escape in quoted literal", + pos, + }; } - const e = input[pos + 1] as string + const e = input[pos + 1] as string; switch (e) { case "b": - out += "\b" - break + out += "\b"; + break; case "f": - out += "\f" - break + out += "\f"; + break; case "n": - out += "\n" - break + out += "\n"; + break; case "r": - out += "\r" - break + out += "\r"; + break; case "t": - out += "\t" - break + out += "\t"; + break; case "0": - out += "\0" - break + out += "\0"; + break; case "a": - out += "\x07" - break + out += "\x07"; + break; case "v": - out += "\v" - break + out += "\v"; + break; /// \\, \', \", \`, and any other char: keep the literal char. default: - out += e - break + out += e; + break; } - pos += 2 - continue + pos += 2; + continue; } - out += c - ++pos + out += c; + ++pos; } - return { ok: false, out, error: "unterminated quoted literal", pos } + return { ok: false, out, error: "unterminated quoted literal", pos }; } /// Tokenize the whole input. The returned array always ends with an `End` /// token. A malformed token yields a single trailing `Error` token. export function tokenize(input: string): Token[] { - const tokens: Token[] = [] - let pos = 0 - const n = input.length + const tokens: Token[] = []; + let pos = 0; + const n = input.length; const fail = (at: number, msg: string): void => { - tokens.push({ type: TokenType.Error, text: msg, is_float: false, begin: at }) - } + tokens.push({ + type: TokenType.Error, + text: msg, + is_float: false, + begin: at, + }); + }; while (pos < n) { - const c = input[pos] as string + const c = input[pos] as string; if (isSpace(c)) { - ++pos - continue + ++pos; + continue; } - const start = pos + const start = pos; switch (c) { case "(": - tokens.push({ type: TokenType.OpeningParen, text: "(", is_float: false, begin: start }) - ++pos - continue + tokens.push({ + type: TokenType.OpeningParen, + text: "(", + is_float: false, + begin: start, + }); + ++pos; + continue; case ")": - tokens.push({ type: TokenType.ClosingParen, text: ")", is_float: false, begin: start }) - ++pos - continue + tokens.push({ + type: TokenType.ClosingParen, + text: ")", + is_float: false, + begin: start, + }); + ++pos; + continue; case ",": - tokens.push({ type: TokenType.Comma, text: ",", is_float: false, begin: start }) - ++pos - continue + tokens.push({ + type: TokenType.Comma, + text: ",", + is_float: false, + begin: start, + }); + ++pos; + continue; case "=": - tokens.push({ type: TokenType.Equals, text: "=", is_float: false, begin: start }) - ++pos - continue + tokens.push({ + type: TokenType.Equals, + text: "=", + is_float: false, + begin: start, + }); + ++pos; + continue; case "-": - tokens.push({ type: TokenType.Minus, text: "-", is_float: false, begin: start }) - ++pos - continue + tokens.push({ + type: TokenType.Minus, + text: "-", + is_float: false, + begin: start, + }); + ++pos; + continue; default: - break + break; } /// A dot may start a fractional number (.5) or be a standalone separator. if (c === "." && !(pos + 1 < n && isDigit(input[pos + 1] as string))) { - tokens.push({ type: TokenType.Dot, text: ".", is_float: false, begin: start }) - ++pos - continue + tokens.push({ + type: TokenType.Dot, + text: ".", + is_float: false, + begin: start, + }); + ++pos; + continue; } /// Quoted identifiers. if (c === "`" || c === '"') { - const r = decodeQuoted(input, pos, c) - pos = r.pos + const r = decodeQuoted(input, pos, c); + pos = r.pos; if (!r.ok) { - fail(start, r.error) - break + fail(start, r.error); + break; } - tokens.push({ type: TokenType.QuotedIdent, text: r.out, is_float: false, begin: start }) - continue + tokens.push({ + type: TokenType.QuotedIdent, + text: r.out, + is_float: false, + begin: start, + }); + continue; } /// String literal. if (c === "'") { - const r = decodeQuoted(input, pos, c) - pos = r.pos + const r = decodeQuoted(input, pos, c); + pos = r.pos; if (!r.ok) { - fail(start, r.error) - break + fail(start, r.error); + break; } - tokens.push({ type: TokenType.String, text: r.out, is_float: false, begin: start }) - continue + tokens.push({ + type: TokenType.String, + text: r.out, + is_float: false, + begin: start, + }); + continue; } /// Number. if (isDigit(c) || c === ".") { - let is_float = false + let is_float = false; /// integer part - while (pos < n && isDigit(input[pos] as string)) ++pos + while (pos < n && isDigit(input[pos] as string)) ++pos; /// fraction if (pos < n && input[pos] === ".") { - is_float = true - ++pos - while (pos < n && isDigit(input[pos] as string)) ++pos + is_float = true; + ++pos; + while (pos < n && isDigit(input[pos] as string)) ++pos; } /// exponent if (pos < n && (input[pos] === "e" || input[pos] === "E")) { - is_float = true - ++pos - if (pos < n && (input[pos] === "+" || input[pos] === "-")) ++pos - while (pos < n && isDigit(input[pos] as string)) ++pos + is_float = true; + ++pos; + if (pos < n && (input[pos] === "+" || input[pos] === "-")) ++pos; + while (pos < n && isDigit(input[pos] as string)) ++pos; } - tokens.push({ type: TokenType.Number, text: input.substring(start, pos), is_float, begin: start }) - continue + tokens.push({ + type: TokenType.Number, + text: input.substring(start, pos), + is_float, + begin: start, + }); + continue; } /// Bare word / identifier / keyword. if (isWordFirst(c)) { - while (pos < n && isWordChar(input[pos] as string)) ++pos - tokens.push({ type: TokenType.Word, text: input.substring(start, pos), is_float: false, begin: start }) - continue + while (pos < n && isWordChar(input[pos] as string)) ++pos; + tokens.push({ + type: TokenType.Word, + text: input.substring(start, pos), + is_float: false, + begin: start, + }); + continue; } - fail(start, "unexpected character '" + c + "'") - break + fail(start, "unexpected character '" + c + "'"); + break; } - tokens.push({ type: TokenType.End, text: "", is_float: false, begin: pos }) - return tokens + tokens.push({ type: TokenType.End, text: "", is_float: false, begin: pos }); + return tokens; } diff --git a/type-parser/mini-parser-ts/src/parser.ts b/type-parser/mini-parser-ts/src/parser.ts index adcd9570a..065d19039 100644 --- a/type-parser/mini-parser-ts/src/parser.ts +++ b/type-parser/mini-parser-ts/src/parser.ts @@ -7,473 +7,487 @@ /// /// This is the TypeScript port of the C++ `chdt/parser.cpp`. -import { EnumValue, makeNode, Node, NodeKind } from "./ast.js" -import { Token, tokenize, TokenType } from "./lexer.js" +import { EnumValue, makeNode, Node, NodeKind } from "./ast.js"; +import { Token, tokenize, TokenType } from "./lexer.js"; /// Public entry point types (ported from parser.h). export interface ParseError { - message: string /// human-readable description - position: number /// byte offset into the input where parsing stuck + message: string; /// human-readable description + position: number; /// byte offset into the input where parsing stuck } export interface ParseResult { - ast: Node | null /// non-null on success - error: ParseError | null /// set on failure - ok(): boolean + ast: Node | null; /// non-null on success + error: ParseError | null; /// set on failure + ok(): boolean; } function toUpper(s: string): string { - let r = "" + let r = ""; for (let i = 0; i < s.length; ++i) { - const c = s[i] as string + const c = s[i] as string; if (c >= "a" && c <= "z") - r += String.fromCharCode(c.charCodeAt(0) - "a".charCodeAt(0) + "A".charCodeAt(0)) - else - r += c + r += String.fromCharCode( + c.charCodeAt(0) - "a".charCodeAt(0) + "A".charCodeAt(0), + ); + else r += c; } - return r + return r; } function toLower(s: string): string { - let r = "" + let r = ""; for (let i = 0; i < s.length; ++i) { - const c = s[i] as string + const c = s[i] as string; if (c >= "A" && c <= "Z") - r += String.fromCharCode(c.charCodeAt(0) - "A".charCodeAt(0) + "a".charCodeAt(0)) - else - r += c + r += String.fromCharCode( + c.charCodeAt(0) - "A".charCodeAt(0) + "a".charCodeAt(0), + ); + else r += c; } - return r + return r; } function isWordCharOrDollar(c: string): boolean { - return (c >= "a" && c <= "z") || (c >= "A" && c <= "Z") || (c >= "0" && c <= "9") || c === "_" || c === "$" + return ( + (c >= "a" && c <= "z") || + (c >= "A" && c <= "Z") || + (c >= "0" && c <= "9") || + c === "_" || + c === "$" + ); } function isEnumTypeUpper(u: string): boolean { - return u === "ENUM" || u === "ENUM8" || u === "ENUM16" + return u === "ENUM" || u === "ENUM8" || u === "ENUM16"; } class Parser { - private tokens: Token[] - private pos = 0 - private hard_error: ParseError | null = null + private tokens: Token[]; + private pos = 0; + private hard_error: ParseError | null = null; constructor(tokens: Token[]) { - this.tokens = tokens + this.tokens = tokens; } run(): ParseResult { /// A lexing error surfaces as a trailing Error token. for (const tok of this.tokens) - if (tok.type === TokenType.Error) - return Parser.fail(tok.begin, tok.text) + if (tok.type === TokenType.Error) return Parser.fail(tok.begin, tok.text); - const node = this.parseType() + const node = this.parseType(); if (!node) { - if (this.hard_error) - return makeResult(null, this.hard_error) - return Parser.fail(this.cur().begin, "expected a data type") + if (this.hard_error) return makeResult(null, this.hard_error); + return Parser.fail(this.cur().begin, "expected a data type"); } if (this.cur().type !== TokenType.End) - return Parser.fail(this.cur().begin, "unexpected trailing input after the data type") + return Parser.fail( + this.cur().begin, + "unexpected trailing input after the data type", + ); - return makeResult(node, null) + return makeResult(node, null); } private cur(): Token { - return this.tokens[this.pos] as Token + return this.tokens[this.pos] as Token; } private type(): TokenType { - return (this.tokens[this.pos] as Token).type + return (this.tokens[this.pos] as Token).type; } private advance(): void { - if ((this.tokens[this.pos] as Token).type !== TokenType.End) - ++this.pos + if ((this.tokens[this.pos] as Token).type !== TokenType.End) ++this.pos; } private static fail(at: number, msg: string): ParseResult { - return makeResult(null, { message: msg, position: at }) + return makeResult(null, { message: msg, position: at }); } private setHardError(at: number, msg: string): void { - if (!this.hard_error) - this.hard_error = { message: msg, position: at } + if (!this.hard_error) this.hard_error = { message: msg, position: at }; } private isIdentifier(): boolean { - return this.type() === TokenType.Word || this.type() === TokenType.QuotedIdent + return ( + this.type() === TokenType.Word || this.type() === TokenType.QuotedIdent + ); } /// Consume `count` consecutive Word tokens iff they match `words` /// (case-insensitive). Returns the original-cased joined match or "". private matchWords(words: string[]): boolean { - let p = this.pos + let p = this.pos; for (const w of words) { - const tok = this.tokens[p] as Token + const tok = this.tokens[p] as Token; if (tok.type !== TokenType.Word || toUpper(tok.text) !== toUpper(w)) - return false - ++p + return false; + ++p; } - this.pos = p - return true + this.pos = p; + return true; } /// Read a single identifier (bare or quoted) into `name`. private parseIdentifier(): { ok: boolean; name: string } { - if (!this.isIdentifier()) - return { ok: false, name: "" } - const name = this.cur().text - this.advance() - return { ok: true, name } + if (!this.isIdentifier()) return { ok: false, name: "" }; + const name = this.cur().text; + this.advance(); + return { ok: true, name }; } private parseType(): Node | null { - const id = this.parseIdentifier() - if (!id.ok) - return null - let type_name = id.name + const id = this.parseIdentifier(); + if (!id.ok) return null; + let type_name = id.name; /// Reject quoted garbage that cannot be a type name (e.g. `x.y`, `Null`). { - let allWordChar = true + let allWordChar = true; for (let i = 0; i < type_name.length; ++i) { if (!isWordCharOrDollar(type_name[i] as string)) { - allWordChar = false - break + allWordChar = false; + break; } } - if (!allWordChar) - return null + if (!allWordChar) return null; } - const type_name_upper = toUpper(type_name) + const type_name_upper = toUpper(type_name); /// Keywords that the column-declaration parser claims before the type. - if (type_name_upper === "NOT" || type_name_upper === "NULL" || type_name_upper === "DEFAULT" - || type_name_upper === "MATERIALIZED" || type_name_upper === "EPHEMERAL" || type_name_upper === "ALIAS" - || type_name_upper === "AUTO" || type_name_upper === "PRIMARY" || type_name_upper === "COMMENT" - || type_name_upper === "CODEC") - return null + if ( + type_name_upper === "NOT" || + type_name_upper === "NULL" || + type_name_upper === "DEFAULT" || + type_name_upper === "MATERIALIZED" || + type_name_upper === "EPHEMERAL" || + type_name_upper === "ALIAS" || + type_name_upper === "AUTO" || + type_name_upper === "PRIMARY" || + type_name_upper === "COMMENT" || + type_name_upper === "CODEC" + ) + return null; /// SQL-standard multi-word type names. - const suffix = this.parseTypeNameSuffix(type_name_upper) - if (suffix !== "") - type_name = type_name_upper + " " + suffix + const suffix = this.parseTypeNameSuffix(type_name_upper); + if (suffix !== "") type_name = type_name_upper + " " + suffix; - this.skipTrailingComma() + this.skipTrailingComma(); /// Enum special case -> EnumDataType with explicit values. - if (isEnumTypeUpper(type_name_upper) && this.type() === TokenType.OpeningParen) { - const saved = this.pos - this.advance() - const values: EnumValue[] = [] - if (this.parseEnumValues(values) && this.type() === TokenType.ClosingParen) { - this.advance() - const node = makeNode(NodeKind.EnumDataType) - node.name = type_name - node.values = values - return node + if ( + isEnumTypeUpper(type_name_upper) && + this.type() === TokenType.OpeningParen + ) { + const saved = this.pos; + this.advance(); + const values: EnumValue[] = []; + if ( + this.parseEnumValues(values) && + this.type() === TokenType.ClosingParen + ) { + this.advance(); + const node = makeNode(NodeKind.EnumDataType); + node.name = type_name; + node.values = values; + return node; } - this.pos = saved + this.pos = saved; } /// Tuple special case -> TupleDataType with optional element names. if (type_name === "Tuple" && this.type() === TokenType.OpeningParen) { - const tuple = this.parseTuple(type_name) - if (tuple) - return tuple + const tuple = this.parseTuple(type_name); + if (tuple) return tuple; /// else: fall through to the generic path } - const node = makeNode(NodeKind.DataType) - node.name = type_name + const node = makeNode(NodeKind.DataType); + node.name = type_name; - if (this.type() !== TokenType.OpeningParen) - return node - this.advance() + if (this.type() !== TokenType.OpeningParen) return node; + this.advance(); - if (!this.parseArgumentList(type_name, node.arguments)) - return null + if (!this.parseArgumentList(type_name, node.arguments)) return null; - if (this.type() !== TokenType.ClosingParen) - return null - this.advance() + if (this.type() !== TokenType.ClosingParen) return null; + this.advance(); - node.has_argument_list = true - return node + node.has_argument_list = true; + return node; } /// Returns the suffix to append for SQL-standard multi-word names, or "". private parseTypeNameSuffix(u: string): string { if (u === "NATIONAL") { - if (this.matchWords(["CHARACTER", "LARGE", "OBJECT"])) return "CHARACTER LARGE OBJECT" - if (this.matchWords(["CHARACTER", "VARYING"])) return "CHARACTER VARYING" - if (this.matchWords(["CHAR", "VARYING"])) return "CHAR VARYING" - if (this.matchWords(["CHARACTER"])) return "CHARACTER" - if (this.matchWords(["CHAR"])) return "CHAR" - } else if (u === "BINARY" || u === "CHARACTER" || u === "CHAR" || u === "NCHAR") { - if (this.matchWords(["LARGE", "OBJECT"])) return "LARGE OBJECT" - if (this.matchWords(["VARYING"])) return "VARYING" + if (this.matchWords(["CHARACTER", "LARGE", "OBJECT"])) + return "CHARACTER LARGE OBJECT"; + if (this.matchWords(["CHARACTER", "VARYING"])) return "CHARACTER VARYING"; + if (this.matchWords(["CHAR", "VARYING"])) return "CHAR VARYING"; + if (this.matchWords(["CHARACTER"])) return "CHARACTER"; + if (this.matchWords(["CHAR"])) return "CHAR"; + } else if ( + u === "BINARY" || + u === "CHARACTER" || + u === "CHAR" || + u === "NCHAR" + ) { + if (this.matchWords(["LARGE", "OBJECT"])) return "LARGE OBJECT"; + if (this.matchWords(["VARYING"])) return "VARYING"; } else if (u === "DOUBLE") { - if (this.matchWords(["PRECISION"])) return "PRECISION" + if (this.matchWords(["PRECISION"])) return "PRECISION"; } else if (u.indexOf("INT") !== -1) { /// MySQL-compatible SIGNED / UNSIGNED, optionally after `(width)`. - if (this.matchWords(["SIGNED"])) return "SIGNED" - if (this.matchWords(["UNSIGNED"])) return "UNSIGNED" + if (this.matchWords(["SIGNED"])) return "SIGNED"; + if (this.matchWords(["UNSIGNED"])) return "UNSIGNED"; if (this.type() === TokenType.OpeningParen) { - const saved = this.pos - this.advance() - if (this.type() === TokenType.Number) - this.advance() + const saved = this.pos; + this.advance(); + if (this.type() === TokenType.Number) this.advance(); if (this.type() === TokenType.ClosingParen) { - this.advance() - if (this.matchWords(["SIGNED"])) return "SIGNED" - if (this.matchWords(["UNSIGNED"])) return "UNSIGNED" + this.advance(); + if (this.matchWords(["SIGNED"])) return "SIGNED"; + if (this.matchWords(["UNSIGNED"])) return "UNSIGNED"; } else { /// not the width form; leave the paren for generic args - this.pos = saved + this.pos = saved; } } } - return "" + return ""; } /// Skip a trailing comma right before a closing paren: `Tuple(Int, String,)`. private skipTrailingComma(): void { - if (this.type() === TokenType.Comma && (this.tokens[this.pos + 1] as Token).type === TokenType.ClosingParen) - this.advance() + if ( + this.type() === TokenType.Comma && + (this.tokens[this.pos + 1] as Token).type === TokenType.ClosingParen + ) + this.advance(); } /// Explicit-only enum body: 'name' = value, ... . Returns false (caller /// restores) for auto-assigned or otherwise non-trivial enums. private parseEnumValues(values: EnumValue[]): boolean { - let first = true + let first = true; while (true) { if (!first) { - if (this.type() !== TokenType.Comma) - break - this.advance() + if (this.type() !== TokenType.Comma) break; + this.advance(); } - first = false + first = false; - if (this.type() !== TokenType.String) - return false - const name = this.cur().text - this.advance() + if (this.type() !== TokenType.String) return false; + const name = this.cur().text; + this.advance(); - if (this.type() !== TokenType.Equals) - return false - this.advance() + if (this.type() !== TokenType.Equals) return false; + this.advance(); - let negative = false + let negative = false; if (this.type() === TokenType.Minus) { - negative = true - this.advance() + negative = true; + this.advance(); } - if (this.type() !== TokenType.Number || this.cur().is_float) - return false - const v = BigInt(this.cur().text) - this.advance() + if (this.type() !== TokenType.Number || this.cur().is_float) return false; + const v = BigInt(this.cur().text); + this.advance(); - values.push({ name, value: negative ? -v : v }) + values.push({ name, value: negative ? -v : v }); } - return values.length !== 0 + return values.length !== 0; } /// Parse a Tuple body into element types + names. Returns null (with the /// position restored) if it cannot, so the caller can try the generic path. private parseTuple(type_name: string): Node | null { - const saved = this.pos - this.advance() /// consume '(' + const saved = this.pos; + this.advance(); /// consume '(' - const node = makeNode(NodeKind.TupleDataType) - node.name = type_name + const node = makeNode(NodeKind.TupleDataType); + node.name = type_name; - const names: string[] = [] - let has_named = false - let first = true + const names: string[] = []; + let has_named = false; + let first = true; while (true) { if (!first) { - if (this.type() === TokenType.Comma) - this.advance() - else - break + if (this.type() === TokenType.Comma) this.advance(); + else break; } - first = false + first = false; - const element_pos = this.pos + const element_pos = this.pos; /// Try: identifier Type (named element) - const id = this.parseIdentifier() + const id = this.parseIdentifier(); if (id.ok) { - const t = this.parseType() + const t = this.parseType(); if (t) { - names.push(id.name) - node.arguments.push(t) - has_named = true - continue + names.push(id.name); + node.arguments.push(t); + has_named = true; + continue; } } /// Else: just Type (unnamed element) - this.pos = element_pos - const t = this.parseType() + this.pos = element_pos; + const t = this.parseType(); if (t) { - names.push("") - node.arguments.push(t) + names.push(""); + node.arguments.push(t); } else { - break + break; } } if (this.type() === TokenType.ClosingParen && node.arguments.length !== 0) { - this.advance() - node.has_argument_list = true - if (has_named) - node.element_names = names - return node + this.advance(); + node.has_argument_list = true; + if (has_named) node.element_names = names; + return node; } - this.pos = saved - return null + this.pos = saved; + return null; } /// The generic comma-separated argument list inside `Type(...)`. private parseArgumentList(type_name: string, out: Node[]): boolean { - const lower = toLower(type_name) - - if (type_name === "AggregateFunction" || type_name === "SimpleAggregateFunction") { - this.setHardError(this.cur().begin, type_name + " is not supported by this parser yet") - return false + const lower = toLower(type_name); + + if ( + type_name === "AggregateFunction" || + type_name === "SimpleAggregateFunction" + ) { + this.setHardError( + this.cur().begin, + type_name + " is not supported by this parser yet", + ); + return false; } if (lower === "json") { - this.setHardError(this.cur().begin, "JSON typed/object arguments are not supported by this parser yet") - return false + this.setHardError( + this.cur().begin, + "JSON typed/object arguments are not supported by this parser yet", + ); + return false; } - let arg_num = 0 + let arg_num = 0; while (true) { if (arg_num > 0) { - if (this.type() === TokenType.Comma) - this.advance() - else - break + if (this.type() === TokenType.Comma) this.advance(); + else break; } - let arg: Node | null - if (type_name === "Dynamic") - arg = this.parseEqualsArgument() - else if (type_name === "Nested") - arg = this.parseNameTypePair() - else if (type_name === "Tuple") - arg = this.parseNameTypePairOrType() - else - arg = this.parseGenericArgument() - - if (!arg) - break - - out.push(arg) - ++arg_num + let arg: Node | null; + if (type_name === "Dynamic") arg = this.parseEqualsArgument(); + else if (type_name === "Nested") arg = this.parseNameTypePair(); + else if (type_name === "Tuple") arg = this.parseNameTypePairOrType(); + else arg = this.parseGenericArgument(); + + if (!arg) break; + + out.push(arg); + ++arg_num; } - return true + return true; } /// `identifier = number` -> Function equals(Identifier, Literal). private parseEqualsArgument(): Node | null { - const id = this.parseIdentifier() - if (!id.ok) - return null - if (this.type() !== TokenType.Equals) - return null - this.advance() - const number = this.parseNumberLiteral() - if (!number) - return null - - const idNode = makeNode(NodeKind.Identifier) - idNode.name = id.name - const fn = makeNode(NodeKind.Function) - fn.name = "equals" - fn.is_operator = true - fn.arguments = [idNode, number] - return fn + const id = this.parseIdentifier(); + if (!id.ok) return null; + if (this.type() !== TokenType.Equals) return null; + this.advance(); + const number = this.parseNumberLiteral(); + if (!number) return null; + + const idNode = makeNode(NodeKind.Identifier); + idNode.name = id.name; + const fn = makeNode(NodeKind.Function); + fn.name = "equals"; + fn.is_operator = true; + fn.arguments = [idNode, number]; + return fn; } /// `name Type` -> NameTypePair (Nested elements). private parseNameTypePair(): Node | null { - const id = this.parseIdentifier() - if (!id.ok) - return null - const t = this.parseType() - if (!t) - return null - const node = makeNode(NodeKind.NameTypePair) - node.name = id.name - node.data_type = t - return node + const id = this.parseIdentifier(); + if (!id.ok) return null; + const t = this.parseType(); + if (!t) return null; + const node = makeNode(NodeKind.NameTypePair); + node.name = id.name; + node.data_type = t; + return node; } private parseNameTypePairOrType(): Node | null { - const saved = this.pos - const pair = this.parseNameTypePair() - if (pair) - return pair - this.pos = saved - return this.parseType() + const saved = this.pos; + const pair = this.parseNameTypePair(); + if (pair) return pair; + this.pos = saved; + return this.parseType(); } /// Generic argument: a scalar literal (optionally `lit = lit`), or a type. private parseGenericArgument(): Node | null { - const lit = this.parseScalarLiteral() + const lit = this.parseScalarLiteral(); if (lit) { if (this.type() === TokenType.Equals) { - this.advance() - const rhs = this.parseScalarLiteral() - if (!rhs) - return null - const fn = makeNode(NodeKind.Function) - fn.name = "equals" - fn.is_operator = true - fn.arguments = [lit, rhs] - return fn + this.advance(); + const rhs = this.parseScalarLiteral(); + if (!rhs) return null; + const fn = makeNode(NodeKind.Function); + fn.name = "equals"; + fn.is_operator = true; + fn.arguments = [lit, rhs]; + return fn; } - return lit + return lit; } - return this.parseType() + return this.parseType(); } private parseNumberLiteral(): Node | null { - let negative = false + let negative = false; if (this.type() === TokenType.Minus) { - negative = true - this.advance() + negative = true; + this.advance(); } - if (this.type() !== TokenType.Number) - return null - const node = makeNode(NodeKind.Literal) - node.value_type = this.cur().is_float ? "Float64" : (negative ? "Int64" : "UInt64") - node.value = (negative ? "-" : "") + this.cur().text - this.advance() - return node + if (this.type() !== TokenType.Number) return null; + const node = makeNode(NodeKind.Literal); + node.value_type = this.cur().is_float + ? "Float64" + : negative + ? "Int64" + : "UInt64"; + node.value = (negative ? "-" : "") + this.cur().text; + this.advance(); + return node; } /// A scalar literal: number (optionally signed) or string. private parseScalarLiteral(): Node | null { if (this.type() === TokenType.Number || this.type() === TokenType.Minus) - return this.parseNumberLiteral() + return this.parseNumberLiteral(); if (this.type() === TokenType.String) { - const node = makeNode(NodeKind.Literal) - node.value_type = "String" - node.value = this.cur().text - this.advance() - return node + const node = makeNode(NodeKind.Literal); + node.value_type = "String"; + node.value = this.cur().text; + this.advance(); + return node; } - return null + return null; } } @@ -482,14 +496,14 @@ function makeResult(ast: Node | null, error: ParseError | null): ParseResult { ast, error, ok(): boolean { - return this.ast !== null + return this.ast !== null; }, - } + }; } /// Parse the whole string as a single data type. Trailing tokens after a /// complete type are an error (the entire input must be one type). export function parseDataType(input: string): ParseResult { - const parser = new Parser(tokenize(input)) - return parser.run() + const parser = new Parser(tokenize(input)); + return parser.run(); } diff --git a/type-parser/mini-parser-ts/test/check_unsupported.ts b/type-parser/mini-parser-ts/test/check_unsupported.ts index 891ac9201..193e22fba 100644 --- a/type-parser/mini-parser-ts/test/check_unsupported.ts +++ b/type-parser/mini-parser-ts/test/check_unsupported.ts @@ -30,7 +30,9 @@ function main(): number { } } - console.log(`\n${cases.length - failures}/${cases.length} correctly rejected`); + console.log( + `\n${cases.length - failures}/${cases.length} correctly rejected`, + ); return failures ? 1 : 0; } diff --git a/type-parser/mini-parser-ts/test/oracle.ts b/type-parser/mini-parser-ts/test/oracle.ts index cc96f4293..590bc3bde 100644 --- a/type-parser/mini-parser-ts/test/oracle.ts +++ b/type-parser/mini-parser-ts/test/oracle.ts @@ -31,10 +31,14 @@ export function findColumnDataType(node: unknown, column: string): unknown { /// server error (invalid type) or an unexpected AST shape. export function serverDataType(clickhouse: string, typeStr: string): unknown { const sql = `EXPLAIN AST json = 1 CREATE TABLE t (c ${typeStr}) ENGINE = Null`; - const out = spawnSync(clickhouse, ["local", "--format", "TSVRaw", "-q", sql], { - encoding: "utf8", - maxBuffer: 64 * 1024 * 1024, - }); + const out = spawnSync( + clickhouse, + ["local", "--format", "TSVRaw", "-q", sql], + { + encoding: "utf8", + maxBuffer: 64 * 1024 * 1024, + }, + ); if (out.status !== 0) { throw new Error(`server failed: ${(out.stderr ?? "").trim()}`); } diff --git a/type-parser/mini-parser-ts/test/oracle_compare.ts b/type-parser/mini-parser-ts/test/oracle_compare.ts index 33ffe48c9..ce25522bb 100644 --- a/type-parser/mini-parser-ts/test/oracle_compare.ts +++ b/type-parser/mini-parser-ts/test/oracle_compare.ts @@ -51,7 +51,9 @@ function main(): number { expected = canon(serverDataType(clickhouse, typeStr)); actual = canon(toolDataType(typeStr)); } catch (exc) { - console.log(`ERROR ${JSON.stringify(typeStr)}: ${(exc as Error).message}`); + console.log( + `ERROR ${JSON.stringify(typeStr)}: ${(exc as Error).message}`, + ); failures++; continue; } diff --git a/type-parser/mini-parser-ts/test/parser.test.ts b/type-parser/mini-parser-ts/test/parser.test.ts index 123d65c82..d68753bb7 100644 --- a/type-parser/mini-parser-ts/test/parser.test.ts +++ b/type-parser/mini-parser-ts/test/parser.test.ts @@ -30,7 +30,11 @@ test("nested parametric type", () => { type: "DataType", name: "Array", arguments: [ - { type: "DataType", name: "Nullable", arguments: [{ type: "DataType", name: "UInt64" }] }, + { + type: "DataType", + name: "Nullable", + arguments: [{ type: "DataType", name: "UInt64" }], + }, ], }); }); @@ -98,13 +102,19 @@ test("Dynamic(max_types = 5) parses to an equals Function argument", () => { }); test("SQL-standard multi-word alias", () => { - assert.deepEqual(json("DOUBLE PRECISION"), { type: "DataType", name: "DOUBLE PRECISION" }); + assert.deepEqual(json("DOUBLE PRECISION"), { + type: "DataType", + name: "DOUBLE PRECISION", + }); }); test("compact output has no whitespace", () => { const r = parseDataType("Array(String)"); assert.ok(r.ok()); - assert.equal(toJSON(r.ast!, -1), '{"type":"DataType","name":"Array","arguments":[{"type":"DataType","name":"String"}]}'); + assert.equal( + toJSON(r.ast!, -1), + '{"type":"DataType","name":"Array","arguments":[{"type":"DataType","name":"String"}]}', + ); }); test("deliberately-unsupported types are rejected with a hard error", () => { diff --git a/type-parser/mini-parser-ts/test/snapshots.ts b/type-parser/mini-parser-ts/test/snapshots.ts index c53fd2fa7..884fde7f8 100644 --- a/type-parser/mini-parser-ts/test/snapshots.ts +++ b/type-parser/mini-parser-ts/test/snapshots.ts @@ -15,7 +15,10 @@ export const SNAPSHOT_DIR = join(here, "snapshots"); /// A stable filename for a type string (content-addressed, so reordering /// cases.txt never churns filenames). export function snapshotName(typeStr: string): string { - return createHash("sha1").update(typeStr, "utf8").digest("hex").slice(0, 16) + ".json"; + return ( + createHash("sha1").update(typeStr, "utf8").digest("hex").slice(0, 16) + + ".json" + ); } export function snapshotPath(typeStr: string): string { diff --git a/type-parser/mini-parser-ts/test/update_snapshots.ts b/type-parser/mini-parser-ts/test/update_snapshots.ts index de3386e47..fe2eb164c 100644 --- a/type-parser/mini-parser-ts/test/update_snapshots.ts +++ b/type-parser/mini-parser-ts/test/update_snapshots.ts @@ -18,13 +18,26 @@ /// The clickhouse binary must be built from /// https://github.com/peter-leonov-ch/ClickHouse/pull/1. -import { existsSync, mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync, appendFileSync } from "node:fs"; +import { + existsSync, + mkdirSync, + readdirSync, + readFileSync, + rmSync, + writeFileSync, + appendFileSync, +} from "node:fs"; import { fileURLToPath } from "node:url"; import { dirname, join } from "node:path"; import { canon, deepEqual, readCases } from "./cases.js"; import { serverDataType, toolDataType } from "./oracle.js"; -import { SNAPSHOT_DIR, snapshotName, snapshotPath, type Snapshot } from "./snapshots.js"; +import { + SNAPSHOT_DIR, + snapshotName, + snapshotPath, + type Snapshot, +} from "./snapshots.js"; const here = dirname(fileURLToPath(import.meta.url)); @@ -57,7 +70,9 @@ function main(): number { /// appended. Dedup by exact (trimmed) string across both sources. const existing = readCases(args.cases); const existingSet = new Set(existing); - const candidates = existsSync(args.candidates) ? readCases(args.candidates) : []; + const candidates = existsSync(args.candidates) + ? readCases(args.candidates) + : []; const order: string[] = []; const seen = new Set(); @@ -83,7 +98,10 @@ function main(): number { try { expected = serverDataType(args.clickhouse, typeStr); } catch (exc) { - rejected.push({ type: typeStr, reason: `server: ${(exc as Error).message}` }); + rejected.push({ + type: typeStr, + reason: `server: ${(exc as Error).message}`, + }); continue; } @@ -91,12 +109,20 @@ function main(): number { try { actual = toolDataType(typeStr); } catch (exc) { - divergent.push({ type: typeStr, expected: JSON.stringify(canon(expected)), actual: `(${(exc as Error).message})` }); + divergent.push({ + type: typeStr, + expected: JSON.stringify(canon(expected)), + actual: `(${(exc as Error).message})`, + }); continue; } if (!deepEqual(expected, actual)) { - divergent.push({ type: typeStr, expected: JSON.stringify(canon(expected)), actual: JSON.stringify(canon(actual)) }); + divergent.push({ + type: typeStr, + expected: JSON.stringify(canon(expected)), + actual: JSON.stringify(canon(actual)), + }); continue; } @@ -130,7 +156,9 @@ function main(): number { const reportLines: string[] = []; reportLines.push(`# snapshot update report`); reportLines.push(`candidates considered: ${order.length}`); - reportLines.push(`kept (snapshotted): ${kept.length} (new in cases.txt: ${newKept.length})`); + reportLines.push( + `kept (snapshotted): ${kept.length} (new in cases.txt: ${newKept.length})`, + ); reportLines.push(`rejected by server: ${rejected.length}`); reportLines.push(`divergent (server!=parser): ${divergent.length}`); reportLines.push(`pruned stale snapshots: ${pruned}`); @@ -139,14 +167,19 @@ function main(): number { for (const r of rejected) reportLines.push(`- ${r.type}\n ${r.reason}`); } if (divergent.length) { - reportLines.push(`\n## divergent (server accepted but parser output differs)`); + reportLines.push( + `\n## divergent (server accepted but parser output differs)`, + ); for (const d of divergent) { reportLines.push(`- ${d.type}`); reportLines.push(` expected: ${d.expected}`); reportLines.push(` actual: ${d.actual}`); } } - writeFileSync(join(here, "snapshots_report.txt"), reportLines.join("\n") + "\n"); + writeFileSync( + join(here, "snapshots_report.txt"), + reportLines.join("\n") + "\n", + ); console.log(reportLines.slice(0, 6).join("\n")); console.log(`\nreport: test/snapshots_report.txt`); diff --git a/type-parser/mini-parser-ts/test/validate_types_live.ts b/type-parser/mini-parser-ts/test/validate_types_live.ts index a462cb1e9..d663e4e49 100644 --- a/type-parser/mini-parser-ts/test/validate_types_live.ts +++ b/type-parser/mini-parser-ts/test/validate_types_live.ts @@ -43,7 +43,11 @@ interface Failure { message: string; } -async function probe(url: string, typeStr: string, i: number): Promise { +async function probe( + url: string, + typeStr: string, + i: number, +): Promise { const sql = `CREATE TEMPORARY TABLE _chdt_probe_${i} (c ${typeStr})`; const resp = await fetch(url, { method: "POST", body: sql }); if (resp.ok) { @@ -68,7 +72,9 @@ async function main(): Promise { const cases = readCases(join(here, "cases.txt")); /// Types the parser handles (and whose AST matches the server) but that the /// type factory refuses to instantiate — documented & expected, not bugs. - const expectedNonInstantiable = new Set(readCases(join(here, "non_instantiable.txt"))); + const expectedNonInstantiable = new Set( + readCases(join(here, "non_instantiable.txt")), + ); /// Confirm reachability up front. try { @@ -83,34 +89,52 @@ async function main(): Promise { let done = 0; for (let start = 0; start < cases.length; start += CONCURRENCY) { const batch = cases.slice(start, start + CONCURRENCY); - const results = await Promise.all(batch.map((t, k) => probe(url, t, start + k))); + const results = await Promise.all( + batch.map((t, k) => probe(url, t, start + k)), + ); for (const f of results) if (f) failures.push(f); done += batch.length; process.stderr.write(` ... ${done}/${cases.length}\n`); } const expected = failures.filter((f) => expectedNonInstantiable.has(f.type)); - const unexpected = failures.filter((f) => !expectedNonInstantiable.has(f.type)); + const unexpected = failures.filter( + (f) => !expectedNonInstantiable.has(f.type), + ); console.log(`\nchecked ${cases.length} types`); console.log(`instantiated OK: ${cases.length - failures.length}`); - console.log(`expected non-instantiable (allowlisted, see non_instantiable.txt): ${expected.length}`); + console.log( + `expected non-instantiable (allowlisted, see non_instantiable.txt): ${expected.length}`, + ); console.log(`UNEXPECTED failures: ${unexpected.length}`); if (expected.length) { - console.log(`\n## expected non-instantiable (parser-valid by design — NOT inventions)`); - for (const f of expected) console.log(`- ${f.type}\n Code ${f.code}: ${f.message.split("\n")[0]}`); + console.log( + `\n## expected non-instantiable (parser-valid by design — NOT inventions)`, + ); + for (const f of expected) + console.log( + `- ${f.type}\n Code ${f.code}: ${f.message.split("\n")[0]}`, + ); } if (unexpected.length) { console.log(`\n## UNEXPECTED — server does not accept these (review!)`); - for (const f of unexpected) console.log(`- ${f.type}\n Code ${f.code}: ${f.message.split("\n")[0]}`); + for (const f of unexpected) + console.log( + `- ${f.type}\n Code ${f.code}: ${f.message.split("\n")[0]}`, + ); } /// Also flag anything allowlisted that now DOES instantiate (stale entry). - const okSet = new Set(cases.filter((t) => !failures.some((f) => f.type === t))); + const okSet = new Set( + cases.filter((t) => !failures.some((f) => f.type === t)), + ); const stale = [...expectedNonInstantiable].filter((t) => okSet.has(t)); if (stale.length) { - console.log(`\n## stale allowlist entries (now instantiate — remove from non_instantiable.txt)`); + console.log( + `\n## stale allowlist entries (now instantiate — remove from non_instantiable.txt)`, + ); for (const t of stale) console.log(`- ${t}`); } From 41818ff688dd5b57574c8559b7a55ba9bb8d9d2b Mon Sep 17 00:00:00 2001 From: Peter Leonov Date: Wed, 24 Jun 2026 19:50:38 +0200 Subject: [PATCH 9/9] fix(type-parser): address PR review comments - parser.ts: correct the matchWords doc comment (it takes an array and returns a boolean while advancing pos, not a count / joined string). - update_snapshots.ts: drop the unused readFileSync import. - mini-parser-extracted/CMakeLists.txt: guard -Wall -Wextra behind non-MSVC; use /W4 on MSVC so Windows generators build. The other two review notes (package main/types -> dist/src/*, and Prettier formatting) were already handled in earlier commits. Co-Authored-By: Claude Opus 4.8 (1M context) --- type-parser/mini-parser-extracted/CMakeLists.txt | 7 ++++++- type-parser/mini-parser-ts/src/parser.ts | 5 +++-- type-parser/mini-parser-ts/test/update_snapshots.ts | 1 - 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/type-parser/mini-parser-extracted/CMakeLists.txt b/type-parser/mini-parser-extracted/CMakeLists.txt index 5ff06511c..c6a897105 100644 --- a/type-parser/mini-parser-extracted/CMakeLists.txt +++ b/type-parser/mini-parser-extracted/CMakeLists.txt @@ -10,7 +10,12 @@ if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Release) endif() -add_compile_options(-Wall -Wextra) +# Warning flags are GCC/Clang-specific; guard them so MSVC builds still work. +if(MSVC) + add_compile_options(/W4) +else() + add_compile_options(-Wall -Wextra) +endif() add_library(chdt_datatype_parser src/lexer.cpp diff --git a/type-parser/mini-parser-ts/src/parser.ts b/type-parser/mini-parser-ts/src/parser.ts index 065d19039..0a87a3af6 100644 --- a/type-parser/mini-parser-ts/src/parser.ts +++ b/type-parser/mini-parser-ts/src/parser.ts @@ -117,8 +117,9 @@ class Parser { ); } - /// Consume `count` consecutive Word tokens iff they match `words` - /// (case-insensitive). Returns the original-cased joined match or "". + /// Consume consecutive Word tokens iff they all match `words` + /// (case-insensitive). On a full match, advances `pos` past them and returns + /// true; otherwise leaves `pos` unchanged and returns false. private matchWords(words: string[]): boolean { let p = this.pos; for (const w of words) { diff --git a/type-parser/mini-parser-ts/test/update_snapshots.ts b/type-parser/mini-parser-ts/test/update_snapshots.ts index fe2eb164c..79eb3d3d9 100644 --- a/type-parser/mini-parser-ts/test/update_snapshots.ts +++ b/type-parser/mini-parser-ts/test/update_snapshots.ts @@ -22,7 +22,6 @@ import { existsSync, mkdirSync, readdirSync, - readFileSync, rmSync, writeFileSync, appendFileSync,