diff --git a/docs/sql-manual/basic-element/sql-data-types/semi-structured/VARIANT.md b/docs/sql-manual/basic-element/sql-data-types/semi-structured/VARIANT.md index 227fa74769688..47f36be65313c 100644 --- a/docs/sql-manual/basic-element/sql-data-types/semi-structured/VARIANT.md +++ b/docs/sql-manual/basic-element/sql-data-types/semi-structured/VARIANT.md @@ -2,7 +2,7 @@ { "title": "VARIANT", "language": "en-US", - "description": "The VARIANT type stores semi-structured JSON data. It can contain different primitive types (integers, strings, booleans, etc.), one-dimensional arrays, and nested objects. On write, Doris infers the structure and type of sub-paths based on JSON paths and performs Subcolumnization on frequent paths, exposing them as independent columnar subcolumns for both flexibility and performance." + "description": "VARIANT stores semi-structured JSON data and supports typed access, casts, canonical equality, grouping, hashing, and selected SQL operations." } --- @@ -67,6 +67,162 @@ FROM ${table_name} WHERE ARRAY_CONTAINS(CAST(v['tags'] AS ARRAY), 'Doris'); ``` +## Create and access values + +:::info Version availability +The behavior in this section applies to Doris 4.2 and later. +::: + +VARIANT values can be created from JSON text, JSON/JSONB values, or typed SQL expressions: + +- Use [PARSE_TO_VARIANT](../../../sql-functions/scalar-functions/variant-functions/parse-to-variant) when a string or JSON/JSONB expression should be parsed as a structured VARIANT value. +- Use `CAST(expression AS VARIANT)` to convert a supported SQL value to VARIANT. String parsing for this CAST is controlled by `enable_variant_string_cast_parse`, as described in [CAST rules](#cast-rules). + +### Parse JSON text + +```sql +SELECT PARSE_TO_VARIANT('{"user": {"id": 42}, "active": true}'); +SELECT PARSE_TO_VARIANT('[10, 20, 30]'); +SELECT PARSE_TO_VARIANT(CAST('{"user": {"id": 42}}' AS JSON)); +``` + +Use [PARSE_TO_VARIANT_ERROR_TO_NULL](../../../sql-functions/scalar-functions/variant-functions/parse-to-variant-error-to-null) when invalid JSON should return SQL `NULL` instead of failing the query. + +### Access objects and arrays + +Object fields can be accessed with a string key. In Doris 4.2 and later, VARIANT array indexes are zero-based for non-negative indexes and support negative indexes from the end. The extracted value remains `VARIANT`; CAST it before typed comparison, arithmetic, or aggregation. + +```sql +SELECT CAST(PARSE_TO_VARIANT('{"user": {"id": 42}}')['user']['id'] AS BIGINT); +SELECT ELEMENT_AT(PARSE_TO_VARIANT('[10, 20, 30]'), 0); -- 10 +SELECT ELEMENT_AT(PARSE_TO_VARIANT('[10, 20, 30]'), -1); -- 30 +``` + +See [ELEMENT_AT](../../../sql-functions/scalar-functions/variant-functions/element-at) for object and array access details. + +## CAST rules + +CAST involving VARIANT has two directions: converting a supported SQL value to VARIANT and extracting a compatible SQL value from VARIANT. + +### CAST other types to VARIANT + +| Source type | Behavior | +| --- | --- | +| `CHAR`, `VARCHAR`, `STRING` | In query sessions, parses the input as JSON by default. Set `enable_variant_string_cast_parse` to `false` to preserve the input as a VARIANT string instead. | +| `JSON` / `JSONB` | Converts the structured JSON value directly to VARIANT. | +| Boolean, integer, floating-point, and Decimal types | Preserves the typed scalar value, subject to the Decimal limits below. | +| `DATE`, `DATETIME`, `TIMESTAMPTZ`, `IPV4`, `IPV6` | Preserves the typed logical value. | +| `ARRAY` | Converts each supported element recursively and preserves SQL NULL elements. | +| `MAP` | Not supported. | + +`enable_variant_string_cast_parse` is `true` by default in query sessions. Use `PARSE_TO_VARIANT` when the SQL text should always make the JSON-parsing intent explicit, independent of the session setting. + +```sql +-- Default behavior: parse the string as JSON. +SELECT CAST('{"id": 1}' AS VARIANT) AS parsed_object; +-- {"id":1} + +-- Preserve the same input as a VARIANT string root. +SET enable_variant_string_cast_parse = false; +SELECT CAST(CAST('{"id": 1}' AS VARIANT) AS STRING) AS string_value, + VARIANT_TYPE(CAST('{"id": 1}' AS VARIANT)) AS root_type; +-- string_value: {"id": 1}; root_type: string + +-- JSON/JSONB input remains structured. +SET enable_variant_string_cast_parse = true; +SELECT CAST(CAST('{"id": 1}' AS JSON) AS VARIANT) AS parsed_object; +-- {"id":1} +``` + +When string parsing is enabled, invalid JSON causes the CAST to fail. Use `PARSE_TO_VARIANT_ERROR_TO_NULL` if malformed input should become SQL `NULL`. + +### CAST VARIANT to other types + +VARIANT can be cast to a compatible scalar, JSON/JSONB, or array target: + +| Target type | Behavior | +| --- | --- | +| Boolean, integer, floating-point, Decimal, date/time, and IP types | Converts compatible scalar roots; incompatible shapes, invalid text, or out-of-range values return an error or SQL `NULL` according to the applicable CAST mode. | +| `STRING` | Returns scalar text for scalar roots and JSON text for objects and arrays. Variant/JSON `null` becomes the string `null`; outer SQL `NULL` remains SQL `NULL`. | +| `JSON` / `JSONB` | Converts a representable VARIANT value to structured JSON/JSONB. | +| `ARRAY` | Converts a VARIANT array element by element to `T`; incompatible elements follow the target CAST rules. | +| `MAP` | Not supported. | + +```sql +SELECT CAST(PARSE_TO_VARIANT('42') AS BIGINT) AS id; +-- 42 + +SELECT CAST(PARSE_TO_VARIANT('[1, null, 3]') AS ARRAY) AS values; +-- [1, NULL, 3] + +SELECT CAST(PARSE_TO_VARIANT('{"id": 1}') AS JSON) AS json_value; +-- {"id":1} +``` + +### Decimal and date/time conversion limits + +| Doris input type | Supported VARIANT behavior | +| --- | --- | +| Legacy `DECIMALV2` | Precision up to 27 and scale up to 9 are preserved exactly. | +| `DECIMAL(p, s)` | `1 <= p <= 38` and `0 <= s <= p` are preserved exactly. Values that require precision greater than 38 are not supported. | +| `DATE` | Preserved as a calendar date with no time or time zone. | +| Legacy `DATETIME` | Preserved with whole-second precision and no time-zone adjustment. | +| `DATETIME(p)` | Supports `0 <= p <= 6` with no time-zone adjustment. | +| `TIMESTAMPTZ(p)` | Supports `0 <= p <= 6` with time-zone-adjusted timestamp semantics. | +| `TIME` | Not supported as input to VARIANT. | + +Every source value must also be valid for its Doris source type. Unsupported precision, invalid dates, or incompatible values return an error instead of being repaired. + +## Equality and hash semantics + +In Doris 4.2 and later, grouping, deduplication, and set operations compare logical values rather than source SQL types or physical representations: + +- Equivalent integral numeric representations compare as equal. +- Decimal trailing zeros do not change the value, so `1.20` and `1.2` compare as equal. +- `+0`, `-0`, and integral zero compare as equal. +- Object key order does not affect equality, while array element order does. +- Variant/JSON `null` is distinct from SQL `NULL`. + +Hash-based operators calculate their keys from the same canonical logical representation. Values that compare as equal under the rules above therefore produce the same internal hash key, regardless of whether they came from parsed JSON or a typed CAST. This hash is an implementation detail, not a stable user-facing checksum. + +These rules apply to supported operations such as `GROUP BY`, `DISTINCT`, `COUNT(DISTINCT ...)`, `INTERSECT`, `EXCEPT`, and `UNION DISTINCT`. They do not enable root VARIANT comparison predicates: direct `VARIANT = VARIANT` and ordering comparisons remain unsupported. + +```sql +-- 1 and 1.0 have one distinct logical value. +SELECT COUNT(DISTINCT value) AS distinct_count +FROM ( + SELECT PARSE_TO_VARIANT('1') AS value + UNION ALL + SELECT PARSE_TO_VARIANT('1.0') AS value +) AS numeric_values; +-- distinct_count: 1 + +-- Object key order is ignored; array order is preserved. +SELECT COUNT(DISTINCT value) AS distinct_count +FROM ( + SELECT PARSE_TO_VARIANT('{"a": 1, "b": 2}') AS value + UNION ALL + SELECT PARSE_TO_VARIANT('{"b": 2, "a": 1}') AS value +) AS object_values; +-- distinct_count: 1 + +SELECT COUNT(DISTINCT value) AS distinct_count +FROM ( + SELECT PARSE_TO_VARIANT('[1, 2]') AS value + UNION ALL + SELECT PARSE_TO_VARIANT('[2, 1]') AS value +) AS array_values; +-- distinct_count: 2 +``` + +## NULL semantics + +SQL `NULL` and Variant/JSON `null` are different values: + +- SQL `NULL` represents the absence of a SQL value and follows normal SQL NULL propagation. +- Variant/JSON `null` is a VARIANT value, for example the result of `PARSE_TO_VARIANT('null')`. +- `PARSE_TO_VARIANT_ERROR_TO_NULL` returns SQL `NULL` for malformed input. This differs from successfully parsing the JSON literal `null`. + ## Primitive types VARIANT infers subcolumn types automatically. Supported types include: @@ -387,10 +543,26 @@ SELECT v FROM variant_tbl WHERE k = 2; Sorting applies at every level — top-level keys become `a`, `b`, `c`, and the nested object's keys become `x`, `y`. -## Supported operations and CAST rules +## Supported operations + +In Doris 4.2 and later, whole VARIANT values support hash-based grouping and deduplication, but they do not support comparison, join-key, or ordering semantics. -- VARIANT cannot be compared/operated directly with other types; comparisons between two VARIANTs are not supported either. -- For comparison, filtering, aggregation, and ordering, CAST subpaths to concrete types (explicitly or implicitly). +| Operation on a whole VARIANT value | Support | Notes | +| --- | --- | --- | +| `GROUP BY` | Supported | Uses the logical equality and canonical hash rules described above. | +| `DISTINCT`, `COUNT(DISTINCT ...)` | Supported | Logically equivalent values are deduplicated. | +| `INTERSECT`, `EXCEPT`, `UNION DISTINCT` | Supported | Uses the same logical equality and hash semantics. | +| `COUNT(*)`, `COUNT(variant)` | Supported | `COUNT(variant)` excludes outer SQL `NULL` in the normal SQL manner. | +| `IF`, `CASE`, `IFNULL`, `COALESCE` | Supported | Conditional expressions can return and consume VARIANT values. | +| VARIANT in transient `ARRAY`, `MAP`, or `STRUCT` expressions | Supported | This does not allow these nested types in persisted table schemas. | +| `EXPLODE_VARIANT_ARRAY`, `EXPLODE`/`EXPLODE_OUTER` on `ARRAY` | Supported | Emits VARIANT elements and preserves SQL NULL versus Variant/JSON `null`. | +| `=`, `!=`, `<=>`, `<`, `<=`, `>`, `>=` | Not supported | Extract and CAST a comparable subpath on both sides. | +| Join key | Not supported | CAST the required subpath to the same concrete type on both inputs. | +| `ORDER BY`, Sort/TopN key | Not supported | CAST the required subpath before ordering. | +| Window partition/order key | Not supported | A whole VARIANT value cannot be a window key. | +| `MIN(variant)`, `MAX(variant)` | Not supported | CAST a scalar subpath before aggregation. | + +For comparison, filtering, arithmetic, and ordering, extract the required subpath and CAST it to a concrete type explicitly or implicitly: ```sql -- Explicit CAST @@ -403,22 +575,6 @@ SELECT * FROM tbl WHERE v['bool']; SELECT * FROM tbl WHERE v['str'] MATCH 'Doris'; ``` -- VARIANT itself cannot be used directly in ORDER BY, GROUP BY, as a JOIN KEY, or as an aggregate argument; CAST subpaths instead. -- Strings can be implicitly converted to VARIANT. - -| VARIANT | Castable | Coercible | -| --------------- | -------- | --------- | -| `ARRAY` | ✔ | ❌ | -| `BOOLEAN` | ✔ | ✔ | -| `DATE/DATETIME` | ✔ | ✔ | -| `FLOAT` | ✔ | ✔ | -| `IPV4/IPV6` | ✔ | ✔ | -| `DECIMAL` | ✔ | ✔ | -| `MAP` | ❌ | ❌ | -| `TIMESTAMP` | ✔ | ✔ | -| `VARCHAR` | ✔ | ✔ | -| `JSON` | ✔ | ✔ | - ## Wide columns When ingested data contains many distinct JSON keys, the number of subcolumns produced by Subcolumnization can grow rapidly; at scale this may cause metadata bloat, higher write/merge cost, and query slowdowns. To address “wide columns” (too many subcolumns), VARIANT provides two mechanisms: **Sparse columns** and **DOC encoding**. @@ -464,7 +620,7 @@ See the “Configuration” section below for the full property list. - **Wide tables optimization**: For wide tables with a large number of dynamic sub-columns (e.g., more than 2000 columns) generated by the `VARIANT` type, it is highly recommended to enable **Storage Format V3** by specifying `"storage_format" = "V3"` in the table `PROPERTIES`. This decouples column metadata from the Segment Footer, speeding up file opening and reducing memory overhead. - JSON key length ≤ 255. - Cannot be a primary key or sort key. -- Cannot be nested within other types (e.g., `Array`, `Struct`). +- Persisted table schemas cannot nest VARIANT within other types (for example, `ARRAY` or `STRUCT`). Transient expression results can use the supported nested-container operations listed above. - Outside DOC mode, reading the entire VARIANT column scans all subpaths. For very wide columns, direct `SELECT variant_col` is generally not recommended unless DOC mode is enabled. If a column has many subpaths, consider storing the original JSON string in an extra STRING/JSONB column for whole-object searches like `LIKE`: ```sql @@ -559,7 +715,7 @@ SET describe_extend_variant_column = true; DESC variant_tbl; ``` -``` sql +```sql DESCRIBE ${table_name} PARTITION ($partition_name); ``` diff --git a/docs/sql-manual/sql-functions/scalar-functions/variant-functions/element-at.md b/docs/sql-manual/sql-functions/scalar-functions/variant-functions/element-at.md index 4a9b8594781f5..3c2e688f5d888 100644 --- a/docs/sql-manual/sql-functions/scalar-functions/variant-functions/element-at.md +++ b/docs/sql-manual/sql-functions/scalar-functions/variant-functions/element-at.md @@ -28,7 +28,8 @@ ELEMENT_AT(container, key_or_index) - For `ARRAY`: An integer, with indexing starting from **1**. - For `MAP`: The key type (`K`) of the `MAP`, which can be any supported primitive type. - For `STRUCT`: A constant integer field position (starting from **1**) or a constant string field name (matched **case-insensitively**). - - For `VARIANT`: A string type. + - For `VARIANT` object access: A string key. + - For a VARIANT array in Doris 4.2 and later: An integer index; non-negative indexes are 0-based and negative indexes count backward from the end. ## Return Value @@ -41,9 +42,16 @@ ELEMENT_AT(container, key_or_index) ## Notes -1. **Array indexes start from 1**, not 0. -2. Negative indexes are supported: `-1` represents the last element, `-2` the second-to-last, and so on. -3. The `ELEMENT_AT(container, key_or_index)` function behaves the same as `container[key_or_index]` (see examples for details). +1. **ARRAY indexes start from 1**, not 0. +2. In Doris 4.2 and later, non-negative indexes into a VARIANT array start from `0`; `0` is the first element and `-1` is the last. +3. Negative indexes are supported for ARRAY and VARIANT array access: `-1` represents the last element, `-2` the second-to-last, and so on. +4. The `ELEMENT_AT(container, key_or_index)` function behaves the same as `container[key_or_index]` (see examples for details). + +```sql +SELECT ELEMENT_AT(parse_to_variant('[10, 20, 30]'), 0); -- 10 +SELECT ELEMENT_AT(parse_to_variant('[10, 20, 30]'), 1); -- 20 +SELECT ELEMENT_AT(parse_to_variant('[10, 20, 30]'), -1); -- 30 +``` ## Examples diff --git a/docs/sql-manual/sql-functions/scalar-functions/variant-functions/parse-to-variant-error-to-null.md b/docs/sql-manual/sql-functions/scalar-functions/variant-functions/parse-to-variant-error-to-null.md new file mode 100644 index 0000000000000..2ec019310e406 --- /dev/null +++ b/docs/sql-manual/sql-functions/scalar-functions/variant-functions/parse-to-variant-error-to-null.md @@ -0,0 +1,90 @@ +--- +{ + "title": "PARSE_TO_VARIANT_ERROR_TO_NULL (Return NULL on Error)", + "language": "en", + "description": "Parses one complete JSON value into VARIANT and returns SQL NULL when parsing or validation fails." +} +--- + +## Description + +`PARSE_TO_VARIANT_ERROR_TO_NULL` parses one complete JSON value into `VARIANT`. The `ERROR_TO_NULL` suffix means that a parsing or validation error returns SQL `NULL` instead of failing the query. This function is available in Doris 4.2 and later. + +## Syntax + +```sql +PARSE_TO_VARIANT_ERROR_TO_NULL() +``` + +## Parameters + +| Parameter | Description | +| --- | --- | +| `` | A `CHAR`, `VARCHAR`, or `STRING` expression containing one complete JSON value, or a `JSON`/`JSONB` expression. JSON/JSONB input is converted to JSON text and then parsed as VARIANT. | + +## Return Value + +Returns a nullable `VARIANT` value. + +- Valid input returns the parsed VARIANT value. +- Invalid JSON or another parsing or validation error returns SQL `NULL`. +- SQL `NULL` input returns SQL `NULL`. +- The valid JSON literal `null` returns Variant/JSON `null`, not SQL `NULL`. + +## Example + +Keep valid values and convert invalid JSON to SQL `NULL`: + +```sql +SELECT CAST( + PARSE_TO_VARIANT_ERROR_TO_NULL('{"id": 1}') + AS STRING + ) AS valid_value, + PARSE_TO_VARIANT_ERROR_TO_NULL('{"id":') IS NULL AS invalid_is_null, + PARSE_TO_VARIANT_ERROR_TO_NULL(NULL) IS NULL AS input_is_null; +``` + +```text ++-------------+-----------------+---------------+ +| valid_value | invalid_is_null | input_is_null | ++-------------+-----------------+---------------+ +| {"id":1} | 1 | 1 | ++-------------+-----------------+---------------+ +``` + +Parse JSON/JSONB input: + +```sql +SELECT CAST( + PARSE_TO_VARIANT_ERROR_TO_NULL(CAST('[10, 20, 30]' AS JSON)) + AS STRING + ) AS value; +``` + +```text ++------------+ +| value | ++------------+ +| [10,20,30] | ++------------+ +``` + +JSON `null` and SQL `NULL` remain distinct: + +```sql +SELECT PARSE_TO_VARIANT_ERROR_TO_NULL('null') IS NULL AS json_null_is_sql_null, + PARSE_TO_VARIANT_ERROR_TO_NULL('{') IS NULL AS error_is_sql_null; +``` + +```text ++-----------------------+-------------------+ +| json_null_is_sql_null | error_is_sql_null | ++-----------------------+-------------------+ +| 0 | 1 | ++-----------------------+-------------------+ +``` + +## Usage Notes + +- Use [PARSE_TO_VARIANT](./parse-to-variant) when invalid input should fail the query and expose the data-quality error. +- This function converts only parsing and validation failures to SQL `NULL`; it does not change the meaning of a valid JSON `null` value. diff --git a/docs/sql-manual/sql-functions/scalar-functions/variant-functions/parse-to-variant.md b/docs/sql-manual/sql-functions/scalar-functions/variant-functions/parse-to-variant.md new file mode 100644 index 0000000000000..3b2ad53c343f2 --- /dev/null +++ b/docs/sql-manual/sql-functions/scalar-functions/variant-functions/parse-to-variant.md @@ -0,0 +1,113 @@ +--- +{ + "title": "PARSE_TO_VARIANT", + "language": "en", + "description": "Parses one complete JSON value from text or a JSON/JSONB expression into a typed VARIANT value." +} +--- + +## Description + +`PARSE_TO_VARIANT` parses one complete JSON value into `VARIANT`. It accepts JSON objects, arrays, strings, numbers, booleans, and the JSON literal `null`. This function is available in Doris 4.2 and later. + +## Syntax + +```sql +PARSE_TO_VARIANT() +``` + +## Parameters + +| Parameter | Description | +| --- | --- | +| `` | A `CHAR`, `VARCHAR`, or `STRING` expression containing one complete JSON value, or a `JSON`/`JSONB` expression. JSON/JSONB input is converted to JSON text and then parsed as VARIANT. | + +## Return Value + +Returns a `VARIANT` value. + +- SQL `NULL` input returns SQL `NULL`. +- The JSON literal `null` returns Variant/JSON `null`, which is different from SQL `NULL`. +- Invalid JSON, duplicate object keys rejected by the current validation settings, unsupported depth, or another validation error causes the query to fail. + +## Example + +Parse JSON text: + +```sql +SELECT CAST( + PARSE_TO_VARIANT('{"id": 42, "tags": ["doris", "sql"]}') + AS STRING + ) AS value; +``` + +```text ++----------------------------------------+ +| value | ++----------------------------------------+ +| {"id":42,"tags":["doris","sql"]} | ++----------------------------------------+ +``` + +Parse a JSON/JSONB expression: + +```sql +SELECT CAST( + PARSE_TO_VARIANT(CAST('{"id": 42}' AS JSON)) + AS STRING + ) AS value; +``` + +```text ++-----------+ +| value | ++-----------+ +| {"id":42} | ++-----------+ +``` + +Extract a value and CAST it to a concrete SQL type: + +```sql +SELECT CAST( + PARSE_TO_VARIANT('{"user": {"id": 42}}')['user']['id'] + AS BIGINT + ) AS user_id; +``` + +```text ++---------+ +| user_id | ++---------+ +| 42 | ++---------+ +``` + +SQL `NULL` remains SQL `NULL`: + +```sql +SELECT PARSE_TO_VARIANT(NULL) IS NULL AS is_sql_null; +``` + +```text ++-------------+ +| is_sql_null | ++-------------+ +| 1 | ++-------------+ +``` + +Invalid JSON returns an error: + +```sql +SELECT PARSE_TO_VARIANT('{"id":'); +``` + +```text +ERROR: Parse json document failed +``` + +## Usage Notes + +- Use [PARSE_TO_VARIANT_ERROR_TO_NULL](./parse-to-variant-error-to-null) when invalid input should become SQL `NULL` instead of failing the query. +- `PARSE_TO_VARIANT` always expresses JSON-parsing intent. By contrast, the behavior of `CAST(string AS VARIANT)` depends on `enable_variant_string_cast_parse`; see the [VARIANT CAST rules](../../../basic-element/sql-data-types/semi-structured/VARIANT#cast-rules). diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/sql-manual/basic-element/sql-data-types/semi-structured/VARIANT.md b/i18n/zh-CN/docusaurus-plugin-content-docs/current/sql-manual/basic-element/sql-data-types/semi-structured/VARIANT.md index 344db4f2d6bb6..3ffd9f14efef0 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/current/sql-manual/basic-element/sql-data-types/semi-structured/VARIANT.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/sql-manual/basic-element/sql-data-types/semi-structured/VARIANT.md @@ -67,6 +67,162 @@ FROM ${table_name} WHERE ARRAY_CONTAINS(CAST(v['tags'] AS ARRAY), 'Doris'); ``` +## 创建和访问值 + +:::info 版本说明 +本节所述行为适用于 Doris 4.2 及后续版本。 +::: + +VARIANT 值可以从 JSON 文本、JSON/JSONB 值或带确定类型的 SQL 表达式创建: + +- 如果要将字符串或 JSON/JSONB 表达式解析为结构化 VARIANT 值,请使用 [PARSE_TO_VARIANT](../../../sql-functions/scalar-functions/variant-functions/parse-to-variant)。 +- 如果要将受支持的 SQL 值转换为 VARIANT,请使用 `CAST(expression AS VARIANT)`。字符串 CAST 是否解析 JSON 由 `enable_variant_string_cast_parse` 控制,详见 [CAST 规则](#cast-规则)。 + +### 解析 JSON 文本 + +```sql +SELECT PARSE_TO_VARIANT('{"user": {"id": 42}, "active": true}'); +SELECT PARSE_TO_VARIANT('[10, 20, 30]'); +SELECT PARSE_TO_VARIANT(CAST('{"user": {"id": 42}}' AS JSON)); +``` + +如果非法 JSON 应该返回 SQL `NULL` 而不是使查询失败,请使用 [PARSE_TO_VARIANT_ERROR_TO_NULL](../../../sql-functions/scalar-functions/variant-functions/parse-to-variant-error-to-null)。 + +### 访问对象和数组 + +对象字段可以使用字符串 key 访问。在 Doris 4.2 及后续版本中,VARIANT 数组的非负索引从 0 开始,并支持从数组末尾倒数的负数索引。提取出的值仍是 `VARIANT`,如需按确定类型比较、计算或聚合,请先 CAST。 + +```sql +SELECT CAST(PARSE_TO_VARIANT('{"user": {"id": 42}}')['user']['id'] AS BIGINT); +SELECT ELEMENT_AT(PARSE_TO_VARIANT('[10, 20, 30]'), 0); -- 10 +SELECT ELEMENT_AT(PARSE_TO_VARIANT('[10, 20, 30]'), -1); -- 30 +``` + +对象和数组访问的详细说明请参见 [ELEMENT_AT](../../../sql-functions/scalar-functions/variant-functions/element-at)。 + +## CAST 规则 + +VARIANT 的 CAST 包括两个方向:把受支持的 SQL 值转换为 VARIANT,以及把 VARIANT 中兼容的值转换为具体 SQL 类型。 + +### 其他类型 CAST 为 VARIANT + +| 源类型 | 行为 | +| --- | --- | +| `CHAR`、`VARCHAR`、`STRING` | 查询 session 默认按 JSON 解析输入。将 `enable_variant_string_cast_parse` 设为 `false` 后,输入会保留为 VARIANT 字符串。 | +| `JSON` / `JSONB` | 将结构化 JSON 值直接转换为 VARIANT。 | +| Boolean、整数、浮点数和 Decimal | 保留带类型的标量值,但需满足下文的 Decimal 限制。 | +| `DATE`、`DATETIME`、`TIMESTAMPTZ`、`IPV4`、`IPV6` | 保留对应的逻辑类型和值。 | +| `ARRAY` | 递归转换每个受支持的元素,并保留 SQL NULL 元素。 | +| `MAP` | 不支持。 | + +查询 session 中,`enable_variant_string_cast_parse` 默认为 `true`。如果 SQL 文本需要明确表达“始终解析 JSON”的意图,建议直接使用 `PARSE_TO_VARIANT`,避免依赖 session 设置。 + +```sql +-- 默认行为:把字符串按 JSON 解析。 +SELECT CAST('{"id": 1}' AS VARIANT) AS parsed_object; +-- {"id":1} + +-- 将相同输入保留为 VARIANT 字符串根值。 +SET enable_variant_string_cast_parse = false; +SELECT CAST(CAST('{"id": 1}' AS VARIANT) AS STRING) AS string_value, + VARIANT_TYPE(CAST('{"id": 1}' AS VARIANT)) AS root_type; +-- string_value:{"id": 1};root_type:string + +-- JSON/JSONB 输入仍保留结构。 +SET enable_variant_string_cast_parse = true; +SELECT CAST(CAST('{"id": 1}' AS JSON) AS VARIANT) AS parsed_object; +-- {"id":1} +``` + +开启字符串解析时,非法 JSON 会使 CAST 失败。如果希望将非法输入转换为 SQL `NULL`,请使用 `PARSE_TO_VARIANT_ERROR_TO_NULL`。 + +### VARIANT CAST 为其他类型 + +VARIANT 可以 CAST 为兼容的标量、JSON/JSONB 或数组类型: + +| 目标类型 | 行为 | +| --- | --- | +| Boolean、整数、浮点数、Decimal、日期时间和 IP 类型 | 转换兼容的标量根值;对象形状不兼容、文本非法或数值越界时,按照相应 CAST 模式报错或返回 SQL `NULL`。 | +| `STRING` | 标量根值返回对应文本,对象和数组返回 JSON 文本。Variant/JSON `null` 返回字符串 `null`,外层 SQL `NULL` 仍是 SQL `NULL`。 | +| `JSON` / `JSONB` | 将可表示的 VARIANT 值转换为结构化 JSON/JSONB。 | +| `ARRAY` | 将 VARIANT 数组逐元素转换为 `T`;不兼容元素遵循目标类型的 CAST 规则。 | +| `MAP` | 不支持。 | + +```sql +SELECT CAST(PARSE_TO_VARIANT('42') AS BIGINT) AS id; +-- 42 + +SELECT CAST(PARSE_TO_VARIANT('[1, null, 3]') AS ARRAY) AS values; +-- [1, NULL, 3] + +SELECT CAST(PARSE_TO_VARIANT('{"id": 1}') AS JSON) AS json_value; +-- {"id":1} +``` + +### Decimal 与日期时间转换限制 + +| Doris 输入类型 | VARIANT 支持情况 | +| --- | --- | +| 旧版 `DECIMALV2` | 精确保留 precision 不超过 27、scale 不超过 9 的值。 | +| `DECIMAL(p, s)` | 精确保留 `1 <= p <= 38` 且 `0 <= s <= p` 的值;不支持需要超过 38 位 precision 的值。 | +| `DATE` | 保留为不含时间和时区的日历日期。 | +| 旧版 `DATETIME` | 保留到秒,不进行时区调整。 | +| `DATETIME(p)` | 支持 `0 <= p <= 6`,不进行时区调整。 | +| `TIMESTAMPTZ(p)` | 支持 `0 <= p <= 6`,保留带时区调整的 timestamp 语义。 | +| `TIME` | 不支持作为 VARIANT 输入。 | + +源值还必须满足对应 Doris 类型本身的合法性要求。precision 超限、日期非法或值不兼容时会报错,不会自动修复。 + +## 相等性与 Hash 语义 + +在 Doris 4.2 及后续版本中,分组、去重和集合运算会按逻辑值判断相等性,而不是按来源 SQL 类型或物理表示: + +- 等价的整数数值表示相等。 +- Decimal 尾随零不影响值,因此 `1.20` 与 `1.2` 相等。 +- `+0`、`-0` 与整数零相等。 +- 对象 key 的顺序不影响相等性,但数组元素顺序会影响相等性。 +- Variant/JSON `null` 与 SQL `NULL` 不同。 + +Hash 类算子使用同一套 canonical 逻辑表示计算 key。因此,只要两个值按上述规则相等,无论来源是解析后的 JSON 还是带类型的 CAST,都会得到相同的内部 Hash Key。该 Hash 只用于 Doris 内部执行,不是稳定的用户侧校验值。 + +这些规则适用于 `GROUP BY`、`DISTINCT`、`COUNT(DISTINCT ...)`、`INTERSECT`、`EXCEPT` 和 `UNION DISTINCT` 等已支持的操作,但不会开放根 VARIANT 比较谓词:直接执行 `VARIANT = VARIANT` 或排序比较仍不支持。 + +```sql +-- 1 和 1.0 只有一个 distinct logical value。 +SELECT COUNT(DISTINCT value) AS distinct_count +FROM ( + SELECT PARSE_TO_VARIANT('1') AS value + UNION ALL + SELECT PARSE_TO_VARIANT('1.0') AS value +) AS numeric_values; +-- distinct_count: 1 + +-- 对象 key 顺序被忽略;数组顺序会保留。 +SELECT COUNT(DISTINCT value) AS distinct_count +FROM ( + SELECT PARSE_TO_VARIANT('{"a": 1, "b": 2}') AS value + UNION ALL + SELECT PARSE_TO_VARIANT('{"b": 2, "a": 1}') AS value +) AS object_values; +-- distinct_count: 1 + +SELECT COUNT(DISTINCT value) AS distinct_count +FROM ( + SELECT PARSE_TO_VARIANT('[1, 2]') AS value + UNION ALL + SELECT PARSE_TO_VARIANT('[2, 1]') AS value +) AS array_values; +-- distinct_count: 2 +``` + +## NULL 语义 + +SQL `NULL` 与 Variant/JSON `null` 是不同的值: + +- SQL `NULL` 表示 SQL 值缺失,并遵循普通 SQL NULL 传播规则。 +- Variant/JSON `null` 是一个 VARIANT 值,例如 `PARSE_TO_VARIANT('null')` 的返回值。 +- `PARSE_TO_VARIANT_ERROR_TO_NULL` 遇到非法输入时返回 SQL `NULL`,这与成功解析 JSON 字面量 `null` 不同。 + ## 基本类型 VARIANT 自动推断的子列基础类型包括: @@ -387,10 +543,26 @@ SELECT v FROM variant_tbl WHERE k = 2; 排序在每一层都会生效——顶层 key 输出为 `a`、`b`、`c`,嵌套 object 内 key 输出为 `x`、`y`。 -## 支持的运算与 CAST 规则 +## 支持的运算 -- VARIANT 本身不支持与其他类型直接比较/运算,两个 VARIANT 之间也不支持直接比较。 -- 如需比较、过滤、聚合、排序,请对子列显式或隐式 CAST 到确定类型。 +在 Doris 4.2 及后续版本中,整个 VARIANT 值支持基于 Hash 的分组和去重,但不支持比较、Join Key 或排序语义。 + +| 对整个 VARIANT 值执行的操作 | 支持情况 | 说明 | +| --- | --- | --- | +| `GROUP BY` | 支持 | 使用上文所述的逻辑相等与 canonical Hash 规则。 | +| `DISTINCT`、`COUNT(DISTINCT ...)` | 支持 | 逻辑等价的值会被去重。 | +| `INTERSECT`、`EXCEPT`、`UNION DISTINCT` | 支持 | 使用相同的逻辑相等与 Hash 语义。 | +| `COUNT(*)`、`COUNT(variant)` | 支持 | `COUNT(variant)` 按普通 SQL 规则排除外层 SQL `NULL`。 | +| `IF`、`CASE`、`IFNULL`、`COALESCE` | 支持 | 条件表达式可以返回和消费 VARIANT 值。 | +| 临时 `ARRAY`、`MAP` 或 `STRUCT` 表达式中包含 VARIANT | 支持 | 这不表示持久化表结构可以使用这些嵌套类型。 | +| `EXPLODE_VARIANT_ARRAY`、对 `ARRAY` 使用 `EXPLODE`/`EXPLODE_OUTER` | 支持 | 输出 VARIANT 元素,并保留 SQL `NULL` 与 Variant/JSON `null` 的区别。 | +| `=`、`!=`、`<=>`、`<`、`<=`、`>`、`>=` | 不支持 | 请在两侧提取可比较的子路径,并 CAST 为具体类型。 | +| Join Key | 不支持 | 请把两侧所需子路径 CAST 为相同的具体类型。 | +| `ORDER BY`、Sort/TopN Key | 不支持 | 排序前请先 CAST 所需子路径。 | +| 窗口分区键或排序键 | 不支持 | 整个 VARIANT 值不能作为窗口 Key。 | +| `MIN(variant)`、`MAX(variant)` | 不支持 | 聚合前请先 CAST 标量子路径。 | + +如需比较、过滤、计算或排序,请提取所需子路径,再显式或隐式 CAST 为具体类型: ```sql -- 显式 CAST @@ -403,22 +575,6 @@ SELECT * FROM tbl WHERE v['bool']; SELECT * FROM tbl WHERE v['str'] MATCH 'Doris'; ``` -- VARIANT 本身不可直接用于 ORDER BY、GROUP BY、JOIN KEY 或聚合参数;对子列 CAST 后可正常使用。 -- 字符串类型可隐式转换为 VARIANT。 - -| VARIANT | Castable | Coercible | -| --------------- | -------- | --------- | -| `ARRAY` | ✔ | ❌ | -| `BOOLEAN` | ✔ | ✔ | -| `DATE/DATETIME` | ✔ | ✔ | -| `FLOAT` | ✔ | ✔ | -| `IPV4/IPV6` | ✔ | ✔ | -| `DECIMAL` | ✔ | ✔ | -| `MAP` | ❌ | ❌ | -| `TIMESTAMP` | ✔ | ✔ | -| `VARCHAR` | ✔ | ✔ | -| `JSON` | ✔ | ✔ | - ## 宽列 当导入数据包含大量不同的 JSON key 时,通过子列列式提取(Subcolumnization)生成的子列会迅速增多;当规模达到一定程度,可能出现元数据膨胀、写入/合并开销增大、查询性能下降等问题。为应对“宽列”(子列过多),VARIANT 提供两种机制:**稀疏列** 与 **DOC 编码**。 @@ -464,7 +620,7 @@ SELECT * FROM tbl WHERE v['str'] MATCH 'Doris'; - **大宽表优化**:对于会通过子列列式提取(Subcolumnization)生成大量独立子列的宽表场景(例如超过 2000 列),强烈建议开启 **V3 存储格式**。通过在建表 `PROPERTIES` 中指定 `"storage_format" = "V3"`,可以将列元数据与 Segment Footer 解耦,加快文件打开速度并降低内存占用。 - JSON key 长度 ≤ 255。 - 不支持作为主键或排序键。 -- 不支持与其他类型嵌套(如 `Array`、`Struct`)。 +- 持久化表结构不能把 VARIANT 嵌套在其他类型中(如 `ARRAY`、`STRUCT`);临时表达式结果可以使用上表列出的嵌套容器能力。 - 在未启用 DOC mode 时,读取整个 VARIANT 列会扫描所有子字段。对于超宽列,一般不建议直接 `SELECT variant_col`;如果整列读取是主要查询模式,建议优先使用 DOC mode。若列包含大量子字段,也可额外存储原始 JSON 的 STRING/JSONB 列,以优化如 `LIKE` 等整体匹配: ```sql diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/sql-manual/sql-functions/scalar-functions/variant-functions/element-at.md b/i18n/zh-CN/docusaurus-plugin-content-docs/current/sql-manual/sql-functions/scalar-functions/variant-functions/element-at.md index f9bc791d6caf5..2bf4a09c67412 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/current/sql-manual/sql-functions/scalar-functions/variant-functions/element-at.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/sql-manual/sql-functions/scalar-functions/variant-functions/element-at.md @@ -2,7 +2,7 @@ { "title": "ELEMENT_AT", "language": "zh-CN", - "description": "ELEMENTAT 函数用于从数组或 map 中按指定的索引或键提取对应的元素值。" + "description": "ELEMENT_AT 函数按索引、键或字段名从 ARRAY、MAP、STRUCT 或 VARIANT 中提取元素,并说明各类型的索引起点、负索引语义与越界行为。" } --- @@ -28,7 +28,8 @@ ELEMENT_AT(container, key_or_index) - 对于 `ARRAY`:为整数类型,索引从 **1** 开始; - 对于 `MAP`:为 `MAP` 中的键类型(`K`),可为任意支持的基础类型。 - 对于 `STRUCT`:为常量整数(字段位置,从 **1** 开始)或常量字符串(字段名,按**大小写不敏感**匹配)。 - - 对于 `VARIANT`: 为字符串类型 + - 对于 `VARIANT` 对象访问:为字符串类型的 key; + - 对于 Doris 4.2 及后续版本中的 VARIANT 数组:为整数索引,非负索引从 0 开始,负数索引从数组末尾倒数。 ## 返回值 @@ -41,9 +42,16 @@ ELEMENT_AT(container, key_or_index) ## 使用说明 -1. **数组索引从 1 开始**,不是从 0 开始; -2. 支持负数索引,`-1` 表示最后一个元素,`-2` 表示倒数第二个,以此类推; -3. `ELEMENT_AT(container, key_or_index)` 函数的功能与 `container[key_or_index]` 作用一致(详细见示例)。 +1. **ARRAY 数组索引从 1 开始**,不是从 0 开始; +2. 在 Doris 4.2 及后续版本中,VARIANT 数组的非负索引从 `0` 开始,`0` 表示第一个元素,`-1` 表示最后一个元素; +3. ARRAY 和 VARIANT 数组都支持负数索引,`-1` 表示最后一个元素,`-2` 表示倒数第二个,以此类推; +4. `ELEMENT_AT(container, key_or_index)` 函数的功能与 `container[key_or_index]` 作用一致(详细见示例)。 + +```sql +SELECT ELEMENT_AT(parse_to_variant('[10, 20, 30]'), 0); -- 10 +SELECT ELEMENT_AT(parse_to_variant('[10, 20, 30]'), 1); -- 20 +SELECT ELEMENT_AT(parse_to_variant('[10, 20, 30]'), -1); -- 30 +``` ## 示例 @@ -129,5 +137,3 @@ ELEMENT_AT(container, key_or_index) | | +----------------------------------------+ ``` - - diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/sql-manual/sql-functions/scalar-functions/variant-functions/parse-to-variant-error-to-null.md b/i18n/zh-CN/docusaurus-plugin-content-docs/current/sql-manual/sql-functions/scalar-functions/variant-functions/parse-to-variant-error-to-null.md new file mode 100644 index 0000000000000..3ce8e9bdea81d --- /dev/null +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/sql-manual/sql-functions/scalar-functions/variant-functions/parse-to-variant-error-to-null.md @@ -0,0 +1,90 @@ +--- +{ + "title": "PARSE_TO_VARIANT_ERROR_TO_NULL(解析失败返回 NULL)", + "language": "zh-CN", + "description": "PARSE_TO_VARIANT_ERROR_TO_NULL 将完整 JSON 值解析为 VARIANT,并在解析或校验失败时返回 SQL NULL,而不是使当前查询失败。" +} +--- + +## 功能 + +`PARSE_TO_VARIANT_ERROR_TO_NULL` 将一个完整 JSON 值解析为 `VARIANT`。函数名中的 `ERROR_TO_NULL` 表示:发生解析或校验错误时返回 SQL `NULL`,而不是使查询失败。该函数自 Doris 4.2 起支持。 + +## 语法 + +```sql +PARSE_TO_VARIANT_ERROR_TO_NULL() +``` + +## 参数 + +| 参数 | 说明 | +| --- | --- | +| `` | 包含一个完整 JSON 值的 `CHAR`、`VARCHAR` 或 `STRING` 表达式,也可以是 `JSON`/`JSONB` 表达式。JSON/JSONB 输入会先转换为 JSON 文本,再解析为 VARIANT。 | + +## 返回值 + +返回可为 NULL 的 `VARIANT` 值。 + +- 合法输入返回解析后的 VARIANT 值。 +- 非法 JSON 或其他解析、校验错误返回 SQL `NULL`。 +- 输入为 SQL `NULL` 时返回 SQL `NULL`。 +- 合法的 JSON 字面量 `null` 返回 Variant/JSON `null`,不是 SQL `NULL`。 + +## 示例 + +保留合法值,并把非法 JSON 转换为 SQL `NULL`: + +```sql +SELECT CAST( + PARSE_TO_VARIANT_ERROR_TO_NULL('{"id": 1}') + AS STRING + ) AS valid_value, + PARSE_TO_VARIANT_ERROR_TO_NULL('{"id":') IS NULL AS invalid_is_null, + PARSE_TO_VARIANT_ERROR_TO_NULL(NULL) IS NULL AS input_is_null; +``` + +```text ++-------------+-----------------+---------------+ +| valid_value | invalid_is_null | input_is_null | ++-------------+-----------------+---------------+ +| {"id":1} | 1 | 1 | ++-------------+-----------------+---------------+ +``` + +解析 JSON/JSONB 输入: + +```sql +SELECT CAST( + PARSE_TO_VARIANT_ERROR_TO_NULL(CAST('[10, 20, 30]' AS JSON)) + AS STRING + ) AS value; +``` + +```text ++------------+ +| value | ++------------+ +| [10,20,30] | ++------------+ +``` + +JSON `null` 与 SQL `NULL` 仍然不同: + +```sql +SELECT PARSE_TO_VARIANT_ERROR_TO_NULL('null') IS NULL AS json_null_is_sql_null, + PARSE_TO_VARIANT_ERROR_TO_NULL('{') IS NULL AS error_is_sql_null; +``` + +```text ++-----------------------+-------------------+ +| json_null_is_sql_null | error_is_sql_null | ++-----------------------+-------------------+ +| 0 | 1 | ++-----------------------+-------------------+ +``` + +## 使用说明 + +- 如果非法输入应该使查询失败并暴露数据质量问题,请使用 [PARSE_TO_VARIANT](./parse-to-variant)。 +- 本函数只会把解析和校验错误转换为 SQL `NULL`,不会改变合法 JSON `null` 的含义。 diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/sql-manual/sql-functions/scalar-functions/variant-functions/parse-to-variant.md b/i18n/zh-CN/docusaurus-plugin-content-docs/current/sql-manual/sql-functions/scalar-functions/variant-functions/parse-to-variant.md new file mode 100644 index 0000000000000..19509d90418b2 --- /dev/null +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/sql-manual/sql-functions/scalar-functions/variant-functions/parse-to-variant.md @@ -0,0 +1,113 @@ +--- +{ + "title": "PARSE_TO_VARIANT", + "language": "zh-CN", + "description": "PARSE_TO_VARIANT 将 JSON 文本或 JSON/JSONB 表达式中的完整 JSON 值解析为带类型信息的 VARIANT,并说明输入、返回值、错误行为与示例。" +} +--- + +## 功能 + +`PARSE_TO_VARIANT` 将一个完整 JSON 值解析为 `VARIANT`,支持 JSON 对象、数组、字符串、数字、布尔值和 JSON 字面量 `null`。该函数自 Doris 4.2 起支持。 + +## 语法 + +```sql +PARSE_TO_VARIANT() +``` + +## 参数 + +| 参数 | 说明 | +| --- | --- | +| `` | 包含一个完整 JSON 值的 `CHAR`、`VARCHAR` 或 `STRING` 表达式,也可以是 `JSON`/`JSONB` 表达式。JSON/JSONB 输入会先转换为 JSON 文本,再解析为 VARIANT。 | + +## 返回值 + +返回 `VARIANT` 值。 + +- 输入为 SQL `NULL` 时返回 SQL `NULL`。 +- 输入为 JSON 字面量 `null` 时返回 Variant/JSON `null`,它与 SQL `NULL` 不同。 +- JSON 非法、对象 key 重复且当前校验设置不允许、嵌套深度超限或发生其他校验错误时,查询失败。 + +## 示例 + +解析 JSON 文本: + +```sql +SELECT CAST( + PARSE_TO_VARIANT('{"id": 42, "tags": ["doris", "sql"]}') + AS STRING + ) AS value; +``` + +```text ++----------------------------------------+ +| value | ++----------------------------------------+ +| {"id":42,"tags":["doris","sql"]} | ++----------------------------------------+ +``` + +解析 JSON/JSONB 表达式: + +```sql +SELECT CAST( + PARSE_TO_VARIANT(CAST('{"id": 42}' AS JSON)) + AS STRING + ) AS value; +``` + +```text ++-----------+ +| value | ++-----------+ +| {"id":42} | ++-----------+ +``` + +提取值并 CAST 为具体 SQL 类型: + +```sql +SELECT CAST( + PARSE_TO_VARIANT('{"user": {"id": 42}}')['user']['id'] + AS BIGINT + ) AS user_id; +``` + +```text ++---------+ +| user_id | ++---------+ +| 42 | ++---------+ +``` + +SQL `NULL` 仍返回 SQL `NULL`: + +```sql +SELECT PARSE_TO_VARIANT(NULL) IS NULL AS is_sql_null; +``` + +```text ++-------------+ +| is_sql_null | ++-------------+ +| 1 | ++-------------+ +``` + +非法 JSON 会报错: + +```sql +SELECT PARSE_TO_VARIANT('{"id":'); +``` + +```text +ERROR: Parse json document failed +``` + +## 使用说明 + +- 如果希望把非法输入转换为 SQL `NULL`,请使用 [PARSE_TO_VARIANT_ERROR_TO_NULL](./parse-to-variant-error-to-null)。 +- `PARSE_TO_VARIANT` 始终明确表示“解析 JSON”。相比之下,`CAST(string AS VARIANT)` 的行为取决于 `enable_variant_string_cast_parse`,详见 [VARIANT CAST 规则](../../../basic-element/sql-data-types/semi-structured/VARIANT#cast-规则)。 diff --git a/sidebars.ts b/sidebars.ts index 0a53243f2dd9a..0365d3a578b60 100644 --- a/sidebars.ts +++ b/sidebars.ts @@ -1867,6 +1867,8 @@ const sidebars: SidebarsConfig = { label: 'Variant Functions', items: [ 'sql-manual/sql-functions/scalar-functions/variant-functions/element-at', + 'sql-manual/sql-functions/scalar-functions/variant-functions/parse-to-variant', + 'sql-manual/sql-functions/scalar-functions/variant-functions/parse-to-variant-error-to-null', 'sql-manual/sql-functions/scalar-functions/variant-functions/variant-type', ], },