From a6f931d9a17caf288fdac592ad16dc7bad280a9d Mon Sep 17 00:00:00 2001 From: taozhi8833998 Date: Sun, 5 May 2024 17:18:07 +0800 Subject: [PATCH] fix: unary operator in redshift --- pegjs/athena.pegjs | 14 ++++++++++++-- pegjs/bigquery.pegjs | 14 ++++++++++++-- pegjs/db2.pegjs | 14 ++++++++++++-- pegjs/flinksql.pegjs | 14 ++++++++++++-- pegjs/hive.pegjs | 14 ++++++++++++-- pegjs/noql.pegjs | 14 ++++++++++++-- pegjs/postgresql.pegjs | 14 ++++++++++++-- pegjs/redshift.pegjs | 14 ++++++++++++-- pegjs/snowflake.pegjs | 14 ++++++++++++-- pegjs/sqlite.pegjs | 14 ++++++++++++-- pegjs/transactsql.pegjs | 14 ++++++++++++-- pegjs/trino.pegjs | 14 ++++++++++++-- test/redshift.spec.js | 5 +++++ 13 files changed, 149 insertions(+), 24 deletions(-) diff --git a/pegjs/athena.pegjs b/pegjs/athena.pegjs index 2b7842eb..d8ec1dcd 100644 --- a/pegjs/athena.pegjs +++ b/pegjs/athena.pegjs @@ -1754,8 +1754,8 @@ additive_operator = "+" / "-" multiplicative_expr - = head:primary - tail:(__ (multiplicative_operator / LOGIC_OPERATOR) __ primary)* { + = head:unary_expr_or_primary + tail:(__ (multiplicative_operator / LOGIC_OPERATOR) __ unary_expr_or_primary)* { return createBinaryExprChain(head, tail) } @@ -1782,6 +1782,16 @@ primary } / var_decl +unary_expr_or_primary + = primary + / op:(unary_operator) tail:(__ unary_expr_or_primary) { + // if (op === '!') op = 'NOT' + return createUnaryExpr(op, tail[1]) + } + +unary_operator + = '!' / '-' / '+' / '~' + column_ref = tbl:ident __ DOT __ col:column { columnList.add(`select::${tbl}::${col}`); diff --git a/pegjs/bigquery.pegjs b/pegjs/bigquery.pegjs index 440d5c55..8e2d2790 100644 --- a/pegjs/bigquery.pegjs +++ b/pegjs/bigquery.pegjs @@ -2263,8 +2263,8 @@ additive_operator = "+" / "-" multiplicative_expr - = head:primary - tail:(__ (multiplicative_operator / LOGIC_OPERATOR) __ primary)* { + = head:unary_expr_or_primary + tail:(__ (multiplicative_operator / LOGIC_OPERATOR) __ unary_expr_or_primary)* { return createBinaryExprChain(head, tail) } @@ -2288,6 +2288,16 @@ primary return list; } +unary_expr_or_primary + = primary + / op:(unary_operator) tail:(__ unary_expr_or_primary) { + // if (op === '!') op = 'NOT' + return createUnaryExpr(op, tail[1]) + } + +unary_operator + = '!' / '-' / '+' / '~' + interval_expr = KW_INTERVAL __ e:expr __ diff --git a/pegjs/db2.pegjs b/pegjs/db2.pegjs index 8712903c..a608111b 100644 --- a/pegjs/db2.pegjs +++ b/pegjs/db2.pegjs @@ -1770,8 +1770,8 @@ additive_operator = "+" / "-" multiplicative_expr - = head:primary - tail:(__ (multiplicative_operator / LOGIC_OPERATOR) __ primary)* { + = head:unary_expr_or_primary + tail:(__ (multiplicative_operator / LOGIC_OPERATOR) __ unary_expr_or_primary)* { return createBinaryExprChain(head, tail) } @@ -1793,6 +1793,16 @@ primary } / var_decl +unary_expr_or_primary + = primary + / op:(unary_operator) tail:(__ unary_expr_or_primary) { + // if (op === '!') op = 'NOT' + return createUnaryExpr(op, tail[1]) + } + +unary_operator + = '!' / '-' / '+' / '~' + column_ref = tbl:(ident __ DOT __)? col:column __ a:((DOUBLE_ARROW / SINGLE_ARROW) __ (literal_string / literal_numeric))+ __ ca:collate_expr? { const tableName = tbl && tbl[0] || null diff --git a/pegjs/flinksql.pegjs b/pegjs/flinksql.pegjs index a695a408..9c32a489 100644 --- a/pegjs/flinksql.pegjs +++ b/pegjs/flinksql.pegjs @@ -2577,8 +2577,8 @@ additive_operator = "+" / "-" multiplicative_expr - = head:primary - tail:(__ (multiplicative_operator / LOGIC_OPERATOR) __ primary)* { + = head:unary_expr_or_primary + tail:(__ (multiplicative_operator / LOGIC_OPERATOR) __ unary_expr_or_primary)* { // => binary_expr return createBinaryExprChain(head, tail) } @@ -2608,6 +2608,16 @@ primary } } +unary_expr_or_primary + = primary + / op:(unary_operator) tail:(__ unary_expr_or_primary) { + // if (op === '!') op = 'NOT' + return createUnaryExpr(op, tail[1]) + } + +unary_operator + = '!' / '-' / '+' / '~' + map_expr_item = k:literal_string __ COMMA __ v:ident_without_kw_type { columnList.add(`select::null::${v.value}`); diff --git a/pegjs/hive.pegjs b/pegjs/hive.pegjs index b66e3276..3dc24638 100644 --- a/pegjs/hive.pegjs +++ b/pegjs/hive.pegjs @@ -1758,8 +1758,8 @@ additive_operator = "+" / "-" multiplicative_expr - = head:primary - tail:(__ (multiplicative_operator / LOGIC_OPERATOR) __ primary)* { + = head:unary_expr_or_primary + tail:(__ (multiplicative_operator / LOGIC_OPERATOR) __ unary_expr_or_primary)* { return createBinaryExprChain(head, tail) } @@ -1786,6 +1786,16 @@ primary } / var_decl +unary_expr_or_primary + = primary + / op:(unary_operator) tail:(__ unary_expr_or_primary) { + // if (op === '!') op = 'NOT' + return createUnaryExpr(op, tail[1]) + } + +unary_operator + = '!' / '-' / '+' / '~' + column_ref = tbl:ident __ DOT __ col:column { columnList.add(`select::${tbl}::${col}`); diff --git a/pegjs/noql.pegjs b/pegjs/noql.pegjs index 20c567fe..e902915d 100644 --- a/pegjs/noql.pegjs +++ b/pegjs/noql.pegjs @@ -3905,8 +3905,8 @@ additive_operator = "+" / "-" multiplicative_expr - = head:primary - tail:(__ (multiplicative_operator / LOGIC_OPERATOR) __ primary)* { + = head:unary_expr_or_primary + tail:(__ (multiplicative_operator / LOGIC_OPERATOR) __ unary_expr_or_primary)* { // => binary_expr return createBinaryExprChain(head, tail) } @@ -3936,6 +3936,16 @@ primary } } +unary_expr_or_primary + = primary + / op:(unary_operator) tail:(__ unary_expr_or_primary) { + // if (op === '!') op = 'NOT' + return createUnaryExpr(op, tail[1]) + } + +unary_operator + = '!' / '-' / '+' / '~' + string_constants_escape = 'E'i"'" __ n:single_char* __ "'" { // => { type: 'origin'; value: string; } diff --git a/pegjs/postgresql.pegjs b/pegjs/postgresql.pegjs index dbc70b85..67522617 100644 --- a/pegjs/postgresql.pegjs +++ b/pegjs/postgresql.pegjs @@ -4087,8 +4087,8 @@ additive_operator = "+" / "-" multiplicative_expr - = head:primary - tail:(__ (multiplicative_operator / LOGIC_OPERATOR) __ primary)* { + = head:unary_expr_or_primary + tail:(__ (multiplicative_operator / LOGIC_OPERATOR) __ unary_expr_or_primary)* { // => binary_expr return createBinaryExprChain(head, tail) } @@ -4118,6 +4118,16 @@ primary } } +unary_expr_or_primary + = primary + / op:(unary_operator) tail:(__ unary_expr_or_primary) { + // if (op === '!') op = 'NOT' + return createUnaryExpr(op, tail[1]) + } + +unary_operator + = '!' / '-' / '+' / '~' + string_constants_escape = 'E'i"'" __ n:single_char* __ "'" { // => { type: 'origin'; value: string; } diff --git a/pegjs/redshift.pegjs b/pegjs/redshift.pegjs index cd1f8462..a7f8c782 100644 --- a/pegjs/redshift.pegjs +++ b/pegjs/redshift.pegjs @@ -3941,8 +3941,8 @@ additive_operator = "+" / "-" multiplicative_expr - = head:primary - tail:(__ (multiplicative_operator / LOGIC_OPERATOR) __ primary)* { + = head:unary_expr_or_primary + tail:(__ (multiplicative_operator / LOGIC_OPERATOR) __ unary_expr_or_primary)* { // => binary_expr return createBinaryExprChain(head, tail) } @@ -3972,6 +3972,16 @@ primary } } +unary_expr_or_primary + = primary + / op:(unary_operator) tail:(__ unary_expr_or_primary) { + // if (op === '!') op = 'NOT' + return createUnaryExpr(op, tail[1]) + } + +unary_operator + = '!' / '-' / '+' / '~' + string_constants_escape = 'E'i"'" __ n:single_char* __ "'" { // => { type: 'origin'; value: string; } diff --git a/pegjs/snowflake.pegjs b/pegjs/snowflake.pegjs index c931bee2..0ea61794 100644 --- a/pegjs/snowflake.pegjs +++ b/pegjs/snowflake.pegjs @@ -3296,8 +3296,8 @@ additive_operator = "+" / "-" multiplicative_expr - = head:primary - tail:(__ (multiplicative_operator / LOGIC_OPERATOR) __ primary)* { + = head:unary_expr_or_primary + tail:(__ (multiplicative_operator / LOGIC_OPERATOR) __ unary_expr_or_primary)* { // => binary_expr return createBinaryExprChain(head, tail) } @@ -3327,6 +3327,16 @@ primary } } +unary_expr_or_primary + = primary + / op:(unary_operator) tail:(__ unary_expr_or_primary) { + // if (op === '!') op = 'NOT' + return createUnaryExpr(op, tail[1]) + } + +unary_operator + = '!' / '-' / '+' / '~' + string_constants_escape = 'E'i"'" __ n:single_char* __ "'" { // => { type: 'origin'; value: string; } diff --git a/pegjs/sqlite.pegjs b/pegjs/sqlite.pegjs index 2e58c2e1..a5f24698 100644 --- a/pegjs/sqlite.pegjs +++ b/pegjs/sqlite.pegjs @@ -1934,8 +1934,8 @@ additive_operator = "+" / "-" multiplicative_expr - = head:primary - tail:(__ (multiplicative_operator / LOGIC_OPERATOR) __ primary)* { + = head:unary_expr_or_primary + tail:(__ (multiplicative_operator / LOGIC_OPERATOR) __ unary_expr_or_primary)* { return createBinaryExprChain(head, tail) } @@ -1963,6 +1963,16 @@ primary } } +unary_expr_or_primary + = primary + / op:(unary_operator) tail:(__ unary_expr_or_primary) { + // if (op === '!') op = 'NOT' + return createUnaryExpr(op, tail[1]) + } + +unary_operator + = '!' / '-' / '+' / '~' + column_ref = tbl:(ident __ DOT __)? col:column __ a:((DOUBLE_ARROW / SINGLE_ARROW) __ (literal_string / literal_numeric))+ __ ca:collate_expr? { const tableName = tbl && tbl[0] || null diff --git a/pegjs/transactsql.pegjs b/pegjs/transactsql.pegjs index 50268d1a..0fadf042 100644 --- a/pegjs/transactsql.pegjs +++ b/pegjs/transactsql.pegjs @@ -2331,8 +2331,8 @@ additive_operator = "+" / "-" multiplicative_expr - = head:primary - tail:(__ (multiplicative_operator / LOGIC_OPERATOR) __ primary)* { + = head:unary_expr_or_primary + tail:(__ (multiplicative_operator / LOGIC_OPERATOR) __ unary_expr_or_primary)* { return createBinaryExprChain(head, tail) } @@ -2354,6 +2354,16 @@ primary } / var_decl +unary_expr_or_primary + = primary + / op:(unary_operator) tail:(__ unary_expr_or_primary) { + // if (op === '!') op = 'NOT' + return createUnaryExpr(op, tail[1]) + } + +unary_operator + = '!' / '-' / '+' / '~' + column_ref = db:(ident __ DOT)? __ schema:(ident __ DOT)? __ tbl:(ident __ DOT)? __ col:column { const obj = { table: null, db: null, schema: null } diff --git a/pegjs/trino.pegjs b/pegjs/trino.pegjs index 26f95bc3..eee7cb16 100644 --- a/pegjs/trino.pegjs +++ b/pegjs/trino.pegjs @@ -3339,8 +3339,8 @@ additive_operator = "+" / "-" multiplicative_expr - = head:primary - tail:(__ (multiplicative_operator / LOGIC_OPERATOR) __ primary)* { + = head:unary_expr_or_primary + tail:(__ (multiplicative_operator / LOGIC_OPERATOR) __ unary_expr_or_primary)* { // => binary_expr return createBinaryExprChain(head, tail) } @@ -3376,6 +3376,16 @@ primary } } +unary_expr_or_primary + = primary + / op:(unary_operator) tail:(__ unary_expr_or_primary) { + // if (op === '!') op = 'NOT' + return createUnaryExpr(op, tail[1]) + } + +unary_operator + = '!' / '-' / '+' / '~' + string_constants_escape = 'E'i"'" __ n:single_char* __ "'" { // => { type: 'origin'; value: string; } diff --git a/test/redshift.spec.js b/test/redshift.spec.js index 6b44412b..fe36082b 100644 --- a/test/redshift.spec.js +++ b/test/redshift.spec.js @@ -32,4 +32,9 @@ describe('redshift', () => { expect(getParsedSql(sql)).to.be.equal(`WITH "pv" AS (SELECT action_date, visitor_id_v, visit_country_name, referer_channel_group, email, sgid, "mp"."brand/non-brand" AS "is_brand" FROM "dwh_fact_pageviews" AS "pv" LEFT JOIN "ppc_keywords_mapping" AS "mp" USING ("campaign_keyword")) SELECT is_brand AS "b/nb" FROM "pv" WHERE "mp"."brand/non-brand" = 'brand'`) }) + it('should support unary operator', () => { + const sql = 'SELECT * FROM montara_raw.raw_listings WHERE price = -minimum_nights' + expect(getParsedSql(sql)).to.be.equal('SELECT * FROM "montara_raw"."raw_listings" WHERE price = -minimum_nights') + }) + }) \ No newline at end of file