~ubuntu-branches/ubuntu/precise/mysql-5.1/precise

« back to all changes in this revision

Viewing changes to sql/sp.cc

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Tretkowski
  • Date: 2010-03-17 14:56:02 UTC
  • Revision ID: james.westby@ubuntu.com-20100317145602-x7e30l1b2sb5s6w6
Tags: upstream-5.1.45
ImportĀ upstreamĀ versionĀ 5.1.45

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2002 MySQL AB
 
2
 
 
3
   This program is free software; you can redistribute it and/or modify
 
4
   it under the terms of the GNU General Public License as published by
 
5
   the Free Software Foundation; version 2 of the License.
 
6
 
 
7
   This program is distributed in the hope that it will be useful,
 
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
10
   GNU General Public License for more details.
 
11
 
 
12
   You should have received a copy of the GNU General Public License
 
13
   along with this program; if not, write to the Free Software
 
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
15
 
 
16
#include "mysql_priv.h"
 
17
#include "sp.h"
 
18
#include "sp_head.h"
 
19
#include "sp_cache.h"
 
20
#include "sql_trigger.h"
 
21
 
 
22
#include <my_user.h>
 
23
 
 
24
static bool
 
25
create_string(THD *thd, String *buf,
 
26
              int sp_type,
 
27
              const char *db, ulong dblen,
 
28
              const char *name, ulong namelen,
 
29
              const char *params, ulong paramslen,
 
30
              const char *returns, ulong returnslen,
 
31
              const char *body, ulong bodylen,
 
32
              st_sp_chistics *chistics,
 
33
              const LEX_STRING *definer_user,
 
34
              const LEX_STRING *definer_host);
 
35
static int
 
36
db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp,
 
37
                ulong sql_mode, const char *params, const char *returns,
 
38
                const char *body, st_sp_chistics &chistics,
 
39
                const char *definer, longlong created, longlong modified,
 
40
                Stored_program_creation_ctx *creation_ctx);
 
41
 
 
42
/*
 
43
 *
 
44
 * DB storage of Stored PROCEDUREs and FUNCTIONs
 
45
 *
 
46
 */
 
47
 
 
48
enum
 
49
{
 
50
  MYSQL_PROC_FIELD_DB = 0,
 
51
  MYSQL_PROC_FIELD_NAME,
 
52
  MYSQL_PROC_MYSQL_TYPE,
 
53
  MYSQL_PROC_FIELD_SPECIFIC_NAME,
 
54
  MYSQL_PROC_FIELD_LANGUAGE,
 
55
  MYSQL_PROC_FIELD_ACCESS,
 
56
  MYSQL_PROC_FIELD_DETERMINISTIC,
 
57
  MYSQL_PROC_FIELD_SECURITY_TYPE,
 
58
  MYSQL_PROC_FIELD_PARAM_LIST,
 
59
  MYSQL_PROC_FIELD_RETURNS,
 
60
  MYSQL_PROC_FIELD_BODY,
 
61
  MYSQL_PROC_FIELD_DEFINER,
 
62
  MYSQL_PROC_FIELD_CREATED,
 
63
  MYSQL_PROC_FIELD_MODIFIED,
 
64
  MYSQL_PROC_FIELD_SQL_MODE,
 
65
  MYSQL_PROC_FIELD_COMMENT,
 
66
  MYSQL_PROC_FIELD_CHARACTER_SET_CLIENT,
 
67
  MYSQL_PROC_FIELD_COLLATION_CONNECTION,
 
68
  MYSQL_PROC_FIELD_DB_COLLATION,
 
69
  MYSQL_PROC_FIELD_BODY_UTF8,
 
70
  MYSQL_PROC_FIELD_COUNT
 
71
};
 
72
 
 
73
static const
 
74
TABLE_FIELD_TYPE proc_table_fields[MYSQL_PROC_FIELD_COUNT] =
 
75
{
 
76
  {
 
77
    { C_STRING_WITH_LEN("db") },
 
78
    { C_STRING_WITH_LEN("char(64)") },
 
79
    { C_STRING_WITH_LEN("utf8") }
 
80
  },
 
81
  {
 
82
    { C_STRING_WITH_LEN("name") },
 
83
    { C_STRING_WITH_LEN("char(64)") },
 
84
    { C_STRING_WITH_LEN("utf8") }
 
85
  },
 
86
  {
 
87
    { C_STRING_WITH_LEN("type") },
 
88
    { C_STRING_WITH_LEN("enum('FUNCTION','PROCEDURE')") },
 
89
    { NULL, 0 }
 
90
  },
 
91
  {
 
92
    { C_STRING_WITH_LEN("specific_name") },
 
93
    { C_STRING_WITH_LEN("char(64)") },
 
94
    { C_STRING_WITH_LEN("utf8") }
 
95
  },
 
96
  {
 
97
    { C_STRING_WITH_LEN("language") },
 
98
    { C_STRING_WITH_LEN("enum('SQL')") },
 
99
    { NULL, 0 }
 
100
  },
 
101
  {
 
102
    { C_STRING_WITH_LEN("sql_data_access") },
 
103
    { C_STRING_WITH_LEN("enum('CONTAINS_SQL','NO_SQL','READS_SQL_DATA','MODIFIES_SQL_DATA')") },
 
104
    { NULL, 0 }
 
105
  },
 
106
  {
 
107
    { C_STRING_WITH_LEN("is_deterministic") },
 
108
    { C_STRING_WITH_LEN("enum('YES','NO')") },
 
109
    { NULL, 0 }
 
110
  },
 
111
  {
 
112
    { C_STRING_WITH_LEN("security_type") },
 
113
    { C_STRING_WITH_LEN("enum('INVOKER','DEFINER')") },
 
114
    { NULL, 0 }
 
115
  },
 
116
  {
 
117
    { C_STRING_WITH_LEN("param_list") },
 
118
    { C_STRING_WITH_LEN("blob") },
 
119
    { NULL, 0 }
 
120
  },
 
121
 
 
122
  {
 
123
    { C_STRING_WITH_LEN("returns") },
 
124
    { C_STRING_WITH_LEN("longblob") },
 
125
    { NULL, 0 }
 
126
  },
 
127
  {
 
128
    { C_STRING_WITH_LEN("body") },
 
129
    { C_STRING_WITH_LEN("longblob") },
 
130
    { NULL, 0 }
 
131
  },
 
132
  {
 
133
    { C_STRING_WITH_LEN("definer") },
 
134
    { C_STRING_WITH_LEN("char(77)") },
 
135
    { C_STRING_WITH_LEN("utf8") }
 
136
  },
 
137
  {
 
138
    { C_STRING_WITH_LEN("created") },
 
139
    { C_STRING_WITH_LEN("timestamp") },
 
140
    { NULL, 0 }
 
141
  },
 
142
  {
 
143
    { C_STRING_WITH_LEN("modified") },
 
144
    { C_STRING_WITH_LEN("timestamp") },
 
145
    { NULL, 0 }
 
146
  },
 
147
  {
 
148
    { C_STRING_WITH_LEN("sql_mode") },
 
149
    { C_STRING_WITH_LEN("set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES',"
 
150
    "'IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION',"
 
151
    "'NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB',"
 
152
    "'NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40',"
 
153
    "'ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES',"
 
154
    "'STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES',"
 
155
    "'ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER',"
 
156
    "'HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')") },
 
157
    { NULL, 0 }
 
158
  },
 
159
  {
 
160
    { C_STRING_WITH_LEN("comment") },
 
161
    { C_STRING_WITH_LEN("char(64)") },
 
162
    { C_STRING_WITH_LEN("utf8") }
 
163
  },
 
164
  {
 
165
    { C_STRING_WITH_LEN("character_set_client") },
 
166
    { C_STRING_WITH_LEN("char(32)") },
 
167
    { C_STRING_WITH_LEN("utf8") }
 
168
  },
 
169
  {
 
170
    { C_STRING_WITH_LEN("collation_connection") },
 
171
    { C_STRING_WITH_LEN("char(32)") },
 
172
    { C_STRING_WITH_LEN("utf8") }
 
173
  },
 
174
  {
 
175
    { C_STRING_WITH_LEN("db_collation") },
 
176
    { C_STRING_WITH_LEN("char(32)") },
 
177
    { C_STRING_WITH_LEN("utf8") }
 
178
  },
 
179
  {
 
180
    { C_STRING_WITH_LEN("body_utf8") },
 
181
    { C_STRING_WITH_LEN("longblob") },
 
182
    { NULL, 0 }
 
183
  }
 
184
};
 
185
 
 
186
static const TABLE_FIELD_DEF
 
187
  proc_table_def= {MYSQL_PROC_FIELD_COUNT, proc_table_fields};
 
188
 
 
189
/*************************************************************************/
 
190
 
 
191
/**
 
192
  Stored_routine_creation_ctx -- creation context of stored routines
 
193
  (stored procedures and functions).
 
194
*/
 
195
 
 
196
class Stored_routine_creation_ctx : public Stored_program_creation_ctx,
 
197
                                    public Sql_alloc
 
198
{
 
199
public:
 
200
  static Stored_routine_creation_ctx *
 
201
  load_from_db(THD *thd, const sp_name *name, TABLE *proc_tbl);
 
202
 
 
203
public:
 
204
  virtual Stored_program_creation_ctx *clone(MEM_ROOT *mem_root)
 
205
  {
 
206
    return new (mem_root) Stored_routine_creation_ctx(m_client_cs,
 
207
                                                      m_connection_cl,
 
208
                                                      m_db_cl);
 
209
  }
 
210
 
 
211
protected:
 
212
  virtual Object_creation_ctx *create_backup_ctx(THD *thd) const
 
213
  {
 
214
    DBUG_ENTER("Stored_routine_creation_ctx::create_backup_ctx");
 
215
    DBUG_RETURN(new Stored_routine_creation_ctx(thd));
 
216
  }
 
217
 
 
218
private:
 
219
  Stored_routine_creation_ctx(THD *thd)
 
220
    : Stored_program_creation_ctx(thd)
 
221
  { }
 
222
 
 
223
  Stored_routine_creation_ctx(CHARSET_INFO *client_cs,
 
224
                              CHARSET_INFO *connection_cl,
 
225
                              CHARSET_INFO *db_cl)
 
226
    : Stored_program_creation_ctx(client_cs, connection_cl, db_cl)
 
227
  { }
 
228
};
 
229
 
 
230
/**************************************************************************
 
231
  Stored_routine_creation_ctx implementation.
 
232
**************************************************************************/
 
233
 
 
234
bool load_charset(MEM_ROOT *mem_root,
 
235
                  Field *field,
 
236
                  CHARSET_INFO *dflt_cs,
 
237
                  CHARSET_INFO **cs)
 
238
{
 
239
  String cs_name;
 
240
 
 
241
  if (get_field(mem_root, field, &cs_name))
 
242
  {
 
243
    *cs= dflt_cs;
 
244
    return TRUE;
 
245
  }
 
246
 
 
247
  *cs= get_charset_by_csname(cs_name.c_ptr(), MY_CS_PRIMARY, MYF(0));
 
248
 
 
249
  if (*cs == NULL)
 
250
  {
 
251
    *cs= dflt_cs;
 
252
    return TRUE;
 
253
  }
 
254
 
 
255
  return FALSE;
 
256
}
 
257
 
 
258
/*************************************************************************/
 
259
 
 
260
bool load_collation(MEM_ROOT *mem_root,
 
261
                    Field *field,
 
262
                    CHARSET_INFO *dflt_cl,
 
263
                    CHARSET_INFO **cl)
 
