/* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ /** @file services.cc Implementation part of the parser service layer. */ #include "my_config.h" #include "services.h" #include "template_utils.h" #include using std::string; namespace services { string print_digest(const unsigned char *digest) { const size_t string_size= PARSER_SERVICE_DIGEST_LENGTH * 2; char digest_str[string_size + sizeof('\0')]; for (int i= 0; i < PARSER_SERVICE_DIGEST_LENGTH; ++i) my_snprintf(digest_str + i * 2, string_size, "%02x", digest[i]); return digest_str; } bool Digest::load(MYSQL_THD thd) { return mysql_parser_get_statement_digest(thd, m_buf) != 0; } Session::Session(MYSQL_THD current_session) : m_previous_session(current_session), m_current_session(mysql_parser_open_session()) {} Condition_handler::~Condition_handler() {} /** Bridge function between the C++ API offered by this module and the C API of the parser service. This layer always uses a Condition_handler object that is passed to mysql_parser_parse(). */ int handle(int sql_errno, const char* sqlstate, const char* message, void *state) { Condition_handler *handler= static_cast(state); return handler->handle(sql_errno, sqlstate, message); } /// Convenience function, to avoid sprinkling the code with const_casts. static MYSQL_LEX_STRING make_lex_string(const string &str) { MYSQL_LEX_STRING lex_str= { const_cast(str.c_str()), str.length() }; return lex_str; } void set_current_database(MYSQL_THD thd, const string &db) { MYSQL_LEX_STRING db_str= make_lex_string(db); mysql_parser_set_current_database(thd, db_str); } bool parse(MYSQL_THD thd, const string &query, bool is_prepared, Condition_handler *handler) { MYSQL_LEX_STRING query_str= make_lex_string(query); return mysql_parser_parse(thd, query_str, is_prepared, handle, handler); } bool parse(MYSQL_THD thd, const string &query, bool is_prepared) { MYSQL_LEX_STRING query_str= make_lex_string(query); return mysql_parser_parse(thd, query_str, is_prepared, NULL, NULL); } bool is_select_statement(MYSQL_THD thd) { return mysql_parser_get_statement_type(thd) == STATEMENT_TYPE_SELECT; } int get_number_params(MYSQL_THD thd) { return mysql_parser_get_number_params(thd); } int process_item(MYSQL_ITEM item, uchar *arg) { Literal_visitor *visitor= pointer_cast(arg); if (visitor->visit(item)) return 1; return 0; } bool visit_parse_tree(MYSQL_THD thd, Literal_visitor *visitor) { uchar *arg= pointer_cast(visitor); return mysql_parser_visit_tree(thd, process_item, arg) != 0; } /** A very limited smart pointer to protect against stack unwinding in case an STL class throws an exception. The interface is similar to unique_ptr. */ class Lex_str { MYSQL_LEX_STRING m_str; Lex_str &operator= (const Lex_str&); Lex_str(const Lex_str&); public: Lex_str(MYSQL_LEX_STRING str) : m_str(str) {} const MYSQL_LEX_STRING get() { return m_str; } ~Lex_str() { mysql_parser_free_string(m_str); } }; /// Prints an Item as an std::string. string print_item(MYSQL_ITEM item) { Lex_str lex_str(mysql_parser_item_string(item)); string literal; literal.assign(lex_str.get().str, lex_str.get().length); return literal; } string get_current_query_normalized(MYSQL_THD thd) { MYSQL_LEX_STRING normalized_pattern= mysql_parser_get_normalized_query(thd); string s; s.assign(normalized_pattern.str, normalized_pattern.length); return s; } /** A very limited smart pointer to protect against stack unwinding in case an STL class throws an exception. The interface is similar to unique_ptr. */ class Array_ptr { int *m_ptr; Array_ptr &operator= (const Array_ptr&); Array_ptr(const Array_ptr&); public: Array_ptr(int *str) : m_ptr(str) {} int *get() { return m_ptr; } ~Array_ptr() { delete [] m_ptr; } }; std::vector get_parameter_positions(MYSQL_THD thd) { int number_params= get_number_params(thd); Array_ptr parameter_positions(new int[number_params]); mysql_parser_extract_prepared_params(thd, parameter_positions.get()); std::vector positions(parameter_positions.get(), parameter_positions.get() + number_params); return positions; } }