1 /* Copyright (c) 2015, 2021, Oracle and/or its affiliates.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License, version 2.0,
5 as published by the Free Software Foundation.
6
7 This program is also distributed with certain software (including
8 but not limited to OpenSSL) that is licensed under separate terms,
9 as designated in a particular file or component or in included license
10 documentation. The authors of MySQL hereby grant you an additional
11 permission to link the program and your derivative works with the
12 separately licensed software that they have included with MySQL.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License, version 2.0, for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software Foundation,
21 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
22
23 /**
24 @file rules_table_service.cc
25 Implementation of the service for accessing the rewrite rules table.
26 */
27
28 #include <mysql/service_rules_table.h>
29
30 #include "thr_lock.h"
31 #include "table.h"
32 #include "handler.h"
33 #include "my_base.h"
34 #include "my_bitmap.h"
35 #include "field.h"
36 #include "sql_string.h"
37 #include "transaction.h"
38 #include "sql_base.h"
39
40 namespace rules_table_service
41 {
42
43 int MY_ATTRIBUTE((visibility("default")))
dummy_function_to_ensure_we_are_linked_into_the_server()44 dummy_function_to_ensure_we_are_linked_into_the_server() { return 1; }
45
46 const char *db_name= "query_rewrite";
47 const char *table_name= "rewrite_rules";
48
read()49 int Cursor::read()
50 {
51 TABLE *table= m_table_list->table;
52 m_last_read_status= table->file->ha_rnd_next(table->record[0]);
53 if (m_last_read_status != 0)
54 m_is_finished= true;
55 return m_last_read_status;
56 }
57
58
free_string(const char * str)59 void free_string(const char *str) { delete [] str; }
60
61
add_column(MY_BITMAP * map,Cursor::column_id column)62 static void add_column(MY_BITMAP *map, Cursor::column_id column)
63 {
64 if (column != Cursor::ILLEGAL_COLUMN_ID)
65 bitmap_set_bit(map, column);
66 }
67
68
Cursor(MYSQL_THD mysql_thd)69 Cursor::Cursor(MYSQL_THD mysql_thd) :
70 m_thd(mysql_thd),
71 m_table_list(NULL),
72 m_is_finished(true),
73 m_table_is_malformed(true)
74 {
75 m_table_list= new TABLE_LIST;
76 if (m_table_list == NULL)
77 return; // Error
78
79 // The below function will memset() the whole object with 0's.
80 m_table_list->init_one_table(db_name, strlen(db_name),
81 table_name, strlen(table_name),
82 "alias", TL_WRITE_DEFAULT);
83
84 m_table_list->updating= true;
85
86 if (open_and_lock_tables(m_thd, m_table_list, MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY))
87 return; // Error
88
89 TABLE *table= m_table_list->table;
90 if (table == NULL)
91 return; // Error
92
93 m_pattern_column= field_index("pattern");
94 m_pattern_database_column= field_index("pattern_database");
95 m_replacement_column= field_index("replacement");
96 m_enabled_column= field_index("enabled");
97
98 // The following columns are not required for the Cursor to work.
99 m_message_column= field_index("message");
100 m_pattern_digest_column= field_index("pattern_digest");
101 m_normalized_pattern_column= field_index("normalized_pattern");
102
103 if (m_pattern_column == ILLEGAL_COLUMN_ID ||
104 m_pattern_database_column == ILLEGAL_COLUMN_ID ||
105 m_replacement_column == ILLEGAL_COLUMN_ID ||
106 m_enabled_column == ILLEGAL_COLUMN_ID)
107 {
108 trans_rollback_stmt(m_thd);
109 close_thread_tables(m_thd);
110
111 /*
112 We are never going to use this table, we might as well get rid of the
113 reference to it.
114 */
115 delete m_table_list;
116 m_table_list= NULL;
117 m_table_is_malformed= true;
118 return; // Error
119 }
120 else
121 m_table_is_malformed= false;
122
123 add_column(table->read_set, pattern_column());
124 add_column(table->read_set, pattern_database_column());
125 add_column(table->read_set, replacement_column());
126 add_column(table->read_set, enabled_column());
127 add_column(table->read_set, message_column());
128
129 add_column(table->write_set, enabled_column());
130 add_column(table->write_set, message_column());
131 add_column(table->write_set, pattern_digest_column());
132 add_column(table->write_set, normalized_pattern_column());
133
134 if (m_table_list->table->file->ha_rnd_init(true) != 0)
135 return; // Error
136
137 // No error occured, set this to false.
138 m_is_finished= false;
139
140 read();
141 }
142
143
fetch_string(int fieldno)144 const char *Cursor::fetch_string(int fieldno)
145 {
146 Field **fields= m_table_list->table->field;
147 Field *field= fields[fieldno];
148 if (field->is_null())
149 return NULL;
150 String value_buf;
151 String *value= field->val_str(&value_buf);
152 size_t length= value->length();
153 char *res= new char[length + 1];
154 strncpy(res, value->ptr(), length);
155 res[length]= '\0';
156 return res;
157 }
158
159
field_index(const char * field_name)160 int Cursor::field_index(const char *field_name)
161 {
162 TABLE *table= m_table_list->table;
163 for (uint i= 0; i < table->s->fields; ++i)
164 if (strcmp(table->field[i]->field_name, field_name) == 0)
165 return i;
166 return -1;
167 }
168
169
make_writeable()170 void Cursor::make_writeable()
171 {
172 TABLE *table= m_table_list->table;
173 memcpy(table->record[1], table->record[0], table->s->rec_buff_length);
174 }
175
176
set(int colno,const char * str,size_t length)177 void Cursor::set(int colno, const char* str, size_t length)
178 {
179 TABLE *table= m_table_list->table;
180 Field *field= table->field[colno];
181
182 const CHARSET_INFO *charset= &my_charset_utf8_unicode_ci;
183 if (str == NULL)
184 field->set_null(0);
185 else
186 {
187 field->store(str, length, charset);
188 field->set_notnull(0);
189 }
190 }
191
192
write()193 int Cursor::write()
194 {
195 TABLE *table= m_table_list->table;
196 return table->file->ha_update_row(table->record[1], table->record[0]);
197 }
198
had_serious_read_error() const199 bool Cursor::had_serious_read_error() const
200 {
201 return
202 m_last_read_status != 0 &&
203 m_last_read_status != HA_ERR_END_OF_FILE;
204 }
205
~Cursor()206 Cursor::~Cursor()
207 {
208 if (m_table_list != NULL && m_table_list->table != NULL)
209 m_table_list->table->file->ha_rnd_end();
210 delete m_table_list;
211 }
212
213
end()214 Cursor end() { return Cursor(); }
215
216 }
217