oceanbase

Форк
0
/
pl_parser_mysql_mode.y 
2653 строки · 82.9 Кб
1
/** 
2
 * Copyright (c) 2021 OceanBase 
3
 * OceanBase CE is licensed under Mulan PubL v2. 
4
 * You can use this software according to the terms and conditions of the Mulan PubL v2. 
5
 * You may obtain a copy of Mulan PubL v2 at: 
6
 *          http://license.coscl.org.cn/MulanPubL-2.0 
7
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 
8
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 
9
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 
10
 * See the Mulan PubL v2 for more details.
11
 */ 
12

13
//first: declare
14
%define api.pure
15
%parse-param {ObParseCtx *parse_ctx}
16
%name-prefix "obpl_mysql_yy"
17
%locations
18
//%no-lines
19
%verbose
20
%error-verbose
21

22
%{
23
#include <stdint.h>
24
#define YYDEBUG 1
25
%}
26

27
%union {
28
  struct _ParseNode *node;
29
  const struct _NonReservedKeyword *non_reserved_keyword;
30
  int64_t ival;
31
}
32

33
%code requires {
34
#ifndef YYLTYPE_IS_DECLARED
35
#define YYLTYPE_IS_DECLARED 1
36
typedef struct YYLTYPE
37
{
38
  int first_line;
39
  int first_column;
40
  int last_line;
41
  int last_column;
42
  int abs_first_column;
43
  int abs_last_column;
44
} YYLTYPE;
45
#endif /*YYLTYPE_IS_DECLARED*/
46

47
# define YYLLOC_DEFAULT(Current, Rhs, N)                        \
48
  do                                                            \
49
    if (YYID (N)) {                                             \
50
      (Current).first_line   = YYRHSLOC (Rhs, 1).first_line;    \
51
      (Current).first_column = YYRHSLOC (Rhs, 1).first_column;  \
52
      (Current).last_line    = YYRHSLOC (Rhs, N).last_line;     \
53
      (Current).last_column  = YYRHSLOC (Rhs, N).last_column;   \
54
      (Current).abs_first_column = YYRHSLOC (Rhs, 1).abs_first_column;     \
55
      (Current).abs_last_column  = YYRHSLOC (Rhs, N).abs_last_column;      \
56
    } else {                                                    \
57
      (Current).first_line   = (Current).last_line   =          \
58
        YYRHSLOC (Rhs, 0).last_line;                            \
59
      (Current).first_column = (Current).last_column =          \
60
        YYRHSLOC (Rhs, 0).last_column;                          \
61
      (Current).abs_first_column = (Current).abs_last_column =          \
62
        YYRHSLOC (Rhs, 0).abs_last_column;                              \
63
    }                                                           \
64
  while (YYID (0))
65
}
66

67
%{
68
#include "pl/parser/pl_parser_mysql_mode_lex.h"
69
#include "pl/parser/pl_parser_base.h"
70

71
typedef struct _YYLookaheadToken
72
{
73
  int *la_yychar;
74
  /* The semantic value of the lookahead symbol.  */
75
  YYSTYPE *la_yylval;
76
  /* Location data for the lookahead symbol.  */
77
  YYLTYPE *la_yylloc;
78
} YYLookaheadToken;
79

80
extern ParseNode *obpl_mysql_read_sql_construct(ObParseCtx *parse_ctx, const char *prefix, YYLookaheadToken *la_token, int end_token_cnt, ...);
81
extern void obpl_mysql_yyerror(YYLTYPE *yylloc, ObParseCtx *parse_ctx, char *s, ...);
82
extern void obpl_mysql_parse_fatal_error(int32_t errcode, yyscan_t yyscanner, yyconst char *msg, ...);
83

84
int obpl_mysql_check_specific_node(const ParseNode *node, const ObItemType type, int *is_contain) {
85
  int ret = OB_PARSER_SUCCESS;
86
  if (obpl_parser_check_stack_overflow()) {
87
    ret = OB_PARSER_ERR_SIZE_OVERFLOW;
88
  } else if (OB_UNLIKELY(NULL == is_contain)) {
89
    ret = OB_PARSER_ERR_UNEXPECTED;
90
  } else {
91
    *is_contain = false;
92
  }
93

94
  if (OB_PARSER_SUCCESS == ret && OB_NOT_NULL(node)) {
95
    if (type == node->type_) {
96
      *is_contain = true;
97
    } else {
98
      for (int64_t i = 0; OB_PARSER_SUCCESS == ret && !*is_contain && i < node->num_child_; ++i) {
99
        ret = obpl_mysql_check_specific_node(node->children_[i], type, is_contain);
100
      }
101
    }
102
  }
103
  return ret;
104
}
105

106
int obpl_mysql_wrap_node_into_subquery(ObParseCtx *_parse_ctx, ParseNode *node) {
107
  int ret = OB_PARSER_SUCCESS;
108
  if (OB_NOT_NULL(node) && OB_NOT_NULL(node->str_value_)) {
109
    int max_query_len = node->str_len_ + 10;
110
    char *subquery = (char *)parse_malloc(max_query_len, _parse_ctx->mem_pool_);
111
    int len = 0;
112
    if (OB_UNLIKELY(NULL == subquery)) {
113
      ret = OB_PARSER_ERR_NO_MEMORY;
114
    } else if ((len = snprintf(subquery, max_query_len, "(SELECT %s)", node->str_value_)) <= 0) {
115
      ret = OB_PARSER_ERR_UNEXPECTED;
116
    } else {
117
      ParseResult parse_result;
118
      memset(&parse_result, 0, sizeof(ParseResult));
119
      parse_result.input_sql_ = subquery;
120
      parse_result.input_sql_len_ = len;
121
      parse_result.malloc_pool_ = _parse_ctx->mem_pool_;
122
      parse_result.pl_parse_info_.is_pl_parse_ = true;
123
      parse_result.pl_parse_info_.is_pl_parse_expr_ = true;
124
      parse_result.is_for_trigger_ = (1 == _parse_ctx->is_for_trigger_);
125
      parse_result.question_mark_ctx_ = _parse_ctx->question_mark_ctx_;
126
      parse_result.charset_info_ = _parse_ctx->charset_info_;
127
      parse_result.charset_info_oracle_db_ = _parse_ctx->charset_info_oracle_db_;
128
      parse_result.is_not_utf8_connection_ = _parse_ctx->is_not_utf8_connection_;
129
      parse_result.connection_collation_ = _parse_ctx->connection_collation_;
130
      parse_result.sql_mode_ = _parse_ctx->scanner_ctx_.sql_mode_;
131
      if (0 == parse_sql_stmt(&parse_result)) {
132
        *node = *parse_result.result_tree_->children_[0];
133
        node->str_value_ = subquery;
134
        node->str_len_ = len;
135
        node->pl_str_off_ = -1;
136
      }
137
    }
138
  }
139
  return ret;
140
}
141

142
void obpl_mysql_wrap_get_user_var_into_subquery(ObParseCtx *parse_ctx, ParseNode *node) {
143
  int ret = OB_PARSER_SUCCESS;
144
  int is_contain = false;
145
  if (OB_PARSER_SUCCESS != (ret = obpl_mysql_check_specific_node(node, T_OP_GET_USER_VAR, &is_contain))) {
146
    obpl_mysql_parse_fatal_error(ret, YYLEX_PARAM, "failed to check T_OP_GET_USER_VAR in parse tree");
147
  } else if (is_contain) {
148
    if (OB_PARSER_SUCCESS != (ret = obpl_mysql_wrap_node_into_subquery(parse_ctx, node))) {
149
      obpl_mysql_parse_fatal_error(ret, YYLEX_PARAM, "failed to wrap T_OP_GET_USER_VAR into subquery");
150
    }
151
  }
152
}
153

154
#define YY_FATAL_ERROR(msg, args...) (obpl_mysql_parse_fatal_error(OB_PARSER_ERR_NO_MEMORY, YYLEX_PARAM, msg, ##args))
155
#define YY_UNEXPECTED_ERROR(msg, args...) (obpl_mysql_parse_fatal_error(OB_PARSER_ERR_UNEXPECTED, YYLEX_PARAM, msg, ##args))
156

157
#define do_parse_sql_stmt(node, _parse_ctx, start_loc, end_loc, end_tok_num, ...)                          \
158
  do {                                                                                                     \
159
    YYLookaheadToken la_token;                                                                             \
160
    la_token.la_yychar = &yychar;                                                                          \
161
    la_token.la_yylval = &yylval;                                                                          \
162
    la_token.la_yylloc = &yylloc;                                                                          \
163
    _parse_ctx->scanner_ctx_.sql_start_loc = start_loc;                                                    \
164
    _parse_ctx->scanner_ctx_.sql_end_loc = end_loc;                                                        \
165
    node = obpl_mysql_read_sql_construct(_parse_ctx, "", &la_token, end_tok_num, ##__VA_ARGS__);           \
166
    if (NULL == node) {                                                                                    \
167
      YYERROR;                                                                                             \
168
    }                                                                                                      \
169
    reset_current_location(_parse_ctx->scanner_ctx_.sql_start_loc, _parse_ctx->scanner_ctx_.sql_end_loc);  \
170
  } while (0)
171

172
#define do_parse_sql_expr_rule(node, _parse_ctx, end_tok_num, ...)                                         \
173
  do {                                                                                                     \
174
    ParseNode *select_node = NULL;                                                                         \
175
    YYLookaheadToken la_token;                                                                             \
176
    la_token.la_yychar = &yychar;                                                                          \
177
    la_token.la_yylval = &yylval;                                                                          \
178
    la_token.la_yylloc = &yylloc;                                                                          \
179
    _parse_ctx->scanner_ctx_.sql_start_loc = -1;                                                           \
180
    _parse_ctx->scanner_ctx_.sql_end_loc = -1;                                                             \
181
    select_node = obpl_mysql_read_sql_construct(_parse_ctx, "SELECT ", &la_token, end_tok_num, ##__VA_ARGS__);        \
182
    reset_current_location(_parse_ctx->scanner_ctx_.sql_start_loc, _parse_ctx->scanner_ctx_.sql_end_loc);  \
183
    if (select_node != NULL) {                                                                             \
184
      if (NULL == select_node->children_[2] || NULL == select_node->children_[2]->children_[0]) {          \
185
        YYERROR;                                                                                           \
186
      } else {                                                                                             \
187
        node = select_node->children_[2]->children_[0]->children_[0];                                      \
188
      }                                                                                                    \
189
    } else {                                                                                               \
190
      node = NULL;                                                                                         \
191
    }                                                                                                      \
192
} while (0)
193
%}
194

195
/*these tokens can't be used for obj names*/
196
%token END_P
197
/* reserved key words */
198
%token  ALTER BEFORE BY CALL CASE CONDITION CONTINUE CREATE CURRENT_USER CURSOR DECLARE
199
        DEFAULT DELETE DETERMINISTIC DROP EACH ELSE ELSEIF EXISTS EXIT FETCH FOR FROM IF IN
200
        INDEX INOUT INSERT INTO IS ITERATE LEAVE LIMIT LONG LOOP MODIFIES  NOT ON OR OUT
201
        PROCEDURE READS REPEAT REPLACE RESIGNAL RETURN SELECT SIGNAL SQL SQLEXCEPTION
202
        SQLSTATE SQLWARNING TABLE THEN TRIGGER UPDATE USING WHEN WHILE
203
/* reserved key words only used in ob, in mysql these keywords are non reserved*/
204
%token  COMMIT ROLLBACK DO UNTIL 
205

206
%token SQL_KEYWORD SQL_TOKEN PARAM_ASSIGN_OPERATOR
207
%token PARSER_SYNTAX_ERROR /*used internal*/
208
%token <node> IDENT STRING INTNUM DECIMAL_VAL HEX_STRING_VALUE DATE_VALUE SYSTEM_VARIABLE USER_VARIABLE NULLX
209
%token <node> USER_NAME
210
//*data type keyword*/
211
%token TINYINT SMALLINT MEDIUMINT INTEGER BIGINT FLOAT DOUBLE PRECISION NUMBER NUMERIC BIT
212
        DATETIME TIMESTAMP TIME DATE YEAR CHARACTER TEXT VARCHAR NCHAR NVARCHAR BINARY VARBINARY UNSIGNED
213
        SIGNED ZEROFILL COLLATE SET CHARSET BOOL BOOLEAN BLOB ENUM TINYTEXT MEDIUMTEXT LONGTEXT TINYBLOB
214
        MEDIUMBLOB LONGBLOB VARYING
215

216
/* non reserved key words */
217
%token <non_reserved_keyword>
218
      AFTER AUTHID BEGIN_KEY BINARY_INTEGER BODY C CATALOG_NAME CLASS_ORIGIN CLOSE COLUMN_NAME COMMENT
219
      CONSTRAINT_CATALOG CONSTRAINT_NAME CONSTRAINT_ORIGIN CONSTRAINT_SCHEMA CONTAINS COUNT CURSOR_NAME
220
      DATA DEFINER END_KEY EXTEND FOLLOWS FOUND FUNCTION HANDLER INTERFACE INVOKER JSON LANGUAGE
221
      MESSAGE_TEXT MYSQL_ERRNO NATIONAL NEXT NO OF OPEN PACKAGE PRAGMA PRECEDES RECORD RETURNS ROW ROWTYPE
222
      SCHEMA_NAME SECURITY SUBCLASS_ORIGIN TABLE_NAME TYPE VALUE
223

224
%right END_KEY
225
%left ELSE IF ELSEIF
226

227
%nonassoc LOWER_PARENS
228
%nonassoc FUNCTION
229
%nonassoc PARENS
230
%left '(' ')'
231
%nonassoc AUTHID INTERFACE
232
%nonassoc DECLARATION
233

234
%type <node> sql_keyword
235
%type <non_reserved_keyword> unreserved_keyword
236
%type <node> stmt_block stmt_list stmt outer_stmt sp_proc_outer_statement sp_proc_inner_statement sp_proc_independent_statement
237
%type <node> create_procedure_stmt sp_proc_stmt expr expr_list procedure_body default_expr
238
%type <node> create_function_stmt function_body
239
%type <node> drop_procedure_stmt drop_function_stmt
240
%type <node> alter_procedure_stmt alter_function_stmt opt_sp_alter_chistics
241
%type <node> sp_unlabeled_block
242
%type <node> sp_block_content opt_sp_decls sp_proc_stmts sp_decl sp_decls
243
%type <node> sp_labeled_block label_ident opt_sp_label
244
%type <node> sp_decl_idents sp_data_type opt_sp_decl_default opt_param_default
245
%type <node> sp_proc_stmt_if sp_if sp_proc_stmt_case sp_when_list sp_when sp_elseifs 
246
%type <node> sp_proc_stmt_return
247
%type <node> sql_stmt ident simple_ident
248
%type <node> into_clause
249
%type <node> sp_name sp_call_name opt_sp_param_list opt_sp_fparam_list sp_param_list sp_fparam_list
250
%type <node> sp_param sp_fparam sp_alter_chistics
251
%type <node> opt_sp_definer sp_create_chistics sp_create_chistic sp_chistic opt_parentheses user opt_host_name
252
%type <node> param_type sp_cparams opt_sp_cparam_list cexpr sp_cparam opt_sp_cparam_with_assign
253
%type <ival> opt_sp_inout opt_if_exists
254
%type <node> call_sp_stmt do_sp_stmt
255
%type <node> sp_cond sp_hcond_list sp_hcond
256
%type <node> sp_unlabeled_control sp_labeled_control
257
%type <node> sp_proc_stmt_iterate
258
%type <node> sp_proc_stmt_leave
259
%type <node> sqlstate opt_value
260
%type <ival> sp_handler_type
261
%type <node> signal_stmt resignal_stmt
262
%type <node> signal_value opt_signal_value opt_set_signal_information signal_allowed_expr
263
%type <node> signal_information_item_list signal_information_item
264
%type <ival> scond_info_item_name
265
%type <node> sp_proc_stmt_open sp_proc_stmt_fetch sp_proc_stmt_close
266
%type <node> opt_package_stmts package_stmts package_stmt drop_package_stmt interface_pragma
267
%type <node> package_block package_body_block create_package_stmt create_package_body_stmt
268
%type <node> invoke_right proc_clause proc_clause_list opt_proc_clause
269
%type <node> decl_stmt_ext_list decl_stmt_ext func_decl proc_decl
270
%type <node> opt_tail_package_name
271
%type <ival> opt_replace
272
%type <node> create_trigger_stmt drop_trigger_stmt plsql_trigger_source
273
%type <node> trigger_definition trigger_event trigger_body pl_obj_access_ref opt_trigger_order
274
%type <ival> trigger_time
275
/*SQL data type*/
276
%type <node> scalar_data_type opt_charset collation opt_collation charset_name collation_name
277
%type <node> number_literal literal charset_key opt_float_precision opt_number_precision opt_binary
278
%type <node> string_list text_string
279
%type <ival> string_length_i opt_string_length_i opt_int_length_i opt_string_length_i_v2
280
%type <ival> opt_bit_length_i opt_datetime_fsp_i opt_unsigned_i opt_zerofill_i opt_year_i
281
%type <ival> int_type_i float_type_i datetime_type_i date_year_type_i text_type_i blob_type_i
282
%type <ival> nchar_type_i nvarchar_type_i
283
%type <node> variable
284
%%
285
/*****************************************************************************
286
 *
287
 *      MULTI STMT BLOCK start grammar
288
 *
289
 *****************************************************************************/
290
stmt_block:
291
    stmt_list END_P
292
    {
293
      merge_nodes($$, parse_ctx->mem_pool_, T_STMT_LIST, $1);
294
      parse_ctx->stmt_tree_ = $$;
295
      YYACCEPT;
296
    }
297
;
298

299
stmt_list:
300
    stmt_list ';' stmt
301
    {
302
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_LINK_NODE, 2, $1, $3);
303
      parse_ctx->stmt_tree_ = $$;
304
    }
305
  | stmt
306
    {
307
      $$ = $1;
308
      parse_ctx->stmt_tree_ = $$;
309
    }
310
/*  | stmt_list ';' error
311
    {
312

313
    }
314
  | error
315
    {
316

317
    }*/
318
;
319

320
stmt:
321
  outer_stmt
322
  {
323
    if(NULL != $1 && !parse_ctx->is_inner_parse_) {
324
      switch($1->type_) {
325
        // wrap nodes of following types into an anonymous block to mock SQL execution.
326
        case T_SP_DO:
327
        case T_SP_SIGNAL:
328
        case T_SP_RESIGNAL: {
329
          ParseNode *proc_stmts = NULL;
330
          merge_nodes(proc_stmts, parse_ctx->mem_pool_, T_SP_PROC_STMT_LIST, $1);
331
          ParseNode *block_content = NULL;
332
          merge_nodes(block_content, parse_ctx->mem_pool_, T_SP_BLOCK_CONTENT, proc_stmts);
333
          malloc_non_terminal_node($1, parse_ctx->mem_pool_, T_SP_ANONYMOUS_BLOCK, 1, block_content);
334
        } break;
335
        default:{
336
          // do nothing
337
        } break;
338
      }
339
    }
340

341
    $$ = $1;
342
    int32_t str_len = @1.last_column - @1.first_column + 1;
343
    $$->pos_ = @1.first_column;
344
    $$->str_len_ = str_len;
345
  }
346
  | /*Empty*/ { $$ = NULL; }
347

348
outer_stmt:
349
    create_procedure_stmt { $$ = $1; }
350
  | create_function_stmt { $$ = $1; }
351
  | drop_procedure_stmt { $$ = $1; }
352
  | drop_function_stmt { $$ = $1; }
353
  | alter_procedure_stmt { $$ = $1; }
354
  | alter_function_stmt { $$ = $1; }
355
  | create_package_stmt { $$ = $1; }
356
  | create_package_body_stmt { $$ = $1; }
357
  | drop_package_stmt { $$ = $1; }
358
  | sql_stmt { $$ = $1; }
359
  | call_sp_stmt { $$ = $1; }
360
  | do_sp_stmt { $$ = $1; }
361
  | signal_stmt { $$ = $1; }
362
  | resignal_stmt { $$ = $1; }
363
  | package_block { $$ = $1; }
364
  | package_body_block { $$ = $1; }
365
  | create_trigger_stmt { $$ = $1; }
366
  | drop_trigger_stmt { $$ = $1; }
367
  | plsql_trigger_source
368
    {
369
      if (!parse_ctx->is_inner_parse_) {
370
        obpl_mysql_yyerror(&@1, parse_ctx, "Syntax Error\n");
371
        YYERROR;
372
      }
373
      $$ = $1;
374
    }
375
;
376

377
/*****************************************************************************
378
 *
379
 *      sql_stmt grammar
380
 *
381
 *****************************************************************************/
382
sql_keyword:
383
    '(' sql_keyword { $$ = NULL; }
384
  | SQL_KEYWORD { $$ = NULL; }
385
  | TABLE { $$ = NULL; }
386
  | INSERT { $$ = NULL; }
387
  | DELETE { $$ = NULL; }
388
  | UPDATE { $$ = NULL; }
389
;
390

391
sql_stmt:
392
    sql_keyword /*sql stmt tail*/
393
    {
394
      //read sql query string直到读到token';'或者END_P
395
      ParseNode *sql_stmt = NULL;
396
      do_parse_sql_stmt(sql_stmt, parse_ctx, @1.first_column, @1.last_column, 2, ';', END_P);
397
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SQL_STMT, 1, sql_stmt);
398
    }
