init push
This commit is contained in:
		
							
								
								
									
										98
									
								
								src/sql/parser/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								src/sql/parser/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,98 @@
 | 
			
		||||
 | 
			
		||||
# charset objects used for proxy_parser
 | 
			
		||||
set(ob_sql_parser_charset_object_list
 | 
			
		||||
  ob_ctype_bin.c
 | 
			
		||||
  ob_ctype_mb.c
 | 
			
		||||
  ob_ctype_simple.c
 | 
			
		||||
  ob_ctype_utf8.c
 | 
			
		||||
  ob_ctype.c
 | 
			
		||||
  ob_dtoa.c
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
list(TRANSFORM ob_sql_parser_charset_object_list
 | 
			
		||||
  PREPEND ${PROJECT_SOURCE_DIR}/deps/oblib/src/lib/charset/)
 | 
			
		||||
 | 
			
		||||
# hash objects used for proxy parser
 | 
			
		||||
set(ob_sql_parser_hash_object_list
 | 
			
		||||
  murmur_hash.cpp
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
list(TRANSFORM ob_sql_parser_hash_object_list
 | 
			
		||||
  PREPEND ${PROJECT_SOURCE_DIR}/deps/oblib/src/lib/hash_func/)
 | 
			
		||||
 | 
			
		||||
add_library(ob_sql_parser_base INTERFACE)
 | 
			
		||||
target_include_directories(ob_sql_parser_base INTERFACE
 | 
			
		||||
  ${PROJECT_SOURCE_DIR}/deps/oblib/src/common/sql_mode/)
 | 
			
		||||
 | 
			
		||||
# parser objects for proxy parser
 | 
			
		||||
set(ob_inner_sql_parser_object_list
 | 
			
		||||
  non_reserved_keywords_mysql_mode.c
 | 
			
		||||
  ob_non_reserved_keywords.c
 | 
			
		||||
  ob_sql_parser.cpp
 | 
			
		||||
  parse_malloc.cpp
 | 
			
		||||
  parse_node.c
 | 
			
		||||
  parse_node_hash.cpp
 | 
			
		||||
  sql_parser_base.c
 | 
			
		||||
  sql_parser_mysql_mode_lex.c
 | 
			
		||||
  sql_parser_mysql_mode_tab.c
 | 
			
		||||
  parser_utility.cpp
 | 
			
		||||
  type_name.c
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
# parser objects for server parser
 | 
			
		||||
set(ob_extra_sql_parser_object_list
 | 
			
		||||
  ob_parser.cpp
 | 
			
		||||
  parser_proxy_func.cpp
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
ob_set_subtarget(inner_sql_parser
 | 
			
		||||
  ${ob_inner_sql_parser_object_list}
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
ob_set_subtarget(sql_parser_charset
 | 
			
		||||
  ${ob_sql_parser_charset_object_list}
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
ob_set_subtarget(sql_parser_hash
 | 
			
		||||
  ${ob_sql_parser_hash_object_list}
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
ob_set_subtarget(extra_sql_parser
 | 
			
		||||
  ${ob_extra_sql_parser_object_list}
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
# ob_sql_proxy_parser_objects is the static library for proxy, it does not link against observer
 | 
			
		||||
add_library(ob_sql_proxy_parser_objects OBJECT
 | 
			
		||||
  ${ob_inner_sql_parser_object_list}
 | 
			
		||||
  ${ob_sql_parser_charset_object_list}
 | 
			
		||||
  ${ob_sql_parser_hash_object_list}
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
# ob_sql_server_parser_object is the static library for observer
 | 
			
		||||
add_library(ob_sql_server_parser_objects OBJECT
 | 
			
		||||
  ${ob_inner_sql_parser_object_list}
 | 
			
		||||
  ${ob_extra_sql_parser_object_list})
 | 
			
		||||
 | 
			
		||||
target_link_libraries(ob_sql_proxy_parser_objects PUBLIC ob_base ob_sql_parser_base)
 | 
			
		||||
target_link_libraries(ob_sql_server_parser_objects PUBLIC ob_base)
 | 
			
		||||
 | 
			
		||||
target_compile_definitions(ob_sql_proxy_parser_objects PUBLIC SQL_PARSER_COMPILATION)
 | 
			
		||||
 | 
			
		||||
disable_pch(ob_sql_server_parser_objects)
 | 
			
		||||
disable_pch(ob_sql_proxy_parser_objects)
 | 
			
		||||
 | 
			
		||||
add_library(ob_sql_proxy_parser_static
 | 
			
		||||
  STATIC
 | 
			
		||||
  EXCLUDE_FROM_ALL)
 | 
			
		||||
 | 
			
		||||
add_library(ob_sql_server_parser_static
 | 
			
		||||
  STATIC
 | 
			
		||||
  EXCLUDE_FROM_ALL)
 | 
			
		||||
 | 
			
		||||
target_link_libraries(ob_sql_proxy_parser_static
 | 
			
		||||
  PUBLIC
 | 
			
		||||
  ob_sql_proxy_parser_objects)
 | 
			
		||||
 | 
			
		||||
target_link_libraries(ob_sql_server_parser_static
 | 
			
		||||
  PUBLIC
 | 
			
		||||
  ob_sql_server_parser_objects)
 | 
			
		||||
							
								
								
									
										32
									
								
								src/sql/parser/gen_parser.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										32
									
								
								src/sql/parser/gen_parser.sh
									
									
									
									
									
										Executable file
									
								
							@ -0,0 +1,32 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
#
 | 
			
		||||
# AUTHOR: Zhifeng YANG
 | 
			
		||||
# DATE: 2012-10-24
 | 
			
		||||
# DESCRIPTION:
 | 
			
		||||
#
 | 
			
		||||
set +x
 | 
			
		||||
CURDIR="$(dirname $(readlink -f "$0"))"
 | 
			
		||||
export PATH=$CURDIR/../../../deps/3rd/usr/local/oceanbase/devtools/bin:$PATH
 | 
			
		||||
export BISON_PKGDATADIR=$CURDIR/../../../deps/3rd/usr/local/oceanbase/devtools/share/bison
 | 
			
		||||
BISON_VERSION=`bison -V| grep 'bison (GNU Bison)'|awk '{ print  $4;}'`
 | 
			
		||||
NEED_VERSION='2.4.1'
 | 
			
		||||
 | 
			
		||||
if [ "$BISON_VERSION" != "$NEED_VERSION" ]; then
 | 
			
		||||
  echo "bison version not match, please use bison-$NEED_VERSION"
 | 
			
		||||
  exit 1
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# generate sql_parser
 | 
			
		||||
bison -v -Werror -d ../../../src/sql/parser/sql_parser_mysql_mode.y -o ../../../src/sql/parser/sql_parser_mysql_mode_tab.c
 | 
			
		||||
if [ $? -ne 0 ]
 | 
			
		||||
then
 | 
			
		||||
    echo Compile error[$?], abort.
 | 
			
		||||
    exit 1
 | 
			
		||||
fi
 | 
			
		||||
flex -Cfa -B -8 -o ../../../src/sql/parser/sql_parser_mysql_mode_lex.c ../../../src/sql/parser/sql_parser_mysql_mode.l ../../../src/sql/parser/sql_parser_mysql_mode_tab.h
 | 
			
		||||
./gen_type_name.sh ./ob_item_type.h > type_name.c
 | 
			
		||||
 | 
			
		||||
sed "/Setup the input buffer state to scan the given bytes/,/}/{/int i/d}" -i sql_parser_mysql_mode_lex.c
 | 
			
		||||
sed "/Setup the input buffer state to scan the given bytes/,/}/{/for ( i = 0; i < _yybytes_len; ++i )/d}" -i sql_parser_mysql_mode_lex.c
 | 
			
		||||
sed "/Setup the input buffer state to scan the given bytes/,/}/{s/\tbuf\[i\] = yybytes\[i\]/memcpy(buf, yybytes, _yybytes_len)/g}" -i sql_parser_mysql_mode_lex.c
 | 
			
		||||
							
								
								
									
										17
									
								
								src/sql/parser/gen_type_name.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										17
									
								
								src/sql/parser/gen_type_name.sh
									
									
									
									
									
										Executable file
									
								
							@ -0,0 +1,17 @@
 | 
			
		||||
#!/bin/sh
 | 
			
		||||
echo '/**
 | 
			
		||||
 * Copyright (c) 2021 OceanBase
 | 
			
		||||
 * OceanBase CE is licensed under Mulan PubL v2.
 | 
			
		||||
 * You can use this software according to the terms and conditions of the Mulan PubL v2.
 | 
			
		||||
 * You may obtain a copy of Mulan PubL v2 at:
 | 
			
		||||
 *          http://license.coscl.org.cn/MulanPubL-2.0
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 | 
			
		||||
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 | 
			
		||||
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 | 
			
		||||
 * See the Mulan PubL v2 for more details.
 | 
			
		||||
 */'
 | 
			
		||||
echo -e '#include "sql/parser/ob_item_type.h"'
 | 
			
		||||
echo -e "const char* get_type_name(int type)\n{"
 | 
			
		||||
echo -e "\tswitch(type){"
 | 
			
		||||
sed -rn 's/\s*(T_[_A-Z1-9]+)[ =0-9]*,/\tcase \1 : return \"\1\";/p' $1
 | 
			
		||||
echo -e '\tdefault:return "Unknown";\n\t}\n}'
 | 
			
		||||
							
								
								
									
										813
									
								
								src/sql/parser/non_reserved_keywords_mysql_mode.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										813
									
								
								src/sql/parser/non_reserved_keywords_mysql_mode.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,813 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Copyright (c) 2021 OceanBase
 | 
			
		||||
 * OceanBase CE is licensed under Mulan PubL v2.
 | 
			
		||||
 * You can use this software according to the terms and conditions of the Mulan PubL v2.
 | 
			
		||||
 * You may obtain a copy of Mulan PubL v2 at:
 | 
			
		||||
 *          http://license.coscl.org.cn/MulanPubL-2.0
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 | 
			
		||||
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 | 
			
		||||
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 | 
			
		||||
 * See the Mulan PubL v2 for more details.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include "lib/alloc/alloc_assist.h"
 | 
			
		||||
#include "ob_non_reserved_keywords.h"
 | 
			
		||||
#include "sql/parser/sql_parser_mysql_mode_tab.h"
 | 
			
		||||
 | 
			
		||||
static t_node* mysql_none_reserved_keywords_root = NULL;
 | 
			
		||||
static t_node* mysql_sql_keywords_in_pl_root = NULL;
 | 
			
		||||
 | 
			
		||||
/* List of non-reserved keywords */
 | 
			
		||||
static const NonReservedKeyword Mysql_none_reserved_keywords[] = {{"access", ACCESS},
 | 
			
		||||
    {"account", ACCOUNT},
 | 
			
		||||
    {"action", ACTION},
 | 
			
		||||
    {"activate", ACTIVATE},
 | 
			
		||||
    {"active", ACTIVE},
 | 
			
		||||
    {"adddate", ADDDATE},
 | 
			
		||||
    {"after", AFTER},
 | 
			
		||||
    {"against", AGAINST},
 | 
			
		||||
    {"aggregate", AGGREGATE},
 | 
			
		||||
    {"algorithm", ALGORITHM},
 | 
			
		||||
    {"always", ALWAYS},
 | 
			
		||||
    {"analyse", ANALYSE},
 | 
			
		||||
    {"any", ANY},
 | 
			
		||||
    {"approx_count_distinct", APPROX_COUNT_DISTINCT},
 | 
			
		||||
    {"approx_count_distinct_synopsis", APPROX_COUNT_DISTINCT_SYNOPSIS},
 | 
			
		||||
    {"approx_count_distinct_synopsis_merge", APPROX_COUNT_DISTINCT_SYNOPSIS_MERGE},
 | 
			
		||||
    {"archivelog", ARCHIVELOG},
 | 
			
		||||
    {"ascii", ASCII},
 | 
			
		||||
    {"at", AT},
 | 
			
		||||
    {"authors", AUTHORS},
 | 
			
		||||
    {"auto", AUTO},
 | 
			
		||||
    {"auto_increment", AUTO_INCREMENT},
 | 
			
		||||
    {"autoextend_size", AUTOEXTEND_SIZE},
 | 
			
		||||
    {"availability", AVAILABILITY},
 | 
			
		||||
    {"avg", AVG},
 | 
			
		||||
    {"avg_row_length", AVG_ROW_LENGTH},
 | 
			
		||||
    {"backup", BACKUP},
 | 
			
		||||
    {"backupset", BACKUPSET},
 | 
			
		||||
    {"balance", BALANCE},
 | 
			
		||||
    {"base", BASE},
 | 
			
		||||
    {"baseline", BASELINE},
 | 
			
		||||
    {"baseline_id", BASELINE_ID},
 | 
			
		||||
    {"basic", BASIC},
 | 
			
		||||
    {"begin", BEGI},
 | 
			
		||||
    {"binlog", BINLOG},
 | 
			
		||||
    {"bit", BIT},
 | 
			
		||||
    {"block", BLOCK},
 | 
			
		||||
    {"block_size", BLOCK_SIZE},
 | 
			
		||||
    {"bool", BOOL},
 | 
			
		||||
    {"boolean", BOOLEAN},
 | 
			
		||||
    {"bootstrap", BOOTSTRAP},
 | 
			
		||||
    {"breadth", BREADTH},
 | 
			
		||||
    {"btree", BTREE},
 | 
			
		||||
    {"byte", BYTE},
 | 
			
		||||
    {"buckets", BUCKETS},
 | 
			
		||||
    {"cache", CACHE},
 | 
			
		||||
    {"cancel", CANCEL},
 | 
			
		||||
    {"cascaded", CASCADED},
 | 
			
		||||
    {"cast", CAST},
 | 
			
		||||
    {"catalog_name", CATALOG_NAME},
 | 
			
		||||
    {"chain", CHAIN},
 | 
			
		||||
    {"changed", CHANGED},
 | 
			
		||||
    {"charset", CHARSET},
 | 
			
		||||
    {"checksum", CHECKSUM},
 | 
			
		||||
    {"checkpoint", CHECKPOINT},
 | 
			
		||||
    {"chunk", CHUNK},
 | 
			
		||||
    {"cipher", CIPHER},
 | 
			
		||||
    {"class_origin", CLASS_ORIGIN},
 | 
			
		||||
    {"clean", CLEAN},
 | 
			
		||||
    {"clear", CLEAR},
 | 
			
		||||
    {"client", CLIENT},
 | 
			
		||||
    {"close", CLOSE},
 | 
			
		||||
    {"cluster", CLUSTER},
 | 
			
		||||
    {"cluster_id", CLUSTER_ID},
 | 
			
		||||
    {"coalesce", COALESCE},
 | 
			
		||||
    {"code", CODE},
 | 
			
		||||
    {"collation", COLLATION},
 | 
			
		||||
    {"column_format", COLUMN_FORMAT},
 | 
			
		||||
    {"column_name", COLUMN_NAME},
 | 
			
		||||
    {"columns", COLUMNS},
 | 
			
		||||
    {"comment", COMMENT},
 | 
			
		||||
    {"commit", COMMIT},
 | 
			
		||||
    {"committed", COMMITTED},
 | 
			
		||||
    {"compact", COMPACT},
 | 
			
		||||
    {"completion", COMPLETION},
 | 
			
		||||
    {"compressed", COMPRESSED},
 | 
			
		||||
    {"compression", COMPRESSION},
 | 
			
		||||
    {"concurrent", CONCURRENT},
 | 
			
		||||
    {"connection", CONNECTION},
 | 
			
		||||
    {"consistent", CONSISTENT},
 | 
			
		||||
    {"constraint_catalog", CONSTRAINT_CATALOG},
 | 
			
		||||
    {"constraint_name", CONSTRAINT_NAME},
 | 
			
		||||
    {"constraint_schema", CONSTRAINT_SCHEMA},
 | 
			
		||||
    {"contains", CONTAINS},
 | 
			
		||||
    {"context", CONTEXT},
 | 
			
		||||
    {"contributors", CONTRIBUTORS},
 | 
			
		||||
    {"copy", COPY},
 | 
			
		||||
    {"count", COUNT},
 | 
			
		||||
    {"cpu", CPU},
 | 
			
		||||
    {"create_timestamp", CREATE_TIMESTAMP},
 | 
			
		||||
    {"cube", CUBE},
 | 
			
		||||
    {"cume_dist", CUME_DIST},
 | 
			
		||||
    {"curdate", CURDATE},
 | 
			
		||||
    {"current", CURRENT},
 | 
			
		||||
    {"cursor_name", CURSOR_NAME},
 | 
			
		||||
    {"curtime", CURTIME},
 | 
			
		||||
    {"ctx_id", CTX_ID},
 | 
			
		||||
    {"cycle", CYCLE},
 | 
			
		||||
    {"dag", DAG},
 | 
			
		||||
    {"data", DATA},
 | 
			
		||||
    {"database_id", DATABASE_ID},
 | 
			
		||||
    {"datafile", DATAFILE},
 | 
			
		||||
    {"data_table_id", DATA_TABLE_ID},
 | 
			
		||||
    {"date", DATE},
 | 
			
		||||
    {"date_add", DATE_ADD},
 | 
			
		||||
    {"date_sub", DATE_SUB},
 | 
			
		||||
    {"datetime", DATETIME},
 | 
			
		||||
    {"day", DAY},
 | 
			
		||||
    {"deallocate", DEALLOCATE},
 | 
			
		||||
    {"decryption", DECRYPTION},
 | 
			
		||||
    {"default_auth", DEFAULT_AUTH},
 | 
			
		||||
    {"definer", DEFINER},
 | 
			
		||||
    {"delay", DELAY},
 | 
			
		||||
    {"delay_key_write", DELAY_KEY_WRITE},
 | 
			
		||||
    {"depth", DEPTH},
 | 
			
		||||
    {"des_key_file", DES_KEY_FILE},
 | 
			
		||||
    {"destination", DESTINATION},
 | 
			
		||||
    {"dense_rank", DENSE_RANK},
 | 
			
		||||
    {"diagnostics", DIAGNOSTICS},
 | 
			
		||||
    {"directory", DIRECTORY},
 | 
			
		||||
    {"disable", DISABLE},
 | 
			
		||||
    {"discard", DISCARD},
 | 
			
		||||
    {"disk", DISK},
 | 
			
		||||
    {"diskgroup", DISKGROUP},
 | 
			
		||||
    {"do", DO},
 | 
			
		||||
    {"dump", DUMP},
 | 
			
		||||
    {"dumpfile", DUMPFILE},
 | 
			
		||||
    {"duplicate", DUPLICATE},
 | 
			
		||||
    {"dynamic", DYNAMIC},
 | 
			
		||||
    {"default_tablegroup", DEFAULT_TABLEGROUP},
 | 
			
		||||
    {"effective", EFFECTIVE},
 | 
			
		||||
    {"enable", ENABLE},
 | 
			
		||||
    {"encryption", ENCRYPTION},
 | 
			
		||||
    {"end", END},
 | 
			
		||||
    {"ends", ENDS},
 | 
			
		||||
    {"engine", ENGINE_},
 | 
			
		||||
    {"engines", ENGINES},
 | 
			
		||||
    {"enum", ENUM},
 | 
			
		||||
    {"entity", ENTITY},
 | 
			
		||||
    {"error", ERROR_P},
 | 
			
		||||
    {"error_code", ERROR_CODE},
 | 
			
		||||
    {"errors", ERRORS},
 | 
			
		||||
    {"escape", ESCAPE},
 | 
			
		||||
    {"event", EVENT},
 | 
			
		||||
    {"events", EVENTS},
 | 
			
		||||
    {"every", EVERY},
 | 
			
		||||
    {"except", EXCEPT},
 | 
			
		||||
    {"exchange", EXCHANGE},
 | 
			
		||||
    {"execute", EXECUTE},
 | 
			
		||||
    {"expansion", EXPANSION},
 | 
			
		||||
    {"expire", EXPIRE},
 | 
			
		||||
    {"expired", EXPIRED},
 | 
			
		||||
    {"expire_info", EXPIRE_INFO},
 | 
			
		||||
    {"export", EXPORT},
 | 
			
		||||
    {"extended", EXTENDED},
 | 
			
		||||
    {"extended_noaddr", EXTENDED_NOADDR},
 | 
			
		||||
    {"extent_size", EXTENT_SIZE},
 | 
			
		||||
    {"extract", EXTRACT},
 | 
			
		||||
    {"failover", FAILOVER},
 | 
			
		||||
    {"fast", FAST},
 | 
			
		||||
    {"faults", FAULTS},
 | 
			
		||||
    {"fields", FIELDS},
 | 
			
		||||
    {"file", FILEX},
 | 
			
		||||
    {"file_id", FILE_ID},
 | 
			
		||||
    {"final_count", FINAL_COUNT},
 | 
			
		||||
    {"first", FIRST},
 | 
			
		||||
    {"first_value", FIRST_VALUE},
 | 
			
		||||
    {"fixed", FIXED},
 | 
			
		||||
    {"flush", FLUSH},
 | 
			
		||||
    {"follower", FOLLOWER},
 | 
			
		||||
    {"format", FORMAT},
 | 
			
		||||
    {"found", FOUND},
 | 
			
		||||
    {"freeze", FREEZE},
 | 
			
		||||
    {"frequency", FREQUENCY},
 | 
			
		||||
    {"frozen", FROZEN},
 | 
			
		||||
    {"function", FUNCTION},
 | 
			
		||||
    {"full", FULL},
 | 
			
		||||
    {"following", FOLLOWING},
 | 
			
		||||
    {"general", GENERAL},
 | 
			
		||||
    {"geometry", GEOMETRY},
 | 
			
		||||
    {"geometrycollection", GEOMETRYCOLLECTION},
 | 
			
		||||
    {"get_format", GET_FORMAT},
 | 
			
		||||
    {"global", GLOBAL},
 | 
			
		||||
    {"global_name", GLOBAL_NAME},
 | 
			
		||||
    {"grants", GRANTS},
 | 
			
		||||
    {"grouping", GROUPING},
 | 
			
		||||
    {"group_concat", GROUP_CONCAT},
 | 
			
		||||
    {"gts", GTS},
 | 
			
		||||
    {"handler", HANDLER},
 | 
			
		||||
    {"hash", HASH},
 | 
			
		||||
    {"help", HELP},
 | 
			
		||||
    {"histogram", HISTOGRAM},
 | 
			
		||||
    {"host", HOST},
 | 
			
		||||
    {"hosts", HOSTS},
 | 
			
		||||
    {"hour", HOUR},
 | 
			
		||||
    {"id", ID},
 | 
			
		||||
    {"idc", IDC},
 | 
			
		||||
    {"identified", IDENTIFIED},
 | 
			
		||||
    {"ignore", IGNORE},
 | 
			
		||||
    {"ignore_server_ids", IGNORE_SERVER_IDS},
 | 
			
		||||
    {"import", IMPORT},
 | 
			
		||||
    {"incr", INCR},
 | 
			
		||||
    {"incremental", INCREMENTAL},
 | 
			
		||||
    {"indexes", INDEXES},
 | 
			
		||||
    {"index_table_id", INDEX_TABLE_ID},
 | 
			
		||||
    {"info", INFO},
 | 
			
		||||
    {"initial_size", INITIAL_SIZE},
 | 
			
		||||
    {"innodb", INNODB},
 | 
			
		||||
    {"insert_method", INSERT_METHOD},
 | 
			
		||||
    {"install", INSTALL},
 | 
			
		||||
    {"instance", INSTANCE},
 | 
			
		||||
    {"intersect", INTERSECT},
 | 
			
		||||
    {"invisible", INVISIBLE},
 | 
			
		||||
    {"invoker", INVOKER},
 | 
			
		||||
    {"io", IO},
 | 
			
		||||
    {"io_thread", IO_THREAD},
 | 
			
		||||
    {"ipc", IPC},
 | 
			
		||||
    {"isnull", ISNULL},
 | 
			
		||||
    {"isolate", ISOLATE},
 | 
			
		||||
    {"isolation", ISOLATION},
 | 
			
		||||
    {"issuer", ISSUER},
 | 
			
		||||
    {"job", JOB},
 | 
			
		||||
    {"json", JSON},
 | 
			
		||||
    {"key_block_size", KEY_BLOCK_SIZE},
 | 
			
		||||
    {"key_version", KEY_VERSION},
 | 
			
		||||
    {"kvcache", KVCACHE},
 | 
			
		||||
    {"ilogcache", ILOGCACHE},
 | 
			
		||||
    {"file_id", FILE_ID},
 | 
			
		||||
    {"lag", LAG},
 | 
			
		||||
    {"language", LANGUAGE},
 | 
			
		||||
    {"last", LAST},
 | 
			
		||||
    {"last_value", LAST_VALUE},
 | 
			
		||||
    {"lead", LEAD},
 | 
			
		||||
    {"leader", LEADER},
 | 
			
		||||
    {"leaves", LEAVES},
 | 
			
		||||
    {"leak", LEAK},
 | 
			
		||||
    {"leak_mod", LEAK_MOD},
 | 
			
		||||
    {"leak_rate", LEAK_RATE},
 | 
			
		||||
    {"less", LESS},
 | 
			
		||||
    {"level", LEVEL},
 | 
			
		||||
    {"linestring", LINESTRING},
 | 
			
		||||
    {"list", LIST_},
 | 
			
		||||
    {"listagg", LISTAGG},
 | 
			
		||||
    {"local", LOCAL},
 | 
			
		||||
    {"locality", LOCALITY},
 | 
			
		||||
    {"location", LOCATION},
 | 
			
		||||
    {"locked", LOCKED},
 | 
			
		||||
    {"locks", LOCKS},
 | 
			
		||||
    {"logfile", LOGFILE},
 | 
			
		||||
    {"logonly_replica_num", LOGONLY_REPLICA_NUM},
 | 
			
		||||
    {"logs", LOGS},
 | 
			
		||||
    {"major", MAJOR},
 | 
			
		||||
    {"manual", MANUAL},
 | 
			
		||||
    {"master", MASTER},
 | 
			
		||||
    {"master_auto_position", MASTER_AUTO_POSITION},
 | 
			
		||||
    {"master_connect_retry", MASTER_CONNECT_RETRY},
 | 
			
		||||
    {"master_delay", MASTER_DELAY},
 | 
			
		||||
    {"master_heartbeat_period", MASTER_HEARTBEAT_PERIOD},
 | 
			
		||||
    {"master_host", MASTER_HOST},
 | 
			
		||||
    {"master_log_file", MASTER_LOG_FILE},
 | 
			
		||||
    {"master_log_pos", MASTER_LOG_POS},
 | 
			
		||||
    {"master_password", MASTER_PASSWORD},
 | 
			
		||||
    {"master_port", MASTER_PORT},
 | 
			
		||||
    {"master_retry_count", MASTER_RETRY_COUNT},
 | 
			
		||||
    {"master_server_id", MASTER_SERVER_ID},
 | 
			
		||||
    {"master_ssl", MASTER_SSL},
 | 
			
		||||
    {"master_ssl_ca", MASTER_SSL_CA},
 | 
			
		||||
    {"master_ssl_capath", MASTER_SSL_CAPATH},
 | 
			
		||||
    {"master_ssl_cert", MASTER_SSL_CERT},
 | 
			
		||||
    {"master_ssl_cipher", MASTER_SSL_CIPHER},
 | 
			
		||||
    {"master_ssl_crl", MASTER_SSL_CRL},
 | 
			
		||||
    {"master_ssl_crlpath", MASTER_SSL_CRLPATH},
 | 
			
		||||
    {"master_ssl_key", MASTER_SSL_KEY},
 | 
			
		||||
    {"master_user", MASTER_USER},
 | 
			
		||||
    {"max", MAX},
 | 
			
		||||
    {"maximize", MAXIMIZE},
 | 
			
		||||
    {"max_connections_per_hour", MAX_CONNECTIONS_PER_HOUR},
 | 
			
		||||
    {"max_cpu", MAX_CPU},
 | 
			
		||||
    {"max_disk_size", MAX_DISK_SIZE},
 | 
			
		||||
    {"max_iops", MAX_IOPS},
 | 
			
		||||
    {"max_memory", MAX_MEMORY},
 | 
			
		||||
    {"max_queries_per_hour", MAX_QUERIES_PER_HOUR},
 | 
			
		||||
    {"max_rows", MAX_ROWS},
 | 
			
		||||
    {"max_session_num", MAX_SESSION_NUM},
 | 
			
		||||
    {"max_size", MAX_SIZE},
 | 
			
		||||
    {"max_updates_per_hour", MAX_UPDATES_PER_HOUR},
 | 
			
		||||
    {"max_used_part_id", MAX_USED_PART_ID},
 | 
			
		||||
    {"max_user_connections", MAX_USER_CONNECTIONS},
 | 
			
		||||
    {"medium", MEDIUM},
 | 
			
		||||
    {"memory", MEMORY},
 | 
			
		||||
    {"memstore_percent", MEMSTORE_PERCENT},
 | 
			
		||||
    {"memtable", MEMTABLE},
 | 
			
		||||
    {"merge", MERGE},
 | 
			
		||||
    {"message_text", MESSAGE_TEXT},
 | 
			
		||||
    {"meta", META},
 | 
			
		||||
    {"microsecond", MICROSECOND},
 | 
			
		||||
    {"migrate", MIGRATE},
 | 
			
		||||
    {"migration", MIGRATION},
 | 
			
		||||
    {"min", MIN},
 | 
			
		||||
    {"min_cpu", MIN_CPU},
 | 
			
		||||
    {"min_iops", MIN_IOPS},
 | 
			
		||||
    {"min_memory", MIN_MEMORY},
 | 
			
		||||
    {"min_rows", MIN_ROWS},
 | 
			
		||||
    {"minor", MINOR},
 | 
			
		||||
    {"minute", MINUTE},
 | 
			
		||||
    {"minus", MINUS},
 | 
			
		||||
    {"mode", MODE},
 | 
			
		||||
    {"modify", MODIFY},
 | 
			
		||||
    {"month", MONTH},
 | 
			
		||||
    {"move", MOVE},
 | 
			
		||||
    {"multilinestring", MULTILINESTRING},
 | 
			
		||||
    {"multipoint", MULTIPOINT},
 | 
			
		||||
    {"multipolygon", MULTIPOLYGON},
 | 
			
		||||
    {"mutex", MUTEX},
 | 
			
		||||
    {"mysql_errno", MYSQL_ERRNO},
 | 
			
		||||
    {"name", NAME},
 | 
			
		||||
    {"names", NAMES},
 | 
			
		||||
    {"national", NATIONAL},
 | 
			
		||||
    {"nchar", NCHAR},
 | 
			
		||||
    {"ndb", NDB},
 | 
			
		||||
    {"ndbcluster", NDBCLUSTER},
 | 
			
		||||
    {"new", NEW},
 | 
			
		||||
    {"next", NEXT},
 | 
			
		||||
    {"no", NO},
 | 
			
		||||
    {"noarchivelog", NOARCHIVELOG},
 | 
			
		||||
    {"noaudit", NOAUDIT},
 | 
			
		||||
    {"no_parallel", NO_PARALLEL},
 | 
			
		||||
    {"no_rewrite", NO_REWRITE},
 | 
			
		||||
    {"no_wait", NO_WAIT},
 | 
			
		||||
    {"nodegroup", NODEGROUP},
 | 
			
		||||
    {"none", NONE},
 | 
			
		||||
    {"noparallel", NOPARALLEL},
 | 
			
		||||
    {"normal", NORMAL},
 | 
			
		||||
    {"now", NOW},
 | 
			
		||||
    {"nowait", NOWAIT},
 | 
			
		||||
    {"nulls", NULLS},
 | 
			
		||||
    {"number", NUMBER},
 | 
			
		||||
    {"nvarchar", NVARCHAR},
 | 
			
		||||
    {"occur", OCCUR},
 | 
			
		||||
    {"ntile", NTILE},
 | 
			
		||||
    {"nth_value", NTH_VALUE},
 | 
			
		||||
    {"of", OF},
 | 
			
		||||
    {"off", OFF},
 | 
			
		||||
    {"offset", OFFSET},
 | 
			
		||||
    {"old_key", OLD_KEY},
 | 
			
		||||
    {"over", OVER},
 | 
			
		||||
    {"old_password", OLD_PASSWORD},
 | 
			
		||||
    {"one", ONE},
 | 
			
		||||
    {"one_shot", ONE_SHOT},
 | 
			
		||||
    {"only", ONLY},
 | 
			
		||||
    {"open", OPEN},
 | 
			
		||||
    {"options", OPTIONS},
 | 
			
		||||
    {"orig_default", ORIG_DEFAULT},
 | 
			
		||||
    {"outline", OUTLINE},
 | 
			
		||||
    {"owner", OWNER},
 | 
			
		||||
    {"pack_keys", PACK_KEYS},
 | 
			
		||||
    {"page", PAGE},
 | 
			
		||||
    {"parameters", PARAMETERS},
 | 
			
		||||
    {"parallel", PARALLEL},
 | 
			
		||||
    {"parser", PARSER},
 | 
			
		||||
    {"partial", PARTIAL},
 | 
			
		||||
    {"partition_id", PARTITION_ID},
 | 
			
		||||
    {"partitioning", PARTITIONING},
 | 
			
		||||
    {"partitions", PARTITIONS},
 | 
			
		||||
    {"password", PASSWORD},
 | 
			
		||||
    {"pause", PAUSE},
 | 
			
		||||
    {"percent_rank", PERCENT_RANK},
 | 
			
		||||
    {"performance", PERFORMANCE},
 | 
			
		||||
    {"phase", PHASE},
 | 
			
		||||
    {"physical", PHYSICAL},
 | 
			
		||||
    {"plan", PLAN},
 | 
			
		||||
    {"planregress", PLANREGRESS},
 | 
			
		||||
    {"plugin", PLUGIN},
 | 
			
		||||
    {"plugin_dir", PLUGIN_DIR},
 | 
			
		||||
    {"plugins", PLUGINS},
 | 
			
		||||
    {"point", POINT},
 | 
			
		||||
    {"polygon", POLYGON},
 | 
			
		||||
    {"pool", POOL},
 | 
			
		||||
    {"port", PORT},
 | 
			
		||||
    {"position", POSITION},
 | 
			
		||||
    {"prepare", PREPARE},
 | 
			
		||||
    {"preserve", PRESERVE},
 | 
			
		||||
    {"prev", PREV},
 | 
			
		||||
    {"primary_cluster_id", PRIMARY_CLUSTER_ID},
 | 
			
		||||
    {"primary_rootservice_list", PRIMARY_ROOTSERVICE_LIST},
 | 
			
		||||
    {"primary_zone", PRIMARY_ZONE},
 | 
			
		||||
    {"privileges", PRIVILEGES},
 | 
			
		||||
    {"process", PROCESS},
 | 
			
		||||
    {"processlist", PROCESSLIST},
 | 
			
		||||
    {"profile", PROFILE},
 | 
			
		||||
    {"profiles", PROFILES},
 | 
			
		||||
    {"progressive_merge_num", PROGRESSIVE_MERGE_NUM},
 | 
			
		||||
    {"protection", PROTECTION},
 | 
			
		||||
    {"proxy", PROXY},
 | 
			
		||||
    {"public", PUBLIC},
 | 
			
		||||
    {"p_entity", P_ENTITY},
 | 
			
		||||
    {"p_chunk", P_CHUNK},
 | 
			
		||||
    {"preceding", PRECEDING},
 | 
			
		||||
    {"pctfree", PCTFREE},
 | 
			
		||||
    {"ps", PS},
 | 
			
		||||
    {"quarter", QUARTER},
 | 
			
		||||
    {"query", QUERY},
 | 
			
		||||
    {"quick", QUICK},
 | 
			
		||||
    {"rank", RANK},
 | 
			
		||||
    {"read_consistency", READ_CONSISTENCY},
 | 
			
		||||
    {"read_only", READ_ONLY},
 | 
			
		||||
    {"rebuild", REBUILD},
 | 
			
		||||
    {"recover", RECOVER},
 | 
			
		||||
    {"recovery", RECOVERY},
 | 
			
		||||
    {"recycle", RECYCLE},
 | 
			
		||||
    {"recyclebin", RECYCLEBIN},
 | 
			
		||||
    {"redo_buffer_size", REDO_BUFFER_SIZE},
 | 
			
		||||
    {"redo_transport_options", REDO_TRANSPORT_OPTIONS},
 | 
			
		||||
    {"redofile", REDOFILE},
 | 
			
		||||
    {"redundant", REDUNDANT},
 | 
			
		||||
    {"refresh", REFRESH},
 | 
			
		||||
    {"region", REGION},
 | 
			
		||||
    {"relay", RELAY},
 | 
			
		||||
    {"relay_log_file", RELAY_LOG_FILE},
 | 
			
		||||
    {"relay_log_pos", RELAY_LOG_POS},
 | 
			
		||||
    {"relay_thread", RELAY_THREAD},
 | 
			
		||||
    {"relaylog", RELAYLOG},
 | 
			
		||||
    {"reload", RELOAD},
 | 
			
		||||
    {"remove", REMOVE},
 | 
			
		||||
    {"reorganize", REORGANIZE},
 | 
			
		||||
    {"repair", REPAIR},
 | 
			
		||||
    {"repeatable", REPEATABLE},
 | 
			
		||||
    {"replica", REPLICA},
 | 
			
		||||
    {"replica_num", REPLICA_NUM},
 | 
			
		||||
    {"replica_type", REPLICA_TYPE},
 | 
			
		||||
    {"duplicate_scope", DUPLICATE_SCOPE},
 | 
			
		||||
    {"replication", REPLICATION},
 | 
			
		||||
    {"report", REPORT},
 | 
			
		||||
    {"reset", RESET},
 | 
			
		||||
    {"resource", RESOURCE},
 | 
			
		||||
    {"resource_pool_list", RESOURCE_POOL_LIST},
 | 
			
		||||
    {"respect", RESPECT},
 | 
			
		||||
    {"restart", RESTART},
 | 
			
		||||
    {"restore", RESTORE},
 | 
			
		||||
    {"resume", RESUME},
 | 
			
		||||
    {"returned_sqlstate", RETURNED_SQLSTATE},
 | 
			
		||||
    {"returns", RETURNS},
 | 
			
		||||
    {"reverse", REVERSE},
 | 
			
		||||
    {"rewrite_merge_version", REWRITE_MERGE_VERSION},
 | 
			
		||||
    {"rollback", ROLLBACK},
 | 
			
		||||
    {"rolling", ROLLING},
 | 
			
		||||
    {"rollup", ROLLUP},
 | 
			
		||||
    {"root", ROOT},
 | 
			
		||||
    {"rootservice", ROOTSERVICE},
 | 
			
		||||
    {"rootservice_list", ROOTSERVICE_LIST},
 | 
			
		||||
    {"roottable", ROOTTABLE},
 | 
			
		||||
    {"rotate", ROTATE},
 | 
			
		||||
    {"routine", ROUTINE},
 | 
			
		||||
    {"row", ROW},
 | 
			
		||||
    {"row_count", ROW_COUNT},
 | 
			
		||||
    {"row_format", ROW_FORMAT},
 | 
			
		||||
    {"row_number", ROW_NUMBER},
 | 
			
		||||
    {"rows", ROWS},
 | 
			
		||||
    {"rtree", RTREE},
 | 
			
		||||
    {"run", RUN},
 | 
			
		||||
    {"sample", SAMPLE},
 | 
			
		||||
    {"savepoint", SAVEPOINT},
 | 
			
		||||
    {"schedule", SCHEDULE},
 | 
			
		||||
    {"schema_name", SCHEMA_NAME},
 | 
			
		||||
    {"scope", SCOPE},
 | 
			
		||||
    {"second", SECOND},
 | 
			
		||||
    {"security", SECURITY},
 | 
			
		||||
    {"seed", SEED},
 | 
			
		||||
    {"serial", SERIAL},
 | 
			
		||||
    {"serializable", SERIALIZABLE},
 | 
			
		||||
    {"server", SERVER},
 | 
			
		||||
    {"server_ip", SERVER_IP},
 | 
			
		||||
    {"server_port", SERVER_PORT},
 | 
			
		||||
    {"server_type", SERVER_TYPE},
 | 
			
		||||
    {"session", SESSION},
 | 
			
		||||
    {"session_user", SESSION_USER},
 | 
			
		||||
    {"statements", STATEMENTS},
 | 
			
		||||
    {"binding", BINDING},
 | 
			
		||||
    {"set_master_cluster", SET_MASTER_CLUSTER},
 | 
			
		||||
    {"set_slave_cluster", SET_SLAVE_CLUSTER},
 | 
			
		||||
    {"set_tp", SET_TP},
 | 
			
		||||
    {"share", SHARE},
 | 
			
		||||
    {"shutdown", SHUTDOWN},
 | 
			
		||||
    {"signed", SIGNED},
 | 
			
		||||
    {"simple", SIMPLE},
 | 
			
		||||
    {"slave", SLAVE},
 | 
			
		||||
    {"size", SIZE},
 | 
			
		||||
    {"slow", SLOW},
 | 
			
		||||
    {"slot_idx", SLOT_IDX},
 | 
			
		||||
    {"snapshot", SNAPSHOT},
 | 
			
		||||
    {"socket", SOCKET},
 | 
			
		||||
    {"some", SOME},
 | 
			
		||||
    {"soname", SONAME},
 | 
			
		||||
    {"sounds", SOUNDS},
 | 
			
		||||
    {"source", SOURCE},
 | 
			
		||||
    {"spfile", SPFILE},
 | 
			
		||||
    {"split", SPLIT},
 | 
			
		||||
    {"sql_after_gtids", SQL_AFTER_GTIDS},
 | 
			
		||||
    {"sql_after_mts_gaps", SQL_AFTER_MTS_GAPS},
 | 
			
		||||
    {"sql_before_gtids", SQL_BEFORE_GTIDS},
 | 
			
		||||
    {"sql_buffer_result", SQL_BUFFER_RESULT},
 | 
			
		||||
    {"sql_cache", SQL_CACHE},
 | 
			
		||||
    {"sql_id", SQL_ID},
 | 
			
		||||
    {"sql_no_cache", SQL_NO_CACHE},
 | 
			
		||||
    {"sql_thread", SQL_THREAD},
 | 
			
		||||
    {"sql_tsi_day", SQL_TSI_DAY},
 | 
			
		||||
    {"sql_tsi_hour", SQL_TSI_HOUR},
 | 
			
		||||
    {"sql_tsi_minute", SQL_TSI_MINUTE},
 | 
			
		||||
    {"sql_tsi_month", SQL_TSI_MONTH},
 | 
			
		||||
    {"sql_tsi_quarter", SQL_TSI_QUARTER},
 | 
			
		||||
    {"sql_tsi_second", SQL_TSI_SECOND},
 | 
			
		||||
    {"sql_tsi_week", SQL_TSI_WEEK},
 | 
			
		||||
    {"sql_tsi_year", SQL_TSI_YEAR},
 | 
			
		||||
    {"standby", STANDBY},
 | 
			
		||||
    {"start", START},
 | 
			
		||||
    {"starts", STARTS},
 | 
			
		||||
    {"stat", STAT},
 | 
			
		||||
    {"stats_auto_recalc", STATS_AUTO_RECALC},
 | 
			
		||||
    {"stats_persistent", STATS_PERSISTENT},
 | 
			
		||||
    {"stats_sample_pages", STATS_SAMPLE_PAGES},
 | 
			
		||||
    {"status", STATUS},
 | 
			
		||||
    {"std", STD},
 | 
			
		||||
    {"stddev", STDDEV},
 | 
			
		||||
    {"stddev_pop", STDDEV_POP},
 | 
			
		||||
    {"stddev_samp", STDDEV_SAMP},
 | 
			
		||||
    {"stop", STOP},
 | 
			
		||||
    {"storage", STORAGE},
 | 
			
		||||
    {"storage_format_version", STORAGE_FORMAT_VERSION},
 | 
			
		||||
    {"storage_format_work_version", STORAGE_FORMAT_WORK_VERSION},
 | 
			
		||||
    {"storing", STORING},
 | 
			
		||||
    {"string", STRING},
 | 
			
		||||
    {"strong", STRONG},
 | 
			
		||||
    {"subclass_origin", SUBCLASS_ORIGIN},
 | 
			
		||||
    {"subdate", SUBDATE},
 | 
			
		||||
    {"subject", SUBJECT},
 | 
			
		||||
    {"subpartition", SUBPARTITION},
 | 
			
		||||
    {"subpartitions", SUBPARTITIONS},
 | 
			
		||||
    {"substr", SUBSTR},
 | 
			
		||||
    {"substring", SUBSTRING},
 | 
			
		||||
    {"sum", SUM},
 | 
			
		||||
    {"super", SUPER},
 | 
			
		||||
    {"suspend", SUSPEND},
 | 
			
		||||
    {"successful", SUCCESSFUL},
 | 
			
		||||
    {"synchronization", SYNCHRONIZATION},
 | 
			
		||||
    {"sysdate", SYSDATE},
 | 
			
		||||
    {"system", SYSTEM},
 | 
			
		||||
    {"system_user", SYSTEM_USER},
 | 
			
		||||
    {"synonym", SYNONYM},
 | 
			
		||||
    {"swaps", SWAPS},
 | 
			
		||||
    {"switch", SWITCH},
 | 
			
		||||
    {"switches", SWITCHES},
 | 
			
		||||
    {"switchover", SWITCHOVER},
 | 
			
		||||
    {"table_checksum", TABLE_CHECKSUM},
 | 
			
		||||
    {"table_mode", TABLE_MODE},
 | 
			
		||||
    {"table_id", TABLE_ID},
 | 
			
		||||
    {"table_name", TABLE_NAME},
 | 
			
		||||
    {"tablegroup", TABLEGROUP},
 | 
			
		||||
    {"tablegroups", TABLEGROUPS},
 | 
			
		||||
    {"tablegroup_id", TABLEGROUP_ID},
 | 
			
		||||
    {"tables", TABLES},
 | 
			
		||||
    {"tablespace", TABLESPACE},
 | 
			
		||||
    {"tablet", TABLET},
 | 
			
		||||
    {"tablet_max_size", TABLET_MAX_SIZE},
 | 
			
		||||
    {"task", TASK},
 | 
			
		||||
    {"template", TEMPLATE},
 | 
			
		||||
    {"temporary", TEMPORARY},
 | 
			
		||||
    {"temptable", TEMPTABLE},
 | 
			
		||||
    {"tenant", TENANT},
 | 
			
		||||
    {"tenant_id", TENANT_ID},
 | 
			
		||||
    {"text", TEXT},
 | 
			
		||||
    {"than", THAN},
 | 
			
		||||
    {"time", TIME},
 | 
			
		||||
    {"timestamp", TIMESTAMP},
 | 
			
		||||
    {"timestampadd", TIMESTAMPADD},
 | 
			
		||||
    {"timestampdiff", TIMESTAMPDIFF},
 | 
			
		||||
    {"tablet_size", TABLET_SIZE},
 | 
			
		||||
    {"tp_name", TP_NAME},
 | 
			
		||||
    {"tp_no", TP_NO},
 | 
			
		||||
    {"trace", TRACE},
 | 
			
		||||
    {"traditional", TRADITIONAL},
 | 
			
		||||
    {"transaction", TRANSACTION},
 | 
			
		||||
    {"trigger", TRIGGER},
 | 
			
		||||
    {"triggers", TRIGGERS},
 | 
			
		||||
    {"trim", TRIM},
 | 
			
		||||
    {"truncate", TRUNCATE},
 | 
			
		||||
    {"type", TYPE},
 | 
			
		||||
    {"types", TYPES},
 | 
			
		||||
    {"uncommitted", UNCOMMITTED},
 | 
			
		||||
    {"undefined", UNDEFINED},
 | 
			
		||||
    {"undo_buffer_size", UNDO_BUFFER_SIZE},
 | 
			
		||||
    {"undofile", UNDOFILE},
 | 
			
		||||
    {"unicode", UNICODE},
 | 
			
		||||
    {"uninstall", UNINSTALL},
 | 
			
		||||
    {"unit", UNIT},
 | 
			
		||||
    {"unit_num", UNIT_NUM},
 | 
			
		||||
    {"unknown", UNKNOWN},
 | 
			
		||||
    {"unlocked", UNLOCKED},
 | 
			
		||||
    {"until", UNTIL},
 | 
			
		||||
    {"unusual", UNUSUAL},
 | 
			
		||||
    {"upgrade", UPGRADE},
 | 
			
		||||
    {"use_bloom_filter", USE_BLOOM_FILTER},
 | 
			
		||||
    {"use_frm", USE_FRM},
 | 
			
		||||
    {"user", USER},
 | 
			
		||||
    {"user_resources", USER_RESOURCES},
 | 
			
		||||
    {"unbounded", UNBOUNDED},
 | 
			
		||||
    {"valid", VALID},
 | 
			
		||||
    {"validate", VALIDATE},
 | 
			
		||||
    {"value", VALUE},
 | 
			
		||||
    {"variance", VARIANCE},
 | 
			
		||||
    {"variables", VARIABLES},
 | 
			
		||||
    {"var_pop", VAR_POP},
 | 
			
		||||
    {"var_samp", VAR_SAMP},
 | 
			
		||||
    {"verbose", VERBOSE},
 | 
			
		||||
    {"verify", VERIFY},
 | 
			
		||||
    {"materialized", MATERIALIZED},
 | 
			
		||||
    {"validate", VALIDATE},
 | 
			
		||||
    {"view", VIEW},
 | 
			
		||||
    {"virtual_column_id", VIRTUAL_COLUMN_ID},
 | 
			
		||||
    {"visible", VISIBLE},
 | 
			
		||||
    {"wait", WAIT},
 | 
			
		||||
    {"warnings", WARNINGS},
 | 
			
		||||
    {"weak", WEAK},
 | 
			
		||||
    {"week", WEEK},
 | 
			
		||||
    {"weight_string", WEIGHT_STRING},
 | 
			
		||||
    {"whenever", WHENEVER},
 | 
			
		||||
    {"window", WINDOW},
 | 
			
		||||
    {"work", WORK},
 | 
			
		||||
    {"wrapper", WRAPPER},
 | 
			
		||||
    {"x509", X509},
 | 
			
		||||
    {"xa", XA},
 | 
			
		||||
    {"xml", XML},
 | 
			
		||||
    {"year", YEAR},
 | 
			
		||||
    {"zone", ZONE},
 | 
			
		||||
    {"zone_list", ZONE_LIST},
 | 
			
		||||
    {"time_zone_info", TIME_ZONE_INFO},
 | 
			
		||||
    {"zone_type", ZONE_TYPE},
 | 
			
		||||
    {"audit", AUDIT},
 | 
			
		||||
    {"PL", PL},
 | 
			
		||||
    {"remote_oss", REMOTE_OSS},
 | 
			
		||||
    {"throttle", THROTTLE},
 | 
			
		||||
    {"priority", PRIORITY},
 | 
			
		||||
    {"rt", RT},
 | 
			
		||||
    {"network", NETWORK},
 | 
			
		||||
    {"logical_reads", LOGICAL_READS},
 | 
			
		||||
    {"queue_time", QUEUE_TIME},
 | 
			
		||||
    {"obsolete", OBSOLETE}};
 | 
			
		||||
 | 
			
		||||
/** https://dev.mysql.com/doc/refman/5.7/en/sql-syntax-prepared-statements.html
 | 
			
		||||
 ALTER TABLE
 | 
			
		||||
 ALTER USER
 | 
			
		||||
 ANALYZE TABLE
 | 
			
		||||
 CACHE INDEX
 | 
			
		||||
 CALL
 | 
			
		||||
 CHANGE MASTER
 | 
			
		||||
 CHECKSUM {TABLE | TABLES}
 | 
			
		||||
 COMMIT
 | 
			
		||||
 {CREATE | DROP} INDEX
 | 
			
		||||
 {CREATE | RENAME | DROP} DATABASE
 | 
			
		||||
 {CREATE | DROP} TABLE
 | 
			
		||||
 {CREATE | RENAME | DROP} USER
 | 
			
		||||
 {CREATE | DROP} VIEW
 | 
			
		||||
 DELETE
 | 
			
		||||
 DO
 | 
			
		||||
 FLUSH {TABLE | TABLES | TABLES WITH READ LOCK | HOSTS | PRIVILEGES
 | 
			
		||||
   | LOGS | STATUS | MASTER | SLAVE | DES_KEY_FILE | USER_RESOURCES}
 | 
			
		||||
 GRANT
 | 
			
		||||
 INSERT
 | 
			
		||||
 INSTALL PLUGIN
 | 
			
		||||
 KILL
 | 
			
		||||
 \LOAD INDEX INTO CACHE
 | 
			
		||||
 OPTIMIZE TABLE
 | 
			
		||||
 RENAME TABLE
 | 
			
		||||
 REPAIR TABLE
 | 
			
		||||
 REPLACE
 | 
			
		||||
 RESET {MASTER | SLAVE | QUERY CACHE}
 | 
			
		||||
 REVOKE
 | 
			
		||||
 SELECT
 | 
			
		||||
 SET
 | 
			
		||||
 SHOW {WARNINGS | ERRORS}
 | 
			
		||||
 SHOW BINLOG EVENTS
 | 
			
		||||
 SHOW CREATE {PROCEDURE | FUNCTION | EVENT | TABLE | VIEW}
 | 
			
		||||
 SHOW {MASTER | BINARY} LOGS
 | 
			
		||||
 SHOW {MASTER | SLAVE} STATUS
 | 
			
		||||
 SLAVE {START | STOP}
 | 
			
		||||
 TRUNCATE TABLE
 | 
			
		||||
 UNINSTALL PLUGIN
 | 
			
		||||
 UPDATE
 | 
			
		||||
 */
 | 
			
		||||
static const NonReservedKeyword Mysql_sql_keywords_in_pl[] = {
 | 
			
		||||
    {"alter", ALTER},
 | 
			
		||||
    {"analyze", ANALYZE},
 | 
			
		||||
    {"binary", BINARY},
 | 
			
		||||
    {"binlog", BINLOG},
 | 
			
		||||
    {"cache", CACHE},
 | 
			
		||||
    {"call", CALL},
 | 
			
		||||
    {"change", CHANGE},
 | 
			
		||||
    {"checksum", CHECKSUM},
 | 
			
		||||
    {"commit", COMMIT},
 | 
			
		||||
    {"create", CREATE},
 | 
			
		||||
    {"database", DATABASE},
 | 
			
		||||
    {"delete", DELETE},
 | 
			
		||||
    {"des_key_file", DES_KEY_FILE},
 | 
			
		||||
    {"do", DO},
 | 
			
		||||
    {"drop", DROP},
 | 
			
		||||
    {"errors", ERRORS},
 | 
			
		||||
    {"event", EVENT},
 | 
			
		||||
    {"events", EVENTS},
 | 
			
		||||
    {"flush", FLUSH},
 | 
			
		||||
    {"function", FUNCTION},
 | 
			
		||||
    {"grant", GRANT},
 | 
			
		||||
    {"hosts", HOSTS},
 | 
			
		||||
    {"index", INDEX},
 | 
			
		||||
    {"insert", INSERT},
 | 
			
		||||
    {"install", INSTALL},
 | 
			
		||||
    {"into", INTO},
 | 
			
		||||
    {"kill", KILL},
 | 
			
		||||
    {"load", LOAD},
 | 
			
		||||
    {"lock", LOCK_},
 | 
			
		||||
    {"logs", LOGS},
 | 
			
		||||
    {"master", MASTER},
 | 
			
		||||
    {"optimize", OPTIMIZE},
 | 
			
		||||
    {"plugin", PLUGIN},
 | 
			
		||||
    {"privileges", PRIVILEGES},
 | 
			
		||||
    {"procedure", PROCEDURE},
 | 
			
		||||
    {"query", QUERY},
 | 
			
		||||
    {"read", READ},
 | 
			
		||||
    {"rename", RENAME},
 | 
			
		||||
    {"repair", REPAIR},
 | 
			
		||||
    {"replace", REPLACE},
 | 
			
		||||
    {"reset", RESET},
 | 
			
		||||
    {"revoke", REVOKE},
 | 
			
		||||
    {"select", SELECT},
 | 
			
		||||
    {"set", SET},
 | 
			
		||||
    {"show", SHOW},
 | 
			
		||||
    {"slave", SLAVE},
 | 
			
		||||
    {"start", START},
 | 
			
		||||
    {"status", STATUS},
 | 
			
		||||
    {"stop", STOP},
 | 
			
		||||
    {"table", TABLE},
 | 
			
		||||
    {"tables", TABLES},
 | 
			
		||||
    {"truncate", TRUNCATE},
 | 
			
		||||
    {"uninstall", UNINSTALL},
 | 
			
		||||
    {"update", UPDATE},
 | 
			
		||||
    {"user", USER},
 | 
			
		||||
    {"user_resources", USER_RESOURCES},
 | 
			
		||||
    {"view", VIEW},
 | 
			
		||||
    {"warnings", WARNINGS},
 | 
			
		||||
    {"with", WITH},
 | 
			
		||||
    {"prepare", PREPARE},
 | 
			
		||||
    {"execute", EXECUTE},
 | 
			
		||||
    {"deallocate", DEALLOCATE},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const NonReservedKeyword* mysql_non_reserved_keyword_lookup(const char* word)
 | 
			
		||||
{
 | 
			
		||||
  return find_word(word, mysql_none_reserved_keywords_root, Mysql_none_reserved_keywords);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int mysql_sql_reserved_keyword_lookup(const char* word)
 | 
			
		||||
{
 | 
			
		||||
  int ret = -1;
 | 
			
		||||
  const NonReservedKeyword* res_word = find_word(word, mysql_sql_keywords_in_pl_root, Mysql_sql_keywords_in_pl);
 | 
			
		||||
  if (NULL != res_word) {
 | 
			
		||||
    ret = res_word->keyword_type;
 | 
			
		||||
  }
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// return 0 if succ, return 1 if fail
 | 
			
		||||
int create_mysql_trie_tree()
 | 
			
		||||
{
 | 
			
		||||
  int ret = 0;
 | 
			
		||||
  if (0 != (ret = create_trie_tree(Mysql_none_reserved_keywords,
 | 
			
		||||
                LENGTH_OF(Mysql_none_reserved_keywords),
 | 
			
		||||
                &mysql_none_reserved_keywords_root))) {
 | 
			
		||||
    (void)printf("ERROR create trie tree failed! \n");
 | 
			
		||||
  } else if (0 !=
 | 
			
		||||
             (ret = create_trie_tree(
 | 
			
		||||
                  Mysql_sql_keywords_in_pl, LENGTH_OF(Mysql_sql_keywords_in_pl), &mysql_sql_keywords_in_pl_root))) {
 | 
			
		||||
    (void)printf("ERROR create trie tree failed! \n");
 | 
			
		||||
  } else { /*do nothing*/
 | 
			
		||||
  }
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void __attribute__((constructor)) init_mysql_non_reserved_keywords_tree()
 | 
			
		||||
{
 | 
			
		||||
  int ret = 0;
 | 
			
		||||
  if (0 != (ret = create_mysql_trie_tree())) {
 | 
			
		||||
    (void)printf("ERROR build mysql_non_reserved_keywords tree failed=>%d", ret);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										1807
									
								
								src/sql/parser/ob_item_type.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1807
									
								
								src/sql/parser/ob_item_type.h
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										71
									
								
								src/sql/parser/ob_item_type_str.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								src/sql/parser/ob_item_type_str.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,71 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Copyright (c) 2021 OceanBase
 | 
			
		||||
 * OceanBase CE is licensed under Mulan PubL v2.
 | 
			
		||||
 * You can use this software according to the terms and conditions of the Mulan PubL v2.
 | 
			
		||||
 * You may obtain a copy of Mulan PubL v2 at:
 | 
			
		||||
 *          http://license.coscl.org.cn/MulanPubL-2.0
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 | 
			
		||||
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 | 
			
		||||
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 | 
			
		||||
 * See the Mulan PubL v2 for more details.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _OB_ITEM_TYPE_STR_H
 | 
			
		||||
#define _OB_ITEM_TYPE_STR_H 1
 | 
			
		||||
#include "sql/parser/ob_item_type.h"
 | 
			
		||||
 | 
			
		||||
namespace oceanbase {
 | 
			
		||||
namespace sql {
 | 
			
		||||
inline const char* ob_aggr_func_str(ObItemType aggr_func)
 | 
			
		||||
{
 | 
			
		||||
  const char* ret = "UNKNOWN_AGGR";
 | 
			
		||||
  switch (aggr_func) {
 | 
			
		||||
    case T_FUN_MAX:
 | 
			
		||||
      ret = "MAX";
 | 
			
		||||
      break;
 | 
			
		||||
    case T_FUN_MIN:
 | 
			
		||||
      ret = "MIN";
 | 
			
		||||
      break;
 | 
			
		||||
    case T_FUN_COUNT_SUM:
 | 
			
		||||
      ret = "COUNT_SUM";
 | 
			
		||||
      break;
 | 
			
		||||
    case T_FUN_SUM:
 | 
			
		||||
      ret = "SUM";
 | 
			
		||||
      break;
 | 
			
		||||
    case T_FUN_COUNT:
 | 
			
		||||
      ret = "COUNT";
 | 
			
		||||
      break;
 | 
			
		||||
    case T_FUN_AVG:
 | 
			
		||||
      ret = "AVG";
 | 
			
		||||
      break;
 | 
			
		||||
    case T_FUN_GROUPING:
 | 
			
		||||
      ret = "GROUPING";
 | 
			
		||||
      break;
 | 
			
		||||
    case T_FUN_GROUP_CONCAT:
 | 
			
		||||
      ret = "GROUP_CONCAT";
 | 
			
		||||
      break;
 | 
			
		||||
    case T_FUN_APPROX_COUNT_DISTINCT:
 | 
			
		||||
      ret = "APPROX_COUNT_DISTINCT";
 | 
			
		||||
      break;
 | 
			
		||||
    case T_FUN_APPROX_COUNT_DISTINCT_SYNOPSIS:
 | 
			
		||||
      ret = "APPROX_COUNT_DISTINCT_SYNOPSIS";
 | 
			
		||||
      break;
 | 
			
		||||
    case T_FUN_APPROX_COUNT_DISTINCT_SYNOPSIS_MERGE:
 | 
			
		||||
      ret = "APPROX_COUNT_DISTINCT_SYNOPSIS_MERGE";
 | 
			
		||||
      break;
 | 
			
		||||
    case T_FUN_VARIANCE:
 | 
			
		||||
      ret = "VARIANCE";
 | 
			
		||||
      break;
 | 
			
		||||
    case T_FUN_STDDEV:
 | 
			
		||||
      ret = "STDDEV";
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      break;
 | 
			
		||||
  }
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // end namespace sql
 | 
			
		||||
}  // end namespace oceanbase
 | 
			
		||||
 | 
			
		||||
#endif /* _OB_ITEM_TYPE_STR_H */
 | 
			
		||||
							
								
								
									
										133
									
								
								src/sql/parser/ob_non_reserved_keywords.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										133
									
								
								src/sql/parser/ob_non_reserved_keywords.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,133 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Copyright (c) 2021 OceanBase
 | 
			
		||||
 * OceanBase CE is licensed under Mulan PubL v2.
 | 
			
		||||
 * You can use this software according to the terms and conditions of the Mulan PubL v2.
 | 
			
		||||
 * You may obtain a copy of Mulan PubL v2 at:
 | 
			
		||||
 *          http://license.coscl.org.cn/MulanPubL-2.0
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 | 
			
		||||
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 | 
			
		||||
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 | 
			
		||||
 * See the Mulan PubL v2 for more details.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "ob_non_reserved_keywords.h"
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <ctype.h>
 | 
			
		||||
#include <strings.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include "lib/alloc/alloc_assist.h"
 | 
			
		||||
#include "sql/parser/sql_parser_mysql_mode_tab.h"
 | 
			
		||||
#include "sql/parser/parse_define.h"
 | 
			
		||||
 | 
			
		||||
int32_t get_next_id(char c)
 | 
			
		||||
{
 | 
			
		||||
  int32_t ch_id = -1;
 | 
			
		||||
  if (c >= 'A' && c <= 'Z') {
 | 
			
		||||
    c += 'a' - 'A';
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if ('_' == c) {
 | 
			
		||||
    ch_id = 36;
 | 
			
		||||
  } else if (c >= 'a' && c <= 'z') {
 | 
			
		||||
    ch_id = c - 'a';
 | 
			
		||||
  } else if (c >= '0' && c <= '9') {
 | 
			
		||||
    ch_id = c - '0' + 26;
 | 
			
		||||
  }
 | 
			
		||||
  return ch_id;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int casesame_cstr(const char* a, const char* b)
 | 
			
		||||
{
 | 
			
		||||
  size_t len1 = strlen(a);
 | 
			
		||||
  size_t len2 = strlen(b);
 | 
			
		||||
  return (len1 == len2) && (strncasecmp(a, b, len1) == 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// return 0 if succ, return 1 if fail
 | 
			
		||||
int add_word(t_node* root, const char* str, const int32_t idx)
 | 
			
		||||
{
 | 
			
		||||
  int ret = 0;
 | 
			
		||||
  t_node* pt = root;
 | 
			
		||||
  if (OB_UNLIKELY(NULL == root)) {
 | 
			
		||||
    ret = 1;
 | 
			
		||||
    printf("ERROR root is NULL! \n");
 | 
			
		||||
  } else if (OB_UNLIKELY(NULL == str)) {
 | 
			
		||||
    ret = 1;
 | 
			
		||||
    printf("ERROR word str is NULL! \n");
 | 
			
		||||
  } else if (OB_UNLIKELY(idx < 0)) {
 | 
			
		||||
    printf("ERROR invalid idx:%d\n", idx);
 | 
			
		||||
  } else {
 | 
			
		||||
    for (; '\0' != *str && 0 == ret; ++str) {
 | 
			
		||||
      int32_t ch_id = get_next_id(*str);
 | 
			
		||||
      if (ch_id >= 0 && NULL == pt->next[ch_id]) {
 | 
			
		||||
        t_node* new_node = (t_node*)calloc(1, sizeof(t_node));
 | 
			
		||||
        if (OB_UNLIKELY(NULL == new_node)) {
 | 
			
		||||
          ret = 1;
 | 
			
		||||
          printf("ERROR malloc memory failed! \n");
 | 
			
		||||
        } else {
 | 
			
		||||
          new_node->idx = -1;
 | 
			
		||||
          pt->next[ch_id] = new_node;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      if (OB_LIKELY(0 == ret)) {
 | 
			
		||||
        if (OB_LIKELY(ch_id >= 0)) {
 | 
			
		||||
          pt = pt->next[ch_id];
 | 
			
		||||
        } else {
 | 
			
		||||
          printf("ERROR ob_non_reserved_keywords.c: wrong index! \n");
 | 
			
		||||
          ret = 1;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  if (0 == ret) {
 | 
			
		||||
    pt->idx = idx;
 | 
			
		||||
  }
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const NonReservedKeyword* find_word(const char* word, const t_node* root, const NonReservedKeyword* words)
 | 
			
		||||
{
 | 
			
		||||
  const NonReservedKeyword* res_word = NULL;
 | 
			
		||||
  const t_node* pt = root;
 | 
			
		||||
  if (OB_UNLIKELY(NULL == word)) {
 | 
			
		||||
    // do nothing
 | 
			
		||||
  } else {
 | 
			
		||||
    for (; *word != '\0' && NULL != pt; ++word) {
 | 
			
		||||
      char c = *word;
 | 
			
		||||
      int32_t ch_id = get_next_id(c);
 | 
			
		||||
      if (ch_id < 0) {
 | 
			
		||||
        pt = NULL;
 | 
			
		||||
      } else {
 | 
			
		||||
        pt = pt->next[ch_id];
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  if (OB_LIKELY(NULL != pt && -1 != pt->idx)) {
 | 
			
		||||
    res_word = &words[pt->idx];
 | 
			
		||||
  }
 | 
			
		||||
  return res_word;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// return 0 if succ, return 1 if fail
 | 
			
		||||
int create_trie_tree(const NonReservedKeyword* words, int32_t count, t_node** root)
 | 
			
		||||
{
 | 
			
		||||
  int ret = 0;
 | 
			
		||||
  if (OB_UNLIKELY(NULL == root)) {
 | 
			
		||||
    (void)printf("ERROR invalid root! \n");
 | 
			
		||||
    ret = 1;
 | 
			
		||||
  } else {
 | 
			
		||||
    *root = (t_node*)calloc(1, sizeof(t_node));
 | 
			
		||||
    if (OB_UNLIKELY(NULL == *root)) {
 | 
			
		||||
      (void)printf("ERROR malloc memory failed! \n");
 | 
			
		||||
      ret = 1;
 | 
			
		||||
    } else {
 | 
			
		||||
      (*root)->idx = -1;
 | 
			
		||||
      int32_t i = 0;
 | 
			
		||||
      for (; 0 == ret && i < count; ++i) {
 | 
			
		||||
        ret = add_word(*root, words[i].keyword_name, i);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										54
									
								
								src/sql/parser/ob_non_reserved_keywords.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								src/sql/parser/ob_non_reserved_keywords.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,54 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Copyright (c) 2021 OceanBase
 | 
			
		||||
 * OceanBase CE is licensed under Mulan PubL v2.
 | 
			
		||||
 * You can use this software according to the terms and conditions of the Mulan PubL v2.
 | 
			
		||||
 * You may obtain a copy of Mulan PubL v2 at:
 | 
			
		||||
 *          http://license.coscl.org.cn/MulanPubL-2.0
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 | 
			
		||||
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 | 
			
		||||
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 | 
			
		||||
 * See the Mulan PubL v2 for more details.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef OCEANBASE_SQL_PARSER_NON_RESERVED_KEYWORDS_
 | 
			
		||||
#define OCEANBASE_SQL_PARSER_NON_RESERVED_KEYWORDS_
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
#define LENGTH_OF(arr) (sizeof(arr) / sizeof(arr[0]))
 | 
			
		||||
#define CHAR_LEN 37  // sum of A-Z,0-9,_
 | 
			
		||||
 | 
			
		||||
typedef struct _NonReservedKeyword {
 | 
			
		||||
  const char* keyword_name;
 | 
			
		||||
  int keyword_type;
 | 
			
		||||
} NonReservedKeyword;
 | 
			
		||||
 | 
			
		||||
typedef NonReservedKeyword ReservedKeyword;
 | 
			
		||||
 | 
			
		||||
typedef struct trie_node {
 | 
			
		||||
  int32_t idx;
 | 
			
		||||
  struct trie_node* next[CHAR_LEN];
 | 
			
		||||
} t_node;
 | 
			
		||||
 | 
			
		||||
extern const NonReservedKeyword* mysql_non_reserved_keyword_lookup(const char* word);
 | 
			
		||||
extern const NonReservedKeyword* oracle_non_reserved_keyword_lookup(const char* word);
 | 
			
		||||
extern int mysql_sql_reserved_keyword_lookup(const char* word);
 | 
			
		||||
extern int oracle_sql_reserved_keyword_lookup(const char* word);
 | 
			
		||||
extern const ReservedKeyword* oracle_pl_reserved_keyword_lookup(const char* word);
 | 
			
		||||
extern const ReservedKeyword* oracle_reserved_keyword_lookup(const char* word);
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
extern int verify_non_reserved_keywords_order();
 | 
			
		||||
extern int create_trie_tree(const NonReservedKeyword* words, int32_t count, t_node** root);
 | 
			
		||||
extern int add_word(t_node* root, const char* str, const int32_t idx);
 | 
			
		||||
extern const NonReservedKeyword* find_word(const char* word, const t_node* root, const NonReservedKeyword* words);
 | 
			
		||||
extern int32_t get_next_id(char c);
 | 
			
		||||
extern int casesame_cstr(const char* a, const char* b);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /*OCEANBASE_SQL_PARSER_NON_RESERVED_KEYWORDS_*/
 | 
			
		||||
							
								
								
									
										473
									
								
								src/sql/parser/ob_parser.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										473
									
								
								src/sql/parser/ob_parser.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,473 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Copyright (c) 2021 OceanBase
 | 
			
		||||
 * OceanBase CE is licensed under Mulan PubL v2.
 | 
			
		||||
 * You can use this software according to the terms and conditions of the Mulan PubL v2.
 | 
			
		||||
 * You may obtain a copy of Mulan PubL v2 at:
 | 
			
		||||
 *          http://license.coscl.org.cn/MulanPubL-2.0
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 | 
			
		||||
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 | 
			
		||||
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 | 
			
		||||
 * See the Mulan PubL v2 for more details.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#define USING_LOG_PREFIX SQL_PARSER
 | 
			
		||||
#include "ob_parser.h"
 | 
			
		||||
#include "lib/oblog/ob_log.h"
 | 
			
		||||
#include "common/sql_mode/ob_sql_mode_utils.h"
 | 
			
		||||
#include "parse_malloc.h"
 | 
			
		||||
#include "parse_node.h"
 | 
			
		||||
#include "ob_sql_parser.h"
 | 
			
		||||
#include "share/ob_define.h"
 | 
			
		||||
using namespace oceanbase::sql;
 | 
			
		||||
using namespace oceanbase::common;
 | 
			
		||||
 | 
			
		||||
ObParser::ObParser(common::ObIAllocator& allocator, ObSQLMode mode, ObCollationType conn_collation)
 | 
			
		||||
    : allocator_(&allocator), sql_mode_(mode), connection_collation_(conn_collation)
 | 
			
		||||
{}
 | 
			
		||||
 | 
			
		||||
ObParser::~ObParser()
 | 
			
		||||
{}
 | 
			
		||||
 | 
			
		||||
#define ISSPACE(c) ((c) == ' ' || (c) == '\n' || (c) == '\r' || (c) == '\t' || (c) == '\f' || (c) == '\v')
 | 
			
		||||
 | 
			
		||||
bool ObParser::is_pl_stmt(const ObString& stmt, bool* is_create_func)
 | 
			
		||||
{
 | 
			
		||||
  UNUSED(stmt);
 | 
			
		||||
  UNUSED(is_create_func);
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool ObParser::is_single_stmt(const ObString& stmt)
 | 
			
		||||
{
 | 
			
		||||
  int64_t count = 0;
 | 
			
		||||
  int64_t end_trim_offset = stmt.length();
 | 
			
		||||
  while (end_trim_offset > 0 && ISSPACE(stmt[end_trim_offset - 1])) {
 | 
			
		||||
    end_trim_offset--;
 | 
			
		||||
  }
 | 
			
		||||
  for (int64_t i = 0; i < end_trim_offset; i++) {
 | 
			
		||||
    if (';' == stmt[i]) {
 | 
			
		||||
      count++;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return (0 == count || (1 == count && stmt[end_trim_offset - 1] == ';'));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// In multi-stmt mode(delimiter #) eg: create t1; create t2; create t3
 | 
			
		||||
// in the case of is_ret_first_stmt(false), queries will return the following stmts:
 | 
			
		||||
//      queries[0]: create t1; create t2; create t3;
 | 
			
		||||
//      queries[1]: create t2; create t3;
 | 
			
		||||
//      queries[2]: create t3;
 | 
			
		||||
// in the case of is_ret_first_stmt(true) and it will return one element
 | 
			
		||||
//      queries[0]: create t1;
 | 
			
		||||
// Actually, sql executor only executes the first stmt(create t1) and ignore the others
 | 
			
		||||
// even though try to execute stmts like 'create t1; create t2; create t3;'
 | 
			
		||||
int ObParser::split_multiple_stmt(
 | 
			
		||||
    const ObString& stmt, ObIArray<ObString>& queries, ObMPParseStat& parse_stat, bool is_ret_first_stmt)
 | 
			
		||||
{
 | 
			
		||||
  int ret = OB_SUCCESS;
 | 
			
		||||
 | 
			
		||||
  if (is_single_stmt(stmt) || is_pl_stmt(stmt)) {
 | 
			
		||||
    ObString query(stmt.length(), stmt.ptr());
 | 
			
		||||
    ret = queries.push_back(query);
 | 
			
		||||
  } else {
 | 
			
		||||
    ParseResult parse_result;
 | 
			
		||||
    ParseMode parse_mode = MULTI_MODE;
 | 
			
		||||
    int64_t offset = 0;
 | 
			
		||||
    int64_t remain = stmt.length();
 | 
			
		||||
 | 
			
		||||
    parse_stat.reset();
 | 
			
		||||
    while (remain > 0 && ISSPACE(stmt[remain - 1])) {
 | 
			
		||||
      --remain;
 | 
			
		||||
    }
 | 
			
		||||
    if (remain > 0 && '\0' == stmt[remain - 1]) {
 | 
			
		||||
      --remain;
 | 
			
		||||
    }
 | 
			
		||||
    while (remain > 0 && ISSPACE(stmt[remain - 1])) {
 | 
			
		||||
      --remain;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (OB_UNLIKELY(0 >= remain)) {
 | 
			
		||||
      ObString part;
 | 
			
		||||
      ret = queries.push_back(part);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int tmp_ret = OB_SUCCESS;
 | 
			
		||||
    while (remain > 0 && OB_SUCC(ret) && !parse_stat.parse_fail_) {
 | 
			
		||||
      ObArenaAllocator allocator(CURRENT_CONTEXT.get_malloc_allocator());
 | 
			
		||||
      allocator.set_label("SplitMultiStmt");
 | 
			
		||||
      ObIAllocator* bak_allocator = allocator_;
 | 
			
		||||
      allocator_ = &allocator;
 | 
			
		||||
      ObString part(remain, stmt.ptr() + offset);
 | 
			
		||||
      if (OB_SUCC(tmp_ret = parse(part, parse_result, parse_mode))) {
 | 
			
		||||
        // length: length of the remainer statements
 | 
			
		||||
        // size: length of the single statement
 | 
			
		||||
        int32_t single_stmt_length = parse_result.end_col_;
 | 
			
		||||
        if ((!is_ret_first_stmt) && (';' == *(stmt.ptr() + offset + parse_result.end_col_ - 1))) {
 | 
			
		||||
          --single_stmt_length;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (is_ret_first_stmt) {
 | 
			
		||||
          ObString first_query(single_stmt_length, stmt.ptr());
 | 
			
		||||
          ret = queries.push_back(first_query);
 | 
			
		||||
          break;  // only return the first stmt, so ignore the remaining stmts
 | 
			
		||||
        } else {
 | 
			
		||||
          ObString query(single_stmt_length, static_cast<int32_t>(remain), stmt.ptr() + offset);
 | 
			
		||||
          ret = queries.push_back(query);
 | 
			
		||||
        }
 | 
			
		||||
        remain -= parse_result.end_col_;
 | 
			
		||||
        offset += parse_result.end_col_;
 | 
			
		||||
        if (remain < 0 || offset > stmt.length()) {
 | 
			
		||||
          LOG_ERROR("split_multiple_stmt data error", K(remain), K(offset), K(stmt.length()), K(ret));
 | 
			
		||||
        }
 | 
			
		||||
      } else {
 | 
			
		||||
        int32_t single_stmt_length = parse_result.end_col_;
 | 
			
		||||
        if (';' == *(stmt.ptr() + offset + parse_result.end_col_ - 1)) {
 | 
			
		||||
          --single_stmt_length;
 | 
			
		||||
        }
 | 
			
		||||
        ObString query(single_stmt_length, static_cast<int32_t>(remain), stmt.ptr() + offset);
 | 
			
		||||
        ret = queries.push_back(query);
 | 
			
		||||
        if (OB_SUCCESS == ret) {
 | 
			
		||||
          parse_stat.parse_fail_ = true;
 | 
			
		||||
          parse_stat.fail_query_idx_ = queries.count() - 1;
 | 
			
		||||
          parse_stat.fail_ret_ = tmp_ret;
 | 
			
		||||
        }
 | 
			
		||||
        LOG_WARN("fail parse multi part", K(part), K(stmt), K(ret));
 | 
			
		||||
      }
 | 
			
		||||
      allocator_ = bak_allocator;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int ObParser::parse_sql(const ObString& stmt, ParseResult& parse_result)
 | 
			
		||||
{
 | 
			
		||||
  int ret = OB_SUCCESS;
 | 
			
		||||
  ObSQLParser sql_parser(*(ObIAllocator*)(parse_result.malloc_pool_), sql_mode_);
 | 
			
		||||
  if (OB_FAIL(sql_parser.parse(stmt.ptr(), stmt.length(), parse_result))) {
 | 
			
		||||
    LOG_INFO("failed to parse stmt as sql", K(stmt), K(ret));
 | 
			
		||||
  } else if (parse_result.is_dynamic_sql_) {
 | 
			
		||||
    memmove(parse_result.no_param_sql_ + parse_result.no_param_sql_len_,
 | 
			
		||||
        parse_result.input_sql_ + parse_result.pl_parse_info_.last_pl_symbol_pos_,
 | 
			
		||||
        parse_result.input_sql_len_ - parse_result.pl_parse_info_.last_pl_symbol_pos_);
 | 
			
		||||
    parse_result.no_param_sql_len_ += parse_result.input_sql_len_ - parse_result.pl_parse_info_.last_pl_symbol_pos_;
 | 
			
		||||
  } else { /*do nothing*/
 | 
			
		||||
  }
 | 
			
		||||
  if (parse_result.is_fp_ || parse_result.is_multi_query_) {
 | 
			
		||||
    if (OB_FAIL(ret)) {
 | 
			
		||||
      LOG_WARN("failed to fast parameterize", K(stmt), K(ret));
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  if (OB_FAIL(ret)) {
 | 
			
		||||
    auto err_charge_sql_mode = lib::is_oracle_mode();
 | 
			
		||||
    LOG_WARN("failed to parse the statement",
 | 
			
		||||
        K(stmt),
 | 
			
		||||
        K(parse_result.is_fp_),
 | 
			
		||||
        K(parse_result.is_multi_query_),
 | 
			
		||||
        K(parse_result.yyscan_info_),
 | 
			
		||||
        K(parse_result.result_tree_),
 | 
			
		||||
        K(parse_result.malloc_pool_),
 | 
			
		||||
        "message",
 | 
			
		||||
        parse_result.error_msg_,
 | 
			
		||||
        "start_col",
 | 
			
		||||
        parse_result.start_col_,
 | 
			
		||||
        "end_col",
 | 
			
		||||
        parse_result.end_col_,
 | 
			
		||||
        K(parse_result.line_),
 | 
			
		||||
        K(parse_result.yycolumn_),
 | 
			
		||||
        K(parse_result.yylineno_),
 | 
			
		||||
        K(parse_result.extra_errno_),
 | 
			
		||||
        K(err_charge_sql_mode),
 | 
			
		||||
        K(sql_mode_),
 | 
			
		||||
        K(parse_result.sql_mode_),
 | 
			
		||||
        K(parse_result.may_bool_value_),
 | 
			
		||||
        K(ret));
 | 
			
		||||
 | 
			
		||||
    static const int32_t max_error_length = 80;
 | 
			
		||||
    int32_t error_length = std::min(stmt.length() - (parse_result.start_col_ - 1), max_error_length);
 | 
			
		||||
 | 
			
		||||
    if (OB_ERR_PARSE_SQL == ret) {
 | 
			
		||||
      LOG_USER_ERROR(OB_ERR_PARSE_SQL,
 | 
			
		||||
          ob_errpkt_strerror(OB_ERR_PARSER_SYNTAX, false),
 | 
			
		||||
          error_length,
 | 
			
		||||
          stmt.ptr() + parse_result.start_col_ - 1,
 | 
			
		||||
          parse_result.line_ + 1);
 | 
			
		||||
    } else {
 | 
			
		||||
      // other errors handle outer side.
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int ObParser::parse(
 | 
			
		||||
    const ObString& query, ParseResult& parse_result, ParseMode parse_mode, const bool is_batched_multi_stmt_split_on)
 | 
			
		||||
{
 | 
			
		||||
  int ret = OB_SUCCESS;
 | 
			
		||||
 | 
			
		||||
  int64_t len = query.length();
 | 
			
		||||
  while (len > 0 && ISSPACE(query[len - 1])) {
 | 
			
		||||
    --len;
 | 
			
		||||
  }
 | 
			
		||||
  if (MULTI_MODE != parse_mode) {
 | 
			
		||||
    if (len > 0 && '\0' == query[len - 1]) {
 | 
			
		||||
      --len;
 | 
			
		||||
    }
 | 
			
		||||
    while (len > 0 && ISSPACE(query[len - 1])) {
 | 
			
		||||
      --len;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const ObString stmt(len, query.ptr());
 | 
			
		||||
  parse_reset(&parse_result);
 | 
			
		||||
  parse_result.is_fp_ = (FP_MODE == parse_mode || FP_PARAMERIZE_AND_FILTER_HINT_MODE == parse_mode ||
 | 
			
		||||
                         FP_NO_PARAMERIZE_AND_FILTER_HINT_MODE == parse_mode);
 | 
			
		||||
  parse_result.is_multi_query_ = (MULTI_MODE == parse_mode);
 | 
			
		||||
  parse_result.malloc_pool_ = allocator_;
 | 
			
		||||
  parse_result.sql_mode_ = sql_mode_;
 | 
			
		||||
  parse_result.is_ignore_hint_ =
 | 
			
		||||
      (FP_PARAMERIZE_AND_FILTER_HINT_MODE == parse_mode || FP_NO_PARAMERIZE_AND_FILTER_HINT_MODE == parse_mode);
 | 
			
		||||
  parse_result.is_ignore_token_ = false;
 | 
			
		||||
  parse_result.need_parameterize_ = (FP_MODE == parse_mode || FP_PARAMERIZE_AND_FILTER_HINT_MODE == parse_mode);
 | 
			
		||||
  parse_result.pl_parse_info_.is_pl_parse_ = false;
 | 
			
		||||
  parse_result.minus_ctx_.has_minus_ = false;
 | 
			
		||||
  parse_result.minus_ctx_.pos_ = -1;
 | 
			
		||||
  parse_result.minus_ctx_.raw_sql_offset_ = -1;
 | 
			
		||||
  parse_result.is_for_trigger_ = (TRIGGER_MODE == parse_mode);
 | 
			
		||||
  parse_result.is_dynamic_sql_ = (DYNAMIC_SQL_MODE == parse_mode);
 | 
			
		||||
  parse_result.is_dbms_sql_ = (DBMS_SQL_MODE == parse_mode);
 | 
			
		||||
  parse_result.is_batched_multi_enabled_split_ = is_batched_multi_stmt_split_on;
 | 
			
		||||
  parse_result.charset_info_ = ObCharset::get_charset(connection_collation_);
 | 
			
		||||
  parse_result.is_not_utf8_connection_ =
 | 
			
		||||
      ObCharset::is_valid_collation(connection_collation_)
 | 
			
		||||
          ? (ObCharset::charset_type_by_coll(connection_collation_) != CHARSET_UTF8MB4)
 | 
			
		||||
          : false;
 | 
			
		||||
 | 
			
		||||
  if (parse_result.is_fp_ || parse_result.is_dynamic_sql_) {
 | 
			
		||||
    int64_t new_length = parse_result.is_fp_ ? stmt.length() + 1 : stmt.length() * 2;
 | 
			
		||||
    char* buf = (char*)parse_malloc(new_length, parse_result.malloc_pool_);
 | 
			
		||||
    if (OB_UNLIKELY(NULL == buf)) {
 | 
			
		||||
      ret = OB_ALLOCATE_MEMORY_FAILED;
 | 
			
		||||
      LOG_ERROR("no memory for parser");
 | 
			
		||||
    } else {
 | 
			
		||||
      parse_result.param_nodes_ = NULL;
 | 
			
		||||
      parse_result.tail_param_node_ = NULL;
 | 
			
		||||
      parse_result.no_param_sql_ = buf;
 | 
			
		||||
      parse_result.no_param_sql_buf_len_ = stmt.length() + 1;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  if (OB_SUCC(ret) && OB_ISNULL(parse_result.charset_info_)) {
 | 
			
		||||
    ret = OB_ERR_UNEXPECTED;
 | 
			
		||||
    LOG_WARN("charset info is null", K(ret), "connection charset", ObCharset::charset_name(connection_collation_));
 | 
			
		||||
  } else {
 | 
			
		||||
    LOG_DEBUG("check parse_result param", "connection charset", ObCharset::charset_name(connection_collation_));
 | 
			
		||||
  }
 | 
			
		||||
  if (OB_SUCC(ret)) {
 | 
			
		||||
    if (OB_FAIL(parse_sql(stmt, parse_result))) {
 | 
			
		||||
      LOG_WARN("failed to parse stmt as sql", K(stmt), K(parse_mode), K(ret));
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int ObParser::prepare_parse(const ObString& query, void* ns, ParseResult& parse_result)
 | 
			
		||||
{
 | 
			
		||||
  int ret = OB_SUCCESS;
 | 
			
		||||
 | 
			
		||||
  int64_t len = query.length();
 | 
			
		||||
  while (len > 0 && ISSPACE(query[len - 1])) {
 | 
			
		||||
    --len;
 | 
			
		||||
  }
 | 
			
		||||
  if (len > 0 && '\0' == query[len - 1]) {
 | 
			
		||||
    --len;
 | 
			
		||||
  }
 | 
			
		||||
  while (len > 0 && ISSPACE(query[len - 1])) {
 | 
			
		||||
    --len;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const ObString stmt(len, query.ptr());
 | 
			
		||||
 | 
			
		||||
  memset(&parse_result, 0, sizeof(ParseResult));
 | 
			
		||||
  parse_result.pl_parse_info_.pl_ns_ = ns;
 | 
			
		||||
  parse_result.malloc_pool_ = allocator_;
 | 
			
		||||
  parse_result.sql_mode_ = sql_mode_;
 | 
			
		||||
  parse_result.pl_parse_info_.is_pl_parse_ = true;
 | 
			
		||||
  parse_result.pl_parse_info_.is_pl_parse_expr_ = false;
 | 
			
		||||
  char* buf = (char*)parse_malloc(stmt.length() * 2, parse_result.malloc_pool_);
 | 
			
		||||
  if (OB_UNLIKELY(NULL == buf)) {
 | 
			
		||||
    ret = OB_ALLOCATE_MEMORY_FAILED;
 | 
			
		||||
    LOG_WARN("no memory for parser");
 | 
			
		||||
  } else {
 | 
			
		||||
    parse_result.param_nodes_ = NULL;
 | 
			
		||||
    parse_result.tail_param_node_ = NULL;
 | 
			
		||||
    parse_result.no_param_sql_ = buf;
 | 
			
		||||
    parse_result.no_param_sql_buf_len_ = stmt.length() * 2;
 | 
			
		||||
    parse_result.may_bool_value_ = false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (OB_SUCC(ret)) {
 | 
			
		||||
    ObSQLParser sql_parser(*(ObIAllocator*)(parse_result.malloc_pool_), sql_mode_);
 | 
			
		||||
    if (OB_FAIL(sql_parser.parse(stmt.ptr(), stmt.length(), parse_result))) {
 | 
			
		||||
      LOG_WARN("failed to parse the statement",
 | 
			
		||||
          K(parse_result.yyscan_info_),
 | 
			
		||||
          K(parse_result.result_tree_),
 | 
			
		||||
          K(parse_result.malloc_pool_),
 | 
			
		||||
          "message",
 | 
			
		||||
          parse_result.error_msg_,
 | 
			
		||||
          "start_col",
 | 
			
		||||
          parse_result.start_col_,
 | 
			
		||||
          "end_col",
 | 
			
		||||
          parse_result.end_col_,
 | 
			
		||||
          K(parse_result.line_),
 | 
			
		||||
          K(parse_result.yycolumn_),
 | 
			
		||||
          K(parse_result.yylineno_),
 | 
			
		||||
          K(parse_result.extra_errno_));
 | 
			
		||||
 | 
			
		||||
      static const int32_t max_error_length = 80;
 | 
			
		||||
      int32_t error_length = std::min(stmt.length() - (parse_result.start_col_ - 1), max_error_length);
 | 
			
		||||
      if (OB_ERR_PARSE_SQL == ret) {
 | 
			
		||||
        LOG_USER_ERROR(OB_ERR_PARSE_SQL,
 | 
			
		||||
            ob_errpkt_strerror(OB_ERR_PARSER_SYNTAX, false),
 | 
			
		||||
            error_length,
 | 
			
		||||
            stmt.ptr() + parse_result.start_col_ - 1,
 | 
			
		||||
            parse_result.line_ + 1);
 | 
			
		||||
      } else {
 | 
			
		||||
        // other errors handle outer side.
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      memmove(parse_result.no_param_sql_ + parse_result.no_param_sql_len_,
 | 
			
		||||
          parse_result.input_sql_ + parse_result.pl_parse_info_.last_pl_symbol_pos_,
 | 
			
		||||
          parse_result.input_sql_len_ - parse_result.pl_parse_info_.last_pl_symbol_pos_);
 | 
			
		||||
      parse_result.no_param_sql_len_ += parse_result.input_sql_len_ - parse_result.pl_parse_info_.last_pl_symbol_pos_;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int ObParser::pre_parse(const common::ObString& stmt, PreParseResult& res)
 | 
			
		||||
{
 | 
			
		||||
  int ret = OB_SUCCESS;
 | 
			
		||||
  // /*tracd_id=xxx*/
 | 
			
		||||
  int64_t len = stmt.length();
 | 
			
		||||
  if (len <= 13) {
 | 
			
		||||
    // do_nothing
 | 
			
		||||
  } else {
 | 
			
		||||
    int32_t pos = 0;
 | 
			
		||||
    const char* ptr = stmt.ptr();
 | 
			
		||||
    while (pos < len && is_space(ptr[pos])) {
 | 
			
		||||
      pos++;
 | 
			
		||||
    };
 | 
			
		||||
    if (pos + 2 < len && ptr[pos++] == '/' && ptr[pos++] == '*') {  // start with '/*'
 | 
			
		||||
      char expect_char = 't';
 | 
			
		||||
      bool find_trace = false;
 | 
			
		||||
      while (!find_trace && pos < len) {
 | 
			
		||||
        if (pos < len && ptr[pos] == '*') {
 | 
			
		||||
          expect_char = 't';
 | 
			
		||||
          if (++pos < len && ptr[pos] == '/') {
 | 
			
		||||
            break;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        if (pos >= len) {
 | 
			
		||||
          break;
 | 
			
		||||
        } else if (ptr[pos] == expect_char ||
 | 
			
		||||
                   (expect_char != '_' && expect_char != '=' && ptr[pos] == expect_char - 32)) {
 | 
			
		||||
          switch (expect_char) {
 | 
			
		||||
            case 't': {
 | 
			
		||||
              expect_char = 'r';
 | 
			
		||||
              break;
 | 
			
		||||
            }
 | 
			
		||||
            case 'r': {
 | 
			
		||||
              expect_char = 'a';
 | 
			
		||||
              break;
 | 
			
		||||
            }
 | 
			
		||||
            case 'a': {
 | 
			
		||||
              expect_char = 'c';
 | 
			
		||||
              break;
 | 
			
		||||
            }
 | 
			
		||||
            case 'c': {
 | 
			
		||||
              expect_char = 'e';
 | 
			
		||||
              break;
 | 
			
		||||
            }
 | 
			
		||||
            case 'e': {
 | 
			
		||||
              expect_char = '_';
 | 
			
		||||
              break;
 | 
			
		||||
            }
 | 
			
		||||
            case '_': {
 | 
			
		||||
              expect_char = 'i';
 | 
			
		||||
              break;
 | 
			
		||||
            }
 | 
			
		||||
            case 'i': {
 | 
			
		||||
              expect_char = 'd';
 | 
			
		||||
              break;
 | 
			
		||||
            }
 | 
			
		||||
            case 'd': {
 | 
			
		||||
              expect_char = '=';
 | 
			
		||||
              break;
 | 
			
		||||
            }
 | 
			
		||||
            case '=': {
 | 
			
		||||
              find_trace = true;
 | 
			
		||||
              break;
 | 
			
		||||
            }
 | 
			
		||||
            default: {
 | 
			
		||||
              // do nothing
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        } else {
 | 
			
		||||
          expect_char = 't';
 | 
			
		||||
        }
 | 
			
		||||
        pos++;
 | 
			
		||||
      }
 | 
			
		||||
      if (find_trace) {
 | 
			
		||||
        scan_trace_id(ptr, len, pos, res.trace_id_);
 | 
			
		||||
      }
 | 
			
		||||
    } else {  // not start with '/*'
 | 
			
		||||
      // do nothing
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int ObParser::scan_trace_id(const char* ptr, int64_t len, int32_t& pos, ObString& trace_id)
 | 
			
		||||
{
 | 
			
		||||
  int ret = OB_SUCCESS;
 | 
			
		||||
  trace_id.reset();
 | 
			
		||||
  int32_t start = pos;
 | 
			
		||||
  int32_t end = pos;
 | 
			
		||||
  while (pos < len && !is_trace_id_end(ptr[pos])) {
 | 
			
		||||
    pos++;
 | 
			
		||||
  }
 | 
			
		||||
  end = pos;
 | 
			
		||||
  if (start < end) {
 | 
			
		||||
    while (pos < len) {
 | 
			
		||||
      if (pos < len && ptr[pos] == '*') {
 | 
			
		||||
        if (++pos < len && ptr[pos] == '/') {
 | 
			
		||||
          int32_t trace_id_len = std::min(static_cast<int32_t>(OB_MAX_TRACE_ID_BUFFER_SIZE), end - start);
 | 
			
		||||
          trace_id.assign_ptr(ptr + start, trace_id_len);
 | 
			
		||||
          break;
 | 
			
		||||
        }
 | 
			
		||||
      } else {
 | 
			
		||||
        pos++;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool ObParser::is_space(char ch)
 | 
			
		||||
{
 | 
			
		||||
  return ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r' || ch == '\f';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool ObParser::is_trace_id_end(char ch)
 | 
			
		||||
{
 | 
			
		||||
  return is_space(ch) || ch == ',' || ch == '*';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ObParser::free_result(ParseResult& parse_result)
 | 
			
		||||
{
 | 
			
		||||
  UNUSED(parse_result);
 | 
			
		||||
  //  destroy_tree(parse_result.result_tree_);
 | 
			
		||||
  //  parse_terminate(&parse_result);
 | 
			
		||||
  //  parse_result.yyscan_info_ = NULL;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										102
									
								
								src/sql/parser/ob_parser.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								src/sql/parser/ob_parser.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,102 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Copyright (c) 2021 OceanBase
 | 
			
		||||
 * OceanBase CE is licensed under Mulan PubL v2.
 | 
			
		||||
 * You can use this software according to the terms and conditions of the Mulan PubL v2.
 | 
			
		||||
 * You may obtain a copy of Mulan PubL v2 at:
 | 
			
		||||
 *          http://license.coscl.org.cn/MulanPubL-2.0
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 | 
			
		||||
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 | 
			
		||||
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 | 
			
		||||
 * See the Mulan PubL v2 for more details.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _OB_PARSER_H
 | 
			
		||||
#define _OB_PARSER_H 1
 | 
			
		||||
#include "sql/parser/parse_node.h"
 | 
			
		||||
#include "sql/parser/parse_define.h"
 | 
			
		||||
#include "lib/allocator/ob_allocator.h"
 | 
			
		||||
#include "lib/container/ob_iarray.h"
 | 
			
		||||
#include "lib/string/ob_string.h"
 | 
			
		||||
#include "lib/charset/ob_charset.h"
 | 
			
		||||
#include "sql/parser/ob_parser_utils.h"
 | 
			
		||||
 | 
			
		||||
namespace oceanbase {
 | 
			
		||||
namespace sql {
 | 
			
		||||
 | 
			
		||||
struct ObMPParseStat {
 | 
			
		||||
  public:
 | 
			
		||||
  ObMPParseStat() : parse_fail_(false), fail_ret_(common::OB_SUCCESS), fail_query_idx_(-1)
 | 
			
		||||
  {}
 | 
			
		||||
  void reset()
 | 
			
		||||
  {
 | 
			
		||||
    parse_fail_ = false;
 | 
			
		||||
    fail_ret_ = common::OB_SUCCESS;
 | 
			
		||||
    fail_query_idx_ = -1;
 | 
			
		||||
  }
 | 
			
		||||
  bool parse_fail_;
 | 
			
		||||
  int fail_ret_;
 | 
			
		||||
  int64_t fail_query_idx_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct PreParseResult {
 | 
			
		||||
  common::ObString trace_id_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class ObParser {
 | 
			
		||||
  public:
 | 
			
		||||
  explicit ObParser(common::ObIAllocator& allocator, ObSQLMode mode,
 | 
			
		||||
      common::ObCollationType conn_collation = common::CS_TYPE_UTF8MB4_GENERAL_CI);
 | 
			
		||||
  virtual ~ObParser();
 | 
			
		||||
  /// @param queries Note that all three members of ObString is valid, size() is the length
 | 
			
		||||
  ///                of the single statement, length() is the length of remainer statements
 | 
			
		||||
  static bool is_pl_stmt(const common::ObString& stmt, bool* is_create_func = NULL);
 | 
			
		||||
  bool is_single_stmt(const common::ObString& stmt);
 | 
			
		||||
  int split_multiple_stmt(const common::ObString& stmt, common::ObIArray<common::ObString>& queries,
 | 
			
		||||
      ObMPParseStat& parse_fail, bool is_ret_first_stmt = false);
 | 
			
		||||
  int parse_sql(const common::ObString& stmt, ParseResult& parse_result);
 | 
			
		||||
 | 
			
		||||
  virtual int parse(const common::ObString& stmt, ParseResult& parse_result, ParseMode mode = STD_MODE,
 | 
			
		||||
      const bool is_batched_multi_stmt_split_on = false);
 | 
			
		||||
 | 
			
		||||
  virtual void free_result(ParseResult& parse_result);
 | 
			
		||||
  /**
 | 
			
		||||
   * @brief  The parse interface for prepare
 | 
			
		||||
   * @param [in] query      - To be parsed statement
 | 
			
		||||
   * @param [in] ns      - External namespace
 | 
			
		||||
   * @param [out] parse_result  - parse result
 | 
			
		||||
   * @retval OB_SUCCESS execute success
 | 
			
		||||
   * @retval OB_SOME_ERROR special errno need to handle
 | 
			
		||||
   *
 | 
			
		||||
   * Compared with general prepare, the external name space is passed in and the redundant process
 | 
			
		||||
   * that this path will not go to is simplified. The main idea is that in the process of parser,
 | 
			
		||||
   * whenever you encounter a variable in sql, try to find it in the pl namespace. If you can find
 | 
			
		||||
   * it, copy the SQL statement before this variable and rewrite this variable as question mark,Also
 | 
			
		||||
   * record this variable.At the same time, all objects (tables, views, functions) encountered are
 | 
			
		||||
   * also recorded.
 | 
			
		||||
   *
 | 
			
		||||
   */
 | 
			
		||||
  int prepare_parse(const common::ObString& query, void* ns, ParseResult& parse_result);
 | 
			
		||||
  static int pre_parse(const common::ObString& stmt, PreParseResult& res);
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
  static int scan_trace_id(const char* ptr, int64_t len, int32_t& pos, common::ObString& trace_id);
 | 
			
		||||
  static bool is_trace_id_end(char ch);
 | 
			
		||||
  static bool is_space(char ch);
 | 
			
		||||
  // types and constants
 | 
			
		||||
  private:
 | 
			
		||||
  // disallow copy
 | 
			
		||||
  DISALLOW_COPY_AND_ASSIGN(ObParser);
 | 
			
		||||
  // function members
 | 
			
		||||
  private:
 | 
			
		||||
  // data members
 | 
			
		||||
  common::ObIAllocator* allocator_;
 | 
			
		||||
  // when sql_mode = "ANSI_QUOTES", Treat " as an identifier quote character
 | 
			
		||||
  // we don't use it in parser now
 | 
			
		||||
  ObSQLMode sql_mode_;
 | 
			
		||||
  common::ObCollationType connection_collation_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // end namespace sql
 | 
			
		||||
}  // end namespace oceanbase
 | 
			
		||||
 | 
			
		||||
#endif /* _OB_PARSER_H */
 | 
			
		||||
							
								
								
									
										139
									
								
								src/sql/parser/ob_parser_utils.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										139
									
								
								src/sql/parser/ob_parser_utils.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,139 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Copyright (c) 2021 OceanBase
 | 
			
		||||
 * OceanBase CE is licensed under Mulan PubL v2.
 | 
			
		||||
 * You can use this software according to the terms and conditions of the Mulan PubL v2.
 | 
			
		||||
 * You may obtain a copy of Mulan PubL v2 at:
 | 
			
		||||
 *          http://license.coscl.org.cn/MulanPubL-2.0
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 | 
			
		||||
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 | 
			
		||||
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 | 
			
		||||
 * See the Mulan PubL v2 for more details.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _OB_PARSER_UTILS_H
 | 
			
		||||
#define _OB_PARSER_UTILS_H 1
 | 
			
		||||
#include "lib/utility/ob_print_utils.h"
 | 
			
		||||
#include "sql/parser/parse_node.h"
 | 
			
		||||
#include "lib/ob_name_def.h"
 | 
			
		||||
const char* get_type_name(int type);
 | 
			
		||||
 | 
			
		||||
namespace oceanbase {
 | 
			
		||||
namespace sql {
 | 
			
		||||
inline void databuff_print_stmt_location(char* buf, int64_t buf_len, int64_t& pos, const ObStmtLoc& obj)
 | 
			
		||||
{
 | 
			
		||||
  if (obj.first_column_ > 0 || obj.last_column_ > 0 || obj.first_line_ > 0 || obj.last_line_ > 0) {
 | 
			
		||||
    J_COMMA();
 | 
			
		||||
    int first_line = obj.first_line_;
 | 
			
		||||
    int last_line = obj.last_line_;
 | 
			
		||||
    int first_column = obj.first_column_;
 | 
			
		||||
    int last_column = obj.last_column_;
 | 
			
		||||
    J_KV(K(first_line), K(last_line), K(first_column), K(last_column));
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void databuff_print_obj(char* buf, const int64_t buf_len, int64_t& pos, const ParseNode& obj)
 | 
			
		||||
{
 | 
			
		||||
  J_OBJ_START();
 | 
			
		||||
  J_KV(N_TYPE,
 | 
			
		||||
      get_type_name(obj.type_),
 | 
			
		||||
      N_INT_VALUE,
 | 
			
		||||
      obj.value_,
 | 
			
		||||
      N_STR_VALUE_LEN,
 | 
			
		||||
      obj.str_len_,
 | 
			
		||||
      N_STR_VALUE,
 | 
			
		||||
      common::ObString(obj.str_len_, obj.str_value_));
 | 
			
		||||
  databuff_print_stmt_location(buf, buf_len, pos, obj.stmt_loc_);
 | 
			
		||||
  if (0 < obj.num_child_) {
 | 
			
		||||
    J_COMMA();
 | 
			
		||||
    J_NAME(N_CHILDREN);
 | 
			
		||||
    J_COLON();
 | 
			
		||||
 | 
			
		||||
    J_ARRAY_START();
 | 
			
		||||
 | 
			
		||||
    for (int64_t i = 0; i < obj.num_child_; ++i) {
 | 
			
		||||
      if (NULL == obj.children_[i]) {
 | 
			
		||||
        J_EMPTY_OBJ();
 | 
			
		||||
      } else {
 | 
			
		||||
        databuff_print_obj(buf, buf_len, pos, *obj.children_[i]);
 | 
			
		||||
      }
 | 
			
		||||
      if (i != obj.num_child_ - 1) {
 | 
			
		||||
        common::databuff_printf(buf, buf_len, pos, ", ");
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    J_ARRAY_END();
 | 
			
		||||
  }
 | 
			
		||||
  J_OBJ_END();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void print_indent(char* buf, const int64_t buf_len, int64_t& pos, const int level)
 | 
			
		||||
{
 | 
			
		||||
  for (int i = 0; i < level; ++i) {
 | 
			
		||||
    common::databuff_printf(buf, buf_len, pos, "\t");
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void databuff_simple_print_obj(
 | 
			
		||||
    char* buf, const int64_t buf_len, const int64_t index, int64_t& pos, const ParseNode* obj, int level)
 | 
			
		||||
{
 | 
			
		||||
  print_indent(buf, buf_len, pos, level);
 | 
			
		||||
  if (NULL != obj) {
 | 
			
		||||
    common::databuff_printf(buf,
 | 
			
		||||
        buf_len,
 | 
			
		||||
        pos,
 | 
			
		||||
        "|--[%ld],[%s], str_value_=[%.*s], value=[%ld]\n",
 | 
			
		||||
        index,
 | 
			
		||||
        get_type_name(obj->type_),
 | 
			
		||||
        int32_t(obj->str_len_),
 | 
			
		||||
        obj->str_value_,
 | 
			
		||||
        obj->value_);
 | 
			
		||||
  } else {
 | 
			
		||||
    common::databuff_printf(buf, buf_len, pos, "|--[%ld]\n", index);
 | 
			
		||||
  }
 | 
			
		||||
  for (int64_t i = 0; i < obj->num_child_; ++i) {
 | 
			
		||||
    if (NULL != obj->children_[i]) {
 | 
			
		||||
      databuff_simple_print_obj(buf, buf_len, i, pos, obj->children_[i], level + 1);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class ObParserResultTreePrintWrapper {
 | 
			
		||||
  public:
 | 
			
		||||
  explicit ObParserResultTreePrintWrapper(const ParseNode& parse_tree) : parse_tree_(parse_tree)
 | 
			
		||||
  {}
 | 
			
		||||
  int64_t to_string(char* buf, const int64_t buf_len) const
 | 
			
		||||
  {
 | 
			
		||||
    int64_t pos = 0;
 | 
			
		||||
    common::databuff_printf(buf, buf_len, pos, "\n");
 | 
			
		||||
    databuff_simple_print_obj(buf, buf_len, 0, pos, &parse_tree_, 0);
 | 
			
		||||
    return pos;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
  DISALLOW_COPY_AND_ASSIGN(ObParserResultTreePrintWrapper);
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
  const ParseNode& parse_tree_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class ObParserResultPrintWrapper {
 | 
			
		||||
  public:
 | 
			
		||||
  explicit ObParserResultPrintWrapper(const ParseNode& parse_tree) : parse_tree_(parse_tree)
 | 
			
		||||
  {}
 | 
			
		||||
  int64_t to_string(char* buf, const int64_t buf_len) const
 | 
			
		||||
  {
 | 
			
		||||
    int64_t pos = 0;
 | 
			
		||||
    databuff_print_obj(buf, buf_len, pos, parse_tree_);
 | 
			
		||||
    return pos;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
  DISALLOW_COPY_AND_ASSIGN(ObParserResultPrintWrapper);
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
  const ParseNode& parse_tree_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // end namespace sql
 | 
			
		||||
}  // end namespace oceanbase
 | 
			
		||||
 | 
			
		||||
#endif /* _OB_PARSER_UTILS_H */
 | 
			
		||||
							
								
								
									
										97
									
								
								src/sql/parser/ob_sql_parser.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								src/sql/parser/ob_sql_parser.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,97 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Copyright (c) 2021 OceanBase
 | 
			
		||||
 * OceanBase CE is licensed under Mulan PubL v2.
 | 
			
		||||
 * You can use this software according to the terms and conditions of the Mulan PubL v2.
 | 
			
		||||
 * You may obtain a copy of Mulan PubL v2 at:
 | 
			
		||||
 *          http://license.coscl.org.cn/MulanPubL-2.0
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 | 
			
		||||
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 | 
			
		||||
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 | 
			
		||||
 * See the Mulan PubL v2 for more details.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#define USING_LOG_PREFIX SQL
 | 
			
		||||
 | 
			
		||||
#include "ob_sql_parser.h"
 | 
			
		||||
#include "sql/parser/parse_node.h"
 | 
			
		||||
#include "sql/parser/parse_malloc.h"
 | 
			
		||||
#include "share/ob_errno.h"
 | 
			
		||||
#include "lib/utility/ob_macro_utils.h"
 | 
			
		||||
#include "sql/parser/parser_utility.h"
 | 
			
		||||
#include <openssl/md5.h>
 | 
			
		||||
 | 
			
		||||
namespace oceanbase {
 | 
			
		||||
using namespace common;
 | 
			
		||||
namespace sql {
 | 
			
		||||
int ObSQLParser::parse(const char* str_ptr, const int64_t str_len, ParseResult& result)
 | 
			
		||||
{
 | 
			
		||||
  int ret = OB_SUCCESS;
 | 
			
		||||
  if (0 != parse_init(&result)) {
 | 
			
		||||
    ret = OB_ERR_PARSER_INIT;
 | 
			
		||||
  } else {
 | 
			
		||||
    ret = parse_sql(&result, str_ptr, static_cast<size_t>(str_len));
 | 
			
		||||
  }
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int ObSQLParser::parse_and_gen_sqlid(
 | 
			
		||||
    void* malloc_pool, const char* str_ptr, const int64_t str_len, const int64_t len, char* sql_id)
 | 
			
		||||
{
 | 
			
		||||
  int ret = OB_SUCCESS;
 | 
			
		||||
  ParseResult* parse_result = (ParseResult*)parse_malloc(sizeof(ParseResult), malloc_pool);
 | 
			
		||||
  if (OB_ISNULL(parse_result)) {
 | 
			
		||||
    ret = OB_ALLOCATE_MEMORY_FAILED;
 | 
			
		||||
  } else {
 | 
			
		||||
    memset((void*)parse_result, 0, sizeof(ParseResult));
 | 
			
		||||
    parse_result->is_fp_ = true;
 | 
			
		||||
    parse_result->is_multi_query_ = false;
 | 
			
		||||
    parse_result->malloc_pool_ = malloc_pool;
 | 
			
		||||
    parse_result->is_ignore_hint_ = false;
 | 
			
		||||
    parse_result->need_parameterize_ = true;
 | 
			
		||||
    parse_result->pl_parse_info_.is_pl_parse_ = false;
 | 
			
		||||
    parse_result->minus_ctx_.has_minus_ = false;
 | 
			
		||||
    parse_result->minus_ctx_.pos_ = -1;
 | 
			
		||||
    parse_result->minus_ctx_.raw_sql_offset_ = -1;
 | 
			
		||||
    parse_result->is_for_trigger_ = false;
 | 
			
		||||
    parse_result->is_dynamic_sql_ = false;
 | 
			
		||||
    parse_result->is_batched_multi_enabled_split_ = false;
 | 
			
		||||
    parse_result->may_bool_value_ = false;
 | 
			
		||||
 | 
			
		||||
    int64_t new_length = str_len + 1;
 | 
			
		||||
    char* buf = (char*)parse_malloc(new_length, parse_result->malloc_pool_);
 | 
			
		||||
 | 
			
		||||
    parse_result->param_nodes_ = NULL;
 | 
			
		||||
    parse_result->tail_param_node_ = NULL;
 | 
			
		||||
    parse_result->no_param_sql_ = buf;
 | 
			
		||||
    parse_result->no_param_sql_buf_len_ = new_length;
 | 
			
		||||
 | 
			
		||||
    ret = parse(str_ptr, new_length, *parse_result);
 | 
			
		||||
 | 
			
		||||
    if (OB_SUCC(ret)) {
 | 
			
		||||
      ret = gen_sqlid(parse_result->no_param_sql_, parse_result->no_param_sql_len_, len, sql_id);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int ObSQLParser::gen_sqlid(const char* paramed_sql, const int64_t sql_len, const int64_t len, char* sql_id)
 | 
			
		||||
{
 | 
			
		||||
  int ret = OB_SUCCESS;
 | 
			
		||||
  const int32_t MD5_LENGTH = 16;
 | 
			
		||||
  if (OB_ISNULL(sql_id) || len < 32) {
 | 
			
		||||
    ret = OB_INVALID_ARGUMENT;
 | 
			
		||||
  } else {
 | 
			
		||||
    unsigned char md5_buf[MD5_LENGTH];
 | 
			
		||||
    unsigned char* res = MD5(reinterpret_cast<const unsigned char*>(paramed_sql), sql_len, md5_buf);
 | 
			
		||||
 | 
			
		||||
    if (OB_ISNULL(res)) {
 | 
			
		||||
      ret = OB_ERR_UNEXPECTED;
 | 
			
		||||
    } else {
 | 
			
		||||
      ret = parser_to_hex_cstr(md5_buf, MD5_LENGTH, sql_id, len);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace sql
 | 
			
		||||
}  // namespace oceanbase
 | 
			
		||||
							
								
								
									
										49
									
								
								src/sql/parser/ob_sql_parser.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								src/sql/parser/ob_sql_parser.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,49 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Copyright (c) 2021 OceanBase
 | 
			
		||||
 * OceanBase CE is licensed under Mulan PubL v2.
 | 
			
		||||
 * You can use this software according to the terms and conditions of the Mulan PubL v2.
 | 
			
		||||
 * You may obtain a copy of Mulan PubL v2 at:
 | 
			
		||||
 *          http://license.coscl.org.cn/MulanPubL-2.0
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 | 
			
		||||
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 | 
			
		||||
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 | 
			
		||||
 * See the Mulan PubL v2 for more details.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef OCEANBASE_SRC_SQL_PARSER_OB_SQL_PARSER_H_
 | 
			
		||||
#define OCEANBASE_SRC_SQL_PARSER_OB_SQL_PARSER_H_
 | 
			
		||||
 | 
			
		||||
#ifdef SQL_PARSER_COMPILATION
 | 
			
		||||
#include "parse_node.h"
 | 
			
		||||
#else
 | 
			
		||||
#include "sql/parser/parse_node.h"
 | 
			
		||||
#endif
 | 
			
		||||
namespace oceanbase {
 | 
			
		||||
namespace common {
 | 
			
		||||
class ObIAllocator;
 | 
			
		||||
}  // namespace common
 | 
			
		||||
 | 
			
		||||
namespace sql {
 | 
			
		||||
class ObSQLParser {
 | 
			
		||||
  public:
 | 
			
		||||
  ObSQLParser(common::ObIAllocator& allocator, ObSQLMode mode) : allocator_(allocator), sql_mode_(mode)
 | 
			
		||||
  {}
 | 
			
		||||
 | 
			
		||||
  int parse(const char* str_ptr, const int64_t str_len, ParseResult& result);
 | 
			
		||||
 | 
			
		||||
  // only for obproxy fast parser
 | 
			
		||||
  // do not use the this function in observer kernel
 | 
			
		||||
  int parse_and_gen_sqlid(
 | 
			
		||||
      void* malloc_pool, const char* str_ptr, const int64_t str_len, const int64_t len, char* sql_id);
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
  int gen_sqlid(const char* paramed_sql, const int64_t sql_len, const int64_t len, char* sql_id);
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
  common::ObIAllocator& allocator_;
 | 
			
		||||
  ObSQLMode sql_mode_;
 | 
			
		||||
};
 | 
			
		||||
}  // namespace sql
 | 
			
		||||
}  // namespace oceanbase
 | 
			
		||||
 | 
			
		||||
#endif /* OCEANBASE_SRC_SQL_PARSER_OB_SQL_PARSER_H_ */
 | 
			
		||||
							
								
								
									
										30
									
								
								src/sql/parser/parse_define.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								src/sql/parser/parse_define.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,30 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Copyright (c) 2021 OceanBase
 | 
			
		||||
 * OceanBase CE is licensed under Mulan PubL v2.
 | 
			
		||||
 * You can use this software according to the terms and conditions of the Mulan PubL v2.
 | 
			
		||||
 * You may obtain a copy of Mulan PubL v2 at:
 | 
			
		||||
 *          http://license.coscl.org.cn/MulanPubL-2.0
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 | 
			
		||||
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 | 
			
		||||
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 | 
			
		||||
 * See the Mulan PubL v2 for more details.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef OCEANBASE_SQL_PARSER_PARSE_DEFINE_
 | 
			
		||||
#define OCEANBASE_SQL_PARSER_PARSE_DEFINE_
 | 
			
		||||
 | 
			
		||||
#include "lib/utility/ob_macro_utils.h"
 | 
			
		||||
 | 
			
		||||
#define NULL_PTR(x) (OB_UNLIKELY(NULL == (x)))
 | 
			
		||||
 | 
			
		||||
static const int64_t OB_MAX_PARSER_INT16_VALUE = 32738;
 | 
			
		||||
// errno keep consistency with  with ob_define.h
 | 
			
		||||
static const int32_t OB_PARSER_ERR_NO_MEMORY = -4013;
 | 
			
		||||
static const int32_t OB_PARSER_ERR_UNEXPECTED = -4016;
 | 
			
		||||
static const int32_t OB_PARSER_ERR_EMPTY_QUERY = -5253;
 | 
			
		||||
static const int32_t OB_PARSER_ERR_PARSE_SQL = -5001;
 | 
			
		||||
static const int32_t OB_PARSER_ERR_SIZE_OVERFLOW = -4019;
 | 
			
		||||
static const int32_t OB_PARSER_SUCCESS = 0;
 | 
			
		||||
static const int32_t OB_PARSER_ERR_ILLEGAL_NAME = -5018;
 | 
			
		||||
 | 
			
		||||
#endif /*OCEANBASE_SQL_PARSER_PARSE_DEFINE_*/
 | 
			
		||||
							
								
								
									
										165
									
								
								src/sql/parser/parse_malloc.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										165
									
								
								src/sql/parser/parse_malloc.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,165 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Copyright (c) 2021 OceanBase
 | 
			
		||||
 * OceanBase CE is licensed under Mulan PubL v2.
 | 
			
		||||
 * You can use this software according to the terms and conditions of the Mulan PubL v2.
 | 
			
		||||
 * You may obtain a copy of Mulan PubL v2 at:
 | 
			
		||||
 *          http://license.coscl.org.cn/MulanPubL-2.0
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 | 
			
		||||
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 | 
			
		||||
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 | 
			
		||||
 * See the Mulan PubL v2 for more details.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#define USING_LOG_PREFIX SQL_PARSER
 | 
			
		||||
#include "sql/parser/parse_malloc.h"
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <lib/alloc/alloc_assist.h>
 | 
			
		||||
#include "lib/charset/ob_ctype.h"
 | 
			
		||||
#include "sql/parser/parse_define.h"
 | 
			
		||||
#include "sql/parser/parser_proxy_func.h"
 | 
			
		||||
 | 
			
		||||
// get memory from the thread obStringBuf, and not release untill thread quits
 | 
			
		||||
void* parse_malloc(const size_t nbyte, void* malloc_pool)
 | 
			
		||||
{
 | 
			
		||||
  void* ptr = NULL;
 | 
			
		||||
  size_t headlen = sizeof(int64_t);
 | 
			
		||||
  if (OB_ISNULL(malloc_pool)) {
 | 
			
		||||
  } else if (OB_UNLIKELY(nbyte <= 0)) {
 | 
			
		||||
  } else {
 | 
			
		||||
    if (OB_UNLIKELY(NULL == (ptr = parser_alloc_buffer(malloc_pool, headlen + nbyte)))) {
 | 
			
		||||
    } else {
 | 
			
		||||
      *(static_cast<int64_t*>(ptr)) = nbyte;
 | 
			
		||||
      ptr = static_cast<char*>(ptr) + headlen;
 | 
			
		||||
      MEMSET(ptr, 0, nbyte);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return ptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* ptr must point to a memory allocated by parse_malloc.cpp */
 | 
			
		||||
void* parse_realloc(void* ptr, size_t nbyte, void* malloc_pool)
 | 
			
		||||
{
 | 
			
		||||
  void* new_ptr = NULL;
 | 
			
		||||
  // need not to check nbyte
 | 
			
		||||
  if (OB_ISNULL(malloc_pool)) {
 | 
			
		||||
  } else {
 | 
			
		||||
    if (OB_UNLIKELY(NULL == ptr)) {
 | 
			
		||||
      new_ptr = parser_alloc_buffer(malloc_pool, nbyte);
 | 
			
		||||
    } else {
 | 
			
		||||
      size_t headlen = sizeof(int64_t);
 | 
			
		||||
      if (OB_UNLIKELY(NULL == (new_ptr = parser_alloc_buffer(malloc_pool, headlen + nbyte)))) {
 | 
			
		||||
      } else {
 | 
			
		||||
        int64_t obyte = *(reinterpret_cast<int64_t*>(static_cast<char*>(ptr) - headlen));
 | 
			
		||||
        *(static_cast<int64_t*>(new_ptr)) = nbyte;
 | 
			
		||||
        new_ptr = static_cast<char*>(new_ptr) + headlen;
 | 
			
		||||
        MEMMOVE(new_ptr, ptr, static_cast<int64_t>(nbyte) > obyte ? obyte : nbyte);
 | 
			
		||||
        parser_free_buffer(malloc_pool, static_cast<char*>(ptr) - headlen);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return new_ptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char* parse_strndup(const char* str, size_t nbyte, void* malloc_pool)
 | 
			
		||||
{
 | 
			
		||||
  char* new_str = NULL;
 | 
			
		||||
  // need not to check nbyte
 | 
			
		||||
  if (OB_ISNULL(str)) {
 | 
			
		||||
  } else {
 | 
			
		||||
    if (OB_LIKELY(NULL != (new_str = static_cast<char*>(parse_malloc(nbyte + 1, malloc_pool))))) {
 | 
			
		||||
      MEMMOVE(new_str, str, nbyte);
 | 
			
		||||
      new_str[nbyte] = '\0';
 | 
			
		||||
    } else {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return new_str;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char* parse_strdup(const char* str, void* malloc_pool, int64_t* out_len)
 | 
			
		||||
{
 | 
			
		||||
  char* out_str = NULL;
 | 
			
		||||
  if (OB_ISNULL(str)) {
 | 
			
		||||
  } else if (OB_ISNULL(out_len)) {
 | 
			
		||||
  } else {
 | 
			
		||||
    size_t dup_len = STRLEN(str);
 | 
			
		||||
    out_str = parse_strndup(str, dup_len, malloc_pool);
 | 
			
		||||
    *out_len = dup_len;
 | 
			
		||||
  }
 | 
			
		||||
  return out_str;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char* parse_str_convert_utf8(
 | 
			
		||||
    const struct ObCharsetInfo* src_cs, const char* str, void* malloc_pool, int64_t* out_len, int* extra_errno)
 | 
			
		||||
{
 | 
			
		||||
  char* out_str = NULL;
 | 
			
		||||
  if (OB_ISNULL(str) || OB_ISNULL(out_len) || OB_ISNULL(extra_errno)) {
 | 
			
		||||
  } else {
 | 
			
		||||
    uint errors;
 | 
			
		||||
    size_t str_len = STRLEN(str);
 | 
			
		||||
    size_t dst_len = str_len * 4;
 | 
			
		||||
    if (OB_ISNULL(out_str = static_cast<char*>(parse_malloc(dst_len + 1, malloc_pool)))) {
 | 
			
		||||
    } else {
 | 
			
		||||
      *out_len = ob_convert(out_str, dst_len, &ob_charset_utf8mb4_general_ci, str, str_len, src_cs, &errors);
 | 
			
		||||
      out_str[*out_len] = '\0';
 | 
			
		||||
      if (0 != errors) {
 | 
			
		||||
        *extra_errno = OB_PARSER_ERR_ILLEGAL_NAME;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return out_str;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char* strndup_with_prefix(const char* prefix, const char* str, size_t nbyte, void* malloc_pool)
 | 
			
		||||
{
 | 
			
		||||
  char* new_str = NULL;
 | 
			
		||||
  size_t prefix_len = strlen(prefix);
 | 
			
		||||
  // need not to check nbyte
 | 
			
		||||
  if (OB_ISNULL(str)) {
 | 
			
		||||
  } else {
 | 
			
		||||
    if (OB_LIKELY(NULL != (new_str = static_cast<char*>(parse_malloc(nbyte + prefix_len, malloc_pool))))) {
 | 
			
		||||
      MEMMOVE(new_str, prefix, prefix_len);
 | 
			
		||||
      MEMMOVE(new_str + prefix_len, str, nbyte);
 | 
			
		||||
    } else {
 | 
			
		||||
      // do nothing
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return new_str;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char* strndup_with_prefix_and_postfix(
 | 
			
		||||
    const char* prefix, const char* postfix, const char* str, size_t nbyte, void* malloc_pool)
 | 
			
		||||
{
 | 
			
		||||
  char* new_str = NULL;
 | 
			
		||||
  size_t prefix_len = strlen(prefix);
 | 
			
		||||
  size_t postfix_len = strlen(postfix);
 | 
			
		||||
  if (OB_ISNULL(str)) {
 | 
			
		||||
  } else {
 | 
			
		||||
    if (OB_LIKELY(
 | 
			
		||||
            NULL != (new_str = static_cast<char*>(parse_malloc(nbyte + prefix_len + postfix_len, malloc_pool))))) {
 | 
			
		||||
      MEMMOVE(new_str, prefix, prefix_len);
 | 
			
		||||
      MEMMOVE(new_str + prefix_len, str, nbyte);
 | 
			
		||||
      MEMMOVE(new_str + prefix_len + nbyte, postfix, postfix_len);
 | 
			
		||||
    } else {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return new_str;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void parse_free(void* ptr)
 | 
			
		||||
{
 | 
			
		||||
  UNUSED(ptr);
 | 
			
		||||
  /* do nothing, we don't really free the memory */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char* cp_str_value(const char* src, const size_t nbyte, void* malloc_pool)
 | 
			
		||||
{
 | 
			
		||||
  char* new_str = NULL;
 | 
			
		||||
  if (OB_ISNULL(src)) {
 | 
			
		||||
  } else {
 | 
			
		||||
    if (OB_LIKELY(NULL != (new_str = static_cast<char*>(parse_malloc(nbyte, malloc_pool))))) {
 | 
			
		||||
      MEMCPY(new_str, src, nbyte);
 | 
			
		||||
    } else {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return new_str;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										40
									
								
								src/sql/parser/parse_malloc.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								src/sql/parser/parse_malloc.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,40 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Copyright (c) 2021 OceanBase
 | 
			
		||||
 * OceanBase CE is licensed under Mulan PubL v2.
 | 
			
		||||
 * You can use this software according to the terms and conditions of the Mulan PubL v2.
 | 
			
		||||
 * You may obtain a copy of Mulan PubL v2 at:
 | 
			
		||||
 *          http://license.coscl.org.cn/MulanPubL-2.0
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 | 
			
		||||
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 | 
			
		||||
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 | 
			
		||||
 * See the Mulan PubL v2 for more details.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef OCEANBASE_SQL_PARSER_PARSE_MALLOC_
 | 
			
		||||
#define OCEANBASE_SQL_PARSER_PARSE_MALLOC_
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// NB: Be careful!!!, it is only used in parser module
 | 
			
		||||
// NOTE, parse_malloc will memset the allocated memory to 0
 | 
			
		||||
extern void* parse_malloc(const size_t nbyte, void* malloc_pool);
 | 
			
		||||
extern void* parse_realloc(void* ptr, size_t nbyte, void* malloc_pool);
 | 
			
		||||
extern void parse_free(void* ptr);
 | 
			
		||||
extern char* parse_strndup(const char* str, size_t nbyte, void* malloc_pool);
 | 
			
		||||
extern char* parse_strdup(const char* str, void* malloc_pool, int64_t* out_len);
 | 
			
		||||
extern char* parse_str_convert_utf8(
 | 
			
		||||
    const struct ObCharsetInfo* src_cs, const char* str, void* malloc_pool, int64_t* out_len, int* extra_errno);
 | 
			
		||||
extern char* strndup_with_prefix(const char* prefix, const char* str, size_t nbyte, void* malloc_pool);
 | 
			
		||||
extern char* strndup_with_prefix_and_postfix(
 | 
			
		||||
    const char* prefix, const char* postfix, const char* str, size_t nbyte, void* malloc_pool);
 | 
			
		||||
extern char* cp_str_value(const char* src, const size_t nbyte, void* malloc_pool);
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif  // OCEANBASE_SQL_PARSER_PARSE_MALLOC_
 | 
			
		||||
							
								
								
									
										634
									
								
								src/sql/parser/parse_node.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										634
									
								
								src/sql/parser/parse_node.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,634 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Copyright (c) 2021 OceanBase
 | 
			
		||||
 * OceanBase CE is licensed under Mulan PubL v2.
 | 
			
		||||
 * You can use this software according to the terms and conditions of the Mulan PubL v2.
 | 
			
		||||
 * You may obtain a copy of Mulan PubL v2 at:
 | 
			
		||||
 *          http://license.coscl.org.cn/MulanPubL-2.0
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 | 
			
		||||
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 | 
			
		||||
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 | 
			
		||||
 * See the Mulan PubL v2 for more details.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "sql/parser/parse_node.h"
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <ctype.h>
 | 
			
		||||
#include "lib/alloc/alloc_assist.h"
 | 
			
		||||
#include "sql/parser/parse_malloc.h"
 | 
			
		||||
#include "sql/parser/parse_node_hash.h"
 | 
			
		||||
#include "sql/parser/parse_define.h"
 | 
			
		||||
#include "sql/parser/sql_parser_base.h"
 | 
			
		||||
extern const char* get_type_name(int type);
 | 
			
		||||
 | 
			
		||||
#ifdef SQL_PARSER_COMPILATION
 | 
			
		||||
#include "sql/parser/parser_proxy_func.h"
 | 
			
		||||
#endif  // SQL_PARSER_COMPILATION
 | 
			
		||||
 | 
			
		||||
#define WINDOW_FUNCTION_NUM 41
 | 
			
		||||
struct FuncPair {
 | 
			
		||||
  char* func_name_;
 | 
			
		||||
  int yytokentype_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int count_child(ParseNode* root, void* malloc_pool, int* count);
 | 
			
		||||
 | 
			
		||||
// merge_child:if succ ,return 0, else return 1
 | 
			
		||||
int merge_child(ParseNode* node, void* malloc_pool, ParseNode* source_tree, int* index);
 | 
			
		||||
 | 
			
		||||
void destroy_tree(ParseNode* root)
 | 
			
		||||
{
 | 
			
		||||
  (void)root;
 | 
			
		||||
  /*
 | 
			
		||||
  if (OB_UNLIKELY(NULL == root)) {
 | 
			
		||||
    //do nothing
 | 
			
		||||
  } else {
 | 
			
		||||
    int64_t i = 0;
 | 
			
		||||
    if (root->num_child_ > 0) {
 | 
			
		||||
      if (OB_UNLIKELY(NULL == root->children_)) {
 | 
			
		||||
        (void)fprintf(stderr, "ERROR children of root is NULL\n");
 | 
			
		||||
      } else {
 | 
			
		||||
        for (; i < root->num_child_; ++i) {
 | 
			
		||||
          destroy_tree(root->children_[i]);
 | 
			
		||||
          root->children_[i] = NULL;
 | 
			
		||||
        }
 | 
			
		||||
        parse_free(root->children_);
 | 
			
		||||
        root->children_ = NULL;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    if (NULL != root->str_value_) {
 | 
			
		||||
      parse_free((char *)root->str_value_);
 | 
			
		||||
      root->str_value_ = NULL;
 | 
			
		||||
    }
 | 
			
		||||
    parse_free(root);
 | 
			
		||||
    }*/
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ParseNode* new_node(void* malloc_pool, ObItemType type, int num)
 | 
			
		||||
{
 | 
			
		||||
  // the mem alloced by parse_malloc has been memset;
 | 
			
		||||
  ParseNode* node = (ParseNode*)parse_malloc(sizeof(ParseNode), malloc_pool);
 | 
			
		||||
  if (OB_UNLIKELY(NULL == node)) {
 | 
			
		||||
    (void)printf("malloc memory failed\n");
 | 
			
		||||
  } else {
 | 
			
		||||
    node->type_ = type;
 | 
			
		||||
    node->num_child_ = num;
 | 
			
		||||
    node->param_num_ = 0;
 | 
			
		||||
    node->is_neg_ = 0;
 | 
			
		||||
    node->is_hidden_const_ = 0;
 | 
			
		||||
    node->is_date_unit_ = 0;
 | 
			
		||||
    node->is_tree_not_param_ = 0;
 | 
			
		||||
    node->length_semantics_ = 0;
 | 
			
		||||
    node->is_change_to_char_ = 0;
 | 
			
		||||
    node->is_val_paramed_item_idx_ = 0;
 | 
			
		||||
    node->is_copy_raw_text_ = 0;
 | 
			
		||||
    node->is_column_varchar_ = 0;
 | 
			
		||||
    node->is_trans_from_minus_ = 0;
 | 
			
		||||
    node->is_assigned_from_child_ = 0;
 | 
			
		||||
    node->is_num_must_be_pos_ = 0;
 | 
			
		||||
    node->value_ = INT64_MAX;
 | 
			
		||||
    node->str_len_ = 0;
 | 
			
		||||
    node->str_value_ = NULL;
 | 
			
		||||
    node->text_len_ = 0;
 | 
			
		||||
    node->raw_text_ = NULL;
 | 
			
		||||
    node->pos_ = 0;
 | 
			
		||||
#ifdef SQL_PARSER_COMPILATION
 | 
			
		||||
    node->token_off_ = -1;
 | 
			
		||||
    node->token_len_ = -1;
 | 
			
		||||
#endif
 | 
			
		||||
    if (num > 0) {
 | 
			
		||||
      int64_t alloc_size = sizeof(ParseNode*) * num;
 | 
			
		||||
      node->children_ = (ParseNode**)parse_malloc(alloc_size, malloc_pool);
 | 
			
		||||
      if (OB_UNLIKELY(NULL == node->children_)) {
 | 
			
		||||
        parse_free(node);
 | 
			
		||||
        node = NULL;
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      node->children_ = NULL;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return node;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int count_child(ParseNode* root, void* malloc_pool, int* count)
 | 
			
		||||
{
 | 
			
		||||
  int ret = OB_PARSER_SUCCESS;
 | 
			
		||||
  ParserLinkNode* stack_top = NULL;
 | 
			
		||||
  if (NULL == count) {
 | 
			
		||||
    ret = OB_PARSER_ERR_UNEXPECTED;
 | 
			
		||||
    (void)fprintf(stderr, "ERROR invalid parameter ret=%d\n", ret);
 | 
			
		||||
  } else if (NULL == root) {
 | 
			
		||||
    *count = 0;
 | 
			
		||||
  } else if (NULL == (stack_top = new_link_node(malloc_pool))) {
 | 
			
		||||
    ret = 1;
 | 
			
		||||
    (void)fprintf(stderr, "ERROR failed to malloc memory\n");
 | 
			
		||||
  } else {
 | 
			
		||||
    *count = 0;
 | 
			
		||||
    stack_top->val_ = root;
 | 
			
		||||
 | 
			
		||||
    do {
 | 
			
		||||
      ParseNode* tree = NULL;
 | 
			
		||||
      if (NULL == stack_top || NULL == (tree = (ParseNode*)stack_top->val_)) {
 | 
			
		||||
        ret = 1;
 | 
			
		||||
        (void)fprintf(stderr, "ERROR invalid null argument\n");
 | 
			
		||||
      } else {
 | 
			
		||||
        stack_top = stack_top->next_;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (OB_PARSER_SUCCESS != ret) {
 | 
			
		||||
      } else if (T_LINK_NODE != tree->type_) {
 | 
			
		||||
        *count += 1;
 | 
			
		||||
      } else if (tree->num_child_ <= 0) {
 | 
			
		||||
        // do nothing
 | 
			
		||||
      } else {
 | 
			
		||||
        if (NULL == tree->children_) {
 | 
			
		||||
          ret = 1;
 | 
			
		||||
          (void)fprintf(stderr, "ERROR invalid null children\n");
 | 
			
		||||
        }
 | 
			
		||||
        ParserLinkNode* tmp_node = NULL;
 | 
			
		||||
        for (int64_t i = tree->num_child_ - 1; OB_PARSER_SUCCESS == ret && i >= 0; i--) {
 | 
			
		||||
          ParseNode* child = tree->children_[i];
 | 
			
		||||
          if (NULL == child) {
 | 
			
		||||
            // do nothing
 | 
			
		||||
          } else if (NULL == (tmp_node = new_link_node(malloc_pool))) {
 | 
			
		||||
            ret = 1;
 | 
			
		||||
            (void)fprintf(stderr, "ERROR failed to allocate memory\n");
 | 
			
		||||
          } else {
 | 
			
		||||
            tmp_node->val_ = child;
 | 
			
		||||
            tmp_node->next_ = stack_top;
 | 
			
		||||
            stack_top = tmp_node;
 | 
			
		||||
          }
 | 
			
		||||
        }  // for end
 | 
			
		||||
      }
 | 
			
		||||
    } while (OB_PARSER_SUCCESS == ret && NULL != stack_top);
 | 
			
		||||
  }
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// merge_child:if succ ,return 0, else return 1
 | 
			
		||||
int merge_child(ParseNode* node, void* malloc_pool, ParseNode* source_tree, int* index)
 | 
			
		||||
{
 | 
			
		||||
  int ret = 0;
 | 
			
		||||
  ParserLinkNode* stack_top = NULL;
 | 
			
		||||
  if (OB_UNLIKELY(NULL == node || NULL == index)) {
 | 
			
		||||
    ret = 1;
 | 
			
		||||
    (void)fprintf(stderr, "ERROR node%p or index:%p is NULL\n", node, index);
 | 
			
		||||
  } else if (NULL == source_tree) {
 | 
			
		||||
    // do nothing
 | 
			
		||||
  } else if (NULL == (stack_top = new_link_node(malloc_pool))) {
 | 
			
		||||
    ret = 1;
 | 
			
		||||
    (void)fprintf(stderr, "ERROR failed to malloc memory\n");
 | 
			
		||||
  } else {
 | 
			
		||||
    stack_top->val_ = source_tree;
 | 
			
		||||
 | 
			
		||||
    do {
 | 
			
		||||
      ParseNode* tree = NULL;
 | 
			
		||||
      if (NULL == stack_top || NULL == (tree = (ParseNode*)stack_top->val_)) {
 | 
			
		||||
        ret = 1;
 | 
			
		||||
        (void)fprintf(stderr, "ERROR invalid null argument\n");
 | 
			
		||||
      } else {
 | 
			
		||||
        // pop stack
 | 
			
		||||
        stack_top = stack_top->next_;
 | 
			
		||||
      }
 | 
			
		||||
      if (OB_PARSER_SUCCESS != ret) {
 | 
			
		||||
        // do nothing
 | 
			
		||||
      } else if (T_LINK_NODE != tree->type_) {
 | 
			
		||||
        if (OB_UNLIKELY(*index < 0 || *index >= node->num_child_)) {
 | 
			
		||||
          ret = 1;
 | 
			
		||||
          (void)fprintf(
 | 
			
		||||
              stderr, "ERROR invalid index: %d, num_child:%d\n tree: %d", *index, node->num_child_, tree->type_);
 | 
			
		||||
        } else if (NULL == node->children_) {
 | 
			
		||||
          ret = 1;
 | 
			
		||||
          (void)fprintf(stderr, "ERROR invalid null children pointer\n");
 | 
			
		||||
        } else {
 | 
			
		||||
          node->children_[*index] = tree;
 | 
			
		||||
          ++(*index);
 | 
			
		||||
        }
 | 
			
		||||
      } else if (tree->num_child_ <= 0) {
 | 
			
		||||
        // do nothing
 | 
			
		||||
      } else if (NULL == tree->children_) {
 | 
			
		||||
        ret = 1;
 | 
			
		||||
        (void)fprintf(stderr, "ERROR invalid children pointer\n");
 | 
			
		||||
      } else {
 | 
			
		||||
        ParserLinkNode* tmp_node = NULL;
 | 
			
		||||
        for (int64_t i = tree->num_child_ - 1; OB_PARSER_SUCCESS == ret && i >= 0; i--) {
 | 
			
		||||
          if (NULL == tree->children_[i]) {
 | 
			
		||||
            // do nothing
 | 
			
		||||
          } else if (NULL == (tmp_node = new_link_node(malloc_pool))) {
 | 
			
		||||
            ret = 1;
 | 
			
		||||
            (void)fprintf(stderr, "ERROR failed to malloc memory\n");
 | 
			
		||||
          } else {
 | 
			
		||||
            // push stack
 | 
			
		||||
            tmp_node->val_ = tree->children_[i];
 | 
			
		||||
            tmp_node->next_ = stack_top;
 | 
			
		||||
            stack_top = tmp_node;
 | 
			
		||||
          }
 | 
			
		||||
        }  // for end
 | 
			
		||||
      }
 | 
			
		||||
    } while (OB_PARSER_SUCCESS == ret && (stack_top != NULL));
 | 
			
		||||
  }
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ParseNode* merge_tree(void* malloc_pool, int* fatal_error, ObItemType node_tag, ParseNode* source_tree)
 | 
			
		||||
{
 | 
			
		||||
  ParseNode* node = NULL;
 | 
			
		||||
  ParseNode* ret_node = NULL;
 | 
			
		||||
  if (OB_UNLIKELY(NULL == malloc_pool) || OB_UNLIKELY(NULL == fatal_error)) {
 | 
			
		||||
    (void)fprintf(stderr, "ERROR parser result is NULL\n");
 | 
			
		||||
  } else if (NULL == source_tree) {
 | 
			
		||||
    // source_tree may be NULL, do nothing
 | 
			
		||||
  } else {
 | 
			
		||||
    int index = 0;
 | 
			
		||||
    int num = 0;
 | 
			
		||||
    int tmp_ret = 0;
 | 
			
		||||
    if (OB_UNLIKELY(OB_PARSER_SUCCESS != (tmp_ret = count_child(source_tree, malloc_pool, &num)))) {
 | 
			
		||||
      (void)fprintf(stderr, "ERROR fail to , count child num code : %d\n", tmp_ret);
 | 
			
		||||
      *fatal_error = tmp_ret;
 | 
			
		||||
    } else if (OB_LIKELY(NULL != (node = new_node(malloc_pool, node_tag, num)))) {
 | 
			
		||||
      if (OB_UNLIKELY(OB_PARSER_SUCCESS != (tmp_ret = merge_child(node, malloc_pool, source_tree, &index)))) {
 | 
			
		||||
        (void)fprintf(stderr, "ERROR fail to merge_child, error code : %d\n", tmp_ret);
 | 
			
		||||
        *fatal_error = tmp_ret;
 | 
			
		||||
      } else if (index != num) {
 | 
			
		||||
        (void)fprintf(stderr, "ERROR index:%d is not equal to num:%d\n", index, num);
 | 
			
		||||
      } else {
 | 
			
		||||
        ret_node = node;
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      *fatal_error = OB_PARSER_ERR_NO_MEMORY;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return ret_node;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ParseNode* new_terminal_node(void* malloc_pool, ObItemType type)
 | 
			
		||||
{
 | 
			
		||||
  int children_num = 0;
 | 
			
		||||
  return new_node(malloc_pool, type, children_num);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ParseNode* new_non_terminal_node(void* malloc_pool, ObItemType node_tag, int num, ...)
 | 
			
		||||
{
 | 
			
		||||
  ParseNode* ret_node = NULL;
 | 
			
		||||
  if (OB_UNLIKELY(num <= 0)) {
 | 
			
		||||
    (void)fprintf(stderr, "ERROR invalid num:%d\n", num);
 | 
			
		||||
  } else {
 | 
			
		||||
    int32_t i = 0;
 | 
			
		||||
    va_list va;
 | 
			
		||||
    ret_node = new_node(malloc_pool, node_tag, num);
 | 
			
		||||
    if (OB_LIKELY(NULL != ret_node)) {
 | 
			
		||||
      va_start(va, num);
 | 
			
		||||
      for (; i < num; ++i) {
 | 
			
		||||
        ret_node->children_[i] = va_arg(va, ParseNode*);
 | 
			
		||||
      }
 | 
			
		||||
      va_end(va);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return ret_node;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char* copy_expr_string(ParseResult* p, int expr_start, int expr_end)
 | 
			
		||||
{
 | 
			
		||||
  char* expr_string = NULL;
 | 
			
		||||
  if (OB_UNLIKELY(NULL == p)) {
 | 
			
		||||
    (void)fprintf(stderr, "ERROR parser result is NULL\n");
 | 
			
		||||
  } else if (OB_UNLIKELY(NULL == p->input_sql_)) {
 | 
			
		||||
    (void)fprintf(stderr, "ERROR input sql is NULL\n");
 | 
			
		||||
  } else if (OB_UNLIKELY(expr_start < 0 || expr_end < 0 || expr_end < expr_start)) {
 | 
			
		||||
    (void)fprintf(stderr, "ERROR invalid argument, expr_start:%d, expr_end:%d\n", expr_start, expr_end);
 | 
			
		||||
  } else {
 | 
			
		||||
    int len = expr_end - expr_start + 1;
 | 
			
		||||
    expr_string = (char*)parse_malloc(len + 1, p->malloc_pool_);
 | 
			
		||||
    if (OB_UNLIKELY(NULL == expr_string)) {
 | 
			
		||||
      (void)printf("malloc memory failed\n");
 | 
			
		||||
    } else {
 | 
			
		||||
      memmove(expr_string, p->input_sql_ + expr_start - 1, len);
 | 
			
		||||
      expr_string[len] = '\0';
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return expr_string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
unsigned char escaped_char(unsigned char c, int* with_back_slash)
 | 
			
		||||
{
 | 
			
		||||
  *with_back_slash = 0;
 | 
			
		||||
  switch (c) {
 | 
			
		||||
    case 'n':
 | 
			
		||||
      return '\n';
 | 
			
		||||
    case 't':
 | 
			
		||||
      return '\t';
 | 
			
		||||
    case 'r':
 | 
			
		||||
      return '\r';
 | 
			
		||||
    case 'b':
 | 
			
		||||
      return '\b';
 | 
			
		||||
    case '0':
 | 
			
		||||
      return '\0';
 | 
			
		||||
    case 'Z':
 | 
			
		||||
      return '\032';
 | 
			
		||||
    case '_':
 | 
			
		||||
    case '%':
 | 
			
		||||
      *with_back_slash = 1;
 | 
			
		||||
      return c;
 | 
			
		||||
    default:
 | 
			
		||||
      return c;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
///* quote_type: 0 - single quotes; 1 - double quotation marks */
 | 
			
		||||
// int64_t ob_parse_string(const char *src, char *dest, int64_t len, int quote_type)
 | 
			
		||||
//{
 | 
			
		||||
//  int64_t i;
 | 
			
		||||
//  int64_t index = 0;
 | 
			
		||||
//  int with_back_slash = 1;
 | 
			
		||||
//  for (i = 0; i < len; ++i) {
 | 
			
		||||
//    unsigned char c = src[i];
 | 
			
		||||
//    if (c == '\\') {
 | 
			
		||||
//      if (i < len - 1) {
 | 
			
		||||
//        c = src[++i];
 | 
			
		||||
//      } else {
 | 
			
		||||
//        break;
 | 
			
		||||
//      }
 | 
			
		||||
//      c = escaped_char(c, &with_back_slash);
 | 
			
		||||
//      if (with_back_slash)
 | 
			
		||||
//      {
 | 
			
		||||
//        dest[index++] = '\\';
 | 
			
		||||
//      }
 | 
			
		||||
//    } else if (quote_type == 0 && c == '\'' && i + 1 < len && src[i + 1] == '\'') {
 | 
			
		||||
//      ++i;
 | 
			
		||||
//    } else if (quote_type == 1 && c == '"' && i + 1 < len && src[i + 1] == '"') {
 | 
			
		||||
//      ++i;
 | 
			
		||||
//    }
 | 
			
		||||
//    dest[index++] = c;
 | 
			
		||||
//  }
 | 
			
		||||
//  assert(index <= len);
 | 
			
		||||
//  dest[index] = '\0';
 | 
			
		||||
//  return index;
 | 
			
		||||
//}
 | 
			
		||||
 | 
			
		||||
static char char_int(char c)
 | 
			
		||||
{
 | 
			
		||||
  return (c >= '0' && c <= '9' ? c - '0' : (c >= 'A' && c <= 'Z' ? c - 'A' + 10 : c - 'a' + 10));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int64_t ob_parse_binary_len(int64_t len)
 | 
			
		||||
{
 | 
			
		||||
  return (len + 1) / 2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ob_parse_binary(const char* src, int64_t len, char* dest)
 | 
			
		||||
{
 | 
			
		||||
  if (OB_UNLIKELY(NULL == src || len <= 0 || NULL == dest)) {
 | 
			
		||||
    // do nothing
 | 
			
		||||
  } else {
 | 
			
		||||
    if (len > 0 && len % 2 != 0) {
 | 
			
		||||
      *dest = char_int(src[0]);
 | 
			
		||||
      ++src;
 | 
			
		||||
      ++dest;
 | 
			
		||||
    }
 | 
			
		||||
    const char* end = src + len - 1;
 | 
			
		||||
    for (; src <= end; src += 2) {
 | 
			
		||||
      *dest = (char)(16 * char_int(src[0]) + char_int(src[1]));
 | 
			
		||||
      ++dest;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int64_t ob_parse_bit_string_len(int64_t len)
 | 
			
		||||
{
 | 
			
		||||
  return (len + 7) / 8;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ob_parse_bit_string(const char* src, int64_t len, char* dest)
 | 
			
		||||
{
 | 
			
		||||
  if (OB_UNLIKELY(NULL == src || len <= 0 || NULL == dest)) {
 | 
			
		||||
    // do nothing
 | 
			
		||||
  } else {
 | 
			
		||||
    const char* end = src + len - 1;
 | 
			
		||||
    char* dest_end = dest + ob_parse_bit_string_len(len) - 1;
 | 
			
		||||
    if (len > 0) {
 | 
			
		||||
      unsigned char c = 0;
 | 
			
		||||
      unsigned int one_bit = 1;
 | 
			
		||||
      for (; end >= src; --end) {
 | 
			
		||||
        if (256 == one_bit) /* one byte ready */
 | 
			
		||||
        {
 | 
			
		||||
          *dest_end = c;
 | 
			
		||||
          --dest_end;
 | 
			
		||||
          c = 0;
 | 
			
		||||
          one_bit = 1;
 | 
			
		||||
        }
 | 
			
		||||
        if ('1' == *end) {
 | 
			
		||||
          c |= one_bit;
 | 
			
		||||
        }
 | 
			
		||||
        one_bit <<= 1;
 | 
			
		||||
      }              /* end for */
 | 
			
		||||
      *dest_end = c; /* the first byte */
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char* str_tolower(char* buff, int64_t len)
 | 
			
		||||
{
 | 
			
		||||
  if (OB_LIKELY(NULL != buff)) {
 | 
			
		||||
    char* ptr = buff;
 | 
			
		||||
    char* end = buff + len;
 | 
			
		||||
    unsigned char ch = *ptr;
 | 
			
		||||
    while (ptr != end) {
 | 
			
		||||
      ch = *ptr;
 | 
			
		||||
      if (ch >= 'A' && ch <= 'Z') {
 | 
			
		||||
        ch += 'a' - 'A';
 | 
			
		||||
      } else if (ch >= 0x80 && isupper(ch)) {
 | 
			
		||||
        ch = tolower(ch);
 | 
			
		||||
      }
 | 
			
		||||
      *ptr = ch;
 | 
			
		||||
      ptr++;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return buff;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char* str_toupper(char* buff, int64_t len)
 | 
			
		||||
{
 | 
			
		||||
  if (OB_LIKELY(NULL != buff)) {
 | 
			
		||||
    char* ptr = buff;
 | 
			
		||||
    char* end = buff + len;
 | 
			
		||||
    unsigned char ch = *ptr;
 | 
			
		||||
    while (ptr != end) {
 | 
			
		||||
      ch = *ptr;
 | 
			
		||||
      if (ch >= 'a' && ch <= 'z') {
 | 
			
		||||
        ch -= 'a' - 'A';
 | 
			
		||||
      } else if (ch >= 0x80 && islower(ch)) {
 | 
			
		||||
        ch = toupper(ch);
 | 
			
		||||
      }
 | 
			
		||||
      *ptr = ch;
 | 
			
		||||
      ptr++;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return buff;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int64_t str_remove_space(char* buff, int64_t len)
 | 
			
		||||
{
 | 
			
		||||
  int64_t length = 0;
 | 
			
		||||
  if (OB_LIKELY(NULL != buff)) {
 | 
			
		||||
    for (int i = 0; i < len; i++) {
 | 
			
		||||
      if (!isspace(buff[i])) {
 | 
			
		||||
        buff[length++] = buff[i];
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return length;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// calculate hash value of syntax tree recursively
 | 
			
		||||
// every member of ParseNode is calculated using murmurhash
 | 
			
		||||
uint64_t parsenode_hash(const ParseNode* node)
 | 
			
		||||
{
 | 
			
		||||
  uint64_t hash_val = 0;
 | 
			
		||||
  if (check_stack_overflow_c()) {
 | 
			
		||||
    (void)fprintf(stderr, "ERROR stack overflow in recursive function\n");
 | 
			
		||||
  } else if (OB_LIKELY(NULL != node)) {
 | 
			
		||||
    hash_val = murmurhash(&node->type_, sizeof(node->type_), hash_val);
 | 
			
		||||
    hash_val = murmurhash(&node->value_, sizeof(node->value_), hash_val);
 | 
			
		||||
    hash_val = murmurhash(&node->str_len_, sizeof(node->str_len_), hash_val);
 | 
			
		||||
    if (NULL != node->str_value_) {
 | 
			
		||||
      hash_val = murmurhash(node->str_value_, node->str_len_, hash_val);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    uint64_t child_hash_val = 0;
 | 
			
		||||
    int32_t i = 0;
 | 
			
		||||
    if (node->num_child_ > 0) {
 | 
			
		||||
      if (OB_UNLIKELY(NULL == node->children_)) {
 | 
			
		||||
        (void)fprintf(stderr, "ERROR children of node is NULL\n");
 | 
			
		||||
      } else {
 | 
			
		||||
        for (; i < node->num_child_; ++i) {
 | 
			
		||||
          if (NULL != node->children_[i]) {
 | 
			
		||||
            child_hash_val = parsenode_hash(node->children_[i]);
 | 
			
		||||
            hash_val = murmurhash(&child_hash_val, sizeof(child_hash_val), hash_val);
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return hash_val;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// compare syntax tree recursively
 | 
			
		||||
// every member of ParseNode is compared
 | 
			
		||||
bool parsenode_equal(const ParseNode* lnode, const ParseNode* rnode)
 | 
			
		||||
{
 | 
			
		||||
  bool result = true;
 | 
			
		||||
  if (check_stack_overflow_c()) {
 | 
			
		||||
    (void)fprintf(stderr, "ERROR stack overflow in recursive function\n");
 | 
			
		||||
  } else if (NULL == lnode && NULL == rnode) {
 | 
			
		||||
    result = true;
 | 
			
		||||
  } else if ((NULL == lnode && NULL != rnode) || (NULL != lnode && NULL == rnode)) {
 | 
			
		||||
    result = false;
 | 
			
		||||
  } else {
 | 
			
		||||
    if (lnode->type_ != rnode->type_ || lnode->value_ != rnode->value_ || lnode->str_len_ != rnode->str_len_ ||
 | 
			
		||||
        lnode->num_child_ != rnode->num_child_) {
 | 
			
		||||
      result = false;
 | 
			
		||||
    } else {
 | 
			
		||||
      if (NULL == lnode->str_value_ && NULL == rnode->str_value_) {
 | 
			
		||||
        result = true;
 | 
			
		||||
      } else if ((NULL == lnode->str_value_ && NULL != rnode->str_value_) ||
 | 
			
		||||
                 (NULL != lnode->str_value_ && NULL == rnode->str_value_)) {
 | 
			
		||||
        result = false;
 | 
			
		||||
      } else if (lnode->str_len_ != rnode->str_len_) {
 | 
			
		||||
        result = false;
 | 
			
		||||
      } else {
 | 
			
		||||
        // T_VARCHAR type: value_ is length, str_value_ is ptr
 | 
			
		||||
        // @ref ob_raw_expr.cpp
 | 
			
		||||
        if (0 != strncmp(lnode->str_value_, rnode->str_value_, lnode->str_len_)) {
 | 
			
		||||
          result = false;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      if (result) {
 | 
			
		||||
        if (lnode->num_child_ > 0) {
 | 
			
		||||
          if (NULL == lnode->children_ || NULL == rnode->children_) {
 | 
			
		||||
            result = false;
 | 
			
		||||
          } else {
 | 
			
		||||
            int32_t i = 0;
 | 
			
		||||
            for (; result && i < lnode->num_child_; ++i) {
 | 
			
		||||
              result = parsenode_equal(lnode->children_[i], rnode->children_[i]);
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Search according to the name, return the subscript of the name when found, add the name and return the subscript when
 | 
			
		||||
// found
 | 
			
		||||
int64_t get_question_mark(ObQuestionMarkCtx* ctx, void* malloc_pool, const char* name)
 | 
			
		||||
{
 | 
			
		||||
  int64_t idx = -1;
 | 
			
		||||
  if (OB_UNLIKELY(NULL == ctx || NULL == name)) {
 | 
			
		||||
    (void)fprintf(stderr, "ERROR question mark ctx or name is NULL\n");
 | 
			
		||||
  } else {
 | 
			
		||||
    bool valid_name = true;
 | 
			
		||||
    for (int64_t i = 0; valid_name && -1 == idx && i < ctx->count_; ++i) {
 | 
			
		||||
      if (NULL == ctx->name_[i]) {
 | 
			
		||||
        (void)fprintf(stderr, "ERROR name_ in question mark ctx is null\n");
 | 
			
		||||
        valid_name = false;
 | 
			
		||||
      } else if (0 == STRCASECMP(ctx->name_[i], name)) {
 | 
			
		||||
        idx = i;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    if (-1 == idx && valid_name) {
 | 
			
		||||
      int64_t len = 0;
 | 
			
		||||
      ctx->name_[ctx->count_] = parse_strdup(name, malloc_pool, &len);
 | 
			
		||||
      idx = ctx->count_++;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return idx;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ParserLinkNode* new_link_node(void* malloc)
 | 
			
		||||
{
 | 
			
		||||
  ParserLinkNode* new_node = (ParserLinkNode*)parse_malloc(sizeof(ParserLinkNode), malloc);
 | 
			
		||||
  if (NULL == new_node) {
 | 
			
		||||
    (void)printf("ERROR malloc memory failed\n");
 | 
			
		||||
  } else {
 | 
			
		||||
    new_node->next_ = NULL;
 | 
			
		||||
    new_node->prev_ = NULL;
 | 
			
		||||
    new_node->val_ = NULL;
 | 
			
		||||
  }
 | 
			
		||||
  return new_node;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool nodename_equal(const ParseNode* node, const char* pattern, int64_t pat_len)
 | 
			
		||||
{
 | 
			
		||||
  bool result = true;
 | 
			
		||||
  if (NULL == node || NULL == node->str_value_ || NULL == pattern || node->str_len_ != pat_len) {
 | 
			
		||||
    result = false;
 | 
			
		||||
  } else {
 | 
			
		||||
    result = true;
 | 
			
		||||
    for (int64_t i = 0; result && i < pat_len; ++i) {
 | 
			
		||||
      if (toupper(node->str_value_[i]) != toupper(pattern[i])) {
 | 
			
		||||
        result = false;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int binary_search(const struct FuncPair* window_func, int64_t begin, int64_t end, const char* value)
 | 
			
		||||
{
 | 
			
		||||
  int result = -1;
 | 
			
		||||
  bool need_break = false;
 | 
			
		||||
  while (!need_break && begin <= end) {
 | 
			
		||||
    int mid = begin + (end - begin) / 2;
 | 
			
		||||
    int cmp = strcmp(window_func[mid].func_name_, value);
 | 
			
		||||
    if (cmp > 0) {
 | 
			
		||||
      end = mid - 1;
 | 
			
		||||
    } else if (cmp < 0) {
 | 
			
		||||
      begin = mid + 1;
 | 
			
		||||
    } else {
 | 
			
		||||
      result = window_func[mid].yytokentype_;
 | 
			
		||||
      need_break = true;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return result;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										354
									
								
								src/sql/parser/parse_node.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										354
									
								
								src/sql/parser/parse_node.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,354 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Copyright (c) 2021 OceanBase
 | 
			
		||||
 * OceanBase CE is licensed under Mulan PubL v2.
 | 
			
		||||
 * You can use this software according to the terms and conditions of the Mulan PubL v2.
 | 
			
		||||
 * You may obtain a copy of Mulan PubL v2 at:
 | 
			
		||||
 *          http://license.coscl.org.cn/MulanPubL-2.0
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 | 
			
		||||
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 | 
			
		||||
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 | 
			
		||||
 * See the Mulan PubL v2 for more details.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef OCEANBASE_SQL_PARSER_PARSE_NODE_H_
 | 
			
		||||
#define OCEANBASE_SQL_PARSER_PARSE_NODE_H_
 | 
			
		||||
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <stdarg.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <setjmp.h>
 | 
			
		||||
#ifdef SQL_PARSER_COMPILATION
 | 
			
		||||
#include "ob_sql_mode.h"
 | 
			
		||||
#include "ob_item_type.h"
 | 
			
		||||
#else
 | 
			
		||||
#include "common/sql_mode/ob_sql_mode.h"
 | 
			
		||||
#include "sql/parser/ob_item_type.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define MAX_ERROR_MSG 1024
 | 
			
		||||
 | 
			
		||||
struct ObCharsetInfo;
 | 
			
		||||
 | 
			
		||||
enum SelectParserOffset {
 | 
			
		||||
  PARSE_SELECT_WITH,
 | 
			
		||||
  PARSE_SELECT_DISTINCT,
 | 
			
		||||
  PARSE_SELECT_SELECT,
 | 
			
		||||
  PARSE_SELECT_INTO,  // into before from
 | 
			
		||||
  PARSE_SELECT_FROM,
 | 
			
		||||
  PARSE_SELECT_WHERE,
 | 
			
		||||
  PARSE_SELECT_DYNAMIC_SW_CBY,  // connect by node or start with node
 | 
			
		||||
  PARSE_SELECT_DYNAMIC_CBY_SW,  // connect by node or start with node
 | 
			
		||||
  PARSE_SELECT_GROUP,
 | 
			
		||||
  PARSE_SELECT_HAVING,
 | 
			
		||||
  PARSE_SELECT_SET,
 | 
			
		||||
  PARSE_SELECT_ALL,
 | 
			
		||||
  PARSE_SELECT_FORMER,
 | 
			
		||||
  PARSE_SELECT_LATER,
 | 
			
		||||
  PARSE_SELECT_ORDER,
 | 
			
		||||
  PARSE_SELECT_LIMIT,
 | 
			
		||||
  PARSE_SELECT_FOR_UPD,
 | 
			
		||||
  PARSE_SELECT_HINTS,
 | 
			
		||||
  PARSE_SELECT_WHEN,
 | 
			
		||||
  PARSE_SELECT_NAMED_WINDOWS,
 | 
			
		||||
  PARSE_SELECT_FETCH,
 | 
			
		||||
  PARSE_SELECT_FETCH_TEMP,  // use to temporary store fetch clause in parser
 | 
			
		||||
  PARSE_SELECT_INTO_EXTRA,  // ATTENTION!! SELECT_INTO_EXTRA must be the last one
 | 
			
		||||
  PARSE_SELECT_MAX_IDX
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum GrantParseOffset {
 | 
			
		||||
  PARSE_GRANT_ROLE_LIST,
 | 
			
		||||
  PARSE_GRANT_ROLE_GRANTEE,
 | 
			
		||||
  PARSE_GRANT_ROLE_OPT_WITH,
 | 
			
		||||
  PARSE_GRANT_ROLE_MAX_IDX
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum GrantParseSysOffset {
 | 
			
		||||
  PARSE_GRANT_SYS_PRIV_ORACLE_LIST,
 | 
			
		||||
  PARSE_GRANT_SYS_PRIV_ORACLE_GRANTEE,
 | 
			
		||||
  PARSE_GRANT_SYS_PRIV_ORACLE_OPT_WITH,
 | 
			
		||||
  PARSE_GRANT_SYS_PRIV_ORACLE_MAX_IDX
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum ParseMode {
 | 
			
		||||
  STD_MODE = 0,
 | 
			
		||||
  FP_MODE,                               /* fast parse, keep hint, and do parameterization*/
 | 
			
		||||
  MULTI_MODE,                            /* multi query ultra-fast parse */
 | 
			
		||||
  FP_PARAMERIZE_AND_FILTER_HINT_MODE,    /*Filter out the hint and do parameterization*/
 | 
			
		||||
  FP_NO_PARAMERIZE_AND_FILTER_HINT_MODE, /*Filter out hints and do not parameterize*/
 | 
			
		||||
  TRIGGER_MODE,                          /* treat ':xxx' as identifier */
 | 
			
		||||
  DYNAMIC_SQL_MODE, /*In the process of parsing dynamic sql: iidx and:identifier should be determined
 | 
			
		||||
                      according to the statement type whether to check the name of the placeholder*/
 | 
			
		||||
  DBMS_SQL_MODE,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
  int err_code_;
 | 
			
		||||
  char err_msg_[MAX_ERROR_MSG];
 | 
			
		||||
} ErrStat;
 | 
			
		||||
 | 
			
		||||
struct _ParseNode;
 | 
			
		||||
 | 
			
		||||
typedef struct _ObStmtLoc {
 | 
			
		||||
  int first_column_;
 | 
			
		||||
  int last_column_;
 | 
			
		||||
  int first_line_;
 | 
			
		||||
  int last_line_;
 | 
			
		||||
} ObStmtLoc;
 | 
			
		||||
 | 
			
		||||
typedef struct _ParseNode {
 | 
			
		||||
  ObItemType type_;
 | 
			
		||||
  int32_t num_child_;
 | 
			
		||||
  int16_t param_num_;
 | 
			
		||||
  struct {
 | 
			
		||||
    uint16_t is_neg_ : 1;
 | 
			
		||||
    uint16_t is_hidden_const_ : 1;
 | 
			
		||||
    uint16_t is_tree_not_param_ : 1;
 | 
			
		||||
    uint16_t length_semantics_ : 2;
 | 
			
		||||
    uint16_t is_change_to_char_ : 1;
 | 
			
		||||
    uint16_t is_val_paramed_item_idx_ : 1;
 | 
			
		||||
    uint16_t is_copy_raw_text_ : 1;
 | 
			
		||||
    uint16_t is_column_varchar_ : 1;
 | 
			
		||||
    uint16_t is_trans_from_minus_ : 1;
 | 
			
		||||
    uint16_t is_assigned_from_child_ : 1;
 | 
			
		||||
    uint16_t is_num_must_be_pos_ : 1;
 | 
			
		||||
    uint16_t is_date_unit_ : 1;
 | 
			
		||||
    uint16_t reserved_ : 3;
 | 
			
		||||
  };
 | 
			
		||||
  union {
 | 
			
		||||
    int64_t value_;
 | 
			
		||||
    int32_t int32_values_[2];
 | 
			
		||||
    int16_t int16_values_[4];
 | 
			
		||||
  };
 | 
			
		||||
  const char* str_value_;
 | 
			
		||||
  int64_t str_len_;
 | 
			
		||||
  const char* raw_text_;
 | 
			
		||||
  int64_t text_len_;
 | 
			
		||||
  int64_t pos_;
 | 
			
		||||
 | 
			
		||||
  struct _ParseNode** children_; /* attributes for non-terninal node, which has children */
 | 
			
		||||
  ObStmtLoc stmt_loc_;
 | 
			
		||||
  union {
 | 
			
		||||
    int64_t raw_param_idx_;
 | 
			
		||||
    int64_t raw_sql_offset_;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
#ifdef SQL_PARSER_COMPILATION
 | 
			
		||||
  int token_off_;
 | 
			
		||||
  int token_len_;
 | 
			
		||||
#endif
 | 
			
		||||
} ParseNode;
 | 
			
		||||
 | 
			
		||||
struct _ParamList;
 | 
			
		||||
 | 
			
		||||
typedef struct _ParamList {
 | 
			
		||||
  ParseNode* node_;
 | 
			
		||||
  struct _ParamList* next_;
 | 
			
		||||
} ParamList;
 | 
			
		||||
 | 
			
		||||
enum RefType {
 | 
			
		||||
  REF_REL = 0,
 | 
			
		||||
  REF_PROC,
 | 
			
		||||
  REF_FUNC,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct _RefObjList {
 | 
			
		||||
  enum RefType type_;
 | 
			
		||||
  ParseNode* node_;
 | 
			
		||||
  struct _RefObjList* next_;
 | 
			
		||||
} RefObjList;
 | 
			
		||||
 | 
			
		||||
typedef struct _PLParseInfo {
 | 
			
		||||
  bool is_pl_parse_;
 | 
			
		||||
  bool is_pl_parse_expr_;
 | 
			
		||||
  /*for mysql pl*/
 | 
			
		||||
  void* pl_ns_;  // ObPLBlockNS
 | 
			
		||||
  int last_pl_symbol_pos_;
 | 
			
		||||
  RefObjList* ref_object_nodes_;
 | 
			
		||||
  RefObjList* tail_ref_object_node_;
 | 
			
		||||
} PLParseInfo;
 | 
			
		||||
 | 
			
		||||
#define MAX_QUESTION_MARK 128
 | 
			
		||||
 | 
			
		||||
typedef struct _ObQuestionMarkCtx {
 | 
			
		||||
  char* name_[MAX_QUESTION_MARK];
 | 
			
		||||
  int count_;
 | 
			
		||||
  bool by_ordinal_;
 | 
			
		||||
  bool by_name_;
 | 
			
		||||
} ObQuestionMarkCtx;
 | 
			
		||||
 | 
			
		||||
// record the minus status while parsing the sql
 | 
			
		||||
// for example, 'select - -1 from dual'
 | 
			
		||||
// when parser sees the first '-', pos_ = 7, raw_sql_offset = 7, has_minus_ = true, is_cur_numeric_ = false
 | 
			
		||||
// after seeing the second '-', members are reseted, pos_ = 9, raw_sql_offset_ = 9, has_minus_ = true,  is_cur_numberic
 | 
			
		||||
// = false after seeing '1', is_cur_numeric = true, then param node '-1' is returned
 | 
			
		||||
typedef struct _ObMinusStatuCtx {
 | 
			
		||||
  int pos_;
 | 
			
		||||
  int raw_sql_offset_;
 | 
			
		||||
  bool has_minus_;
 | 
			
		||||
  bool is_cur_numeric_;
 | 
			
		||||
} ObMinusStatusCtx;
 | 
			
		||||
 | 
			
		||||
#ifdef SQL_PARSER_COMPILATION
 | 
			
		||||
// for comment_list_ in ParseResult
 | 
			
		||||
typedef struct TokenPosInfo {
 | 
			
		||||
  int token_off_;
 | 
			
		||||
  int token_len_;
 | 
			
		||||
} TokenPosInfo;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
  void* yyscan_info_;
 | 
			
		||||
  ParseNode* result_tree_;
 | 
			
		||||
  jmp_buf jmp_buf_;  // handle fatal error
 | 
			
		||||
  const char* input_sql_;
 | 
			
		||||
  int input_sql_len_;
 | 
			
		||||
  void* malloc_pool_;  // ObIAllocator
 | 
			
		||||
  int extra_errno_;
 | 
			
		||||
  char error_msg_[MAX_ERROR_MSG];
 | 
			
		||||
  int start_col_;
 | 
			
		||||
  int end_col_;
 | 
			
		||||
  int line_;
 | 
			
		||||
  int yycolumn_;
 | 
			
		||||
  int yylineno_;
 | 
			
		||||
  char* tmp_literal_;
 | 
			
		||||
  ObQuestionMarkCtx question_mark_ctx_;
 | 
			
		||||
  ObSQLMode sql_mode_;
 | 
			
		||||
  bool has_encount_comment_;
 | 
			
		||||
  /*for faster parser*/
 | 
			
		||||
  bool is_fp_;
 | 
			
		||||
  /* for multi query fast parse (split queries) */
 | 
			
		||||
  bool is_multi_query_;
 | 
			
		||||
  char* no_param_sql_;
 | 
			
		||||
  int no_param_sql_len_;
 | 
			
		||||
  int no_param_sql_buf_len_;
 | 
			
		||||
  ParamList* param_nodes_;
 | 
			
		||||
  ParamList* tail_param_node_;
 | 
			
		||||
  int param_node_num_;
 | 
			
		||||
  int token_num_;
 | 
			
		||||
  bool is_ignore_hint_;     // used for outline
 | 
			
		||||
  bool is_ignore_token_;    // used for outline
 | 
			
		||||
  bool need_parameterize_;  // used for outline, to support signature of outline can contain hint
 | 
			
		||||
  /*for pl*/
 | 
			
		||||
  PLParseInfo pl_parse_info_;
 | 
			
		||||
  /*for  q-quote*/
 | 
			
		||||
  bool in_q_quote_;
 | 
			
		||||
  ObMinusStatusCtx minus_ctx_;  // for fast parser to parse negative value
 | 
			
		||||
  bool is_for_trigger_;
 | 
			
		||||
  bool is_dynamic_sql_;
 | 
			
		||||
  bool is_dbms_sql_;
 | 
			
		||||
  bool is_batched_multi_enabled_split_;
 | 
			
		||||
  bool is_not_utf8_connection_;
 | 
			
		||||
  const struct ObCharsetInfo* charset_info_;
 | 
			
		||||
  int last_well_formed_len_;
 | 
			
		||||
  bool may_bool_value_;  // used for true/false in sql parser
 | 
			
		||||
 | 
			
		||||
#ifdef SQL_PARSER_COMPILATION
 | 
			
		||||
  TokenPosInfo* comment_list_;
 | 
			
		||||
  int comment_cnt_;
 | 
			
		||||
  int comment_cap_;
 | 
			
		||||
  int realloc_cnt_;
 | 
			
		||||
  bool stop_add_comment_;
 | 
			
		||||
#endif
 | 
			
		||||
} ParseResult;
 | 
			
		||||
 | 
			
		||||
typedef struct _ObFastParseCtx {
 | 
			
		||||
  bool is_fp_;
 | 
			
		||||
} ObFastParseCtx;
 | 
			
		||||
 | 
			
		||||
typedef enum ObSizeUnitType {
 | 
			
		||||
  SIZE_UNIT_TYPE_INVALID = -1,
 | 
			
		||||
  SIZE_UNIT_TYPE_K,
 | 
			
		||||
  SIZE_UNIT_TYPE_M,
 | 
			
		||||
  SIZE_UNIT_TYPE_G,
 | 
			
		||||
  SIZE_UNIT_TYPE_T,
 | 
			
		||||
  SIZE_UNIT_TYPE_P,
 | 
			
		||||
  SIZE_UNIT_TYPE_E,
 | 
			
		||||
  SIZE_UNIT_TYPE_MAX
 | 
			
		||||
} ObSizeUnitType;
 | 
			
		||||
 | 
			
		||||
extern int parse_init(ParseResult* p);
 | 
			
		||||
extern int parse_reset(ParseResult* p);
 | 
			
		||||
extern int parse_terminate(ParseResult* p);
 | 
			
		||||
extern int parse_sql(ParseResult* p, const char* pszSql, size_t iLen);
 | 
			
		||||
extern void destroy_tree(ParseNode* pRoot);
 | 
			
		||||
extern unsigned char escaped_char(unsigned char c, int* with_back_slash);
 | 
			
		||||
extern char* str_tolower(char* buff, int64_t len);
 | 
			
		||||
extern char* str_toupper(char* buff, int64_t len);
 | 
			
		||||
extern int64_t str_remove_space(char* buff, int64_t len);
 | 
			
		||||
// extern int64_t ob_parse_string(const char *src, char *dest, int64_t len, int quote_type);
 | 
			
		||||
 | 
			
		||||
extern ParseNode* new_node(void* malloc_pool, ObItemType type, int num);
 | 
			
		||||
extern ParseNode* new_non_terminal_node(void* malloc_pool, ObItemType node_tag, int num, ...);
 | 
			
		||||
extern ParseNode* new_terminal_node(void* malloc_pool, ObItemType type);
 | 
			
		||||
 | 
			
		||||
/// convert x'42ab' to binary string
 | 
			
		||||
void ob_parse_binary(const char* src, int64_t len, char* dest);
 | 
			
		||||
int64_t ob_parse_binary_len(int64_t len);
 | 
			
		||||
 | 
			
		||||
// convert b'10010110' to binary string
 | 
			
		||||
// @pre dest buffer is enough
 | 
			
		||||
void ob_parse_bit_string(const char* src, int64_t len, char* dest);
 | 
			
		||||
int64_t ob_parse_bit_string_len(int64_t len);
 | 
			
		||||
 | 
			
		||||
// calculate hash value of syntax tree recursively
 | 
			
		||||
// @param [in] node         syntax tree root
 | 
			
		||||
// @return                  hash value of syntax tree
 | 
			
		||||
extern uint64_t parsenode_hash(const ParseNode* node);
 | 
			
		||||
// compare syntax tree recursively
 | 
			
		||||
// @param [in] node1        first syntax tree
 | 
			
		||||
// @param [in] node2        second syntax tree
 | 
			
		||||
extern bool parsenode_equal(const ParseNode* node1, const ParseNode* node2);
 | 
			
		||||
 | 
			
		||||
extern int64_t get_question_mark(ObQuestionMarkCtx* ctx, void* malloc_pool, const char* name);
 | 
			
		||||
 | 
			
		||||
// compare ParseNode str_value_ to pattern
 | 
			
		||||
// @param [in] node        ParseNode
 | 
			
		||||
// @param [in] pattern     pattern_str
 | 
			
		||||
// @param [in] pat_len     length of pattern
 | 
			
		||||
extern bool nodename_equal(const ParseNode* node, const char* pattern, int64_t pat_len);
 | 
			
		||||
 | 
			
		||||
#define OB_NODE_CAST_TYPE_IDX 0
 | 
			
		||||
#define OB_NODE_CAST_COLL_IDX 1
 | 
			
		||||
#define OB_NODE_CAST_N_PREC_IDX 2
 | 
			
		||||
#define OB_NODE_CAST_N_SCALE_IDX 3
 | 
			
		||||
#define OB_NODE_CAST_NUMBER_TYPE_IDX 1
 | 
			
		||||
#define OB_NODE_CAST_C_LEN_IDX 1
 | 
			
		||||
 | 
			
		||||
typedef enum ObNumberParseType {
 | 
			
		||||
  NPT_PERC_SCALE = 0,
 | 
			
		||||
  NPT_STAR_SCALE,
 | 
			
		||||
  NPT_STAR,
 | 
			
		||||
  NPT_PERC,
 | 
			
		||||
  NPT_EMPTY,
 | 
			
		||||
} ObNumberParseType;
 | 
			
		||||
 | 
			
		||||
#ifndef SQL_PARSER_COMPILATION
 | 
			
		||||
bool check_stack_overflow_c();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
typedef struct _ParserLinkNode {
 | 
			
		||||
  struct _ParserLinkNode* next_;
 | 
			
		||||
  struct _ParserLinkNode* prev_;
 | 
			
		||||
  void* val_;
 | 
			
		||||
} ParserLinkNode;
 | 
			
		||||
 | 
			
		||||
ParserLinkNode* new_link_node(void* malloc);
 | 
			
		||||
 | 
			
		||||
typedef enum ObTranslateCharset {
 | 
			
		||||
  TRANSLATE_CHAR_CS = 0,
 | 
			
		||||
  TRANSLATE_NCHAR_CS = 1,
 | 
			
		||||
} ObTranslateCharset;
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif  // OCEANBASE_SQL_PARSER_PARSE_NODE_H_
 | 
			
		||||
							
								
								
									
										20
									
								
								src/sql/parser/parse_node_hash.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								src/sql/parser/parse_node_hash.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,20 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Copyright (c) 2021 OceanBase
 | 
			
		||||
 * OceanBase CE is licensed under Mulan PubL v2.
 | 
			
		||||
 * You can use this software according to the terms and conditions of the Mulan PubL v2.
 | 
			
		||||
 * You may obtain a copy of Mulan PubL v2 at:
 | 
			
		||||
 *          http://license.coscl.org.cn/MulanPubL-2.0
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 | 
			
		||||
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 | 
			
		||||
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 | 
			
		||||
 * See the Mulan PubL v2 for more details.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "parse_node_hash.h"
 | 
			
		||||
#include "lib/hash_func/murmur_hash.h"
 | 
			
		||||
 | 
			
		||||
// this is a C wrapper to call murmurhash in C++ definition
 | 
			
		||||
uint64_t murmurhash(const void* data, int32_t len, uint64_t hash)
 | 
			
		||||
{
 | 
			
		||||
  return oceanbase::common::murmurhash(data, len, hash);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										28
									
								
								src/sql/parser/parse_node_hash.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								src/sql/parser/parse_node_hash.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,28 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Copyright (c) 2021 OceanBase
 | 
			
		||||
 * OceanBase CE is licensed under Mulan PubL v2.
 | 
			
		||||
 * You can use this software according to the terms and conditions of the Mulan PubL v2.
 | 
			
		||||
 * You may obtain a copy of Mulan PubL v2 at:
 | 
			
		||||
 *          http://license.coscl.org.cn/MulanPubL-2.0
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 | 
			
		||||
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 | 
			
		||||
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 | 
			
		||||
 * See the Mulan PubL v2 for more details.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef OCEANBASE_SQL_PARSER_PARSENODE_HASH_
 | 
			
		||||
#define OCEANBASE_SQL_PARSER_PARSENODE_HASH_
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
// this is a C wrapper to call murmurhash in C++ definition
 | 
			
		||||
uint64_t murmurhash(const void* data, int32_t len, uint64_t hash);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /*OCEANBASE_SQL_PARSER_PARSENODE_HASH_*/
 | 
			
		||||
							
								
								
									
										53
									
								
								src/sql/parser/parser_proxy_func.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								src/sql/parser/parser_proxy_func.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,53 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Copyright (c) 2021 OceanBase
 | 
			
		||||
 * OceanBase CE is licensed under Mulan PubL v2.
 | 
			
		||||
 * You can use this software according to the terms and conditions of the Mulan PubL v2.
 | 
			
		||||
 * You may obtain a copy of Mulan PubL v2 at:
 | 
			
		||||
 *          http://license.coscl.org.cn/MulanPubL-2.0
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 | 
			
		||||
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 | 
			
		||||
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 | 
			
		||||
 * See the Mulan PubL v2 for more details.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#define USING_LOG_PREFIX SQL_PARSER
 | 
			
		||||
 | 
			
		||||
#include "parser_proxy_func.h"
 | 
			
		||||
 | 
			
		||||
#include "share/ob_errno.h"
 | 
			
		||||
#include "lib/utility/ob_macro_utils.h"
 | 
			
		||||
#include "lib/oblog/ob_log.h"
 | 
			
		||||
#include "lib/allocator/ob_allocator.h"
 | 
			
		||||
 | 
			
		||||
using namespace oceanbase::common;
 | 
			
		||||
 | 
			
		||||
void* parser_alloc_buffer(void* malloc_pool, const int64_t alloc_size)
 | 
			
		||||
{
 | 
			
		||||
  int ret = OB_SUCCESS;
 | 
			
		||||
  void* alloced_buf = NULL;
 | 
			
		||||
  if (OB_ISNULL(malloc_pool)) {
 | 
			
		||||
    ret = OB_INVALID_ARGUMENT;
 | 
			
		||||
    LOG_WARN("invalid malloc pool", K(ret));
 | 
			
		||||
  } else {
 | 
			
		||||
    ObIAllocator* allocator = static_cast<ObIAllocator*>(malloc_pool);
 | 
			
		||||
    if (OB_ISNULL(alloced_buf = allocator->alloc(alloc_size))) {
 | 
			
		||||
      ret = OB_ALLOCATE_MEMORY_FAILED;
 | 
			
		||||
      LOG_WARN("failed to allocate memory", K(ret), K(alloc_size));
 | 
			
		||||
    } else {
 | 
			
		||||
      // do nothing
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return alloced_buf;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void parser_free_buffer(void* malloc_pool, void* buffer)
 | 
			
		||||
{
 | 
			
		||||
  int ret = OB_SUCCESS;
 | 
			
		||||
  if (OB_ISNULL(malloc_pool)) {
 | 
			
		||||
    ret = OB_INVALID_ARGUMENT;
 | 
			
		||||
    LOG_WARN("invalid null malloc pool", K(ret));
 | 
			
		||||
  } else {
 | 
			
		||||
    ObIAllocator* allocator = static_cast<ObIAllocator*>(malloc_pool);
 | 
			
		||||
    allocator->free(buffer);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										37
									
								
								src/sql/parser/parser_proxy_func.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								src/sql/parser/parser_proxy_func.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,37 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Copyright (c) 2021 OceanBase
 | 
			
		||||
 * OceanBase CE is licensed under Mulan PubL v2.
 | 
			
		||||
 * You can use this software according to the terms and conditions of the Mulan PubL v2.
 | 
			
		||||
 * You may obtain a copy of Mulan PubL v2 at:
 | 
			
		||||
 *          http://license.coscl.org.cn/MulanPubL-2.0
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 | 
			
		||||
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 | 
			
		||||
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 | 
			
		||||
 * See the Mulan PubL v2 for more details.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef PARSER_ALLOC_FUNC_H_
 | 
			
		||||
#define PARSER_ALLOC_FUNC_H_
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
// ObSQLParser module extracts a static link library to Proxy, Proxy must implement the following
 | 
			
		||||
// functions by itself to link correctly
 | 
			
		||||
 | 
			
		||||
void* parser_alloc_buffer(void* malloc_pool, const int64_t alloc_size);
 | 
			
		||||
void parser_free_buffer(void* malloc_pool, void* buffer);
 | 
			
		||||
 | 
			
		||||
#ifdef SQL_PARSER_COMPILATION
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif  // __cplusplus
 | 
			
		||||
 | 
			
		||||
extern bool check_stack_overflow_c();
 | 
			
		||||
extern int check_stack_overflow_in_c(int* check_overflow);
 | 
			
		||||
extern void right_to_die_or_duty_to_live_c();
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif  // __cplusplus
 | 
			
		||||
#endif  // SQL_PARSER_COMPILATION
 | 
			
		||||
 | 
			
		||||
#endif  // !PASER_ALLOC_FUNC_H_
 | 
			
		||||
							
								
								
									
										54
									
								
								src/sql/parser/parser_utility.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								src/sql/parser/parser_utility.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,54 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Copyright (c) 2021 OceanBase
 | 
			
		||||
 * OceanBase CE is licensed under Mulan PubL v2.
 | 
			
		||||
 * You can use this software according to the terms and conditions of the Mulan PubL v2.
 | 
			
		||||
 * You may obtain a copy of Mulan PubL v2 at:
 | 
			
		||||
 *          http://license.coscl.org.cn/MulanPubL-2.0
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 | 
			
		||||
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 | 
			
		||||
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 | 
			
		||||
 * See the Mulan PubL v2 for more details.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "sql/parser/parser_utility.h"
 | 
			
		||||
#include "lib/utility/ob_macro_utils.h"
 | 
			
		||||
 | 
			
		||||
#include <cstddef>
 | 
			
		||||
 | 
			
		||||
int parser_to_hex_cstr(const void* in_data, const int64_t data_length, char* buff, const int64_t buff_size)
 | 
			
		||||
{
 | 
			
		||||
  int ret = 0;
 | 
			
		||||
  int64_t pos = 0;
 | 
			
		||||
  int64_t cstr_pos = 0;
 | 
			
		||||
  if (0 != (ret = parser_to_hex_cstr_(in_data, data_length, buff, buff_size, &pos, &cstr_pos))) {}
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const char* HEXCHARS = "0123456789ABCDEF";
 | 
			
		||||
 | 
			
		||||
int parser_to_hex_cstr_(
 | 
			
		||||
    const void* in_data, const int64_t data_length, char* buf, const int64_t buf_len, int64_t* pos, int64_t* cstr_pos)
 | 
			
		||||
{
 | 
			
		||||
  int ret = 0;
 | 
			
		||||
  *cstr_pos = *pos;
 | 
			
		||||
  if ((OB_UNLIKELY(data_length > 0) && OB_ISNULL(in_data)) || OB_ISNULL(buf) || OB_UNLIKELY(*pos < 0) ||
 | 
			
		||||
      OB_UNLIKELY(buf_len - *pos) < 1) {
 | 
			
		||||
    ret = -1;
 | 
			
		||||
    // LOG_WARN("Invalid argument", KP(in_data), KP(buf), K(data_length), K(buf_len), K(ret));
 | 
			
		||||
  } else if ((buf_len - *pos) < (data_length * 2 + 1)) {
 | 
			
		||||
    buf[*pos++] = '\0';
 | 
			
		||||
    ret = -2;
 | 
			
		||||
    // LOG_WARN("size is overflow", K(buf_len), K(data_length), K(buf_len), K(pos), K(ret));
 | 
			
		||||
  } else {
 | 
			
		||||
    unsigned const char* p = (unsigned const char*)in_data;
 | 
			
		||||
    char* dst = static_cast<char*>(buf + *pos);
 | 
			
		||||
    for (int64_t i = 0; i < data_length; ++i) {
 | 
			
		||||
      *dst++ = HEXCHARS[*p >> 4 & 0xF];
 | 
			
		||||
      *dst++ = HEXCHARS[*p & 0xF];
 | 
			
		||||
      p++;
 | 
			
		||||
    }
 | 
			
		||||
    *dst = '\0';
 | 
			
		||||
    *pos += (data_length * 2 + 1);
 | 
			
		||||
  }
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										29
									
								
								src/sql/parser/parser_utility.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								src/sql/parser/parser_utility.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,29 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Copyright (c) 2021 OceanBase
 | 
			
		||||
 * OceanBase CE is licensed under Mulan PubL v2.
 | 
			
		||||
 * You can use this software according to the terms and conditions of the Mulan PubL v2.
 | 
			
		||||
 * You may obtain a copy of Mulan PubL v2 at:
 | 
			
		||||
 *          http://license.coscl.org.cn/MulanPubL-2.0
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 | 
			
		||||
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 | 
			
		||||
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 | 
			
		||||
 * See the Mulan PubL v2 for more details.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef PARSER_UTILITY_H_
 | 
			
		||||
#define PARSER_UTILITY_H_
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
int parser_to_hex_cstr(const void* in_data, const int64_t data_length, char* buff, const int64_t buff_size);
 | 
			
		||||
 | 
			
		||||
int parser_to_hex_cstr_(
 | 
			
		||||
    const void* in_data, const int64_t data_length, char* buf, const int64_t buf_len, int64_t* pos, int64_t* cstr_pos);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										274
									
								
								src/sql/parser/sql_parser_base.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										274
									
								
								src/sql/parser/sql_parser_base.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,274 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Copyright (c) 2021 OceanBase
 | 
			
		||||
 * OceanBase CE is licensed under Mulan PubL v2.
 | 
			
		||||
 * You can use this software according to the terms and conditions of the Mulan PubL v2.
 | 
			
		||||
 * You may obtain a copy of Mulan PubL v2 at:
 | 
			
		||||
 *          http://license.coscl.org.cn/MulanPubL-2.0
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 | 
			
		||||
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 | 
			
		||||
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 | 
			
		||||
 * See the Mulan PubL v2 for more details.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "sql_parser_base.h"
 | 
			
		||||
 | 
			
		||||
#define YY_EXTRA_TYPE void*
 | 
			
		||||
#define yyconst const
 | 
			
		||||
typedef void* yyscan_t;
 | 
			
		||||
typedef struct yy_buffer_state* YY_BUFFER_STATE;
 | 
			
		||||
#define IS_ORACLE_MODE(mode) (0 != (mode & SMO_ORACLE))
 | 
			
		||||
#define IS_ORACLE_COMPATIBLE (IS_ORACLE_MODE(p->sql_mode_))
 | 
			
		||||
 | 
			
		||||
extern int obsql_mysql_yylex_init_extra(YY_EXTRA_TYPE yy_user_defined, yyscan_t* ptr_yy_globals);
 | 
			
		||||
extern int obsql_mysql_yyparse(ParseResult* result);
 | 
			
		||||
extern int obsql_mysql_multi_fast_parse(ParseResult* p);
 | 
			
		||||
extern int obsql_mysql_fast_parse(ParseResult* p);
 | 
			
		||||
extern int obsql_mysql_yylex_destroy(yyscan_t yyscanner);
 | 
			
		||||
extern YY_BUFFER_STATE obsql_mysql_yy_scan_bytes(yyconst char* bytes, int len, yyscan_t yyscanner);
 | 
			
		||||
extern void obsql_mysql_yy_switch_to_buffer(YY_BUFFER_STATE new_buffer, yyscan_t yyscanner);
 | 
			
		||||
extern void obsql_mysql_yy_delete_buffer(YY_BUFFER_STATE b, yyscan_t yyscanner);
 | 
			
		||||
 | 
			
		||||
int parse_init(ParseResult* p)
 | 
			
		||||
{
 | 
			
		||||
  int ret = 0;  // can not include C++ file "ob_define.h"
 | 
			
		||||
  if (OB_UNLIKELY(NULL == p || NULL == p->malloc_pool_)) {
 | 
			
		||||
    ret = -1;
 | 
			
		||||
    if (NULL != p) {
 | 
			
		||||
      (void)snprintf(p->error_msg_, MAX_ERROR_MSG, "malloc_pool_ must be set");
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (OB_LIKELY(0 == ret)) {
 | 
			
		||||
    ret = IS_ORACLE_COMPATIBLE ? OB_PARSER_ERR_PARSE_SQL : obsql_mysql_yylex_init_extra(p, &(p->yyscan_info_));
 | 
			
		||||
  }
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int parse_reset(ParseResult* p)
 | 
			
		||||
{
 | 
			
		||||
  if (NULL != p) {
 | 
			
		||||
    p->yyscan_info_ = NULL;
 | 
			
		||||
    p->result_tree_ = NULL;
 | 
			
		||||
    p->input_sql_ = NULL;
 | 
			
		||||
    p->input_sql_len_ = 0;
 | 
			
		||||
    p->malloc_pool_ = NULL;
 | 
			
		||||
    p->extra_errno_ = 0;
 | 
			
		||||
    p->error_msg_[0] = '\0';
 | 
			
		||||
    p->start_col_ = 0;
 | 
			
		||||
    p->end_col_ = 0;
 | 
			
		||||
    p->line_ = 0;
 | 
			
		||||
    p->yycolumn_ = 0;
 | 
			
		||||
    p->yylineno_ = 0;
 | 
			
		||||
    p->tmp_literal_ = NULL;
 | 
			
		||||
 | 
			
		||||
    p->question_mark_ctx_.count_ = 0;
 | 
			
		||||
    p->question_mark_ctx_.by_ordinal_ = false;
 | 
			
		||||
    p->question_mark_ctx_.by_name_ = false;
 | 
			
		||||
    p->sql_mode_ = 0;
 | 
			
		||||
 | 
			
		||||
    p->has_encount_comment_ = false;
 | 
			
		||||
    p->is_fp_ = false;
 | 
			
		||||
    p->is_multi_query_ = false;
 | 
			
		||||
    p->no_param_sql_ = NULL;
 | 
			
		||||
    p->no_param_sql_len_ = 0;
 | 
			
		||||
    p->no_param_sql_buf_len_ = 0;
 | 
			
		||||
    p->param_nodes_ = NULL;
 | 
			
		||||
    p->tail_param_node_ = NULL;
 | 
			
		||||
    p->param_node_num_ = 0;
 | 
			
		||||
    p->token_num_ = 0;
 | 
			
		||||
    p->is_ignore_hint_ = false;
 | 
			
		||||
    p->is_ignore_token_ = false;
 | 
			
		||||
    p->need_parameterize_ = false;
 | 
			
		||||
    /*for pl*/
 | 
			
		||||
    p->pl_parse_info_.is_pl_parse_ = false;
 | 
			
		||||
    p->pl_parse_info_.is_pl_parse_expr_ = false;
 | 
			
		||||
    p->pl_parse_info_.pl_ns_ = NULL;
 | 
			
		||||
    p->pl_parse_info_.last_pl_symbol_pos_ = 0;
 | 
			
		||||
    p->pl_parse_info_.ref_object_nodes_ = NULL;
 | 
			
		||||
    p->pl_parse_info_.tail_ref_object_node_ = NULL;
 | 
			
		||||
    /*for  q-quote*/
 | 
			
		||||
    p->in_q_quote_ = false;
 | 
			
		||||
 | 
			
		||||
    p->minus_ctx_.pos_ = 0;
 | 
			
		||||
    p->minus_ctx_.raw_sql_offset_ = 0;
 | 
			
		||||
    p->minus_ctx_.has_minus_ = false;
 | 
			
		||||
    p->minus_ctx_.is_cur_numeric_ = false;
 | 
			
		||||
 | 
			
		||||
    p->is_for_trigger_ = false;
 | 
			
		||||
    p->is_dynamic_sql_ = false;
 | 
			
		||||
    p->is_dbms_sql_ = false;
 | 
			
		||||
    p->is_batched_multi_enabled_split_ = false;
 | 
			
		||||
    p->is_not_utf8_connection_ = false;
 | 
			
		||||
    p->charset_info_ = NULL;
 | 
			
		||||
    p->last_well_formed_len_ = 0;
 | 
			
		||||
    p->may_bool_value_ = false;
 | 
			
		||||
 | 
			
		||||
#ifdef SQL_PARSER_COMPILATION
 | 
			
		||||
    p->comment_list_ = NULL;
 | 
			
		||||
    p->comment_cnt_ = 0;
 | 
			
		||||
    p->comment_cap_ = 0;
 | 
			
		||||
    p->realloc_cnt_ = 0;
 | 
			
		||||
    p->stop_add_comment_ = false;
 | 
			
		||||
#endif
 | 
			
		||||
  }
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int parse_terminate(ParseResult* p)
 | 
			
		||||
{
 | 
			
		||||
  int ret = 0;
 | 
			
		||||
  if (OB_LIKELY(NULL != p->yyscan_info_)) {
 | 
			
		||||
    ret = IS_ORACLE_COMPATIBLE ? OB_PARSER_ERR_PARSE_SQL : obsql_mysql_yylex_destroy(p->yyscan_info_);
 | 
			
		||||
  }
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int parse_sql(ParseResult* p, const char* buf, size_t len)
 | 
			
		||||
{
 | 
			
		||||
  int ret = OB_PARSER_ERR_PARSE_SQL;
 | 
			
		||||
  if (OB_UNLIKELY(NULL == p)) {
 | 
			
		||||
  } else if (IS_ORACLE_COMPATIBLE) {
 | 
			
		||||
    ret = OB_PARSER_ERR_PARSE_SQL;
 | 
			
		||||
  } else if (OB_UNLIKELY(NULL == buf || len <= 0)) {
 | 
			
		||||
    snprintf(p->error_msg_, MAX_ERROR_MSG, "Input SQL can not be empty");
 | 
			
		||||
    ret = OB_PARSER_ERR_EMPTY_QUERY;
 | 
			
		||||
  } else {
 | 
			
		||||
    p->result_tree_ = 0;
 | 
			
		||||
    p->error_msg_[0] = 0;
 | 
			
		||||
    p->input_sql_ = buf;
 | 
			
		||||
    p->input_sql_len_ = len;
 | 
			
		||||
    p->start_col_ = 1;
 | 
			
		||||
    p->end_col_ = 1;
 | 
			
		||||
    p->line_ = 1;
 | 
			
		||||
    p->yycolumn_ = 1;
 | 
			
		||||
    p->yylineno_ = 1;
 | 
			
		||||
    p->tmp_literal_ = NULL;
 | 
			
		||||
    p->last_well_formed_len_ = 0;
 | 
			
		||||
#ifdef SQL_PARSER_COMPILATION
 | 
			
		||||
    p->realloc_cnt_ = p->realloc_cnt_ <= 0 ? 10 : p->realloc_cnt_;
 | 
			
		||||
    p->comment_cap_ = p->realloc_cnt_;
 | 
			
		||||
    p->comment_cnt_ = 0;
 | 
			
		||||
    p->stop_add_comment_ = false;
 | 
			
		||||
#endif
 | 
			
		||||
    if (false == p->pl_parse_info_.is_pl_parse_) {
 | 
			
		||||
      p->question_mark_ctx_.count_ = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // while (len > 0 && ISSPACE(buf[len - 1])) {
 | 
			
		||||
    //  --len;
 | 
			
		||||
    // }
 | 
			
		||||
 | 
			
		||||
    // if (OB_UNLIKELY(len <= 0)) {
 | 
			
		||||
    // (void)snprintf(p->error_msg_, MAX_ERROR_MSG, "Input SQL can not be white space only");
 | 
			
		||||
    //  ret = OB_PARSER_ERR_EMPTY_QUERY;
 | 
			
		||||
    //  } else {
 | 
			
		||||
    {
 | 
			
		||||
      int val = setjmp(p->jmp_buf_);
 | 
			
		||||
      if (val) {
 | 
			
		||||
        ret = OB_PARSER_ERR_NO_MEMORY;
 | 
			
		||||
#ifdef SQL_PARSER_COMPILATION
 | 
			
		||||
      } else if (OB_ISNULL(p->comment_list_ = (TokenPosInfo*)(parse_malloc(
 | 
			
		||||
                               p->realloc_cnt_ * sizeof(TokenPosInfo), p->malloc_pool_)))) {
 | 
			
		||||
        ret = OB_PARSER_ERR_NO_MEMORY;
 | 
			
		||||
#endif
 | 
			
		||||
      } else {
 | 
			
		||||
        // bp = yy_scan_string(buf, p->yyscan_info_);
 | 
			
		||||
        YY_BUFFER_STATE bp = obsql_mysql_yy_scan_bytes(buf, len, p->yyscan_info_);
 | 
			
		||||
        obsql_mysql_yy_switch_to_buffer(bp, p->yyscan_info_);
 | 
			
		||||
        int tmp_ret = -1;
 | 
			
		||||
        if (p->is_fp_) {
 | 
			
		||||
          tmp_ret = obsql_mysql_fast_parse(p);
 | 
			
		||||
        } else if (p->is_multi_query_) {
 | 
			
		||||
          tmp_ret = obsql_mysql_multi_fast_parse(p);
 | 
			
		||||
        } else {
 | 
			
		||||
          tmp_ret = obsql_mysql_yyparse(p);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (0 == tmp_ret) {
 | 
			
		||||
          ret = OB_PARSER_SUCCESS;
 | 
			
		||||
        } else if (2 == tmp_ret) {
 | 
			
		||||
          ret = OB_PARSER_ERR_NO_MEMORY;
 | 
			
		||||
        } else {
 | 
			
		||||
          if (0 != p->extra_errno_) {
 | 
			
		||||
            ret = p->extra_errno_;
 | 
			
		||||
          } else {
 | 
			
		||||
            ret = OB_PARSER_ERR_PARSE_SQL;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        obsql_mysql_yy_delete_buffer(bp, p->yyscan_info_);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int parse_sql_stmt(ParseResult* parse_result)
 | 
			
		||||
{
 | 
			
		||||
  int ret = -1;
 | 
			
		||||
  if (0 != (ret = parse_init(parse_result))) {
 | 
			
		||||
    // fix bug #16298144
 | 
			
		||||
    // fprintf(stderr, "init parse result failed, ret=%d\n", ret);
 | 
			
		||||
  } else if (0 != (ret = parse_sql(parse_result, parse_result->input_sql_, parse_result->input_sql_len_))) {
 | 
			
		||||
    // fix bug #16298144
 | 
			
		||||
    // fprintf(stderr, "parse sql failed, ret=%d, input_sql=%.*s\n", ret, parse_result->input_sql_len_,
 | 
			
		||||
    // parse_result->input_sql_);
 | 
			
		||||
  }
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void setup_token_pos_info(ParseNode* node, int off, int len)
 | 
			
		||||
{
 | 
			
		||||
#ifdef SQL_PARSER_COMPILATION
 | 
			
		||||
  node->token_off_ = off;
 | 
			
		||||
  node->token_len_ = len;
 | 
			
		||||
#else
 | 
			
		||||
  // do nothing
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int setup_token_pos_info_and_dup_string(ParseNode* node, ParseResult* result, int start, int end)
 | 
			
		||||
{
 | 
			
		||||
  int ret = OB_PARSER_SUCCESS;
 | 
			
		||||
#ifdef SQL_PARSER_COMPILATION
 | 
			
		||||
  node->token_off_ = start - 1;
 | 
			
		||||
  node->token_len_ = end - start + 1;
 | 
			
		||||
  if (start > end) {
 | 
			
		||||
    ret = OB_PARSER_ERR_UNEXPECTED;
 | 
			
		||||
  } else if (OB_UNLIKELY((NULL == (node->str_value_ = copy_expr_string(result, start, end))))) {
 | 
			
		||||
    ret = OB_PARSER_ERR_NO_MEMORY;
 | 
			
		||||
  } else {
 | 
			
		||||
    node->str_len_ = end - start + 1;
 | 
			
		||||
  }
 | 
			
		||||
#else
 | 
			
		||||
  // do nothing
 | 
			
		||||
#endif
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef SQL_PARSER_COMPILATION
 | 
			
		||||
int add_comment_list(ParseResult* p, const TokenPosInfo* info)
 | 
			
		||||
{
 | 
			
		||||
  int ret = OB_PARSER_SUCCESS;
 | 
			
		||||
  if (OB_ISNULL(p) || OB_ISNULL(info)) {
 | 
			
		||||
    ret = OB_PARSER_ERR_UNEXPECTED;
 | 
			
		||||
  }
 | 
			
		||||
  if (OB_PARSER_SUCCESS == ret && p->comment_cnt_ + 1 >= p->comment_cap_) {
 | 
			
		||||
    int alloc_cnt = p->comment_cnt_ + p->realloc_cnt_;
 | 
			
		||||
    char* buf = parse_malloc(sizeof(TokenPosInfo) * alloc_cnt, p->malloc_pool_);
 | 
			
		||||
    if (OB_ISNULL(buf)) {
 | 
			
		||||
      ret = OB_PARSER_ERR_NO_MEMORY;
 | 
			
		||||
    } else {
 | 
			
		||||
      memset(buf, 0, sizeof(TokenPosInfo) * alloc_cnt);
 | 
			
		||||
      memcpy(buf, (void*)(p->comment_list_), sizeof(TokenPosInfo) * p->comment_cnt_);
 | 
			
		||||
      p->comment_list_ = (TokenPosInfo*)buf;
 | 
			
		||||
      p->comment_cap_ += p->realloc_cnt_;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  if (OB_PARSER_SUCCESS == ret) {
 | 
			
		||||
    p->comment_list_[p->comment_cnt_].token_off_ = info->token_off_;
 | 
			
		||||
    p->comment_list_[p->comment_cnt_].token_len_ = info->token_len_;
 | 
			
		||||
    p->comment_cnt_ += 1;
 | 
			
		||||
  }
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										742
									
								
								src/sql/parser/sql_parser_base.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										742
									
								
								src/sql/parser/sql_parser_base.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,742 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Copyright (c) 2021 OceanBase
 | 
			
		||||
 * OceanBase CE is licensed under Mulan PubL v2.
 | 
			
		||||
 * You can use this software according to the terms and conditions of the Mulan PubL v2.
 | 
			
		||||
 * You may obtain a copy of Mulan PubL v2 at:
 | 
			
		||||
 *          http://license.coscl.org.cn/MulanPubL-2.0
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 | 
			
		||||
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 | 
			
		||||
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 | 
			
		||||
 * See the Mulan PubL v2 for more details.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef OCEANBASE_SRC_SQL_PARSER_SQL_PARSER_BASE_H_
 | 
			
		||||
#define OCEANBASE_SRC_SQL_PARSER_SQL_PARSER_BASE_H_
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
#include <time.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdarg.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <ctype.h>
 | 
			
		||||
#include "lib/charset/ob_ctype.h"
 | 
			
		||||
#include "lib/ob_date_unit_type.h"
 | 
			
		||||
#include "share/schema/ob_priv_type.h"
 | 
			
		||||
#include "sql/ob_trans_character.h"
 | 
			
		||||
#include "parse_node.h"
 | 
			
		||||
#include "parse_malloc.h"
 | 
			
		||||
#include "ob_non_reserved_keywords.h"
 | 
			
		||||
#include "parse_define.h"
 | 
			
		||||
#include <math.h>
 | 
			
		||||
 | 
			
		||||
#define MAX_VARCHAR_LENGTH 4194303
 | 
			
		||||
#define INT16NUM_OVERFLOW INT16_MAX
 | 
			
		||||
#define OUT_OF_STR_LEN -2
 | 
			
		||||
#define DEFAULT_STR_LENGTH -1
 | 
			
		||||
#define BINARY_COLLATION 63
 | 
			
		||||
#define INVALID_COLLATION 0
 | 
			
		||||
#define INVALID_INDEX -1
 | 
			
		||||
 | 
			
		||||
#define YYLEX_PARAM result->yyscan_info_
 | 
			
		||||
 | 
			
		||||
#define JOIN_MERGE_NODES(node1, node2)                       \
 | 
			
		||||
  do {                                                       \
 | 
			
		||||
    if (T_LINK_NODE == node1->type_) {                       \
 | 
			
		||||
      merge_nodes(node1, result, T_TABLE_REFERENCES, node1); \
 | 
			
		||||
    }                                                        \
 | 
			
		||||
    if (T_LINK_NODE == node2->type_) {                       \
 | 
			
		||||
      merge_nodes(node2, result, T_TABLE_REFERENCES, node2); \
 | 
			
		||||
    }                                                        \
 | 
			
		||||
  } while (0)
 | 
			
		||||
 | 
			
		||||
extern void yyerror(void* yylloc, ParseResult* p, char* s, ...);
 | 
			
		||||
extern ParseNode* merge_tree(void* malloc_pool, int* fatal_error, ObItemType node_tag, ParseNode* source_tree);
 | 
			
		||||
extern ParseNode* new_terminal_node(void* malloc_pool, ObItemType type);
 | 
			
		||||
extern ParseNode* new_non_terminal_node(void* malloc_pool, ObItemType node_tag, int num, ...);
 | 
			
		||||
extern char* copy_expr_string(ParseResult* p, int expr_start, int expr_end);
 | 
			
		||||
 | 
			
		||||
#define ISSPACE(c) ((c) == ' ' || (c) == '\n' || (c) == '\r' || (c) == '\t' || (c) == '\f' || (c) == '\v')
 | 
			
		||||
 | 
			
		||||
#define YYABORT_NO_MEMORY                                \
 | 
			
		||||
  do {                                                   \
 | 
			
		||||
    if (OB_UNLIKELY(NULL == result)) {                   \
 | 
			
		||||
      (void)fprintf(stderr, "ERROR : result is NULL\n"); \
 | 
			
		||||
    } else if (0 == result->extra_errno_) {              \
 | 
			
		||||
      result->extra_errno_ = OB_PARSER_ERR_NO_MEMORY;    \
 | 
			
		||||
    } else { /*do nothing*/                              \
 | 
			
		||||
    }                                                    \
 | 
			
		||||
    YYABORT;                                             \
 | 
			
		||||
  } while (0)
 | 
			
		||||
 | 
			
		||||
#define YYABORT_UNEXPECTED                               \
 | 
			
		||||
  do {                                                   \
 | 
			
		||||
    if (OB_UNLIKELY(NULL == result)) {                   \
 | 
			
		||||
      (void)fprintf(stderr, "ERROR : result is NULL\n"); \
 | 
			
		||||
    } else if (0 == result->extra_errno_) {              \
 | 
			
		||||
      result->extra_errno_ = OB_PARSER_ERR_UNEXPECTED;   \
 | 
			
		||||
    } else { /*do nothing*/                              \
 | 
			
		||||
    }                                                    \
 | 
			
		||||
    YYABORT;                                             \
 | 
			
		||||
  } while (0)
 | 
			
		||||
 | 
			
		||||
#define YYABORT_PARSE_SQL_ERROR YYERROR
 | 
			
		||||
 | 
			
		||||
#define malloc_terminal_node(node, malloc_pool, type)                         \
 | 
			
		||||
  do {                                                                        \
 | 
			
		||||
    if (OB_UNLIKELY(NULL == (node = new_terminal_node(malloc_pool, type)))) { \
 | 
			
		||||
      yyerror(NULL, result, "No more space for malloc\n");                    \
 | 
			
		||||
      YYABORT_NO_MEMORY;                                                      \
 | 
			
		||||
    }                                                                         \
 | 
			
		||||
  } while (0)
 | 
			
		||||
 | 
			
		||||
#define malloc_non_terminal_node(node, malloc_pool, node_tag, ...)                                   \
 | 
			
		||||
  do {                                                                                               \
 | 
			
		||||
    if (OB_UNLIKELY(NULL == (node = new_non_terminal_node(malloc_pool, node_tag, ##__VA_ARGS__)))) { \
 | 
			
		||||
      yyerror(NULL, result, "No more space for malloc\n");                                           \
 | 
			
		||||
      YYABORT_NO_MEMORY;                                                                             \
 | 
			
		||||
    }                                                                                                \
 | 
			
		||||
  } while (0)
 | 
			
		||||
 | 
			
		||||
#define merge_nodes(node, result, node_tag, source_tree)                                                           \
 | 
			
		||||
  do {                                                                                                             \
 | 
			
		||||
    if (OB_UNLIKELY(NULL == source_tree)) {                                                                        \
 | 
			
		||||
      node = NULL;                                                                                                 \
 | 
			
		||||
    } else if (OB_UNLIKELY(NULL == (node = merge_tree(                                                             \
 | 
			
		||||
                                        result->malloc_pool_, &(result->extra_errno_), node_tag, source_tree)))) { \
 | 
			
		||||
      yyerror(NULL, result, "No more space for merging nodes\n");                                                  \
 | 
			
		||||
      YYABORT_NO_MEMORY;                                                                                           \
 | 
			
		||||
    }                                                                                                              \
 | 
			
		||||
  } while (0)
 | 
			
		||||
 | 
			
		||||
#define dup_expr_string(node, result, expr_start, expr_end)                                                            \
 | 
			
		||||
  do {                                                                                                                 \
 | 
			
		||||
    if (OB_UNLIKELY(NULL == node || NULL == result || NULL == result->input_sql_)) {                                   \
 | 
			
		||||
      yyerror(NULL, result, "invalid argument, node:%p, result:%p or input_sql is NULL\n", node, result);              \
 | 
			
		||||
      YYABORT_UNEXPECTED;                                                                                              \
 | 
			
		||||
    } else if (OB_UNLIKELY(expr_start < 0 || expr_end < 0 || expr_start > expr_end)) {                                 \
 | 
			
		||||
      yyerror(NULL, result, "invalid argument, expr_start:%d, expr_end:%d\n", (int32_t)expr_start, (int32_t)expr_end); \
 | 
			
		||||
      YYABORT_UNEXPECTED;                                                                                              \
 | 
			
		||||
    } else {                                                                                                           \
 | 
			
		||||
      int start = expr_start;                                                                                          \
 | 
			
		||||
      node->str_value_ = NULL;                                                                                         \
 | 
			
		||||
      node->str_len_ = 0;                                                                                              \
 | 
			
		||||
      while (start <= expr_end && ISSPACE(result->input_sql_[start - 1])) {                                            \
 | 
			
		||||
        start++;                                                                                                       \
 | 
			
		||||
      }                                                                                                                \
 | 
			
		||||
      if (start >= expr_start &&                                                                                       \
 | 
			
		||||
          (OB_UNLIKELY((NULL == (node->str_value_ = copy_expr_string(result, start, expr_end)))))) {                   \
 | 
			
		||||
        yyerror(NULL, result, "No more space for copying expression string\n");                                        \
 | 
			
		||||
        YYABORT_NO_MEMORY;                                                                                             \
 | 
			
		||||
      } else {                                                                                                         \
 | 
			
		||||
        node->str_len_ = expr_end - start + 1;                                                                         \
 | 
			
		||||
      }                                                                                                                \
 | 
			
		||||
    }                                                                                                                  \
 | 
			
		||||
  } while (0)
 | 
			
		||||
 | 
			
		||||
#define dup_string(node, result, start, end)                                                               \
 | 
			
		||||
  if (start > end || (OB_UNLIKELY((NULL == (node->str_value_ = copy_expr_string(result, start, end)))))) { \
 | 
			
		||||
    yyerror(NULL, result, "No more space for copying expression string\n");                                \
 | 
			
		||||
    YYABORT_NO_MEMORY;                                                                                     \
 | 
			
		||||
  } else {                                                                                                 \
 | 
			
		||||
    node->str_len_ = end - start + 1;                                                                      \
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
#define dup_modify_key_string(node, result, expr_start, expr_end, prefix)                                              \
 | 
			
		||||
  do {                                                                                                                 \
 | 
			
		||||
    if (OB_UNLIKELY(NULL == node || NULL == result || NULL == result->input_sql_)) {                                   \
 | 
			
		||||
      yyerror(NULL, result, "invalid argument, node:%p, result:%p or input_sql is NULL\n", node, result);              \
 | 
			
		||||
      YYABORT_UNEXPECTED;                                                                                              \
 | 
			
		||||
    } else if (OB_UNLIKELY(expr_start < 0 || expr_end < 0 || expr_start > expr_end)) {                                 \
 | 
			
		||||
      yyerror(NULL, result, "invalid argument, expr_start:%d, expr_end:%d\n", (int32_t)expr_start, (int32_t)expr_end); \
 | 
			
		||||
      YYABORT_UNEXPECTED;                                                                                              \
 | 
			
		||||
    } else {                                                                                                           \
 | 
			
		||||
      int start = expr_start;                                                                                          \
 | 
			
		||||
      node->str_value_ = NULL;                                                                                         \
 | 
			
		||||
      node->str_len_ = 0;                                                                                              \
 | 
			
		||||
      while (start <= expr_end && ISSPACE(result->input_sql_[start - 1])) {                                            \
 | 
			
		||||
        start++;                                                                                                       \
 | 
			
		||||
      }                                                                                                                \
 | 
			
		||||
      int len = expr_end - start + sizeof(prefix);                                                                     \
 | 
			
		||||
      char* expr_string = (char*)parse_malloc(len + 1, result->malloc_pool_);                                          \
 | 
			
		||||
      if (OB_UNLIKELY(NULL == expr_string)) {                                                                          \
 | 
			
		||||
        yyerror(NULL, result, "No more space for copying expression string\n");                                        \
 | 
			
		||||
        YYABORT_NO_MEMORY;                                                                                             \
 | 
			
		||||
      } else {                                                                                                         \
 | 
			
		||||
        memmove(expr_string, (prefix), strlen(prefix));                                                                \
 | 
			
		||||
        memmove(expr_string + strlen(prefix), result->input_sql_ + start - 1, expr_end - start + 1);                   \
 | 
			
		||||
        expr_string[len] = '\0';                                                                                       \
 | 
			
		||||
        node->str_value_ = expr_string;                                                                                \
 | 
			
		||||
        node->str_len_ = len;                                                                                          \
 | 
			
		||||
      }                                                                                                                \
 | 
			
		||||
    }                                                                                                                  \
 | 
			
		||||
  } while (0)
 | 
			
		||||
 | 
			
		||||
#define get_non_reserved_node(node, malloc_pool, word_start, word_end)     \
 | 
			
		||||
  do {                                                                     \
 | 
			
		||||
    malloc_terminal_node(node, malloc_pool, T_IDENT);                      \
 | 
			
		||||
    dup_expr_string(node, result, word_start, word_end);                   \
 | 
			
		||||
    setup_token_pos_info(node, word_start - 1, word_end - word_start + 1); \
 | 
			
		||||
  } while (0)
 | 
			
		||||
 | 
			
		||||
#define make_name_node(node, malloc_pool, name)                            \
 | 
			
		||||
  do {                                                                     \
 | 
			
		||||
    malloc_terminal_node(node, malloc_pool, T_IDENT);                      \
 | 
			
		||||
    node->str_value_ = parse_strdup(name, malloc_pool, &(node->str_len_)); \
 | 
			
		||||
    if (OB_UNLIKELY(NULL == node->str_value_)) {                           \
 | 
			
		||||
      yyerror(NULL, result, "No more space for string duplicate\n");       \
 | 
			
		||||
      YYABORT_NO_MEMORY;                                                   \
 | 
			
		||||
    }                                                                      \
 | 
			
		||||
  } while (0)
 | 
			
		||||
 | 
			
		||||
#define dup_string_to_node(node, malloc_pool, name)                          \
 | 
			
		||||
  do {                                                                       \
 | 
			
		||||
    if (OB_UNLIKELY(NULL == node)) {                                         \
 | 
			
		||||
      yyerror(NULL, result, "invalid arguments node: %p\n", node);           \
 | 
			
		||||
      YYABORT_UNEXPECTED;                                                    \
 | 
			
		||||
    } else {                                                                 \
 | 
			
		||||
      node->str_value_ = parse_strdup(name, malloc_pool, &(node->str_len_)); \
 | 
			
		||||
      if (OB_UNLIKELY(NULL == node->str_value_)) {                           \
 | 
			
		||||
        yyerror(NULL, result, "No more space for string duplicate\n");       \
 | 
			
		||||
        YYABORT_NO_MEMORY;                                                   \
 | 
			
		||||
      }                                                                      \
 | 
			
		||||
    }                                                                        \
 | 
			
		||||
  } while (0)
 | 
			
		||||
 | 
			
		||||
#define dup_node_string(node_src, node_dest, malloc_pool)                                            \
 | 
			
		||||
  do {                                                                                               \
 | 
			
		||||
    if (OB_UNLIKELY((NULL == node_src || NULL == node_dest || NULL == node_src->str_value_))) {      \
 | 
			
		||||
      yyerror(NULL, result, "invalid arguments node_src: %p, node_dest: %p\n", node_src, node_dest); \
 | 
			
		||||
      YYABORT_UNEXPECTED;                                                                            \
 | 
			
		||||
    } else {                                                                                         \
 | 
			
		||||
      node_dest->str_value_ = parse_strndup(node_src->str_value_, node_src->str_len_, malloc_pool);  \
 | 
			
		||||
      if (OB_UNLIKELY(NULL == node_dest->str_value_)) {                                              \
 | 
			
		||||
        yyerror(NULL, result, "No more space for dup_node_string\n");                                \
 | 
			
		||||
        YYABORT_NO_MEMORY;                                                                           \
 | 
			
		||||
      } else {                                                                                       \
 | 
			
		||||
        node_dest->str_len_ = node_src->str_len_;                                                    \
 | 
			
		||||
      }                                                                                              \
 | 
			
		||||
    }                                                                                                \
 | 
			
		||||
  } while (0)
 | 
			
		||||
 | 
			
		||||
/* to minimize modification, we use stmt->value_ as question mark size */
 | 
			
		||||
#define question_mark_issue(node, result)                     \
 | 
			
		||||
  do {                                                        \
 | 
			
		||||
    if (OB_UNLIKELY(NULL == node || NULL == result)) {        \
 | 
			
		||||
      yyerror(NULL, result, "node or result is NULL\n");      \
 | 
			
		||||
      YYABORT_UNEXPECTED;                                     \
 | 
			
		||||
    } else if (OB_UNLIKELY(INT64_MAX != node->value_)) {      \
 | 
			
		||||
      yyerror(NULL, result, "node value is not INT64_MAX\n"); \
 | 
			
		||||
      YYABORT_UNEXPECTED;                                     \
 | 
			
		||||
    } else {                                                  \
 | 
			
		||||
      node->value_ = result->question_mark_ctx_.count_;       \
 | 
			
		||||
    }                                                         \
 | 
			
		||||
  } while (0)
 | 
			
		||||
 | 
			
		||||
#define check_question_mark(node, result)                                                                     \
 | 
			
		||||
  do {                                                                                                        \
 | 
			
		||||
    if (OB_UNLIKELY(NULL == node || NULL == result)) {                                                        \
 | 
			
		||||
      yyerror(NULL, result, "node or result is NULL\n");                                                      \
 | 
			
		||||
      YYABORT_UNEXPECTED;                                                                                     \
 | 
			
		||||
    } else if (OB_UNLIKELY(!result->pl_parse_info_.is_pl_parse_ && 0 != result->question_mark_ctx_.count_)) { \
 | 
			
		||||
      yyerror(NULL, result, "Unknown column '?'\n");                                                          \
 | 
			
		||||
      YYABORT_UNEXPECTED;                                                                                     \
 | 
			
		||||
    } else {                                                                                                  \
 | 
			
		||||
      node->value_ = result->question_mark_ctx_.count_;                                                       \
 | 
			
		||||
    }                                                                                                         \
 | 
			
		||||
  } while (0)
 | 
			
		||||
 | 
			
		||||
#define store_pl_symbol(node, head, tail)                                                 \
 | 
			
		||||
  do {                                                                                    \
 | 
			
		||||
    ParamList* param = (ParamList*)parse_malloc(sizeof(ParamList), result->malloc_pool_); \
 | 
			
		||||
    if (OB_UNLIKELY(NULL == param)) {                                                     \
 | 
			
		||||
      yyerror(NULL, result, "No more space for alloc ParamList\n");                       \
 | 
			
		||||
      YYABORT_NO_MEMORY;                                                                  \
 | 
			
		||||
    } else {                                                                              \
 | 
			
		||||
      param->node_ = node;                                                                \
 | 
			
		||||
      param->next_ = NULL;                                                                \
 | 
			
		||||
      if (NULL == head) {                                                                 \
 | 
			
		||||
        head = param;                                                                     \
 | 
			
		||||
      } else {                                                                            \
 | 
			
		||||
        tail->next_ = param;                                                              \
 | 
			
		||||
      }                                                                                   \
 | 
			
		||||
      tail = param;                                                                       \
 | 
			
		||||
    }                                                                                     \
 | 
			
		||||
  } while (0)
 | 
			
		||||
 | 
			
		||||
#define copy_and_replace_questionmark(result, start, end, idx)                                                       \
 | 
			
		||||
  do {                                                                                                               \
 | 
			
		||||
    if (NULL == result) {                                                                                            \
 | 
			
		||||
      YY_FATAL_ERROR("invalid var node\n");                                                                          \
 | 
			
		||||
    } else if ((result->pl_parse_info_.is_pl_parse_ && NULL == result->pl_parse_info_.pl_ns_) ||                     \
 | 
			
		||||
               result->is_dynamic_sql_) {                                                                            \
 | 
			
		||||
      if (result->no_param_sql_len_ + (start - result->pl_parse_info_.last_pl_symbol_pos_ - 1) + (int)(log10(idx)) + \
 | 
			
		||||
              3 >                                                                                                    \
 | 
			
		||||
          result->no_param_sql_buf_len_) {                                                                           \
 | 
			
		||||
        char* buf = parse_malloc(result->no_param_sql_buf_len_ * 2, result->malloc_pool_);                           \
 | 
			
		||||
        if (OB_UNLIKELY(NULL == buf)) {                                                                              \
 | 
			
		||||
          YY_FATAL_ERROR("no memory to alloc\n");                                                                    \
 | 
			
		||||
        } else {                                                                                                     \
 | 
			
		||||
          memmove(buf, result->no_param_sql_, result->no_param_sql_len_);                                            \
 | 
			
		||||
          result->no_param_sql_ = buf;                                                                               \
 | 
			
		||||
          result->no_param_sql_buf_len_ = result->no_param_sql_buf_len_ * 2;                                         \
 | 
			
		||||
        }                                                                                                            \
 | 
			
		||||
      }                                                                                                              \
 | 
			
		||||
      memmove(result->no_param_sql_ + result->no_param_sql_len_,                                                     \
 | 
			
		||||
          result->input_sql_ + result->pl_parse_info_.last_pl_symbol_pos_,                                           \
 | 
			
		||||
          start - result->pl_parse_info_.last_pl_symbol_pos_ - 1);                                                   \
 | 
			
		||||
      result->no_param_sql_len_ += start - result->pl_parse_info_.last_pl_symbol_pos_ - 1;                           \
 | 
			
		||||
      result->pl_parse_info_.last_pl_symbol_pos_ = end;                                                              \
 | 
			
		||||
      result->no_param_sql_[result->no_param_sql_len_++] = ':';                                                      \
 | 
			
		||||
      result->no_param_sql_len_ += sprintf(result->no_param_sql_ + result->no_param_sql_len_, "%ld", idx);           \
 | 
			
		||||
    }                                                                                                                \
 | 
			
		||||
  } while (0)
 | 
			
		||||
 | 
			
		||||
#define copy_and_skip_symbol(result, start, end)                                           \
 | 
			
		||||
  do {                                                                                     \
 | 
			
		||||
    if (NULL == result) {                                                                  \
 | 
			
		||||
      yyerror(NULL, result, "invalid var node\n");                                         \
 | 
			
		||||
      YYABORT_UNEXPECTED;                                                                  \
 | 
			
		||||
    } else if (NULL == result->pl_parse_info_.pl_ns_) {                                    \
 | 
			
		||||
    } else {                                                                               \
 | 
			
		||||
      memmove(result->no_param_sql_ + result->no_param_sql_len_,                           \
 | 
			
		||||
          result->input_sql_ + result->pl_parse_info_.last_pl_symbol_pos_,                 \
 | 
			
		||||
          start - result->pl_parse_info_.last_pl_symbol_pos_ - 1);                         \
 | 
			
		||||
      result->no_param_sql_len_ += start - result->pl_parse_info_.last_pl_symbol_pos_ - 1; \
 | 
			
		||||
      result->pl_parse_info_.last_pl_symbol_pos_ = end;                                    \
 | 
			
		||||
    }                                                                                      \
 | 
			
		||||
  } while (0)
 | 
			
		||||
 | 
			
		||||
#define store_pl_ref_object_symbol(node, result, type)                                          \
 | 
			
		||||
  do {                                                                                          \
 | 
			
		||||
    if (OB_UNLIKELY((NULL == node || NULL == result))) {                                        \
 | 
			
		||||
      yyerror(NULL, result, "invalid var node: %p\n", node);                                    \
 | 
			
		||||
      YYABORT_UNEXPECTED;                                                                       \
 | 
			
		||||
    } else if (NULL == result->pl_parse_info_.pl_ns_) {                                         \
 | 
			
		||||
    } else {                                                                                    \
 | 
			
		||||
      RefObjList* object = (RefObjList*)parse_malloc(sizeof(RefObjList), result->malloc_pool_); \
 | 
			
		||||
      if (OB_UNLIKELY(NULL == object)) {                                                        \
 | 
			
		||||
        yyerror(NULL, result, "No more space for alloc ParamList\n");                           \
 | 
			
		||||
        YYABORT_NO_MEMORY;                                                                      \
 | 
			
		||||
      } else {                                                                                  \
 | 
			
		||||
        object->type_ = type;                                                                   \
 | 
			
		||||
        object->node_ = node;                                                                   \
 | 
			
		||||
        object->next_ = NULL;                                                                   \
 | 
			
		||||
        if (NULL == result->pl_parse_info_.ref_object_nodes_) {                                 \
 | 
			
		||||
          result->pl_parse_info_.ref_object_nodes_ = object;                                    \
 | 
			
		||||
        } else {                                                                                \
 | 
			
		||||
          result->pl_parse_info_.tail_ref_object_node_->next_ = object;                         \
 | 
			
		||||
        }                                                                                       \
 | 
			
		||||
        result->pl_parse_info_.tail_ref_object_node_ = object;                                  \
 | 
			
		||||
      }                                                                                         \
 | 
			
		||||
    }                                                                                           \
 | 
			
		||||
  } while (0)
 | 
			
		||||
 | 
			
		||||
#define process_placeholder_for_dynamic                                                          \
 | 
			
		||||
  do {                                                                                           \
 | 
			
		||||
    if (p->pl_parse_info_.is_pl_parse_) {                                                        \
 | 
			
		||||
      yylval->node->value_ = get_question_mark(&p->question_mark_ctx_, p->malloc_pool_, yytext); \
 | 
			
		||||
    } else {                                                                                     \
 | 
			
		||||
      yylval->node->value_ = p->question_mark_ctx_.count_++;                                     \
 | 
			
		||||
    }                                                                                            \
 | 
			
		||||
  } while (0)
 | 
			
		||||
 | 
			
		||||
//////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
#define YY_USER_ACTION                                       \
 | 
			
		||||
  do {                                                       \
 | 
			
		||||
    check_value(yylloc);                                     \
 | 
			
		||||
    ParseResult* p = (ParseResult*)yyextra;                  \
 | 
			
		||||
    yylloc->first_line = yylloc->last_line = yylineno;       \
 | 
			
		||||
    yylloc->first_column = p->yycolumn_;                     \
 | 
			
		||||
    yylloc->last_column = yylloc->first_column + yyleng - 1; \
 | 
			
		||||
    p->yycolumn_ += yyleng;                                  \
 | 
			
		||||
  } while (0);
 | 
			
		||||
 | 
			
		||||
extern ParseNode* new_node(void* malloc_pool, ObItemType type, int num);
 | 
			
		||||
 | 
			
		||||
#define malloc_new_node(node, malloc_pool, type, num)                         \
 | 
			
		||||
  do {                                                                        \
 | 
			
		||||
    if (OB_UNLIKELY(NULL == (node = new_node(malloc_pool, type, num)))) {     \
 | 
			
		||||
      ((ParseResult*)yyextra)->extra_errno_ = OB_PARSER_ERR_NO_MEMORY;        \
 | 
			
		||||
      yyerror(yylloc, yyextra, "No more space for mallocing '%s'\n", yytext); \
 | 
			
		||||
      return ERROR;                                                           \
 | 
			
		||||
    }                                                                         \
 | 
			
		||||
  } while (0);
 | 
			
		||||
 | 
			
		||||
#define malloc_time_node(malloc_pool, type, find_char) \
 | 
			
		||||
  do {                                                 \
 | 
			
		||||
    ParseNode* node = NULL;                            \
 | 
			
		||||
    malloc_new_node(node, malloc_pool, type, 0);       \
 | 
			
		||||
    char* begin = strchr(yytext, find_char);           \
 | 
			
		||||
    check_value(begin);                                \
 | 
			
		||||
    char* end = strchr(begin + 1, find_char);          \
 | 
			
		||||
    check_value(end);                                  \
 | 
			
		||||
    char* dest = NULL;                                 \
 | 
			
		||||
    size_t len = end - begin - 1;                      \
 | 
			
		||||
    dest = parse_strndup(begin + 1, len, malloc_pool); \
 | 
			
		||||
    check_value(dest);                                 \
 | 
			
		||||
    node->str_value_ = dest;                           \
 | 
			
		||||
    node->str_len_ = len;                              \
 | 
			
		||||
    check_value(yylval);                               \
 | 
			
		||||
    yylval->node = node;                               \
 | 
			
		||||
  } while (0);
 | 
			
		||||
 | 
			
		||||
#define malloc_time_node_s(malloc_pool, type) malloc_time_node(malloc_pool, type, '\'');
 | 
			
		||||
#define malloc_time_node_d(malloc_pool, type) malloc_time_node(malloc_pool, type, '\"');
 | 
			
		||||
 | 
			
		||||
#define check_value(val_ptr)                                            \
 | 
			
		||||
  do {                                                                  \
 | 
			
		||||
    if (OB_UNLIKELY(NULL == val_ptr)) {                                 \
 | 
			
		||||
      ((ParseResult*)yyextra)->extra_errno_ = OB_PARSER_ERR_UNEXPECTED; \
 | 
			
		||||
      yyerror(yylloc, yyextra, "'%s' is NULL\n", #val_ptr);             \
 | 
			
		||||
      return ERROR;                                                     \
 | 
			
		||||
    }                                                                   \
 | 
			
		||||
  } while (0);
 | 
			
		||||
 | 
			
		||||
#define check_malloc(val_ptr, nbyte)                                                    \
 | 
			
		||||
  do {                                                                                  \
 | 
			
		||||
    if (OB_UNLIKELY(NULL == val_ptr)) {                                                 \
 | 
			
		||||
      ((ParseResult*)yyextra)->extra_errno_ = OB_PARSER_ERR_NO_MEMORY;                  \
 | 
			
		||||
      yyerror(yylloc, yyextra, "No more space for malloc(size: %ld)\n", (size_t)nbyte); \
 | 
			
		||||
      return ERROR;                                                                     \
 | 
			
		||||
    }                                                                                   \
 | 
			
		||||
  } while (0);
 | 
			
		||||
 | 
			
		||||
#define check_identifier_convert_result(errno)                    \
 | 
			
		||||
  do {                                                            \
 | 
			
		||||
    if (OB_PARSER_ERR_ILLEGAL_NAME == errno) {                    \
 | 
			
		||||
      yyerror(yylloc, yyextra, "name '%s' is illegal\n", yytext); \
 | 
			
		||||
      return ERROR;                                               \
 | 
			
		||||
    }                                                             \
 | 
			
		||||
  } while (0);
 | 
			
		||||
 | 
			
		||||
#define IS_FAST_PARAMETERIZE ((ParseResult*)yyextra)->is_fp_
 | 
			
		||||
#define IS_NEED_PARAMETERIZE ((ParseResult*)yyextra)->need_parameterize_
 | 
			
		||||
#define IS_FOR_TRIGGER ((ParseResult*)yyextra)->is_for_trigger_
 | 
			
		||||
 | 
			
		||||
#define COPY_STRING(src, src_len, dst)                    \
 | 
			
		||||
  do {                                                    \
 | 
			
		||||
    if (IS_FAST_PARAMETERIZE && IS_NEED_PARAMETERIZE) {   \
 | 
			
		||||
      dst = src;                                          \
 | 
			
		||||
    } else {                                              \
 | 
			
		||||
      ParseResult* p = (ParseResult*)yyextra;             \
 | 
			
		||||
      dst = parse_strndup(src, src_len, p->malloc_pool_); \
 | 
			
		||||
      check_value(dst);                                   \
 | 
			
		||||
    }                                                     \
 | 
			
		||||
  } while (0);
 | 
			
		||||
 | 
			
		||||
#define COPY_STR_NODE_TO_TMP_LITERAL(str_node)                                                  \
 | 
			
		||||
  do {                                                                                          \
 | 
			
		||||
    ParseResult* p = (ParseResult*)yyextra;                                                     \
 | 
			
		||||
    char** tmp_literal = &(p->tmp_literal_);                                                    \
 | 
			
		||||
    if (NULL == *tmp_literal) {                                                                 \
 | 
			
		||||
      *tmp_literal = (char*)parse_malloc(p->input_sql_len_ + 1, p->malloc_pool_);               \
 | 
			
		||||
      check_value(*tmp_literal);                                                                \
 | 
			
		||||
    }                                                                                           \
 | 
			
		||||
    if (str_node->str_value_ != NULL) {                                                         \
 | 
			
		||||
      memmove(((ParseResult*)yyextra)->tmp_literal_, str_node->str_value_, str_node->str_len_); \
 | 
			
		||||
      str_node->str_value_ = NULL;                                                              \
 | 
			
		||||
    }                                                                                           \
 | 
			
		||||
  } while (0);
 | 
			
		||||
 | 
			
		||||
#define STORE_STR_CONTENT(str_node)                                                 \
 | 
			
		||||
  do {                                                                              \
 | 
			
		||||
    ParseResult* p = (ParseResult*)yyextra;                                         \
 | 
			
		||||
    if (str_node->str_len_ <= 0 && IS_FAST_PARAMETERIZE && IS_NEED_PARAMETERIZE) {  \
 | 
			
		||||
      str_node->str_value_ = p->input_sql_ + yylloc->first_column - 1;              \
 | 
			
		||||
      str_node->str_len_ = yyleng;                                                  \
 | 
			
		||||
    } else {                                                                        \
 | 
			
		||||
      char** tmp_literal = &(p->tmp_literal_);                                      \
 | 
			
		||||
      if (NULL == *tmp_literal) {                                                   \
 | 
			
		||||
        *tmp_literal = (char*)parse_malloc(p->input_sql_len_ + 1, p->malloc_pool_); \
 | 
			
		||||
        check_value(*tmp_literal);                                                  \
 | 
			
		||||
      }                                                                             \
 | 
			
		||||
      memmove(*tmp_literal + str_node->str_len_, yytext, yyleng);                   \
 | 
			
		||||
      str_node->str_len_ += yyleng;                                                 \
 | 
			
		||||
    }                                                                               \
 | 
			
		||||
  } while (0);
 | 
			
		||||
 | 
			
		||||
#define FORMAT_STR_NODE(str_node)                                                                 \
 | 
			
		||||
  do {                                                                                            \
 | 
			
		||||
    ParseResult* p = (ParseResult*)yyextra;                                                       \
 | 
			
		||||
    if (str_node->str_value_ == NULL && str_node->str_len_ > 0) {                                 \
 | 
			
		||||
      char* tmp_literal = p->tmp_literal_;                                                        \
 | 
			
		||||
      tmp_literal[yylval->node->str_len_] = '\0';                                                 \
 | 
			
		||||
      str_node->str_value_ = parse_strndup(tmp_literal, str_node->str_len_ + 1, p->malloc_pool_); \
 | 
			
		||||
      check_value(str_node->str_value_);                                                          \
 | 
			
		||||
    }                                                                                             \
 | 
			
		||||
  } while (0);
 | 
			
		||||
 | 
			
		||||
#define COPY_WRITE()                                                  \
 | 
			
		||||
  do {                                                                \
 | 
			
		||||
    ParseResult* p = (ParseResult*)yyextra;                           \
 | 
			
		||||
    memmove(p->no_param_sql_ + p->no_param_sql_len_, yytext, yyleng); \
 | 
			
		||||
    p->no_param_sql_len_ += yyleng;                                   \
 | 
			
		||||
    p->no_param_sql_[p->no_param_sql_len_] = '\0';                    \
 | 
			
		||||
  } while (0);
 | 
			
		||||
 | 
			
		||||
#define REPUT_NEG_SIGN(parse_result)                                                         \
 | 
			
		||||
  do {                                                                                       \
 | 
			
		||||
    if (parse_result->minus_ctx_.has_minus_) {                                               \
 | 
			
		||||
      int start_pos = parse_result->no_param_sql_len_;                                       \
 | 
			
		||||
      int end_pos = parse_result->minus_ctx_.pos_;                                           \
 | 
			
		||||
      for (; start_pos > end_pos; start_pos--) {                                             \
 | 
			
		||||
        parse_result->no_param_sql_[start_pos] = parse_result->no_param_sql_[start_pos - 1]; \
 | 
			
		||||
      }                                                                                      \
 | 
			
		||||
      parse_result->no_param_sql_[end_pos] = '-';                                            \
 | 
			
		||||
      parse_result->no_param_sql_[++parse_result->no_param_sql_len_] = '\0';                 \
 | 
			
		||||
      parse_result->minus_ctx_.pos_ = -1;                                                    \
 | 
			
		||||
      parse_result->minus_ctx_.raw_sql_offset_ = -1;                                         \
 | 
			
		||||
      parse_result->minus_ctx_.has_minus_ = false;                                           \
 | 
			
		||||
    }                                                                                        \
 | 
			
		||||
  } while (0);
 | 
			
		||||
 | 
			
		||||
#define STORE_PARAM_NODE()                                                                        \
 | 
			
		||||
  do {                                                                                            \
 | 
			
		||||
    ParseResult* p = (ParseResult*)yyextra;                                                       \
 | 
			
		||||
    if (p->need_parameterize_) {                                                                  \
 | 
			
		||||
      if (p->minus_ctx_.has_minus_ && p->minus_ctx_.is_cur_numeric_) {                            \
 | 
			
		||||
        p->no_param_sql_[p->minus_ctx_.pos_] = '?';                                               \
 | 
			
		||||
        p->no_param_sql_len_ = p->minus_ctx_.pos_ + 1;                                            \
 | 
			
		||||
      } else {                                                                                    \
 | 
			
		||||
        if (p->minus_ctx_.has_minus_) {                                                           \
 | 
			
		||||
          REPUT_NEG_SIGN(p);                                                                      \
 | 
			
		||||
        }                                                                                         \
 | 
			
		||||
        p->no_param_sql_[p->no_param_sql_len_++] = '?';                                           \
 | 
			
		||||
      }                                                                                           \
 | 
			
		||||
      p->no_param_sql_[p->no_param_sql_len_] = '\0';                                              \
 | 
			
		||||
      size_t alloc_len = sizeof(ParamList);                                                       \
 | 
			
		||||
      ParamList* param = (ParamList*)parse_malloc(alloc_len, p->malloc_pool_);                    \
 | 
			
		||||
      check_malloc(param, alloc_len);                                                             \
 | 
			
		||||
      check_value(yylval);                                                                        \
 | 
			
		||||
      check_value(yylval->node);                                                                  \
 | 
			
		||||
      yylval->node->pos_ = p->no_param_sql_len_ - 1;                                              \
 | 
			
		||||
      yylval->node->raw_sql_offset_ = (p->minus_ctx_.has_minus_ && p->minus_ctx_.is_cur_numeric_) \
 | 
			
		||||
                                          ? p->minus_ctx_.raw_sql_offset_                         \
 | 
			
		||||
                                          : yylloc->first_column - 1;                             \
 | 
			
		||||
      param->node_ = yylval->node;                                                                \
 | 
			
		||||
      param->next_ = NULL;                                                                        \
 | 
			
		||||
      if (NULL == p->param_nodes_) {                                                              \
 | 
			
		||||
        p->param_nodes_ = param;                                                                  \
 | 
			
		||||
      } else {                                                                                    \
 | 
			
		||||
        p->tail_param_node_->next_ = param;                                                       \
 | 
			
		||||
      }                                                                                           \
 | 
			
		||||
      p->tail_param_node_ = param;                                                                \
 | 
			
		||||
      p->param_node_num_++;                                                                       \
 | 
			
		||||
      p->token_num_++;                                                                            \
 | 
			
		||||
      p->minus_ctx_.has_minus_ = false;                                                           \
 | 
			
		||||
      p->minus_ctx_.pos_ = -1;                                                                    \
 | 
			
		||||
      p->minus_ctx_.is_cur_numeric_ = false;                                                      \
 | 
			
		||||
      p->minus_ctx_.raw_sql_offset_ = -1;                                                         \
 | 
			
		||||
    } else {                                                                                      \
 | 
			
		||||
      return OUTLINE_DEFAULT_TOKEN;                                                               \
 | 
			
		||||
    }                                                                                             \
 | 
			
		||||
  } while (0);
 | 
			
		||||
 | 
			
		||||
#define STORE_UNIT_TYPE_NODE(str_val)                                                                            \
 | 
			
		||||
  do {                                                                                                           \
 | 
			
		||||
    ParseResult* p = (ParseResult*)yyextra;                                                                      \
 | 
			
		||||
    if (p->need_parameterize_) {                                                                                 \
 | 
			
		||||
      ParseNode* node = NULL;                                                                                    \
 | 
			
		||||
      malloc_new_node(node, ((ParseResult*)yyextra)->malloc_pool_, T_INT, 0);                                    \
 | 
			
		||||
      check_value(yylval);                                                                                       \
 | 
			
		||||
      yylval->node = node;                                                                                       \
 | 
			
		||||
      yylval->node->raw_text_ =                                                                                  \
 | 
			
		||||
          parse_strdup(yytext, ((ParseResult*)yyextra)->malloc_pool_, &(yylval->node->text_len_));               \
 | 
			
		||||
      check_value(yylval->node->raw_text_);                                                                      \
 | 
			
		||||
      node->str_value_ = parse_strdup((char*)str_val, ((ParseResult*)yyextra)->malloc_pool_, &(node->str_len_)); \
 | 
			
		||||
      check_value(node->str_value_);                                                                             \
 | 
			
		||||
      node->value_ = strtoll(node->str_value_, NULL, 10);                                                        \
 | 
			
		||||
      STORE_PARAM_NODE()                                                                                         \
 | 
			
		||||
    } else {                                                                                                     \
 | 
			
		||||
      return OUTLINE_DEFAULT_TOKEN;                                                                              \
 | 
			
		||||
    }                                                                                                            \
 | 
			
		||||
  } while (0);
 | 
			
		||||
 | 
			
		||||
#define HANDLE_UNIT_TYPE(type)                                             \
 | 
			
		||||
  do {                                                                     \
 | 
			
		||||
    if (IS_FAST_PARAMETERIZE) {                                            \
 | 
			
		||||
      ParseResult* p = (ParseResult*)yyextra;                              \
 | 
			
		||||
      if (p->need_parameterize_) {                                         \
 | 
			
		||||
        STORE_UNIT_TYPE_NODE(ob_date_unit_type_num_str(DATE_UNIT_##type)); \
 | 
			
		||||
      } else {                                                             \
 | 
			
		||||
        return OUTLINE_DEFAULT_TOKEN;                                      \
 | 
			
		||||
      }                                                                    \
 | 
			
		||||
    } else {                                                               \
 | 
			
		||||
      return type;                                                         \
 | 
			
		||||
    }                                                                      \
 | 
			
		||||
  } while (0);
 | 
			
		||||
 | 
			
		||||
#define HANDLE_ESCAPE(presult)                                   \
 | 
			
		||||
  do {                                                           \
 | 
			
		||||
    int with_back_slash = 1;                                     \
 | 
			
		||||
    unsigned char c = escaped_char(yytext[1], &with_back_slash); \
 | 
			
		||||
    if (with_back_slash) {                                       \
 | 
			
		||||
      presult->tmp_literal_[yylval->node->str_len_++] = '\\';    \
 | 
			
		||||
    }                                                            \
 | 
			
		||||
    presult->tmp_literal_[yylval->node->str_len_++] = c;         \
 | 
			
		||||
  } while (0);
 | 
			
		||||
 | 
			
		||||
#define HANDLE_FALSE_ESCAPE(presult)                        \
 | 
			
		||||
  do {                                                      \
 | 
			
		||||
    presult->tmp_literal_[yylval->node->str_len_++] = '\\'; \
 | 
			
		||||
    yyless(1);                                              \
 | 
			
		||||
    presult->yycolumn_--;                                   \
 | 
			
		||||
  } while (0);
 | 
			
		||||
 | 
			
		||||
#define CHECK_REAL_ESCAPE(is_real_escape)                                                                           \
 | 
			
		||||
  do {                                                                                                              \
 | 
			
		||||
    if (NULL != p->charset_info_ && p->charset_info_->escape_with_backslash_is_dangerous) {                         \
 | 
			
		||||
      char* cur_pos = p->tmp_literal_ + yylval->node->str_len_;                                                     \
 | 
			
		||||
      char* last_check_pos = p->tmp_literal_ + p->last_well_formed_len_;                                            \
 | 
			
		||||
      int error = 0;                                                                                                \
 | 
			
		||||
      int expected_well_formed_len = cur_pos - last_check_pos;                                                      \
 | 
			
		||||
      int real_well_formed_len =                                                                                    \
 | 
			
		||||
          p->charset_info_->cset->well_formed_len(last_check_pos, cur_pos - last_check_pos, UINT64_MAX, &error);    \
 | 
			
		||||
      if (error != 0) {                                                                                             \
 | 
			
		||||
        *cur_pos = '\\';                                                                                            \
 | 
			
		||||
        if (real_well_formed_len == expected_well_formed_len - 1 && p->charset_info_->cset->ismbchar(cur_pos, 2)) { \
 | 
			
		||||
          is_real_escape = false;                                                                                   \
 | 
			
		||||
          p->last_well_formed_len_ = yylval->node->str_len_ + 1;                                                    \
 | 
			
		||||
        } else {                                                                                                    \
 | 
			
		||||
          p->last_well_formed_len_ = yylval->node->str_len_;                                                        \
 | 
			
		||||
        }                                                                                                           \
 | 
			
		||||
      } else {                                                                                                      \
 | 
			
		||||
        p->last_well_formed_len_ = yylval->node->str_len_;                                                          \
 | 
			
		||||
      }                                                                                                             \
 | 
			
		||||
    }                                                                                                               \
 | 
			
		||||
  } while (0);
 | 
			
		||||
 | 
			
		||||
#define CHECK_NODE_STRING_VALUE_ASCII(token, my_str_ptr, my_str_len)                                               \
 | 
			
		||||
  do {                                                                                                             \
 | 
			
		||||
    if (p->charset_info_ != NULL && p->is_not_utf8_connection_) {                                                  \
 | 
			
		||||
      if (my_str_len != p->charset_info_->cset->numchars(p->charset_info_, my_str_ptr, my_str_ptr + my_str_len)) { \
 | 
			
		||||
        p->extra_errno_ = OB_PARSER_ERR_ILLEGAL_NAME;                                                              \
 | 
			
		||||
        yyerror(yylloc,                                                                                            \
 | 
			
		||||
            yyextra,                                                                                               \
 | 
			
		||||
            "multi-byte identifier '%.*s' not support in charset '%s'\n",                                          \
 | 
			
		||||
            my_str_len,                                                                                            \
 | 
			
		||||
            my_str_ptr,                                                                                            \
 | 
			
		||||
            p->charset_info_->csname);                                                                             \
 | 
			
		||||
        token = PARSER_SYNTAX_ERROR;                                                                               \
 | 
			
		||||
      }                                                                                                            \
 | 
			
		||||
    }                                                                                                              \
 | 
			
		||||
  } while (0)
 | 
			
		||||
 | 
			
		||||
#define ADD_YYLINENO(_yytext, _yyleng)       \
 | 
			
		||||
  for (int32_t _i = 0; _i < _yyleng; ++_i) { \
 | 
			
		||||
    if (_yytext[_i] == '\n') {               \
 | 
			
		||||
      ++yylineno;                            \
 | 
			
		||||
    }                                        \
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
#define COPY_NUM_STRING(parse_result, node)                                              \
 | 
			
		||||
  do {                                                                                   \
 | 
			
		||||
    if (IS_FAST_PARAMETERIZE) {                                                          \
 | 
			
		||||
      if (parse_result->minus_ctx_.has_minus_) {                                         \
 | 
			
		||||
        int64_t start_pos = parse_result->minus_ctx_.raw_sql_offset_;                    \
 | 
			
		||||
        int64_t cp_len = yylloc->first_column - start_pos - 1 + yyleng;                  \
 | 
			
		||||
        COPY_STRING(p->input_sql_ + start_pos, cp_len, node->str_value_);                \
 | 
			
		||||
        node->str_len_ = cp_len;                                                         \
 | 
			
		||||
      } else {                                                                           \
 | 
			
		||||
        COPY_STRING(p->input_sql_ + yylloc->first_column - 1, yyleng, node->str_value_); \
 | 
			
		||||
        node->str_len_ = yyleng;                                                         \
 | 
			
		||||
      }                                                                                  \
 | 
			
		||||
    } else {                                                                             \
 | 
			
		||||
      COPY_STRING(p->input_sql_ + yylloc->first_column - 1, yyleng, node->str_value_);   \
 | 
			
		||||
      node->str_len_ = yyleng;                                                           \
 | 
			
		||||
    }                                                                                    \
 | 
			
		||||
  } while (0);
 | 
			
		||||
 | 
			
		||||
#define PARSE_INT_STR_MYSQL(param_node, malloc_pool, errno)                                               \
 | 
			
		||||
  do {                                                                                                    \
 | 
			
		||||
    if ('-' == param_node->str_value_[0]) {                                                               \
 | 
			
		||||
      char* copied_str = parse_strndup(param_node->str_value_, param_node->str_len_, malloc_pool);        \
 | 
			
		||||
      if (OB_ISNULL(copied_str)) {                                                                        \
 | 
			
		||||
        yyerror(NULL, yyextra, "No more space for mallocing");                                            \
 | 
			
		||||
        return ERROR;                                                                                     \
 | 
			
		||||
      } else {                                                                                            \
 | 
			
		||||
        int pos = 1;                                                                                      \
 | 
			
		||||
        for (; pos < param_node->str_len_ && ISSPACE(copied_str[pos]); pos++)                             \
 | 
			
		||||
          ;                                                                                               \
 | 
			
		||||
        copied_str[--pos] = '-';                                                                          \
 | 
			
		||||
        param_node->value_ = ob_strntoll(copied_str + pos, param_node->str_len_ - pos, 10, NULL, &errno); \
 | 
			
		||||
        if (ERANGE == errno) {                                                                            \
 | 
			
		||||
          param_node->type_ = T_NUMBER;                                                                   \
 | 
			
		||||
          token_ret = DECIMAL_VAL;                                                                        \
 | 
			
		||||
        }                                                                                                 \
 | 
			
		||||
      }                                                                                                   \
 | 
			
		||||
    } else {                                                                                              \
 | 
			
		||||
      uint64_t value = ob_strntoull(param_node->str_value_, param_node->str_len_, 10, NULL, &errno);      \
 | 
			
		||||
      param_node->value_ = value;                                                                         \
 | 
			
		||||
      if (ERANGE == errno) {                                                                              \
 | 
			
		||||
        param_node->type_ = T_NUMBER;                                                                     \
 | 
			
		||||
        token_ret = DECIMAL_VAL;                                                                          \
 | 
			
		||||
      } else if (value > INT64_MAX) {                                                                     \
 | 
			
		||||
        param_node->type_ = T_UINT64;                                                                     \
 | 
			
		||||
      }                                                                                                   \
 | 
			
		||||
    }                                                                                                     \
 | 
			
		||||
  } while (0);
 | 
			
		||||
 | 
			
		||||
#define RM_MULTI_STMT_END_P(p)                                \
 | 
			
		||||
  do {                                                        \
 | 
			
		||||
    int pos = p->no_param_sql_len_ - 1;                       \
 | 
			
		||||
    for (; pos >= 0 && ISSPACE(p->no_param_sql_[pos]); --pos) \
 | 
			
		||||
      ;                                                       \
 | 
			
		||||
    p->no_param_sql_len_ = pos + 1;                           \
 | 
			
		||||
    p->no_param_sql_[p->no_param_sql_len_] = '\0';            \
 | 
			
		||||
    p->end_col_ = p->no_param_sql_len_;                       \
 | 
			
		||||
  } while (0);
 | 
			
		||||
 | 
			
		||||
#define malloc_select_node(node, malloc_pool) \
 | 
			
		||||
  malloc_non_terminal_node(node,              \
 | 
			
		||||
      malloc_pool,                            \
 | 
			
		||||
      T_SELECT,                               \
 | 
			
		||||
      PARSE_SELECT_MAX_IDX,                   \
 | 
			
		||||
      NULL,                                   \
 | 
			
		||||
      NULL,                                   \
 | 
			
		||||
      NULL,                                   \
 | 
			
		||||
      NULL,                                   \
 | 
			
		||||
      NULL,                                   \
 | 
			
		||||
      NULL,                                   \
 | 
			
		||||
      NULL,                                   \
 | 
			
		||||
      NULL,                                   \
 | 
			
		||||
      NULL,                                   \
 | 
			
		||||
      NULL,                                   \
 | 
			
		||||
      NULL,                                   \
 | 
			
		||||
      NULL,                                   \
 | 
			
		||||
      NULL,                                   \
 | 
			
		||||
      NULL,                                   \
 | 
			
		||||
      NULL,                                   \
 | 
			
		||||
      NULL,                                   \
 | 
			
		||||
      NULL,                                   \
 | 
			
		||||
      NULL,                                   \
 | 
			
		||||
      NULL,                                   \
 | 
			
		||||
      NULL,                                   \
 | 
			
		||||
      NULL,                                   \
 | 
			
		||||
      NULL,                                   \
 | 
			
		||||
      NULL);
 | 
			
		||||
 | 
			
		||||
// only used by setup_token_pos_info_and_dup_string for now
 | 
			
		||||
#define check_ret(stmt, loc, extra)                                        \
 | 
			
		||||
  int ret = (stmt);                                                        \
 | 
			
		||||
  if (OB_UNLIKELY(ret != OB_PARSER_SUCCESS)) {                             \
 | 
			
		||||
    yyerror((loc), (extra), "setup token pos info failed ret: %d\n", ret); \
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
#define REPUT_TOKEN_NEG_SIGN(TOKEN)       \
 | 
			
		||||
  ParseResult* p = (ParseResult*)yyextra; \
 | 
			
		||||
  REPUT_NEG_SIGN(p);                      \
 | 
			
		||||
  return TOKEN;
 | 
			
		||||
 | 
			
		||||
extern void setup_token_pos_info(ParseNode* node, int off, int len);
 | 
			
		||||
// setup pos info and copy sql from p->input_sql_([strat, end]) to node->str_value_
 | 
			
		||||
extern int setup_token_pos_info_and_dup_string(ParseNode* node, ParseResult* p, int start, int end);
 | 
			
		||||
#ifdef SQL_PARSER_COMPILATION
 | 
			
		||||
int add_comment_list(ParseResult* p, const TokenPosInfo* info);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* OCEANBASE_SRC_SQL_PARSER_SQL_PARSER_BASE_H_ */
 | 
			
		||||
							
								
								
									
										1457
									
								
								src/sql/parser/sql_parser_mysql_mode.l
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1457
									
								
								src/sql/parser/sql_parser_mysql_mode.l
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										13364
									
								
								src/sql/parser/sql_parser_mysql_mode.y
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13364
									
								
								src/sql/parser/sql_parser_mysql_mode.y
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										77898
									
								
								src/sql/parser/sql_parser_mysql_mode_lex.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77898
									
								
								src/sql/parser/sql_parser_mysql_mode_lex.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										71801
									
								
								src/sql/parser/sql_parser_mysql_mode_lex.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71801
									
								
								src/sql/parser/sql_parser_mysql_mode_lex.h
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										52520
									
								
								src/sql/parser/sql_parser_mysql_mode_tab.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52520
									
								
								src/sql/parser/sql_parser_mysql_mode_tab.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1080
									
								
								src/sql/parser/sql_parser_mysql_mode_tab.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1080
									
								
								src/sql/parser/sql_parser_mysql_mode_tab.h
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										3054
									
								
								src/sql/parser/type_name.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3054
									
								
								src/sql/parser/type_name.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
		Reference in New Issue
	
	Block a user