264
{
 
265
  String cl_name;
 
266
 
 
267
  if (get_field(mem_root, field, &cl_name))
 
268
  {
 
269
    *cl= dflt_cl;
 
270
    return TRUE;
 
271
  }
 
272
 
 
273
  *cl= get_charset_by_name(cl_name.c_ptr(), MYF(0));
 
274
 
 
275
  if (*cl == NULL)
 
276
  {
 
277
    *cl= dflt_cl;
 
278
    return TRUE;
 
279
  }
 
280
 
 
281
  return FALSE;
 
282
}
 
283
 
 
284
/*************************************************************************/
 
285
 
 
286
Stored_routine_creation_ctx *
 
287
Stored_routine_creation_ctx::load_from_db(THD *thd,
 
288
                                         const sp_name *name,
 
289
                                         TABLE *proc_tbl)
 
290
{
 
291
  /* Load character set/collation attributes. */
 
292
 
 
293
  CHARSET_INFO *client_cs;
 
294
  CHARSET_INFO *connection_cl;
 
295
  CHARSET_INFO *db_cl;
 
296
 
 
297
  const char *db_name= thd->strmake(name->m_db.str, name->m_db.length);
 
298
  const char *sr_name= thd->strmake(name->m_name.str, name->m_name.length);
 
299
 
 
300
  bool invalid_creation_ctx= FALSE;
 
301
 
 
302
  if (load_charset(thd->mem_root,
 
303
                   proc_tbl->field[MYSQL_PROC_FIELD_CHARACTER_SET_CLIENT],
 
304
                   thd->variables.character_set_client,
 
305
                   &client_cs))
 
306
  {
 
307
    sql_print_warning("Stored routine '%s'.'%s': invalid value "
 
308
                      "in column mysql.proc.character_set_client.",
 
309
                      (const char *) db_name,
 
310
                      (const char *) sr_name);
 
311
 
 
312
    invalid_creation_ctx= TRUE;
 
313
  }
 
314
 
 
315
  if (load_collation(thd->mem_root,
 
316
                     proc_tbl->field[MYSQL_PROC_FIELD_COLLATION_CONNECTION],
 
317
                     thd->variables.collation_connection,
 
318
                     &connection_cl))
 
319
  {
 
320
    sql_print_warning("Stored routine '%s'.'%s': invalid value "
 
321
                      "in column mysql.proc.collation_connection.",
 
322
                      (const char *) db_name,
 
323
                      (const char *) sr_name);
 
324
 
 
325
    invalid_creation_ctx= TRUE;
 
326
  }
 
327
 
 
328
  if (load_collation(thd->mem_root,
 
329
                     proc_tbl->field[MYSQL_PROC_FIELD_DB_COLLATION],
 
330
                     NULL,
 
331
                     &db_cl))
 
332
  {
 
333
    sql_print_warning("Stored routine '%s'.'%s': invalid value "
 
334
                      "in column mysql.proc.db_collation.",
 
335
                      (const char *) db_name,
 
336
                      (const char *) sr_name);
 
337
 
 
338
    invalid_creation_ctx= TRUE;
 
339
  }
 
340
 
 
341
  if (invalid_creation_ctx)
 
342
  {
 
343
    push_warning_printf(thd,
 
344
                        MYSQL_ERROR::WARN_LEVEL_WARN,
 
345
                        ER_SR_INVALID_CREATION_CTX,
 
346
                        ER(ER_SR_INVALID_CREATION_CTX),
 
347
                        (const char *) db_name,
 
348
                        (const char *) sr_name);
 
349
  }
 
350
 
 
351
  /*
 
352
    If we failed to retrieve the database collation, load the default one
 
353
    from the disk.
 
354
  */
 
355
 
 
356
  if (!db_cl)
 
357
    db_cl= get_default_db_collation(thd, name->m_db.str);
 
358
 
 
359
  /* Create the context. */
 
360
 
 
361
  return new Stored_routine_creation_ctx(client_cs, connection_cl, db_cl);
 
362
}
 
363
 
 
364
/*************************************************************************/
 
365
 
 
366
class Proc_table_intact : public Table_check_intact
 
367
{
 
368
private:
 
369
  bool m_print_once;
 
370
 
 
371
public:
 
372
  Proc_table_intact() : m_print_once(TRUE) {}
 
373
 
 
374
protected:
 
375
  void report_error(uint code, const char *fmt, ...);
 
376
};
 
377
 
 
378
 
 
379
/**
 
380
  Report failure to validate the mysql.proc table definition.
 
381
  Print a message to the error log only once.
 
382
*/
 
383
 
 
384
void Proc_table_intact::report_error(uint code, const char *fmt, ...)
 
385
{
 
386
  va_list args;
 
387
  char buf[512];
 
388
 
 
389
  va_start(args, fmt);
 
390
  my_vsnprintf(buf, sizeof(buf), fmt, args);
 
391
  va_end(args);
 
392
 
 
393
  if (code)
 
394
    my_message(code, buf, MYF(0));
 
395
  else
 
396
    my_error(ER_CANNOT_LOAD_FROM_TABLE, MYF(0), "proc");
 
397
 
 
398
  if (m_print_once)
 
399
  {
 
400
    m_print_once= FALSE;
 
401
    sql_print_error("%s", buf);
 
402
  }
 
403
};
 
404
 
 
405
 
 
406
/** Single instance used to control printing to the error log. */
 
407
static Proc_table_intact proc_table_intact;
 
408
 
 
409
 
 
410
/**
 
411
  Open the mysql.proc table for read.
 
412
 
 
413
  @param thd     Thread context
 
414
  @param backup  Pointer to Open_tables_state instance where information about
 
415
                 currently open tables will be saved, and from which will be
 
416
                 restored when we will end work with mysql.proc.
 
417
 
 
418
  @retval
 
419
    0   Error
 
420
  @retval
 
421
    \#  Pointer to TABLE object of mysql.proc
 
422
*/
 
423
 
 
424
TABLE *open_proc_table_for_read(THD *thd, Open_tables_state *backup)
 
425
{
 
426
  DBUG_ENTER("open_proc_table_for_read");
 
427
 
 
428
  TABLE_LIST table;
 
429
  table.init_one_table("mysql", "proc", TL_READ);
 
430
 
 
431
  if (open_system_tables_for_read(thd, &table, backup))
 
432
    DBUG_RETURN(NULL);
 
433
 
 
434
  if (!proc_table_intact.check(table.table, &proc_table_def))
 
435
    DBUG_RETURN(table.table);
 
436
 
 
437
  close_system_tables(thd, backup);
 
438
 
 
439
  DBUG_RETURN(NULL);
 
440
}
 
441
 
 
442
 
 
443
/**
 
444
  Open the mysql.proc table for update.
 
445
 
 
446
  @param thd  Thread context
 
447
 
 
448
  @note
 
449
    Table opened with this call should closed using close_thread_tables().
 
450
 
 
451
  @retval
 
452
    0   Error
 
453
  @retval
 
454
    \#  Pointer to TABLE object of mysql.proc
 
455
*/
 
456
 
 
457
static TABLE *open_proc_table_for_update(THD *thd)
 
458
{
 
459
  DBUG_ENTER("open_proc_table_for_update");
 
460
 
 
461
  TABLE *table;
 
462
  TABLE_LIST table_list;
 
463
  table_list.init_one_table("mysql", "proc", TL_WRITE);
 
464
 
 
465
  if (!(table= open_system_table_for_update(thd, &table_list)))
 
466
    DBUG_RETURN(NULL);
 
467
 
 
468
  if (!proc_table_intact.check(table, &proc_table_def))
 
469
    DBUG_RETURN(table);
 
470
 
 
471
  close_thread_tables(thd);
 
472
 
 
473
  DBUG_RETURN(NULL);
 
474
}
 
475
 
 
476
 
 
477
/**
 
478
  Find row in open mysql.proc table representing stored routine.
 
479
 
 
480
  @param thd    Thread context
 
481
  @param type   Type of routine to find (function or procedure)
 
482
  @param name   Name of routine
 
483
  @param table  TABLE object for open mysql.proc table.
 
484
 
 
485
  @retval
 
486
    SP_OK             Routine found
 
487
  @retval
 
488
    SP_KEY_NOT_FOUND  No routine with given name
 
489
*/
 
490
 
 
491
static int
 
492
db_find_routine_aux(THD *thd, int type, sp_name *name, TABLE *table)
 
493
{
 
494
  uchar key[MAX_KEY_LENGTH];    // db, name, optional key length type
 
495
  DBUG_ENTER("db_find_routine_aux");
 
496
  DBUG_PRINT("enter", ("type: %d  name: %.*s",
 
497
                       type, (int) name->m_name.length, name->m_name.str));
 
498
 
 
499
  /*
 
500
    Create key to find row. We have to use field->store() to be able to
 
501
    handle VARCHAR and CHAR fields.
 
502
    Assumption here is that the three first fields in the table are
 
503
    'db', 'name' and 'type' and the first key is the primary key over the
 
504
    same fields.
 
505
  */
 
506
  if (name->m_name.length > table->field[1]->field_length)
 
507
    DBUG_RETURN(SP_KEY_NOT_FOUND);
 
508
  table->field[0]->store(name->m_db.str, name->m_db.length, &my_charset_bin);
 
509
  table->field[1]->store(name->m_name.str, name->m_name.length,
 
510
                         &my_charset_bin);
 
511
  table->field[2]->store((longlong) type, TRUE);
 
512
  key_copy(key, table->record[0], table->key_info,
 
513
           table->key_info->key_length);
 
514
 
 
515
  if (table->file->index_read_idx_map(table->record[0], 0, key, HA_WHOLE_KEY,
 
516
                                      HA_READ_KEY_EXACT))
 
517
    DBUG_RETURN(SP_KEY_NOT_FOUND);
 
518
 
 
519
  DBUG_RETURN(SP_OK);
 
520
}
 
521
 
 
522
 
 
523
/**
 
524
  Find routine definition in mysql.proc table and create corresponding
 
525
  sp_head object for it.
 
526
 
 
527
  @param thd   Thread context
 
528
  @param type  Type of routine (TYPE_ENUM_PROCEDURE/...)
 
529
  @param name  Name of routine
 
530
  @param sphp  Out parameter in which pointer to created sp_head
 
531
               object is returned (0 in case of error).
 
532
 
 
533
  @note
 
534
    This function may damage current LEX during execution, so it is good
 
535
    idea to create temporary LEX and make it active before calling it.
 
536
 
 
537
  @retval
 
538
    0       Success
 
539
  @retval
 
540
    non-0   Error (may be one of special codes like SP_KEY_NOT_FOUND)
 
541
*/
 
542
 
 
543
static int
 
544
db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp)
 