399
  | REPLACE /*sql stmt tail*/
400
    {
401
      //read sql query string直到读到token';'或者END_P
402
      ParseNode *sql_stmt = NULL;
403
      do_parse_sql_stmt(sql_stmt, parse_ctx, @1.first_column, @1.last_column, 2, ';', END_P);
404
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SQL_STMT, 1, sql_stmt);
405
    }
406
  | CREATE sql_keyword /*sql stmt tail*/
407
    {
408
      //read sql query string直到读到token';'或者END_P
409
      ParseNode *sql_stmt = NULL;
410
      do_parse_sql_stmt(sql_stmt, parse_ctx, @1.first_column, @1.last_column, 2, ';', END_P);
411
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SQL_STMT, 1, sql_stmt);
412
    }
413
  | CREATE OR REPLACE sql_keyword /*sql stmt tail*/
414
    {
415
      //read sql query string直到读到token';'或者END_P
416
      ParseNode *sql_stmt = NULL;
417
      do_parse_sql_stmt(sql_stmt, parse_ctx, @1.first_column, @1.last_column, 2, ';', END_P);
418
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SQL_STMT, 1, sql_stmt);
419
    }
420
  | DROP sql_keyword /*sql stmt tail*/
421
    {
422
      //read sql query string直到读到token';'或者END_P
423
      ParseNode *sql_stmt = NULL;
424
      do_parse_sql_stmt(sql_stmt, parse_ctx, @1.first_column, @1.last_column, 2, ';', END_P);
425
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SQL_STMT, 1, sql_stmt);
426
    }
427
  | ALTER sql_keyword /*sql stmt tail*/
428
    {
429
      //read sql query string直到读到token';'或者END_P
430
      ParseNode *sql_stmt = NULL;
431
      do_parse_sql_stmt(sql_stmt, parse_ctx, @1.first_column, @1.last_column, 2, ';', END_P);
432
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SQL_STMT, 1, sql_stmt);
433
    }
434
  | SET /*sql stmt tail*/
435
    {
436
      //read sql query string直到读到token';'或者END_P
437
      ParseNode *sql_stmt = NULL;
438
      do_parse_sql_stmt(sql_stmt, parse_ctx, @1.first_column, @1.last_column, 2, ';', END_P);
439
      if (T_SET_PASSWORD == sql_stmt->type_ ||
440
          T_SET_NAMES == sql_stmt->type_ ||
441
          T_SET_CHARSET == sql_stmt->type_) {
442
        malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SQL_STMT, 1, sql_stmt);
443
      } else {
444
        $$ = sql_stmt;
445
      }
446
      if(T_VARIABLE_SET == $$->type_) {
447
        for(int64_t i = 0; i < $$->num_child_; ++i) {
448
          if(OB_UNLIKELY(NULL == $$->children_[i] || NULL == $$->children_[i]->children_[1])) {
449
            YY_UNEXPECTED_ERROR("value node in SET statement is NULL");
450
          } else {
451
            obpl_mysql_wrap_get_user_var_into_subquery(parse_ctx, $$->children_[i]->children_[1]);
452
          }
453
        }
454
      }
455
    }
456
  | COMMIT
457
    {
458
      malloc_terminal_node($$, parse_ctx->mem_pool_, T_SQL_STMT);
459
      $$->str_value_ = parse_strdup("COMMIT", parse_ctx->mem_pool_, &($$->str_len_));
460
      if (OB_UNLIKELY(NULL == $$->str_value_)) {
461
        YY_FATAL_ERROR("no more memory to malloc 'COMMIT; string\n");
462
      }
463
    }
464
  | ROLLBACK
465
    {
466
      malloc_terminal_node($$, parse_ctx->mem_pool_, T_SQL_STMT);
467
      $$->str_value_ = parse_strdup("ROLLBACK", parse_ctx->mem_pool_, &($$->str_len_));
468
      if (OB_UNLIKELY(NULL == $$->str_value_)) {
469
        YY_FATAL_ERROR("no more memory to malloc 'ROLLBACK; string\n");
470
      }
471
    }
472
  | SELECT //为了支持(select……)的用法,把SELECT也从sql_keyword分支里拿出来
473
  {
474
    //read sql query string直到读到token';'或者END_P
475
    ParseNode *sql_stmt = NULL;
476
    do_parse_sql_stmt(sql_stmt, parse_ctx, @1.first_column, @1.last_column, 2, ';', END_P);
477
    malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SQL_STMT, 1, sql_stmt);
478
  }
479
  | '(' SELECT %prec PARENS
480
  {
481
      //read sql query string直到读到token';'或者END_P
482
      ParseNode *sql_stmt = NULL;
483
      do_parse_sql_stmt(sql_stmt, parse_ctx, @1.first_column, @1.last_column, 2, ';', END_P);
484
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SQL_STMT, 1, sql_stmt);
485
  }
486
;
487

488
do_sp_stmt:
489
    DO expr_list
490
    {
491
      if (NULL == $2) {
492
        obpl_mysql_yyerror(&@2, parse_ctx, "Syntax Error, Invalid expr to be evaluated\n");
493
        YYERROR;
494
      } else if (T_OBJ_ACCESS_REF == $2->type_) {
495
        ParseNode *cur_node = $2;
496
        ParseNode *last_node = NULL;
497
        while (NULL != cur_node->children_[1] && T_OBJ_ACCESS_REF == cur_node->children_[1]->type_) {
498
          last_node = cur_node;
499
          cur_node = cur_node->children_[1];
500
        }
501
        if (OB_UNLIKELY(NULL == cur_node || NULL != cur_node->children_[1] || NULL == cur_node->children_[0])) {
502
          obpl_mysql_yyerror(&@2, parse_ctx, "Syntax Error, Invalid ObjAccess string\n");
503
          YYERROR;
504
        } else if (T_IDENT == cur_node->children_[0]->type_
505
            && 6 == cur_node->children_[0]->str_len_
506
            && 0 == strncasecmp(cur_node->children_[0]->str_value_, "EXTEND", 6)) {
507
          if (OB_UNLIKELY(NULL == last_node)) {
508
            obpl_mysql_yyerror(&@2, parse_ctx, "Syntax Error, Invalid ObjAccess string\n");
509
            YYERROR;
510
          } else {
511
            last_node->children_[1] = NULL;
512
            malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_EXTEND, 2, $2, NULL);
513
          }
514
        } else if (T_FUN_SYS == cur_node->children_[0]->type_
515
            && NULL != cur_node->children_[0]->children_[0]
516
            && T_IDENT == cur_node->children_[0]->children_[0]->type_
517
            && 6 == cur_node->children_[0]->children_[0]->str_len_
518
            && 0 == strncasecmp(cur_node->children_[0]->children_[0]->str_value_, "EXTEND", 6)) {
519
          if (OB_UNLIKELY(NULL == last_node)) {
520
            obpl_mysql_yyerror(&@2, parse_ctx, "Syntax Error, Invalid ObjAccess string\n");
521
            YYERROR;
522
          } else {
523
            last_node->children_[1] = NULL;
524
            malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_EXTEND, 2, $2, cur_node->children_[0]);
525
          }
526
        } else {
527
        ParseNode *do_expr_list = NULL;
528
        merge_nodes(do_expr_list, parse_ctx->mem_pool_, T_EXPR_LIST, $2);
529
        malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_DO, 1, do_expr_list);
530
        }
531
      } else {
532
        ParseNode *do_expr_list = NULL;
533
        merge_nodes(do_expr_list, parse_ctx->mem_pool_, T_EXPR_LIST, $2);
534
        for (int64_t i = 0; i < do_expr_list->num_child_; ++i) {
535
          if (T_COLUMN_REF == do_expr_list->children_[i]->type_) {
536
            obpl_mysql_yyerror(&@2, parse_ctx, "Syntax Error, DO statement cannot reference to a table\n");
537
            YYERROR;
538
            break;
539
          }
540
        }
541
        malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_DO, 1, do_expr_list);
