CUBRID Engine  latest
shard_parser.c
Go to the documentation of this file.
1 /*
2  * Copyright 2008 Search Solution Corporation
3  * Copyright 2016 CUBRID Corporation
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 
20 /*
21  * shard_parser.c -
22  *
23  */
24 
25 #ident "$Id$"
26 
27 
28 #include "shard_parser.h"
29 #include "shard_proxy_log.h"
30 
31 #if defined(WINDOWS)
32 static const char *left_trim (const char *str);
33 #else /* WINDOWS */
34 static inline const char *left_trim (const char *str);
35 #endif /* !WINDOWS */
36 
37 static int sp_init_sp_value (SP_VALUE * value_p);
38 static void sp_free_sp_value (SP_VALUE * value_p);
39 static int sp_make_sp_value (SP_VALUE * value_p, const char *pos, int length);
40 static int sp_make_string_sp_value (SP_VALUE * value_p, const char *pos, int length);
41 static int sp_make_int_sp_value_from_string (SP_VALUE * value_p, char *pos, int length);
42 
43 
45 static void sp_append_parser_hint_to_ctx (SP_PARSER_CTX * parser_p, SP_PARSER_HINT * hint_p);
46 static int sp_parse_sql_internal (SP_PARSER_CTX * parser_p);
47 
48 static void sp_free_parser_hint_from_ctx (SP_PARSER_CTX * parser_p);
49 static int sp_process_token (SP_PARSER_CTX * parser_p, SP_TOKEN token_type);
50 static int sp_get_bind_type_and_value (SP_PARSER_CTX * parser_p, SP_PARSER_HINT * hint_p);
51 #if defined(WINDOWS)
52 static void sp_copy_cursor_to_prv (SP_PARSER_CTX * parser_p);
53 #else /* WINDOWS */
54 static inline void sp_copy_cursor_to_prv (SP_PARSER_CTX * parser_p);
55 #endif /* !WINDOWS */
56 static int sp_get_string_bind_value (SP_PARSER_CTX * parser_p, SP_PARSER_HINT * hint_p);
57 static int sp_get_int_bind_value (SP_PARSER_CTX * parser_p, SP_PARSER_HINT * hint_p);
58 static int sp_is_valid_hint (SP_PARSER_CTX * parser_p, SP_PARSER_HINT * hint_p);
59 static bool sp_is_start_token (SP_TOKEN token);
60 
61 
63 sp_create_parser (const char *sql_stmt)
64 {
65  SP_PARSER_CTX *parser_p = (SP_PARSER_CTX *) malloc (sizeof (SP_PARSER_CTX));
66  if (parser_p == NULL)
67  {
68  PROXY_LOG (PROXY_LOG_MODE_ERROR, "Not enough virtual memory. failed to malloc parser context. " "(size:%d). \n",
69  sizeof (SP_PARSER_CTX));
70  return NULL;
71  }
72 
73  parser_p->sql_stmt = strdup (sql_stmt);
74  if (parser_p->sql_stmt == NULL)
75  {
76  free (parser_p);
77  PROXY_LOG (PROXY_LOG_MODE_ERROR, "Not enough virtual memory. failed to strdup sql statement. " "(sql_stmt:[%s]).",
78  sql_stmt);
79  return NULL;
80  }
81  parser_p->is_select = false;
82  parser_p->bind_count = 0;
83  parser_p->cursor.pos = parser_p->sql_stmt;
84  parser_p->cursor.token = TT_NONE;
85  parser_p->prv_cursor.pos = parser_p->sql_stmt;
86  parser_p->prv_cursor.token = TT_NONE;
87  parser_p->operator_ = TT_NONE;
88  sp_init_praser_hint_list (&parser_p->list_a);
91 
92  return parser_p;
93 }
94 
95 int
97 {
98  int error = NO_ERROR;
99 
100  error = sp_parse_sql_internal (parser_p);
101  if (error != NO_ERROR)
102  {
103  return error;
104  }
105 
106  if (parser_p->cursor.token != TT_NONE)
107  {
108  PROXY_LOG (PROXY_LOG_MODE_ERROR, "Unexpected token type. " "(token_type:%d).", parser_p->cursor.token);
109  return ER_SP_INVALID_SYNTAX;
110  }
111 
112  return NO_ERROR;
113 }
114 
115 void
117 {
118  if (parser_p != NULL)
119  {
120  if (parser_p->sql_stmt != NULL)
121  {
122  free (parser_p->sql_stmt);
123  }
124 
125  sp_free_parser_hint_from_ctx (parser_p);
126  free (parser_p);
127  }
128 }
129 
130 bool
132 {
133  return parser_p->list_a.size == parser_p->list_t[BT_STATIC].size;
134 }
135 
136 int
138 {
139  return parser_p->list_a.size;
140 }
141 
142 int
144 {
145  return parser_p->list_t[BT_STATIC].size;
146 }
147 
148 int
150 {
151  return parser_p->list_t[BT_DYNAMIC].size;
152 }
153 
156 {
157  return parser_p->list_a.head;
158 }
159 
162 {
163  return hint_p->next_a;
164 }
165 
168 {
169  return parser_p->list_t[BT_STATIC].head;
170 }
171 
174 {
175  return hint_p->next_t[BT_STATIC];
176 }
177 
180 {
181  return parser_p->list_t[BT_DYNAMIC].head;
182 }
183 
186 {
187  return hint_p->next_t[BT_DYNAMIC];
188 }
189 
190 char *
192 {
193  return hint_p->arg.string.value;
194 }
195 
196 const char *
198 {
199  return parser_p->sql_stmt;
200 }
201 
202 bool
203 sp_is_pair_token (SP_TOKEN start_token, SP_TOKEN end_token)
204 {
205  switch (start_token)
206  {
207  case TT_NONE:
208  case TT_WHITESPACE:
209  case TT_NEWLINE:
210  case TT_C_COMMENT_END:
211  case TT_ASSIGN_OP:
212  case TT_IN_OP:
213  case TT_RIGHT_BRAKET:
214  case TT_BIND_CHAR:
215  case TT_SINGLE_QUOTED:
216  case TT_DOUBLE_QUOTED:
217  return start_token == end_token;
218  case TT_LEFT_BRAKET:
219  return end_token == TT_RIGHT_BRAKET;
220  case TT_CSQL_COMMENT:
221  case TT_CPP_COMMENT:
222  return end_token == TT_NEWLINE;
223  case TT_C_COMMENT:
224  case TT_HINT:
225  case TT_SHARD_HINT:
226  return end_token == TT_C_COMMENT_END;
227  }
228  return false;
229 }
230 
231 #if defined(WINDOWS)
232 static const char *
233 left_trim (const char *str)
234 #else /* WINDOWS */
235 static inline const char *
236 left_trim (const char *str)
237 #endif /* !WINDOWS */
238 {
239  const char *p = str;
240 
241  while (*p && isspace (*p))
242  {
243  p++;
244  }
245 
246  return p;
247 }
248 
249 static int
251 {
252  value_p->type = VT_INTEGER;
253  value_p->string.length = 0;
254  value_p->string.value = value_p->string.value_arr;
255  value_p->string.value_arr[0] = '\0';
256  value_p->string.value_ex = NULL;
257  value_p->integer = 0;
258  return NO_ERROR;
259 }
260 
261 static void
263 {
264  if (value_p != NULL && value_p->string.value_ex != NULL)
265  {
266  free (value_p->string.value_ex);
267  }
268 }
269 
270 static int
271 sp_make_sp_value (SP_VALUE * value_p, const char *pos, int length)
272 {
273  SP_TOKEN token;
274  char *p = (char *) left_trim (pos);
275  while (isspace (p[length - 1]))
276  {
277  length--;
278  }
279 
280  sp_get_token_type (p, &token);
281  if (token == TT_SINGLE_QUOTED || token == TT_DOUBLE_QUOTED)
282  {
283  return sp_make_string_sp_value (value_p, p + 1, length - 2);
284  }
285  else
286  {
287  return sp_make_int_sp_value_from_string (value_p, p, length);
288  }
289 }
290 
291 static int
292 sp_make_string_sp_value (SP_VALUE * value_p, const char *pos, int length)
293 {
294  if (length <= 0)
295  {
296  return ER_SP_INVALID_HINT;
297  }
298 
299  if (length > SP_VALUE_INIT_SIZE)
300  {
301  value_p->string.value_ex = (char *) malloc (sizeof (char) * (length + 1));
302  if (value_p->string.value_ex == NULL)
303  {
304  return ER_SP_OUT_OF_MEMORY;
305  }
306  value_p->string.value = value_p->string.value_ex;
307  }
308  memcpy (value_p->string.value, pos, length);
309  value_p->type = VT_STRING;
310  value_p->string.length = length;
311  value_p->string.value[length] = '\0';
312  return NO_ERROR;
313 }
314 
315 static int
316 sp_make_int_sp_value_from_string (SP_VALUE * value_p, char *pos, int length)
317 {
318  int result = 0;
319  char tmp = pos[length];
320 
321  pos[length] = '\0';
322  result = parse_bigint (&value_p->integer, pos, 10);
323  if (result != 0)
324  {
325  return ER_SP_INVALID_HINT;
326  }
327  pos[length] = tmp;
328  value_p->type = VT_INTEGER;
329  return NO_ERROR;
330 }
331 
334 {
335  int error = NO_ERROR;
336  SP_PARSER_HINT *hint_p = NULL;
337 
338  hint_p = (SP_PARSER_HINT *) malloc (sizeof (SP_PARSER_HINT));
339  if (hint_p == NULL)
340  {
341  PROXY_LOG (PROXY_LOG_MODE_ERROR, "Not enough virtual memory. failed to malloc parser hint. " "(size:%d).",
342  sizeof (SP_PARSER_HINT));
343 
344  return NULL;
345  }
346 
347  error = sp_init_sp_value (&hint_p->arg);
348  if (error != NO_ERROR)
349  {
350  PROXY_LOG (PROXY_LOG_MODE_ERROR, "Failed to initialize parser argument. " "(error:%d).", error);
351  goto PARSER_ERROR;
352  }
353 
354  error = sp_init_sp_value (&hint_p->value);
355  if (error != NO_ERROR)
356  {
357  PROXY_LOG (PROXY_LOG_MODE_ERROR, "Failed to initialize parser value. " "(error:%d). \n", error);
358 
359  goto PARSER_ERROR;
360  }
361 
362  hint_p->next_a = NULL;
363  hint_p->next_t[BT_STATIC] = NULL;
364  hint_p->next_t[BT_DYNAMIC] = NULL;
365  hint_p->hint_type = HT_NONE;
366  hint_p->bind_type = BT_STATIC;
367  hint_p->bind_position = -1 /* INVALID POSITION */ ;
368  return hint_p;
369 PARSER_ERROR:
370  if (hint_p != NULL)
371  {
372  sp_free_parser_hint (hint_p);
373  free (hint_p);
374  }
375  return NULL;
376 }
377 
378 static void
380 {
381  list->head = NULL;
382  list->tail = NULL;
383  list->size = 0;
384 }
385 
386 static void
388 {
389  SP_BIND_TYPE type = hint_p->bind_type;
390 
391  parser_p->list_a.size++;
392  parser_p->list_t[hint_p->bind_type].size++;
393 
394  if (parser_p->list_a.head == NULL)
395  {
396  parser_p->list_a.head = hint_p;
397  }
398  if (parser_p->list_t[type].head == NULL)
399  {
400  parser_p->list_t[type].head = hint_p;
401  }
402  if (parser_p->list_a.tail != NULL)
403  {
404  parser_p->list_a.tail->next_a = hint_p;
405  }
406  if (parser_p->list_t[type].tail != NULL)
407  {
408  parser_p->list_t[type].tail->next_t[type] = hint_p;
409  }
410 
411  parser_p->list_a.tail = hint_p;
412  parser_p->list_t[type].tail = hint_p;
413 }
414 
415 void
417 {
418  if (hint_p != NULL)
419  {
420  sp_free_sp_value (&hint_p->arg);
421  sp_free_sp_value (&hint_p->value);
422  }
423 }
424 
425 static int
427 {
428  int error = NO_ERROR;
429  SP_TOKEN token_type = TT_NONE;
430 
431  while (*parser_p->cursor.pos)
432  {
433  parser_p->cursor.pos = sp_get_token_type (parser_p->cursor.pos, &token_type);
434  if (token_type == TT_NONE)
435  {
436  continue;
437  }
438 
439  if (parser_p->cursor.token == TT_NONE)
440  {
441  if (sp_is_start_token (token_type) == false)
442  {
443  return ER_SP_INVALID_SYNTAX;
444  }
445 
446  parser_p->cursor.token = token_type;
447 
448  error = sp_process_token (parser_p, token_type);
449  if (error != NO_ERROR)
450  {
451  return error;
452  }
453 
454  if (!sp_is_exist_pair_token (parser_p->cursor.token))
455  {
456  sp_copy_cursor_to_prv (parser_p);
457  }
458  }
459  else if (sp_is_pair_token (parser_p->cursor.token, token_type))
460  {
461  sp_copy_cursor_to_prv (parser_p);
462  }
463  }
464 
465  if (parser_p->cursor.token == TT_CSQL_COMMENT || parser_p->cursor.token == TT_CPP_COMMENT)
466  {
467  parser_p->cursor.token = TT_NONE;
468  }
469 
470  return NO_ERROR;
471 }
472 
473 static void
475 {
476  SP_PARSER_HINT *hint_p = sp_get_first_hint (parser_p);
477  SP_PARSER_HINT *hint_np = NULL;
478 
479  while (hint_p != NULL)
480  {
481  hint_np = sp_get_next_hint (hint_p);
482  sp_free_parser_hint (hint_p);
483  free (hint_p);
484  hint_p = hint_np;
485  }
486 }
487 
488 const char *
489 sp_get_token_type (const char *sql, SP_TOKEN * token)
490 {
491  const char *p = sql;
492 
493  *token = TT_NONE;
494 
495  switch (*(p++))
496  {
497  case '\'':
498  *token = TT_SINGLE_QUOTED;
499  break;
500  case '"':
501  *token = TT_DOUBLE_QUOTED;
502  break;
503  case '\\':
504  /* escape char */
505  p += 1;
506  break;
507  case '/':
508  switch (*p)
509  {
510  case '/':
511  p += 1;
512  *token = TT_CPP_COMMENT;
513  break;
514  case '*':
515  if (*(p + 1) == '+')
516  {
517  p += 2;
518  *token = TT_HINT;
519  }
520  else
521  {
522  p += 1;
523  *token = TT_C_COMMENT;
524  }
525  break;
526  }
527  break;
528  case '-':
529  if (*p == '-')
530  {
531  p += 1;
532  *token = TT_CSQL_COMMENT;
533  }
534  break;
535  case '*':
536  if (*p == '/')
537  {
538  p += 1;
539  *token = TT_C_COMMENT_END;
540  }
541  break;
542  case '=':
543  *token = TT_ASSIGN_OP;
544  break;
545  case '\n':
546  *token = TT_NEWLINE;
547  break;
548  case ' ':
549  case '\f':
550  case '\r':
551  case '\t':
552  case '\v':
553  *token = TT_WHITESPACE;
554  if (tolower (*p) == 'i' && tolower (*(p + 1)) == 'n' && (isspace (*(p + 2)) || *(p + 2) == '('))
555  {
556  p += 3;
557  *token = TT_IN_OP;
558  }
559  break;
560  case '?':
561  *token = TT_BIND_CHAR;
562  break;
563  case '(':
564  *token = TT_LEFT_BRAKET;
565  break;
566  case ')':
567  *token = TT_RIGHT_BRAKET;
568  break;
569  }
570 
571  return p;
572 }
573 
574 const char *
575 sp_get_hint_type (const char *sql, SP_HINT_TYPE * hint_type)
576 {
577  sql = left_trim (sql);
578 
579  *hint_type = HT_NONE;
580  if (strncasecmp (sql, "shard_", 6) != 0)
581  {
582  return sql;
583  }
584 
585  sql += 6;
586  if (strncasecmp (sql, "key", 3) == 0)
587  {
588  sql += 3;
589  *hint_type = HT_KEY;
590  }
591  else if (strncasecmp (sql, "val", 3) == 0)
592  {
593  sql += 3;
594  *hint_type = HT_VAL;
595  }
596  else if (strncasecmp (sql, "all", 3) == 0)
597  {
598  sql += 3;
599  *hint_type = HT_ALL;
600  }
601  else if (strncasecmp (sql, "id", 2) == 0)
602  {
603  sql += 2;
604  *hint_type = HT_ID;
605  }
606  return sql;
607 }
608 
609 const char *
610 sp_get_hint_arg (const char *sql, SP_PARSER_HINT * hint_p, int *error)
611 {
612  SP_TOKEN start_token;
613  SP_TOKEN end_token;
614  const char *p, *q;
615 
616  *error = ER_SP_INVALID_HINT;
617 
618  sql = left_trim (sql);
619  sp_get_token_type (sql, &start_token);
620 
621  if (start_token != TT_LEFT_BRAKET)
622  {
623  if (hint_p->hint_type != HT_VAL && hint_p->hint_type != HT_ID)
624  {
625  *error = NO_ERROR;
626  }
627  return sql;
628  }
629 
630  sql = left_trim (sql + 1);
631  q = p = sql;
632 
633  while (*p)
634  {
635  q = sp_get_token_type (p, &end_token);
636  if (sp_is_pair_token (start_token, end_token))
637  {
638  *error = sp_make_sp_value (&hint_p->arg, sql, p - sql);
639  return q;
640  }
641  p = q;
642  }
643 
644  *error = ER_SP_INVALID_HINT;
645  return sql;
646 }
647 
648 const char *
649 sp_check_end_of_hint (const char *sql, int *error)
650 {
651  sql = left_trim (sql);
652 
653  if (*(sql++) == '*' && *(sql++) == '/')
654  {
655  *error = NO_ERROR;
656  }
657  else
658  {
659  *error = ER_SP_INVALID_HINT;
660  }
661 
662  return sql;
663 }
664 
665 static int
666 sp_process_token (SP_PARSER_CTX * parser_p, SP_TOKEN token_type)
667 {
668  int error = NO_ERROR;
669  SP_PARSER_HINT *hint_p = NULL;
670  SP_HINT_TYPE hint_type = HT_NONE;
671 
672  switch (token_type)
673  {
674  case TT_BIND_CHAR:
675  parser_p->bind_count++;
676  break;
677  case TT_HINT:
678  parser_p->cursor.pos = sp_get_hint_type (parser_p->cursor.pos, &hint_type);
679  if (hint_type == HT_NONE)
680  {
681  return NO_ERROR;
682  }
683  parser_p->cursor.token = TT_SHARD_HINT;
684 
685  hint_p = sp_create_parser_hint ();
686  if (hint_p == NULL)
687  {
688  error = ER_SP_OUT_OF_MEMORY;
689  goto PARSER_ERROR;
690  }
691  hint_p->hint_type = hint_type;
692 
693  parser_p->cursor.pos = sp_get_hint_arg (parser_p->cursor.pos, hint_p, &error);
694  if (error != NO_ERROR)
695  {
696  goto PARSER_ERROR;
697  }
698 
699  parser_p->cursor.pos = sp_check_end_of_hint (parser_p->cursor.pos, &error);
700  if (error != NO_ERROR)
701  {
702  goto PARSER_ERROR;
703  }
704 
705  error = sp_is_valid_hint (parser_p, hint_p);
706  if (error != NO_ERROR)
707  {
708  goto PARSER_ERROR;
709  }
710 
711  if (hint_p->hint_type == HT_KEY)
712  {
713  error = sp_get_bind_type_and_value (parser_p, hint_p);
714  if (error != NO_ERROR)
715  {
716  goto PARSER_ERROR;
717  }
718  }
719 
720  if (parser_p->operator_ == TT_ASSIGN_OP)
721  {
722  parser_p->operator_ = TT_NONE;
723  }
724 
725  sp_append_parser_hint_to_ctx (parser_p, hint_p);
726  break;
727  case TT_IN_OP:
728  case TT_ASSIGN_OP:
729  parser_p->operator_ = token_type;
730  break;
731  case TT_RIGHT_BRAKET:
732  parser_p->operator_ = TT_NONE;
733  break;
734  default:
735  break;
736  }
737 
738  return error;
739 PARSER_ERROR:
740  if (hint_p != NULL)
741  {
742  sp_free_parser_hint (hint_p);
743  free (hint_p);
744  }
745  return error;
746 }
747 
748 static int
750 {
751  int error = NO_ERROR;
752 
753  parser_p->cursor.pos = left_trim (parser_p->cursor.pos);
754 
755  switch (*parser_p->cursor.pos)
756  {
757  case '?':
758  hint_p->bind_type = BT_DYNAMIC;
759  hint_p->bind_position = parser_p->bind_count;
760  parser_p->bind_count++;
761  parser_p->cursor.pos++;
762  break;
763  case '\'':
764  case '"':
765  error = sp_get_string_bind_value (parser_p, hint_p);
766  parser_p->cursor.pos++;
767  break;
768  default:
769  error = sp_get_int_bind_value (parser_p, hint_p);
770  break;
771  }
772 
773  if (error != NO_ERROR)
774  {
775  return error;
776  }
777 
778  return error;
779 }
780 
781 #if defined(WINDOWS)
782 static void
784 #else /* WINDOWS */
785 static inline void
787 #endif /* !WINDOWS */
788 {
789  parser_p->prv_cursor = parser_p->cursor;
790  parser_p->cursor.token = TT_NONE;
791 }
792 
793 static int
795 {
796  char *p;
797 
798  if (parser_p->cursor.pos == NULL)
799  {
800  return ER_SP_INVALID_SYNTAX;
801  }
802  p = (char *) parser_p->cursor.pos++;
803 
804  while (*parser_p->cursor.pos && *parser_p->cursor.pos != *p)
805  {
806  parser_p->cursor.pos++;
807  }
808 
809  return sp_make_string_sp_value (&hint_p->value, p + 1, parser_p->cursor.pos - p - 1);
810 }
811 
812 static int
814 {
815  char *p = (char *) parser_p->cursor.pos;
816  char *s = p;
817  while (*s && (!isspace (*s) && *s != ',' && *s != ')'))
818  {
819  s++;
820  }
821 
822  parser_p->cursor.pos = s;
823  return sp_make_int_sp_value_from_string (&hint_p->value, p, parser_p->cursor.pos - p);
824 }
825 
826 static int
828 {
829  if (parser_p->is_select)
830  {
831  if (hint_p->hint_type == HT_KEY && parser_p->operator_ != TT_ASSIGN_OP && parser_p->operator_ != TT_IN_OP)
832  {
833  return ER_SP_INVALID_SYNTAX;
834  }
835  }
836  return NO_ERROR;
837 }
838 
839 static bool
841 {
842  switch (token)
843  {
844  case TT_C_COMMENT_END:
845  return false;
846  default:
847  return true;
848  }
849 }
850 
851 bool
853 {
854  switch (token)
855  {
856  case TT_NONE:
857  case TT_WHITESPACE:
858  case TT_NEWLINE:
859  case TT_C_COMMENT_END:
860  case TT_ASSIGN_OP:
861  case TT_IN_OP:
862  case TT_LEFT_BRAKET:
863  case TT_RIGHT_BRAKET:
864  case TT_BIND_CHAR:
865  case TT_SHARD_HINT:
866  return false;
867  default:
868  return true;
869  }
870 }
SP_CURSOR prv_cursor
Definition: shard_parser.h:144
enum sp_hint_type SP_HINT_TYPE
Definition: shard_parser.h:59
#define NO_ERROR
Definition: error_code.h:46
char * sp_get_hint_key(SP_PARSER_HINT *hint_p)
Definition: shard_parser.c:191
char * value_ex
Definition: shard_parser.h:112
SP_PARSER_HINT * sp_get_first_static_hint(SP_PARSER_CTX *parser_p)
Definition: shard_parser.c:167
SP_PARSER_HINT * tail
Definition: shard_parser.h:133
SP_PARSER_HINT_LIST list_t[2]
Definition: shard_parser.h:147
void sp_free_parser_hint(SP_PARSER_HINT *hint_p)
Definition: shard_parser.c:416
void sp_destroy_parser(SP_PARSER_CTX *parser_p)
Definition: shard_parser.c:116
static bool sp_is_start_token(SP_TOKEN token)
Definition: shard_parser.c:840
INT64 integer
Definition: shard_parser.h:114
SP_PARSER_HINT * sp_get_first_dynamic_hint(SP_PARSER_CTX *parser_p)
Definition: shard_parser.c:179
SP_VALUE value
Definition: shard_parser.h:126
SP_PARSER_HINT_LIST list_a
Definition: shard_parser.h:146
#define SP_VALUE_INIT_SIZE
Definition: shard_parser.h:37
SP_PARSER_HINT * sp_get_next_static_hint(SP_PARSER_HINT *hint_p)
Definition: shard_parser.c:173
static int sp_make_string_sp_value(SP_VALUE *value_p, const char *pos, int length)
Definition: shard_parser.c:292
static int sp_get_int_bind_value(SP_PARSER_CTX *parser_p, SP_PARSER_HINT *hint_p)
Definition: shard_parser.c:813
char * value
Definition: shard_parser.h:110
SP_HINT_TYPE hint_type
Definition: shard_parser.h:122
static int sp_get_bind_type_and_value(SP_PARSER_CTX *parser_p, SP_PARSER_HINT *hint_p)
Definition: shard_parser.c:749
static int sp_make_int_sp_value_from_string(SP_VALUE *value_p, char *pos, int length)
Definition: shard_parser.c:316
SP_PARSER_HINT * sp_get_first_hint(SP_PARSER_CTX *parser_p)
Definition: shard_parser.c:155
SP_PARSER_CTX * sp_create_parser(const char *sql_stmt)
Definition: shard_parser.c:63
const char * sp_check_end_of_hint(const char *sql, int *error)
Definition: shard_parser.c:649
static void sp_append_parser_hint_to_ctx(SP_PARSER_CTX *parser_p, SP_PARSER_HINT *hint_p)
Definition: shard_parser.c:387
static int sp_parse_sql_internal(SP_PARSER_CTX *parser_p)
Definition: shard_parser.c:426
static void sp_init_praser_hint_list(SP_PARSER_HINT_LIST *list)
Definition: shard_parser.c:379
SP_VALUE_TYPE type
Definition: shard_parser.h:106
const char * sp_get_token_type(const char *sql, SP_TOKEN *token)
Definition: shard_parser.c:489
SP_CURSOR cursor
Definition: shard_parser.h:143
SP_PARSER_HINT * next_t[2]
Definition: shard_parser.h:121
bool sp_is_pair_token(SP_TOKEN start_token, SP_TOKEN end_token)
Definition: shard_parser.c:203
int sp_get_total_hint_count(SP_PARSER_CTX *parser_p)
Definition: shard_parser.c:137
static int sp_get_string_bind_value(SP_PARSER_CTX *parser_p, SP_PARSER_HINT *hint_p)
Definition: shard_parser.c:794
static int sp_make_sp_value(SP_VALUE *value_p, const char *pos, int length)
Definition: shard_parser.c:271
bool sp_is_hint_static(SP_PARSER_CTX *parser_p)
Definition: shard_parser.c:131
#define NULL
Definition: freelistheap.h:34
static void sp_free_parser_hint_from_ctx(SP_PARSER_CTX *parser_p)
Definition: shard_parser.c:474
SP_TOKEN token
Definition: shard_parser.h:100
SP_PARSER_HINT * head
Definition: shard_parser.h:132
enum sp_bind_type SP_BIND_TYPE
Definition: shard_parser.h:66
const char * sp_get_hint_arg(const char *sql, SP_PARSER_HINT *hint_p, int *error)
Definition: shard_parser.c:610
enum sp_token SP_TOKEN
Definition: shard_parser.h:94
SP_PARSER_HINT * sp_create_parser_hint(void)
Definition: shard_parser.c:333
int sp_get_static_hint_count(SP_PARSER_CTX *parser_p)
Definition: shard_parser.c:143
SP_TOKEN operator_
Definition: shard_parser.h:145
static void error(const char *msg)
Definition: gencat.c:331
SP_PARSER_HINT * sp_get_next_dynamic_hint(SP_PARSER_HINT *hint_p)
Definition: shard_parser.c:185
int sp_get_dynamic_hint_count(SP_PARSER_CTX *parser_p)
Definition: shard_parser.c:149
#define PROXY_LOG(level, fmt, args...)
const char * sp_get_hint_type(const char *sql, SP_HINT_TYPE *hint_type)
Definition: shard_parser.c:575
static void sp_free_sp_value(SP_VALUE *value_p)
Definition: shard_parser.c:262
static int sp_init_sp_value(SP_VALUE *value_p)
Definition: shard_parser.c:250
SP_PARSER_HINT * next_a
Definition: shard_parser.h:120
struct sp_value::@40 string
while(1)
Definition: cnvlex.c:816
char * strdup(const char *str)
Definition: porting.c:901
int parse_bigint(INT64 *ret_p, const char *str_p, int base)
Definition: porting.c:2318
static int sp_is_valid_hint(SP_PARSER_CTX *parser_p, SP_PARSER_HINT *hint_p)
Definition: shard_parser.c:827
bool sp_is_exist_pair_token(SP_TOKEN token)
Definition: shard_parser.c:852
int sp_parse_sql(SP_PARSER_CTX *parser_p)
Definition: shard_parser.c:96
SP_BIND_TYPE bind_type
Definition: shard_parser.h:123
const char * sp_get_sql_stmt(SP_PARSER_CTX *parser_p)
Definition: shard_parser.c:197
static int sp_process_token(SP_PARSER_CTX *parser_p, SP_TOKEN token_type)
Definition: shard_parser.c:666
SP_PARSER_HINT * sp_get_next_hint(SP_PARSER_HINT *hint_p)
Definition: shard_parser.c:161
const char * pos
Definition: shard_parser.h:99
char value_arr[SP_VALUE_INIT_SIZE]
Definition: shard_parser.h:111
static const char * left_trim(const char *str)
Definition: shard_parser.c:236
const char ** p
Definition: dynamic_load.c:945
static void sp_copy_cursor_to_prv(SP_PARSER_CTX *parser_p)
Definition: shard_parser.c:786