545
{
 
546
  TABLE *table;
 
547
  const char *params, *returns, *body;
 
548
  int ret;
 
549
  const char *definer;
 
550
  longlong created;
 
551
  longlong modified;
 
552
  st_sp_chistics chistics;
 
553
  char *ptr;
 
554
  uint length;
 
555
  char buff[65];
 
556
  String str(buff, sizeof(buff), &my_charset_bin);
 
557
  bool saved_time_zone_used= thd->time_zone_used;
 
558
  ulong sql_mode, saved_mode= thd->variables.sql_mode;
 
559
  Open_tables_state open_tables_state_backup;
 
560
  Stored_program_creation_ctx *creation_ctx;
 
561
 
 
562
  DBUG_ENTER("db_find_routine");
 
563
  DBUG_PRINT("enter", ("type: %d name: %.*s",
 
564
                       type, (int) name->m_name.length, name->m_name.str));
 
565
 
 
566
  *sphp= 0;                                     // In case of errors
 
567
  if (!(table= open_proc_table_for_read(thd, &open_tables_state_backup)))
 
568
    DBUG_RETURN(SP_OPEN_TABLE_FAILED);
 
569
 
 
570
  /* Reset sql_mode during data dictionary operations. */
 
571
  thd->variables.sql_mode= 0;
 
572
 
 
573
  if ((ret= db_find_routine_aux(thd, type, name, table)) != SP_OK)
 
574
    goto done;
 
575
 
 
576
  if (table->s->fields < MYSQL_PROC_FIELD_COUNT)
 
577
  {
 
578
    ret= SP_GET_FIELD_FAILED;
 
579
    goto done;
 
580
  }
 
581
 
 
582
  bzero((char *)&chistics, sizeof(chistics));
 
583
  if ((ptr= get_field(thd->mem_root,
 
584
                      table->field[MYSQL_PROC_FIELD_ACCESS])) == NULL)
 
585
  {
 
586
    ret= SP_GET_FIELD_FAILED;
 
587
    goto done;
 
588
  }
 
589
  switch (ptr[0]) {
 
590
  case 'N':
 
591
    chistics.daccess= SP_NO_SQL;
 
592
    break;
 
593
  case 'C':
 
594
    chistics.daccess= SP_CONTAINS_SQL;
 
595
    break;
 
596
  case 'R':
 
597
    chistics.daccess= SP_READS_SQL_DATA;
 
598
    break;
 
599
  case 'M':
 
600
    chistics.daccess= SP_MODIFIES_SQL_DATA;
 
601
    break;
 
602
  default:
 
603
    chistics.daccess= SP_DEFAULT_ACCESS_MAPPING;
 
604
  }
 
605
 
 
606
  if ((ptr= get_field(thd->mem_root,
 
607
                      table->field[MYSQL_PROC_FIELD_DETERMINISTIC])) == NULL)
 
608
  {
 
609
    ret= SP_GET_FIELD_FAILED;
 
610
    goto done;
 
611
  }
 
612
  chistics.detistic= (ptr[0] == 'N' ? FALSE : TRUE);    
 
613
 
 
614
  if ((ptr= get_field(thd->mem_root,
 
615
                      table->field[MYSQL_PROC_FIELD_SECURITY_TYPE])) == NULL)
 
616
  {
 
617
    ret= SP_GET_FIELD_FAILED;
 
618
    goto done;
 
619
  }
 
620
  chistics.suid= (ptr[0] == 'I' ? SP_IS_NOT_SUID : SP_IS_SUID);
 
621
 
 
622
  if ((params= get_field(thd->mem_root,
 
623
                         table->field[MYSQL_PROC_FIELD_PARAM_LIST])) == NULL)
 
624
  {
 
625
    params= "";
 
626
  }
 
627
 
 
628
  if (type == TYPE_ENUM_PROCEDURE)
 
629
    returns= "";
 
630
  else if ((returns= get_field(thd->mem_root,
 
631
                               table->field[MYSQL_PROC_FIELD_RETURNS])) == NULL)
 
632
  {
 
633
    ret= SP_GET_FIELD_FAILED;
 
634
    goto done;
 
635
  }
 
636
 
 
637
  if ((body= get_field(thd->mem_root,
 
638
                       table->field[MYSQL_PROC_FIELD_BODY])) == NULL)
 
639
  {
 
640
    ret= SP_GET_FIELD_FAILED;
 
641
    goto done;
 
642
  }
 
643
 
 
644
  // Get additional information
 
645
  if ((definer= get_field(thd->mem_root,
 
646
                          table->field[MYSQL_PROC_FIELD_DEFINER])) == NULL)
 
647
  {
 
648
    ret= SP_GET_FIELD_FAILED;
 
649
    goto done;
 
650
  }
 
651
 
 
652
  modified= table->field[MYSQL_PROC_FIELD_MODIFIED]->val_int();
 
653
  created= table->field[MYSQL_PROC_FIELD_CREATED]->val_int();
 
654
 
 
655
  sql_mode= (ulong) table->field[MYSQL_PROC_FIELD_SQL_MODE]->val_int();
 
656
 
 
657
  table->field[MYSQL_PROC_FIELD_COMMENT]->val_str(&str, &str);
 
658
 
 
659
  ptr= 0;
 
660
  if ((length= str.length()))
 
661
    ptr= thd->strmake(str.ptr(), length);
 
662
  chistics.comment.str= ptr;
 
663
  chistics.comment.length= length;
 
664
 
 
665
  creation_ctx= Stored_routine_creation_ctx::load_from_db(thd, name, table);
 
666
 
 
667
  close_system_tables(thd, &open_tables_state_backup);
 
668
  table= 0;
 
669
 
 
670
  ret= db_load_routine(thd, type, name, sphp,
 
671
                       sql_mode, params, returns, body, chistics,
 
672
                       definer, created, modified, creation_ctx);
 
673
 done:
 
674
  /* 
 
675
    Restore the time zone flag as the timezone usage in proc table
 
676
    does not affect replication.
 
677
  */  
 
678
  thd->time_zone_used= saved_time_zone_used;
 
679
  if (table)
 
680
    close_system_tables(thd, &open_tables_state_backup);
 
681
  thd->variables.sql_mode= saved_mode;
 
682
  DBUG_RETURN(ret);
 
683
}
 
684
 
 
685
 
 
686
/**
 
687
  Silence DEPRECATED SYNTAX warnings when loading a stored procedure
 
688
  into the cache.
 
689
*/
 
690
struct Silence_deprecated_warning : public Internal_error_handler
 
691
{
 
692
public:
 
693
  virtual bool handle_error(uint sql_errno, const char *message,
 
694
                            MYSQL_ERROR::enum_warning_level level,
 
695
                            THD *thd);
 
696
};
 
697
 
 
698
bool
 
699
Silence_deprecated_warning::handle_error(uint sql_errno, const char *message,
 
700
                                         MYSQL_ERROR::enum_warning_level level,
 
701
                                         THD *thd)
 
702
{
 
703
  if (sql_errno == ER_WARN_DEPRECATED_SYNTAX &&
 
704
      level == MYSQL_ERROR::WARN_LEVEL_WARN)
 
705
    return TRUE;
 
706
 
 
707
  return FALSE;
 
708
}
 
709
 
 
710
 
 
711
static int
 
712
db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp,
 
713
                ulong sql_mode, const char *params, const char *returns,
 
714
                const char *body, st_sp_chistics &chistics,
 
715
                const char *definer, longlong created, longlong modified,
 
716
                Stored_program_creation_ctx *creation_ctx)
 
717
{
 
718
  LEX *old_lex= thd->lex, newlex;
 
719
  String defstr;
 
720
  char saved_cur_db_name_buf[NAME_LEN+1];
 
721
  LEX_STRING saved_cur_db_name=
 
722
    { saved_cur_db_name_buf, sizeof(saved_cur_db_name_buf) };
 
723
  bool cur_db_changed;
 
724
  ulong old_sql_mode= thd->variables.sql_mode;
 
725
  ha_rows old_select_limit= thd->variables.select_limit;
 
726
  sp_rcontext *old_spcont= thd->spcont;
 
727
  Silence_deprecated_warning warning_handler;
 
728
 
 
729
  char definer_user_name_holder[USERNAME_LENGTH + 1];
 
730
  LEX_STRING definer_user_name= { definer_user_name_holder,
 
731
                                  USERNAME_LENGTH };
 
732
 
 
733
  char definer_host_name_holder[HOSTNAME_LENGTH + 1];
 
734
  LEX_STRING definer_host_name= { definer_host_name_holder, HOSTNAME_LENGTH };
 
735
 
 
736
  int ret;
 
737
 
 
738
  thd->variables.sql_mode= sql_mode;
 
739
  thd->variables.select_limit= HA_POS_ERROR;
 
740
 
 
741
  thd->lex= &newlex;
 
742
  newlex.current_select= NULL;
 
743
 
 
744
  parse_user(definer, strlen(definer),
 
745
             definer_user_name.str, &definer_user_name.length,
 
746
             definer_host_name.str, &definer_host_name.length);
 
747
 
 
748
  defstr.set_charset(creation_ctx->get_client_cs());
 
749
 
 
750
  /*
 
751
    We have to add DEFINER clause and provide proper routine characterstics in
 
752
    routine definition statement that we build here to be able to use this
 
753
    definition for SHOW CREATE PROCEDURE later.
 
754
   */
 
755
 
 
756
  if (!create_string(thd, &defstr,
 
757
                     type,
 
758
                     NULL, 0,
 
759
                     name->m_name.str, name->m_name.length,
 
760
                     params, strlen(params),
 
761
                     returns, strlen(returns),
 
762
                     body, strlen(body),
 
763
                     &chistics, &definer_user_name, &definer_host_name))
 
764
  {
 
765
    ret= SP_INTERNAL_ERROR;
 
766
    goto end;
 
767
  }
 
768
 
 
769
  /*
 
770
    Change the current database (if needed).
 
771
 
 
772
    TODO: why do we force switch here?
 
773
  */
 
774
 
 
775
  if (mysql_opt_change_db(thd, &name->m_db, &saved_cur_db_name, TRUE,
 
776
                          &cur_db_changed))
 
777
  {
 
778
    ret= SP_INTERNAL_ERROR;
 
779
    goto end;
 
780
  }
 
781
 
 
782
  thd->spcont= NULL;
 
783
 
 
784
  {
 
785
    Parser_state parser_state(thd, defstr.c_ptr(), defstr.length());
 
786
 
 
787
    lex_start(thd);
 
788
 
 
789
    thd->push_internal_handler(&warning_handler);
 
790
    ret= parse_sql(thd, & parser_state, creation_ctx) || newlex.sphead == NULL;
 
791
    thd->pop_internal_handler();
 
792
 
 
793
    /*
 
794
      Force switching back to the saved current database (if changed),
 
795
      because it may be NULL. In this case, mysql_change_db() would
 
796
      generate an error.
 
797
    */
 
798
 
 
799
    if (cur_db_changed && mysql_change_db(thd, &saved_cur_db_name, TRUE))
 
800
    {
 
801
      delete newlex.sphead;
 
802
      ret= SP_INTERNAL_ERROR;
 
803
      goto end;
 
804
    }
 
805
 
 
806
    if (ret)
 
807
    {
 
808
      delete newlex.sphead;
 
809
      ret= SP_PARSE_ERROR;
 
810
      goto end;
 
811
    }
 
812
 
 
813
    *sphp= newlex.sphead;
 
814
    (*sphp)->set_definer(&definer_user_name, &definer_host_name);
 
815
    (*sphp)->set_info(created, modified, &chistics, sql_mode);
 
816
    (*sphp)->set_creation_ctx(creation_ctx);
 
817
    (*sphp)->optimize();
 
818
    /*
 
819
      Not strictly necessary to invoke this method here, since we know
 
820
      that we've parsed CREATE PROCEDURE/FUNCTION and not an
 
821
      UPDATE/DELETE/INSERT/REPLACE/LOAD/CREATE TABLE, but we try to
 
822
      maintain the invariant that this method is called for each
 
823
      distinct statement, in case its logic is extended with other
 
824
      types of analyses in future.
 
825
    */
 
826
    newlex.set_trg_event_type_for_tables();
 
827
  }
 
828
 
 
829
end:
 
830
  lex_end(thd->lex);
 
831
  thd->spcont= old_spcont;
 
832
  thd->variables.sql_mode= old_sql_mode;
 
833
  thd->variables.select_limit= old_select_limit;
 
834
  thd->lex= old_lex;
 
835
  return ret;
 
836
}
 
837
 
 
838
 
 
839
static void
 
840
sp_returns_type(THD *thd, String &result, sp_head *sp)
 
841
{
 
842
  TABLE table;
 
843
  TABLE_SHARE share;
 
844
  Field *field;
 
845
  bzero((char*) &table, sizeof(table));
 
846
  bzero((char*) &share, sizeof(share));
 
847
  table.in_use= thd;
 
848
  table.s = &share;
 
849
  field= sp->create_result_field(0, 0, &table);
 
850
  field->sql_type(result);
 
851
 
 
852
  if (field->has_charset())
 
853
  {
 
854
    result.append(STRING_WITH_LEN(" CHARSET "));
 
855
    result.append(field->charset()->csname);
 
856
  }
 
857
 
 
858
  delete field;
 
859
}
 