542
      }
543
    }
544
  | DO sp_proc_stmt_open { $$ = $2; }
545
  | DO sp_proc_stmt_fetch { $$ = $2; }
546
  | DO sp_proc_stmt_close { $$ = $2; }
547
;
548

549
call_sp_stmt:
550
    CALL sp_call_name opt_sp_cparam_list
551
    {
552
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_CALL_STMT, 2, $2, $3);
553
    }
554
  | CALL sp_proc_stmt
555
    {
556
      if (!parse_ctx->is_inner_parse_) {
557
        obpl_mysql_yyerror(&@2, parse_ctx, "Syntax Error\n");
558
        YYERROR; //生成一个语法错误
559
      }
560
      $$ = $2;
561
    }
562
  | CALL PROCEDURE sp_name '(' opt_sp_param_list ')' sp_create_chistics procedure_body
563
    {
564
      if (!parse_ctx->is_inner_parse_) {
565
        obpl_mysql_yyerror(&@2, parse_ctx, "Syntax Error\n");
566
        YYERROR; //生成一个语法错误
567
      }
568
      $$ = $8;
569
    }
570
  | CALL PROCEDURE sp_name '(' opt_sp_param_list ')' procedure_body
571
    {
572
      if (!parse_ctx->is_inner_parse_) {
573
        obpl_mysql_yyerror(&@2, parse_ctx, "Syntax Error\n");
574
        YYERROR; //生成一个语法错误
575
      }
576
      $$ = $7;
577
    }
578
  | CALL FUNCTION sp_name '(' opt_sp_fparam_list ')' RETURNS sp_data_type sp_create_chistics function_body
579
    {
580
      if (!parse_ctx->is_inner_parse_) {
581
        obpl_mysql_yyerror(&@2, parse_ctx, "Syntax Error\n");
582
        YYERROR; //生成一个语法错误
583
      }
584
      $$ = $10;
585
    }
586
  | CALL FUNCTION sp_name '(' opt_sp_fparam_list ')' RETURNS sp_data_type function_body
587
    {
588
      if (!parse_ctx->is_inner_parse_) {
589
        obpl_mysql_yyerror(&@2, parse_ctx, "Syntax Error\n");
590
        YYERROR; //生成一个语法错误
591
      }
592
      $$ = $9;
593
    }
594
;
595

596
opt_sp_cparam_list:
597
    /* Empty */ { $$ = NULL; }
598
  | '(' ')' { $$ = NULL; }
599
  | '(' sp_cparams ')'
600
    {
601
      merge_nodes($$, parse_ctx->mem_pool_, T_SP_CPARAM_LIST, $2);
602
    }
603
;
604

605
sp_cparams:
606
    sp_cparams ',' sp_cparam
607
    {
608
      if ($1 == NULL || $3 == NULL) {
609
        YYERROR;
610
      }
611
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_LINK_NODE, 2, $1, $3);
612
    }
613
  | sp_cparam { $$ = $1; }
614
;
615

616
sp_cparam:
617
  cexpr opt_sp_cparam_with_assign
618
  {
619
    if (NULL == $1 && NULL != $2) {
620
      YYERROR;
621
    }
622
    if (NULL == $2) {
623
      $$ = $1;
624
    }
625
    if (NULL != $2) {
626
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_CPARAM, 2, $1, $2);
627
    }
628
      if (NULL != $1)
629
    copy_node_abs_location($1->stmt_loc_, @1);
630
  }
631
;
632

633
opt_sp_cparam_with_assign:
634
    /*EMPTY*/ { $$ = NULL; }
635
  | PARAM_ASSIGN_OPERATOR cexpr
636
  {
637
    if (NULL == $2) YYERROR; $$ = $2;
638
      if (NULL != $2)
639
    copy_node_abs_location($2->stmt_loc_, @2);
640
  }
641
;
642

643
cexpr:
644
    %prec LOWER_PARENS {
645
      //same as expr in sql rule, and terminate when read ';'
646
      do_parse_sql_expr_rule($$, parse_ctx, 3, ',', ')', PARAM_ASSIGN_OPERATOR);
647
      if (NULL == $$) {
648
        YYERROR;
649
      }
650
    }
651
;
652

653
/*****************************************************************************
654
 *
655
 *      common pl grammar
656
 *
657
 *****************************************************************************/
658
sp_name:
659
    ident '.' ident
660
    {
661
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_NAME, 2, $1, $3);
662
    }
663
  | ident
664
    {
665
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_NAME, 2, NULL, $1);
666
    }
667
;
668

669
sp_call_name:
670
    ident '.' ident '.' ident
671
    {
672
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_ACCESS_NAME, 3, $1, $3, $5);
673
    }
674
  | ident '.' ident
675
    {
676
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_ACCESS_NAME, 3, NULL, $1, $3);
677
    }
678
  | ident
679
    {
680
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_ACCESS_NAME, 3, NULL, NULL, $1);
681
    }
682
;
683

684
ident:
685
    IDENT
686
    {
687
      $$ = $1;
688
      $$->pl_str_off_ = @1.first_column;
689
    }
690
  | unreserved_keyword
691
    {
692
      get_non_reserved_node($$, parse_ctx->mem_pool_, @1.first_column, @1.last_column);
693
      $$->pl_str_off_ = @1.first_column;
694
    }
695
;
696

697
unreserved_keyword:
698
    AFTER
699
  | AUTHID
700
  | BEGIN_KEY %prec LOWER_PARENS
701
  | BINARY_INTEGER
702
  | BODY %prec LOWER_PARENS
703
  | C
704
  | CATALOG_NAME
705
  | CLASS_ORIGIN
706
  | CLOSE
707
  | COLUMN_NAME
708
  | COMMENT
709
  | CONSTRAINT_CATALOG
710
  | CONSTRAINT_NAME
711
  | CONSTRAINT_ORIGIN
712
  | CONSTRAINT_SCHEMA
713
  | CONTAINS
714
  | COUNT
715
  | CURSOR_NAME
716
  | DATA
717
  | DEFINER
718
  | END_KEY %prec LOWER_PARENS
719
  | EXTEND
720
  | FOUND
721
  | FUNCTION
722
  | HANDLER
723
  | INTERFACE 
724
  | INVOKER
725
  | JSON
726
  | LANGUAGE
727
  | MESSAGE_TEXT
728
  | MYSQL_ERRNO
729
  | NEXT
730
  | NO
731
  | OF
732
  | OPEN
733
  | PACKAGE
734
  | PRAGMA
735
  | RECORD
736
  | RETURNS
737
  | ROW
738
  | ROWTYPE
739
  | SCHEMA_NAME
740
  | SECURITY
741
  | SUBCLASS_ORIGIN
742
  | TABLE_NAME
743
  | TYPE
744
  | VALUE
745
;
746

747
/*****************************************************************************
748
 *
749
 *      CREATE PACKAGE grammar
750
 *
751
 *****************************************************************************/
752
create_package_stmt:
753
    CREATE opt_replace package_block
754
    {
755
      const char *stmt_str = parse_ctx->orig_stmt_str_ + @3.first_column;
756
      int32_t str_len = @3.last_column - @3.first_column + 1;
757
      $3->str_value_ = parse_strndup(stmt_str, str_len, parse_ctx->mem_pool_);
758
      check_ptr($3->str_value_);
759
      $3->str_len_ = str_len;
760
      $3->pl_str_off_ = @3.first_column;
761
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_PACKAGE_CREATE, 1, $3);
762
      $$->int32_values_[0] = $2;
763
      $$->int32_values_[1] = 0;
764
    }
765
;
766

767
package_block:
768
    PACKAGE sp_name opt_proc_clause opt_package_stmts END_KEY opt_tail_package_name
769
    {
770
      ParseNode *pkg_decl_stmts = NULL;
771
      merge_nodes(pkg_decl_stmts, parse_ctx->mem_pool_, T_PACKAGE_STMTS, $4);
772
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_PACKAGE_BLOCK, 4, $2, $3, pkg_decl_stmts, $6);
773
      if (parse_ctx->is_inner_parse_) {
774
        const char *stmt_str = parse_ctx->orig_stmt_str_ + @4.first_column;
775
        int32_t str_len = @6.last_column - @4.first_column + 1;
776
        $$->str_value_ = parse_strndup(stmt_str, str_len, parse_ctx->mem_pool_);
777
        check_ptr($$->str_value_);
778
        $$->str_len_ = str_len;
779
        $$->pl_str_off_ = @4.first_column;
780
      }
781
    }
782
;
783

784
invoke_right:
785
    AUTHID CURRENT_USER
786
    {
787
      malloc_terminal_node($$, parse_ctx->mem_pool_, T_SP_INVOKE);
788
      $$->value_ = SP_CURRENT_USER;
789
    }
790
  | AUTHID DEFINER
791
    {
792
      malloc_terminal_node($$, parse_ctx->mem_pool_, T_SP_INVOKE);
793
      $$->value_ = SP_DEFINER;
794
    }
795
;
796

797
proc_clause:
798
    invoke_right { $$ = $1; }
799
;
800

801
proc_clause_list:
802
    proc_clause_list proc_clause
803
    {
804
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_LINK_NODE, 2, $1, $2);
805
    }
806
  | proc_clause { $$ = $1; }
807
;
808

809
opt_proc_clause:
810
    /*EMPTY*/ { $$ = NULL; }
811
  | proc_clause_list
812
    {
813
      merge_nodes($$, parse_ctx->mem_pool_, T_SP_CLAUSE_LIST, $1);
814
    }
815
;
816

817
opt_replace:
818
      /*EMPTY*/       { $$ = 0; }
819
    | OR REPLACE      { $$ = 1; }
820
;
821

822
opt_package_stmts:
823
    /*Empty*/ { $$ = NULL; }
824
  | package_stmts 
825
    {
826
      merge_nodes($$, parse_ctx->mem_pool_, T_PACKAGE_STMTS, $1);
827
    }
828
;
829

830
package_stmts:
831
    package_stmts package_stmt ';'
832
    {
833
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_LINK_NODE, 2, $1, $2);
834
    }
835
  | package_stmt ';' { $$ = $1; }
836
  
837
package_stmt:
838
    sp_decl    { $$ = $1; }
839
  | func_decl  { $$ = $1; }
840
  | proc_decl  { $$ = $1; }
841
;
842

843
func_decl:
844
    FUNCTION ident '(' opt_sp_param_list ')' RETURN sp_data_type
845
    {
846
      const char *stmt_str = parse_ctx->stmt_str_ + @1.first_column;
847
      int32_t str_len = @7.last_column - @1.first_column + 1;
848
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SUB_FUNC_DECL, 5, $2, $4, $7, NULL, NULL);
849
      check_ptr($$);
850
      $$->str_value_ = parse_strndup(stmt_str, str_len, parse_ctx->mem_pool_);
851
      check_ptr($$->str_value_);
852
      $$->str_len_ = str_len;
853
    }
854
;
855

856
proc_decl:
857
    PROCEDURE ident '(' opt_sp_param_list ')'
858
    {
859
      const char *stmt_str = parse_ctx->stmt_str_ + @1.first_column;
860
      int32_t str_len = @5.last_column - @1.first_column + 1;
861
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SUB_PROC_DECL, 3, $2, $4, NULL);
862
      check_ptr($$);
863
      $$->str_value_ = parse_strndup(stmt_str, str_len, parse_ctx->mem_pool_);
864
      check_ptr($$->str_value_);
865
      $$->str_len_ = str_len;
866
    }
867
;
868

869
opt_tail_package_name:
870
      /*EMPTY*/     { $$ = NULL; }
871
    | ident         { $$ = $1; }
872
;
873

874
/*****************************************************************************
875
 *
876
 *      CREATE PACKAGE BODY grammar
877
 *
878
 *****************************************************************************/
879
create_package_body_stmt:
880
    CREATE opt_replace package_body_block
881
    {
882
      check_ptr($3);
883
      const char *stmt_str = parse_ctx->orig_stmt_str_ + @3.first_column;
884
      int32_t str_len = @3.last_column - @3.first_column + 1;
885
      $3->str_value_ = parse_strndup(stmt_str, str_len, parse_ctx->mem_pool_);
886
      check_ptr($3->str_value_);
887
      $3->str_len_ = str_len;
888
      $3->pl_str_off_ = @3.first_column;
889
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_PACKAGE_CREATE_BODY, 1, $3);
890
      $$->int32_values_[0] = $2;
891
      $$->int32_values_[1] = 0;
892
    }
893
;
894

895

896
package_body_block:
897
    PACKAGE BODY sp_name decl_stmt_ext_list sp_proc_stmts END_KEY opt_tail_package_name %prec PARENS
898
    {
899
      ParseNode *proc_stmts = NULL;
900
      ParseNode *decl_ext_list = NULL;
901
      merge_nodes(decl_ext_list, parse_ctx->mem_pool_, T_PACKAGE_BODY_STMTS, $4);
902
      merge_nodes(proc_stmts, parse_ctx->mem_pool_, T_SP_PROC_STMT_LIST, $5);
903
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_PACKAGE_BODY_BLOCK, 4, $3, decl_ext_list, proc_stmts, $7);
904
      if (parse_ctx->is_inner_parse_) {
905
        const char *stmt_str = parse_ctx->orig_stmt_str_ + @4.first_column;
906
        int32_t str_len = @7.last_column - @4.first_column + 1;
907
        $$->str_value_ = parse_strndup(stmt_str, str_len, parse_ctx->mem_pool_);
908
        check_ptr($$->str_value_);
909
        $$->str_len_ = str_len;
910
        $$->pl_str_off_ = @4.first_column;
911
      }
912
    }
913
  | PACKAGE BODY sp_name sp_proc_stmts END_KEY opt_tail_package_name %prec PARENS
914
    {
915
      ParseNode *proc_stmts = NULL;
916
      ParseNode *decl_ext_list = NULL;
917
      merge_nodes(proc_stmts, parse_ctx->mem_pool_, T_SP_PROC_STMT_LIST, $4);
918
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_PACKAGE_BODY_BLOCK, 4, $3, decl_ext_list, proc_stmts, $6);
919
      if (parse_ctx->is_inner_parse_) {
920
        const char *stmt_str = parse_ctx->orig_stmt_str_ + @4.first_column;
921
        int32_t str_len = @6.last_column - @4.first_column + 1;
922
        $$->str_value_ = parse_strndup(stmt_str, str_len, parse_ctx->mem_pool_);
923
        check_ptr($$->str_value_);
924
        $$->str_len_ = str_len;
925
        $$->pl_str_off_ = @4.first_column;
926
      }
