PostgreSQL Source Code git master
Loading...
Searching...
No Matches
jsonpath_scan.l
Go to the documentation of this file.
1%top{
2/*-------------------------------------------------------------------------
3 *
4 * jsonpath_scan.l
5 * Lexical parser for jsonpath datatype
6 *
7 * Splits jsonpath string into tokens represented as JsonPathString structs.
8 * Decodes unicode and hex escaped strings.
9 *
10 * Copyright (c) 2019-2026, PostgreSQL Global Development Group
11 *
12 * IDENTIFICATION
13 * src/backend/utils/adt/jsonpath_scan.l
14 *
15 *-------------------------------------------------------------------------
16 */
17
18#include "postgres.h"
19
20/*
21 * NB: include jsonpath_gram.h only AFTER including jsonpath_internal.h,
22 * because jsonpath_internal.h contains the declaration for JsonPathString.
23 */
24#include "jsonpath_internal.h"
25#include "jsonpath_gram.h"
26
27#include "mb/pg_wchar.h"
28#include "nodes/miscnodes.h"
29#include "nodes/pg_list.h"
30}
31
32%{
34{
36};
37
38static void addstring(bool init, char *s, int l, yyscan_t yyscanner);
39static void addchar(bool init, char c, yyscan_t yyscanner);
40static enum yytokentype checkKeyword(yyscan_t yyscanner);
41static bool parseUnicode(char *s, int l, struct Node *escontext, yyscan_t yyscanner);
42static bool parseHexChar(char *s, struct Node *escontext, yyscan_t yyscanner);
43
44/* Avoid exit() on fatal scanner errors (a bit ugly -- see yy_fatal_error) */
45#undef fprintf
46#define fprintf(file, fmt, msg) fprintf_to_ereport(fmt, msg)
47
48static void
49fprintf_to_ereport(const char *fmt, const char *msg)
50{
51 ereport(ERROR, (errmsg_internal("%s", msg)));
52}
53
54/* LCOV_EXCL_START */
55
void * yyscan_t
Definition cubedata.h:65
int int errmsg_internal(const char *fmt,...) pg_attribute_printf(1
#define ERROR
Definition elog.h:40
#define ereport(elevel,...)
Definition elog.h:152
static bool parseHexChar(char *s, struct Node *escontext, yyscan_t yyscanner)
static bool parseUnicode(char *s, int l, struct Node *escontext, yyscan_t yyscanner)
static void addchar(bool init, char c, yyscan_t yyscanner)
static void fprintf_to_ereport(const char *fmt, const char *msg)
static enum yytokentype checkKeyword(yyscan_t yyscanner)
static void addstring(bool init, char *s, int l, yyscan_t yyscanner)
char * c
static int fb(int x)
#define init()
Definition nodes.h:135
JsonPathString scanstring
56%}
57
58%option 8bit
59%option never-interactive
60%option nodefault
61%option noinput
62%option nounput
63%option noyywrap
64%option warn
65%option prefix="jsonpath_yy"
66%option extra-type="struct jsonpath_yy_extra_type *"
67%option reentrant
68%option bison-bridge
69%option noyyalloc
70%option noyyrealloc
71%option noyyfree
72
73/*
74 * We use exclusive states for quoted and non-quoted strings,
75 * quoted variable names and C-style comments.
76 * Exclusive states:
77 * <xq> - quoted strings
78 * <xnq> - non-quoted strings
79 * <xvq> - quoted variable names
80 * <xc> - C-style comment
81 */
82
83%x xq
84%x xnq
85%x xvq
86%x xc
87
88special [\?\%\$\.\[\]\{\}\‍(\‍)\|\&\!\=<>\@\#\,\*:\-\+\/]
89blank [ \t\n\r\f]
90/* "other" means anything that's not special, blank, or '\' or '"' */
91other [^\?\%\$\.\[\]\{\}\‍(\‍)\|\&\!\=<>\@\#\,\*:\-\+\/\\\" \t\n\r\f]
92
93decdigit [0-9]
94hexdigit [0-9A-Fa-f]
95octdigit [0-7]
96bindigit [0-1]
97
98/* DecimalInteger in ECMAScript; must not start with 0 unless it's exactly 0 */
99decinteger (0|[1-9](_?{decdigit})*)
100/* DecimalDigits in ECMAScript; only used as part of other rules */
101decdigits {decdigit}(_?{decdigit})*
102/* Non-decimal integers; in ECMAScript, these must not have underscore after prefix */
103hexinteger 0[xX]{hexdigit}(_?{hexdigit})*
104octinteger 0[oO]{octdigit}(_?{octdigit})*
105bininteger 0[bB]{bindigit}(_?{bindigit})*
106
107decimal ({decinteger}\.{decdigits}?|\.{decdigits})
108real ({decinteger}|{decimal})[Ee][-+]?{decdigits}
109realfail ({decinteger}|{decimal})[Ee][-+]
110
111decinteger_junk {decinteger}{other}
112decimal_junk {decimal}{other}
113real_junk {real}{other}
114
115unicode \\u({hexdigit}{4}|\{{hexdigit}{1,6}\})
116unicodefail \\u({hexdigit}{0,3}|\{{hexdigit}{0,6})
117hex_char \\x{hexdigit}{2}
118hex_fail \\x{hexdigit}{0,1}
119
121
122<xnq>{other}+ {
123 addstring(false, yytext, yyleng, yyscanner);
124 }
#define yyleng
Definition scan.l:1108
125
126<xnq>{blank}+ {
127 yylval->str = yyextra->scanstring;
129 return checkKeyword(yyscanner);
130 }
#define yyextra
131
132<xnq>\/\* {
133 yylval->str = yyextra->scanstring;
134 BEGIN xc;
135 }
136
137<xnq>({special}|\") {
138 yylval->str = yyextra->scanstring;
139 yyless(0);
141 return checkKeyword(yyscanner);
142 }
143
144<xnq><<EOF>> {
145 yylval->str = yyextra->scanstring;
147 return checkKeyword(yyscanner);
148 }
149
150<xnq,xq,xvq>\\b { addchar(false, '\b', yyscanner); }
151
152<xnq,xq,xvq>\\f { addchar(false, '\f', yyscanner); }
153
154<xnq,xq,xvq>\\n { addchar(false, '\n', yyscanner); }
155
156<xnq,xq,xvq>\\r { addchar(false, '\r', yyscanner); }
157
158<xnq,xq,xvq>\\t { addchar(false, '\t', yyscanner); }
159
160<xnq,xq,xvq>\\v { addchar(false, '\v', yyscanner); }
161
162<xnq,xq,xvq>{unicode}+ {
163 if (!parseUnicode(yytext, yyleng, escontext, yyscanner))
164 yyterminate();
165 }
166
167<xnq,xq,xvq>{hex_char} {
168 if (!parseHexChar(yytext, escontext, yyscanner))
169 yyterminate();
170 }
171
172<xnq,xq,xvq>{unicode}*{unicodefail} {
173 jsonpath_yyerror(NULL, escontext, yyscanner,
174 "invalid Unicode escape sequence");
175 yyterminate();
176 }
void jsonpath_yyerror(JsonPathParseResult **result, struct Node *escontext, yyscan_t yyscanner, const char *message)
177
178<xnq,xq,xvq>{hex_fail} {
179 jsonpath_yyerror(NULL, escontext, yyscanner,
180 "invalid hexadecimal character sequence");
181 yyterminate();
182 }
183
184<xnq,xq,xvq>{unicode}+\\ {
185 /* throw back the \\, and treat as unicode */
186 yyless(yyleng - 1);
187 if (!parseUnicode(yytext, yyleng, escontext, yyscanner))
188 yyterminate();
189 }
190
191<xnq,xq,xvq>\\. { addchar(false, yytext[1], yyscanner); }
192
193<xnq,xq,xvq>\\ {
194 jsonpath_yyerror(NULL, escontext, yyscanner,
195 "unexpected end after backslash");
196 yyterminate();
197 }
198
199<xq,xvq><<EOF>> {
200 jsonpath_yyerror(NULL, escontext, yyscanner,
201 "unterminated quoted string");
202 yyterminate();
203 }
204
205<xq>\" {
206 yylval->str = yyextra->scanstring;
208 return STRING_P;
209 }
210
211<xvq>\" {
212 yylval->str = yyextra->scanstring;
214 return VARIABLE_P;
215 }
216
217<xq,xvq>[^\\\"]+ { addstring(false, yytext, yyleng, yyscanner); }
218
219<xc>\*\/ { BEGIN INITIAL; }
220
221<xc>[^\*]+ { }
222
223<xc>\* { }
224
225<xc><<EOF>> {
226 jsonpath_yyerror(NULL, escontext, yyscanner,
227 "unexpected end of comment");
228 yyterminate();
229 }
230\&\& { return AND_P; }
231
232\|\| { return OR_P; }
233
234\! { return NOT_P; }
235
236\*\* { return ANY_P; }
237
238< { return LESS_P; }
239
240<\= { return LESSEQUAL_P; }
241
242\=\= { return EQUAL_P; }
243
244<> { return NOTEQUAL_P; }
245
246\!\= { return NOTEQUAL_P; }
247
248>\= { return GREATEREQUAL_P; }
249
250> { return GREATER_P; }
251
252\${other}+ {
253 addstring(true, yytext + 1, yyleng - 1, yyscanner);
254 addchar(false, '\0', yyscanner);
255 yylval->str = yyextra->scanstring;
256 return VARIABLE_P;
257 }
258
259\$\" {
260 addchar(true, '\0', yyscanner);
261 BEGIN xvq;
262 }
263
264{special} { return *yytext; }
265
266{blank}+ { /* ignore */ }
267
268\/\* {
269 addchar(true, '\0', yyscanner);
270 BEGIN xc;
271 }
272
273{real} {
274 addstring(true, yytext, yyleng, yyscanner);
275 addchar(false, '\0', yyscanner);
276 yylval->str = yyextra->scanstring;
277 return NUMERIC_P;
278 }
279
280{decimal} {
281 addstring(true, yytext, yyleng, yyscanner);
282 addchar(false, '\0', yyscanner);
283 yylval->str = yyextra->scanstring;
284 return NUMERIC_P;
285 }
286
287{decinteger} {
288 addstring(true, yytext, yyleng, yyscanner);
289 addchar(false, '\0', yyscanner);
290 yylval->str = yyextra->scanstring;
291 return INT_P;
292 }
293
294{hexinteger} {
295 addstring(true, yytext, yyleng, yyscanner);
296 addchar(false, '\0', yyscanner);
297 yylval->str = yyextra->scanstring;
298 return INT_P;
299 }
300
301{octinteger} {
302 addstring(true, yytext, yyleng, yyscanner);
303 addchar(false, '\0', yyscanner);
304 yylval->str = yyextra->scanstring;
305 return INT_P;
306 }
307
308{bininteger} {
309 addstring(true, yytext, yyleng, yyscanner);
310 addchar(false, '\0', yyscanner);
311 yylval->str = yyextra->scanstring;
312 return INT_P;
313 }
314
315{realfail} {
316 jsonpath_yyerror(NULL, escontext, yyscanner,
317 "invalid numeric literal");
318 yyterminate();
319 }
320{decinteger_junk} {
321 jsonpath_yyerror(NULL, escontext, yyscanner,
322 "trailing junk after numeric literal");
323 yyterminate();
324 }
325{decimal_junk} {
326 jsonpath_yyerror(NULL, escontext, yyscanner,
327 "trailing junk after numeric literal");
328 yyterminate();
329 }
330{real_junk} {
331 jsonpath_yyerror(NULL, escontext, yyscanner,
332 "trailing junk after numeric literal");
333 yyterminate();
334 }
335\" {
336 addchar(true, '\0', yyscanner);
337 BEGIN xq;
338 }
339
340\\ {
341 yyless(0);
342 addchar(true, '\0', yyscanner);
343 BEGIN xnq;
344 }
345
346{other}+ {
347 addstring(true, yytext, yyleng, yyscanner);
348 BEGIN xnq;
349 }
350
351<<EOF>> { yyterminate(); }
352
353%%
354
355/* LCOV_EXCL_STOP */
356
357/* see scan.l */
358#undef yyextra
359#define yyextra (((struct yyguts_t *) yyscanner)->yyextra_r)
360
361void
363 yyscan_t yyscanner,
364 const char *message)
365{
366 struct yyguts_t *yyg = (struct yyguts_t *) yyscanner; /* needed for yytext
367 * macro */
368
369 /* don't overwrite escontext if it's already been set */
370 if (SOFT_ERROR_OCCURRED(escontext))
371 return;
372
374 {
375 errsave(escontext,
377 /* translator: %s is typically "syntax error" */
378 errmsg("%s at end of jsonpath input", _(message))));
379 }
380 else
381 {
382 errsave(escontext,
384 /* translator: first %s is typically "syntax error" */
385 errmsg("%s at or near \"%s\" of jsonpath input",
386 _(message), yytext)));
387 }
388}
389
390typedef struct JsonPathKeyword
391{
394 int val;
395 const char *keyword;
397
398/*
399 * Array of key words should be sorted by length and then
400 * alphabetical order
401 */
402static const JsonPathKeyword keywords[] = {
403 {2, false, IS_P, "is"},
404 {2, false, TO_P, "to"},
405 {3, false, ABS_P, "abs"},
406 {3, false, LAX_P, "lax"},
407 {4, false, DATE_P, "date"},
408 {4, false, FLAG_P, "flag"},
409 {4, false, LAST_P, "last"},
410 {4, true, NULL_P, "null"},
411 {4, false, SIZE_P, "size"},
412 {4, false, TIME_P, "time"},
413 {4, true, TRUE_P, "true"},
414 {4, false, TYPE_P, "type"},
415 {4, false, WITH_P, "with"},
416 {5, false, STR_BTRIM_P, "btrim"},
417 {5, true, FALSE_P, "false"},
418 {5, false, FLOOR_P, "floor"},
419 {5, false, STR_LOWER_P, "lower"},
420 {5, false, STR_LTRIM_P, "ltrim"},
421 {5, false, STR_RTRIM_P, "rtrim"},
422 {5, false, STR_UPPER_P, "upper"},
423 {6, false, BIGINT_P, "bigint"},
424 {6, false, DOUBLE_P, "double"},
425 {6, false, EXISTS_P, "exists"},
426 {6, false, NUMBER_P, "number"},
427 {6, false, STARTS_P, "starts"},
428 {6, false, STRICT_P, "strict"},
429 {6, false, STRINGFUNC_P, "string"},
430 {7, false, BOOLEAN_P, "boolean"},
431 {7, false, CEILING_P, "ceiling"},
432 {7, false, DECIMAL_P, "decimal"},
433 {7, false, STR_INITCAP_P, "initcap"},
434 {7, false, INTEGER_P, "integer"},
435 {7, false, STR_REPLACE_P, "replace"},
436 {7, false, TIME_TZ_P, "time_tz"},
437 {7, false, UNKNOWN_P, "unknown"},
438 {8, false, DATETIME_P, "datetime"},
439 {8, false, KEYVALUE_P, "keyvalue"},
440 {9, false, TIMESTAMP_P, "timestamp"},
441 {10, false, LIKE_REGEX_P, "like_regex"},
442 {10, false, STR_SPLIT_PART_P, "split_part"},
443 {12, false, TIMESTAMP_TZ_P, "timestamp_tz"},
444};
445
446/*
447 * Check if current scanstring value is a keyword
448 */
449static enum yytokentype
451{
452 int res = IDENT_P;
453 int diff;
456 *StopMiddle;
457
458 if (yyextra->scanstring.len > keywords[lengthof(keywords) - 1].len)
459 return res;
460
461 while (StopLow < StopHigh)
462 {
463 StopMiddle = StopLow + ((StopHigh - StopLow) >> 1);
464
465 if (StopMiddle->len == yyextra->scanstring.len)
466 diff = pg_strncasecmp(StopMiddle->keyword, yyextra->scanstring.val,
467 yyextra->scanstring.len);
468 else
469 diff = StopMiddle->len - yyextra->scanstring.len;
470
471 if (diff < 0)
472 StopLow = StopMiddle + 1;
473 else if (diff > 0)
475 else
476 {
477 if (StopMiddle->lowercase)
478 diff = strncmp(StopMiddle->keyword, yyextra->scanstring.val,
479 yyextra->scanstring.len);
480
481 if (diff == 0)
482 res = StopMiddle->val;
483
484 break;
485 }
486 }
487
488 return res;
489}
490
491/*
492 * Resize scanstring so that it can append string of given length.
493 * Reinitialize if required.
494 */
495static void
496resizeString(bool init, int appendLen, yyscan_t yyscanner)
497{
498 if (init)
499 {
500 yyextra->scanstring.total = Max(32, appendLen);
501 yyextra->scanstring.val = (char *) palloc(yyextra->scanstring.total);
502 yyextra->scanstring.len = 0;
503 }
504 else
505 {
506 if (yyextra->scanstring.len + appendLen >= yyextra->scanstring.total)
507 {
508 while (yyextra->scanstring.len + appendLen >= yyextra->scanstring.total)
509 yyextra->scanstring.total *= 2;
510 yyextra->scanstring.val = repalloc(yyextra->scanstring.val, yyextra->scanstring.total);
511 }
512 }
513}
514
515/* Add set of bytes at "s" of length "l" to scanstring */
516static void
517addstring(bool init, char *s, int l, yyscan_t yyscanner)
518{
519 resizeString(init, l + 1, yyscanner);
520 memcpy(yyextra->scanstring.val + yyextra->scanstring.len, s, l);
521 yyextra->scanstring.len += l;
522}
523
524/* Add single byte "c" to scanstring */
525static void
526addchar(bool init, char c, yyscan_t yyscanner)
527{
528 resizeString(init, 1, yyscanner);
529 yyextra->scanstring.val[yyextra->scanstring.len] = c;
530 if (c != '\0')
531 yyextra->scanstring.len++;
532}
533
534/* Interface to jsonpath parser */
536parsejsonpath(const char *str, int len, struct Node *escontext)
537{
539 yyscan_t scanner;
541
542 if (jsonpath_yylex_init(&scanner) != 0)
543 elog(ERROR, "yylex_init() failed: %m");
544
545 yyset_extra(&yyext, scanner);
546
547 if (len <= 0)
548 len = strlen(str);
549
550 jsonpath_yy_scan_bytes(str, len, scanner);
551
552 if (jsonpath_yyparse(&parseresult, escontext, scanner) != 0)
553 jsonpath_yyerror(NULL, escontext, scanner, "invalid input"); /* shouldn't happen */
554
555 jsonpath_yylex_destroy(scanner);
556
557 return parseresult;
558}
559
560/* Turn hex character into integer */
561static bool
562hexval(char c, int *result, struct Node *escontext, yyscan_t yyscanner)
563{
564 if (c >= '0' && c <= '9')
565 {
566 *result = c - '0';
567 return true;
568 }
569 if (c >= 'a' && c <= 'f')
570 {
571 *result = c - 'a' + 0xA;
572 return true;
573 }
574 if (c >= 'A' && c <= 'F')
575 {
576 *result = c - 'A' + 0xA;
577 return true;
578 }
579 jsonpath_yyerror(NULL, escontext, yyscanner, "invalid hexadecimal digit");
580 return false;
581}
582
583/* Add given unicode character to scanstring */
584static bool
585addUnicodeChar(char32_t ch, struct Node *escontext, yyscan_t yyscanner)
586{
587 if (ch == 0)
588 {
589 /* We can't allow this, since our TEXT type doesn't */
590 ereturn(escontext, false,
592 errmsg("unsupported Unicode escape sequence"),
593 errdetail("\\u0000 cannot be converted to text.")));
594 }
595 else
596 {
598
599 /*
600 * If we're trapping the error status, call the noerror form of the
601 * conversion function. Otherwise call the normal form which provides
602 * more detailed errors.
603 */
604
605 if (!escontext || !IsA(escontext, ErrorSaveContext))
606 pg_unicode_to_server(ch, (unsigned char *) cbuf);
607 else if (!pg_unicode_to_server_noerror(ch, (unsigned char *) cbuf))
608 ereturn(escontext, false,
610 errmsg("could not convert Unicode to server encoding")));
611 addstring(false, cbuf, strlen(cbuf), yyscanner);
612 }
613 return true;
614}
615
616/* Add unicode character, processing any surrogate pairs */
617static bool
618addUnicode(char32_t ch, int *hi_surrogate, struct Node *escontext, yyscan_t yyscanner)
619{
621 {
622 if (*hi_surrogate != -1)
623 ereturn(escontext, false,
625 errmsg("invalid input syntax for type %s", "jsonpath"),
626 errdetail("Unicode high surrogate must not follow "
627 "a high surrogate.")));
628 *hi_surrogate = ch;
629 return true;
630 }
632 {
633 if (*hi_surrogate == -1)
634 ereturn(escontext, false,
636 errmsg("invalid input syntax for type %s", "jsonpath"),
637 errdetail("Unicode low surrogate must follow a high "
638 "surrogate.")));
640 *hi_surrogate = -1;
641 }
642 else if (*hi_surrogate != -1)
643 {
644 ereturn(escontext, false,
646 errmsg("invalid input syntax for type %s", "jsonpath"),
647 errdetail("Unicode low surrogate must follow a high "
648 "surrogate.")));
649 }
650
651 return addUnicodeChar(ch, escontext, yyscanner);
652}
653
654/*
655 * parseUnicode was adopted from json_lex_string() in
656 * src/backend/utils/adt/json.c
657 */
658static bool
659parseUnicode(char *s, int l, struct Node *escontext, yyscan_t yyscanner)
660{
661 int i = 2;
662 int hi_surrogate = -1;
663
664 for (i = 2; i < l; i += 2) /* skip '\u' */
665 {
666 char32_t ch = 0;
667 int j,
668 si;
669
670 if (s[i] == '{') /* parse '\u{XX...}' */
671 {
672 while (s[++i] != '}' && i < l)
673 {
674 if (!hexval(s[i], &si, escontext, yyscanner))
675 return false;
676 ch = (ch << 4) | si;
677 }
678 i++; /* skip '}' */
679 }
680 else /* parse '\uXXXX' */
681 {
682 for (j = 0; j < 4 && i < l; j++)
683 {
684 if (!hexval(s[i++], &si, escontext, yyscanner))
685 return false;
686 ch = (ch << 4) | si;
687 }
688 }
689
690 if (!addUnicode(ch, &hi_surrogate, escontext, yyscanner))
691 return false;
692 }
693
694 if (hi_surrogate != -1)
695 {
696 ereturn(escontext, false,
698 errmsg("invalid input syntax for type %s", "jsonpath"),
699 errdetail("Unicode low surrogate must follow a high "
700 "surrogate.")));
701 }
702
703 return true;
704}
705
706/* Parse sequence of hex-encoded characters */
707static bool
708parseHexChar(char *s, struct Node *escontext, yyscan_t yyscanner)
709{
710 int s2,
711 s3,
712 ch;
713
714 if (!hexval(s[2], &s2, escontext, yyscanner))
715 return false;
716 if (!hexval(s[3], &s3, escontext, yyscanner))
717 return false;
718
719 ch = (s2 << 4) | s3;
720
721 return addUnicodeChar(ch, escontext, yyscanner);
722}
723
724/*
725 * Interface functions to make flex use palloc() instead of malloc().
726 * It'd be better to make these static, but flex insists otherwise.
727 */
728
729void *
731{
732 return palloc(bytes);
733}
734
735void *
736jsonpath_yyrealloc(void *ptr, yy_size_t bytes, yyscan_t yyscanner)
737{
738 if (ptr)
739 return repalloc(ptr, bytes);
740 else
741 return palloc(bytes);
742}
743
744void
745jsonpath_yyfree(void *ptr, yyscan_t yyscanner)
746{
747 if (ptr)
748 pfree(ptr);
749}
#define Max(x, y)
Definition c.h:1085
int16_t int16
Definition c.h:619
#define lengthof(array)
Definition c.h:873
uint32 result
memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets))
int errcode(int sqlerrcode)
Definition elog.c:874
#define _(x)
Definition elog.c:95
#define ereturn(context, dummy_value,...)
Definition elog.h:280
#define errsave(context,...)
Definition elog.h:264
int errdetail(const char *fmt,...) pg_attribute_printf(1
#define elog(elevel,...)
Definition elog.h:228
const char * str
int j
Definition isn.c:78
int i
Definition isn.c:77
TestSpec parseresult
int jsonpath_yyparse(JsonPathParseResult **result, struct Node *escontext, yyscan_t yyscanner)
static void resizeString(bool init, int appendLen, yyscan_t yyscanner)
void jsonpath_yyfree(void *ptr, yyscan_t yyscanner)
void * jsonpath_yyrealloc(void *ptr, yy_size_t bytes, yyscan_t yyscanner)
JsonPathParseResult * parsejsonpath(const char *str, int len, struct Node *escontext)
static const JsonPathKeyword keywords[]
static bool addUnicodeChar(char32_t ch, struct Node *escontext, yyscan_t yyscanner)
void * jsonpath_yyalloc(yy_size_t bytes, yyscan_t yyscanner)
static bool hexval(char c, int *result, struct Node *escontext, yyscan_t yyscanner)
static bool addUnicode(char32_t ch, int *hi_surrogate, struct Node *escontext, yyscan_t yyscanner)
bool pg_unicode_to_server_noerror(char32_t c, unsigned char *s)
Definition mbutils.c:937
void pg_unicode_to_server(char32_t c, unsigned char *s)
Definition mbutils.c:875
void * repalloc(void *pointer, Size size)
Definition mcxt.c:1632
void pfree(void *pointer)
Definition mcxt.c:1616
void * palloc(Size size)
Definition mcxt.c:1387
#define SOFT_ERROR_OCCURRED(escontext)
Definition miscnodes.h:53
#define IsA(nodeptr, _type_)
Definition nodes.h:164
static char * errmsg
const void size_t len
static bool is_utf16_surrogate_first(char32_t c)
Definition pg_wchar.h:378
static bool is_utf16_surrogate_second(char32_t c)
Definition pg_wchar.h:384
static char32_t surrogate_pair_to_codepoint(char16_t first, char16_t second)
Definition pg_wchar.h:390
#define MAX_UNICODE_EQUIVALENT_STRING
Definition pg_wchar.h:182
int pg_strncasecmp(const char *s1, const char *s2, size_t n)
char * s2
char * s3
const char * keyword