860
 
 
861
 
 
862
/**
 
863
  Write stored-routine object into mysql.proc.
 
864
 
 
865
  This operation stores attributes of the stored procedure/function into
 
866
  the mysql.proc.
 
867
 
 
868
  @param thd  Thread context.
 
869
  @param type Stored routine type
 
870
              (TYPE_ENUM_PROCEDURE or TYPE_ENUM_FUNCTION).
 
871
  @param sp   Stored routine object to store.
 
872
 
 
873
  @note Opens and closes the thread tables. Therefore assumes
 
874
  that there are no locked tables in this thread at the time of
 
875
  invocation.
 
876
  Unlike some other DDL statements, *does* close the tables
 
877
  in the end, since the call to this function is normally
 
878
  followed by an implicit grant (sp_grant_privileges())
 
879
  and this subsequent call opens and closes mysql.procs_priv.
 
880
 
 
881
  @return Error code. SP_OK is returned on success. Other
 
882
  SP_ constants are used to indicate about errors.
 
883
*/
 
884
 
 
885
int
 
886
sp_create_routine(THD *thd, int type, sp_head *sp)
 
887
{
 
888
  int ret;
 
889
  TABLE *table;
 
890
  char definer[USER_HOST_BUFF_SIZE];
 
891
  ulong saved_mode= thd->variables.sql_mode;
 
892
 
 
893
  CHARSET_INFO *db_cs= get_default_db_collation(thd, sp->m_db.str);
 
894
 
 
895
  enum_check_fields saved_count_cuted_fields;
 
896
 
 
897
  bool store_failed= FALSE;
 
898
 
 
899
  bool save_binlog_row_based;
 
900
 
 
901
  DBUG_ENTER("sp_create_routine");
 
902
  DBUG_PRINT("enter", ("type: %d  name: %.*s",type, (int) sp->m_name.length,
 
903
                       sp->m_name.str));
 
904
  String retstr(64);
 
905
  retstr.set_charset(system_charset_info);
 
906
 
 
907
  DBUG_ASSERT(type == TYPE_ENUM_PROCEDURE ||
 
908
              type == TYPE_ENUM_FUNCTION);
 
909
 
 
910
  /* Reset sql_mode during data dictionary operations. */
 
911
  thd->variables.sql_mode= 0;
 
912
 
 
913
  /*
 
914
    This statement will be replicated as a statement, even when using
 
915
    row-based replication.  The flag will be reset at the end of the
 
916
    statement.
 
917
  */
 
918
  save_binlog_row_based= thd->current_stmt_binlog_row_based;
 
919
  thd->clear_current_stmt_binlog_row_based();
 
920
 
 
921
  saved_count_cuted_fields= thd->count_cuted_fields;
 
922
  thd->count_cuted_fields= CHECK_FIELD_WARN;
 
923
 
 
924
  if (!(table= open_proc_table_for_update(thd)))
 
925
    ret= SP_OPEN_TABLE_FAILED;
 
926
  else
 
927
  {
 
928
    restore_record(table, s->default_values); // Get default values for fields
 
929
 
 
930
    /* NOTE: all needed privilege checks have been already done. */
 
931
    strxnmov(definer, sizeof(definer)-1, thd->lex->definer->user.str, "@",
 
932
            thd->lex->definer->host.str, NullS);
 
933
 
 
934
    if (table->s->fields < MYSQL_PROC_FIELD_COUNT)
 
935
    {
 
936
      ret= SP_GET_FIELD_FAILED;
 
937
      goto done;
 
938
    }
 
939
 
 
940
    if (system_charset_info->cset->numchars(system_charset_info,
 
941
                                            sp->m_name.str,
 
942
                                            sp->m_name.str+sp->m_name.length) >
 
943
        table->field[MYSQL_PROC_FIELD_NAME]->char_length())
 
944
    {
 
945
      ret= SP_BAD_IDENTIFIER;
 
946
      goto done;
 
947
    }
 
948
    if (sp->m_body.length > table->field[MYSQL_PROC_FIELD_BODY]->field_length)
 
949
    {
 
950
      ret= SP_BODY_TOO_LONG;
 
951
      goto done;
 
952
    }
 
953
 
 
954
    store_failed=
 
955
      table->field[MYSQL_PROC_FIELD_DB]->
 
956
        store(sp->m_db.str, sp->m_db.length, system_charset_info);
 
957
 
 
958
    store_failed= store_failed ||
 
959
      table->field[MYSQL_PROC_FIELD_NAME]->
 
960
        store(sp->m_name.str, sp->m_name.length, system_charset_info);
 
961
 
 
962
    store_failed= store_failed ||
 
963
      table->field[MYSQL_PROC_MYSQL_TYPE]->
 
964
        store((longlong)type, TRUE);
 
965
 
 
966
    store_failed= store_failed ||
 
967
      table->field[MYSQL_PROC_FIELD_SPECIFIC_NAME]->
 
968
        store(sp->m_name.str, sp->m_name.length, system_charset_info);
 
969
 
 
970
    if (sp->m_chistics->daccess != SP_DEFAULT_ACCESS)
 
971
    {
 
972
      store_failed= store_failed ||
 
973
        table->field[MYSQL_PROC_FIELD_ACCESS]->
 
974
          store((longlong)sp->m_chistics->daccess, TRUE);
 
975
    }
 
976
 
 
977
    store_failed= store_failed ||
 
978
      table->field[MYSQL_PROC_FIELD_DETERMINISTIC]->
 
979
        store((longlong)(sp->m_chistics->detistic ? 1 : 2), TRUE);
 
980
 
 
981
    if (sp->m_chistics->suid != SP_IS_DEFAULT_SUID)
 
982
    {
 
983
      store_failed= store_failed ||
 
984
        table->field[MYSQL_PROC_FIELD_SECURITY_TYPE]->
 
985
          store((longlong)sp->m_chistics->suid, TRUE);
 
986
    }
 
987
 
 
988
    store_failed= store_failed ||
 
989
      table->field[MYSQL_PROC_FIELD_PARAM_LIST]->
 
990
        store(sp->m_params.str, sp->m_params.length, system_charset_info);
 
991
 
 
992
    if (sp->m_type == TYPE_ENUM_FUNCTION)
 
993
    {
 
994
      sp_returns_type(thd, retstr, sp);
 
995
 
 
996
      store_failed= store_failed ||
 
997
        table->field[MYSQL_PROC_FIELD_RETURNS]->
 
998
          store(retstr.ptr(), retstr.length(), system_charset_info);
 
999
    }
 
1000
 
 
1001
    store_failed= store_failed ||
 
1002
      table->field[MYSQL_PROC_FIELD_BODY]->
 
1003
        store(sp->m_body.str, sp->m_body.length, system_charset_info);
 
1004
 
 
1005
    store_failed= store_failed ||
 
1006
      table->field[MYSQL_PROC_FIELD_DEFINER]->
 
1007
        store(definer, (uint)strlen(definer), system_charset_info);
 
1008
 
 
1009
    ((Field_timestamp *)table->field[MYSQL_PROC_FIELD_CREATED])->set_time();
 
1010
    ((Field_timestamp *)table->field[MYSQL_PROC_FIELD_MODIFIED])->set_time();
 
1011
 
 
1012
    store_failed= store_failed ||
 
1013
      table->field[MYSQL_PROC_FIELD_SQL_MODE]->
 
1014
        store((longlong)saved_mode, TRUE);
 
1015
 
 
1016
    if (sp->m_chistics->comment.str)
 
1017
    {
 
1018
      store_failed= store_failed ||
 
1019
        table->field[MYSQL_PROC_FIELD_COMMENT]->
 
1020
          store(sp->m_chistics->comment.str, sp->m_chistics->comment.length,
 
1021
                system_charset_info);
 
1022
    }
 
1023
 
 
1024
    if ((sp->m_type == TYPE_ENUM_FUNCTION) &&
 
1025
        !trust_function_creators && mysql_bin_log.is_open())
 
1026
    {
 
1027
      if (!sp->m_chistics->detistic)
 
1028
      {
 
1029
        /*
 
1030
          Note that this test is not perfect; one could use
 
1031
          a non-deterministic read-only function in an update statement.
 
1032
        */
 
1033
        enum enum_sp_data_access access=
 
1034
          (sp->m_chistics->daccess == SP_DEFAULT_ACCESS) ?
 
1035
          SP_DEFAULT_ACCESS_MAPPING : sp->m_chistics->daccess;
 
1036
        if (access == SP_CONTAINS_SQL ||
 
1037
            access == SP_MODIFIES_SQL_DATA)
 
1038
        {
 
1039
          my_message(ER_BINLOG_UNSAFE_ROUTINE,
 
1040
                     ER(ER_BINLOG_UNSAFE_ROUTINE), MYF(0));
 
1041
          ret= SP_INTERNAL_ERROR;
 
1042
          goto done;
 
1043
        }
 
1044
      }
 
1045
      if (!(thd->security_ctx->master_access & SUPER_ACL))
 
1046
      {
 
1047
        my_message(ER_BINLOG_CREATE_ROUTINE_NEED_SUPER,
 
1048
                   ER(ER_BINLOG_CREATE_ROUTINE_NEED_SUPER), MYF(0));
 
1049
        ret= SP_INTERNAL_ERROR;
 
1050
        goto done;
 
1051
      }
 
1052
    }
 
1053
 
 
1054
    table->field[MYSQL_PROC_FIELD_CHARACTER_SET_CLIENT]->set_notnull();
 
1055
    store_failed= store_failed ||
 
1056
      table->field[MYSQL_PROC_FIELD_CHARACTER_SET_CLIENT]->store(
 
1057
        thd->charset()->csname,
 
1058
        strlen(thd->charset()->csname),
 
1059
        system_charset_info);
 
1060
 
 
1061
    table->field[MYSQL_PROC_FIELD_COLLATION_CONNECTION]->set_notnull();
 
1062
    store_failed= store_failed ||
 
1063
      table->field[MYSQL_PROC_FIELD_COLLATION_CONNECTION]->store(
 
1064
        thd->variables.collation_connection->name,
 
1065
        strlen(thd->variables.collation_connection->name),
 
1066
        system_charset_info);
 
1067
 
 
1068
    table->field[MYSQL_PROC_FIELD_DB_COLLATION]->set_notnull();
 
1069
    store_failed= store_failed ||
 
1070
      table->field[MYSQL_PROC_FIELD_DB_COLLATION]->store(
 
1071
        db_cs->name, strlen(db_cs->name), system_charset_info);
 
1072
 
 
1073
    table->field[MYSQL_PROC_FIELD_BODY_UTF8]->set_notnull();
 
1074
    store_failed= store_failed ||
 
1075
      table->field[MYSQL_PROC_FIELD_BODY_UTF8]->store(
 
1076
        sp->m_body_utf8.str, sp->m_body_utf8.length, system_charset_info);
 
1077
 
 
1078
    if (store_failed)
 
1079
    {
 
1080
      ret= SP_FLD_STORE_FAILED;
 
1081
      goto done;
 
1082
    }
 
1083
 
 
1084
    ret= SP_OK;
 
1085
    if (table->file->ha_write_row(table->record[0]))
 
1086
      ret= SP_WRITE_ROW_FAILED;
 
1087
    else if (mysql_bin_log.is_open())
 
1088
    {
 
1089
      thd->clear_error();
 
1090
 
 
1091
      String log_query;
 
1092
      log_query.set_charset(system_charset_info);
 
1093
 
 
1094
      if (!create_string(thd, &log_query,
 
1095
                         sp->m_type,
 
1096
                         (sp->m_explicit_name ? sp->m_db.str : NULL), 
 
1097
                         (sp->m_explicit_name ? sp->m_db.length : 0), 
 
1098
                         sp->m_name.str, sp->m_name.length,
 
1099
                         sp->m_params.str, sp->m_params.length,
 
1100
                         retstr.c_ptr(), retstr.length(),
 
1101
                         sp->m_body.str, sp->m_body.length,
 
1102
                         sp->m_chistics, &(thd->lex->definer->user),
 
1103
                         &(thd->lex->definer->host)))
 
1104
      {
 
1105
        ret= SP_INTERNAL_ERROR;
 
1106
        goto done;
 
1107
      }
 
1108
      /* restore sql_mode when binloging */
 
1109
      thd->variables.sql_mode= saved_mode;
 
1110
      /* Such a statement can always go directly to binlog, no trans cache */
 
1111
      if (thd->binlog_query(THD::MYSQL_QUERY_TYPE,
 
1112
                            log_query.c_ptr(), log_query.length(),
 
1113
                            FALSE, FALSE, 0))
 
1114
        ret= SP_INTERNAL_ERROR;
 
1115
      thd->variables.sql_mode= 0;
 
1116
    }
 
1117
 
 
1118
  }
 
1119
 
 
1120
done:
 
1121
  thd->count_cuted_fields= saved_count_cuted_fields;
 
1122
  thd->variables.sql_mode= saved_mode;
 
1123
 
 
1124
  close_thread_tables(thd);
 
1125
  /* Restore the state of binlog format */
 
1126
  thd->current_stmt_binlog_row_based= save_binlog_row_based;
 
1127
  DBUG_RETURN(ret);
 
1128
}
 
