diff --git a/contrib/babelfishpg_tsql/src/tsqlIface.cpp b/contrib/babelfishpg_tsql/src/tsqlIface.cpp index 6a641cb16d5..5f422a25be8 100644 --- a/contrib/babelfishpg_tsql/src/tsqlIface.cpp +++ b/contrib/babelfishpg_tsql/src/tsqlIface.cpp @@ -2489,7 +2489,42 @@ class tsqlMutator : public TSqlParserBaseListener std::string result = Trees::getNodeText(t, this->ruleNames); return result; } - + + void enterComparison_operator(TSqlParser::Comparison_operatorContext *ctx) override + { + // Handle multiple cases: + // - 2-char comparison operators containing whitespace, i.e. '! =', '< >', etc. + // - operators !< and !> (which may also contains whitespace), convert to >= and <= + std::string str = getFullText(ctx); + std::string operator_final = ""; + int fill = 0; + + if (str.length() > 2) + { + // This operator contains whitespace, remove it + for(size_t i = 0; i < str.length(); i++) + { + if (!isspace(str[i])) + operator_final += str[i]; + } + fill = str.length() - operator_final.length(); + } + + // Handle !> and !< operators by converting to <= and >= + if (pg_strncasecmp(str.c_str(), "!<", 2) == 0) operator_final = ">="; + else if (pg_strncasecmp(operator_final.c_str(), "!<", 2) == 0) operator_final = ">="; + else if (pg_strncasecmp(str.c_str(), "!>", 2) == 0) operator_final = "<="; + else if (pg_strncasecmp(operator_final.c_str(), "!>", 2) == 0) operator_final = "<="; + + // Fill with spaces until original length + operator_final.append(fill, ' '); + + if (operator_final.length() > 0) + { + stream.setText(ctx->start->getStartIndex(), operator_final.c_str()); + } + } + // Tree listener overrides void enterEveryRule(ParserRuleContext *ctx) override { @@ -2507,8 +2542,8 @@ class tsqlMutator : public TSqlParserBaseListener std::cout << "-leaving (tsqlMutator)" << (void *) ctx << "[" << desc << "]" << std::endl; } - void enterFunc_proc_name_server_database_schema(TSqlParser::Func_proc_name_server_database_schemaContext *ctx) override - { + void enterFunc_proc_name_server_database_schema(TSqlParser::Func_proc_name_server_database_schemaContext *ctx) override + { // We are looking at a function name; it may be a function call, or a // DROP function statement, or some other reference. // diff --git a/test/JDBC/expected/operator_whitespace-vu-cleanup.out b/test/JDBC/expected/operator_whitespace-vu-cleanup.out new file mode 100644 index 00000000000..183ce7dd5a2 --- /dev/null +++ b/test/JDBC/expected/operator_whitespace-vu-cleanup.out @@ -0,0 +1,8 @@ +drop procedure p1_operator_whitespace +go + +drop view v1_operator_whitespace +go + +drop table t1_operator_whitespace +go diff --git a/test/JDBC/expected/operator_whitespace-vu-prepare.out b/test/JDBC/expected/operator_whitespace-vu-prepare.out new file mode 100644 index 00000000000..58c47db319c --- /dev/null +++ b/test/JDBC/expected/operator_whitespace-vu-prepare.out @@ -0,0 +1,31 @@ +create table t1_operator_whitespace(a int) +go + +create view v1_operator_whitespace as +select c1=1, c2=a from t1_operator_whitespace where a = case when a! >2 then a else 0 end +go + + +create procedure p1_operator_whitespace +as +select a as p1 from t1_operator_whitespace where a ! = 2 +select a as p2 from t1_operator_whitespace where a ! =2 +select a as q3 from t1_operator_whitespace where a ! + + += 2 +select a as p4 from t1_operator_whitespace where a < >2 +select a as p5 from t1_operator_whitespace where a < = 2 +select a as p6 from t1_operator_whitespace where a > =2 +select a as p7 from t1_operator_whitespace where a!<2 +select a as p8 from t1_operator_whitespace where a !< 2 +select a as p9 from t1_operator_whitespace where a ! < 2 +select a as p10 from t1_operator_whitespace where a! <2 +select a as p11 from t1_operator_whitespace where a !> 2 +select a as p12 from t1_operator_whitespace where a!>2 +select a as p13 from t1_operator_whitespace where a ! > 2 +select a as p14 from t1_operator_whitespace where a! >2 +select a as q15 from t1_operator_whitespace where a = case when a! >2 then a else 0 end +EXECUTE('select a as p16 from t1_operator_whitespace where a ! = 2') +EXECUTE('select a as p17 from t1_operator_whitespace where a ! < 2') +go diff --git a/test/JDBC/expected/operator_whitespace-vu-verify.out b/test/JDBC/expected/operator_whitespace-vu-verify.out new file mode 100644 index 00000000000..9340a6ab952 --- /dev/null +++ b/test/JDBC/expected/operator_whitespace-vu-verify.out @@ -0,0 +1,311 @@ +-- Combines BABEL-3379 (whitespace in 2-char comparison operators (!=, <>, <=, etc.)) and BABEL-4114 (comparison operators !< and !>) +alter table t1_operator_whitespace add check(a! <1) +go + +alter table t1_operator_whitespace add check(a< +=3) +go + +insert t1_operator_whitespace values (0) +go +~~ERROR (Code: 547)~~ + +~~ERROR (Message: new row for relation "t1_operator_whitespace" violates check constraint "t1_operator_whitespace_a_check")~~ + +insert t1_operator_whitespace values (4) +go +~~ERROR (Code: 547)~~ + +~~ERROR (Message: new row for relation "t1_operator_whitespace" violates check constraint "t1_operator_whitespace_a_check1")~~ + +insert t1_operator_whitespace values (1) +insert t1_operator_whitespace values (2) +insert t1_operator_whitespace values (3) +go +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + + +select a from t1_operator_whitespace +go +~~START~~ +int +1 +2 +3 +~~END~~ + + +select a as q1 from t1_operator_whitespace where a != 2 +go +~~START~~ +int +1 +3 +~~END~~ + + +select a as q1 from t1_operator_whitespace where a ! = 2 +go +~~START~~ +int +1 +3 +~~END~~ + + +select a as q2 from t1_operator_whitespace where a ! =2 +go +~~START~~ +int +1 +3 +~~END~~ + + + +select a as q3 from t1_operator_whitespace where a ! + + += 2 +go +~~START~~ +int +1 +3 +~~END~~ + + +select a as q4 from t1_operator_whitespace where a < >2 +go +~~START~~ +int +1 +3 +~~END~~ + + +select a as q5 from t1_operator_whitespace where a < = 2 +go +~~START~~ +int +1 +2 +~~END~~ + + +select a as q6 from t1_operator_whitespace where a > =2 +go +~~START~~ +int +2 +3 +~~END~~ + + +select a as q7 from t1_operator_whitespace where a!<2 +go +~~START~~ +int +2 +3 +~~END~~ + + +select a as q8 from t1_operator_whitespace where a !< 2 +go +~~START~~ +int +2 +3 +~~END~~ + + +select a as q9 from t1_operator_whitespace where a ! < 2 +go +~~START~~ +int +2 +3 +~~END~~ + + +select a as q10 from t1_operator_whitespace where a! <2 +go +~~START~~ +int +2 +3 +~~END~~ + + +select a as q11 from t1_operator_whitespace where a !> 2 +go +~~START~~ +int +1 +2 +~~END~~ + + +select a as q12 from t1_operator_whitespace where a!>2 +go +~~START~~ +int +1 +2 +~~END~~ + + +select a as q13 from t1_operator_whitespace where a ! > 2 +go +~~START~~ +int +1 +2 +~~END~~ + + +select a as q14 from t1_operator_whitespace where a! >2 +go +~~START~~ +int +1 +2 +~~END~~ + + +select a as q15 from t1_operator_whitespace where a = case when a! >2 then a else 0 end +go +~~START~~ +int +1 +2 +~~END~~ + + +EXECUTE('select a as q16 from t1_operator_whitespace where a ! = 2') +go +~~START~~ +int +1 +3 +~~END~~ + + +EXECUTE('select a as q17 from t1_operator_whitespace where a ! < 2') +go +~~START~~ +int +2 +3 +~~END~~ + + +EXECUTE p1_operator_whitespace +go +~~START~~ +int +1 +3 +~~END~~ + +~~START~~ +int +1 +3 +~~END~~ + +~~START~~ +int +1 +3 +~~END~~ + +~~START~~ +int +1 +3 +~~END~~ + +~~START~~ +int +1 +2 +~~END~~ + +~~START~~ +int +2 +3 +~~END~~ + +~~START~~ +int +2 +3 +~~END~~ + +~~START~~ +int +2 +3 +~~END~~ + +~~START~~ +int +2 +3 +~~END~~ + +~~START~~ +int +2 +3 +~~END~~ + +~~START~~ +int +1 +2 +~~END~~ + +~~START~~ +int +1 +2 +~~END~~ + +~~START~~ +int +1 +2 +~~END~~ + +~~START~~ +int +1 +2 +~~END~~ + +~~START~~ +int +1 +2 +~~END~~ + +~~START~~ +int +1 +3 +~~END~~ + +~~START~~ +int +2 +3 +~~END~~ + diff --git a/test/JDBC/input/operator_whitespace-vu-cleanup.sql b/test/JDBC/input/operator_whitespace-vu-cleanup.sql new file mode 100644 index 00000000000..183ce7dd5a2 --- /dev/null +++ b/test/JDBC/input/operator_whitespace-vu-cleanup.sql @@ -0,0 +1,8 @@ +drop procedure p1_operator_whitespace +go + +drop view v1_operator_whitespace +go + +drop table t1_operator_whitespace +go diff --git a/test/JDBC/input/operator_whitespace-vu-prepare.sql b/test/JDBC/input/operator_whitespace-vu-prepare.sql new file mode 100644 index 00000000000..5e61300deb8 --- /dev/null +++ b/test/JDBC/input/operator_whitespace-vu-prepare.sql @@ -0,0 +1,31 @@ +create table t1_operator_whitespace(a int) +go + +create view v1_operator_whitespace as +select c1=1, c2=a from t1_operator_whitespace where a = case when a! >2 then a else 0 end +go + +create procedure p1_operator_whitespace +as +select a as p1 from t1_operator_whitespace where a ! = 2 +select a as p2 from t1_operator_whitespace where a ! =2 +select a as q3 from t1_operator_whitespace where a ! + + + += 2 +select a as p4 from t1_operator_whitespace where a < >2 +select a as p5 from t1_operator_whitespace where a < = 2 +select a as p6 from t1_operator_whitespace where a > =2 +select a as p7 from t1_operator_whitespace where a!<2 +select a as p8 from t1_operator_whitespace where a !< 2 +select a as p9 from t1_operator_whitespace where a ! < 2 +select a as p10 from t1_operator_whitespace where a! <2 +select a as p11 from t1_operator_whitespace where a !> 2 +select a as p12 from t1_operator_whitespace where a!>2 +select a as p13 from t1_operator_whitespace where a ! > 2 +select a as p14 from t1_operator_whitespace where a! >2 +select a as q15 from t1_operator_whitespace where a = case when a! >2 then a else 0 end +EXECUTE('select a as p16 from t1_operator_whitespace where a ! = 2') +EXECUTE('select a as p17 from t1_operator_whitespace where a ! < 2') +go diff --git a/test/JDBC/input/operator_whitespace-vu-verify.sql b/test/JDBC/input/operator_whitespace-vu-verify.sql new file mode 100644 index 00000000000..906300bd444 --- /dev/null +++ b/test/JDBC/input/operator_whitespace-vu-verify.sql @@ -0,0 +1,80 @@ +-- Combines BABEL-3379 (whitespace in 2-char comparison operators (!=, <>, <=, etc.)) and BABEL-4114 (comparison operators !< and !>) +alter table t1_operator_whitespace add check(a! <1) +go + +alter table t1_operator_whitespace add check(a< +=3) +go + +insert t1_operator_whitespace values (0) +go +insert t1_operator_whitespace values (4) +go +insert t1_operator_whitespace values (1) +insert t1_operator_whitespace values (2) +insert t1_operator_whitespace values (3) +go + +select a from t1_operator_whitespace +go + +select a as q1 from t1_operator_whitespace where a != 2 +go + +select a as q1 from t1_operator_whitespace where a ! = 2 +go + +select a as q2 from t1_operator_whitespace where a ! =2 +go + +select a as q3 from t1_operator_whitespace where a ! + + + += 2 +go + +select a as q4 from t1_operator_whitespace where a < >2 +go + +select a as q5 from t1_operator_whitespace where a < = 2 +go + +select a as q6 from t1_operator_whitespace where a > =2 +go + +select a as q7 from t1_operator_whitespace where a!<2 +go + +select a as q8 from t1_operator_whitespace where a !< 2 +go + +select a as q9 from t1_operator_whitespace where a ! < 2 +go + +select a as q10 from t1_operator_whitespace where a! <2 +go + +select a as q11 from t1_operator_whitespace where a !> 2 +go + +select a as q12 from t1_operator_whitespace where a!>2 +go + +select a as q13 from t1_operator_whitespace where a ! > 2 +go + +select a as q14 from t1_operator_whitespace where a! >2 +go + +select a as q15 from t1_operator_whitespace where a = case when a! >2 then a else 0 end +go + +EXECUTE('select a as q16 from t1_operator_whitespace where a ! = 2') +go + +EXECUTE('select a as q17 from t1_operator_whitespace where a ! < 2') +go + +EXECUTE p1_operator_whitespace +go diff --git a/test/JDBC/upgrade/latest/schedule b/test/JDBC/upgrade/latest/schedule index d0ca7d1eb4d..7dfe52fac56 100644 --- a/test/JDBC/upgrade/latest/schedule +++ b/test/JDBC/upgrade/latest/schedule @@ -465,6 +465,7 @@ typeid-typename-dep print_null unquoted_string doublequoted_string +operator_whitespace alter_authorization_change_db_owner sp_changedbowner float_exponent