github.com/matrixorigin/matrixone@v0.7.0/pkg/sql/colexec/table_function/README.md (about)

     1  # **UNNEST**
     2  
     3  ## **函数说明**
     4  
     5  `UNNEST`是一个表函数,出现在 SQL 的 from 子句中,用于将 json[object|array]类型的数据展开为多行,每行包含json中的一个元素.
     6  
     7  ## **语法结构**
     8  
     9  ```
    10  > UNNEST(src[, path[, outer]])
    11  ```
    12  
    13  ## **相关参数**
    14  
    15  | 参数 | 说明                                       | 类型                                               |
    16  |----------|------------------------------------------|--------------------------------------------------|
    17  | src | 必要参数,待展开的数据源                             | 类型可以是 json 列或 json 字符串                               |
    18  | path | 可选参数,指明待展开数据源的具体 json 路径。默认为"$",展开整个 json 数据 | [path 字符串](../../../container/bytejson/README.md) |
    19  | outer | 可选参数,如果数据源展开后结果行为 0,是否加上一个空行作为标记。默认为 false | bool 类型                                           |
    20  
    21  ## **返回表结构**
    22  
    23  | 字段名 | 类型 | 说明                                                |
    24  |-----|---------|---------------------------------------------------|
    25  | col | varchar | 数据源的名称。如果数据源是列,则是列名;如果数据源是 json 字符串,则是"UNNEST_DEFAULT" |
    26  | seq | int32 | 数据源中元素的索引,从 0 开始                                    |
    27  |key    |varchar    | 展开元素的键名,如果父级元素是数组,则为 null                          |
    28  |path | varchar | 展开元素的在数据源中的路径                                     |
    29  |index | int32 | 展开元素在父级元素中的索引,如果数据源是对象,则为 null                     |
    30  |value | varchar | 展开元素的值                                            |
    31  |this | varchar | 展开元素的父级元素值                                        |
    32  
    33  ## **示例**
    34  
    35  ```
    36  > select *
    37  > from unnest('{"a":1,"b":2,"c":3}') as u;
    38  +----------------+------+------+------+-------+-------+--------------------------+
    39  | col            | seq  | key  | path | index | value | this                     |
    40  +----------------+------+------+------+-------+-------+--------------------------+
    41  | UNNEST_DEFAULT |    0 | a    | $.a  |  NULL | 1     | {"a": 1, "b": 2, "c": 3} |
    42  | UNNEST_DEFAULT |    0 | b    | $.b  |  NULL | 2     | {"a": 1, "b": 2, "c": 3} |
    43  | UNNEST_DEFAULT |    0 | c    | $.c  |  NULL | 3     | {"a": 1, "b": 2, "c": 3} |
    44  +----------------+------+------+------+-------+-------+--------------------------+
    45  
    46  > select *
    47  > from unnest('{"a":1,"b":2,"c":3}') as u
    48  > where u.`key` = 'b';
    49  +----------------+------+------+------+-------+-------+--------------------------+
    50  | col            | seq  | key  | path | index | value | this                     |
    51  +----------------+------+------+------+-------+-------+--------------------------+
    52  | UNNEST_DEFAULT |    0 | b    | $.b  |  NULL | 2     | {"a": 1, "b": 2, "c": 3} |
    53  +----------------+------+------+------+-------+-------+--------------------------+
    54  
    55  > select *
    56  > from unnest('{"a":1,"b":2,"c":3}',"$.b") as u;
    57  Empty set (0.01 sec)
    58  
    59  > select *
    60  > from unnest('{"a":1,"b":2,"c":3}',"$.b",true) as u;
    61  +----------------+------+------+------+-------+-------+--------------------------+
    62  | col            | seq  | key  | path | index | value | this                     |
    63  +----------------+------+------+------+-------+-------+--------------------------+
    64  | UNNEST_DEFAULT |    0 | NULL | $.b  |  NULL | NULL  | 2                        |
    65  
    66  > drop table if exists t1;
    67  > create table t1 (a json,b int);
    68  > insert into t1
    69  > values ('{"a":1,"b":[{"c":2,"d":3},false,4],"e":{"f":true,"g":[null,true,1.1]}}',1);
    70  > insert into t1
    71  > values ('[1,true,false,null,"aaa",1.1,{"t":false}]',2);
    72  > select * from unnest(t1.a, "$.b") as u;
    73  +------+------+------+--------+-------+------------------+------------------------------+
    74  | col  | seq  | key  | path   | index | value            | this                         |
    75  +------+------+------+--------+-------+------------------+------------------------------+
    76  | a    |    0 | NULL | $.b[0] |     0 | {"c": 2, "d": 3} | [{"c": 2, "d": 3}, false, 4] |
    77  | a    |    0 | NULL | $.b[1] |     1 | false            | [{"c": 2, "d": 3}, false, 4] |
    78  | a    |    0 | NULL | $.b[2] |     2 | 4                | [{"c": 2, "d": 3}, false, 4] |
    79  +------+------+------+--------+-------+------------------+------------------------------+
    80  
    81  > select * from unnest(t1.a, "$.b[0]") as u;
    82  +------+------+------+----------+-------+-------+------------------+
    83  | col  | seq  | key  | path     | index | value | this             |
    84  +------+------+------+----------+-------+-------+------------------+
    85  | a    |    0 | c    | $.b[0].c |  NULL | 2     | {"c": 2, "d": 3} |
    86  | a    |    0 | d    | $.b[0].d |  NULL | 3     | {"c": 2, "d": 3} |
    87  +------+------+------+----------+-------+-------+------------------+
    88  
    89  > select distinct(f.seq) from unnest(t1.a, "$") as f;
    90  +-------+
    91  | f.seq |
    92  +-------+
    93  |     0 |
    94  |     1 |
    95  +-------+
    96  ```
    97  
    98  ## **注意事项**
    99  
   100  * key,index 和 value 全为 null 则代表当前行是 outer 为 true 时默认添加的空行
   101  
   102  ## **执行流程**
   103  
   104  1. 数据源是 json 列
   105     `...unnest -> project(jsonCol) -> tableScan`
   106  2. 数据源是 json 字符串
   107     `...unnest -> project(default) -> valueScan(parse jsonStr)`
   108  
   109  ## **实现细节**
   110  
   111  ### 数据源为 json 字符串
   112  
   113  1. 构建 plan 时将存储在`tree.Unnest`中的参数序列化后存储到`unnestNode.TableDef.TableFunctionParam`中
   114  2. 在`unnestNode`中添加`valueScan`节点
   115  3. 给`valueScan.TableDef.TableFunctionParam`赋值为`tree.Unnest`中存储的 json 字符串转化的字节切片
   116  4. 在编译阶段首先将`valueScan`的`TableDef.TableFunctionParam`存入`scope.Datasource.Bat`
   117  5. 在 scope 中添加`vm.Unnest`指令,并通过`unnestNode.TableDef.TableFunctionParam`构建运行参数
   118  6. 执行阶段通过`bytejson`包解析 json 字节切片,解析 path 字符串,通过 json,path, outer,*filter*参数调用`bytejson.Unnest`函数,返回`UnnestResult`结果集
   119  7. 通过`makeBatch`组装`UnnestResult`结果集为`batch`
   120  
   121  ### 数据源为 json 列
   122  
   123  1. 构建 plan 时将存储在`tree.Unnest`中的参数序列化后存储到`unnestNode.TableDef.TableFunctionParam`中
   124  2. 在`unnestNode`中添加`tableScan`节点,并根据`tree.Unnest`中的参数初始化`tableScan`的`TableDef`
   125  3. 编译阶段在 scope 中添加`vm.Unnest`指令,并通过`unnestNode.TableDef.TableFunctionParam`构建运行参数
   126  4. 执行阶段通过`bytejson`包解析由`tableScan`传递 bytejson 字节切片,解析 path 字符串,通过 json,path, outer,*filter*参数调用`bytejson.Unnest`
   127     函数,返回`UnnestResult`结果集
   128  5. 通过`makeBatch`组装`UnnestResult`结果集为`batch`
   129  
   130  *filter*参数是根据`tree.Unnest`中的`Attrs`字段构建的 string 切片,其目的是为了在`bytejson.Unnest`函数中过滤不需要的结果集
   131