1129
 
 
1130
 
 
1131
/**
 
1132
  Delete the record for the stored routine object from mysql.proc.
 
1133
 
 
1134
  The operation deletes the record for the stored routine specified by name
 
1135
  from the mysql.proc table and invalidates the stored-routine cache.
 
1136
 
 
1137
  @param thd  Thread context.
 
1138
  @param type Stored routine type
 
1139
              (TYPE_ENUM_PROCEDURE or TYPE_ENUM_FUNCTION)
 
1140
  @param name Stored routine name.
 
1141
 
 
1142
  @return Error code. SP_OK is returned on success. Other SP_ constants are
 
1143
  used to indicate about errors.
 
1144
*/
 
1145
 
 
1146
int
 
1147
sp_drop_routine(THD *thd, int type, sp_name *name)
 
1148
{
 
1149
  TABLE *table;
 
1150
  int ret;
 
1151
  bool save_binlog_row_based;
 
1152
  DBUG_ENTER("sp_drop_routine");
 
1153
  DBUG_PRINT("enter", ("type: %d  name: %.*s",
 
1154
                       type, (int) name->m_name.length, name->m_name.str));
 
1155
 
 
1156
  DBUG_ASSERT(type == TYPE_ENUM_PROCEDURE ||
 
1157
              type == TYPE_ENUM_FUNCTION);
 
1158
 
 
1159
  /*
 
1160
    This statement will be replicated as a statement, even when using
 
1161
    row-based replication.  The flag will be reset at the end of the
 
1162
    statement.
 
1163
  */
 
1164
  save_binlog_row_based= thd->current_stmt_binlog_row_based;
 
1165
  thd->clear_current_stmt_binlog_row_based();
 
1166
 
 
1167
  if (!(table= open_proc_table_for_update(thd)))
 
1168
    DBUG_RETURN(SP_OPEN_TABLE_FAILED);
 
1169
  if ((ret= db_find_routine_aux(thd, type, name, table)) == SP_OK)
 
1170
  {
 
1171
    if (table->file->ha_delete_row(table->record[0]))
 
1172
      ret= SP_DELETE_ROW_FAILED;
 
1173
  }
 
1174
 
 
1175
  if (ret == SP_OK)
 
1176
  {
 
1177
    if (write_bin_log(thd, TRUE, thd->query(), thd->query_length()))
 
1178
      ret= SP_INTERNAL_ERROR;
 
1179
    sp_cache_invalidate();
 
1180
  }
 
1181
 
 
1182
  close_thread_tables(thd);
 
1183
  /* Restore the state of binlog format */
 
1184
  thd->current_stmt_binlog_row_based= save_binlog_row_based;
 
1185
  DBUG_RETURN(ret);
 
1186
}
 
1187
 
 
1188
 
 
1189
/**
 
1190
  Find and updated the record for the stored routine object in mysql.proc.
 
1191
 
 
1192
  The operation finds the record for the stored routine specified by name
 
1193
  in the mysql.proc table and updates it with new attributes. After
 
1194
  successful update, the cache is invalidated.
 
1195
 
 
1196
  @param thd      Thread context.
 
1197
  @param type     Stored routine type
 
1198
                  (TYPE_ENUM_PROCEDURE or TYPE_ENUM_FUNCTION)
 
1199
  @param name     Stored routine name.
 
1200
  @param chistics New values of stored routine attributes to write.
 
1201
 
 
1202
  @return Error code. SP_OK is returned on success. Other SP_ constants are
 
1203
  used to indicate about errors.
 
1204
*/
 
1205
 
 
1206
int
 
1207
sp_update_routine(THD *thd, int type, sp_name *name, st_sp_chistics *chistics)
 
1208
{
 
1209
  TABLE *table;
 
1210
  int ret;
 
1211
  bool save_binlog_row_based;
 
1212
  DBUG_ENTER("sp_update_routine");
 
1213
  DBUG_PRINT("enter", ("type: %d  name: %.*s",
 
1214
                       type, (int) name->m_name.length, name->m_name.str));
 
1215
 
 
1216
  DBUG_ASSERT(type == TYPE_ENUM_PROCEDURE ||
 
1217
              type == TYPE_ENUM_FUNCTION);
 
1218
  /*
 
1219
    This statement will be replicated as a statement, even when using
 
1220
    row-based replication. The flag will be reset at the end of the
 
1221
    statement.
 
1222
  */
 
1223
  save_binlog_row_based= thd->current_stmt_binlog_row_based;
 
1224
  thd->clear_current_stmt_binlog_row_based();
 
1225
 
 
1226
  if (!(table= open_proc_table_for_update(thd)))
 
1227
    DBUG_RETURN(SP_OPEN_TABLE_FAILED);
 
1228
  if ((ret= db_find_routine_aux(thd, type, name, table)) == SP_OK)
 
1229
  {
 
1230
    store_record(table,record[1]);
 
1231
    table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
 
1232
    ((Field_timestamp *)table->field[MYSQL_PROC_FIELD_MODIFIED])->set_time();
 
1233
    if (chistics->suid != SP_IS_DEFAULT_SUID)
 
1234
      table->field[MYSQL_PROC_FIELD_SECURITY_TYPE]->
 
1235
        store((longlong)chistics->suid, TRUE);
 
1236
    if (chistics->daccess != SP_DEFAULT_ACCESS)
 
1237
      table->field[MYSQL_PROC_FIELD_ACCESS]->
 
1238
        store((longlong)chistics->daccess, TRUE);
 
1239
    if (chistics->comment.str)
 
1240
      table->field[MYSQL_PROC_FIELD_COMMENT]->store(chistics->comment.str,
 
1241
                                                    chistics->comment.length,
 
1242
                                                    system_charset_info);
 
1243
    if ((ret= table->file->ha_update_row(table->record[1],table->record[0])) &&
 
1244
        ret != HA_ERR_RECORD_IS_THE_SAME)
 
1245
      ret= SP_WRITE_ROW_FAILED;
 
1246
    else
 
1247
      ret= 0;
 
1248
  }
 
1249
 
 
1250
  if (ret == SP_OK)
 
1251
  {
 
1252
    if (write_bin_log(thd, TRUE, thd->query(), thd->query_length()))
 
1253
      ret= SP_INTERNAL_ERROR;
 
1254
    sp_cache_invalidate();
 
1255
  }
 
1256
 
 
1257
  close_thread_tables(thd);
 
1258
  /* Restore the state of binlog format */
 
1259
  thd->current_stmt_binlog_row_based= save_binlog_row_based;
 
1260
  DBUG_RETURN(ret);
 
1261
}
 
1262
 
 
1263
 
 
1264
/**
 
1265
  Drop all routines in database 'db'
 
1266
 
 
1267
  @note Close the thread tables, the calling code might want to
 
1268
  delete from other system tables afterwards.
 
1269
*/
 
1270
 
 
1271
int
 
1272
sp_drop_db_routines(THD *thd, char *db)
 
1273
{
 
1274
  TABLE *table;
 
1275
  int ret;
 
1276
  uint key_len;
 
1277
  DBUG_ENTER("sp_drop_db_routines");
 
1278
  DBUG_PRINT("enter", ("db: %s", db));
 
1279
 
 
1280
  ret= SP_OPEN_TABLE_FAILED;
 
1281
  if (!(table= open_proc_table_for_update(thd)))
 
1282
    goto err;
 
1283
 
 
1284
  table->field[MYSQL_PROC_FIELD_DB]->store(db, strlen(db), system_charset_info);
 
1285
  key_len= table->key_info->key_part[0].store_length;
 
1286
 
 
1287
  ret= SP_OK;
 
1288
  table->file->ha_index_init(0, 1);
 
1289
  if (! table->file->index_read_map(table->record[0],
 
1290
                                    (uchar *)table->field[MYSQL_PROC_FIELD_DB]->ptr,
 
1291
                                    (key_part_map)1, HA_READ_KEY_EXACT))
 
1292
  {
 
1293
    int nxtres;
 
1294
    bool deleted= FALSE;
 
1295
 
 
1296
    do
 
1297
    {
 
1298
      if (! table->file->ha_delete_row(table->record[0]))
 
1299
        deleted= TRUE;          /* We deleted something */
 
1300
      else
 
1301
      {
 
1302
        ret= SP_DELETE_ROW_FAILED;
 
1303
        nxtres= 0;
 
1304
        break;
 
1305
      }
 
1306
    } while (! (nxtres= table->file->index_next_same(table->record[0],
 
1307
                                (uchar *)table->field[MYSQL_PROC_FIELD_DB]->ptr,
 
1308
                                                     key_len)));
 
1309
    if (nxtres != HA_ERR_END_OF_FILE)
 
1310
      ret= SP_KEY_NOT_FOUND;
 
1311
    if (deleted)
 
1312
      sp_cache_invalidate();
 
1313
  }
 
1314
  table->file->ha_index_end();
 
1315
 
 
1316
  close_thread_tables(thd);
 
1317
 
 
1318
err:
 
1319
  DBUG_RETURN(ret);
 
1320
}
 
1321
 
 
1322
 
 
1323
/**
 
1324
  Implement SHOW CREATE statement for stored routines.
 
1325
 
 
1326
  The operation finds the stored routine object specified by name and then
 
1327
  calls sp_head::show_create_routine() for the object.
 
1328
 
 
1329
  @param thd  Thread context.
 
1330
  @param type Stored routine type
 
1331
              (TYPE_ENUM_PROCEDURE or TYPE_ENUM_FUNCTION)
 
1332
  @param name Stored routine name.
 
1333
 
 
1334
  @return Error status.
 
1335
    @retval FALSE on success
 
1336
    @retval TRUE on error
 
1337
*/
 
1338
 
 
1339
bool
 
1340
sp_show_create_routine(THD *thd, int type, sp_name *name)
 