927
    }
928
  | PACKAGE BODY sp_name decl_stmt_ext_list END_KEY opt_tail_package_name %prec PARENS
929
    {
930
      ParseNode *proc_stmts = NULL;
931
      ParseNode *decl_ext_list = NULL;
932
      merge_nodes(decl_ext_list, parse_ctx->mem_pool_, T_PACKAGE_BODY_STMTS, $4);
933
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_PACKAGE_BODY_BLOCK, 4, $3, decl_ext_list, proc_stmts, $6);
934
      if (parse_ctx->is_inner_parse_) {
935
        const char *stmt_str = parse_ctx->orig_stmt_str_ + @4.first_column;
936
        int32_t str_len = @6.last_column - @4.first_column + 1;
937
        $$->str_value_ = parse_strndup(stmt_str, str_len, parse_ctx->mem_pool_);
938
        check_ptr($$->str_value_);
939
        $$->str_len_ = str_len;
940
      }
941
    }
942
  | PACKAGE BODY sp_name END_KEY opt_tail_package_name %prec PARENS
943
    {
944
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_PACKAGE_BODY_BLOCK, 4, $3, NULL, NULL, $5);
945
      if (parse_ctx->is_inner_parse_) {
946
        const char *stmt_str = parse_ctx->orig_stmt_str_ + @4.first_column;
947
        int32_t str_len = @5.last_column - @4.first_column + 1;
948
        $$->str_value_ = parse_strndup(stmt_str, str_len, parse_ctx->mem_pool_);
949
        check_ptr($$->str_value_);
950
        $$->str_len_ = str_len;
951
        $$->pl_str_off_ = @4.first_column;
952
      }
953
    }
954
;
955

956
/*****************************************************************************
957
 *
958
 *      DROP PACKAGE grammar
959
 *
960
 *****************************************************************************/
961
drop_package_stmt:
962
    DROP PACKAGE sp_name
963
    {
964
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_PACKAGE_DROP, 1, $3);
965
      $$->value_ = 0;
966
    }
967
    | DROP PACKAGE BODY sp_name
968
    {
969
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_PACKAGE_DROP, 1, $4);
970
      $$->value_ = 2;
971
    }
972
;
973

974
interface_pragma:
975
  PRAGMA INTERFACE '(' C ',' ident ')'
976
  {
977
    malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_PRAGMA_INTERFACE, 1, $6);
978
  }
979
;
980

981
decl_stmt_ext_list:
982
    decl_stmt_ext ';' { $$ = $1; }
983
  | decl_stmt_ext_list decl_stmt_ext ';'
984
    {
985
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_LINK_NODE, 2, $1, $2);
986
    }
987
;
988

989
decl_stmt_ext:
990
    sp_decl   { $$ = $1; }
991
  | func_decl  { $$ = $1; }
992
  | proc_decl  { $$ = $1; }
993
  | interface_pragma { $$ = $1; }
994
  | func_decl /*is_or_as*/ function_body
995
    {
996
      check_ptr($2);
997
      const char *stmt_str = parse_ctx->stmt_str_ + @1.first_column;
998
      int32_t str_len = @2.last_column - @1.first_column + 1;
999
      $2->str_value_ = parse_strndup(stmt_str, str_len, parse_ctx->mem_pool_);
1000
      check_ptr($2->str_value_);
1001
      $2->str_len_ = str_len;
1002
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SUB_FUNC_DEF, 2, $1, $2);
1003
    }
1004
  | proc_decl /*is_or_as*/ procedure_body 
1005
    {
1006
      check_ptr($2);
1007
      const char *stmt_str = parse_ctx->stmt_str_ + @1.first_column;
1008
      int32_t str_len = @2.last_column - @1.first_column + 1;
1009
      $2->str_value_ = parse_strndup(stmt_str, str_len, parse_ctx->mem_pool_);
1010
      check_ptr($2->str_value_);
1011
      $2->str_len_ = str_len;
1012
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SUB_PROC_DEF, 2, $1, $2);
1013
    }
1014
;
1015

1016
/*****************************************************************************
1017
 *
1018
 *      CREATE TRIGGER grammar
1019
 *
1020
 *****************************************************************************/
1021
create_trigger_stmt:
1022
    CREATE opt_sp_definer plsql_trigger_source
1023
    {
1024
      check_ptr($3);
1025
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_TG_CREATE, 2, $2, $3);
1026
      $$->int32_values_[0] = 0; // or_replace = false
1027
      $$->int32_values_[1] = 0; // editionable = false
1028
    }
1029
;
1030

1031
plsql_trigger_source:
1032
    TRIGGER sp_name trigger_definition
1033
    {
1034
      check_ptr($3);
1035
      const char *stmt_str = parse_ctx->stmt_str_ + @1.first_column;
1036
      int32_t str_len = @3.last_column - @1.first_column + 1;
1037
      $3->str_value_ = parse_strndup(stmt_str, str_len, parse_ctx->mem_pool_);
1038
      check_ptr($3->str_value_);
1039
      $3->str_len_ = str_len;
1040
      $3->pl_str_off_ = @1.first_column;
1041
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_TG_SOURCE, 2, $2, $3);
1042
    }
1043
;
1044

1045
trigger_definition:
1046
    trigger_time trigger_event ON sp_name FOR EACH ROW opt_trigger_order trigger_body
1047
    {
1048
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_TG_SIMPLE_DML, 4, $2, $4, $8, $9);
1049
      $$->int16_values_[0] = $1;
1050
    }
1051

1052
trigger_time:
1053
    BEFORE { $$ = T_BEFORE; }
1054
  | AFTER  { $$ = T_AFTER; }
1055
;
1056

1057
trigger_event:
1058
    INSERT { malloc_terminal_node($$, parse_ctx->mem_pool_, T_INSERT); }
1059
  | DELETE { malloc_terminal_node($$, parse_ctx->mem_pool_, T_DELETE); }
1060
  | UPDATE { malloc_terminal_node($$, parse_ctx->mem_pool_, T_UPDATE); }
1061
;
1062

1063
opt_trigger_order:
1064
    /*EMPTY*/ { $$ = NULL; }
1065
  | FOLLOWS sp_name
1066
   {
1067
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_TG_ORDER, 1, $2);
1068
      $$->value_ = 1; // FOLLOWS
1069
   }
1070
  | PRECEDES sp_name
1071
    {
1072
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_TG_ORDER, 1, $2);
1073
      $$->value_ = 2; // PRECEDES
1074
    }
1075

1076
trigger_body:
1077
  sp_proc_stmt
1078
  {
1079
    $$ = $1;
1080
    const char *body_str = parse_ctx->stmt_str_ + @1.first_column;
1081
    int32_t body_len = @1.last_column - @1.first_column + 1 + 2;
1082
    char *dup_body = NULL;
1083
    if (OB_LIKELY(NULL != (dup_body = (char *)parse_malloc(body_len + 1, parse_ctx->mem_pool_)))) {
1084
      memmove(dup_body, body_str, body_len - 2);
1085
      dup_body[body_len - 2] = ';';
1086
      dup_body[body_len - 1] = '\n';
1087
      dup_body[body_len] = '\0';
1088
    }
1089
    check_ptr(dup_body);
1090
    $$->str_value_ = dup_body;
1091
    $$->str_len_ = body_len;
1092
    $$->pl_str_off_ = @1.first_column;
1093
  }
1094
;
1095

1096
/*****************************************************************************
1097
 *
1098
 *      DROP TRIGGER grammar
1099
 *
1100
 *****************************************************************************/
1101
drop_trigger_stmt:
1102
    DROP TRIGGER opt_if_exists sp_name
1103
    {
1104
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_TG_DROP, 1, $4);
1105
      $$->value_ = $3;
1106
    }
1107
;
1108

1109
/*****************************************************************************
1110
 *
1111
 *      CREATE PROCEDURE grammar
1112
 *
1113
 *****************************************************************************/
1114
create_procedure_stmt:
1115
    CREATE opt_sp_definer PROCEDURE sp_name '(' opt_sp_param_list ')' sp_create_chistics procedure_body
1116
    {
1117
      check_ptr($9);
1118
      ParseNode *sp_clause_node = NULL;
1119
      merge_nodes(sp_clause_node, parse_ctx->mem_pool_, T_SP_CLAUSE_LIST, $8);
1120
      const char *stmt_str = parse_ctx->stmt_str_ + @3.first_column;
1121
      int32_t str_len = @9.last_column - @3.first_column + 1;
1122
      $9->str_value_ = parse_strndup(stmt_str, str_len, parse_ctx->mem_pool_);
1123
      check_ptr($9->str_value_);
1124
      $9->str_len_ = str_len;
1125
      $9->raw_text_ = $9->str_value_ + @9.first_column - @3.first_column;
1126
      $9->text_len_ = str_len - (@9.first_column - @3.first_column);
1127
      if (NULL != $6) {
1128
        const char *param_str = parse_ctx->stmt_str_ + @5.first_column + 1;
1129
        int32_t param_len = @7.last_column - @5.last_column - 1;
1130
        $6->str_value_ = parse_strndup(param_str, param_len, parse_ctx->mem_pool_);
1131
        check_ptr($6->str_value_);
1132
        $6->str_len_ = param_len;
1133
      }
1134
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_CREATE, 5, $2, $4, $6, sp_clause_node, $9);
1135
    }
1136
  | CREATE opt_sp_definer PROCEDURE sp_name '(' opt_sp_param_list ')' procedure_body
1137
    {
1138
      check_ptr($8);
1139
      const char *stmt_str = parse_ctx->stmt_str_ + @3.first_column;
1140
      int32_t str_len = @8.last_column - @3.first_column + 1;
1141
      $8->str_value_ = parse_strndup(stmt_str, str_len, parse_ctx->mem_pool_);
1142
      check_ptr($8->str_value_);
1143
      $8->str_len_ = str_len;
1144
      $8->raw_text_ = $8->str_value_ + @8.first_column - @3.first_column;
1145
      $8->text_len_ = str_len - (@8.first_column - @3.first_column);
1146
      if (NULL != $6) {
1147
        const char *param_str = parse_ctx->stmt_str_ + @5.first_column + 1;
1148
        int32_t param_len = @7.last_column - @5.last_column - 1;
1149
        $6->str_value_ = parse_strndup(param_str, param_len, parse_ctx->mem_pool_);
1150
        check_ptr($6->str_value_);
1151
        $6->str_len_ = param_len;
1152
      }
1153
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_CREATE, 5, $2, $4, $6, NULL, $8);
1154
    }
1155
;
1156

1157
create_function_stmt:
1158
    CREATE opt_sp_definer FUNCTION sp_name '(' opt_sp_fparam_list ')' RETURNS sp_data_type sp_create_chistics function_body
1159
    {
1160
      check_ptr($11);
1161
      ParseNode *sp_clause_node = NULL;
1162
      merge_nodes(sp_clause_node, parse_ctx->mem_pool_, T_SP_CLAUSE_LIST, $10);
1163
      const char *stmt_str = parse_ctx->stmt_str_ + @3.first_column;
1164
      int32_t str_len = @11.last_column - @3.first_column + 1;
1165
      $11->str_value_ = parse_strndup(stmt_str, str_len, parse_ctx->mem_pool_);
1166
      check_ptr($11->str_value_);
1167
      $11->str_len_ = str_len;
1168
      $11->raw_text_ = $11->str_value_ + @11.first_column - @3.first_column;
1169
      $11->text_len_ = str_len - (@11.first_column - @3.first_column);
1170
      if (NULL != $6) {
1171
        const char *param_str = parse_ctx->stmt_str_ + @5.first_column + 1;
1172
        int32_t param_len = @7.last_column - @5.last_column - 1;
1173
        $6->str_value_ = parse_strndup(param_str, param_len, parse_ctx->mem_pool_);
1174
        check_ptr($6->str_value_);
1175
        $6->str_len_ = param_len;
1176
      }
1177
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SF_CREATE, 6, $2, $4, $6, $9, sp_clause_node, $11);
1178
    }
1179
  | CREATE opt_sp_definer FUNCTION sp_name '(' opt_sp_fparam_list ')' RETURNS sp_data_type function_body
1180
    {
1181
      check_ptr($10);
1182
      const char *stmt_str = parse_ctx->stmt_str_ + @3.first_column;
1183
      int32_t str_len = @10.last_column - @3.first_column + 1;
1184
      $10->str_value_ = parse_strndup(stmt_str, str_len, parse_ctx->mem_pool_);
1185
      check_ptr($10->str_value_);
1186
      $10->str_len_ = str_len;
1187
      $10->raw_text_ = $10->str_value_ + @10.first_column - @3.first_column;
1188
      $10->text_len_ = str_len - (@10.first_column - @3.first_column);
1189
      if (NULL != $6) {
1190
        const char *param_str = parse_ctx->stmt_str_ + @5.first_column + 1;
1191
        int32_t param_len = @7.last_column - @5.last_column - 1;
1192
        $6->str_value_ = parse_strndup(param_str, param_len, parse_ctx->mem_pool_);
1193
        check_ptr($6->str_value_);
1194
        $6->str_len_ = param_len;
1195
      }
1196
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SF_CREATE, 6, $2, $4, $6, $9, NULL, $10);
1197
    }
1198
;
1199

1200
opt_sp_definer:
1201
    /* empty */ { $$ = NULL; }
1202
  | DEFINER '=' user opt_host_name
1203
  {
1204
    malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_USER_WITH_HOST_NAME, 2, $3, $4);
1205
  }
1206
  | DEFINER '=' CURRENT_USER opt_parentheses
1207
  {
1208
    ParseNode *user_node = NULL;
1209
    malloc_terminal_node(user_node, parse_ctx->mem_pool_, T_IDENT);
1210
    user_node->str_value_ = "CURRENT_USER";
1211
    user_node->str_len_ = strlen("CURRENT_USER");
1212
    malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_USER_WITH_HOST_NAME, 2, user_node, NULL);
1213
  }
1214
;
1215

1216
user:
1217
STRING
1218
{
1219
  $$ = $1;
1220
}
1221
| IDENT
1222
{
1223
  $$ = $1;
1224
}
1225

1226
opt_host_name:
1227
USER_VARIABLE
1228
{
1229
  $$ = $1;
1230
}
1231
|
1232
{
1233
  $$ = NULL;
1234
}
1235
;
1236

1237

