210 lines
5.4 KiB
C++
210 lines
5.4 KiB
C++
/* 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 <mysql/service_rules_table.h>
|
|
|
|
#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(); }
|
|
|
|
}
|