/* Copyright (c) 2015, 2017, 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 rules_table_service.cc Implementation of the service for accessing the rewrite rules table. */ #include #include "thr_lock.h" #include "table.h" #include "handler.h" #include "my_base.h" #include "my_bitmap.h" #include "field.h" #include "sql_string.h" #include "transaction.h" #include "sql_base.h" namespace rules_table_service { int MY_ATTRIBUTE((visibility("default"))) dummy_function_to_ensure_we_are_linked_into_the_server() { return 1; } const char *db_name= "query_rewrite"; const char *table_name= "rewrite_rules"; int Cursor::read() { TABLE *table= m_table_list->table; m_last_read_status= table->file->ha_rnd_next(table->record[0]); if (m_last_read_status != 0) m_is_finished= true; return m_last_read_status; } void free_string(const char *str) { delete [] str; } static void add_column(MY_BITMAP *map, Cursor::column_id column) { if (column != Cursor::ILLEGAL_COLUMN_ID) bitmap_set_bit(map, column); } Cursor::Cursor(MYSQL_THD mysql_thd) : m_thd(mysql_thd), m_table_list(NULL), m_is_finished(true), m_table_is_malformed(true) { m_table_list= new TABLE_LIST; if (m_table_list == NULL) return; // Error // The below function will memset() the whole object with 0's. m_table_list->init_one_table(db_name, strlen(db_name), table_name, strlen(table_name), "alias", TL_WRITE_DEFAULT); m_table_list->updating= true; if (open_and_lock_tables(m_thd, m_table_list, MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY)) return; // Error TABLE *table= m_table_list->table; if (table == NULL) return; // Error m_pattern_column= field_index("pattern"); m_pattern_database_column= field_index("pattern_database"); m_replacement_column= field_index("replacement"); m_enabled_column= field_index("enabled"); // The following columns are not required for the Cursor to work. m_message_column= field_index("message"); m_pattern_digest_column= field_index("pattern_digest"); m_normalized_pattern_column= field_index("normalized_pattern"); if (m_pattern_column == ILLEGAL_COLUMN_ID || m_pattern_database_column == ILLEGAL_COLUMN_ID || m_replacement_column == ILLEGAL_COLUMN_ID || m_enabled_column == ILLEGAL_COLUMN_ID) { trans_rollback_stmt(m_thd); close_thread_tables(m_thd); /* We are never going to use this table, we might as well get rid of the reference to it. */ delete m_table_list; m_table_list= NULL; m_table_is_malformed= true; return; // Error } else m_table_is_malformed= false; add_column(table->read_set, pattern_column()); add_column(table->read_set, pattern_database_column()); add_column(table->read_set, replacement_column()); add_column(table->read_set, enabled_column()); add_column(table->read_set, message_column()); add_column(table->write_set, enabled_column()); add_column(table->write_set, message_column()); add_column(table->write_set, pattern_digest_column()); add_column(table->write_set, normalized_pattern_column()); if (m_table_list->table->file->ha_rnd_init(true) != 0) return; // Error // No error occured, set this to false. m_is_finished= false; read(); } const char *Cursor::fetch_string(int fieldno) { Field **fields= m_table_list->table->field; Field *field= fields[fieldno]; if (field->is_null()) return NULL; String value_buf; String *value= field->val_str(&value_buf); size_t length= value->length(); char *res= new char[length + 1]; strncpy(res, value->ptr(), length); res[length]= '\0'; return res; } int Cursor::field_index(const char *field_name) { TABLE *table= m_table_list->table; for (uint i= 0; i < table->s->fields; ++i) if (strcmp(table->field[i]->field_name, field_name) == 0) return i; return -1; } void Cursor::make_writeable() { TABLE *table= m_table_list->table; memcpy(table->record[1], table->record[0], table->s->rec_buff_length); } void Cursor::set(int colno, const char* str, size_t length) { TABLE *table= m_table_list->table; Field *field= table->field[colno]; const CHARSET_INFO *charset= &my_charset_utf8_unicode_ci; if (str == NULL) field->set_null(0); else { field->store(str, length, charset); field->set_notnull(0); } } int Cursor::write() { TABLE *table= m_table_list->table; return table->file->ha_update_row(table->record[1], table->record[0]); } bool Cursor::had_serious_read_error() const { return m_last_read_status != 0 && m_last_read_status != HA_ERR_END_OF_FILE; } Cursor::~Cursor() { if (m_table_list != NULL && m_table_list->table != NULL) m_table_list->table->file->ha_rnd_end(); delete m_table_list; } Cursor end() { return Cursor(); } }