diff --git a/.gitignore b/.gitignore index 3d09169185..df0741e93c 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,12 @@ *.oo2 *.pyc +# Intermediate Files (Parser/Lexer) +MySQL_Lexer.yy.c +MySQL_Parser.output +MySQL_Parser.tab.c +MySQL_Parser.tab.h + # Libraries *.lib *.a diff --git a/Makefile b/Makefile index e34ff5629f..aa634f1861 100644 --- a/Makefile +++ b/Makefile @@ -50,9 +50,9 @@ export MAKE export CURVER ### detect compiler support for c++11/17 -CPLUSPLUS := $(shell ${CC} -std=c++17 -dM -E -x c++ /dev/null 2>/dev/null | grep -F __cplusplus | egrep -o '[0-9]{6}L') +CPLUSPLUS := $(shell ${CC} -std=c++17 -dM -E -x c++ /dev/null 2>/dev/null | grep -F __cplusplus | grep -Eo '[0-9]{6}L') ifneq ($(CPLUSPLUS),201703L) - CPLUSPLUS := $(shell ${CC} -std=c++11 -dM -E -x c++ /dev/null 2>/dev/null| grep -F __cplusplus | egrep -o '[0-9]{6}L') + CPLUSPLUS := $(shell ${CC} -std=c++11 -dM -E -x c++ /dev/null 2>/dev/null| grep -F __cplusplus | grep -Eo '[0-9]{6}L') LEGACY_BUILD := 1 ifneq ($(CPLUSPLUS),201103L) $(error Compiler must support at least c++11) diff --git a/common_mk/openssl_flags.mk b/common_mk/openssl_flags.mk index 4b709e7aa9..9326eadf64 100644 --- a/common_mk/openssl_flags.mk +++ b/common_mk/openssl_flags.mk @@ -21,8 +21,8 @@ ifeq ($(CUSTOM_OPENSSL_PATH),) else SSL_IDIR := $(shell export PKG_CONFIG_ALLOW_SYSTEM_CFLAGS=1; export PKG_CONFIG_ALLOW_SYSTEM_LIBS=1; pkg-config --cflags $(OPENSSL_PACKAGE) | grep -oP "(?<=-I)[^ ]+") SSL_LDIR := $(shell pkg-config --variable=libdir $(OPENSSL_PACKAGE)) - LIB_SSL_PATH := $(shell find $(SSL_LDIR) -name "libssl.so" 2>/dev/null | head -n 1) - LIB_CRYPTO_PATH := $(shell find $(SSL_LDIR) -name "libcrypto.so" 2>/dev/null | head -n 1) + LIB_SSL_PATH := $(shell find $(SSL_LDIR) --maxdepth 1 -name "libssl.so" 2>/dev/null | head -n 1) + LIB_CRYPTO_PATH := $(shell find $(SSL_LDIR) --maxdepth 1 -name "libcrypto.so" 2>/dev/null | head -n 1) endif else SSL_IDIR := $(CUSTOM_OPENSSL_PATH)/include @@ -44,4 +44,4 @@ else endif else $(error Warning: OpenSSL headers (SSL_IDIR) not found. Exiting. Please install OpenSSL version 3.) -endif \ No newline at end of file +endif diff --git a/deps/Makefile b/deps/Makefile index 87d2a20e8f..6c2134b1e5 100644 --- a/deps/Makefile +++ b/deps/Makefile @@ -35,9 +35,9 @@ endif ### detect compiler support for c++11/17 -CPLUSPLUS := $(shell ${CC} -std=c++17 -dM -E -x c++ /dev/null 2>/dev/null | grep -F __cplusplus | egrep -o '[0-9]{6}L') +CPLUSPLUS := $(shell ${CC} -std=c++17 -dM -E -x c++ /dev/null 2>/dev/null | grep -F __cplusplus | grep -Eo '[0-9]{6}L') ifneq ($(CPLUSPLUS),201703L) - CPLUSPLUS := $(shell ${CC} -std=c++11 -dM -E -x c++ /dev/null 2>/dev/null| grep -F __cplusplus | egrep -o '[0-9]{6}L') + CPLUSPLUS := $(shell ${CC} -std=c++11 -dM -E -x c++ /dev/null 2>/dev/null| grep -F __cplusplus | grep -Eo '[0-9]{6}L') ifneq ($(CPLUSPLUS),201103L) $(error Compiler must support at least c++11) endif @@ -112,7 +112,7 @@ coredumper/coredumper/src/libcoredumper.a: cd coredumper && rm -rf coredumper-*/ || true cd coredumper && tar -zxf coredumper-*.tar.gz cd coredumper/coredumper && patch -p1 < ../includes.patch - cd coredumper/coredumper && cmake . -DBUILD_TESTING=OFF -DBUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Debug + cd coredumper/coredumper && cmake . -DBUILD_TESTING=OFF -DBUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Debug -DCMAKE_POLICY_VERSION_MINIMUM=3.5 cd coredumper/coredumper && CC=${CC} CXX=${CXX} ${MAKE} coredumper: coredumper/coredumper/src/libcoredumper.a @@ -161,7 +161,8 @@ clickhouse-cpp/clickhouse-cpp/clickhouse/libclickhouse-cpp-lib-static.a: cd clickhouse-cpp && tar -zxf v2.3.0.tar.gz cd clickhouse-cpp && ln -fs clickhouse-cpp-*/ clickhouse-cpp cd clickhouse-cpp/clickhouse-cpp && patch clickhouse/base/wire_format.h < ../wire_format.patch - cd clickhouse-cpp/clickhouse-cpp && cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo . + cd clickhouse-cpp/clickhouse-cpp && patch -p0 < ../ciso646-options.h.patch + cd clickhouse-cpp/clickhouse-cpp && cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_POLICY_VERSION_MINIMUM=3.5 . cd clickhouse-cpp/clickhouse-cpp && CC=${CC} CXX=${CXX} ${MAKE} clickhouse-cpp: clickhouse-cpp/clickhouse-cpp/clickhouse/libclickhouse-cpp-lib-static.a @@ -194,7 +195,7 @@ mariadb-client-library/mariadb_client/libmariadb/libmariadbclient.a: cd mariadb-client-library && rm -rf mariadb-connector-c-*/ || true cd mariadb-client-library && tar -zxf mariadb-connector-c-3.3.8-src.tar.gz cd mariadb-client-library/mariadb_client && patch -p0 < ../plugin_auth_CMakeLists.txt.patch - cd mariadb-client-library/mariadb_client && cmake . -Wno-dev -DCMAKE_BUILD_TYPE=RelWithDebInfo -DOPENSSL_ROOT_DIR=$(SSL_IDIR) -DOPENSSL_LIBRARIES=$(SSL_LDIR) -DICONV_LIBRARIES=$(brew --prefix libiconv)/lib -DICONV_INCLUDE=$(brew --prefix libiconv)/include . + cd mariadb-client-library/mariadb_client && cmake . -Wno-dev -DCMAKE_POLICY_VERSION_MINIMUM=3.5 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DOPENSSL_ROOT_DIR=$(SSL_IDIR) -DOPENSSL_LIBRARIES=$(SSL_LDIR) -DICONV_LIBRARIES=$(brew --prefix libiconv)/lib -DICONV_INCLUDE=$(brew --prefix libiconv)/include . ifeq ($(PROXYDEBUG),1) cd mariadb-client-library/mariadb_client && patch -p0 < ../ma_context.h.patch else ifeq ($(USEVALGRIND),1) @@ -234,6 +235,7 @@ endif cd mariadb-client-library/mariadb_client && patch -p0 < ../mariadb_rpl.patch cd mariadb-client-library/mariadb_client && patch -p0 < ../cmakelists.txt.patch cd mariadb-client-library/mariadb_client && patch -p0 < ../mariadb_lib.c.metadata_column_check.patch + cd mariadb-client-library/mariadb_client && patch -p0 < ../ma_global.h.patch cd mariadb-client-library/mariadb_client && CC=${CC} CXX=${CXX} ${MAKE} mariadbclient # cd mariadb-client-library/mariadb_client/include && make my_config.h @@ -255,6 +257,7 @@ sqlite3: sqlite3/sqlite3/sqlite3.o libconfig/libconfig/lib/.libs/libconfig++.a: cd libconfig && rm -rf libconfig-*/ || true cd libconfig && tar -zxf libconfig-*.tar.gz + cd libconfig/libconfig && patch -p0 < ../gcc-15.patch cd libconfig/libconfig && ./configure --disable-examples cd libconfig/libconfig && CC=${CC} CXX=${CXX} ${MAKE} @@ -307,6 +310,7 @@ postgresql/postgresql/src/interfaces/libpq/libpq.a: cd postgresql/postgresql && patch -p0 < ../get_result_from_pgconn.patch cd postgresql/postgresql && patch -p0 < ../handle_row_data.patch cd postgresql/postgresql && patch -p0 < ../fmt_err_msg.patch + cd postgresql/postgresql && patch -p0 < ../c23_bool-c.h.patch #cd postgresql/postgresql && LD_LIBRARY_PATH="$(shell pwd)/libssl/openssl" ./configure --with-ssl=openssl --with-includes="$(shell pwd)/libssl/openssl/include/" --with-libraries="$(shell pwd)/libssl/openssl/" --without-readline --enable-debug CFLAGS="-ggdb -O0 -fno-omit-frame-pointer" CPPFLAGS="-g -O0" cd postgresql/postgresql && LD_LIBRARY_PATH="$(SSL_LDIR)" ./configure --with-ssl=openssl --with-includes="$(SSL_IDIR)" --with-libraries="$(SSL_LDIR)" --without-readline cd postgresql/postgresql/src/interfaces/libpq && CC=${CC} CXX=${CXX} ${MAKE} MAKELEVEL=0 diff --git a/deps/clickhouse-cpp/ciso646-options.h.patch b/deps/clickhouse-cpp/ciso646-options.h.patch new file mode 100644 index 0000000000..9c45d8a2f8 --- /dev/null +++ b/deps/clickhouse-cpp/ciso646-options.h.patch @@ -0,0 +1,15 @@ +--- contrib/absl/base/options.h 2022-11-23 10:33:15.000000000 +0100 ++++ contrib/absl/base/options.h 2022-11-23 10:33:15.000000000 +0100 +@@ -70,7 +70,11 @@ + // Include a standard library header to allow configuration based on the + // standard library in use. + #ifdef __cplusplus +-#include ++#if __has_include() ++#include ++#else ++#include ++#endif + #endif + + // ----------------------------------------------------------------------------- diff --git a/deps/libconfig/gcc-15.patch b/deps/libconfig/gcc-15.patch new file mode 100644 index 0000000000..3ea6ed763f --- /dev/null +++ b/deps/libconfig/gcc-15.patch @@ -0,0 +1,26 @@ +diff --git lib/grammar.y lib/grammar.y +index f614fa7..b7d6989 100644 +--- lib/grammar.y ++++ lib/grammar.y +@@ -40,8 +40,7 @@ + #include "wincompat.h" + + /* These declarations are provided to suppress compiler warnings. */ +-extern int libconfig_yylex(); +-extern int libconfig_yyget_lineno(); ++extern int libconfig_yyget_lineno(void *); + + #define YYMALLOC libconfig_malloc + +@@ -82,6 +81,11 @@ void libconfig_yyerror(void *scanner, struct parse_context *ctx, + char *sval; + } + ++%{ ++/* These declarations are provided to suppress compiler warnings. */ ++extern int libconfig_yylex(YYSTYPE *, void *); ++%} ++ + %token TOK_BOOLEAN TOK_INTEGER TOK_HEX + %token TOK_INTEGER64 TOK_HEX64 + %token TOK_FLOAT diff --git a/deps/mariadb-client-library/ma_global.h.patch b/deps/mariadb-client-library/ma_global.h.patch new file mode 100644 index 0000000000..e2deaf400f --- /dev/null +++ b/deps/mariadb-client-library/ma_global.h.patch @@ -0,0 +1,13 @@ +--- include/ma_global.h 2023-11-01 11:28:04.000000000 +0100 ++++ include/ma_global.h 2023-11-01 11:28:04.000000000 +0100 +@@ -683,9 +683,9 @@ + typedef int myf; /* Type of MyFlags in my_funcs */ + typedef char my_bool; /* Small bool */ + typedef unsigned long long my_ulonglong; +-#if !defined(bool) && !defined(bool_defined) && (!defined(HAVE_BOOL) || !defined(__cplusplus)) ++#if !defined(bool) && !defined(bool_defined) && (!defined(HAVE_BOOL) || !defined(__cplusplus)) && (__STDC_VERSION__ < 202300L) + typedef char bool; /* Ordinary boolean values 0 1 */ + #endif + /* Macros for converting *constants* to the right type */ + #define INT8(v) (int8) (v) + #define INT16(v) (int16) (v) diff --git a/deps/postgresql/c23_bool-c.h.patch b/deps/postgresql/c23_bool-c.h.patch new file mode 100644 index 0000000000..3e70aebf7c --- /dev/null +++ b/deps/postgresql/c23_bool-c.h.patch @@ -0,0 +1,14 @@ +--- src/include/c.h 2025-06-23 13:30:51.563824789 +0200 ++++ src/include/c.h 2025-06-23 13:30:51.563824789 +0200 +@@ -436,10 +436,10 @@ + #include + #else + +-#ifndef bool ++#if !defined(bool) && (__STDC_VERSION__ < 202300L) + typedef unsigned char bool; + #endif + + #ifndef true + #define true ((bool) 1) + #endif diff --git a/include/Base_Session_Utils.h b/include/Base_Session_Utils.h new file mode 100644 index 0000000000..d0b30db8c9 --- /dev/null +++ b/include/Base_Session_Utils.h @@ -0,0 +1,23 @@ +#ifndef BASE_SESSION_UTILS_H +#define BASE_SESSION_UTILS_H + +/** + * @class Session_Regex + * @brief Encapsulates regex operations for session handling. + * + * This class is used for matching patterns in SQL queries, specifically for + * settings like sql_log_bin, sql_mode, and time_zone. + * See issues #509 , #815 and #816 + */ +class Session_Regex { +private: + void* opt; + void* re; + char* s; +public: + Session_Regex(const char* p); + ~Session_Regex(); + bool match(const char* m); +}; + +#endif // BASE_SESSION_UTILS_H diff --git a/include/Base_Thread.h b/include/Base_Thread.h index 485fec913b..db927acf1b 100644 --- a/include/Base_Thread.h +++ b/include/Base_Thread.h @@ -1,7 +1,11 @@ #ifndef CLASS_BASE_THREAD_H #define CLASS_BASE_THREAD_H -#include "proxysql.h" +#ifdef DEBUG +#include +#endif + +#include "proxysql_structs.h" typedef struct _thr_id_username_t { uint32_t id; @@ -14,25 +18,6 @@ typedef struct _kill_queue_t { std::vector query_ids; } kill_queue_t; -/** - * @class Session_Regex - * @brief Encapsulates regex operations for session handling. - * - * This class is used for matching patterns in SQL queries, specifically for - * settings like sql_log_bin, sql_mode, and time_zone. - * See issues #509 , #815 and #816 - */ -class Session_Regex { -private: - void* opt; - void* re; - char* s; -public: - Session_Regex(const char* p); - ~Session_Regex(); - bool match(const char* m); -}; - class MySQL_Thread; class PgSQL_Thread; @@ -53,7 +38,6 @@ class Base_Thread { bool epoll_thread; int shutdown; PtrArray *mysql_sessions; - Session_Regex **match_regexes; Base_Thread(); ~Base_Thread(); template diff --git a/include/MySQL_AST.h b/include/MySQL_AST.h new file mode 100644 index 0000000000..4591f11abc --- /dev/null +++ b/include/MySQL_AST.h @@ -0,0 +1,301 @@ +#ifndef MYSQL_PARSER_AST_H +#define MYSQL_PARSER_AST_H + +#include +#include +#include + +namespace MySQLParser { + +// Enum for Abstract Syntax Tree Node Types +enum class NodeType { + NODE_UNKNOWN, + NODE_COMMAND, // General command like QUIT + NODE_SELECT_STATEMENT, + NODE_INSERT_STATEMENT, + NODE_DELETE_STATEMENT, + NODE_IDENTIFIER, + NODE_STRING_LITERAL, + NODE_NUMBER_LITERAL, // For numeric values + NODE_BOOLEAN_LITERAL, // For boolean values + NODE_NULL_LITERAL, // For NULL literal + NODE_VALUE_LITERAL, // For values with no type; options like 'ON' + NODE_TIMESTAMP, // For dates + NODE_INTERVAL, // For dates + NODE_ASTERISK, // For '*' in SELECT + NODE_SET_STATEMENT, + NODE_SET_OPTION_VALUE_LIST, + NODE_VARIABLE_ASSIGNMENT, + NODE_USER_VARIABLE, // e.g., @my_var + NODE_SYSTEM_VARIABLE, // e.g., @@global.var + NODE_VARIABLE_SCOPE, // GLOBAL, SESSION, PERSIST, etc. + NODE_EXPR, // Placeholder for more complex expressions (and functions) + NODE_SIMPLE_EXPRESSION, // More specific expression type + NODE_INTERVAL_EXPRESSION, // More specific expression type + NODE_AGGREGATE_FUNCTION_CALL, // For COUNT, SUM, AVG etc. + NODE_SET_NAMES, + NODE_SET_CHARSET, + NODE_DELETE_OPTIONS, // LOW_PRIORITY, QUICK, IGNORE for DELETE + NODE_TABLE_NAME_LIST, // For multi-table DELETE or other lists of tables + NODE_FROM_CLAUSE, + NODE_USING_CLAUSE, // For JOIN ... USING (...) + NODE_WHERE_CLAUSE, + NODE_HAVING_CLAUSE, // Added for HAVING + NODE_ORDER_BY_CLAUSE, + NODE_ORDER_BY_ITEM, + NODE_LIMIT_CLAUSE, + NODE_ESCAPE_CLAUSE, + NODE_COMPARISON_EXPRESSION, // e.g., col = 5 + NODE_LOGICAL_AND_EXPRESSION, // For AND operator + NODE_OPERATOR, // e.g., =, <, +, -, JOIN type strings + NODE_LEFT_SHIFT_OPERATOR, // e.g., << + NODE_RIGHT_SHIFT_OPERATOR, // e.g., >> + NODE_QUALIFIED_IDENTIFIER, // e.g., table.column + + // For SELECT specific parts + NODE_SELECT_OPTIONS, // DISTINCT, SQL_CALC_FOUND_ROWS etc. + NODE_SELECT_ITEM_LIST, // List of expressions/columns in SELECT + NODE_SELECT_ITEM, // A single item in the SELECT list + NODE_SELECT_RAW_SUBQUERY, // Subquery parsing placeholder + NODE_ALIAS, // For 'AS alias_name' + NODE_TABLE_REFERENCE, // Reference to a table (name, derived, join result) + NODE_GROUP_BY_CLAUSE, + NODE_GROUPING_ELEMENT, // Item in GROUP BY + + // For JOIN clauses + NODE_JOIN_CLAUSE, // Represents a join operation (e.g., t1 JOIN t2) + NODE_JOIN_TYPE_NATURAL_SPEC,// For 'NATURAL [LEFT|RIGHT|INNER] JOIN' specifier + NODE_JOIN_CONDITION_ON, // ON + NODE_JOIN_CONDITION_USING, // USING (col1, col2) + NODE_COLUMN_LIST, // For USING (col_list) or INTO (var_list) + + // Nodes for INTO, LOCKING, DERIVED TABLES + NODE_INTO_CLAUSE, // Wrapper for INTO ... variants + NODE_INTO_VAR_LIST, // INTO @var1, @var2 + NODE_INTO_OUTFILE, // INTO OUTFILE 'filename' [options] + NODE_INTO_DUMPFILE, // INTO DUMPFILE 'filename' + NODE_LOCKING_CLAUSE_LIST, // Wrapper for one or more locking clauses + NODE_LOCKING_CLAUSE, // FOR UPDATE | FOR SHARE + NODE_LOCK_STRENGTH, // Stores "UPDATE" or "SHARE" + NODE_LOCK_TABLE_LIST, // Optional 'OF table_list' for locking + NODE_LOCK_OPTION, // Optional 'NOWAIT' or 'SKIP LOCKED' + NODE_DERIVED_TABLE, // Represents (SELECT ...) AS alias + NODE_SUBQUERY, // The (SELECT ...) part of a derived table or sub-expression + + // For INTO OUTFILE options + NODE_FILE_OPTIONS, // Wrapper for all file format options + NODE_FIELDS_OPTIONS_CLAUSE, // Wrapper for FIELDS related options + NODE_LINES_OPTIONS_CLAUSE, // Wrapper for LINES related options + NODE_FIELDS_TERMINATED_BY, + NODE_FIELDS_ENCLOSED_BY, + NODE_FIELDS_OPTIONALLY_ENCLOSED_BY, + NODE_FIELDS_ESCAPED_BY, + NODE_LINES_STARTING_BY, + NODE_LINES_TERMINATED_BY, + NODE_CHARSET_OPTION, // For CHARACTER SET 'name' in OUTFILE + + NODE_KEYWORD, // For storing keywords like ALL, DISTINCT (as value) in some contexts + + // Added for SHOW, BEGIN, COMMIT + NODE_SHOW_STATEMENT, + NODE_BEGIN_STATEMENT, + NODE_COMMIT_STATEMENT, + NODE_SHOW_OPTION_FULL, // For SHOW FULL ... + NODE_SHOW_OPTION_FIELDS, // For SHOW ... FIELDS + NODE_SHOW_TARGET_DATABASES, // For SHOW DATABASES + NODE_TABLE_SPECIFICATION, // For FROM table_name in SHOW FIELDS + + // Added for IS NULL / IS NOT NULL + NODE_IS_NULL_EXPRESSION, + NODE_IS_NOT_NULL_EXPRESSION +}; + +struct AstNode; + +inline void print_ast(const AstNode* node, int indent = 0); + +/** + * @brief Structure for an Abstract Syntax Tree (AST) Node. + * @details Represents a node in the AST, storing its type, value, children, and position information. + */ +struct AstNode { + /** + * @brief The type of the AST node. + */ + NodeType type; + /** + * @brief The value of the AST node. + * @details Identifier name, literal value, operator type, etc. + */ + std::string value; + /** + * @brief The child nodes of this AST node. + */ + std::vector children; + /** + * @brief The starting position of the value in the source code. + */ + size_t val_init_pos { 0 }; + /** + * @brief The ending position of the value in the source code. + */ + size_t val_end_pos { 0 }; + /** + * @brief Constructor for AstNode. + * @param t The type of the node. + * @param val The value of the node (default: ""). + */ + AstNode(NodeType t, const std::string& val = "") : type(t), value(val) {} + /** + * @brief Move constructor for value. + * @param t The type of the node. + * @param val The value of the node (rvalue reference). + */ + AstNode(NodeType t, std::string&& val) : type(t), value(std::move(val)) {} + /** + * @brief Destructor. + * @details Iterates through the childs, freeing resources. + */ + ~AstNode() { + for (AstNode* child : children) { + delete child; + } + } + /** + * @brief Deleted copy constructor to prevent implicit copying. + */ + AstNode(const AstNode&) = delete; + /** + * @brief Deleted copy assignment operator to prevent implicit copying. + */ + AstNode& operator=(const AstNode&) = delete; + /** + * @brief Deleted move constructor. + */ + AstNode(AstNode&&) = delete; + /** + * @brief Deleted move assignment operator. + */ + AstNode& operator=(AstNode&&) = delete; + /** + * @brief Adds a child node to the current node. + * @param child Pointer to the child node to be added. If the pointer is null, the child is not added. + */ + void add_child(AstNode* child) { + if (child) { + children.push_back(child); + } + } +}; + +inline std::string to_string(NodeType t) { + if (t == NodeType::NODE_UNKNOWN) { return "UNKNOWN"; } + else if (t == NodeType::NODE_COMMAND) { return "COMMAND"; } + else if (t == NodeType::NODE_SELECT_STATEMENT) { return "SELECT_STMT"; } + else if (t == NodeType::NODE_INSERT_STATEMENT) { return "INSERT_STMT"; } + else if (t == NodeType::NODE_DELETE_STATEMENT) { return "DELETE_STMT"; } + else if (t == NodeType::NODE_IDENTIFIER) { return "IDENTIFIER"; } + else if (t == NodeType::NODE_STRING_LITERAL) { return "STRING_LITERAL"; } + else if (t == NodeType::NODE_NUMBER_LITERAL) { return "NUMBER_LITERAL"; } + else if (t == NodeType::NODE_BOOLEAN_LITERAL) { return "BOOLEAN_LITERAL"; } + else if (t == NodeType::NODE_NULL_LITERAL) { return "NULL_LITERAL"; } + else if (t == NodeType::NODE_VALUE_LITERAL) { return "VALUE_LITERAL"; } + else if (t == NodeType::NODE_TIMESTAMP) { return "TIMESTAMP"; } + else if (t == NodeType::NODE_INTERVAL) { return "INTERVAL"; } + else if (t == NodeType::NODE_ASTERISK) { return "ASTERISK"; } + else if (t == NodeType::NODE_SET_STATEMENT) { return "SET_STATEMENT"; } + else if (t == NodeType::NODE_VARIABLE_ASSIGNMENT) { return "VAR_ASSIGN"; } + else if (t == NodeType::NODE_SET_OPTION_VALUE_LIST) { return "SET_OPTION_VALUE_LIST"; } + else if (t == NodeType::NODE_USER_VARIABLE) { return "USER_VAR"; } + else if (t == NodeType::NODE_SYSTEM_VARIABLE) { return "SYSTEM_VAR"; } + else if (t == NodeType::NODE_VARIABLE_SCOPE) { return "VAR_SCOPE"; } + else if (t == NodeType::NODE_EXPR) { return "EXPR"; } + else if (t == NodeType::NODE_SIMPLE_EXPRESSION) { return "SIMPLE_EXPRESSION"; } + else if (t == NodeType::NODE_INTERVAL_EXPRESSION) { return "INTERVAL_EXPRESSION"; } + else if (t == NodeType::NODE_AGGREGATE_FUNCTION_CALL) { return "AGGREGATE_FUNC_CALL"; } + else if (t == NodeType::NODE_SET_NAMES) { return "SET_NAMES"; } + else if (t == NodeType::NODE_SET_CHARSET) { return "SET_CHARSET"; } + else if (t == NodeType::NODE_DELETE_OPTIONS) { return "DELETE_OPTIONS"; } + else if (t == NodeType::NODE_TABLE_NAME_LIST) { return "TABLE_NAME_LIST"; } + else if (t == NodeType::NODE_FROM_CLAUSE) { return "FROM_CLAUSE"; } + else if (t == NodeType::NODE_USING_CLAUSE) { return "USING_CLAUSE"; } + else if (t == NodeType::NODE_WHERE_CLAUSE) { return "WHERE_CLAUSE"; } + else if (t == NodeType::NODE_HAVING_CLAUSE) { return "HAVING_CLAUSE"; } + else if (t == NodeType::NODE_ORDER_BY_CLAUSE) { return "ORDER_BY_CLAUSE"; } + else if (t == NodeType::NODE_ORDER_BY_ITEM) { return "ORDER_BY_ITEM"; } + else if (t == NodeType::NODE_LIMIT_CLAUSE) { return "LIMIT_CLAUSE"; } + else if (t == NodeType::NODE_ESCAPE_CLAUSE) { return "ESCAPE_CLAUSE"; } + else if (t == NodeType::NODE_COMPARISON_EXPRESSION) { return "COMPARISON_EXPR"; } + else if (t == NodeType::NODE_LOGICAL_AND_EXPRESSION) { return "LOGICAL_AND_EXPR"; } + else if (t == NodeType::NODE_OPERATOR) { return "OPERATOR"; } + else if (t == NodeType::NODE_QUALIFIED_IDENTIFIER) { return "QUALIFIED_IDENTIFIER"; } + else if (t == NodeType::NODE_SELECT_OPTIONS) { return "SELECT_OPTIONS"; } + else if (t == NodeType::NODE_SELECT_ITEM_LIST) { return "SELECT_ITEM_LIST"; } + else if (t == NodeType::NODE_SELECT_ITEM) { return "SELECT_ITEM"; } + else if (t == NodeType::NODE_SELECT_RAW_SUBQUERY) { return "NODE_SELECT_RAW_SUBQUERY"; } + else if (t == NodeType::NODE_ALIAS) { return "ALIAS"; } + else if (t == NodeType::NODE_TABLE_REFERENCE) { return "TABLE_REFERENCE"; } + else if (t == NodeType::NODE_GROUP_BY_CLAUSE) { return "GROUP_BY_CLAUSE"; } + else if (t == NodeType::NODE_GROUPING_ELEMENT) { return "GROUPING_ELEMENT"; } + else if (t == NodeType::NODE_JOIN_CLAUSE) { return "JOIN_CLAUSE"; } + else if (t == NodeType::NODE_JOIN_TYPE_NATURAL_SPEC) { return "JOIN_TYPE_NATURAL_SPEC"; } + else if (t == NodeType::NODE_JOIN_CONDITION_ON) { return "JOIN_CONDITION_ON"; } + else if (t == NodeType::NODE_JOIN_CONDITION_USING) { return "JOIN_CONDITION_USING"; } + else if (t == NodeType::NODE_COLUMN_LIST) { return "COLUMN_LIST"; } + else if (t == NodeType::NODE_INTO_CLAUSE) { return "INTO_CLAUSE"; } + else if (t == NodeType::NODE_INTO_VAR_LIST) { return "INTO_VAR_LIST"; } + else if (t == NodeType::NODE_INTO_OUTFILE) { return "INTO_OUTFILE"; } + else if (t == NodeType::NODE_INTO_DUMPFILE) { return "INTO_DUMPFILE"; } + else if (t == NodeType::NODE_LOCKING_CLAUSE_LIST) { return "LOCKING_CLAUSE_LIST"; } + else if (t == NodeType::NODE_LOCKING_CLAUSE) { return "LOCKING_CLAUSE"; } + else if (t == NodeType::NODE_LOCK_STRENGTH) { return "LOCK_STRENGTH"; } + else if (t == NodeType::NODE_LOCK_TABLE_LIST) { return "LOCK_TABLE_LIST"; } + else if (t == NodeType::NODE_LOCK_OPTION) { return "LOCK_OPTION"; } + else if (t == NodeType::NODE_DERIVED_TABLE) { return "DERIVED_TABLE"; } + else if (t == NodeType::NODE_SUBQUERY) { return "SUBQUERY"; } + else if (t == NodeType::NODE_FILE_OPTIONS) { return "FILE_OPTIONS"; } + else if (t == NodeType::NODE_FIELDS_OPTIONS_CLAUSE) { return "FIELDS_OPTIONS_CLAUSE"; } + else if (t == NodeType::NODE_LINES_OPTIONS_CLAUSE) { return "LINES_OPTIONS_CLAUSE"; } + else if (t == NodeType::NODE_FIELDS_TERMINATED_BY) { return "FIELDS_TERMINATED_BY"; } + else if (t == NodeType::NODE_FIELDS_ENCLOSED_BY) { return "FIELDS_ENCLOSED_BY"; } + else if (t == NodeType::NODE_FIELDS_OPTIONALLY_ENCLOSED_BY) { return "FIELDS_OPTIONALLY_ENCLOSED_BY"; } + else if (t == NodeType::NODE_FIELDS_ESCAPED_BY) { return "FIELDS_ESCAPED_BY"; } + else if (t == NodeType::NODE_LINES_STARTING_BY) { return "LINES_STARTING_BY"; } + else if (t == NodeType::NODE_LINES_TERMINATED_BY) { return "LINES_TERMINATED_BY"; } + else if (t == NodeType::NODE_CHARSET_OPTION) { return "CHARSET_OPTION"; } + else if (t == NodeType::NODE_KEYWORD) { return "KEYWORD"; } + else if (t == NodeType::NODE_SHOW_STATEMENT) { return "SHOW_STMT"; } + else if (t == NodeType::NODE_BEGIN_STATEMENT) { return "BEGIN_STMT"; } + else if (t == NodeType::NODE_COMMIT_STATEMENT) { return "COMMIT_STMT"; } + else if (t == NodeType::NODE_SHOW_OPTION_FULL) { return "SHOW_OPT_FULL"; } + else if (t == NodeType::NODE_SHOW_OPTION_FIELDS) { return "SHOW_OPT_FIELDS"; } + else if (t == NodeType::NODE_SHOW_TARGET_DATABASES) { return "SHOW_TARGET_DB"; } + else if (t == NodeType::NODE_TABLE_SPECIFICATION) { return "TABLE_SPEC"; } + else if (t == NodeType::NODE_IS_NULL_EXPRESSION) { return "IS_NULL_EXPR"; } + else if (t == NodeType::NODE_IS_NOT_NULL_EXPRESSION) { return "IS_NOT_NULL_EXPR"; } + else { + return "UNHANDLED_TYPE(" + std::to_string(static_cast(t)) + ")"; + } +} + +// Helper function to print the AST (for debugging) +inline void print_ast(const AstNode* node, int indent) { + if (!node) return; + + for (int i = 0; i < indent; ++i) std::cout << " "; + + std::cout << "Type: " << to_string(node->type); + if (!node->value.empty()) { + std::cout << ", Value: '" << node->value << "'"; + } + std::cout << std::endl; + + for (const AstNode* child : node->children) { + print_ast(child, indent + 1); + } +} + +} // namespace MySQLParser + +#endif // MYSQL_PARSER_AST_H + diff --git a/include/MySQL_Parser.h b/include/MySQL_Parser.h new file mode 100644 index 0000000000..a572301f3e --- /dev/null +++ b/include/MySQL_Parser.h @@ -0,0 +1,109 @@ +#ifndef MYSQL_PARSER_PARSER_H +#define MYSQL_PARSER_PARSER_H + +#include "MySQL_AST.h" // Uses MySQLParser::AstNode +#include +#include +#include + +/** + * @brief Opaque type for Flex holding the scanner state + */ +typedef void* yyscan_t; + +namespace MySQLParser { + +/** + * @class Parser + * @brief Parses SQL queries and generates an Abstract Syntax Tree (AST). + * @details Uses Flex and Bison to tokenize and parse SQL queries. The class itself acts as a + * closure, holding the internal parser state and error reporting. This state is shared with the + * Bison parser through `this` pointer. + */ +class Parser { +public: + /** + * @brief Constructor for the Parser class. + * @details Initializes the Flex scanner. + * @throws std::runtime_error On scanner initialization fails. + */ + Parser(); + /** + * @brief Destructor for the Parser class. + * @details Cleanups Flex scanner internal state. + */ + ~Parser(); + /** + * @brief Parses an SQL query string. + * @param sql_query The SQL query string to parse. + * @return Root node of the generated AST, or nullptr on failure. + */ + std::unique_ptr parse(const std::string& sql_query); + /** + * @brief Retrieves the list of errors encountered during parsing. + * @return A constant reference to the vector of error messages. + */ + const std::vector& get_errors() const; + /** + * @brief Clears the list of errors. + */ + void clear_errors(); + + /** + * @brief Internal method used by Bison to set the root of the AST. + * @details Called by the Bison-generated parsing code to set the root + * of the Abstract Syntax Tree (AST) after a successful parse. + * @param root The root AstNode of the AST. Parser takes ownership. + */ + void internal_set_ast(AstNode* root); + /** + * @brief Internal method used by Flex/Bison to add a generic error message. + * @param msg The error message to add. + */ + void internal_add_error(const std::string& msg); + /** + * @brief Internal method used by Flex/Bison to add an error message with line and column information. + * @param msg The error message to add. + * @param line The line number where the error occurred. + * @param column The column number where the error occurred. + */ + void internal_add_error_at(const std::string& msg, int line, int column); + +private: + /** + * @brief The root node of the Abstract Syntax Tree (AST). + */ + std::unique_ptr ast_root_; + /** + * @brief Vector with the error messages encountered during parsing. + */ + std::vector errors_; + /** + * @brief The Flex scanner state. + */ + yyscan_t scanner_state_; +}; + +} // namespace MySQLParser + +struct MYSQL_YYLTYPE; + +/** + * @brief Declaration for mysql_yyerror, called by Bison's mysql_yyparse. + * @param yyscanner The scanner state. + * @param parser_context The parser context. + * @param msg The error message. + */ +void mysql_yyerror(yyscan_t yyscanner, MySQLParser::Parser* parser_context, const char* msg); +/** + * @brief Overload for mysql_yyerror, including an extra parameter for location tracking. + * @param yyloc The location of the token where the error occurred, provided by the lexer. + * @param yyscanner The scanner state. + * @param parser_context The parser context. + * @param msg The error message. + */ +void mysql_yyerror( + MYSQL_YYLTYPE* yyloc, yyscan_t yyscanner, MySQLParser::Parser* parser_context, const char* msg +); + +#endif // MYSQL_PARSER_PARSER_H diff --git a/include/MySQL_SET_Parser_Utils.h b/include/MySQL_SET_Parser_Utils.h new file mode 100644 index 0000000000..1232fc7f2f --- /dev/null +++ b/include/MySQL_SET_Parser_Utils.h @@ -0,0 +1,153 @@ +#ifndef MYSQL_SET_PARSER_UTILS_H +#define MYSQL_SET_PARSER_UTILS_H + +#include "MySQL_AST.h" + +#include + +/** + * @brief Map where the key is the variable name and the value is a vector of strings representing the + * assigned values for that variable. + */ +using var_map_t = std::map>>; + +/** + * @brief Extracts the AST nodes corresponding to variable assignments from a SQL SET statement's AST. + * @details This function performs a breadth-first traversal of the Abstract Syntax Tree (AST) rooted at + * `root` to identify and extract all nodes representing variable assignments (NODE_VARIABLE_ASSIGNMENT). It + * prunes the search space by considering the depth of the nodes. Once the first variable assignment node is + * found, subsequent nodes at the same depth are also added to the result. Deeper nodes are ignored, and + * shallower nodes terminate the search. + * + * @param root A pointer to the root node of the AST. If `root` is `nullptr`, an empty vector is returned. + * @return A vector containing pointers to the AST nodes of type `NODE_VARIABLE_ASSIGNMENT` that represent + * variable assignments within the SQL SET statement. Returns an empty vector if no such nodes are found, + * or if the input `root` is `nullptr`. + */ +std::vector ext_vars_assigns(const MySQLParser::AstNode* root); +/** + * @brief Extracts variable assignments and maps them to their corresponding values from a SQL SET + * statement's AST. + * @details This function leverages the `ext_vars_assigns` function to identify variable assignment nodes + * within the AST and then extracts the variable name and assigned value for each assignment. + * + * @param root A pointer to the root node of the AST. If `root` is `nullptr`, an empty map is returned. + * @param q The original SQL query string from which the AST was generated. Used to extract the values. + * @return A map where the key is the variable name (string) and the value is a vector of strings + * representing the assigned values for that variable. Returns an empty map if no variable assignments are + * found or if the input `root` is `nullptr`. + */ +var_map_t ext_vars_assigns_map(const MySQLParser::AstNode* root, const std::string& q); + +/** + * @brief Helper type that holds an RC and an extra value. + * @details The kind of the contained object is { error_code, value }: + * - { rc, {} }: When holding an error, and empty (default constructed) value. + * - { 0, val }: On succeed operation. + */ +template +using rc_t = std::pair; +/** + * @brief Helper type used to specify a child type and expected index in the AST tree. + * @details The first element of the pair is the expected `NodeType` of the child, and the second element is + * the index of the child within the parent's `children` vector. + */ +using child_idx_t = std::pair; +/** + * @brief Retrieves a node from the AST based on a provided path. + * @details Traverses the Abstract Syntax Tree (AST) from a given root node, following a specified path of + * child indices. It checks the node type at each step against the expected type in the path. + * + * @param root A pointer to the root node of the AST to traverse. + * @param c_path A vector of child_idx_t, where each pair represents a child index to follow. + * + * @return A `rc_t`: + * - The first element of the pair is an integer return code, `0` on success, `-1` otherwise. + * - The second element of the pair is a pointer to the `AstNode` where the traversal ended, either the + * target node or the node where an error occurred. + * + * @details The function iterates through the `c_path` vector. For each `c_idx` in the path: + * 1. It checks if the current node has children and if the child index `c_idx.second` is within the bounds + * of the `children` vector. + * 2. If the index is valid, it updates `cur_node` to point to the child node. + * 3. It then checks the `NodeType` of the child. + * - If the expected `NodeType` is `NODE_UNKNOWN`, the check is skipped, and traversal continues. + * - Otherwise, it compares the `type` of the current node with the expected `NodeType` `c_idx.first`. + * If they don't match, it returns an error code of `-1` along with the current node. + * 4. If the index is invalid (either no children or index out of bounds), it returns an error code of `-1` + * along with the current node. + * If the entire path is traversed successfully, the function returns a success code of `0` along with the + * final `cur_node`. + */ +rc_t get_node( + const MySQLParser::AstNode* root, const std::vector& c_path +); +/** + * @brief Checks if a given AST node matches a specific pattern related to SET statements. + * @details Hanldes both `NODE_SET_STATEMENT` and `NODE_SET_NAMES` node types. This implementation + * serves as an equivalent to a previous regex-based approach (`match_regexes[1]`): + * - `NODE_SET_STATEMENT`: Verifies that the statement contains variable assignments, that each assigned + * variable is a tracked system variable (or "autocommit"), and that the system variable is present in + * the `tracked_vars` list. + * - `NODE_SET_NAMES`: Returns `true`, expected to be verified later. + * - Other node type: Returns `false`. + * @param node A pointer to the AST node to check. + * @return `true` if the node matches the expected pattern, `false` otherwise. + */ +bool p_match_regex_1(const MySQLParser::AstNode* node); +/** + * @brief Checks if a given AST node matches a specific pattern related to transaction SET statements. + * @details Handles `NODE_SET_STATEMENT` node types. This implementation + * serves as an equivalent to a previous regex-based approach (`match_regexes[2]`): + * - `NODE_SET_STATEMENT`: Verifies that the node's value is either "SET_SESSION_TRANSACTION" or + * "SET_TRANSACTION". + * - Other node type: Returns `false`. + * @param node A pointer to the AST node to check. + * @return `true` if the node matches the expected pattern, `false` otherwise. + */ +bool p_match_regex_2(const MySQLParser::AstNode* node); +/** + * @brief Checks if a given AST node matches a specific pattern related to SET CHARSET statements. + * @details Handles `NODE_SET_CHARSET` node types. This implementation + * serves as an equivalent to a previous regex-based approach (`match_regexes[3]`): + * - `NODE_SET_CHARSET`: Returns `true`. + * - Other node type: Returns `false`. + * @param node A pointer to the AST node to check. + * @return `true` if the node matches the expected pattern, `false` otherwise. + */ +bool p_match_regex_3(const MySQLParser::AstNode* node); +/** + * @brief Type used for improved error reporting for AST based validation. + * @details When returning an AST error message, it's expected to. + */ +struct perr_t { + /// Return code used for error identification. + int rc { 0 }; + /// Error message to report to the caller. + std::string msg {}; + /// Chain of conditions, or sub-errors, that add context to the error. + std::vector ctx {}; +}; + +/** + * @brief Verifies recurring simple expressions. + * @details The allowed expressions kinds are: + * + * - STRING_LITERAL + * - SYSTEM_VAR + * - EXPR + * |-- FUNCTION CALL EXPRS, eg: 'REPLACE(@@sql_mode, 'STRICT_ALL_TABLES', 'STRICT_TRANS_TABLES')' + * |-- STRING_LITERAL + * |-- SYSTEM_VAR (SQL_MODE), eg: 'CONCAT(@@sql_mode, LITERAL)' + * `-- SELECT_SUBQUERY, of kind '(SELECT STRING_LITERAL)' + * - (SELECT EXPR) - Previously defined 'EXPR' + * + * These definitions allows recursion, but only through the EXPR. Allowing generic recursion for + * '(SELECT EXPR)' was out of the scope. This can be enabled in the future. + * @param n The node from which to start the expression verification. + * @param offset Offset of the original query at which AST represented by 'n' is found. + * @return A pair of kind { success, error_message }. + */ +perr_t verf_sql_mode_val(const MySQLParser::AstNode* n, const std::string& v, const std::string& q); + +#endif // MYSQL_SET_PARSER_UTILS_H diff --git a/include/MySQL_Session.h b/include/MySQL_Session.h index 8474499fc4..535f483226 100644 --- a/include/MySQL_Session.h +++ b/include/MySQL_Session.h @@ -150,6 +150,11 @@ class MySQL_Session: public Base_Session& e, + const std::string& q + ); void handler___client_DSS_QUERY_SENT___server_DSS_NOT_INITIALIZED__get_connection(); @@ -374,8 +379,6 @@ class MySQL_Session: public Base_Session + +extern std::array mysql_match_regexes; + +#endif // MYSQL_SESSION_UTILS_H diff --git a/include/MySQL_Set_Stmt_Parser.h b/include/MySQL_Set_Stmt_Parser.h index fd2e77db11..8b5b4471f3 100644 --- a/include/MySQL_Set_Stmt_Parser.h +++ b/include/MySQL_Set_Stmt_Parser.h @@ -6,7 +6,6 @@ #include #include "re2/re2.h" -#include "re2/regexp.h" //#define PARSERDEBUG diff --git a/include/MySQL_Thread.h b/include/MySQL_Thread.h index 20eada2bae..ceecd631eb 100644 --- a/include/MySQL_Thread.h +++ b/include/MySQL_Thread.h @@ -15,6 +15,7 @@ #include "prometheus_helpers.h" #include "MySQL_Set_Stmt_Parser.h" +#include "MySQL_Parser.h" /* #define MIN_POLL_LEN 8 @@ -110,8 +111,6 @@ class __attribute__((aligned(64))) MySQL_Thread : public Base_Thread std::map sessmap; #endif // IDLE_THREADS - //Session_Regex **match_regexes; - #ifdef IDLE_THREADS void worker_thread_assigns_sessions_to_idle_thread(MySQL_Thread *thr); void worker_thread_gets_sessions_from_idle_thread(); @@ -193,6 +192,7 @@ class __attribute__((aligned(64))) MySQL_Thread : public Base_Thread // if set_parser_algorithm == 2 , a single thr_SetParser is used MySQL_Set_Stmt_Parser* thr_SetParser; + MySQLParser::Parser parser {}; MySQL_Thread(); ~MySQL_Thread(); diff --git a/include/MySQL_Variables.h b/include/MySQL_Variables.h index 4d0aa5c8a9..f8dc7d7910 100644 --- a/include/MySQL_Variables.h +++ b/include/MySQL_Variables.h @@ -1,17 +1,14 @@ #ifndef MYSQL_VARIABLES_H #define MYSQL_VARIABLES_H -#include "proxysql.h" -#include "cpp.h" +#include "proxysql_structs.h" #include +#include #include -#include class MySQL_Session; -extern void print_backtrace(void); - typedef bool (*verify_var)(MySQL_Session* session, int idx, uint32_t client_hash, uint32_t server_hash); typedef bool (*update_var)(MySQL_Session* session, int idx, int &_rc); @@ -26,10 +23,6 @@ class MySQL_Variables { static verify_var verifiers[SQL_NAME_LAST_HIGH_WM]; static update_var updaters[SQL_NAME_LAST_HIGH_WM]; -public: - std::string variables_regexp; - // ignore_vars is a list of all variables that proxysql will parse but ignore its value - std::vector ignore_vars; public: MySQL_Variables(); diff --git a/include/MySQL_Variables_Utils.h b/include/MySQL_Variables_Utils.h new file mode 100644 index 0000000000..7c2a319954 --- /dev/null +++ b/include/MySQL_Variables_Utils.h @@ -0,0 +1,16 @@ +#ifndef MYSQL_VARIABLES_UTILS_H +#define MYSQL_VARIABLES_UTILS_H + +#include +#include + +/** + * @brief Gets all the variables for ProxySQL to recognize but ignore. + */ +const std::vector& get_mysql_ignore_vars(); +/** + * @brief Gets a regex with all the variables ProxySQL should recognize for SET statements. + */ +const std::string& get_mysql_variables_regexp(); + +#endif diff --git a/include/PgSQL_Session.h b/include/PgSQL_Session.h index 664aaeaee7..94097ad66a 100644 --- a/include/PgSQL_Session.h +++ b/include/PgSQL_Session.h @@ -502,7 +502,6 @@ class PgSQL_Session : public Base_Session + +extern std::array pgsql_match_regexes; + +#endif // PGSQL_SESSION_UTILS_H diff --git a/include/PgSQL_Thread.h b/include/PgSQL_Thread.h index 874afd2c1f..b030366617 100644 --- a/include/PgSQL_Thread.h +++ b/include/PgSQL_Thread.h @@ -157,8 +157,6 @@ class __attribute__((aligned(64))) PgSQL_Thread : public Base_Thread std::map sessmap; #endif // IDLE_THREADS - //Session_Regex** match_regexes; - #ifdef IDLE_THREADS void worker_thread_assigns_sessions_to_idle_thread(PgSQL_Thread * thr); void worker_thread_gets_sessions_from_idle_thread(); diff --git a/include/PgSQL_Variables.h b/include/PgSQL_Variables.h index 04768bfa0c..0115f09867 100644 --- a/include/PgSQL_Variables.h +++ b/include/PgSQL_Variables.h @@ -21,10 +21,6 @@ class PgSQL_Variables { static pgsql_verify_var verifiers[PGSQL_NAME_LAST_HIGH_WM]; static pgsql_update_var updaters[PGSQL_NAME_LAST_HIGH_WM]; -public: - std::string variables_regexp; - // ignore_vars is a list of all variables that proxysql will parse but ignore its value - std::vector ignore_vars; public: PgSQL_Variables(); ~PgSQL_Variables(); diff --git a/include/PgSQL_Variables_Utils.h b/include/PgSQL_Variables_Utils.h new file mode 100644 index 0000000000..901fce88c1 --- /dev/null +++ b/include/PgSQL_Variables_Utils.h @@ -0,0 +1,16 @@ +#ifndef PGSQL_VARIABLES_UTILS_H +#define PGSQL_VARIABLES_UTILS_H + +#include +#include + +/** + * @brief Gets all the variables for ProxySQL to recognize but ignore. + */ +const std::vector& get_pgsql_ignore_vars(); +/** + * @brief Gets a regex with all the variables ProxySQL should recognize for SET statements. + */ +const std::string& get_pgsql_variables_regexp(); + +#endif diff --git a/include/btree.h b/include/btree.h index bb22e0cf33..fcc599e0b2 100644 --- a/include/btree.h +++ b/include/btree.h @@ -105,6 +105,7 @@ #include #include #include +#include #include #include #include diff --git a/include/gen_utils.h b/include/gen_utils.h index 68acb9ab01..ad0f3b7b01 100644 --- a/include/gen_utils.h +++ b/include/gen_utils.h @@ -3,8 +3,11 @@ #include #include -#include "proxysql.h" -#include "sqlite3db.h" + +#include "proxysql_structs.h" +#include "proxysql_mem.h" + +#include "mysql.h" #define MIN_ARRAY_LEN 8 #define MIN_ARRAY_DELETE_RATIO 8 diff --git a/include/proxysql_coredump.h b/include/proxysql_coredump.h index 2843de9acb..9890b0c3f7 100644 --- a/include/proxysql_coredump.h +++ b/include/proxysql_coredump.h @@ -1,6 +1,8 @@ #ifndef __PROXYSQL_COREDUMP_H #define __PROXYSQL_COREDUMP_H + #include +#include #define S1(x) #x #define S2(x) S1(x) diff --git a/include/proxysql_debug.h b/include/proxysql_debug.h index 569f92e00f..420f05f012 100644 --- a/include/proxysql_debug.h +++ b/include/proxysql_debug.h @@ -1,10 +1,6 @@ #ifndef __PROXYSQL_DEBUG_H #define __PROXYSQL_DEBUG_H -#include -#include -#include - #include "proxysql_macros.h" #if ENABLE_TIMER // this is defined in proxysql_macros.h diff --git a/include/proxysql_glovars.hpp b/include/proxysql_glovars.hpp index c5b52b2db1..d31889cfe9 100644 --- a/include/proxysql_glovars.hpp +++ b/include/proxysql_glovars.hpp @@ -50,6 +50,16 @@ class ProxySQL_Checksum_Value { } }; +// Forward declarations +//////////////////////////////////////////////////////////////////////////////// + +typedef struct ssl_ctx_st SSL_CTX; +typedef struct ssl_st SSL; + +typedef struct _debug_level debug_level; + +//////////////////////////////////////////////////////////////////////////////// + class ProxySQL_GlobalVariables { public: ez::ezOptionParser *opt; @@ -179,12 +189,4 @@ class ProxySQL_GlobalVariables { void install_signal_handler(); }; -/* -#ifndef PROXYSQL_EXTERN -#define EXTERN extern -#else -#define EXTERN -#endif // PROXYSQL_EXTERN -EXTERN ProxySQL_GlobalVariables GloVars; -*/ #endif /* __CLASS_PROXYSQL_GLOVARS_H */ diff --git a/include/proxysql_structs.h b/include/proxysql_structs.h index 90c7e02222..f9d16e451b 100644 --- a/include/proxysql_structs.h +++ b/include/proxysql_structs.h @@ -1,6 +1,12 @@ #define PKT_PARSED 0 #define PKT_ERROR 1 +#include +#include +#include +#include +#include + #ifdef max_allowed_packet #undef max_allowed_packet #endif @@ -1793,9 +1799,21 @@ mysql_variable_st mysql_tracked_variables[] { */ }; +/** + * @brief Holds an sorted vector (s_vector) of the variable names being tracked. + * @details This ordered vector is used for set statement matches by `p_match_regex_1`. + * It's always defined as 'extern' in headers, symbol is defined in 'proxysql_global.cpp'. + */ +extern const s_vector mysql_tracked_vars; #else extern mysql_variable_st mysql_tracked_variables[]; extern var_track_err_st perm_track_errs[]; +/** + * @brief Holds an sorted vector (s_vector) of the variable names being tracked. + * @details This ordered vector is used for set statement matches by `p_match_regex_1`. + * It's always defined as 'extern' in headers, symbol is defined in 'proxysql_global.cpp'. + */ +extern const s_vector mysql_tracked_vars; #endif // PROXYSQL_EXTERN #endif // MYSQL_TRACKED_VARIABLES diff --git a/include/proxysql_utils.h b/include/proxysql_utils.h index df8e13600b..832e031e63 100644 --- a/include/proxysql_utils.h +++ b/include/proxysql_utils.h @@ -2,6 +2,7 @@ #define __PROXYSQL_UTILS_H #include +#include #include #include #include @@ -141,6 +142,82 @@ cfmt_t cstr_format(char (&out_buf)[N], const char* fmt, ...) { } } +template +struct rm_cvref +{ + using type = std::remove_cv_t>; +}; + +template< class T > +using rm_cvref_t = typename rm_cvref::type; + +template +struct _h_fold : _h_fold +{}; + +/** + * @brief Helper type for 'fold', responsible for performing the type deduction. + * @tparam C Inferred type for the lambda, class or function object. + * @tparam R The return type of the function object. + * @tparam B The second parameter type (accumulator) of the function object. + * @tparam A The first parameter type (range value) of the function object. + */ +template +struct _h_fold +{ + template