1341
{
 
1342
  bool err_status= TRUE;
 
1343
  sp_head *sp;
 
1344
  sp_cache **cache = type == TYPE_ENUM_PROCEDURE ?
 
1345
                     &thd->sp_proc_cache : &thd->sp_func_cache;
 
1346
 
 
1347
  DBUG_ENTER("sp_show_create_routine");
 
1348
  DBUG_PRINT("enter", ("name: %.*s",
 
1349
                       (int) name->m_name.length,
 
1350
                       name->m_name.str));
 
1351
 
 
1352
  DBUG_ASSERT(type == TYPE_ENUM_PROCEDURE ||
 
1353
              type == TYPE_ENUM_FUNCTION);
 
1354
 
 
1355
  if (type == TYPE_ENUM_PROCEDURE)
 
1356
  {
 
1357
    /*
 
1358
       SHOW CREATE PROCEDURE may require two instances of one sp_head
 
1359
       object when SHOW CREATE PROCEDURE is called for the procedure that
 
1360
       is being executed. Basically, there is no actual recursion, so we
 
1361
       increase the recursion limit for this statement (kind of hack).
 
1362
 
 
1363
       SHOW CREATE FUNCTION does not require this because SHOW CREATE
 
1364
       statements are prohibitted within stored functions.
 
1365
     */
 
1366
 
 
1367
    thd->variables.max_sp_recursion_depth++;
 
1368
  }
 
1369
 
 
1370
  if ((sp= sp_find_routine(thd, type, name, cache, FALSE)))
 
1371
    err_status= sp->show_create_routine(thd, type);
 
1372
 
 
1373
  if (type == TYPE_ENUM_PROCEDURE)
 
1374
    thd->variables.max_sp_recursion_depth--;
 
1375
 
 
1376
  DBUG_RETURN(err_status);
 
1377
}
 
1378
 
 
1379
 
 
1380
/**
 
1381
  Obtain object representing stored procedure/function by its name from
 
1382
  stored procedures cache and looking into mysql.proc if needed.
 
1383
 
 
1384
  @param thd          thread context
 
1385
  @param type         type of object (TYPE_ENUM_FUNCTION or TYPE_ENUM_PROCEDURE)
 
1386
  @param name         name of procedure
 
1387
  @param cp           hash to look routine in
 
1388
  @param cache_only   if true perform cache-only lookup
 
1389
                      (Don't look in mysql.proc).
 
1390
 
 
1391
  @retval
 
1392
    NonNULL pointer to sp_head object for the procedure
 
1393
  @retval
 
1394
    NULL    in case of error.
 
1395
*/
 
1396
 
 
1397
sp_head *
 
1398
sp_find_routine(THD *thd, int type, sp_name *name, sp_cache **cp,
 
1399
                bool cache_only)
 
1400
{
 
1401
  sp_head *sp;
 
1402
  ulong depth= (type == TYPE_ENUM_PROCEDURE ?
 
1403
                thd->variables.max_sp_recursion_depth :
 
1404
                0);
 
1405
  DBUG_ENTER("sp_find_routine");
 
1406
  DBUG_PRINT("enter", ("name:  %.*s.%.*s  type: %d  cache only %d",
 
1407
                       (int) name->m_db.length, name->m_db.str,
 
1408
                       (int) name->m_name.length, name->m_name.str,
 
1409
                       type, cache_only));
 
1410
 
 
1411
  if ((sp= sp_cache_lookup(cp, name)))
 
1412
  {
 
1413
    ulong level;
 
1414
    sp_head *new_sp;
 
1415
    const char *returns= "";
 
1416
    char definer[USER_HOST_BUFF_SIZE];
 
1417
 
 
1418
    /*
 
1419
      String buffer for RETURNS data type must have system charset;
 
1420
      64 -- size of "returns" column of mysql.proc.
 
1421
    */
 
1422
    String retstr(64);
 
1423
    retstr.set_charset(sp->get_creation_ctx()->get_client_cs());
 
1424
 
 
1425
    DBUG_PRINT("info", ("found: 0x%lx", (ulong)sp));
 
1426
    if (sp->m_first_free_instance)
 
1427
    {
 
1428
      DBUG_PRINT("info", ("first free: 0x%lx  level: %lu  flags %x",
 
1429
                          (ulong)sp->m_first_free_instance,
 
1430
                          sp->m_first_free_instance->m_recursion_level,
 
1431
                          sp->m_first_free_instance->m_flags));
 
1432
      DBUG_ASSERT(!(sp->m_first_free_instance->m_flags & sp_head::IS_INVOKED));
 
1433
      if (sp->m_first_free_instance->m_recursion_level > depth)
 
1434
      {
 
1435
        sp->recursion_level_error(thd);
 
1436
        DBUG_RETURN(0);
 
1437
      }
 
1438
      DBUG_RETURN(sp->m_first_free_instance);
 
1439
    }
 
1440
    /*
 
1441
      Actually depth could be +1 than the actual value in case a SP calls
 
1442
      SHOW CREATE PROCEDURE. Hence, the linked list could hold up to one more
 
1443
      instance.
 
1444
    */
 
1445
 
 
1446
    level= sp->m_last_cached_sp->m_recursion_level + 1;
 
1447
    if (level > depth)
 
1448
    {
 
1449
      sp->recursion_level_error(thd);
 
1450
      DBUG_RETURN(0);
 
1451
    }
 
1452
 
 
1453
    strxmov(definer, sp->m_definer_user.str, "@",
 
1454
            sp->m_definer_host.str, NullS);
 
1455
    if (type == TYPE_ENUM_FUNCTION)
 
1456
    {
 
1457
      sp_returns_type(thd, retstr, sp);
 
1458
      returns= retstr.ptr();
 
1459
    }
 
1460
    if (db_load_routine(thd, type, name, &new_sp,
 
1461
                        sp->m_sql_mode, sp->m_params.str, returns,
 
1462
                        sp->m_body.str, *sp->m_chistics, definer,
 
1463
                        sp->m_created, sp->m_modified,
 
1464
                        sp->get_creation_ctx()) == SP_OK)
 
1465
    {
 
1466
      sp->m_last_cached_sp->m_next_cached_sp= new_sp;
 
1467
      new_sp->m_recursion_level= level;
 
1468
      new_sp->m_first_instance= sp;
 
1469
      sp->m_last_cached_sp= sp->m_first_free_instance= new_sp;
 
1470
      DBUG_PRINT("info", ("added level: 0x%lx, level: %lu, flags %x",
 
1471
                          (ulong)new_sp, new_sp->m_recursion_level,
 
1472
                          new_sp->m_flags));
 
1473
      DBUG_RETURN(new_sp);
 
1474
    }
 
1475
    DBUG_RETURN(0);
 
1476
  }
 
1477
  if (!cache_only)
 
1478
  {
 
1479
    if (db_find_routine(thd, type, name, &sp) == SP_OK)
 
1480
    {
 
1481
      sp_cache_insert(cp, sp);
 
1482
      DBUG_PRINT("info", ("added new: 0x%lx, level: %lu, flags %x",
 
1483
                          (ulong)sp, sp->m_recursion_level,
 
1484
                          sp->m_flags));
 
1485
    }
 
1486
  }
 
1487
  DBUG_RETURN(sp);
 
1488
}
 
1489
 
 
1490
 
 
1491
/**
 
1492
  This is used by sql_acl.cc:mysql_routine_grant() and is used to find
 
1493
  the routines in 'routines'.
 
1494
 
 
1495
  @param thd Thread handler
 
1496
  @param routines List of needles in the hay stack
 
1497
  @param any Any of the needles are good enough
 
1498
 
 
1499
  @return
 
1500
    @retval FALSE Found.
 
1501
    @retval TRUE  Not found
 
1502
*/
 
1503
 
 
1504
bool
 
1505
sp_exist_routines(THD *thd, TABLE_LIST *routines, bool any)
 
1506
{
 
1507
  TABLE_LIST *routine;
 
1508
  bool sp_object_found;
 
1509
  DBUG_ENTER("sp_exists_routine");
 
1510
  for (routine= routines; routine; routine= routine->next_global)
 
1511
  {
 
1512
    sp_name *name;
 
1513
    LEX_STRING lex_db;
 
1514
    LEX_STRING lex_name;
 
1515
    lex_db.length= strlen(routine->db);
 
1516
    lex_name.length= strlen(routine->table_name);
 
1517
    lex_db.str= thd->strmake(routine->db, lex_db.length);
 
1518
    lex_name.str= thd->strmake(routine->table_name, lex_name.length);
 
1519
    name= new sp_name(lex_db, lex_name, true);
 
1520
    name->init_qname(thd);
 
1521
    sp_object_found= sp_find_routine(thd, TYPE_ENUM_PROCEDURE, name,
 
1522
                                     &thd->sp_proc_cache, FALSE) != NULL ||
 
1523
                     sp_find_routine(thd, TYPE_ENUM_FUNCTION, name,
 
1524
                                     &thd->sp_func_cache, FALSE) != NULL;
 
1525
    mysql_reset_errors(thd, TRUE);
 
1526
    if (sp_object_found)
 
1527
    {
 
1528
      if (any)
 
1529
        break;
 
1530
    }
 
1531
    else if (!any)
 
1532
    {
 
1533
      my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION or PROCEDURE",
 
1534
               routine->table_name);
 
1535
      DBUG_RETURN(TRUE);
 
1536
    }
 
1537
  }
 
1538
  DBUG_RETURN(FALSE);
 
1539
}
 
1540
 
 
1541
 
 
1542
/**
 
1543
  Check if a routine exists in the mysql.proc table, without actually
 
1544
  parsing the definition. (Used for dropping).
 
1545
 
 
1546
  @param thd          thread context
 
1547
  @param name         name of procedure
 
1548
 
 
1549
  @retval
 
1550
    0       Success
 
1551
  @retval
 
1552
    non-0   Error;  SP_OPEN_TABLE_FAILED or SP_KEY_NOT_FOUND
 
1553
*/
 
1554
 
 
1555
int
 
1556
sp_routine_exists_in_table(THD *thd, int type, sp_name *name)
 
1557
{
 
1558
  TABLE *table;
 
1559
  int ret;
 
1560
  Open_tables_state open_tables_state_backup;
 
1561
 
 
1562
  if (!(table= open_proc_table_for_read(thd, &open_tables_state_backup)))
 
1563
    ret= SP_OPEN_TABLE_FAILED;
 
1564
  else
 
1565
  {
 
1566
    if ((ret= db_find_routine_aux(thd, type, name, table)) != SP_OK)
 
1567
      ret= SP_KEY_NOT_FOUND;
 
1568
    close_system_tables(thd, &open_tables_state_backup);
 
1569
  }
 
1570
  return ret;
 
1571
}
 
1572
 
 
1573
 
 
1574
/**
 
1575
  Structure that represents element in the set of stored routines
 
1576
  used by statement or routine.
 
1577
*/
 
1578
struct Sroutine_hash_entry;
 
1579
 
 
1580
struct Sroutine_hash_entry
 
1581
{
 
1582
  /**
 
1583
    Set key consisting of one-byte routine type and quoted routine name.
 
1584
  */
 
1585
  LEX_STRING key;
 
1586
  /**
 
1587
    Next element in list linking all routines in set. See also comments
 
1588
    for LEX::sroutine/sroutine_list and sp_head::m_sroutines.
 
1589
  */
 
1590
  Sroutine_hash_entry *next;
 
1591
  /**
 
1592
    Uppermost view which directly or indirectly uses this routine.
 
1593
    0 if routine is not used in view. Note that it also can be 0 if
 
1594
    statement uses routine both via view and directly.
 
1595
  */
 
1596
  TABLE_LIST *belong_to_view;
 
1597
};
 
1598
 
 
1599
 
 
1600
extern "C" uchar* sp_sroutine_key(const uchar *ptr, size_t *plen,
 
1601
                                  my_bool first)
 
1602
{
 
1603
  Sroutine_hash_entry *rn= (Sroutine_hash_entry *)ptr;
 
1604
  *plen= rn->key.length;
 
1605
  return (uchar *)rn->key.str;
 
1606
}
 