1238
opt_parentheses:
1239
    /* empty */ { $$ = NULL; }
1240
  | '(' ')' { $$ = NULL; }
1241

1242
/*stored procedure param list*/
1243
opt_sp_param_list:
1244
    /* empty */ { $$ = NULL; }
1245
  | sp_param_list
1246
    {
1247
      merge_nodes($$, parse_ctx->mem_pool_, T_SP_PARAM_LIST, $1);
1248
    }
1249
;
1250

1251
sp_param_list:
1252
    sp_param_list ',' sp_param
1253
    {
1254
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_LINK_NODE, 2, $1, $3);
1255
    }
1256
  | sp_param { $$ = $1; }
1257
;
1258

1259
sp_param:
1260
    opt_sp_inout ident param_type opt_param_default
1261
    {
1262
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_PARAM, 3, $2, $3, $4);
1263
      $$->value_ = $1;
1264
    }
1265
;
1266

1267
/*stored function param list*/
1268
opt_sp_fparam_list:
1269
    /* empty */ { $$ = NULL; }
1270
  | sp_fparam_list
1271
    {
1272
      merge_nodes($$, parse_ctx->mem_pool_, T_SP_PARAM_LIST, $1);
1273
    }
1274
;
1275

1276
sp_fparam_list:
1277
    sp_fparam_list ',' sp_fparam
1278
    {
1279
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_LINK_NODE, 2, $1, $3);
1280
    }
1281
  | sp_fparam { $$ = $1; }
1282
;
1283

1284
sp_fparam:
1285
    ident param_type
1286
    {
1287
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_PARAM, 2, $1, $2);
1288
      $$->value_ = MODE_IN;
1289
    }
1290
;
1291

1292
opt_sp_inout:
1293
    /* Empty */ { $$ = MODE_IN; }
1294
  | IN      { $$ = MODE_IN; }
1295
  | OUT     { $$ = MODE_OUT; }
1296
  | INOUT { $$ = MODE_INOUT; }
1297
;
1298

1299
param_type:
1300
    sp_data_type { $$ = $1; }
1301

1302
simple_ident:
1303
    ident
1304
    {
1305
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_COLUMN_REF, 3, NULL, NULL, $1);
1306
    }
1307
  | ident '.' ident
1308
    {
1309
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_COLUMN_REF, 3, NULL, $1, $3);
1310
    }
1311
  | '.' ident '.' ident
1312
    {
1313
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_COLUMN_REF, 3, NULL, $2, $4);
1314
    }
1315
  | ident '.' ident '.' ident
1316
    {
1317
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_COLUMN_REF, 3, $1, $3, $5);
1318
    }
1319
;
1320

1321
sp_create_chistics:
1322
    sp_create_chistic { $$ = $1; }
1323
  | sp_create_chistics sp_create_chistic
1324
    {
1325
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_LINK_NODE, 2, $1, $2);
1326
    }
1327
;
1328

1329
sp_create_chistic:
1330
    sp_chistic { $$ = $1; }
1331
  | DETERMINISTIC
1332
  {
1333
    malloc_terminal_node($$, parse_ctx->mem_pool_, T_SP_DETERMINISTIC);
1334
  }
1335
  | NOT DETERMINISTIC { }
1336
;
1337

1338
sp_chistic:
1339
    COMMENT STRING
1340
  {
1341
    malloc_terminal_node($$, parse_ctx->mem_pool_, T_COMMENT);
1342
    $$->str_value_ = $2->str_value_;
1343
    $$->str_len_ = $2->str_len_;
1344
  }
1345
  | LANGUAGE SQL { /* Just parse it, we only have one language for now. */ $$ = NULL; }
1346
  | NO SQL
1347
  {
1348
    malloc_terminal_node($$, parse_ctx->mem_pool_, T_SP_DATA_ACCESS);
1349
    $$->value_ = SP_NO_SQL;
1350
  }
1351
  | CONTAINS SQL
1352
  {
1353
    malloc_terminal_node($$, parse_ctx->mem_pool_, T_SP_DATA_ACCESS);
1354
    $$->value_ = SP_CONTAINS_SQL;
1355
  }
1356
  | READS SQL DATA
1357
  {
1358
    malloc_terminal_node($$, parse_ctx->mem_pool_, T_SP_DATA_ACCESS);
1359
    $$->value_ = SP_READS_SQL_DATA;
1360
  }
1361
  | MODIFIES SQL DATA
1362
  {
1363
    malloc_terminal_node($$, parse_ctx->mem_pool_, T_SP_DATA_ACCESS);
1364
    $$->value_ = SP_MODIFIES_SQL_DATA;
1365
  }
1366
  | SQL SECURITY DEFINER
1367
  {
1368
    malloc_terminal_node($$, parse_ctx->mem_pool_, T_SP_INVOKE);
1369
    $$->value_ = SP_DEFINER;
1370
  }
1371
  | SQL SECURITY INVOKER
1372
  {
1373
    malloc_terminal_node($$, parse_ctx->mem_pool_, T_SP_INVOKE);
1374
    $$->value_ = SP_INVOKER;
1375
  }
1376
;
1377

1378
procedure_body:
1379
  sp_proc_stmt { $$ = $1; }
1380
;
1381

1382
function_body:
1383
  sp_proc_independent_statement { $$ = $1; }
1384
;
1385

1386
/*****************************************************************************
1387
 *
1388
 *      ALTER PROCEDURE grammar
1389
 *
1390
 *****************************************************************************/
1391
alter_procedure_stmt:
1392
    ALTER PROCEDURE sp_name opt_sp_alter_chistics
1393
    {
1394
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_ALTER, 2, $3, $4);
1395
    }
1396
;
1397

1398
alter_function_stmt:
1399
    ALTER FUNCTION sp_name opt_sp_alter_chistics
1400
    {
1401
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SF_ALTER, 2, $3, $4);
1402
    }
1403
;
1404

1405
opt_sp_alter_chistics:
1406
    /* empty */ { $$ = NULL; }
1407
  | sp_alter_chistics
1408
    {
1409
      merge_nodes($$, parse_ctx->mem_pool_, T_SP_CLAUSE_LIST, $1);
1410
    }
1411
;
1412

1413
sp_alter_chistics:
1414
  sp_chistic { $$ = $1; }
1415
  | sp_alter_chistics sp_chistic
1416
  {
1417
    malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_LINK_NODE, 2, $1, $2);
1418
  }
1419

1420
sp_proc_stmt:
1421
    sp_proc_outer_statement
1422
    {
1423
      $$ = $1;
1424
      copy_node_abs_location($$->stmt_loc_, @1);
1425
    }
1426
  | sp_proc_inner_statement
1427
    {
1428
      $$ = $1;
1429
      copy_node_abs_location($$->stmt_loc_, @1);
1430
    }
1431
;
1432

1433
sp_proc_outer_statement:
1434
    outer_stmt
1435
    {
1436
      $$ = $1;
1437
      const char *stmt_str = parse_ctx->stmt_str_ + @1.first_column;
1438
      int32_t str_len = @1.last_column - @1.first_column + 1;
1439
      $1->str_value_ = parse_strndup(stmt_str, str_len, parse_ctx->mem_pool_);
1440
      check_ptr($1->str_value_);
1441
      $1->str_len_ = str_len;
1442
    }
1443
;
1444

1445
sp_proc_inner_statement:
1446
  sp_proc_independent_statement
1447
    {
1448
      $$ = $1;
1449
      copy_node_abs_location($$->stmt_loc_, @1);
1450
    }
1451
  | sp_proc_stmt_iterate
1452
    {
1453
      $$ = $1;
1454
      copy_node_abs_location($$->stmt_loc_, @1);
1455
    }
1456
  | sp_proc_stmt_leave
1457
    {
1458
      $$ = $1;
1459
      copy_node_abs_location($$->stmt_loc_, @1);
1460
    }
1461
  | sp_proc_stmt_open
1462
    {
1463
      $$ = $1;
1464
      copy_node_abs_location($$->stmt_loc_, @1);
1465
    }
1466
  | sp_proc_stmt_fetch
1467
    {
1468
      $$ = $1;
1469
      copy_node_abs_location($$->stmt_loc_, @1);
1470
    }
1471
  | sp_proc_stmt_close
1472
    {
1473
      $$ = $1;
1474
      copy_node_abs_location($$->stmt_loc_, @1);
1475
    }
1476
;
1477

1478
sp_proc_independent_statement: //可以独立存在(不依赖于其他语句)的内部语句类型
1479
  sp_proc_stmt_if
1480
    {
1481
      $$ = $1;
1482
    }
1483
  | sp_proc_stmt_case
1484
    {
1485
      $$ = $1;
1486
    }
1487
  | sp_unlabeled_block
1488
    {
1489
      $$ = $1;
1490
    }
1491
  | sp_labeled_block
1492
    {
1493
      $$ = $1;
1494
    }
1495
  | sp_unlabeled_control
1496
    {
1497
      $$ = $1;
1498
    }
1499
  | sp_labeled_control
1500
    {
1501
      $$ = $1;
1502
    }
1503
  | sp_proc_stmt_return
1504
    {
1505
      $$ = $1;
1506
    }
1507
;
1508

1509
sp_proc_stmt_if:
1510
    IF sp_if END_KEY IF { $$ = $2; }
1511
;
1512

1513
sp_if:
1514
    expr THEN sp_proc_stmts sp_elseifs
1515
    {
1516
      ParseNode *proc_stmts = NULL;
1517
      merge_nodes(proc_stmts, parse_ctx->mem_pool_, T_SP_PROC_STMT_LIST, $3);
1518
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_IF, 3, $1, proc_stmts, $4);
1519
    }
1520
  | expr THEN sp_proc_stmts %prec PARENS
1521
    {
1522
      ParseNode *proc_stmts = NULL;
1523
      merge_nodes(proc_stmts, parse_ctx->mem_pool_, T_SP_PROC_STMT_LIST, $3);
1524
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_IF, 3, $1, proc_stmts, NULL);
1525
    }
1526
;
1527

1528
sp_proc_stmt_case:
1529
    CASE expr sp_when_list sp_elseifs END_KEY CASE
1530
    {
1531
      ParseNode *when_list = NULL;
1532
      merge_nodes(when_list, parse_ctx->mem_pool_, T_WHEN_LIST, $3);
1533
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_CASE, 3, $2, when_list, $4);
1534
    }
1535
  | CASE expr sp_when_list END_KEY CASE
1536
    {
1537
      ParseNode *when_list = NULL;
1538
      merge_nodes(when_list, parse_ctx->mem_pool_, T_WHEN_LIST, $3);
1539
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_CASE, 3, $2, when_list, NULL);
1540
    }
1541
;
1542

1543
sp_when_list:
1544
    sp_when { $$ = $1; }
1545
    | sp_when_list sp_when
1546
    {
1547
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_LINK_NODE, 2, $1, $2);
1548
    }
1549
;
1550

1551
sp_when:
1552
    WHEN expr THEN sp_proc_stmts %prec PARENS
1553
    {
1554
      ParseNode *proc_stmts = NULL;
1555
      merge_nodes(proc_stmts, parse_ctx->mem_pool_, T_SP_PROC_STMT_LIST, $4);
1556
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_WHEN, 2, $2, proc_stmts);
1557
    }
1558
;
1559

1560
sp_elseifs:
1561
  // | ELSE IF sp_if
1562
  //   {
1563
  //     ParseNode *proc_stmts = NULL;
1564
  //     merge_nodes(proc_stmts, parse_ctx->mem_pool_, T_SP_PROC_STMT_LIST, $3);
1565
  //     malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_ELSE, 1, proc_stmts);
1566
  //   }
1567
    ELSEIF sp_if
1568
    {
1569
      ParseNode *proc_stmts = NULL;
1570
      merge_nodes(proc_stmts, parse_ctx->mem_pool_, T_SP_PROC_STMT_LIST, $2);
1571
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_ELSE, 1, proc_stmts);
1572
    }
1573
  | ELSE sp_proc_stmts
1574
    {
1575
      ParseNode *proc_stmts = NULL;
1576
      merge_nodes(proc_stmts, parse_ctx->mem_pool_, T_SP_PROC_STMT_LIST, $2);
1577
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_ELSE, 1, proc_stmts);
1578
    }
1579
;
1580

1581
sp_unlabeled_block:
1582
    sp_block_content { $$ = $1; }
1583
;
1584

1585
sp_block_content:
1586
   BEGIN_KEY END_KEY
1587
    {
1588
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_BLOCK_CONTENT, 2, NULL, NULL);
1589
    }
1590
  |  BEGIN_KEY sp_decls END_KEY
1591
    {
1592
      ParseNode *decl_list = NULL;
1593
      merge_nodes(decl_list, parse_ctx->mem_pool_, T_SP_DECL_LIST, $2);
1594
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_BLOCK_CONTENT, 2, decl_list, NULL);
1595
    }
1596
  | BEGIN_KEY sp_proc_stmts END_KEY
1597
    {
1598
      ParseNode *proc_stmts = NULL;
1599
      merge_nodes(proc_stmts, parse_ctx->mem_pool_, T_SP_PROC_STMT_LIST, $2);
1600
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_BLOCK_CONTENT, 2, NULL, proc_stmts);
1601
    }
1602
  | BEGIN_KEY sp_decls sp_proc_stmts END_KEY
1603
    {
1604
      ParseNode *decl_list = NULL;
1605
      ParseNode *proc_stmts = NULL;
1606
      merge_nodes(decl_list, parse_ctx->mem_pool_, T_SP_DECL_LIST, $2);
1607
      merge_nodes(proc_stmts, parse_ctx->mem_pool_, T_SP_PROC_STMT_LIST, $3);
1608
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_BLOCK_CONTENT, 2, decl_list, proc_stmts);
1609
    }
1610
;
1611

1612
sp_labeled_block:
1613
    label_ident ':' sp_block_content opt_sp_label
1614
    {
1615
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_LABELED_BLOCK, 3, $1, $3, $4);
1616
    }
1617
;
1618

1619
label_ident:
1620
    ident { $$ = $1; }
1621
;
1622

1623
opt_sp_label:
1624
    /* Empty */ { $$ = NULL }
1625
  | label_ident
1626
    {
1627
      $$ = $1;
1628
    }
1629
;
1630

1631
sp_proc_stmts:
1632
    sp_proc_stmt ';' { $$ = $1; }
1633
  | sp_proc_stmts sp_proc_stmt ';'
1634
    {
1635
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_LINK_NODE, 2, $1, $2);
1636
    }
1637
;
1638

1639
sp_decls:
1640
    sp_decls ';'
1641
    {
1642
      $$ = $1;
1643
    }
