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