1607
 
 
1608
 
 
1609
/**
 
1610
  Check if
 
1611
   - current statement (the one in thd->lex) needs table prelocking
 
1612
   - first routine in thd->lex->sroutines_list needs to execute its body in
 
1613
     prelocked mode.
 
1614
 
 
1615
  @param thd                  Current thread, thd->lex is the statement to be
 
1616
                              checked.
 
1617
  @param[out] need_prelocking    TRUE  - prelocked mode should be activated
 
1618
                                 before executing the statement; 
 
1619
                                 FALSE - Don't activate prelocking
 
1620
  @param[out] first_no_prelocking  TRUE  - Tables used by first routine in
 
1621
                                   thd->lex->sroutines_list should be
 
1622
                                   prelocked. FALSE - Otherwise.
 
1623
 
 
1624
  @note
 
1625
    This function assumes that for any "CALL proc(...)" statement routines_list 
 
1626
    will have 'proc' as first element (it may have several, consider e.g.
 
1627
    "proc(sp_func(...)))". This property is currently guaranted by the parser.
 
1628
*/
 
1629
 
 
1630
void sp_get_prelocking_info(THD *thd, bool *need_prelocking, 
 
1631
                            bool *first_no_prelocking)
 
1632
{
 
1633
  Sroutine_hash_entry *routine;
 
1634
  routine= (Sroutine_hash_entry*)thd->lex->sroutines_list.first;
 
1635
 
 
1636
  DBUG_ASSERT(routine);
 
1637
  bool first_is_procedure= (routine->key.str[0] == TYPE_ENUM_PROCEDURE);
 
1638
 
 
1639
  *first_no_prelocking= first_is_procedure;
 
1640
  *need_prelocking= !first_is_procedure || test(routine->next);
 
1641
}
 
1642
 
 
1643
 
 
1644
/**
 
1645
  Auxilary function that adds new element to the set of stored routines
 
1646
  used by statement.
 
1647
 
 
1648
  In case when statement uses stored routines but does not need
 
1649
  prelocking (i.e. it does not use any tables) we will access the
 
1650
  elements of LEX::sroutines set on prepared statement re-execution.
 
1651
  Because of this we have to allocate memory for both hash element
 
1652
  and copy of its key in persistent arena.
 
1653
 
 
1654
  @param lex             LEX representing statement
 
1655
  @param arena           Arena in which memory for new element will be
 
1656
                         allocated
 
1657
  @param key             Key for the hash representing set
 
1658
  @param belong_to_view  Uppermost view which uses this routine
 
1659
                         (0 if routine is not used by view)
 
1660
 
 
1661
  @note
 
1662
    Will also add element to end of 'LEX::sroutines_list' list.
 
1663
 
 
1664
  @todo
 
1665
    When we will got rid of these accesses on re-executions we will be
 
1666
    able to allocate memory for hash elements in non-persitent arena
 
1667
    and directly use key values from sp_head::m_sroutines sets instead
 
1668
    of making their copies.
 
1669
 
 
1670
  @retval
 
1671
    TRUE   new element was added.
 
1672
  @retval
 
1673
    FALSE  element was not added (because it is already present in
 
1674
    the set).
 
1675
*/
 
1676
 
 
1677
static bool add_used_routine(LEX *lex, Query_arena *arena,
 
1678
                             const LEX_STRING *key,
 
1679
                             TABLE_LIST *belong_to_view)
 
1680
{
 
1681
  hash_init_opt(&lex->sroutines, system_charset_info,
 
1682
                Query_tables_list::START_SROUTINES_HASH_SIZE,
 
1683
                0, 0, sp_sroutine_key, 0, 0);
 
1684
 
 
1685
  if (!hash_search(&lex->sroutines, (uchar *)key->str, key->length))
 
1686
  {
 
1687
    Sroutine_hash_entry *rn=
 
1688
      (Sroutine_hash_entry *)arena->alloc(sizeof(Sroutine_hash_entry) +
 
1689
                                          key->length + 1);
 
1690
    if (!rn)              // OOM. Error will be reported using fatal_error().
 
1691
      return FALSE;
 
1692
    rn->key.length= key->length;
 
1693
    rn->key.str= (char *)rn + sizeof(Sroutine_hash_entry);
 
1694
    memcpy(rn->key.str, key->str, key->length + 1);
 
1695
    if (my_hash_insert(&lex->sroutines, (uchar *)rn))
 
1696
      return FALSE;
 
1697
    lex->sroutines_list.link_in_list((uchar *)rn, (uchar **)&rn->next);
 
1698
    rn->belong_to_view= belong_to_view;
 
1699
    return TRUE;
 
1700
  }
 
1701
  return FALSE;
 
1702
}
 
1703
 
 
1704
 
 
1705
/**
 
1706
  Add routine which is explicitly used by statement to the set of stored
 
1707
  routines used by this statement.
 
1708
 
 
1709
  To be friendly towards prepared statements one should pass
 
1710
  persistent arena as second argument.
 
1711
 
 
1712
  @param lex       LEX representing statement
 
1713
  @param arena     arena in which memory for new element of the set
 
1714
                   will be allocated
 
1715
  @param rt        routine name
 
1716
  @param rt_type   routine type (one of TYPE_ENUM_PROCEDURE/...)
 
1717
 
 
1718
  @note
 
1719
    Will also add element to end of 'LEX::sroutines_list' list (and will
 
1720
    take into account that this is explicitly used routine).
 
1721
*/
 
1722
 
 
1723
void sp_add_used_routine(LEX *lex, Query_arena *arena,
 
1724
                         sp_name *rt, char rt_type)
 
1725
{
 
1726
  rt->set_routine_type(rt_type);
 
1727
  (void)add_used_routine(lex, arena, &rt->m_sroutines_key, 0);
 
1728
  lex->sroutines_list_own_last= lex->sroutines_list.next;
 
1729
  lex->sroutines_list_own_elements= lex->sroutines_list.elements;
 
1730
}
 
1731
 
 
1732
 
 
1733
/**
 
1734
  Remove routines which are only indirectly used by statement from
 
1735
  the set of routines used by this statement.
 
1736
 
 
1737
  @param lex  LEX representing statement
 
1738
*/
 
1739
 
 
1740
void sp_remove_not_own_routines(LEX *lex)
 
1741
{
 
1742
  Sroutine_hash_entry *not_own_rt, *next_rt;
 
1743
  for (not_own_rt= *(Sroutine_hash_entry **)lex->sroutines_list_own_last;
 
1744
       not_own_rt; not_own_rt= next_rt)
 
1745
  {
 
1746
    /*
 
1747
      It is safe to obtain not_own_rt->next after calling hash_delete() now
 
1748
      but we want to be more future-proof.
 
1749
    */
 
1750
    next_rt= not_own_rt->next;
 
1751
    hash_delete(&lex->sroutines, (uchar *)not_own_rt);
 
1752
  }
 
1753
 
 
1754
  *(Sroutine_hash_entry **)lex->sroutines_list_own_last= NULL;
 
1755
  lex->sroutines_list.next= lex->sroutines_list_own_last;
 
1756
  lex->sroutines_list.elements= lex->sroutines_list_own_elements;
 
1757
}
 
1758
 
 
1759
 
 
1760
/**
 
1761
  Merge contents of two hashes representing sets of routines used
 
1762
  by statements or by other routines.
 
1763
 
 
1764
  @param dst   hash to which elements should be added
 
1765
  @param src   hash from which elements merged
 
1766
 
 
1767
  @note
 
1768
    This procedure won't create new Sroutine_hash_entry objects,
 
1769
    instead it will simply add elements from source to destination
 
1770
    hash. Thus time of life of elements in destination hash becomes
 
1771
    dependant on time of life of elements from source hash. It also
 
1772
    won't touch lists linking elements in source and destination
 
1773
    hashes.
 
1774
 
 
1775
  @returns
 
1776
    @return TRUE Failure
 
1777
    @return FALSE Success
 
1778
*/
 
1779
 
 
1780
bool sp_update_sp_used_routines(HASH *dst, HASH *src)
 
1781
{
 
1782
  for (uint i=0 ; i < src->records ; i++)
 
1783
  {
 
1784
    Sroutine_hash_entry *rt= (Sroutine_hash_entry *)hash_element(src, i);
 
1785
    if (!hash_search(dst, (uchar *)rt->key.str, rt->key.length))
 
1786
    {
 
1787
      if (my_hash_insert(dst, (uchar *)rt))
 
1788
        return TRUE;
 
1789
    }
 
1790
  }
 
1791
  return FALSE;
 
1792
}
 
1793
 
 
1794
 
 
1795
/**
 
1796
  Add contents of hash representing set of routines to the set of
 
1797
  routines used by statement.
 
1798
 
 
1799
  @param thd             Thread context
 
1800
  @param lex             LEX representing statement
 
1801
  @param src             Hash representing set from which routines will
 
1802
                         be added
 
1803
  @param belong_to_view  Uppermost view which uses these routines, 0 if none
 
1804
 
 
1805
  @note
 
1806
    It will also add elements to end of 'LEX::sroutines_list' list.
 
1807
*/
 
1808
 
 
1809
static void
 
1810
sp_update_stmt_used_routines(THD *thd, LEX *lex, HASH *src,
 
1811
                             TABLE_LIST *belong_to_view)
 
1812
{
 
1813
  for (uint i=0 ; i < src->records ; i++)
 
1814
  {
 
1815
    Sroutine_hash_entry *rt= (Sroutine_hash_entry *)hash_element(src, i);
 
1816
    (void)add_used_routine(lex, thd->stmt_arena, &rt->key, belong_to_view);
 
1817
  }
 
1818
}
 
1819
 
 
1820
 
 
1821
/**
 
1822
  Add contents of list representing set of routines to the set of
 
1823
  routines used by statement.
 
1824
 
 
1825
  @param thd             Thread context
 
1826
  @param lex             LEX representing statement
 
1827
  @param src             List representing set from which routines will
 
1828
                         be added
 
1829
  @param belong_to_view  Uppermost view which uses these routines, 0 if none
 
1830
 
 
1831
  @note
 
1832
    It will also add elements to end of 'LEX::sroutines_list' list.
 
1833
*/
 
1834
 
 
1835
static void sp_update_stmt_used_routines(THD *thd, LEX *lex, SQL_LIST *src,
 
1836
                                         TABLE_LIST *belong_to_view)
 
1837
{
 
1838
  for (Sroutine_hash_entry *rt= (Sroutine_hash_entry *)src->first;
 
1839
       rt; rt= rt->next)
 
1840
    (void)add_used_routine(lex, thd->stmt_arena, &rt->key, belong_to_view);
 
1841
}
 
1842
 
 
1843
 
 
1844
/**
 
1845
  Cache sub-set of routines used by statement, add tables used by these
 
1846
  routines to statement table list. Do the same for all routines used
 
1847
  by these routines.
 
1848
 
 
1849
  @param thd               thread context
 
1850
  @param lex               LEX representing statement
 
1851
  @param start             first routine from the list of routines to be cached
 
1852
                           (this list defines mentioned sub-set).
 
1853
  @param first_no_prelock  If true, don't add tables or cache routines used by
 
1854
                           the body of the first routine (i.e. *start)
 
1855
                           will be executed in non-prelocked mode.
 
1856
  @param tabs_changed      Set to TRUE some tables were added, FALSE otherwise
 
1857
 
 
1858
  @note
 
1859
    If some function is missing this won't be reported here.
 
1860
    Instead this fact will be discovered during query execution.
 
1861
 
 
1862
  @retval
 
1863
    0       success
 
1864
  @retval
 
1865
    non-0   failure
 
1866
*/
 
1867
 
 
1868
static int
 
1869
sp_cache_routines_and_add_tables_aux(THD *thd, LEX *lex,
 
1870
                                     Sroutine_hash_entry *start, 
 
1871
                                     bool first_no_prelock)
 