1644
  | opt_sp_decls sp_decl ';'
1645
    {
1646
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_LINK_NODE, 2, $1, $2);
1647
    }
1648
;
1649

1650

1651
opt_sp_decls:
1652
    /*Empty*/ { $$ = NULL; }
1653
  | opt_sp_decls sp_decl ';'
1654
    {
1655
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_LINK_NODE, 2, $1, $2);
1656
    }
1657
;
1658

1659
sp_decl:
1660
    DECLARE sp_decl_idents sp_data_type opt_sp_decl_default
1661
    {
1662
      ParseNode *decl_idents = NULL;
1663
      merge_nodes(decl_idents, parse_ctx->mem_pool_, T_SP_DECL_IDENT_LIST, $2);
1664
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_DECL, 3, decl_idents, $3, $4);
1665
      copy_node_abs_location($$->stmt_loc_, @1);
1666
    }
1667
  | DECLARE ident CONDITION FOR sp_cond
1668
    {
1669
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_DECL_COND, 2, $2, $5);
1670
      copy_node_abs_location($$->stmt_loc_, @1);
1671
    }
1672
  | DECLARE sp_handler_type HANDLER FOR sp_hcond_list sp_proc_stmt
1673
    {
1674
      ParseNode *hcond_list = NULL;
1675
      ParseNode *proc_stmts = NULL;
1676
      malloc_non_terminal_node(proc_stmts, parse_ctx->mem_pool_, T_SP_PROC_STMT_LIST, 1, $6);
1677
      merge_nodes(hcond_list, parse_ctx->mem_pool_, T_SP_HCOND_LIST, $5);
1678
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_DECL_HANDLER, 2, hcond_list, proc_stmts);
1679
      $$->value_ = $2;
1680
      copy_node_abs_location($$->stmt_loc_, @1);
1681
    }
1682
  | DECLARE ident CURSOR FOR sql_stmt
1683
    {
1684
      if ($5->children_[0]->type_ != T_SELECT) {
1685
        obpl_mysql_yyerror(&@5, parse_ctx, "Syntax Error\n");
1686
        YYERROR;
1687
      }
1688
      const char *stmt_str = parse_ctx->stmt_str_ + @5.first_column;
1689
      int32_t str_len = @5.last_column - @5.first_column + 1;
1690
      $5->str_value_ = parse_strndup(stmt_str, str_len, parse_ctx->mem_pool_);
1691
      check_ptr($5->str_value_);
1692
      $5->str_len_ = str_len;
1693
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_DECL_CURSOR, 4, $2, NULL, NULL, $5); //4参数和Oracle模式保持一致
1694
      copy_node_abs_location($$->stmt_loc_, @1);
1695
    }
1696
;
1697

1698
sp_handler_type:
1699
    EXIT { $$ = SP_HANDLER_TYPE_EXIT; }
1700
  | CONTINUE { $$ = SP_HANDLER_TYPE_CONTINUE; }
1701
;
1702

1703
sp_hcond_list:
1704
    sp_hcond { $$ = $1; }
1705
  | sp_hcond_list ',' sp_hcond
1706
    {
1707
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_LINK_NODE, 2, $1, $3);
1708
    }
1709
;
1710

1711
sp_hcond:
1712
    sp_cond { $$ = $1; }
1713
  | ident { $$ = $1; }
1714
  | SQLWARNING { malloc_terminal_node($$, parse_ctx->mem_pool_, T_SQL_WARNING); }
1715
  | NOT FOUND { malloc_terminal_node($$, parse_ctx->mem_pool_, T_SQL_NOT_FOUND); }
1716
  | SQLEXCEPTION { malloc_terminal_node($$, parse_ctx->mem_pool_, T_SQL_EXCEPTION); }
1717
;
1718

1719
sp_cond:
1720
    number_literal
1721
    {
1722
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_CONDITION, 1, $1);
1723
    }
1724
  | sqlstate
1725
    {
1726
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_CONDITION, 1, $1);
1727
    }
1728
;
1729

1730
sqlstate:
1731
    SQLSTATE opt_value STRING
1732
    {
1733
      (void)($2);
1734
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SQL_STATE, 1, $3);
1735
    }
1736
;
1737

1738
sp_proc_stmt_open:
1739
    OPEN ident
1740
    {
1741
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_PROC_OPEN, 3, $2, NULL, NULL, NULL); //4参数和Oracle模式保持一致
1742
    }
1743
;
1744

1745
sp_proc_stmt_close:
1746
    CLOSE ident
1747
    {
1748
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_PROC_CLOSE, 1, $2);
1749
    }
1750
;
1751

1752
sp_proc_stmt_fetch:
1753
    FETCH ident into_clause
1754
    {
1755
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_PROC_FETCH, 2, $2, $3);
1756
    }
1757
    | FETCH FROM ident into_clause
1758
    {
1759
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_PROC_FETCH, 2, $3, $4);
1760
    }
1761
    | FETCH NEXT FROM ident into_clause
1762
    {
1763
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_PROC_FETCH, 2, $4, $5);
1764
    }
1765
;
1766

1767
into_clause:
1768
    INTO expr_list
1769
    {
1770
      ParseNode *vars_list = NULL;
1771
      merge_nodes(vars_list, parse_ctx->mem_pool_, T_SP_INTO_LIST, $2);
1772
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_INTO_VARIABLES, 1, vars_list);
1773
    }
1774
;
1775

1776
opt_value:
1777
    /*Empty*/ { $$ = NULL; }
1778
  | VALUE { $$ = NULL; }
1779

1780
sp_decl_idents:
1781
    ident { $$ = $1; }
1782
  | sp_decl_idents ',' ident
1783
    {
1784
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_LINK_NODE, 2, $1, $3);
1785
    }
1786
;
1787

1788
sp_data_type:
1789
    scalar_data_type { $$ = $1; }
1790
;
1791

1792
opt_sp_decl_default:
1793
    /*Empty*/ { $$ = NULL; }
1794
  | DEFAULT expr
1795
    {
1796
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_DECL_DEFAULT, 1, $2);
1797
    }
1798
;
1799

1800
opt_param_default:
1801
    /*Empty*/ { $$ = NULL; }
1802
  | DEFAULT default_expr
1803
    {
1804
      if (NULL == $2) {
1805
        YYERROR;
1806
      }
1807
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_DECL_DEFAULT, 1, $2);
1808
      // 拷贝EXPR语句
1809
      const char *expr_str = parse_ctx->stmt_str_ + @2.first_column;
1810
      int32_t expr_str_len = @2.last_column - @2.first_column + 1;
1811
      $$->str_value_ = parse_strndup(expr_str, expr_str_len, parse_ctx->mem_pool_);
1812
      check_ptr($$->str_value_);
1813
      $$->str_len_ = expr_str_len;
1814
      if (NULL != $2) {
1815
        copy_node_abs_location($2->stmt_loc_, @2);
1816
      }
1817
    }
1818
;
1819

1820
default_expr:
1821
    {
1822
      do_parse_sql_expr_rule($$, parse_ctx, 3, ',', ')', ';');
1823
    }
1824
;
1825

1826
expr_list:
1827
    expr { $$ = $1; }
1828
  | expr_list ',' expr
1829
    {
1830
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_LINK_NODE, 2, $1, $3);
1831
    }
1832
;
1833

1834
expr:
1835
    {
1836
      //same as expr in sql rule, and terminate when read ';'
1837
      do_parse_sql_expr_rule($$, parse_ctx, 9, INTO, USING, WHEN, THEN, ';', DO, LIMIT, ',', END_KEY);
1838
      obpl_mysql_wrap_get_user_var_into_subquery(parse_ctx, $$);
1839
    }
1840
;
1841

1842
sp_unlabeled_control:
1843
    LOOP sp_proc_stmts END_KEY LOOP
1844
    {
1845
      ParseNode *proc_stmts = NULL;
1846
      merge_nodes(proc_stmts, parse_ctx->mem_pool_, T_SP_PROC_STMT_LIST, $2);
1847
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_LOOP, 1, proc_stmts);
1848
    }
1849
  | WHILE expr DO sp_proc_stmts END_KEY WHILE
1850
    {
1851
      ParseNode *proc_stmts = NULL;
1852
      merge_nodes(proc_stmts, parse_ctx->mem_pool_, T_SP_PROC_STMT_LIST, $4);
1853
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_WHILE, 2, $2, proc_stmts);
1854
    }
1855
  | REPEAT sp_proc_stmts UNTIL expr END_KEY REPEAT %prec PARENS
1856
    {
1857
      ParseNode *proc_stmts = NULL;
1858
      merge_nodes(proc_stmts, parse_ctx->mem_pool_, T_SP_PROC_STMT_LIST, $2);
1859
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_REPEAT, 2, proc_stmts, $4);
1860
    }
1861
;
1862

1863
sp_labeled_control:
1864
    label_ident ':' sp_unlabeled_control opt_sp_label
1865
    {
1866
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_LABELED_CONTROL, 3, $1, $3, $4);
1867
    }
1868
;
1869

1870
sp_proc_stmt_return:
1871
    RETURN expr
1872
    {
1873
      if (NULL == $2) YYERROR;
1874
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_RETURN, 1, $2);
1875
    }
1876
;
1877

1878
sp_proc_stmt_iterate:
1879
    ITERATE label_ident
1880
    {
1881
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_ITERATE, 2, $2, NULL);
1882
    }
1883
;
1884

1885
sp_proc_stmt_leave:
1886
    LEAVE label_ident
1887
    {
1888
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_LEAVE, 2, $2, NULL);
1889
    }
1890
;
1891

1892
drop_procedure_stmt:
1893
    DROP PROCEDURE opt_if_exists sp_name
1894
    {
1895
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_DROP, 1, $4);
1896
      $$->value_ = $3;
1897
    }
1898
;
1899

1900
drop_function_stmt:
1901
    DROP FUNCTION opt_if_exists sp_name
1902
    {
1903
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SF_DROP, 1, $4);
1904
      $$->value_ = $3;
1905
    }
1906
;
1907

1908
opt_if_exists:
1909
    /*Empty*/ { $$ = 0; }
1910
  | IF EXISTS { $$ = 1; }
1911
;
1912

1913
scalar_data_type:
1914
    int_type_i opt_int_length_i opt_unsigned_i opt_zerofill_i
1915
    {
1916
      malloc_terminal_node($$, parse_ctx->mem_pool_, ($3 || $4) ? $1 + (T_UTINYINT - T_TINYINT) : $1);
1917
      $$->int16_values_[0] = $2;
1918
      $$->int16_values_[2] = $4;   /* 2 is the same index as float or number. */
1919
    }
1920
  | float_type_i opt_float_precision opt_unsigned_i opt_zerofill_i
1921
    {
1922
      if (T_FLOAT != $1 && NULL != $2 && -1 == $2->int16_values_[1]) {
1923
        obpl_mysql_yyerror(&@2, parse_ctx, "double type not support double(M) syntax\n");
1924
        YYERROR;
1925
      }
1926
      malloc_terminal_node($$, parse_ctx->mem_pool_, ($3 || $4) ? $1 + (T_UFLOAT - T_FLOAT) : $1);
1927
      if (NULL != $2) {
1928
        $$->int16_values_[0] = $2->int16_values_[0];
1929
        $$->int16_values_[1] = $2->int16_values_[1];
1930
      }
1931
      /* malloc_terminal_node() has set memory to 0 filled, so there is no else. */
1932
      $$->int16_values_[2] = $4;
1933
    }
1934
  | NUMBER opt_number_precision opt_unsigned_i opt_zerofill_i
1935
    {
1936
      malloc_terminal_node($$, parse_ctx->mem_pool_, ($3 || $4) ? T_UNUMBER : T_NUMBER);
1937
      if (NULL != $2) {
1938
        $$->int16_values_[0] = $2->int16_values_[0];
1939
        $$->int16_values_[1] = $2->int16_values_[1];
1940
      }
1941
      /* malloc_terminal_node() has set memory to 0 filled, so there is no else. */
1942
      $$->int16_values_[2] = $4;
1943
    }
1944
  | datetime_type_i opt_datetime_fsp_i
1945
    {
1946
      malloc_terminal_node($$, parse_ctx->mem_pool_, $1);
1947
      $$->int16_values_[1] = $2;
1948
    }
1949
  | date_year_type_i
1950
    {
1951
      malloc_terminal_node($$, parse_ctx->mem_pool_, $1);
1952
    }
1953
  | CHARACTER opt_string_length_i opt_binary opt_charset opt_collation
1954
    {
1955
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_CHAR, 3, $4, $5, $3);
1956
      if ($2 < 0) {
1957
        $2 = 1;
1958
      }
1959
      $$->int32_values_[0] = $2;
1960
      $$->int32_values_[1] = 0; /* is char */
1961
    }
1962
  | nchar_type_i opt_string_length_i opt_binary opt_collation
1963
    {
1964
      ParseNode *charset_node = NULL;
1965
      malloc_terminal_node(charset_node, parse_ctx->mem_pool_, T_CHARSET);
1966
      charset_node->str_value_ = parse_strdup("utf8mb4", parse_ctx->mem_pool_, &(charset_node->str_len_));
1967
      if (OB_UNLIKELY(NULL == charset_node->str_value_)) {
1968
        obpl_mysql_yyerror(NULL, parse_ctx, "memory space for string is not enough\n");
1969
        YYERROR;
1970
      }
1971

1972
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, $1, 3, charset_node, $4, $3);
1973
      $$->int32_values_[0] = $2;
1974
      $$->int32_values_[1] = 0; /* is char */
1975
    }
1976
  /*  | TEXT opt_binary opt_charset opt_collation
1977
  //  {
1978
  //    UNUSED($2);
1979
  //    malloc_non_terminal_node($$, result->malloc_pool_, T_VARCHAR, 3, $3, $4, $2);
1980
  //    $$->int32_values_[0] = 256;
1981
  //    $$->int32_values_[1] = 0; /* is char */
1982
  /*  }*/
1983
  | CHARACTER VARYING string_length_i opt_binary opt_charset opt_collation
1984
    {
1985
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_VARCHAR, 3, $5, $6, $4);
1986
      $$->int32_values_[0] = $3;
1987
      $$->int32_values_[1] = 0; /* is char */
1988
    }
1989
  | VARCHAR string_length_i opt_binary opt_charset opt_collation
1990
    {
1991
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_VARCHAR, 3, $4, $5, $3);
1992
      $$->int32_values_[0] = $2;
1993
      $$->int32_values_[1] = 0; /* is char */
1994
    }
1995
  | nvarchar_type_i opt_string_length_i opt_binary opt_collation
