1 /*
2 Copyright (c) 2002, 2018, Oracle and/or its affiliates.
3 Copyright (c) 2009, 2020, MariaDB
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; version 2 of the License.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */
17
18 #include "mariadb.h"
19 #include "sql_priv.h"
20 #include "unireg.h"
21 #include "sp.h"
22 #include "sql_base.h" // close_thread_tables
23 #include "sql_lex.h" // empty_clex_str
24 #include "sql_parse.h" // parse_sql
25 #include "key.h" // key_copy
26 #include "sql_show.h" // append_definer, append_identifier
27 #include "sql_db.h" // get_default_db_collation, mysql_opt_change_db,
28 // mysql_change_db, check_db_dir_existence,
29 // load_db_opt_by_name
30 #include "sql_table.h" // write_bin_log
31 #include "sql_acl.h" // SUPER_ACL
32 #include "sp_head.h"
33 #include "sp_cache.h"
34 #include "lock.h" // lock_object_name
35
36 #include <my_user.h>
37
get_cache(THD * thd) const38 sp_cache **Sp_handler_procedure::get_cache(THD *thd) const
39 {
40 return &thd->sp_proc_cache;
41 }
42
get_cache(THD * thd) const43 sp_cache **Sp_handler_function::get_cache(THD *thd) const
44 {
45 return &thd->sp_func_cache;
46 }
47
get_cache(THD * thd) const48 sp_cache **Sp_handler_package_spec::get_cache(THD *thd) const
49 {
50 return &thd->sp_package_spec_cache;
51 }
52
get_cache(THD * thd) const53 sp_cache **Sp_handler_package_body::get_cache(THD *thd) const
54 {
55 return &thd->sp_package_body_cache;
56 }
57
58
recursion_depth(THD * thd) const59 ulong Sp_handler_procedure::recursion_depth(THD *thd) const
60 {
61 return thd->variables.max_sp_recursion_depth;
62 }
63
64
add_instr_freturn(THD * thd,sp_head * sp,sp_pcontext * spcont,Item * item,LEX * lex) const65 bool Sp_handler::add_instr_freturn(THD *thd, sp_head *sp,
66 sp_pcontext *spcont,
67 Item *item, LEX *lex) const
68 {
69 my_error(ER_SP_BADRETURN, MYF(0));
70 return true;
71 }
72
73
add_instr_preturn(THD * thd,sp_head * sp,sp_pcontext * spcont) const74 bool Sp_handler::add_instr_preturn(THD *thd, sp_head *sp,
75 sp_pcontext *spcont) const
76 {
77 thd->parse_error();
78 return true;
79 }
80
81
add_instr_freturn(THD * thd,sp_head * sp,sp_pcontext * spcont,Item * item,LEX * lex) const82 bool Sp_handler_function::add_instr_freturn(THD *thd, sp_head *sp,
83 sp_pcontext *spcont,
84 Item *item, LEX *lex) const
85 {
86 return sp->add_instr_freturn(thd, spcont, item, lex);
87 }
88
89
add_instr_preturn(THD * thd,sp_head * sp,sp_pcontext * spcont) const90 bool Sp_handler_procedure::add_instr_preturn(THD *thd, sp_head *sp,
91 sp_pcontext *spcont) const
92 {
93 return sp->add_instr_preturn(thd, spcont);
94 }
95
96
97 Sp_handler_procedure sp_handler_procedure;
98 Sp_handler_function sp_handler_function;
99 Sp_handler_package_spec sp_handler_package_spec;
100 Sp_handler_package_body sp_handler_package_body;
101 Sp_handler_trigger sp_handler_trigger;
102 Sp_handler_package_procedure sp_handler_package_procedure;
103 Sp_handler_package_function sp_handler_package_function;
104
105
package_routine_handler() const106 const Sp_handler *Sp_handler_procedure::package_routine_handler() const
107 {
108 return &sp_handler_package_procedure;
109 }
110
111
package_routine_handler() const112 const Sp_handler *Sp_handler_function::package_routine_handler() const
113 {
114 return &sp_handler_package_function;
115 }
116
117
118 static const
119 TABLE_FIELD_TYPE proc_table_fields[MYSQL_PROC_FIELD_COUNT] =
120 {
121 {
122 { STRING_WITH_LEN("db") },
123 { STRING_WITH_LEN("char(64)") },
124 { STRING_WITH_LEN("utf8") }
125 },
126 {
127 { STRING_WITH_LEN("name") },
128 { STRING_WITH_LEN("char(64)") },
129 { STRING_WITH_LEN("utf8") }
130 },
131 {
132 { STRING_WITH_LEN("type") },
133 { STRING_WITH_LEN("enum('FUNCTION','PROCEDURE')") },
134 { NULL, 0 }
135 },
136 {
137 { STRING_WITH_LEN("specific_name") },
138 { STRING_WITH_LEN("char(64)") },
139 { STRING_WITH_LEN("utf8") }
140 },
141 {
142 { STRING_WITH_LEN("language") },
143 { STRING_WITH_LEN("enum('SQL')") },
144 { NULL, 0 }
145 },
146 {
147 { STRING_WITH_LEN("sql_data_access") },
148 { STRING_WITH_LEN("enum('CONTAINS_SQL','NO_SQL','READS_SQL_DATA','MODIFIES_SQL_DATA')") },
149 { NULL, 0 }
150 },
151 {
152 { STRING_WITH_LEN("is_deterministic") },
153 { STRING_WITH_LEN("enum('YES','NO')") },
154 { NULL, 0 }
155 },
156 {
157 { STRING_WITH_LEN("security_type") },
158 { STRING_WITH_LEN("enum('INVOKER','DEFINER')") },
159 { NULL, 0 }
160 },
161 {
162 { STRING_WITH_LEN("param_list") },
163 { STRING_WITH_LEN("blob") },
164 { NULL, 0 }
165 },
166
167 {
168 { STRING_WITH_LEN("returns") },
169 { STRING_WITH_LEN("longblob") },
170 { NULL, 0 }
171 },
172 {
173 { STRING_WITH_LEN("body") },
174 { STRING_WITH_LEN("longblob") },
175 { NULL, 0 }
176 },
177 {
178 { STRING_WITH_LEN("definer") },
179 { STRING_WITH_LEN("char(") },
180 { STRING_WITH_LEN("utf8") }
181 },
182 {
183 { STRING_WITH_LEN("created") },
184 { STRING_WITH_LEN("timestamp") },
185 { NULL, 0 }
186 },
187 {
188 { STRING_WITH_LEN("modified") },
189 { STRING_WITH_LEN("timestamp") },
190 { NULL, 0 }
191 },
192 {
193 { STRING_WITH_LEN("sql_mode") },
194 { STRING_WITH_LEN("set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES',"
195 "'IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY',"
196 "'NO_UNSIGNED_SUBTRACTION',"
197 "'NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB',"
198 "'NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40',"
199 "'ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES',"
200 "'STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES',"
201 "'ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER',"
202 "'HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH',"
203 "'EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT',"
204 "'TIME_ROUND_FRACTIONAL')") },
205 { NULL, 0 }
206 },
207 {
208 { STRING_WITH_LEN("comment") },
209 { STRING_WITH_LEN("text") },
210 { STRING_WITH_LEN("utf8") }
211 },
212 {
213 { STRING_WITH_LEN("character_set_client") },
214 { STRING_WITH_LEN("char(32)") },
215 { STRING_WITH_LEN("utf8") }
216 },
217 {
218 { STRING_WITH_LEN("collation_connection") },
219 { STRING_WITH_LEN("char(32)") },
220 { STRING_WITH_LEN("utf8") }
221 },
222 {
223 { STRING_WITH_LEN("db_collation") },
224 { STRING_WITH_LEN("char(32)") },
225 { STRING_WITH_LEN("utf8") }
226 },
227 {
228 { STRING_WITH_LEN("body_utf8") },
229 { STRING_WITH_LEN("longblob") },
230 { NULL, 0 }
231 },
232 {
233 { STRING_WITH_LEN("aggregate") },
234 { STRING_WITH_LEN("enum('NONE','GROUP')") },
235 { NULL, 0 }
236 }
237 };
238
239 static const TABLE_FIELD_DEF
240 proc_table_def= {MYSQL_PROC_FIELD_COUNT, proc_table_fields, 0, (uint*) 0 };
241
242 /*************************************************************************/
243
244 /**
245 Stored_routine_creation_ctx -- creation context of stored routines
246 (stored procedures and functions).
247 */
248
249 class Stored_routine_creation_ctx : public Stored_program_creation_ctx,
250 public Sql_alloc
251 {
252 public:
253 static Stored_routine_creation_ctx *
254 load_from_db(THD *thd, const Database_qualified_name *name, TABLE *proc_tbl);
255
256 public:
clone(MEM_ROOT * mem_root)257 virtual Stored_program_creation_ctx *clone(MEM_ROOT *mem_root)
258 {
259 return new (mem_root) Stored_routine_creation_ctx(m_client_cs,
260 m_connection_cl,
261 m_db_cl);
262 }
263
264 protected:
create_backup_ctx(THD * thd) const265 virtual Object_creation_ctx *create_backup_ctx(THD *thd) const
266 {
267 DBUG_ENTER("Stored_routine_creation_ctx::create_backup_ctx");
268 DBUG_RETURN(new Stored_routine_creation_ctx(thd));
269 }
270
271 private:
Stored_routine_creation_ctx(THD * thd)272 Stored_routine_creation_ctx(THD *thd)
273 : Stored_program_creation_ctx(thd)
274 { }
275
Stored_routine_creation_ctx(CHARSET_INFO * client_cs,CHARSET_INFO * connection_cl,CHARSET_INFO * db_cl)276 Stored_routine_creation_ctx(CHARSET_INFO *client_cs,
277 CHARSET_INFO *connection_cl,
278 CHARSET_INFO *db_cl)
279 : Stored_program_creation_ctx(client_cs, connection_cl, db_cl)
280 { }
281 };
282
283 /**************************************************************************
284 Stored_routine_creation_ctx implementation.
285 **************************************************************************/
286
load_charset(MEM_ROOT * mem_root,Field * field,CHARSET_INFO * dflt_cs,CHARSET_INFO ** cs)287 bool load_charset(MEM_ROOT *mem_root,
288 Field *field,
289 CHARSET_INFO *dflt_cs,
290 CHARSET_INFO **cs)
291 {
292 LEX_CSTRING cs_name;
293
294 if (field->val_str_nopad(mem_root, &cs_name))
295 {
296 *cs= dflt_cs;
297 return TRUE;
298 }
299
300 DBUG_ASSERT(cs_name.str[cs_name.length] == 0);
301 *cs= get_charset_by_csname(cs_name.str, MY_CS_PRIMARY, MYF(0));
302
303 if (*cs == NULL)
304 {
305 *cs= dflt_cs;
306 return TRUE;
307 }
308
309 return FALSE;
310 }
311
312 /*************************************************************************/
313
load_collation(MEM_ROOT * mem_root,Field * field,CHARSET_INFO * dflt_cl,CHARSET_INFO ** cl)314 bool load_collation(MEM_ROOT *mem_root,
315 Field *field,
316 CHARSET_INFO *dflt_cl,
317 CHARSET_INFO **cl)
318 {
319 LEX_CSTRING cl_name;
320
321 if (field->val_str_nopad(mem_root, &cl_name))
322 {
323 *cl= dflt_cl;
324 return TRUE;
325 }
326
327 DBUG_ASSERT(cl_name.str[cl_name.length] == 0);
328 *cl= get_charset_by_name(cl_name.str, MYF(0));
329
330 if (*cl == NULL)
331 {
332 *cl= dflt_cl;
333 return TRUE;
334 }
335
336 return FALSE;
337 }
338
339 /*************************************************************************/
340
341 Stored_routine_creation_ctx *
load_from_db(THD * thd,const Database_qualified_name * name,TABLE * proc_tbl)342 Stored_routine_creation_ctx::load_from_db(THD *thd,
343 const Database_qualified_name *name,
344 TABLE *proc_tbl)
345 {
346 /* Load character set/collation attributes. */
347
348 CHARSET_INFO *client_cs;
349 CHARSET_INFO *connection_cl;
350 CHARSET_INFO *db_cl;
351
352 const char *db_name= thd->strmake(name->m_db.str, name->m_db.length);
353 const char *sr_name= thd->strmake(name->m_name.str, name->m_name.length);
354
355 bool invalid_creation_ctx= FALSE;
356
357 if (load_charset(thd->mem_root,
358 proc_tbl->field[MYSQL_PROC_FIELD_CHARACTER_SET_CLIENT],
359 thd->variables.character_set_client,
360 &client_cs))
361 {
362 sql_print_warning("Stored routine '%s'.'%s': invalid value "
363 "in column mysql.proc.character_set_client.",
364 (const char *) db_name,
365 (const char *) sr_name);
366
367 invalid_creation_ctx= TRUE;
368 }
369
370 if (load_collation(thd->mem_root,
371 proc_tbl->field[MYSQL_PROC_FIELD_COLLATION_CONNECTION],
372 thd->variables.collation_connection,
373 &connection_cl))
374 {
375 sql_print_warning("Stored routine '%s'.'%s': invalid value "
376 "in column mysql.proc.collation_connection.",
377 (const char *) db_name,
378 (const char *) sr_name);
379
380 invalid_creation_ctx= TRUE;
381 }
382
383 if (load_collation(thd->mem_root,
384 proc_tbl->field[MYSQL_PROC_FIELD_DB_COLLATION],
385 NULL,
386 &db_cl))
387 {
388 sql_print_warning("Stored routine '%s'.'%s': invalid value "
389 "in column mysql.proc.db_collation.",
390 (const char *) db_name,
391 (const char *) sr_name);
392
393 invalid_creation_ctx= TRUE;
394 }
395
396 if (invalid_creation_ctx)
397 {
398 push_warning_printf(thd,
399 Sql_condition::WARN_LEVEL_WARN,
400 ER_SR_INVALID_CREATION_CTX,
401 ER_THD(thd, ER_SR_INVALID_CREATION_CTX),
402 (const char *) db_name,
403 (const char *) sr_name);
404 }
405
406 /*
407 If we failed to retrieve the database collation, load the default one
408 from the disk.
409 */
410
411 if (!db_cl)
412 db_cl= get_default_db_collation(thd, name->m_db.str);
413
414 /* Create the context. */
415
416 return new Stored_routine_creation_ctx(client_cs, connection_cl, db_cl);
417 }
418
419 /*************************************************************************/
420
421 class Proc_table_intact : public Table_check_intact
422 {
423 private:
424 bool m_print_once;
425
426 public:
Proc_table_intact()427 Proc_table_intact() : m_print_once(TRUE) { has_keys= TRUE; }
428
429 protected:
430 void report_error(uint code, const char *fmt, ...);
431 };
432
433
434 /**
435 Report failure to validate the mysql.proc table definition.
436 Print a message to the error log only once.
437 */
438
report_error(uint code,const char * fmt,...)439 void Proc_table_intact::report_error(uint code, const char *fmt, ...)
440 {
441 va_list args;
442 char buf[512];
443
444 va_start(args, fmt);
445 my_vsnprintf(buf, sizeof(buf), fmt, args);
446 va_end(args);
447
448 if (code)
449 my_message(code, buf, MYF(0));
450 else
451 my_error(ER_CANNOT_LOAD_FROM_TABLE_V2, MYF(0), "mysql", "proc");
452
453 if (m_print_once)
454 {
455 m_print_once= FALSE;
456 sql_print_error("%s", buf);
457 }
458 };
459
460
461 /** Single instance used to control printing to the error log. */
462 static Proc_table_intact proc_table_intact;
463
464
465 /**
466 Open the mysql.proc table for read.
467
468 @param thd Thread context
469 @param backup Pointer to Open_tables_state instance where information about
470 currently open tables will be saved, and from which will be
471 restored when we will end work with mysql.proc.
472
473 @retval
474 0 Error
475 @retval
476 \# Pointer to TABLE object of mysql.proc
477 */
478
open_proc_table_for_read(THD * thd,Open_tables_backup * backup)479 TABLE *open_proc_table_for_read(THD *thd, Open_tables_backup *backup)
480 {
481 TABLE_LIST table;
482
483 DBUG_ENTER("open_proc_table_for_read");
484
485 table.init_one_table(&MYSQL_SCHEMA_NAME, &MYSQL_PROC_NAME, NULL, TL_READ);
486
487 if (open_system_tables_for_read(thd, &table, backup))
488 DBUG_RETURN(NULL);
489
490 if (!proc_table_intact.check(table.table, &proc_table_def))
491 DBUG_RETURN(table.table);
492
493 close_system_tables(thd, backup);
494
495 DBUG_RETURN(NULL);
496 }
497
498
499 /**
500 Open the mysql.proc table for update.
501
502 @param thd Thread context
503
504 @note
505 Table opened with this call should closed using close_thread_tables().
506
507 @retval
508 0 Error
509 @retval
510 \# Pointer to TABLE object of mysql.proc
511 */
512
open_proc_table_for_update(THD * thd)513 static TABLE *open_proc_table_for_update(THD *thd)
514 {
515 TABLE_LIST table_list;
516 TABLE *table;
517 MDL_savepoint mdl_savepoint= thd->mdl_context.mdl_savepoint();
518 DBUG_ENTER("open_proc_table_for_update");
519
520 table_list.init_one_table(&MYSQL_SCHEMA_NAME, &MYSQL_PROC_NAME, NULL, TL_WRITE);
521
522 if (!(table= open_system_table_for_update(thd, &table_list)))
523 DBUG_RETURN(NULL);
524
525 if (!proc_table_intact.check(table, &proc_table_def))
526 DBUG_RETURN(table);
527
528 close_thread_tables(thd);
529 thd->mdl_context.rollback_to_savepoint(mdl_savepoint);
530
531 DBUG_RETURN(NULL);
532 }
533
534
535 /**
536 Find row in open mysql.proc table representing stored routine.
537
538 @param thd Thread context
539 @param name Name of routine
540 @param table TABLE object for open mysql.proc table.
541
542 @retval
543 SP_OK Routine found
544 @retval
545 SP_KEY_NOT_FOUND No routine with given name
546 */
547
548 int
db_find_routine_aux(THD * thd,const Database_qualified_name * name,TABLE * table) const549 Sp_handler::db_find_routine_aux(THD *thd,
550 const Database_qualified_name *name,
551 TABLE *table) const
552 {
553 uchar key[MAX_KEY_LENGTH]; // db, name, optional key length type
554 DBUG_ENTER("db_find_routine_aux");
555 DBUG_PRINT("enter", ("type: %s name: %.*s",
556 type_str(),
557 (int) name->m_name.length, name->m_name.str));
558
559 /*
560 Create key to find row. We have to use field->store() to be able to
561 handle VARCHAR and CHAR fields.
562 Assumption here is that the three first fields in the table are
563 'db', 'name' and 'type' and the first key is the primary key over the
564 same fields.
565 */
566 if (name->m_name.length > table->field[1]->field_length)
567 DBUG_RETURN(SP_KEY_NOT_FOUND);
568 table->field[0]->store(name->m_db, &my_charset_bin);
569 table->field[1]->store(name->m_name, &my_charset_bin);
570 table->field[2]->store((longlong) type(), true);
571 key_copy(key, table->record[0], table->key_info,
572 table->key_info->key_length);
573
574 if (table->file->ha_index_read_idx_map(table->record[0], 0, key,
575 HA_WHOLE_KEY,
576 HA_READ_KEY_EXACT))
577 DBUG_RETURN(SP_KEY_NOT_FOUND);
578
579 DBUG_RETURN(SP_OK);
580 }
581
582
read_from_mysql_proc_row(THD * thd,TABLE * table)583 bool st_sp_chistics::read_from_mysql_proc_row(THD *thd, TABLE *table)
584 {
585 LEX_CSTRING str;
586
587 if (table->field[MYSQL_PROC_FIELD_ACCESS]->val_str_nopad(thd->mem_root,
588 &str))
589 return true;
590
591 switch (str.str[0]) {
592 case 'N':
593 daccess= SP_NO_SQL;
594 break;
595 case 'C':
596 daccess= SP_CONTAINS_SQL;
597 break;
598 case 'R':
599 daccess= SP_READS_SQL_DATA;
600 break;
601 case 'M':
602 daccess= SP_MODIFIES_SQL_DATA;
603 break;
604 default:
605 daccess= SP_DEFAULT_ACCESS_MAPPING;
606 }
607
608 if (table->field[MYSQL_PROC_FIELD_DETERMINISTIC]->val_str_nopad(thd->mem_root,
609 &str))
610 return true;
611 detistic= str.str[0] == 'N' ? false : true;
612
613 if (table->field[MYSQL_PROC_FIELD_SECURITY_TYPE]->val_str_nopad(thd->mem_root,
614 &str))
615 return true;
616 suid= str.str[0] == 'I' ? SP_IS_NOT_SUID : SP_IS_SUID;
617
618 if (table->field[MYSQL_PROC_FIELD_AGGREGATE]->val_str_nopad(thd->mem_root,
619 &str))
620 return true;
621
622 switch (str.str[0]) {
623 case 'N':
624 agg_type= NOT_AGGREGATE;
625 break;
626 case 'G':
627 agg_type= GROUP_AGGREGATE;
628 break;
629 default:
630 agg_type= DEFAULT_AGGREGATE;
631 }
632
633
634 if (table->field[MYSQL_PROC_FIELD_COMMENT]->val_str_nopad(thd->mem_root,
635 &comment))
636 return true;
637
638 return false;
639 }
640
641
read_from_mysql_proc_row(THD * thd,TABLE * table)642 bool AUTHID::read_from_mysql_proc_row(THD *thd, TABLE *table)
643 {
644 LEX_CSTRING str;
645 if (table->field[MYSQL_PROC_FIELD_DEFINER]->val_str_nopad(thd->mem_root,
646 &str))
647 return true;
648 parse(str.str, str.length);
649 if (user.str[user.length])
650 ((char *) user.str)[user.length]= '\0'; // 0-terminate if was truncated
651 return false;
652 }
653
654
655 /**
656 Find routine definition in mysql.proc table and create corresponding
657 sp_head object for it.
658
659 @param thd Thread context
660 @param name Name of routine
661 @param sphp Out parameter in which pointer to created sp_head
662 object is returned (0 in case of error).
663
664 @note
665 This function may damage current LEX during execution, so it is good
666 idea to create temporary LEX and make it active before calling it.
667
668 @retval
669 0 Success
670 @retval
671 non-0 Error (may be one of special codes like SP_KEY_NOT_FOUND)
672 */
673
674 int
db_find_routine(THD * thd,const Database_qualified_name * name,sp_head ** sphp) const675 Sp_handler::db_find_routine(THD *thd,
676 const Database_qualified_name *name,
677 sp_head **sphp) const
678 {
679 TABLE *table;
680 LEX_CSTRING params, returns, body;
681 int ret;
682 longlong created;
683 longlong modified;
684 Sp_chistics chistics;
685 bool saved_time_zone_used= thd->time_zone_used;
686 sql_mode_t sql_mode, saved_mode= thd->variables.sql_mode;
687 Open_tables_backup open_tables_state_backup;
688 Stored_program_creation_ctx *creation_ctx;
689 AUTHID definer;
690
691 DBUG_ENTER("db_find_routine");
692 DBUG_PRINT("enter", ("type: %s name: %.*s",
693 type_str(),
694 (int) name->m_name.length, name->m_name.str));
695
696 *sphp= 0; // In case of errors
697 if (!(table= open_proc_table_for_read(thd, &open_tables_state_backup)))
698 DBUG_RETURN(SP_OPEN_TABLE_FAILED);
699
700 /* Reset sql_mode during data dictionary operations. */
701 thd->variables.sql_mode= 0;
702
703 if ((ret= db_find_routine_aux(thd, name, table)) != SP_OK)
704 goto done;
705
706 if (table->s->fields < MYSQL_PROC_FIELD_COUNT)
707 {
708 ret= SP_GET_FIELD_FAILED;
709 goto done;
710 }
711
712 if (chistics.read_from_mysql_proc_row(thd, table) ||
713 definer.read_from_mysql_proc_row(thd, table))
714 {
715 ret= SP_GET_FIELD_FAILED;
716 goto done;
717 }
718
719 table->field[MYSQL_PROC_FIELD_PARAM_LIST]->val_str_nopad(thd->mem_root,
720 ¶ms);
721 if (type() != TYPE_ENUM_FUNCTION)
722 returns= empty_clex_str;
723 else if (table->field[MYSQL_PROC_FIELD_RETURNS]->val_str_nopad(thd->mem_root,
724 &returns))
725 {
726 ret= SP_GET_FIELD_FAILED;
727 goto done;
728 }
729
730 if (table->field[MYSQL_PROC_FIELD_BODY]->val_str_nopad(thd->mem_root,
731 &body))
732 {
733 ret= SP_GET_FIELD_FAILED;
734 goto done;
735 }
736
737 // Get additional information
738 modified= table->field[MYSQL_PROC_FIELD_MODIFIED]->val_int();
739 created= table->field[MYSQL_PROC_FIELD_CREATED]->val_int();
740 sql_mode= (sql_mode_t) table->field[MYSQL_PROC_FIELD_SQL_MODE]->val_int();
741
742 creation_ctx= Stored_routine_creation_ctx::load_from_db(thd, name, table);
743
744 close_system_tables(thd, &open_tables_state_backup);
745 table= 0;
746
747 ret= db_load_routine(thd, name, sphp,
748 sql_mode, params, returns, body, chistics, definer,
749 created, modified, NULL, creation_ctx);
750 done:
751 /*
752 Restore the time zone flag as the timezone usage in proc table
753 does not affect replication.
754 */
755 thd->time_zone_used= saved_time_zone_used;
756 if (table)
757 close_system_tables(thd, &open_tables_state_backup);
758 thd->variables.sql_mode= saved_mode;
759 DBUG_RETURN(ret);
760 }
761
762
763 int
db_find_and_cache_routine(THD * thd,const Database_qualified_name * name,sp_head ** sp) const764 Sp_handler::db_find_and_cache_routine(THD *thd,
765 const Database_qualified_name *name,
766 sp_head **sp) const
767 {
768 int rc= db_find_routine(thd, name, sp);
769 if (rc == SP_OK)
770 {
771 sp_cache_insert(get_cache(thd), *sp);
772 DBUG_PRINT("info", ("added new: %p, level: %lu, flags %x",
773 sp[0], sp[0]->m_recursion_level,
774 sp[0]->m_flags));
775 }
776 return rc;
777 }
778
779
780 /**
781 Silence DEPRECATED SYNTAX warnings when loading a stored procedure
782 into the cache.
783 */
784
785 struct Silence_deprecated_warning : public Internal_error_handler
786 {
787 public:
788 virtual bool handle_condition(THD *thd,
789 uint sql_errno,
790 const char* sqlstate,
791 Sql_condition::enum_warning_level *level,
792 const char* msg,
793 Sql_condition ** cond_hdl);
794 };
795
796 bool
handle_condition(THD *,uint sql_errno,const char *,Sql_condition::enum_warning_level * level,const char *,Sql_condition ** cond_hdl)797 Silence_deprecated_warning::handle_condition(
798 THD *,
799 uint sql_errno,
800 const char*,
801 Sql_condition::enum_warning_level *level,
802 const char*,
803 Sql_condition ** cond_hdl)
804 {
805 *cond_hdl= NULL;
806 if (sql_errno == ER_WARN_DEPRECATED_SYNTAX &&
807 *level == Sql_condition::WARN_LEVEL_WARN)
808 return TRUE;
809
810 return FALSE;
811 }
812
813
814 /**
815 @brief The function parses input strings and returns SP stucture.
816
817 @param[in] thd Thread handler
818 @param[in] defstr CREATE... string
819 @param[in] sql_mode SQL mode
820 @param[in] parent The owner package for package routines,
821 or NULL for standalone routines.
822 @param[in] creation_ctx Creation context of stored routines
823
824 @return Pointer on sp_head struct
825 @retval # Pointer on sp_head struct
826 @retval 0 error
827 */
828
sp_compile(THD * thd,String * defstr,sql_mode_t sql_mode,sp_package * parent,Stored_program_creation_ctx * creation_ctx)829 static sp_head *sp_compile(THD *thd, String *defstr, sql_mode_t sql_mode,
830 sp_package *parent,
831 Stored_program_creation_ctx *creation_ctx)
832 {
833 sp_head *sp;
834 sql_mode_t old_sql_mode= thd->variables.sql_mode;
835 ha_rows old_select_limit= thd->variables.select_limit;
836 sp_rcontext *old_spcont= thd->spcont;
837 Silence_deprecated_warning warning_handler;
838 Parser_state parser_state;
839
840 thd->variables.sql_mode= sql_mode;
841 thd->variables.select_limit= HA_POS_ERROR;
842
843 if (parser_state.init(thd, defstr->c_ptr_safe(), defstr->length()))
844 {
845 thd->variables.sql_mode= old_sql_mode;
846 thd->variables.select_limit= old_select_limit;
847 return NULL;
848 }
849
850 lex_start(thd);
851 thd->lex->sphead= parent;
852 thd->push_internal_handler(&warning_handler);
853 thd->spcont= 0;
854
855 if (parse_sql(thd, & parser_state, creation_ctx) || thd->lex == NULL)
856 {
857 sp= thd->lex->sphead;
858 sp_head::destroy(sp);
859 sp= 0;
860 }
861 else
862 {
863 sp= thd->lex->sphead;
864 }
865
866 thd->pop_internal_handler();
867 thd->spcont= old_spcont;
868 thd->variables.sql_mode= old_sql_mode;
869 thd->variables.select_limit= old_select_limit;
870 return sp;
871 }
872
873
874 class Bad_db_error_handler : public Internal_error_handler
875 {
876 public:
Bad_db_error_handler()877 Bad_db_error_handler()
878 :m_error_caught(false)
879 {}
880
881 virtual bool handle_condition(THD *thd,
882 uint sql_errno,
883 const char* sqlstate,
884 Sql_condition::enum_warning_level *level,
885 const char* message,
886 Sql_condition ** cond_hdl);
887
error_caught() const888 bool error_caught() const { return m_error_caught; }
889
890 private:
891 bool m_error_caught;
892 };
893
894 bool
handle_condition(THD * thd,uint sql_errno,const char * sqlstate,Sql_condition::enum_warning_level * level,const char * message,Sql_condition ** cond_hdl)895 Bad_db_error_handler::handle_condition(THD *thd,
896 uint sql_errno,
897 const char* sqlstate,
898 Sql_condition::enum_warning_level
899 *level,
900 const char* message,
901 Sql_condition ** cond_hdl)
902 {
903 if (sql_errno == ER_BAD_DB_ERROR)
904 {
905 m_error_caught= true;
906 return true;
907 }
908 return false;
909 }
910
911
912 int
db_load_routine(THD * thd,const Database_qualified_name * name,sp_head ** sphp,sql_mode_t sql_mode,const LEX_CSTRING & params,const LEX_CSTRING & returns,const LEX_CSTRING & body,const st_sp_chistics & chistics,const AUTHID & definer,longlong created,longlong modified,sp_package * parent,Stored_program_creation_ctx * creation_ctx) const913 Sp_handler::db_load_routine(THD *thd, const Database_qualified_name *name,
914 sp_head **sphp,
915 sql_mode_t sql_mode,
916 const LEX_CSTRING ¶ms,
917 const LEX_CSTRING &returns,
918 const LEX_CSTRING &body,
919 const st_sp_chistics &chistics,
920 const AUTHID &definer,
921 longlong created, longlong modified,
922 sp_package *parent,
923 Stored_program_creation_ctx *creation_ctx) const
924 {
925 LEX *old_lex= thd->lex, newlex;
926 String defstr;
927 char saved_cur_db_name_buf[SAFE_NAME_LEN+1];
928 LEX_STRING saved_cur_db_name=
929 { saved_cur_db_name_buf, sizeof(saved_cur_db_name_buf) };
930 bool cur_db_changed;
931 Bad_db_error_handler db_not_exists_handler;
932
933 int ret= 0;
934
935 thd->lex= &newlex;
936 newlex.current_select= NULL;
937
938 defstr.set_charset(creation_ctx->get_client_cs());
939
940 /*
941 We have to add DEFINER clause and provide proper routine characterstics in
942 routine definition statement that we build here to be able to use this
943 definition for SHOW CREATE PROCEDURE later.
944 */
945
946 if (show_create_sp(thd, &defstr,
947 null_clex_str, name->m_name,
948 params, returns, body,
949 chistics, definer, DDL_options(), sql_mode))
950 {
951 ret= SP_INTERNAL_ERROR;
952 goto end;
953 }
954
955 thd->push_internal_handler(&db_not_exists_handler);
956 /*
957 Change the current database (if needed).
958
959 TODO: why do we force switch here?
960 */
961
962 if (mysql_opt_change_db(thd, &name->m_db, &saved_cur_db_name, TRUE,
963 &cur_db_changed))
964 {
965 ret= SP_INTERNAL_ERROR;
966 thd->pop_internal_handler();
967 goto end;
968 }
969 thd->pop_internal_handler();
970 if (db_not_exists_handler.error_caught())
971 {
972 ret= SP_INTERNAL_ERROR;
973 my_error(ER_BAD_DB_ERROR, MYF(0), name->m_db.str);
974
975 goto end;
976 }
977
978 {
979 *sphp= sp_compile(thd, &defstr, sql_mode, parent, creation_ctx);
980 /*
981 Force switching back to the saved current database (if changed),
982 because it may be NULL. In this case, mysql_change_db() would
983 generate an error.
984 */
985
986 if (cur_db_changed && mysql_change_db(thd,
987 (LEX_CSTRING*) &saved_cur_db_name,
988 TRUE))
989 {
990 ret= SP_INTERNAL_ERROR;
991 goto end;
992 }
993
994 if (!*sphp)
995 {
996 ret= SP_PARSE_ERROR;
997 goto end;
998 }
999
1000 (*sphp)->set_definer(&definer.user, &definer.host);
1001 (*sphp)->set_info(created, modified, chistics, sql_mode);
1002 (*sphp)->set_creation_ctx(creation_ctx);
1003 (*sphp)->optimize();
1004
1005 if (type() == TYPE_ENUM_PACKAGE_BODY)
1006 {
1007 sp_package *package= (*sphp)->get_package();
1008 List_iterator<LEX> it(package->m_routine_implementations);
1009 for (LEX *lex; (lex= it++); )
1010 {
1011 DBUG_ASSERT(lex->sphead);
1012 lex->sphead->set_definer(&definer.user, &definer.host);
1013 lex->sphead->set_suid(package->suid());
1014 lex->sphead->m_sql_mode= sql_mode;
1015 lex->sphead->set_creation_ctx(creation_ctx);
1016 lex->sphead->optimize();
1017 }
1018 }
1019
1020 /*
1021 Not strictly necessary to invoke this method here, since we know
1022 that we've parsed CREATE PROCEDURE/FUNCTION and not an
1023 UPDATE/DELETE/INSERT/REPLACE/LOAD/CREATE TABLE, but we try to
1024 maintain the invariant that this method is called for each
1025 distinct statement, in case its logic is extended with other
1026 types of analyses in future.
1027 */
1028 newlex.set_trg_event_type_for_tables();
1029 }
1030
1031 end:
1032 thd->lex->sphead= NULL;
1033 lex_end(thd->lex);
1034 thd->lex= old_lex;
1035 return ret;
1036 }
1037
1038
1039 void
sp_returns_type(THD * thd,String & result,const sp_head * sp)1040 sp_returns_type(THD *thd, String &result, const sp_head *sp)
1041 {
1042 TABLE table;
1043 TABLE_SHARE share;
1044 Field *field;
1045 bzero((char*) &table, sizeof(table));
1046 bzero((char*) &share, sizeof(share));
1047 table.in_use= thd;
1048 table.s = &share;
1049 field= sp->create_result_field(0, 0, &table);
1050 field->sql_type(result);
1051
1052 if (field->has_charset())
1053 {
1054 result.append(STRING_WITH_LEN(" CHARSET "));
1055 result.append(field->charset()->csname);
1056 if (!(field->charset()->state & MY_CS_PRIMARY))
1057 {
1058 result.append(STRING_WITH_LEN(" COLLATE "));
1059 result.append(field->charset()->name);
1060 }
1061 }
1062
1063 delete field;
1064 }
1065
1066
1067 /**
1068 Delete the record for the stored routine object from mysql.proc,
1069 which is already opened, locked, and positioned to the record with the
1070 record to be deleted.
1071
1072 The operation deletes the record for the current record in "table"
1073 and invalidates the stored-routine cache.
1074
1075 @param thd Thread context.
1076 @param name Stored routine name.
1077 @param table A pointer to the opened mysql.proc table
1078
1079 @returns Error code.
1080 @return SP_OK on success, or SP_DELETE_ROW_FAILED on error.
1081 used to indicate about errors.
1082 */
1083
1084 int
sp_drop_routine_internal(THD * thd,const Database_qualified_name * name,TABLE * table) const1085 Sp_handler::sp_drop_routine_internal(THD *thd,
1086 const Database_qualified_name *name,
1087 TABLE *table) const
1088 {
1089 DBUG_ENTER("sp_drop_routine_internal");
1090
1091 if (table->file->ha_delete_row(table->record[0]))
1092 DBUG_RETURN(SP_DELETE_ROW_FAILED);
1093
1094 /* Make change permanent and avoid 'table is marked as crashed' errors */
1095 table->file->extra(HA_EXTRA_FLUSH);
1096
1097 sp_cache_invalidate();
1098 /*
1099 A lame workaround for lack of cache flush:
1100 make sure the routine is at least gone from the
1101 local cache.
1102 */
1103 sp_head *sp;
1104 sp_cache **spc= get_cache(thd);
1105 DBUG_ASSERT(spc);
1106 if ((sp= sp_cache_lookup(spc, name)))
1107 sp_cache_flush_obsolete(spc, &sp);
1108 DBUG_RETURN(SP_OK);
1109 }
1110
1111
1112 int
sp_find_and_drop_routine(THD * thd,TABLE * table,const Database_qualified_name * name) const1113 Sp_handler::sp_find_and_drop_routine(THD *thd, TABLE *table,
1114 const Database_qualified_name *name) const
1115 {
1116 int ret;
1117 if ((ret= db_find_routine_aux(thd, name, table)) != SP_OK)
1118 return ret;
1119 return sp_drop_routine_internal(thd, name, table);
1120 }
1121
1122
1123 int
1124 Sp_handler_package_spec::
sp_find_and_drop_routine(THD * thd,TABLE * table,const Database_qualified_name * name) const1125 sp_find_and_drop_routine(THD *thd, TABLE *table,
1126 const Database_qualified_name *name) const
1127 {
1128 int ret;
1129 if ((ret= db_find_routine_aux(thd, name, table)) != SP_OK)
1130 return ret;
1131 /*
1132 When we do "DROP PACKAGE pkg", we should also perform
1133 "DROP PACKAGE BODY pkg" automatically.
1134 */
1135 ret= sp_handler_package_body.sp_find_and_drop_routine(thd, table, name);
1136 if (ret != SP_KEY_NOT_FOUND && ret != SP_OK)
1137 {
1138 /*
1139 - SP_KEY_NOT_FOUND means that "CREATE PACKAGE pkg" did not
1140 have a correspoinding "CREATE PACKAGE BODY pkg" yet.
1141 - SP_OK means that "CREATE PACKAGE pkg" had a correspoinding
1142 "CREATE PACKAGE BODY pkg", which was successfully dropped.
1143 */
1144 return ret; // Other codes mean an unexpecte error
1145 }
1146 return Sp_handler::sp_find_and_drop_routine(thd, table, name);
1147 }
1148
1149
1150 /**
1151 Write stored-routine object into mysql.proc.
1152
1153 This operation stores attributes of the stored procedure/function into
1154 the mysql.proc.
1155
1156 @param thd Thread context.
1157 @param sp Stored routine object to store.
1158
1159 @note Opens and closes the thread tables. Therefore assumes
1160 that there are no locked tables in this thread at the time of
1161 invocation.
1162 Unlike some other DDL statements, *does* close the tables
1163 in the end, since the call to this function is normally
1164 followed by an implicit grant (sp_grant_privileges())
1165 and this subsequent call opens and closes mysql.procs_priv.
1166
1167 @return Error status.
1168 @retval FALSE on success
1169 @retval TRUE on error
1170 */
1171
1172 bool
sp_create_routine(THD * thd,const sp_head * sp) const1173 Sp_handler::sp_create_routine(THD *thd, const sp_head *sp) const
1174 {
1175 LEX *lex= thd->lex;
1176 bool ret= TRUE;
1177 TABLE *table;
1178 char definer_buf[USER_HOST_BUFF_SIZE];
1179 LEX_CSTRING definer;
1180 sql_mode_t saved_mode= thd->variables.sql_mode;
1181
1182 CHARSET_INFO *db_cs= get_default_db_collation(thd, sp->m_db.str);
1183
1184 bool store_failed= FALSE;
1185 DBUG_ENTER("sp_create_routine");
1186 DBUG_PRINT("enter", ("type: %s name: %.*s",
1187 type_str(),
1188 (int) sp->m_name.length,
1189 sp->m_name.str));
1190 MDL_key::enum_mdl_namespace mdl_type= get_mdl_type();
1191 LEX_CSTRING returns= empty_clex_str;
1192 String retstr(64);
1193 retstr.set_charset(system_charset_info);
1194
1195 /* Grab an exclusive MDL lock. */
1196 if (lock_object_name(thd, mdl_type, sp->m_db.str, sp->m_name.str))
1197 {
1198 my_error(ER_BAD_DB_ERROR, MYF(0), sp->m_db.str);
1199 DBUG_RETURN(TRUE);
1200 }
1201
1202 /*
1203 Check that a database directory with this name
1204 exists. Design note: This won't work on virtual databases
1205 like information_schema.
1206 */
1207 if (check_db_dir_existence(sp->m_db.str))
1208 {
1209 my_error(ER_BAD_DB_ERROR, MYF(0), sp->m_db.str);
1210 DBUG_RETURN(TRUE);
1211 }
1212
1213
1214 /* Reset sql_mode during data dictionary operations. */
1215 thd->variables.sql_mode= 0;
1216
1217 Check_level_instant_set check_level_save(thd, CHECK_FIELD_WARN);
1218
1219 if (!(table= open_proc_table_for_update(thd)))
1220 {
1221 my_error(ER_SP_STORE_FAILED, MYF(0), type_str(), sp->m_name.str);
1222 goto done;
1223 }
1224 else
1225 {
1226 /* Checking if the routine already exists */
1227 if (db_find_routine_aux(thd, sp, table) == SP_OK)
1228 {
1229 if (lex->create_info.or_replace())
1230 {
1231 switch (type()) {
1232 case TYPE_ENUM_PACKAGE:
1233 // Drop together with its PACKAGE BODY mysql.proc record
1234 if (sp_handler_package_spec.sp_find_and_drop_routine(thd, table, sp))
1235 goto done;
1236 break;
1237 case TYPE_ENUM_PACKAGE_BODY:
1238 case TYPE_ENUM_FUNCTION:
1239 case TYPE_ENUM_PROCEDURE:
1240 if (sp_drop_routine_internal(thd, sp, table))
1241 goto done;
1242 break;
1243 case TYPE_ENUM_TRIGGER:
1244 case TYPE_ENUM_PROXY:
1245 DBUG_ASSERT(0);
1246 ret= SP_OK;
1247 }
1248 }
1249 else if (lex->create_info.if_not_exists())
1250 {
1251 push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
1252 ER_SP_ALREADY_EXISTS,
1253 ER_THD(thd, ER_SP_ALREADY_EXISTS),
1254 type_str(), sp->m_name.str);
1255
1256 ret= FALSE;
1257
1258 // Setting retstr as it is used for logging.
1259 if (type() == TYPE_ENUM_FUNCTION)
1260 {
1261 sp_returns_type(thd, retstr, sp);
1262 returns= retstr.lex_cstring();
1263 }
1264 goto log;
1265 }
1266 else
1267 {
1268 my_error(ER_SP_ALREADY_EXISTS, MYF(0), type_str(), sp->m_name.str);
1269 goto done;
1270 }
1271 }
1272
1273 restore_record(table, s->default_values); // Get default values for fields
1274
1275 /* NOTE: all needed privilege checks have been already done. */
1276 thd->lex->definer->set_lex_string(&definer, definer_buf);
1277
1278 if (table->s->fields < MYSQL_PROC_FIELD_COUNT)
1279 {
1280 my_error(ER_SP_STORE_FAILED, MYF(0), type_str(), sp->m_name.str);
1281 goto done;
1282 }
1283
1284 if (system_charset_info->cset->numchars(system_charset_info,
1285 sp->m_name.str,
1286 sp->m_name.str+sp->m_name.length) >
1287 table->field[MYSQL_PROC_FIELD_NAME]->char_length())
1288 {
1289 my_error(ER_TOO_LONG_IDENT, MYF(0), sp->m_name.str);
1290 goto done;
1291 }
1292 if (sp->m_body.length > table->field[MYSQL_PROC_FIELD_BODY]->field_length)
1293 {
1294 my_error(ER_TOO_LONG_BODY, MYF(0), sp->m_name.str);
1295 goto done;
1296 }
1297
1298 store_failed=
1299 table->field[MYSQL_PROC_FIELD_DB]->
1300 store(sp->m_db, system_charset_info);
1301
1302 store_failed= store_failed ||
1303 table->field[MYSQL_PROC_FIELD_NAME]->
1304 store(sp->m_name, system_charset_info);
1305
1306 if (sp->agg_type() != DEFAULT_AGGREGATE)
1307 {
1308 store_failed= store_failed ||
1309 table->field[MYSQL_PROC_FIELD_AGGREGATE]->
1310 store((longlong)sp->agg_type(),TRUE);
1311 }
1312
1313 store_failed= store_failed ||
1314 table->field[MYSQL_PROC_MYSQL_TYPE]->
1315 store((longlong) type(), true);
1316
1317 store_failed= store_failed ||
1318 table->field[MYSQL_PROC_FIELD_SPECIFIC_NAME]->
1319 store(sp->m_name, system_charset_info);
1320
1321 if (sp->daccess() != SP_DEFAULT_ACCESS)
1322 {
1323 store_failed= store_failed ||
1324 table->field[MYSQL_PROC_FIELD_ACCESS]->
1325 store((longlong)sp->daccess(), TRUE);
1326 }
1327
1328 store_failed= store_failed ||
1329 table->field[MYSQL_PROC_FIELD_DETERMINISTIC]->
1330 store((longlong)(sp->detistic() ? 1 : 2), TRUE);
1331
1332 if (sp->suid() != SP_IS_DEFAULT_SUID)
1333 {
1334 store_failed= store_failed ||
1335 table->field[MYSQL_PROC_FIELD_SECURITY_TYPE]->
1336 store((longlong)sp->suid(), TRUE);
1337 }
1338
1339 store_failed= store_failed ||
1340 table->field[MYSQL_PROC_FIELD_PARAM_LIST]->
1341 store(sp->m_params, system_charset_info);
1342
1343 if (type() == TYPE_ENUM_FUNCTION)
1344 {
1345 sp_returns_type(thd, retstr, sp);
1346 returns= retstr.lex_cstring();
1347
1348 store_failed= store_failed ||
1349 table->field[MYSQL_PROC_FIELD_RETURNS]->
1350 store(retstr.ptr(), retstr.length(), system_charset_info);
1351 }
1352
1353 store_failed= store_failed ||
1354 table->field[MYSQL_PROC_FIELD_BODY]->
1355 store(sp->m_body, system_charset_info);
1356
1357 store_failed= store_failed ||
1358 table->field[MYSQL_PROC_FIELD_DEFINER]->
1359 store(definer, system_charset_info);
1360
1361 ((Field_timestamp *)table->field[MYSQL_PROC_FIELD_CREATED])->set_time();
1362 ((Field_timestamp *)table->field[MYSQL_PROC_FIELD_MODIFIED])->set_time();
1363
1364 store_failed= store_failed ||
1365 table->field[MYSQL_PROC_FIELD_SQL_MODE]->
1366 store((longlong)saved_mode, TRUE);
1367
1368 if (sp->comment().str)
1369 {
1370 store_failed= store_failed ||
1371 table->field[MYSQL_PROC_FIELD_COMMENT]->
1372 store(sp->comment(), system_charset_info);
1373 }
1374
1375 if (type() == TYPE_ENUM_FUNCTION &&
1376 !trust_function_creators && mysql_bin_log.is_open())
1377 {
1378 if (!sp->detistic())
1379 {
1380 /*
1381 Note that this test is not perfect; one could use
1382 a non-deterministic read-only function in an update statement.
1383 */
1384 enum enum_sp_data_access access=
1385 (sp->daccess() == SP_DEFAULT_ACCESS) ?
1386 SP_DEFAULT_ACCESS_MAPPING : sp->daccess();
1387 if (access == SP_CONTAINS_SQL ||
1388 access == SP_MODIFIES_SQL_DATA)
1389 {
1390 my_error(ER_BINLOG_UNSAFE_ROUTINE, MYF(0));
1391 goto done;
1392 }
1393 }
1394 if (!(thd->security_ctx->master_access & SUPER_ACL))
1395 {
1396 my_error(ER_BINLOG_CREATE_ROUTINE_NEED_SUPER,MYF(0));
1397 goto done;
1398 }
1399 }
1400
1401 table->field[MYSQL_PROC_FIELD_CHARACTER_SET_CLIENT]->set_notnull();
1402 store_failed= store_failed ||
1403 table->field[MYSQL_PROC_FIELD_CHARACTER_SET_CLIENT]->store(
1404 thd->charset()->csname,
1405 strlen(thd->charset()->csname),
1406 system_charset_info);
1407
1408 table->field[MYSQL_PROC_FIELD_COLLATION_CONNECTION]->set_notnull();
1409 store_failed= store_failed ||
1410 table->field[MYSQL_PROC_FIELD_COLLATION_CONNECTION]->store(
1411 thd->variables.collation_connection->name,
1412 strlen(thd->variables.collation_connection->name),
1413 system_charset_info);
1414
1415 table->field[MYSQL_PROC_FIELD_DB_COLLATION]->set_notnull();
1416 store_failed= store_failed ||
1417 table->field[MYSQL_PROC_FIELD_DB_COLLATION]->store(
1418 db_cs->name, strlen(db_cs->name), system_charset_info);
1419
1420 table->field[MYSQL_PROC_FIELD_BODY_UTF8]->set_notnull();
1421 store_failed= store_failed ||
1422 table->field[MYSQL_PROC_FIELD_BODY_UTF8]->store(
1423 sp->m_body_utf8, system_charset_info);
1424
1425 if (store_failed)
1426 {
1427 my_error(ER_CANT_CREATE_SROUTINE, MYF(0), sp->m_name.str);
1428 goto done;
1429 }
1430
1431 if (table->file->ha_write_row(table->record[0]))
1432 {
1433 my_error(ER_SP_ALREADY_EXISTS, MYF(0), type_str(), sp->m_name.str);
1434 goto done;
1435 }
1436 /* Make change permanent and avoid 'table is marked as crashed' errors */
1437 table->file->extra(HA_EXTRA_FLUSH);
1438
1439 sp_cache_invalidate();
1440 }
1441
1442 log:
1443 if (mysql_bin_log.is_open())
1444 {
1445 thd->clear_error();
1446
1447 StringBuffer<128> log_query(thd->variables.character_set_client);
1448 DBUG_ASSERT(log_query.charset()->mbminlen == 1);
1449
1450 if (show_create_sp(thd, &log_query,
1451 sp->m_explicit_name ? sp->m_db : null_clex_str,
1452 sp->m_name,
1453 sp->m_params, returns, sp->m_body,
1454 sp->chistics(),
1455 thd->lex->definer[0],
1456 thd->lex->create_info,
1457 saved_mode))
1458 {
1459 my_error(ER_OUT_OF_RESOURCES, MYF(0));
1460 goto done;
1461 }
1462 /* restore sql_mode when binloging */
1463 thd->variables.sql_mode= saved_mode;
1464 /* Such a statement can always go directly to binlog, no trans cache */
1465 if (thd->binlog_query(THD::STMT_QUERY_TYPE,
1466 log_query.ptr(), log_query.length(),
1467 FALSE, FALSE, FALSE, 0) > 0)
1468 {
1469 my_error(ER_ERROR_ON_WRITE, MYF(0), "binary log", -1);
1470 goto done;
1471 }
1472 thd->variables.sql_mode= 0;
1473 }
1474 ret= FALSE;
1475
1476 done:
1477 thd->variables.sql_mode= saved_mode;
1478 DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row());
1479 DBUG_RETURN(ret);
1480 }
1481
1482
1483 static bool
append_suid(String * buf,enum_sp_suid_behaviour suid)1484 append_suid(String *buf, enum_sp_suid_behaviour suid)
1485 {
1486 return suid == SP_IS_NOT_SUID &&
1487 buf->append(STRING_WITH_LEN(" SQL SECURITY INVOKER\n"));
1488 }
1489
1490
1491 static bool
append_comment(String * buf,const LEX_CSTRING & comment)1492 append_comment(String *buf, const LEX_CSTRING &comment)
1493 {
1494 if (!comment.length)
1495 return false;
1496 if (buf->append(STRING_WITH_LEN(" COMMENT ")))
1497 return true;
1498 append_unescaped(buf, comment.str, comment.length);
1499 return buf->append('\n');
1500 }
1501
1502
1503 static bool
append_package_chistics(String * buf,const st_sp_chistics & chistics)1504 append_package_chistics(String *buf, const st_sp_chistics &chistics)
1505 {
1506 return append_suid(buf, chistics.suid) ||
1507 append_comment(buf, chistics.comment);
1508 }
1509
1510
1511 bool
show_create_sp(THD * thd,String * buf,const LEX_CSTRING & db,const LEX_CSTRING & name,const LEX_CSTRING & params,const LEX_CSTRING & returns,const LEX_CSTRING & body,const st_sp_chistics & chistics,const AUTHID & definer,const DDL_options_st ddl_options,sql_mode_t sql_mode) const1512 Sp_handler_package::show_create_sp(THD *thd, String *buf,
1513 const LEX_CSTRING &db,
1514 const LEX_CSTRING &name,
1515 const LEX_CSTRING ¶ms,
1516 const LEX_CSTRING &returns,
1517 const LEX_CSTRING &body,
1518 const st_sp_chistics &chistics,
1519 const AUTHID &definer,
1520 const DDL_options_st ddl_options,
1521 sql_mode_t sql_mode) const
1522 {
1523 sql_mode_t old_sql_mode= thd->variables.sql_mode;
1524 thd->variables.sql_mode= sql_mode;
1525 bool rc=
1526 buf->append(STRING_WITH_LEN("CREATE ")) ||
1527 (ddl_options.or_replace() &&
1528 buf->append(STRING_WITH_LEN("OR REPLACE "))) ||
1529 append_definer(thd, buf, &definer.user, &definer.host) ||
1530 buf->append(type_lex_cstring()) ||
1531 buf->append(" ", 1) ||
1532 (ddl_options.if_not_exists() &&
1533 buf->append(STRING_WITH_LEN("IF NOT EXISTS "))) ||
1534 (db.length > 0 &&
1535 (append_identifier(thd, buf, db.str, db.length) ||
1536 buf->append('.'))) ||
1537 append_identifier(thd, buf, name.str, name.length) ||
1538 append_package_chistics(buf, chistics) ||
1539 buf->append(" ", 1) ||
1540 buf->append(body.str, body.length);
1541 thd->variables.sql_mode= old_sql_mode;
1542 return rc;
1543 }
1544
1545
1546 /**
1547 Delete the record for the stored routine object from mysql.proc
1548 and do binary logging.
1549
1550 The operation deletes the record for the stored routine specified by name
1551 from the mysql.proc table and invalidates the stored-routine cache.
1552
1553 @param thd Thread context.
1554 @param name Stored routine name.
1555
1556 @return Error code. SP_OK is returned on success. Other SP_ constants are
1557 used to indicate about errors.
1558 */
1559
1560 int
sp_drop_routine(THD * thd,const Database_qualified_name * name) const1561 Sp_handler::sp_drop_routine(THD *thd,
1562 const Database_qualified_name *name) const
1563 {
1564 TABLE *table;
1565 int ret;
1566 DBUG_ENTER("sp_drop_routine");
1567 DBUG_PRINT("enter", ("type: %s name: %.*s",
1568 type_str(),
1569 (int) name->m_name.length, name->m_name.str));
1570 MDL_key::enum_mdl_namespace mdl_type= get_mdl_type();
1571
1572 /* Grab an exclusive MDL lock. */
1573 if (lock_object_name(thd, mdl_type, name->m_db.str, name->m_name.str))
1574 DBUG_RETURN(SP_DELETE_ROW_FAILED);
1575
1576 if (!(table= open_proc_table_for_update(thd)))
1577 DBUG_RETURN(SP_OPEN_TABLE_FAILED);
1578
1579 if ((ret= sp_find_and_drop_routine(thd, table, name)) == SP_OK &&
1580 write_bin_log(thd, TRUE, thd->query(), thd->query_length()))
1581 ret= SP_INTERNAL_ERROR;
1582 /*
1583 This statement will be replicated as a statement, even when using
1584 row-based replication. The flag will be reset at the end of the
1585 statement.
1586 */
1587 DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row());
1588 DBUG_RETURN(ret);
1589 }
1590
1591
1592 /**
1593 Find and updated the record for the stored routine object in mysql.proc.
1594
1595 The operation finds the record for the stored routine specified by name
1596 in the mysql.proc table and updates it with new attributes. After
1597 successful update, the cache is invalidated.
1598
1599 @param thd Thread context.
1600 @param name Stored routine name.
1601 @param chistics New values of stored routine attributes to write.
1602
1603 @return Error code. SP_OK is returned on success. Other SP_ constants are
1604 used to indicate about errors.
1605 */
1606
1607 int
sp_update_routine(THD * thd,const Database_qualified_name * name,const st_sp_chistics * chistics) const1608 Sp_handler::sp_update_routine(THD *thd, const Database_qualified_name *name,
1609 const st_sp_chistics *chistics) const
1610 {
1611 TABLE *table;
1612 int ret;
1613 DBUG_ENTER("sp_update_routine");
1614 DBUG_PRINT("enter", ("type: %s name: %.*s",
1615 type_str(),
1616 (int) name->m_name.length, name->m_name.str));
1617 MDL_key::enum_mdl_namespace mdl_type= get_mdl_type();
1618
1619 /* Grab an exclusive MDL lock. */
1620 if (lock_object_name(thd, mdl_type, name->m_db.str, name->m_name.str))
1621 DBUG_RETURN(SP_OPEN_TABLE_FAILED);
1622
1623 if (!(table= open_proc_table_for_update(thd)))
1624 DBUG_RETURN(SP_OPEN_TABLE_FAILED);
1625
1626 if ((ret= db_find_routine_aux(thd, name, table)) == SP_OK)
1627 {
1628 if (type() == TYPE_ENUM_FUNCTION && ! trust_function_creators &&
1629 mysql_bin_log.is_open() &&
1630 (chistics->daccess == SP_CONTAINS_SQL ||
1631 chistics->daccess == SP_MODIFIES_SQL_DATA))
1632 {
1633 char *ptr;
1634 bool is_deterministic;
1635 ptr= get_field(thd->mem_root,
1636 table->field[MYSQL_PROC_FIELD_DETERMINISTIC]);
1637 if (ptr == NULL)
1638 {
1639 ret= SP_INTERNAL_ERROR;
1640 goto err;
1641 }
1642 is_deterministic= ptr[0] == 'N' ? FALSE : TRUE;
1643 if (!is_deterministic)
1644 {
1645 my_message(ER_BINLOG_UNSAFE_ROUTINE,
1646 ER_THD(thd, ER_BINLOG_UNSAFE_ROUTINE), MYF(0));
1647 ret= SP_INTERNAL_ERROR;
1648 goto err;
1649 }
1650 }
1651
1652 store_record(table,record[1]);
1653 ((Field_timestamp *)table->field[MYSQL_PROC_FIELD_MODIFIED])->set_time();
1654 if (chistics->suid != SP_IS_DEFAULT_SUID)
1655 table->field[MYSQL_PROC_FIELD_SECURITY_TYPE]->
1656 store((longlong)chistics->suid, TRUE);
1657 if (chistics->daccess != SP_DEFAULT_ACCESS)
1658 table->field[MYSQL_PROC_FIELD_ACCESS]->
1659 store((longlong)chistics->daccess, TRUE);
1660 if (chistics->comment.str)
1661 table->field[MYSQL_PROC_FIELD_COMMENT]->store(chistics->comment,
1662 system_charset_info);
1663 if (chistics->agg_type != DEFAULT_AGGREGATE)
1664 table->field[MYSQL_PROC_FIELD_AGGREGATE]->
1665 store((longlong)chistics->agg_type, TRUE);
1666 if ((ret= table->file->ha_update_row(table->record[1],table->record[0])) &&
1667 ret != HA_ERR_RECORD_IS_THE_SAME)
1668 ret= SP_WRITE_ROW_FAILED;
1669 else
1670 ret= 0;
1671 /* Make change permanent and avoid 'table is marked as crashed' errors */
1672 table->file->extra(HA_EXTRA_FLUSH);
1673 }
1674
1675 if (ret == SP_OK)
1676 {
1677 if (write_bin_log(thd, TRUE, thd->query(), thd->query_length()))
1678 ret= SP_INTERNAL_ERROR;
1679 sp_cache_invalidate();
1680 }
1681 err:
1682 DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row());
1683 DBUG_RETURN(ret);
1684 }
1685
1686
1687 /**
1688 This internal handler is used to trap errors from opening mysql.proc.
1689 */
1690
1691 class Lock_db_routines_error_handler : public Internal_error_handler
1692 {
1693 public:
handle_condition(THD * thd,uint sql_errno,const char * sqlstate,Sql_condition::enum_warning_level * level,const char * msg,Sql_condition ** cond_hdl)1694 bool handle_condition(THD *thd,
1695 uint sql_errno,
1696 const char* sqlstate,
1697 Sql_condition::enum_warning_level *level,
1698 const char* msg,
1699 Sql_condition ** cond_hdl)
1700 {
1701 if (sql_errno == ER_NO_SUCH_TABLE ||
1702 sql_errno == ER_NO_SUCH_TABLE_IN_ENGINE ||
1703 sql_errno == ER_CANNOT_LOAD_FROM_TABLE_V2 ||
1704 sql_errno == ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE ||
1705 sql_errno == ER_COL_COUNT_DOESNT_MATCH_CORRUPTED_V2)
1706 return true;
1707 return false;
1708 }
1709 };
1710
1711
1712 /**
1713 Acquires exclusive metadata lock on all stored routines in the
1714 given database.
1715
1716 @note Will also return false (=success) if mysql.proc can't be opened
1717 or is outdated. This allows DROP DATABASE to continue in these
1718 cases.
1719 */
1720
lock_db_routines(THD * thd,const char * db)1721 bool lock_db_routines(THD *thd, const char *db)
1722 {
1723 TABLE *table;
1724 uint key_len;
1725 Open_tables_backup open_tables_state_backup;
1726 MDL_request_list mdl_requests;
1727 Lock_db_routines_error_handler err_handler;
1728 uchar keybuf[MAX_KEY_LENGTH];
1729 DBUG_ENTER("lock_db_routines");
1730
1731 DBUG_SLOW_ASSERT(ok_for_lower_case_names(db));
1732
1733 /*
1734 mysql.proc will be re-opened during deletion, so we can ignore
1735 errors when opening the table here. The error handler is
1736 used to avoid getting the same warning twice.
1737 */
1738 thd->push_internal_handler(&err_handler);
1739 table= open_proc_table_for_read(thd, &open_tables_state_backup);
1740 thd->pop_internal_handler();
1741 if (!table)
1742 {
1743 /*
1744 DROP DATABASE should not fail even if mysql.proc does not exist
1745 or is outdated. We therefore only abort mysql_rm_db() if we
1746 have errors not handled by the error handler.
1747 */
1748 DBUG_RETURN(thd->is_error() || thd->killed);
1749 }
1750
1751 table->field[MYSQL_PROC_FIELD_DB]->store(db, strlen(db), system_charset_info);
1752 key_len= table->key_info->key_part[0].store_length;
1753 table->field[MYSQL_PROC_FIELD_DB]->get_key_image(keybuf, key_len, Field::itRAW);
1754 int nxtres= table->file->ha_index_init(0, 1);
1755 if (nxtres)
1756 {
1757 table->file->print_error(nxtres, MYF(0));
1758 close_system_tables(thd, &open_tables_state_backup);
1759 DBUG_RETURN(true);
1760 }
1761
1762 if (! table->file->ha_index_read_map(table->record[0], keybuf, (key_part_map)1,
1763 HA_READ_KEY_EXACT))
1764 {
1765 do
1766 {
1767 char *sp_name= get_field(thd->mem_root,
1768 table->field[MYSQL_PROC_FIELD_NAME]);
1769 if (sp_name == NULL) // skip invalid sp names (hand-edited mysql.proc?)
1770 continue;
1771
1772 longlong sp_type= table->field[MYSQL_PROC_MYSQL_TYPE]->val_int();
1773 MDL_request *mdl_request= new (thd->mem_root) MDL_request;
1774 const Sp_handler *sph= Sp_handler::handler((stored_procedure_type)
1775 sp_type);
1776 if (!sph)
1777 sph= &sp_handler_procedure;
1778 mdl_request->init(sph->get_mdl_type(), db, sp_name,
1779 MDL_EXCLUSIVE, MDL_TRANSACTION);
1780 mdl_requests.push_front(mdl_request);
1781 } while (! (nxtres= table->file->ha_index_next_same(table->record[0], keybuf, key_len)));
1782 }
1783 table->file->ha_index_end();
1784 if (nxtres != 0 && nxtres != HA_ERR_END_OF_FILE)
1785 {
1786 table->file->print_error(nxtres, MYF(0));
1787 close_system_tables(thd, &open_tables_state_backup);
1788 DBUG_RETURN(true);
1789 }
1790 close_system_tables(thd, &open_tables_state_backup);
1791
1792 /* We should already hold a global IX lock and a schema X lock. */
1793 DBUG_ASSERT(thd->mdl_context.is_lock_owner(MDL_key::BACKUP, "", "",
1794 MDL_BACKUP_DDL) &&
1795 thd->mdl_context.is_lock_owner(MDL_key::SCHEMA, db, "",
1796 MDL_EXCLUSIVE));
1797 DBUG_RETURN(thd->mdl_context.acquire_locks(&mdl_requests,
1798 thd->variables.lock_wait_timeout));
1799 }
1800
1801
1802 /**
1803 Drop all routines in database 'db'
1804
1805 @note Close the thread tables, the calling code might want to
1806 delete from other system tables afterwards.
1807 */
1808
1809 int
sp_drop_db_routines(THD * thd,const char * db)1810 sp_drop_db_routines(THD *thd, const char *db)
1811 {
1812 TABLE *table;
1813 int ret;
1814 uint key_len;
1815 MDL_savepoint mdl_savepoint= thd->mdl_context.mdl_savepoint();
1816 uchar keybuf[MAX_KEY_LENGTH];
1817 DBUG_ENTER("sp_drop_db_routines");
1818 DBUG_PRINT("enter", ("db: %s", db));
1819
1820 ret= SP_OPEN_TABLE_FAILED;
1821 if (!(table= open_proc_table_for_update(thd)))
1822 goto err;
1823
1824 table->field[MYSQL_PROC_FIELD_DB]->store(db, strlen(db), system_charset_info);
1825 key_len= table->key_info->key_part[0].store_length;
1826 table->field[MYSQL_PROC_FIELD_DB]->get_key_image(keybuf, key_len, Field::itRAW);
1827
1828 ret= SP_OK;
1829 if (table->file->ha_index_init(0, 1))
1830 {
1831 ret= SP_KEY_NOT_FOUND;
1832 goto err_idx_init;
1833 }
1834 if (!table->file->ha_index_read_map(table->record[0], keybuf, (key_part_map)1,
1835 HA_READ_KEY_EXACT))
1836 {
1837 int nxtres;
1838 bool deleted= FALSE;
1839
1840 do
1841 {
1842 if (! table->file->ha_delete_row(table->record[0]))
1843 deleted= TRUE; /* We deleted something */
1844 else
1845 {
1846 ret= SP_DELETE_ROW_FAILED;
1847 nxtres= 0;
1848 break;
1849 }
1850 } while (!(nxtres= table->file->ha_index_next_same(table->record[0],
1851 keybuf, key_len)));
1852 if (nxtres != HA_ERR_END_OF_FILE)
1853 ret= SP_KEY_NOT_FOUND;
1854 if (deleted)
1855 {
1856 sp_cache_invalidate();
1857 /* Make change permanent and avoid 'table is marked as crashed' errors */
1858 table->file->extra(HA_EXTRA_FLUSH);
1859 }
1860 }
1861 table->file->ha_index_end();
1862
1863 err_idx_init:
1864 close_thread_tables(thd);
1865 /*
1866 Make sure to only release the MDL lock on mysql.proc, not other
1867 metadata locks DROP DATABASE might have acquired.
1868 */
1869 thd->mdl_context.rollback_to_savepoint(mdl_savepoint);
1870
1871 err:
1872 DBUG_RETURN(ret);
1873 }
1874
1875
1876 /**
1877 Implement SHOW CREATE statement for stored routines.
1878
1879 The operation finds the stored routine object specified by name and then
1880 calls sp_head::show_create_routine() for the object.
1881
1882 @param thd Thread context.
1883 @param name Stored routine name.
1884
1885 @return Error status.
1886 @retval FALSE on success
1887 @retval TRUE on error
1888 */
1889
1890 bool
sp_show_create_routine(THD * thd,const Database_qualified_name * name) const1891 Sp_handler::sp_show_create_routine(THD *thd,
1892 const Database_qualified_name *name) const
1893 {
1894 DBUG_ENTER("sp_show_create_routine");
1895 DBUG_PRINT("enter", ("type: %s name: %.*s",
1896 type_str(),
1897 (int) name->m_name.length,
1898 name->m_name.str));
1899 /*
1900 @todo: Consider using prelocking for this code as well. Currently
1901 SHOW CREATE PROCEDURE/FUNCTION is a dirty read of the data
1902 dictionary, i.e. takes no metadata locks.
1903 It is "safe" to do as long as it doesn't affect the results
1904 of the binary log or the query cache, which currently it does not.
1905 */
1906 sp_head *sp= 0;
1907
1908 DBUG_EXECUTE_IF("cache_sp_in_show_create",
1909 /* Some tests need just need a way to cache SP without other side-effects.*/
1910 sp_cache_routine(thd, name, false, &sp);
1911 sp->show_create_routine(thd, this);
1912 DBUG_RETURN(false);
1913 );
1914
1915 bool free_sp= db_find_routine(thd, name, &sp) == SP_OK;
1916 bool ret= !sp || sp->show_create_routine(thd, this);
1917 if (ret)
1918 {
1919 /*
1920 If we have insufficient privileges, pretend the routine
1921 does not exist.
1922 */
1923 my_error(ER_SP_DOES_NOT_EXIST, MYF(0), type_str(), name->m_name.str);
1924 }
1925 if (free_sp)
1926 sp_head::destroy(sp);
1927 DBUG_RETURN(ret);
1928 }
1929
1930
1931 /*
1932 A helper class to split package name from a dot-qualified name
1933 and return it as a 0-terminated string
1934 'pkg.name' -> 'pkg\0'
1935 */
1936
1937 class Prefix_name_buf: public LEX_CSTRING
1938 {
1939 char m_buf[SAFE_NAME_LEN + 1];
1940 public:
Prefix_name_buf(const THD * thd,const LEX_CSTRING & name)1941 Prefix_name_buf(const THD *thd, const LEX_CSTRING &name)
1942 {
1943 const char *end;
1944 if (!(end= strrchr(name.str, '.')))
1945 {
1946 static_cast<LEX_CSTRING*>(this)[0]= null_clex_str;
1947 }
1948 else
1949 {
1950 str= m_buf;
1951 length= end - name.str;
1952 set_if_smaller(length, sizeof(m_buf) - 1);
1953 memcpy(m_buf, name.str, length);
1954 m_buf[length]= '\0';
1955 }
1956 }
1957 };
1958
1959
1960 /*
1961 In case of recursions, we create multiple copies of the same SP.
1962 This methods checks the current recursion depth.
1963 In case if the recursion limit exceeded, it throws an error
1964 and returns NULL.
1965 Otherwise, depending on the current recursion level, it:
1966 - either returns the original SP,
1967 - or makes and returns a new clone of SP
1968 */
1969
1970 sp_head *
sp_clone_and_link_routine(THD * thd,const Database_qualified_name * name,sp_head * sp) const1971 Sp_handler::sp_clone_and_link_routine(THD *thd,
1972 const Database_qualified_name *name,
1973 sp_head *sp) const
1974 {
1975 DBUG_ENTER("sp_link_routine");
1976 int rc;
1977 ulong level;
1978 sp_head *new_sp;
1979 LEX_CSTRING returns= empty_clex_str;
1980 Database_qualified_name lname(name->m_db, name->m_name);
1981 #ifndef DBUG_OFF
1982 uint parent_subroutine_count=
1983 !sp->m_parent ? 0 :
1984 sp->m_parent->m_routine_declarations.elements +
1985 sp->m_parent->m_routine_implementations.elements;
1986 #endif
1987
1988 /*
1989 String buffer for RETURNS data type must have system charset;
1990 64 -- size of "returns" column of mysql.proc.
1991 */
1992 String retstr(64);
1993 retstr.set_charset(sp->get_creation_ctx()->get_client_cs());
1994
1995 DBUG_PRINT("info", ("found: %p", sp));
1996 if (sp->m_first_free_instance)
1997 {
1998 DBUG_PRINT("info", ("first free: %p level: %lu flags %x",
1999 sp->m_first_free_instance,
2000 sp->m_first_free_instance->m_recursion_level,
2001 sp->m_first_free_instance->m_flags));
2002 DBUG_ASSERT(!(sp->m_first_free_instance->m_flags & sp_head::IS_INVOKED));
2003 if (sp->m_first_free_instance->m_recursion_level > recursion_depth(thd))
2004 {
2005 recursion_level_error(thd, sp);
2006 DBUG_RETURN(0);
2007 }
2008 DBUG_RETURN(sp->m_first_free_instance);
2009 }
2010 /*
2011 Actually depth could be +1 than the actual value in case a SP calls
2012 SHOW CREATE PROCEDURE. Hence, the linked list could hold up to one more
2013 instance.
2014 */
2015
2016 level= sp->m_last_cached_sp->m_recursion_level + 1;
2017 if (level > recursion_depth(thd))
2018 {
2019 recursion_level_error(thd, sp);
2020 DBUG_RETURN(0);
2021 }
2022
2023 if (type() == TYPE_ENUM_FUNCTION)
2024 {
2025 sp_returns_type(thd, retstr, sp);
2026 returns= retstr.lex_cstring();
2027 }
2028
2029 if (sp->m_parent)
2030 {
2031 /*
2032 If we're cloning a recursively called package routine,
2033 we need to take some special measures:
2034 1. Cut the package name prefix from the routine name: 'pkg1.p1' -> 'p1',
2035 to have db_load_routine() generate and parse a query like this:
2036 CREATE PROCEDURE p1 ...;
2037 rather than:
2038 CREATE PROCEDURE pkg1.p1 ...;
2039 The latter would be misinterpreted by the parser as a standalone
2040 routine 'p1' in the database 'pkg1', which is not what we need.
2041 2. We pass m_parent to db_load_routine() to have it set
2042 thd->lex->sphead to sp->m_parent before calling parse_sql().
2043 These two measures allow to parse a package subroutine using
2044 the grammar for standalone routines, e.g.:
2045 CREATE PROCEDURE p1 ... END;
2046 instead of going through a more complex query, e.g.:
2047 CREATE PACKAGE BODY pkg1 AS
2048 PROCEDURE p1 ... END;
2049 END;
2050 */
2051 size_t prefix_length= sp->m_parent->m_name.length + 1;
2052 DBUG_ASSERT(prefix_length < lname.m_name.length);
2053 DBUG_ASSERT(lname.m_name.str[sp->m_parent->m_name.length] == '.');
2054 lname.m_name.str+= prefix_length;
2055 lname.m_name.length-= prefix_length;
2056 sp->m_parent->m_is_cloning_routine= true;
2057 }
2058
2059
2060 rc= db_load_routine(thd, &lname, &new_sp,
2061 sp->m_sql_mode, sp->m_params, returns,
2062 sp->m_body, sp->chistics(),
2063 sp->m_definer,
2064 sp->m_created, sp->m_modified,
2065 sp->m_parent,
2066 sp->get_creation_ctx());
2067 if (sp->m_parent)
2068 sp->m_parent->m_is_cloning_routine= false;
2069
2070 if (rc == SP_OK)
2071 {
2072 #ifndef DBUG_OFF
2073 /*
2074 We've just called the parser to clone the routine.
2075 In case of a package routine, make sure that the parser
2076 has not added any new subroutines directly to the parent package.
2077 The cloned subroutine instances get linked below to the first instance,
2078 they must have no direct links from the parent package.
2079 */
2080 DBUG_ASSERT(!sp->m_parent ||
2081 parent_subroutine_count ==
2082 sp->m_parent->m_routine_declarations.elements +
2083 sp->m_parent->m_routine_implementations.elements);
2084 #endif
2085 sp->m_last_cached_sp->m_next_cached_sp= new_sp;
2086 new_sp->m_recursion_level= level;
2087 new_sp->m_first_instance= sp;
2088 sp->m_last_cached_sp= sp->m_first_free_instance= new_sp;
2089 DBUG_PRINT("info", ("added level: %p, level: %lu, flags %x",
2090 new_sp, new_sp->m_recursion_level,
2091 new_sp->m_flags));
2092 DBUG_RETURN(new_sp);
2093 }
2094 DBUG_RETURN(0);
2095 }
2096
2097
2098 /**
2099 Obtain object representing stored procedure/function by its name from
2100 stored procedures cache and looking into mysql.proc if needed.
2101
2102 @param thd thread context
2103 @param name name of procedure
2104 @param cp hash to look routine in
2105 @param cache_only if true perform cache-only lookup
2106 (Don't look in mysql.proc).
2107
2108 @retval
2109 NonNULL pointer to sp_head object for the procedure
2110 @retval
2111 NULL in case of error.
2112 */
2113
2114 sp_head *
sp_find_routine(THD * thd,const Database_qualified_name * name,bool cache_only) const2115 Sp_handler::sp_find_routine(THD *thd, const Database_qualified_name *name,
2116 bool cache_only) const
2117 {
2118 DBUG_ENTER("Sp_handler::sp_find_routine");
2119 DBUG_PRINT("enter", ("name: %.*s.%.*s type: %s cache only %d",
2120 (int) name->m_db.length, name->m_db.str,
2121 (int) name->m_name.length, name->m_name.str,
2122 type_str(), cache_only));
2123 sp_cache **cp= get_cache(thd);
2124 sp_head *sp;
2125
2126 if ((sp= sp_cache_lookup(cp, name)))
2127 DBUG_RETURN(sp_clone_and_link_routine(thd, name, sp));
2128 if (!cache_only)
2129 db_find_and_cache_routine(thd, name, &sp);
2130 DBUG_RETURN(sp);
2131 }
2132
2133
2134 /**
2135 Find a package routine.
2136 See sp_cache_routine() for more information on parameters and return value.
2137
2138 @param thd - current THD
2139 @param pkgname_str - package name
2140 @param name - a mixed qualified name, with:
2141 * name->m_db set to the database, e.g. "dbname"
2142 * name->m_name set to a package-qualified name,
2143 e.g. "pkgname.spname".
2144 @param cache_only - don't load mysql.proc if not cached
2145 @retval non-NULL - a pointer to an sp_head object
2146 @retval NULL - an error happened.
2147 */
2148
2149 sp_head *
sp_find_package_routine(THD * thd,const LEX_CSTRING pkgname_str,const Database_qualified_name * name,bool cache_only) const2150 Sp_handler::sp_find_package_routine(THD *thd,
2151 const LEX_CSTRING pkgname_str,
2152 const Database_qualified_name *name,
2153 bool cache_only) const
2154 {
2155 DBUG_ENTER("sp_find_package_routine");
2156 Database_qualified_name pkgname(&name->m_db, &pkgname_str);
2157 sp_head *ph= sp_cache_lookup(&thd->sp_package_body_cache, &pkgname);
2158 if (!ph && !cache_only)
2159 sp_handler_package_body.db_find_and_cache_routine(thd, &pkgname, &ph);
2160 if (ph)
2161 {
2162 LEX_CSTRING tmp= name->m_name;
2163 const char *dot= strrchr(tmp.str, '.');
2164 size_t prefix_length= dot ? dot - tmp.str + 1 : 0;
2165 sp_package *pkg= ph->get_package();
2166 tmp.str+= prefix_length;
2167 tmp.length-= prefix_length;
2168 LEX *plex= pkg ? pkg->m_routine_implementations.find(tmp, type()) : NULL;
2169 sp_head *sp= plex ? plex->sphead : NULL;
2170 if (sp)
2171 DBUG_RETURN(sp_clone_and_link_routine(thd, name, sp));
2172 }
2173 DBUG_RETURN(NULL);
2174 }
2175
2176
2177 /**
2178 Find a package routine.
2179 See sp_cache_routine() for more information on parameters and return value.
2180
2181 @param thd - current THD
2182 @param name - Qualified name with the following format:
2183 * name->m_db is set to the database name, e.g. "dbname"
2184 * name->m_name is set to a package-qualified name,
2185 e.g. "pkgname.spname", as a single string with a
2186 dot character as a separator.
2187 @param cache_only - don't load mysql.proc if not cached
2188 @retval non-NULL - a pointer to an sp_head object
2189 @retval NULL - an error happened
2190 */
2191
2192 sp_head *
sp_find_package_routine(THD * thd,const Database_qualified_name * name,bool cache_only) const2193 Sp_handler::sp_find_package_routine(THD *thd,
2194 const Database_qualified_name *name,
2195 bool cache_only) const
2196 {
2197 DBUG_ENTER("Sp_handler::sp_find_package_routine");
2198 Prefix_name_buf pkgname(thd, name->m_name);
2199 DBUG_ASSERT(pkgname.length);
2200 DBUG_RETURN(sp_find_package_routine(thd, pkgname, name, cache_only));
2201 }
2202
2203
2204 /**
2205 This is used by sql_acl.cc:mysql_routine_grant() and is used to find
2206 the routines in 'routines'.
2207
2208 @param thd Thread handler
2209 @param routines List of needles in the hay stack
2210
2211 @return
2212 @retval FALSE Found.
2213 @retval TRUE Not found
2214 */
2215
2216 bool
sp_exist_routines(THD * thd,TABLE_LIST * routines) const2217 Sp_handler::sp_exist_routines(THD *thd, TABLE_LIST *routines) const
2218 {
2219 TABLE_LIST *routine;
2220 bool sp_object_found;
2221 DBUG_ENTER("sp_exists_routine");
2222 for (routine= routines; routine; routine= routine->next_global)
2223 {
2224 sp_name *name;
2225 LEX_CSTRING lex_db;
2226 LEX_CSTRING lex_name;
2227 thd->make_lex_string(&lex_db, routine->db.str, routine->db.length);
2228 thd->make_lex_string(&lex_name, routine->table_name.str,
2229 routine->table_name.length);
2230 name= new sp_name(&lex_db, &lex_name, true);
2231 sp_object_found= sp_find_routine(thd, name, false) != NULL;
2232 thd->get_stmt_da()->clear_warning_info(thd->query_id);
2233 if (! sp_object_found)
2234 {
2235 my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION or PROCEDURE",
2236 routine->table_name.str);
2237 DBUG_RETURN(TRUE);
2238 }
2239 }
2240 DBUG_RETURN(FALSE);
2241 }
2242
2243
sp_sroutine_key(const uchar * ptr,size_t * plen,my_bool first)2244 extern "C" uchar* sp_sroutine_key(const uchar *ptr, size_t *plen,
2245 my_bool first)
2246 {
2247 Sroutine_hash_entry *rn= (Sroutine_hash_entry *)ptr;
2248 *plen= rn->mdl_request.key.length();
2249 return (uchar *)rn->mdl_request.key.ptr();
2250 }
2251
2252
2253 /**
2254 Auxilary function that adds new element to the set of stored routines
2255 used by statement.
2256
2257 In case when statement uses stored routines but does not need
2258 prelocking (i.e. it does not use any tables) we will access the
2259 elements of Query_tables_list::sroutines set on prepared statement
2260 re-execution. Because of this we have to allocate memory for both
2261 hash element and copy of its key in persistent arena.
2262
2263 @param prelocking_ctx Prelocking context of the statement
2264 @param arena Arena in which memory for new element will be
2265 allocated
2266 @param key Key for the hash representing set
2267 @param belong_to_view Uppermost view which uses this routine
2268 (0 if routine is not used by view)
2269
2270 @note
2271 Will also add element to end of 'Query_tables_list::sroutines_list' list.
2272
2273 @todo
2274 When we will got rid of these accesses on re-executions we will be
2275 able to allocate memory for hash elements in non-persitent arena
2276 and directly use key values from sp_head::m_sroutines sets instead
2277 of making their copies.
2278
2279 @retval
2280 TRUE new element was added.
2281 @retval
2282 FALSE element was not added (because it is already present in
2283 the set).
2284 */
2285
sp_add_used_routine(Query_tables_list * prelocking_ctx,Query_arena * arena,const MDL_key * key,const Sp_handler * handler,TABLE_LIST * belong_to_view)2286 bool sp_add_used_routine(Query_tables_list *prelocking_ctx, Query_arena *arena,
2287 const MDL_key *key,
2288 const Sp_handler *handler,
2289 TABLE_LIST *belong_to_view)
2290 {
2291 my_hash_init_opt(&prelocking_ctx->sroutines, system_charset_info,
2292 Query_tables_list::START_SROUTINES_HASH_SIZE,
2293 0, 0, sp_sroutine_key, 0, 0);
2294
2295 if (!my_hash_search(&prelocking_ctx->sroutines, key->ptr(), key->length()))
2296 {
2297 Sroutine_hash_entry *rn=
2298 (Sroutine_hash_entry *)arena->alloc(sizeof(Sroutine_hash_entry));
2299 if (unlikely(!rn)) // OOM. Error will be reported using fatal_error().
2300 return FALSE;
2301 rn->mdl_request.init(key, MDL_SHARED, MDL_TRANSACTION);
2302 if (my_hash_insert(&prelocking_ctx->sroutines, (uchar *)rn))
2303 return FALSE;
2304 prelocking_ctx->sroutines_list.link_in_list(rn, &rn->next);
2305 rn->belong_to_view= belong_to_view;
2306 rn->m_handler= handler;
2307 rn->m_sp_cache_version= 0;
2308 return TRUE;
2309 }
2310 return FALSE;
2311 }
2312
2313
2314 /*
2315 Find and cache a routine in a parser-safe reentrant mode.
2316
2317 If sp_head is not in the cache,
2318 its loaded from mysql.proc, parsed using parse_sql(), and cached.
2319 Note, as it is called from inside parse_sql() itself,
2320 we need to preserve and restore the parser state.
2321
2322 It's used during parsing of CREATE PACKAGE BODY,
2323 to load the corresponding CREATE PACKAGE.
2324 */
2325
2326 int
sp_cache_routine_reentrant(THD * thd,const Database_qualified_name * name,sp_head ** sp) const2327 Sp_handler::sp_cache_routine_reentrant(THD *thd,
2328 const Database_qualified_name *name,
2329 sp_head **sp) const
2330 {
2331 int ret;
2332 Parser_state *oldps= thd->m_parser_state;
2333 thd->m_parser_state= NULL;
2334 ret= sp_cache_routine(thd, name, false, sp);
2335 thd->m_parser_state= oldps;
2336 return ret;
2337 }
2338
2339
2340 /**
2341 Check if a routine has a declaration in the CREATE PACKAGE statement,
2342 by looking up in thd->sp_package_spec_cache, and by loading from mysql.proc
2343 if needed.
2344
2345 @param thd current thd
2346 @param db the database name
2347 @param package the package name
2348 @param name the routine name
2349 @param type the routine type
2350 @retval true, if the routine has a declaration
2351 @retval false, if the routine does not have a declaration
2352
2353 This function can be called in arbitrary context:
2354 - inside a package routine
2355 - inside a standalone routine
2356 - inside a anonymous block
2357 - outside of any routines
2358
2359 The state of the package specification (i.e. the CREATE PACKAGE statement)
2360 for "package" before the call of this function is not known:
2361 it can be cached, or not cached.
2362 After the call of this function, the package specification is always cached,
2363 unless a fatal error happens.
2364 */
2365
2366 static bool
is_package_public_routine(THD * thd,const LEX_CSTRING & db,const LEX_CSTRING & package,const LEX_CSTRING & routine,stored_procedure_type type)2367 is_package_public_routine(THD *thd,
2368 const LEX_CSTRING &db,
2369 const LEX_CSTRING &package,
2370 const LEX_CSTRING &routine,
2371 stored_procedure_type type)
2372 {
2373 sp_head *sp= NULL;
2374 Database_qualified_name tmp(db, package);
2375 bool ret= sp_handler_package_spec.
2376 sp_cache_routine_reentrant(thd, &tmp, &sp);
2377 sp_package *spec= (!ret && sp) ? sp->get_package() : NULL;
2378 return spec && spec->m_routine_declarations.find(routine, type);
2379 }
2380
2381
2382 /**
2383 Check if a routine has a declaration in the CREATE PACKAGE statement
2384 by looking up in sp_package_spec_cache.
2385
2386 @param thd current thd
2387 @param db the database name
2388 @param pkgname the package name
2389 @param name the routine name
2390 @param type the routine type
2391 @retval true, if the routine has a declaration
2392 @retval false, if the routine does not have a declaration
2393
2394 This function is called in the middle of CREATE PACKAGE BODY parsing,
2395 to lookup the current package routines.
2396 The package specification (i.e. the CREATE PACKAGE statement) for
2397 the current package body must already be loaded and cached at this point.
2398 */
2399
2400 static bool
is_package_public_routine_quick(THD * thd,const LEX_CSTRING & db,const LEX_CSTRING & pkgname,const LEX_CSTRING & name,stored_procedure_type type)2401 is_package_public_routine_quick(THD *thd,
2402 const LEX_CSTRING &db,
2403 const LEX_CSTRING &pkgname,
2404 const LEX_CSTRING &name,
2405 stored_procedure_type type)
2406 {
2407 Database_qualified_name tmp(db, pkgname);
2408 sp_head *sp= sp_cache_lookup(&thd->sp_package_spec_cache, &tmp);
2409 sp_package *pkg= sp ? sp->get_package() : NULL;
2410 DBUG_ASSERT(pkg); // Must already be cached
2411 return pkg && pkg->m_routine_declarations.find(name, type);
2412 }
2413
2414
2415 /**
2416 Check if a qualified name, e.g. "CALL name1.name2",
2417 refers to a known routine in the package body "pkg".
2418 */
2419
2420 static bool
is_package_body_routine(THD * thd,sp_package * pkg,const LEX_CSTRING & name1,const LEX_CSTRING & name2,stored_procedure_type type)2421 is_package_body_routine(THD *thd, sp_package *pkg,
2422 const LEX_CSTRING &name1,
2423 const LEX_CSTRING &name2,
2424 stored_procedure_type type)
2425 {
2426 return Sp_handler::eq_routine_name(pkg->m_name, name1) &&
2427 (pkg->m_routine_declarations.find(name2, type) ||
2428 pkg->m_routine_implementations.find(name2, type));
2429 }
2430
2431
2432 /**
2433 Resolve a qualified routine reference xxx.yyy(), between:
2434 - A standalone routine: xxx.yyy
2435 - A package routine: current_database.xxx.yyy
2436 */
2437
2438 bool Sp_handler::
sp_resolve_package_routine_explicit(THD * thd,sp_head * caller,sp_name * name,const Sp_handler ** pkg_routine_handler,Database_qualified_name * pkgname) const2439 sp_resolve_package_routine_explicit(THD *thd,
2440 sp_head *caller,
2441 sp_name *name,
2442 const Sp_handler **pkg_routine_handler,
2443 Database_qualified_name *pkgname) const
2444 {
2445 sp_package *pkg;
2446
2447 /*
2448 If a qualified routine name was used, e.g. xxx.yyy(),
2449 we possibly have a call to a package routine.
2450 Rewrite name if name->m_db (xxx) is a known package,
2451 and name->m_name (yyy) is a known routine in this package.
2452 */
2453 LEX_CSTRING tmpdb= thd->db;
2454 if (is_package_public_routine(thd, tmpdb, name->m_db, name->m_name, type()) ||
2455 // Check if a package routine calls a private routine
2456 (caller && caller->m_parent &&
2457 is_package_body_routine(thd, caller->m_parent,
2458 name->m_db, name->m_name, type())) ||
2459 // Check if a package initialization sections calls a private routine
2460 (caller && (pkg= caller->get_package()) &&
2461 is_package_body_routine(thd, pkg, name->m_db, name->m_name, type())))
2462 {
2463 pkgname->m_db= tmpdb;
2464 pkgname->m_name= name->m_db;
2465 *pkg_routine_handler= package_routine_handler();
2466 return name->make_package_routine_name(thd->mem_root, tmpdb,
2467 name->m_db, name->m_name);
2468 }
2469 return false;
2470 }
2471
2472
2473 /**
2474 Resolve a non-qualified routine reference yyy(), between:
2475 - A standalone routine: current_database.yyy
2476 - A package routine: current_database.current_package.yyy
2477 */
2478
2479 bool Sp_handler::
sp_resolve_package_routine_implicit(THD * thd,sp_head * caller,sp_name * name,const Sp_handler ** pkg_routine_handler,Database_qualified_name * pkgname) const2480 sp_resolve_package_routine_implicit(THD *thd,
2481 sp_head *caller,
2482 sp_name *name,
2483 const Sp_handler **pkg_routine_handler,
2484 Database_qualified_name *pkgname) const
2485 {
2486 sp_package *pkg;
2487
2488 if (!caller || !caller->m_name.length)
2489 {
2490 /*
2491 We are either in a an anonymous block,
2492 or not in a routine at all.
2493 */
2494 return false; // A standalone routine is called
2495 }
2496
2497 if (caller->m_parent)
2498 {
2499 // A package routine calls a non-qualified routine
2500 int ret= SP_OK;
2501 Prefix_name_buf pkgstr(thd, caller->m_name);
2502 DBUG_ASSERT(pkgstr.length);
2503 LEX_CSTRING tmpname; // Non-qualified m_name
2504 tmpname.str= caller->m_name.str + pkgstr.length + 1;
2505 tmpname.length= caller->m_name.length - pkgstr.length - 1;
2506
2507 /*
2508 We're here if a package routine calls another non-qualified
2509 function or procedure, e.g. yyy().
2510 We need to distinguish two cases:
2511 - yyy() is another routine from the same package
2512 - yyy() is a standalone routine from the same database
2513 To detect if yyy() is a package (rather than a standalone) routine,
2514 we check if:
2515 - yyy() recursively calls itself
2516 - yyy() is earlier implemented in the current CREATE PACKAGE BODY
2517 - yyy() has a forward declaration
2518 - yyy() is declared in the corresponding CREATE PACKAGE
2519 */
2520 if (eq_routine_name(tmpname, name->m_name) ||
2521 caller->m_parent->m_routine_implementations.find(name->m_name, type()) ||
2522 caller->m_parent->m_routine_declarations.find(name->m_name, type()) ||
2523 is_package_public_routine_quick(thd, caller->m_db,
2524 pkgstr, name->m_name, type()))
2525 {
2526 DBUG_ASSERT(ret == SP_OK);
2527 pkgname->copy(thd->mem_root, caller->m_db, pkgstr);
2528 *pkg_routine_handler= package_routine_handler();
2529 if (name->make_package_routine_name(thd->mem_root, pkgstr, name->m_name))
2530 return true;
2531 }
2532 return ret != SP_OK;
2533 }
2534
2535 if ((pkg= caller->get_package()) &&
2536 pkg->m_routine_implementations.find(name->m_name, type()))
2537 {
2538 pkgname->m_db= caller->m_db;
2539 pkgname->m_name= caller->m_name;
2540 // Package initialization section is calling a non-qualified routine
2541 *pkg_routine_handler= package_routine_handler();
2542 return name->make_package_routine_name(thd->mem_root,
2543 caller->m_name, name->m_name);
2544 }
2545
2546 return false; // A standalone routine is called
2547
2548 }
2549
2550
2551 /**
2552 Detect cases when a package routine (rather than a standalone routine)
2553 is called, and rewrite sp_name accordingly.
2554
2555 @param thd Current thd
2556 @param caller The caller routine (or NULL if outside of a routine)
2557 @param [IN/OUT] name The called routine name
2558 @param [OUT] pkgname If the routine is found to be a package routine,
2559 pkgname is populated with the package name.
2560 Otherwise, it's not touched.
2561 @retval false on success
2562 @retval true on error (e.g. EOM, could not read CREATE PACKAGE)
2563 */
2564
2565 bool
sp_resolve_package_routine(THD * thd,sp_head * caller,sp_name * name,const Sp_handler ** pkg_routine_handler,Database_qualified_name * pkgname) const2566 Sp_handler::sp_resolve_package_routine(THD *thd,
2567 sp_head *caller,
2568 sp_name *name,
2569 const Sp_handler **pkg_routine_handler,
2570 Database_qualified_name *pkgname) const
2571 {
2572 if (!thd->db.length || !(thd->variables.sql_mode & MODE_ORACLE))
2573 return false;
2574
2575 return name->m_explicit_name ?
2576 sp_resolve_package_routine_explicit(thd, caller, name,
2577 pkg_routine_handler, pkgname) :
2578 sp_resolve_package_routine_implicit(thd, caller, name,
2579 pkg_routine_handler, pkgname);
2580 }
2581
2582
2583 /**
2584 Add routine which is explicitly used by statement to the set of stored
2585 routines used by this statement.
2586
2587 To be friendly towards prepared statements one should pass
2588 persistent arena as second argument.
2589
2590 @param prelocking_ctx Prelocking context of the statement
2591 @param arena Arena in which memory for new element of the set
2592 will be allocated
2593 @param rt Routine name
2594
2595 @note
2596 Will also add element to end of 'Query_tables_list::sroutines_list' list
2597 (and will take into account that this is an explicitly used routine).
2598 */
2599
add_used_routine(Query_tables_list * prelocking_ctx,Query_arena * arena,const Database_qualified_name * rt) const2600 void Sp_handler::add_used_routine(Query_tables_list *prelocking_ctx,
2601 Query_arena *arena,
2602 const Database_qualified_name *rt) const
2603 {
2604 MDL_key key(get_mdl_type(), rt->m_db.str, rt->m_name.str);
2605 (void) sp_add_used_routine(prelocking_ctx, arena, &key, this, 0);
2606 prelocking_ctx->sroutines_list_own_last= prelocking_ctx->sroutines_list.next;
2607 prelocking_ctx->sroutines_list_own_elements=
2608 prelocking_ctx->sroutines_list.elements;
2609 }
2610
2611
2612 /**
2613 Remove routines which are only indirectly used by statement from
2614 the set of routines used by this statement.
2615
2616 @param prelocking_ctx Prelocking context of the statement
2617 */
2618
sp_remove_not_own_routines(Query_tables_list * prelocking_ctx)2619 void sp_remove_not_own_routines(Query_tables_list *prelocking_ctx)
2620 {
2621 Sroutine_hash_entry *not_own_rt, *next_rt;
2622 for (not_own_rt= *prelocking_ctx->sroutines_list_own_last;
2623 not_own_rt; not_own_rt= next_rt)
2624 {
2625 /*
2626 It is safe to obtain not_own_rt->next after calling hash_delete() now
2627 but we want to be more future-proof.
2628 */
2629 next_rt= not_own_rt->next;
2630 my_hash_delete(&prelocking_ctx->sroutines, (uchar *)not_own_rt);
2631 }
2632
2633 *prelocking_ctx->sroutines_list_own_last= NULL;
2634 prelocking_ctx->sroutines_list.next= prelocking_ctx->sroutines_list_own_last;
2635 prelocking_ctx->sroutines_list.elements=
2636 prelocking_ctx->sroutines_list_own_elements;
2637 }
2638
2639
2640 /**
2641 Merge contents of two hashes representing sets of routines used
2642 by statements or by other routines.
2643
2644 @param dst hash to which elements should be added
2645 @param src hash from which elements merged
2646
2647 @note
2648 This procedure won't create new Sroutine_hash_entry objects,
2649 instead it will simply add elements from source to destination
2650 hash. Thus time of life of elements in destination hash becomes
2651 dependant on time of life of elements from source hash. It also
2652 won't touch lists linking elements in source and destination
2653 hashes.
2654
2655 @returns
2656 @return TRUE Failure
2657 @return FALSE Success
2658 */
2659
sp_update_sp_used_routines(HASH * dst,HASH * src)2660 bool sp_update_sp_used_routines(HASH *dst, HASH *src)
2661 {
2662 for (uint i=0 ; i < src->records ; i++)
2663 {
2664 Sroutine_hash_entry *rt= (Sroutine_hash_entry *)my_hash_element(src, i);
2665 if (!my_hash_search(dst, (uchar *)rt->mdl_request.key.ptr(),
2666 rt->mdl_request.key.length()))
2667 {
2668 if (my_hash_insert(dst, (uchar *)rt))
2669 return TRUE;
2670 }
2671 }
2672 return FALSE;
2673 }
2674
2675
2676 /**
2677 Add contents of hash representing set of routines to the set of
2678 routines used by statement.
2679
2680 @param thd Thread context
2681 @param prelocking_ctx Prelocking context of the statement
2682 @param src Hash representing set from which routines will
2683 be added
2684 @param belong_to_view Uppermost view which uses these routines, 0 if none
2685
2686 @note It will also add elements to end of
2687 'Query_tables_list::sroutines_list' list.
2688 */
2689
2690 void
sp_update_stmt_used_routines(THD * thd,Query_tables_list * prelocking_ctx,HASH * src,TABLE_LIST * belong_to_view)2691 sp_update_stmt_used_routines(THD *thd, Query_tables_list *prelocking_ctx,
2692 HASH *src, TABLE_LIST *belong_to_view)
2693 {
2694 for (uint i=0 ; i < src->records ; i++)
2695 {
2696 Sroutine_hash_entry *rt= (Sroutine_hash_entry *)my_hash_element(src, i);
2697 (void)sp_add_used_routine(prelocking_ctx, thd->stmt_arena,
2698 &rt->mdl_request.key, rt->m_handler,
2699 belong_to_view);
2700 }
2701 }
2702
2703
2704 /**
2705 Add contents of list representing set of routines to the set of
2706 routines used by statement.
2707
2708 @param thd Thread context
2709 @param prelocking_ctx Prelocking context of the statement
2710 @param src List representing set from which routines will
2711 be added
2712 @param belong_to_view Uppermost view which uses these routines, 0 if none
2713
2714 @note It will also add elements to end of
2715 'Query_tables_list::sroutines_list' list.
2716 */
2717
sp_update_stmt_used_routines(THD * thd,Query_tables_list * prelocking_ctx,SQL_I_List<Sroutine_hash_entry> * src,TABLE_LIST * belong_to_view)2718 void sp_update_stmt_used_routines(THD *thd, Query_tables_list *prelocking_ctx,
2719 SQL_I_List<Sroutine_hash_entry> *src,
2720 TABLE_LIST *belong_to_view)
2721 {
2722 for (Sroutine_hash_entry *rt= src->first; rt; rt= rt->next)
2723 (void)sp_add_used_routine(prelocking_ctx, thd->stmt_arena,
2724 &rt->mdl_request.key, rt->m_handler,
2725 belong_to_view);
2726 }
2727
2728
2729 /**
2730 A helper wrapper around sp_cache_routine() to use from
2731 prelocking until 'sp_name' is eradicated as a class.
2732 */
2733
sp_cache_routine(THD * thd,bool lookup_only,sp_head ** sp) const2734 int Sroutine_hash_entry::sp_cache_routine(THD *thd,
2735 bool lookup_only,
2736 sp_head **sp) const
2737 {
2738 char qname_buff[NAME_LEN*2+1+1];
2739 sp_name name(&mdl_request.key, qname_buff);
2740 /*
2741 Check that we have an MDL lock on this routine, unless it's a top-level
2742 CALL. The assert below should be unambiguous: the first element
2743 in sroutines_list has an MDL lock unless it's a top-level call, or a
2744 trigger, but triggers can't occur here (see the preceding assert).
2745 */
2746 DBUG_ASSERT(mdl_request.ticket || this == thd->lex->sroutines_list.first);
2747
2748 return m_handler->sp_cache_routine(thd, &name, lookup_only, sp);
2749 }
2750
2751
2752 /**
2753 Ensure that routine is present in cache by loading it from the mysql.proc
2754 table if needed. If the routine is present but old, reload it.
2755 Emit an appropriate error if there was a problem during
2756 loading.
2757
2758 @param[in] thd Thread context.
2759 @param[in] name Name of routine.
2760 @param[in] lookup_only Only check that the routine is in the cache.
2761 If it's not, don't try to load. If it is present,
2762 but old, don't try to reload.
2763 @param[out] sp Pointer to sp_head object for routine, NULL if routine was
2764 not found.
2765
2766 @retval 0 Either routine is found and was succesfully loaded into cache
2767 or it does not exist.
2768 @retval non-0 Error while loading routine from mysql,proc table.
2769 */
2770
sp_cache_routine(THD * thd,const Database_qualified_name * name,bool lookup_only,sp_head ** sp) const2771 int Sp_handler::sp_cache_routine(THD *thd,
2772 const Database_qualified_name *name,
2773 bool lookup_only,
2774 sp_head **sp) const
2775 {
2776 int ret= 0;
2777 sp_cache **spc= get_cache(thd);
2778
2779 DBUG_ENTER("Sp_handler::sp_cache_routine");
2780
2781 DBUG_ASSERT(spc);
2782
2783 *sp= sp_cache_lookup(spc, name);
2784
2785 if (lookup_only)
2786 DBUG_RETURN(SP_OK);
2787
2788 if (*sp)
2789 {
2790 sp_cache_flush_obsolete(spc, sp);
2791 if (*sp)
2792 DBUG_RETURN(SP_OK);
2793 }
2794
2795 switch ((ret= db_find_and_cache_routine(thd, name, sp)))
2796 {
2797 case SP_OK:
2798 break;
2799 case SP_KEY_NOT_FOUND:
2800 ret= SP_OK;
2801 break;
2802 default:
2803 /* Query might have been killed, don't set error. */
2804 if (thd->killed)
2805 break;
2806 /*
2807 Any error when loading an existing routine is either some problem
2808 with the mysql.proc table, or a parse error because the contents
2809 has been tampered with (in which case we clear that error).
2810 */
2811 if (ret == SP_PARSE_ERROR)
2812 thd->clear_error();
2813 /*
2814 If we cleared the parse error, or when db_find_routine() flagged
2815 an error with it's return value without calling my_error(), we
2816 set the generic "mysql.proc table corrupt" error here.
2817 */
2818 if (!thd->is_error())
2819 {
2820 my_error(ER_SP_PROC_TABLE_CORRUPT, MYF(0),
2821 ErrConvDQName(name).ptr(), ret);
2822 }
2823 break;
2824 }
2825 DBUG_RETURN(ret);
2826 }
2827
2828
2829 /**
2830 Cache a package routine using its package name and a qualified name.
2831 See sp_cache_routine() for more information on parameters and return values.
2832
2833 @param thd - current THD
2834 @param pkgname_str - package name, e.g. "pkgname"
2835 @param name - name with the following format:
2836 * name->m_db is a database name, e.g. "dbname"
2837 * name->m_name is a package-qualified name,
2838 e.g. "pkgname.spname"
2839 @param lookup_only - don't load mysql.proc if not cached
2840 @param [OUT] sp - the result is returned here.
2841 @retval false - loaded or does not exists
2842 @retval true - error while loading mysql.proc
2843 */
2844
2845 int
sp_cache_package_routine(THD * thd,const LEX_CSTRING & pkgname_cstr,const Database_qualified_name * name,bool lookup_only,sp_head ** sp) const2846 Sp_handler::sp_cache_package_routine(THD *thd,
2847 const LEX_CSTRING &pkgname_cstr,
2848 const Database_qualified_name *name,
2849 bool lookup_only, sp_head **sp) const
2850 {
2851 DBUG_ENTER("sp_cache_package_routine");
2852 DBUG_ASSERT(type() == TYPE_ENUM_FUNCTION || type() == TYPE_ENUM_PROCEDURE);
2853 sp_name pkgname(&name->m_db, &pkgname_cstr, false);
2854 sp_head *ph= NULL;
2855 int ret= sp_handler_package_body.sp_cache_routine(thd, &pkgname,
2856 lookup_only,
2857 &ph);
2858 if (!ret)
2859 {
2860 sp_package *pkg= ph ? ph->get_package() : NULL;
2861 LEX_CSTRING tmp= name->m_name;
2862 const char *dot= strrchr(tmp.str, '.');
2863 size_t prefix_length= dot ? dot - tmp.str + 1 : 0;
2864 tmp.str+= prefix_length;
2865 tmp.length-= prefix_length;
2866 LEX *rlex= pkg ? pkg->m_routine_implementations.find(tmp, type()) : NULL;
2867 *sp= rlex ? rlex->sphead : NULL;
2868 }
2869
2870 DBUG_RETURN(ret);
2871 }
2872
2873
2874 /**
2875 Cache a package routine by its fully qualified name.
2876 See sp_cache_routine() for more information on parameters and return values.
2877
2878 @param thd - current THD
2879 @param name - name with the following format:
2880 * name->m_db is a database name, e.g. "dbname"
2881 * name->m_name is a package-qualified name,
2882 e.g. "pkgname.spname"
2883 @param lookup_only - don't load mysql.proc if not cached
2884 @param [OUT] sp - the result is returned here
2885 @retval false - loaded or does not exists
2886 @retval true - error while loading mysql.proc
2887 */
2888
sp_cache_package_routine(THD * thd,const Database_qualified_name * name,bool lookup_only,sp_head ** sp) const2889 int Sp_handler::sp_cache_package_routine(THD *thd,
2890 const Database_qualified_name *name,
2891 bool lookup_only, sp_head **sp) const
2892 {
2893 DBUG_ENTER("Sp_handler::sp_cache_package_routine");
2894 Prefix_name_buf pkgname(thd, name->m_name);
2895 DBUG_ASSERT(pkgname.length);
2896 DBUG_RETURN(sp_cache_package_routine(thd, pkgname, name, lookup_only, sp));
2897 }
2898
2899
2900 /**
2901 Generates the CREATE... string from the table information.
2902
2903 @return
2904 Returns false on success, true on (alloc) failure.
2905 */
2906
2907 bool
show_create_sp(THD * thd,String * buf,const LEX_CSTRING & db,const LEX_CSTRING & name,const LEX_CSTRING & params,const LEX_CSTRING & returns,const LEX_CSTRING & body,const st_sp_chistics & chistics,const AUTHID & definer,const DDL_options_st ddl_options,sql_mode_t sql_mode) const2908 Sp_handler::show_create_sp(THD *thd, String *buf,
2909 const LEX_CSTRING &db,
2910 const LEX_CSTRING &name,
2911 const LEX_CSTRING ¶ms,
2912 const LEX_CSTRING &returns,
2913 const LEX_CSTRING &body,
2914 const st_sp_chistics &chistics,
2915 const AUTHID &definer,
2916 const DDL_options_st ddl_options,
2917 sql_mode_t sql_mode) const
2918 {
2919 sql_mode_t old_sql_mode= thd->variables.sql_mode;
2920 size_t agglen= (chistics.agg_type == GROUP_AGGREGATE)? 10 : 0;
2921 LEX_CSTRING tmp;
2922
2923 /* Make some room to begin with */
2924 if (buf->alloc(100 + db.length + 1 + name.length +
2925 params.length + returns.length +
2926 chistics.comment.length + 10 /* length of " DEFINER= "*/ +
2927 agglen + USER_HOST_BUFF_SIZE))
2928 return true;
2929
2930 thd->variables.sql_mode= sql_mode;
2931 buf->append(STRING_WITH_LEN("CREATE "));
2932 if (ddl_options.or_replace())
2933 buf->append(STRING_WITH_LEN("OR REPLACE "));
2934 append_definer(thd, buf, &definer.user, &definer.host);
2935 if (chistics.agg_type == GROUP_AGGREGATE)
2936 buf->append(STRING_WITH_LEN("AGGREGATE "));
2937 tmp= type_lex_cstring();
2938 buf->append(&tmp);
2939 buf->append(STRING_WITH_LEN(" "));
2940 if (ddl_options.if_not_exists())
2941 buf->append(STRING_WITH_LEN("IF NOT EXISTS "));
2942
2943 if (db.length > 0)
2944 {
2945 append_identifier(thd, buf, &db);
2946 buf->append('.');
2947 }
2948 append_identifier(thd, buf, &name);
2949 buf->append('(');
2950 buf->append(¶ms);
2951 buf->append(')');
2952 if (type() == TYPE_ENUM_FUNCTION)
2953 {
2954 if (sql_mode & MODE_ORACLE)
2955 buf->append(STRING_WITH_LEN(" RETURN "));
2956 else
2957 buf->append(STRING_WITH_LEN(" RETURNS "));
2958 buf->append(returns.str, returns.length); // Not \0 terminated
2959 }
2960 buf->append('\n');
2961 switch (chistics.daccess) {
2962 case SP_NO_SQL:
2963 buf->append(STRING_WITH_LEN(" NO SQL\n"));
2964 break;
2965 case SP_READS_SQL_DATA:
2966 buf->append(STRING_WITH_LEN(" READS SQL DATA\n"));
2967 break;
2968 case SP_MODIFIES_SQL_DATA:
2969 buf->append(STRING_WITH_LEN(" MODIFIES SQL DATA\n"));
2970 break;
2971 case SP_DEFAULT_ACCESS:
2972 case SP_CONTAINS_SQL:
2973 /* Do nothing */
2974 break;
2975 }
2976 if (chistics.detistic)
2977 buf->append(STRING_WITH_LEN(" DETERMINISTIC\n"));
2978 append_suid(buf, chistics.suid);
2979 append_comment(buf, chistics.comment);
2980 buf->append(body.str, body.length); // Not \0 terminated
2981 thd->variables.sql_mode= old_sql_mode;
2982 return false;
2983 }
2984
2985
2986 /**
2987 @brief The function loads sp_head struct for information schema purposes
2988 (used for I_S ROUTINES & PARAMETERS tables).
2989
2990 @param[in] thd thread handler
2991 @param[in] proc_table mysql.proc table structurte
2992 @param[in] db database name
2993 @param[in] name sp name
2994 @param[in] sql_mode SQL mode
2995 @param[in] type Routine type
2996 @param[in] returns 'returns' string
2997 @param[in] params parameters definition string
2998 @param[out] free_sp_head returns 1 if we need to free sp_head struct
2999 otherwise returns 0
3000
3001 @return Pointer on sp_head struct
3002 @retval # Pointer on sp_head struct
3003 @retval 0 error
3004 */
3005
3006 sp_head *
sp_load_for_information_schema(THD * thd,TABLE * proc_table,const LEX_CSTRING & db,const LEX_CSTRING & name,const LEX_CSTRING & params,const LEX_CSTRING & returns,sql_mode_t sql_mode,bool * free_sp_head) const3007 Sp_handler::sp_load_for_information_schema(THD *thd, TABLE *proc_table,
3008 const LEX_CSTRING &db,
3009 const LEX_CSTRING &name,
3010 const LEX_CSTRING ¶ms,
3011 const LEX_CSTRING &returns,
3012 sql_mode_t sql_mode,
3013 bool *free_sp_head) const
3014 {
3015 String defstr;
3016 const AUTHID definer= {{STRING_WITH_LEN("")}, {STRING_WITH_LEN("")}};
3017 sp_head *sp;
3018 sp_cache **spc= get_cache(thd);
3019 sp_name sp_name_obj(&db, &name, true); // This can change "name"
3020 *free_sp_head= 0;
3021 if ((sp= sp_cache_lookup(spc, &sp_name_obj)))
3022 {
3023 return sp;
3024 }
3025
3026 LEX *old_lex= thd->lex, newlex;
3027 Stored_program_creation_ctx *creation_ctx=
3028 Stored_routine_creation_ctx::load_from_db(thd, &sp_name_obj, proc_table);
3029 defstr.set_charset(creation_ctx->get_client_cs());
3030 if (show_create_sp(thd, &defstr,
3031 sp_name_obj.m_db, sp_name_obj.m_name,
3032 params, returns, empty_body_lex_cstring(sql_mode),
3033 Sp_chistics(), definer, DDL_options(), sql_mode))
3034 return 0;
3035
3036 thd->lex= &newlex;
3037 newlex.current_select= NULL;
3038 sp= sp_compile(thd, &defstr, sql_mode, NULL, creation_ctx);
3039 *free_sp_head= 1;
3040 thd->lex->sphead= NULL;
3041 lex_end(thd->lex);
3042 thd->lex= old_lex;
3043 return sp;
3044 }
3045
3046
empty_body_lex_cstring(sql_mode_t mode) const3047 LEX_CSTRING Sp_handler_procedure::empty_body_lex_cstring(sql_mode_t mode) const
3048 {
3049 static LEX_CSTRING m_empty_body_std= {STRING_WITH_LEN("BEGIN END")};
3050 static LEX_CSTRING m_empty_body_ora= {STRING_WITH_LEN("AS BEGIN NULL; END")};
3051 return mode & MODE_ORACLE ? m_empty_body_ora : m_empty_body_std;
3052 }
3053
3054
empty_body_lex_cstring(sql_mode_t mode) const3055 LEX_CSTRING Sp_handler_function::empty_body_lex_cstring(sql_mode_t mode) const
3056 {
3057 static LEX_CSTRING m_empty_body_std= {STRING_WITH_LEN("RETURN NULL")};
3058 static LEX_CSTRING m_empty_body_ora= {STRING_WITH_LEN("AS BEGIN RETURN NULL; END")};
3059 return mode & MODE_ORACLE ? m_empty_body_ora : m_empty_body_std;
3060 }
3061