00001 /* Copyright (C) 1995-2002 MySQL AB 00002 00003 This program is free software; you can redistribute it and/or modify 00004 it under the terms of the GNU General Public License as published by 00005 the Free Software Foundation; either version 2 of the License, or 00006 (at your option) any later version. 00007 00008 This program is distributed in the hope that it will be useful, 00009 but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00011 GNU General Public License for more details. 00012 00013 You should have received a copy of the GNU General Public License 00014 along with this program; if not, write to the Free Software 00015 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 00016 00017 /********************************************************************** 00018 This file contains the implementation of prepared statements. 00019 00020 When one prepares a statement: 00021 00022 - Server gets the query from client with command 'COM_STMT_PREPARE'; 00023 in the following format: 00024 [COM_STMT_PREPARE:1] [query] 00025 - Parse the query and recognize any parameter markers '?' and 00026 store its information list in lex->param_list 00027 - Allocate a new statement for this prepare; and keep this in 00028 'thd->stmt_map'. 00029 - Without executing the query, return back to client the total 00030 number of parameters along with result-set metadata information 00031 (if any) in the following format: 00032 [STMT_ID:4] 00033 [Column_count:2] 00034 [Param_count:2] 00035 [Params meta info (stubs only for now)] (if Param_count > 0) 00036 [Columns meta info] (if Column_count > 0) 00037 00038 When one executes a statement: 00039 00040 - Server gets the command 'COM_STMT_EXECUTE' to execute the 00041 previously prepared query. If there are any parameter markers, then the 00042 client will send the data in the following format: 00043 [COM_STMT_EXECUTE:1] 00044 [STMT_ID:4] 00045 [NULL_BITS:(param_count+7)/8)] 00046 [TYPES_SUPPLIED_BY_CLIENT(0/1):1] 00047 [[length]data] 00048 [[length]data] .. [[length]data]. 00049 (Note: Except for string/binary types; all other types will not be 00050 supplied with length field) 00051 - If it is a first execute or types of parameters were altered by client, 00052 then setup the conversion routines. 00053 - Assign parameter items from the supplied data. 00054 - Execute the query without re-parsing and send back the results 00055 to client 00056 00057 When one supplies long data for a placeholder: 00058 00059 - Server gets the long data in pieces with command type 00060 'COM_STMT_SEND_LONG_DATA'. 00061 - The packet recieved will have the format as: 00062 [COM_STMT_SEND_LONG_DATA:1][STMT_ID:4][parameter_number:2][data] 00063 - data from the packet is appended to the long data value buffer for this 00064 placeholder. 00065 - It's up to the client to stop supplying data chunks at any point. The 00066 server doesn't care; also, the server doesn't notify the client whether 00067 it got the data or not; if there is any error, then it will be returned 00068 at statement execute. 00069 00070 ***********************************************************************/ 00071 00072 #include "mysql_priv.h" 00073 #include "sql_select.h" // for JOIN 00074 #include "sql_cursor.h" 00075 #include "sp_head.h" 00076 #include "sp.h" 00077 #include "sp_cache.h" 00078 #ifdef EMBEDDED_LIBRARY 00079 /* include MYSQL_BIND headers */ 00080 #include <mysql.h> 00081 #else 00082 #include <mysql_com.h> 00083 #endif 00084 00085 /* A result class used to send cursor rows using the binary protocol. */ 00086 00087 class Select_fetch_protocol_prep: public select_send 00088 { 00089 Protocol_prep protocol; 00090 public: 00091 Select_fetch_protocol_prep(THD *thd); 00092 virtual bool send_fields(List<Item> &list, uint flags); 00093 virtual bool send_data(List<Item> &items); 00094 virtual bool send_eof(); 00095 #ifdef EMBEDDED_LIBRARY 00096 void begin_dataset() 00097 { 00098 protocol.begin_dataset(); 00099 } 00100 #endif 00101 }; 00102 00103 /****************************************************************************** 00104 Prepared_statement: a statement that can contain placeholders 00105 ******************************************************************************/ 00106 00107 class Prepared_statement: public Statement 00108 { 00109 public: 00110 enum flag_values 00111 { 00112 IS_IN_USE= 1 00113 }; 00114 00115 THD *thd; 00116 Select_fetch_protocol_prep result; 00117 Protocol *protocol; 00118 Item_param **param_array; 00119 uint param_count; 00120 uint last_errno; 00121 uint flags; 00122 char last_error[MYSQL_ERRMSG_SIZE]; 00123 #ifndef EMBEDDED_LIBRARY 00124 bool (*set_params)(Prepared_statement *st, uchar *data, uchar *data_end, 00125 uchar *read_pos, String *expanded_query); 00126 #else 00127 bool (*set_params_data)(Prepared_statement *st, String *expanded_query); 00128 #endif 00129 bool (*set_params_from_vars)(Prepared_statement *stmt, 00130 List<LEX_STRING>& varnames, 00131 String *expanded_query); 00132 public: 00133 Prepared_statement(THD *thd_arg, Protocol *protocol_arg); 00134 virtual ~Prepared_statement(); 00135 void setup_set_params(); 00136 virtual Query_arena::Type type() const; 00137 virtual void cleanup_stmt(); 00138 bool set_name(LEX_STRING *name); 00139 inline void close_cursor() { delete cursor; cursor= 0; } 00140 00141 bool prepare(const char *packet, uint packet_length); 00142 bool execute(String *expanded_query, bool open_cursor); 00143 /* Destroy this statement */ 00144 bool deallocate(); 00145 }; 00146 00147 00148 /****************************************************************************** 00149 Implementation 00150 ******************************************************************************/ 00151 00152 00153 inline bool is_param_null(const uchar *pos, ulong param_no) 00154 { 00155 return pos[param_no/8] & (1 << (param_no & 7)); 00156 } 00157 00158 /* 00159 Find a prepared statement in the statement map by id. 00160 00161 SYNOPSIS 00162 find_prepared_statement() 00163 thd thread handle 00164 id statement id 00165 where the place from which this function is called (for 00166 error reporting). 00167 00168 DESCRIPTION 00169 Try to find a prepared statement and set THD error if it's not found. 00170 00171 RETURN VALUE 00172 0 if the statement was not found, a pointer otherwise. 00173 */ 00174 00175 static Prepared_statement * 00176 find_prepared_statement(THD *thd, ulong id, const char *where) 00177 { 00178 /* 00179 To strictly separate namespaces of SQL prepared statements and C API 00180 prepared statements find() will return 0 if there is a named prepared 00181 statement with such id. 00182 */ 00183 Statement *stmt= thd->stmt_map.find(id); 00184 00185 if (stmt == 0 || stmt->type() != Query_arena::PREPARED_STATEMENT) 00186 { 00187 char llbuf[22]; 00188 my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0), sizeof(llbuf), llstr(id, llbuf), 00189 where); 00190 return 0; 00191 } 00192 return (Prepared_statement *) stmt; 00193 } 00194 00195 00196 /* 00197 Send prepared statement id and metadata to the client after prepare. 00198 00199 SYNOPSIS 00200 send_prep_stmt() 00201 00202 RETURN VALUE 00203 0 in case of success, 1 otherwise 00204 */ 00205 00206 #ifndef EMBEDDED_LIBRARY 00207 static bool send_prep_stmt(Prepared_statement *stmt, uint columns) 00208 { 00209 NET *net= &stmt->thd->net; 00210 char buff[12]; 00211 uint tmp; 00212 DBUG_ENTER("send_prep_stmt"); 00213 00214 buff[0]= 0; /* OK packet indicator */ 00215 int4store(buff+1, stmt->id); 00216 int2store(buff+5, columns); 00217 int2store(buff+7, stmt->param_count); 00218 buff[9]= 0; // Guard against a 4.1 client 00219 tmp= min(stmt->thd->total_warn_count, 65535); 00220 int2store(buff+10, tmp); 00221 00222 /* 00223 Send types and names of placeholders to the client 00224 XXX: fix this nasty upcast from List<Item_param> to List<Item> 00225 */ 00226 DBUG_RETURN(my_net_write(net, buff, sizeof(buff)) || 00227 (stmt->param_count && 00228 stmt->thd->protocol_simple.send_fields((List<Item> *) 00229 &stmt->lex->param_list, 00230 Protocol::SEND_EOF))); 00231 } 00232 #else 00233 static bool send_prep_stmt(Prepared_statement *stmt, 00234 uint columns __attribute__((unused))) 00235 { 00236 THD *thd= stmt->thd; 00237 00238 thd->client_stmt_id= stmt->id; 00239 thd->client_param_count= stmt->param_count; 00240 thd->clear_error(); 00241 00242 return 0; 00243 } 00244 #endif 00247 /* 00248 Read the length of the parameter data and return it back to 00249 the caller. 00250 00251 SYNOPSIS 00252 get_param_length() 00253 packet a pointer to the data 00254 len remaining packet length 00255 00256 DESCRIPTION 00257 Read data length, position the packet to the first byte after it, 00258 and return the length to the caller. 00259 00260 RETURN VALUE 00261 Length of data piece. 00262 */ 00263 00264 #ifndef EMBEDDED_LIBRARY 00265 static ulong get_param_length(uchar **packet, ulong len) 00266 { 00267 reg1 uchar *pos= *packet; 00268 if (len < 1) 00269 return 0; 00270 if (*pos < 251) 00271 { 00272 (*packet)++; 00273 return (ulong) *pos; 00274 } 00275 if (len < 3) 00276 return 0; 00277 if (*pos == 252) 00278 { 00279 (*packet)+=3; 00280 return (ulong) uint2korr(pos+1); 00281 } 00282 if (len < 4) 00283 return 0; 00284 if (*pos == 253) 00285 { 00286 (*packet)+=4; 00287 return (ulong) uint3korr(pos+1); 00288 } 00289 if (len < 5) 00290 return 0; 00291 (*packet)+=9; // Must be 254 when here 00292 /* 00293 In our client-server protocol all numbers bigger than 2^24 00294 stored as 8 bytes with uint8korr. Here we always know that 00295 parameter length is less than 2^4 so don't look at the second 00296 4 bytes. But still we need to obey the protocol hence 9 in the 00297 assignment above. 00298 */ 00299 return (ulong) uint4korr(pos+1); 00300 } 00301 #else 00302 #define get_param_length(packet, len) len 00303 #endif 00305 /* 00306 Data conversion routines. 00307 00308 SYNOPSIS 00309 set_param_xx() 00310 param parameter item 00311 pos input data buffer 00312 len length of data in the buffer 00313 00314 DESCRIPTION 00315 All these functions read the data from pos, convert it to requested 00316 type and assign to param; pos is advanced to predefined length. 00317 00318 Make a note that the NULL handling is examined at first execution 00319 (i.e. when input types altered) and for all subsequent executions 00320 we don't read any values for this. 00321 00322 RETURN VALUE 00323 none 00324 */ 00325 00326 static void set_param_tiny(Item_param *param, uchar **pos, ulong len) 00327 { 00328 #ifndef EMBEDDED_LIBRARY 00329 if (len < 1) 00330 return; 00331 #endif 00332 int8 value= (int8) **pos; 00333 param->set_int(param->unsigned_flag ? (longlong) ((uint8) value) : 00334 (longlong) value, 4); 00335 *pos+= 1; 00336 } 00337 00338 static void set_param_short(Item_param *param, uchar **pos, ulong len) 00339 { 00340 int16 value; 00341 #ifndef EMBEDDED_LIBRARY 00342 if (len < 2) 00343 return; 00344 value= sint2korr(*pos); 00345 #else 00346 shortget(value, *pos); 00347 #endif 00348 param->set_int(param->unsigned_flag ? (longlong) ((uint16) value) : 00349 (longlong) value, 6); 00350 *pos+= 2; 00351 } 00352 00353 static void set_param_int32(Item_param *param, uchar **pos, ulong len) 00354 { 00355 int32 value; 00356 #ifndef EMBEDDED_LIBRARY 00357 if (len < 4) 00358 return; 00359 value= sint4korr(*pos); 00360 #else 00361 longget(value, *pos); 00362 #endif 00363 param->set_int(param->unsigned_flag ? (longlong) ((uint32) value) : 00364 (longlong) value, 11); 00365 *pos+= 4; 00366 } 00367 00368 static void set_param_int64(Item_param *param, uchar **pos, ulong len) 00369 { 00370 longlong value; 00371 #ifndef EMBEDDED_LIBRARY 00372 if (len < 8) 00373 return; 00374 value= (longlong) sint8korr(*pos); 00375 #else 00376 longlongget(value, *pos); 00377 #endif 00378 param->set_int(value, 21); 00379 *pos+= 8; 00380 } 00381 00382 static void set_param_float(Item_param *param, uchar **pos, ulong len) 00383 { 00384 float data; 00385 #ifndef EMBEDDED_LIBRARY 00386 if (len < 4) 00387 return; 00388 float4get(data,*pos); 00389 #else 00390 floatget(data, *pos); 00391 #endif 00392 param->set_double((double) data); 00393 *pos+= 4; 00394 } 00395 00396 static void set_param_double(Item_param *param, uchar **pos, ulong len) 00397 { 00398 double data; 00399 #ifndef EMBEDDED_LIBRARY 00400 if (len < 8) 00401 return; 00402 float8get(data,*pos); 00403 #else 00404 doubleget(data, *pos); 00405 #endif 00406 param->set_double((double) data); 00407 *pos+= 8; 00408 } 00409 00410 static void set_param_decimal(Item_param *param, uchar **pos, ulong len) 00411 { 00412 ulong length= get_param_length(pos, len); 00413 param->set_decimal((char*)*pos, length); 00414 *pos+= length; 00415 } 00416 00417 #ifndef EMBEDDED_LIBRARY 00418 00419 /* 00420 Read date/time/datetime parameter values from network (binary 00421 protocol). See writing counterparts of these functions in 00422 libmysql.c (store_param_{time,date,datetime}). 00423 */ 00424 00425 static void set_param_time(Item_param *param, uchar **pos, ulong len) 00426 { 00427 MYSQL_TIME tm; 00428 ulong length= get_param_length(pos, len); 00429 00430 if (length >= 8) 00431 { 00432 uchar *to= *pos; 00433 uint day; 00434 00435 tm.neg= (bool) to[0]; 00436 day= (uint) sint4korr(to+1); 00437 tm.hour= (uint) to[5] + day * 24; 00438 tm.minute= (uint) to[6]; 00439 tm.second= (uint) to[7]; 00440 tm.second_part= (length > 8) ? (ulong) sint4korr(to+8) : 0; 00441 if (tm.hour > 838) 00442 { 00443 /* TODO: add warning 'Data truncated' here */ 00444 tm.hour= 838; 00445 tm.minute= 59; 00446 tm.second= 59; 00447 } 00448 tm.day= tm.year= tm.month= 0; 00449 } 00450 else 00451 set_zero_time(&tm, MYSQL_TIMESTAMP_TIME); 00452 param->set_time(&tm, MYSQL_TIMESTAMP_TIME, 00453 MAX_TIME_WIDTH * MY_CHARSET_BIN_MB_MAXLEN); 00454 *pos+= length; 00455 } 00456 00457 static void set_param_datetime(Item_param *param, uchar **pos, ulong len) 00458 { 00459 MYSQL_TIME tm; 00460 ulong length= get_param_length(pos, len); 00461 00462 if (length >= 4) 00463 { 00464 uchar *to= *pos; 00465 00466 tm.neg= 0; 00467 tm.year= (uint) sint2korr(to); 00468 tm.month= (uint) to[2]; 00469 tm.day= (uint) to[3]; 00470 if (length > 4) 00471 { 00472 tm.hour= (uint) to[4]; 00473 tm.minute= (uint) to[5]; 00474 tm.second= (uint) to[6]; 00475 } 00476 else 00477 tm.hour= tm.minute= tm.second= 0; 00478 00479 tm.second_part= (length > 7) ? (ulong) sint4korr(to+7) : 0; 00480 } 00481 else 00482 set_zero_time(&tm, MYSQL_TIMESTAMP_DATETIME); 00483 param->set_time(&tm, MYSQL_TIMESTAMP_DATETIME, 00484 MAX_DATETIME_WIDTH * MY_CHARSET_BIN_MB_MAXLEN); 00485 *pos+= length; 00486 } 00487 00488 00489 static void set_param_date(Item_param *param, uchar **pos, ulong len) 00490 { 00491 MYSQL_TIME tm; 00492 ulong length= get_param_length(pos, len); 00493 00494 if (length >= 4) 00495 { 00496 uchar *to= *pos; 00497 00498 tm.year= (uint) sint2korr(to); 00499 tm.month= (uint) to[2]; 00500 tm.day= (uint) to[3]; 00501 00502 tm.hour= tm.minute= tm.second= 0; 00503 tm.second_part= 0; 00504 tm.neg= 0; 00505 } 00506 else 00507 set_zero_time(&tm, MYSQL_TIMESTAMP_DATE); 00508 param->set_time(&tm, MYSQL_TIMESTAMP_DATE, 00509 MAX_DATE_WIDTH * MY_CHARSET_BIN_MB_MAXLEN); 00510 *pos+= length; 00511 } 00512 00513 #else 00514 void set_param_time(Item_param *param, uchar **pos, ulong len) 00515 { 00516 MYSQL_TIME tm= *((MYSQL_TIME*)*pos); 00517 tm.hour+= tm.day * 24; 00518 tm.day= tm.year= tm.month= 0; 00519 if (tm.hour > 838) 00520 { 00521 /* TODO: add warning 'Data truncated' here */ 00522 tm.hour= 838; 00523 tm.minute= 59; 00524 tm.second= 59; 00525 } 00526 param->set_time(&tm, MYSQL_TIMESTAMP_TIME, 00527 MAX_TIME_WIDTH * MY_CHARSET_BIN_MB_MAXLEN); 00528 00529 } 00530 00531 void set_param_datetime(Item_param *param, uchar **pos, ulong len) 00532 { 00533 MYSQL_TIME tm= *((MYSQL_TIME*)*pos); 00534 tm.neg= 0; 00535 00536 param->set_time(&tm, MYSQL_TIMESTAMP_DATETIME, 00537 MAX_DATETIME_WIDTH * MY_CHARSET_BIN_MB_MAXLEN); 00538 } 00539 00540 void set_param_date(Item_param *param, uchar **pos, ulong len) 00541 { 00542 MYSQL_TIME *to= (MYSQL_TIME*)*pos; 00543 00544 param->set_time(to, MYSQL_TIMESTAMP_DATE, 00545 MAX_DATE_WIDTH * MY_CHARSET_BIN_MB_MAXLEN); 00546 } 00547 #endif 00550 static void set_param_str(Item_param *param, uchar **pos, ulong len) 00551 { 00552 ulong length= get_param_length(pos, len); 00553 param->set_str((const char *)*pos, length); 00554 *pos+= length; 00555 } 00556 00557 00558 #undef get_param_length 00559 00560 static void setup_one_conversion_function(THD *thd, Item_param *param, 00561 uchar param_type) 00562 { 00563 switch (param_type) { 00564 case MYSQL_TYPE_TINY: 00565 param->set_param_func= set_param_tiny; 00566 param->item_type= Item::INT_ITEM; 00567 param->item_result_type= INT_RESULT; 00568 break; 00569 case MYSQL_TYPE_SHORT: 00570 param->set_param_func= set_param_short; 00571 param->item_type= Item::INT_ITEM; 00572 param->item_result_type= INT_RESULT; 00573 break; 00574 case MYSQL_TYPE_LONG: 00575 param->set_param_func= set_param_int32; 00576 param->item_type= Item::INT_ITEM; 00577 param->item_result_type= INT_RESULT; 00578 break; 00579 case MYSQL_TYPE_LONGLONG: 00580 param->set_param_func= set_param_int64; 00581 param->item_type= Item::INT_ITEM; 00582 param->item_result_type= INT_RESULT; 00583 break; 00584 case MYSQL_TYPE_FLOAT: 00585 param->set_param_func= set_param_float; 00586 param->item_type= Item::REAL_ITEM; 00587 param->item_result_type= REAL_RESULT; 00588 break; 00589 case MYSQL_TYPE_DOUBLE: 00590 param->set_param_func= set_param_double; 00591 param->item_type= Item::REAL_ITEM; 00592 param->item_result_type= REAL_RESULT; 00593 break; 00594 case MYSQL_TYPE_DECIMAL: 00595 case MYSQL_TYPE_NEWDECIMAL: 00596 param->set_param_func= set_param_decimal; 00597 param->item_type= Item::DECIMAL_ITEM; 00598 param->item_result_type= DECIMAL_RESULT; 00599 break; 00600 case MYSQL_TYPE_TIME: 00601 param->set_param_func= set_param_time; 00602 param->item_type= Item::STRING_ITEM; 00603 param->item_result_type= STRING_RESULT; 00604 break; 00605 case MYSQL_TYPE_DATE: 00606 param->set_param_func= set_param_date; 00607 param->item_type= Item::STRING_ITEM; 00608 param->item_result_type= STRING_RESULT; 00609 break; 00610 case MYSQL_TYPE_DATETIME: 00611 case MYSQL_TYPE_TIMESTAMP: 00612 param->set_param_func= set_param_datetime; 00613 param->item_type= Item::STRING_ITEM; 00614 param->item_result_type= STRING_RESULT; 00615 break; 00616 case MYSQL_TYPE_TINY_BLOB: 00617 case MYSQL_TYPE_MEDIUM_BLOB: 00618 case MYSQL_TYPE_LONG_BLOB: 00619 case MYSQL_TYPE_BLOB: 00620 param->set_param_func= set_param_str; 00621 param->value.cs_info.character_set_of_placeholder= &my_charset_bin; 00622 param->value.cs_info.character_set_client= 00623 thd->variables.character_set_client; 00624 DBUG_ASSERT(thd->variables.character_set_client); 00625 param->value.cs_info.final_character_set_of_str_value= &my_charset_bin; 00626 param->item_type= Item::STRING_ITEM; 00627 param->item_result_type= STRING_RESULT; 00628 break; 00629 default: 00630 /* 00631 The client library ensures that we won't get any other typecodes 00632 except typecodes above and typecodes for string types. Marking 00633 label as 'default' lets us to handle malformed packets as well. 00634 */ 00635 { 00636 CHARSET_INFO *fromcs= thd->variables.character_set_client; 00637 CHARSET_INFO *tocs= thd->variables.collation_connection; 00638 uint32 dummy_offset; 00639 00640 param->value.cs_info.character_set_of_placeholder= fromcs; 00641 param->value.cs_info.character_set_client= fromcs; 00642 00643 /* 00644 Setup source and destination character sets so that they 00645 are different only if conversion is necessary: this will 00646 make later checks easier. 00647 */ 00648 param->value.cs_info.final_character_set_of_str_value= 00649 String::needs_conversion(0, fromcs, tocs, &dummy_offset) ? 00650 tocs : fromcs; 00651 param->set_param_func= set_param_str; 00652 /* 00653 Exact value of max_length is not known unless data is converted to 00654 charset of connection, so we have to set it later. 00655 */ 00656 param->item_type= Item::STRING_ITEM; 00657 param->item_result_type= STRING_RESULT; 00658 } 00659 } 00660 param->param_type= (enum enum_field_types) param_type; 00661 } 00662 00663 #ifndef EMBEDDED_LIBRARY 00664 /* 00665 Routines to assign parameters from data supplied by the client. 00666 00667 DESCRIPTION 00668 Update the parameter markers by reading data from the packet and 00669 and generate a valid query for logging. 00670 00671 NOTES 00672 This function, along with other _withlog functions is called when one of 00673 binary, slow or general logs is open. Logging of prepared statements in 00674 all cases is performed by means of conventional queries: if parameter 00675 data was supplied from C API, each placeholder in the query is 00676 replaced with its actual value; if we're logging a [Dynamic] SQL 00677 prepared statement, parameter markers are replaced with variable names. 00678 Example: 00679 mysql_stmt_prepare("UPDATE t1 SET a=a*1.25 WHERE a=?") 00680 --> general logs gets [Prepare] UPDATE t1 SET a*1.25 WHERE a=?" 00681 mysql_stmt_execute(stmt); 00682 --> general and binary logs get 00683 [Execute] UPDATE t1 SET a*1.25 WHERE a=1" 00684 If a statement has been prepared using SQL syntax: 00685 PREPARE stmt FROM "UPDATE t1 SET a=a*1.25 WHERE a=?" 00686 --> general log gets 00687 [Query] PREPARE stmt FROM "UPDATE ..." 00688 EXECUTE stmt USING @a 00689 --> general log gets 00690 [Query] EXECUTE stmt USING @a; 00691 00692 RETURN VALUE 00693 0 if success, 1 otherwise 00694 */ 00695 00696 static bool insert_params_withlog(Prepared_statement *stmt, uchar *null_array, 00697 uchar *read_pos, uchar *data_end, 00698 String *query) 00699 { 00700 THD *thd= stmt->thd; 00701 Item_param **begin= stmt->param_array; 00702 Item_param **end= begin + stmt->param_count; 00703 uint32 length= 0; 00704 String str; 00705 const String *res; 00706 DBUG_ENTER("insert_params_withlog"); 00707 00708 if (query->copy(stmt->query, stmt->query_length, default_charset_info)) 00709 DBUG_RETURN(1); 00710 00711 for (Item_param **it= begin; it < end; ++it) 00712 { 00713 Item_param *param= *it; 00714 if (param->state != Item_param::LONG_DATA_VALUE) 00715 { 00716 if (is_param_null(null_array, it - begin)) 00717 param->set_null(); 00718 else 00719 { 00720 if (read_pos >= data_end) 00721 DBUG_RETURN(1); 00722 param->set_param_func(param, &read_pos, data_end - read_pos); 00723 } 00724 } 00725 res= param->query_val_str(&str); 00726 if (param->convert_str_value(thd)) 00727 DBUG_RETURN(1); /* out of memory */ 00728 00729 if (query->replace(param->pos_in_query+length, 1, *res)) 00730 DBUG_RETURN(1); 00731 00732 length+= res->length()-1; 00733 } 00734 DBUG_RETURN(0); 00735 } 00736 00737 00738 static bool insert_params(Prepared_statement *stmt, uchar *null_array, 00739 uchar *read_pos, uchar *data_end, 00740 String *expanded_query) 00741 { 00742 Item_param **begin= stmt->param_array; 00743 Item_param **end= begin + stmt->param_count; 00744 00745 DBUG_ENTER("insert_params"); 00746 00747 for (Item_param **it= begin; it < end; ++it) 00748 { 00749 Item_param *param= *it; 00750 if (param->state != Item_param::LONG_DATA_VALUE) 00751 { 00752 if (is_param_null(null_array, it - begin)) 00753 param->set_null(); 00754 else 00755 { 00756 if (read_pos >= data_end) 00757 DBUG_RETURN(1); 00758 param->set_param_func(param, &read_pos, data_end - read_pos); 00759 } 00760 } 00761 if (param->convert_str_value(stmt->thd)) 00762 DBUG_RETURN(1); /* out of memory */ 00763 } 00764 DBUG_RETURN(0); 00765 } 00766 00767 00768 static bool setup_conversion_functions(Prepared_statement *stmt, 00769 uchar **data, uchar *data_end) 00770 { 00771 /* skip null bits */ 00772 uchar *read_pos= *data + (stmt->param_count+7) / 8; 00773 00774 DBUG_ENTER("setup_conversion_functions"); 00775 00776 if (*read_pos++) //types supplied / first execute 00777 { 00778 /* 00779 First execute or types altered by the client, setup the 00780 conversion routines for all parameters (one time) 00781 */ 00782 Item_param **it= stmt->param_array; 00783 Item_param **end= it + stmt->param_count; 00784 THD *thd= stmt->thd; 00785 for (; it < end; ++it) 00786 { 00787 ushort typecode; 00788 const uint signed_bit= 1 << 15; 00789 00790 if (read_pos >= data_end) 00791 DBUG_RETURN(1); 00792 00793 typecode= sint2korr(read_pos); 00794 read_pos+= 2; 00795 (**it).unsigned_flag= test(typecode & signed_bit); 00796 setup_one_conversion_function(thd, *it, (uchar) (typecode & ~signed_bit)); 00797 } 00798 } 00799 *data= read_pos; 00800 DBUG_RETURN(0); 00801 } 00802 00803 #else 00804 00805 /* 00806 Embedded counterparts of parameter assignment routines. 00807 00808 DESCRIPTION 00809 The main difference between the embedded library and the server is 00810 that in embedded case we don't serialize/deserialize parameters data. 00811 Additionally, for unknown reason, the client-side flag raised for 00812 changed types of placeholders is ignored and we simply setup conversion 00813 functions at each execute (TODO: fix). 00814 */ 00815 00816 static bool emb_insert_params(Prepared_statement *stmt, String *expanded_query) 00817 { 00818 THD *thd= stmt->thd; 00819 Item_param **it= stmt->param_array; 00820 Item_param **end= it + stmt->param_count; 00821 MYSQL_BIND *client_param= stmt->thd->client_params; 00822 00823 DBUG_ENTER("emb_insert_params"); 00824 00825 for (; it < end; ++it, ++client_param) 00826 { 00827 Item_param *param= *it; 00828 setup_one_conversion_function(thd, param, client_param->buffer_type); 00829 if (param->state != Item_param::LONG_DATA_VALUE) 00830 { 00831 if (*client_param->is_null) 00832 param->set_null(); 00833 else 00834 { 00835 uchar *buff= (uchar*) client_param->buffer; 00836 param->unsigned_flag= client_param->is_unsigned; 00837 param->set_param_func(param, &buff, 00838 client_param->length ? 00839 *client_param->length : 00840 client_param->buffer_length); 00841 } 00842 } 00843 if (param->convert_str_value(thd)) 00844 DBUG_RETURN(1); /* out of memory */ 00845 } 00846 DBUG_RETURN(0); 00847 } 00848 00849 00850 static bool emb_insert_params_withlog(Prepared_statement *stmt, String *query) 00851 { 00852 THD *thd= stmt->thd; 00853 Item_param **it= stmt->param_array; 00854 Item_param **end= it + stmt->param_count; 00855 MYSQL_BIND *client_param= thd->client_params; 00856 00857 String str; 00858 const String *res; 00859 uint32 length= 0; 00860 00861 DBUG_ENTER("emb_insert_params_withlog"); 00862 00863 if (query->copy(stmt->query, stmt->query_length, default_charset_info)) 00864 DBUG_RETURN(1); 00865 00866 for (; it < end; ++it, ++client_param) 00867 { 00868 Item_param *param= *it; 00869 setup_one_conversion_function(thd, param, client_param->buffer_type); 00870 if (param->state != Item_param::LONG_DATA_VALUE) 00871 { 00872 if (*client_param->is_null) 00873 param->set_null(); 00874 else 00875 { 00876 uchar *buff= (uchar*)client_param->buffer; 00877 param->unsigned_flag= client_param->is_unsigned; 00878 param->set_param_func(param, &buff, 00879 client_param->length ? 00880 *client_param->length : 00881 client_param->buffer_length); 00882 } 00883 } 00884 res= param->query_val_str(&str); 00885 if (param->convert_str_value(thd)) 00886 DBUG_RETURN(1); /* out of memory */ 00887 00888 if (query->replace(param->pos_in_query+length, 1, *res)) 00889 DBUG_RETURN(1); 00890 00891 length+= res->length()-1; 00892 } 00893 DBUG_RETURN(0); 00894 } 00895 00896 #endif 00899 /* 00900 Assign prepared statement parameters from user variables. 00901 00902 SYNOPSIS 00903 insert_params_from_vars() 00904 stmt Statement 00905 varnames List of variables. Caller must ensure that number of variables 00906 in the list is equal to number of statement parameters 00907 query Ignored 00908 */ 00909 00910 static bool insert_params_from_vars(Prepared_statement *stmt, 00911 List<LEX_STRING>& varnames, 00912 String *query __attribute__((unused))) 00913 { 00914 Item_param **begin= stmt->param_array; 00915 Item_param **end= begin + stmt->param_count; 00916 user_var_entry *entry; 00917 LEX_STRING *varname; 00918 List_iterator<LEX_STRING> var_it(varnames); 00919 DBUG_ENTER("insert_params_from_vars"); 00920 00921 for (Item_param **it= begin; it < end; ++it) 00922 { 00923 Item_param *param= *it; 00924 varname= var_it++; 00925 entry= (user_var_entry*)hash_search(&stmt->thd->user_vars, 00926 (byte*) varname->str, 00927 varname->length); 00928 if (param->set_from_user_var(stmt->thd, entry) || 00929 param->convert_str_value(stmt->thd)) 00930 DBUG_RETURN(1); 00931 } 00932 DBUG_RETURN(0); 00933 } 00934 00935 00936 /* 00937 Do the same as insert_params_from_vars but also construct query text for 00938 binary log. 00939 00940 SYNOPSIS 00941 insert_params_from_vars() 00942 stmt Prepared statement 00943 varnames List of variables. Caller must ensure that number of variables 00944 in the list is equal to number of statement parameters 00945 query The query with parameter markers replaced with corresponding 00946 user variables that were used to execute the query. 00947 */ 00948 00949 static bool insert_params_from_vars_with_log(Prepared_statement *stmt, 00950 List<LEX_STRING>& varnames, 00951 String *query) 00952 { 00953 Item_param **begin= stmt->param_array; 00954 Item_param **end= begin + stmt->param_count; 00955 user_var_entry *entry; 00956 LEX_STRING *varname; 00957 List_iterator<LEX_STRING> var_it(varnames); 00958 String buf; 00959 const String *val; 00960 uint32 length= 0; 00961 00962 DBUG_ENTER("insert_params_from_vars"); 00963 00964 if (query->copy(stmt->query, stmt->query_length, default_charset_info)) 00965 DBUG_RETURN(1); 00966 00967 for (Item_param **it= begin; it < end; ++it) 00968 { 00969 Item_param *param= *it; 00970 varname= var_it++; 00971 if (get_var_with_binlog(stmt->thd, stmt->lex->sql_command, 00972 *varname, &entry)) 00973 DBUG_RETURN(1); 00974 00975 if (param->set_from_user_var(stmt->thd, entry)) 00976 DBUG_RETURN(1); 00977 /* Insert @'escaped-varname' instead of parameter in the query */ 00978 if (entry) 00979 { 00980 char *begin, *ptr; 00981 buf.length(0); 00982 if (buf.reserve(entry->name.length*2+3)) 00983 DBUG_RETURN(1); 00984 00985 begin= ptr= buf.c_ptr_quick(); 00986 *ptr++= '@'; 00987 *ptr++= '\''; 00988 ptr+= escape_string_for_mysql(&my_charset_utf8_general_ci, 00989 ptr, 0, entry->name.str, 00990 entry->name.length); 00991 *ptr++= '\''; 00992 buf.length(ptr - begin); 00993 val= &buf; 00994 } 00995 else 00996 val= &my_null_string; 00997 00998 if (param->convert_str_value(stmt->thd)) 00999 DBUG_RETURN(1); /* out of memory */ 01000 01001 if (query->replace(param->pos_in_query+length, 1, *val)) 01002 DBUG_RETURN(1); 01003 length+= val->length()-1; 01004 } 01005 DBUG_RETURN(0); 01006 } 01007 01008 /* 01009 Validate INSERT statement. 01010 01011 SYNOPSIS 01012 mysql_test_insert() 01013 stmt prepared statement 01014 tables global/local table list 01015 01016 RETURN VALUE 01017 FALSE success 01018 TRUE error, error message is set in THD 01019 */ 01020 01021 static bool mysql_test_insert(Prepared_statement *stmt, 01022 TABLE_LIST *table_list, 01023 List<Item> &fields, 01024 List<List_item> &values_list, 01025 List<Item> &update_fields, 01026 List<Item> &update_values, 01027 enum_duplicates duplic) 01028 { 01029 THD *thd= stmt->thd; 01030 LEX *lex= stmt->lex; 01031 List_iterator_fast<List_item> its(values_list); 01032 List_item *values; 01033 DBUG_ENTER("mysql_test_insert"); 01034 01035 if (insert_precheck(thd, table_list)) 01036 goto error; 01037 01038 /* 01039 open temporary memory pool for temporary data allocated by derived 01040 tables & preparation procedure 01041 Note that this is done without locks (should not be needed as we will not 01042 access any data here) 01043 If we would use locks, then we have to ensure we are not using 01044 TL_WRITE_DELAYED as having two such locks can cause table corruption. 01045 */ 01046 if (open_normal_and_derived_tables(thd, table_list, 0)) 01047 goto error; 01048 01049 if ((values= its++)) 01050 { 01051 uint value_count; 01052 ulong counter= 0; 01053 Item *unused_conds= 0; 01054 01055 if (table_list->table) 01056 { 01057 // don't allocate insert_values 01058 table_list->table->insert_values=(byte *)1; 01059 } 01060 01061 if (mysql_prepare_insert(thd, table_list, table_list->table, 01062 fields, values, update_fields, update_values, 01063 duplic, &unused_conds, FALSE)) 01064 goto error; 01065 01066 value_count= values->elements; 01067 its.rewind(); 01068 01069 if (table_list->lock_type == TL_WRITE_DELAYED && 01070 !(table_list->table->file->ha_table_flags() & HA_CAN_INSERT_DELAYED)) 01071 { 01072 my_error(ER_ILLEGAL_HA, MYF(0), (table_list->view ? 01073 table_list->view_name.str : 01074 table_list->table_name)); 01075 goto error; 01076 } 01077 while ((values= its++)) 01078 { 01079 counter++; 01080 if (values->elements != value_count) 01081 { 01082 my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), counter); 01083 goto error; 01084 } 01085 if (setup_fields(thd, 0, *values, MARK_COLUMNS_NONE, 0, 0)) 01086 goto error; 01087 } 01088 } 01089 DBUG_RETURN(FALSE); 01090 01091 error: 01092 /* insert_values is cleared in open_table */ 01093 DBUG_RETURN(TRUE); 01094 } 01095 01096 01097 /* 01098 Validate UPDATE statement 01099 01100 SYNOPSIS 01101 mysql_test_update() 01102 stmt prepared statement 01103 tables list of tables used in this query 01104 01105 RETURN VALUE 01106 0 success 01107 1 error, error message is set in THD 01108 2 convert to multi_update 01109 */ 01110 01111 static int mysql_test_update(Prepared_statement *stmt, 01112 TABLE_LIST *table_list) 01113 { 01114 int res; 01115 THD *thd= stmt->thd; 01116 uint table_count= 0; 01117 SELECT_LEX *select= &stmt->lex->select_lex; 01118 #ifndef NO_EMBEDDED_ACCESS_CHECKS 01119 uint want_privilege; 01120 #endif 01121 bool need_reopen; 01122 DBUG_ENTER("mysql_test_update"); 01123 01124 if (update_precheck(thd, table_list)) 01125 goto error; 01126 01127 for ( ; ; ) 01128 { 01129 if (open_tables(thd, &table_list, &table_count, 0)) 01130 goto error; 01131 01132 if (table_list->multitable_view) 01133 { 01134 DBUG_ASSERT(table_list->view != 0); 01135 DBUG_PRINT("info", ("Switch to multi-update")); 01136 /* pass counter value */ 01137 thd->lex->table_count= table_count; 01138 /* convert to multiupdate */ 01139 DBUG_RETURN(2); 01140 } 01141 01142 if (!lock_tables(thd, table_list, table_count, &need_reopen)) 01143 break; 01144 if (!need_reopen) 01145 goto error; 01146 close_tables_for_reopen(thd, &table_list); 01147 } 01148 01149 /* 01150 thd->fill_derived_tables() is false here for sure (because it is 01151 preparation of PS, so we even do not check it). 01152 */ 01153 if (mysql_handle_derived(thd->lex, &mysql_derived_prepare)) 01154 goto error; 01155 01156 #ifndef NO_EMBEDDED_ACCESS_CHECKS 01157 /* TABLE_LIST contain right privilages request */ 01158 want_privilege= table_list->grant.want_privilege; 01159 #endif 01160 01161 if (mysql_prepare_update(thd, table_list, &select->where, 01162 select->order_list.elements, 01163 (ORDER *) select->order_list.first)) 01164 goto error; 01165 01166 #ifndef NO_EMBEDDED_ACCESS_CHECKS 01167 table_list->grant.want_privilege= want_privilege; 01168 table_list->table->grant.want_privilege= want_privilege; 01169 table_list->register_want_access(want_privilege); 01170 #endif 01171 thd->lex->select_lex.no_wrap_view_item= TRUE; 01172 res= setup_fields(thd, 0, select->item_list, MARK_COLUMNS_READ, 0, 0); 01173 thd->lex->select_lex.no_wrap_view_item= FALSE; 01174 if (res) 01175 goto error; 01176 #ifndef NO_EMBEDDED_ACCESS_CHECKS 01177 /* Check values */ 01178 table_list->grant.want_privilege= 01179 table_list->table->grant.want_privilege= 01180 (SELECT_ACL & ~table_list->table->grant.privilege); 01181 table_list->register_want_access(SELECT_ACL); 01182 #endif 01183 if (setup_fields(thd, 0, stmt->lex->value_list, MARK_COLUMNS_NONE, 0, 0)) 01184 goto error; 01185 /* TODO: here we should send types of placeholders to the client. */ 01186 DBUG_RETURN(0); 01187 error: 01188 DBUG_RETURN(1); 01189 } 01190 01191 01192 /* 01193 Validate DELETE statement. 01194 01195 SYNOPSIS 01196 mysql_test_delete() 01197 stmt prepared statement 01198 tables list of tables used in this query 01199 01200 RETURN VALUE 01201 FALSE success 01202 TRUE error, error message is set in THD 01203 */ 01204 01205 static bool mysql_test_delete(Prepared_statement *stmt, 01206 TABLE_LIST *table_list) 01207 { 01208 THD *thd= stmt->thd; 01209 LEX *lex= stmt->lex; 01210 DBUG_ENTER("mysql_test_delete"); 01211 01212 if (delete_precheck(thd, table_list) || 01213 open_and_lock_tables(thd, table_list)) 01214 goto error; 01215 01216 if (!table_list->table) 01217 { 01218 my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0), 01219 table_list->view_db.str, table_list->view_name.str); 01220 goto error; 01221 } 01222 01223 DBUG_RETURN(mysql_prepare_delete(thd, table_list, &lex->select_lex.where)); 01224 error: 01225 DBUG_RETURN(TRUE); 01226 } 01227 01228 01229 /* 01230 Validate SELECT statement. 01231 01232 SYNOPSIS 01233 mysql_test_select() 01234 stmt prepared statement 01235 tables list of tables used in the query 01236 01237 DESCRIPTION 01238 In case of success, if this query is not EXPLAIN, send column list info 01239 back to the client. 01240 01241 RETURN VALUE 01242 0 success 01243 1 error, error message is set in THD 01244 2 success, and statement metadata has been sent 01245 */ 01246 01247 static int mysql_test_select(Prepared_statement *stmt, 01248 TABLE_LIST *tables, bool text_protocol) 01249 { 01250 THD *thd= stmt->thd; 01251 LEX *lex= stmt->lex; 01252 SELECT_LEX_UNIT *unit= &lex->unit; 01253 DBUG_ENTER("mysql_test_select"); 01254 01255 lex->select_lex.context.resolve_in_select_list= TRUE; 01256 01257 #ifndef NO_EMBEDDED_ACCESS_CHECKS 01258 ulong privilege= lex->exchange ? SELECT_ACL | FILE_ACL : SELECT_ACL; 01259 if (tables) 01260 { 01261 if (check_table_access(thd, privilege, tables,0)) 01262 goto error; 01263 } 01264 else if (check_access(thd, privilege, any_db,0,0,0,0)) 01265 goto error; 01266 #endif 01267 01268 if (!lex->result && !(lex->result= new (stmt->mem_root) select_send)) 01269 { 01270 my_error(ER_OUTOFMEMORY, MYF(0), sizeof(select_send)); 01271 goto error; 01272 } 01273 01274 if (open_and_lock_tables(thd, tables)) 01275 goto error; 01276 01277 thd->used_tables= 0; // Updated by setup_fields 01278 01279 /* 01280 JOIN::prepare calls 01281 It is not SELECT COMMAND for sure, so setup_tables will be called as 01282 usual, and we pass 0 as setup_tables_done_option 01283 */ 01284 if (unit->prepare(thd, 0, 0)) 01285 goto error; 01286 if (!lex->describe && !text_protocol) 01287 { 01288 /* Make copy of item list, as change_columns may change it */ 01289 List<Item> fields(lex->select_lex.item_list); 01290 01291 /* Change columns if a procedure like analyse() */ 01292 if (unit->last_procedure && unit->last_procedure->change_columns(fields)) 01293 goto error; 01294 01295 /* 01296 We can use lex->result as it should've been prepared in 01297 unit->prepare call above. 01298 */ 01299 if (send_prep_stmt(stmt, lex->result->field_count(fields)) || 01300 lex->result->send_fields(fields, Protocol::SEND_EOF) || 01301 thd->protocol->flush()) 01302 goto error; 01303 DBUG_RETURN(2); 01304 } 01305 DBUG_RETURN(0); 01306 error: 01307 DBUG_RETURN(1); 01308 } 01309 01310 01311 /* 01312 Validate and prepare for execution DO statement expressions. 01313 01314 SYNOPSIS 01315 mysql_test_do_fields() 01316 stmt prepared statement 01317 tables list of tables used in this query 01318 values list of expressions 01319 01320 RETURN VALUE 01321 FALSE success 01322 TRUE error, error message is set in THD 01323 */ 01324 01325 static bool mysql_test_do_fields(Prepared_statement *stmt, 01326 TABLE_LIST *tables, 01327 List<Item> *values) 01328 { 01329 THD *thd= stmt->thd; 01330 01331 DBUG_ENTER("mysql_test_do_fields"); 01332 if (tables && check_table_access(thd, SELECT_ACL, tables, 0)) 01333 DBUG_RETURN(TRUE); 01334 01335 if (open_and_lock_tables(thd, tables)) 01336 DBUG_RETURN(TRUE); 01337 DBUG_RETURN(setup_fields(thd, 0, *values, MARK_COLUMNS_NONE, 0, 0)); 01338 } 01339 01340 01341 /* 01342 Validate and prepare for execution SET statement expressions 01343 01344 SYNOPSIS 01345 mysql_test_set_fields() 01346 stmt prepared statement 01347 tables list of tables used in this query 01348 values list of expressions 01349 01350 RETURN VALUE 01351 FALSE success 01352 TRUE error, error message is set in THD 01353 */ 01354 01355 static bool mysql_test_set_fields(Prepared_statement *stmt, 01356 TABLE_LIST *tables, 01357 List<set_var_base> *var_list) 01358 { 01359 DBUG_ENTER("mysql_test_set_fields"); 01360 List_iterator_fast<set_var_base> it(*var_list); 01361 THD *thd= stmt->thd; 01362 set_var_base *var; 01363 01364 if (tables && check_table_access(thd, SELECT_ACL, tables, 0) || 01365 open_and_lock_tables(thd, tables)) 01366 goto error; 01367 01368 while ((var= it++)) 01369 { 01370 if (var->light_check(thd)) 01371 goto error; 01372 } 01373 DBUG_RETURN(FALSE); 01374 error: 01375 DBUG_RETURN(TRUE); 01376 } 01377 01378 01379 /* 01380 Check internal SELECT of the prepared command 01381 01382 SYNOPSIS 01383 select_like_stmt_test() 01384 stmt prepared statement 01385 specific_prepare function of command specific prepare 01386 setup_tables_done_option options to be passed to LEX::unit.prepare() 01387 01388 NOTE 01389 This function won't directly open tables used in select. They should 01390 be opened either by calling function (and in this case you probably 01391 should use select_like_stmt_test_with_open_n_lock()) or by 01392 "specific_prepare" call (like this happens in case of multi-update). 01393 01394 RETURN VALUE 01395 FALSE success 01396 TRUE error, error message is set in THD 01397 */ 01398 01399 static bool select_like_stmt_test(Prepared_statement *stmt, 01400 bool (*specific_prepare)(THD *thd), 01401 ulong setup_tables_done_option) 01402 { 01403 DBUG_ENTER("select_like_stmt_test"); 01404 THD *thd= stmt->thd; 01405 LEX *lex= stmt->lex; 01406 01407 lex->select_lex.context.resolve_in_select_list= TRUE; 01408 01409 if (specific_prepare && (*specific_prepare)(thd)) 01410 DBUG_RETURN(TRUE); 01411 01412 thd->used_tables= 0; // Updated by setup_fields 01413 01414 /* Calls JOIN::prepare */ 01415 DBUG_RETURN(lex->unit.prepare(thd, 0, setup_tables_done_option)); 01416 } 01417 01418 /* 01419 Check internal SELECT of the prepared command (with opening and 01420 locking of used tables). 01421 01422 SYNOPSIS 01423 select_like_stmt_test_with_open_n_lock() 01424 stmt prepared statement 01425 tables list of tables to be opened and locked 01426 before calling specific_prepare function 01427 specific_prepare function of command specific prepare 01428 setup_tables_done_option options to be passed to LEX::unit.prepare() 01429 01430 RETURN VALUE 01431 FALSE success 01432 TRUE error 01433 */ 01434 01435 static bool 01436 select_like_stmt_test_with_open_n_lock(Prepared_statement *stmt, 01437 TABLE_LIST *tables, 01438 bool (*specific_prepare)(THD *thd), 01439 ulong setup_tables_done_option) 01440 { 01441 DBUG_ENTER("select_like_stmt_test_with_open_n_lock"); 01442 01443 /* 01444 We should not call LEX::unit.cleanup() after this open_and_lock_tables() 01445 call because we don't allow prepared EXPLAIN yet so derived tables will 01446 clean up after themself. 01447 */ 01448 if (open_and_lock_tables(stmt->thd, tables)) 01449 DBUG_RETURN(TRUE); 01450 01451 DBUG_RETURN(select_like_stmt_test(stmt, specific_prepare, 01452 setup_tables_done_option)); 01453 } 01454 01455 01456 /* 01457 Validate and prepare for execution CREATE TABLE statement 01458 01459 SYNOPSIS 01460 mysql_test_create_table() 01461 stmt prepared statement 01462 tables list of tables used in this query 01463 01464 RETURN VALUE 01465 FALSE success 01466 TRUE error, error message is set in THD 01467 */ 01468 01469 static bool mysql_test_create_table(Prepared_statement *stmt) 01470 { 01471 DBUG_ENTER("mysql_test_create_table"); 01472 THD *thd= stmt->thd; 01473 LEX *lex= stmt->lex; 01474 SELECT_LEX *select_lex= &lex->select_lex; 01475 bool res= FALSE; 01476 /* Skip first table, which is the table we are creating */ 01477 bool link_to_local; 01478 TABLE_LIST *create_table= lex->unlink_first_table(&link_to_local); 01479 TABLE_LIST *tables= lex->query_tables; 01480 01481 if (create_table_precheck(thd, tables, create_table)) 01482 DBUG_RETURN(TRUE); 01483 01484 if (select_lex->item_list.elements) 01485 { 01486 select_lex->context.resolve_in_select_list= TRUE; 01487 res= select_like_stmt_test_with_open_n_lock(stmt, tables, 0, 0); 01488 } 01489 01490 /* put tables back for PS rexecuting */ 01491 lex->link_first_table_back(create_table, link_to_local); 01492 DBUG_RETURN(res); 01493 } 01494 01495 01496 /* 01497 Validate and prepare for execution a multi update statement. 01498 01499 SYNOPSIS 01500 mysql_test_multiupdate() 01501 stmt prepared statement 01502 tables list of tables used in this query 01503 converted converted to multi-update from usual update 01504 01505 RETURN VALUE 01506 FALSE success 01507 TRUE error, error message is set in THD 01508 */ 01509 01510 static bool mysql_test_multiupdate(Prepared_statement *stmt, 01511 TABLE_LIST *tables, 01512 bool converted) 01513 { 01514 /* if we switched from normal update, rights are checked */ 01515 if (!converted && multi_update_precheck(stmt->thd, tables)) 01516 return TRUE; 01517 01518 return select_like_stmt_test(stmt, &mysql_multi_update_prepare, 01519 OPTION_SETUP_TABLES_DONE); 01520 } 01521 01522 01523 /* 01524 Validate and prepare for execution a multi delete statement. 01525 01526 SYNOPSIS 01527 mysql_test_multidelete() 01528 stmt prepared statement 01529 tables list of tables used in this query 01530 01531 RETURN VALUE 01532 FALSE success 01533 TRUE error, error message in THD is set. 01534 */ 01535 01536 static bool mysql_test_multidelete(Prepared_statement *stmt, 01537 TABLE_LIST *tables) 01538 { 01539 stmt->thd->lex->current_select= &stmt->thd->lex->select_lex; 01540 if (add_item_to_list(stmt->thd, new Item_null())) 01541 { 01542 my_error(ER_OUTOFMEMORY, MYF(0), 0); 01543 goto error; 01544 } 01545 01546 if (multi_delete_precheck(stmt->thd, tables) || 01547 select_like_stmt_test_with_open_n_lock(stmt, tables, 01548 &mysql_multi_delete_prepare, 01549 OPTION_SETUP_TABLES_DONE)) 01550 goto error; 01551 if (!tables->table) 01552 { 01553 my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0), 01554 tables->view_db.str, tables->view_name.str); 01555 goto error; 01556 } 01557 return FALSE; 01558 error: 01559 return TRUE; 01560 } 01561 01562 01563 /* 01564 Wrapper for mysql_insert_select_prepare, to make change of local tables 01565 after open_and_lock_tables() call. 01566 01567 SYNOPSIS 01568 mysql_insert_select_prepare_tester() 01569 thd thread handle 01570 01571 NOTE 01572 We need to remove the first local table after open_and_lock_tables, 01573 because mysql_handle_derived uses local tables lists. 01574 */ 01575 01576 static bool mysql_insert_select_prepare_tester(THD *thd) 01577 { 01578 TABLE_LIST *first; 01579 bool res; 01580 SELECT_LEX *first_select= &thd->lex->select_lex; 01581 /* Skip first table, which is the table we are inserting in */ 01582 first_select->table_list.first= (byte*)(first= 01583 ((TABLE_LIST*)first_select-> 01584 table_list.first)->next_local); 01585 res= mysql_insert_select_prepare(thd); 01586 /* 01587 insert/replace from SELECT give its SELECT_LEX for SELECT, 01588 and item_list belong to SELECT 01589 */ 01590 thd->lex->select_lex.context.resolve_in_select_list= TRUE; 01591 thd->lex->select_lex.context.table_list= first; 01592 return res; 01593 } 01594 01595 01596 /* 01597 Validate and prepare for execution INSERT ... SELECT statement. 01598 01599 SYNOPSIS 01600 mysql_test_insert_select() 01601 stmt prepared statement 01602 tables list of tables used in this query 01603 01604 RETURN VALUE 01605 FALSE success 01606 TRUE error, error message is set in THD 01607 */ 01608 01609 static bool mysql_test_insert_select(Prepared_statement *stmt, 01610 TABLE_LIST *tables) 01611 { 01612 int res; 01613 LEX *lex= stmt->lex; 01614 TABLE_LIST *first_local_table; 01615 01616 if (tables->table) 01617 { 01618 // don't allocate insert_values 01619 tables->table->insert_values=(byte *)1; 01620 } 01621 01622 if (insert_precheck(stmt->thd, tables)) 01623 return 1; 01624 01625 /* store it, because mysql_insert_select_prepare_tester change it */ 01626 first_local_table= (TABLE_LIST *)lex->select_lex.table_list.first; 01627 DBUG_ASSERT(first_local_table != 0); 01628 01629 res= 01630 select_like_stmt_test_with_open_n_lock(stmt, tables, 01631 &mysql_insert_select_prepare_tester, 01632 OPTION_SETUP_TABLES_DONE); 01633 /* revert changes made by mysql_insert_select_prepare_tester */ 01634 lex->select_lex.table_list.first= (byte*) first_local_table; 01635 return res; 01636 } 01637 01638 01639 /* 01640 Perform semantic analysis of the parsed tree and send a response packet 01641 to the client. 01642 01643 SYNOPSIS 01644 check_prepared_statement() 01645 stmt prepared statement 01646 01647 DESCRIPTION 01648 This function 01649 - opens all tables and checks access rights 01650 - validates semantics of statement columns and SQL functions 01651 by calling fix_fields. 01652 01653 RETURN VALUE 01654 FALSE success, statement metadata is sent to client 01655 TRUE error, error message is set in THD (but not sent) 01656 */ 01657 01658 static bool check_prepared_statement(Prepared_statement *stmt, 01659 bool text_protocol) 01660 { 01661 THD *thd= stmt->thd; 01662 LEX *lex= stmt->lex; 01663 SELECT_LEX *select_lex= &lex->select_lex; 01664 TABLE_LIST *tables; 01665 enum enum_sql_command sql_command= lex->sql_command; 01666 int res= 0; 01667 DBUG_ENTER("check_prepared_statement"); 01668 DBUG_PRINT("enter",("command: %d, param_count: %ld", 01669 sql_command, stmt->param_count)); 01670 01671 lex->first_lists_tables_same(); 01672 tables= lex->query_tables; 01673 01674 /* set context for commands which do not use setup_tables */ 01675 lex->select_lex.context.resolve_in_table_list_only(select_lex-> 01676 get_table_list()); 01677 01678 switch (sql_command) { 01679 case SQLCOM_REPLACE: 01680 case SQLCOM_INSERT: 01681 res= mysql_test_insert(stmt, tables, lex->field_list, 01682 lex->many_values, 01683 select_lex->item_list, lex->value_list, 01684 lex->duplicates); 01685 break; 01686 01687 case SQLCOM_UPDATE: 01688 res= mysql_test_update(stmt, tables); 01689 /* mysql_test_update returns 2 if we need to switch to multi-update */ 01690 if (res != 2) 01691 break; 01692 01693 case SQLCOM_UPDATE_MULTI: 01694 res= mysql_test_multiupdate(stmt, tables, res == 2); 01695 break; 01696 01697 case SQLCOM_DELETE: 01698 res= mysql_test_delete(stmt, tables); 01699 break; 01700 01701 case SQLCOM_SELECT: 01702 res= mysql_test_select(stmt, tables, text_protocol); 01703 if (res == 2) 01704 { 01705 /* Statement and field info has already been sent */ 01706 DBUG_RETURN(FALSE); 01707 } 01708 break; 01709 case SQLCOM_CREATE_TABLE: 01710 res= mysql_test_create_table(stmt); 01711 break; 01712 01713 case SQLCOM_DO: 01714 res= mysql_test_do_fields(stmt, tables, lex->insert_list); 01715 break; 01716 01717 case SQLCOM_SET_OPTION: 01718 res= mysql_test_set_fields(stmt, tables, &lex->var_list); 01719 break; 01720 01721 case SQLCOM_DELETE_MULTI: 01722 res= mysql_test_multidelete(stmt, tables); 01723 break; 01724 01725 case SQLCOM_INSERT_SELECT: 01726 case SQLCOM_REPLACE_SELECT: 01727 res= mysql_test_insert_select(stmt, tables); 01728 break; 01729 01730 /* 01731 Note that we don't need to have cases in this list if they are 01732 marked with CF_STATUS_COMMAND in sql_command_flags 01733 */ 01734 case SQLCOM_SHOW_PROCESSLIST: 01735 case SQLCOM_SHOW_STORAGE_ENGINES: 01736 case SQLCOM_SHOW_PRIVILEGES: 01737 case SQLCOM_SHOW_COLUMN_TYPES: 01738 case SQLCOM_SHOW_ENGINE_LOGS: 01739 case SQLCOM_SHOW_ENGINE_STATUS: 01740 case SQLCOM_SHOW_ENGINE_MUTEX: 01741 case SQLCOM_SHOW_CREATE_DB: 01742 case SQLCOM_SHOW_GRANTS: 01743 case SQLCOM_SHOW_BINLOG_EVENTS: 01744 case SQLCOM_SHOW_MASTER_STAT: 01745 case SQLCOM_SHOW_SLAVE_STAT: 01746 case SQLCOM_SHOW_CREATE_PROC: 01747 case SQLCOM_SHOW_CREATE_FUNC: 01748 case SQLCOM_SHOW_CREATE_EVENT: 01749 case SQLCOM_SHOW_CREATE: 01750 case SQLCOM_SHOW_PROC_CODE: 01751 case SQLCOM_SHOW_FUNC_CODE: 01752 case SQLCOM_SHOW_AUTHORS: 01753 case SQLCOM_SHOW_CONTRIBUTORS: 01754 case SQLCOM_SHOW_WARNS: 01755 case SQLCOM_SHOW_ERRORS: 01756 case SQLCOM_SHOW_BINLOGS: 01757 case SQLCOM_DROP_TABLE: 01758 case SQLCOM_RENAME_TABLE: 01759 case SQLCOM_ALTER_TABLE: 01760 case SQLCOM_COMMIT: 01761 case SQLCOM_CREATE_INDEX: 01762 case SQLCOM_DROP_INDEX: 01763 case SQLCOM_ROLLBACK: 01764 case SQLCOM_TRUNCATE: 01765 case SQLCOM_CALL: 01766 case SQLCOM_CREATE_VIEW: 01767 case SQLCOM_DROP_VIEW: 01768 case SQLCOM_REPAIR: 01769 case SQLCOM_ANALYZE: 01770 case SQLCOM_OPTIMIZE: 01771 case SQLCOM_CHANGE_MASTER: 01772 case SQLCOM_RESET: 01773 case SQLCOM_FLUSH: 01774 case SQLCOM_SLAVE_START: 01775 case SQLCOM_SLAVE_STOP: 01776 case SQLCOM_INSTALL_PLUGIN: 01777 case SQLCOM_UNINSTALL_PLUGIN: 01778 case SQLCOM_CREATE_DB: 01779 case SQLCOM_DROP_DB: 01780 case SQLCOM_RENAME_DB: 01781 case SQLCOM_CHECKSUM: 01782 case SQLCOM_CREATE_USER: 01783 case SQLCOM_RENAME_USER: 01784 case SQLCOM_DROP_USER: 01785 case SQLCOM_ASSIGN_TO_KEYCACHE: 01786 case SQLCOM_PRELOAD_KEYS: 01787 case SQLCOM_GRANT: 01788 case SQLCOM_REVOKE: 01789 case SQLCOM_KILL: 01790 break; 01791 01792 default: 01793 /* 01794 Trivial check of all status commands. This is easier than having 01795 things in the above case list, as it's less chance for mistakes. 01796 */ 01797 if (!(sql_command_flags[sql_command] & CF_STATUS_COMMAND)) 01798 { 01799 /* All other statements are not supported yet. */ 01800 my_message(ER_UNSUPPORTED_PS, ER(ER_UNSUPPORTED_PS), MYF(0)); 01801 goto error; 01802 } 01803 break; 01804 } 01805 if (res == 0) 01806 DBUG_RETURN(text_protocol? FALSE : (send_prep_stmt(stmt, 0) || 01807 thd->protocol->flush())); 01808 error: 01809 DBUG_RETURN(TRUE); 01810 } 01811 01812 /* 01813 Initialize array of parameters in statement from LEX. 01814 (We need to have quick access to items by number in mysql_stmt_get_longdata). 01815 This is to avoid using malloc/realloc in the parser. 01816 */ 01817 01818 static bool init_param_array(Prepared_statement *stmt) 01819 { 01820 LEX *lex= stmt->lex; 01821 if ((stmt->param_count= lex->param_list.elements)) 01822 { 01823 if (stmt->param_count > (uint) UINT_MAX16) 01824 { 01825 /* Error code to be defined in 5.0 */ 01826 my_message(ER_PS_MANY_PARAM, ER(ER_PS_MANY_PARAM), MYF(0)); 01827 return TRUE; 01828 } 01829 Item_param **to; 01830 List_iterator<Item_param> param_iterator(lex->param_list); 01831 /* Use thd->mem_root as it points at statement mem_root */ 01832 stmt->param_array= (Item_param **) 01833 alloc_root(stmt->thd->mem_root, 01834 sizeof(Item_param*) * stmt->param_count); 01835 if (!stmt->param_array) 01836 return TRUE; 01837 for (to= stmt->param_array; 01838 to < stmt->param_array + stmt->param_count; 01839 ++to) 01840 { 01841 *to= param_iterator++; 01842 } 01843 } 01844 return FALSE; 01845 } 01846 01847 01848 /* 01849 COM_STMT_PREPARE handler. 01850 01851 SYNOPSIS 01852 mysql_stmt_prepare() 01853 packet query to be prepared 01854 packet_length query string length, including ignored 01855 trailing NULL or quote char. 01856 01857 DESCRIPTION 01858 Given a query string with parameter markers, create a prepared 01859 statement from it and send PS info back to the client. 01860 01861 NOTES 01862 This function parses the query and sends the total number of parameters 01863 and resultset metadata information back to client (if any), without 01864 executing the query i.e. without any log/disk writes. This allows the 01865 queries to be re-executed without re-parsing during execute. 01866 01867 If parameter markers are found in the query, then store the information 01868 using Item_param along with maintaining a list in lex->param_array, so 01869 that a fast and direct retrieval can be made without going through all 01870 field items. 01871 01872 RETURN VALUE 01873 none: in case of success a new statement id and metadata is sent 01874 to the client, otherwise an error message is set in THD. 01875 */ 01876 01877 void mysql_stmt_prepare(THD *thd, const char *packet, uint packet_length) 01878 { 01879 Prepared_statement *stmt; 01880 bool error; 01881 DBUG_ENTER("mysql_stmt_prepare"); 01882 01883 DBUG_PRINT("prep_query", ("%s", packet)); 01884 01885 /* First of all clear possible warnings from the previous command */ 01886 mysql_reset_thd_for_next_command(thd); 01887 01888 if (! (stmt= new Prepared_statement(thd, &thd->protocol_prep))) 01889 DBUG_VOID_RETURN; /* out of memory: error is set in Sql_alloc */ 01890 01891 if (thd->stmt_map.insert(thd, stmt)) 01892 { 01893 /* 01894 The error is set in the insert. The statement itself 01895 will be also deleted there (this is how the hash works). 01896 */ 01897 DBUG_VOID_RETURN; 01898 } 01899 01900 /* Reset warnings from previous command */ 01901 mysql_reset_errors(thd, 0); 01902 sp_cache_flush_obsolete(&thd->sp_proc_cache); 01903 sp_cache_flush_obsolete(&thd->sp_func_cache); 01904 01905 if (!(specialflag & SPECIAL_NO_PRIOR)) 01906 my_pthread_setprio(pthread_self(),QUERY_PRIOR); 01907 01908 error= stmt->prepare(packet, packet_length); 01909 01910 if (!(specialflag & SPECIAL_NO_PRIOR)) 01911 my_pthread_setprio(pthread_self(),WAIT_PRIOR); 01912 01913 if (error) 01914 { 01915 /* Statement map deletes statement on erase */ 01916 thd->stmt_map.erase(stmt); 01917 } 01918 else 01919 general_log_print(thd, COM_STMT_PREPARE, "[%lu] %s", stmt->id, packet); 01920 01921 /* check_prepared_statemnt sends the metadata packet in case of success */ 01922 DBUG_VOID_RETURN; 01923 } 01924 01925 /* 01926 SYNOPSIS 01927 get_dynamic_sql_string() 01928 lex in main lex 01929 query_len out length of the SQL statement (is set only 01930 in case of success) 01931 01932 DESCRIPTION 01933 Get an SQL statement text from a user variable or from plain 01934 text. If the statement is plain text, just assign the 01935 pointers, otherwise allocate memory in thd->mem_root and copy 01936 the contents of the variable, possibly with character 01937 set conversion. 01938 01939 RETURN VALUE 01940 non-zero success, 0 in case of error (out of memory) 01941 */ 01942 01943 static const char *get_dynamic_sql_string(LEX *lex, uint *query_len) 01944 { 01945 THD *thd= lex->thd; 01946 char *query_str= 0; 01947 01948 if (lex->prepared_stmt_code_is_varref) 01949 { 01950 /* This is PREPARE stmt FROM or EXECUTE IMMEDIATE @var. */ 01951 String str; 01952 CHARSET_INFO *to_cs= thd->variables.collation_connection; 01953 bool needs_conversion; 01954 user_var_entry *entry; 01955 String *var_value= &str; 01956 uint32 unused, len; 01957 /* 01958 Convert @var contents to string in connection character set. Although 01959 it is known that int/real/NULL value cannot be a valid query we still 01960 convert it for error messages to be uniform. 01961 */ 01962 if ((entry= 01963 (user_var_entry*)hash_search(&thd->user_vars, 01964 (byte*)lex->prepared_stmt_code.str, 01965 lex->prepared_stmt_code.length)) 01966 && entry->value) 01967 { 01968 my_bool is_var_null; 01969 var_value= entry->val_str(&is_var_null, &str, NOT_FIXED_DEC); 01970 /* 01971 NULL value of variable checked early as entry->value so here 01972 we can't get NULL in normal conditions 01973 */ 01974 DBUG_ASSERT(!is_var_null); 01975 if (!var_value) 01976 goto end; 01977 } 01978 else 01979 { 01980 /* 01981 variable absent or equal to NULL, so we need to set variable to 01982 something reasonable to get a readable error message during parsing 01983 */ 01984 str.set(STRING_WITH_LEN("NULL"), &my_charset_latin1); 01985 } 01986 01987 needs_conversion= String::needs_conversion(var_value->length(), 01988 var_value->charset(), to_cs, 01989 &unused); 01990 01991 len= (needs_conversion ? var_value->length() * to_cs->mbmaxlen : 01992 var_value->length()); 01993 if (!(query_str= alloc_root(thd->mem_root, len+1))) 01994 goto end; 01995 01996 if (needs_conversion) 01997 { 01998 uint dummy_errors; 01999 len= copy_and_convert(query_str, len, to_cs, var_value->ptr(), 02000 var_value->length(), var_value->charset(), 02001 &dummy_errors); 02002 } 02003 else 02004 memcpy(query_str, var_value->ptr(), var_value->length()); 02005 query_str[len]= '\0'; // Safety (mostly for debug) 02006 *query_len= len; 02007 } 02008 else 02009 { 02010 query_str= lex->prepared_stmt_code.str; 02011 *query_len= lex->prepared_stmt_code.length; 02012 } 02013 end: 02014 return query_str; 02015 } 02016 02017 02018 /* Init PS/SP specific parse tree members. */ 02019 02020 static void init_stmt_after_parse(LEX *lex) 02021 { 02022 SELECT_LEX *sl= lex->all_selects_list; 02023 /* 02024 Switch off a temporary flag that prevents evaluation of 02025 subqueries in statement prepare. 02026 */ 02027 for (; sl; sl= sl->next_select_in_list()) 02028 sl->uncacheable&= ~UNCACHEABLE_PREPARE; 02029 } 02030 02031 /* 02032 SQLCOM_PREPARE implementation. 02033 02034 SYNOPSIS 02035 mysql_sql_stmt_prepare() 02036 thd thread handle 02037 02038 DESCRIPTION 02039 Prepare an SQL prepared statement. This is called from 02040 mysql_execute_command and should therefore behave like an 02041 ordinary query (e.g. should not reset any global THD data). 02042 02043 RETURN VALUE 02044 none: in case of success, OK packet is sent to the client, 02045 otherwise an error message is set in THD 02046 */ 02047 02048 void mysql_sql_stmt_prepare(THD *thd) 02049 { 02050 LEX *lex= thd->lex; 02051 LEX_STRING *name= &lex->prepared_stmt_name; 02052 Prepared_statement *stmt; 02053 const char *query; 02054 uint query_len; 02055 DBUG_ENTER("mysql_sql_stmt_prepare"); 02056 DBUG_ASSERT(thd->protocol == &thd->protocol_simple); 02057 02058 if ((stmt= (Prepared_statement*) thd->stmt_map.find_by_name(name))) 02059 { 02060 /* 02061 If there is a statement with the same name, remove it. It is ok to 02062 remove old and fail to insert a new one at the same time. 02063 */ 02064 if (stmt->deallocate()) 02065 DBUG_VOID_RETURN; 02066 } 02067 02068 if (! (query= get_dynamic_sql_string(lex, &query_len)) || 02069 ! (stmt= new Prepared_statement(thd, &thd->protocol_simple))) 02070 { 02071 DBUG_VOID_RETURN; /* out of memory */ 02072 } 02073 02074 /* Set the name first, insert should know that this statement has a name */ 02075 if (stmt->set_name(name)) 02076 { 02077 delete stmt; 02078 DBUG_VOID_RETURN; 02079 } 02080 if (thd->stmt_map.insert(thd, stmt)) 02081 { 02082 /* The statement is deleted and an error is set if insert fails */ 02083 DBUG_VOID_RETURN; 02084 } 02085 02086 if (stmt->prepare(query, query_len+1)) 02087 { 02088 /* Statement map deletes the statement on erase */ 02089 thd->stmt_map.erase(stmt); 02090 } 02091 else 02092 send_ok(thd, 0L, 0L, "Statement prepared"); 02093 02094 DBUG_VOID_RETURN; 02095 } 02096 02097 /* Reinit prepared statement/stored procedure before execution */ 02098 02099 void reinit_stmt_before_use(THD *thd, LEX *lex) 02100 { 02101 SELECT_LEX *sl= lex->all_selects_list; 02102 DBUG_ENTER("reinit_stmt_before_use"); 02103 02104 /* 02105 We have to update "thd" pointer in LEX, all its units and in LEX::result, 02106 since statements which belong to trigger body are associated with TABLE 02107 object and because of this can be used in different threads. 02108 */ 02109 lex->thd= thd; 02110 02111 if (lex->empty_field_list_on_rset) 02112 { 02113 lex->empty_field_list_on_rset= 0; 02114 lex->field_list.empty(); 02115 } 02116 for (; sl; sl= sl->next_select_in_list()) 02117 { 02118 if (!sl->first_execution) 02119 { 02120 /* remove option which was put by mysql_explain_union() */ 02121 sl->options&= ~SELECT_DESCRIBE; 02122 02123 /* see unique_table() */ 02124 sl->exclude_from_table_unique_test= FALSE; 02125 02126 /* 02127 Copy WHERE, HAVING clause pointers to avoid damaging them 02128 by optimisation 02129 */ 02130 if (sl->prep_where) 02131 { 02132 sl->where= sl->prep_where->copy_andor_structure(thd); 02133 sl->where->cleanup(); 02134 } 02135 if (sl->prep_having) 02136 { 02137 sl->having= sl->prep_having->copy_andor_structure(thd); 02138 sl->having->cleanup(); 02139 } 02140 DBUG_ASSERT(sl->join == 0); 02141 ORDER *order; 02142 /* Fix GROUP list */ 02143 for (order= (ORDER *)sl->group_list.first; order; order= order->next) 02144 order->item= &order->item_ptr; 02145 /* Fix ORDER list */ 02146 for (order= (ORDER *)sl->order_list.first; order; order= order->next) 02147 order->item= &order->item_ptr; 02148 } 02149 { 02150 SELECT_LEX_UNIT *unit= sl->master_unit(); 02151 unit->unclean(); 02152 unit->types.empty(); 02153 /* for derived tables & PS (which can't be reset by Item_subquery) */ 02154 unit->reinit_exec_mechanism(); 02155 unit->set_thd(thd); 02156 } 02157 } 02158 02159 /* 02160 TODO: When the new table structure is ready, then have a status bit 02161 to indicate the table is altered, and re-do the setup_* 02162 and open the tables back. 02163 */ 02164 /* 02165 NOTE: We should reset whole table list here including all tables added 02166 by prelocking algorithm (it is not a problem for substatements since 02167 they have their own table list). 02168 */ 02169 for (TABLE_LIST *tables= lex->query_tables; 02170 tables; 02171 tables= tables->next_global) 02172 { 02173 tables->reinit_before_use(thd); 02174 } 02175 /* 02176 Cleanup of the special case of DELETE t1, t2 FROM t1, t2, t3 ... 02177 (multi-delete). We do a full clean up, although at the moment all we 02178 need to clean in the tables of MULTI-DELETE list is 'table' member. 02179 */ 02180 for (TABLE_LIST *tables= (TABLE_LIST*) lex->auxiliary_table_list.first; 02181 tables; 02182 tables= tables->next_global) 02183 { 02184 tables->reinit_before_use(thd); 02185 } 02186 lex->current_select= &lex->select_lex; 02187 02188 /* restore original list used in INSERT ... SELECT */ 02189 if (lex->leaf_tables_insert) 02190 lex->select_lex.leaf_tables= lex->leaf_tables_insert; 02191 02192 if (lex->result) 02193 { 02194 lex->result->cleanup(); 02195 lex->result->set_thd(thd); 02196 } 02197 lex->allow_sum_func= 0; 02198 lex->in_sum_func= NULL; 02199 DBUG_VOID_RETURN; 02200 } 02201 02202 02203 /* 02204 Clears parameters from data left from previous execution or long data 02205 02206 SYNOPSIS 02207 reset_stmt_params() 02208 stmt prepared statement for which parameters should 02209 be reset 02210 */ 02211 02212 static void reset_stmt_params(Prepared_statement *stmt) 02213 { 02214 Item_param **item= stmt->param_array; 02215 Item_param **end= item + stmt->param_count; 02216 for (;item < end ; ++item) 02217 (**item).reset(); 02218 } 02219 02220 02221 /* 02222 COM_STMT_EXECUTE handler: execute a previously prepared statement. 02223 02224 SYNOPSIS 02225 mysql_stmt_execute() 02226 thd current thread 02227 packet parameter types and data, if any 02228 packet_length packet length, including the terminator character. 02229 02230 DESCRIPTION 02231 If there are any parameters, then replace parameter markers with the 02232 data supplied from the client, and then execute the statement. 02233 This function uses binary protocol to send a possible result set 02234 to the client. 02235 02236 RETURN VALUE 02237 none: in case of success OK packet or a result set is sent to the 02238 client, otherwise an error message is set in THD. 02239 */ 02240 02241 void mysql_stmt_execute(THD *thd, char *packet_arg, uint packet_length) 02242 { 02243 uchar *packet= (uchar*)packet_arg; // GCC 4.0.1 workaround 02244 ulong stmt_id= uint4korr(packet); 02245 ulong flags= (ulong) ((uchar) packet[4]); 02246 /* Query text for binary, general or slow log, if any of them is open */ 02247 String expanded_query; 02248 #ifndef EMBEDDED_LIBRARY 02249 uchar *packet_end= (uchar *) packet + packet_length - 1; 02250 #endif 02251 Prepared_statement *stmt; 02252 bool error; 02253 DBUG_ENTER("mysql_stmt_execute"); 02254 02255 packet+= 9; /* stmt_id + 5 bytes of flags */ 02256 02257 /* First of all clear possible warnings from the previous command */ 02258 mysql_reset_thd_for_next_command(thd); 02259 02260 if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_execute"))) 02261 DBUG_VOID_RETURN; 02262 02263 DBUG_PRINT("exec_query", ("%s", stmt->query)); 02264 DBUG_PRINT("info",("stmt: %p", stmt)); 02265 02266 sp_cache_flush_obsolete(&thd->sp_proc_cache); 02267 sp_cache_flush_obsolete(&thd->sp_func_cache); 02268 02269 #ifndef EMBEDDED_LIBRARY 02270 if (stmt->param_count) 02271 { 02272 uchar *null_array= (uchar *) packet; 02273 if (setup_conversion_functions(stmt, (uchar **) &packet, packet_end) || 02274 stmt->set_params(stmt, null_array, (uchar *) packet, packet_end, 02275 &expanded_query)) 02276 goto set_params_data_err; 02277 } 02278 #else 02279 /* 02280 In embedded library we re-install conversion routines each time 02281 we set params, and also we don't need to parse packet. 02282 So we do it in one function. 02283 */ 02284 if (stmt->param_count && stmt->set_params_data(stmt, &expanded_query)) 02285 goto set_params_data_err; 02286 #endif 02287 if (!(specialflag & SPECIAL_NO_PRIOR)) 02288 my_pthread_setprio(pthread_self(),QUERY_PRIOR); 02289 error= stmt->execute(&expanded_query, 02290 test(flags & (ulong) CURSOR_TYPE_READ_ONLY)); 02291 if (!(specialflag & SPECIAL_NO_PRIOR)) 02292 my_pthread_setprio(pthread_self(), WAIT_PRIOR); 02293 if (error == 0) 02294 general_log_print(thd, COM_STMT_EXECUTE, "[%lu] %s", stmt->id, thd->query); 02295 02296 DBUG_VOID_RETURN; 02297 02298 set_params_data_err: 02299 my_error(ER_WRONG_ARGUMENTS, MYF(0), "mysql_stmt_execute"); 02300 reset_stmt_params(stmt); 02301 DBUG_VOID_RETURN; 02302 } 02303 02304 02305 /* 02306 SQLCOM_EXECUTE implementation. 02307 02308 SYNOPSIS 02309 mysql_sql_stmt_execute() 02310 thd thread handle 02311 02312 DESCRIPTION 02313 Execute prepared statement using parameter values from 02314 lex->prepared_stmt_params and send result to the client using 02315 text protocol. This is called from mysql_execute_command and 02316 therefore should behave like an ordinary query (e.g. not change 02317 global THD data, such as warning count, server status, etc). 02318 This function uses text protocol to send a possible result set. 02319 02320 RETURN 02321 none: in case of success, OK (or result set) packet is sent to the 02322 client, otherwise an error is set in THD 02323 */ 02324 02325 void mysql_sql_stmt_execute(THD *thd) 02326 { 02327 LEX *lex= thd->lex; 02328 Prepared_statement *stmt; 02329 LEX_STRING *name= &lex->prepared_stmt_name; 02330 /* Query text for binary, general or slow log, if any of them is open */ 02331 String expanded_query; 02332 DBUG_ENTER("mysql_sql_stmt_execute"); 02333 DBUG_PRINT("info", ("EXECUTE: %.*s\n", name->length, name->str)); 02334 02335 if (!(stmt= (Prepared_statement*) thd->stmt_map.find_by_name(name))) 02336 { 02337 my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0), 02338 name->length, name->str, "EXECUTE"); 02339 DBUG_VOID_RETURN; 02340 } 02341 02342 if (stmt->param_count != lex->prepared_stmt_params.elements) 02343 { 02344 my_error(ER_WRONG_ARGUMENTS, MYF(0), "EXECUTE"); 02345 DBUG_VOID_RETURN; 02346 } 02347 02348 DBUG_PRINT("info",("stmt: %p", stmt)); 02349 02350 if (stmt->set_params_from_vars(stmt, lex->prepared_stmt_params, 02351 &expanded_query)) 02352 goto set_params_data_err; 02353 02354 (void) stmt->execute(&expanded_query, FALSE); 02355 02356 DBUG_VOID_RETURN; 02357 02358 set_params_data_err: 02359 my_error(ER_WRONG_ARGUMENTS, MYF(0), "EXECUTE"); 02360 reset_stmt_params(stmt); 02361 DBUG_VOID_RETURN; 02362 } 02363 02364 02365 /* 02366 COM_STMT_FETCH handler: fetches requested amount of rows from cursor 02367 02368 SYNOPSIS 02369 mysql_stmt_fetch() 02370 thd Thread handle 02371 packet Packet from client (with stmt_id & num_rows) 02372 packet_length Length of packet 02373 */ 02374 02375 void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length) 02376 { 02377 /* assume there is always place for 8-16 bytes */ 02378 ulong stmt_id= uint4korr(packet); 02379 ulong num_rows= uint4korr(packet+4); 02380 Prepared_statement *stmt; 02381 Statement stmt_backup; 02382 Server_side_cursor *cursor; 02383 DBUG_ENTER("mysql_stmt_fetch"); 02384 02385 /* First of all clear possible warnings from the previous command */ 02386 mysql_reset_thd_for_next_command(thd); 02387 statistic_increment(thd->status_var.com_stmt_fetch, &LOCK_status); 02388 if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_fetch"))) 02389 DBUG_VOID_RETURN; 02390 02391 cursor= stmt->cursor; 02392 if (!cursor) 02393 { 02394 my_error(ER_STMT_HAS_NO_OPEN_CURSOR, MYF(0), stmt_id); 02395 DBUG_VOID_RETURN; 02396 } 02397 02398 thd->stmt_arena= stmt; 02399 thd->set_n_backup_statement(stmt, &stmt_backup); 02400 02401 if (!(specialflag & SPECIAL_NO_PRIOR)) 02402 my_pthread_setprio(pthread_self(), QUERY_PRIOR); 02403 02404 cursor->fetch(num_rows); 02405 02406 if (!(specialflag & SPECIAL_NO_PRIOR)) 02407 my_pthread_setprio(pthread_self(), WAIT_PRIOR); 02408 02409 if (!cursor->is_open()) 02410 { 02411 stmt->close_cursor(); 02412 thd->cursor= 0; 02413 reset_stmt_params(stmt); 02414 } 02415 02416 thd->restore_backup_statement(stmt, &stmt_backup); 02417 thd->stmt_arena= thd; 02418 02419 DBUG_VOID_RETURN; 02420 } 02421 02422 02423 /* 02424 Reset a prepared statement in case there was a recoverable error. 02425 SYNOPSIS 02426 mysql_stmt_reset() 02427 thd Thread handle 02428 packet Packet with stmt id 02429 02430 DESCRIPTION 02431 This function resets statement to the state it was right after prepare. 02432 It can be used to: 02433 - clear an error happened during mysql_stmt_send_long_data 02434 - cancel long data stream for all placeholders without 02435 having to call mysql_stmt_execute. 02436 - close an open cursor 02437 Sends 'OK' packet in case of success (statement was reset) 02438 or 'ERROR' packet (unrecoverable error/statement not found/etc). 02439 */ 02440 02441 void mysql_stmt_reset(THD *thd, char *packet) 02442 { 02443 /* There is always space for 4 bytes in buffer */ 02444 ulong stmt_id= uint4korr(packet); 02445 Prepared_statement *stmt; 02446 DBUG_ENTER("mysql_stmt_reset"); 02447 02448 /* First of all clear possible warnings from the previous command */ 02449 mysql_reset_thd_for_next_command(thd); 02450 02451 statistic_increment(thd->status_var.com_stmt_reset, &LOCK_status); 02452 if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_reset"))) 02453 DBUG_VOID_RETURN; 02454 02455 stmt->close_cursor(); 02456 02457 /* 02458 Clear parameters from data which could be set by 02459 mysql_stmt_send_long_data() call. 02460 */ 02461 reset_stmt_params(stmt); 02462 02463 stmt->state= Query_arena::PREPARED; 02464 02465 send_ok(thd); 02466 02467 DBUG_VOID_RETURN; 02468 } 02469 02470 02471 /* 02472 Delete a prepared statement from memory. 02473 Note: we don't send any reply to this command. 02474 */ 02475 02476 void mysql_stmt_close(THD *thd, char *packet) 02477 { 02478 /* There is always space for 4 bytes in packet buffer */ 02479 ulong stmt_id= uint4korr(packet); 02480 Prepared_statement *stmt; 02481 DBUG_ENTER("mysql_stmt_close"); 02482 02483 if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_close"))) 02484 DBUG_VOID_RETURN; 02485 02486 /* 02487 The only way currently a statement can be deallocated when it's 02488 in use is from within Dynamic SQL. 02489 */ 02490 DBUG_ASSERT(! (stmt->flags & (uint) Prepared_statement::IS_IN_USE)); 02491 (void) stmt->deallocate(); 02492 02493 DBUG_VOID_RETURN; 02494 } 02495 02496 02497 /* 02498 SQLCOM_DEALLOCATE implementation. 02499 02500 DESCRIPTION 02501 Close an SQL prepared statement. As this can be called from Dynamic 02502 SQL, we should be careful to not close a statement that is currently 02503 being executed. 02504 02505 RETURN VALUE 02506 none: OK packet is sent in case of success, otherwise an error 02507 message is set in THD 02508 */ 02509 02510 void mysql_sql_stmt_close(THD *thd) 02511 { 02512 Prepared_statement* stmt; 02513 LEX_STRING *name= &thd->lex->prepared_stmt_name; 02514 DBUG_PRINT("info", ("DEALLOCATE PREPARE: %.*s\n", name->length, name->str)); 02515 02516 if (! (stmt= (Prepared_statement*) thd->stmt_map.find_by_name(name))) 02517 { 02518 my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0), 02519 name->length, name->str, "DEALLOCATE PREPARE"); 02520 return; 02521 } 02522 02523 if (stmt->deallocate() == 0) 02524 send_ok(thd); 02525 } 02526 02527 /* 02528 Handle long data in pieces from client. 02529 02530 SYNOPSIS 02531 mysql_stmt_get_longdata() 02532 thd Thread handle 02533 packet String to append 02534 packet_length Length of string (including end \0) 02535 02536 DESCRIPTION 02537 Get a part of a long data. To make the protocol efficient, we are 02538 not sending any return packets here. If something goes wrong, then 02539 we will send the error on 'execute' We assume that the client takes 02540 care of checking that all parts are sent to the server. (No checking 02541 that we get a 'end of column' in the server is performed). 02542 */ 02543 02544 void mysql_stmt_get_longdata(THD *thd, char *packet, ulong packet_length) 02545 { 02546 ulong stmt_id; 02547 uint param_number; 02548 Prepared_statement *stmt; 02549 Item_param *param; 02550 char *packet_end= packet + packet_length - 1; 02551 DBUG_ENTER("mysql_stmt_get_longdata"); 02552 02553 statistic_increment(thd->status_var.com_stmt_send_long_data, &LOCK_status); 02554 #ifndef EMBEDDED_LIBRARY 02555 /* Minimal size of long data packet is 6 bytes */ 02556 if (packet_length <= MYSQL_LONG_DATA_HEADER) 02557 { 02558 my_error(ER_WRONG_ARGUMENTS, MYF(0), "mysql_stmt_send_long_data"); 02559 DBUG_VOID_RETURN; 02560 } 02561 #endif 02562 02563 stmt_id= uint4korr(packet); 02564 packet+= 4; 02565 02566 if (!(stmt=find_prepared_statement(thd, stmt_id, 02567 "mysql_stmt_send_long_data"))) 02568 DBUG_VOID_RETURN; 02569 02570 param_number= uint2korr(packet); 02571 packet+= 2; 02572 #ifndef EMBEDDED_LIBRARY 02573 if (param_number >= stmt->param_count) 02574 { 02575 /* Error will be sent in execute call */ 02576 stmt->state= Query_arena::ERROR; 02577 stmt->last_errno= ER_WRONG_ARGUMENTS; 02578 sprintf(stmt->last_error, ER(ER_WRONG_ARGUMENTS), 02579 "mysql_stmt_send_long_data"); 02580 DBUG_VOID_RETURN; 02581 } 02582 #endif 02583 02584 param= stmt->param_array[param_number]; 02585 02586 #ifndef EMBEDDED_LIBRARY 02587 if (param->set_longdata(packet, (ulong) (packet_end - packet))) 02588 #else 02589 if (param->set_longdata(thd->extra_data, thd->extra_length)) 02590 #endif 02591 { 02592 stmt->state= Query_arena::ERROR; 02593 stmt->last_errno= ER_OUTOFMEMORY; 02594 sprintf(stmt->last_error, ER(ER_OUTOFMEMORY), 0); 02595 } 02596 DBUG_VOID_RETURN; 02597 } 02598 02599 02600 /*************************************************************************** 02601 Select_fetch_protocol_prep 02602 ****************************************************************************/ 02603 02604 Select_fetch_protocol_prep::Select_fetch_protocol_prep(THD *thd) 02605 :protocol(thd) 02606 {} 02607 02608 bool Select_fetch_protocol_prep::send_fields(List<Item> &list, uint flags) 02609 { 02610 bool rc; 02611 Protocol *save_protocol= thd->protocol; 02612 02613 /* 02614 Protocol::send_fields caches the information about column types: 02615 this information is later used to send data. Therefore, the same 02616 dedicated Protocol object must be used for all operations with 02617 a cursor. 02618 */ 02619 thd->protocol= &protocol; 02620 rc= select_send::send_fields(list, flags); 02621 thd->protocol= save_protocol; 02622 02623 return rc; 02624 } 02625 02626 bool Select_fetch_protocol_prep::send_eof() 02627 { 02628 Protocol *save_protocol= thd->protocol; 02629 02630 thd->protocol= &protocol; 02631 ::send_eof(thd); 02632 thd->protocol= save_protocol; 02633 return FALSE; 02634 } 02635 02636 02637 bool 02638 Select_fetch_protocol_prep::send_data(List<Item> &fields) 02639 { 02640 Protocol *save_protocol= thd->protocol; 02641 bool rc; 02642 02643 thd->protocol= &protocol; 02644 rc= select_send::send_data(fields); 02645 thd->protocol= save_protocol; 02646 return rc; 02647 } 02648 02649 /*************************************************************************** 02650 Prepared_statement 02651 ****************************************************************************/ 02652 02653 Prepared_statement::Prepared_statement(THD *thd_arg, Protocol *protocol_arg) 02654 :Statement(INITIALIZED, ++thd_arg->statement_id_counter, 02655 thd_arg->variables.query_alloc_block_size, 02656 thd_arg->variables.query_prealloc_size), 02657 thd(thd_arg), 02658 result(thd_arg), 02659 protocol(protocol_arg), 02660 param_array(0), 02661 param_count(0), 02662 last_errno(0), 02663 flags((uint) IS_IN_USE) 02664 { 02665 *last_error= '\0'; 02666 } 02667 02668 02669 void Prepared_statement::setup_set_params() 02670 { 02671 /* Setup binary logging */ 02672 if (mysql_bin_log.is_open() && is_update_query(lex->sql_command) || 02673 opt_log || opt_slow_log) 02674 { 02675 set_params_from_vars= insert_params_from_vars_with_log; 02676 #ifndef EMBEDDED_LIBRARY 02677 set_params= insert_params_withlog; 02678 #else 02679 set_params_data= emb_insert_params_withlog; 02680 #endif 02681 } 02682 else 02683 { 02684 set_params_from_vars= insert_params_from_vars; 02685 #ifndef EMBEDDED_LIBRARY 02686 set_params= insert_params; 02687 #else 02688 set_params_data= emb_insert_params; 02689 #endif 02690 } 02691 } 02692 02693 02694 /* 02695 DESCRIPTION 02696 Destroy this prepared statement, cleaning up all used memory 02697 and resources. This is called from ::deallocate() to 02698 handle COM_STMT_CLOSE and DEALLOCATE PREPARE or when 02699 THD ends and all prepared statements are freed. 02700 */ 02701 02702 Prepared_statement::~Prepared_statement() 02703 { 02704 DBUG_ENTER("Prepared_statement::~Prepared_statement"); 02705 DBUG_PRINT("enter",("stmt: %p cursor: %p", this, cursor)); 02706 delete cursor; 02707 /* 02708 We have to call free on the items even if cleanup is called as some items, 02709 like Item_param, don't free everything until free_items() 02710 */ 02711 free_items(); 02712 delete lex->result; 02713 DBUG_VOID_RETURN; 02714 } 02715 02716 02717 Query_arena::Type Prepared_statement::type() const 02718 { 02719 return PREPARED_STATEMENT; 02720 } 02721 02722 02723 void Prepared_statement::cleanup_stmt() 02724 { 02725 DBUG_ENTER("Prepared_statement::cleanup_stmt"); 02726 DBUG_PRINT("enter",("stmt: %p", this)); 02727 02728 /* The order is important */ 02729 lex->unit.cleanup(); 02730 cleanup_items(free_list); 02731 thd->cleanup_after_query(); 02732 close_thread_tables(thd); 02733 thd->rollback_item_tree_changes(); 02734 02735 DBUG_VOID_RETURN; 02736 } 02737 02738 02739 bool Prepared_statement::set_name(LEX_STRING *name_arg) 02740 { 02741 name.length= name_arg->length; 02742 name.str= memdup_root(mem_root, (char*) name_arg->str, name_arg->length); 02743 return name.str == 0; 02744 } 02745 02746 /************************************************************************** 02747 Common parts of mysql_[sql]_stmt_prepare, mysql_[sql]_stmt_execute. 02748 Essentially, these functions do all the magic of preparing/executing 02749 a statement, leaving network communication, input data handling and 02750 global THD state management to the caller. 02751 ***************************************************************************/ 02752 02753 /* 02754 Parse statement text, validate the statement, and prepare it for execution. 02755 02756 SYNOPSIS 02757 Prepared_statement::prepare() 02758 packet statement text 02759 packet_len 02760 02761 DESCRIPTION 02762 You should not change global THD state in this function, if at all 02763 possible: it may be called from any context, e.g. when executing 02764 a COM_* command, and SQLCOM_* command, or a stored procedure. 02765 02766 NOTES 02767 Precondition. 02768 ------------- 02769 The caller must ensure that thd->change_list and thd->free_list 02770 is empty: this function will not back them up but will free 02771 in the end of its execution. 02772 02773 Postcondition. 02774 -------------- 02775 thd->mem_root contains unused memory allocated during validation. 02776 */ 02777 02778 bool Prepared_statement::prepare(const char *packet, uint packet_len) 02779 { 02780 bool error; 02781 Statement stmt_backup; 02782 Query_arena *old_stmt_arena; 02783 DBUG_ENTER("Prepared_statement::prepare"); 02784 /* 02785 If this is an SQLCOM_PREPARE, we also increase Com_prepare_sql. 02786 However, it seems handy if com_stmt_prepare is increased always, 02787 no matter what kind of prepare is processed. 02788 */ 02789 statistic_increment(thd->status_var.com_stmt_prepare, &LOCK_status); 02790 02791 /* 02792 alloc_query() uses thd->memroot && thd->query, so we should call 02793 both of backup_statement() and backup_query_arena() here. 02794 */ 02795 thd->set_n_backup_statement(this, &stmt_backup); 02796 thd->set_n_backup_active_arena(this, &stmt_backup); 02797 02798 if (alloc_query(thd, packet, packet_len)) 02799 { 02800 thd->restore_backup_statement(this, &stmt_backup); 02801 thd->restore_active_arena(this, &stmt_backup); 02802 DBUG_RETURN(TRUE); 02803 } 02804 02805 old_stmt_arena= thd->stmt_arena; 02806 thd->stmt_arena= this; 02807 lex_start(thd, (uchar*) thd->query, thd->query_length); 02808 lex->stmt_prepare_mode= TRUE; 02809 02810 error= MYSQLparse((void *)thd) || thd->is_fatal_error || 02811 thd->net.report_error || init_param_array(this); 02812 lex->safe_to_cache_query= FALSE; 02813 /* 02814 While doing context analysis of the query (in check_prepared_statement) 02815 we allocate a lot of additional memory: for open tables, JOINs, derived 02816 tables, etc. Let's save a snapshot of current parse tree to the 02817 statement and restore original THD. In cases when some tree 02818 transformation can be reused on execute, we set again thd->mem_root from 02819 stmt->mem_root (see setup_wild for one place where we do that). 02820 */ 02821 thd->restore_active_arena(this, &stmt_backup); 02822 02823 /* 02824 If called from a stored procedure, ensure that we won't rollback 02825 external changes when cleaning up after validation. 02826 */ 02827 DBUG_ASSERT(thd->change_list.is_empty()); 02828 /* 02829 If the free_list is not empty, we'll wrongly free some externally 02830 allocated items when cleaning up after validation of the prepared 02831 statement. 02832 */ 02833 DBUG_ASSERT(thd->free_list == NULL); 02834 02835 if (error == 0) 02836 error= check_prepared_statement(this, name.str != 0); 02837 02838 if (error && lex->sphead) 02839 { 02840 delete lex->sphead; 02841 lex->sphead= NULL; 02842 } 02843 lex_end(lex); 02844 cleanup_stmt(); 02845 thd->restore_backup_statement(this, &stmt_backup); 02846 thd->stmt_arena= old_stmt_arena; 02847 02848 if (error == 0) 02849 { 02850 setup_set_params(); 02851 init_stmt_after_parse(lex); 02852 state= Query_arena::PREPARED; 02853 flags&= ~ (uint) IS_IN_USE; 02854 } 02855 DBUG_RETURN(error); 02856 } 02857 02858 /* 02859 Execute a prepared statement. 02860 02861 SYNOPSIS 02862 Prepared_statement::execute() 02863 expanded_query A query for binlogging which has all parameter 02864 markers ('?') replaced with their actual values. 02865 open_cursor True if an attempt to open a cursor should be made. 02866 Currenlty used only in the binary protocol. 02867 02868 DESCRIPTION 02869 You should not change global THD state in this function, if at all 02870 possible: it may be called from any context, e.g. when executing 02871 a COM_* command, and SQLCOM_* command, or a stored procedure. 02872 02873 NOTES 02874 Preconditions, postconditions. 02875 ------------------------------ 02876 See the comment for Prepared_statement::prepare(). 02877 02878 RETURN 02879 FALSE ok 02880 TRUE Error 02881 */ 02882 02883 bool Prepared_statement::execute(String *expanded_query, bool open_cursor) 02884 { 02885 Statement stmt_backup; 02886 Query_arena *old_stmt_arena; 02887 Item *old_free_list; 02888 bool error= TRUE; 02889 02890 statistic_increment(thd->status_var.com_stmt_execute, &LOCK_status); 02891 02892 /* Check if we got an error when sending long data */ 02893 if (state == Query_arena::ERROR) 02894 { 02895 my_message(last_errno, last_error, MYF(0)); 02896 return TRUE; 02897 } 02898 if (flags & (uint) IS_IN_USE) 02899 { 02900 my_error(ER_PS_NO_RECURSION, MYF(0)); 02901 return TRUE; 02902 } 02903 02904 /* 02905 For SHOW VARIABLES lex->result is NULL, as it's a non-SELECT 02906 command. For such queries we don't return an error and don't 02907 open a cursor -- the client library will recognize this case and 02908 materialize the result set. 02909 For SELECT statements lex->result is created in 02910 check_prepared_statement. lex->result->simple_select() is FALSE 02911 in INSERT ... SELECT and similar commands. 02912 */ 02913 02914 if (open_cursor && lex->result && !lex->result->simple_select()) 02915 { 02916 DBUG_PRINT("info",("Cursor asked for not SELECT stmt")); 02917 my_error(ER_SP_BAD_CURSOR_QUERY, MYF(0)); 02918 return TRUE; 02919 } 02920 02921 /* In case the command has a call to SP which re-uses this statement name */ 02922 flags|= IS_IN_USE; 02923 02924 close_cursor(); 02925 02926 /* 02927 If the free_list is not empty, we'll wrongly free some externally 02928 allocated items when cleaning up after execution of this statement. 02929 */ 02930 DBUG_ASSERT(thd->change_list.is_empty()); 02931 DBUG_ASSERT(thd->free_list == NULL); 02932 thd->set_n_backup_statement(this, &stmt_backup); 02933 if (expanded_query->length() && 02934 alloc_query(thd, (char*) expanded_query->ptr(), 02935 expanded_query->length()+1)) 02936 { 02937 my_error(ER_OUTOFMEMORY, 0, expanded_query->length()); 02938 goto error; 02939 } 02940 /* 02941 Expanded query is needed for slow logging, so we want thd->query 02942 to point at it even after we restore from backup. This is ok, as 02943 expanded query was allocated in thd->mem_root. 02944 */ 02945 stmt_backup.query= thd->query; 02946 stmt_backup.query_length= thd->query_length; 02947 02948 /* 02949 At first execution of prepared statement we may perform logical 02950 transformations of the query tree. Such changes should be performed 02951 on the parse tree of current prepared statement and new items should 02952 be allocated in its memory root. Set the appropriate pointer in THD 02953 to the arena of the statement. 02954 */ 02955 old_stmt_arena= thd->stmt_arena; 02956 thd->stmt_arena= this; 02957 reinit_stmt_before_use(thd, lex); 02958 02959 thd->protocol= protocol; /* activate stmt protocol */ 02960 error= (open_cursor ? 02961 mysql_open_cursor(thd, (uint) ALWAYS_MATERIALIZED_CURSOR, 02962 &result, &cursor) : 02963 mysql_execute_command(thd)); 02964 thd->protocol= &thd->protocol_simple; /* use normal protocol */ 02965 02966 /* Assert that if an error, no cursor is open */ 02967 DBUG_ASSERT(! (error && cursor)); 02968 02969 if (! cursor) 02970 { 02971 cleanup_stmt(); 02972 reset_stmt_params(this); 02973 } 02974 02975 thd->set_statement(&stmt_backup); 02976 thd->stmt_arena= old_stmt_arena; 02977 02978 if (state == Query_arena::PREPARED) 02979 state= Query_arena::EXECUTED; 02980 02981 error: 02982 flags&= ~ (uint) IS_IN_USE; 02983 return error; 02984 } 02985 02986 02987 /* Common part of DEALLOCATE PREPARE and mysql_stmt_close */ 02988 02989 bool Prepared_statement::deallocate() 02990 { 02991 /* We account deallocate in the same manner as mysql_stmt_close */ 02992 statistic_increment(thd->status_var.com_stmt_close, &LOCK_status); 02993 if (flags & (uint) IS_IN_USE) 02994 { 02995 my_error(ER_PS_NO_RECURSION, MYF(0)); 02996 return TRUE; 02997 } 02998 /* Statement map calls delete stmt on erase */ 02999 thd->stmt_map.erase(this); 03000 return FALSE; 03001 }
1.4.7

