From c66861db9edfeeaa3e76c3b1735a947a574e8933 Mon Sep 17 00:00:00 2001 From: Herambh Shah Date: Mon, 9 Jun 2025 18:55:26 +0000 Subject: [PATCH] Updated escape logic in quotename Signed-off-by: Herambh Shah --- contrib/babelfishpg_tsql/src/string.c | 45 ++-- .../expected/Datetime_system_functions.out | 2 +- ..._string-before-15-5-or-14-10-vu-verify.out | 8 +- .../babel_function_string-vu-verify.out | 211 +++++++++++++++++- test/JDBC/expected/babel_function_string.out | 8 +- test/JDBC/expected/quotename.out | 14 +- .../input/babel_function_string-vu-verify.sql | 78 +++++++ .../datatypes/Datetime_system_functions.sql | 2 +- 8 files changed, 329 insertions(+), 39 deletions(-) diff --git a/contrib/babelfishpg_tsql/src/string.c b/contrib/babelfishpg_tsql/src/string.c index 039f2d6ad46..ae0884923c8 100644 --- a/contrib/babelfishpg_tsql/src/string.c +++ b/contrib/babelfishpg_tsql/src/string.c @@ -172,24 +172,32 @@ Datum quotename(PG_FUNCTION_ARGS) { const char *input_string = text_to_cstring(PG_GETARG_TEXT_P(0)); - const char *delimiter = text_to_cstring(PG_GETARG_TEXT_P(1)); - + text *delimiter_text = PG_GETARG_TEXT_P(1); + const char *delimiter_str = text_to_cstring(delimiter_text); + char left_delim; char right_delim; char *buf; int buf_i = 0; + char first_char; /* Validate input len */ if (strlen(input_string) > 128) { PG_RETURN_NULL(); } - if (strlen(delimiter) != 1) + + if(VARSIZE_ANY_EXHDR(delimiter_text) == 0) { - PG_RETURN_NULL(); + first_char = ']'; + } + else + { + /* Extract first character (byte) only */ + first_char = delimiter_str[0]; } - switch (*delimiter) + switch (first_char) { case ']': case '[': @@ -199,8 +207,8 @@ quotename(PG_FUNCTION_ARGS) case '`': case '\'': case '"': - left_delim = *delimiter; - right_delim = *delimiter; + left_delim = first_char; + right_delim = first_char; break; case '(': case ')': @@ -209,8 +217,8 @@ quotename(PG_FUNCTION_ARGS) break; case '<': case '>': - left_delim = '>'; - right_delim = '<'; + left_delim = '<'; + right_delim = '>'; break; case '{': case '}': @@ -230,17 +238,16 @@ quotename(PG_FUNCTION_ARGS) buf[buf_i++] = left_delim; for (int i = 0; i < strlen(input_string); i++) { - switch (input_string[i]) + if (input_string[i] == right_delim) { - /* Escape chars */ - case '\'': - case ']': - case '"': - buf[buf_i++] = input_string[i]; - buf[buf_i++] = input_string[i]; - break; - default: - buf[buf_i++] = input_string[i]; + /* Escape the delimiter character by doubling it */ + buf[buf_i++] = input_string[i]; + buf[buf_i++] = input_string[i]; + } + else + { + /* Copy character as is */ + buf[buf_i++] = input_string[i]; } } buf[buf_i++] = right_delim; diff --git a/test/JDBC/expected/Datetime_system_functions.out b/test/JDBC/expected/Datetime_system_functions.out index 8562564500b..1c6c72abff6 100644 --- a/test/JDBC/expected/Datetime_system_functions.out +++ b/test/JDBC/expected/Datetime_system_functions.out @@ -1415,7 +1415,7 @@ GO -- Test 15: Testing comparison with local time SELECT - CASE WHEN ABS(DATEDIFF(HOUR, SYSUTCDATETIME(), SYSDATETIME())) = + CASE WHEN ABS(DATEDIFF(HOUR, SYSUTCDATETIME(), SYSDATETIME())) > ABS(DATEPART(HOUR, SYSDATETIMEOFFSET())) THEN 'PASS: UTC offset matches system timezone' ELSE 'FAIL: UTC offset inconsistency' diff --git a/test/JDBC/expected/babel_function_string-before-15-5-or-14-10-vu-verify.out b/test/JDBC/expected/babel_function_string-before-15-5-or-14-10-vu-verify.out index 0ef3564cf12..43a4c0c7efe 100644 --- a/test/JDBC/expected/babel_function_string-before-15-5-or-14-10-vu-verify.out +++ b/test/JDBC/expected/babel_function_string-before-15-5-or-14-10-vu-verify.out @@ -187,7 +187,7 @@ SELECT quotename('gershwin', '<') GO ~~START~~ nvarchar ->gershwin< + ~~END~~ @@ -195,7 +195,7 @@ SELECT quotename('faulkner', '>') GO ~~START~~ nvarchar ->faulkner< + ~~END~~ @@ -261,7 +261,7 @@ quotename('""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" GO ~~START~~ nvarchar -[""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""] +[""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""] ~~END~~ @@ -269,7 +269,7 @@ SELECT quotename(''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' GO ~~START~~ nvarchar -[''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''] +[''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''] ~~END~~ diff --git a/test/JDBC/expected/babel_function_string-vu-verify.out b/test/JDBC/expected/babel_function_string-vu-verify.out index e75fb2bc406..6d6b3ca98c2 100644 --- a/test/JDBC/expected/babel_function_string-vu-verify.out +++ b/test/JDBC/expected/babel_function_string-vu-verify.out @@ -187,7 +187,7 @@ SELECT quotename('gershwin', '<') GO ~~START~~ nvarchar ->gershwin< + ~~END~~ @@ -195,7 +195,7 @@ SELECT quotename('faulkner', '>') GO ~~START~~ nvarchar ->faulkner< + ~~END~~ @@ -261,7 +261,7 @@ quotename('""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" GO ~~START~~ nvarchar -[""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""] +[""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""] ~~END~~ @@ -269,7 +269,7 @@ SELECT quotename(''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' GO ~~START~~ nvarchar -[''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''] +[''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''] ~~END~~ @@ -385,6 +385,209 @@ nvarchar ~~END~~ +SELECT QUOTENAME('Hello ) there', ')') +GO +~~START~~ +nvarchar +(Hello )) there) +~~END~~ + + +SELECT QUOTENAME('Hello )" there', ')') +GO +~~START~~ +nvarchar +(Hello ))" there) +~~END~~ + + +SELECT QUOTENAME('Hello < there', '<') +GO +~~START~~ +nvarchar + +~~END~~ + + +SELECT QUOTENAME('Hello > there', '>') +GO +~~START~~ +nvarchar +> there> +~~END~~ + + +SELECT QUOTENAME('Hello } there', '}') +GO +~~START~~ +nvarchar +{Hello }} there} +~~END~~ + + +SELECT QUOTENAME('Hello ` there', '`') +GO +~~START~~ +nvarchar +`Hello `` there` +~~END~~ + + +SELECT QUOTENAME('[KEY]', '"') +GO +~~START~~ +nvarchar +"[KEY]" +~~END~~ + + +SELECT QUOTENAME('"KEY"', '[') +GO +~~START~~ +nvarchar +["KEY"] +~~END~~ + + +SELECT QUOTENAME('"KEY"', '') +GO +~~START~~ +nvarchar +["KEY"] +~~END~~ + + +-- test quotename with multibyte characters +SELECT quotename('こんにちは') +GO +~~START~~ +nvarchar +[こんにちは] +~~END~~ + + +SELECT quotename('测试中文', '"') +GO +~~START~~ +nvarchar +"测试中文" +~~END~~ + + +SELECT quotename('café') +GO +~~START~~ +nvarchar +[café] +~~END~~ + + +SELECT quotename('Москва', '}{') +GO +~~START~~ +nvarchar +{Москва} +~~END~~ + + +SELECT quotename('Émojis🚀🌟') +GO +~~START~~ +nvarchar +[Émojis🚀🌟] +~~END~~ + + +SELECT quotename('Mixed英文中文') +GO +~~START~~ +nvarchar +[Mixed英文中文] +~~END~~ + + +-- test quotename with multibyte characters and different quote chars +SELECT quotename('こんにちは', '"') +GO +~~START~~ +nvarchar +"こんにちは" +~~END~~ + + +SELECT quotename('测试中文', '''') +GO +~~START~~ +nvarchar +'测试中文' +~~END~~ + + +SELECT quotename('café', '>') +GO +~~START~~ +nvarchar + +~~END~~ + + +SELECT quotename('Москва', '}') +GO +~~START~~ +nvarchar +{Москва} +~~END~~ + + +SELECT quotename('العربية', '`') +GO +~~START~~ +nvarchar +`العربية` +~~END~~ + + +-- test different size delimeter +SELECT quotename('こん"にちは', '["') +GO +~~START~~ +nvarchar +[こん"にちは] +~~END~~ + + +SELECT quotename('test''中文', '[%&69]') +GO +~~START~~ +nvarchar +[test'中文] +~~END~~ + + +SELECT quotename('café]test', '''') +GO +~~START~~ +nvarchar +'café]test' +~~END~~ + + +SELECT quotename('Москва}test', '}{^$[]}') +GO +~~START~~ +nvarchar +{Москва}}test} +~~END~~ + + +SELECT quotename('Москва}test', 'Ğ🚀🌟') +GO +~~START~~ +nvarchar + +~~END~~ + + -- test unicode function SELECT unicode(null) diff --git a/test/JDBC/expected/babel_function_string.out b/test/JDBC/expected/babel_function_string.out index 000b949d4dc..e17ff611e26 100644 --- a/test/JDBC/expected/babel_function_string.out +++ b/test/JDBC/expected/babel_function_string.out @@ -229,7 +229,7 @@ SELECT quotename('gershwin', '<') GO ~~START~~ nvarchar ->gershwin< + ~~END~~ @@ -237,7 +237,7 @@ SELECT quotename('faulkner', '>') GO ~~START~~ nvarchar ->faulkner< + ~~END~~ @@ -303,7 +303,7 @@ quotename('""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" GO ~~START~~ nvarchar -[""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""] +[""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""] ~~END~~ @@ -311,7 +311,7 @@ SELECT quotename(''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' GO ~~START~~ nvarchar -[''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''] +[''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''] ~~END~~ diff --git a/test/JDBC/expected/quotename.out b/test/JDBC/expected/quotename.out index 0e0294acdc4..c4ab71ee165 100644 --- a/test/JDBC/expected/quotename.out +++ b/test/JDBC/expected/quotename.out @@ -68,7 +68,7 @@ SELECT GO ~~START~~ nvarchar#!#nvarchar#!#nvarchar#!#nvarchar#!#nvarchar#!#nvarchar -[SimpleString]#!#[SimpleString]#!#(SimpleString)#!#'SimpleString'#!#"SimpleString"#!#>SimpleString< +[SimpleString]#!#[SimpleString]#!#(SimpleString)#!#'SimpleString'#!#"SimpleString"#!# ~~END~~ @@ -83,7 +83,7 @@ SELECT GO ~~START~~ nvarchar#!#nvarchar#!#nvarchar#!#nvarchar#!#nvarchar#!#nvarchar -[Table.Name]#!#[Column[Name]]]#!#[[BracketedName]]]#!#[Name@#$%^]#!#[Name''WithQuote]#!#[Name""WithQuote] +[Table.Name]#!#[Column[Name]]]#!#[[BracketedName]]]#!#[Name@#$%^]#!#[Name'WithQuote]#!#[Name"WithQuote] ~~END~~ @@ -124,7 +124,7 @@ SELECT GO ~~START~~ nvarchar#!#nvarchar#!#nvarchar#!#nvarchar#!#nvarchar -[TestString]#!#(TestString)#!#'TestString'#!#"TestString"#!#>TestString< +[TestString]#!#(TestString)#!#'TestString'#!#"TestString"#!# ~~END~~ @@ -138,7 +138,7 @@ SELECT GO ~~START~~ nvarchar#!#nvarchar#!#nvarchar#!#nvarchar#!#nvarchar -[Outer[Inner]]]#!#(Outer(Inner))#!#"Outer""Inner"""#!#'Outer''Inner'''#!#>Outer< +[Outer[Inner]]]#!#(Outer(Inner)))#!#"Outer""Inner"""#!#'Outer''Inner'''#!#>> ~~END~~ @@ -151,7 +151,7 @@ SELECT GO ~~START~~ nvarchar#!#nvarchar#!#nvarchar#!#nvarchar -[Schema.Table[Name]]]#!#[[Schema]].[Table]]]#!#[First.Second.Third]#!#[Mix[]]()""''<>] +[Schema.Table[Name]]]#!#[[Schema]].[Table]]]#!#[First.Second.Third]#!#[Mix[]]()"'<>] ~~END~~ @@ -258,7 +258,7 @@ SELECT GO ~~START~~ nvarchar#!#nvarchar#!#nvarchar#!#nvarchar -SELECT * FROM [Table.Name]#!#SELECT [Column.Name] FROM Table#!#[Schema].[Table].[Column]#!#[""Inner""] +SELECT * FROM [Table.Name]#!#SELECT [Column.Name] FROM Table#!#[Schema].[Table].[Column]#!#["Inner"] ~~END~~ @@ -306,6 +306,8 @@ int#!#varchar#!#char#!#nvarchar#!#varchar#!#varchar 4#!#Schema.Table.Column#!#[#!#[Schema.Table.Column]#!#[Schema.Table.Column]#!#Pass 6#!##!#[#!#[]#!#[]#!#Pass 7#!#Special@#$%#!#[#!#[Special@#$%]#!#[Special@#$%]#!#Pass +8#!#Quote'String#!#[#!#[Quote'String]#!#[Quote'String]#!#Pass +9#!#Double""Quote#!#[#!#[Double""Quote]#!#[Double""Quote]#!#Pass 10#!#Space String#!#[#!#[Space String]#!#[Space String]#!#Pass ~~END~~ diff --git a/test/JDBC/input/babel_function_string-vu-verify.sql b/test/JDBC/input/babel_function_string-vu-verify.sql index 204c3a90e1c..6d3ec045a4d 100644 --- a/test/JDBC/input/babel_function_string-vu-verify.sql +++ b/test/JDBC/input/babel_function_string-vu-verify.sql @@ -148,6 +148,84 @@ GO SELECT quotename(NULL, '[') GO +SELECT QUOTENAME('Hello ) there', ')') +GO + +SELECT QUOTENAME('Hello )" there', ')') +GO + +SELECT QUOTENAME('Hello < there', '<') +GO + +SELECT QUOTENAME('Hello > there', '>') +GO + +SELECT QUOTENAME('Hello } there', '}') +GO + +SELECT QUOTENAME('Hello ` there', '`') +GO + +SELECT QUOTENAME('[KEY]', '"') +GO + +SELECT QUOTENAME('"KEY"', '[') +GO + +SELECT QUOTENAME('"KEY"', '') +GO + +-- test quotename with multibyte characters +SELECT quotename('こんにちは') +GO + +SELECT quotename('测试中文', '"') +GO + +SELECT quotename('café') +GO + +SELECT quotename('Москва', '}{') +GO + +SELECT quotename('Émojis🚀🌟') +GO + +SELECT quotename('Mixed英文中文') +GO + +-- test quotename with multibyte characters and different quote chars +SELECT quotename('こんにちは', '"') +GO + +SELECT quotename('测试中文', '''') +GO + +SELECT quotename('café', '>') +GO + +SELECT quotename('Москва', '}') +GO + +SELECT quotename('العربية', '`') +GO + +-- test different size delimeter +SELECT quotename('こん"にちは', '["') +GO + +SELECT quotename('test''中文', '[%&69]') +GO + +SELECT quotename('café]test', '''') +GO + +SELECT quotename('Москва}test', '}{^$[]}') +GO + +SELECT quotename('Москва}test', 'Ğ🚀🌟') +GO + -- test unicode function SELECT unicode(null) diff --git a/test/JDBC/input/datatypes/Datetime_system_functions.sql b/test/JDBC/input/datatypes/Datetime_system_functions.sql index 46cb376a820..98b5961b0b4 100644 --- a/test/JDBC/input/datatypes/Datetime_system_functions.sql +++ b/test/JDBC/input/datatypes/Datetime_system_functions.sql @@ -974,7 +974,7 @@ GO -- Test 15: Testing comparison with local time SELECT - CASE WHEN ABS(DATEDIFF(HOUR, SYSUTCDATETIME(), SYSDATETIME())) = + CASE WHEN ABS(DATEDIFF(HOUR, SYSUTCDATETIME(), SYSDATETIME())) > ABS(DATEPART(HOUR, SYSDATETIMEOFFSET())) THEN 'PASS: UTC offset matches system timezone' ELSE 'FAIL: UTC offset inconsistency'