1 #ifndef SQL_PREPARE_H 2 #define SQL_PREPARE_H 3 /* Copyright (c) 1995-2008 MySQL AB, 2009 Sun Microsystems, Inc. 4 Use is subject to license terms. 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; version 2 of the License. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program; if not, write to the Free Software 17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ 18 19 #include "sql_error.h" 20 21 22 #define LAST_STMT_ID 0xFFFFFFFF 23 #define STMT_ID_MASK 0x7FFFFFFF 24 25 class THD; 26 struct LEX; 27 28 /** 29 An interface that is used to take an action when 30 the locking module notices that a table version has changed 31 since the last execution. "Table" here may refer to any kind of 32 table -- a base table, a temporary table, a view or an 33 information schema table. 34 35 When we open and lock tables for execution of a prepared 36 statement, we must verify that they did not change 37 since statement prepare. If some table did change, the statement 38 parse tree *may* be no longer valid, e.g. in case it contains 39 optimizations that depend on table metadata. 40 41 This class provides an interface (a method) that is 42 invoked when such a situation takes place. 43 The implementation of the method simply reports an error, but 44 the exact details depend on the nature of the SQL statement. 45 46 At most 1 instance of this class is active at a time, in which 47 case THD::m_reprepare_observer is not NULL. 48 49 @sa check_and_update_table_version() for details of the 50 version tracking algorithm 51 52 @sa Open_tables_state::m_reprepare_observer for the life cycle 53 of metadata observers. 54 */ 55 56 class Reprepare_observer 57 { 58 public: 59 /** 60 Check if a change of metadata is OK. In future 61 the signature of this method may be extended to accept the old 62 and the new versions, but since currently the check is very 63 simple, we only need the THD to report an error. 64 */ 65 bool report_error(THD *thd); is_invalidated()66 bool is_invalidated() const { return m_invalidated; } reset_reprepare_observer()67 void reset_reprepare_observer() { m_invalidated= FALSE; } 68 private: 69 bool m_invalidated; 70 }; 71 72 73 void mysqld_stmt_prepare(THD *thd, const char *packet, uint packet_length); 74 void mysqld_stmt_execute(THD *thd, char *packet, uint packet_length); 75 void mysqld_stmt_execute_bulk(THD *thd, char *packet, uint packet_length); 76 void mysqld_stmt_bulk_execute(THD *thd, char *packet, uint packet_length); 77 void mysqld_stmt_close(THD *thd, char *packet); 78 void mysql_sql_stmt_prepare(THD *thd); 79 void mysql_sql_stmt_execute(THD *thd); 80 void mysql_sql_stmt_execute_immediate(THD *thd); 81 void mysql_sql_stmt_close(THD *thd); 82 void mysqld_stmt_fetch(THD *thd, char *packet, uint packet_length); 83 void mysqld_stmt_reset(THD *thd, char *packet); 84 void mysql_stmt_get_longdata(THD *thd, char *pos, ulong packet_length); 85 void reinit_stmt_before_use(THD *thd, LEX *lex); 86 87 my_bool bulk_parameters_iterations(THD *thd); 88 my_bool bulk_parameters_set(THD *thd); 89 /** 90 Execute a fragment of server code in an isolated context, so that 91 it doesn't leave any effect on THD. THD must have no open tables. 92 The code must not leave any open tables around. 93 The result of execution (if any) is stored in Ed_result. 94 */ 95 96 class Server_runnable 97 { 98 public: 99 virtual bool execute_server_code(THD *thd)= 0; 100 virtual ~Server_runnable(); 101 }; 102 103 104 /** 105 Execute direct interface. 106 107 @todo Implement support for prelocked mode. 108 */ 109 110 class Ed_row; 111 112 /** 113 Ed_result_set -- a container with result set rows. 114 @todo Implement support for result set metadata and 115 automatic type conversion. 116 */ 117 118 class Ed_result_set 119 { 120 public: 121 operator List<Ed_row>&() { return *m_rows; } size()122 unsigned int size() const { return m_rows->elements; } 123 124 Ed_result_set(List<Ed_row> *rows_arg, size_t column_count, 125 MEM_ROOT *mem_root_arg); 126 127 /** We don't call member destructors, they all are POD types. */ ~Ed_result_set()128 ~Ed_result_set() {} 129 get_field_count()130 size_t get_field_count() const { return m_column_count; } 131 new(size_t size,MEM_ROOT * mem_root)132 static void *operator new(size_t size, MEM_ROOT *mem_root) 133 { return alloc_root(mem_root, size); } 134 static void operator delete(void *ptr, size_t size) throw (); delete(void *,MEM_ROOT *)135 static void operator delete(void *, MEM_ROOT *){} 136 private: 137 Ed_result_set(const Ed_result_set &); /* not implemented */ 138 Ed_result_set &operator=(Ed_result_set &); /* not implemented */ 139 private: 140 MEM_ROOT m_mem_root; 141 size_t m_column_count; 142 List<Ed_row> *m_rows; 143 Ed_result_set *m_next_rset; 144 friend class Ed_connection; 145 }; 146 147 148 class Ed_connection 149 { 150 public: 151 /** 152 Construct a new "execute direct" connection. 153 154 The connection can be used to execute SQL statements. 155 If the connection failed to initialize, the error 156 will be returned on the attempt to execute a statement. 157 158 @pre thd must have no open tables 159 while the connection is used. However, 160 Ed_connection works okay in LOCK TABLES mode. 161 Other properties of THD, such as the current warning 162 information, errors, etc. do not matter and are 163 preserved by Ed_connection. One thread may have many 164 Ed_connections created for it. 165 */ 166 Ed_connection(THD *thd); 167 168 /** 169 Execute one SQL statement. 170 171 Until this method is executed, no other methods of 172 Ed_connection can be used. Life cycle of Ed_connection is: 173 174 Initialized -> a statement has been executed -> 175 look at result, move to next result -> 176 look at result, move to next result -> 177 ... 178 moved beyond the last result == Initialized. 179 180 This method can be called repeatedly. Once it's invoked, 181 results of the previous execution are lost. 182 183 A result of execute_direct() can be either: 184 185 - success, no result set rows. In this case get_field_count() 186 returns 0. This happens after execution of INSERT, UPDATE, 187 DELETE, DROP and similar statements. Some other methods, such 188 as get_affected_rows() can be used to retrieve additional 189 result information. 190 191 - success, there are some result set rows (maybe 0). E.g. 192 happens after SELECT. In this case get_field_count() returns 193 the number of columns in a result set and store_result() 194 can be used to retrieve a result set.. 195 196 - an error, methods to retrieve error information can 197 be used. 198 199 @return execution status 200 @retval FALSE success, use get_field_count() 201 to determine what to do next. 202 @retval TRUE error, use get_last_error() 203 to see the error number. 204 */ 205 bool execute_direct(LEX_STRING sql_text); 206 207 /** 208 Same as the previous, but takes an instance of Server_runnable 209 instead of SQL statement text. 210 211 @return execution status 212 213 @retval FALSE success, use get_field_count() 214 if your code fragment is supposed to 215 return a result set 216 @retval TRUE failure 217 */ 218 bool execute_direct(Server_runnable *server_runnable); 219 220 /** 221 Get the number of affected (deleted, updated) 222 rows for the current statement. Can be 223 used for statements with get_field_count() == 0. 224 225 @sa Documentation for C API function 226 mysql_affected_rows(). 227 */ get_affected_rows()228 ulonglong get_affected_rows() const 229 { 230 return m_diagnostics_area.affected_rows(); 231 } 232 233 /** 234 Get the last insert id, if any. 235 236 @sa Documentation for mysql_insert_id(). 237 */ get_last_insert_id()238 ulonglong get_last_insert_id() const 239 { 240 return m_diagnostics_area.last_insert_id(); 241 } 242 243 /** 244 Get the total number of warnings for the last executed 245 statement. Note, that there is only one warning list even 246 if a statement returns multiple results. 247 248 @sa Documentation for C API function 249 mysql_num_warnings(). 250 */ get_warn_count()251 ulong get_warn_count() const 252 { 253 return m_diagnostics_area.warn_count(); 254 } 255 256 /** 257 The following members are only valid if execute_direct() 258 or move_to_next_result() returned an error. 259 They never fail, but if they are called when there is no 260 result, or no error, the result is not defined. 261 */ get_last_error()262 const char *get_last_error() const { return m_diagnostics_area.message(); } get_last_errno()263 unsigned int get_last_errno() const { return m_diagnostics_area.sql_errno(); } get_last_sqlstate()264 const char *get_last_sqlstate() const { return m_diagnostics_area.get_sqlstate(); } 265 266 /** 267 Provided get_field_count() is not 0, this never fails. You don't 268 need to free the result set, this is done automatically when 269 you advance to the next result set or destroy the connection. 270 Not returning const because of List iterator not accepting 271 Should be used when you would like Ed_connection to manage 272 result set memory for you. 273 */ use_result_set()274 Ed_result_set *use_result_set() { return m_current_rset; } 275 /** 276 Provided get_field_count() is not 0, this never fails. You 277 must free the returned result set. This can be called only 278 once after execute_direct(). 279 Should be used when you would like to get the results 280 and destroy the connection. 281 */ 282 Ed_result_set *store_result_set(); 283 284 /** 285 If the query returns multiple results, this method 286 can be checked if there is another result beyond the next 287 one. 288 Never fails. 289 */ has_next_result()290 bool has_next_result() const { return MY_TEST(m_current_rset->m_next_rset); } 291 /** 292 Only valid to call if has_next_result() returned true. 293 Otherwise the result is undefined. 294 */ move_to_next_result()295 bool move_to_next_result() 296 { 297 m_current_rset= m_current_rset->m_next_rset; 298 return MY_TEST(m_current_rset); 299 } 300 ~Ed_connection()301 ~Ed_connection() { free_old_result(); } 302 private: 303 Diagnostics_area m_diagnostics_area; 304 /** 305 Execute direct interface does not support multi-statements, only 306 multi-results. So we never have a situation when we have 307 a mix of result sets and OK or error packets. We either 308 have a single result set, a single error, or a single OK, 309 or we have a series of result sets, followed by an OK or error. 310 */ 311 THD *m_thd; 312 Ed_result_set *m_rsets; 313 Ed_result_set *m_current_rset; 314 friend class Protocol_local; 315 private: 316 void free_old_result(); 317 void add_result_set(Ed_result_set *ed_result_set); 318 private: 319 Ed_connection(const Ed_connection &); /* not implemented */ 320 Ed_connection &operator=(Ed_connection &); /* not implemented */ 321 }; 322 323 324 /** One result set column. */ 325 326 struct Ed_column: public LEX_STRING 327 { 328 /** Implementation note: destructor for this class is never called. */ 329 }; 330 331 332 /** One result set record. */ 333 334 class Ed_row: public Sql_alloc 335 { 336 public: 337 const Ed_column &operator[](const unsigned int column_index) const 338 { 339 return *get_column(column_index); 340 } get_column(const unsigned int column_index)341 const Ed_column *get_column(const unsigned int column_index) const 342 { 343 DBUG_ASSERT(column_index < size()); 344 return m_column_array + column_index; 345 } size()346 size_t size() const { return m_column_count; } 347 Ed_row(Ed_column * column_array_arg,size_t column_count_arg)348 Ed_row(Ed_column *column_array_arg, size_t column_count_arg) 349 :m_column_array(column_array_arg), 350 m_column_count(column_count_arg) 351 {} 352 private: 353 Ed_column *m_column_array; 354 size_t m_column_count; /* TODO: change to point to metadata */ 355 }; 356 357 #endif // SQL_PREPARE_H 358