1996
    {
1997
      ParseNode *charset_node = NULL;
1998
      malloc_terminal_node(charset_node, parse_ctx->mem_pool_, T_CHARSET);
1999
      charset_node->str_value_ = parse_strdup("utf8mb4", parse_ctx->mem_pool_, &(charset_node->str_len_));
2000
      if (OB_UNLIKELY(NULL == charset_node->str_value_)) {
2001
        obpl_mysql_yyerror(NULL, parse_ctx, "memory space for string is not enough\n");
2002
        YYERROR;
2003
      }
2004

2005
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, $1, 3, charset_node, $4, $3);
2006
      $$->int32_values_[0] = $2;
2007
      $$->int32_values_[1] = 0; /* is char */
2008
    }
2009
  | BINARY opt_string_length_i
2010
    {
2011
      malloc_terminal_node($$, parse_ctx->mem_pool_, T_CHAR);
2012
      if ($2 < 0) {
2013
        $2 = 1;
2014
      }
2015
      $$->int32_values_[0] = $2;
2016
      $$->int32_values_[1] = 1; /* is binary */
2017
    }
2018
  | VARBINARY string_length_i
2019
    {
2020
      malloc_terminal_node($$, parse_ctx->mem_pool_, T_VARCHAR);
2021
      $$->int32_values_[0] = $2;
2022
      $$->int32_values_[1] = 1; /* is binary */
2023
    }
2024
  | STRING /* wrong or unsupported data type */
2025
    {
2026
      malloc_terminal_node($$, parse_ctx->mem_pool_, T_INVALID);
2027
      $$->str_value_ = $1->str_value_;
2028
      $$->str_len_ = $1->str_len_;
2029
    }
2030
  | BIT opt_bit_length_i
2031
    {
2032
      malloc_terminal_node($$, parse_ctx->mem_pool_, T_BIT);
2033
      $$->int16_values_[0] = $2;
2034
    }
2035
  | BOOL
2036
	{
2037
      malloc_terminal_node($$, parse_ctx->mem_pool_, T_TINYINT);
2038
  	  $$->int16_values_[0] = 1;
2039
      $$->int16_values_[2] = 0;  // zerofill always false
2040
    }
2041
  | BOOLEAN
2042
    {
2043
      malloc_terminal_node($$, parse_ctx->mem_pool_, T_TINYINT);
2044
      $$->int16_values_[0] = 1;
2045
      $$->int16_values_[2] = 0; // zerofill always false
2046
    }
2047
  | blob_type_i opt_string_length_i_v2
2048
    {
2049
      malloc_terminal_node($$, parse_ctx->mem_pool_, $1);
2050
      if ($1 != T_TEXT && $2 != 0) {
2051
        obpl_mysql_yyerror(&@2, parse_ctx, "not support to specify the length in parentheses\n");
2052
        YYERROR;
2053
      }
2054
      $$->int32_values_[0] = $2;
2055
      $$->int32_values_[1] = 1; /* is binary */
2056
    }
2057
  | text_type_i opt_string_length_i_v2 opt_binary opt_charset opt_collation
2058
    {
2059
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, $1, 3, $4, $5, $3);
2060
      if ($1 != T_TEXT && $2 != 0) {
2061
        obpl_mysql_yyerror(&@2, parse_ctx, "not support to specify the length in parentheses\n");
2062
        YYERROR;
2063
      }
2064
      $$->int32_values_[0] = $2;
2065
      $$->int32_values_[1] = 0; /* is text */
2066
    }
2067
  | ENUM '(' string_list ')' opt_binary opt_charset opt_collation
2068
  {
2069
    ParseNode *string_list_node = NULL;
2070
    merge_nodes(string_list_node, parse_ctx->mem_pool_, T_STRING_LIST, $3);
2071
    malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_ENUM, 4, $6, $7, $5, string_list_node);
2072
    $$->int32_values_[0] = 0;//not used so far
2073
    $$->int32_values_[1] = 0; /* is char */
2074
  }
2075
  | SET '(' string_list ')' opt_binary opt_charset opt_collation
2076
  {
2077
    ParseNode *string_list_node = NULL;
2078
    merge_nodes(string_list_node, parse_ctx->mem_pool_, T_STRING_LIST, $3);
2079
    malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SET, 4, $6, $7, $5, string_list_node);
2080
    $$->int32_values_[0] = 0;//not used so far
2081
    $$->int32_values_[1] = 0; /* is char */
2082
  }
2083
  | pl_obj_access_ref
2084
	{
2085
    if ($1 != NULL && $1->type_ == T_SP_OBJ_ACCESS_REF && 
2086
        $1->num_child_ == 2 && 
2087
        $1->children_[0] != NULL &&
2088
        $1->children_[0]->type_ == T_SP_ACCESS_NAME &&
2089
        $1->children_[0]->num_child_ == 3 &&
2090
        $1->children_[0]->children_[0] == NULL && 
2091
        $1->children_[0]->children_[1] == NULL &&
2092
        nodename_equal($1->children_[0]->children_[2], "JSON", 4)) {
2093
      malloc_terminal_node($$, parse_ctx->mem_pool_, T_JSON);
2094
      $$->int32_values_[0] = 0; 
2095
    } else {
2096
      obpl_mysql_yyerror(&@1, parse_ctx, "Syntax Error\n");
2097
      YYERROR;
2098
    }
2099
  }
2100
  | pl_obj_access_ref '%' ROWTYPE
2101
  {
2102
    if (parse_ctx->is_for_trigger_ && parse_ctx->is_inner_parse_) {
2103
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_ROWTYPE, 1, $1);
2104
    } else {
2105
      obpl_mysql_yyerror(&@3, parse_ctx, "Syntax Error\n");
2106
      YYERROR;
2107
    }
2108
  }
2109
;
2110

2111
pl_obj_access_ref:
2112
    sp_call_name
2113
    {
2114
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_OBJ_ACCESS_REF, 2, $1, NULL);
2115
    }
2116

2117
int_type_i:
2118
    TINYINT     { $$ = T_TINYINT; }
2119
  | SMALLINT    { $$ = T_SMALLINT; }
2120
  | MEDIUMINT   { $$ = T_MEDIUMINT; }
2121
  | INTEGER     { $$ = T_INT32; }
2122
  | BIGINT      { $$ = T_INT; }
2123
;
2124

2125
float_type_i:
2126
    FLOAT              { $$ = T_FLOAT; }
2127
  | DOUBLE             { $$ = T_DOUBLE; }
2128
  | DOUBLE PRECISION   { $$ = T_DOUBLE; }
2129
;
2130

2131
datetime_type_i:
2132
    DATETIME    { $$ = T_DATETIME; }
2133
  | TIMESTAMP   { $$ = T_TIMESTAMP; }
2134
  | TIME        { $$ = T_TIME; }
2135
;
2136

2137
date_year_type_i:
2138
    DATE        { $$ = T_DATE; }
2139
  | YEAR opt_year_i { $$ = T_YEAR; }
2140
;
2141

2142
nchar_type_i:
2143
    NCHAR               { $$ = T_CHAR; }
2144
  | NATIONAL CHARACTER  { $$ = T_CHAR; }
2145
;
2146

2147
nvarchar_type_i:
2148
    NVARCHAR                    { $$ = T_VARCHAR; }
2149
  | NCHAR VARCHAR               { $$ = T_VARCHAR; }
2150
  | NATIONAL VARCHAR            { $$ = T_VARCHAR; }
2151
  | NATIONAL CHARACTER VARYING  { $$ = T_VARCHAR; }
2152
;
2153

2154
opt_int_length_i:
2155
    '(' INTNUM ')'  { $$ = $2->value_; }
2156
  | /*EMPTY*/       { $$ = -1; }
2157
;
2158

2159
opt_bit_length_i:
2160
    '(' INTNUM ')'  { $$ = $2->value_; }
2161
  | /*EMPTY*/       { $$ = 1; }
2162
;
2163

2164
opt_float_precision:
2165
    '(' INTNUM ',' INTNUM ')'
2166
    {
2167
      malloc_terminal_node($$, parse_ctx->mem_pool_, T_LINK_NODE);
2168
      $$->int16_values_[0] = $2->value_;
2169
      $$->int16_values_[1] = $4->value_;
2170
    }
2171
  | '(' INTNUM ')'
2172
    {
2173
      malloc_terminal_node($$, parse_ctx->mem_pool_, T_LINK_NODE);
2174
      $$->int16_values_[0] = $2->value_;
2175
      $$->int16_values_[1] = -1;
2176
    }
2177
  | '(' DECIMAL_VAL ')'
2178
  {
2179
    malloc_terminal_node($$, parse_ctx->mem_pool_, T_LINK_NODE);
2180
    int err_no = 0;
2181
    $2->value_ = ob_strntoll($2->str_value_, $2->str_len_, 10, NULL, &err_no);
2182
    $$->int16_values_[0] = $2->value_;
2183
    $$->int16_values_[1] = -1;
2184
  }
2185
  | /*EMPTY*/ { $$ = NULL; }
2186
;
2187

2188
opt_number_precision:
2189
    '(' INTNUM ',' INTNUM ')'
2190
    {
2191
      malloc_terminal_node($$, parse_ctx->mem_pool_, T_LINK_NODE);
2192
      if($2->value_ > OB_MAX_PARSER_INT16_VALUE) {
2193
        $$->int16_values_[0] = OB_MAX_PARSER_INT16_VALUE;
2194
      } else {
2195
        $$->int16_values_[0] = $2->value_;
2196
      }
2197
      if($4->value_ > OB_MAX_PARSER_INT16_VALUE) {
2198
        $$->int16_values_[1] = OB_MAX_PARSER_INT16_VALUE;
2199
      } else {
2200
        $$->int16_values_[1] = $4->value_;
2201
      }
2202
      $$->param_num_ = 2;
2203
    }
2204
  | '(' INTNUM ')'
2205
    {
2206
      malloc_terminal_node($$, parse_ctx->mem_pool_, T_LINK_NODE);
2207
      if($2->value_ > OB_MAX_PARSER_INT16_VALUE) {
2208
        $$->int16_values_[0] = OB_MAX_PARSER_INT16_VALUE;
2209
      } else {
2210
        $$->int16_values_[0] = $2->value_;
2211
      }
2212
      $$->int16_values_[1] = 0;
2213
      $$->param_num_ = 1;
2214
    }
2215
  | /*EMPTY*/
2216
    {
2217
      malloc_terminal_node($$, parse_ctx->mem_pool_, T_LINK_NODE);
2218
      $$->int16_values_[0] = 10;
2219
      $$->int16_values_[1] = 0;
2220
      $$->param_num_ = 0;
2221
    }
2222
;
2223

2224
opt_year_i:
2225
    '(' INTNUM  ')' { $$ = $2->value_; }
2226
  | /*EMPTY*/ { $$ = 0; }
2227
;
2228

2229
opt_datetime_fsp_i:
2230
    '(' INTNUM ')'
2231
    {
2232
      $$ = $2->value_;
2233
    }
2234
  | /*EMPTY*/
2235
    {
2236
      $$ = 0;
2237
    }
2238
;
2239

2240
number_literal:
2241
    INTNUM
2242
    {
2243
      $$ = $1;
2244
      $$->param_num_ = 1;
2245
    }
2246
  | DECIMAL_VAL
2247
    {
2248
      $$ = $1;
2249
      $$->param_num_ = 1;
2250
    }
2251
;
2252

2253
literal:
2254
    number_literal { $$ = $1; }
2255
  | DATE_VALUE { $$ = $1; }
2256
  | HEX_STRING_VALUE { $$ = $1; }
2257
  | NULLX { $$ = $1; }
2258
;
2259

2260
text_type_i:
2261
TINYTEXT     { $$ = T_TINYTEXT; }
2262
| TEXT       { $$ = T_TEXT; }
2263
| MEDIUMTEXT { $$ = T_MEDIUMTEXT; }
2264
| LONGTEXT   { $$ = T_LONGTEXT;  }
2265
| LONG VARCHAR { $$ = T_MEDIUMTEXT; }
2266
| LONG { $$ = T_MEDIUMTEXT; }
2267
;
2268

2269
blob_type_i:
2270
TINYBLOB     { $$ = T_TINYTEXT; }
2271
| BLOB       { $$ = T_TEXT; }
2272
| MEDIUMBLOB { $$ = T_MEDIUMTEXT; }
2273
| LONGBLOB   { $$ = T_LONGTEXT;  }
2274
| LONG VARBINARY {$$ = T_MEDIUMTEXT; }
2275
;
2276

2277
opt_string_length_i_v2:
2278
string_length_i { $$ = $1; }
2279
| /*EMPTY*/     { $$ = 0; }
2280

2281
string_length_i:
2282
'(' number_literal ')'
2283
{
2284
  // 在 `*` 处报语法错误
2285
  // select cast('' as BINARY(-1));
2286
  //                          *
2287
  // select cast('' as CHARACTER(-1));
2288
  //                             *
2289
  int64_t val = 0;
2290
  if (T_NUMBER == $2->type_) {
2291
    errno = 0;
2292
    val = strtoll($2->str_value_, NULL, 10);
2293
    if (ERANGE == errno) {
2294
      $$ = OUT_OF_STR_LEN;// out of str_max_len
2295
    } else if (val < 0) {
2296
      obpl_mysql_yyerror(&@2, parse_ctx, "length cannot < 0\n");
2297
      YYERROR;
2298
    } else if (val > UINT32_MAX) {
2299
      $$ = OUT_OF_STR_LEN;// out of str_max_len
2300
    } else if (val > INT32_MAX) {
2301
      $$ = DEFAULT_STR_LENGTH;
2302
    } else {
2303
      $$ = val;
2304
    }
2305
  } else if ($2->value_ < 0) {
2306
    obpl_mysql_yyerror(&@2, parse_ctx, "length cannot < 0\n");
2307
    YYERROR;
2308
  } else if ($2->value_ > UINT32_MAX) {
2309
    $$ = OUT_OF_STR_LEN;;
2310
  } else if ($2->value_ > INT32_MAX) {
2311
    $$ = DEFAULT_STR_LENGTH;
2312
  } else {
2313
    $$ = $2->value_;
2314
  }
2315
  // $$ = $2->param_num_;
2316
}
2317
;
2318

2319
string_list:
2320
  text_string
2321
  {
2322
   $$ = $1;
2323
  }
2324
  | string_list ',' text_string
2325
  {
2326
    malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_LINK_NODE, 2, $1, $3);
2327
  }
2328
;
2329

2330
text_string:
2331
  STRING
2332
  {
2333
    $$ = $1;
2334
  }
