diff --git a/ast/postgresql.ts b/ast/postgresql.ts index 317b8b28..e66df085 100644 --- a/ast/postgresql.ts +++ b/ast/postgresql.ts @@ -277,7 +277,7 @@ export type create_table_definition = create_definition[]; export type create_definition = create_column_definition | create_index_definition | create_fulltext_spatial_index_definition | create_constraint_definition; -export type column_definition_opt = column_constraint | { auto_increment: 'auto_increment'; } | { unique: 'unique' | 'unique key'; } | { unique: 'key' | 'primary key'; } | { comment: keyword_comment; } | { collate: collate_expr; } | { column_format: column_format; } | { storage: storage } | { reference_definition: reference_definition; } | { check: check_constraint_definition; } | { character_set: collate_expr }; +export type column_definition_opt = column_constraint | { auto_increment: 'auto_increment'; } | { unique: 'unique' | 'unique key'; } | { unique: 'key' | 'primary key'; } | { comment: keyword_comment; } | { collate: collate_expr; } | { column_format: column_format; } | { storage: storage } | { reference_definition: reference_definition; } | { check: check_constraint_definition; } | { character_set: { type: 'CHARACTER SET'; symbol: '=' | null; value: ident_without_kw_type; } }; @@ -314,7 +314,7 @@ export type create_column_definition = { export type column_constraint = { nullable: literal_null | literal_not_null; default_val: default_expr; }; -export type collate_expr = { type: 'collate'; symbol: '=' | null; value: ident; }; +export type collate_expr = { type: 'collate'; keyword: 'collate'; collate: { symbol: '=' ; name: ident_type; value: ident_type; }} | { type: 'collate'; keyword: 'collate'; collate: { symbol: '=' | null ; name: ident_type; }}; export type column_format = { type: 'column_format'; value: 'fixed' | 'dynamic' | 'default'; }; @@ -391,6 +391,9 @@ export type alter_schema_stmt = AstStatement; export interface alter_table_stmt_node { type: 'alter'; table: table_ref_list; + keyword: 'table'; + if_exists: if_exists; + prefix?: literal_string; expr: alter_action_list; } @@ -398,7 +401,7 @@ export type alter_table_stmt = AstStatement; export type alter_action_list = alter_action[]; -export type alter_action = ALTER_ADD_COLUMN | ALTER_ADD_CONSTRAINT | ALTER_DROP_COLUMN | ALTER_ADD_INDEX_OR_KEY | ALTER_ADD_FULLETXT_SPARITAL_INDEX | ALTER_RENAME | ALTER_ALGORITHM | ALTER_LOCK; +export type alter_action = ALTER_ADD_COLUMN | ALTER_ADD_CONSTRAINT | ALTER_DROP_COLUMN | ALTER_ADD_INDEX_OR_KEY | ALTER_ADD_FULLETXT_SPARITAL_INDEX | ALTER_RENAME | ALTER_ALGORITHM | ALTER_LOCK | ALTER_COLUMN_DATA_TYPE | ALTER_COLUMN_DEFAULT | ALTER_COLUMN_NOT_NULL; @@ -406,6 +409,7 @@ export type ALTER_ADD_COLUMN = { action: 'add'; keyword: KW_COLUMN; resource: 'column'; + if_not_exists: ife; type: 'alter'; } & create_column_definition;; @@ -415,6 +419,7 @@ export type ALTER_DROP_COLUMN = { action: 'drop'; collumn: column_ref; keyword: KW_COLUMN; + if_exists: if_exists; resource: 'column'; type: 'alter'; }; @@ -471,6 +476,35 @@ export type ALTER_LOCK = { +export type ALTER_COLUMN_DATA_TYPE = { + action: 'alter'; + keyword?: KW_COLUMN; + using?: expr; + type: 'alter'; + } & create_column_definition;; + + + + + +export type ALTER_COLUMN_DEFAULT = { + action: 'alter'; + keyword?: KW_COLUMN; + default_val?: { type: 'set default', value: expr }; + type: 'alter'; + } & create_column_definition;; + + + +export type ALTER_COLUMN_NOT_NULL = { + action: 'alter'; + keyword?: KW_COLUMN; + nullable: literal_not_null; + type: 'alter'; + } & create_column_definition;; + + + export type create_index_definition = { index: column; definition: cte_column_definition; @@ -611,7 +645,7 @@ export type create_option_character_set_kw = string; export type create_option_character_set = { keyword: 'character set' | 'charset' | 'collate' | 'default character set' | 'default charset' | 'default collate'; symbol: '='; - value: ident_name; + value: ident_without_kw_type; }; @@ -838,7 +872,7 @@ export type expr_item = binary_column_expr & { array_index: array_index }; export type cast_data_type = data_type & { quoted?: string }; -export type column_list_item = { expr: expr; as: null; } | { type: 'cast'; expr: expr; symbol: '::'; target: cast_data_type; as?: null; arrows?: ('->>' | '->')[]; property?: (literal_string | literal_numeric)[]; } | { expr: column_ref; as: null; } | { type: 'expr'; expr: expr; as?: alias_clause; }; +export type column_list_item = { expr: expr; as: null; } | { type: 'cast'; expr: expr; symbol: '::'; target: cast_data_type; as?: null; jsonb?: jsonb_or_json_op_right[]; } | { expr: column_ref; as: null; } | { type: 'expr'; expr: expr; as?: alias_clause; }; @@ -881,7 +915,7 @@ export type table_ref = table_base | table_join; export type table_join = table_base & {join: join_op; using: ident_name[]; } | table_base & {join: join_op; on?: on_clause; } | { expr: (union_stmt | table_ref_list) & { parentheses: true; }; as?: alias_clause; - join: join_op; + join: join_op | set_op; on?: on_clause; }; @@ -1114,7 +1148,7 @@ export type exists_expr = unary_expr; export type exists_op = 'NOT EXISTS' | KW_EXISTS; -export type comparison_op_right = arithmetic_op_right | in_op_right | between_op_right | is_op_right | like_op_right | jsonb_op_right | regex_op_right; +export type comparison_op_right = arithmetic_op_right | in_op_right | between_op_right | is_op_right | like_op_right | jsonb_or_json_op_right | regex_op_right; export type arithmetic_op_right = { type: 'arithmetic'; tail: any }; @@ -1146,7 +1180,7 @@ export type like_op_right = { op: like_op; right: (literal | comparison_expr) & export type in_op_right = {op: in_op; right: expr_list | var_decl | literal_string; }; -export type jsonb_op_right = { op: string; right: expr }; +export type jsonb_or_json_op_right = { op: string; right: { type: 'expr'; expr: expr_item } }; export type additive_expr = binary_expr; @@ -1175,14 +1209,11 @@ export type column_ref = string_constants_escape | { schema: string; table: string; column: column | '*'; - arrows?: ('->>' | '->')[]; - property?: (literal_string | literal_numeric)[]; + jsonb?: jsonb_or_json_op_right[]; } | { type: 'column_ref'; table: ident; column: column | '*'; - arrows?: ('->>' | '->')[]; - property?: (literal_string | literal_numeric)[]; }; export type column_ref_quoted = unknown; @@ -1307,8 +1338,7 @@ export type cast_double_colon = { as?: alias_clause, symbol: '::' | 'as', target: data_type; - arrows?: ('->>' | '->')[]; - property?: (literal_string | literal_numeric)[]; + jsonb?: jsonb_or_json_op_right[]; }; @@ -1851,6 +1881,8 @@ export type data_type = { + + export type array_type = data_type; diff --git a/pegjs/db2.pegjs b/pegjs/db2.pegjs index ea544fab..7a96402d 100644 --- a/pegjs/db2.pegjs +++ b/pegjs/db2.pegjs @@ -1728,6 +1728,7 @@ comparison_op_right / between_op_right / is_op_right / like_op_right + / jsonb_or_json_op_right arithmetic_op_right = l:(__ arithmetic_comparison_operator __ additive_expr)+ { @@ -1781,6 +1782,24 @@ in_op_right return { op: op, right: e }; } +jsonb_or_json_op_right + = s: ('@>' / '<@' / '?|' / '?&' / '?' / '#-') __ e:expr { + // => { op: string; right: expr } + return { + type: 'jsonb', + op: s, + right: { type: 'expr', expr: e } + } + } + / s: ('#>>' / '#>' / DOUBLE_ARROW / SINGLE_ARROW) __ e:expr { + // => { op: string; right: expr } + return { + type: 'json', + op: s, + right: { type: 'expr', expr: e } + } + } + additive_expr = head:multiplicative_expr tail:(__ additive_operator __ multiplicative_expr)* { @@ -1826,15 +1845,14 @@ unary_operator = '!' / '-' / '+' / '~' column_ref - = tbl:(ident __ DOT __)? col:column __ a:((DOUBLE_ARROW / SINGLE_ARROW) __ (literal_string / literal_numeric))+ { + = tbl:(ident __ DOT __)? col:column __ jo:jsonb_or_json_op_right+ { const tableName = tbl && tbl[0] || null columnList.add(`select::${tableName}::${col}`); return { type: 'column_ref', table: tableName, column: col, - arrows: a.map(item => item[0]), - properties: a.map(item => item[2]) + jsonb: jo, }; } / tbl:ident __ DOT __ col:column_without_kw { diff --git a/pegjs/flinksql.pegjs b/pegjs/flinksql.pegjs index 9088f76a..1282209e 100644 --- a/pegjs/flinksql.pegjs +++ b/pegjs/flinksql.pegjs @@ -2469,7 +2469,7 @@ comparison_op_right / is_op_right / like_op_right / similar_to_op_right - / jsonb_op_right + / jsonb_or_json_op_right arithmetic_op_right = l:(__ arithmetic_comparison_operator __ additive_expr)+ { @@ -2576,13 +2576,21 @@ exists_op_right return { op: op, right: l }; } -jsonb_op_right - = s: ('@>' / '<@' / OPERATOR_CONCATENATION / DOUBLE_WELL_ARROW / WELL_ARROW / '?' / '?|' / '?&' / '#-') __ - c:column_list_item { +jsonb_or_json_op_right + = s: ('@>' / '<@' / '?|' / '?&' / '?' / '#-') __ e:expr { // => { op: string; right: expr } return { + type: 'jsonb', op: s, - right: c && c.expr || c + right: { type: 'expr', expr: e } + } + } + / s: ('#>>' / '#>' / DOUBLE_ARROW / SINGLE_ARROW) __ e:expr { + // => { op: string; right: expr } + return { + type: 'json', + op: s, + right: { type: 'expr', expr: e } } } @@ -2682,7 +2690,7 @@ column_ref column: '*' } } - / tbl:(ident __ DOT)? __ col:column __ a:((DOUBLE_ARROW / SINGLE_ARROW) __ (literal_string / literal_numeric))+ { + / tbl:(ident __ DOT)? __ col:column __ jo:jsonb_or_json_op_right+ { // => IGNORE const tableName = tbl && tbl[0] || null columnList.add(`select::${tableName}::${col}`); @@ -2690,8 +2698,7 @@ column_ref type: 'column_ref', table: tableName, column: col, - arrows: a.map(item => item[0]), - properties: a.map(item => item[2]) + jsonb: jo, }; } / tbl:ident __ DOT __ col:column { diff --git a/pegjs/mysql.pegjs b/pegjs/mysql.pegjs index 94e4f7c1..912125be 100644 --- a/pegjs/mysql.pegjs +++ b/pegjs/mysql.pegjs @@ -3034,6 +3034,24 @@ in_op_right return { op: op, right: e }; } +jsonb_or_json_op_right + = s: ('@>' / '<@' / '?|' / '?&' / '?' / '#-') __ e:expr { + // => { op: string; right: expr } + return { + type: 'jsonb', + op: s, + right: { type: 'expr', expr: e } + } + } + / s: ('#>>' / '#>' / DOUBLE_ARROW / SINGLE_ARROW) __ e:expr { + // => { op: string; right: expr } + return { + type: 'json', + op: s, + right: { type: 'expr', expr: e } + } + } + additive_expr = head: multiplicative_expr tail:(__ additive_operator __ multiplicative_expr)* { @@ -3090,15 +3108,14 @@ primary } column_ref - = tbl:(ident __ DOT __)? col:column __ a:((DOUBLE_ARROW / SINGLE_ARROW) __ literal)+ { + = tbl:(ident __ DOT __)? col:column __ jo:jsonb_or_json_op_right+ { const tableName = tbl && tbl[0] || null columnList.add(`select::${tableName}::${col}`); return { type: 'column_ref', table: tableName, column: col, - arrows: a.map(item => item[0]), - properties: a.map(item => item[2]), + jsonb: jo, ...getLocationObject(), }; } diff --git a/pegjs/noql.pegjs b/pegjs/noql.pegjs index a574218a..75d21c71 100644 --- a/pegjs/noql.pegjs +++ b/pegjs/noql.pegjs @@ -2836,8 +2836,7 @@ column_list_item // => { expr: expr; as: null; } return { expr: c, as: null } } - / e:expr_item __ s:KW_DOUBLE_COLON __ t:cast_data_type __ a:((DOUBLE_ARROW / SINGLE_ARROW) __ (literal_string / literal_numeric))* __ tail:(__ (additive_operator / multiplicative_operator) __ expr_item)* __ alias:alias_clause? { - // => { type: 'cast'; expr: expr; symbol: '::'; target: cast_data_type; as?: null; arrows?: ('->>' | '->')[]; property?: (literal_string | literal_numeric)[]; } + / e:expr_item __ s:KW_DOUBLE_COLON __ t:cast_data_type __ jo:jsonb_or_json_op_right* __ tail:(__ (additive_operator / multiplicative_operator) __ expr_item)* __ alias:alias_clause? { return { as: alias, type: 'cast', @@ -2845,8 +2844,7 @@ column_list_item symbol: '::', target: t, tail: tail && tail[0] && { operator: tail[0][1], expr: tail[0][3] }, - arrows: a.map(item => item[0]), - properties: a.map(item => item[2]), + jsonb: jo, } } / tbl:ident __ DOT pro:(ident __ DOT)? __ STAR { @@ -3786,7 +3784,7 @@ comparison_op_right / between_op_right / is_op_right / like_op_right - / jsonb_op_right + / jsonb_or_json_op_right / regex_op_right arithmetic_op_right @@ -3886,13 +3884,21 @@ in_op_right return { op: op, right: e }; } -jsonb_op_right - = s: ('@>' / '<@' / OPERATOR_CONCATENATION / DOUBLE_WELL_ARROW / WELL_ARROW / '?' / '?|' / '?&' / '#-') __ - c:column_list_item { +jsonb_or_json_op_right + = s: ('@>' / '<@' / '?|' / '?&' / '?' / '#-') __ e:expr_item { // => { op: string; right: expr } return { + type: 'jsonb', op: s, - right: c && c.expr || c + right: { type: 'expr', expr: e } + } + } + / s: ('#>>' / '#>' / DOUBLE_ARROW / SINGLE_ARROW) __ e:expr_item { + // => { op: string; right: expr } + return { + type: 'json', + op: s, + right: { type: 'expr', expr: e } } } @@ -3970,7 +3976,7 @@ column_ref column: '*' } } - / tbl:(ident __ DOT)? __ col:column __ a:((DOUBLE_ARROW / SINGLE_ARROW) __ (literal_string / literal_numeric))+ { + / tbl:(ident __ DOT)? __ col:column __ jo:jsonb_or_json_op_right+ { // => IGNORE const tableName = tbl && tbl[0] || null columnList.add(`select::${tableName}::${col}`) @@ -3978,19 +3984,10 @@ column_ref type: 'column_ref', table: tableName, column: col, - arrows: a.map(item => item[0]), - properties: a.map(item => item[2]) + jsonb: jo, }; } / schema:ident tbl:(__ DOT __ ident) col:(__ DOT __ column) { - /* => { - type: 'column_ref'; - schema: string; - table: string; - column: column | '*'; - arrows?: ('->>' | '->')[]; - property?: (literal_string | literal_numeric)[]; - } */ columnList.add(`select::${schema}.${tbl[3]}::${col[3]}`); return { type: 'column_ref', @@ -4000,13 +3997,6 @@ column_ref }; } / tbl:ident __ DOT __ col:column { - /* => { - type: 'column_ref'; - table: ident; - column: column | '*'; - arrows?: ('->>' | '->')[]; - property?: (literal_string | literal_numeric)[]; - } */ columnList.add(`select::${tbl}::${col}`); return { type: 'column_ref', @@ -4461,25 +4451,16 @@ scalar_func / "NTILE"i cast_double_colon - = s:KW_DOUBLE_COLON __ t:data_type __ a:((DOUBLE_ARROW / SINGLE_ARROW) __ (literal_string / literal_numeric))* __ alias:alias_clause? { - /* => { - as?: alias_clause, - symbol: '::' | 'as', - target: data_type; - arrows?: ('->>' | '->')[]; - property?: (literal_string | literal_numeric)[]; - } - */ + = s:KW_DOUBLE_COLON __ t:data_type __ jo:jsonb_or_json_op_right* __ alias:alias_clause? { return { as: alias, symbol: '::', target: t, - arrows: a.map(item => item[0]), - properties: a.map(item => item[2]), + jsonb: jo, } } cast_expr - = c:KW_CAST __ LPAREN __ e:expr __ KW_AS __ t:data_type __ RPAREN __ a:((DOUBLE_ARROW / SINGLE_ARROW) __ (literal_string / literal_numeric))* { + = c:KW_CAST __ LPAREN __ e:expr __ KW_AS __ t:data_type __ RPAREN __ jo:jsonb_or_json_op_right* { // => IGNORE return { type: 'cast', @@ -4487,8 +4468,7 @@ cast_expr expr: e, symbol: 'as', target: t, - arrows: a.map(item => item[0]), - properties: a.map(item => item[2]), + jsonb: jo, }; } / c:KW_CAST __ LPAREN __ e:expr __ KW_AS __ KW_DECIMAL __ LPAREN __ precision:int __ RPAREN __ RPAREN { diff --git a/pegjs/postgresql.pegjs b/pegjs/postgresql.pegjs index 342f31d3..95625981 100644 --- a/pegjs/postgresql.pegjs +++ b/pegjs/postgresql.pegjs @@ -3145,8 +3145,8 @@ column_list_item // => { expr: expr; as: null; } return { expr: c, as: null } } - / e:(column_ref_quoted / expr_item) __ s:KW_DOUBLE_COLON __ t:cast_data_type __ a:((DOUBLE_ARROW / SINGLE_ARROW) __ (literal_string / literal_numeric))* __ tail:(__ (additive_operator / multiplicative_operator) __ expr_item)* __ alias:alias_clause? { - // => { type: 'cast'; expr: expr; symbol: '::'; target: cast_data_type; as?: null; arrows?: ('->>' | '->')[]; property?: (literal_string | literal_numeric)[]; } + / e:(column_ref_quoted / expr_item) __ s:KW_DOUBLE_COLON __ t:cast_data_type __ jo:jsonb_or_json_op_right* __ tail:(__ (additive_operator / multiplicative_operator) __ expr_item)* __ alias:alias_clause? { + // => { type: 'cast'; expr: expr; symbol: '::'; target: cast_data_type; as?: null; jsonb?: jsonb_or_json_op_right[]; } return { as: alias, type: 'cast', @@ -3154,8 +3154,7 @@ column_list_item symbol: '::', target: t, tail: tail && tail[0] && { operator: tail[0][1], expr: tail[0][3] }, - arrows: a.map(item => item[0]), - properties: a.map(item => item[2]), + jsonb: jo, } } / tbl:ident_type __ DOT pro:(ident_type __ DOT)? __ STAR { @@ -4127,7 +4126,7 @@ comparison_op_right / between_op_right / is_op_right / like_op_right - / jsonb_op_right + / jsonb_or_json_op_right / regex_op_right arithmetic_op_right @@ -4227,13 +4226,21 @@ in_op_right return { op: op, right: e }; } -jsonb_op_right - = s: ('@>' / '<@' / OPERATOR_CONCATENATION / DOUBLE_WELL_ARROW / WELL_ARROW / '?' / '?|' / '?&' / '#-') __ - c:column_list_item { - // => { op: string; right: expr } +jsonb_or_json_op_right + = s: ('@>' / '<@' / '?|' / '?&' / '?' / '#-') __ e:expr_item { + // => { op: string; right: { type: 'expr'; expr: expr_item } } return { + type: 'jsonb', op: s, - right: c && c.expr || c + right: { type: 'expr', expr: e } + } + } + / s: ('#>>' / '#>' / DOUBLE_ARROW / SINGLE_ARROW) __ e:expr_item { + // => { op: string; right: { type: 'expr'; expr: expr_item } } + return { + type: 'json', + op: s, + right: { type: 'expr', expr: e } } } @@ -4311,7 +4318,7 @@ column_ref column: '*' } } - / tbl:(ident __ DOT)? __ col:column_type __ a:((DOUBLE_ARROW / SINGLE_ARROW) __ (literal_string / literal_numeric))+ { + / tbl:(ident __ DOT)? __ col:column_type __ jo:jsonb_or_json_op_right+ { // => IGNORE const tableName = tbl && tbl[0] || null columnList.add(`select::${tableName}::${col.value}`) @@ -4319,8 +4326,7 @@ column_ref type: 'column_ref', table: tableName, column: { expr: col }, - arrows: a.map(item => item[0]), - properties: a.map(item => item[2]) + jsonb: jo, }; } / schema:ident tbl:(__ DOT __ ident) col:(__ DOT __ column_type) { @@ -4329,8 +4335,7 @@ column_ref schema: string; table: string; column: column | '*'; - arrows?: ('->>' | '->')[]; - property?: (literal_string | literal_numeric)[]; + jsonb?: jsonb_or_json_op_right[]; } */ columnList.add(`select::${schema}.${tbl[3]}::${col[3].value}`); return { @@ -4345,8 +4350,6 @@ column_ref type: 'column_ref'; table: ident; column: column | '*'; - arrows?: ('->>' | '->')[]; - property?: (literal_string | literal_numeric)[]; } */ columnList.add(`select::${tbl}::${col.value}`); return { @@ -4830,25 +4833,23 @@ scalar_func / "NTILE"i cast_double_colon - = s:KW_DOUBLE_COLON __ t:data_type __ a:((DOUBLE_ARROW / SINGLE_ARROW) __ (literal_string / literal_numeric))* __ alias:alias_clause? { + = s:KW_DOUBLE_COLON __ t:data_type __ jo:jsonb_or_json_op_right* __ alias:alias_clause? { /* => { as?: alias_clause, symbol: '::' | 'as', target: data_type; - arrows?: ('->>' | '->')[]; - property?: (literal_string | literal_numeric)[]; + jsonb?: jsonb_or_json_op_right[]; } */ return { as: alias, symbol: '::', target: t, - arrows: a.map(item => item[0]), - properties: a.map(item => item[2]), + jsonb: jo } } cast_expr - = c:KW_CAST __ LPAREN __ e:expr __ KW_AS __ t:data_type __ RPAREN __ a:((DOUBLE_ARROW / SINGLE_ARROW) __ (literal_string / literal_numeric))* { + = c:KW_CAST __ LPAREN __ e:expr __ KW_AS __ t:data_type __ RPAREN __ jo:jsonb_or_json_op_right* { // => IGNORE return { type: 'cast', @@ -4856,8 +4857,7 @@ cast_expr expr: e, symbol: 'as', target: t, - arrows: a.map(item => item[0]), - properties: a.map(item => item[2]), + jsonb: jo }; } / c:KW_CAST __ LPAREN __ e:expr __ KW_AS __ KW_DECIMAL __ LPAREN __ precision:int __ RPAREN __ RPAREN { diff --git a/pegjs/redshift.pegjs b/pegjs/redshift.pegjs index 6ad2cfd8..38bb1987 100644 --- a/pegjs/redshift.pegjs +++ b/pegjs/redshift.pegjs @@ -2875,8 +2875,7 @@ column_list_item // => { expr: expr; as: null; } return { expr: c, as: null } } - / e:(column_ref_quoted / expr_item) __ s:KW_DOUBLE_COLON __ t:cast_data_type __ a:((DOUBLE_ARROW / SINGLE_ARROW) __ (literal_string / literal_numeric))* __ tail:(__ (additive_operator / multiplicative_operator) __ expr_item)* __ alias:alias_clause? { - // => { type: 'cast'; expr: expr; symbol: '::'; target: cast_data_type; as?: null; arrows?: ('->>' | '->')[]; property?: (literal_string | literal_numeric)[]; } + / e:(column_ref_quoted / expr_item) __ s:KW_DOUBLE_COLON __ t:cast_data_type __ jo:jsonb_or_json_op_right* __ tail:(__ (additive_operator / multiplicative_operator) __ expr_item)* __ alias:alias_clause? { return { as: alias, type: 'cast', @@ -2884,8 +2883,7 @@ column_list_item symbol: '::', target: t, tail: tail && tail[0] && { operator: tail[0][1], expr: tail[0][3] }, - arrows: a.map(item => item[0]), - properties: a.map(item => item[2]), + jsonb: jo, } } / tbl:ident_type __ DOT pro:(ident_type __ DOT)? __ STAR { @@ -3826,7 +3824,7 @@ comparison_op_right / between_op_right / is_op_right / like_op_right - / jsonb_op_right + / jsonb_or_json_op_right / regex_op_right arithmetic_op_right @@ -3926,13 +3924,21 @@ in_op_right return { op: op, right: e }; } -jsonb_op_right - = s: ('@>' / '<@' / OPERATOR_CONCATENATION / DOUBLE_WELL_ARROW / WELL_ARROW / '?' / '?|' / '?&' / '#-') __ - c:column_list_item { +jsonb_or_json_op_right + = s: ('@>' / '<@' / '?|' / '?&' / '?' / '#-') __ e:expr_item { // => { op: string; right: expr } return { + type: 'jsonb', op: s, - right: c && c.expr || c + right: { type: 'expr', expr: e } + } + } + / s: ('#>>' / '#>' / DOUBLE_ARROW / SINGLE_ARROW) __ e:expr_item { + // => { op: string; right: expr } + return { + type: 'json', + op: s, + right: { type: 'expr', expr: e } } } @@ -4010,7 +4016,7 @@ column_ref column: '*' } } - / tbl:(ident __ DOT)? __ col:column_type __ a:((DOUBLE_ARROW / SINGLE_ARROW) __ (literal_string / literal_numeric))+ { + / tbl:(ident __ DOT)? __ col:column_type __ jo:jsonb_or_json_op_right+ { // => IGNORE const tableName = tbl && tbl[0] || null columnList.add(`select::${tableName}::${col.value}`) @@ -4018,19 +4024,10 @@ column_ref type: 'column_ref', table: tableName, column: { expr: col }, - arrows: a.map(item => item[0]), - properties: a.map(item => item[2]) + jsonb: jo, }; } / schema:ident tbl:(__ DOT __ ident) col:(__ DOT __ column_type) { - /* => { - type: 'column_ref'; - schema: string; - table: string; - column: column | '*'; - arrows?: ('->>' | '->')[]; - property?: (literal_string | literal_numeric)[]; - } */ columnList.add(`select::${schema}.${tbl[3]}::${col[3].value}`); return { type: 'column_ref', @@ -4040,13 +4037,6 @@ column_ref }; } / tbl:ident __ DOT __ col:column_type { - /* => { - type: 'column_ref'; - table: ident; - column: column | '*'; - arrows?: ('->>' | '->')[]; - property?: (literal_string | literal_numeric)[]; - } */ columnList.add(`select::${tbl}::${col.value}`); return { type: 'column_ref', @@ -4529,25 +4519,16 @@ scalar_func / "NTILE"i cast_double_colon - = s:KW_DOUBLE_COLON __ t:data_type __ a:((DOUBLE_ARROW / SINGLE_ARROW) __ (literal_string / literal_numeric))* __ alias:alias_clause? { - /* => { - as?: alias_clause, - symbol: '::' | 'as', - target: data_type; - arrows?: ('->>' | '->')[]; - property?: (literal_string | literal_numeric)[]; - } - */ + = s:KW_DOUBLE_COLON __ t:data_type __ jo:jsonb_or_json_op_right* __ alias:alias_clause? { return { as: alias, symbol: '::', target: t, - arrows: a.map(item => item[0]), - properties: a.map(item => item[2]), + jsonb: jo, } } cast_expr - = c:KW_CAST __ LPAREN __ e:expr __ KW_AS __ t:data_type __ RPAREN __ a:((DOUBLE_ARROW / SINGLE_ARROW) __ (literal_string / literal_numeric))* { + = c:KW_CAST __ LPAREN __ e:expr __ KW_AS __ t:data_type __ RPAREN __ jo:jsonb_or_json_op_right* { // => IGNORE return { type: 'cast', @@ -4555,8 +4536,7 @@ cast_expr expr: e, symbol: 'as', target: t, - arrows: a.map(item => item[0]), - properties: a.map(item => item[2]), + jsonb: jo, }; } / c:KW_CAST __ LPAREN __ e:expr __ KW_AS __ KW_DECIMAL __ LPAREN __ precision:int __ RPAREN __ RPAREN { diff --git a/pegjs/snowflake.pegjs b/pegjs/snowflake.pegjs index 886596c9..22f1c83a 100644 --- a/pegjs/snowflake.pegjs +++ b/pegjs/snowflake.pegjs @@ -2230,8 +2230,7 @@ column_list_item // => { expr: expr; as: null; } return { expr: c, as: null, ...getLocationObject(), } } - / e:expr_item __ s:KW_DOUBLE_COLON __ t:cast_data_type __ a:((DOUBLE_ARROW / SINGLE_ARROW) __ (literal_string / literal_numeric))* __ tail:(__ (additive_operator / multiplicative_operator) __ expr_item)* __ alias:alias_clause? { - // => { type: 'cast'; expr: expr; symbol: '::'; target: cast_data_type; as?: null; arrows?: ('->>' | '->')[]; property?: (literal_string | literal_numeric)[]; } + / e:expr_item __ s:KW_DOUBLE_COLON __ t:cast_data_type __ jo:jsonb_or_json_op_right* __ tail:(__ (additive_operator / multiplicative_operator) __ expr_item)* __ alias:alias_clause? { return { as: alias, type: 'cast', @@ -2239,8 +2238,7 @@ column_list_item symbol: '::', target: t, tail: tail && tail[0] && { operator: tail[0][1], expr: tail[0][3] }, - arrows: a.map(item => item[0]), - properties: a.map(item => item[2]), + jsonb: jo, ...getLocationObject(), } } @@ -3261,7 +3259,7 @@ comparison_op_right / between_op_right / is_op_right / like_op_right - / jsonb_op_right + / jsonb_or_json_op_right / regex_op_right arithmetic_op_right @@ -3356,13 +3354,21 @@ in_op_right return { op: op, right: e }; } -jsonb_op_right - = s: ('@>' / '<@' / OPERATOR_CONCATENATION / DOUBLE_WELL_ARROW / WELL_ARROW / '?' / '?|' / '?&' / '#-') __ - c:column_list_item { +jsonb_or_json_op_right + = s: ('@>' / '<@' / '?|' / '?&' / '?' / '#-') __ e:expr_item { // => { op: string; right: expr } return { + type: 'jsonb', op: s, - right: c && c.expr || c + right: { type: 'expr', expr: e } + } + } + / s: ('#>>' / '#>' / DOUBLE_ARROW / SINGLE_ARROW) __ e:expr_item { + // => { op: string; right: expr } + return { + type: 'json', + op: s, + right: { type: 'expr', expr: e } } } @@ -3450,7 +3456,7 @@ column_ref ...getLocationObject() } } - / tbl:(ident __ column_symbol)? __ col:column __ a:((DOUBLE_ARROW / SINGLE_ARROW) __ (literal_string / literal_numeric))+ { + / tbl:(ident __ column_symbol)? __ col:column __ jo:jsonb_or_json_op_right+ { // => IGNORE const tableName = tbl && tbl[0] || null columnList.add(`select::${tableName}::${col}`) @@ -3459,21 +3465,11 @@ column_ref table: tableName, column: col, notations: [tbl && tbl[2]], - arrows: a.map(item => item[0]), - properties: a.map(item => item[2]), + jsonb: jo, ...getLocationObject() }; } / schema:ident tbl:(__ column_symbol __ ident) col:(__ column_symbol __ column) { - /* => { - type: 'column_ref'; - schema: string; - table: string; - column: column | '*'; - notations: string[]; - arrows?: ('->>' | '->')[]; - property?: (literal_string | literal_numeric)[]; - } */ columnList.add(`select::${schema}.${tbl[3]}::${col[3]}`); return { type: 'column_ref', @@ -3485,14 +3481,6 @@ column_ref }; } / tbl:ident __ s:column_symbol __ col:column { - /* => { - type: 'column_ref'; - table: ident; - column: column | '*'; - notations: string[]; - arrows?: ('->>' | '->')[]; - property?: (literal_string | literal_numeric)[]; - } */ columnList.add(`select::${tbl}::${col}`); return { type: 'column_ref', @@ -4022,26 +4010,17 @@ scalar_func / "NTILE"i cast_double_colon - = s:KW_DOUBLE_COLON __ t:data_type __ a:((DOUBLE_ARROW / SINGLE_ARROW) __ (literal_string / literal_numeric))* __ alias:alias_clause? { - /* => { - as?: alias_clause, - symbol: '::' | 'as', - target: data_type; - arrows?: ('->>' | '->')[]; - property?: (literal_string | literal_numeric)[]; - } - */ + = s:KW_DOUBLE_COLON __ t:data_type __ jo:jsonb_or_json_op_right* __ alias:alias_clause? { return { as: alias, symbol: '::', target: t, - arrows: a.map(item => item[0]), - properties: a.map(item => item[2]), + jsonb: jo, ...getLocationObject(), } } cast_expr - = c:KW_CAST __ LPAREN __ e:expr __ KW_AS __ t:data_type __ RPAREN __ a:((DOUBLE_ARROW / SINGLE_ARROW) __ (literal_string / literal_numeric))* { + = c:KW_CAST __ LPAREN __ e:expr __ KW_AS __ t:data_type __ RPAREN __ jo:jsonb_or_json_op_right* { // => IGNORE return { type: 'cast', @@ -4049,8 +4028,7 @@ cast_expr expr: e, symbol: 'as', target: t, - arrows: a.map(item => item[0]), - properties: a.map(item => item[2]), + jsonb: jo, }; } / c:KW_CAST __ LPAREN __ e:expr __ KW_AS __ KW_DECIMAL __ LPAREN __ precision:int __ RPAREN __ RPAREN { diff --git a/pegjs/sqlite.pegjs b/pegjs/sqlite.pegjs index f4d22390..a22a74af 100644 --- a/pegjs/sqlite.pegjs +++ b/pegjs/sqlite.pegjs @@ -2107,6 +2107,24 @@ in_op_right return { op: op, right: e }; } +jsonb_or_json_op_right + = s: ('@>' / '<@' / '?|' / '?&' / '?' / '#-') __ e:expr { + // => { op: string; right: expr } + return { + type: 'jsonb', + op: s, + right: { type: 'expr', expr: e } + } + } + / s: ('#>>' / '#>' / DOUBLE_ARROW / SINGLE_ARROW) __ e:expr { + // => { op: string; right: expr } + return { + type: 'json', + op: s, + right: { type: 'expr', expr: e } + } + } + additive_expr = head: multiplicative_expr tail:(__ additive_operator __ multiplicative_expr)* { @@ -2158,15 +2176,14 @@ unary_operator = '!' / '-' / '+' / '~' column_ref - = tbl:(ident __ DOT __)? col:column __ a:((DOUBLE_ARROW / SINGLE_ARROW) __ (literal_string / literal_numeric))+ { + = tbl:(ident __ DOT __)? col:column __ jo:jsonb_or_json_op_right+ { const tableName = tbl && tbl[0] || null columnList.add(`select::${tableName}::${col}`); return { type: 'column_ref', table: tableName, column: col, - arrows: a.map(item => item[0]), - properties: a.map(item => item[2]) + jsonb: jo, }; } / tbl:ident __ DOT __ col:column_without_kw { diff --git a/pegjs/trino.pegjs b/pegjs/trino.pegjs index ffc8d6c4..06ac65a2 100644 --- a/pegjs/trino.pegjs +++ b/pegjs/trino.pegjs @@ -2227,8 +2227,7 @@ column_list_item // => { expr: expr; as: null; } return { expr: c, as: null, ...getLocationObject(), } } - / e:expr_item __ s:KW_DOUBLE_COLON __ t:cast_data_type __ a:((DOUBLE_ARROW / SINGLE_ARROW) __ (literal_string / literal_numeric))* __ tail:(__ (additive_operator / multiplicative_operator) __ expr_item)* __ alias:alias_clause? { - // => { type: 'cast'; expr: expr; symbol: '::'; target: cast_data_type; as?: null; arrows?: ('->>' | '->')[]; property?: (literal_string | literal_numeric)[]; } + / e:expr_item __ s:KW_DOUBLE_COLON __ t:cast_data_type __ jo:jsonb_or_json_op_right* __ tail:(__ (additive_operator / multiplicative_operator) __ expr_item)* __ alias:alias_clause? { return { as: alias, type: 'cast', @@ -2236,8 +2235,7 @@ column_list_item symbol: '::', target: t, tail: tail && tail[0] && { operator: tail[0][1], expr: tail[0][3] }, - arrows: a.map(item => item[0]), - properties: a.map(item => item[2]), + jsonb: jo, ...getLocationObject(), } } @@ -3227,7 +3225,7 @@ comparison_op_right / between_op_right / is_op_right / like_op_right - / jsonb_op_right + / jsonb_or_json_op_right / regex_op_right arithmetic_op_right @@ -3327,13 +3325,21 @@ in_op_right return { op: op, right: e }; } -jsonb_op_right - = s: ('@>' / '<@' / OPERATOR_CONCATENATION / DOUBLE_WELL_ARROW / WELL_ARROW / '?' / '?|' / '?&' / '#-') __ - c:column_list_item { +jsonb_or_json_op_right + = s: ('@>' / '<@' / '?|' / '?&' / '?' / '#-') __ e:expr_item { // => { op: string; right: expr } return { + type: 'jsonb', op: s, - right: c && c.expr || c + right: { type: 'expr', expr: e } + } + } + / s: ('#>>' / '#>' / DOUBLE_ARROW / SINGLE_ARROW) __ e:expr_item { + // => { op: string; right: expr } + return { + type: 'json', + op: s, + right: { type: 'expr', expr: e } } } @@ -3418,7 +3424,7 @@ column_ref ...getLocationObject() } } - / tbl:(ident __ DOT)? __ col:column_type __ a:((DOUBLE_ARROW / SINGLE_ARROW) __ (literal_string / literal_numeric))+ { + / tbl:(ident __ DOT)? __ col:column_type __ jo:jsonb_or_json_op_right+ { // => IGNORE const tableName = tbl && tbl[0] || null columnList.add(`select::${tableName}::${col.value}`) @@ -3426,20 +3432,11 @@ column_ref type: 'column_ref', table: tableName, column: { expr: col }, - arrows: a.map(item => item[0]), - properties: a.map(item => item[2]), + jsonb: jo, ...getLocationObject() }; } / schema:ident tbl:(__ DOT __ ident) col:(__ DOT __ column_type) { - /* => { - type: 'column_ref'; - schema: string; - table: string; - column: column | '*'; - arrows?: ('->>' | '->')[]; - property?: (literal_string | literal_numeric)[]; - } */ columnList.add(`select::${schema}.${tbl[3]}::${col[3].value}`); return { type: 'column_ref', @@ -3450,13 +3447,6 @@ column_ref }; } / tbl:ident __ DOT __ col:column_type { - /* => { - type: 'column_ref'; - table: ident; - column: column | '*'; - arrows?: ('->>' | '->')[]; - property?: (literal_string | literal_numeric)[]; - } */ columnList.add(`select::${tbl}::${col.value}`); return { type: 'column_ref', @@ -3986,26 +3976,17 @@ scalar_func / "NTILE"i cast_double_colon - = s:KW_DOUBLE_COLON __ t:data_type __ a:((DOUBLE_ARROW / SINGLE_ARROW) __ (literal_string / literal_numeric))* __ alias:alias_clause? { - /* => { - as?: alias_clause, - symbol: '::' | 'as', - target: data_type; - arrows?: ('->>' | '->')[]; - property?: (literal_string | literal_numeric)[]; - } - */ + = s:KW_DOUBLE_COLON __ t:data_type __ jo:jsonb_or_json_op_right* __ alias:alias_clause? { return { as: alias, symbol: '::', target: t, - arrows: a.map(item => item[0]), - properties: a.map(item => item[2]), + jsonb: jo, ...getLocationObject(), } } cast_expr - = c:(KW_CAST / KW_TRY_CAST) __ LPAREN __ e:expr __ KW_AS __ t:data_type __ RPAREN __ a:((DOUBLE_ARROW / SINGLE_ARROW) __ (literal_string / literal_numeric))* { + = c:(KW_CAST / KW_TRY_CAST) __ LPAREN __ e:expr __ KW_AS __ t:data_type __ RPAREN __ jo:jsonb_or_json_op_right* { // => IGNORE return { type: 'cast', @@ -4013,8 +3994,7 @@ cast_expr expr: e, symbol: 'as', target: t, - arrows: a.map(item => item[0]), - properties: a.map(item => item[2]), + jsonb: jo, }; } / c:(KW_CAST / KW_TRY_CAST) __ LPAREN __ e:expr __ KW_AS __ KW_DECIMAL __ LPAREN __ precision:int __ RPAREN __ RPAREN { diff --git a/src/column.js b/src/column.js index 2b2b0d2a..380b027c 100644 --- a/src/column.js +++ b/src/column.js @@ -1,6 +1,6 @@ import { constraintDefinitionToSQL } from './constrain' import { exprToSQL } from './expr' -import { arrayDimensionToSymbol, castToSQL } from './func' +import { arrayDimensionToSymbol, castToSQL, jsonOrJsonbToSQL } from './func' import { tablesToSQL } from './tables' import { autoIncrementToSQL, @@ -35,7 +35,7 @@ function arrayIndexToSQL(arrayIndexList) { } function columnRefToSQL(expr) { const { - array_index, arrows = [], as, column, db, isDual, notations = [], schema, table, parentheses, properties, + array_index, as, column, db, isDual, notations = [], schema, table, parentheses, jsonb, suffix, order_by, subFields = [], } = expr let str = column === '*' ? '*' : columnOffsetToSQL(column, isDual) @@ -52,7 +52,7 @@ function columnRefToSQL(expr) { const result = [ str, commonOptionConnector('AS', exprToSQL, as), - arrows.map((arrow, index) => commonOptionConnector(arrow, literalToSQL, properties[index])).join(' '), + jsonOrJsonbToSQL(jsonb), ] result.push(toUpper(suffix)) result.push(toUpper(order_by)) @@ -206,6 +206,7 @@ function columnsToSQL(columns, tables) { export { arrayIndexToSQL, + asToSQL, columnDefinitionToSQL, columnRefToSQL, columnToSQL, diff --git a/src/expr.js b/src/expr.js index ddd4c44d..dfa71fa4 100644 --- a/src/expr.js +++ b/src/expr.js @@ -70,7 +70,9 @@ function exprToSQL(exprOrigin) { expr[key] = ast[key] } } - return exprToSQLConvertFn[expr.type] ? exprToSQLConvertFn[expr.type](expr) : literalToSQL(expr) + const { type } = expr + if (type === 'expr') return exprToSQL(expr.expr) + return exprToSQLConvertFn[type] ? exprToSQLConvertFn[type](expr) : literalToSQL(expr) } function unaryToSQL(unarExpr) { diff --git a/src/func.js b/src/func.js index 0e412b16..568b71ac 100644 --- a/src/func.js +++ b/src/func.js @@ -1,4 +1,4 @@ -import { arrayIndexToSQL } from './column' +import { arrayIndexToSQL, asToSQL } from './column' import { exprToSQL } from './expr' import { commonOptionConnector, hasVal, identifierToSql, literalToSQL, toUpper } from './util' import { overToSQL } from './over' @@ -27,8 +27,16 @@ function arrayDimensionToSymbol(target) { return result.join('') } +function jsonOrJsonbToSQL(jsonb) { + if (!jsonb || jsonb.length === 0) return '' + return jsonb.map(operator => { + const { op, right } = operator + return [commonOptionConnector(op, exprToSQL, right.expr), asToSQL(right.as)].filter(hasVal).join(' ') + }).join(' ') +} + function castToSQL(expr) { - const { arrows = [], target, expr: expression, keyword, symbol, as: alias, parentheses: outParentheses, properties = [] } = expr + const { target, expr: expression, keyword, symbol, as: alias, parentheses: outParentheses, jsonb } = expr const { length, dataType, parentheses, quoted, scale, suffix: dataTypeSuffix, expr: targetExpr } = target let str = targetExpr ? exprToSQL(targetExpr) : '' if (length != null) str = scale ? `${length}, ${scale}` : length @@ -42,7 +50,9 @@ function castToSQL(expr) { suffix = ')' symbolChar = ` ${symbol.toUpperCase()} ` } - suffix += arrows.map((arrow, index) => commonOptionConnector(arrow, literalToSQL, properties[index])).join(' ') + const jsonbOperatorStr = jsonOrJsonbToSQL(jsonb) + const whitespace = jsonbOperatorStr ? ' ' : '' + suffix += `${whitespace}${jsonbOperatorStr}` if (alias) suffix += ` AS ${identifierToSql(alias)}` const arrayDimension = arrayDimensionToSymbol(target) const result = [prefix, symbolChar, quoted, dataType, quoted, arrayDimension, str, suffix].filter(hasVal).join('') @@ -117,6 +127,7 @@ export { flattenFunToSQL, funcToSQL, jsonObjectArgToSQL, + jsonOrJsonbToSQL, lambdaToSQL, tablefuncFunToSQL, } diff --git a/test/mysql-mariadb.spec.js b/test/mysql-mariadb.spec.js index a53f49d5..ae0931f9 100644 --- a/test/mysql-mariadb.spec.js +++ b/test/mysql-mariadb.spec.js @@ -1093,7 +1093,7 @@ describe('mysql', () => { expect(parser.astify.bind(parser, sql)).to.throw('Expected "!=", "#", "%", "&", "&&", "*", "+", ",", "-", "--", "/", "/*", "<", "<<", "<=", "<>", "=", ">", ">=", ">>", "AND", "BETWEEN", "IN", "IS", "LIKE", "NOT", "ON", "OR", "OVER", "REGEXP", "RLIKE", "USING", "XOR", "^", "div", "|", "||", or [ \\t\\n\\r] but ")" found.') expect(parser.astify.bind(parser, 'select convert("");')).to.throw('Expected "!=", "#", "%", "&", "&&", "*", "+", ",", "-", "--", "/", "/*", "<", "<<", "<=", "<>", "=", ">", ">=", ">>", "AND", "BETWEEN", "COLLATE", "IN", "IS", "LIKE", "NOT", "OR", "REGEXP", "RLIKE", "USING", "XOR", "^", "div", "|", "||", or [ \\t\\n\\r] but ")" found.') sql = 'SELECT AVG(Quantity,age) FROM table1;' - expect(parser.astify.bind(parser, sql)).to.throw('Expected "!=", "#", "%", "&", "&&", "(", ")", "*", "+", "-", "--", "->", "->>", ".", "/", "/*", "<", "<<", "<=", "<>", "=", ">", ">=", ">>", "BETWEEN", "IN", "IS", "LIKE", "NOT", "REGEXP", "RLIKE", "XOR", "^", "div", "|", "||", [ \\t\\n\\r], [A-Za-z0-9_$\\x80-￿], or [A-Za-z0-9_:] but "," found.') + expect(parser.astify.bind(parser, sql)).to.throw('Expected "!=", "#", "#-", "#>", "#>>", "%", "&", "&&", "(", ")", "*", "+", "-", "--", "->", "->>", ".", "/", "/*", "<", "<<", "<=", "<>", "<@", "=", ">", ">=", ">>", "?", "?&", "?|", "@>", "BETWEEN", "IN", "IS", "LIKE", "NOT", "REGEXP", "RLIKE", "XOR", "^", "div", "|", "||", [ \\t\\n\\r], [A-Za-z0-9_$\\x80-￿], or [A-Za-z0-9_:] but "," found.') }) it('should join multiple table with comma', () => { diff --git a/test/postgres.spec.js b/test/postgres.spec.js index 23d9761e..71f251b2 100644 --- a/test/postgres.spec.js +++ b/test/postgres.spec.js @@ -921,14 +921,14 @@ describe('Postgres', () => { title: 'cast to jsonb and select key', sql: [ "SELECT TextColumn::JSONB->>'name' FROM table1", - `SELECT TextColumn::JSONB->> 'name' FROM "table1"` + `SELECT TextColumn::JSONB ->> 'name' FROM "table1"` ] }, { title: 'cast to jsonb and select key in function', sql: [ "SELECT CAST(properties AS JSONB)->>'name' FROM table1", - `SELECT CAST(properties AS JSONB)->> 'name' FROM "table1"` + `SELECT CAST(properties AS JSONB) ->> 'name' FROM "table1"` ] }, { @@ -1562,6 +1562,13 @@ describe('Postgres', () => { 'ALTER TABLE "transactions" ALTER COLUMN status SET NOT NULL', ] }, + { + title: 'jsonb operator', + sql: [ + "SELECT id, collection::jsonb ?| array['val1', 'val2'] FROM instances", + `SELECT id, collection::JSONB ?| ARRAY['val1','val2'] FROM "instances"` + ] + }, ] function neatlyNestTestedSQL(sqlList){ sqlList.forEach(sqlInfo => { @@ -1571,6 +1578,7 @@ describe('Postgres', () => { }) }) } + neatlyNestTestedSQL(SQL_LIST) describe('tables to sql', () => {