1872
{
 
1873
  int ret= 0;
 
1874
  bool first= TRUE;
 
1875
  DBUG_ENTER("sp_cache_routines_and_add_tables_aux");
 
1876
 
 
1877
  for (Sroutine_hash_entry *rt= start; rt; rt= rt->next)
 
1878
  {
 
1879
    sp_name name(thd, rt->key.str, rt->key.length);
 
1880
    int type= rt->key.str[0];
 
1881
    sp_head *sp;
 
1882
 
 
1883
    if (!(sp= sp_cache_lookup((type == TYPE_ENUM_FUNCTION ?
 
1884
                              &thd->sp_func_cache : &thd->sp_proc_cache),
 
1885
                              &name)))
 
1886
    {
 
1887
      switch ((ret= db_find_routine(thd, type, &name, &sp)))
 
1888
      {
 
1889
      case SP_OK:
 
1890
        {
 
1891
          if (type == TYPE_ENUM_FUNCTION)
 
1892
            sp_cache_insert(&thd->sp_func_cache, sp);
 
1893
          else
 
1894
            sp_cache_insert(&thd->sp_proc_cache, sp);
 
1895
        }
 
1896
        break;
 
1897
      case SP_KEY_NOT_FOUND:
 
1898
        ret= SP_OK;
 
1899
        break;
 
1900
      default:
 
1901
        /* Query might have been killed, don't set error. */
 
1902
        if (thd->killed)
 
1903
          break;
 
1904
 
 
1905
        /*
 
1906
          Any error when loading an existing routine is either some problem
 
1907
          with the mysql.proc table, or a parse error because the contents
 
1908
          has been tampered with (in which case we clear that error).
 
1909
        */
 
1910
        if (ret == SP_PARSE_ERROR)
 
1911
          thd->clear_error();
 
1912
        /*
 
1913
          If we cleared the parse error, or when db_find_routine() flagged
 
1914
          an error with it's return value without calling my_error(), we
 
1915
          set the generic "mysql.proc table corrupt" error here.
 
1916
         */
 
1917
        if (! thd->is_error())
 
1918
        {
 
1919
          /*
 
1920
            SP allows full NAME_LEN chars thus he have to allocate enough
 
1921
            size in bytes. Otherwise there is stack overrun could happen
 
1922
            if multibyte sequence is `name`. `db` is still safe because the
 
1923
            rest of the server checks agains NAME_LEN bytes and not chars.
 
1924
            Hence, the overrun happens only if the name is in length > 32 and
 
1925
            uses multibyte (cyrillic, greek, etc.)
 
1926
          */
 
1927
          char n[NAME_LEN*2+2];
 
1928
 
 
1929
          /* m_qname.str is not always \0 terminated */
 
1930
          memcpy(n, name.m_qname.str, name.m_qname.length);
 
1931
          n[name.m_qname.length]= '\0';
 
1932
          my_error(ER_SP_PROC_TABLE_CORRUPT, MYF(0), n, ret);
 
1933
        }
 
1934
        break;
 
1935
      }
 
1936
    }
 
1937
    if (sp)
 
1938
    {
 
1939
      if (!(first && first_no_prelock))
 
1940
      {
 
1941
        sp_update_stmt_used_routines(thd, lex, &sp->m_sroutines,
 
1942
                                     rt->belong_to_view);
 
1943
        (void)sp->add_used_tables_to_table_list(thd, &lex->query_tables_last,
 
1944
                                                rt->belong_to_view);
 
1945
      }
 
1946
      sp->propagate_attributes(lex);
 
1947
    }
 
1948
    first= FALSE;
 
1949
  }
 
1950
  DBUG_RETURN(ret);
 
1951
}
 
1952
 
 
1953
 
 
1954
/**
 
1955
  Cache all routines from the set of used by statement, add tables used
 
1956
  by those routines to statement table list. Do the same for all routines
 
1957
  used by those routines.
 
1958
 
 
1959
  @param thd               thread context
 
1960
  @param lex               LEX representing statement
 
1961
  @param first_no_prelock  If true, don't add tables or cache routines used by
 
1962
                           the body of the first routine (i.e. *start)
 
1963
 
 
1964
  @retval
 
1965
    0       success
 
1966
  @retval
 
1967
    non-0   failure
 
1968
*/
 
1969
 
 
1970
int
 
1971
sp_cache_routines_and_add_tables(THD *thd, LEX *lex, bool first_no_prelock)
 
1972
{
 
1973
  return sp_cache_routines_and_add_tables_aux(thd, lex,
 
1974
           (Sroutine_hash_entry *)lex->sroutines_list.first,
 
1975
           first_no_prelock);
 
1976
}
 
1977
 
 
1978
 
 
1979
/**
 
1980
  Add all routines used by view to the set of routines used by
 
1981
  statement.
 
1982
 
 
1983
  Add tables used by those routines to statement table list. Do the same
 
1984
  for all routines used by these routines.
 
1985
 
 
1986
  @param thd   Thread context
 
1987
  @param lex   LEX representing statement
 
1988
  @param view  Table list element representing view
 
1989
 
 
1990
  @retval
 
1991
    0       success
 
1992
  @retval
 
1993
    non-0   failure
 
1994
*/
 
1995
 
 
1996
int
 
1997
sp_cache_routines_and_add_tables_for_view(THD *thd, LEX *lex, TABLE_LIST *view)
 
1998
{
 
1999
  Sroutine_hash_entry **last_cached_routine_ptr=
 
2000
                          (Sroutine_hash_entry **)lex->sroutines_list.next;
 
2001
  sp_update_stmt_used_routines(thd, lex, &view->view->sroutines_list,
 
2002
                               view->top_table());
 
2003
  return sp_cache_routines_and_add_tables_aux(thd, lex,
 
2004
                                              *last_cached_routine_ptr, FALSE);
 
2005
}
 
2006
 
 
2007
 
 
2008
/**
 
2009
  Add triggers for table to the set of routines used by statement.
 
2010
  Add tables used by them to statement table list. Do the same for
 
2011
  all implicitly used routines.
 
2012
 
 
2013
  @param thd    thread context
 
2014
  @param lex    LEX respresenting statement
 
2015
  @param table  Table list element for table with trigger
 
2016
 
 
2017
  @retval
 
2018
    0       success
 
2019
  @retval
 
2020
    non-0   failure
 
2021
*/
 
2022
 
 
2023
int
 
2024
sp_cache_routines_and_add_tables_for_triggers(THD *thd, LEX *lex,
 
2025
                                              TABLE_LIST *table)
 
2026
{
 
2027
  int ret= 0;
 
2028
 
 
2029
  Sroutine_hash_entry **last_cached_routine_ptr=
 
2030
    (Sroutine_hash_entry **)lex->sroutines_list.next;
 
2031
 
 
2032
  if (static_cast<int>(table->lock_type) >=
 
2033
      static_cast<int>(TL_WRITE_ALLOW_WRITE))
 
2034
  {
 
2035
    for (int i= 0; i < (int)TRG_EVENT_MAX; i++)
 
2036
    {
 
2037
      if (table->trg_event_map &
 
2038
          static_cast<uint8>(1 << static_cast<int>(i)))
 
2039
      {
 
2040
        for (int j= 0; j < (int)TRG_ACTION_MAX; j++)
 
2041
        {
 
2042
          /* We can have only one trigger per action type currently */
 
2043
          sp_head *trigger= table->table->triggers->bodies[i][j];
 
2044
          if (trigger &&
 
2045
              add_used_routine(lex, thd->stmt_arena, &trigger->m_sroutines_key,
 
2046
                               table->belong_to_view))
 
2047
          {
 
2048
            trigger->add_used_tables_to_table_list(thd, &lex->query_tables_last,
 
2049
                                                   table->belong_to_view);
 
2050
            trigger->propagate_attributes(lex);
 
2051
            sp_update_stmt_used_routines(thd, lex,
 
2052
                                         &trigger->m_sroutines,
 
2053
                                         table->belong_to_view);
 
2054
          }
 
2055
        }
 
2056
      }
 
2057
    }
 
2058
  }
 
2059
  ret= sp_cache_routines_and_add_tables_aux(thd, lex,
 
2060
                                            *last_cached_routine_ptr,
 
2061
                                            FALSE);
 
2062
  return ret;
 
2063
}
 
2064
 
 
2065
 
 
2066
/**
 
2067
  Generates the CREATE... string from the table information.
 
2068
 
 
2069
  @return
 
2070
    Returns TRUE on success, FALSE on (alloc) failure.
 
2071
*/
 
2072
static bool
 
2073
create_string(THD *thd, String *buf,
 
2074
              int type,
 
2075
              const char *db, ulong dblen,
 
2076
              const char *name, ulong namelen,
 
2077
              const char *params, ulong paramslen,
 
2078
              const char *returns, ulong returnslen,
 
2079
              const char *body, ulong bodylen,
 
2080
              st_sp_chistics *chistics,
 
2081
              const LEX_STRING *definer_user,
 
2082
              const LEX_STRING *definer_host)
 
2083
{
 
2084
  /* Make some room to begin with */
 
2085
  if (buf->alloc(100 + dblen + 1 + namelen + paramslen + returnslen + bodylen +
 
2086
                 chistics->comment.length + 10 /* length of " DEFINER= "*/ +
 
2087
                 USER_HOST_BUFF_SIZE))
 
2088
    return FALSE;
 
2089
 
 
2090
  buf->append(STRING_WITH_LEN("CREATE "));
 
2091
  append_definer(thd, buf, definer_user, definer_host);
 
2092
  if (type == TYPE_ENUM_FUNCTION)
 
2093
    buf->append(STRING_WITH_LEN("FUNCTION "));
 
2094
  else
 
2095
    buf->append(STRING_WITH_LEN("PROCEDURE "));
 
2096
  if (dblen > 0)
 
2097
  {
 
2098
    append_identifier(thd, buf, db, dblen);
 
2099
    buf->append('.');
 
2100
  }
 
2101
  append_identifier(thd, buf, name, namelen);
 
2102
  buf->append('(');
 
2103
  buf->append(params, paramslen);
 
2104
  buf->append(')');
 
2105
  if (type == TYPE_ENUM_FUNCTION)
 
2106
  {
 
2107
    buf->append(STRING_WITH_LEN(" RETURNS "));
 
2108
    buf->append(returns, returnslen);
 
2109
  }
 
2110
  buf->append('\n');
 
2111
  switch (chistics->daccess) {
 
2112
  case SP_NO_SQL:
 
2113
    buf->append(STRING_WITH_LEN("    NO SQL\n"));
 
2114
    break;
 
2115
  case SP_READS_SQL_DATA:
 
2116
    buf->append(STRING_WITH_LEN("    READS SQL DATA\n"));
 
2117
    break;
 
2118
  case SP_MODIFIES_SQL_DATA:
 
2119
    buf->append(STRING_WITH_LEN("    MODIFIES SQL DATA\n"));
 
2120
    break;
 
2121
  case SP_DEFAULT_ACCESS:
 
2122
  case SP_CONTAINS_SQL:
 
2123
    /* Do nothing */
 
2124
    break;
 
2125
  }
 
2126
  if (chistics->detistic)
 
2127
    buf->append(STRING_WITH_LEN("    DETERMINISTIC\n"));
 
2128
  if (chistics->suid == SP_IS_NOT_SUID)
 
2129
    buf->append(STRING_WITH_LEN("    SQL SECURITY INVOKER\n"));
 
2130
  if (chistics->comment.length)
 
2131
  {
 
2132
    buf->append(STRING_WITH_LEN("    COMMENT "));
 
2133
    append_unescaped(buf, chistics->comment.str, chistics->comment.length);
 
2134
    buf->append('\n');
 
2135
  }
 
2136
  buf->append(body, bodylen);
 
2137
  return TRUE;
 
2138
}