Skip to content

Commit a63a930

Browse files
authored
Updated escape logic in quotename (#3857)
Issue Description: In Babelfish, the QUOTENAME function currently produces incorrect results for many queries due to flaws in its escape character handling logic. The function fails to properly escape characters that match the right delimiter. Also handle Unicode character handling in delimeter. Changes logic to accept fetch first character from delimeter string and use it as delimeter This PR is cherry-pick from 5_X_DEV to 4_X_DEV branch: #3817 Solution: The escape logic has been updated to properly handle special characters. Now, when QUOTENAME encounters any character within the input string that matches the right delimiter, it correctly escapes that character. Updated logic to check byte size instead of len check. Issues Resolved :BABEL-2311 Signed-off-by: Herambh Shah <herambhs@amazon.com>
1 parent 83a1131 commit a63a930

File tree

8 files changed

+329
-39
lines changed

8 files changed

+329
-39
lines changed

contrib/babelfishpg_tsql/src/string.c

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -172,24 +172,32 @@ Datum
172172
quotename(PG_FUNCTION_ARGS)
173173
{
174174
const char *input_string = text_to_cstring(PG_GETARG_TEXT_P(0));
175-
const char *delimiter = text_to_cstring(PG_GETARG_TEXT_P(1));
176-
175+
text *delimiter_text = PG_GETARG_TEXT_P(1);
176+
const char *delimiter_str = text_to_cstring(delimiter_text);
177+
177178
char left_delim;
178179
char right_delim;
179180
char *buf;
180181
int buf_i = 0;
182+
char first_char;
181183

182184
/* Validate input len */
183185
if (strlen(input_string) > 128)
184186
{
185187
PG_RETURN_NULL();
186188
}
187-
if (strlen(delimiter) != 1)
189+
190+
if(VARSIZE_ANY_EXHDR(delimiter_text) == 0)
188191
{
189-
PG_RETURN_NULL();
192+
first_char = ']';
193+
}
194+
else
195+
{
196+
/* Extract first character (byte) only */
197+
first_char = delimiter_str[0];
190198
}
191199

192-
switch (*delimiter)
200+
switch (first_char)
193201
{
194202
case ']':
195203
case '[':
@@ -199,8 +207,8 @@ quotename(PG_FUNCTION_ARGS)
199207
case '`':
200208
case '\'':
201209
case '"':
202-
left_delim = *delimiter;
203-
right_delim = *delimiter;
210+
left_delim = first_char;
211+
right_delim = first_char;
204212
break;
205213
case '(':
206214
case ')':
@@ -209,8 +217,8 @@ quotename(PG_FUNCTION_ARGS)
209217
break;
210218
case '<':
211219
case '>':
212-
left_delim = '>';
213-
right_delim = '<';
220+
left_delim = '<';
221+
right_delim = '>';
214222
break;
215223
case '{':
216224
case '}':
@@ -230,17 +238,16 @@ quotename(PG_FUNCTION_ARGS)
230238
buf[buf_i++] = left_delim;
231239
for (int i = 0; i < strlen(input_string); i++)
232240
{
233-
switch (input_string[i])
241+
if (input_string[i] == right_delim)
234242
{
235-
/* Escape chars */
236-
case '\'':
237-
case ']':
238-
case '"':
239-
buf[buf_i++] = input_string[i];
240-
buf[buf_i++] = input_string[i];
241-
break;
242-
default:
243-
buf[buf_i++] = input_string[i];
243+
/* Escape the delimiter character by doubling it */
244+
buf[buf_i++] = input_string[i];
245+
buf[buf_i++] = input_string[i];
246+
}
247+
else
248+
{
249+
/* Copy character as is */
250+
buf[buf_i++] = input_string[i];
244251
}
245252
}
246253
buf[buf_i++] = right_delim;

test/JDBC/expected/Datetime_system_functions.out

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1415,7 +1415,7 @@ GO
14151415

14161416
-- Test 15: Testing comparison with local time
14171417
SELECT
1418-
CASE WHEN ABS(DATEDIFF(HOUR, SYSUTCDATETIME(), SYSDATETIME())) =
1418+
CASE WHEN ABS(DATEDIFF(HOUR, SYSUTCDATETIME(), SYSDATETIME())) >
14191419
ABS(DATEPART(HOUR, SYSDATETIMEOFFSET()))
14201420
THEN 'PASS: UTC offset matches system timezone'
14211421
ELSE 'FAIL: UTC offset inconsistency'

test/JDBC/expected/babel_function_string-before-15-5-or-14-10-vu-verify.out

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -187,15 +187,15 @@ SELECT quotename('gershwin', '<')
187187
GO
188188
~~START~~
189189
nvarchar
190-
>gershwin<
190+
<gershwin>
191191
~~END~~
192192

193193

194194
SELECT quotename('faulkner', '>')
195195
GO
196196
~~START~~
197197
nvarchar
198-
>faulkner<
198+
<faulkner>
199199
~~END~~
200200

201201

@@ -261,15 +261,15 @@ quotename('"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
261261
GO
262262
~~START~~
263263
nvarchar
264-
[""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""]
264+
[""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""]
265265
~~END~~
266266

267267

268268
SELECT quotename('''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''')
269269
GO
270270
~~START~~
271271
nvarchar
272-
['''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''']
272+
['''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''']
273273
~~END~~
274274

275275

test/JDBC/expected/babel_function_string-vu-verify.out

Lines changed: 207 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -187,15 +187,15 @@ SELECT quotename('gershwin', '<')
187187
GO
188188
~~START~~
189189
nvarchar
190-
>gershwin<
190+
<gershwin>
191191
~~END~~
192192

193193

194194
SELECT quotename('faulkner', '>')
195195
GO
196196
~~START~~
197197
nvarchar
198-
>faulkner<
198+
<faulkner>
199199
~~END~~
200200

201201

@@ -261,15 +261,15 @@ quotename('"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
261261
GO
262262
~~START~~
263263
nvarchar
264-
[""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""]
264+
[""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""]
265265
~~END~~
266266

267267

268268
SELECT quotename('''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''')
269269
GO
270270
~~START~~
271271
nvarchar
272-
['''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''']
272+
['''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''']
273273
~~END~~
274274

275275

@@ -385,6 +385,209 @@ nvarchar
385385
~~END~~
386386

387387

388+
SELECT QUOTENAME('Hello ) there', ')')
389+
GO
390+
~~START~~
391+
nvarchar
392+
(Hello )) there)
393+
~~END~~
394+
395+
396+
SELECT QUOTENAME('Hello )" there', ')')
397+
GO
398+
~~START~~
399+
nvarchar
400+
(Hello ))" there)
401+
~~END~~
402+
403+
404+
SELECT QUOTENAME('Hello < there', '<')
405+
GO
406+
~~START~~
407+
nvarchar
408+
<Hello < there>
409+
~~END~~
410+
411+
412+
SELECT QUOTENAME('Hello > there', '>')
413+
GO
414+
~~START~~
415+
nvarchar
416+
<Hello >> there>
417+
~~END~~
418+
419+
420+
SELECT QUOTENAME('Hello } there', '}')
421+
GO
422+
~~START~~
423+
nvarchar
424+
{Hello }} there}
425+
~~END~~
426+
427+
428+
SELECT QUOTENAME('Hello ` there', '`')
429+
GO
430+
~~START~~
431+
nvarchar
432+
`Hello `` there`
433+
~~END~~
434+
435+
436+
SELECT QUOTENAME('[KEY]', '"')
437+
GO
438+
~~START~~
439+
nvarchar
440+
"[KEY]"
441+
~~END~~
442+
443+
444+
SELECT QUOTENAME('"KEY"', '[')
445+
GO
446+
~~START~~
447+
nvarchar
448+
["KEY"]
449+
~~END~~
450+
451+
452+
SELECT QUOTENAME('"KEY"', '')
453+
GO
454+
~~START~~
455+
nvarchar
456+
["KEY"]
457+
~~END~~
458+
459+
460+
-- test quotename with multibyte characters
461+
SELECT quotename('こんにちは')
462+
GO
463+
~~START~~
464+
nvarchar
465+
[こんにちは]
466+
~~END~~
467+
468+
469+
SELECT quotename('测试中文', '"')
470+
GO
471+
~~START~~
472+
nvarchar
473+
"测试中文"
474+
~~END~~
475+
476+
477+
SELECT quotename('café')
478+
GO
479+
~~START~~
480+
nvarchar
481+
[café]
482+
~~END~~
483+
484+
485+
SELECT quotename('Москва', '}{')
486+
GO
487+
~~START~~
488+
nvarchar
489+
{Москва}
490+
~~END~~
491+
492+
493+
SELECT quotename('Émojis🚀🌟')
494+
GO
495+
~~START~~
496+
nvarchar
497+
[Émojis🚀🌟]
498+
~~END~~
499+
500+
501+
SELECT quotename('Mixed英文中文')
502+
GO
503+
~~START~~
504+
nvarchar
505+
[Mixed英文中文]
506+
~~END~~
507+
508+
509+
-- test quotename with multibyte characters and different quote chars
510+
SELECT quotename('こんにちは', '"')
511+
GO
512+
~~START~~
513+
nvarchar
514+
"こんにちは"
515+
~~END~~
516+
517+
518+
SELECT quotename('测试中文', '''')
519+
GO
520+
~~START~~
521+
nvarchar
522+
'测试中文'
523+
~~END~~
524+
525+
526+
SELECT quotename('café', '>')
527+
GO
528+
~~START~~
529+
nvarchar
530+
<café>
531+
~~END~~
532+
533+
534+
SELECT quotename('Москва', '}')
535+
GO
536+
~~START~~
537+
nvarchar
538+
{Москва}
539+
~~END~~
540+
541+
542+
SELECT quotename('العربية', '`')
543+
GO
544+
~~START~~
545+
nvarchar
546+
`العربية`
547+
~~END~~
548+
549+
550+
-- test different size delimeter
551+
SELECT quotename('こん"にちは', '["')
552+
GO
553+
~~START~~
554+
nvarchar
555+
[こん"にちは]
556+
~~END~~
557+
558+
559+
SELECT quotename('test''中文', '[%&69]')
560+
GO
561+
~~START~~
562+
nvarchar
563+
[test'中文]
564+
~~END~~
565+
566+
567+
SELECT quotename('café]test', '''')
568+
GO
569+
~~START~~
570+
nvarchar
571+
'café]test'
572+
~~END~~
573+
574+
575+
SELECT quotename('Москва}test', '}{^$[]}')
576+
GO
577+
~~START~~
578+
nvarchar
579+
{Москва}}test}
580+
~~END~~
581+
582+
583+
SELECT quotename('Москва}test', 'Ğ🚀🌟')
584+
GO
585+
~~START~~
586+
nvarchar
587+
<NULL>
588+
~~END~~
589+
590+
388591

389592
-- test unicode function
390593
SELECT unicode(null)

0 commit comments

Comments
 (0)