2335
  | HEX_STRING_VALUE
2336
  {
2337
    $$ = $1;
2338
  }
2339
;
2340

2341
opt_string_length_i:
2342
    string_length_i
2343
    {
2344
      $$ = $1;
2345
    }
2346
  | /*EMPTY*/
2347
    {
2348
      $$ = 1;
2349
    }
2350
;
2351

2352
opt_unsigned_i:
2353
    UNSIGNED    { $$ = 1; }
2354
  | SIGNED      { $$ = 0; }
2355
  | /*EMPTY*/   { $$ = 0; }
2356
;
2357

2358
opt_zerofill_i:
2359
    ZEROFILL    { $$ = 1; }
2360
  | /*EMPTY*/   { $$ = 0; }
2361
;
2362

2363
opt_binary:
2364
    BINARY
2365
    {
2366
      malloc_terminal_node($$, parse_ctx->mem_pool_, T_BINARY);
2367
      $$->value_ = 1;
2368
    }
2369
  | /*EMPTY*/ {$$ = 0; }
2370
;
2371

2372
collation_name:
2373
    ident
2374
    {
2375
      $$ = $1;
2376
      $$->type_ = T_VARCHAR;
2377
      $$->param_num_ = 0;
2378
    }
2379
  | STRING
2380
    {
2381
      $$ = $1;
2382
      $$->param_num_ = 1;
2383
    }
2384
;
2385

2386
charset_name:
2387
    ident
2388
    {
2389
      $$ = $1;
2390
      $$->type_ = T_VARCHAR;
2391
      $$->param_num_ = 0;
2392
      $$->is_hidden_const_ = 1;
2393
    }
2394
  | STRING
2395
    {
2396
      $$ = $1;
2397
      $$->param_num_ = 1;
2398
      $$->is_hidden_const_ = 0;
2399
    }
2400
  | BINARY
2401
    {
2402
      malloc_terminal_node($$, parse_ctx->mem_pool_, T_VARCHAR);
2403
      $$->str_value_ = parse_strdup("binary", parse_ctx->mem_pool_, &($$->str_len_));
2404
      if (OB_UNLIKELY(NULL == $$->str_value_)) {
2405
        YY_FATAL_ERROR("no more memory to malloc 'binary; string\n");
2406
      }
2407
      $$->param_num_ = 0;
2408
      $$->is_hidden_const_ = 1;
2409
    }
2410
;
2411

2412
opt_charset:
2413
    charset_key charset_name
2414
    {
2415
      (void)($1);
2416
      malloc_terminal_node($$, parse_ctx->mem_pool_, T_CHARSET);
2417
      $$->str_value_ = $2->str_value_;
2418
      $$->str_len_ = $2->str_len_;
2419
    }
2420
  | /*EMPTY*/ { $$ = NULL; }
2421
;
2422

2423
charset_key:
2424
    CHARSET
2425
    {
2426
      $$ = NULL;
2427
    }
2428
  | CHARACTER SET
2429
    {
2430
      $$ = NULL;
2431
    }
2432
;
2433

2434
collation:
2435
    COLLATE collation_name
2436
    {
2437
      malloc_terminal_node($$, parse_ctx->mem_pool_, T_COLLATION);
2438
      $$->str_value_ = $2->str_value_;
2439
      $$->str_len_ = $2->str_len_;
2440
      $$->param_num_ = $2->param_num_;
2441
    }
2442
;
2443

2444
opt_collation:
2445
    collation
2446
    {
2447
      $$ = $1;
2448
    }
2449
  | /*EMPTY*/ { $$ = NULL; }
2450
;
2451

2452
signal_stmt:
2453
    SIGNAL signal_value opt_set_signal_information
2454
    {
2455
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_SIGNAL, 2, $2, $3);
2456
    }
2457
;
2458

2459
resignal_stmt:
2460
    RESIGNAL opt_signal_value opt_set_signal_information
2461
    {
2462
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_RESIGNAL, 2, $2, $3);
2463
    }
2464
;
2465

2466
opt_signal_value:
2467
    /*Empty*/ { $$ = NULL; }
2468
  | signal_value { $$ = $1; }
2469
;
2470

2471
signal_value:
2472
    ident { $$ = $1; }
2473
  | sqlstate { $$ = $1; }
2474
;
2475

2476
opt_set_signal_information:
2477
    /*Empty*/ { $$ = NULL; }
2478
  | SET signal_information_item_list
2479
    {
2480
      merge_nodes($$, parse_ctx->mem_pool_, T_SP_SIGNAL_INFO_LIST, $2);
2481
    }
2482
;
2483

2484
signal_information_item_list:
2485
    signal_information_item { $$ = $1; }
2486
  | signal_information_item_list ',' signal_information_item
2487
    {
2488
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_LINK_NODE, 2, $1, $3);
2489
    }
2490
;
2491

2492
signal_information_item:
2493
    scond_info_item_name '=' signal_allowed_expr
2494
    {
2495
      malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_SIGNAL_INFO_ITEM, 1, $3);
2496
      $$->value_ = $1;
2497
    }
2498
;
2499

2500
signal_allowed_expr:
2501
    literal { $$ = $1; }
2502
  | variable { $$ = $1; }
2503
  | simple_ident { $$ = $1; }
2504
  | STRING { $$ = $1; }
2505
;
2506

2507
variable:
2508
    SYSTEM_VARIABLE { $$ = $1; }
2509
  | USER_VARIABLE { $$ = $1; }
2510
;
2511

2512
scond_info_item_name:
2513
    CLASS_ORIGIN { $$ = DIAG_CLASS_ORIGIN; }
2514
  | SUBCLASS_ORIGIN { $$ = DIAG_SUBCLASS_ORIGIN; }
2515
  | CONSTRAINT_CATALOG { $$ = DIAG_CONSTRAINT_CATALOG; }
2516
  | CONSTRAINT_SCHEMA { $$ = DIAG_CONSTRAINT_SCHEMA; }
2517
  | CONSTRAINT_NAME { $$ = DIAG_CONSTRAINT_NAME; }
2518
  | CATALOG_NAME { $$ = DIAG_CATALOG_NAME; }
2519
  | SCHEMA_NAME { $$ = DIAG_SCHEMA_NAME; }
2520
  | TABLE_NAME { $$ = DIAG_TABLE_NAME; }
2521
  | COLUMN_NAME { $$ = DIAG_COLUMN_NAME; }
2522
  | CURSOR_NAME { $$ = DIAG_CURSOR_NAME; }
2523
  | MESSAGE_TEXT { $$ = DIAG_MESSAGE_TEXT; }
2524
  | MYSQL_ERRNO { $$ = DIAG_MYSQL_ERRNO; }
2525
;
2526

2527
%%
2528
/**
2529
 * parser function
2530
 * @param [out] pl_yychar, set the pl parser look-ahead token
2531
 */
2532
ParseNode *obpl_mysql_read_sql_construct(ObParseCtx *parse_ctx, const char *prefix, YYLookaheadToken *la_token, int end_token_cnt, ...)
2533
{
2534
  int errcode = OB_PARSER_SUCCESS;
2535
  va_list va;
2536
  bool is_break = false;
2537
  int sql_str_len = -1;
2538
  int parenlevel = (*(la_token->la_yychar) == '(' || *(la_token->la_yychar) == '[') ? 1 : 0;
2539
  const char *sql_str = NULL;
2540
  ParseResult parse_result;
2541
  ParseNode *sql_node = NULL;
2542
  if (*(la_token->la_yychar) != -2) { //#define YYEMPTY    (-2)
2543
    parse_ctx->scanner_ctx_.sql_end_loc = la_token->la_yylloc->last_column;
2544
    if (parse_ctx->scanner_ctx_.sql_start_loc < 0) {
2545
      parse_ctx->scanner_ctx_.sql_start_loc = la_token->la_yylloc->first_column;
2546
    }
2547
  }
2548
  while (!is_break) {
2549
    *(la_token->la_yychar) = obpl_mysql_yylex(la_token->la_yylval, la_token->la_yylloc, parse_ctx->scanner_ctx_.yyscan_info_);
2550
    if (parse_ctx->scanner_ctx_.sql_start_loc < 0) {
2551
      //get sql rule start location
2552
      parse_ctx->scanner_ctx_.sql_start_loc = la_token->la_yylloc->first_column;
2553
    }
2554
    va_start(va, end_token_cnt);
2555
    int i = 0;
2556
    for (; !is_break && i < end_token_cnt; ++i) {
2557
      int end_token = va_arg(va, int);
2558
      if (end_token == *(la_token->la_yychar) && parenlevel <= 0) { //正常应该用==0,但是可能外面已经读出了左括号,所以这里用<=
2559
        is_break = true;
2560
        if (END_P == end_token) {
2561
          parse_ctx->scanner_ctx_.sql_end_loc = la_token->la_yylloc->last_column;
2562
        } else {
2563
          parse_ctx->scanner_ctx_.sql_end_loc = la_token->la_yylloc->first_column - 1;
2564
        }
2565
      }
2566
    }
2567
    va_end(va);
2568
    if (*(la_token->la_yychar) == '(' || *(la_token->la_yychar) == '[') {
2569
      ++parenlevel;
2570
    } else if (*(la_token->la_yychar) == ')' || *(la_token->la_yychar) == ']') {
2571
      --parenlevel;
2572
    }
2573
    if (END_P == *(la_token->la_yychar)) {
2574
      is_break = true;
2575
      parse_ctx->scanner_ctx_.sql_end_loc = la_token->la_yylloc->last_column;
2576
    }
2577
    if (!is_break) {
2578
      //get sql rule end location
2579
      parse_ctx->scanner_ctx_.sql_end_loc = la_token->la_yylloc->last_column;
2580
    }
2581
  }
2582
  if (OB_PARSER_SUCCESS == errcode) {
2583
    parse_ctx->scanner_ctx_.sql_end_loc = parse_ctx->stmt_len_ <= parse_ctx->scanner_ctx_.sql_end_loc ?
2584
                                            parse_ctx->stmt_len_ - 1 : parse_ctx->scanner_ctx_.sql_end_loc;
2585
    sql_str_len = parse_ctx->scanner_ctx_.sql_end_loc - parse_ctx->scanner_ctx_.sql_start_loc + 1;
2586
  }
2587
  if (OB_PARSER_SUCCESS == errcode && sql_str_len > 0) {
2588
    sql_str = strndup_with_prefix(prefix, parse_ctx->stmt_str_ + parse_ctx->scanner_ctx_.sql_start_loc,
2589
                                  sql_str_len, parse_ctx->mem_pool_);
2590
    if (NULL == sql_str) {
2591
      YY_FATAL_ERROR("no memory to strdup sql string\n");
2592
    }
2593
    //parse sql_str...
2594
    memset(&parse_result, 0, sizeof(ParseResult));
2595
    parse_result.input_sql_ = sql_str;
2596
    parse_result.input_sql_len_ = sql_str_len + strlen(prefix);
2597
    parse_result.malloc_pool_ = parse_ctx->mem_pool_;
2598
    parse_result.pl_parse_info_.is_pl_parse_ = true;
2599
    parse_result.pl_parse_info_.is_pl_parse_expr_ = false;
2600
    parse_result.is_for_trigger_ = (1 == parse_ctx->is_for_trigger_);
2601
    //将pl_parser的question_mark_size赋值给sql_parser,使得parser sql的question mark能够接着pl_parser的index
2602
    parse_result.question_mark_ctx_ = parse_ctx->question_mark_ctx_;
2603
    parse_result.charset_info_ = parse_ctx->charset_info_;
2604
    parse_result.charset_info_oracle_db_ = parse_ctx->charset_info_oracle_db_;
2605
    parse_result.is_not_utf8_connection_ = parse_ctx->is_not_utf8_connection_;
2606
    parse_result.connection_collation_ = parse_ctx->connection_collation_;
2607
    parse_result.sql_mode_ = parse_ctx->scanner_ctx_.sql_mode_;
2608
  }
2609
  if (sql_str_len <= 0) {
2610
    //do nothing
2611
  } else if (0 != parse_sql_stmt(&parse_result)) {
2612
    if (parse_result.extra_errno_ != OB_PARSER_SUCCESS) {
2613
      obpl_mysql_parse_fatal_error(parse_result.extra_errno_, YYLEX_PARAM, parse_result.error_msg_);
2614
    } else {
2615
      YYLTYPE sql_yylloc;
2616
      memset(&sql_yylloc, 0, sizeof(YYLTYPE));
2617
      sql_yylloc.first_column = parse_ctx->scanner_ctx_.sql_start_loc;
2618
      sql_yylloc.last_column = parse_ctx->scanner_ctx_.sql_end_loc;
2619
      sql_yylloc.first_line = la_token->la_yylloc->first_line;
2620
      sql_yylloc.last_line = la_token->la_yylloc->last_line;
2621
      obpl_mysql_yyerror(&sql_yylloc, parse_ctx, "Syntax Error\n");
2622
    }
2623
  } else {
2624
    sql_node = parse_result.result_tree_->children_[0];
2625
    //通过sql_parser的question_mark_size来更新pl_parser
2626
    parse_ctx->question_mark_ctx_ = parse_result.question_mark_ctx_;
2627
  }
2628
  return sql_node;
2629
}
2630

2631
void obpl_mysql_yyerror(YYLTYPE *yylloc, ObParseCtx *parse_ctx, char *s, ...)
2632
{
2633
  if (OB_LIKELY(NULL != parse_ctx)) {
2634
    va_list ap;
2635
    va_start(ap, s);
2636
    vsnprintf(parse_ctx->global_errmsg_, MAX_ERROR_MSG, s, ap);
2637
    // vfprintf(stderr, s, ap);
2638
    if (OB_LIKELY(NULL != yylloc)) {
2639
      ObParseErrorInfo *error_info = (ObParseErrorInfo*)parse_malloc(sizeof(ObParseErrorInfo), parse_ctx->mem_pool_);
2640
      if (NULL == error_info) {
2641
        YY_FATAL_ERROR("No memory for malloc parse error info\n");
2642
      } else {
2643
        memset(error_info, 0, sizeof(ObParseErrorInfo));
2644
        error_info->stmt_loc_.first_column_ = yylloc->first_column;
2645
        error_info->stmt_loc_.last_column_ = yylloc->last_column;
2646
        error_info->stmt_loc_.first_line_ = yylloc->first_line;
2647
        error_info->stmt_loc_.last_line_ = yylloc->last_line;
2648
        parse_ctx->cur_error_info_ = error_info;
2649
      }
2650
    }
2651
    va_end(ap);
2652
  }
2653
}
2654

2655

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.