Gentoo Archives: gentoo-commits

From: "Robin H. Johnson" <robbat2@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/mysql-extras:master commit in: /
Date: Tue, 28 May 2013 19:34:28
Message-Id: 1369769611.4c4de3089d89d2d44edbcfedcafffab325dc1172.robbat2@gentoo
1 commit: 4c4de3089d89d2d44edbcfedcafffab325dc1172
2 Author: Robin H. Johnson <robbat2 <AT> gentoo <DOT> org>
3 AuthorDate: Tue May 28 19:33:31 2013 +0000
4 Commit: Robin H. Johnson <robbat2 <AT> gentoo <DOT> org>
5 CommitDate: Tue May 28 19:33:31 2013 +0000
6 URL: http://git.overlays.gentoo.org/gitweb/?p=proj/mysql-extras.git;a=commit;h=4c4de308
7
8 Clean up .orig and .rej blocks, add tracking.
9
10 Signed-off-by: Robin H. Johnson <robbat2 <AT> gentoo.org>
11
12 ---
13 07110_all_mysql_gcc-4.2_5.1.57.patch | 66446 +--------------------------------
14 1 file changed, 6 insertions(+), 66440 deletions(-)
15
16 diff --git a/07110_all_mysql_gcc-4.2_5.1.57.patch b/07110_all_mysql_gcc-4.2_5.1.57.patch
17 index 7265c94..24bb194 100644
18 --- a/07110_all_mysql_gcc-4.2_5.1.57.patch
19 +++ b/07110_all_mysql_gcc-4.2_5.1.57.patch
20 @@ -1,3 +1,9 @@
21 +
22 +X-Gentoo-Bug: 280843
23 +X-Upstream-Bug: 30866
24 +X-Gentoo-Bug-URL: http://bugs.gentoo.org/show_bug.cgi?id=280843
25 +X-Upstream-Bug-URL: http://bugs.mysql.com/bug.php?id=30866
26 +
27 diff -urN mysql-old/client/mysqlbinlog.cc mysql/client/mysqlbinlog.cc
28 --- mysql-old/client/mysqlbinlog.cc 2011-05-10 17:45:45.693349043 +0000
29 +++ mysql/client/mysqlbinlog.cc 2011-05-10 17:56:01.266682376 +0000
30 @@ -1231,6170 +1237,6 @@ diff -urN mysql-old/sql/item_func.cc mysql/sql/item_func.cc
31 }
32 initialized=1;
33 if (error)
34 -diff -urN mysql-old/sql/item_func.cc.orig mysql/sql/item_func.cc.orig
35 ---- mysql-old/sql/item_func.cc.orig 1969-12-31 23:00:00.000000000 -0100
36 -+++ mysql/sql/item_func.cc.orig 2011-04-12 12:11:35.000000000 +0000
37 -@@ -0,0 +1,6160 @@
38 -+/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
39 -+
40 -+ This program is free software; you can redistribute it and/or modify
41 -+ it under the terms of the GNU General Public License as published by
42 -+ the Free Software Foundation; version 2 of the License.
43 -+
44 -+ This program is distributed in the hope that it will be useful,
45 -+ but WITHOUT ANY WARRANTY; without even the implied warranty of
46 -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
47 -+ GNU General Public License for more details.
48 -+
49 -+ You should have received a copy of the GNU General Public License
50 -+ along with this program; if not, write to the Free Software
51 -+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
52 -+
53 -+
54 -+/**
55 -+ @file
56 -+
57 -+ @brief
58 -+ This file defines all numerical functions
59 -+*/
60 -+
61 -+#ifdef USE_PRAGMA_IMPLEMENTATION
62 -+#pragma implementation // gcc: Class implementation
63 -+#endif
64 -+
65 -+#include "mysql_priv.h"
66 -+#include "slave.h" // for wait_for_master_pos
67 -+#include "rpl_mi.h"
68 -+#include <m_ctype.h>
69 -+#include <hash.h>
70 -+#include <time.h>
71 -+#include <ft_global.h>
72 -+#include <my_bit.h>
73 -+
74 -+#include "sp_head.h"
75 -+#include "sp_rcontext.h"
76 -+#include "sp.h"
77 -+
78 -+#ifdef NO_EMBEDDED_ACCESS_CHECKS
79 -+#define sp_restore_security_context(A,B) while (0) {}
80 -+#endif
81 -+
82 -+bool check_reserved_words(LEX_STRING *name)
83 -+{
84 -+ if (!my_strcasecmp(system_charset_info, name->str, "GLOBAL") ||
85 -+ !my_strcasecmp(system_charset_info, name->str, "LOCAL") ||
86 -+ !my_strcasecmp(system_charset_info, name->str, "SESSION"))
87 -+ return TRUE;
88 -+ return FALSE;
89 -+}
90 -+
91 -+
92 -+/**
93 -+ @return
94 -+ TRUE if item is a constant
95 -+*/
96 -+
97 -+bool
98 -+eval_const_cond(COND *cond)
99 -+{
100 -+ return ((Item_func*) cond)->val_int() ? TRUE : FALSE;
101 -+}
102 -+
103 -+
104 -+void Item_func::set_arguments(List<Item> &list)
105 -+{
106 -+ allowed_arg_cols= 1;
107 -+ arg_count=list.elements;
108 -+ args= tmp_arg; // If 2 arguments
109 -+ if (arg_count <= 2 || (args=(Item**) sql_alloc(sizeof(Item*)*arg_count)))
110 -+ {
111 -+ List_iterator_fast<Item> li(list);
112 -+ Item *item;
113 -+ Item **save_args= args;
114 -+
115 -+ while ((item=li++))
116 -+ {
117 -+ *(save_args++)= item;
118 -+ with_sum_func|=item->with_sum_func;
119 -+ }
120 -+ }
121 -+ list.empty(); // Fields are used
122 -+}
123 -+
124 -+Item_func::Item_func(List<Item> &list)
125 -+ :allowed_arg_cols(1)
126 -+{
127 -+ set_arguments(list);
128 -+}
129 -+
130 -+Item_func::Item_func(THD *thd, Item_func *item)
131 -+ :Item_result_field(thd, item),
132 -+ allowed_arg_cols(item->allowed_arg_cols),
133 -+ arg_count(item->arg_count),
134 -+ used_tables_cache(item->used_tables_cache),
135 -+ not_null_tables_cache(item->not_null_tables_cache),
136 -+ const_item_cache(item->const_item_cache)
137 -+{
138 -+ if (arg_count)
139 -+ {
140 -+ if (arg_count <=2)
141 -+ args= tmp_arg;
142 -+ else
143 -+ {
144 -+ if (!(args=(Item**) thd->alloc(sizeof(Item*)*arg_count)))
145 -+ return;
146 -+ }
147 -+ memcpy((char*) args, (char*) item->args, sizeof(Item*)*arg_count);
148 -+ }
149 -+}
150 -+
151 -+
152 -+/*
153 -+ Resolve references to table column for a function and its argument
154 -+
155 -+ SYNOPSIS:
156 -+ fix_fields()
157 -+ thd Thread object
158 -+ ref Pointer to where this object is used. This reference
159 -+ is used if we want to replace this object with another
160 -+ one (for example in the summary functions).
161 -+
162 -+ DESCRIPTION
163 -+ Call fix_fields() for all arguments to the function. The main intention
164 -+ is to allow all Item_field() objects to setup pointers to the table fields.
165 -+
166 -+ Sets as a side effect the following class variables:
167 -+ maybe_null Set if any argument may return NULL
168 -+ with_sum_func Set if any of the arguments contains a sum function
169 -+ used_tables_cache Set to union of the tables used by arguments
170 -+
171 -+ str_value.charset If this is a string function, set this to the
172 -+ character set for the first argument.
173 -+ If any argument is binary, this is set to binary
174 -+
175 -+ If for any item any of the defaults are wrong, then this can
176 -+ be fixed in the fix_length_and_dec() function that is called
177 -+ after this one or by writing a specialized fix_fields() for the
178 -+ item.
179 -+
180 -+ RETURN VALUES
181 -+ FALSE ok
182 -+ TRUE Got error. Stored with my_error().
183 -+*/
184 -+
185 -+bool
186 -+Item_func::fix_fields(THD *thd, Item **ref)
187 -+{
188 -+ DBUG_ASSERT(fixed == 0);
189 -+ Item **arg,**arg_end;
190 -+#ifndef EMBEDDED_LIBRARY // Avoid compiler warning
191 -+ uchar buff[STACK_BUFF_ALLOC]; // Max argument in function
192 -+#endif
193 -+
194 -+ used_tables_cache= not_null_tables_cache= 0;
195 -+ const_item_cache=1;
196 -+
197 -+ /*
198 -+ Use stack limit of STACK_MIN_SIZE * 2 since
199 -+ on some platforms a recursive call to fix_fields
200 -+ requires more than STACK_MIN_SIZE bytes (e.g. for
201 -+ MIPS, it takes about 22kB to make one recursive
202 -+ call to Item_func::fix_fields())
203 -+ */
204 -+ if (check_stack_overrun(thd, STACK_MIN_SIZE * 2, buff))
205 -+ return TRUE; // Fatal error if flag is set!
206 -+ if (arg_count)
207 -+ { // Print purify happy
208 -+ for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++)
209 -+ {
210 -+ Item *item;
211 -+ /*
212 -+ We can't yet set item to *arg as fix_fields may change *arg
213 -+ We shouldn't call fix_fields() twice, so check 'fixed' field first
214 -+ */
215 -+ if ((!(*arg)->fixed && (*arg)->fix_fields(thd, arg)))
216 -+ return TRUE; /* purecov: inspected */
217 -+ item= *arg;
218 -+
219 -+ if (allowed_arg_cols)
220 -+ {
221 -+ if (item->check_cols(allowed_arg_cols))
222 -+ return 1;
223 -+ }
224 -+ else
225 -+ {
226 -+ /* we have to fetch allowed_arg_cols from first argument */
227 -+ DBUG_ASSERT(arg == args); // it is first argument
228 -+ allowed_arg_cols= item->cols();
229 -+ DBUG_ASSERT(allowed_arg_cols); // Can't be 0 any more
230 -+ }
231 -+
232 -+ if (item->maybe_null)
233 -+ maybe_null=1;
234 -+
235 -+ with_sum_func= with_sum_func || item->with_sum_func;
236 -+ used_tables_cache|= item->used_tables();
237 -+ not_null_tables_cache|= item->not_null_tables();
238 -+ const_item_cache&= item->const_item();
239 -+ with_subselect|= item->with_subselect;
240 -+ }
241 -+ }
242 -+ fix_length_and_dec();
243 -+ if (thd->is_error()) // An error inside fix_length_and_dec occured
244 -+ return TRUE;
245 -+ fixed= 1;
246 -+ return FALSE;
247 -+}
248 -+
249 -+
250 -+bool Item_func::walk(Item_processor processor, bool walk_subquery,
251 -+ uchar *argument)
252 -+{
253 -+ if (arg_count)
254 -+ {
255 -+ Item **arg,**arg_end;
256 -+ for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
257 -+ {
258 -+ if ((*arg)->walk(processor, walk_subquery, argument))
259 -+ return 1;
260 -+ }
261 -+ }
262 -+ return (this->*processor)(argument);
263 -+}
264 -+
265 -+void Item_func::traverse_cond(Cond_traverser traverser,
266 -+ void *argument, traverse_order order)
267 -+{
268 -+ if (arg_count)
269 -+ {
270 -+ Item **arg,**arg_end;
271 -+
272 -+ switch (order) {
273 -+ case(PREFIX):
274 -+ (*traverser)(this, argument);
275 -+ for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
276 -+ {
277 -+ (*arg)->traverse_cond(traverser, argument, order);
278 -+ }
279 -+ break;
280 -+ case (POSTFIX):
281 -+ for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
282 -+ {
283 -+ (*arg)->traverse_cond(traverser, argument, order);
284 -+ }
285 -+ (*traverser)(this, argument);
286 -+ }
287 -+ }
288 -+ else
289 -+ (*traverser)(this, argument);
290 -+}
291 -+
292 -+
293 -+/**
294 -+ Transform an Item_func object with a transformer callback function.
295 -+
296 -+ The function recursively applies the transform method to each
297 -+ argument of the Item_func node.
298 -+ If the call of the method for an argument item returns a new item
299 -+ the old item is substituted for a new one.
300 -+ After this the transformer is applied to the root node
301 -+ of the Item_func object.
302 -+ @param transformer the transformer callback function to be applied to
303 -+ the nodes of the tree of the object
304 -+ @param argument parameter to be passed to the transformer
305 -+
306 -+ @return
307 -+ Item returned as the result of transformation of the root node
308 -+*/
309 -+
310 -+Item *Item_func::transform(Item_transformer transformer, uchar *argument)
311 -+{
312 -+ DBUG_ASSERT(!current_thd->is_stmt_prepare());
313 -+
314 -+ if (arg_count)
315 -+ {
316 -+ Item **arg,**arg_end;
317 -+ for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
318 -+ {
319 -+ Item *new_item= (*arg)->transform(transformer, argument);
320 -+ if (!new_item)
321 -+ return 0;
322 -+
323 -+ /*
324 -+ THD::change_item_tree() should be called only if the tree was
325 -+ really transformed, i.e. when a new item has been created.
326 -+ Otherwise we'll be allocating a lot of unnecessary memory for
327 -+ change records at each execution.
328 -+ */
329 -+ if (*arg != new_item)
330 -+ current_thd->change_item_tree(arg, new_item);
331 -+ }
332 -+ }
333 -+ return (this->*transformer)(argument);
334 -+}
335 -+
336 -+
337 -+/**
338 -+ Compile Item_func object with a processor and a transformer
339 -+ callback functions.
340 -+
341 -+ First the function applies the analyzer to the root node of
342 -+ the Item_func object. Then if the analizer succeeeds (returns TRUE)
343 -+ the function recursively applies the compile method to each argument
344 -+ of the Item_func node.
345 -+ If the call of the method for an argument item returns a new item
346 -+ the old item is substituted for a new one.
347 -+ After this the transformer is applied to the root node
348 -+ of the Item_func object.
349 -+
350 -+ @param analyzer the analyzer callback function to be applied to the
351 -+ nodes of the tree of the object
352 -+ @param[in,out] arg_p parameter to be passed to the processor
353 -+ @param transformer the transformer callback function to be applied to the
354 -+ nodes of the tree of the object
355 -+ @param arg_t parameter to be passed to the transformer
356 -+
357 -+ @return
358 -+ Item returned as the result of transformation of the root node
359 -+*/
360 -+
361 -+Item *Item_func::compile(Item_analyzer analyzer, uchar **arg_p,
362 -+ Item_transformer transformer, uchar *arg_t)
363 -+{
364 -+ if (!(this->*analyzer)(arg_p))
365 -+ return 0;
366 -+ if (arg_count)
367 -+ {
368 -+ Item **arg,**arg_end;
369 -+ for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
370 -+ {
371 -+ /*
372 -+ The same parameter value of arg_p must be passed
373 -+ to analyze any argument of the condition formula.
374 -+ */
375 -+ uchar *arg_v= *arg_p;
376 -+ Item *new_item= (*arg)->compile(analyzer, &arg_v, transformer, arg_t);
377 -+ if (new_item && *arg != new_item)
378 -+ current_thd->change_item_tree(arg, new_item);
379 -+ }
380 -+ }
381 -+ return (this->*transformer)(arg_t);
382 -+}
383 -+
384 -+/**
385 -+ See comments in Item_cmp_func::split_sum_func()
386 -+*/
387 -+
388 -+void Item_func::split_sum_func(THD *thd, Item **ref_pointer_array,
389 -+ List<Item> &fields)
390 -+{
391 -+ Item **arg, **arg_end;
392 -+ for (arg= args, arg_end= args+arg_count; arg != arg_end ; arg++)
393 -+ (*arg)->split_sum_func2(thd, ref_pointer_array, fields, arg, TRUE);
394 -+}
395 -+
396 -+
397 -+void Item_func::update_used_tables()
398 -+{
399 -+ used_tables_cache=0;
400 -+ const_item_cache=1;
401 -+ for (uint i=0 ; i < arg_count ; i++)
402 -+ {
403 -+ args[i]->update_used_tables();
404 -+ used_tables_cache|=args[i]->used_tables();
405 -+ const_item_cache&=args[i]->const_item();
406 -+ }
407 -+}
408 -+
409 -+
410 -+table_map Item_func::used_tables() const
411 -+{
412 -+ return used_tables_cache;
413 -+}
414 -+
415 -+
416 -+table_map Item_func::not_null_tables() const
417 -+{
418 -+ return not_null_tables_cache;
419 -+}
420 -+
421 -+
422 -+void Item_func::print(String *str, enum_query_type query_type)
423 -+{
424 -+ str->append(func_name());
425 -+ str->append('(');
426 -+ print_args(str, 0, query_type);
427 -+ str->append(')');
428 -+}
429 -+
430 -+
431 -+void Item_func::print_args(String *str, uint from, enum_query_type query_type)
432 -+{
433 -+ for (uint i=from ; i < arg_count ; i++)
434 -+ {
435 -+ if (i != from)
436 -+ str->append(',');
437 -+ args[i]->print(str, query_type);
438 -+ }
439 -+}
440 -+
441 -+
442 -+void Item_func::print_op(String *str, enum_query_type query_type)
443 -+{
444 -+ str->append('(');
445 -+ for (uint i=0 ; i < arg_count-1 ; i++)
446 -+ {
447 -+ args[i]->print(str, query_type);
448 -+ str->append(' ');
449 -+ str->append(func_name());
450 -+ str->append(' ');
451 -+ }
452 -+ args[arg_count-1]->print(str, query_type);
453 -+ str->append(')');
454 -+}
455 -+
456 -+
457 -+bool Item_func::eq(const Item *item, bool binary_cmp) const
458 -+{
459 -+ /* Assume we don't have rtti */
460 -+ if (this == item)
461 -+ return 1;
462 -+ if (item->type() != FUNC_ITEM)
463 -+ return 0;
464 -+ Item_func *item_func=(Item_func*) item;
465 -+ Item_func::Functype func_type;
466 -+ if ((func_type= functype()) != item_func->functype() ||
467 -+ arg_count != item_func->arg_count ||
468 -+ (func_type != Item_func::FUNC_SP &&
469 -+ func_name() != item_func->func_name()) ||
470 -+ (func_type == Item_func::FUNC_SP &&
471 -+ my_strcasecmp(system_charset_info, func_name(), item_func->func_name())))
472 -+ return 0;
473 -+ for (uint i=0; i < arg_count ; i++)
474 -+ if (!args[i]->eq(item_func->args[i], binary_cmp))
475 -+ return 0;
476 -+ return 1;
477 -+}
478 -+
479 -+
480 -+Field *Item_func::tmp_table_field(TABLE *table)
481 -+{
482 -+ Field *field= NULL;
483 -+
484 -+ switch (result_type()) {
485 -+ case INT_RESULT:
486 -+ if (max_length > MY_INT32_NUM_DECIMAL_DIGITS)
487 -+ field= new Field_longlong(max_length, maybe_null, name, unsigned_flag);
488 -+ else
489 -+ field= new Field_long(max_length, maybe_null, name, unsigned_flag);
490 -+ break;
491 -+ case REAL_RESULT:
492 -+ field= new Field_double(max_length, maybe_null, name, decimals);
493 -+ break;
494 -+ case STRING_RESULT:
495 -+ return make_string_field(table);
496 -+ break;
497 -+ case DECIMAL_RESULT:
498 -+ field= Field_new_decimal::create_from_item(this);
499 -+ break;
500 -+ case ROW_RESULT:
501 -+ default:
502 -+ // This case should never be chosen
503 -+ DBUG_ASSERT(0);
504 -+ field= 0;
505 -+ break;
506 -+ }
507 -+ if (field)
508 -+ field->init(table);
509 -+ return field;
510 -+}
511 -+
512 -+
513 -+bool Item_func::is_expensive_processor(uchar *arg)
514 -+{
515 -+ return is_expensive();
516 -+}
517 -+
518 -+
519 -+my_decimal *Item_func::val_decimal(my_decimal *decimal_value)
520 -+{
521 -+ DBUG_ASSERT(fixed);
522 -+ longlong nr= val_int();
523 -+ if (null_value)
524 -+ return 0; /* purecov: inspected */
525 -+ int2my_decimal(E_DEC_FATAL_ERROR, nr, unsigned_flag, decimal_value);
526 -+ return decimal_value;
527 -+}
528 -+
529 -+
530 -+String *Item_real_func::val_str(String *str)
531 -+{
532 -+ DBUG_ASSERT(fixed == 1);
533 -+ double nr= val_real();
534 -+ if (null_value)
535 -+ return 0; /* purecov: inspected */
536 -+ str->set_real(nr,decimals, &my_charset_bin);
537 -+ return str;
538 -+}
539 -+
540 -+
541 -+my_decimal *Item_real_func::val_decimal(my_decimal *decimal_value)
542 -+{
543 -+ DBUG_ASSERT(fixed);
544 -+ double nr= val_real();
545 -+ if (null_value)
546 -+ return 0; /* purecov: inspected */
547 -+ double2my_decimal(E_DEC_FATAL_ERROR, nr, decimal_value);
548 -+ return decimal_value;
549 -+}
550 -+
551 -+
552 -+void Item_func::fix_num_length_and_dec()
553 -+{
554 -+ uint fl_length= 0;
555 -+ decimals=0;
556 -+ for (uint i=0 ; i < arg_count ; i++)
557 -+ {
558 -+ set_if_bigger(decimals,args[i]->decimals);
559 -+ set_if_bigger(fl_length, args[i]->max_length);
560 -+ }
561 -+ max_length=float_length(decimals);
562 -+ if (fl_length > max_length)
563 -+ {
564 -+ decimals= NOT_FIXED_DEC;
565 -+ max_length= float_length(NOT_FIXED_DEC);
566 -+ }
567 -+}
568 -+
569 -+
570 -+void Item_func_numhybrid::fix_num_length_and_dec()
571 -+{}
572 -+
573 -+
574 -+/**
575 -+ Set max_length/decimals of function if function is fixed point and
576 -+ result length/precision depends on argument ones.
577 -+*/
578 -+
579 -+void Item_func::count_decimal_length()
580 -+{
581 -+ int max_int_part= 0;
582 -+ decimals= 0;
583 -+ unsigned_flag= 1;
584 -+ for (uint i=0 ; i < arg_count ; i++)
585 -+ {
586 -+ set_if_bigger(decimals, args[i]->decimals);
587 -+ set_if_bigger(max_int_part, args[i]->decimal_int_part());
588 -+ set_if_smaller(unsigned_flag, args[i]->unsigned_flag);
589 -+ }
590 -+ int precision= min(max_int_part + decimals, DECIMAL_MAX_PRECISION);
591 -+ max_length= my_decimal_precision_to_length_no_truncation(precision, decimals,
592 -+ unsigned_flag);
593 -+}
594 -+
595 -+
596 -+/**
597 -+ Set max_length of if it is maximum length of its arguments.
598 -+*/
599 -+
600 -+void Item_func::count_only_length()
601 -+{
602 -+ max_length= 0;
603 -+ unsigned_flag= 0;
604 -+ for (uint i=0 ; i < arg_count ; i++)
605 -+ {
606 -+ set_if_bigger(max_length, args[i]->max_length);
607 -+ set_if_bigger(unsigned_flag, args[i]->unsigned_flag);
608 -+ }
609 -+}
610 -+
611 -+
612 -+/**
613 -+ Set max_length/decimals of function if function is floating point and
614 -+ result length/precision depends on argument ones.
615 -+*/
616 -+
617 -+void Item_func::count_real_length()
618 -+{
619 -+ uint32 length= 0;
620 -+ decimals= 0;
621 -+ max_length= 0;
622 -+ for (uint i=0 ; i < arg_count ; i++)
623 -+ {
624 -+ if (decimals != NOT_FIXED_DEC)
625 -+ {
626 -+ set_if_bigger(decimals, args[i]->decimals);
627 -+ set_if_bigger(length, (args[i]->max_length - args[i]->decimals));
628 -+ }
629 -+ set_if_bigger(max_length, args[i]->max_length);
630 -+ }
631 -+ if (decimals != NOT_FIXED_DEC)
632 -+ {
633 -+ max_length= length;
634 -+ length+= decimals;
635 -+ if (length < max_length) // If previous operation gave overflow
636 -+ max_length= UINT_MAX32;
637 -+ else
638 -+ max_length= length;
639 -+ }
640 -+}
641 -+
642 -+
643 -+
644 -+void Item_func::signal_divide_by_null()
645 -+{
646 -+ THD *thd= current_thd;
647 -+ if (thd->variables.sql_mode & MODE_ERROR_FOR_DIVISION_BY_ZERO)
648 -+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, ER_DIVISION_BY_ZERO,
649 -+ ER(ER_DIVISION_BY_ZERO));
650 -+ null_value= 1;
651 -+}
652 -+
653 -+
654 -+Item *Item_func::get_tmp_table_item(THD *thd)
655 -+{
656 -+ if (!with_sum_func && !const_item())
657 -+ return new Item_field(result_field);
658 -+ return copy_or_same(thd);
659 -+}
660 -+
661 -+double Item_int_func::val_real()
662 -+{
663 -+ DBUG_ASSERT(fixed == 1);
664 -+
665 -+ return unsigned_flag ? (double) ((ulonglong) val_int()) : (double) val_int();
666 -+}
667 -+
668 -+
669 -+String *Item_int_func::val_str(String *str)
670 -+{
671 -+ DBUG_ASSERT(fixed == 1);
672 -+ longlong nr=val_int();
673 -+ if (null_value)
674 -+ return 0;
675 -+ str->set_int(nr, unsigned_flag, &my_charset_bin);
676 -+ return str;
677 -+}
678 -+
679 -+
680 -+void Item_func_connection_id::fix_length_and_dec()
681 -+{
682 -+ Item_int_func::fix_length_and_dec();
683 -+ max_length= 10;
684 -+}
685 -+
686 -+
687 -+bool Item_func_connection_id::fix_fields(THD *thd, Item **ref)
688 -+{
689 -+ if (Item_int_func::fix_fields(thd, ref))
690 -+ return TRUE;
691 -+ thd->thread_specific_used= TRUE;
692 -+ value= thd->variables.pseudo_thread_id;
693 -+ return FALSE;
694 -+}
695 -+
696 -+
697 -+/**
698 -+ Check arguments here to determine result's type for a numeric
699 -+ function of two arguments.
700 -+*/
701 -+
702 -+void Item_num_op::find_num_type(void)
703 -+{
704 -+ DBUG_ENTER("Item_num_op::find_num_type");
705 -+ DBUG_PRINT("info", ("name %s", func_name()));
706 -+ DBUG_ASSERT(arg_count == 2);
707 -+ Item_result r0= args[0]->result_type();
708 -+ Item_result r1= args[1]->result_type();
709 -+
710 -+ if (r0 == REAL_RESULT || r1 == REAL_RESULT ||
711 -+ r0 == STRING_RESULT || r1 ==STRING_RESULT)
712 -+ {
713 -+ count_real_length();
714 -+ max_length= float_length(decimals);
715 -+ hybrid_type= REAL_RESULT;
716 -+ }
717 -+ else if (r0 == DECIMAL_RESULT || r1 == DECIMAL_RESULT)
718 -+ {
719 -+ hybrid_type= DECIMAL_RESULT;
720 -+ result_precision();
721 -+ }
722 -+ else
723 -+ {
724 -+ DBUG_ASSERT(r0 == INT_RESULT && r1 == INT_RESULT);
725 -+ decimals= 0;
726 -+ hybrid_type=INT_RESULT;
727 -+ result_precision();
728 -+ }
729 -+ DBUG_PRINT("info", ("Type: %s",
730 -+ (hybrid_type == REAL_RESULT ? "REAL_RESULT" :
731 -+ hybrid_type == DECIMAL_RESULT ? "DECIMAL_RESULT" :
732 -+ hybrid_type == INT_RESULT ? "INT_RESULT" :
733 -+ "--ILLEGAL!!!--")));
734 -+ DBUG_VOID_RETURN;
735 -+}
736 -+
737 -+
738 -+/**
739 -+ Set result type for a numeric function of one argument
740 -+ (can be also used by a numeric function of many arguments, if the result
741 -+ type depends only on the first argument)
742 -+*/
743 -+
744 -+void Item_func_num1::find_num_type()
745 -+{
746 -+ DBUG_ENTER("Item_func_num1::find_num_type");
747 -+ DBUG_PRINT("info", ("name %s", func_name()));
748 -+ switch (hybrid_type= args[0]->result_type()) {
749 -+ case INT_RESULT:
750 -+ unsigned_flag= args[0]->unsigned_flag;
751 -+ break;
752 -+ case STRING_RESULT:
753 -+ case REAL_RESULT:
754 -+ hybrid_type= REAL_RESULT;
755 -+ max_length= float_length(decimals);
756 -+ break;
757 -+ case DECIMAL_RESULT:
758 -+ break;
759 -+ default:
760 -+ DBUG_ASSERT(0);
761 -+ }
762 -+ DBUG_PRINT("info", ("Type: %s",
763 -+ (hybrid_type == REAL_RESULT ? "REAL_RESULT" :
764 -+ hybrid_type == DECIMAL_RESULT ? "DECIMAL_RESULT" :
765 -+ hybrid_type == INT_RESULT ? "INT_RESULT" :
766 -+ "--ILLEGAL!!!--")));
767 -+ DBUG_VOID_RETURN;
768 -+}
769 -+
770 -+
771 -+void Item_func_num1::fix_num_length_and_dec()
772 -+{
773 -+ decimals= args[0]->decimals;
774 -+ max_length= args[0]->max_length;
775 -+}
776 -+
777 -+
778 -+void Item_func_numhybrid::fix_length_and_dec()
779 -+{
780 -+ fix_num_length_and_dec();
781 -+ find_num_type();
782 -+}
783 -+
784 -+
785 -+String *Item_func_numhybrid::val_str(String *str)
786 -+{
787 -+ DBUG_ASSERT(fixed == 1);
788 -+ switch (hybrid_type) {
789 -+ case DECIMAL_RESULT:
790 -+ {
791 -+ my_decimal decimal_value, *val;
792 -+ if (!(val= decimal_op(&decimal_value)))
793 -+ return 0; // null is set
794 -+ my_decimal_round(E_DEC_FATAL_ERROR, val, decimals, FALSE, val);
795 -+ my_decimal2string(E_DEC_FATAL_ERROR, val, 0, 0, 0, str);
796 -+ break;
797 -+ }
798 -+ case INT_RESULT:
799 -+ {
800 -+ longlong nr= int_op();
801 -+ if (null_value)
802 -+ return 0; /* purecov: inspected */
803 -+ str->set_int(nr, unsigned_flag, &my_charset_bin);
804 -+ break;
805 -+ }
806 -+ case REAL_RESULT:
807 -+ {
808 -+ double nr= real_op();
809 -+ if (null_value)
810 -+ return 0; /* purecov: inspected */
811 -+ str->set_real(nr,decimals,&my_charset_bin);
812 -+ break;
813 -+ }
814 -+ case STRING_RESULT:
815 -+ return str_op(&str_value);
816 -+ default:
817 -+ DBUG_ASSERT(0);
818 -+ }
819 -+ return str;
820 -+}
821 -+
822 -+
823 -+double Item_func_numhybrid::val_real()
824 -+{
825 -+ DBUG_ASSERT(fixed == 1);
826 -+ switch (hybrid_type) {
827 -+ case DECIMAL_RESULT:
828 -+ {
829 -+ my_decimal decimal_value, *val;
830 -+ double result;
831 -+ if (!(val= decimal_op(&decimal_value)))
832 -+ return 0.0; // null is set
833 -+ my_decimal2double(E_DEC_FATAL_ERROR, val, &result);
834 -+ return result;
835 -+ }
836 -+ case INT_RESULT:
837 -+ {
838 -+ longlong result= int_op();
839 -+ return unsigned_flag ? (double) ((ulonglong) result) : (double) result;
840 -+ }
841 -+ case REAL_RESULT:
842 -+ return real_op();
843 -+ case STRING_RESULT:
844 -+ {
845 -+ char *end_not_used;
846 -+ int err_not_used;
847 -+ String *res= str_op(&str_value);
848 -+ return (res ? my_strntod(res->charset(), (char*) res->ptr(), res->length(),
849 -+ &end_not_used, &err_not_used) : 0.0);
850 -+ }
851 -+ default:
852 -+ DBUG_ASSERT(0);
853 -+ }
854 -+ return 0.0;
855 -+}
856 -+
857 -+
858 -+longlong Item_func_numhybrid::val_int()
859 -+{
860 -+ DBUG_ASSERT(fixed == 1);
861 -+ switch (hybrid_type) {
862 -+ case DECIMAL_RESULT:
863 -+ {
864 -+ my_decimal decimal_value, *val;
865 -+ if (!(val= decimal_op(&decimal_value)))
866 -+ return 0; // null is set
867 -+ longlong result;
868 -+ my_decimal2int(E_DEC_FATAL_ERROR, val, unsigned_flag, &result);
869 -+ return result;
870 -+ }
871 -+ case INT_RESULT:
872 -+ return int_op();
873 -+ case REAL_RESULT:
874 -+ return (longlong) rint(real_op());
875 -+ case STRING_RESULT:
876 -+ {
877 -+ int err_not_used;
878 -+ String *res;
879 -+ if (!(res= str_op(&str_value)))
880 -+ return 0;
881 -+
882 -+ char *end= (char*) res->ptr() + res->length();
883 -+ CHARSET_INFO *cs= res->charset();
884 -+ return (*(cs->cset->strtoll10))(cs, res->ptr(), &end, &err_not_used);
885 -+ }
886 -+ default:
887 -+ DBUG_ASSERT(0);
888 -+ }
889 -+ return 0;
890 -+}
891 -+
892 -+
893 -+my_decimal *Item_func_numhybrid::val_decimal(my_decimal *decimal_value)
894 -+{
895 -+ my_decimal *val= decimal_value;
896 -+ DBUG_ASSERT(fixed == 1);
897 -+ switch (hybrid_type) {
898 -+ case DECIMAL_RESULT:
899 -+ val= decimal_op(decimal_value);
900 -+ break;
901 -+ case INT_RESULT:
902 -+ {
903 -+ longlong result= int_op();
904 -+ int2my_decimal(E_DEC_FATAL_ERROR, result, unsigned_flag, decimal_value);
905 -+ break;
906 -+ }
907 -+ case REAL_RESULT:
908 -+ {
909 -+ double result= (double)real_op();
910 -+ double2my_decimal(E_DEC_FATAL_ERROR, result, decimal_value);
911 -+ break;
912 -+ }
913 -+ case STRING_RESULT:
914 -+ {
915 -+ String *res;
916 -+ if (!(res= str_op(&str_value)))
917 -+ return NULL;
918 -+
919 -+ str2my_decimal(E_DEC_FATAL_ERROR, (char*) res->ptr(),
920 -+ res->length(), res->charset(), decimal_value);
921 -+ break;
922 -+ }
923 -+ case ROW_RESULT:
924 -+ default:
925 -+ DBUG_ASSERT(0);
926 -+ }
927 -+ return val;
928 -+}
929 -+
930 -+
931 -+void Item_func_signed::print(String *str, enum_query_type query_type)
932 -+{
933 -+ str->append(STRING_WITH_LEN("cast("));
934 -+ args[0]->print(str, query_type);
935 -+ str->append(STRING_WITH_LEN(" as signed)"));
936 -+
937 -+}
938 -+
939 -+
940 -+longlong Item_func_signed::val_int_from_str(int *error)
941 -+{
942 -+ char buff[MAX_FIELD_WIDTH], *end, *start;
943 -+ uint32 length;
944 -+ String tmp(buff,sizeof(buff), &my_charset_bin), *res;
945 -+ longlong value;
946 -+
947 -+ /*
948 -+ For a string result, we must first get the string and then convert it
949 -+ to a longlong
950 -+ */
951 -+
952 -+ if (!(res= args[0]->val_str(&tmp)))
953 -+ {
954 -+ null_value= 1;
955 -+ *error= 0;
956 -+ return 0;
957 -+ }
958 -+ null_value= 0;
959 -+ start= (char *)res->ptr();
960 -+ length= res->length();
961 -+
962 -+ end= start + length;
963 -+ value= my_strtoll10(start, &end, error);
964 -+ if (*error > 0 || end != start+ length)
965 -+ {
966 -+ char err_buff[128];
967 -+ String err_tmp(err_buff,(uint32) sizeof(err_buff), system_charset_info);
968 -+ err_tmp.copy(start, length, system_charset_info);
969 -+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
970 -+ ER_TRUNCATED_WRONG_VALUE,
971 -+ ER(ER_TRUNCATED_WRONG_VALUE), "INTEGER",
972 -+ err_tmp.c_ptr());
973 -+ }
974 -+ return value;
975 -+}
976 -+
977 -+
978 -+longlong Item_func_signed::val_int()
979 -+{
980 -+ longlong value;
981 -+ int error;
982 -+
983 -+ if (args[0]->cast_to_int_type() != STRING_RESULT ||
984 -+ args[0]->result_as_longlong())
985 -+ {
986 -+ value= args[0]->val_int();
987 -+ null_value= args[0]->null_value;
988 -+ return value;
989 -+ }
990 -+
991 -+ value= val_int_from_str(&error);
992 -+ if (value < 0 && error == 0)
993 -+ {
994 -+ push_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
995 -+ "Cast to signed converted positive out-of-range integer to "
996 -+ "it's negative complement");
997 -+ }
998 -+ return value;
999 -+}
1000 -+
1001 -+
1002 -+void Item_func_unsigned::print(String *str, enum_query_type query_type)
1003 -+{
1004 -+ str->append(STRING_WITH_LEN("cast("));
1005 -+ args[0]->print(str, query_type);
1006 -+ str->append(STRING_WITH_LEN(" as unsigned)"));
1007 -+
1008 -+}
1009 -+
1010 -+
1011 -+longlong Item_func_unsigned::val_int()
1012 -+{
1013 -+ longlong value;
1014 -+ int error;
1015 -+
1016 -+ if (args[0]->cast_to_int_type() == DECIMAL_RESULT)
1017 -+ {
1018 -+ my_decimal tmp, *dec= args[0]->val_decimal(&tmp);
1019 -+ if (!(null_value= args[0]->null_value))
1020 -+ my_decimal2int(E_DEC_FATAL_ERROR, dec, 1, &value);
1021 -+ else
1022 -+ value= 0;
1023 -+ return value;
1024 -+ }
1025 -+ else if (args[0]->cast_to_int_type() != STRING_RESULT ||
1026 -+ args[0]->result_as_longlong())
1027 -+ {
1028 -+ value= args[0]->val_int();
1029 -+ null_value= args[0]->null_value;
1030 -+ return value;
1031 -+ }
1032 -+
1033 -+ value= val_int_from_str(&error);
1034 -+ if (error < 0)
1035 -+ push_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
1036 -+ "Cast to unsigned converted negative integer to it's "
1037 -+ "positive complement");
1038 -+ return value;
1039 -+}
1040 -+
1041 -+
1042 -+String *Item_decimal_typecast::val_str(String *str)
1043 -+{
1044 -+ my_decimal tmp_buf, *tmp= val_decimal(&tmp_buf);
1045 -+ if (null_value)
1046 -+ return NULL;
1047 -+ my_decimal2string(E_DEC_FATAL_ERROR, tmp, 0, 0, 0, str);
1048 -+ return str;
1049 -+}
1050 -+
1051 -+
1052 -+double Item_decimal_typecast::val_real()
1053 -+{
1054 -+ my_decimal tmp_buf, *tmp= val_decimal(&tmp_buf);
1055 -+ double res;
1056 -+ if (null_value)
1057 -+ return 0.0;
1058 -+ my_decimal2double(E_DEC_FATAL_ERROR, tmp, &res);
1059 -+ return res;
1060 -+}
1061 -+
1062 -+
1063 -+longlong Item_decimal_typecast::val_int()
1064 -+{
1065 -+ my_decimal tmp_buf, *tmp= val_decimal(&tmp_buf);
1066 -+ longlong res;
1067 -+ if (null_value)
1068 -+ return 0;
1069 -+ my_decimal2int(E_DEC_FATAL_ERROR, tmp, unsigned_flag, &res);
1070 -+ return res;
1071 -+}
1072 -+
1073 -+
1074 -+my_decimal *Item_decimal_typecast::val_decimal(my_decimal *dec)
1075 -+{
1076 -+ my_decimal tmp_buf, *tmp= args[0]->val_decimal(&tmp_buf);
1077 -+ bool sign;
1078 -+ uint precision;
1079 -+
1080 -+ if ((null_value= args[0]->null_value))
1081 -+ return NULL;
1082 -+ my_decimal_round(E_DEC_FATAL_ERROR, tmp, decimals, FALSE, dec);
1083 -+ sign= dec->sign();
1084 -+ if (unsigned_flag)
1085 -+ {
1086 -+ if (sign)
1087 -+ {
1088 -+ my_decimal_set_zero(dec);
1089 -+ goto err;
1090 -+ }
1091 -+ }
1092 -+ precision= my_decimal_length_to_precision(max_length,
1093 -+ decimals, unsigned_flag);
1094 -+ if (precision - decimals < (uint) my_decimal_intg(dec))
1095 -+ {
1096 -+ max_my_decimal(dec, precision, decimals);
1097 -+ dec->sign(sign);
1098 -+ goto err;
1099 -+ }
1100 -+ return dec;
1101 -+
1102 -+err:
1103 -+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
1104 -+ ER_WARN_DATA_OUT_OF_RANGE,
1105 -+ ER(ER_WARN_DATA_OUT_OF_RANGE),
1106 -+ name, 1);
1107 -+ return dec;
1108 -+}
1109 -+
1110 -+
1111 -+void Item_decimal_typecast::print(String *str, enum_query_type query_type)
1112 -+{
1113 -+ char len_buf[20*3 + 1];
1114 -+ char *end;
1115 -+
1116 -+ uint precision= my_decimal_length_to_precision(max_length, decimals,
1117 -+ unsigned_flag);
1118 -+ str->append(STRING_WITH_LEN("cast("));
1119 -+ args[0]->print(str, query_type);
1120 -+ str->append(STRING_WITH_LEN(" as decimal("));
1121 -+
1122 -+ end=int10_to_str(precision, len_buf,10);
1123 -+ str->append(len_buf, (uint32) (end - len_buf));
1124 -+
1125 -+ str->append(',');
1126 -+
1127 -+ end=int10_to_str(decimals, len_buf,10);
1128 -+ str->append(len_buf, (uint32) (end - len_buf));
1129 -+
1130 -+ str->append(')');
1131 -+ str->append(')');
1132 -+}
1133 -+
1134 -+
1135 -+double Item_func_plus::real_op()
1136 -+{
1137 -+ double value= args[0]->val_real() + args[1]->val_real();
1138 -+ if ((null_value=args[0]->null_value || args[1]->null_value))
1139 -+ return 0.0;
1140 -+ return fix_result(value);
1141 -+}
1142 -+
1143 -+
1144 -+longlong Item_func_plus::int_op()
1145 -+{
1146 -+ longlong value=args[0]->val_int()+args[1]->val_int();
1147 -+ if ((null_value=args[0]->null_value || args[1]->null_value))
1148 -+ return 0;
1149 -+ return value;
1150 -+}
1151 -+
1152 -+
1153 -+/**
1154 -+ Calculate plus of two decimals.
1155 -+
1156 -+ @param decimal_value Buffer that can be used to store result
1157 -+
1158 -+ @retval
1159 -+ 0 Value was NULL; In this case null_value is set
1160 -+ @retval
1161 -+ \# Value of operation as a decimal
1162 -+*/
1163 -+
1164 -+my_decimal *Item_func_plus::decimal_op(my_decimal *decimal_value)
1165 -+{
1166 -+ my_decimal value1, *val1;
1167 -+ my_decimal value2, *val2;
1168 -+ val1= args[0]->val_decimal(&value1);
1169 -+ if ((null_value= args[0]->null_value))
1170 -+ return 0;
1171 -+ val2= args[1]->val_decimal(&value2);
1172 -+ if (!(null_value= (args[1]->null_value ||
1173 -+ (my_decimal_add(E_DEC_FATAL_ERROR, decimal_value, val1,
1174 -+ val2) > 3))))
1175 -+ return decimal_value;
1176 -+ return 0;
1177 -+}
1178 -+
1179 -+/**
1180 -+ Set precision of results for additive operations (+ and -)
1181 -+*/
1182 -+void Item_func_additive_op::result_precision()
1183 -+{
1184 -+ decimals= max(args[0]->decimals, args[1]->decimals);
1185 -+ int arg1_int= args[0]->decimal_precision() - args[0]->decimals;
1186 -+ int arg2_int= args[1]->decimal_precision() - args[1]->decimals;
1187 -+ int precision= max(arg1_int, arg2_int) + 1 + decimals;
1188 -+
1189 -+ /* Integer operations keep unsigned_flag if one of arguments is unsigned */
1190 -+ if (result_type() == INT_RESULT)
1191 -+ unsigned_flag= args[0]->unsigned_flag | args[1]->unsigned_flag;
1192 -+ else
1193 -+ unsigned_flag= args[0]->unsigned_flag & args[1]->unsigned_flag;
1194 -+ max_length= my_decimal_precision_to_length_no_truncation(precision, decimals,
1195 -+ unsigned_flag);
1196 -+}
1197 -+
1198 -+
1199 -+/**
1200 -+ The following function is here to allow the user to force
1201 -+ subtraction of UNSIGNED BIGINT to return negative values.
1202 -+*/
1203 -+
1204 -+void Item_func_minus::fix_length_and_dec()
1205 -+{
1206 -+ Item_num_op::fix_length_and_dec();
1207 -+ if (unsigned_flag &&
1208 -+ (current_thd->variables.sql_mode & MODE_NO_UNSIGNED_SUBTRACTION))
1209 -+ unsigned_flag=0;
1210 -+}
1211 -+
1212 -+
1213 -+double Item_func_minus::real_op()
1214 -+{
1215 -+ double value= args[0]->val_real() - args[1]->val_real();
1216 -+ if ((null_value=args[0]->null_value || args[1]->null_value))
1217 -+ return 0.0;
1218 -+ return fix_result(value);
1219 -+}
1220 -+
1221 -+
1222 -+longlong Item_func_minus::int_op()
1223 -+{
1224 -+ longlong value=args[0]->val_int() - args[1]->val_int();
1225 -+ if ((null_value=args[0]->null_value || args[1]->null_value))
1226 -+ return 0;
1227 -+ return value;
1228 -+}
1229 -+
1230 -+
1231 -+/**
1232 -+ See Item_func_plus::decimal_op for comments.
1233 -+*/
1234 -+
1235 -+my_decimal *Item_func_minus::decimal_op(my_decimal *decimal_value)
1236 -+{
1237 -+ my_decimal value1, *val1;
1238 -+ my_decimal value2, *val2=
1239 -+
1240 -+ val1= args[0]->val_decimal(&value1);
1241 -+ if ((null_value= args[0]->null_value))
1242 -+ return 0;
1243 -+ val2= args[1]->val_decimal(&value2);
1244 -+ if (!(null_value= (args[1]->null_value ||
1245 -+ (my_decimal_sub(E_DEC_FATAL_ERROR, decimal_value, val1,
1246 -+ val2) > 3))))
1247 -+ return decimal_value;
1248 -+ return 0;
1249 -+}
1250 -+
1251 -+
1252 -+double Item_func_mul::real_op()
1253 -+{
1254 -+ DBUG_ASSERT(fixed == 1);
1255 -+ double value= args[0]->val_real() * args[1]->val_real();
1256 -+ if ((null_value=args[0]->null_value || args[1]->null_value))
1257 -+ return 0.0;
1258 -+ return fix_result(value);
1259 -+}
1260 -+
1261 -+
1262 -+longlong Item_func_mul::int_op()
1263 -+{
1264 -+ DBUG_ASSERT(fixed == 1);
1265 -+ longlong value=args[0]->val_int()*args[1]->val_int();
1266 -+ if ((null_value=args[0]->null_value || args[1]->null_value))
1267 -+ return 0;
1268 -+ return value;
1269 -+}
1270 -+
1271 -+
1272 -+/** See Item_func_plus::decimal_op for comments. */
1273 -+
1274 -+my_decimal *Item_func_mul::decimal_op(my_decimal *decimal_value)
1275 -+{
1276 -+ my_decimal value1, *val1;
1277 -+ my_decimal value2, *val2;
1278 -+ val1= args[0]->val_decimal(&value1);
1279 -+ if ((null_value= args[0]->null_value))
1280 -+ return 0;
1281 -+ val2= args[1]->val_decimal(&value2);
1282 -+ if (!(null_value= (args[1]->null_value ||
1283 -+ (my_decimal_mul(E_DEC_FATAL_ERROR, decimal_value, val1,
1284 -+ val2) > 3))))
1285 -+ return decimal_value;
1286 -+ return 0;
1287 -+}
1288 -+
1289 -+
1290 -+void Item_func_mul::result_precision()
1291 -+{
1292 -+ /* Integer operations keep unsigned_flag if one of arguments is unsigned */
1293 -+ if (result_type() == INT_RESULT)
1294 -+ unsigned_flag= args[0]->unsigned_flag | args[1]->unsigned_flag;
1295 -+ else
1296 -+ unsigned_flag= args[0]->unsigned_flag & args[1]->unsigned_flag;
1297 -+ decimals= min(args[0]->decimals + args[1]->decimals, DECIMAL_MAX_SCALE);
1298 -+ uint est_prec = args[0]->decimal_precision() + args[1]->decimal_precision();
1299 -+ uint precision= min(est_prec, DECIMAL_MAX_PRECISION);
1300 -+ max_length= my_decimal_precision_to_length_no_truncation(precision, decimals,
1301 -+ unsigned_flag);
1302 -+}
1303 -+
1304 -+
1305 -+double Item_func_div::real_op()
1306 -+{
1307 -+ DBUG_ASSERT(fixed == 1);
1308 -+ double value= args[0]->val_real();
1309 -+ double val2= args[1]->val_real();
1310 -+ if ((null_value= args[0]->null_value || args[1]->null_value))
1311 -+ return 0.0;
1312 -+ if (val2 == 0.0)
1313 -+ {
1314 -+ signal_divide_by_null();
1315 -+ return 0.0;
1316 -+ }
1317 -+ return fix_result(value/val2);
1318 -+}
1319 -+
1320 -+
1321 -+my_decimal *Item_func_div::decimal_op(my_decimal *decimal_value)
1322 -+{
1323 -+ my_decimal value1, *val1;
1324 -+ my_decimal value2, *val2;
1325 -+ int err;
1326 -+
1327 -+ val1= args[0]->val_decimal(&value1);
1328 -+ if ((null_value= args[0]->null_value))
1329 -+ return 0;
1330 -+ val2= args[1]->val_decimal(&value2);
1331 -+ if ((null_value= args[1]->null_value))
1332 -+ return 0;
1333 -+ if ((err= my_decimal_div(E_DEC_FATAL_ERROR & ~E_DEC_DIV_ZERO, decimal_value,
1334 -+ val1, val2, prec_increment)) > 3)
1335 -+ {
1336 -+ if (err == E_DEC_DIV_ZERO)
1337 -+ signal_divide_by_null();
1338 -+ null_value= 1;
1339 -+ return 0;
1340 -+ }
1341 -+ return decimal_value;
1342 -+}
1343 -+
1344 -+
1345 -+void Item_func_div::result_precision()
1346 -+{
1347 -+ uint precision=min(args[0]->decimal_precision() +
1348 -+ args[1]->decimals + prec_increment,
1349 -+ DECIMAL_MAX_PRECISION);
1350 -+
1351 -+ /* Integer operations keep unsigned_flag if one of arguments is unsigned */
1352 -+ if (result_type() == INT_RESULT)
1353 -+ unsigned_flag= args[0]->unsigned_flag | args[1]->unsigned_flag;
1354 -+ else
1355 -+ unsigned_flag= args[0]->unsigned_flag & args[1]->unsigned_flag;
1356 -+ decimals= min(args[0]->decimals + prec_increment, DECIMAL_MAX_SCALE);
1357 -+ max_length= my_decimal_precision_to_length_no_truncation(precision, decimals,
1358 -+ unsigned_flag);
1359 -+}
1360 -+
1361 -+
1362 -+void Item_func_div::fix_length_and_dec()
1363 -+{
1364 -+ DBUG_ENTER("Item_func_div::fix_length_and_dec");
1365 -+ prec_increment= current_thd->variables.div_precincrement;
1366 -+ Item_num_op::fix_length_and_dec();
1367 -+ switch(hybrid_type) {
1368 -+ case REAL_RESULT:
1369 -+ {
1370 -+ decimals=max(args[0]->decimals,args[1]->decimals)+prec_increment;
1371 -+ set_if_smaller(decimals, NOT_FIXED_DEC);
1372 -+ uint tmp=float_length(decimals);
1373 -+ if (decimals == NOT_FIXED_DEC)
1374 -+ max_length= tmp;
1375 -+ else
1376 -+ {
1377 -+ max_length=args[0]->max_length - args[0]->decimals + decimals;
1378 -+ set_if_smaller(max_length,tmp);
1379 -+ }
1380 -+ break;
1381 -+ }
1382 -+ case INT_RESULT:
1383 -+ hybrid_type= DECIMAL_RESULT;
1384 -+ DBUG_PRINT("info", ("Type changed: DECIMAL_RESULT"));
1385 -+ result_precision();
1386 -+ break;
1387 -+ case DECIMAL_RESULT:
1388 -+ result_precision();
1389 -+ break;
1390 -+ default:
1391 -+ DBUG_ASSERT(0);
1392 -+ }
1393 -+ maybe_null= 1; // devision by zero
1394 -+ DBUG_VOID_RETURN;
1395 -+}
1396 -+
1397 -+
1398 -+/* Integer division */
1399 -+longlong Item_func_int_div::val_int()
1400 -+{
1401 -+ DBUG_ASSERT(fixed == 1);
1402 -+ longlong value=args[0]->val_int();
1403 -+ longlong val2=args[1]->val_int();
1404 -+ if ((null_value= (args[0]->null_value || args[1]->null_value)))
1405 -+ return 0;
1406 -+ if (val2 == 0)
1407 -+ {
1408 -+ signal_divide_by_null();
1409 -+ return 0;
1410 -+ }
1411 -+
1412 -+ if (unsigned_flag)
1413 -+ return ((ulonglong) value / (ulonglong) val2);
1414 -+ else if (value == LONGLONG_MIN && val2 == -1)
1415 -+ return LONGLONG_MIN;
1416 -+ else
1417 -+ return value / val2;
1418 -+}
1419 -+
1420 -+
1421 -+void Item_func_int_div::fix_length_and_dec()
1422 -+{
1423 -+ Item_result argtype= args[0]->result_type();
1424 -+ /* use precision ony for the data type it is applicable for and valid */
1425 -+ max_length=args[0]->max_length -
1426 -+ (argtype == DECIMAL_RESULT || argtype == INT_RESULT ?
1427 -+ args[0]->decimals : 0);
1428 -+ maybe_null=1;
1429 -+ unsigned_flag=args[0]->unsigned_flag | args[1]->unsigned_flag;
1430 -+}
1431 -+
1432 -+
1433 -+longlong Item_func_mod::int_op()
1434 -+{
1435 -+ DBUG_ASSERT(fixed == 1);
1436 -+ longlong value= args[0]->val_int();
1437 -+ longlong val2= args[1]->val_int();
1438 -+ longlong result;
1439 -+
1440 -+ if ((null_value= args[0]->null_value || args[1]->null_value))
1441 -+ return 0; /* purecov: inspected */
1442 -+ if (val2 == 0)
1443 -+ {
1444 -+ signal_divide_by_null();
1445 -+ return 0;
1446 -+ }
1447 -+
1448 -+ if (args[0]->unsigned_flag)
1449 -+ result= args[1]->unsigned_flag ?
1450 -+ ((ulonglong) value) % ((ulonglong) val2) : ((ulonglong) value) % val2;
1451 -+ else result= args[1]->unsigned_flag ?
1452 -+ value % ((ulonglong) val2) :
1453 -+ (val2 == -1) ? 0 : value % val2;
1454 -+
1455 -+ return result;
1456 -+}
1457 -+
1458 -+double Item_func_mod::real_op()
1459 -+{
1460 -+ DBUG_ASSERT(fixed == 1);
1461 -+ double value= args[0]->val_real();
1462 -+ double val2= args[1]->val_real();
1463 -+ if ((null_value= args[0]->null_value || args[1]->null_value))
1464 -+ return 0.0; /* purecov: inspected */
1465 -+ if (val2 == 0.0)
1466 -+ {
1467 -+ signal_divide_by_null();
1468 -+ return 0.0;
1469 -+ }
1470 -+ return fmod(value,val2);
1471 -+}
1472 -+
1473 -+
1474 -+my_decimal *Item_func_mod::decimal_op(my_decimal *decimal_value)
1475 -+{
1476 -+ my_decimal value1, *val1;
1477 -+ my_decimal value2, *val2;
1478 -+
1479 -+ val1= args[0]->val_decimal(&value1);
1480 -+ if ((null_value= args[0]->null_value))
1481 -+ return 0;
1482 -+ val2= args[1]->val_decimal(&value2);
1483 -+ if ((null_value= args[1]->null_value))
1484 -+ return 0;
1485 -+ switch (my_decimal_mod(E_DEC_FATAL_ERROR & ~E_DEC_DIV_ZERO, decimal_value,
1486 -+ val1, val2)) {
1487 -+ case E_DEC_TRUNCATED:
1488 -+ case E_DEC_OK:
1489 -+ return decimal_value;
1490 -+ case E_DEC_DIV_ZERO:
1491 -+ signal_divide_by_null();
1492 -+ default:
1493 -+ null_value= 1;
1494 -+ return 0;
1495 -+ }
1496 -+}
1497 -+
1498 -+
1499 -+void Item_func_mod::result_precision()
1500 -+{
1501 -+ decimals= max(args[0]->decimals, args[1]->decimals);
1502 -+ max_length= max(args[0]->max_length, args[1]->max_length);
1503 -+}
1504 -+
1505 -+
1506 -+void Item_func_mod::fix_length_and_dec()
1507 -+{
1508 -+ Item_num_op::fix_length_and_dec();
1509 -+ maybe_null= 1;
1510 -+ unsigned_flag= args[0]->unsigned_flag;
1511 -+}
1512 -+
1513 -+
1514 -+double Item_func_neg::real_op()
1515 -+{
1516 -+ double value= args[0]->val_real();
1517 -+ null_value= args[0]->null_value;
1518 -+ return -value;
1519 -+}
1520 -+
1521 -+
1522 -+longlong Item_func_neg::int_op()
1523 -+{
1524 -+ longlong value= args[0]->val_int();
1525 -+ null_value= args[0]->null_value;
1526 -+ return -value;
1527 -+}
1528 -+
1529 -+
1530 -+my_decimal *Item_func_neg::decimal_op(my_decimal *decimal_value)
1531 -+{
1532 -+ my_decimal val, *value= args[0]->val_decimal(&val);
1533 -+ if (!(null_value= args[0]->null_value))
1534 -+ {
1535 -+ my_decimal2decimal(value, decimal_value);
1536 -+ my_decimal_neg(decimal_value);
1537 -+ return decimal_value;
1538 -+ }
1539 -+ return 0;
1540 -+}
1541 -+
1542 -+
1543 -+void Item_func_neg::fix_num_length_and_dec()
1544 -+{
1545 -+ decimals= args[0]->decimals;
1546 -+ /* 1 add because sign can appear */
1547 -+ max_length= args[0]->max_length + 1;
1548 -+}
1549 -+
1550 -+
1551 -+void Item_func_neg::fix_length_and_dec()
1552 -+{
1553 -+ DBUG_ENTER("Item_func_neg::fix_length_and_dec");
1554 -+ Item_func_num1::fix_length_and_dec();
1555 -+
1556 -+ /*
1557 -+ If this is in integer context keep the context as integer if possible
1558 -+ (This is how multiplication and other integer functions works)
1559 -+ Use val() to get value as arg_type doesn't mean that item is
1560 -+ Item_int or Item_real due to existence of Item_param.
1561 -+ */
1562 -+ if (hybrid_type == INT_RESULT && args[0]->const_item())
1563 -+ {
1564 -+ longlong val= args[0]->val_int();
1565 -+ if ((ulonglong) val >= (ulonglong) LONGLONG_MIN &&
1566 -+ ((ulonglong) val != (ulonglong) LONGLONG_MIN ||
1567 -+ args[0]->type() != INT_ITEM))
1568 -+ {
1569 -+ /*
1570 -+ Ensure that result is converted to DECIMAL, as longlong can't hold
1571 -+ the negated number
1572 -+ */
1573 -+ hybrid_type= DECIMAL_RESULT;
1574 -+ DBUG_PRINT("info", ("Type changed: DECIMAL_RESULT"));
1575 -+ }
1576 -+ }
1577 -+ unsigned_flag= 0;
1578 -+ DBUG_VOID_RETURN;
1579 -+}
1580 -+
1581 -+
1582 -+double Item_func_abs::real_op()
1583 -+{
1584 -+ double value= args[0]->val_real();
1585 -+ null_value= args[0]->null_value;
1586 -+ return fabs(value);
1587 -+}
1588 -+
1589 -+
1590 -+longlong Item_func_abs::int_op()
1591 -+{
1592 -+ longlong value= args[0]->val_int();
1593 -+ if ((null_value= args[0]->null_value))
1594 -+ return 0;
1595 -+ return (value >= 0) || unsigned_flag ? value : -value;
1596 -+}
1597 -+
1598 -+
1599 -+my_decimal *Item_func_abs::decimal_op(my_decimal *decimal_value)
1600 -+{
1601 -+ my_decimal val, *value= args[0]->val_decimal(&val);
1602 -+ if (!(null_value= args[0]->null_value))
1603 -+ {
1604 -+ my_decimal2decimal(value, decimal_value);
1605 -+ if (decimal_value->sign())
1606 -+ my_decimal_neg(decimal_value);
1607 -+ return decimal_value;
1608 -+ }
1609 -+ return 0;
1610 -+}
1611 -+
1612 -+
1613 -+void Item_func_abs::fix_length_and_dec()
1614 -+{
1615 -+ Item_func_num1::fix_length_and_dec();
1616 -+ unsigned_flag= args[0]->unsigned_flag;
1617 -+}
1618 -+
1619 -+
1620 -+/** Gateway to natural LOG function. */
1621 -+double Item_func_ln::val_real()
1622 -+{
1623 -+ DBUG_ASSERT(fixed == 1);
1624 -+ double value= args[0]->val_real();
1625 -+ if ((null_value= args[0]->null_value))
1626 -+ return 0.0;
1627 -+ if (value <= 0.0)
1628 -+ {
1629 -+ signal_divide_by_null();
1630 -+ return 0.0;
1631 -+ }
1632 -+ return log(value);
1633 -+}
1634 -+
1635 -+/**
1636 -+ Extended but so slower LOG function.
1637 -+
1638 -+ We have to check if all values are > zero and first one is not one
1639 -+ as these are the cases then result is not a number.
1640 -+*/
1641 -+double Item_func_log::val_real()
1642 -+{
1643 -+ DBUG_ASSERT(fixed == 1);
1644 -+ double value= args[0]->val_real();
1645 -+ if ((null_value= args[0]->null_value))
1646 -+ return 0.0;
1647 -+ if (value <= 0.0)
1648 -+ {
1649 -+ signal_divide_by_null();
1650 -+ return 0.0;
1651 -+ }
1652 -+ if (arg_count == 2)
1653 -+ {
1654 -+ double value2= args[1]->val_real();
1655 -+ if ((null_value= args[1]->null_value))
1656 -+ return 0.0;
1657 -+ if (value2 <= 0.0 || value == 1.0)
1658 -+ {
1659 -+ signal_divide_by_null();
1660 -+ return 0.0;
1661 -+ }
1662 -+ return log(value2) / log(value);
1663 -+ }
1664 -+ return log(value);
1665 -+}
1666 -+
1667 -+double Item_func_log2::val_real()
1668 -+{
1669 -+ DBUG_ASSERT(fixed == 1);
1670 -+ double value= args[0]->val_real();
1671 -+
1672 -+ if ((null_value=args[0]->null_value))
1673 -+ return 0.0;
1674 -+ if (value <= 0.0)
1675 -+ {
1676 -+ signal_divide_by_null();
1677 -+ return 0.0;
1678 -+ }
1679 -+ return log(value) / M_LN2;
1680 -+}
1681 -+
1682 -+double Item_func_log10::val_real()
1683 -+{
1684 -+ DBUG_ASSERT(fixed == 1);
1685 -+ double value= args[0]->val_real();
1686 -+ if ((null_value= args[0]->null_value))
1687 -+ return 0.0;
1688 -+ if (value <= 0.0)
1689 -+ {
1690 -+ signal_divide_by_null();
1691 -+ return 0.0;
1692 -+ }
1693 -+ return log10(value);
1694 -+}
1695 -+
1696 -+double Item_func_exp::val_real()
1697 -+{
1698 -+ DBUG_ASSERT(fixed == 1);
1699 -+ double value= args[0]->val_real();
1700 -+ if ((null_value=args[0]->null_value))
1701 -+ return 0.0; /* purecov: inspected */
1702 -+ return fix_result(exp(value));
1703 -+}
1704 -+
1705 -+double Item_func_sqrt::val_real()
1706 -+{
1707 -+ DBUG_ASSERT(fixed == 1);
1708 -+ double value= args[0]->val_real();
1709 -+ if ((null_value=(args[0]->null_value || value < 0)))
1710 -+ return 0.0; /* purecov: inspected */
1711 -+ return sqrt(value);
1712 -+}
1713 -+
1714 -+double Item_func_pow::val_real()
1715 -+{
1716 -+ DBUG_ASSERT(fixed == 1);
1717 -+ double value= args[0]->val_real();
1718 -+ double val2= args[1]->val_real();
1719 -+ if ((null_value=(args[0]->null_value || args[1]->null_value)))
1720 -+ return 0.0; /* purecov: inspected */
1721 -+ return fix_result(pow(value,val2));
1722 -+}
1723 -+
1724 -+// Trigonometric functions
1725 -+
1726 -+double Item_func_acos::val_real()
1727 -+{
1728 -+ DBUG_ASSERT(fixed == 1);
1729 -+ // the volatile's for BUG #2338 to calm optimizer down (because of gcc's bug)
1730 -+ volatile double value= args[0]->val_real();
1731 -+ if ((null_value=(args[0]->null_value || (value < -1.0 || value > 1.0))))
1732 -+ return 0.0;
1733 -+ return acos(value);
1734 -+}
1735 -+
1736 -+double Item_func_asin::val_real()
1737 -+{
1738 -+ DBUG_ASSERT(fixed == 1);
1739 -+ // the volatile's for BUG #2338 to calm optimizer down (because of gcc's bug)
1740 -+ volatile double value= args[0]->val_real();
1741 -+ if ((null_value=(args[0]->null_value || (value < -1.0 || value > 1.0))))
1742 -+ return 0.0;
1743 -+ return asin(value);
1744 -+}
1745 -+
1746 -+double Item_func_atan::val_real()
1747 -+{
1748 -+ DBUG_ASSERT(fixed == 1);
1749 -+ double value= args[0]->val_real();
1750 -+ if ((null_value=args[0]->null_value))
1751 -+ return 0.0;
1752 -+ if (arg_count == 2)
1753 -+ {
1754 -+ double val2= args[1]->val_real();
1755 -+ if ((null_value=args[1]->null_value))
1756 -+ return 0.0;
1757 -+ return fix_result(atan2(value,val2));
1758 -+ }
1759 -+ return atan(value);
1760 -+}
1761 -+
1762 -+double Item_func_cos::val_real()
1763 -+{
1764 -+ DBUG_ASSERT(fixed == 1);
1765 -+ double value= args[0]->val_real();
1766 -+ if ((null_value=args[0]->null_value))
1767 -+ return 0.0;
1768 -+ return cos(value);
1769 -+}
1770 -+
1771 -+double Item_func_sin::val_real()
1772 -+{
1773 -+ DBUG_ASSERT(fixed == 1);
1774 -+ double value= args[0]->val_real();
1775 -+ if ((null_value=args[0]->null_value))
1776 -+ return 0.0;
1777 -+ return sin(value);
1778 -+}
1779 -+
1780 -+double Item_func_tan::val_real()
1781 -+{
1782 -+ DBUG_ASSERT(fixed == 1);
1783 -+ double value= args[0]->val_real();
1784 -+ if ((null_value=args[0]->null_value))
1785 -+ return 0.0;
1786 -+ return fix_result(tan(value));
1787 -+}
1788 -+
1789 -+
1790 -+// Shift-functions, same as << and >> in C/C++
1791 -+
1792 -+
1793 -+longlong Item_func_shift_left::val_int()
1794 -+{
1795 -+ DBUG_ASSERT(fixed == 1);
1796 -+ uint shift;
1797 -+ ulonglong res= ((ulonglong) args[0]->val_int() <<
1798 -+ (shift=(uint) args[1]->val_int()));
1799 -+ if (args[0]->null_value || args[1]->null_value)
1800 -+ {
1801 -+ null_value=1;
1802 -+ return 0;
1803 -+ }
1804 -+ null_value=0;
1805 -+ return (shift < sizeof(longlong)*8 ? (longlong) res : LL(0));
1806 -+}
1807 -+
1808 -+longlong Item_func_shift_right::val_int()
1809 -+{
1810 -+ DBUG_ASSERT(fixed == 1);
1811 -+ uint shift;
1812 -+ ulonglong res= (ulonglong) args[0]->val_int() >>
1813 -+ (shift=(uint) args[1]->val_int());
1814 -+ if (args[0]->null_value || args[1]->null_value)
1815 -+ {
1816 -+ null_value=1;
1817 -+ return 0;
1818 -+ }
1819 -+ null_value=0;
1820 -+ return (shift < sizeof(longlong)*8 ? (longlong) res : LL(0));
1821 -+}
1822 -+
1823 -+
1824 -+longlong Item_func_bit_neg::val_int()
1825 -+{
1826 -+ DBUG_ASSERT(fixed == 1);
1827 -+ ulonglong res= (ulonglong) args[0]->val_int();
1828 -+ if ((null_value=args[0]->null_value))
1829 -+ return 0;
1830 -+ return ~res;
1831 -+}
1832 -+
1833 -+
1834 -+// Conversion functions
1835 -+
1836 -+void Item_func_integer::fix_length_and_dec()
1837 -+{
1838 -+ max_length=args[0]->max_length - args[0]->decimals+1;
1839 -+ uint tmp=float_length(decimals);
1840 -+ set_if_smaller(max_length,tmp);
1841 -+ decimals=0;
1842 -+}
1843 -+
1844 -+void Item_func_int_val::fix_num_length_and_dec()
1845 -+{
1846 -+ ulonglong tmp_max_length= (ulonglong ) args[0]->max_length -
1847 -+ (args[0]->decimals ? args[0]->decimals + 1 : 0) + 2;
1848 -+ max_length= tmp_max_length > (ulonglong) max_field_size ?
1849 -+ max_field_size : (uint32) tmp_max_length;
1850 -+ uint tmp= float_length(decimals);
1851 -+ set_if_smaller(max_length,tmp);
1852 -+ decimals= 0;
1853 -+}
1854 -+
1855 -+
1856 -+void Item_func_int_val::find_num_type()
1857 -+{
1858 -+ DBUG_ENTER("Item_func_int_val::find_num_type");
1859 -+ DBUG_PRINT("info", ("name %s", func_name()));
1860 -+ switch(hybrid_type= args[0]->result_type())
1861 -+ {
1862 -+ case STRING_RESULT:
1863 -+ case REAL_RESULT:
1864 -+ hybrid_type= REAL_RESULT;
1865 -+ max_length= float_length(decimals);
1866 -+ break;
1867 -+ case INT_RESULT:
1868 -+ case DECIMAL_RESULT:
1869 -+ /*
1870 -+ -2 because in most high position can't be used any digit for longlong
1871 -+ and one position for increasing value during operation
1872 -+ */
1873 -+ if ((args[0]->max_length - args[0]->decimals) >=
1874 -+ (DECIMAL_LONGLONG_DIGITS - 2))
1875 -+ {
1876 -+ hybrid_type= DECIMAL_RESULT;
1877 -+ }
1878 -+ else
1879 -+ {
1880 -+ unsigned_flag= args[0]->unsigned_flag;
1881 -+ hybrid_type= INT_RESULT;
1882 -+ }
1883 -+ break;
1884 -+ default:
1885 -+ DBUG_ASSERT(0);
1886 -+ }
1887 -+ DBUG_PRINT("info", ("Type: %s",
1888 -+ (hybrid_type == REAL_RESULT ? "REAL_RESULT" :
1889 -+ hybrid_type == DECIMAL_RESULT ? "DECIMAL_RESULT" :
1890 -+ hybrid_type == INT_RESULT ? "INT_RESULT" :
1891 -+ "--ILLEGAL!!!--")));
1892 -+
1893 -+ DBUG_VOID_RETURN;
1894 -+}
1895 -+
1896 -+
1897 -+longlong Item_func_ceiling::int_op()
1898 -+{
1899 -+ longlong result;
1900 -+ switch (args[0]->result_type()) {
1901 -+ case INT_RESULT:
1902 -+ result= args[0]->val_int();
1903 -+ null_value= args[0]->null_value;
1904 -+ break;
1905 -+ case DECIMAL_RESULT:
1906 -+ {
1907 -+ my_decimal dec_buf, *dec;
1908 -+ if ((dec= Item_func_ceiling::decimal_op(&dec_buf)))
1909 -+ my_decimal2int(E_DEC_FATAL_ERROR, dec, unsigned_flag, &result);
1910 -+ else
1911 -+ result= 0;
1912 -+ break;
1913 -+ }
1914 -+ default:
1915 -+ result= (longlong)Item_func_ceiling::real_op();
1916 -+ };
1917 -+ return result;
1918 -+}
1919 -+
1920 -+
1921 -+double Item_func_ceiling::real_op()
1922 -+{
1923 -+ /*
1924 -+ the volatile's for BUG #3051 to calm optimizer down (because of gcc's
1925 -+ bug)
1926 -+ */
1927 -+ volatile double value= args[0]->val_real();
1928 -+ null_value= args[0]->null_value;
1929 -+ return ceil(value);
1930 -+}
1931 -+
1932 -+
1933 -+my_decimal *Item_func_ceiling::decimal_op(my_decimal *decimal_value)
1934 -+{
1935 -+ my_decimal val, *value= args[0]->val_decimal(&val);
1936 -+ if (!(null_value= (args[0]->null_value ||
1937 -+ my_decimal_ceiling(E_DEC_FATAL_ERROR, value,
1938 -+ decimal_value) > 1)))
1939 -+ return decimal_value;
1940 -+ return 0;
1941 -+}
1942 -+
1943 -+
1944 -+longlong Item_func_floor::int_op()
1945 -+{
1946 -+ longlong result;
1947 -+ switch (args[0]->result_type()) {
1948 -+ case INT_RESULT:
1949 -+ result= args[0]->val_int();
1950 -+ null_value= args[0]->null_value;
1951 -+ break;
1952 -+ case DECIMAL_RESULT:
1953 -+ {
1954 -+ my_decimal dec_buf, *dec;
1955 -+ if ((dec= Item_func_floor::decimal_op(&dec_buf)))
1956 -+ my_decimal2int(E_DEC_FATAL_ERROR, dec, unsigned_flag, &result);
1957 -+ else
1958 -+ result= 0;
1959 -+ break;
1960 -+ }
1961 -+ default:
1962 -+ result= (longlong)Item_func_floor::real_op();
1963 -+ };
1964 -+ return result;
1965 -+}
1966 -+
1967 -+
1968 -+double Item_func_floor::real_op()
1969 -+{
1970 -+ /*
1971 -+ the volatile's for BUG #3051 to calm optimizer down (because of gcc's
1972 -+ bug)
1973 -+ */
1974 -+ volatile double value= args[0]->val_real();
1975 -+ null_value= args[0]->null_value;
1976 -+ return floor(value);
1977 -+}
1978 -+
1979 -+
1980 -+my_decimal *Item_func_floor::decimal_op(my_decimal *decimal_value)
1981 -+{
1982 -+ my_decimal val, *value= args[0]->val_decimal(&val);
1983 -+ if (!(null_value= (args[0]->null_value ||
1984 -+ my_decimal_floor(E_DEC_FATAL_ERROR, value,
1985 -+ decimal_value) > 1)))
1986 -+ return decimal_value;
1987 -+ return 0;
1988 -+}
1989 -+
1990 -+
1991 -+void Item_func_round::fix_length_and_dec()
1992 -+{
1993 -+ int decimals_to_set;
1994 -+ longlong val1;
1995 -+ bool val1_unsigned;
1996 -+
1997 -+ unsigned_flag= args[0]->unsigned_flag;
1998 -+ if (!args[1]->const_item())
1999 -+ {
2000 -+ decimals= args[0]->decimals;
2001 -+ max_length= float_length(decimals);
2002 -+ if (args[0]->result_type() == DECIMAL_RESULT)
2003 -+ {
2004 -+ max_length++;
2005 -+ hybrid_type= DECIMAL_RESULT;
2006 -+ }
2007 -+ else
2008 -+ hybrid_type= REAL_RESULT;
2009 -+ return;
2010 -+ }
2011 -+
2012 -+ val1= args[1]->val_int();
2013 -+ val1_unsigned= args[1]->unsigned_flag;
2014 -+ if (val1 < 0)
2015 -+ decimals_to_set= val1_unsigned ? INT_MAX : 0;
2016 -+ else
2017 -+ decimals_to_set= (val1 > INT_MAX) ? INT_MAX : (int) val1;
2018 -+
2019 -+ if (args[0]->decimals == NOT_FIXED_DEC)
2020 -+ {
2021 -+ decimals= min(decimals_to_set, NOT_FIXED_DEC);
2022 -+ max_length= float_length(decimals);
2023 -+ hybrid_type= REAL_RESULT;
2024 -+ return;
2025 -+ }
2026 -+
2027 -+ switch (args[0]->result_type()) {
2028 -+ case REAL_RESULT:
2029 -+ case STRING_RESULT:
2030 -+ hybrid_type= REAL_RESULT;
2031 -+ decimals= min(decimals_to_set, NOT_FIXED_DEC);
2032 -+ max_length= float_length(decimals);
2033 -+ break;
2034 -+ case INT_RESULT:
2035 -+ if ((!decimals_to_set && truncate) || (args[0]->decimal_precision() < DECIMAL_LONGLONG_DIGITS))
2036 -+ {
2037 -+ int length_can_increase= test(!truncate && (val1 < 0) && !val1_unsigned);
2038 -+ max_length= args[0]->max_length + length_can_increase;
2039 -+ /* Here we can keep INT_RESULT */
2040 -+ hybrid_type= INT_RESULT;
2041 -+ decimals= 0;
2042 -+ break;
2043 -+ }
2044 -+ /* fall through */
2045 -+ case DECIMAL_RESULT:
2046 -+ {
2047 -+ hybrid_type= DECIMAL_RESULT;
2048 -+ decimals_to_set= min(DECIMAL_MAX_SCALE, decimals_to_set);
2049 -+ int decimals_delta= args[0]->decimals - decimals_to_set;
2050 -+ int precision= args[0]->decimal_precision();
2051 -+ int length_increase= ((decimals_delta <= 0) || truncate) ? 0:1;
2052 -+
2053 -+ precision-= decimals_delta - length_increase;
2054 -+ decimals= min(decimals_to_set, DECIMAL_MAX_SCALE);
2055 -+ max_length= my_decimal_precision_to_length_no_truncation(precision,
2056 -+ decimals,
2057 -+ unsigned_flag);
2058 -+ break;
2059 -+ }
2060 -+ default:
2061 -+ DBUG_ASSERT(0); /* This result type isn't handled */
2062 -+ }
2063 -+}
2064 -+
2065 -+double my_double_round(double value, longlong dec, bool dec_unsigned,
2066 -+ bool truncate)
2067 -+{
2068 -+ double tmp;
2069 -+ bool dec_negative= (dec < 0) && !dec_unsigned;
2070 -+ ulonglong abs_dec= dec_negative ? -dec : dec;
2071 -+ /*
2072 -+ tmp2 is here to avoid return the value with 80 bit precision
2073 -+ This will fix that the test round(0.1,1) = round(0.1,1) is true
2074 -+ */
2075 -+ volatile double tmp2;
2076 -+
2077 -+ tmp=(abs_dec < array_elements(log_10) ?
2078 -+ log_10[abs_dec] : pow(10.0,(double) abs_dec));
2079 -+
2080 -+ if (dec_negative && my_isinf(tmp))
2081 -+ tmp2= 0;
2082 -+ else if (!dec_negative && my_isinf(value * tmp))
2083 -+ tmp2= value;
2084 -+ else if (truncate)
2085 -+ {
2086 -+ if (value >= 0)
2087 -+ tmp2= dec < 0 ? floor(value/tmp)*tmp : floor(value*tmp)/tmp;
2088 -+ else
2089 -+ tmp2= dec < 0 ? ceil(value/tmp)*tmp : ceil(value*tmp)/tmp;
2090 -+ }
2091 -+ else
2092 -+ tmp2=dec < 0 ? rint(value/tmp)*tmp : rint(value*tmp)/tmp;
2093 -+ return tmp2;
2094 -+}
2095 -+
2096 -+
2097 -+double Item_func_round::real_op()
2098 -+{
2099 -+ double value= args[0]->val_real();
2100 -+
2101 -+ if (!(null_value= args[0]->null_value || args[1]->null_value))
2102 -+ return my_double_round(value, args[1]->val_int(), args[1]->unsigned_flag,
2103 -+ truncate);
2104 -+
2105 -+ return 0.0;
2106 -+}
2107 -+
2108 -+/*
2109 -+ Rounds a given value to a power of 10 specified as the 'to' argument,
2110 -+ avoiding overflows when the value is close to the ulonglong range boundary.
2111 -+*/
2112 -+
2113 -+static inline ulonglong my_unsigned_round(ulonglong value, ulonglong to)
2114 -+{
2115 -+ ulonglong tmp= value / to * to;
2116 -+ return (value - tmp < (to >> 1)) ? tmp : tmp + to;
2117 -+}
2118 -+
2119 -+
2120 -+longlong Item_func_round::int_op()
2121 -+{
2122 -+ longlong value= args[0]->val_int();
2123 -+ longlong dec= args[1]->val_int();
2124 -+ decimals= 0;
2125 -+ ulonglong abs_dec;
2126 -+ if ((null_value= args[0]->null_value || args[1]->null_value))
2127 -+ return 0;
2128 -+ if ((dec >= 0) || args[1]->unsigned_flag)
2129 -+ return value; // integer have not digits after point
2130 -+
2131 -+ abs_dec= -dec;
2132 -+ longlong tmp;
2133 -+
2134 -+ if(abs_dec >= array_elements(log_10_int))
2135 -+ return 0;
2136 -+
2137 -+ tmp= log_10_int[abs_dec];
2138 -+
2139 -+ if (truncate)
2140 -+ value= (unsigned_flag) ?
2141 -+ ((ulonglong) value / tmp) * tmp : (value / tmp) * tmp;
2142 -+ else
2143 -+ value= (unsigned_flag || value >= 0) ?
2144 -+ my_unsigned_round((ulonglong) value, tmp) :
2145 -+ -(longlong) my_unsigned_round((ulonglong) -value, tmp);
2146 -+ return value;
2147 -+}
2148 -+
2149 -+
2150 -+my_decimal *Item_func_round::decimal_op(my_decimal *decimal_value)
2151 -+{
2152 -+ my_decimal val, *value= args[0]->val_decimal(&val);
2153 -+ longlong dec= args[1]->val_int();
2154 -+ if (dec >= 0 || args[1]->unsigned_flag)
2155 -+ dec= min((ulonglong) dec, decimals);
2156 -+ else if (dec < INT_MIN)
2157 -+ dec= INT_MIN;
2158 -+
2159 -+ if (!(null_value= (args[0]->null_value || args[1]->null_value ||
2160 -+ my_decimal_round(E_DEC_FATAL_ERROR, value, (int) dec,
2161 -+ truncate, decimal_value) > 1)))
2162 -+ {
2163 -+ decimal_value->frac= decimals;
2164 -+ return decimal_value;
2165 -+ }
2166 -+ return 0;
2167 -+}
2168 -+
2169 -+
2170 -+void Item_func_rand::seed_random(Item *arg)
2171 -+{
2172 -+ /*
2173 -+ TODO: do not do reinit 'rand' for every execute of PS/SP if
2174 -+ args[0] is a constant.
2175 -+ */
2176 -+ uint32 tmp= (uint32) arg->val_int();
2177 -+ randominit(rand, (uint32) (tmp*0x10001L+55555555L),
2178 -+ (uint32) (tmp*0x10000001L));
2179 -+}
2180 -+
2181 -+
2182 -+bool Item_func_rand::fix_fields(THD *thd,Item **ref)
2183 -+{
2184 -+ if (Item_real_func::fix_fields(thd, ref))
2185 -+ return TRUE;
2186 -+ used_tables_cache|= RAND_TABLE_BIT;
2187 -+ if (arg_count)
2188 -+ { // Only use argument once in query
2189 -+ /*
2190 -+ Allocate rand structure once: we must use thd->stmt_arena
2191 -+ to create rand in proper mem_root if it's a prepared statement or
2192 -+ stored procedure.
2193 -+
2194 -+ No need to send a Rand log event if seed was given eg: RAND(seed),
2195 -+ as it will be replicated in the query as such.
2196 -+ */
2197 -+ if (!rand && !(rand= (struct rand_struct*)
2198 -+ thd->stmt_arena->alloc(sizeof(*rand))))
2199 -+ return TRUE;
2200 -+ }
2201 -+ else
2202 -+ {
2203 -+ /*
2204 -+ Save the seed only the first time RAND() is used in the query
2205 -+ Once events are forwarded rather than recreated,
2206 -+ the following can be skipped if inside the slave thread
2207 -+ */
2208 -+ if (!thd->rand_used)
2209 -+ {
2210 -+ thd->rand_used= 1;
2211 -+ thd->rand_saved_seed1= thd->rand.seed1;
2212 -+ thd->rand_saved_seed2= thd->rand.seed2;
2213 -+ }
2214 -+ rand= &thd->rand;
2215 -+ }
2216 -+ return FALSE;
2217 -+}
2218 -+
2219 -+void Item_func_rand::update_used_tables()
2220 -+{
2221 -+ Item_real_func::update_used_tables();
2222 -+ used_tables_cache|= RAND_TABLE_BIT;
2223 -+}
2224 -+
2225 -+
2226 -+double Item_func_rand::val_real()
2227 -+{
2228 -+ DBUG_ASSERT(fixed == 1);
2229 -+ if (arg_count)
2230 -+ {
2231 -+ if (!args[0]->const_item())
2232 -+ seed_random(args[0]);
2233 -+ else if (first_eval)
2234 -+ {
2235 -+ /*
2236 -+ Constantness of args[0] may be set during JOIN::optimize(), if arg[0]
2237 -+ is a field item of "constant" table. Thus, we have to evaluate
2238 -+ seed_random() for constant arg there but not at the fix_fields method.
2239 -+ */
2240 -+ first_eval= FALSE;
2241 -+ seed_random(args[0]);
2242 -+ }
2243 -+ }
2244 -+ return my_rnd(rand);
2245 -+}
2246 -+
2247 -+longlong Item_func_sign::val_int()
2248 -+{
2249 -+ DBUG_ASSERT(fixed == 1);
2250 -+ double value= args[0]->val_real();
2251 -+ null_value=args[0]->null_value;
2252 -+ return value < 0.0 ? -1 : (value > 0 ? 1 : 0);
2253 -+}
2254 -+
2255 -+
2256 -+double Item_func_units::val_real()
2257 -+{
2258 -+ DBUG_ASSERT(fixed == 1);
2259 -+ double value= args[0]->val_real();
2260 -+ if ((null_value=args[0]->null_value))
2261 -+ return 0;
2262 -+ return value*mul+add;
2263 -+}
2264 -+
2265 -+
2266 -+void Item_func_min_max::fix_length_and_dec()
2267 -+{
2268 -+ int max_int_part=0;
2269 -+ bool datetime_found= FALSE;
2270 -+ decimals=0;
2271 -+ max_length=0;
2272 -+ maybe_null=0;
2273 -+ cmp_type=args[0]->result_type();
2274 -+
2275 -+ for (uint i=0 ; i < arg_count ; i++)
2276 -+ {
2277 -+ set_if_bigger(max_length, args[i]->max_length);
2278 -+ set_if_bigger(decimals, args[i]->decimals);
2279 -+ set_if_bigger(max_int_part, args[i]->decimal_int_part());
2280 -+ if (args[i]->maybe_null)
2281 -+ maybe_null=1;
2282 -+ cmp_type=item_cmp_type(cmp_type,args[i]->result_type());
2283 -+ if (args[i]->result_type() != ROW_RESULT && args[i]->is_datetime())
2284 -+ {
2285 -+ datetime_found= TRUE;
2286 -+ if (!datetime_item || args[i]->field_type() == MYSQL_TYPE_DATETIME)
2287 -+ datetime_item= args[i];
2288 -+ }
2289 -+ }
2290 -+ if (cmp_type == STRING_RESULT)
2291 -+ {
2292 -+ agg_arg_charsets(collation, args, arg_count, MY_COLL_CMP_CONV, 1);
2293 -+ if (datetime_found)
2294 -+ {
2295 -+ thd= current_thd;
2296 -+ compare_as_dates= TRUE;
2297 -+ }
2298 -+ }
2299 -+ else if ((cmp_type == DECIMAL_RESULT) || (cmp_type == INT_RESULT))
2300 -+ max_length= my_decimal_precision_to_length_no_truncation(max_int_part +
2301 -+ decimals, decimals,
2302 -+ unsigned_flag);
2303 -+ else if (cmp_type == REAL_RESULT)
2304 -+ max_length= float_length(decimals);
2305 -+ cached_field_type= agg_field_type(args, arg_count);
2306 -+}
2307 -+
2308 -+
2309 -+/*
2310 -+ Compare item arguments in the DATETIME context.
2311 -+
2312 -+ SYNOPSIS
2313 -+ cmp_datetimes()
2314 -+ value [out] found least/greatest DATE/DATETIME value
2315 -+
2316 -+ DESCRIPTION
2317 -+ Compare item arguments as DATETIME values and return the index of the
2318 -+ least/greatest argument in the arguments array.
2319 -+ The correct integer DATE/DATETIME value of the found argument is
2320 -+ stored to the value pointer, if latter is provided.
2321 -+
2322 -+ RETURN
2323 -+ 0 If one of arguments is NULL or there was a execution error
2324 -+ # index of the least/greatest argument
2325 -+*/
2326 -+
2327 -+uint Item_func_min_max::cmp_datetimes(ulonglong *value)
2328 -+{
2329 -+ longlong UNINIT_VAR(min_max);
2330 -+ uint min_max_idx= 0;
2331 -+
2332 -+ for (uint i=0; i < arg_count ; i++)
2333 -+ {
2334 -+ Item **arg= args + i;
2335 -+ bool is_null;
2336 -+ longlong res= get_datetime_value(thd, &arg, 0, datetime_item, &is_null);
2337 -+
2338 -+ /* Check if we need to stop (because of error or KILL) and stop the loop */
2339 -+ if (thd->is_error())
2340 -+ {
2341 -+ null_value= 1;
2342 -+ return 0;
2343 -+ }
2344 -+
2345 -+ if ((null_value= args[i]->null_value))
2346 -+ return 0;
2347 -+ if (i == 0 || (res < min_max ? cmp_sign : -cmp_sign) > 0)
2348 -+ {
2349 -+ min_max= res;
2350 -+ min_max_idx= i;
2351 -+ }
2352 -+ }
2353 -+ if (value)
2354 -+ {
2355 -+ *value= min_max;
2356 -+ if (datetime_item->field_type() == MYSQL_TYPE_DATE)
2357 -+ *value/= 1000000L;
2358 -+ }
2359 -+ return min_max_idx;
2360 -+}
2361 -+
2362 -+
2363 -+String *Item_func_min_max::val_str(String *str)
2364 -+{
2365 -+ DBUG_ASSERT(fixed == 1);
2366 -+ if (compare_as_dates)
2367 -+ {
2368 -+ String *str_res;
2369 -+ uint min_max_idx= cmp_datetimes(NULL);
2370 -+ if (null_value)
2371 -+ return 0;
2372 -+ str_res= args[min_max_idx]->val_str(str);
2373 -+ if (args[min_max_idx]->null_value)
2374 -+ {
2375 -+ // check if the call to val_str() above returns a NULL value
2376 -+ null_value= 1;
2377 -+ return NULL;
2378 -+ }
2379 -+ str_res->set_charset(collation.collation);
2380 -+ return str_res;
2381 -+ }
2382 -+ switch (cmp_type) {
2383 -+ case INT_RESULT:
2384 -+ {
2385 -+ longlong nr=val_int();
2386 -+ if (null_value)
2387 -+ return 0;
2388 -+ str->set_int(nr, unsigned_flag, &my_charset_bin);
2389 -+ return str;
2390 -+ }
2391 -+ case DECIMAL_RESULT:
2392 -+ {
2393 -+ my_decimal dec_buf, *dec_val= val_decimal(&dec_buf);
2394 -+ if (null_value)
2395 -+ return 0;
2396 -+ my_decimal2string(E_DEC_FATAL_ERROR, dec_val, 0, 0, 0, str);
2397 -+ return str;
2398 -+ }
2399 -+ case REAL_RESULT:
2400 -+ {
2401 -+ double nr= val_real();
2402 -+ if (null_value)
2403 -+ return 0; /* purecov: inspected */
2404 -+ str->set_real(nr,decimals,&my_charset_bin);
2405 -+ return str;
2406 -+ }
2407 -+ case STRING_RESULT:
2408 -+ {
2409 -+ String *UNINIT_VAR(res);
2410 -+ for (uint i=0; i < arg_count ; i++)
2411 -+ {
2412 -+ if (i == 0)
2413 -+ res=args[i]->val_str(str);
2414 -+ else
2415 -+ {
2416 -+ String *res2;
2417 -+ res2= args[i]->val_str(res == str ? &tmp_value : str);
2418 -+ if (res2)
2419 -+ {
2420 -+ int cmp= sortcmp(res,res2,collation.collation);
2421 -+ if ((cmp_sign < 0 ? cmp : -cmp) < 0)
2422 -+ res=res2;
2423 -+ }
2424 -+ }
2425 -+ if ((null_value= args[i]->null_value))
2426 -+ return 0;
2427 -+ }
2428 -+ res->set_charset(collation.collation);
2429 -+ return res;
2430 -+ }
2431 -+ case ROW_RESULT:
2432 -+ default:
2433 -+ // This case should never be chosen
2434 -+ DBUG_ASSERT(0);
2435 -+ return 0;
2436 -+ }
2437 -+ return 0; // Keep compiler happy
2438 -+}
2439 -+
2440 -+
2441 -+double Item_func_min_max::val_real()
2442 -+{
2443 -+ DBUG_ASSERT(fixed == 1);
2444 -+ double value=0.0;
2445 -+ if (compare_as_dates)
2446 -+ {
2447 -+ ulonglong result= 0;
2448 -+ (void)cmp_datetimes(&result);
2449 -+ return (double)result;
2450 -+ }
2451 -+ for (uint i=0; i < arg_count ; i++)
2452 -+ {
2453 -+ if (i == 0)
2454 -+ value= args[i]->val_real();
2455 -+ else
2456 -+ {
2457 -+ double tmp= args[i]->val_real();
2458 -+ if (!args[i]->null_value && (tmp < value ? cmp_sign : -cmp_sign) > 0)
2459 -+ value=tmp;
2460 -+ }
2461 -+ if ((null_value= args[i]->null_value))
2462 -+ break;
2463 -+ }
2464 -+ return value;
2465 -+}
2466 -+
2467 -+
2468 -+longlong Item_func_min_max::val_int()
2469 -+{
2470 -+ DBUG_ASSERT(fixed == 1);
2471 -+ longlong value=0;
2472 -+ if (compare_as_dates)
2473 -+ {
2474 -+ ulonglong result= 0;
2475 -+ (void)cmp_datetimes(&result);
2476 -+ return (longlong)result;
2477 -+ }
2478 -+ for (uint i=0; i < arg_count ; i++)
2479 -+ {
2480 -+ if (i == 0)
2481 -+ value=args[i]->val_int();
2482 -+ else
2483 -+ {
2484 -+ longlong tmp=args[i]->val_int();
2485 -+ if (!args[i]->null_value && (tmp < value ? cmp_sign : -cmp_sign) > 0)
2486 -+ value=tmp;
2487 -+ }
2488 -+ if ((null_value= args[i]->null_value))
2489 -+ break;
2490 -+ }
2491 -+ return value;
2492 -+}
2493 -+
2494 -+
2495 -+my_decimal *Item_func_min_max::val_decimal(my_decimal *dec)
2496 -+{
2497 -+ DBUG_ASSERT(fixed == 1);
2498 -+ my_decimal tmp_buf, *tmp, *UNINIT_VAR(res);
2499 -+
2500 -+ if (compare_as_dates)
2501 -+ {
2502 -+ ulonglong value= 0;
2503 -+ (void)cmp_datetimes(&value);
2504 -+ ulonglong2decimal(value, dec);
2505 -+ return dec;
2506 -+ }
2507 -+ for (uint i=0; i < arg_count ; i++)
2508 -+ {
2509 -+ if (i == 0)
2510 -+ res= args[i]->val_decimal(dec);
2511 -+ else
2512 -+ {
2513 -+ tmp= args[i]->val_decimal(&tmp_buf); // Zero if NULL
2514 -+ if (tmp && (my_decimal_cmp(tmp, res) * cmp_sign) < 0)
2515 -+ {
2516 -+ if (tmp == &tmp_buf)
2517 -+ {
2518 -+ /* Move value out of tmp_buf as this will be reused on next loop */
2519 -+ my_decimal2decimal(tmp, dec);
2520 -+ res= dec;
2521 -+ }
2522 -+ else
2523 -+ res= tmp;
2524 -+ }
2525 -+ }
2526 -+ if ((null_value= args[i]->null_value))
2527 -+ {
2528 -+ res= 0;
2529 -+ break;
2530 -+ }
2531 -+ }
2532 -+ return res;
2533 -+}
2534 -+
2535 -+
2536 -+longlong Item_func_length::val_int()
2537 -+{
2538 -+ DBUG_ASSERT(fixed == 1);
2539 -+ String *res=args[0]->val_str(&value);
2540 -+ if (!res)
2541 -+ {
2542 -+ null_value=1;
2543 -+ return 0; /* purecov: inspected */
2544 -+ }
2545 -+ null_value=0;
2546 -+ return (longlong) res->length();
2547 -+}
2548 -+
2549 -+
2550 -+longlong Item_func_char_length::val_int()
2551 -+{
2552 -+ DBUG_ASSERT(fixed == 1);
2553 -+ String *res=args[0]->val_str(&value);
2554 -+ if (!res)
2555 -+ {
2556 -+ null_value=1;
2557 -+ return 0; /* purecov: inspected */
2558 -+ }
2559 -+ null_value=0;
2560 -+ return (longlong) res->numchars();
2561 -+}
2562 -+
2563 -+
2564 -+longlong Item_func_coercibility::val_int()
2565 -+{
2566 -+ DBUG_ASSERT(fixed == 1);
2567 -+ null_value= 0;
2568 -+ return (longlong) args[0]->collation.derivation;
2569 -+}
2570 -+
2571 -+
2572 -+void Item_func_locate::fix_length_and_dec()
2573 -+{
2574 -+ max_length= MY_INT32_NUM_DECIMAL_DIGITS;
2575 -+ agg_arg_charsets(cmp_collation, args, 2, MY_COLL_CMP_CONV, 1);
2576 -+}
2577 -+
2578 -+
2579 -+longlong Item_func_locate::val_int()
2580 -+{
2581 -+ DBUG_ASSERT(fixed == 1);
2582 -+ String *a=args[0]->val_str(&value1);
2583 -+ String *b=args[1]->val_str(&value2);
2584 -+ if (!a || !b)
2585 -+ {
2586 -+ null_value=1;
2587 -+ return 0; /* purecov: inspected */
2588 -+ }
2589 -+ null_value=0;
2590 -+ /* must be longlong to avoid truncation */
2591 -+ longlong start= 0;
2592 -+ longlong start0= 0;
2593 -+ my_match_t match;
2594 -+
2595 -+ if (arg_count == 3)
2596 -+ {
2597 -+ start0= start= args[2]->val_int() - 1;
2598 -+
2599 -+ if ((start < 0) || (start > a->length()))
2600 -+ return 0;
2601 -+
2602 -+ /* start is now sufficiently valid to pass to charpos function */
2603 -+ start= a->charpos((int) start);
2604 -+
2605 -+ if (start + b->length() > a->length())
2606 -+ return 0;
2607 -+ }
2608 -+
2609 -+ if (!b->length()) // Found empty string at start
2610 -+ return start + 1;
2611 -+
2612 -+ if (!cmp_collation.collation->coll->instr(cmp_collation.collation,
2613 -+ a->ptr()+start,
2614 -+ (uint) (a->length()-start),
2615 -+ b->ptr(), b->length(),
2616 -+ &match, 1))
2617 -+ return 0;
2618 -+ return (longlong) match.mb_len + start0 + 1;
2619 -+}
2620 -+
2621 -+
2622 -+void Item_func_locate::print(String *str, enum_query_type query_type)
2623 -+{
2624 -+ str->append(STRING_WITH_LEN("locate("));
2625 -+ args[1]->print(str, query_type);
2626 -+ str->append(',');
2627 -+ args[0]->print(str, query_type);
2628 -+ if (arg_count == 3)
2629 -+ {
2630 -+ str->append(',');
2631 -+ args[2]->print(str, query_type);
2632 -+ }
2633 -+ str->append(')');
2634 -+}
2635 -+
2636 -+
2637 -+longlong Item_func_field::val_int()
2638 -+{
2639 -+ DBUG_ASSERT(fixed == 1);
2640 -+
2641 -+ if (cmp_type == STRING_RESULT)
2642 -+ {
2643 -+ String *field;
2644 -+ if (!(field= args[0]->val_str(&value)))
2645 -+ return 0;
2646 -+ for (uint i=1 ; i < arg_count ; i++)
2647 -+ {
2648 -+ String *tmp_value=args[i]->val_str(&tmp);
2649 -+ if (tmp_value && !sortcmp(field,tmp_value,cmp_collation.collation))
2650 -+ return (longlong) (i);
2651 -+ }
2652 -+ }
2653 -+ else if (cmp_type == INT_RESULT)
2654 -+ {
2655 -+ longlong val= args[0]->val_int();
2656 -+ if (args[0]->null_value)
2657 -+ return 0;
2658 -+ for (uint i=1; i < arg_count ; i++)
2659 -+ {
2660 -+ if (val == args[i]->val_int() && !args[i]->null_value)
2661 -+ return (longlong) (i);
2662 -+ }
2663 -+ }
2664 -+ else if (cmp_type == DECIMAL_RESULT)
2665 -+ {
2666 -+ my_decimal dec_arg_buf, *dec_arg,
2667 -+ dec_buf, *dec= args[0]->val_decimal(&dec_buf);
2668 -+ if (args[0]->null_value)
2669 -+ return 0;
2670 -+ for (uint i=1; i < arg_count; i++)
2671 -+ {
2672 -+ dec_arg= args[i]->val_decimal(&dec_arg_buf);
2673 -+ if (!args[i]->null_value && !my_decimal_cmp(dec_arg, dec))
2674 -+ return (longlong) (i);
2675 -+ }
2676 -+ }
2677 -+ else
2678 -+ {
2679 -+ double val= args[0]->val_real();
2680 -+ if (args[0]->null_value)
2681 -+ return 0;
2682 -+ for (uint i=1; i < arg_count ; i++)
2683 -+ {
2684 -+ if (val == args[i]->val_real() && !args[i]->null_value)
2685 -+ return (longlong) (i);
2686 -+ }
2687 -+ }
2688 -+ return 0;
2689 -+}
2690 -+
2691 -+
2692 -+void Item_func_field::fix_length_and_dec()
2693 -+{
2694 -+ maybe_null=0; max_length=3;
2695 -+ cmp_type= args[0]->result_type();
2696 -+ for (uint i=1; i < arg_count ; i++)
2697 -+ cmp_type= item_cmp_type(cmp_type, args[i]->result_type());
2698 -+ if (cmp_type == STRING_RESULT)
2699 -+ agg_arg_charsets(cmp_collation, args, arg_count, MY_COLL_CMP_CONV, 1);
2700 -+}
2701 -+
2702 -+
2703 -+longlong Item_func_ascii::val_int()
2704 -+{
2705 -+ DBUG_ASSERT(fixed == 1);
2706 -+ String *res=args[0]->val_str(&value);
2707 -+ if (!res)
2708 -+ {
2709 -+ null_value=1;
2710 -+ return 0;
2711 -+ }
2712 -+ null_value=0;
2713 -+ return (longlong) (res->length() ? (uchar) (*res)[0] : (uchar) 0);
2714 -+}
2715 -+
2716 -+longlong Item_func_ord::val_int()
2717 -+{
2718 -+ DBUG_ASSERT(fixed == 1);
2719 -+ String *res=args[0]->val_str(&value);
2720 -+ if (!res)
2721 -+ {
2722 -+ null_value=1;
2723 -+ return 0;
2724 -+ }
2725 -+ null_value=0;
2726 -+ if (!res->length()) return 0;
2727 -+#ifdef USE_MB
2728 -+ if (use_mb(res->charset()))
2729 -+ {
2730 -+ register const char *str=res->ptr();
2731 -+ register uint32 n=0, l=my_ismbchar(res->charset(),str,str+res->length());
2732 -+ if (!l)
2733 -+ return (longlong)((uchar) *str);
2734 -+ while (l--)
2735 -+ n=(n<<8)|(uint32)((uchar) *str++);
2736 -+ return (longlong) n;
2737 -+ }
2738 -+#endif
2739 -+ return (longlong) ((uchar) (*res)[0]);
2740 -+}
2741 -+
2742 -+ /* Search after a string in a string of strings separated by ',' */
2743 -+ /* Returns number of found type >= 1 or 0 if not found */
2744 -+ /* This optimizes searching in enums to bit testing! */
2745 -+
2746 -+void Item_func_find_in_set::fix_length_and_dec()
2747 -+{
2748 -+ decimals=0;
2749 -+ max_length=3; // 1-999
2750 -+ if (args[0]->const_item() && args[1]->type() == FIELD_ITEM)
2751 -+ {
2752 -+ Field *field= ((Item_field*) args[1])->field;
2753 -+ if (field->real_type() == MYSQL_TYPE_SET)
2754 -+ {
2755 -+ String *find=args[0]->val_str(&value);
2756 -+ if (find)
2757 -+ {
2758 -+ enum_value= find_type(((Field_enum*) field)->typelib,find->ptr(),
2759 -+ find->length(), 0);
2760 -+ enum_bit=0;
2761 -+ if (enum_value)
2762 -+ enum_bit=LL(1) << (enum_value-1);
2763 -+ }
2764 -+ }
2765 -+ }
2766 -+ agg_arg_charsets(cmp_collation, args, 2, MY_COLL_CMP_CONV, 1);
2767 -+}
2768 -+
2769 -+static const char separator=',';
2770 -+
2771 -+longlong Item_func_find_in_set::val_int()
2772 -+{
2773 -+ DBUG_ASSERT(fixed == 1);
2774 -+ if (enum_value)
2775 -+ {
2776 -+ ulonglong tmp=(ulonglong) args[1]->val_int();
2777 -+ if (!(null_value=args[1]->null_value || args[0]->null_value))
2778 -+ {
2779 -+ if (tmp & enum_bit)
2780 -+ return enum_value;
2781 -+ }
2782 -+ return 0L;
2783 -+ }
2784 -+
2785 -+ String *find=args[0]->val_str(&value);
2786 -+ String *buffer=args[1]->val_str(&value2);
2787 -+ if (!find || !buffer)
2788 -+ {
2789 -+ null_value=1;
2790 -+ return 0; /* purecov: inspected */
2791 -+ }
2792 -+ null_value=0;
2793 -+
2794 -+ int diff;
2795 -+ if ((diff=buffer->length() - find->length()) >= 0)
2796 -+ {
2797 -+ my_wc_t wc= 0;
2798 -+ CHARSET_INFO *cs= cmp_collation.collation;
2799 -+ const char *str_begin= buffer->ptr();
2800 -+ const char *str_end= buffer->ptr();
2801 -+ const char *real_end= str_end+buffer->length();
2802 -+ const uchar *find_str= (const uchar *) find->ptr();
2803 -+ uint find_str_len= find->length();
2804 -+ int position= 0;
2805 -+ while (1)
2806 -+ {
2807 -+ int symbol_len;
2808 -+ if ((symbol_len= cs->cset->mb_wc(cs, &wc, (uchar*) str_end,
2809 -+ (uchar*) real_end)) > 0)
2810 -+ {
2811 -+ const char *substr_end= str_end + symbol_len;
2812 -+ bool is_last_item= (substr_end == real_end);
2813 -+ bool is_separator= (wc == (my_wc_t) separator);
2814 -+ if (is_separator || is_last_item)
2815 -+ {
2816 -+ position++;
2817 -+ if (is_last_item && !is_separator)
2818 -+ str_end= substr_end;
2819 -+ if (!my_strnncoll(cs, (const uchar *) str_begin,
2820 -+ (uint) (str_end - str_begin),
2821 -+ find_str, find_str_len))
2822 -+ return (longlong) position;
2823 -+ else
2824 -+ str_begin= substr_end;
2825 -+ }
2826 -+ str_end= substr_end;
2827 -+ }
2828 -+ else if (str_end - str_begin == 0 &&
2829 -+ find_str_len == 0 &&
2830 -+ wc == (my_wc_t) separator)
2831 -+ return (longlong) ++position;
2832 -+ else
2833 -+ return LL(0);
2834 -+ }
2835 -+ }
2836 -+ return 0;
2837 -+}
2838 -+
2839 -+longlong Item_func_bit_count::val_int()
2840 -+{
2841 -+ DBUG_ASSERT(fixed == 1);
2842 -+ ulonglong value= (ulonglong) args[0]->val_int();
2843 -+ if ((null_value= args[0]->null_value))
2844 -+ return 0; /* purecov: inspected */
2845 -+ return (longlong) my_count_bits(value);
2846 -+}
2847 -+
2848 -+
2849 -+/****************************************************************************
2850 -+** Functions to handle dynamic loadable functions
2851 -+** Original source by: Alexis Mikhailov <root@××××××××××××××××.su>
2852 -+** Rewritten by monty.
2853 -+****************************************************************************/
2854 -+
2855 -+#ifdef HAVE_DLOPEN
2856 -+
2857 -+void udf_handler::cleanup()
2858 -+{
2859 -+ if (!not_original)
2860 -+ {
2861 -+ if (initialized)
2862 -+ {
2863 -+ if (u_d->func_deinit != NULL)
2864 -+ {
2865 -+ Udf_func_deinit deinit= u_d->func_deinit;
2866 -+ (*deinit)(&initid);
2867 -+ }
2868 -+ free_udf(u_d);
2869 -+ initialized= FALSE;
2870 -+ }
2871 -+ if (buffers) // Because of bug in ecc
2872 -+ delete [] buffers;
2873 -+ buffers= 0;
2874 -+ }
2875 -+}
2876 -+
2877 -+
2878 -+bool
2879 -+udf_handler::fix_fields(THD *thd, Item_result_field *func,
2880 -+ uint arg_count, Item **arguments)
2881 -+{
2882 -+#ifndef EMBEDDED_LIBRARY // Avoid compiler warning
2883 -+ uchar buff[STACK_BUFF_ALLOC]; // Max argument in function
2884 -+#endif
2885 -+ DBUG_ENTER("Item_udf_func::fix_fields");
2886 -+
2887 -+ if (check_stack_overrun(thd, STACK_MIN_SIZE, buff))
2888 -+ DBUG_RETURN(TRUE); // Fatal error flag is set!
2889 -+
2890 -+ udf_func *tmp_udf=find_udf(u_d->name.str,(uint) u_d->name.length,1);
2891 -+
2892 -+ if (!tmp_udf)
2893 -+ {
2894 -+ my_error(ER_CANT_FIND_UDF, MYF(0), u_d->name.str, errno);
2895 -+ DBUG_RETURN(TRUE);
2896 -+ }
2897 -+ u_d=tmp_udf;
2898 -+ args=arguments;
2899 -+
2900 -+ /* Fix all arguments */
2901 -+ func->maybe_null=0;
2902 -+ used_tables_cache=0;
2903 -+ const_item_cache=1;
2904 -+
2905 -+ if ((f_args.arg_count=arg_count))
2906 -+ {
2907 -+ if (!(f_args.arg_type= (Item_result*)
2908 -+ sql_alloc(f_args.arg_count*sizeof(Item_result))))
2909 -+
2910 -+ {
2911 -+ free_udf(u_d);
2912 -+ DBUG_RETURN(TRUE);
2913 -+ }
2914 -+ uint i;
2915 -+ Item **arg,**arg_end;
2916 -+ for (i=0, arg=arguments, arg_end=arguments+arg_count;
2917 -+ arg != arg_end ;
2918 -+ arg++,i++)
2919 -+ {
2920 -+ if (!(*arg)->fixed &&
2921 -+ (*arg)->fix_fields(thd, arg))
2922 -+ DBUG_RETURN(1);
2923 -+ // we can't assign 'item' before, because fix_fields() can change arg
2924 -+ Item *item= *arg;
2925 -+ if (item->check_cols(1))
2926 -+ DBUG_RETURN(TRUE);
2927 -+ /*
2928 -+ TODO: We should think about this. It is not always
2929 -+ right way just to set an UDF result to return my_charset_bin
2930 -+ if one argument has binary sorting order.
2931 -+ The result collation should be calculated according to arguments
2932 -+ derivations in some cases and should not in other cases.
2933 -+ Moreover, some arguments can represent a numeric input
2934 -+ which doesn't effect the result character set and collation.
2935 -+ There is no a general rule for UDF. Everything depends on
2936 -+ the particular user defined function.
2937 -+ */
2938 -+ if (item->collation.collation->state & MY_CS_BINSORT)
2939 -+ func->collation.set(&my_charset_bin);
2940 -+ if (item->maybe_null)
2941 -+ func->maybe_null=1;
2942 -+ func->with_sum_func= func->with_sum_func || item->with_sum_func;
2943 -+ used_tables_cache|=item->used_tables();
2944 -+ const_item_cache&=item->const_item();
2945 -+ f_args.arg_type[i]=item->result_type();
2946 -+ }
2947 -+ //TODO: why all following memory is not allocated with 1 call of sql_alloc?
2948 -+ if (!(buffers=new String[arg_count]) ||
2949 -+ !(f_args.args= (char**) sql_alloc(arg_count * sizeof(char *))) ||
2950 -+ !(f_args.lengths= (ulong*) sql_alloc(arg_count * sizeof(long))) ||
2951 -+ !(f_args.maybe_null= (char*) sql_alloc(arg_count * sizeof(char))) ||
2952 -+ !(num_buffer= (char*) sql_alloc(arg_count *
2953 -+ ALIGN_SIZE(sizeof(double)))) ||
2954 -+ !(f_args.attributes= (char**) sql_alloc(arg_count * sizeof(char *))) ||
2955 -+ !(f_args.attribute_lengths= (ulong*) sql_alloc(arg_count *
2956 -+ sizeof(long))))
2957 -+ {
2958 -+ free_udf(u_d);
2959 -+ DBUG_RETURN(TRUE);
2960 -+ }
2961 -+ }
2962 -+ func->fix_length_and_dec();
2963 -+ initid.max_length=func->max_length;
2964 -+ initid.maybe_null=func->maybe_null;
2965 -+ initid.const_item=const_item_cache;
2966 -+ initid.decimals=func->decimals;
2967 -+ initid.ptr=0;
2968 -+
2969 -+ if (u_d->func_init)
2970 -+ {
2971 -+ char init_msg_buff[MYSQL_ERRMSG_SIZE];
2972 -+ char *to=num_buffer;
2973 -+ for (uint i=0; i < arg_count; i++)
2974 -+ {
2975 -+ /*
2976 -+ For a constant argument i, args->args[i] points to the argument value.
2977 -+ For non-constant, args->args[i] is NULL.
2978 -+ */
2979 -+ f_args.args[i]= NULL; /* Non-const unless updated below. */
2980 -+
2981 -+ f_args.lengths[i]= arguments[i]->max_length;
2982 -+ f_args.maybe_null[i]= (char) arguments[i]->maybe_null;
2983 -+ f_args.attributes[i]= arguments[i]->name;
2984 -+ f_args.attribute_lengths[i]= arguments[i]->name_length;
2985 -+
2986 -+ if (arguments[i]->const_item())
2987 -+ {
2988 -+ switch (arguments[i]->result_type())
2989 -+ {
2990 -+ case STRING_RESULT:
2991 -+ case DECIMAL_RESULT:
2992 -+ {
2993 -+ String *res= arguments[i]->val_str(&buffers[i]);
2994 -+ if (arguments[i]->null_value)
2995 -+ continue;
2996 -+ f_args.args[i]= (char*) res->c_ptr();
2997 -+ f_args.lengths[i]= res->length();
2998 -+ break;
2999 -+ }
3000 -+ case INT_RESULT:
3001 -+ *((longlong*) to)= arguments[i]->val_int();
3002 -+ if (arguments[i]->null_value)
3003 -+ continue;
3004 -+ f_args.args[i]= to;
3005 -+ to+= ALIGN_SIZE(sizeof(longlong));
3006 -+ break;
3007 -+ case REAL_RESULT:
3008 -+ *((double*) to)= arguments[i]->val_real();
3009 -+ if (arguments[i]->null_value)
3010 -+ continue;
3011 -+ f_args.args[i]= to;
3012 -+ to+= ALIGN_SIZE(sizeof(double));
3013 -+ break;
3014 -+ case ROW_RESULT:
3015 -+ default:
3016 -+ // This case should never be chosen
3017 -+ DBUG_ASSERT(0);
3018 -+ break;
3019 -+ }
3020 -+ }
3021 -+ }
3022 -+ Udf_func_init init= u_d->func_init;
3023 -+ if ((error=(uchar) init(&initid, &f_args, init_msg_buff)))
3024 -+ {
3025 -+ my_error(ER_CANT_INITIALIZE_UDF, MYF(0),
3026 -+ u_d->name.str, init_msg_buff);
3027 -+ free_udf(u_d);
3028 -+ DBUG_RETURN(TRUE);
3029 -+ }
3030 -+ func->max_length=min(initid.max_length,MAX_BLOB_WIDTH);
3031 -+ func->maybe_null=initid.maybe_null;
3032 -+ const_item_cache=initid.const_item;
3033 -+ /*
3034 -+ Keep used_tables_cache in sync with const_item_cache.
3035 -+ See the comment in Item_udf_func::update_used tables.
3036 -+ */
3037 -+ if (!const_item_cache && !used_tables_cache)
3038 -+ used_tables_cache= RAND_TABLE_BIT;
3039 -+ func->decimals=min(initid.decimals,NOT_FIXED_DEC);
3040 -+ }
3041 -+ initialized=1;
3042 -+ if (error)
3043 -+ {
3044 -+ my_error(ER_CANT_INITIALIZE_UDF, MYF(0),
3045 -+ u_d->name.str, ER(ER_UNKNOWN_ERROR));
3046 -+ DBUG_RETURN(TRUE);
3047 -+ }
3048 -+ DBUG_RETURN(FALSE);
3049 -+}
3050 -+
3051 -+
3052 -+bool udf_handler::get_arguments()
3053 -+{
3054 -+ if (error)
3055 -+ return 1; // Got an error earlier
3056 -+ char *to= num_buffer;
3057 -+ uint str_count=0;
3058 -+ for (uint i=0; i < f_args.arg_count; i++)
3059 -+ {
3060 -+ f_args.args[i]=0;
3061 -+ switch (f_args.arg_type[i]) {
3062 -+ case STRING_RESULT:
3063 -+ case DECIMAL_RESULT:
3064 -+ {
3065 -+ String *res=args[i]->val_str(&buffers[str_count++]);
3066 -+ if (!(args[i]->null_value))
3067 -+ {
3068 -+ f_args.args[i]= (char*) res->ptr();
3069 -+ f_args.lengths[i]= res->length();
3070 -+ break;
3071 -+ }
3072 -+ }
3073 -+ case INT_RESULT:
3074 -+ *((longlong*) to) = args[i]->val_int();
3075 -+ if (!args[i]->null_value)
3076 -+ {
3077 -+ f_args.args[i]=to;
3078 -+ to+= ALIGN_SIZE(sizeof(longlong));
3079 -+ }
3080 -+ break;
3081 -+ case REAL_RESULT:
3082 -+ *((double*) to)= args[i]->val_real();
3083 -+ if (!args[i]->null_value)
3084 -+ {
3085 -+ f_args.args[i]=to;
3086 -+ to+= ALIGN_SIZE(sizeof(double));
3087 -+ }
3088 -+ break;
3089 -+ case ROW_RESULT:
3090 -+ default:
3091 -+ // This case should never be chosen
3092 -+ DBUG_ASSERT(0);
3093 -+ break;
3094 -+ }
3095 -+ }
3096 -+ return 0;
3097 -+}
3098 -+
3099 -+/**
3100 -+ @return
3101 -+ (String*)NULL in case of NULL values
3102 -+*/
3103 -+String *udf_handler::val_str(String *str,String *save_str)
3104 -+{
3105 -+ uchar is_null_tmp=0;
3106 -+ ulong res_length;
3107 -+ DBUG_ENTER("udf_handler::val_str");
3108 -+
3109 -+ if (get_arguments())
3110 -+ DBUG_RETURN(0);
3111 -+ char * (*func)(UDF_INIT *, UDF_ARGS *, char *, ulong *, uchar *, uchar *)=
3112 -+ (char* (*)(UDF_INIT *, UDF_ARGS *, char *, ulong *, uchar *, uchar *))
3113 -+ u_d->func;
3114 -+
3115 -+ if ((res_length=str->alloced_length()) < MAX_FIELD_WIDTH)
3116 -+ { // This happens VERY seldom
3117 -+ if (str->alloc(MAX_FIELD_WIDTH))
3118 -+ {
3119 -+ error=1;
3120 -+ DBUG_RETURN(0);
3121 -+ }
3122 -+ }
3123 -+ char *res=func(&initid, &f_args, (char*) str->ptr(), &res_length,
3124 -+ &is_null_tmp, &error);
3125 -+ DBUG_PRINT("info", ("udf func returned, res_length: %lu", res_length));
3126 -+ if (is_null_tmp || !res || error) // The !res is for safety
3127 -+ {
3128 -+ DBUG_PRINT("info", ("Null or error"));
3129 -+ DBUG_RETURN(0);
3130 -+ }
3131 -+ if (res == str->ptr())
3132 -+ {
3133 -+ str->length(res_length);
3134 -+ DBUG_PRINT("exit", ("str: %s", str->ptr()));
3135 -+ DBUG_RETURN(str);
3136 -+ }
3137 -+ save_str->set(res, res_length, str->charset());
3138 -+ DBUG_PRINT("exit", ("save_str: %s", save_str->ptr()));
3139 -+ DBUG_RETURN(save_str);
3140 -+}
3141 -+
3142 -+
3143 -+/*
3144 -+ For the moment, UDF functions are returning DECIMAL values as strings
3145 -+*/
3146 -+
3147 -+my_decimal *udf_handler::val_decimal(my_bool *null_value, my_decimal *dec_buf)
3148 -+{
3149 -+ char buf[DECIMAL_MAX_STR_LENGTH+1], *end;
3150 -+ ulong res_length= DECIMAL_MAX_STR_LENGTH;
3151 -+
3152 -+ if (get_arguments())
3153 -+ {
3154 -+ *null_value=1;
3155 -+ return 0;
3156 -+ }
3157 -+ char *(*func)(UDF_INIT *, UDF_ARGS *, char *, ulong *, uchar *, uchar *)=
3158 -+ (char* (*)(UDF_INIT *, UDF_ARGS *, char *, ulong *, uchar *, uchar *))
3159 -+ u_d->func;
3160 -+
3161 -+ char *res= func(&initid, &f_args, buf, &res_length, &is_null, &error);
3162 -+ if (is_null || error)
3163 -+ {
3164 -+ *null_value= 1;
3165 -+ return 0;
3166 -+ }
3167 -+ end= res+ res_length;
3168 -+ str2my_decimal(E_DEC_FATAL_ERROR, res, dec_buf, &end);
3169 -+ return dec_buf;
3170 -+}
3171 -+
3172 -+
3173 -+void Item_udf_func::cleanup()
3174 -+{
3175 -+ udf.cleanup();
3176 -+ Item_func::cleanup();
3177 -+}
3178 -+
3179 -+
3180 -+void Item_udf_func::print(String *str, enum_query_type query_type)
3181 -+{
3182 -+ str->append(func_name());
3183 -+ str->append('(');
3184 -+ for (uint i=0 ; i < arg_count ; i++)
3185 -+ {
3186 -+ if (i != 0)
3187 -+ str->append(',');
3188 -+ args[i]->print_item_w_name(str, query_type);
3189 -+ }
3190 -+ str->append(')');
3191 -+}
3192 -+
3193 -+
3194 -+double Item_func_udf_float::val_real()
3195 -+{
3196 -+ DBUG_ASSERT(fixed == 1);
3197 -+ DBUG_ENTER("Item_func_udf_float::val");
3198 -+ DBUG_PRINT("info",("result_type: %d arg_count: %d",
3199 -+ args[0]->result_type(), arg_count));
3200 -+ DBUG_RETURN(udf.val(&null_value));
3201 -+}
3202 -+
3203 -+
3204 -+String *Item_func_udf_float::val_str(String *str)
3205 -+{
3206 -+ DBUG_ASSERT(fixed == 1);
3207 -+ double nr= val_real();
3208 -+ if (null_value)
3209 -+ return 0; /* purecov: inspected */
3210 -+ str->set_real(nr,decimals,&my_charset_bin);
3211 -+ return str;
3212 -+}
3213 -+
3214 -+
3215 -+longlong Item_func_udf_int::val_int()
3216 -+{
3217 -+ DBUG_ASSERT(fixed == 1);
3218 -+ DBUG_ENTER("Item_func_udf_int::val_int");
3219 -+ DBUG_RETURN(udf.val_int(&null_value));
3220 -+}
3221 -+
3222 -+
3223 -+String *Item_func_udf_int::val_str(String *str)
3224 -+{
3225 -+ DBUG_ASSERT(fixed == 1);
3226 -+ longlong nr=val_int();
3227 -+ if (null_value)
3228 -+ return 0;
3229 -+ str->set_int(nr, unsigned_flag, &my_charset_bin);
3230 -+ return str;
3231 -+}
3232 -+
3233 -+
3234 -+longlong Item_func_udf_decimal::val_int()
3235 -+{
3236 -+ my_decimal dec_buf, *dec= udf.val_decimal(&null_value, &dec_buf);
3237 -+ longlong result;
3238 -+ if (null_value)
3239 -+ return 0;
3240 -+ my_decimal2int(E_DEC_FATAL_ERROR, dec, unsigned_flag, &result);
3241 -+ return result;
3242 -+}
3243 -+
3244 -+
3245 -+double Item_func_udf_decimal::val_real()
3246 -+{
3247 -+ my_decimal dec_buf, *dec= udf.val_decimal(&null_value, &dec_buf);
3248 -+ double result;
3249 -+ if (null_value)
3250 -+ return 0.0;
3251 -+ my_decimal2double(E_DEC_FATAL_ERROR, dec, &result);
3252 -+ return result;
3253 -+}
3254 -+
3255 -+
3256 -+my_decimal *Item_func_udf_decimal::val_decimal(my_decimal *dec_buf)
3257 -+{
3258 -+ DBUG_ASSERT(fixed == 1);
3259 -+ DBUG_ENTER("Item_func_udf_decimal::val_decimal");
3260 -+ DBUG_PRINT("info",("result_type: %d arg_count: %d",
3261 -+ args[0]->result_type(), arg_count));
3262 -+
3263 -+ DBUG_RETURN(udf.val_decimal(&null_value, dec_buf));
3264 -+}
3265 -+
3266 -+
3267 -+String *Item_func_udf_decimal::val_str(String *str)
3268 -+{
3269 -+ my_decimal dec_buf, *dec= udf.val_decimal(&null_value, &dec_buf);
3270 -+ if (null_value)
3271 -+ return 0;
3272 -+ if (str->length() < DECIMAL_MAX_STR_LENGTH)
3273 -+ str->length(DECIMAL_MAX_STR_LENGTH);
3274 -+ my_decimal_round(E_DEC_FATAL_ERROR, dec, decimals, FALSE, &dec_buf);
3275 -+ my_decimal2string(E_DEC_FATAL_ERROR, &dec_buf, 0, 0, '0', str);
3276 -+ return str;
3277 -+}
3278 -+
3279 -+
3280 -+void Item_func_udf_decimal::fix_length_and_dec()
3281 -+{
3282 -+ fix_num_length_and_dec();
3283 -+}
3284 -+
3285 -+
3286 -+/* Default max_length is max argument length */
3287 -+
3288 -+void Item_func_udf_str::fix_length_and_dec()
3289 -+{
3290 -+ DBUG_ENTER("Item_func_udf_str::fix_length_and_dec");
3291 -+ max_length=0;
3292 -+ for (uint i = 0; i < arg_count; i++)
3293 -+ set_if_bigger(max_length,args[i]->max_length);
3294 -+ DBUG_VOID_RETURN;
3295 -+}
3296 -+
3297 -+String *Item_func_udf_str::val_str(String *str)
3298 -+{
3299 -+ DBUG_ASSERT(fixed == 1);
3300 -+ String *res=udf.val_str(str,&str_value);
3301 -+ null_value = !res;
3302 -+ return res;
3303 -+}
3304 -+
3305 -+
3306 -+/**
3307 -+ @note
3308 -+ This has to come last in the udf_handler methods, or C for AIX
3309 -+ version 6.0.0.0 fails to compile with debugging enabled. (Yes, really.)
3310 -+*/
3311 -+
3312 -+udf_handler::~udf_handler()
3313 -+{
3314 -+ /* Everything should be properly cleaned up by this moment. */
3315 -+ DBUG_ASSERT(not_original || !(initialized || buffers));
3316 -+}
3317 -+
3318 -+#else
3319 -+bool udf_handler::get_arguments() { return 0; }
3320 -+#endif /* HAVE_DLOPEN */
3321 -+
3322 -+/*
3323 -+** User level locks
3324 -+*/
3325 -+
3326 -+pthread_mutex_t LOCK_user_locks;
3327 -+static HASH hash_user_locks;
3328 -+
3329 -+class User_level_lock
3330 -+{
3331 -+ uchar *key;
3332 -+ size_t key_length;
3333 -+
3334 -+public:
3335 -+ int count;
3336 -+ bool locked;
3337 -+ pthread_cond_t cond;
3338 -+ my_thread_id thread_id;
3339 -+ void set_thread(THD *thd) { thread_id= thd->thread_id; }
3340 -+
3341 -+ User_level_lock(const uchar *key_arg,uint length, ulong id)
3342 -+ :key_length(length),count(1),locked(1), thread_id(id)
3343 -+ {
3344 -+ key= (uchar*) my_memdup(key_arg,length,MYF(0));
3345 -+ pthread_cond_init(&cond,NULL);
3346 -+ if (key)
3347 -+ {
3348 -+ if (my_hash_insert(&hash_user_locks,(uchar*) this))
3349 -+ {
3350 -+ my_free(key,MYF(0));
3351 -+ key=0;
3352 -+ }
3353 -+ }
3354 -+ }
3355 -+ ~User_level_lock()
3356 -+ {
3357 -+ if (key)
3358 -+ {
3359 -+ hash_delete(&hash_user_locks,(uchar*) this);
3360 -+ my_free(key, MYF(0));
3361 -+ }
3362 -+ pthread_cond_destroy(&cond);
3363 -+ }
3364 -+ inline bool initialized() { return key != 0; }
3365 -+ friend void item_user_lock_release(User_level_lock *ull);
3366 -+ friend uchar *ull_get_key(const User_level_lock *ull, size_t *length,
3367 -+ my_bool not_used);
3368 -+};
3369 -+
3370 -+uchar *ull_get_key(const User_level_lock *ull, size_t *length,
3371 -+ my_bool not_used __attribute__((unused)))
3372 -+{
3373 -+ *length= ull->key_length;
3374 -+ return ull->key;
3375 -+}
3376 -+
3377 -+
3378 -+static bool item_user_lock_inited= 0;
3379 -+
3380 -+void item_user_lock_init(void)
3381 -+{
3382 -+ pthread_mutex_init(&LOCK_user_locks,MY_MUTEX_INIT_SLOW);
3383 -+ hash_init(&hash_user_locks,system_charset_info,
3384 -+ 16,0,0,(hash_get_key) ull_get_key,NULL,0);
3385 -+ item_user_lock_inited= 1;
3386 -+}
3387 -+
3388 -+void item_user_lock_free(void)
3389 -+{
3390 -+ if (item_user_lock_inited)
3391 -+ {
3392 -+ item_user_lock_inited= 0;
3393 -+ hash_free(&hash_user_locks);
3394 -+ pthread_mutex_destroy(&LOCK_user_locks);
3395 -+ }
3396 -+}
3397 -+
3398 -+void item_user_lock_release(User_level_lock *ull)
3399 -+{
3400 -+ ull->locked=0;
3401 -+ ull->thread_id= 0;
3402 -+ if (--ull->count)
3403 -+ pthread_cond_signal(&ull->cond);
3404 -+ else
3405 -+ delete ull;
3406 -+}
3407 -+
3408 -+/**
3409 -+ Wait until we are at or past the given position in the master binlog
3410 -+ on the slave.
3411 -+*/
3412 -+
3413 -+longlong Item_master_pos_wait::val_int()
3414 -+{
3415 -+ DBUG_ASSERT(fixed == 1);
3416 -+ THD* thd = current_thd;
3417 -+ String *log_name = args[0]->val_str(&value);
3418 -+ int event_count= 0;
3419 -+
3420 -+ null_value=0;
3421 -+ if (thd->slave_thread || !log_name || !log_name->length())
3422 -+ {
3423 -+ null_value = 1;
3424 -+ return 0;
3425 -+ }
3426 -+#ifdef HAVE_REPLICATION
3427 -+ longlong pos = (ulong)args[1]->val_int();
3428 -+ longlong timeout = (arg_count==3) ? args[2]->val_int() : 0 ;
3429 -+ if ((event_count = active_mi->rli.wait_for_pos(thd, log_name, pos, timeout)) == -2)
3430 -+ {
3431 -+ null_value = 1;
3432 -+ event_count=0;
3433 -+ }
3434 -+#endif
3435 -+ return event_count;
3436 -+}
3437 -+
3438 -+
3439 -+/**
3440 -+ Get a user level lock. If the thread has an old lock this is first released.
3441 -+
3442 -+ @retval
3443 -+ 1 : Got lock
3444 -+ @retval
3445 -+ 0 : Timeout
3446 -+ @retval
3447 -+ NULL : Error
3448 -+*/
3449 -+
3450 -+longlong Item_func_get_lock::val_int()
3451 -+{
3452 -+ DBUG_ASSERT(fixed == 1);
3453 -+ String *res=args[0]->val_str(&value);
3454 -+ longlong timeout=args[1]->val_int();
3455 -+ struct timespec abstime;
3456 -+ THD *thd=current_thd;
3457 -+ User_level_lock *ull;
3458 -+ int error;
3459 -+ DBUG_ENTER("Item_func_get_lock::val_int");
3460 -+
3461 -+ /*
3462 -+ In slave thread no need to get locks, everything is serialized. Anyway
3463 -+ there is no way to make GET_LOCK() work on slave like it did on master
3464 -+ (i.e. make it return exactly the same value) because we don't have the
3465 -+ same other concurrent threads environment. No matter what we return here,
3466 -+ it's not guaranteed to be same as on master.
3467 -+ */
3468 -+ if (thd->slave_thread)
3469 -+ DBUG_RETURN(1);
3470 -+
3471 -+ pthread_mutex_lock(&LOCK_user_locks);
3472 -+
3473 -+ if (!res || !res->length())
3474 -+ {
3475 -+ pthread_mutex_unlock(&LOCK_user_locks);
3476 -+ null_value=1;
3477 -+ DBUG_RETURN(0);
3478 -+ }
3479 -+ DBUG_PRINT("info", ("lock %.*s, thd=%ld", res->length(), res->ptr(),
3480 -+ (long) thd->real_id));
3481 -+ null_value=0;
3482 -+
3483 -+ if (thd->ull)
3484 -+ {
3485 -+ item_user_lock_release(thd->ull);
3486 -+ thd->ull=0;
3487 -+ }
3488 -+
3489 -+ if (!(ull= ((User_level_lock *) hash_search(&hash_user_locks,
3490 -+ (uchar*) res->ptr(),
3491 -+ (size_t) res->length()))))
3492 -+ {
3493 -+ ull= new User_level_lock((uchar*) res->ptr(), (size_t) res->length(),
3494 -+ thd->thread_id);
3495 -+ if (!ull || !ull->initialized())
3496 -+ {
3497 -+ delete ull;
3498 -+ pthread_mutex_unlock(&LOCK_user_locks);
3499 -+ null_value=1; // Probably out of memory
3500 -+ DBUG_RETURN(0);
3501 -+ }
3502 -+ ull->set_thread(thd);
3503 -+ thd->ull=ull;
3504 -+ pthread_mutex_unlock(&LOCK_user_locks);
3505 -+ DBUG_PRINT("info", ("made new lock"));
3506 -+ DBUG_RETURN(1); // Got new lock
3507 -+ }
3508 -+ ull->count++;
3509 -+ DBUG_PRINT("info", ("ull->count=%d", ull->count));
3510 -+
3511 -+ /*
3512 -+ Structure is now initialized. Try to get the lock.
3513 -+ Set up control struct to allow others to abort locks.
3514 -+ */
3515 -+ thd_proc_info(thd, "User lock");
3516 -+ thd->mysys_var->current_mutex= &LOCK_user_locks;
3517 -+ thd->mysys_var->current_cond= &ull->cond;
3518 -+
3519 -+ set_timespec(abstime,timeout);
3520 -+ error= 0;
3521 -+ while (ull->locked && !thd->killed)
3522 -+ {
3523 -+ DBUG_PRINT("info", ("waiting on lock"));
3524 -+ error= pthread_cond_timedwait(&ull->cond,&LOCK_user_locks,&abstime);
3525 -+ if (error == ETIMEDOUT || error == ETIME)
3526 -+ {
3527 -+ DBUG_PRINT("info", ("lock wait timeout"));
3528 -+ break;
3529 -+ }
3530 -+ error= 0;
3531 -+ }
3532 -+
3533 -+ if (ull->locked)
3534 -+ {
3535 -+ if (!--ull->count)
3536 -+ {
3537 -+ DBUG_ASSERT(0);
3538 -+ delete ull; // Should never happen
3539 -+ }
3540 -+ if (!error) // Killed (thd->killed != 0)
3541 -+ {
3542 -+ error=1;
3543 -+ null_value=1; // Return NULL
3544 -+ }
3545 -+ }
3546 -+ else // We got the lock
3547 -+ {
3548 -+ ull->locked=1;
3549 -+ ull->set_thread(thd);
3550 -+ ull->thread_id= thd->thread_id;
3551 -+ thd->ull=ull;
3552 -+ error=0;
3553 -+ DBUG_PRINT("info", ("got the lock"));
3554 -+ }
3555 -+ pthread_mutex_unlock(&LOCK_user_locks);
3556 -+
3557 -+ pthread_mutex_lock(&thd->mysys_var->mutex);
3558 -+ thd_proc_info(thd, 0);
3559 -+ thd->mysys_var->current_mutex= 0;
3560 -+ thd->mysys_var->current_cond= 0;
3561 -+ pthread_mutex_unlock(&thd->mysys_var->mutex);
3562 -+
3563 -+ DBUG_RETURN(!error ? 1 : 0);
3564 -+}
3565 -+
3566 -+
3567 -+/**
3568 -+ Release a user level lock.
3569 -+ @return
3570 -+ - 1 if lock released
3571 -+ - 0 if lock wasn't held
3572 -+ - (SQL) NULL if no such lock
3573 -+*/
3574 -+
3575 -+longlong Item_func_release_lock::val_int()
3576 -+{
3577 -+ DBUG_ASSERT(fixed == 1);
3578 -+ String *res=args[0]->val_str(&value);
3579 -+ User_level_lock *ull;
3580 -+ longlong result;
3581 -+ THD *thd=current_thd;
3582 -+ DBUG_ENTER("Item_func_release_lock::val_int");
3583 -+ if (!res || !res->length())
3584 -+ {
3585 -+ null_value=1;
3586 -+ DBUG_RETURN(0);
3587 -+ }
3588 -+ DBUG_PRINT("info", ("lock %.*s", res->length(), res->ptr()));
3589 -+ null_value=0;
3590 -+
3591 -+ result=0;
3592 -+ pthread_mutex_lock(&LOCK_user_locks);
3593 -+ if (!(ull= ((User_level_lock*) hash_search(&hash_user_locks,
3594 -+ (const uchar*) res->ptr(),
3595 -+ (size_t) res->length()))))
3596 -+ {
3597 -+ null_value=1;
3598 -+ }
3599 -+ else
3600 -+ {
3601 -+ DBUG_PRINT("info", ("ull->locked=%d ull->thread=%lu thd=%lu",
3602 -+ (int) ull->locked,
3603 -+ (long)ull->thread_id,
3604 -+ (long)thd->thread_id));
3605 -+ if (ull->locked && current_thd->thread_id == ull->thread_id)
3606 -+ {
3607 -+ DBUG_PRINT("info", ("release lock"));
3608 -+ result=1; // Release is ok
3609 -+ item_user_lock_release(ull);
3610 -+ thd->ull=0;
3611 -+ }
3612 -+ }
3613 -+ pthread_mutex_unlock(&LOCK_user_locks);
3614 -+ DBUG_RETURN(result);
3615 -+}
3616 -+
3617 -+
3618 -+longlong Item_func_last_insert_id::val_int()
3619 -+{
3620 -+ THD *thd= current_thd;
3621 -+ DBUG_ASSERT(fixed == 1);
3622 -+ if (arg_count)
3623 -+ {
3624 -+ longlong value= args[0]->val_int();
3625 -+ null_value= args[0]->null_value;
3626 -+ /*
3627 -+ LAST_INSERT_ID(X) must affect the client's mysql_insert_id() as
3628 -+ documented in the manual. We don't want to touch
3629 -+ first_successful_insert_id_in_cur_stmt because it would make
3630 -+ LAST_INSERT_ID(X) take precedence over an generated auto_increment
3631 -+ value for this row.
3632 -+ */
3633 -+ thd->arg_of_last_insert_id_function= TRUE;
3634 -+ thd->first_successful_insert_id_in_prev_stmt= value;
3635 -+ return value;
3636 -+ }
3637 -+ return thd->read_first_successful_insert_id_in_prev_stmt();
3638 -+}
3639 -+
3640 -+
3641 -+bool Item_func_last_insert_id::fix_fields(THD *thd, Item **ref)
3642 -+{
3643 -+ thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
3644 -+ return Item_int_func::fix_fields(thd, ref);
3645 -+}
3646 -+
3647 -+
3648 -+/* This function is just used to test speed of different functions */
3649 -+
3650 -+longlong Item_func_benchmark::val_int()
3651 -+{
3652 -+ DBUG_ASSERT(fixed == 1);
3653 -+ char buff[MAX_FIELD_WIDTH];
3654 -+ String tmp(buff,sizeof(buff), &my_charset_bin);
3655 -+ my_decimal tmp_decimal;
3656 -+ THD *thd=current_thd;
3657 -+ ulonglong loop_count;
3658 -+
3659 -+ loop_count= (ulonglong) args[0]->val_int();
3660 -+
3661 -+ if (args[0]->null_value ||
3662 -+ (!args[0]->unsigned_flag && (((longlong) loop_count) < 0)))
3663 -+ {
3664 -+ if (!args[0]->null_value)
3665 -+ {
3666 -+ char buff[22];
3667 -+ llstr(((longlong) loop_count), buff);
3668 -+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
3669 -+ ER_WRONG_VALUE_FOR_TYPE, ER(ER_WRONG_VALUE_FOR_TYPE),
3670 -+ "count", buff, "benchmark");
3671 -+ }
3672 -+
3673 -+ null_value= 1;
3674 -+ return 0;
3675 -+ }
3676 -+
3677 -+ null_value=0;
3678 -+ for (ulonglong loop=0 ; loop < loop_count && !thd->killed; loop++)
3679 -+ {
3680 -+ switch (args[1]->result_type()) {
3681 -+ case REAL_RESULT:
3682 -+ (void) args[1]->val_real();
3683 -+ break;
3684 -+ case INT_RESULT:
3685 -+ (void) args[1]->val_int();
3686 -+ break;
3687 -+ case STRING_RESULT:
3688 -+ (void) args[1]->val_str(&tmp);
3689 -+ break;
3690 -+ case DECIMAL_RESULT:
3691 -+ (void) args[1]->val_decimal(&tmp_decimal);
3692 -+ break;
3693 -+ case ROW_RESULT:
3694 -+ default:
3695 -+ // This case should never be chosen
3696 -+ DBUG_ASSERT(0);
3697 -+ return 0;
3698 -+ }
3699 -+ }
3700 -+ return 0;
3701 -+}
3702 -+
3703 -+
3704 -+void Item_func_benchmark::print(String *str, enum_query_type query_type)
3705 -+{
3706 -+ str->append(STRING_WITH_LEN("benchmark("));
3707 -+ args[0]->print(str, query_type);
3708 -+ str->append(',');
3709 -+ args[1]->print(str, query_type);
3710 -+ str->append(')');
3711 -+}
3712 -+
3713 -+
3714 -+/** This function is just used to create tests with time gaps. */
3715 -+
3716 -+longlong Item_func_sleep::val_int()
3717 -+{
3718 -+ THD *thd= current_thd;
3719 -+ struct timespec abstime;
3720 -+ pthread_cond_t cond;
3721 -+ int error;
3722 -+
3723 -+ DBUG_ASSERT(fixed == 1);
3724 -+
3725 -+ double time= args[0]->val_real();
3726 -+ /*
3727 -+ On 64-bit OSX pthread_cond_timedwait() waits forever
3728 -+ if passed abstime time has already been exceeded by
3729 -+ the system time.
3730 -+ When given a very short timeout (< 10 mcs) just return
3731 -+ immediately.
3732 -+ We assume that the lines between this test and the call
3733 -+ to pthread_cond_timedwait() will be executed in less than 0.00001 sec.
3734 -+ */
3735 -+ if (time < 0.00001)
3736 -+ return 0;
3737 -+
3738 -+ set_timespec_nsec(abstime, (ulonglong)(time * ULL(1000000000)));
3739 -+
3740 -+ pthread_cond_init(&cond, NULL);
3741 -+ pthread_mutex_lock(&LOCK_user_locks);
3742 -+
3743 -+ thd_proc_info(thd, "User sleep");
3744 -+ thd->mysys_var->current_mutex= &LOCK_user_locks;
3745 -+ thd->mysys_var->current_cond= &cond;
3746 -+
3747 -+ error= 0;
3748 -+ while (!thd->killed)
3749 -+ {
3750 -+ error= pthread_cond_timedwait(&cond, &LOCK_user_locks, &abstime);
3751 -+ if (error == ETIMEDOUT || error == ETIME)
3752 -+ break;
3753 -+ error= 0;
3754 -+ }
3755 -+ thd_proc_info(thd, 0);
3756 -+ pthread_mutex_unlock(&LOCK_user_locks);
3757 -+ pthread_mutex_lock(&thd->mysys_var->mutex);
3758 -+ thd->mysys_var->current_mutex= 0;
3759 -+ thd->mysys_var->current_cond= 0;
3760 -+ pthread_mutex_unlock(&thd->mysys_var->mutex);
3761 -+
3762 -+ pthread_cond_destroy(&cond);
3763 -+
3764 -+ return test(!error); // Return 1 killed
3765 -+}
3766 -+
3767 -+
3768 -+#define extra_size sizeof(double)
3769 -+
3770 -+static user_var_entry *get_variable(HASH *hash, LEX_STRING &name,
3771 -+ bool create_if_not_exists)
3772 -+{
3773 -+ user_var_entry *entry;
3774 -+
3775 -+ if (!(entry = (user_var_entry*) hash_search(hash, (uchar*) name.str,
3776 -+ name.length)) &&
3777 -+ create_if_not_exists)
3778 -+ {
3779 -+ uint size=ALIGN_SIZE(sizeof(user_var_entry))+name.length+1+extra_size;
3780 -+ if (!hash_inited(hash))
3781 -+ return 0;
3782 -+ if (!(entry = (user_var_entry*) my_malloc(size,MYF(MY_WME))))
3783 -+ return 0;
3784 -+ entry->name.str=(char*) entry+ ALIGN_SIZE(sizeof(user_var_entry))+
3785 -+ extra_size;
3786 -+ entry->name.length=name.length;
3787 -+ entry->value=0;
3788 -+ entry->length=0;
3789 -+ entry->update_query_id=0;
3790 -+ entry->collation.set(NULL, DERIVATION_IMPLICIT, 0);
3791 -+ entry->unsigned_flag= 0;
3792 -+ /*
3793 -+ If we are here, we were called from a SET or a query which sets a
3794 -+ variable. Imagine it is this:
3795 -+ INSERT INTO t SELECT @a:=10, @a:=@a+1.
3796 -+ Then when we have a Item_func_get_user_var (because of the @a+1) so we
3797 -+ think we have to write the value of @a to the binlog. But before that,
3798 -+ we have a Item_func_set_user_var to create @a (@a:=10), in this we mark
3799 -+ the variable as "already logged" (line below) so that it won't be logged
3800 -+ by Item_func_get_user_var (because that's not necessary).
3801 -+ */
3802 -+ entry->used_query_id=current_thd->query_id;
3803 -+ entry->type=STRING_RESULT;
3804 -+ memcpy(entry->name.str, name.str, name.length+1);
3805 -+ if (my_hash_insert(hash,(uchar*) entry))
3806 -+ {
3807 -+ my_free((char*) entry,MYF(0));
3808 -+ return 0;
3809 -+ }
3810 -+ }
3811 -+ return entry;
3812 -+}
3813 -+
3814 -+
3815 -+void Item_func_set_user_var::cleanup()
3816 -+{
3817 -+ Item_func::cleanup();
3818 -+ entry= NULL;
3819 -+}
3820 -+
3821 -+
3822 -+bool Item_func_set_user_var::set_entry(THD *thd, bool create_if_not_exists)
3823 -+{
3824 -+ if (entry && thd->thread_id == entry_thread_id)
3825 -+ goto end; // update entry->update_query_id for PS
3826 -+ if (!(entry= get_variable(&thd->user_vars, name, create_if_not_exists)))
3827 -+ {
3828 -+ entry_thread_id= 0;
3829 -+ return TRUE;
3830 -+ }
3831 -+ entry_thread_id= thd->thread_id;
3832 -+ /*
3833 -+ Remember the last query which updated it, this way a query can later know
3834 -+ if this variable is a constant item in the query (it is if update_query_id
3835 -+ is different from query_id).
3836 -+ */
3837 -+end:
3838 -+ entry->update_query_id= thd->query_id;
3839 -+ return FALSE;
3840 -+}
3841 -+
3842 -+
3843 -+/*
3844 -+ When a user variable is updated (in a SET command or a query like
3845 -+ SELECT @a:= ).
3846 -+*/
3847 -+
3848 -+bool Item_func_set_user_var::fix_fields(THD *thd, Item **ref)
3849 -+{
3850 -+ DBUG_ASSERT(fixed == 0);
3851 -+ /* fix_fields will call Item_func_set_user_var::fix_length_and_dec */
3852 -+ if (Item_func::fix_fields(thd, ref) || set_entry(thd, TRUE))
3853 -+ return TRUE;
3854 -+ /*
3855 -+ As it is wrong and confusing to associate any
3856 -+ character set with NULL, @a should be latin2
3857 -+ after this query sequence:
3858 -+
3859 -+ SET @a=_latin2'string';
3860 -+ SET @a=NULL;
3861 -+
3862 -+ I.e. the second query should not change the charset
3863 -+ to the current default value, but should keep the
3864 -+ original value assigned during the first query.
3865 -+ In order to do it, we don't copy charset
3866 -+ from the argument if the argument is NULL
3867 -+ and the variable has previously been initialized.
3868 -+ */
3869 -+ null_item= (args[0]->type() == NULL_ITEM);
3870 -+ if (!entry->collation.collation || !null_item)
3871 -+ entry->collation.set(args[0]->collation.collation, DERIVATION_IMPLICIT);
3872 -+ collation.set(entry->collation.collation, DERIVATION_IMPLICIT);
3873 -+ cached_result_type= args[0]->result_type();
3874 -+ return FALSE;
3875 -+}
3876 -+
3877 -+
3878 -+void
3879 -+Item_func_set_user_var::fix_length_and_dec()
3880 -+{
3881 -+ maybe_null=args[0]->maybe_null;
3882 -+ max_length=args[0]->max_length;
3883 -+ decimals=args[0]->decimals;
3884 -+ unsigned_flag= args[0]->unsigned_flag;
3885 -+ collation.set(args[0]->collation.collation, DERIVATION_IMPLICIT);
3886 -+}
3887 -+
3888 -+
3889 -+/*
3890 -+ Mark field in read_map
3891 -+
3892 -+ NOTES
3893 -+ This is used by filesort to register used fields in a a temporary
3894 -+ column read set or to register used fields in a view
3895 -+*/
3896 -+
3897 -+bool Item_func_set_user_var::register_field_in_read_map(uchar *arg)
3898 -+{
3899 -+ if (result_field)
3900 -+ {
3901 -+ TABLE *table= (TABLE *) arg;
3902 -+ if (result_field->table == table || !table)
3903 -+ bitmap_set_bit(result_field->table->read_set, result_field->field_index);
3904 -+ }
3905 -+ return 0;
3906 -+}
3907 -+
3908 -+
3909 -+/**
3910 -+ Set value to user variable.
3911 -+
3912 -+ @param entry pointer to structure representing variable
3913 -+ @param set_null should we set NULL value ?
3914 -+ @param ptr pointer to buffer with new value
3915 -+ @param length length of new value
3916 -+ @param type type of new value
3917 -+ @param cs charset info for new value
3918 -+ @param dv derivation for new value
3919 -+ @param unsigned_arg indiates if a value of type INT_RESULT is unsigned
3920 -+
3921 -+ @retval
3922 -+ false success
3923 -+ @retval
3924 -+ true failure
3925 -+*/
3926 -+
3927 -+static bool
3928 -+update_hash(user_var_entry *entry, bool set_null, void *ptr, uint length,
3929 -+ Item_result type, CHARSET_INFO *cs, Derivation dv,
3930 -+ bool unsigned_arg)
3931 -+{
3932 -+ if (set_null)
3933 -+ {
3934 -+ char *pos= (char*) entry+ ALIGN_SIZE(sizeof(user_var_entry));
3935 -+ if (entry->value && entry->value != pos)
3936 -+ my_free(entry->value,MYF(0));
3937 -+ entry->value= 0;
3938 -+ entry->length= 0;
3939 -+ }
3940 -+ else
3941 -+ {
3942 -+ if (type == STRING_RESULT)
3943 -+ length++; // Store strings with end \0
3944 -+ if (length <= extra_size)
3945 -+ {
3946 -+ /* Save value in value struct */
3947 -+ char *pos= (char*) entry+ ALIGN_SIZE(sizeof(user_var_entry));
3948 -+ if (entry->value != pos)
3949 -+ {
3950 -+ if (entry->value)
3951 -+ my_free(entry->value,MYF(0));
3952 -+ entry->value=pos;
3953 -+ }
3954 -+ }
3955 -+ else
3956 -+ {
3957 -+ /* Allocate variable */
3958 -+ if (entry->length != length)
3959 -+ {
3960 -+ char *pos= (char*) entry+ ALIGN_SIZE(sizeof(user_var_entry));
3961 -+ if (entry->value == pos)
3962 -+ entry->value=0;
3963 -+ entry->value= (char*) my_realloc(entry->value, length,
3964 -+ MYF(MY_ALLOW_ZERO_PTR | MY_WME));
3965 -+ if (!entry->value)
3966 -+ return 1;
3967 -+ }
3968 -+ }
3969 -+ if (type == STRING_RESULT)
3970 -+ {
3971 -+ length--; // Fix length change above
3972 -+ entry->value[length]= 0; // Store end \0
3973 -+ }
3974 -+ memmove(entry->value, ptr, length);
3975 -+ if (type == DECIMAL_RESULT)
3976 -+ ((my_decimal*)entry->value)->fix_buffer_pointer();
3977 -+ entry->length= length;
3978 -+ entry->collation.set(cs, dv);
3979 -+ entry->unsigned_flag= unsigned_arg;
3980 -+ }
3981 -+ entry->type=type;
3982 -+ return 0;
3983 -+}
3984 -+
3985 -+
3986 -+bool
3987 -+Item_func_set_user_var::update_hash(void *ptr, uint length,
3988 -+ Item_result res_type,
3989 -+ CHARSET_INFO *cs, Derivation dv,
3990 -+ bool unsigned_arg)
3991 -+{
3992 -+ /*
3993 -+ If we set a variable explicitely to NULL then keep the old
3994 -+ result type of the variable
3995 -+ */
3996 -+ if ((null_value= args[0]->null_value) && null_item)
3997 -+ res_type= entry->type; // Don't change type of item
3998 -+ if (::update_hash(entry, (null_value= args[0]->null_value),
3999 -+ ptr, length, res_type, cs, dv, unsigned_arg))
4000 -+ {
4001 -+ current_thd->fatal_error(); // Probably end of memory
4002 -+ null_value= 1;
4003 -+ return 1;
4004 -+ }
4005 -+ return 0;
4006 -+}
4007 -+
4008 -+
4009 -+/** Get the value of a variable as a double. */
4010 -+
4011 -+double user_var_entry::val_real(my_bool *null_value)
4012 -+{
4013 -+ if ((*null_value= (value == 0)))
4014 -+ return 0.0;
4015 -+
4016 -+ switch (type) {
4017 -+ case REAL_RESULT:
4018 -+ return *(double*) value;
4019 -+ case INT_RESULT:
4020 -+ return (double) *(longlong*) value;
4021 -+ case DECIMAL_RESULT:
4022 -+ {
4023 -+ double result;
4024 -+ my_decimal2double(E_DEC_FATAL_ERROR, (my_decimal *)value, &result);
4025 -+ return result;
4026 -+ }
4027 -+ case STRING_RESULT:
4028 -+ return my_atof(value); // This is null terminated
4029 -+ case ROW_RESULT:
4030 -+ DBUG_ASSERT(1); // Impossible
4031 -+ break;
4032 -+ }
4033 -+ return 0.0; // Impossible
4034 -+}
4035 -+
4036 -+
4037 -+/** Get the value of a variable as an integer. */
4038 -+
4039 -+longlong user_var_entry::val_int(my_bool *null_value) const
4040 -+{
4041 -+ if ((*null_value= (value == 0)))
4042 -+ return LL(0);
4043 -+
4044 -+ switch (type) {
4045 -+ case REAL_RESULT:
4046 -+ return (longlong) *(double*) value;
4047 -+ case INT_RESULT:
4048 -+ return *(longlong*) value;
4049 -+ case DECIMAL_RESULT:
4050 -+ {
4051 -+ longlong result;
4052 -+ my_decimal2int(E_DEC_FATAL_ERROR, (my_decimal *)value, 0, &result);
4053 -+ return result;
4054 -+ }
4055 -+ case STRING_RESULT:
4056 -+ {
4057 -+ int error;
4058 -+ return my_strtoll10(value, (char**) 0, &error);// String is null terminated
4059 -+ }
4060 -+ case ROW_RESULT:
4061 -+ DBUG_ASSERT(1); // Impossible
4062 -+ break;
4063 -+ }
4064 -+ return LL(0); // Impossible
4065 -+}
4066 -+
4067 -+
4068 -+/** Get the value of a variable as a string. */
4069 -+
4070 -+String *user_var_entry::val_str(my_bool *null_value, String *str,
4071 -+ uint decimals)
4072 -+{
4073 -+ if ((*null_value= (value == 0)))
4074 -+ return (String*) 0;
4075 -+
4076 -+ switch (type) {
4077 -+ case REAL_RESULT:
4078 -+ str->set_real(*(double*) value, decimals, &my_charset_bin);
4079 -+ break;
4080 -+ case INT_RESULT:
4081 -+ if (!unsigned_flag)
4082 -+ str->set(*(longlong*) value, &my_charset_bin);
4083 -+ else
4084 -+ str->set(*(ulonglong*) value, &my_charset_bin);
4085 -+ break;
4086 -+ case DECIMAL_RESULT:
4087 -+ my_decimal2string(E_DEC_FATAL_ERROR, (my_decimal *)value, 0, 0, 0, str);
4088 -+ break;
4089 -+ case STRING_RESULT:
4090 -+ if (str->copy(value, length, collation.collation))
4091 -+ str= 0; // EOM error
4092 -+ case ROW_RESULT:
4093 -+ DBUG_ASSERT(1); // Impossible
4094 -+ break;
4095 -+ }
4096 -+ return(str);
4097 -+}
4098 -+
4099 -+/** Get the value of a variable as a decimal. */
4100 -+
4101 -+my_decimal *user_var_entry::val_decimal(my_bool *null_value, my_decimal *val)
4102 -+{
4103 -+ if ((*null_value= (value == 0)))
4104 -+ return 0;
4105 -+
4106 -+ switch (type) {
4107 -+ case REAL_RESULT:
4108 -+ double2my_decimal(E_DEC_FATAL_ERROR, *(double*) value, val);
4109 -+ break;
4110 -+ case INT_RESULT:
4111 -+ int2my_decimal(E_DEC_FATAL_ERROR, *(longlong*) value, 0, val);
4112 -+ break;
4113 -+ case DECIMAL_RESULT:
4114 -+ my_decimal2decimal((my_decimal *) value, val);
4115 -+ break;
4116 -+ case STRING_RESULT:
4117 -+ str2my_decimal(E_DEC_FATAL_ERROR, value, length, collation.collation, val);
4118 -+ break;
4119 -+ case ROW_RESULT:
4120 -+ DBUG_ASSERT(1); // Impossible
4121 -+ break;
4122 -+ }
4123 -+ return(val);
4124 -+}
4125 -+
4126 -+/**
4127 -+ This functions is invoked on SET \@variable or
4128 -+ \@variable:= expression.
4129 -+
4130 -+ Evaluate (and check expression), store results.
4131 -+
4132 -+ @note
4133 -+ For now it always return OK. All problem with value evaluating
4134 -+ will be caught by thd->is_error() check in sql_set_variables().
4135 -+
4136 -+ @retval
4137 -+ FALSE OK.
4138 -+*/
4139 -+
4140 -+bool
4141 -+Item_func_set_user_var::check(bool use_result_field)
4142 -+{
4143 -+ DBUG_ENTER("Item_func_set_user_var::check");
4144 -+ if (use_result_field && !result_field)
4145 -+ use_result_field= FALSE;
4146 -+
4147 -+ switch (cached_result_type) {
4148 -+ case REAL_RESULT:
4149 -+ {
4150 -+ save_result.vreal= use_result_field ? result_field->val_real() :
4151 -+ args[0]->val_real();
4152 -+ break;
4153 -+ }
4154 -+ case INT_RESULT:
4155 -+ {
4156 -+ save_result.vint= use_result_field ? result_field->val_int() :
4157 -+ args[0]->val_int();
4158 -+ unsigned_flag= use_result_field ? ((Field_num*)result_field)->unsigned_flag:
4159 -+ args[0]->unsigned_flag;
4160 -+ break;
4161 -+ }
4162 -+ case STRING_RESULT:
4163 -+ {
4164 -+ save_result.vstr= use_result_field ? result_field->val_str(&value) :
4165 -+ args[0]->val_str(&value);
4166 -+ break;
4167 -+ }
4168 -+ case DECIMAL_RESULT:
4169 -+ {
4170 -+ save_result.vdec= use_result_field ?
4171 -+ result_field->val_decimal(&decimal_buff) :
4172 -+ args[0]->val_decimal(&decimal_buff);
4173 -+ break;
4174 -+ }
4175 -+ case ROW_RESULT:
4176 -+ default:
4177 -+ // This case should never be chosen
4178 -+ DBUG_ASSERT(0);
4179 -+ break;
4180 -+ }
4181 -+ DBUG_RETURN(FALSE);
4182 -+}
4183 -+
4184 -+
4185 -+/**
4186 -+ @brief Evaluate and store item's result.
4187 -+ This function is invoked on "SELECT ... INTO @var ...".
4188 -+
4189 -+ @param item An item to get value from.
4190 -+*/
4191 -+
4192 -+void Item_func_set_user_var::save_item_result(Item *item)
4193 -+{
4194 -+ DBUG_ENTER("Item_func_set_user_var::save_item_result");
4195 -+
4196 -+ switch (cached_result_type) {
4197 -+ case REAL_RESULT:
4198 -+ save_result.vreal= item->val_result();
4199 -+ break;
4200 -+ case INT_RESULT:
4201 -+ save_result.vint= item->val_int_result();
4202 -+ unsigned_flag= item->unsigned_flag;
4203 -+ break;
4204 -+ case STRING_RESULT:
4205 -+ save_result.vstr= item->str_result(&value);
4206 -+ break;
4207 -+ case DECIMAL_RESULT:
4208 -+ save_result.vdec= item->val_decimal_result(&decimal_buff);
4209 -+ break;
4210 -+ case ROW_RESULT:
4211 -+ default:
4212 -+ // Should never happen
4213 -+ DBUG_ASSERT(0);
4214 -+ break;
4215 -+ }
4216 -+ DBUG_VOID_RETURN;
4217 -+}
4218 -+
4219 -+
4220 -+/**
4221 -+ This functions is invoked on
4222 -+ SET \@variable or \@variable:= expression.
4223 -+
4224 -+ @note
4225 -+ We have to store the expression as such in the variable, independent of
4226 -+ the value method used by the user
4227 -+
4228 -+ @retval
4229 -+ 0 OK
4230 -+ @retval
4231 -+ 1 EOM Error
4232 -+
4233 -+*/
4234 -+
4235 -+bool
4236 -+Item_func_set_user_var::update()
4237 -+{
4238 -+ bool res= 0;
4239 -+ DBUG_ENTER("Item_func_set_user_var::update");
4240 -+
4241 -+ switch (cached_result_type) {
4242 -+ case REAL_RESULT:
4243 -+ {
4244 -+ res= update_hash((void*) &save_result.vreal,sizeof(save_result.vreal),
4245 -+ REAL_RESULT, &my_charset_bin, DERIVATION_IMPLICIT, 0);
4246 -+ break;
4247 -+ }
4248 -+ case INT_RESULT:
4249 -+ {
4250 -+ res= update_hash((void*) &save_result.vint, sizeof(save_result.vint),
4251 -+ INT_RESULT, &my_charset_bin, DERIVATION_IMPLICIT,
4252 -+ unsigned_flag);
4253 -+ break;
4254 -+ }
4255 -+ case STRING_RESULT:
4256 -+ {
4257 -+ if (!save_result.vstr) // Null value
4258 -+ res= update_hash((void*) 0, 0, STRING_RESULT, &my_charset_bin,
4259 -+ DERIVATION_IMPLICIT, 0);
4260 -+ else
4261 -+ res= update_hash((void*) save_result.vstr->ptr(),
4262 -+ save_result.vstr->length(), STRING_RESULT,
4263 -+ save_result.vstr->charset(),
4264 -+ DERIVATION_IMPLICIT, 0);
4265 -+ break;
4266 -+ }
4267 -+ case DECIMAL_RESULT:
4268 -+ {
4269 -+ if (!save_result.vdec) // Null value
4270 -+ res= update_hash((void*) 0, 0, DECIMAL_RESULT, &my_charset_bin,
4271 -+ DERIVATION_IMPLICIT, 0);
4272 -+ else
4273 -+ res= update_hash((void*) save_result.vdec,
4274 -+ sizeof(my_decimal), DECIMAL_RESULT,
4275 -+ &my_charset_bin, DERIVATION_IMPLICIT, 0);
4276 -+ break;
4277 -+ }
4278 -+ case ROW_RESULT:
4279 -+ default:
4280 -+ // This case should never be chosen
4281 -+ DBUG_ASSERT(0);
4282 -+ break;
4283 -+ }
4284 -+ DBUG_RETURN(res);
4285 -+}
4286 -+
4287 -+
4288 -+double Item_func_set_user_var::val_real()
4289 -+{
4290 -+ DBUG_ASSERT(fixed == 1);
4291 -+ check(0);
4292 -+ update(); // Store expression
4293 -+ return entry->val_real(&null_value);
4294 -+}
4295 -+
4296 -+longlong Item_func_set_user_var::val_int()
4297 -+{
4298 -+ DBUG_ASSERT(fixed == 1);
4299 -+ check(0);
4300 -+ update(); // Store expression
4301 -+ return entry->val_int(&null_value);
4302 -+}
4303 -+
4304 -+String *Item_func_set_user_var::val_str(String *str)
4305 -+{
4306 -+ DBUG_ASSERT(fixed == 1);
4307 -+ check(0);
4308 -+ update(); // Store expression
4309 -+ return entry->val_str(&null_value, str, decimals);
4310 -+}
4311 -+
4312 -+
4313 -+my_decimal *Item_func_set_user_var::val_decimal(my_decimal *val)
4314 -+{
4315 -+ DBUG_ASSERT(fixed == 1);
4316 -+ check(0);
4317 -+ update(); // Store expression
4318 -+ return entry->val_decimal(&null_value, val);
4319 -+}
4320 -+
4321 -+
4322 -+double Item_func_set_user_var::val_result()
4323 -+{
4324 -+ DBUG_ASSERT(fixed == 1);
4325 -+ check(TRUE);
4326 -+ update(); // Store expression
4327 -+ return entry->val_real(&null_value);
4328 -+}
4329 -+
4330 -+longlong Item_func_set_user_var::val_int_result()
4331 -+{
4332 -+ DBUG_ASSERT(fixed == 1);
4333 -+ check(TRUE);
4334 -+ update(); // Store expression
4335 -+ return entry->val_int(&null_value);
4336 -+}
4337 -+
4338 -+bool Item_func_set_user_var::val_bool_result()
4339 -+{
4340 -+ DBUG_ASSERT(fixed == 1);
4341 -+ check(TRUE);
4342 -+ update(); // Store expression
4343 -+ return entry->val_int(&null_value) != 0;
4344 -+}
4345 -+
4346 -+String *Item_func_set_user_var::str_result(String *str)
4347 -+{
4348 -+ DBUG_ASSERT(fixed == 1);
4349 -+ check(TRUE);
4350 -+ update(); // Store expression
4351 -+ return entry->val_str(&null_value, str, decimals);
4352 -+}
4353 -+
4354 -+
4355 -+my_decimal *Item_func_set_user_var::val_decimal_result(my_decimal *val)
4356 -+{
4357 -+ DBUG_ASSERT(fixed == 1);
4358 -+ check(TRUE);
4359 -+ update(); // Store expression
4360 -+ return entry->val_decimal(&null_value, val);
4361 -+}
4362 -+
4363 -+
4364 -+bool Item_func_set_user_var::is_null_result()
4365 -+{
4366 -+ DBUG_ASSERT(fixed == 1);
4367 -+ check(TRUE);
4368 -+ update(); // Store expression
4369 -+ return is_null();
4370 -+}
4371 -+
4372 -+
4373 -+void Item_func_set_user_var::print(String *str, enum_query_type query_type)
4374 -+{
4375 -+ str->append(STRING_WITH_LEN("(@"));
4376 -+ str->append(name.str, name.length);
4377 -+ str->append(STRING_WITH_LEN(":="));
4378 -+ args[0]->print(str, query_type);
4379 -+ str->append(')');
4380 -+}
4381 -+
4382 -+
4383 -+void Item_func_set_user_var::print_as_stmt(String *str,
4384 -+ enum_query_type query_type)
4385 -+{
4386 -+ str->append(STRING_WITH_LEN("set @"));
4387 -+ str->append(name.str, name.length);
4388 -+ str->append(STRING_WITH_LEN(":="));
4389 -+ args[0]->print(str, query_type);
4390 -+ str->append(')');
4391 -+}
4392 -+
4393 -+bool Item_func_set_user_var::send(Protocol *protocol, String *str_arg)
4394 -+{
4395 -+ if (result_field)
4396 -+ {
4397 -+ check(1);
4398 -+ update();
4399 -+ return protocol->store(result_field);
4400 -+ }
4401 -+ return Item::send(protocol, str_arg);
4402 -+}
4403 -+
4404 -+void Item_func_set_user_var::make_field(Send_field *tmp_field)
4405 -+{
4406 -+ if (result_field)
4407 -+ {
4408 -+ result_field->make_field(tmp_field);
4409 -+ DBUG_ASSERT(tmp_field->table_name != 0);
4410 -+ if (Item::name)
4411 -+ tmp_field->col_name=Item::name; // Use user supplied name
4412 -+ }
4413 -+ else
4414 -+ Item::make_field(tmp_field);
4415 -+}
4416 -+
4417 -+
4418 -+/*
4419 -+ Save the value of a user variable into a field
4420 -+
4421 -+ SYNOPSIS
4422 -+ save_in_field()
4423 -+ field target field to save the value to
4424 -+ no_conversion flag indicating whether conversions are allowed
4425 -+
4426 -+ DESCRIPTION
4427 -+ Save the function value into a field and update the user variable
4428 -+ accordingly. If a result field is defined and the target field doesn't
4429 -+ coincide with it then the value from the result field will be used as
4430 -+ the new value of the user variable.
4431 -+
4432 -+ The reason to have this method rather than simply using the result
4433 -+ field in the val_xxx() methods is that the value from the result field
4434 -+ not always can be used when the result field is defined.
4435 -+ Let's consider the following cases:
4436 -+ 1) when filling a tmp table the result field is defined but the value of it
4437 -+ is undefined because it has to be produced yet. Thus we can't use it.
4438 -+ 2) on execution of an INSERT ... SELECT statement the save_in_field()
4439 -+ function will be called to fill the data in the new record. If the SELECT
4440 -+ part uses a tmp table then the result field is defined and should be
4441 -+ used in order to get the correct result.
4442 -+
4443 -+ The difference between the SET_USER_VAR function and regular functions
4444 -+ like CONCAT is that the Item_func objects for the regular functions are
4445 -+ replaced by Item_field objects after the values of these functions have
4446 -+ been stored in a tmp table. Yet an object of the Item_field class cannot
4447 -+ be used to update a user variable.
4448 -+ Due to this we have to handle the result field in a special way here and
4449 -+ in the Item_func_set_user_var::send() function.
4450 -+
4451 -+ RETURN VALUES
4452 -+ FALSE Ok
4453 -+ TRUE Error
4454 -+*/
4455 -+
4456 -+int Item_func_set_user_var::save_in_field(Field *field, bool no_conversions,
4457 -+ bool can_use_result_field)
4458 -+{
4459 -+ bool use_result_field= (!can_use_result_field ? 0 :
4460 -+ (result_field && result_field != field));
4461 -+ int error;
4462 -+
4463 -+ /* Update the value of the user variable */
4464 -+ check(use_result_field);
4465 -+ update();
4466 -+
4467 -+ if (result_type() == STRING_RESULT ||
4468 -+ (result_type() == REAL_RESULT &&
4469 -+ field->result_type() == STRING_RESULT))
4470 -+ {
4471 -+ String *result;
4472 -+ CHARSET_INFO *cs= collation.collation;
4473 -+ char buff[MAX_FIELD_WIDTH]; // Alloc buffer for small columns
4474 -+ str_value.set_quick(buff, sizeof(buff), cs);
4475 -+ result= entry->val_str(&null_value, &str_value, decimals);
4476 -+
4477 -+ if (null_value)
4478 -+ {
4479 -+ str_value.set_quick(0, 0, cs);
4480 -+ return set_field_to_null_with_conversions(field, no_conversions);
4481 -+ }
4482 -+
4483 -+ /* NOTE: If null_value == FALSE, "result" must be not NULL. */
4484 -+
4485 -+ field->set_notnull();
4486 -+ error=field->store(result->ptr(),result->length(),cs);
4487 -+ str_value.set_quick(0, 0, cs);
4488 -+ }
4489 -+ else if (result_type() == REAL_RESULT)
4490 -+ {
4491 -+ double nr= entry->val_real(&null_value);
4492 -+ if (null_value)
4493 -+ return set_field_to_null(field);
4494 -+ field->set_notnull();
4495 -+ error=field->store(nr);
4496 -+ }
4497 -+ else if (result_type() == DECIMAL_RESULT)
4498 -+ {
4499 -+ my_decimal decimal_value;
4500 -+ my_decimal *val= entry->val_decimal(&null_value, &decimal_value);
4501 -+ if (null_value)
4502 -+ return set_field_to_null(field);
4503 -+ field->set_notnull();
4504 -+ error=field->store_decimal(val);
4505 -+ }
4506 -+ else
4507 -+ {
4508 -+ longlong nr= entry->val_int(&null_value);
4509 -+ if (null_value)
4510 -+ return set_field_to_null_with_conversions(field, no_conversions);
4511 -+ field->set_notnull();
4512 -+ error=field->store(nr, unsigned_flag);
4513 -+ }
4514 -+ return error;
4515 -+}
4516 -+
4517 -+
4518 -+String *
4519 -+Item_func_get_user_var::val_str(String *str)
4520 -+{
4521 -+ DBUG_ASSERT(fixed == 1);
4522 -+ DBUG_ENTER("Item_func_get_user_var::val_str");
4523 -+ if (!var_entry)
4524 -+ DBUG_RETURN((String*) 0); // No such variable
4525 -+ DBUG_RETURN(var_entry->val_str(&null_value, str, decimals));
4526 -+}
4527 -+
4528 -+
4529 -+double Item_func_get_user_var::val_real()
4530 -+{
4531 -+ DBUG_ASSERT(fixed == 1);
4532 -+ if (!var_entry)
4533 -+ return 0.0; // No such variable
4534 -+ return (var_entry->val_real(&null_value));
4535 -+}
4536 -+
4537 -+
4538 -+my_decimal *Item_func_get_user_var::val_decimal(my_decimal *dec)
4539 -+{
4540 -+ DBUG_ASSERT(fixed == 1);
4541 -+ if (!var_entry)
4542 -+ return 0;
4543 -+ return var_entry->val_decimal(&null_value, dec);
4544 -+}
4545 -+
4546 -+
4547 -+longlong Item_func_get_user_var::val_int()
4548 -+{
4549 -+ DBUG_ASSERT(fixed == 1);
4550 -+ if (!var_entry)
4551 -+ return LL(0); // No such variable
4552 -+ return (var_entry->val_int(&null_value));
4553 -+}
4554 -+
4555 -+
4556 -+/**
4557 -+ Get variable by name and, if necessary, put the record of variable
4558 -+ use into the binary log.
4559 -+
4560 -+ When a user variable is invoked from an update query (INSERT, UPDATE etc),
4561 -+ stores this variable and its value in thd->user_var_events, so that it can be
4562 -+ written to the binlog (will be written just before the query is written, see
4563 -+ log.cc).
4564 -+
4565 -+ @param thd Current thread
4566 -+ @param name Variable name
4567 -+ @param[out] out_entry variable structure or NULL. The pointer is set
4568 -+ regardless of whether function succeeded or not.
4569 -+
4570 -+ @retval
4571 -+ 0 OK
4572 -+ @retval
4573 -+ 1 Failed to put appropriate record into binary log
4574 -+
4575 -+*/
4576 -+
4577 -+int get_var_with_binlog(THD *thd, enum_sql_command sql_command,
4578 -+ LEX_STRING &name, user_var_entry **out_entry)
4579 -+{
4580 -+ BINLOG_USER_VAR_EVENT *user_var_event;
4581 -+ user_var_entry *var_entry;
4582 -+ var_entry= get_variable(&thd->user_vars, name, 0);
4583 -+
4584 -+ /*
4585 -+ Any reference to user-defined variable which is done from stored
4586 -+ function or trigger affects their execution and the execution of the
4587 -+ calling statement. We must log all such variables even if they are
4588 -+ not involved in table-updating statements.
4589 -+ */
4590 -+ if (!(opt_bin_log &&
4591 -+ (is_update_query(sql_command) || thd->in_sub_stmt)))
4592 -+ {
4593 -+ *out_entry= var_entry;
4594 -+ return 0;
4595 -+ }
4596 -+
4597 -+ if (!var_entry)
4598 -+ {
4599 -+ /*
4600 -+ If the variable does not exist, it's NULL, but we want to create it so
4601 -+ that it gets into the binlog (if it didn't, the slave could be
4602 -+ influenced by a variable of the same name previously set by another
4603 -+ thread).
4604 -+ We create it like if it had been explicitly set with SET before.
4605 -+ The 'new' mimics what sql_yacc.yy does when 'SET @a=10;'.
4606 -+ sql_set_variables() is what is called from 'case SQLCOM_SET_OPTION'
4607 -+ in dispatch_command()). Instead of building a one-element list to pass to
4608 -+ sql_set_variables(), we could instead manually call check() and update();
4609 -+ this would save memory and time; but calling sql_set_variables() makes
4610 -+ one unique place to maintain (sql_set_variables()).
4611 -+
4612 -+ Manipulation with lex is necessary since free_underlaid_joins
4613 -+ is going to release memory belonging to the main query.
4614 -+ */
4615 -+
4616 -+ List<set_var_base> tmp_var_list;
4617 -+ LEX *sav_lex= thd->lex, lex_tmp;
4618 -+ thd->lex= &lex_tmp;
4619 -+ lex_start(thd);
4620 -+ tmp_var_list.push_back(new set_var_user(new Item_func_set_user_var(name,
4621 -+ new Item_null())));
4622 -+ /* Create the variable */
4623 -+ if (sql_set_variables(thd, &tmp_var_list))
4624 -+ {
4625 -+ thd->lex= sav_lex;
4626 -+ goto err;
4627 -+ }
4628 -+ thd->lex= sav_lex;
4629 -+ if (!(var_entry= get_variable(&thd->user_vars, name, 0)))
4630 -+ goto err;
4631 -+ }
4632 -+ else if (var_entry->used_query_id == thd->query_id ||
4633 -+ mysql_bin_log.is_query_in_union(thd, var_entry->used_query_id))
4634 -+ {
4635 -+ /*
4636 -+ If this variable was already stored in user_var_events by this query
4637 -+ (because it's used in more than one place in the query), don't store
4638 -+ it.
4639 -+ */
4640 -+ *out_entry= var_entry;
4641 -+ return 0;
4642 -+ }
4643 -+
4644 -+ uint size;
4645 -+ /*
4646 -+ First we need to store value of var_entry, when the next situation
4647 -+ appears:
4648 -+ > set @a:=1;
4649 -+ > insert into t1 values (@a), (@a:=@a+1), (@a:=@a+1);
4650 -+ We have to write to binlog value @a= 1.
4651 -+
4652 -+ We allocate the user_var_event on user_var_events_alloc pool, not on
4653 -+ the this-statement-execution pool because in SPs user_var_event objects
4654 -+ may need to be valid after current [SP] statement execution pool is
4655 -+ destroyed.
4656 -+ */
4657 -+ size= ALIGN_SIZE(sizeof(BINLOG_USER_VAR_EVENT)) + var_entry->length;
4658 -+ if (!(user_var_event= (BINLOG_USER_VAR_EVENT *)
4659 -+ alloc_root(thd->user_var_events_alloc, size)))
4660 -+ goto err;
4661 -+
4662 -+ user_var_event->value= (char*) user_var_event +
4663 -+ ALIGN_SIZE(sizeof(BINLOG_USER_VAR_EVENT));
4664 -+ user_var_event->user_var_event= var_entry;
4665 -+ user_var_event->type= var_entry->type;
4666 -+ user_var_event->charset_number= var_entry->collation.collation->number;
4667 -+ if (!var_entry->value)
4668 -+ {
4669 -+ /* NULL value*/
4670 -+ user_var_event->length= 0;
4671 -+ user_var_event->value= 0;
4672 -+ }
4673 -+ else
4674 -+ {
4675 -+ user_var_event->length= var_entry->length;
4676 -+ memcpy(user_var_event->value, var_entry->value,
4677 -+ var_entry->length);
4678 -+ }
4679 -+ /* Mark that this variable has been used by this query */
4680 -+ var_entry->used_query_id= thd->query_id;
4681 -+ if (insert_dynamic(&thd->user_var_events, (uchar*) &user_var_event))
4682 -+ goto err;
4683 -+
4684 -+ *out_entry= var_entry;
4685 -+ return 0;
4686 -+
4687 -+err:
4688 -+ *out_entry= var_entry;
4689 -+ return 1;
4690 -+}
4691 -+
4692 -+void Item_func_get_user_var::fix_length_and_dec()
4693 -+{
4694 -+ THD *thd=current_thd;
4695 -+ int error;
4696 -+ maybe_null=1;
4697 -+ decimals=NOT_FIXED_DEC;
4698 -+ max_length=MAX_BLOB_WIDTH;
4699 -+
4700 -+ error= get_var_with_binlog(thd, thd->lex->sql_command, name, &var_entry);
4701 -+
4702 -+ /*
4703 -+ If the variable didn't exist it has been created as a STRING-type.
4704 -+ 'var_entry' is NULL only if there occured an error during the call to
4705 -+ get_var_with_binlog.
4706 -+ */
4707 -+ if (var_entry)
4708 -+ {
4709 -+ m_cached_result_type= var_entry->type;
4710 -+ unsigned_flag= var_entry->unsigned_flag;
4711 -+ max_length= var_entry->length;
4712 -+
4713 -+ collation.set(var_entry->collation);
4714 -+ switch(m_cached_result_type) {
4715 -+ case REAL_RESULT:
4716 -+ max_length= DBL_DIG + 8;
4717 -+ break;
4718 -+ case INT_RESULT:
4719 -+ max_length= MAX_BIGINT_WIDTH;
4720 -+ decimals=0;
4721 -+ break;
4722 -+ case STRING_RESULT:
4723 -+ max_length= MAX_BLOB_WIDTH - 1;
4724 -+ break;
4725 -+ case DECIMAL_RESULT:
4726 -+ max_length= DECIMAL_MAX_STR_LENGTH;
4727 -+ decimals= DECIMAL_MAX_SCALE;
4728 -+ break;
4729 -+ case ROW_RESULT: // Keep compiler happy
4730 -+ default:
4731 -+ DBUG_ASSERT(0);
4732 -+ break;
4733 -+ }
4734 -+ }
4735 -+ else
4736 -+ {
4737 -+ collation.set(&my_charset_bin, DERIVATION_IMPLICIT);
4738 -+ null_value= 1;
4739 -+ m_cached_result_type= STRING_RESULT;
4740 -+ max_length= MAX_BLOB_WIDTH;
4741 -+ }
4742 -+
4743 -+ if (error)
4744 -+ thd->fatal_error();
4745 -+
4746 -+ return;
4747 -+}
4748 -+
4749 -+
4750 -+bool Item_func_get_user_var::const_item() const
4751 -+{
4752 -+ return (!var_entry || current_thd->query_id != var_entry->update_query_id);
4753 -+}
4754 -+
4755 -+
4756 -+enum Item_result Item_func_get_user_var::result_type() const
4757 -+{
4758 -+ return m_cached_result_type;
4759 -+}
4760 -+
4761 -+
4762 -+void Item_func_get_user_var::print(String *str, enum_query_type query_type)
4763 -+{
4764 -+ str->append(STRING_WITH_LEN("(@"));
4765 -+ str->append(name.str,name.length);
4766 -+ str->append(')');
4767 -+}
4768 -+
4769 -+
4770 -+bool Item_func_get_user_var::eq(const Item *item, bool binary_cmp) const
4771 -+{
4772 -+ /* Assume we don't have rtti */
4773 -+ if (this == item)
4774 -+ return 1; // Same item is same.
4775 -+ /* Check if other type is also a get_user_var() object */
4776 -+ if (item->type() != FUNC_ITEM ||
4777 -+ ((Item_func*) item)->functype() != functype())
4778 -+ return 0;
4779 -+ Item_func_get_user_var *other=(Item_func_get_user_var*) item;
4780 -+ return (name.length == other->name.length &&
4781 -+ !memcmp(name.str, other->name.str, name.length));
4782 -+}
4783 -+
4784 -+
4785 -+bool Item_func_get_user_var::set_value(THD *thd,
4786 -+ sp_rcontext * /*ctx*/, Item **it)
4787 -+{
4788 -+ Item_func_set_user_var *suv= new Item_func_set_user_var(get_name(), *it);
4789 -+ /*
4790 -+ Item_func_set_user_var is not fixed after construction, call
4791 -+ fix_fields().
4792 -+ */
4793 -+ return (!suv || suv->fix_fields(thd, it) || suv->check(0) || suv->update());
4794 -+}
4795 -+
4796 -+
4797 -+bool Item_user_var_as_out_param::fix_fields(THD *thd, Item **ref)
4798 -+{
4799 -+ DBUG_ASSERT(fixed == 0);
4800 -+ DBUG_ASSERT(thd->lex->exchange);
4801 -+ if (Item::fix_fields(thd, ref) ||
4802 -+ !(entry= get_variable(&thd->user_vars, name, 1)))
4803 -+ return TRUE;
4804 -+ entry->type= STRING_RESULT;
4805 -+ /*
4806 -+ Let us set the same collation which is used for loading
4807 -+ of fields in LOAD DATA INFILE.
4808 -+ (Since Item_user_var_as_out_param is used only there).
4809 -+ */
4810 -+ entry->collation.set(thd->lex->exchange->cs ?
4811 -+ thd->lex->exchange->cs :
4812 -+ thd->variables.collation_database);
4813 -+ entry->update_query_id= thd->query_id;
4814 -+ return FALSE;
4815 -+}
4816 -+
4817 -+
4818 -+void Item_user_var_as_out_param::set_null_value(CHARSET_INFO* cs)
4819 -+{
4820 -+ if (::update_hash(entry, TRUE, 0, 0, STRING_RESULT, cs,
4821 -+ DERIVATION_IMPLICIT, 0 /* unsigned_arg */))
4822 -+ current_thd->fatal_error(); // Probably end of memory
4823 -+}
4824 -+
4825 -+
4826 -+void Item_user_var_as_out_param::set_value(const char *str, uint length,
4827 -+ CHARSET_INFO* cs)
4828 -+{
4829 -+ if (::update_hash(entry, FALSE, (void*)str, length, STRING_RESULT, cs,
4830 -+ DERIVATION_IMPLICIT, 0 /* unsigned_arg */))
4831 -+ current_thd->fatal_error(); // Probably end of memory
4832 -+}
4833 -+
4834 -+
4835 -+double Item_user_var_as_out_param::val_real()
4836 -+{
4837 -+ DBUG_ASSERT(0);
4838 -+ return 0.0;
4839 -+}
4840 -+
4841 -+
4842 -+longlong Item_user_var_as_out_param::val_int()
4843 -+{
4844 -+ DBUG_ASSERT(0);
4845 -+ return 0;
4846 -+}
4847 -+
4848 -+
4849 -+String* Item_user_var_as_out_param::val_str(String *str)
4850 -+{
4851 -+ DBUG_ASSERT(0);
4852 -+ return 0;
4853 -+}
4854 -+
4855 -+
4856 -+my_decimal* Item_user_var_as_out_param::val_decimal(my_decimal *decimal_buffer)
4857 -+{
4858 -+ DBUG_ASSERT(0);
4859 -+ return 0;
4860 -+}
4861 -+
4862 -+
4863 -+void Item_user_var_as_out_param::print(String *str, enum_query_type query_type)
4864 -+{
4865 -+ str->append('@');
4866 -+ str->append(name.str,name.length);
4867 -+}
4868 -+
4869 -+
4870 -+Item_func_get_system_var::
4871 -+Item_func_get_system_var(sys_var *var_arg, enum_var_type var_type_arg,
4872 -+ LEX_STRING *component_arg, const char *name_arg,
4873 -+ size_t name_len_arg)
4874 -+ :var(var_arg), var_type(var_type_arg), orig_var_type(var_type_arg),
4875 -+ component(*component_arg), cache_present(0)
4876 -+{
4877 -+ /* set_name() will allocate the name */
4878 -+ set_name(name_arg, (uint) name_len_arg, system_charset_info);
4879 -+}
4880 -+
4881 -+
4882 -+bool Item_func_get_system_var::is_written_to_binlog()
4883 -+{
4884 -+ return var->is_written_to_binlog(var_type);
4885 -+}
4886 -+
4887 -+
4888 -+void Item_func_get_system_var::update_null_value()
4889 -+{
4890 -+ THD *thd= current_thd;
4891 -+ int save_no_errors= thd->no_errors;
4892 -+ thd->no_errors= TRUE;
4893 -+ Item::update_null_value();
4894 -+ thd->no_errors= save_no_errors;
4895 -+}
4896 -+
4897 -+
4898 -+void Item_func_get_system_var::fix_length_and_dec()
4899 -+{
4900 -+ char *cptr;
4901 -+ maybe_null= TRUE;
4902 -+ max_length= 0;
4903 -+
4904 -+ if (var->check_type(var_type))
4905 -+ {
4906 -+ if (var_type != OPT_DEFAULT)
4907 -+ {
4908 -+ my_error(ER_INCORRECT_GLOBAL_LOCAL_VAR, MYF(0),
4909 -+ var->name, var_type == OPT_GLOBAL ? "SESSION" : "GLOBAL");
4910 -+ return;
4911 -+ }
4912 -+ /* As there was no local variable, return the global value */
4913 -+ var_type= OPT_GLOBAL;
4914 -+ }
4915 -+
4916 -+ switch (var->show_type())
4917 -+ {
4918 -+ case SHOW_LONG:
4919 -+ case SHOW_INT:
4920 -+ case SHOW_HA_ROWS:
4921 -+ unsigned_flag= TRUE;
4922 -+ max_length= MY_INT64_NUM_DECIMAL_DIGITS;
4923 -+ decimals=0;
4924 -+ break;
4925 -+ case SHOW_LONGLONG:
4926 -+ unsigned_flag= TRUE;
4927 -+ max_length= MY_INT64_NUM_DECIMAL_DIGITS;
4928 -+ decimals=0;
4929 -+ break;
4930 -+ case SHOW_CHAR:
4931 -+ case SHOW_CHAR_PTR:
4932 -+ pthread_mutex_lock(&LOCK_global_system_variables);
4933 -+ cptr= var->show_type() == SHOW_CHAR_PTR ?
4934 -+ *(char**) var->value_ptr(current_thd, var_type, &component) :
4935 -+ (char*) var->value_ptr(current_thd, var_type, &component);
4936 -+ if (cptr)
4937 -+ max_length= strlen(cptr) * system_charset_info->mbmaxlen;
4938 -+ pthread_mutex_unlock(&LOCK_global_system_variables);
4939 -+ collation.set(system_charset_info, DERIVATION_SYSCONST);
4940 -+ decimals=NOT_FIXED_DEC;
4941 -+ break;
4942 -+ case SHOW_BOOL:
4943 -+ case SHOW_MY_BOOL:
4944 -+ unsigned_flag= FALSE;
4945 -+ max_length= 1;
4946 -+ decimals=0;
4947 -+ break;
4948 -+ case SHOW_DOUBLE:
4949 -+ unsigned_flag= FALSE;
4950 -+ decimals= 6;
4951 -+ max_length= DBL_DIG + 6;
4952 -+ break;
4953 -+ default:
4954 -+ my_error(ER_VAR_CANT_BE_READ, MYF(0), var->name);
4955 -+ break;
4956 -+ }
4957 -+}
4958 -+
4959 -+
4960 -+void Item_func_get_system_var::print(String *str, enum_query_type query_type)
4961 -+{
4962 -+ str->append(name, name_length);
4963 -+}
4964 -+
4965 -+
4966 -+enum Item_result Item_func_get_system_var::result_type() const
4967 -+{
4968 -+ switch (var->show_type())
4969 -+ {
4970 -+ case SHOW_BOOL:
4971 -+ case SHOW_MY_BOOL:
4972 -+ case SHOW_INT:
4973 -+ case SHOW_LONG:
4974 -+ case SHOW_LONGLONG:
4975 -+ case SHOW_HA_ROWS:
4976 -+ return INT_RESULT;
4977 -+ case SHOW_CHAR:
4978 -+ case SHOW_CHAR_PTR:
4979 -+ return STRING_RESULT;
4980 -+ case SHOW_DOUBLE:
4981 -+ return REAL_RESULT;
4982 -+ default:
4983 -+ my_error(ER_VAR_CANT_BE_READ, MYF(0), var->name);
4984 -+ return STRING_RESULT; // keep the compiler happy
4985 -+ }
4986 -+}
4987 -+
4988 -+
4989 -+enum_field_types Item_func_get_system_var::field_type() const
4990 -+{
4991 -+ switch (var->show_type())
4992 -+ {
4993 -+ case SHOW_BOOL:
4994 -+ case SHOW_MY_BOOL:
4995 -+ case SHOW_INT:
4996 -+ case SHOW_LONG:
4997 -+ case SHOW_LONGLONG:
4998 -+ case SHOW_HA_ROWS:
4999 -+ return MYSQL_TYPE_LONGLONG;
5000 -+ case SHOW_CHAR:
5001 -+ case SHOW_CHAR_PTR:
5002 -+ return MYSQL_TYPE_VARCHAR;
5003 -+ case SHOW_DOUBLE:
5004 -+ return MYSQL_TYPE_DOUBLE;
5005 -+ default:
5006 -+ my_error(ER_VAR_CANT_BE_READ, MYF(0), var->name);
5007 -+ return MYSQL_TYPE_VARCHAR; // keep the compiler happy
5008 -+ }
5009 -+}
5010 -+
5011 -+
5012 -+/*
5013 -+ Uses var, var_type, component, cache_present, used_query_id, thd,
5014 -+ cached_llval, null_value, cached_null_value
5015 -+*/
5016 -+#define get_sys_var_safe(type) \
5017 -+do { \
5018 -+ type value; \
5019 -+ pthread_mutex_lock(&LOCK_global_system_variables); \
5020 -+ value= *(type*) var->value_ptr(thd, var_type, &component); \
5021 -+ pthread_mutex_unlock(&LOCK_global_system_variables); \
5022 -+ cache_present |= GET_SYS_VAR_CACHE_LONG; \
5023 -+ used_query_id= thd->query_id; \
5024 -+ cached_llval= null_value ? 0 : (longlong) value; \
5025 -+ cached_null_value= null_value; \
5026 -+ return cached_llval; \
5027 -+} while (0)
5028 -+
5029 -+
5030 -+longlong Item_func_get_system_var::val_int()
5031 -+{
5032 -+ THD *thd= current_thd;
5033 -+
5034 -+ if (cache_present && thd->query_id == used_query_id)
5035 -+ {
5036 -+ if (cache_present & GET_SYS_VAR_CACHE_LONG)
5037 -+ {
5038 -+ null_value= cached_null_value;
5039 -+ return cached_llval;
5040 -+ }
5041 -+ else if (cache_present & GET_SYS_VAR_CACHE_DOUBLE)
5042 -+ {
5043 -+ null_value= cached_null_value;
5044 -+ cached_llval= (longlong) cached_dval;
5045 -+ cache_present|= GET_SYS_VAR_CACHE_LONG;
5046 -+ return cached_llval;
5047 -+ }
5048 -+ else if (cache_present & GET_SYS_VAR_CACHE_STRING)
5049 -+ {
5050 -+ null_value= cached_null_value;
5051 -+ if (!null_value)
5052 -+ cached_llval= longlong_from_string_with_check (cached_strval.charset(),
5053 -+ cached_strval.c_ptr(),
5054 -+ cached_strval.c_ptr() +
5055 -+ cached_strval.length());
5056 -+ else
5057 -+ cached_llval= 0;
5058 -+ cache_present|= GET_SYS_VAR_CACHE_LONG;
5059 -+ return cached_llval;
5060 -+ }
5061 -+ }
5062 -+
5063 -+ switch (var->show_type())
5064 -+ {
5065 -+ case SHOW_INT: get_sys_var_safe (uint);
5066 -+ case SHOW_LONG: get_sys_var_safe (ulong);
5067 -+ case SHOW_LONGLONG: get_sys_var_safe (ulonglong);
5068 -+ case SHOW_HA_ROWS: get_sys_var_safe (ha_rows);
5069 -+ case SHOW_BOOL: get_sys_var_safe (bool);
5070 -+ case SHOW_MY_BOOL: get_sys_var_safe (my_bool);
5071 -+ case SHOW_DOUBLE:
5072 -+ {
5073 -+ double dval= val_real();
5074 -+
5075 -+ used_query_id= thd->query_id;
5076 -+ cached_llval= (longlong) dval;
5077 -+ cache_present|= GET_SYS_VAR_CACHE_LONG;
5078 -+ return cached_llval;
5079 -+ }
5080 -+ case SHOW_CHAR:
5081 -+ case SHOW_CHAR_PTR:
5082 -+ {
5083 -+ String *str_val= val_str(NULL);
5084 -+
5085 -+ if (str_val && str_val->length())
5086 -+ cached_llval= longlong_from_string_with_check (system_charset_info,
5087 -+ str_val->c_ptr(),
5088 -+ str_val->c_ptr() +
5089 -+ str_val->length());
5090 -+ else
5091 -+ {
5092 -+ null_value= TRUE;
5093 -+ cached_llval= 0;
5094 -+ }
5095 -+
5096 -+ cache_present|= GET_SYS_VAR_CACHE_LONG;
5097 -+ return cached_llval;
5098 -+ }
5099 -+
5100 -+ default:
5101 -+ my_error(ER_VAR_CANT_BE_READ, MYF(0), var->name);
5102 -+ return 0; // keep the compiler happy
5103 -+ }
5104 -+}
5105 -+
5106 -+
5107 -+String* Item_func_get_system_var::val_str(String* str)
5108 -+{
5109 -+ THD *thd= current_thd;
5110 -+
5111 -+ if (cache_present && thd->query_id == used_query_id)
5112 -+ {
5113 -+ if (cache_present & GET_SYS_VAR_CACHE_STRING)
5114 -+ {
5115 -+ null_value= cached_null_value;
5116 -+ return null_value ? NULL : &cached_strval;
5117 -+ }
5118 -+ else if (cache_present & GET_SYS_VAR_CACHE_LONG)
5119 -+ {
5120 -+ null_value= cached_null_value;
5121 -+ if (!null_value)
5122 -+ cached_strval.set (cached_llval, collation.collation);
5123 -+ cache_present|= GET_SYS_VAR_CACHE_STRING;
5124 -+ return null_value ? NULL : &cached_strval;
5125 -+ }
5126 -+ else if (cache_present & GET_SYS_VAR_CACHE_DOUBLE)
5127 -+ {
5128 -+ null_value= cached_null_value;
5129 -+ if (!null_value)
5130 -+ cached_strval.set_real (cached_dval, decimals, collation.collation);
5131 -+ cache_present|= GET_SYS_VAR_CACHE_STRING;
5132 -+ return null_value ? NULL : &cached_strval;
5133 -+ }
5134 -+ }
5135 -+
5136 -+ str= &cached_strval;
5137 -+ switch (var->show_type())
5138 -+ {
5139 -+ case SHOW_CHAR:
5140 -+ case SHOW_CHAR_PTR:
5141 -+ {
5142 -+ pthread_mutex_lock(&LOCK_global_system_variables);
5143 -+ char *cptr= var->show_type() == SHOW_CHAR_PTR ?
5144 -+ *(char**) var->value_ptr(thd, var_type, &component) :
5145 -+ (char*) var->value_ptr(thd, var_type, &component);
5146 -+ if (cptr)
5147 -+ {
5148 -+ if (str->copy(cptr, strlen(cptr), collation.collation))
5149 -+ {
5150 -+ null_value= TRUE;
5151 -+ str= NULL;
5152 -+ }
5153 -+ }
5154 -+ else
5155 -+ {
5156 -+ null_value= TRUE;
5157 -+ str= NULL;
5158 -+ }
5159 -+ pthread_mutex_unlock(&LOCK_global_system_variables);
5160 -+ break;
5161 -+ }
5162 -+
5163 -+ case SHOW_INT:
5164 -+ case SHOW_LONG:
5165 -+ case SHOW_LONGLONG:
5166 -+ case SHOW_HA_ROWS:
5167 -+ case SHOW_BOOL:
5168 -+ case SHOW_MY_BOOL:
5169 -+ str->set (val_int(), collation.collation);
5170 -+ break;
5171 -+ case SHOW_DOUBLE:
5172 -+ str->set_real (val_real(), decimals, collation.collation);
5173 -+ break;
5174 -+
5175 -+ default:
5176 -+ my_error(ER_VAR_CANT_BE_READ, MYF(0), var->name);
5177 -+ str= NULL;
5178 -+ break;
5179 -+ }
5180 -+
5181 -+ cache_present|= GET_SYS_VAR_CACHE_STRING;
5182 -+ used_query_id= thd->query_id;
5183 -+ cached_null_value= null_value;
5184 -+ return str;
5185 -+}
5186 -+
5187 -+
5188 -+double Item_func_get_system_var::val_real()
5189 -+{
5190 -+ THD *thd= current_thd;
5191 -+
5192 -+ if (cache_present && thd->query_id == used_query_id)
5193 -+ {
5194 -+ if (cache_present & GET_SYS_VAR_CACHE_DOUBLE)
5195 -+ {
5196 -+ null_value= cached_null_value;
5197 -+ return cached_dval;
5198 -+ }
5199 -+ else if (cache_present & GET_SYS_VAR_CACHE_LONG)
5200 -+ {
5201 -+ null_value= cached_null_value;
5202 -+ cached_dval= (double)cached_llval;
5203 -+ cache_present|= GET_SYS_VAR_CACHE_DOUBLE;
5204 -+ return cached_dval;
5205 -+ }
5206 -+ else if (cache_present & GET_SYS_VAR_CACHE_STRING)
5207 -+ {
5208 -+ null_value= cached_null_value;
5209 -+ if (!null_value)
5210 -+ cached_dval= double_from_string_with_check (cached_strval.charset(),
5211 -+ cached_strval.c_ptr(),
5212 -+ cached_strval.c_ptr() +
5213 -+ cached_strval.length());
5214 -+ else
5215 -+ cached_dval= 0;
5216 -+ cache_present|= GET_SYS_VAR_CACHE_DOUBLE;
5217 -+ return cached_dval;
5218 -+ }
5219 -+ }
5220 -+
5221 -+ switch (var->show_type())
5222 -+ {
5223 -+ case SHOW_DOUBLE:
5224 -+ pthread_mutex_lock(&LOCK_global_system_variables);
5225 -+ cached_dval= *(double*) var->value_ptr(thd, var_type, &component);
5226 -+ pthread_mutex_unlock(&LOCK_global_system_variables);
5227 -+ used_query_id= thd->query_id;
5228 -+ cached_null_value= null_value;
5229 -+ if (null_value)
5230 -+ cached_dval= 0;
5231 -+ cache_present|= GET_SYS_VAR_CACHE_DOUBLE;
5232 -+ return cached_dval;
5233 -+ case SHOW_CHAR:
5234 -+ case SHOW_CHAR_PTR:
5235 -+ {
5236 -+ char *cptr;
5237 -+
5238 -+ pthread_mutex_lock(&LOCK_global_system_variables);
5239 -+ cptr= var->show_type() == SHOW_CHAR ?
5240 -+ (char*) var->value_ptr(thd, var_type, &component) :
5241 -+ *(char**) var->value_ptr(thd, var_type, &component);
5242 -+ if (cptr)
5243 -+ cached_dval= double_from_string_with_check (system_charset_info,
5244 -+ cptr, cptr + strlen (cptr));
5245 -+ else
5246 -+ {
5247 -+ null_value= TRUE;
5248 -+ cached_dval= 0;
5249 -+ }
5250 -+ pthread_mutex_unlock(&LOCK_global_system_variables);
5251 -+ used_query_id= thd->query_id;
5252 -+ cached_null_value= null_value;
5253 -+ cache_present|= GET_SYS_VAR_CACHE_DOUBLE;
5254 -+ return cached_dval;
5255 -+ }
5256 -+ case SHOW_INT:
5257 -+ case SHOW_LONG:
5258 -+ case SHOW_LONGLONG:
5259 -+ case SHOW_HA_ROWS:
5260 -+ case SHOW_BOOL:
5261 -+ case SHOW_MY_BOOL:
5262 -+ cached_dval= (double) val_int();
5263 -+ cache_present|= GET_SYS_VAR_CACHE_DOUBLE;
5264 -+ used_query_id= thd->query_id;
5265 -+ cached_null_value= null_value;
5266 -+ return cached_dval;
5267 -+ default:
5268 -+ my_error(ER_VAR_CANT_BE_READ, MYF(0), var->name);
5269 -+ return 0;
5270 -+ }
5271 -+}
5272 -+
5273 -+
5274 -+bool Item_func_get_system_var::eq(const Item *item, bool binary_cmp) const
5275 -+{
5276 -+ /* Assume we don't have rtti */
5277 -+ if (this == item)
5278 -+ return 1; // Same item is same.
5279 -+ /* Check if other type is also a get_user_var() object */
5280 -+ if (item->type() != FUNC_ITEM ||
5281 -+ ((Item_func*) item)->functype() != functype())
5282 -+ return 0;
5283 -+ Item_func_get_system_var *other=(Item_func_get_system_var*) item;
5284 -+ return (var == other->var && var_type == other->var_type);
5285 -+}
5286 -+
5287 -+
5288 -+void Item_func_get_system_var::cleanup()
5289 -+{
5290 -+ Item_func::cleanup();
5291 -+ cache_present= 0;
5292 -+ var_type= orig_var_type;
5293 -+ cached_strval.free();
5294 -+}
5295 -+
5296 -+
5297 -+longlong Item_func_inet_aton::val_int()
5298 -+{
5299 -+ DBUG_ASSERT(fixed == 1);
5300 -+ uint byte_result = 0;
5301 -+ ulonglong result = 0; // We are ready for 64 bit addresses
5302 -+ const char *p,* end;
5303 -+ char c = '.'; // we mark c to indicate invalid IP in case length is 0
5304 -+ char buff[36];
5305 -+ int dot_count= 0;
5306 -+
5307 -+ String *s,tmp(buff,sizeof(buff),&my_charset_bin);
5308 -+ if (!(s = args[0]->val_str(&tmp))) // If null value
5309 -+ goto err;
5310 -+ null_value=0;
5311 -+
5312 -+ end= (p = s->ptr()) + s->length();
5313 -+ while (p < end)
5314 -+ {
5315 -+ c = *p++;
5316 -+ int digit = (int) (c - '0'); // Assume ascii
5317 -+ if (digit >= 0 && digit <= 9)
5318 -+ {
5319 -+ if ((byte_result = byte_result * 10 + digit) > 255)
5320 -+ goto err; // Wrong address
5321 -+ }
5322 -+ else if (c == '.')
5323 -+ {
5324 -+ dot_count++;
5325 -+ result= (result << 8) + (ulonglong) byte_result;
5326 -+ byte_result = 0;
5327 -+ }
5328 -+ else
5329 -+ goto err; // Invalid character
5330 -+ }
5331 -+ if (c != '.') // IP number can't end on '.'
5332 -+ {
5333 -+ /*
5334 -+ Handle short-forms addresses according to standard. Examples:
5335 -+ 127 -> 0.0.0.127
5336 -+ 127.1 -> 127.0.0.1
5337 -+ 127.2.1 -> 127.2.0.1
5338 -+ */
5339 -+ switch (dot_count) {
5340 -+ case 1: result<<= 8; /* Fall through */
5341 -+ case 2: result<<= 8; /* Fall through */
5342 -+ }
5343 -+ return (result << 8) + (ulonglong) byte_result;
5344 -+ }
5345 -+
5346 -+err:
5347 -+ null_value=1;
5348 -+ return 0;
5349 -+}
5350 -+
5351 -+
5352 -+void Item_func_match::init_search(bool no_order)
5353 -+{
5354 -+ DBUG_ENTER("Item_func_match::init_search");
5355 -+
5356 -+ /* Check if init_search() has been called before */
5357 -+ if (ft_handler)
5358 -+ {
5359 -+ /*
5360 -+ We should reset ft_handler as it is cleaned up
5361 -+ on destruction of FT_SELECT object
5362 -+ (necessary in case of re-execution of subquery).
5363 -+ TODO: FT_SELECT should not clean up ft_handler.
5364 -+ */
5365 -+ if (join_key)
5366 -+ table->file->ft_handler= ft_handler;
5367 -+ DBUG_VOID_RETURN;
5368 -+ }
5369 -+
5370 -+ if (key == NO_SUCH_KEY)
5371 -+ {
5372 -+ List<Item> fields;
5373 -+ fields.push_back(new Item_string(" ",1, cmp_collation.collation));
5374 -+ for (uint i=1; i < arg_count; i++)
5375 -+ fields.push_back(args[i]);
5376 -+ concat_ws=new Item_func_concat_ws(fields);
5377 -+ /*
5378 -+ Above function used only to get value and do not need fix_fields for it:
5379 -+ Item_string - basic constant
5380 -+ fields - fix_fields() was already called for this arguments
5381 -+ Item_func_concat_ws - do not need fix_fields() to produce value
5382 -+ */
5383 -+ concat_ws->quick_fix_field();
5384 -+ }
5385 -+
5386 -+ if (master)
5387 -+ {
5388 -+ join_key=master->join_key=join_key|master->join_key;
5389 -+ master->init_search(no_order);
5390 -+ ft_handler=master->ft_handler;
5391 -+ join_key=master->join_key;
5392 -+ DBUG_VOID_RETURN;
5393 -+ }
5394 -+
5395 -+ String *ft_tmp= 0;
5396 -+
5397 -+ // MATCH ... AGAINST (NULL) is meaningless, but possible
5398 -+ if (!(ft_tmp=key_item()->val_str(&value)))
5399 -+ {
5400 -+ ft_tmp= &value;
5401 -+ value.set("",0,cmp_collation.collation);
5402 -+ }
5403 -+
5404 -+ if (ft_tmp->charset() != cmp_collation.collation)
5405 -+ {
5406 -+ uint dummy_errors;
5407 -+ search_value.copy(ft_tmp->ptr(), ft_tmp->length(), ft_tmp->charset(),
5408 -+ cmp_collation.collation, &dummy_errors);
5409 -+ ft_tmp= &search_value;
5410 -+ }
5411 -+
5412 -+ if (join_key && !no_order)
5413 -+ flags|=FT_SORTED;
5414 -+ ft_handler=table->file->ft_init_ext(flags, key, ft_tmp);
5415 -+
5416 -+ if (join_key)
5417 -+ table->file->ft_handler=ft_handler;
5418 -+
5419 -+ DBUG_VOID_RETURN;
5420 -+}
5421 -+
5422 -+
5423 -+bool Item_func_match::fix_fields(THD *thd, Item **ref)
5424 -+{
5425 -+ DBUG_ASSERT(fixed == 0);
5426 -+ Item *UNINIT_VAR(item); // Safe as arg_count is > 1
5427 -+
5428 -+ maybe_null=1;
5429 -+ join_key=0;
5430 -+
5431 -+ /*
5432 -+ const_item is assumed in quite a bit of places, so it would be difficult
5433 -+ to remove; If it would ever to be removed, this should include
5434 -+ modifications to find_best and auto_close as complement to auto_init code
5435 -+ above.
5436 -+ */
5437 -+ if (Item_func::fix_fields(thd, ref) ||
5438 -+ !args[0]->const_during_execution())
5439 -+ {
5440 -+ my_error(ER_WRONG_ARGUMENTS,MYF(0),"AGAINST");
5441 -+ return TRUE;
5442 -+ }
5443 -+
5444 -+ const_item_cache=0;
5445 -+ for (uint i=1 ; i < arg_count ; i++)
5446 -+ {
5447 -+ item=args[i];
5448 -+ if (item->type() == Item::REF_ITEM)
5449 -+ args[i]= item= *((Item_ref *)item)->ref;
5450 -+ if (item->type() != Item::FIELD_ITEM)
5451 -+ {
5452 -+ my_error(ER_WRONG_ARGUMENTS, MYF(0), "AGAINST");
5453 -+ return TRUE;
5454 -+ }
5455 -+ }
5456 -+ /*
5457 -+ Check that all columns come from the same table.
5458 -+ We've already checked that columns in MATCH are fields so
5459 -+ PARAM_TABLE_BIT can only appear from AGAINST argument.
5460 -+ */
5461 -+ if ((used_tables_cache & ~PARAM_TABLE_BIT) != item->used_tables())
5462 -+ key=NO_SUCH_KEY;
5463 -+
5464 -+ if (key == NO_SUCH_KEY && !(flags & FT_BOOL))
5465 -+ {
5466 -+ my_error(ER_WRONG_ARGUMENTS,MYF(0),"MATCH");
5467 -+ return TRUE;
5468 -+ }
5469 -+ table=((Item_field *)item)->field->table;
5470 -+ if (!(table->file->ha_table_flags() & HA_CAN_FULLTEXT))
5471 -+ {
5472 -+ my_error(ER_TABLE_CANT_HANDLE_FT, MYF(0));
5473 -+ return 1;
5474 -+ }
5475 -+ table->fulltext_searched=1;
5476 -+ return agg_arg_collations_for_comparison(cmp_collation,
5477 -+ args+1, arg_count-1, 0);
5478 -+}
5479 -+
5480 -+bool Item_func_match::fix_index()
5481 -+{
5482 -+ Item_field *item;
5483 -+ uint ft_to_key[MAX_KEY], ft_cnt[MAX_KEY], fts=0, keynr;
5484 -+ uint max_cnt=0, mkeys=0, i;
5485 -+
5486 -+ if (key == NO_SUCH_KEY)
5487 -+ return 0;
5488 -+
5489 -+ if (!table)
5490 -+ goto err;
5491 -+
5492 -+ for (keynr=0 ; keynr < table->s->keys ; keynr++)
5493 -+ {
5494 -+ if ((table->key_info[keynr].flags & HA_FULLTEXT) &&
5495 -+ (flags & FT_BOOL ? table->keys_in_use_for_query.is_set(keynr) :
5496 -+ table->s->keys_in_use.is_set(keynr)))
5497 -+
5498 -+ {
5499 -+ ft_to_key[fts]=keynr;
5500 -+ ft_cnt[fts]=0;
5501 -+ fts++;
5502 -+ }
5503 -+ }
5504 -+
5505 -+ if (!fts)
5506 -+ goto err;
5507 -+
5508 -+ for (i=1; i < arg_count; i++)
5509 -+ {
5510 -+ item=(Item_field*)args[i];
5511 -+ for (keynr=0 ; keynr < fts ; keynr++)
5512 -+ {
5513 -+ KEY *ft_key=&table->key_info[ft_to_key[keynr]];
5514 -+ uint key_parts=ft_key->key_parts;
5515 -+
5516 -+ for (uint part=0 ; part < key_parts ; part++)
5517 -+ {
5518 -+ if (item->field->eq(ft_key->key_part[part].field))
5519 -+ ft_cnt[keynr]++;
5520 -+ }
5521 -+ }
5522 -+ }
5523 -+
5524 -+ for (keynr=0 ; keynr < fts ; keynr++)
5525 -+ {
5526 -+ if (ft_cnt[keynr] > max_cnt)
5527 -+ {
5528 -+ mkeys=0;
5529 -+ max_cnt=ft_cnt[mkeys]=ft_cnt[keynr];
5530 -+ ft_to_key[mkeys]=ft_to_key[keynr];
5531 -+ continue;
5532 -+ }
5533 -+ if (max_cnt && ft_cnt[keynr] == max_cnt)
5534 -+ {
5535 -+ mkeys++;
5536 -+ ft_cnt[mkeys]=ft_cnt[keynr];
5537 -+ ft_to_key[mkeys]=ft_to_key[keynr];
5538 -+ continue;
5539 -+ }
5540 -+ }
5541 -+
5542 -+ for (keynr=0 ; keynr <= mkeys ; keynr++)
5543 -+ {
5544 -+ // partial keys doesn't work
5545 -+ if (max_cnt < arg_count-1 ||
5546 -+ max_cnt < table->key_info[ft_to_key[keynr]].key_parts)
5547 -+ continue;
5548 -+
5549 -+ key=ft_to_key[keynr];
5550 -+
5551 -+ return 0;
5552 -+ }
5553 -+
5554 -+err:
5555 -+ if (flags & FT_BOOL)
5556 -+ {
5557 -+ key=NO_SUCH_KEY;
5558 -+ return 0;
5559 -+ }
5560 -+ my_message(ER_FT_MATCHING_KEY_NOT_FOUND,
5561 -+ ER(ER_FT_MATCHING_KEY_NOT_FOUND), MYF(0));
5562 -+ return 1;
5563 -+}
5564 -+
5565 -+
5566 -+bool Item_func_match::eq(const Item *item, bool binary_cmp) const
5567 -+{
5568 -+ if (item->type() != FUNC_ITEM ||
5569 -+ ((Item_func*)item)->functype() != FT_FUNC ||
5570 -+ flags != ((Item_func_match*)item)->flags)
5571 -+ return 0;
5572 -+
5573 -+ Item_func_match *ifm=(Item_func_match*) item;
5574 -+
5575 -+ if (key == ifm->key && table == ifm->table &&
5576 -+ key_item()->eq(ifm->key_item(), binary_cmp))
5577 -+ return 1;
5578 -+
5579 -+ return 0;
5580 -+}
5581 -+
5582 -+
5583 -+double Item_func_match::val_real()
5584 -+{
5585 -+ DBUG_ASSERT(fixed == 1);
5586 -+ DBUG_ENTER("Item_func_match::val");
5587 -+ if (ft_handler == NULL)
5588 -+ DBUG_RETURN(-1.0);
5589 -+
5590 -+ if (key != NO_SUCH_KEY && table->null_row) /* NULL row from an outer join */
5591 -+ DBUG_RETURN(0.0);
5592 -+
5593 -+ if (join_key)
5594 -+ {
5595 -+ if (table->file->ft_handler)
5596 -+ DBUG_RETURN(ft_handler->please->get_relevance(ft_handler));
5597 -+ join_key=0;
5598 -+ }
5599 -+
5600 -+ if (key == NO_SUCH_KEY)
5601 -+ {
5602 -+ String *a= concat_ws->val_str(&value);
5603 -+ if ((null_value= (a == 0)) || !a->length())
5604 -+ DBUG_RETURN(0);
5605 -+ DBUG_RETURN(ft_handler->please->find_relevance(ft_handler,
5606 -+ (uchar *)a->ptr(), a->length()));
5607 -+ }
5608 -+ DBUG_RETURN(ft_handler->please->find_relevance(ft_handler,
5609 -+ table->record[0], 0));
5610 -+}
5611 -+
5612 -+void Item_func_match::print(String *str, enum_query_type query_type)
5613 -+{
5614 -+ str->append(STRING_WITH_LEN("(match "));
5615 -+ print_args(str, 1, query_type);
5616 -+ str->append(STRING_WITH_LEN(" against ("));
5617 -+ args[0]->print(str, query_type);
5618 -+ if (flags & FT_BOOL)
5619 -+ str->append(STRING_WITH_LEN(" in boolean mode"));
5620 -+ else if (flags & FT_EXPAND)
5621 -+ str->append(STRING_WITH_LEN(" with query expansion"));
5622 -+ str->append(STRING_WITH_LEN("))"));
5623 -+}
5624 -+
5625 -+longlong Item_func_bit_xor::val_int()
5626 -+{
5627 -+ DBUG_ASSERT(fixed == 1);
5628 -+ ulonglong arg1= (ulonglong) args[0]->val_int();
5629 -+ ulonglong arg2= (ulonglong) args[1]->val_int();
5630 -+ if ((null_value= (args[0]->null_value || args[1]->null_value)))
5631 -+ return 0;
5632 -+ return (longlong) (arg1 ^ arg2);
5633 -+}
5634 -+
5635 -+
5636 -+/***************************************************************************
5637 -+ System variables
5638 -+****************************************************************************/
5639 -+
5640 -+/**
5641 -+ Return value of an system variable base[.name] as a constant item.
5642 -+
5643 -+ @param thd Thread handler
5644 -+ @param var_type global / session
5645 -+ @param name Name of base or system variable
5646 -+ @param component Component.
5647 -+
5648 -+ @note
5649 -+ If component.str = 0 then the variable name is in 'name'
5650 -+
5651 -+ @return
5652 -+ - 0 : error
5653 -+ - # : constant item
5654 -+*/
5655 -+
5656 -+
5657 -+Item *get_system_var(THD *thd, enum_var_type var_type, LEX_STRING name,
5658 -+ LEX_STRING component)
5659 -+{
5660 -+ sys_var *var;
5661 -+ LEX_STRING *base_name, *component_name;
5662 -+
5663 -+ if (component.str)
5664 -+ {
5665 -+ base_name= &component;
5666 -+ component_name= &name;
5667 -+ }
5668 -+ else
5669 -+ {
5670 -+ base_name= &name;
5671 -+ component_name= &component; // Empty string
5672 -+ }
5673 -+
5674 -+ if (!(var= find_sys_var(thd, base_name->str, base_name->length)))
5675 -+ return 0;
5676 -+ if (component.str)
5677 -+ {
5678 -+ if (!var->is_struct())
5679 -+ {
5680 -+ my_error(ER_VARIABLE_IS_NOT_STRUCT, MYF(0), base_name->str);
5681 -+ return 0;
5682 -+ }
5683 -+ }
5684 -+ thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
5685 -+
5686 -+ set_if_smaller(component_name->length, MAX_SYS_VAR_LENGTH);
5687 -+
5688 -+ return new Item_func_get_system_var(var, var_type, component_name,
5689 -+ NULL, 0);
5690 -+}
5691 -+
5692 -+
5693 -+/**
5694 -+ Check a user level lock.
5695 -+
5696 -+ Sets null_value=TRUE on error.
5697 -+
5698 -+ @retval
5699 -+ 1 Available
5700 -+ @retval
5701 -+ 0 Already taken, or error
5702 -+*/
5703 -+
5704 -+longlong Item_func_is_free_lock::val_int()
5705 -+{
5706 -+ DBUG_ASSERT(fixed == 1);
5707 -+ String *res=args[0]->val_str(&value);
5708 -+ User_level_lock *ull;
5709 -+
5710 -+ null_value=0;
5711 -+ if (!res || !res->length())
5712 -+ {
5713 -+ null_value=1;
5714 -+ return 0;
5715 -+ }
5716 -+
5717 -+ pthread_mutex_lock(&LOCK_user_locks);
5718 -+ ull= (User_level_lock *) hash_search(&hash_user_locks, (uchar*) res->ptr(),
5719 -+ (size_t) res->length());
5720 -+ pthread_mutex_unlock(&LOCK_user_locks);
5721 -+ if (!ull || !ull->locked)
5722 -+ return 1;
5723 -+ return 0;
5724 -+}
5725 -+
5726 -+longlong Item_func_is_used_lock::val_int()
5727 -+{
5728 -+ DBUG_ASSERT(fixed == 1);
5729 -+ String *res=args[0]->val_str(&value);
5730 -+ User_level_lock *ull;
5731 -+
5732 -+ null_value=1;
5733 -+ if (!res || !res->length())
5734 -+ return 0;
5735 -+
5736 -+ pthread_mutex_lock(&LOCK_user_locks);
5737 -+ ull= (User_level_lock *) hash_search(&hash_user_locks, (uchar*) res->ptr(),
5738 -+ (size_t) res->length());
5739 -+ pthread_mutex_unlock(&LOCK_user_locks);
5740 -+ if (!ull || !ull->locked)
5741 -+ return 0;
5742 -+
5743 -+ null_value=0;
5744 -+ return ull->thread_id;
5745 -+}
5746 -+
5747 -+
5748 -+longlong Item_func_row_count::val_int()
5749 -+{
5750 -+ DBUG_ASSERT(fixed == 1);
5751 -+ THD *thd= current_thd;
5752 -+
5753 -+ return thd->row_count_func;
5754 -+}
5755 -+
5756 -+
5757 -+
5758 -+
5759 -+Item_func_sp::Item_func_sp(Name_resolution_context *context_arg, sp_name *name)
5760 -+ :Item_func(), context(context_arg), m_name(name), m_sp(NULL), sp_result_field(NULL)
5761 -+{
5762 -+ maybe_null= 1;
5763 -+ m_name->init_qname(current_thd);
5764 -+ dummy_table= (TABLE*) sql_calloc(sizeof(TABLE)+ sizeof(TABLE_SHARE));
5765 -+ dummy_table->s= (TABLE_SHARE*) (dummy_table+1);
5766 -+}
5767 -+
5768 -+
5769 -+Item_func_sp::Item_func_sp(Name_resolution_context *context_arg,
5770 -+ sp_name *name, List<Item> &list)
5771 -+ :Item_func(list), context(context_arg), m_name(name), m_sp(NULL),sp_result_field(NULL)
5772 -+{
5773 -+ maybe_null= 1;
5774 -+ m_name->init_qname(current_thd);
5775 -+ dummy_table= (TABLE*) sql_calloc(sizeof(TABLE)+ sizeof(TABLE_SHARE));
5776 -+ dummy_table->s= (TABLE_SHARE*) (dummy_table+1);
5777 -+}
5778 -+
5779 -+
5780 -+void
5781 -+Item_func_sp::cleanup()
5782 -+{
5783 -+ if (sp_result_field)
5784 -+ {
5785 -+ delete sp_result_field;
5786 -+ sp_result_field= NULL;
5787 -+ }
5788 -+ m_sp= NULL;
5789 -+ dummy_table->alias= NULL;
5790 -+ Item_func::cleanup();
5791 -+}
5792 -+
5793 -+const char *
5794 -+Item_func_sp::func_name() const
5795 -+{
5796 -+ THD *thd= current_thd;
5797 -+ /* Calculate length to avoid reallocation of string for sure */
5798 -+ uint len= (((m_name->m_explicit_name ? m_name->m_db.length : 0) +
5799 -+ m_name->m_name.length)*2 + //characters*quoting
5800 -+ 2 + // ` and `
5801 -+ (m_name->m_explicit_name ?
5802 -+ 3 : 0) + // '`', '`' and '.' for the db
5803 -+ 1 + // end of string
5804 -+ ALIGN_SIZE(1)); // to avoid String reallocation
5805 -+ String qname((char *)alloc_root(thd->mem_root, len), len,
5806 -+ system_charset_info);
5807 -+
5808 -+ qname.length(0);
5809 -+ if (m_name->m_explicit_name)
5810 -+ {
5811 -+ append_identifier(thd, &qname, m_name->m_db.str, m_name->m_db.length);
5812 -+ qname.append('.');
5813 -+ }
5814 -+ append_identifier(thd, &qname, m_name->m_name.str, m_name->m_name.length);
5815 -+ return qname.ptr();
5816 -+}
5817 -+
5818 -+
5819 -+int my_missing_function_error(const LEX_STRING &token, const char *func_name)
5820 -+{
5821 -+ if (token.length && is_lex_native_function (&token))
5822 -+ return my_error(ER_FUNC_INEXISTENT_NAME_COLLISION, MYF(0), func_name);
5823 -+ else
5824 -+ return my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", func_name);
5825 -+}
5826 -+
5827 -+
5828 -+/**
5829 -+ @brief Initialize the result field by creating a temporary dummy table
5830 -+ and assign it to a newly created field object. Meta data used to
5831 -+ create the field is fetched from the sp_head belonging to the stored
5832 -+ proceedure found in the stored procedure functon cache.
5833 -+
5834 -+ @note This function should be called from fix_fields to init the result
5835 -+ field. It is some what related to Item_field.
5836 -+
5837 -+ @see Item_field
5838 -+
5839 -+ @param thd A pointer to the session and thread context.
5840 -+
5841 -+ @return Function return error status.
5842 -+ @retval TRUE is returned on an error
5843 -+ @retval FALSE is returned on success.
5844 -+*/
5845 -+
5846 -+bool
5847 -+Item_func_sp::init_result_field(THD *thd)
5848 -+{
5849 -+ LEX_STRING empty_name= { C_STRING_WITH_LEN("") };
5850 -+ TABLE_SHARE *share;
5851 -+ DBUG_ENTER("Item_func_sp::init_result_field");
5852 -+
5853 -+ DBUG_ASSERT(m_sp == NULL);
5854 -+ DBUG_ASSERT(sp_result_field == NULL);
5855 -+
5856 -+ if (!(m_sp= sp_find_routine(thd, TYPE_ENUM_FUNCTION, m_name,
5857 -+ &thd->sp_func_cache, TRUE)))
5858 -+ {
5859 -+ my_missing_function_error (m_name->m_name, m_name->m_qname.str);
5860 -+ context->process_error(thd);
5861 -+ DBUG_RETURN(TRUE);
5862 -+ }
5863 -+
5864 -+ /*
5865 -+ A Field need to be attached to a Table.
5866 -+ Below we "create" a dummy table by initializing
5867 -+ the needed pointers.
5868 -+ */
5869 -+
5870 -+ share= dummy_table->s;
5871 -+ dummy_table->alias = "";
5872 -+ dummy_table->maybe_null = maybe_null;
5873 -+ dummy_table->in_use= thd;
5874 -+ dummy_table->copy_blobs= TRUE;
5875 -+ share->table_cache_key = empty_name;
5876 -+ share->table_name = empty_name;
5877 -+
5878 -+ if (!(sp_result_field= m_sp->create_result_field(max_length, name,
5879 -+ dummy_table)))
5880 -+ {
5881 -+ DBUG_RETURN(TRUE);
5882 -+ }
5883 -+
5884 -+ if (sp_result_field->pack_length() > sizeof(result_buf))
5885 -+ {
5886 -+ void *tmp;
5887 -+ if (!(tmp= sql_alloc(sp_result_field->pack_length())))
5888 -+ DBUG_RETURN(TRUE);
5889 -+ sp_result_field->move_field((uchar*) tmp);
5890 -+ }
5891 -+ else
5892 -+ sp_result_field->move_field(result_buf);
5893 -+
5894 -+ sp_result_field->null_ptr= (uchar *) &null_value;
5895 -+ sp_result_field->null_bit= 1;
5896 -+ DBUG_RETURN(FALSE);
5897 -+}
5898 -+
5899 -+
5900 -+/**
5901 -+ @brief Initialize local members with values from the Field interface.
5902 -+
5903 -+ @note called from Item::fix_fields.
5904 -+*/
5905 -+
5906 -+void Item_func_sp::fix_length_and_dec()
5907 -+{
5908 -+ DBUG_ENTER("Item_func_sp::fix_length_and_dec");
5909 -+
5910 -+ DBUG_ASSERT(sp_result_field);
5911 -+ decimals= sp_result_field->decimals();
5912 -+ max_length= sp_result_field->field_length;
5913 -+ collation.set(sp_result_field->charset());
5914 -+ maybe_null= 1;
5915 -+ unsigned_flag= test(sp_result_field->flags & UNSIGNED_FLAG);
5916 -+
5917 -+ DBUG_VOID_RETURN;
5918 -+}
5919 -+
5920 -+
5921 -+/**
5922 -+ @brief Execute function & store value in field.
5923 -+
5924 -+ @return Function returns error status.
5925 -+ @retval FALSE on success.
5926 -+ @retval TRUE if an error occurred.
5927 -+*/
5928 -+
5929 -+bool
5930 -+Item_func_sp::execute()
5931 -+{
5932 -+ THD *thd= current_thd;
5933 -+
5934 -+ /* Execute function and store the return value in the field. */
5935 -+
5936 -+ if (execute_impl(thd))
5937 -+ {
5938 -+ null_value= 1;
5939 -+ context->process_error(thd);
5940 -+ if (thd->killed)
5941 -+ thd->send_kill_message();
5942 -+ return TRUE;
5943 -+ }
5944 -+
5945 -+ /* Check that the field (the value) is not NULL. */
5946 -+
5947 -+ null_value= sp_result_field->is_null();
5948 -+
5949 -+ return null_value;
5950 -+}
5951 -+
5952 -+
5953 -+/**
5954 -+ @brief Execute function and store the return value in the field.
5955 -+
5956 -+ @note This function was intended to be the concrete implementation of
5957 -+ the interface function execute. This was never realized.
5958 -+
5959 -+ @return The error state.
5960 -+ @retval FALSE on success
5961 -+ @retval TRUE if an error occurred.
5962 -+*/
5963 -+bool
5964 -+Item_func_sp::execute_impl(THD *thd)
5965 -+{
5966 -+ bool err_status= TRUE;
5967 -+ Sub_statement_state statement_state;
5968 -+#ifndef NO_EMBEDDED_ACCESS_CHECKS
5969 -+ Security_context *save_security_ctx= thd->security_ctx;
5970 -+#endif
5971 -+ enum enum_sp_data_access access=
5972 -+ (m_sp->m_chistics->daccess == SP_DEFAULT_ACCESS) ?
5973 -+ SP_DEFAULT_ACCESS_MAPPING : m_sp->m_chistics->daccess;
5974 -+
5975 -+ DBUG_ENTER("Item_func_sp::execute_impl");
5976 -+
5977 -+#ifndef NO_EMBEDDED_ACCESS_CHECKS
5978 -+ if (context->security_ctx)
5979 -+ {
5980 -+ /* Set view definer security context */
5981 -+ thd->security_ctx= context->security_ctx;
5982 -+ }
5983 -+#endif
5984 -+ if (sp_check_access(thd))
5985 -+ goto error;
5986 -+
5987 -+ /*
5988 -+ Throw an error if a non-deterministic function is called while
5989 -+ statement-based replication (SBR) is active.
5990 -+ */
5991 -+
5992 -+ if (!m_sp->m_chistics->detistic && !trust_function_creators &&
5993 -+ (access == SP_CONTAINS_SQL || access == SP_MODIFIES_SQL_DATA) &&
5994 -+ (mysql_bin_log.is_open() &&
5995 -+ thd->variables.binlog_format == BINLOG_FORMAT_STMT))
5996 -+ {
5997 -+ my_error(ER_BINLOG_UNSAFE_ROUTINE, MYF(0));
5998 -+ goto error;
5999 -+ }
6000 -+
6001 -+ /*
6002 -+ Disable the binlogging if this is not a SELECT statement. If this is a
6003 -+ SELECT, leave binlogging on, so execute_function() code writes the
6004 -+ function call into binlog.
6005 -+ */
6006 -+ thd->reset_sub_statement_state(&statement_state, SUB_STMT_FUNCTION);
6007 -+ err_status= m_sp->execute_function(thd, args, arg_count, sp_result_field);
6008 -+ thd->restore_sub_statement_state(&statement_state);
6009 -+
6010 -+error:
6011 -+#ifndef NO_EMBEDDED_ACCESS_CHECKS
6012 -+ thd->security_ctx= save_security_ctx;
6013 -+#endif
6014 -+
6015 -+ DBUG_RETURN(err_status);
6016 -+}
6017 -+
6018 -+
6019 -+void
6020 -+Item_func_sp::make_field(Send_field *tmp_field)
6021 -+{
6022 -+ DBUG_ENTER("Item_func_sp::make_field");
6023 -+ DBUG_ASSERT(sp_result_field);
6024 -+ sp_result_field->make_field(tmp_field);
6025 -+ if (name)
6026 -+ tmp_field->col_name= name;
6027 -+ DBUG_VOID_RETURN;
6028 -+}
6029 -+
6030 -+
6031 -+enum enum_field_types
6032 -+Item_func_sp::field_type() const
6033 -+{
6034 -+ DBUG_ENTER("Item_func_sp::field_type");
6035 -+ DBUG_ASSERT(sp_result_field);
6036 -+ DBUG_RETURN(sp_result_field->type());
6037 -+}
6038 -+
6039 -+Item_result
6040 -+Item_func_sp::result_type() const
6041 -+{
6042 -+ DBUG_ENTER("Item_func_sp::result_type");
6043 -+ DBUG_PRINT("info", ("m_sp = %p", (void *) m_sp));
6044 -+ DBUG_ASSERT(sp_result_field);
6045 -+ DBUG_RETURN(sp_result_field->result_type());
6046 -+}
6047 -+
6048 -+longlong Item_func_found_rows::val_int()
6049 -+{
6050 -+ DBUG_ASSERT(fixed == 1);
6051 -+ return current_thd->found_rows();
6052 -+}
6053 -+
6054 -+
6055 -+Field *
6056 -+Item_func_sp::tmp_table_field(TABLE *t_arg)
6057 -+{
6058 -+ DBUG_ENTER("Item_func_sp::tmp_table_field");
6059 -+
6060 -+ DBUG_ASSERT(sp_result_field);
6061 -+ DBUG_RETURN(sp_result_field);
6062 -+}
6063 -+
6064 -+
6065 -+/**
6066 -+ @brief Checks if requested access to function can be granted to user.
6067 -+ If function isn't found yet, it searches function first.
6068 -+ If function can't be found or user don't have requested access
6069 -+ error is raised.
6070 -+
6071 -+ @param thd thread handler
6072 -+
6073 -+ @return Indication if the access was granted or not.
6074 -+ @retval FALSE Access is granted.
6075 -+ @retval TRUE Requested access can't be granted or function doesn't exists.
6076 -+
6077 -+*/
6078 -+
6079 -+bool
6080 -+Item_func_sp::sp_check_access(THD *thd)
6081 -+{
6082 -+ DBUG_ENTER("Item_func_sp::sp_check_access");
6083 -+ DBUG_ASSERT(m_sp);
6084 -+#ifndef NO_EMBEDDED_ACCESS_CHECKS
6085 -+ if (check_routine_access(thd, EXECUTE_ACL,
6086 -+ m_sp->m_db.str, m_sp->m_name.str, 0, FALSE))
6087 -+ DBUG_RETURN(TRUE);
6088 -+#endif
6089 -+
6090 -+ DBUG_RETURN(FALSE);
6091 -+}
6092 -+
6093 -+
6094 -+bool
6095 -+Item_func_sp::fix_fields(THD *thd, Item **ref)
6096 -+{
6097 -+ bool res;
6098 -+ DBUG_ENTER("Item_func_sp::fix_fields");
6099 -+ DBUG_ASSERT(fixed == 0);
6100 -+
6101 -+ /*
6102 -+ We must call init_result_field before Item_func::fix_fields()
6103 -+ to make m_sp and result_field members available to fix_length_and_dec(),
6104 -+ which is called from Item_func::fix_fields().
6105 -+ */
6106 -+ res= init_result_field(thd);
6107 -+
6108 -+ if (res)
6109 -+ DBUG_RETURN(res);
6110 -+
6111 -+ res= Item_func::fix_fields(thd, ref);
6112 -+
6113 -+ if (res)
6114 -+ DBUG_RETURN(res);
6115 -+
6116 -+ if (thd->lex->context_analysis_only & CONTEXT_ANALYSIS_ONLY_VIEW)
6117 -+ {
6118 -+ /*
6119 -+ Here we check privileges of the stored routine only during view
6120 -+ creation, in order to validate the view. A runtime check is
6121 -+ perfomed in Item_func_sp::execute(), and this method is not
6122 -+ called during context analysis. Notice, that during view
6123 -+ creation we do not infer into stored routine bodies and do not
6124 -+ check privileges of its statements, which would probably be a
6125 -+ good idea especially if the view has SQL SECURITY DEFINER and
6126 -+ the used stored procedure has SQL SECURITY DEFINER.
6127 -+ */
6128 -+ res= sp_check_access(thd);
6129 -+#ifndef NO_EMBEDDED_ACCESS_CHECKS
6130 -+ /*
6131 -+ Try to set and restore the security context to see whether it's valid
6132 -+ */
6133 -+ Security_context *save_secutiry_ctx;
6134 -+ res= set_routine_security_ctx(thd, m_sp, false, &save_secutiry_ctx);
6135 -+ if (!res)
6136 -+ m_sp->m_security_ctx.restore_security_context(thd, save_secutiry_ctx);
6137 -+
6138 -+#endif /* ! NO_EMBEDDED_ACCESS_CHECKS */
6139 -+ }
6140 -+
6141 -+ if (!m_sp->m_chistics->detistic)
6142 -+ {
6143 -+ used_tables_cache |= RAND_TABLE_BIT;
6144 -+ const_item_cache= FALSE;
6145 -+ }
6146 -+
6147 -+ DBUG_RETURN(res);
6148 -+}
6149 -+
6150 -+
6151 -+void Item_func_sp::update_used_tables()
6152 -+{
6153 -+ Item_func::update_used_tables();
6154 -+
6155 -+ if (!m_sp->m_chistics->detistic)
6156 -+ {
6157 -+ used_tables_cache |= RAND_TABLE_BIT;
6158 -+ const_item_cache= FALSE;
6159 -+ }
6160 -+}
6161 -+
6162 -+
6163 -+/*
6164 -+ uuid_short handling.
6165 -+
6166 -+ The short uuid is defined as a longlong that contains the following bytes:
6167 -+
6168 -+ Bytes Comment
6169 -+ 1 Server_id & 255
6170 -+ 4 Startup time of server in seconds
6171 -+ 3 Incrementor
6172 -+
6173 -+ This means that an uuid is guaranteed to be unique
6174 -+ even in a replication environment if the following holds:
6175 -+
6176 -+ - The last byte of the server id is unique
6177 -+ - If you between two shutdown of the server don't get more than
6178 -+ an average of 2^24 = 16M calls to uuid_short() per second.
6179 -+*/
6180 -+
6181 -+ulonglong uuid_value;
6182 -+
6183 -+void uuid_short_init()
6184 -+{
6185 -+ uuid_value= ((((ulonglong) server_id) << 56) +
6186 -+ (((ulonglong) server_start_time) << 24));
6187 -+}
6188 -+
6189 -+
6190 -+longlong Item_func_uuid_short::val_int()
6191 -+{
6192 -+ ulonglong val;
6193 -+ pthread_mutex_lock(&LOCK_uuid_generator);
6194 -+ val= uuid_value++;
6195 -+ pthread_mutex_unlock(&LOCK_uuid_generator);
6196 -+ return (longlong) val;
6197 -+}
6198 diff -urN mysql-old/sql/item_func.h mysql/sql/item_func.h
6199 --- mysql-old/sql/item_func.h 2011-05-10 17:45:45.640015709 +0000
6200 +++ mysql/sql/item_func.h 2011-05-10 17:56:01.346682377 +0000
6201 @@ -7478,4540 +1320,6 @@ diff -urN mysql-old/sql/item_strfunc.cc mysql/sql/item_strfunc.cc
6202 tv-= delta;
6203 nanoseq-= delta;
6204 }
6205 -diff -urN mysql-old/sql/item_strfunc.cc.orig mysql/sql/item_strfunc.cc.orig
6206 ---- mysql-old/sql/item_strfunc.cc.orig 1969-12-31 23:00:00.000000000 -0100
6207 -+++ mysql/sql/item_strfunc.cc.orig 2011-04-12 12:11:38.000000000 +0000
6208 -@@ -0,0 +1,3643 @@
6209 -+/* Copyright (C) 2000-2006 MySQL AB
6210 -+
6211 -+ This program is free software; you can redistribute it and/or modify
6212 -+ it under the terms of the GNU General Public License as published by
6213 -+ the Free Software Foundation; version 2 of the License.
6214 -+
6215 -+ This program is distributed in the hope that it will be useful,
6216 -+ but WITHOUT ANY WARRANTY; without even the implied warranty of
6217 -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6218 -+ GNU General Public License for more details.
6219 -+
6220 -+ You should have received a copy of the GNU General Public License
6221 -+ along with this program; if not, write to the Free Software
6222 -+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
6223 -+
6224 -+
6225 -+/**
6226 -+ @file
6227 -+
6228 -+ @brief
6229 -+ This file defines all string functions
6230 -+
6231 -+ @warning
6232 -+ Some string functions don't always put and end-null on a String.
6233 -+ (This shouldn't be needed)
6234 -+*/
6235 -+
6236 -+#ifdef USE_PRAGMA_IMPLEMENTATION
6237 -+#pragma implementation // gcc: Class implementation
6238 -+#endif
6239 -+
6240 -+#include "mysql_priv.h"
6241 -+#include <m_ctype.h>
6242 -+#include "my_md5.h"
6243 -+#include "sha1.h"
6244 -+#include "my_aes.h"
6245 -+#include <zlib.h>
6246 -+C_MODE_START
6247 -+#include "../mysys/my_static.h" // For soundex_map
6248 -+C_MODE_END
6249 -+
6250 -+/**
6251 -+ @todo Remove this. It is not safe to use a shared String object.
6252 -+ */
6253 -+String my_empty_string("",default_charset_info);
6254 -+
6255 -+
6256 -+/*
6257 -+ Convert an array of bytes to a hexadecimal representation.
6258 -+
6259 -+ Used to generate a hexadecimal representation of a message digest.
6260 -+*/
6261 -+static void array_to_hex(char *to, const char *str, uint len)
6262 -+{
6263 -+ const char *str_end= str + len;
6264 -+ for (; str != str_end; ++str)
6265 -+ {
6266 -+ *to++= _dig_vec_lower[((uchar) *str) >> 4];
6267 -+ *to++= _dig_vec_lower[((uchar) *str) & 0x0F];
6268 -+ }
6269 -+}
6270 -+
6271 -+
6272 -+bool Item_str_func::fix_fields(THD *thd, Item **ref)
6273 -+{
6274 -+ bool res= Item_func::fix_fields(thd, ref);
6275 -+ /*
6276 -+ In Item_str_func::check_well_formed_result() we may set null_value
6277 -+ flag on the same condition as in test() below.
6278 -+ */
6279 -+ maybe_null= (maybe_null ||
6280 -+ test(thd->variables.sql_mode &
6281 -+ (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES)));
6282 -+ return res;
6283 -+}
6284 -+
6285 -+
6286 -+my_decimal *Item_str_func::val_decimal(my_decimal *decimal_value)
6287 -+{
6288 -+ DBUG_ASSERT(fixed == 1);
6289 -+ char buff[64];
6290 -+ String *res, tmp(buff,sizeof(buff), &my_charset_bin);
6291 -+ res= val_str(&tmp);
6292 -+ if (!res)
6293 -+ return 0;
6294 -+ (void)str2my_decimal(E_DEC_FATAL_ERROR, (char*) res->ptr(),
6295 -+ res->length(), res->charset(), decimal_value);
6296 -+ return decimal_value;
6297 -+}
6298 -+
6299 -+
6300 -+double Item_str_func::val_real()
6301 -+{
6302 -+ DBUG_ASSERT(fixed == 1);
6303 -+ int err_not_used;
6304 -+ char *end_not_used, buff[64];
6305 -+ String *res, tmp(buff,sizeof(buff), &my_charset_bin);
6306 -+ res= val_str(&tmp);
6307 -+ return res ? my_strntod(res->charset(), (char*) res->ptr(), res->length(),
6308 -+ &end_not_used, &err_not_used) : 0.0;
6309 -+}
6310 -+
6311 -+
6312 -+longlong Item_str_func::val_int()
6313 -+{
6314 -+ DBUG_ASSERT(fixed == 1);
6315 -+ int err;
6316 -+ char buff[22];
6317 -+ String *res, tmp(buff,sizeof(buff), &my_charset_bin);
6318 -+ res= val_str(&tmp);
6319 -+ return (res ?
6320 -+ my_strntoll(res->charset(), res->ptr(), res->length(), 10, NULL,
6321 -+ &err) :
6322 -+ (longlong) 0);
6323 -+}
6324 -+
6325 -+
6326 -+String *Item_func_md5::val_str(String *str)
6327 -+{
6328 -+ DBUG_ASSERT(fixed == 1);
6329 -+ String * sptr= args[0]->val_str(str);
6330 -+ str->set_charset(&my_charset_bin);
6331 -+ if (sptr)
6332 -+ {
6333 -+ uchar digest[16];
6334 -+
6335 -+ null_value=0;
6336 -+ MY_MD5_HASH(digest,(uchar *) sptr->ptr(), sptr->length());
6337 -+ if (str->alloc(32)) // Ensure that memory is free
6338 -+ {
6339 -+ null_value=1;
6340 -+ return 0;
6341 -+ }
6342 -+ array_to_hex((char *) str->ptr(), (const char*) digest, 16);
6343 -+ str->length((uint) 32);
6344 -+ return str;
6345 -+ }
6346 -+ null_value=1;
6347 -+ return 0;
6348 -+}
6349 -+
6350 -+
6351 -+void Item_func_md5::fix_length_and_dec()
6352 -+{
6353 -+ max_length=32;
6354 -+ /*
6355 -+ The MD5() function treats its parameter as being a case sensitive. Thus
6356 -+ we set binary collation on it so different instances of MD5() will be
6357 -+ compared properly.
6358 -+ */
6359 -+ args[0]->collation.set(
6360 -+ get_charset_by_csname(args[0]->collation.collation->csname,
6361 -+ MY_CS_BINSORT,MYF(0)), DERIVATION_COERCIBLE);
6362 -+}
6363 -+
6364 -+
6365 -+String *Item_func_sha::val_str(String *str)
6366 -+{
6367 -+ DBUG_ASSERT(fixed == 1);
6368 -+ String * sptr= args[0]->val_str(str);
6369 -+ str->set_charset(&my_charset_bin);
6370 -+ if (sptr) /* If we got value different from NULL */
6371 -+ {
6372 -+ SHA1_CONTEXT context; /* Context used to generate SHA1 hash */
6373 -+ /* Temporary buffer to store 160bit digest */
6374 -+ uint8 digest[SHA1_HASH_SIZE];
6375 -+ mysql_sha1_reset(&context); /* We do not have to check for error here */
6376 -+ /* No need to check error as the only case would be too long message */
6377 -+ mysql_sha1_input(&context,
6378 -+ (const uchar *) sptr->ptr(), sptr->length());
6379 -+ /* Ensure that memory is free and we got result */
6380 -+ if (!( str->alloc(SHA1_HASH_SIZE*2) ||
6381 -+ (mysql_sha1_result(&context,digest))))
6382 -+ {
6383 -+ array_to_hex((char *) str->ptr(), (const char*) digest, SHA1_HASH_SIZE);
6384 -+ str->length((uint) SHA1_HASH_SIZE*2);
6385 -+ null_value=0;
6386 -+ return str;
6387 -+ }
6388 -+ }
6389 -+ null_value=1;
6390 -+ return 0;
6391 -+}
6392 -+
6393 -+void Item_func_sha::fix_length_and_dec()
6394 -+{
6395 -+ max_length=SHA1_HASH_SIZE*2; // size of hex representation of hash
6396 -+ /*
6397 -+ The SHA() function treats its parameter as being a case sensitive. Thus
6398 -+ we set binary collation on it so different instances of MD5() will be
6399 -+ compared properly.
6400 -+ */
6401 -+ args[0]->collation.set(
6402 -+ get_charset_by_csname(args[0]->collation.collation->csname,
6403 -+ MY_CS_BINSORT,MYF(0)), DERIVATION_COERCIBLE);
6404 -+}
6405 -+
6406 -+
6407 -+/* Implementation of AES encryption routines */
6408 -+
6409 -+String *Item_func_aes_encrypt::val_str(String *str)
6410 -+{
6411 -+ DBUG_ASSERT(fixed == 1);
6412 -+ char key_buff[80];
6413 -+ String tmp_key_value(key_buff, sizeof(key_buff), system_charset_info);
6414 -+ String *sptr= args[0]->val_str(str); // String to encrypt
6415 -+ String *key= args[1]->val_str(&tmp_key_value); // key
6416 -+ int aes_length;
6417 -+ if (sptr && key) // we need both arguments to be not NULL
6418 -+ {
6419 -+ null_value=0;
6420 -+ aes_length=my_aes_get_size(sptr->length()); // Calculate result length
6421 -+
6422 -+ if (!str_value.alloc(aes_length)) // Ensure that memory is free
6423 -+ {
6424 -+ // finally encrypt directly to allocated buffer.
6425 -+ if (my_aes_encrypt(sptr->ptr(),sptr->length(), (char*) str_value.ptr(),
6426 -+ key->ptr(), key->length()) == aes_length)
6427 -+ {
6428 -+ // We got the expected result length
6429 -+ str_value.length((uint) aes_length);
6430 -+ return &str_value;
6431 -+ }
6432 -+ }
6433 -+ }
6434 -+ null_value=1;
6435 -+ return 0;
6436 -+}
6437 -+
6438 -+
6439 -+void Item_func_aes_encrypt::fix_length_and_dec()
6440 -+{
6441 -+ max_length=my_aes_get_size(args[0]->max_length);
6442 -+}
6443 -+
6444 -+
6445 -+String *Item_func_aes_decrypt::val_str(String *str)
6446 -+{
6447 -+ DBUG_ASSERT(fixed == 1);
6448 -+ char key_buff[80];
6449 -+ String tmp_key_value(key_buff, sizeof(key_buff), system_charset_info);
6450 -+ String *sptr, *key;
6451 -+ DBUG_ENTER("Item_func_aes_decrypt::val_str");
6452 -+
6453 -+ sptr= args[0]->val_str(str); // String to decrypt
6454 -+ key= args[1]->val_str(&tmp_key_value); // Key
6455 -+ if (sptr && key) // Need to have both arguments not NULL
6456 -+ {
6457 -+ null_value=0;
6458 -+ if (!str_value.alloc(sptr->length())) // Ensure that memory is free
6459 -+ {
6460 -+ // finally decrypt directly to allocated buffer.
6461 -+ int length;
6462 -+ length=my_aes_decrypt(sptr->ptr(), sptr->length(),
6463 -+ (char*) str_value.ptr(),
6464 -+ key->ptr(), key->length());
6465 -+ if (length >= 0) // if we got correct data data
6466 -+ {
6467 -+ str_value.length((uint) length);
6468 -+ DBUG_RETURN(&str_value);
6469 -+ }
6470 -+ }
6471 -+ }
6472 -+ // Bad parameters. No memory or bad data will all go here
6473 -+ null_value=1;
6474 -+ DBUG_RETURN(0);
6475 -+}
6476 -+
6477 -+
6478 -+void Item_func_aes_decrypt::fix_length_and_dec()
6479 -+{
6480 -+ max_length=args[0]->max_length;
6481 -+ maybe_null= 1;
6482 -+}
6483 -+
6484 -+
6485 -+/**
6486 -+ Concatenate args with the following premises:
6487 -+ If only one arg (which is ok), return value of arg;
6488 -+ Don't reallocate val_str() if not absolute necessary.
6489 -+*/
6490 -+
6491 -+String *Item_func_concat::val_str(String *str)
6492 -+{
6493 -+ DBUG_ASSERT(fixed == 1);
6494 -+ String *res,*res2,*use_as_buff;
6495 -+ uint i;
6496 -+ bool is_const= 0;
6497 -+
6498 -+ null_value=0;
6499 -+ if (!(res=args[0]->val_str(str)))
6500 -+ goto null;
6501 -+ use_as_buff= &tmp_value;
6502 -+ /* Item_subselect in --ps-protocol mode will state it as a non-const */
6503 -+ is_const= args[0]->const_item() || !args[0]->used_tables();
6504 -+ for (i=1 ; i < arg_count ; i++)
6505 -+ {
6506 -+ if (res->length() == 0)
6507 -+ {
6508 -+ if (!(res=args[i]->val_str(str)))
6509 -+ goto null;
6510 -+ /*
6511 -+ CONCAT accumulates its result in the result of its the first
6512 -+ non-empty argument. Because of this we need is_const to be
6513 -+ evaluated only for it.
6514 -+ */
6515 -+ is_const= args[i]->const_item() || !args[i]->used_tables();
6516 -+ }
6517 -+ else
6518 -+ {
6519 -+ if (!(res2=args[i]->val_str(use_as_buff)))
6520 -+ goto null;
6521 -+ if (res2->length() == 0)
6522 -+ continue;
6523 -+ if (res->length()+res2->length() >
6524 -+ current_thd->variables.max_allowed_packet)
6525 -+ {
6526 -+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
6527 -+ ER_WARN_ALLOWED_PACKET_OVERFLOWED,
6528 -+ ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED), func_name(),
6529 -+ current_thd->variables.max_allowed_packet);
6530 -+ goto null;
6531 -+ }
6532 -+ if (!is_const && res->alloced_length() >= res->length()+res2->length())
6533 -+ { // Use old buffer
6534 -+ res->append(*res2);
6535 -+ }
6536 -+ else if (str->alloced_length() >= res->length()+res2->length())
6537 -+ {
6538 -+ if (str->ptr() == res2->ptr())
6539 -+ str->replace(0,0,*res);
6540 -+ else
6541 -+ {
6542 -+ str->copy(*res);
6543 -+ str->append(*res2);
6544 -+ }
6545 -+ res= str;
6546 -+ use_as_buff= &tmp_value;
6547 -+ }
6548 -+ else if (res == &tmp_value)
6549 -+ {
6550 -+ if (res->append(*res2)) // Must be a blob
6551 -+ goto null;
6552 -+ }
6553 -+ else if (res2 == &tmp_value)
6554 -+ { // This can happend only 1 time
6555 -+ if (tmp_value.replace(0,0,*res))
6556 -+ goto null;
6557 -+ res= &tmp_value;
6558 -+ use_as_buff=str; // Put next arg here
6559 -+ }
6560 -+ else if (tmp_value.is_alloced() && res2->ptr() >= tmp_value.ptr() &&
6561 -+ res2->ptr() <= tmp_value.ptr() + tmp_value.alloced_length())
6562 -+ {
6563 -+ /*
6564 -+ This happens really seldom:
6565 -+ In this case res2 is sub string of tmp_value. We will
6566 -+ now work in place in tmp_value to set it to res | res2
6567 -+ */
6568 -+ /* Chop the last characters in tmp_value that isn't in res2 */
6569 -+ tmp_value.length((uint32) (res2->ptr() - tmp_value.ptr()) +
6570 -+ res2->length());
6571 -+ /* Place res2 at start of tmp_value, remove chars before res2 */
6572 -+ if (tmp_value.replace(0,(uint32) (res2->ptr() - tmp_value.ptr()),
6573 -+ *res))
6574 -+ goto null;
6575 -+ res= &tmp_value;
6576 -+ use_as_buff=str; // Put next arg here
6577 -+ }
6578 -+ else
6579 -+ { // Two big const strings
6580 -+ /*
6581 -+ NOTE: We should be prudent in the initial allocation unit -- the
6582 -+ size of the arguments is a function of data distribution, which
6583 -+ can be any. Instead of overcommitting at the first row, we grow
6584 -+ the allocated amount by the factor of 2. This ensures that no
6585 -+ more than 25% of memory will be overcommitted on average.
6586 -+ */
6587 -+
6588 -+ uint concat_len= res->length() + res2->length();
6589 -+
6590 -+ if (tmp_value.alloced_length() < concat_len)
6591 -+ {
6592 -+ if (tmp_value.alloced_length() == 0)
6593 -+ {
6594 -+ if (tmp_value.alloc(concat_len))
6595 -+ goto null;
6596 -+ }
6597 -+ else
6598 -+ {
6599 -+ uint new_len = max(tmp_value.alloced_length() * 2, concat_len);
6600 -+
6601 -+ if (tmp_value.realloc(new_len))
6602 -+ goto null;
6603 -+ }
6604 -+ }
6605 -+
6606 -+ if (tmp_value.copy(*res) || tmp_value.append(*res2))
6607 -+ goto null;
6608 -+
6609 -+ res= &tmp_value;
6610 -+ use_as_buff=str;
6611 -+ }
6612 -+ is_const= 0;
6613 -+ }
6614 -+ }
6615 -+ res->set_charset(collation.collation);
6616 -+ return res;
6617 -+
6618 -+null:
6619 -+ null_value=1;
6620 -+ return 0;
6621 -+}
6622 -+
6623 -+
6624 -+void Item_func_concat::fix_length_and_dec()
6625 -+{
6626 -+ ulonglong max_result_length= 0;
6627 -+
6628 -+ if (agg_arg_charsets(collation, args, arg_count, MY_COLL_ALLOW_CONV, 1))
6629 -+ return;
6630 -+
6631 -+ for (uint i=0 ; i < arg_count ; i++)
6632 -+ {
6633 -+ if (args[i]->collation.collation->mbmaxlen != collation.collation->mbmaxlen)
6634 -+ max_result_length+= (args[i]->max_length /
6635 -+ args[i]->collation.collation->mbmaxlen) *
6636 -+ collation.collation->mbmaxlen;
6637 -+ else
6638 -+ max_result_length+= args[i]->max_length;
6639 -+ }
6640 -+
6641 -+ if (max_result_length >= MAX_BLOB_WIDTH)
6642 -+ {
6643 -+ max_result_length= MAX_BLOB_WIDTH;
6644 -+ maybe_null= 1;
6645 -+ }
6646 -+ max_length= (ulong) max_result_length;
6647 -+}
6648 -+
6649 -+/**
6650 -+ @details
6651 -+ Function des_encrypt() by tonu@××××.ee & monty
6652 -+ Works only if compiled with OpenSSL library support.
6653 -+ @return
6654 -+ A binary string where first character is CHAR(128 | key-number).
6655 -+ If one uses a string key key_number is 127.
6656 -+ Encryption result is longer than original by formula:
6657 -+ @code new_length= org_length + (8-(org_length % 8))+1 @endcode
6658 -+*/
6659 -+
6660 -+String *Item_func_des_encrypt::val_str(String *str)
6661 -+{
6662 -+ DBUG_ASSERT(fixed == 1);
6663 -+#ifdef HAVE_OPENSSL
6664 -+ uint code= ER_WRONG_PARAMETERS_TO_PROCEDURE;
6665 -+ DES_cblock ivec;
6666 -+ struct st_des_keyblock keyblock;
6667 -+ struct st_des_keyschedule keyschedule;
6668 -+ const char *append_str="********";
6669 -+ uint key_number, res_length, tail;
6670 -+ String *res= args[0]->val_str(str);
6671 -+
6672 -+ if ((null_value= args[0]->null_value))
6673 -+ return 0; // ENCRYPT(NULL) == NULL
6674 -+ if ((res_length=res->length()) == 0)
6675 -+ return make_empty_result();
6676 -+
6677 -+ if (arg_count == 1)
6678 -+ {
6679 -+ /* Protect against someone doing FLUSH DES_KEY_FILE */
6680 -+ VOID(pthread_mutex_lock(&LOCK_des_key_file));
6681 -+ keyschedule= des_keyschedule[key_number=des_default_key];
6682 -+ VOID(pthread_mutex_unlock(&LOCK_des_key_file));
6683 -+ }
6684 -+ else if (args[1]->result_type() == INT_RESULT)
6685 -+ {
6686 -+ key_number= (uint) args[1]->val_int();
6687 -+ if (key_number > 9)
6688 -+ goto error;
6689 -+ VOID(pthread_mutex_lock(&LOCK_des_key_file));
6690 -+ keyschedule= des_keyschedule[key_number];
6691 -+ VOID(pthread_mutex_unlock(&LOCK_des_key_file));
6692 -+ }
6693 -+ else
6694 -+ {
6695 -+ String *keystr=args[1]->val_str(&tmp_value);
6696 -+ if (!keystr)
6697 -+ goto error;
6698 -+ key_number=127; // User key string
6699 -+
6700 -+ /* We make good 24-byte (168 bit) key from given plaintext key with MD5 */
6701 -+ bzero((char*) &ivec,sizeof(ivec));
6702 -+ EVP_BytesToKey(EVP_des_ede3_cbc(),EVP_md5(),NULL,
6703 -+ (uchar*) keystr->ptr(), (int) keystr->length(),
6704 -+ 1, (uchar*) &keyblock,ivec);
6705 -+ DES_set_key_unchecked(&keyblock.key1,&keyschedule.ks1);
6706 -+ DES_set_key_unchecked(&keyblock.key2,&keyschedule.ks2);
6707 -+ DES_set_key_unchecked(&keyblock.key3,&keyschedule.ks3);
6708 -+ }
6709 -+
6710 -+ /*
6711 -+ The problem: DES algorithm requires original data to be in 8-bytes
6712 -+ chunks. Missing bytes get filled with '*'s and result of encryption
6713 -+ can be up to 8 bytes longer than original string. When decrypted,
6714 -+ we do not know the size of original string :(
6715 -+ We add one byte with value 0x1..0x8 as the last byte of the padded
6716 -+ string marking change of string length.
6717 -+ */
6718 -+
6719 -+ tail= 8 - (res_length % 8); // 1..8 marking extra length
6720 -+ res_length+=tail;
6721 -+ tmp_arg.realloc(res_length);
6722 -+ tmp_arg.length(0);
6723 -+ tmp_arg.append(res->ptr(), res->length());
6724 -+ code= ER_OUT_OF_RESOURCES;
6725 -+ if (tmp_arg.append(append_str, tail) || tmp_value.alloc(res_length+1))
6726 -+ goto error;
6727 -+ tmp_arg[res_length-1]=tail; // save extra length
6728 -+ tmp_value.realloc(res_length+1);
6729 -+ tmp_value.length(res_length+1);
6730 -+ tmp_value.set_charset(&my_charset_bin);
6731 -+ tmp_value[0]=(char) (128 | key_number);
6732 -+ // Real encryption
6733 -+ bzero((char*) &ivec,sizeof(ivec));
6734 -+ DES_ede3_cbc_encrypt((const uchar*) (tmp_arg.ptr()),
6735 -+ (uchar*) (tmp_value.ptr()+1),
6736 -+ res_length,
6737 -+ &keyschedule.ks1,
6738 -+ &keyschedule.ks2,
6739 -+ &keyschedule.ks3,
6740 -+ &ivec, TRUE);
6741 -+ return &tmp_value;
6742 -+
6743 -+error:
6744 -+ push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_ERROR,
6745 -+ code, ER(code),
6746 -+ "des_encrypt");
6747 -+#else
6748 -+ push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_ERROR,
6749 -+ ER_FEATURE_DISABLED, ER(ER_FEATURE_DISABLED),
6750 -+ "des_encrypt","--with-openssl");
6751 -+#endif /* HAVE_OPENSSL */
6752 -+ null_value=1;
6753 -+ return 0;
6754 -+}
6755 -+
6756 -+
6757 -+String *Item_func_des_decrypt::val_str(String *str)
6758 -+{
6759 -+ DBUG_ASSERT(fixed == 1);
6760 -+#ifdef HAVE_OPENSSL
6761 -+ uint code= ER_WRONG_PARAMETERS_TO_PROCEDURE;
6762 -+ DES_cblock ivec;
6763 -+ struct st_des_keyblock keyblock;
6764 -+ struct st_des_keyschedule keyschedule;
6765 -+ String *res= args[0]->val_str(str);
6766 -+ uint length,tail;
6767 -+
6768 -+ if ((null_value= args[0]->null_value))
6769 -+ return 0;
6770 -+ length= res->length();
6771 -+ if (length < 9 || (length % 8) != 1 || !((*res)[0] & 128))
6772 -+ return res; // Skip decryption if not encrypted
6773 -+
6774 -+ if (arg_count == 1) // If automatic uncompression
6775 -+ {
6776 -+ uint key_number=(uint) (*res)[0] & 127;
6777 -+ // Check if automatic key and that we have privilege to uncompress using it
6778 -+ if (!(current_thd->security_ctx->master_access & SUPER_ACL) ||
6779 -+ key_number > 9)
6780 -+ goto error;
6781 -+
6782 -+ VOID(pthread_mutex_lock(&LOCK_des_key_file));
6783 -+ keyschedule= des_keyschedule[key_number];
6784 -+ VOID(pthread_mutex_unlock(&LOCK_des_key_file));
6785 -+ }
6786 -+ else
6787 -+ {
6788 -+ // We make good 24-byte (168 bit) key from given plaintext key with MD5
6789 -+ String *keystr=args[1]->val_str(&tmp_value);
6790 -+ if (!keystr)
6791 -+ goto error;
6792 -+
6793 -+ bzero((char*) &ivec,sizeof(ivec));
6794 -+ EVP_BytesToKey(EVP_des_ede3_cbc(),EVP_md5(),NULL,
6795 -+ (uchar*) keystr->ptr(),(int) keystr->length(),
6796 -+ 1,(uchar*) &keyblock,ivec);
6797 -+ // Here we set all 64-bit keys (56 effective) one by one
6798 -+ DES_set_key_unchecked(&keyblock.key1,&keyschedule.ks1);
6799 -+ DES_set_key_unchecked(&keyblock.key2,&keyschedule.ks2);
6800 -+ DES_set_key_unchecked(&keyblock.key3,&keyschedule.ks3);
6801 -+ }
6802 -+ code= ER_OUT_OF_RESOURCES;
6803 -+ if (tmp_value.alloc(length-1))
6804 -+ goto error;
6805 -+
6806 -+ bzero((char*) &ivec,sizeof(ivec));
6807 -+ DES_ede3_cbc_encrypt((const uchar*) res->ptr()+1,
6808 -+ (uchar*) (tmp_value.ptr()),
6809 -+ length-1,
6810 -+ &keyschedule.ks1,
6811 -+ &keyschedule.ks2,
6812 -+ &keyschedule.ks3,
6813 -+ &ivec, FALSE);
6814 -+ /* Restore old length of key */
6815 -+ if ((tail=(uint) (uchar) tmp_value[length-2]) > 8)
6816 -+ goto wrong_key; // Wrong key
6817 -+ tmp_value.length(length-1-tail);
6818 -+ tmp_value.set_charset(&my_charset_bin);
6819 -+ return &tmp_value;
6820 -+
6821 -+error:
6822 -+ push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_ERROR,
6823 -+ code, ER(code),
6824 -+ "des_decrypt");
6825 -+wrong_key:
6826 -+#else
6827 -+ push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_ERROR,
6828 -+ ER_FEATURE_DISABLED, ER(ER_FEATURE_DISABLED),
6829 -+ "des_decrypt","--with-openssl");
6830 -+#endif /* HAVE_OPENSSL */
6831 -+ null_value=1;
6832 -+ return 0;
6833 -+}
6834 -+
6835 -+
6836 -+/**
6837 -+ concat with separator. First arg is the separator
6838 -+ concat_ws takes at least two arguments.
6839 -+*/
6840 -+
6841 -+String *Item_func_concat_ws::val_str(String *str)
6842 -+{
6843 -+ DBUG_ASSERT(fixed == 1);
6844 -+ char tmp_str_buff[10];
6845 -+ String tmp_sep_str(tmp_str_buff, sizeof(tmp_str_buff),default_charset_info),
6846 -+ *sep_str, *res, *res2,*use_as_buff;
6847 -+ uint i;
6848 -+ bool is_const= 0;
6849 -+
6850 -+ null_value=0;
6851 -+ if (!(sep_str= args[0]->val_str(&tmp_sep_str)))
6852 -+ goto null;
6853 -+
6854 -+ use_as_buff= &tmp_value;
6855 -+ str->length(0); // QQ; Should be removed
6856 -+ res=str;
6857 -+
6858 -+ // Skip until non-null argument is found.
6859 -+ // If not, return the empty string
6860 -+ for (i=1; i < arg_count; i++)
6861 -+ if ((res= args[i]->val_str(str)))
6862 -+ {
6863 -+ is_const= args[i]->const_item() || !args[i]->used_tables();
6864 -+ break;
6865 -+ }
6866 -+
6867 -+ if (i == arg_count)
6868 -+ return make_empty_result();
6869 -+
6870 -+ for (i++; i < arg_count ; i++)
6871 -+ {
6872 -+ if (!(res2= args[i]->val_str(use_as_buff)))
6873 -+ continue; // Skip NULL
6874 -+
6875 -+ if (res->length() + sep_str->length() + res2->length() >
6876 -+ current_thd->variables.max_allowed_packet)
6877 -+ {
6878 -+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
6879 -+ ER_WARN_ALLOWED_PACKET_OVERFLOWED,
6880 -+ ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED), func_name(),
6881 -+ current_thd->variables.max_allowed_packet);
6882 -+ goto null;
6883 -+ }
6884 -+ if (!is_const && res->alloced_length() >=
6885 -+ res->length() + sep_str->length() + res2->length())
6886 -+ { // Use old buffer
6887 -+ res->append(*sep_str); // res->length() > 0 always
6888 -+ res->append(*res2);
6889 -+ }
6890 -+ else if (str->alloced_length() >=
6891 -+ res->length() + sep_str->length() + res2->length())
6892 -+ {
6893 -+ /* We have room in str; We can't get any errors here */
6894 -+ if (str->ptr() == res2->ptr())
6895 -+ { // This is quite uncommon!
6896 -+ str->replace(0,0,*sep_str);
6897 -+ str->replace(0,0,*res);
6898 -+ }
6899 -+ else
6900 -+ {
6901 -+ str->copy(*res);
6902 -+ str->append(*sep_str);
6903 -+ str->append(*res2);
6904 -+ }
6905 -+ res=str;
6906 -+ use_as_buff= &tmp_value;
6907 -+ }
6908 -+ else if (res == &tmp_value)
6909 -+ {
6910 -+ if (res->append(*sep_str) || res->append(*res2))
6911 -+ goto null; // Must be a blob
6912 -+ }
6913 -+ else if (res2 == &tmp_value)
6914 -+ { // This can happend only 1 time
6915 -+ if (tmp_value.replace(0,0,*sep_str) || tmp_value.replace(0,0,*res))
6916 -+ goto null;
6917 -+ res= &tmp_value;
6918 -+ use_as_buff=str; // Put next arg here
6919 -+ }
6920 -+ else if (tmp_value.is_alloced() && res2->ptr() >= tmp_value.ptr() &&
6921 -+ res2->ptr() < tmp_value.ptr() + tmp_value.alloced_length())
6922 -+ {
6923 -+ /*
6924 -+ This happens really seldom:
6925 -+ In this case res2 is sub string of tmp_value. We will
6926 -+ now work in place in tmp_value to set it to res | sep_str | res2
6927 -+ */
6928 -+ /* Chop the last characters in tmp_value that isn't in res2 */
6929 -+ tmp_value.length((uint32) (res2->ptr() - tmp_value.ptr()) +
6930 -+ res2->length());
6931 -+ /* Place res2 at start of tmp_value, remove chars before res2 */
6932 -+ if (tmp_value.replace(0,(uint32) (res2->ptr() - tmp_value.ptr()),
6933 -+ *res) ||
6934 -+ tmp_value.replace(res->length(),0, *sep_str))
6935 -+ goto null;
6936 -+ res= &tmp_value;
6937 -+ use_as_buff=str; // Put next arg here
6938 -+ }
6939 -+ else
6940 -+ { // Two big const strings
6941 -+ /*
6942 -+ NOTE: We should be prudent in the initial allocation unit -- the
6943 -+ size of the arguments is a function of data distribution, which can
6944 -+ be any. Instead of overcommitting at the first row, we grow the
6945 -+ allocated amount by the factor of 2. This ensures that no more than
6946 -+ 25% of memory will be overcommitted on average.
6947 -+ */
6948 -+
6949 -+ uint concat_len= res->length() + sep_str->length() + res2->length();
6950 -+
6951 -+ if (tmp_value.alloced_length() < concat_len)
6952 -+ {
6953 -+ if (tmp_value.alloced_length() == 0)
6954 -+ {
6955 -+ if (tmp_value.alloc(concat_len))
6956 -+ goto null;
6957 -+ }
6958 -+ else
6959 -+ {
6960 -+ uint new_len = max(tmp_value.alloced_length() * 2, concat_len);
6961 -+
6962 -+ if (tmp_value.realloc(new_len))
6963 -+ goto null;
6964 -+ }
6965 -+ }
6966 -+
6967 -+ if (tmp_value.copy(*res) ||
6968 -+ tmp_value.append(*sep_str) ||
6969 -+ tmp_value.append(*res2))
6970 -+ goto null;
6971 -+ res= &tmp_value;
6972 -+ use_as_buff=str;
6973 -+ }
6974 -+ }
6975 -+ res->set_charset(collation.collation);
6976 -+ return res;
6977 -+
6978 -+null:
6979 -+ null_value=1;
6980 -+ return 0;
6981 -+}
6982 -+
6983 -+
6984 -+void Item_func_concat_ws::fix_length_and_dec()
6985 -+{
6986 -+ ulonglong max_result_length;
6987 -+
6988 -+ if (agg_arg_charsets(collation, args, arg_count, MY_COLL_ALLOW_CONV, 1))
6989 -+ return;
6990 -+
6991 -+ /*
6992 -+ arg_count cannot be less than 2,
6993 -+ it is done on parser level in sql_yacc.yy
6994 -+ so, (arg_count - 2) is safe here.
6995 -+ */
6996 -+ max_result_length= (ulonglong) args[0]->max_length * (arg_count - 2);
6997 -+ for (uint i=1 ; i < arg_count ; i++)
6998 -+ max_result_length+=args[i]->max_length;
6999 -+
7000 -+ if (max_result_length >= MAX_BLOB_WIDTH)
7001 -+ {
7002 -+ max_result_length= MAX_BLOB_WIDTH;
7003 -+ maybe_null= 1;
7004 -+ }
7005 -+ max_length= (ulong) max_result_length;
7006 -+}
7007 -+
7008 -+
7009 -+String *Item_func_reverse::val_str(String *str)
7010 -+{
7011 -+ DBUG_ASSERT(fixed == 1);
7012 -+ String *res = args[0]->val_str(str);
7013 -+ char *ptr, *end, *tmp;
7014 -+
7015 -+ if ((null_value=args[0]->null_value))
7016 -+ return 0;
7017 -+ /* An empty string is a special case as the string pointer may be null */
7018 -+ if (!res->length())
7019 -+ return make_empty_result();
7020 -+ if (tmp_value.alloced_length() < res->length() &&
7021 -+ tmp_value.realloc(res->length()))
7022 -+ {
7023 -+ null_value= 1;
7024 -+ return 0;
7025 -+ }
7026 -+ tmp_value.length(res->length());
7027 -+ tmp_value.set_charset(res->charset());
7028 -+ ptr= (char *) res->ptr();
7029 -+ end= ptr + res->length();
7030 -+ tmp= (char *) tmp_value.ptr() + tmp_value.length();
7031 -+#ifdef USE_MB
7032 -+ if (use_mb(res->charset()))
7033 -+ {
7034 -+ register uint32 l;
7035 -+ while (ptr < end)
7036 -+ {
7037 -+ if ((l= my_ismbchar(res->charset(),ptr,end)))
7038 -+ {
7039 -+ tmp-= l;
7040 -+ memcpy(tmp,ptr,l);
7041 -+ ptr+= l;
7042 -+ }
7043 -+ else
7044 -+ *--tmp= *ptr++;
7045 -+ }
7046 -+ }
7047 -+ else
7048 -+#endif /* USE_MB */
7049 -+ {
7050 -+ while (ptr < end)
7051 -+ *--tmp= *ptr++;
7052 -+ }
7053 -+ return &tmp_value;
7054 -+}
7055 -+
7056 -+
7057 -+void Item_func_reverse::fix_length_and_dec()
7058 -+{
7059 -+ collation.set(args[0]->collation);
7060 -+ max_length = args[0]->max_length;
7061 -+}
7062 -+
7063 -+/**
7064 -+ Replace all occurences of string2 in string1 with string3.
7065 -+
7066 -+ Don't reallocate val_str() if not needed.
7067 -+
7068 -+ @todo
7069 -+ Fix that this works with binary strings when using USE_MB
7070 -+*/
7071 -+
7072 -+String *Item_func_replace::val_str(String *str)
7073 -+{
7074 -+ DBUG_ASSERT(fixed == 1);
7075 -+ String *res,*res2,*res3;
7076 -+ int offset;
7077 -+ uint from_length,to_length;
7078 -+ bool alloced=0;
7079 -+#ifdef USE_MB
7080 -+ const char *ptr,*end,*strend,*search,*search_end;
7081 -+ register uint32 l;
7082 -+ bool binary_cmp;
7083 -+#endif
7084 -+
7085 -+ null_value=0;
7086 -+ res=args[0]->val_str(str);
7087 -+ if (args[0]->null_value)
7088 -+ goto null;
7089 -+ res2=args[1]->val_str(&tmp_value);
7090 -+ if (args[1]->null_value)
7091 -+ goto null;
7092 -+
7093 -+ res->set_charset(collation.collation);
7094 -+
7095 -+#ifdef USE_MB
7096 -+ binary_cmp = ((res->charset()->state & MY_CS_BINSORT) || !use_mb(res->charset()));
7097 -+#endif
7098 -+
7099 -+ if (res2->length() == 0)
7100 -+ return res;
7101 -+#ifndef USE_MB
7102 -+ if ((offset=res->strstr(*res2)) < 0)
7103 -+ return res;
7104 -+#else
7105 -+ offset=0;
7106 -+ if (binary_cmp && (offset=res->strstr(*res2)) < 0)
7107 -+ return res;
7108 -+#endif
7109 -+ if (!(res3=args[2]->val_str(&tmp_value2)))
7110 -+ goto null;
7111 -+ from_length= res2->length();
7112 -+ to_length= res3->length();
7113 -+
7114 -+#ifdef USE_MB
7115 -+ if (!binary_cmp)
7116 -+ {
7117 -+ search=res2->ptr();
7118 -+ search_end=search+from_length;
7119 -+redo:
7120 -+ DBUG_ASSERT(res->ptr() || !offset);
7121 -+ ptr=res->ptr()+offset;
7122 -+ strend=res->ptr()+res->length();
7123 -+ /*
7124 -+ In some cases val_str() can return empty string
7125 -+ with ptr() == NULL and length() == 0.
7126 -+ Let's check strend to avoid overflow.
7127 -+ */
7128 -+ end= strend ? strend - from_length + 1 : NULL;
7129 -+ while (ptr < end)
7130 -+ {
7131 -+ if (*ptr == *search)
7132 -+ {
7133 -+ register char *i,*j;
7134 -+ i=(char*) ptr+1; j=(char*) search+1;
7135 -+ while (j != search_end)
7136 -+ if (*i++ != *j++) goto skip;
7137 -+ offset= (int) (ptr-res->ptr());
7138 -+ if (res->length()-from_length + to_length >
7139 -+ current_thd->variables.max_allowed_packet)
7140 -+ {
7141 -+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
7142 -+ ER_WARN_ALLOWED_PACKET_OVERFLOWED,
7143 -+ ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED),
7144 -+ func_name(),
7145 -+ current_thd->variables.max_allowed_packet);
7146 -+
7147 -+ goto null;
7148 -+ }
7149 -+ if (!alloced)
7150 -+ {
7151 -+ alloced=1;
7152 -+ res=copy_if_not_alloced(str,res,res->length()+to_length);
7153 -+ }
7154 -+ res->replace((uint) offset,from_length,*res3);
7155 -+ offset+=(int) to_length;
7156 -+ goto redo;
7157 -+ }
7158 -+skip:
7159 -+ if ((l=my_ismbchar(res->charset(), ptr,strend))) ptr+=l;
7160 -+ else ++ptr;
7161 -+ }
7162 -+ }
7163 -+ else
7164 -+#endif /* USE_MB */
7165 -+ do
7166 -+ {
7167 -+ if (res->length()-from_length + to_length >
7168 -+ current_thd->variables.max_allowed_packet)
7169 -+ {
7170 -+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
7171 -+ ER_WARN_ALLOWED_PACKET_OVERFLOWED,
7172 -+ ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED), func_name(),
7173 -+ current_thd->variables.max_allowed_packet);
7174 -+ goto null;
7175 -+ }
7176 -+ if (!alloced)
7177 -+ {
7178 -+ alloced=1;
7179 -+ res=copy_if_not_alloced(str,res,res->length()+to_length);
7180 -+ }
7181 -+ res->replace((uint) offset,from_length,*res3);
7182 -+ offset+=(int) to_length;
7183 -+ }
7184 -+ while ((offset=res->strstr(*res2,(uint) offset)) >= 0);
7185 -+ return res;
7186 -+
7187 -+null:
7188 -+ null_value=1;
7189 -+ return 0;
7190 -+}
7191 -+
7192 -+
7193 -+void Item_func_replace::fix_length_and_dec()
7194 -+{
7195 -+ ulonglong max_result_length= args[0]->max_length;
7196 -+ int diff=(int) (args[2]->max_length - args[1]->max_length);
7197 -+ if (diff > 0 && args[1]->max_length)
7198 -+ { // Calculate of maxreplaces
7199 -+ ulonglong max_substrs= max_result_length/args[1]->max_length;
7200 -+ max_result_length+= max_substrs * (uint) diff;
7201 -+ }
7202 -+ if (max_result_length >= MAX_BLOB_WIDTH)
7203 -+ {
7204 -+ max_result_length= MAX_BLOB_WIDTH;
7205 -+ maybe_null= 1;
7206 -+ }
7207 -+ max_length= (ulong) max_result_length;
7208 -+
7209 -+ if (agg_arg_charsets(collation, args, 3, MY_COLL_CMP_CONV, 1))
7210 -+ return;
7211 -+}
7212 -+
7213 -+
7214 -+String *Item_func_insert::val_str(String *str)
7215 -+{
7216 -+ DBUG_ASSERT(fixed == 1);
7217 -+ String *res,*res2;
7218 -+ longlong start, length; /* must be longlong to avoid truncation */
7219 -+
7220 -+ null_value=0;
7221 -+ res=args[0]->val_str(str);
7222 -+ res2=args[3]->val_str(&tmp_value);
7223 -+ start= args[1]->val_int() - 1;
7224 -+ length= args[2]->val_int();
7225 -+
7226 -+ if (args[0]->null_value || args[1]->null_value || args[2]->null_value ||
7227 -+ args[3]->null_value)
7228 -+ goto null; /* purecov: inspected */
7229 -+
7230 -+ if ((start < 0) || (start > res->length()))
7231 -+ return res; // Wrong param; skip insert
7232 -+ if ((length < 0) || (length > res->length()))
7233 -+ length= res->length();
7234 -+
7235 -+ /*
7236 -+ There is one exception not handled (intentionaly) by the character set
7237 -+ aggregation code. If one string is strong side and is binary, and
7238 -+ another one is weak side and is a multi-byte character string,
7239 -+ then we need to operate on the second string in terms on bytes when
7240 -+ calling ::numchars() and ::charpos(), rather than in terms of characters.
7241 -+ Lets substitute its character set to binary.
7242 -+ */
7243 -+ if (collation.collation == &my_charset_bin)
7244 -+ {
7245 -+ res->set_charset(&my_charset_bin);
7246 -+ res2->set_charset(&my_charset_bin);
7247 -+ }
7248 -+
7249 -+ /* start and length are now sufficiently valid to pass to charpos function */
7250 -+ start= res->charpos((int) start);
7251 -+ length= res->charpos((int) length, (uint32) start);
7252 -+
7253 -+ /* Re-testing with corrected params */
7254 -+ if (start > res->length())
7255 -+ return res; /* purecov: inspected */ // Wrong param; skip insert
7256 -+ if (length > res->length() - start)
7257 -+ length= res->length() - start;
7258 -+
7259 -+ if ((ulonglong) (res->length() - length + res2->length()) >
7260 -+ (ulonglong) current_thd->variables.max_allowed_packet)
7261 -+ {
7262 -+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
7263 -+ ER_WARN_ALLOWED_PACKET_OVERFLOWED,
7264 -+ ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED),
7265 -+ func_name(), current_thd->variables.max_allowed_packet);
7266 -+ goto null;
7267 -+ }
7268 -+ res=copy_if_not_alloced(str,res,res->length());
7269 -+ res->replace((uint32) start,(uint32) length,*res2);
7270 -+ return res;
7271 -+null:
7272 -+ null_value=1;
7273 -+ return 0;
7274 -+}
7275 -+
7276 -+
7277 -+void Item_func_insert::fix_length_and_dec()
7278 -+{
7279 -+ ulonglong max_result_length;
7280 -+
7281 -+ // Handle character set for args[0] and args[3].
7282 -+ if (agg_arg_charsets(collation, &args[0], 2, MY_COLL_ALLOW_CONV, 3))
7283 -+ return;
7284 -+ max_result_length= ((ulonglong) args[0]->max_length+
7285 -+ (ulonglong) args[3]->max_length);
7286 -+ if (max_result_length >= MAX_BLOB_WIDTH)
7287 -+ {
7288 -+ max_result_length= MAX_BLOB_WIDTH;
7289 -+ maybe_null= 1;
7290 -+ }
7291 -+ max_length= (ulong) max_result_length;
7292 -+}
7293 -+
7294 -+
7295 -+String *Item_str_conv::val_str(String *str)
7296 -+{
7297 -+ DBUG_ASSERT(fixed == 1);
7298 -+ String *res;
7299 -+ if (!(res=args[0]->val_str(str)))
7300 -+ {
7301 -+ null_value=1; /* purecov: inspected */
7302 -+ return 0; /* purecov: inspected */
7303 -+ }
7304 -+ null_value=0;
7305 -+ if (multiply == 1)
7306 -+ {
7307 -+ uint len;
7308 -+ res= copy_if_not_alloced(str,res,res->length());
7309 -+ len= converter(collation.collation, (char*) res->ptr(), res->length(),
7310 -+ (char*) res->ptr(), res->length());
7311 -+ DBUG_ASSERT(len <= res->length());
7312 -+ res->length(len);
7313 -+ }
7314 -+ else
7315 -+ {
7316 -+ uint len= res->length() * multiply;
7317 -+ tmp_value.alloc(len);
7318 -+ tmp_value.set_charset(collation.collation);
7319 -+ len= converter(collation.collation, (char*) res->ptr(), res->length(),
7320 -+ (char*) tmp_value.ptr(), len);
7321 -+ tmp_value.length(len);
7322 -+ res= &tmp_value;
7323 -+ }
7324 -+ return res;
7325 -+}
7326 -+
7327 -+
7328 -+void Item_func_lcase::fix_length_and_dec()
7329 -+{
7330 -+ collation.set(args[0]->collation);
7331 -+ multiply= collation.collation->casedn_multiply;
7332 -+ converter= collation.collation->cset->casedn;
7333 -+ max_length= args[0]->max_length * multiply;
7334 -+}
7335 -+
7336 -+void Item_func_ucase::fix_length_and_dec()
7337 -+{
7338 -+ collation.set(args[0]->collation);
7339 -+ multiply= collation.collation->caseup_multiply;
7340 -+ converter= collation.collation->cset->caseup;
7341 -+ max_length= args[0]->max_length * multiply;
7342 -+}
7343 -+
7344 -+
7345 -+String *Item_func_left::val_str(String *str)
7346 -+{
7347 -+ DBUG_ASSERT(fixed == 1);
7348 -+ String *res= args[0]->val_str(str);
7349 -+
7350 -+ /* must be longlong to avoid truncation */
7351 -+ longlong length= args[1]->val_int();
7352 -+ uint char_pos;
7353 -+
7354 -+ if ((null_value=(args[0]->null_value || args[1]->null_value)))
7355 -+ return 0;
7356 -+
7357 -+ /* if "unsigned_flag" is set, we have a *huge* positive number. */
7358 -+ if ((length <= 0) && (!args[1]->unsigned_flag))
7359 -+ return make_empty_result();
7360 -+ if ((res->length() <= (ulonglong) length) ||
7361 -+ (res->length() <= (char_pos= res->charpos((int) length))))
7362 -+ return res;
7363 -+
7364 -+ tmp_value.set(*res, 0, char_pos);
7365 -+ return &tmp_value;
7366 -+}
7367 -+
7368 -+
7369 -+void Item_str_func::left_right_max_length()
7370 -+{
7371 -+ max_length=args[0]->max_length;
7372 -+ if (args[1]->const_item())
7373 -+ {
7374 -+ int length=(int) args[1]->val_int()*collation.collation->mbmaxlen;
7375 -+ if (length <= 0)
7376 -+ max_length=0;
7377 -+ else
7378 -+ set_if_smaller(max_length,(uint) length);
7379 -+ }
7380 -+}
7381 -+
7382 -+
7383 -+void Item_func_left::fix_length_and_dec()
7384 -+{
7385 -+ collation.set(args[0]->collation);
7386 -+ left_right_max_length();
7387 -+}
7388 -+
7389 -+
7390 -+String *Item_func_right::val_str(String *str)
7391 -+{
7392 -+ DBUG_ASSERT(fixed == 1);
7393 -+ String *res= args[0]->val_str(str);
7394 -+ /* must be longlong to avoid truncation */
7395 -+ longlong length= args[1]->val_int();
7396 -+
7397 -+ if ((null_value=(args[0]->null_value || args[1]->null_value)))
7398 -+ return 0; /* purecov: inspected */
7399 -+
7400 -+ /* if "unsigned_flag" is set, we have a *huge* positive number. */
7401 -+ if ((length <= 0) && (!args[1]->unsigned_flag))
7402 -+ return make_empty_result(); /* purecov: inspected */
7403 -+
7404 -+ if (res->length() <= (ulonglong) length)
7405 -+ return res; /* purecov: inspected */
7406 -+
7407 -+ uint start=res->numchars();
7408 -+ if (start <= (uint) length)
7409 -+ return res;
7410 -+ start=res->charpos(start - (uint) length);
7411 -+ tmp_value.set(*res,start,res->length()-start);
7412 -+ return &tmp_value;
7413 -+}
7414 -+
7415 -+
7416 -+void Item_func_right::fix_length_and_dec()
7417 -+{
7418 -+ collation.set(args[0]->collation);
7419 -+ left_right_max_length();
7420 -+}
7421 -+
7422 -+
7423 -+String *Item_func_substr::val_str(String *str)
7424 -+{
7425 -+ DBUG_ASSERT(fixed == 1);
7426 -+ String *res = args[0]->val_str(str);
7427 -+ /* must be longlong to avoid truncation */
7428 -+ longlong start= args[1]->val_int();
7429 -+ /* Assumes that the maximum length of a String is < INT_MAX32. */
7430 -+ /* Limit so that code sees out-of-bound value properly. */
7431 -+ longlong length= arg_count == 3 ? args[2]->val_int() : INT_MAX32;
7432 -+ longlong tmp_length;
7433 -+
7434 -+ if ((null_value=(args[0]->null_value || args[1]->null_value ||
7435 -+ (arg_count == 3 && args[2]->null_value))))
7436 -+ return 0; /* purecov: inspected */
7437 -+
7438 -+ /* Negative or zero length, will return empty string. */
7439 -+ if ((arg_count == 3) && (length <= 0) &&
7440 -+ (length == 0 || !args[2]->unsigned_flag))
7441 -+ return make_empty_result();
7442 -+
7443 -+ /* Assumes that the maximum length of a String is < INT_MAX32. */
7444 -+ /* Set here so that rest of code sees out-of-bound value as such. */
7445 -+ if ((length <= 0) || (length > INT_MAX32))
7446 -+ length= INT_MAX32;
7447 -+
7448 -+ /* if "unsigned_flag" is set, we have a *huge* positive number. */
7449 -+ /* Assumes that the maximum length of a String is < INT_MAX32. */
7450 -+ if ((!args[1]->unsigned_flag && (start < INT_MIN32 || start > INT_MAX32)) ||
7451 -+ (args[1]->unsigned_flag && ((ulonglong) start > INT_MAX32)))
7452 -+ return make_empty_result();
7453 -+
7454 -+ start= ((start < 0) ? res->numchars() + start : start - 1);
7455 -+ start= res->charpos((int) start);
7456 -+ if ((start < 0) || ((uint) start + 1 > res->length()))
7457 -+ return make_empty_result();
7458 -+
7459 -+ length= res->charpos((int) length, (uint32) start);
7460 -+ tmp_length= res->length() - start;
7461 -+ length= min(length, tmp_length);
7462 -+
7463 -+ if (!start && (longlong) res->length() == length)
7464 -+ return res;
7465 -+ tmp_value.set(*res, (uint32) start, (uint32) length);
7466 -+ return &tmp_value;
7467 -+}
7468 -+
7469 -+
7470 -+void Item_func_substr::fix_length_and_dec()
7471 -+{
7472 -+ max_length=args[0]->max_length;
7473 -+
7474 -+ collation.set(args[0]->collation);
7475 -+ if (args[1]->const_item())
7476 -+ {
7477 -+ int32 start= (int32) args[1]->val_int();
7478 -+ if (start < 0)
7479 -+ max_length= ((uint)(-start) > max_length) ? 0 : (uint)(-start);
7480 -+ else
7481 -+ max_length-= min((uint)(start - 1), max_length);
7482 -+ }
7483 -+ if (arg_count == 3 && args[2]->const_item())
7484 -+ {
7485 -+ int32 length= (int32) args[2]->val_int();
7486 -+ if (length <= 0)
7487 -+ max_length=0; /* purecov: inspected */
7488 -+ else
7489 -+ set_if_smaller(max_length,(uint) length);
7490 -+ }
7491 -+ max_length*= collation.collation->mbmaxlen;
7492 -+}
7493 -+
7494 -+
7495 -+void Item_func_substr_index::fix_length_and_dec()
7496 -+{
7497 -+ max_length= args[0]->max_length;
7498 -+
7499 -+ if (agg_arg_charsets(collation, args, 2, MY_COLL_CMP_CONV, 1))
7500 -+ return;
7501 -+}
7502 -+
7503 -+
7504 -+String *Item_func_substr_index::val_str(String *str)
7505 -+{
7506 -+ DBUG_ASSERT(fixed == 1);
7507 -+ String *res= args[0]->val_str(str);
7508 -+ String *delimiter= args[1]->val_str(&tmp_value);
7509 -+ int32 count= (int32) args[2]->val_int();
7510 -+ uint offset;
7511 -+
7512 -+ if (args[0]->null_value || args[1]->null_value || args[2]->null_value)
7513 -+ { // string and/or delim are null
7514 -+ null_value=1;
7515 -+ return 0;
7516 -+ }
7517 -+ null_value=0;
7518 -+ uint delimiter_length= delimiter->length();
7519 -+ if (!res->length() || !delimiter_length || !count)
7520 -+ return make_empty_result(); // Wrong parameters
7521 -+
7522 -+ res->set_charset(collation.collation);
7523 -+
7524 -+#ifdef USE_MB
7525 -+ if (use_mb(res->charset()))
7526 -+ {
7527 -+ const char *ptr= res->ptr();
7528 -+ const char *strend= ptr+res->length();
7529 -+ const char *end= strend-delimiter_length+1;
7530 -+ const char *search= delimiter->ptr();
7531 -+ const char *search_end= search+delimiter_length;
7532 -+ int32 n=0,c=count,pass;
7533 -+ register uint32 l;
7534 -+ for (pass=(count>0);pass<2;++pass)
7535 -+ {
7536 -+ while (ptr < end)
7537 -+ {
7538 -+ if (*ptr == *search)
7539 -+ {
7540 -+ register char *i,*j;
7541 -+ i=(char*) ptr+1; j=(char*) search+1;
7542 -+ while (j != search_end)
7543 -+ if (*i++ != *j++) goto skip;
7544 -+ if (pass==0) ++n;
7545 -+ else if (!--c) break;
7546 -+ ptr+= delimiter_length;
7547 -+ continue;
7548 -+ }
7549 -+ skip:
7550 -+ if ((l=my_ismbchar(res->charset(), ptr,strend))) ptr+=l;
7551 -+ else ++ptr;
7552 -+ } /* either not found or got total number when count<0 */
7553 -+ if (pass == 0) /* count<0 */
7554 -+ {
7555 -+ c+=n+1;
7556 -+ if (c<=0) return res; /* not found, return original string */
7557 -+ ptr=res->ptr();
7558 -+ }
7559 -+ else
7560 -+ {
7561 -+ if (c) return res; /* Not found, return original string */
7562 -+ if (count>0) /* return left part */
7563 -+ {
7564 -+ tmp_value.set(*res,0,(ulong) (ptr-res->ptr()));
7565 -+ }
7566 -+ else /* return right part */
7567 -+ {
7568 -+ ptr+= delimiter_length;
7569 -+ tmp_value.set(*res,(ulong) (ptr-res->ptr()), (ulong) (strend-ptr));
7570 -+ }
7571 -+ }
7572 -+ }
7573 -+ }
7574 -+ else
7575 -+#endif /* USE_MB */
7576 -+ {
7577 -+ if (count > 0)
7578 -+ { // start counting from the beginning
7579 -+ for (offset=0; ; offset+= delimiter_length)
7580 -+ {
7581 -+ if ((int) (offset= res->strstr(*delimiter, offset)) < 0)
7582 -+ return res; // Didn't find, return org string
7583 -+ if (!--count)
7584 -+ {
7585 -+ tmp_value.set(*res,0,offset);
7586 -+ break;
7587 -+ }
7588 -+ }
7589 -+ }
7590 -+ else
7591 -+ {
7592 -+ /*
7593 -+ Negative index, start counting at the end
7594 -+ */
7595 -+ for (offset=res->length(); offset ;)
7596 -+ {
7597 -+ /*
7598 -+ this call will result in finding the position pointing to one
7599 -+ address space less than where the found substring is located
7600 -+ in res
7601 -+ */
7602 -+ if ((int) (offset= res->strrstr(*delimiter, offset)) < 0)
7603 -+ return res; // Didn't find, return org string
7604 -+ /*
7605 -+ At this point, we've searched for the substring
7606 -+ the number of times as supplied by the index value
7607 -+ */
7608 -+ if (!++count)
7609 -+ {
7610 -+ offset+= delimiter_length;
7611 -+ tmp_value.set(*res,offset,res->length()- offset);
7612 -+ break;
7613 -+ }
7614 -+ }
7615 -+ }
7616 -+ }
7617 -+ /*
7618 -+ We always mark tmp_value as const so that if val_str() is called again
7619 -+ on this object, we don't disrupt the contents of tmp_value when it was
7620 -+ derived from another String.
7621 -+ */
7622 -+ tmp_value.mark_as_const();
7623 -+ return (&tmp_value);
7624 -+}
7625 -+
7626 -+/*
7627 -+** The trim functions are extension to ANSI SQL because they trim substrings
7628 -+** They ltrim() and rtrim() functions are optimized for 1 byte strings
7629 -+** They also return the original string if possible, else they return
7630 -+** a substring that points at the original string.
7631 -+*/
7632 -+
7633 -+
7634 -+String *Item_func_ltrim::val_str(String *str)
7635 -+{
7636 -+ DBUG_ASSERT(fixed == 1);
7637 -+ char buff[MAX_FIELD_WIDTH], *ptr, *end;
7638 -+ String tmp(buff,sizeof(buff),system_charset_info);
7639 -+ String *res, *remove_str;
7640 -+ uint remove_length;
7641 -+ LINT_INIT(remove_length);
7642 -+
7643 -+ res= args[0]->val_str(str);
7644 -+ if ((null_value=args[0]->null_value))
7645 -+ return 0;
7646 -+ remove_str= &remove; /* Default value. */
7647 -+ if (arg_count == 2)
7648 -+ {
7649 -+ remove_str= args[1]->val_str(&tmp);
7650 -+ if ((null_value= args[1]->null_value))
7651 -+ return 0;
7652 -+ }
7653 -+
7654 -+ if ((remove_length= remove_str->length()) == 0 ||
7655 -+ remove_length > res->length())
7656 -+ return res;
7657 -+
7658 -+ ptr= (char*) res->ptr();
7659 -+ end= ptr+res->length();
7660 -+ if (remove_length == 1)
7661 -+ {
7662 -+ char chr=(*remove_str)[0];
7663 -+ while (ptr != end && *ptr == chr)
7664 -+ ptr++;
7665 -+ }
7666 -+ else
7667 -+ {
7668 -+ const char *r_ptr=remove_str->ptr();
7669 -+ end-=remove_length;
7670 -+ while (ptr <= end && !memcmp(ptr, r_ptr, remove_length))
7671 -+ ptr+=remove_length;
7672 -+ end+=remove_length;
7673 -+ }
7674 -+ if (ptr == res->ptr())
7675 -+ return res;
7676 -+ tmp_value.set(*res,(uint) (ptr - res->ptr()),(uint) (end-ptr));
7677 -+ return &tmp_value;
7678 -+}
7679 -+
7680 -+
7681 -+String *Item_func_rtrim::val_str(String *str)
7682 -+{
7683 -+ DBUG_ASSERT(fixed == 1);
7684 -+ char buff[MAX_FIELD_WIDTH], *ptr, *end;
7685 -+ String tmp(buff, sizeof(buff), system_charset_info);
7686 -+ String *res, *remove_str;
7687 -+ uint remove_length;
7688 -+ LINT_INIT(remove_length);
7689 -+
7690 -+ res= args[0]->val_str(str);
7691 -+ if ((null_value=args[0]->null_value))
7692 -+ return 0;
7693 -+ remove_str= &remove; /* Default value. */
7694 -+ if (arg_count == 2)
7695 -+ {
7696 -+ remove_str= args[1]->val_str(&tmp);
7697 -+ if ((null_value= args[1]->null_value))
7698 -+ return 0;
7699 -+ }
7700 -+
7701 -+ if ((remove_length= remove_str->length()) == 0 ||
7702 -+ remove_length > res->length())
7703 -+ return res;
7704 -+
7705 -+ ptr= (char*) res->ptr();
7706 -+ end= ptr+res->length();
7707 -+#ifdef USE_MB
7708 -+ char *p=ptr;
7709 -+ register uint32 l;
7710 -+#endif
7711 -+ if (remove_length == 1)
7712 -+ {
7713 -+ char chr=(*remove_str)[0];
7714 -+#ifdef USE_MB
7715 -+ if (use_mb(res->charset()))
7716 -+ {
7717 -+ while (ptr < end)
7718 -+ {
7719 -+ if ((l=my_ismbchar(res->charset(), ptr,end))) ptr+=l,p=ptr;
7720 -+ else ++ptr;
7721 -+ }
7722 -+ ptr=p;
7723 -+ }
7724 -+#endif
7725 -+ while (ptr != end && end[-1] == chr)
7726 -+ end--;
7727 -+ }
7728 -+ else
7729 -+ {
7730 -+ const char *r_ptr=remove_str->ptr();
7731 -+#ifdef USE_MB
7732 -+ if (use_mb(res->charset()))
7733 -+ {
7734 -+ loop:
7735 -+ while (ptr + remove_length < end)
7736 -+ {
7737 -+ if ((l=my_ismbchar(res->charset(), ptr,end))) ptr+=l;
7738 -+ else ++ptr;
7739 -+ }
7740 -+ if (ptr + remove_length == end && !memcmp(ptr,r_ptr,remove_length))
7741 -+ {
7742 -+ end-=remove_length;
7743 -+ ptr=p;
7744 -+ goto loop;
7745 -+ }
7746 -+ }
7747 -+ else
7748 -+#endif /* USE_MB */
7749 -+ {
7750 -+ while (ptr + remove_length <= end &&
7751 -+ !memcmp(end-remove_length, r_ptr, remove_length))
7752 -+ end-=remove_length;
7753 -+ }
7754 -+ }
7755 -+ if (end == res->ptr()+res->length())
7756 -+ return res;
7757 -+ tmp_value.set(*res,0,(uint) (end-res->ptr()));
7758 -+ return &tmp_value;
7759 -+}
7760 -+
7761 -+
7762 -+String *Item_func_trim::val_str(String *str)
7763 -+{
7764 -+ DBUG_ASSERT(fixed == 1);
7765 -+ char buff[MAX_FIELD_WIDTH], *ptr, *end;
7766 -+ const char *r_ptr;
7767 -+ String tmp(buff, sizeof(buff), system_charset_info);
7768 -+ String *res, *remove_str;
7769 -+ uint remove_length;
7770 -+ LINT_INIT(remove_length);
7771 -+
7772 -+ res= args[0]->val_str(str);
7773 -+ if ((null_value=args[0]->null_value))
7774 -+ return 0;
7775 -+ remove_str= &remove; /* Default value. */
7776 -+ if (arg_count == 2)
7777 -+ {
7778 -+ remove_str= args[1]->val_str(&tmp);
7779 -+ if ((null_value= args[1]->null_value))
7780 -+ return 0;
7781 -+ }
7782 -+
7783 -+ if ((remove_length= remove_str->length()) == 0 ||
7784 -+ remove_length > res->length())
7785 -+ return res;
7786 -+
7787 -+ ptr= (char*) res->ptr();
7788 -+ end= ptr+res->length();
7789 -+ r_ptr= remove_str->ptr();
7790 -+ while (ptr+remove_length <= end && !memcmp(ptr,r_ptr,remove_length))
7791 -+ ptr+=remove_length;
7792 -+#ifdef USE_MB
7793 -+ if (use_mb(res->charset()))
7794 -+ {
7795 -+ char *p=ptr;
7796 -+ register uint32 l;
7797 -+ loop:
7798 -+ while (ptr + remove_length < end)
7799 -+ {
7800 -+ if ((l=my_ismbchar(res->charset(), ptr,end))) ptr+=l;
7801 -+ else ++ptr;
7802 -+ }
7803 -+ if (ptr + remove_length == end && !memcmp(ptr,r_ptr,remove_length))
7804 -+ {
7805 -+ end-=remove_length;
7806 -+ ptr=p;
7807 -+ goto loop;
7808 -+ }
7809 -+ ptr=p;
7810 -+ }
7811 -+ else
7812 -+#endif /* USE_MB */
7813 -+ {
7814 -+ while (ptr + remove_length <= end &&
7815 -+ !memcmp(end-remove_length,r_ptr,remove_length))
7816 -+ end-=remove_length;
7817 -+ }
7818 -+ if (ptr == res->ptr() && end == ptr+res->length())
7819 -+ return res;
7820 -+ tmp_value.set(*res,(uint) (ptr - res->ptr()),(uint) (end-ptr));
7821 -+ return &tmp_value;
7822 -+}
7823 -+
7824 -+void Item_func_trim::fix_length_and_dec()
7825 -+{
7826 -+ max_length= args[0]->max_length;
7827 -+ if (arg_count == 1)
7828 -+ {
7829 -+ collation.set(args[0]->collation);
7830 -+ remove.set_charset(collation.collation);
7831 -+ remove.set_ascii(" ",1);
7832 -+ }
7833 -+ else
7834 -+ {
7835 -+ // Handle character set for args[1] and args[0].
7836 -+ // Note that we pass args[1] as the first item, and args[0] as the second.
7837 -+ if (agg_arg_charsets(collation, &args[1], 2, MY_COLL_CMP_CONV, -1))
7838 -+ return;
7839 -+ }
7840 -+}
7841 -+
7842 -+void Item_func_trim::print(String *str, enum_query_type query_type)
7843 -+{
7844 -+ if (arg_count == 1)
7845 -+ {
7846 -+ Item_func::print(str, query_type);
7847 -+ return;
7848 -+ }
7849 -+ str->append(Item_func_trim::func_name());
7850 -+ str->append('(');
7851 -+ str->append(mode_name());
7852 -+ str->append(' ');
7853 -+ args[1]->print(str, query_type);
7854 -+ str->append(STRING_WITH_LEN(" from "));
7855 -+ args[0]->print(str, query_type);
7856 -+ str->append(')');
7857 -+}
7858 -+
7859 -+
7860 -+/* Item_func_password */
7861 -+
7862 -+String *Item_func_password::val_str(String *str)
7863 -+{
7864 -+ DBUG_ASSERT(fixed == 1);
7865 -+ String *res= args[0]->val_str(str);
7866 -+ if ((null_value=args[0]->null_value))
7867 -+ return 0;
7868 -+ if (res->length() == 0)
7869 -+ return make_empty_result();
7870 -+ my_make_scrambled_password(tmp_value, res->ptr(), res->length());
7871 -+ str->set(tmp_value, SCRAMBLED_PASSWORD_CHAR_LENGTH, res->charset());
7872 -+ return str;
7873 -+}
7874 -+
7875 -+char *Item_func_password::alloc(THD *thd, const char *password,
7876 -+ size_t pass_len)
7877 -+{
7878 -+ char *buff= (char *) thd->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH+1);
7879 -+ if (buff)
7880 -+ my_make_scrambled_password(buff, password, pass_len);
7881 -+ return buff;
7882 -+}
7883 -+
7884 -+/* Item_func_old_password */
7885 -+
7886 -+String *Item_func_old_password::val_str(String *str)
7887 -+{
7888 -+ DBUG_ASSERT(fixed == 1);
7889 -+ String *res= args[0]->val_str(str);
7890 -+ if ((null_value=args[0]->null_value))
7891 -+ return 0;
7892 -+ if (res->length() == 0)
7893 -+ return make_empty_result();
7894 -+ my_make_scrambled_password_323(tmp_value, res->ptr(), res->length());
7895 -+ str->set(tmp_value, SCRAMBLED_PASSWORD_CHAR_LENGTH_323, res->charset());
7896 -+ return str;
7897 -+}
7898 -+
7899 -+char *Item_func_old_password::alloc(THD *thd, const char *password,
7900 -+ size_t pass_len)
7901 -+{
7902 -+ char *buff= (char *) thd->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH_323+1);
7903 -+ if (buff)
7904 -+ my_make_scrambled_password_323(buff, password, pass_len);
7905 -+ return buff;
7906 -+}
7907 -+
7908 -+
7909 -+#define bin_to_ascii(c) ((c)>=38?((c)-38+'a'):(c)>=12?((c)-12+'A'):(c)+'.')
7910 -+
7911 -+String *Item_func_encrypt::val_str(String *str)
7912 -+{
7913 -+ DBUG_ASSERT(fixed == 1);
7914 -+ String *res =args[0]->val_str(str);
7915 -+
7916 -+#ifdef HAVE_CRYPT
7917 -+ char salt[3],*salt_ptr;
7918 -+ if ((null_value=args[0]->null_value))
7919 -+ return 0;
7920 -+ if (res->length() == 0)
7921 -+ return make_empty_result();
7922 -+ if (arg_count == 1)
7923 -+ { // generate random salt
7924 -+ time_t timestamp=current_thd->query_start();
7925 -+ salt[0] = bin_to_ascii( (ulong) timestamp & 0x3f);
7926 -+ salt[1] = bin_to_ascii(( (ulong) timestamp >> 5) & 0x3f);
7927 -+ salt[2] = 0;
7928 -+ salt_ptr=salt;
7929 -+ }
7930 -+ else
7931 -+ { // obtain salt from the first two bytes
7932 -+ String *salt_str=args[1]->val_str(&tmp_value);
7933 -+ if ((null_value= (args[1]->null_value || salt_str->length() < 2)))
7934 -+ return 0;
7935 -+ salt_ptr= salt_str->c_ptr_safe();
7936 -+ }
7937 -+ pthread_mutex_lock(&LOCK_crypt);
7938 -+ char *tmp= crypt(res->c_ptr_safe(),salt_ptr);
7939 -+ if (!tmp)
7940 -+ {
7941 -+ pthread_mutex_unlock(&LOCK_crypt);
7942 -+ null_value= 1;
7943 -+ return 0;
7944 -+ }
7945 -+ str->set(tmp, (uint) strlen(tmp), &my_charset_bin);
7946 -+ str->copy();
7947 -+ pthread_mutex_unlock(&LOCK_crypt);
7948 -+ return str;
7949 -+#else
7950 -+ null_value=1;
7951 -+ return 0;
7952 -+#endif /* HAVE_CRYPT */
7953 -+}
7954 -+
7955 -+bool Item_func_encode::seed()
7956 -+{
7957 -+ char buf[80];
7958 -+ ulong rand_nr[2];
7959 -+ String *key, tmp(buf, sizeof(buf), system_charset_info);
7960 -+
7961 -+ if (!(key= args[1]->val_str(&tmp)))
7962 -+ return TRUE;
7963 -+
7964 -+ hash_password(rand_nr, key->ptr(), key->length());
7965 -+ sql_crypt.init(rand_nr);
7966 -+
7967 -+ return FALSE;
7968 -+}
7969 -+
7970 -+void Item_func_encode::fix_length_and_dec()
7971 -+{
7972 -+ max_length=args[0]->max_length;
7973 -+ maybe_null=args[0]->maybe_null || args[1]->maybe_null;
7974 -+ collation.set(&my_charset_bin);
7975 -+ /* Precompute the seed state if the item is constant. */
7976 -+ seeded= args[1]->const_item() &&
7977 -+ (args[1]->result_type() == STRING_RESULT) && !seed();
7978 -+}
7979 -+
7980 -+String *Item_func_encode::val_str(String *str)
7981 -+{
7982 -+ String *res;
7983 -+ DBUG_ASSERT(fixed == 1);
7984 -+
7985 -+ if (!(res=args[0]->val_str(str)))
7986 -+ {
7987 -+ null_value= 1;
7988 -+ return NULL;
7989 -+ }
7990 -+
7991 -+ if (!seeded && seed())
7992 -+ {
7993 -+ null_value= 1;
7994 -+ return NULL;
7995 -+ }
7996 -+
7997 -+ null_value= 0;
7998 -+ res= copy_if_not_alloced(str, res, res->length());
7999 -+ crypto_transform(res);
8000 -+ sql_crypt.reinit();
8001 -+
8002 -+ return res;
8003 -+}
8004 -+
8005 -+void Item_func_encode::crypto_transform(String *res)
8006 -+{
8007 -+ sql_crypt.encode((char*) res->ptr(),res->length());
8008 -+ res->set_charset(&my_charset_bin);
8009 -+}
8010 -+
8011 -+void Item_func_decode::crypto_transform(String *res)
8012 -+{
8013 -+ sql_crypt.decode((char*) res->ptr(),res->length());
8014 -+}
8015 -+
8016 -+
8017 -+Item *Item_func_sysconst::safe_charset_converter(CHARSET_INFO *tocs)
8018 -+{
8019 -+ Item_string *conv;
8020 -+ uint conv_errors;
8021 -+ String tmp, cstr, *ostr= val_str(&tmp);
8022 -+ if (null_value)
8023 -+ {
8024 -+ Item *null_item= new Item_null((char *) fully_qualified_func_name());
8025 -+ null_item->collation.set (tocs);
8026 -+ return null_item;
8027 -+ }
8028 -+ cstr.copy(ostr->ptr(), ostr->length(), ostr->charset(), tocs, &conv_errors);
8029 -+ if (conv_errors ||
8030 -+ !(conv= new Item_static_string_func(fully_qualified_func_name(),
8031 -+ cstr.ptr(), cstr.length(),
8032 -+ cstr.charset(),
8033 -+ collation.derivation)))
8034 -+ {
8035 -+ return NULL;
8036 -+ }
8037 -+ conv->str_value.copy();
8038 -+ conv->str_value.mark_as_const();
8039 -+ return conv;
8040 -+}
8041 -+
8042 -+
8043 -+String *Item_func_database::val_str(String *str)
8044 -+{
8045 -+ DBUG_ASSERT(fixed == 1);
8046 -+ THD *thd= current_thd;
8047 -+ if (thd->db == NULL)
8048 -+ {
8049 -+ null_value= 1;
8050 -+ return 0;
8051 -+ }
8052 -+ else
8053 -+ str->copy(thd->db, thd->db_length, system_charset_info);
8054 -+ return str;
8055 -+}
8056 -+
8057 -+
8058 -+/**
8059 -+ @note USER() is replicated correctly if binlog_format=ROW or (as of
8060 -+ BUG#28086) binlog_format=MIXED, but is incorrectly replicated to ''
8061 -+ if binlog_format=STATEMENT.
8062 -+*/
8063 -+bool Item_func_user::init(const char *user, const char *host)
8064 -+{
8065 -+ DBUG_ASSERT(fixed == 1);
8066 -+
8067 -+ // For system threads (e.g. replication SQL thread) user may be empty
8068 -+ if (user)
8069 -+ {
8070 -+ CHARSET_INFO *cs= str_value.charset();
8071 -+ size_t res_length= (strlen(user)+strlen(host)+2) * cs->mbmaxlen;
8072 -+
8073 -+ if (str_value.alloc((uint) res_length))
8074 -+ {
8075 -+ null_value=1;
8076 -+ return TRUE;
8077 -+ }
8078 -+
8079 -+ res_length=cs->cset->snprintf(cs, (char*)str_value.ptr(), (uint) res_length,
8080 -+ "%s@%s", user, host);
8081 -+ str_value.length((uint) res_length);
8082 -+ str_value.mark_as_const();
8083 -+ }
8084 -+ return FALSE;
8085 -+}
8086 -+
8087 -+
8088 -+bool Item_func_user::fix_fields(THD *thd, Item **ref)
8089 -+{
8090 -+ return (Item_func_sysconst::fix_fields(thd, ref) ||
8091 -+ init(thd->main_security_ctx.user,
8092 -+ thd->main_security_ctx.host_or_ip));
8093 -+}
8094 -+
8095 -+
8096 -+bool Item_func_current_user::fix_fields(THD *thd, Item **ref)
8097 -+{
8098 -+ if (Item_func_sysconst::fix_fields(thd, ref))
8099 -+ return TRUE;
8100 -+
8101 -+ Security_context *ctx=
8102 -+#ifndef NO_EMBEDDED_ACCESS_CHECKS
8103 -+ (context->security_ctx
8104 -+ ? context->security_ctx : thd->security_ctx);
8105 -+#else
8106 -+ thd->security_ctx;
8107 -+#endif /*NO_EMBEDDED_ACCESS_CHECKS*/
8108 -+ return init(ctx->priv_user, ctx->priv_host);
8109 -+}
8110 -+
8111 -+
8112 -+void Item_func_soundex::fix_length_and_dec()
8113 -+{
8114 -+ collation.set(args[0]->collation);
8115 -+ max_length=args[0]->max_length;
8116 -+ set_if_bigger(max_length, 4 * collation.collation->mbminlen);
8117 -+ tmp_value.set_charset(collation.collation);
8118 -+}
8119 -+
8120 -+
8121 -+/**
8122 -+ If alpha, map input letter to soundex code.
8123 -+ If not alpha and remove_garbage is set then skip to next char
8124 -+ else return 0
8125 -+*/
8126 -+
8127 -+static int soundex_toupper(int ch)
8128 -+{
8129 -+ return (ch >= 'a' && ch <= 'z') ? ch - 'a' + 'A' : ch;
8130 -+}
8131 -+
8132 -+
8133 -+static char get_scode(int wc)
8134 -+{
8135 -+ int ch= soundex_toupper(wc);
8136 -+ if (ch < 'A' || ch > 'Z')
8137 -+ {
8138 -+ // Thread extended alfa (country spec)
8139 -+ return '0'; // as vokal
8140 -+ }
8141 -+ return(soundex_map[ch-'A']);
8142 -+}
8143 -+
8144 -+
8145 -+static bool my_uni_isalpha(int wc)
8146 -+{
8147 -+ /*
8148 -+ Return true for all Basic Latin letters: a..z A..Z.
8149 -+ Return true for all Unicode characters with code higher than U+00C0:
8150 -+ - characters between 'z' and U+00C0 are controls and punctuations.
8151 -+ - "U+00C0 LATIN CAPITAL LETTER A WITH GRAVE" is the first letter after 'z'.
8152 -+ */
8153 -+ return (wc >= 'a' && wc <= 'z') ||
8154 -+ (wc >= 'A' && wc <= 'Z') ||
8155 -+ (wc >= 0xC0);
8156 -+}
8157 -+
8158 -+
8159 -+String *Item_func_soundex::val_str(String *str)
8160 -+{
8161 -+ DBUG_ASSERT(fixed == 1);
8162 -+ String *res =args[0]->val_str(str);
8163 -+ char last_ch,ch;
8164 -+ CHARSET_INFO *cs= collation.collation;
8165 -+ my_wc_t wc;
8166 -+ uint nchars;
8167 -+ int rc;
8168 -+
8169 -+ if ((null_value= args[0]->null_value))
8170 -+ return 0; /* purecov: inspected */
8171 -+
8172 -+ if (tmp_value.alloc(max(res->length(), 4 * cs->mbminlen)))
8173 -+ return str; /* purecov: inspected */
8174 -+ char *to= (char *) tmp_value.ptr();
8175 -+ char *to_end= to + tmp_value.alloced_length();
8176 -+ char *from= (char *) res->ptr(), *end= from + res->length();
8177 -+
8178 -+ for ( ; ; ) /* Skip pre-space */
8179 -+ {
8180 -+ if ((rc= cs->cset->mb_wc(cs, &wc, (uchar*) from, (uchar*) end)) <= 0)
8181 -+ return make_empty_result(); /* EOL or invalid byte sequence */
8182 -+
8183 -+ if (rc == 1 && cs->ctype)
8184 -+ {
8185 -+ /* Single byte letter found */
8186 -+ if (my_isalpha(cs, *from))
8187 -+ {
8188 -+ last_ch= get_scode(*from); // Code of the first letter
8189 -+ *to++= soundex_toupper(*from++); // Copy first letter
8190 -+ break;
8191 -+ }
8192 -+ from++;
8193 -+ }
8194 -+ else
8195 -+ {
8196 -+ from+= rc;
8197 -+ if (my_uni_isalpha(wc))
8198 -+ {
8199 -+ /* Multibyte letter found */
8200 -+ wc= soundex_toupper(wc);
8201 -+ last_ch= get_scode(wc); // Code of the first letter
8202 -+ if ((rc= cs->cset->wc_mb(cs, wc, (uchar*) to, (uchar*) to_end)) <= 0)
8203 -+ {
8204 -+ /* Extra safety - should not really happen */
8205 -+ DBUG_ASSERT(false);
8206 -+ return make_empty_result();
8207 -+ }
8208 -+ to+= rc;
8209 -+ break;
8210 -+ }
8211 -+ }
8212 -+ }
8213 -+
8214 -+ /*
8215 -+ last_ch is now set to the first 'double-letter' check.
8216 -+ loop on input letters until end of input
8217 -+ */
8218 -+ for (nchars= 1 ; ; )
8219 -+ {
8220 -+ if ((rc= cs->cset->mb_wc(cs, &wc, (uchar*) from, (uchar*) end)) <= 0)
8221 -+ break; /* EOL or invalid byte sequence */
8222 -+
8223 -+ if (rc == 1 && cs->ctype)
8224 -+ {
8225 -+ if (!my_isalpha(cs, *from++))
8226 -+ continue;
8227 -+ }
8228 -+ else
8229 -+ {
8230 -+ from+= rc;
8231 -+ if (!my_uni_isalpha(wc))
8232 -+ continue;
8233 -+ }
8234 -+
8235 -+ ch= get_scode(wc);
8236 -+ if ((ch != '0') && (ch != last_ch)) // if not skipped or double
8237 -+ {
8238 -+ // letter, copy to output
8239 -+ if ((rc= cs->cset->wc_mb(cs, (my_wc_t) ch,
8240 -+ (uchar*) to, (uchar*) to_end)) <= 0)
8241 -+ {
8242 -+ // Extra safety - should not really happen
8243 -+ DBUG_ASSERT(false);
8244 -+ break;
8245 -+ }
8246 -+ to+= rc;
8247 -+ nchars++;
8248 -+ last_ch= ch; // save code of last input letter
8249 -+ } // for next double-letter check
8250 -+ }
8251 -+
8252 -+ /* Pad up to 4 characters with DIGIT ZERO, if the string is shorter */
8253 -+ if (nchars < 4)
8254 -+ {
8255 -+ uint nbytes= (4 - nchars) * cs->mbminlen;
8256 -+ cs->cset->fill(cs, to, nbytes, '0');
8257 -+ to+= nbytes;
8258 -+ }
8259 -+
8260 -+ tmp_value.length((uint) (to-tmp_value.ptr()));
8261 -+ return &tmp_value;
8262 -+}
8263 -+
8264 -+
8265 -+/**
8266 -+ Change a number to format '3,333,333,333.000'.
8267 -+
8268 -+ This should be 'internationalized' sometimes.
8269 -+*/
8270 -+
8271 -+const int FORMAT_MAX_DECIMALS= 30;
8272 -+
8273 -+Item_func_format::Item_func_format(Item *org, Item *dec)
8274 -+: Item_str_func(org, dec)
8275 -+{
8276 -+}
8277 -+
8278 -+void Item_func_format::fix_length_and_dec()
8279 -+{
8280 -+ uint char_length= args[0]->max_length/args[0]->collation.collation->mbmaxlen;
8281 -+ uint max_sep_count= char_length/3 + (decimals ? 1 : 0) + /*sign*/1;
8282 -+ collation.set(default_charset());
8283 -+ max_length= (char_length + max_sep_count + decimals) *
8284 -+ collation.collation->mbmaxlen;
8285 -+}
8286 -+
8287 -+
8288 -+/**
8289 -+ @todo
8290 -+ This needs to be fixed for multi-byte character set where numbers
8291 -+ are stored in more than one byte
8292 -+*/
8293 -+
8294 -+String *Item_func_format::val_str(String *str)
8295 -+{
8296 -+ uint32 length;
8297 -+ uint32 str_length;
8298 -+ /* Number of decimal digits */
8299 -+ int dec;
8300 -+ /* Number of characters used to represent the decimals, including '.' */
8301 -+ uint32 dec_length;
8302 -+ int diff;
8303 -+ DBUG_ASSERT(fixed == 1);
8304 -+
8305 -+ dec= (int) args[1]->val_int();
8306 -+ if (args[1]->null_value)
8307 -+ {
8308 -+ null_value=1;
8309 -+ return NULL;
8310 -+ }
8311 -+
8312 -+ dec= set_zone(dec, 0, FORMAT_MAX_DECIMALS);
8313 -+ dec_length= dec ? dec+1 : 0;
8314 -+ null_value=0;
8315 -+
8316 -+ if (args[0]->result_type() == DECIMAL_RESULT ||
8317 -+ args[0]->result_type() == INT_RESULT)
8318 -+ {
8319 -+ my_decimal dec_val, rnd_dec, *res;
8320 -+ res= args[0]->val_decimal(&dec_val);
8321 -+ if ((null_value=args[0]->null_value))
8322 -+ return 0; /* purecov: inspected */
8323 -+ my_decimal_round(E_DEC_FATAL_ERROR, res, dec, false, &rnd_dec);
8324 -+ my_decimal2string(E_DEC_FATAL_ERROR, &rnd_dec, 0, 0, 0, str);
8325 -+ str_length= str->length();
8326 -+ if (rnd_dec.sign())
8327 -+ str_length--;
8328 -+ }
8329 -+ else
8330 -+ {
8331 -+ double nr= args[0]->val_real();
8332 -+ if ((null_value=args[0]->null_value))
8333 -+ return 0; /* purecov: inspected */
8334 -+ nr= my_double_round(nr, (longlong) dec, FALSE, FALSE);
8335 -+ /* Here default_charset() is right as this is not an automatic conversion */
8336 -+ str->set_real(nr, dec, default_charset());
8337 -+ if (isnan(nr))
8338 -+ return str;
8339 -+ str_length=str->length();
8340 -+ if (nr < 0)
8341 -+ str_length--; // Don't count sign
8342 -+ }
8343 -+ /* We need this test to handle 'nan' values */
8344 -+ if (str_length >= dec_length+4)
8345 -+ {
8346 -+ char *tmp,*pos;
8347 -+ length= str->length()+(diff=((int)(str_length- dec_length-1))/3);
8348 -+ str= copy_if_not_alloced(&tmp_str,str,length);
8349 -+ str->length(length);
8350 -+ tmp= (char*) str->ptr()+length - dec_length-1;
8351 -+ for (pos= (char*) str->ptr()+length-1; pos != tmp; pos--)
8352 -+ pos[0]= pos[-diff];
8353 -+ while (diff)
8354 -+ {
8355 -+ *pos= *(pos - diff);
8356 -+ pos--;
8357 -+ *pos= *(pos - diff);
8358 -+ pos--;
8359 -+ *pos= *(pos - diff);
8360 -+ pos--;
8361 -+ pos[0]=',';
8362 -+ pos--;
8363 -+ diff--;
8364 -+ }
8365 -+ }
8366 -+ return str;
8367 -+}
8368 -+
8369 -+
8370 -+void Item_func_format::print(String *str, enum_query_type query_type)
8371 -+{
8372 -+ str->append(STRING_WITH_LEN("format("));
8373 -+ args[0]->print(str, query_type);
8374 -+ str->append(',');
8375 -+ args[1]->print(str, query_type);
8376 -+ str->append(')');
8377 -+}
8378 -+
8379 -+void Item_func_elt::fix_length_and_dec()
8380 -+{
8381 -+ max_length=0;
8382 -+ decimals=0;
8383 -+
8384 -+ if (agg_arg_charsets(collation, args+1, arg_count-1, MY_COLL_ALLOW_CONV, 1))
8385 -+ return;
8386 -+
8387 -+ for (uint i= 1 ; i < arg_count ; i++)
8388 -+ {
8389 -+ set_if_bigger(max_length,args[i]->max_length);
8390 -+ set_if_bigger(decimals,args[i]->decimals);
8391 -+ }
8392 -+ maybe_null=1; // NULL if wrong first arg
8393 -+}
8394 -+
8395 -+
8396 -+double Item_func_elt::val_real()
8397 -+{
8398 -+ DBUG_ASSERT(fixed == 1);
8399 -+ uint tmp;
8400 -+ null_value=1;
8401 -+ if ((tmp=(uint) args[0]->val_int()) == 0 || tmp >= arg_count)
8402 -+ return 0.0;
8403 -+ double result= args[tmp]->val_real();
8404 -+ null_value= args[tmp]->null_value;
8405 -+ return result;
8406 -+}
8407 -+
8408 -+
8409 -+longlong Item_func_elt::val_int()
8410 -+{
8411 -+ DBUG_ASSERT(fixed == 1);
8412 -+ uint tmp;
8413 -+ null_value=1;
8414 -+ if ((tmp=(uint) args[0]->val_int()) == 0 || tmp >= arg_count)
8415 -+ return 0;
8416 -+
8417 -+ longlong result= args[tmp]->val_int();
8418 -+ null_value= args[tmp]->null_value;
8419 -+ return result;
8420 -+}
8421 -+
8422 -+
8423 -+String *Item_func_elt::val_str(String *str)
8424 -+{
8425 -+ DBUG_ASSERT(fixed == 1);
8426 -+ uint tmp;
8427 -+ null_value=1;
8428 -+ if ((tmp=(uint) args[0]->val_int()) == 0 || tmp >= arg_count)
8429 -+ return NULL;
8430 -+
8431 -+ String *result= args[tmp]->val_str(str);
8432 -+ if (result)
8433 -+ result->set_charset(collation.collation);
8434 -+ null_value= args[tmp]->null_value;
8435 -+ return result;
8436 -+}
8437 -+
8438 -+
8439 -+void Item_func_make_set::split_sum_func(THD *thd, Item **ref_pointer_array,
8440 -+ List<Item> &fields)
8441 -+{
8442 -+ item->split_sum_func2(thd, ref_pointer_array, fields, &item, TRUE);
8443 -+ Item_str_func::split_sum_func(thd, ref_pointer_array, fields);
8444 -+}
8445 -+
8446 -+
8447 -+void Item_func_make_set::fix_length_and_dec()
8448 -+{
8449 -+ max_length=arg_count-1;
8450 -+
8451 -+ if (agg_arg_charsets(collation, args, arg_count, MY_COLL_ALLOW_CONV, 1))
8452 -+ return;
8453 -+
8454 -+ for (uint i=0 ; i < arg_count ; i++)
8455 -+ max_length+=args[i]->max_length;
8456 -+
8457 -+ used_tables_cache|= item->used_tables();
8458 -+ not_null_tables_cache&= item->not_null_tables();
8459 -+ const_item_cache&= item->const_item();
8460 -+ with_sum_func= with_sum_func || item->with_sum_func;
8461 -+}
8462 -+
8463 -+
8464 -+void Item_func_make_set::update_used_tables()
8465 -+{
8466 -+ Item_func::update_used_tables();
8467 -+ item->update_used_tables();
8468 -+ used_tables_cache|=item->used_tables();
8469 -+ const_item_cache&=item->const_item();
8470 -+}
8471 -+
8472 -+
8473 -+String *Item_func_make_set::val_str(String *str)
8474 -+{
8475 -+ DBUG_ASSERT(fixed == 1);
8476 -+ ulonglong bits;
8477 -+ bool first_found=0;
8478 -+ Item **ptr=args;
8479 -+ String *result=&my_empty_string;
8480 -+
8481 -+ bits=item->val_int();
8482 -+ if ((null_value=item->null_value))
8483 -+ return NULL;
8484 -+
8485 -+ if (arg_count < 64)
8486 -+ bits &= ((ulonglong) 1 << arg_count)-1;
8487 -+
8488 -+ for (; bits; bits >>= 1, ptr++)
8489 -+ {
8490 -+ if (bits & 1)
8491 -+ {
8492 -+ String *res= (*ptr)->val_str(str);
8493 -+ if (res) // Skip nulls
8494 -+ {
8495 -+ if (!first_found)
8496 -+ { // First argument
8497 -+ first_found=1;
8498 -+ if (res != str)
8499 -+ result=res; // Use original string
8500 -+ else
8501 -+ {
8502 -+ if (tmp_str.copy(*res)) // Don't use 'str'
8503 -+ return make_empty_result();
8504 -+ result= &tmp_str;
8505 -+ }
8506 -+ }
8507 -+ else
8508 -+ {
8509 -+ if (result != &tmp_str)
8510 -+ { // Copy data to tmp_str
8511 -+ if (tmp_str.alloc(result->length()+res->length()+1) ||
8512 -+ tmp_str.copy(*result))
8513 -+ return make_empty_result();
8514 -+ result= &tmp_str;
8515 -+ }
8516 -+ if (tmp_str.append(STRING_WITH_LEN(","), &my_charset_bin) || tmp_str.append(*res))
8517 -+ return make_empty_result();
8518 -+ }
8519 -+ }
8520 -+ }
8521 -+ }
8522 -+ return result;
8523 -+}
8524 -+
8525 -+
8526 -+Item *Item_func_make_set::transform(Item_transformer transformer, uchar *arg)
8527 -+{
8528 -+ DBUG_ASSERT(!current_thd->is_stmt_prepare());
8529 -+
8530 -+ Item *new_item= item->transform(transformer, arg);
8531 -+ if (!new_item)
8532 -+ return 0;
8533 -+
8534 -+ /*
8535 -+ THD::change_item_tree() should be called only if the tree was
8536 -+ really transformed, i.e. when a new item has been created.
8537 -+ Otherwise we'll be allocating a lot of unnecessary memory for
8538 -+ change records at each execution.
8539 -+ */
8540 -+ if (item != new_item)
8541 -+ current_thd->change_item_tree(&item, new_item);
8542 -+ return Item_str_func::transform(transformer, arg);
8543 -+}
8544 -+
8545 -+
8546 -+void Item_func_make_set::print(String *str, enum_query_type query_type)
8547 -+{
8548 -+ str->append(STRING_WITH_LEN("make_set("));
8549 -+ item->print(str, query_type);
8550 -+ if (arg_count)
8551 -+ {
8552 -+ str->append(',');
8553 -+ print_args(str, 0, query_type);
8554 -+ }
8555 -+ str->append(')');
8556 -+}
8557 -+
8558 -+
8559 -+String *Item_func_char::val_str(String *str)
8560 -+{
8561 -+ DBUG_ASSERT(fixed == 1);
8562 -+ str->length(0);
8563 -+ str->set_charset(collation.collation);
8564 -+ for (uint i=0 ; i < arg_count ; i++)
8565 -+ {
8566 -+ int32 num=(int32) args[i]->val_int();
8567 -+ if (!args[i]->null_value)
8568 -+ {
8569 -+ char char_num= (char) num;
8570 -+ if (num&0xFF000000L) {
8571 -+ str->append((char)(num>>24));
8572 -+ goto b2;
8573 -+ } else if (num&0xFF0000L) {
8574 -+ b2: str->append((char)(num>>16));
8575 -+ goto b1;
8576 -+ } else if (num&0xFF00L) {
8577 -+ b1: str->append((char)(num>>8));
8578 -+ }
8579 -+ str->append(&char_num, 1);
8580 -+ }
8581 -+ }
8582 -+ str->realloc(str->length()); // Add end 0 (for Purify)
8583 -+ return check_well_formed_result(str);
8584 -+}
8585 -+
8586 -+
8587 -+inline String* alloc_buffer(String *res,String *str,String *tmp_value,
8588 -+ ulong length)
8589 -+{
8590 -+ if (res->alloced_length() < length)
8591 -+ {
8592 -+ if (str->alloced_length() >= length)
8593 -+ {
8594 -+ (void) str->copy(*res);
8595 -+ str->length(length);
8596 -+ return str;
8597 -+ }
8598 -+ if (tmp_value->alloc(length))
8599 -+ return 0;
8600 -+ (void) tmp_value->copy(*res);
8601 -+ tmp_value->length(length);
8602 -+ return tmp_value;
8603 -+ }
8604 -+ res->length(length);
8605 -+ return res;
8606 -+}
8607 -+
8608 -+
8609 -+void Item_func_repeat::fix_length_and_dec()
8610 -+{
8611 -+ collation.set(args[0]->collation);
8612 -+ if (args[1]->const_item())
8613 -+ {
8614 -+ /* must be longlong to avoid truncation */
8615 -+ longlong count= args[1]->val_int();
8616 -+
8617 -+ /* Assumes that the maximum length of a String is < INT_MAX32. */
8618 -+ /* Set here so that rest of code sees out-of-bound value as such. */
8619 -+ if (count > INT_MAX32)
8620 -+ count= INT_MAX32;
8621 -+
8622 -+ ulonglong max_result_length= (ulonglong) args[0]->max_length * count;
8623 -+ if (max_result_length >= MAX_BLOB_WIDTH)
8624 -+ {
8625 -+ max_result_length= MAX_BLOB_WIDTH;
8626 -+ maybe_null= 1;
8627 -+ }
8628 -+ max_length= (ulong) max_result_length;
8629 -+ }
8630 -+ else
8631 -+ {
8632 -+ max_length= MAX_BLOB_WIDTH;
8633 -+ maybe_null= 1;
8634 -+ }
8635 -+}
8636 -+
8637 -+/**
8638 -+ Item_func_repeat::str is carefully written to avoid reallocs
8639 -+ as much as possible at the cost of a local buffer
8640 -+*/
8641 -+
8642 -+String *Item_func_repeat::val_str(String *str)
8643 -+{
8644 -+ DBUG_ASSERT(fixed == 1);
8645 -+ uint length,tot_length;
8646 -+ char *to;
8647 -+ /* must be longlong to avoid truncation */
8648 -+ longlong count= args[1]->val_int();
8649 -+ String *res= args[0]->val_str(str);
8650 -+
8651 -+ if (args[0]->null_value || args[1]->null_value)
8652 -+ goto err; // string and/or delim are null
8653 -+ null_value= 0;
8654 -+
8655 -+ if (count <= 0 && (count == 0 || !args[1]->unsigned_flag))
8656 -+ return make_empty_result();
8657 -+
8658 -+ /* Assumes that the maximum length of a String is < INT_MAX32. */
8659 -+ /* Bounds check on count: If this is triggered, we will error. */
8660 -+ if ((ulonglong) count > INT_MAX32)
8661 -+ count= INT_MAX32;
8662 -+ if (count == 1) // To avoid reallocs
8663 -+ return res;
8664 -+ length=res->length();
8665 -+ // Safe length check
8666 -+ if (length > current_thd->variables.max_allowed_packet / (uint) count)
8667 -+ {
8668 -+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
8669 -+ ER_WARN_ALLOWED_PACKET_OVERFLOWED,
8670 -+ ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED),
8671 -+ func_name(), current_thd->variables.max_allowed_packet);
8672 -+ goto err;
8673 -+ }
8674 -+ tot_length= length*(uint) count;
8675 -+ if (!(res= alloc_buffer(res,str,&tmp_value,tot_length)))
8676 -+ goto err;
8677 -+
8678 -+ to=(char*) res->ptr()+length;
8679 -+ while (--count)
8680 -+ {
8681 -+ memcpy(to,res->ptr(),length);
8682 -+ to+=length;
8683 -+ }
8684 -+ return (res);
8685 -+
8686 -+err:
8687 -+ null_value=1;
8688 -+ return 0;
8689 -+}
8690 -+
8691 -+
8692 -+void Item_func_rpad::fix_length_and_dec()
8693 -+{
8694 -+ // Handle character set for args[0] and args[2].
8695 -+ if (agg_arg_charsets(collation, &args[0], 2, MY_COLL_ALLOW_CONV, 2))
8696 -+ return;
8697 -+ if (args[1]->const_item())
8698 -+ {
8699 -+ ulonglong length= 0;
8700 -+
8701 -+ if (collation.collation->mbmaxlen > 0)
8702 -+ {
8703 -+ ulonglong temp= (ulonglong) args[1]->val_int();
8704 -+
8705 -+ /* Assumes that the maximum length of a String is < INT_MAX32. */
8706 -+ /* Set here so that rest of code sees out-of-bound value as such. */
8707 -+ if (temp > INT_MAX32)
8708 -+ temp = INT_MAX32;
8709 -+
8710 -+ length= temp * collation.collation->mbmaxlen;
8711 -+ }
8712 -+
8713 -+ if (length >= MAX_BLOB_WIDTH)
8714 -+ {
8715 -+ length= MAX_BLOB_WIDTH;
8716 -+ maybe_null= 1;
8717 -+ }
8718 -+ max_length= (ulong) length;
8719 -+ }
8720 -+ else
8721 -+ {
8722 -+ max_length= MAX_BLOB_WIDTH;
8723 -+ maybe_null= 1;
8724 -+ }
8725 -+}
8726 -+
8727 -+
8728 -+String *Item_func_rpad::val_str(String *str)
8729 -+{
8730 -+ DBUG_ASSERT(fixed == 1);
8731 -+ uint32 res_byte_length,res_char_length,pad_char_length,pad_byte_length;
8732 -+ char *to;
8733 -+ const char *ptr_pad;
8734 -+ /* must be longlong to avoid truncation */
8735 -+ longlong count= args[1]->val_int();
8736 -+ longlong byte_count;
8737 -+ String *res= args[0]->val_str(str);
8738 -+ String *rpad= args[2]->val_str(&rpad_str);
8739 -+
8740 -+ if (!res || args[1]->null_value || !rpad ||
8741 -+ ((count < 0) && !args[1]->unsigned_flag))
8742 -+ goto err;
8743 -+ null_value=0;
8744 -+ /* Assumes that the maximum length of a String is < INT_MAX32. */
8745 -+ /* Set here so that rest of code sees out-of-bound value as such. */
8746 -+ if ((ulonglong) count > INT_MAX32)
8747 -+ count= INT_MAX32;
8748 -+ /*
8749 -+ There is one exception not handled (intentionaly) by the character set
8750 -+ aggregation code. If one string is strong side and is binary, and
8751 -+ another one is weak side and is a multi-byte character string,
8752 -+ then we need to operate on the second string in terms on bytes when
8753 -+ calling ::numchars() and ::charpos(), rather than in terms of characters.
8754 -+ Lets substitute its character set to binary.
8755 -+ */
8756 -+ if (collation.collation == &my_charset_bin)
8757 -+ {
8758 -+ res->set_charset(&my_charset_bin);
8759 -+ rpad->set_charset(&my_charset_bin);
8760 -+ }
8761 -+
8762 -+ if (count <= (res_char_length= res->numchars()))
8763 -+ { // String to pad is big enough
8764 -+ res->length(res->charpos((int) count)); // Shorten result if longer
8765 -+ return (res);
8766 -+ }
8767 -+ pad_char_length= rpad->numchars();
8768 -+
8769 -+ byte_count= count * collation.collation->mbmaxlen;
8770 -+ if ((ulonglong) byte_count > current_thd->variables.max_allowed_packet)
8771 -+ {
8772 -+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
8773 -+ ER_WARN_ALLOWED_PACKET_OVERFLOWED,
8774 -+ ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED),
8775 -+ func_name(), current_thd->variables.max_allowed_packet);
8776 -+ goto err;
8777 -+ }
8778 -+ if (args[2]->null_value || !pad_char_length)
8779 -+ goto err;
8780 -+ res_byte_length= res->length(); /* Must be done before alloc_buffer */
8781 -+ if (!(res= alloc_buffer(res,str,&tmp_value, (ulong) byte_count)))
8782 -+ goto err;
8783 -+
8784 -+ to= (char*) res->ptr()+res_byte_length;
8785 -+ ptr_pad=rpad->ptr();
8786 -+ pad_byte_length= rpad->length();
8787 -+ count-= res_char_length;
8788 -+ for ( ; (uint32) count > pad_char_length; count-= pad_char_length)
8789 -+ {
8790 -+ memcpy(to,ptr_pad,pad_byte_length);
8791 -+ to+= pad_byte_length;
8792 -+ }
8793 -+ if (count)
8794 -+ {
8795 -+ pad_byte_length= rpad->charpos((int) count);
8796 -+ memcpy(to,ptr_pad,(size_t) pad_byte_length);
8797 -+ to+= pad_byte_length;
8798 -+ }
8799 -+ res->length((uint) (to- (char*) res->ptr()));
8800 -+ return (res);
8801 -+
8802 -+ err:
8803 -+ null_value=1;
8804 -+ return 0;
8805 -+}
8806 -+
8807 -+
8808 -+void Item_func_lpad::fix_length_and_dec()
8809 -+{
8810 -+ // Handle character set for args[0] and args[2].
8811 -+ if (agg_arg_charsets(collation, &args[0], 2, MY_COLL_ALLOW_CONV, 2))
8812 -+ return;
8813 -+
8814 -+ if (args[1]->const_item())
8815 -+ {
8816 -+ ulonglong length= 0;
8817 -+
8818 -+ if (collation.collation->mbmaxlen > 0)
8819 -+ {
8820 -+ ulonglong temp= (ulonglong) args[1]->val_int();
8821 -+
8822 -+ /* Assumes that the maximum length of a String is < INT_MAX32. */
8823 -+ /* Set here so that rest of code sees out-of-bound value as such. */
8824 -+ if (temp > INT_MAX32)
8825 -+ temp= INT_MAX32;
8826 -+
8827 -+ length= temp * collation.collation->mbmaxlen;
8828 -+ }
8829 -+
8830 -+ if (length >= MAX_BLOB_WIDTH)
8831 -+ {
8832 -+ length= MAX_BLOB_WIDTH;
8833 -+ maybe_null= 1;
8834 -+ }
8835 -+ max_length= (ulong) length;
8836 -+ }
8837 -+ else
8838 -+ {
8839 -+ max_length= MAX_BLOB_WIDTH;
8840 -+ maybe_null= 1;
8841 -+ }
8842 -+}
8843 -+
8844 -+
8845 -+String *Item_func_lpad::val_str(String *str)
8846 -+{
8847 -+ DBUG_ASSERT(fixed == 1);
8848 -+ uint32 res_char_length,pad_char_length;
8849 -+ /* must be longlong to avoid truncation */
8850 -+ longlong count= args[1]->val_int();
8851 -+ longlong byte_count;
8852 -+ String *res= args[0]->val_str(&tmp_value);
8853 -+ String *pad= args[2]->val_str(&lpad_str);
8854 -+
8855 -+ if (!res || args[1]->null_value || !pad ||
8856 -+ ((count < 0) && !args[1]->unsigned_flag))
8857 -+ goto err;
8858 -+ null_value=0;
8859 -+ /* Assumes that the maximum length of a String is < INT_MAX32. */
8860 -+ /* Set here so that rest of code sees out-of-bound value as such. */
8861 -+ if ((ulonglong) count > INT_MAX32)
8862 -+ count= INT_MAX32;
8863 -+
8864 -+ /*
8865 -+ There is one exception not handled (intentionaly) by the character set
8866 -+ aggregation code. If one string is strong side and is binary, and
8867 -+ another one is weak side and is a multi-byte character string,
8868 -+ then we need to operate on the second string in terms on bytes when
8869 -+ calling ::numchars() and ::charpos(), rather than in terms of characters.
8870 -+ Lets substitute its character set to binary.
8871 -+ */
8872 -+ if (collation.collation == &my_charset_bin)
8873 -+ {
8874 -+ res->set_charset(&my_charset_bin);
8875 -+ pad->set_charset(&my_charset_bin);
8876 -+ }
8877 -+
8878 -+ res_char_length= res->numchars();
8879 -+
8880 -+ if (count <= res_char_length)
8881 -+ {
8882 -+ res->length(res->charpos((int) count));
8883 -+ return res;
8884 -+ }
8885 -+
8886 -+ pad_char_length= pad->numchars();
8887 -+ byte_count= count * collation.collation->mbmaxlen;
8888 -+
8889 -+ if ((ulonglong) byte_count > current_thd->variables.max_allowed_packet)
8890 -+ {
8891 -+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
8892 -+ ER_WARN_ALLOWED_PACKET_OVERFLOWED,
8893 -+ ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED),
8894 -+ func_name(), current_thd->variables.max_allowed_packet);
8895 -+ goto err;
8896 -+ }
8897 -+
8898 -+ if (args[2]->null_value || !pad_char_length ||
8899 -+ str->alloc((uint32) byte_count))
8900 -+ goto err;
8901 -+
8902 -+ str->length(0);
8903 -+ str->set_charset(collation.collation);
8904 -+ count-= res_char_length;
8905 -+ while (count >= pad_char_length)
8906 -+ {
8907 -+ str->append(*pad);
8908 -+ count-= pad_char_length;
8909 -+ }
8910 -+ if (count > 0)
8911 -+ str->append(pad->ptr(), pad->charpos((int) count), collation.collation);
8912 -+
8913 -+ str->append(*res);
8914 -+ null_value= 0;
8915 -+ return str;
8916 -+
8917 -+err:
8918 -+ null_value= 1;
8919 -+ return 0;
8920 -+}
8921 -+
8922 -+
8923 -+String *Item_func_conv::val_str(String *str)
8924 -+{
8925 -+ DBUG_ASSERT(fixed == 1);
8926 -+ String *res= args[0]->val_str(str);
8927 -+ char *endptr,ans[65],*ptr;
8928 -+ longlong dec;
8929 -+ int from_base= (int) args[1]->val_int();
8930 -+ int to_base= (int) args[2]->val_int();
8931 -+ int err;
8932 -+
8933 -+ if (args[0]->null_value || args[1]->null_value || args[2]->null_value ||
8934 -+ abs(to_base) > 36 || abs(to_base) < 2 ||
8935 -+ abs(from_base) > 36 || abs(from_base) < 2 || !(res->length()))
8936 -+ {
8937 -+ null_value= 1;
8938 -+ return NULL;
8939 -+ }
8940 -+ null_value= 0;
8941 -+ unsigned_flag= !(from_base < 0);
8942 -+
8943 -+ if (args[0]->field_type() == MYSQL_TYPE_BIT)
8944 -+ {
8945 -+ /*
8946 -+ Special case: The string representation of BIT doesn't resemble the
8947 -+ decimal representation, so we shouldn't change it to string and then to
8948 -+ decimal.
8949 -+ */
8950 -+ dec= args[0]->val_int();
8951 -+ }
8952 -+ else
8953 -+ {
8954 -+ if (from_base < 0)
8955 -+ dec= my_strntoll(res->charset(), res->ptr(), res->length(),
8956 -+ -from_base, &endptr, &err);
8957 -+ else
8958 -+ dec= (longlong) my_strntoull(res->charset(), res->ptr(), res->length(),
8959 -+ from_base, &endptr, &err);
8960 -+ }
8961 -+
8962 -+ ptr= longlong2str(dec, ans, to_base);
8963 -+ if (str->copy(ans, (uint32) (ptr-ans), default_charset()))
8964 -+ return make_empty_result();
8965 -+ return str;
8966 -+}
8967 -+
8968 -+
8969 -+String *Item_func_conv_charset::val_str(String *str)
8970 -+{
8971 -+ DBUG_ASSERT(fixed == 1);
8972 -+ if (use_cached_value)
8973 -+ return null_value ? 0 : &str_value;
8974 -+ String *arg= args[0]->val_str(str);
8975 -+ uint dummy_errors;
8976 -+ if (!arg)
8977 -+ {
8978 -+ null_value=1;
8979 -+ return 0;
8980 -+ }
8981 -+ null_value= tmp_value.copy(arg->ptr(), arg->length(), arg->charset(),
8982 -+ conv_charset, &dummy_errors);
8983 -+ return null_value ? 0 : check_well_formed_result(&tmp_value);
8984 -+}
8985 -+
8986 -+void Item_func_conv_charset::fix_length_and_dec()
8987 -+{
8988 -+ collation.set(conv_charset, DERIVATION_IMPLICIT);
8989 -+ max_length = args[0]->max_length*conv_charset->mbmaxlen;
8990 -+}
8991 -+
8992 -+void Item_func_conv_charset::print(String *str, enum_query_type query_type)
8993 -+{
8994 -+ str->append(STRING_WITH_LEN("convert("));
8995 -+ args[0]->print(str, query_type);
8996 -+ str->append(STRING_WITH_LEN(" using "));
8997 -+ str->append(conv_charset->csname);
8998 -+ str->append(')');
8999 -+}
9000 -+
9001 -+String *Item_func_set_collation::val_str(String *str)
9002 -+{
9003 -+ DBUG_ASSERT(fixed == 1);
9004 -+ str=args[0]->val_str(str);
9005 -+ if ((null_value=args[0]->null_value))
9006 -+ return 0;
9007 -+ str->set_charset(collation.collation);
9008 -+ return str;
9009 -+}
9010 -+
9011 -+void Item_func_set_collation::fix_length_and_dec()
9012 -+{
9013 -+ CHARSET_INFO *set_collation;
9014 -+ const char *colname;
9015 -+ String tmp, *str= args[1]->val_str(&tmp);
9016 -+ colname= str->c_ptr();
9017 -+ if (colname == binary_keyword)
9018 -+ set_collation= get_charset_by_csname(args[0]->collation.collation->csname,
9019 -+ MY_CS_BINSORT,MYF(0));
9020 -+ else
9021 -+ {
9022 -+ if (!(set_collation= get_charset_by_name(colname,MYF(0))))
9023 -+ {
9024 -+ my_error(ER_UNKNOWN_COLLATION, MYF(0), colname);
9025 -+ return;
9026 -+ }
9027 -+ }
9028 -+
9029 -+ if (!set_collation ||
9030 -+ !my_charset_same(args[0]->collation.collation,set_collation))
9031 -+ {
9032 -+ my_error(ER_COLLATION_CHARSET_MISMATCH, MYF(0),
9033 -+ colname, args[0]->collation.collation->csname);
9034 -+ return;
9035 -+ }
9036 -+ collation.set(set_collation, DERIVATION_EXPLICIT,
9037 -+ args[0]->collation.repertoire);
9038 -+ max_length= args[0]->max_length;
9039 -+}
9040 -+
9041 -+
9042 -+bool Item_func_set_collation::eq(const Item *item, bool binary_cmp) const
9043 -+{
9044 -+ /* Assume we don't have rtti */
9045 -+ if (this == item)
9046 -+ return 1;
9047 -+ if (item->type() != FUNC_ITEM)
9048 -+ return 0;
9049 -+ Item_func *item_func=(Item_func*) item;
9050 -+ if (arg_count != item_func->arg_count ||
9051 -+ functype() != item_func->functype())
9052 -+ return 0;
9053 -+ Item_func_set_collation *item_func_sc=(Item_func_set_collation*) item;
9054 -+ if (collation.collation != item_func_sc->collation.collation)
9055 -+ return 0;
9056 -+ for (uint i=0; i < arg_count ; i++)
9057 -+ if (!args[i]->eq(item_func_sc->args[i], binary_cmp))
9058 -+ return 0;
9059 -+ return 1;
9060 -+}
9061 -+
9062 -+
9063 -+void Item_func_set_collation::print(String *str, enum_query_type query_type)
9064 -+{
9065 -+ str->append('(');
9066 -+ args[0]->print(str, query_type);
9067 -+ str->append(STRING_WITH_LEN(" collate "));
9068 -+ DBUG_ASSERT(args[1]->basic_const_item() &&
9069 -+ args[1]->type() == Item::STRING_ITEM);
9070 -+ args[1]->str_value.print(str);
9071 -+ str->append(')');
9072 -+}
9073 -+
9074 -+String *Item_func_charset::val_str(String *str)
9075 -+{
9076 -+ DBUG_ASSERT(fixed == 1);
9077 -+ uint dummy_errors;
9078 -+
9079 -+ CHARSET_INFO *cs= args[0]->collation.collation;
9080 -+ null_value= 0;
9081 -+ str->copy(cs->csname, (uint) strlen(cs->csname),
9082 -+ &my_charset_latin1, collation.collation, &dummy_errors);
9083 -+ return str;
9084 -+}
9085 -+
9086 -+String *Item_func_collation::val_str(String *str)
9087 -+{
9088 -+ DBUG_ASSERT(fixed == 1);
9089 -+ uint dummy_errors;
9090 -+ CHARSET_INFO *cs= args[0]->collation.collation;
9091 -+
9092 -+ null_value= 0;
9093 -+ str->copy(cs->name, (uint) strlen(cs->name),
9094 -+ &my_charset_latin1, collation.collation, &dummy_errors);
9095 -+ return str;
9096 -+}
9097 -+
9098 -+
9099 -+String *Item_func_hex::val_str(String *str)
9100 -+{
9101 -+ String *res;
9102 -+ DBUG_ASSERT(fixed == 1);
9103 -+ if (args[0]->result_type() != STRING_RESULT)
9104 -+ {
9105 -+ ulonglong dec;
9106 -+ char ans[65],*ptr;
9107 -+ /* Return hex of unsigned longlong value */
9108 -+ if (args[0]->result_type() == REAL_RESULT ||
9109 -+ args[0]->result_type() == DECIMAL_RESULT)
9110 -+ {
9111 -+ double val= args[0]->val_real();
9112 -+ if ((val <= (double) LONGLONG_MIN) ||
9113 -+ (val >= (double) (ulonglong) ULONGLONG_MAX))
9114 -+ dec= ~(longlong) 0;
9115 -+ else
9116 -+ dec= (ulonglong) (val + (val > 0 ? 0.5 : -0.5));
9117 -+ }
9118 -+ else
9119 -+ dec= (ulonglong) args[0]->val_int();
9120 -+
9121 -+ if ((null_value= args[0]->null_value))
9122 -+ return 0;
9123 -+ ptr= longlong2str(dec,ans,16);
9124 -+ if (str->copy(ans,(uint32) (ptr-ans),default_charset()))
9125 -+ return make_empty_result(); // End of memory
9126 -+ return str;
9127 -+ }
9128 -+
9129 -+ /* Convert given string to a hex string, character by character */
9130 -+ res= args[0]->val_str(str);
9131 -+ if (!res || tmp_value.alloc(res->length()*2+1))
9132 -+ {
9133 -+ null_value=1;
9134 -+ return 0;
9135 -+ }
9136 -+ null_value=0;
9137 -+ tmp_value.length(res->length()*2);
9138 -+
9139 -+ octet2hex((char*) tmp_value.ptr(), res->ptr(), res->length());
9140 -+ return &tmp_value;
9141 -+}
9142 -+
9143 -+ /** Convert given hex string to a binary string. */
9144 -+
9145 -+String *Item_func_unhex::val_str(String *str)
9146 -+{
9147 -+ const char *from, *end;
9148 -+ char *to;
9149 -+ String *res;
9150 -+ uint length;
9151 -+ DBUG_ASSERT(fixed == 1);
9152 -+
9153 -+ res= args[0]->val_str(str);
9154 -+ if (!res || tmp_value.alloc(length= (1+res->length())/2))
9155 -+ {
9156 -+ null_value=1;
9157 -+ return 0;
9158 -+ }
9159 -+
9160 -+ from= res->ptr();
9161 -+ null_value= 0;
9162 -+ tmp_value.length(length);
9163 -+ to= (char*) tmp_value.ptr();
9164 -+ if (res->length() % 2)
9165 -+ {
9166 -+ int hex_char;
9167 -+ *to++= hex_char= hexchar_to_int(*from++);
9168 -+ if ((null_value= (hex_char == -1)))
9169 -+ return 0;
9170 -+ }
9171 -+ for (end=res->ptr()+res->length(); from < end ; from+=2, to++)
9172 -+ {
9173 -+ int hex_char;
9174 -+ *to= (hex_char= hexchar_to_int(from[0])) << 4;
9175 -+ if ((null_value= (hex_char == -1)))
9176 -+ return 0;
9177 -+ *to|= hex_char= hexchar_to_int(from[1]);
9178 -+ if ((null_value= (hex_char == -1)))
9179 -+ return 0;
9180 -+ }
9181 -+ return &tmp_value;
9182 -+}
9183 -+
9184 -+
9185 -+void Item_func_binary::print(String *str, enum_query_type query_type)
9186 -+{
9187 -+ str->append(STRING_WITH_LEN("cast("));
9188 -+ args[0]->print(str, query_type);
9189 -+ str->append(STRING_WITH_LEN(" as binary)"));
9190 -+}
9191 -+
9192 -+
9193 -+#include <my_dir.h> // For my_stat
9194 -+
9195 -+String *Item_load_file::val_str(String *str)
9196 -+{
9197 -+ DBUG_ASSERT(fixed == 1);
9198 -+ String *file_name;
9199 -+ File file;
9200 -+ MY_STAT stat_info;
9201 -+ char path[FN_REFLEN];
9202 -+ DBUG_ENTER("load_file");
9203 -+
9204 -+ if (!(file_name= args[0]->val_str(str))
9205 -+#ifndef NO_EMBEDDED_ACCESS_CHECKS
9206 -+ || !(current_thd->security_ctx->master_access & FILE_ACL)
9207 -+#endif
9208 -+ )
9209 -+ goto err;
9210 -+
9211 -+ (void) fn_format(path, file_name->c_ptr_safe(), mysql_real_data_home, "",
9212 -+ MY_RELATIVE_PATH | MY_UNPACK_FILENAME);
9213 -+
9214 -+ /* Read only allowed from within dir specified by secure_file_priv */
9215 -+ if (!is_secure_file_path(path))
9216 -+ goto err;
9217 -+
9218 -+ if (!my_stat(path, &stat_info, MYF(0)))
9219 -+ goto err;
9220 -+
9221 -+ if (!(stat_info.st_mode & S_IROTH))
9222 -+ {
9223 -+ /* my_error(ER_TEXTFILE_NOT_READABLE, MYF(0), file_name->c_ptr()); */
9224 -+ goto err;
9225 -+ }
9226 -+ if (stat_info.st_size > (long) current_thd->variables.max_allowed_packet)
9227 -+ {
9228 -+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
9229 -+ ER_WARN_ALLOWED_PACKET_OVERFLOWED,
9230 -+ ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED),
9231 -+ func_name(), current_thd->variables.max_allowed_packet);
9232 -+ goto err;
9233 -+ }
9234 -+ if (tmp_value.alloc(stat_info.st_size))
9235 -+ goto err;
9236 -+ if ((file = my_open(file_name->ptr(), O_RDONLY, MYF(0))) < 0)
9237 -+ goto err;
9238 -+ if (my_read(file, (uchar*) tmp_value.ptr(), stat_info.st_size, MYF(MY_NABP)))
9239 -+ {
9240 -+ my_close(file, MYF(0));
9241 -+ goto err;
9242 -+ }
9243 -+ tmp_value.length(stat_info.st_size);
9244 -+ my_close(file, MYF(0));
9245 -+ null_value = 0;
9246 -+ DBUG_RETURN(&tmp_value);
9247 -+
9248 -+err:
9249 -+ null_value = 1;
9250 -+ DBUG_RETURN(0);
9251 -+}
9252 -+
9253 -+
9254 -+String* Item_func_export_set::val_str(String* str)
9255 -+{
9256 -+ DBUG_ASSERT(fixed == 1);
9257 -+ ulonglong the_set = (ulonglong) args[0]->val_int();
9258 -+ String yes_buf, *yes;
9259 -+ yes = args[1]->val_str(&yes_buf);
9260 -+ String no_buf, *no;
9261 -+ no = args[2]->val_str(&no_buf);
9262 -+ String *sep = NULL, sep_buf ;
9263 -+
9264 -+ uint num_set_values = 64;
9265 -+ ulonglong mask = 0x1;
9266 -+ str->length(0);
9267 -+ str->set_charset(collation.collation);
9268 -+
9269 -+ /* Check if some argument is a NULL value */
9270 -+ if (args[0]->null_value || args[1]->null_value || args[2]->null_value)
9271 -+ {
9272 -+ null_value=1;
9273 -+ return 0;
9274 -+ }
9275 -+ /*
9276 -+ Arg count can only be 3, 4 or 5 here. This is guaranteed from the
9277 -+ grammar for EXPORT_SET()
9278 -+ */
9279 -+ switch(arg_count) {
9280 -+ case 5:
9281 -+ num_set_values = (uint) args[4]->val_int();
9282 -+ if (num_set_values > 64)
9283 -+ num_set_values=64;
9284 -+ if (args[4]->null_value)
9285 -+ {
9286 -+ null_value=1;
9287 -+ return 0;
9288 -+ }
9289 -+ /* Fall through */
9290 -+ case 4:
9291 -+ if (!(sep = args[3]->val_str(&sep_buf))) // Only true if NULL
9292 -+ {
9293 -+ null_value=1;
9294 -+ return 0;
9295 -+ }
9296 -+ break;
9297 -+ case 3:
9298 -+ {
9299 -+ /* errors is not checked - assume "," can always be converted */
9300 -+ uint errors;
9301 -+ sep_buf.copy(STRING_WITH_LEN(","), &my_charset_bin, collation.collation, &errors);
9302 -+ sep = &sep_buf;
9303 -+ }
9304 -+ break;
9305 -+ default:
9306 -+ DBUG_ASSERT(0); // cannot happen
9307 -+ }
9308 -+ null_value=0;
9309 -+
9310 -+ for (uint i = 0; i < num_set_values; i++, mask = (mask << 1))
9311 -+ {
9312 -+ if (the_set & mask)
9313 -+ str->append(*yes);
9314 -+ else
9315 -+ str->append(*no);
9316 -+ if (i != num_set_values - 1)
9317 -+ str->append(*sep);
9318 -+ }
9319 -+ return str;
9320 -+}
9321 -+
9322 -+void Item_func_export_set::fix_length_and_dec()
9323 -+{
9324 -+ uint length=max(args[1]->max_length,args[2]->max_length);
9325 -+ uint sep_length=(arg_count > 3 ? args[3]->max_length : 1);
9326 -+ max_length=length*64+sep_length*63;
9327 -+
9328 -+ if (agg_arg_charsets(collation, args+1, min(4,arg_count)-1,
9329 -+ MY_COLL_ALLOW_CONV, 1))
9330 -+ return;
9331 -+}
9332 -+
9333 -+String* Item_func_inet_ntoa::val_str(String* str)
9334 -+{
9335 -+ DBUG_ASSERT(fixed == 1);
9336 -+ uchar buf[8], *p;
9337 -+ ulonglong n = (ulonglong) args[0]->val_int();
9338 -+ char num[4];
9339 -+
9340 -+ /*
9341 -+ We do not know if args[0] is NULL until we have called
9342 -+ some val function on it if args[0] is not a constant!
9343 -+
9344 -+ Also return null if n > 255.255.255.255
9345 -+ */
9346 -+ if ((null_value= (args[0]->null_value || n > (ulonglong) LL(4294967295))))
9347 -+ return 0; // Null value
9348 -+
9349 -+ str->set_charset(collation.collation);
9350 -+ str->length(0);
9351 -+ int4store(buf,n);
9352 -+
9353 -+ /* Now we can assume little endian. */
9354 -+
9355 -+ num[3]='.';
9356 -+ for (p=buf+4 ; p-- > buf ; )
9357 -+ {
9358 -+ uint c = *p;
9359 -+ uint n1,n2; // Try to avoid divisions
9360 -+ n1= c / 100; // 100 digits
9361 -+ c-= n1*100;
9362 -+ n2= c / 10; // 10 digits
9363 -+ c-=n2*10; // last digit
9364 -+ num[0]=(char) n1+'0';
9365 -+ num[1]=(char) n2+'0';
9366 -+ num[2]=(char) c+'0';
9367 -+ uint length=(n1 ? 4 : n2 ? 3 : 2); // Remove pre-zero
9368 -+
9369 -+ (void) str->append(num+4-length,length);
9370 -+ }
9371 -+ str->length(str->length()-1); // Remove last '.';
9372 -+ return str;
9373 -+}
9374 -+
9375 -+
9376 -+#define get_esc_bit(mask, num) (1 & (*((mask) + ((num) >> 3))) >> ((num) & 7))
9377 -+
9378 -+/**
9379 -+ QUOTE() function returns argument string in single quotes suitable for
9380 -+ using in a SQL statement.
9381 -+
9382 -+ Adds a \\ before all characters that needs to be escaped in a SQL string.
9383 -+ We also escape '^Z' (END-OF-FILE in windows) to avoid probelms when
9384 -+ running commands from a file in windows.
9385 -+
9386 -+ This function is very useful when you want to generate SQL statements.
9387 -+
9388 -+ @note
9389 -+ QUOTE(NULL) returns the string 'NULL' (4 letters, without quotes).
9390 -+
9391 -+ @retval
9392 -+ str Quoted string
9393 -+ @retval
9394 -+ NULL Out of memory.
9395 -+*/
9396 -+
9397 -+String *Item_func_quote::val_str(String *str)
9398 -+{
9399 -+ DBUG_ASSERT(fixed == 1);
9400 -+ /*
9401 -+ Bit mask that has 1 for set for the position of the following characters:
9402 -+ 0, \, ' and ^Z
9403 -+ */
9404 -+
9405 -+ static uchar escmask[32]=
9406 -+ {
9407 -+ 0x01, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x00,
9408 -+ 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
9409 -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9410 -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
9411 -+ };
9412 -+
9413 -+ char *from, *to, *end, *start;
9414 -+ String *arg= args[0]->val_str(str);
9415 -+ uint arg_length, new_length;
9416 -+ if (!arg) // Null argument
9417 -+ {
9418 -+ /* Return the string 'NULL' */
9419 -+ str->copy(STRING_WITH_LEN("NULL"), collation.collation);
9420 -+ null_value= 0;
9421 -+ return str;
9422 -+ }
9423 -+
9424 -+ arg_length= arg->length();
9425 -+
9426 -+ if (collation.collation->mbmaxlen == 1)
9427 -+ {
9428 -+ new_length= arg_length + 2; /* for beginning and ending ' signs */
9429 -+ for (from= (char*) arg->ptr(), end= from + arg_length; from < end; from++)
9430 -+ new_length+= get_esc_bit(escmask, (uchar) *from);
9431 -+ }
9432 -+ else
9433 -+ {
9434 -+ new_length= (arg_length * 2) + /* For string characters */
9435 -+ (2 * collation.collation->mbmaxlen); /* For quotes */
9436 -+ }
9437 -+
9438 -+ if (tmp_value.alloc(new_length))
9439 -+ goto null;
9440 -+
9441 -+ if (collation.collation->mbmaxlen > 1)
9442 -+ {
9443 -+ CHARSET_INFO *cs= collation.collation;
9444 -+ int mblen;
9445 -+ uchar *to_end;
9446 -+ to= (char*) tmp_value.ptr();
9447 -+ to_end= (uchar*) to + new_length;
9448 -+
9449 -+ /* Put leading quote */
9450 -+ if ((mblen= cs->cset->wc_mb(cs, '\'', (uchar *) to, to_end)) <= 0)
9451 -+ goto null;
9452 -+ to+= mblen;
9453 -+
9454 -+ for (start= (char*) arg->ptr(), end= start + arg_length; start < end; )
9455 -+ {
9456 -+ my_wc_t wc;
9457 -+ bool escape;
9458 -+ if ((mblen= cs->cset->mb_wc(cs, &wc, (uchar*) start, (uchar*) end)) <= 0)
9459 -+ goto null;
9460 -+ start+= mblen;
9461 -+ switch (wc) {
9462 -+ case 0: escape= 1; wc= '0'; break;
9463 -+ case '\032': escape= 1; wc= 'Z'; break;
9464 -+ case '\'': escape= 1; break;
9465 -+ case '\\': escape= 1; break;
9466 -+ default: escape= 0; break;
9467 -+ }
9468 -+ if (escape)
9469 -+ {
9470 -+ if ((mblen= cs->cset->wc_mb(cs, '\\', (uchar*) to, to_end)) <= 0)
9471 -+ goto null;
9472 -+ to+= mblen;
9473 -+ }
9474 -+ if ((mblen= cs->cset->wc_mb(cs, wc, (uchar*) to, to_end)) <= 0)
9475 -+ goto null;
9476 -+ to+= mblen;
9477 -+ }
9478 -+
9479 -+ /* Put trailing quote */
9480 -+ if ((mblen= cs->cset->wc_mb(cs, '\'', (uchar *) to, to_end)) <= 0)
9481 -+ goto null;
9482 -+ to+= mblen;
9483 -+ new_length= to - tmp_value.ptr();
9484 -+ goto ret;
9485 -+ }
9486 -+
9487 -+ /*
9488 -+ We replace characters from the end to the beginning
9489 -+ */
9490 -+ to= (char*) tmp_value.ptr() + new_length - 1;
9491 -+ *to--= '\'';
9492 -+ for (start= (char*) arg->ptr(),end= start + arg_length; end-- != start; to--)
9493 -+ {
9494 -+ /*
9495 -+ We can't use the bitmask here as we want to replace \O and ^Z with 0
9496 -+ and Z
9497 -+ */
9498 -+ switch (*end) {
9499 -+ case 0:
9500 -+ *to--= '0';
9501 -+ *to= '\\';
9502 -+ break;
9503 -+ case '\032':
9504 -+ *to--= 'Z';
9505 -+ *to= '\\';
9506 -+ break;
9507 -+ case '\'':
9508 -+ case '\\':
9509 -+ *to--= *end;
9510 -+ *to= '\\';
9511 -+ break;
9512 -+ default:
9513 -+ *to= *end;
9514 -+ break;
9515 -+ }
9516 -+ }
9517 -+ *to= '\'';
9518 -+
9519 -+ret:
9520 -+ tmp_value.length(new_length);
9521 -+ tmp_value.set_charset(collation.collation);
9522 -+ null_value= 0;
9523 -+ return &tmp_value;
9524 -+
9525 -+null:
9526 -+ null_value= 1;
9527 -+ return 0;
9528 -+}
9529 -+
9530 -+longlong Item_func_uncompressed_length::val_int()
9531 -+{
9532 -+ DBUG_ASSERT(fixed == 1);
9533 -+ String *res= args[0]->val_str(&value);
9534 -+ if (!res)
9535 -+ {
9536 -+ null_value=1;
9537 -+ return 0; /* purecov: inspected */
9538 -+ }
9539 -+ null_value=0;
9540 -+ if (res->is_empty()) return 0;
9541 -+
9542 -+ /*
9543 -+ If length is <= 4 bytes, data is corrupt. This is the best we can do
9544 -+ to detect garbage input without decompressing it.
9545 -+ */
9546 -+ if (res->length() <= 4)
9547 -+ {
9548 -+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
9549 -+ ER_ZLIB_Z_DATA_ERROR,
9550 -+ ER(ER_ZLIB_Z_DATA_ERROR));
9551 -+ null_value= 1;
9552 -+ return 0;
9553 -+ }
9554 -+
9555 -+ /*
9556 -+ res->ptr() using is safe because we have tested that string is at least
9557 -+ 5 bytes long.
9558 -+ res->c_ptr() is not used because:
9559 -+ - we do not need \0 terminated string to get first 4 bytes
9560 -+ - c_ptr() tests simbol after string end (uninitialiozed memory) which
9561 -+ confuse valgrind
9562 -+ */
9563 -+ return uint4korr(res->ptr()) & 0x3FFFFFFF;
9564 -+}
9565 -+
9566 -+longlong Item_func_crc32::val_int()
9567 -+{
9568 -+ DBUG_ASSERT(fixed == 1);
9569 -+ String *res=args[0]->val_str(&value);
9570 -+ if (!res)
9571 -+ {
9572 -+ null_value=1;
9573 -+ return 0; /* purecov: inspected */
9574 -+ }
9575 -+ null_value=0;
9576 -+ return (longlong) crc32(0L, (uchar*)res->ptr(), res->length());
9577 -+}
9578 -+
9579 -+#ifdef HAVE_COMPRESS
9580 -+#include "zlib.h"
9581 -+
9582 -+String *Item_func_compress::val_str(String *str)
9583 -+{
9584 -+ int err= Z_OK, code;
9585 -+ ulong new_size;
9586 -+ String *res;
9587 -+ Byte *body;
9588 -+ char *tmp, *last_char;
9589 -+ DBUG_ASSERT(fixed == 1);
9590 -+
9591 -+ if (!(res= args[0]->val_str(str)))
9592 -+ {
9593 -+ null_value= 1;
9594 -+ return 0;
9595 -+ }
9596 -+ null_value= 0;
9597 -+ if (res->is_empty()) return res;
9598 -+
9599 -+ /*
9600 -+ Citation from zlib.h (comment for compress function):
9601 -+
9602 -+ Compresses the source buffer into the destination buffer. sourceLen is
9603 -+ the byte length of the source buffer. Upon entry, destLen is the total
9604 -+ size of the destination buffer, which must be at least 0.1% larger than
9605 -+ sourceLen plus 12 bytes.
9606 -+ We assume here that the buffer can't grow more than .25 %.
9607 -+ */
9608 -+ new_size= res->length() + res->length() / 5 + 12;
9609 -+
9610 -+ // Check new_size overflow: new_size <= res->length()
9611 -+ if (((uint32) (new_size+5) <= res->length()) ||
9612 -+ buffer.realloc((uint32) new_size + 4 + 1))
9613 -+ {
9614 -+ null_value= 1;
9615 -+ return 0;
9616 -+ }
9617 -+
9618 -+ body= ((Byte*)buffer.ptr()) + 4;
9619 -+
9620 -+ // As far as we have checked res->is_empty() we can use ptr()
9621 -+ if ((err= compress(body, &new_size,
9622 -+ (const Bytef*)res->ptr(), res->length())) != Z_OK)
9623 -+ {
9624 -+ code= err==Z_MEM_ERROR ? ER_ZLIB_Z_MEM_ERROR : ER_ZLIB_Z_BUF_ERROR;
9625 -+ push_warning(current_thd,MYSQL_ERROR::WARN_LEVEL_ERROR,code,ER(code));
9626 -+ null_value= 1;
9627 -+ return 0;
9628 -+ }
9629 -+
9630 -+ tmp= (char*)buffer.ptr(); // int4store is a macro; avoid side effects
9631 -+ int4store(tmp, res->length() & 0x3FFFFFFF);
9632 -+
9633 -+ /* This is to ensure that things works for CHAR fields, which trim ' ': */
9634 -+ last_char= ((char*)body)+new_size-1;
9635 -+ if (*last_char == ' ')
9636 -+ {
9637 -+ *++last_char= '.';
9638 -+ new_size++;
9639 -+ }
9640 -+
9641 -+ buffer.length((uint32)new_size + 4);
9642 -+ return &buffer;
9643 -+}
9644 -+
9645 -+
9646 -+String *Item_func_uncompress::val_str(String *str)
9647 -+{
9648 -+ DBUG_ASSERT(fixed == 1);
9649 -+ String *res= args[0]->val_str(str);
9650 -+ ulong new_size;
9651 -+ int err;
9652 -+ uint code;
9653 -+
9654 -+ if (!res)
9655 -+ goto err;
9656 -+ null_value= 0;
9657 -+ if (res->is_empty())
9658 -+ return res;
9659 -+
9660 -+ /* If length is less than 4 bytes, data is corrupt */
9661 -+ if (res->length() <= 4)
9662 -+ {
9663 -+ push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_ERROR,
9664 -+ ER_ZLIB_Z_DATA_ERROR,
9665 -+ ER(ER_ZLIB_Z_DATA_ERROR));
9666 -+ goto err;
9667 -+ }
9668 -+
9669 -+ /* Size of uncompressed data is stored as first 4 bytes of field */
9670 -+ new_size= uint4korr(res->ptr()) & 0x3FFFFFFF;
9671 -+ if (new_size > current_thd->variables.max_allowed_packet)
9672 -+ {
9673 -+ push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_ERROR,
9674 -+ ER_TOO_BIG_FOR_UNCOMPRESS,
9675 -+ ER(ER_TOO_BIG_FOR_UNCOMPRESS),
9676 -+ current_thd->variables.max_allowed_packet);
9677 -+ goto err;
9678 -+ }
9679 -+ if (buffer.realloc((uint32)new_size))
9680 -+ goto err;
9681 -+
9682 -+ if ((err= uncompress((Byte*)buffer.ptr(), &new_size,
9683 -+ ((const Bytef*)res->ptr())+4,res->length())) == Z_OK)
9684 -+ {
9685 -+ buffer.length((uint32) new_size);
9686 -+ return &buffer;
9687 -+ }
9688 -+
9689 -+ code= ((err == Z_BUF_ERROR) ? ER_ZLIB_Z_BUF_ERROR :
9690 -+ ((err == Z_MEM_ERROR) ? ER_ZLIB_Z_MEM_ERROR : ER_ZLIB_Z_DATA_ERROR));
9691 -+ push_warning(current_thd,MYSQL_ERROR::WARN_LEVEL_ERROR,code,ER(code));
9692 -+
9693 -+err:
9694 -+ null_value= 1;
9695 -+ return 0;
9696 -+}
9697 -+#endif
9698 -+
9699 -+/*
9700 -+ UUID, as in
9701 -+ DCE 1.1: Remote Procedure Call,
9702 -+ Open Group Technical Standard Document Number C706, October 1997,
9703 -+ (supersedes C309 DCE: Remote Procedure Call 8/1994,
9704 -+ which was basis for ISO/IEC 11578:1996 specification)
9705 -+*/
9706 -+
9707 -+static struct rand_struct uuid_rand;
9708 -+static uint nanoseq;
9709 -+static ulonglong uuid_time=0;
9710 -+static char clock_seq_and_node_str[]="-0000-000000000000";
9711 -+
9712 -+/**
9713 -+ number of 100-nanosecond intervals between
9714 -+ 1582-10-15 00:00:00.00 and 1970-01-01 00:00:00.00.
9715 -+*/
9716 -+#define UUID_TIME_OFFSET ((ulonglong) 141427 * 24 * 60 * 60 * \
9717 -+ 1000 * 1000 * 10)
9718 -+
9719 -+#define UUID_VERSION 0x1000
9720 -+#define UUID_VARIANT 0x8000
9721 -+
9722 -+static void tohex(char *to, uint from, uint len)
9723 -+{
9724 -+ to+= len;
9725 -+ while (len--)
9726 -+ {
9727 -+ *--to= _dig_vec_lower[from & 15];
9728 -+ from >>= 4;
9729 -+ }
9730 -+}
9731 -+
9732 -+static void set_clock_seq_str()
9733 -+{
9734 -+ uint16 clock_seq= ((uint)(my_rnd(&uuid_rand)*16383)) | UUID_VARIANT;
9735 -+ tohex(clock_seq_and_node_str+1, clock_seq, 4);
9736 -+ nanoseq= 0;
9737 -+}
9738 -+
9739 -+String *Item_func_uuid::val_str(String *str)
9740 -+{
9741 -+ DBUG_ASSERT(fixed == 1);
9742 -+ char *s;
9743 -+ THD *thd= current_thd;
9744 -+
9745 -+ pthread_mutex_lock(&LOCK_uuid_generator);
9746 -+ if (! uuid_time) /* first UUID() call. initializing data */
9747 -+ {
9748 -+ ulong tmp=sql_rnd_with_mutex();
9749 -+ uchar mac[6];
9750 -+ int i;
9751 -+ if (my_gethwaddr(mac))
9752 -+ {
9753 -+ /* purecov: begin inspected */
9754 -+ /*
9755 -+ generating random "hardware addr"
9756 -+ and because specs explicitly specify that it should NOT correlate
9757 -+ with a clock_seq value (initialized random below), we use a separate
9758 -+ randominit() here
9759 -+ */
9760 -+ randominit(&uuid_rand, tmp + (ulong) thd, tmp + (ulong)global_query_id);
9761 -+ for (i=0; i < (int)sizeof(mac); i++)
9762 -+ mac[i]=(uchar)(my_rnd(&uuid_rand)*255);
9763 -+ /* purecov: end */
9764 -+ }
9765 -+ s=clock_seq_and_node_str+sizeof(clock_seq_and_node_str)-1;
9766 -+ for (i=sizeof(mac)-1 ; i>=0 ; i--)
9767 -+ {
9768 -+ *--s=_dig_vec_lower[mac[i] & 15];
9769 -+ *--s=_dig_vec_lower[mac[i] >> 4];
9770 -+ }
9771 -+ randominit(&uuid_rand, tmp + (ulong) server_start_time,
9772 -+ tmp + (ulong) thd->status_var.bytes_sent);
9773 -+ set_clock_seq_str();
9774 -+ }
9775 -+
9776 -+ ulonglong tv= my_getsystime() + UUID_TIME_OFFSET + nanoseq;
9777 -+
9778 -+ if (likely(tv > uuid_time))
9779 -+ {
9780 -+ /*
9781 -+ Current time is ahead of last timestamp, as it should be.
9782 -+ If we "borrowed time", give it back, just as long as we
9783 -+ stay ahead of the previous timestamp.
9784 -+ */
9785 -+ if (nanoseq)
9786 -+ {
9787 -+ DBUG_ASSERT((tv > uuid_time) && (nanoseq > 0));
9788 -+ /*
9789 -+ -1 so we won't make tv= uuid_time for nanoseq >= (tv - uuid_time)
9790 -+ */
9791 -+ ulong delta= min(nanoseq, (ulong) (tv - uuid_time -1));
9792 -+ tv-= delta;
9793 -+ nanoseq-= delta;
9794 -+ }
9795 -+ }
9796 -+ else
9797 -+ {
9798 -+ if (unlikely(tv == uuid_time))
9799 -+ {
9800 -+ /*
9801 -+ For low-res system clocks. If several requests for UUIDs
9802 -+ end up on the same tick, we add a nano-second to make them
9803 -+ different.
9804 -+ ( current_timestamp + nanoseq * calls_in_this_period )
9805 -+ may end up > next_timestamp; this is OK. Nonetheless, we'll
9806 -+ try to unwind nanoseq when we get a chance to.
9807 -+ If nanoseq overflows, we'll start over with a new numberspace
9808 -+ (so the if() below is needed so we can avoid the ++tv and thus
9809 -+ match the follow-up if() if nanoseq overflows!).
9810 -+ */
9811 -+ if (likely(++nanoseq))
9812 -+ ++tv;
9813 -+ }
9814 -+
9815 -+ if (unlikely(tv <= uuid_time))
9816 -+ {
9817 -+ /*
9818 -+ If the admin changes the system clock (or due to Daylight
9819 -+ Saving Time), the system clock may be turned *back* so we
9820 -+ go through a period once more for which we already gave out
9821 -+ UUIDs. To avoid duplicate UUIDs despite potentially identical
9822 -+ times, we make a new random component.
9823 -+ We also come here if the nanoseq "borrowing" overflows.
9824 -+ In either case, we throw away any nanoseq borrowing since it's
9825 -+ irrelevant in the new numberspace.
9826 -+ */
9827 -+ set_clock_seq_str();
9828 -+ tv= my_getsystime() + UUID_TIME_OFFSET;
9829 -+ nanoseq= 0;
9830 -+ DBUG_PRINT("uuid",("making new numberspace"));
9831 -+ }
9832 -+ }
9833 -+
9834 -+ uuid_time=tv;
9835 -+ pthread_mutex_unlock(&LOCK_uuid_generator);
9836 -+
9837 -+ uint32 time_low= (uint32) (tv & 0xFFFFFFFF);
9838 -+ uint16 time_mid= (uint16) ((tv >> 32) & 0xFFFF);
9839 -+ uint16 time_hi_and_version= (uint16) ((tv >> 48) | UUID_VERSION);
9840 -+
9841 -+ str->realloc(UUID_LENGTH+1);
9842 -+ str->length(UUID_LENGTH);
9843 -+ str->set_charset(system_charset_info);
9844 -+ s=(char *) str->ptr();
9845 -+ s[8]=s[13]='-';
9846 -+ tohex(s, time_low, 8);
9847 -+ tohex(s+9, time_mid, 4);
9848 -+ tohex(s+14, time_hi_and_version, 4);
9849 -+ strmov(s+18, clock_seq_and_node_str);
9850 -+ return str;
9851 -+}
9852 -diff -urN mysql-old/sql/item_strfunc.h.orig mysql/sql/item_strfunc.h.orig
9853 ---- mysql-old/sql/item_strfunc.h.orig 1969-12-31 23:00:00.000000000 -0100
9854 -+++ mysql/sql/item_strfunc.h.orig 2011-04-12 12:11:38.000000000 +0000
9855 -@@ -0,0 +1,868 @@
9856 -+/* Copyright (C) 2000-2003 MySQL AB
9857 -+
9858 -+ This program is free software; you can redistribute it and/or modify
9859 -+ it under the terms of the GNU General Public License as published by
9860 -+ the Free Software Foundation; version 2 of the License.
9861 -+
9862 -+ This program is distributed in the hope that it will be useful,
9863 -+ but WITHOUT ANY WARRANTY; without even the implied warranty of
9864 -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9865 -+ GNU General Public License for more details.
9866 -+
9867 -+ You should have received a copy of the GNU General Public License
9868 -+ along with this program; if not, write to the Free Software
9869 -+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
9870 -+
9871 -+
9872 -+/* This file defines all string functions */
9873 -+
9874 -+#ifdef USE_PRAGMA_INTERFACE
9875 -+#pragma interface /* gcc class implementation */
9876 -+#endif
9877 -+
9878 -+class Item_str_func :public Item_func
9879 -+{
9880 -+protected:
9881 -+ /**
9882 -+ Sets the result value of the function an empty string, using the current
9883 -+ character set. No memory is allocated.
9884 -+ @retval A pointer to the str_value member.
9885 -+ */
9886 -+ String *make_empty_result() {
9887 -+ str_value.set("", 0, collation.collation);
9888 -+ return &str_value;
9889 -+ }
9890 -+public:
9891 -+ Item_str_func() :Item_func() { decimals=NOT_FIXED_DEC; }
9892 -+ Item_str_func(Item *a) :Item_func(a) {decimals=NOT_FIXED_DEC; }
9893 -+ Item_str_func(Item *a,Item *b) :Item_func(a,b) { decimals=NOT_FIXED_DEC; }
9894 -+ Item_str_func(Item *a,Item *b,Item *c) :Item_func(a,b,c) { decimals=NOT_FIXED_DEC; }
9895 -+ Item_str_func(Item *a,Item *b,Item *c,Item *d) :Item_func(a,b,c,d) {decimals=NOT_FIXED_DEC; }
9896 -+ Item_str_func(Item *a,Item *b,Item *c,Item *d, Item* e) :Item_func(a,b,c,d,e) {decimals=NOT_FIXED_DEC; }
9897 -+ Item_str_func(List<Item> &list) :Item_func(list) {decimals=NOT_FIXED_DEC; }
9898 -+ longlong val_int();
9899 -+ double val_real();
9900 -+ my_decimal *val_decimal(my_decimal *);
9901 -+ enum Item_result result_type () const { return STRING_RESULT; }
9902 -+ void left_right_max_length();
9903 -+ bool fix_fields(THD *thd, Item **ref);
9904 -+};
9905 -+
9906 -+class Item_func_md5 :public Item_str_func
9907 -+{
9908 -+ String tmp_value;
9909 -+public:
9910 -+ Item_func_md5(Item *a) :Item_str_func(a)
9911 -+ {
9912 -+ collation.set(&my_charset_bin);
9913 -+ }
9914 -+ String *val_str(String *);
9915 -+ void fix_length_and_dec();
9916 -+ const char *func_name() const { return "md5"; }
9917 -+};
9918 -+
9919 -+
9920 -+class Item_func_sha :public Item_str_func
9921 -+{
9922 -+public:
9923 -+ Item_func_sha(Item *a) :Item_str_func(a)
9924 -+ {
9925 -+ collation.set(&my_charset_bin);
9926 -+ }
9927 -+ String *val_str(String *);
9928 -+ void fix_length_and_dec();
9929 -+ const char *func_name() const { return "sha"; }
9930 -+};
9931 -+
9932 -+class Item_func_aes_encrypt :public Item_str_func
9933 -+{
9934 -+public:
9935 -+ Item_func_aes_encrypt(Item *a, Item *b) :Item_str_func(a,b) {}
9936 -+ String *val_str(String *);
9937 -+ void fix_length_and_dec();
9938 -+ const char *func_name() const { return "aes_encrypt"; }
9939 -+};
9940 -+
9941 -+class Item_func_aes_decrypt :public Item_str_func
9942 -+{
9943 -+public:
9944 -+ Item_func_aes_decrypt(Item *a, Item *b) :Item_str_func(a,b) {}
9945 -+ String *val_str(String *);
9946 -+ void fix_length_and_dec();
9947 -+ const char *func_name() const { return "aes_decrypt"; }
9948 -+};
9949 -+
9950 -+
9951 -+class Item_func_concat :public Item_str_func
9952 -+{
9953 -+ String tmp_value;
9954 -+public:
9955 -+ Item_func_concat(List<Item> &list) :Item_str_func(list) {}
9956 -+ Item_func_concat(Item *a,Item *b) :Item_str_func(a,b) {}
9957 -+ String *val_str(String *);
9958 -+ void fix_length_and_dec();
9959 -+ const char *func_name() const { return "concat"; }
9960 -+};
9961 -+
9962 -+class Item_func_concat_ws :public Item_str_func
9963 -+{
9964 -+ String tmp_value;
9965 -+public:
9966 -+ Item_func_concat_ws(List<Item> &list) :Item_str_func(list) {}
9967 -+ String *val_str(String *);
9968 -+ void fix_length_and_dec();
9969 -+ const char *func_name() const { return "concat_ws"; }
9970 -+ table_map not_null_tables() const { return 0; }
9971 -+};
9972 -+
9973 -+class Item_func_reverse :public Item_str_func
9974 -+{
9975 -+ String tmp_value;
9976 -+public:
9977 -+ Item_func_reverse(Item *a) :Item_str_func(a) {}
9978 -+ String *val_str(String *);
9979 -+ void fix_length_and_dec();
9980 -+ const char *func_name() const { return "reverse"; }
9981 -+};
9982 -+
9983 -+
9984 -+class Item_func_replace :public Item_str_func
9985 -+{
9986 -+ String tmp_value,tmp_value2;
9987 -+public:
9988 -+ Item_func_replace(Item *org,Item *find,Item *replace)
9989 -+ :Item_str_func(org,find,replace) {}
9990 -+ String *val_str(String *);
9991 -+ void fix_length_and_dec();
9992 -+ const char *func_name() const { return "replace"; }
9993 -+};
9994 -+
9995 -+
9996 -+class Item_func_insert :public Item_str_func
9997 -+{
9998 -+ String tmp_value;
9999 -+public:
10000 -+ Item_func_insert(Item *org,Item *start,Item *length,Item *new_str)
10001 -+ :Item_str_func(org,start,length,new_str) {}
10002 -+ String *val_str(String *);
10003 -+ void fix_length_and_dec();
10004 -+ const char *func_name() const { return "insert"; }
10005 -+};
10006 -+
10007 -+
10008 -+class Item_str_conv :public Item_str_func
10009 -+{
10010 -+protected:
10011 -+ uint multiply;
10012 -+ my_charset_conv_case converter;
10013 -+ String tmp_value;
10014 -+public:
10015 -+ Item_str_conv(Item *item) :Item_str_func(item) {}
10016 -+ String *val_str(String *);
10017 -+};
10018 -+
10019 -+
10020 -+class Item_func_lcase :public Item_str_conv
10021 -+{
10022 -+public:
10023 -+ Item_func_lcase(Item *item) :Item_str_conv(item) {}
10024 -+ const char *func_name() const { return "lcase"; }
10025 -+ void fix_length_and_dec();
10026 -+};
10027 -+
10028 -+class Item_func_ucase :public Item_str_conv
10029 -+{
10030 -+public:
10031 -+ Item_func_ucase(Item *item) :Item_str_conv(item) {}
10032 -+ const char *func_name() const { return "ucase"; }
10033 -+ void fix_length_and_dec();
10034 -+};
10035 -+
10036 -+
10037 -+class Item_func_left :public Item_str_func
10038 -+{
10039 -+ String tmp_value;
10040 -+public:
10041 -+ Item_func_left(Item *a,Item *b) :Item_str_func(a,b) {}
10042 -+ String *val_str(String *);
10043 -+ void fix_length_and_dec();
10044 -+ const char *func_name() const { return "left"; }
10045 -+};
10046 -+
10047 -+
10048 -+class Item_func_right :public Item_str_func
10049 -+{
10050 -+ String tmp_value;
10051 -+public:
10052 -+ Item_func_right(Item *a,Item *b) :Item_str_func(a,b) {}
10053 -+ String *val_str(String *);
10054 -+ void fix_length_and_dec();
10055 -+ const char *func_name() const { return "right"; }
10056 -+};
10057 -+
10058 -+
10059 -+class Item_func_substr :public Item_str_func
10060 -+{
10061 -+ String tmp_value;
10062 -+public:
10063 -+ Item_func_substr(Item *a,Item *b) :Item_str_func(a,b) {}
10064 -+ Item_func_substr(Item *a,Item *b,Item *c) :Item_str_func(a,b,c) {}
10065 -+ String *val_str(String *);
10066 -+ void fix_length_and_dec();
10067 -+ const char *func_name() const { return "substr"; }
10068 -+};
10069 -+
10070 -+
10071 -+class Item_func_substr_index :public Item_str_func
10072 -+{
10073 -+ String tmp_value;
10074 -+public:
10075 -+ Item_func_substr_index(Item *a,Item *b,Item *c) :Item_str_func(a,b,c) {}
10076 -+ String *val_str(String *);
10077 -+ void fix_length_and_dec();
10078 -+ const char *func_name() const { return "substring_index"; }
10079 -+};
10080 -+
10081 -+
10082 -+class Item_func_trim :public Item_str_func
10083 -+{
10084 -+protected:
10085 -+ String tmp_value;
10086 -+ String remove;
10087 -+public:
10088 -+ Item_func_trim(Item *a,Item *b) :Item_str_func(a,b) {}
10089 -+ Item_func_trim(Item *a) :Item_str_func(a) {}
10090 -+ String *val_str(String *);
10091 -+ void fix_length_and_dec();
10092 -+ const char *func_name() const { return "trim"; }
10093 -+ virtual void print(String *str, enum_query_type query_type);
10094 -+ virtual const char *mode_name() const { return "both"; }
10095 -+};
10096 -+
10097 -+
10098 -+class Item_func_ltrim :public Item_func_trim
10099 -+{
10100 -+public:
10101 -+ Item_func_ltrim(Item *a,Item *b) :Item_func_trim(a,b) {}
10102 -+ Item_func_ltrim(Item *a) :Item_func_trim(a) {}
10103 -+ String *val_str(String *);
10104 -+ const char *func_name() const { return "ltrim"; }
10105 -+ const char *mode_name() const { return "leading"; }
10106 -+};
10107 -+
10108 -+
10109 -+class Item_func_rtrim :public Item_func_trim
10110 -+{
10111 -+public:
10112 -+ Item_func_rtrim(Item *a,Item *b) :Item_func_trim(a,b) {}
10113 -+ Item_func_rtrim(Item *a) :Item_func_trim(a) {}
10114 -+ String *val_str(String *);
10115 -+ const char *func_name() const { return "rtrim"; }
10116 -+ const char *mode_name() const { return "trailing"; }
10117 -+};
10118 -+
10119 -+
10120 -+/*
10121 -+ Item_func_password -- new (4.1.1) PASSWORD() function implementation.
10122 -+ Returns strcat('*', octet2hex(sha1(sha1(password)))). '*' stands for new
10123 -+ password format, sha1(sha1(password) is so-called hash_stage2 value.
10124 -+ Length of returned string is always 41 byte. To find out how entire
10125 -+ authentication procedure works, see comments in password.c.
10126 -+*/
10127 -+
10128 -+class Item_func_password :public Item_str_func
10129 -+{
10130 -+ char tmp_value[SCRAMBLED_PASSWORD_CHAR_LENGTH+1];
10131 -+public:
10132 -+ Item_func_password(Item *a) :Item_str_func(a) {}
10133 -+ String *val_str(String *str);
10134 -+ void fix_length_and_dec() { max_length= SCRAMBLED_PASSWORD_CHAR_LENGTH; }
10135 -+ const char *func_name() const { return "password"; }
10136 -+ static char *alloc(THD *thd, const char *password, size_t pass_len);
10137 -+};
10138 -+
10139 -+
10140 -+/*
10141 -+ Item_func_old_password -- PASSWORD() implementation used in MySQL 3.21 - 4.0
10142 -+ compatibility mode. This item is created in sql_yacc.yy when
10143 -+ 'old_passwords' session variable is set, and to handle OLD_PASSWORD()
10144 -+ function.
10145 -+*/
10146 -+
10147 -+class Item_func_old_password :public Item_str_func
10148 -+{
10149 -+ char tmp_value[SCRAMBLED_PASSWORD_CHAR_LENGTH_323+1];
10150 -+public:
10151 -+ Item_func_old_password(Item *a) :Item_str_func(a) {}
10152 -+ String *val_str(String *str);
10153 -+ void fix_length_and_dec() { max_length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323; }
10154 -+ const char *func_name() const { return "old_password"; }
10155 -+ static char *alloc(THD *thd, const char *password, size_t pass_len);
10156 -+};
10157 -+
10158 -+
10159 -+class Item_func_des_encrypt :public Item_str_func
10160 -+{
10161 -+ String tmp_value,tmp_arg;
10162 -+public:
10163 -+ Item_func_des_encrypt(Item *a) :Item_str_func(a) {}
10164 -+ Item_func_des_encrypt(Item *a, Item *b): Item_str_func(a,b) {}
10165 -+ String *val_str(String *);
10166 -+ void fix_length_and_dec()
10167 -+ {
10168 -+ maybe_null=1;
10169 -+ /* 9 = MAX ((8- (arg_len % 8)) + 1) */
10170 -+ max_length = args[0]->max_length + 9;
10171 -+ }
10172 -+ const char *func_name() const { return "des_encrypt"; }
10173 -+};
10174 -+
10175 -+class Item_func_des_decrypt :public Item_str_func
10176 -+{
10177 -+ String tmp_value;
10178 -+public:
10179 -+ Item_func_des_decrypt(Item *a) :Item_str_func(a) {}
10180 -+ Item_func_des_decrypt(Item *a, Item *b): Item_str_func(a,b) {}
10181 -+ String *val_str(String *);
10182 -+ void fix_length_and_dec()
10183 -+ {
10184 -+ maybe_null=1;
10185 -+ /* 9 = MAX ((8- (arg_len % 8)) + 1) */
10186 -+ max_length = args[0]->max_length - 9;
10187 -+ }
10188 -+ const char *func_name() const { return "des_decrypt"; }
10189 -+};
10190 -+
10191 -+class Item_func_encrypt :public Item_str_func
10192 -+{
10193 -+ String tmp_value;
10194 -+
10195 -+ /* Encapsulate common constructor actions */
10196 -+ void constructor_helper()
10197 -+ {
10198 -+ collation.set(&my_charset_bin);
10199 -+ }
10200 -+public:
10201 -+ Item_func_encrypt(Item *a) :Item_str_func(a)
10202 -+ {
10203 -+ constructor_helper();
10204 -+ }
10205 -+ Item_func_encrypt(Item *a, Item *b): Item_str_func(a,b)
10206 -+ {
10207 -+ constructor_helper();
10208 -+ }
10209 -+ String *val_str(String *);
10210 -+ void fix_length_and_dec() { maybe_null=1; max_length = 13; }
10211 -+ const char *func_name() const { return "encrypt"; }
10212 -+};
10213 -+
10214 -+#include "sql_crypt.h"
10215 -+
10216 -+
10217 -+class Item_func_encode :public Item_str_func
10218 -+{
10219 -+private:
10220 -+ /** Whether the PRNG has already been seeded. */
10221 -+ bool seeded;
10222 -+protected:
10223 -+ SQL_CRYPT sql_crypt;
10224 -+public:
10225 -+ Item_func_encode(Item *a, Item *seed):
10226 -+ Item_str_func(a, seed) {}
10227 -+ String *val_str(String *);
10228 -+ void fix_length_and_dec();
10229 -+ const char *func_name() const { return "encode"; }
10230 -+protected:
10231 -+ virtual void crypto_transform(String *);
10232 -+private:
10233 -+ /** Provide a seed for the PRNG sequence. */
10234 -+ bool seed();
10235 -+};
10236 -+
10237 -+
10238 -+class Item_func_decode :public Item_func_encode
10239 -+{
10240 -+public:
10241 -+ Item_func_decode(Item *a, Item *seed): Item_func_encode(a, seed) {}
10242 -+ const char *func_name() const { return "decode"; }
10243 -+protected:
10244 -+ void crypto_transform(String *);
10245 -+};
10246 -+
10247 -+
10248 -+class Item_func_sysconst :public Item_str_func
10249 -+{
10250 -+public:
10251 -+ Item_func_sysconst()
10252 -+ { collation.set(system_charset_info,DERIVATION_SYSCONST); }
10253 -+ Item *safe_charset_converter(CHARSET_INFO *tocs);
10254 -+ /*
10255 -+ Used to create correct Item name in new converted item in
10256 -+ safe_charset_converter, return string representation of this function
10257 -+ call
10258 -+ */
10259 -+ virtual const char *fully_qualified_func_name() const = 0;
10260 -+};
10261 -+
10262 -+
10263 -+class Item_func_database :public Item_func_sysconst
10264 -+{
10265 -+public:
10266 -+ Item_func_database() :Item_func_sysconst() {}
10267 -+ String *val_str(String *);
10268 -+ void fix_length_and_dec()
10269 -+ {
10270 -+ max_length= MAX_FIELD_NAME * system_charset_info->mbmaxlen;
10271 -+ maybe_null=1;
10272 -+ }
10273 -+ const char *func_name() const { return "database"; }
10274 -+ const char *fully_qualified_func_name() const { return "database()"; }
10275 -+};
10276 -+
10277 -+
10278 -+class Item_func_user :public Item_func_sysconst
10279 -+{
10280 -+protected:
10281 -+ bool init (const char *user, const char *host);
10282 -+
10283 -+public:
10284 -+ Item_func_user()
10285 -+ {
10286 -+ str_value.set("", 0, system_charset_info);
10287 -+ }
10288 -+ String *val_str(String *)
10289 -+ {
10290 -+ DBUG_ASSERT(fixed == 1);
10291 -+ return (null_value ? 0 : &str_value);
10292 -+ }
10293 -+ bool fix_fields(THD *thd, Item **ref);
10294 -+ void fix_length_and_dec()
10295 -+ {
10296 -+ max_length= (USERNAME_LENGTH +
10297 -+ (HOSTNAME_LENGTH + 1) * SYSTEM_CHARSET_MBMAXLEN);
10298 -+ }
10299 -+ const char *func_name() const { return "user"; }
10300 -+ const char *fully_qualified_func_name() const { return "user()"; }
10301 -+ int save_in_field(Field *field, bool no_conversions)
10302 -+ {
10303 -+ return save_str_value_in_field(field, &str_value);
10304 -+ }
10305 -+};
10306 -+
10307 -+
10308 -+class Item_func_current_user :public Item_func_user
10309 -+{
10310 -+ Name_resolution_context *context;
10311 -+
10312 -+public:
10313 -+ Item_func_current_user(Name_resolution_context *context_arg)
10314 -+ : context(context_arg) {}
10315 -+ bool fix_fields(THD *thd, Item **ref);
10316 -+ const char *func_name() const { return "current_user"; }
10317 -+ const char *fully_qualified_func_name() const { return "current_user()"; }
10318 -+};
10319 -+
10320 -+
10321 -+class Item_func_soundex :public Item_str_func
10322 -+{
10323 -+ String tmp_value;
10324 -+public:
10325 -+ Item_func_soundex(Item *a) :Item_str_func(a) {}
10326 -+ String *val_str(String *);
10327 -+ void fix_length_and_dec();
10328 -+ const char *func_name() const { return "soundex"; }
10329 -+};
10330 -+
10331 -+
10332 -+class Item_func_elt :public Item_str_func
10333 -+{
10334 -+public:
10335 -+ Item_func_elt(List<Item> &list) :Item_str_func(list) {}
10336 -+ double val_real();
10337 -+ longlong val_int();
10338 -+ String *val_str(String *str);
10339 -+ void fix_length_and_dec();
10340 -+ const char *func_name() const { return "elt"; }
10341 -+};
10342 -+
10343 -+
10344 -+class Item_func_make_set :public Item_str_func
10345 -+{
10346 -+ Item *item;
10347 -+ String tmp_str;
10348 -+
10349 -+public:
10350 -+ Item_func_make_set(Item *a,List<Item> &list) :Item_str_func(list),item(a) {}
10351 -+ String *val_str(String *str);
10352 -+ bool fix_fields(THD *thd, Item **ref)
10353 -+ {
10354 -+ DBUG_ASSERT(fixed == 0);
10355 -+ return ((!item->fixed && item->fix_fields(thd, &item)) ||
10356 -+ item->check_cols(1) ||
10357 -+ Item_func::fix_fields(thd, ref));
10358 -+ }
10359 -+ void split_sum_func(THD *thd, Item **ref_pointer_array, List<Item> &fields);
10360 -+ void fix_length_and_dec();
10361 -+ void update_used_tables();
10362 -+ const char *func_name() const { return "make_set"; }
10363 -+
10364 -+ bool walk(Item_processor processor, bool walk_subquery, uchar *arg)
10365 -+ {
10366 -+ return item->walk(processor, walk_subquery, arg) ||
10367 -+ Item_str_func::walk(processor, walk_subquery, arg);
10368 -+ }
10369 -+ Item *transform(Item_transformer transformer, uchar *arg);
10370 -+ virtual void print(String *str, enum_query_type query_type);
10371 -+};
10372 -+
10373 -+
10374 -+class Item_func_format :public Item_str_func
10375 -+{
10376 -+ String tmp_str;
10377 -+public:
10378 -+ Item_func_format(Item *org, Item *dec);
10379 -+ String *val_str(String *);
10380 -+ void fix_length_and_dec();
10381 -+ const char *func_name() const { return "format"; }
10382 -+ virtual void print(String *str, enum_query_type query_type);
10383 -+};
10384 -+
10385 -+
10386 -+class Item_func_char :public Item_str_func
10387 -+{
10388 -+public:
10389 -+ Item_func_char(List<Item> &list) :Item_str_func(list)
10390 -+ { collation.set(&my_charset_bin); }
10391 -+ Item_func_char(List<Item> &list, CHARSET_INFO *cs) :Item_str_func(list)
10392 -+ { collation.set(cs); }
10393 -+ String *val_str(String *);
10394 -+ void fix_length_and_dec()
10395 -+ {
10396 -+ max_length= arg_count * 4;
10397 -+ }
10398 -+ const char *func_name() const { return "char"; }
10399 -+};
10400 -+
10401 -+
10402 -+class Item_func_repeat :public Item_str_func
10403 -+{
10404 -+ String tmp_value;
10405 -+public:
10406 -+ Item_func_repeat(Item *arg1,Item *arg2) :Item_str_func(arg1,arg2) {}
10407 -+ String *val_str(String *);
10408 -+ void fix_length_and_dec();
10409 -+ const char *func_name() const { return "repeat"; }
10410 -+};
10411 -+
10412 -+
10413 -+class Item_func_rpad :public Item_str_func
10414 -+{
10415 -+ String tmp_value, rpad_str;
10416 -+public:
10417 -+ Item_func_rpad(Item *arg1,Item *arg2,Item *arg3)
10418 -+ :Item_str_func(arg1,arg2,arg3) {}
10419 -+ String *val_str(String *);
10420 -+ void fix_length_and_dec();
10421 -+ const char *func_name() const { return "rpad"; }
10422 -+};
10423 -+
10424 -+
10425 -+class Item_func_lpad :public Item_str_func
10426 -+{
10427 -+ String tmp_value, lpad_str;
10428 -+public:
10429 -+ Item_func_lpad(Item *arg1,Item *arg2,Item *arg3)
10430 -+ :Item_str_func(arg1,arg2,arg3) {}
10431 -+ String *val_str(String *);
10432 -+ void fix_length_and_dec();
10433 -+ const char *func_name() const { return "lpad"; }
10434 -+};
10435 -+
10436 -+
10437 -+class Item_func_conv :public Item_str_func
10438 -+{
10439 -+public:
10440 -+ Item_func_conv(Item *a,Item *b,Item *c) :Item_str_func(a,b,c) {}
10441 -+ const char *func_name() const { return "conv"; }
10442 -+ String *val_str(String *);
10443 -+ void fix_length_and_dec()
10444 -+ {
10445 -+ collation.set(default_charset());
10446 -+ max_length=64;
10447 -+ maybe_null= 1;
10448 -+ }
10449 -+};
10450 -+
10451 -+
10452 -+class Item_func_hex :public Item_str_func
10453 -+{
10454 -+ String tmp_value;
10455 -+public:
10456 -+ Item_func_hex(Item *a) :Item_str_func(a) {}
10457 -+ const char *func_name() const { return "hex"; }
10458 -+ String *val_str(String *);
10459 -+ void fix_length_and_dec()
10460 -+ {
10461 -+ collation.set(default_charset());
10462 -+ decimals=0;
10463 -+ max_length=args[0]->max_length*2*collation.collation->mbmaxlen;
10464 -+ }
10465 -+};
10466 -+
10467 -+class Item_func_unhex :public Item_str_func
10468 -+{
10469 -+ String tmp_value;
10470 -+public:
10471 -+ Item_func_unhex(Item *a) :Item_str_func(a)
10472 -+ {
10473 -+ /* there can be bad hex strings */
10474 -+ maybe_null= 1;
10475 -+ }
10476 -+ const char *func_name() const { return "unhex"; }
10477 -+ String *val_str(String *);
10478 -+ void fix_length_and_dec()
10479 -+ {
10480 -+ collation.set(&my_charset_bin);
10481 -+ decimals=0;
10482 -+ max_length=(1+args[0]->max_length)/2;
10483 -+ }
10484 -+};
10485 -+
10486 -+
10487 -+class Item_func_binary :public Item_str_func
10488 -+{
10489 -+public:
10490 -+ Item_func_binary(Item *a) :Item_str_func(a) {}
10491 -+ String *val_str(String *a)
10492 -+ {
10493 -+ DBUG_ASSERT(fixed == 1);
10494 -+ String *tmp=args[0]->val_str(a);
10495 -+ null_value=args[0]->null_value;
10496 -+ if (tmp)
10497 -+ tmp->set_charset(&my_charset_bin);
10498 -+ return tmp;
10499 -+ }
10500 -+ void fix_length_and_dec()
10501 -+ {
10502 -+ collation.set(&my_charset_bin);
10503 -+ max_length=args[0]->max_length;
10504 -+ }
10505 -+ virtual void print(String *str, enum_query_type query_type);
10506 -+ const char *func_name() const { return "cast_as_binary"; }
10507 -+};
10508 -+
10509 -+
10510 -+class Item_load_file :public Item_str_func
10511 -+{
10512 -+ String tmp_value;
10513 -+public:
10514 -+ Item_load_file(Item *a) :Item_str_func(a) {}
10515 -+ String *val_str(String *);
10516 -+ const char *func_name() const { return "load_file"; }
10517 -+ void fix_length_and_dec()
10518 -+ {
10519 -+ collation.set(&my_charset_bin, DERIVATION_COERCIBLE);
10520 -+ maybe_null=1;
10521 -+ max_length=MAX_BLOB_WIDTH;
10522 -+ }
10523 -+};
10524 -+
10525 -+
10526 -+class Item_func_export_set: public Item_str_func
10527 -+{
10528 -+ public:
10529 -+ Item_func_export_set(Item *a,Item *b,Item* c) :Item_str_func(a,b,c) {}
10530 -+ Item_func_export_set(Item *a,Item *b,Item* c,Item* d) :Item_str_func(a,b,c,d) {}
10531 -+ Item_func_export_set(Item *a,Item *b,Item* c,Item* d,Item* e) :Item_str_func(a,b,c,d,e) {}
10532 -+ String *val_str(String *str);
10533 -+ void fix_length_and_dec();
10534 -+ const char *func_name() const { return "export_set"; }
10535 -+};
10536 -+
10537 -+class Item_func_inet_ntoa : public Item_str_func
10538 -+{
10539 -+public:
10540 -+ Item_func_inet_ntoa(Item *a) :Item_str_func(a)
10541 -+ {
10542 -+ }
10543 -+ String* val_str(String* str);
10544 -+ const char *func_name() const { return "inet_ntoa"; }
10545 -+ void fix_length_and_dec()
10546 -+ {
10547 -+ decimals= 0;
10548 -+ max_length= 3 * 8 + 7;
10549 -+ maybe_null= 1;
10550 -+ }
10551 -+};
10552 -+
10553 -+class Item_func_quote :public Item_str_func
10554 -+{
10555 -+ String tmp_value;
10556 -+public:
10557 -+ Item_func_quote(Item *a) :Item_str_func(a) {}
10558 -+ const char *func_name() const { return "quote"; }
10559 -+ String *val_str(String *);
10560 -+ void fix_length_and_dec()
10561 -+ {
10562 -+ collation.set(args[0]->collation);
10563 -+ ulonglong max_result_length= (ulonglong) args[0]->max_length * 2 +
10564 -+ 2 * collation.collation->mbmaxlen;
10565 -+ max_length= (uint32) min(max_result_length, MAX_BLOB_WIDTH);
10566 -+ }
10567 -+};
10568 -+
10569 -+class Item_func_conv_charset :public Item_str_func
10570 -+{
10571 -+ bool use_cached_value;
10572 -+ String tmp_value;
10573 -+public:
10574 -+ bool safe;
10575 -+ CHARSET_INFO *conv_charset; // keep it public
10576 -+ Item_func_conv_charset(Item *a, CHARSET_INFO *cs) :Item_str_func(a)
10577 -+ { conv_charset= cs; use_cached_value= 0; safe= 0; }
10578 -+ Item_func_conv_charset(Item *a, CHARSET_INFO *cs, bool cache_if_const)
10579 -+ :Item_str_func(a)
10580 -+ {
10581 -+ DBUG_ASSERT(args[0]->fixed);
10582 -+ conv_charset= cs;
10583 -+ if (cache_if_const && args[0]->const_item())
10584 -+ {
10585 -+ uint errors= 0;
10586 -+ String tmp, *str= args[0]->val_str(&tmp);
10587 -+ if (!str || str_value.copy(str->ptr(), str->length(),
10588 -+ str->charset(), conv_charset, &errors))
10589 -+ null_value= 1;
10590 -+ use_cached_value= 1;
10591 -+ str_value.mark_as_const();
10592 -+ safe= (errors == 0);
10593 -+ }
10594 -+ else
10595 -+ {
10596 -+ use_cached_value= 0;
10597 -+ /*
10598 -+ Conversion from and to "binary" is safe.
10599 -+ Conversion to Unicode is safe.
10600 -+ Other kind of conversions are potentially lossy.
10601 -+ */
10602 -+ safe= (args[0]->collation.collation == &my_charset_bin ||
10603 -+ cs == &my_charset_bin ||
10604 -+ (cs->state & MY_CS_UNICODE));
10605 -+ }
10606 -+ }
10607 -+ String *val_str(String *);
10608 -+ void fix_length_and_dec();
10609 -+ const char *func_name() const { return "convert"; }
10610 -+ virtual void print(String *str, enum_query_type query_type);
10611 -+};
10612 -+
10613 -+class Item_func_set_collation :public Item_str_func
10614 -+{
10615 -+public:
10616 -+ Item_func_set_collation(Item *a, Item *b) :Item_str_func(a,b) {};
10617 -+ String *val_str(String *);
10618 -+ void fix_length_and_dec();
10619 -+ bool eq(const Item *item, bool binary_cmp) const;
10620 -+ const char *func_name() const { return "collate"; }
10621 -+ enum Functype functype() const { return COLLATE_FUNC; }
10622 -+ virtual void print(String *str, enum_query_type query_type);
10623 -+ Item_field *filed_for_view_update()
10624 -+ {
10625 -+ /* this function is transparent for view updating */
10626 -+ return args[0]->filed_for_view_update();
10627 -+ }
10628 -+};
10629 -+
10630 -+class Item_func_charset :public Item_str_func
10631 -+{
10632 -+public:
10633 -+ Item_func_charset(Item *a) :Item_str_func(a) {}
10634 -+ String *val_str(String *);
10635 -+ const char *func_name() const { return "charset"; }
10636 -+ void fix_length_and_dec()
10637 -+ {
10638 -+ collation.set(system_charset_info);
10639 -+ max_length= 64 * collation.collation->mbmaxlen; // should be enough
10640 -+ maybe_null= 0;
10641 -+ };
10642 -+ table_map not_null_tables() const { return 0; }
10643 -+};
10644 -+
10645 -+class Item_func_collation :public Item_str_func
10646 -+{
10647 -+public:
10648 -+ Item_func_collation(Item *a) :Item_str_func(a) {}
10649 -+ String *val_str(String *);
10650 -+ const char *func_name() const { return "collation"; }
10651 -+ void fix_length_and_dec()
10652 -+ {
10653 -+ collation.set(system_charset_info);
10654 -+ max_length= 64 * collation.collation->mbmaxlen; // should be enough
10655 -+ maybe_null= 0;
10656 -+ };
10657 -+ table_map not_null_tables() const { return 0; }
10658 -+};
10659 -+
10660 -+class Item_func_crc32 :public Item_int_func
10661 -+{
10662 -+ String value;
10663 -+public:
10664 -+ Item_func_crc32(Item *a) :Item_int_func(a) { unsigned_flag= 1; }
10665 -+ const char *func_name() const { return "crc32"; }
10666 -+ void fix_length_and_dec() { max_length=10; }
10667 -+ longlong val_int();
10668 -+};
10669 -+
10670 -+class Item_func_uncompressed_length : public Item_int_func
10671 -+{
10672 -+ String value;
10673 -+public:
10674 -+ Item_func_uncompressed_length(Item *a):Item_int_func(a){}
10675 -+ const char *func_name() const{return "uncompressed_length";}
10676 -+ void fix_length_and_dec() { max_length=10; }
10677 -+ longlong val_int();
10678 -+};
10679 -+
10680 -+#ifdef HAVE_COMPRESS
10681 -+#define ZLIB_DEPENDED_FUNCTION ;
10682 -+#else
10683 -+#define ZLIB_DEPENDED_FUNCTION { null_value=1; return 0; }
10684 -+#endif
10685 -+
10686 -+class Item_func_compress: public Item_str_func
10687 -+{
10688 -+ String buffer;
10689 -+public:
10690 -+ Item_func_compress(Item *a):Item_str_func(a){}
10691 -+ void fix_length_and_dec(){max_length= (args[0]->max_length*120)/100+12;}
10692 -+ const char *func_name() const{return "compress";}
10693 -+ String *val_str(String *) ZLIB_DEPENDED_FUNCTION
10694 -+};
10695 -+
10696 -+class Item_func_uncompress: public Item_str_func
10697 -+{
10698 -+ String buffer;
10699 -+public:
10700 -+ Item_func_uncompress(Item *a): Item_str_func(a){}
10701 -+ void fix_length_and_dec(){ maybe_null= 1; max_length= MAX_BLOB_WIDTH; }
10702 -+ const char *func_name() const{return "uncompress";}
10703 -+ String *val_str(String *) ZLIB_DEPENDED_FUNCTION
10704 -+};
10705 -+
10706 -+#define UUID_LENGTH (8+1+4+1+4+1+4+1+12)
10707 -+class Item_func_uuid: public Item_str_func
10708 -+{
10709 -+public:
10710 -+ Item_func_uuid(): Item_str_func() {}
10711 -+ void fix_length_and_dec() {
10712 -+ collation.set(system_charset_info);
10713 -+ /*
10714 -+ NOTE! uuid() should be changed to use 'ascii'
10715 -+ charset when hex(), format(), md5(), etc, and implicit
10716 -+ number-to-string conversion will use 'ascii'
10717 -+ */
10718 -+ max_length= UUID_LENGTH * system_charset_info->mbmaxlen;
10719 -+ }
10720 -+ const char *func_name() const{ return "uuid"; }
10721 -+ String *val_str(String *);
10722 -+};
10723 -+
10724 -diff -urN mysql-old/sql/item_strfunc.h.rej mysql/sql/item_strfunc.h.rej
10725 ---- mysql-old/sql/item_strfunc.h.rej 1969-12-31 23:00:00.000000000 -0100
10726 -+++ mysql/sql/item_strfunc.h.rej 2011-05-10 17:56:01.353349043 +0000
10727 -@@ -0,0 +1,11 @@
10728 -+--- sql/item_strfunc.h 2010-08-03 17:24:28.000000000 +0000
10729 -++++ sql/item_strfunc.h 2010-08-20 22:27:12.919596025 +0000
10730 -+@@ -705,7 +705,7 @@
10731 -+ void fix_length_and_dec()
10732 -+ {
10733 -+ ulonglong max_result_length= (ulonglong) args[0]->max_length * 2 + 2;
10734 -+- max_length= (uint32) min(max_result_length, MAX_BLOB_WIDTH);
10735 -++ max_length= (uint32) MYSQL_MIN(max_result_length, MAX_BLOB_WIDTH);
10736 -+ collation.set(args[0]->collation);
10737 -+ }
10738 -+ };
10739 diff -urN mysql-old/sql/item_sum.cc mysql/sql/item_sum.cc
10740 --- mysql-old/sql/item_sum.cc 2011-05-10 17:45:45.636682376 +0000
10741 +++ mysql/sql/item_sum.cc 2011-05-10 17:56:01.353349043 +0000
10742 @@ -12369,9302 +1677,6 @@ diff -urN mysql-old/sql/mysqld.cc mysql/sql/mysqld.cc
10743 fd_set readFDs,clientFDs;
10744 THD *thd;
10745 struct sockaddr_in cAddr;
10746 -diff -urN mysql-old/sql/mysqld.cc.orig mysql/sql/mysqld.cc.orig
10747 ---- mysql-old/sql/mysqld.cc.orig 1969-12-31 23:00:00.000000000 -0100
10748 -+++ mysql/sql/mysqld.cc.orig 2011-04-12 12:11:35.000000000 +0000
10749 -@@ -0,0 +1,9292 @@
10750 -+/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
10751 -+
10752 -+ This program is free software; you can redistribute it and/or modify
10753 -+ it under the terms of the GNU General Public License as published by
10754 -+ the Free Software Foundation; version 2 of the License.
10755 -+
10756 -+ This program is distributed in the hope that it will be useful,
10757 -+ but WITHOUT ANY WARRANTY; without even the implied warranty of
10758 -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10759 -+ GNU General Public License for more details.
10760 -+
10761 -+ You should have received a copy of the GNU General Public License
10762 -+ along with this program; if not, write to the Free Software
10763 -+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
10764 -+
10765 -+#include "mysql_priv.h"
10766 -+#include <m_ctype.h>
10767 -+#include <my_dir.h>
10768 -+#include <my_bit.h>
10769 -+#include "slave.h"
10770 -+#include "rpl_mi.h"
10771 -+#include "sql_repl.h"
10772 -+#include "rpl_filter.h"
10773 -+#include "repl_failsafe.h"
10774 -+#include <my_stacktrace.h>
10775 -+#include "mysqld_suffix.h"
10776 -+#include "mysys_err.h"
10777 -+#include "events.h"
10778 -+#include "debug_sync.h"
10779 -+
10780 -+#include "../storage/myisam/ha_myisam.h"
10781 -+
10782 -+#include "rpl_injector.h"
10783 -+
10784 -+#ifdef HAVE_SYS_PRCTL_H
10785 -+#include <sys/prctl.h>
10786 -+#endif
10787 -+
10788 -+#ifdef WITH_NDBCLUSTER_STORAGE_ENGINE
10789 -+#if defined(NOT_ENOUGH_TESTED) \
10790 -+ && defined(NDB_SHM_TRANSPORTER) && MYSQL_VERSION_ID >= 50000
10791 -+#define OPT_NDB_SHM_DEFAULT 1
10792 -+#else
10793 -+#define OPT_NDB_SHM_DEFAULT 0
10794 -+#endif
10795 -+#endif
10796 -+
10797 -+#ifndef DEFAULT_SKIP_THREAD_PRIORITY
10798 -+#define DEFAULT_SKIP_THREAD_PRIORITY 0
10799 -+#endif
10800 -+
10801 -+#include <thr_alarm.h>
10802 -+#include <ft_global.h>
10803 -+#include <errmsg.h>
10804 -+#include "sp_rcontext.h"
10805 -+#include "sp_cache.h"
10806 -+
10807 -+#define mysqld_charset &my_charset_latin1
10808 -+
10809 -+#ifdef HAVE_purify
10810 -+#define IF_PURIFY(A,B) (A)
10811 -+#else
10812 -+#define IF_PURIFY(A,B) (B)
10813 -+#endif
10814 -+
10815 -+#if SIZEOF_CHARP == 4
10816 -+#define MAX_MEM_TABLE_SIZE ~(ulong) 0
10817 -+#else
10818 -+#define MAX_MEM_TABLE_SIZE ~(ulonglong) 0
10819 -+#endif
10820 -+
10821 -+/* stack traces are only supported on linux intel */
10822 -+#if defined(__linux__) && defined(__i386__)
10823 -+#define HAVE_STACK_TRACE_ON_SEGV
10824 -+#endif /* __linux__ */
10825 -+
10826 -+/* We have HAVE_purify below as this speeds up the shutdown of MySQL */
10827 -+
10828 -+#if defined(HAVE_DEC_3_2_THREADS) || defined(SIGNALS_DONT_BREAK_READ) || defined(HAVE_purify) && defined(__linux__)
10829 -+#define HAVE_CLOSE_SERVER_SOCK 1
10830 -+#endif
10831 -+
10832 -+extern "C" { // Because of SCO 3.2V4.2
10833 -+#include <errno.h>
10834 -+#include <sys/stat.h>
10835 -+#ifndef __GNU_LIBRARY__
10836 -+#define __GNU_LIBRARY__ // Skip warnings in getopt.h
10837 -+#endif
10838 -+#include <my_getopt.h>
10839 -+#ifdef HAVE_SYSENT_H
10840 -+#include <sysent.h>
10841 -+#endif
10842 -+#ifdef HAVE_PWD_H
10843 -+#include <pwd.h> // For getpwent
10844 -+#endif
10845 -+#ifdef HAVE_GRP_H
10846 -+#include <grp.h>
10847 -+#endif
10848 -+#include <my_net.h>
10849 -+
10850 -+#if !defined(__WIN__)
10851 -+# ifndef __NETWARE__
10852 -+#include <sys/resource.h>
10853 -+# endif /* __NETWARE__ */
10854 -+#ifdef HAVE_SYS_UN_H
10855 -+# include <sys/un.h>
10856 -+#endif
10857 -+#include <netdb.h>
10858 -+#ifdef HAVE_SELECT_H
10859 -+# include <select.h>
10860 -+#endif
10861 -+#ifdef HAVE_SYS_SELECT_H
10862 -+#include <sys/select.h>
10863 -+#endif
10864 -+#include <sys/utsname.h>
10865 -+#endif /* __WIN__ */
10866 -+
10867 -+#include <my_libwrap.h>
10868 -+
10869 -+#ifdef HAVE_SYS_MMAN_H
10870 -+#include <sys/mman.h>
10871 -+#endif
10872 -+
10873 -+#ifdef __WIN__
10874 -+#include <crtdbg.h>
10875 -+#define SIGNAL_FMT "exception 0x%x"
10876 -+#else
10877 -+#define SIGNAL_FMT "signal %d"
10878 -+#endif
10879 -+
10880 -+#ifdef __NETWARE__
10881 -+#define zVOLSTATE_ACTIVE 6
10882 -+#define zVOLSTATE_DEACTIVE 2
10883 -+#define zVOLSTATE_MAINTENANCE 3
10884 -+
10885 -+#undef __event_h__
10886 -+#include <../include/event.h>
10887 -+/*
10888 -+ This #undef exists here because both libc of NetWare and MySQL have
10889 -+ files named event.h which causes compilation errors.
10890 -+*/
10891 -+
10892 -+#include <nks/netware.h>
10893 -+#include <nks/vm.h>
10894 -+#include <library.h>
10895 -+#include <monitor.h>
10896 -+#include <zOmni.h> //For NEB
10897 -+#include <neb.h> //For NEB
10898 -+#include <nebpub.h> //For NEB
10899 -+#include <zEvent.h> //For NSS event structures
10900 -+#include <zPublics.h>
10901 -+
10902 -+static void *neb_consumer_id= NULL; //For storing NEB consumer id
10903 -+static char datavolname[256]= {0};
10904 -+static VolumeID_t datavolid;
10905 -+static event_handle_t eh;
10906 -+static Report_t ref;
10907 -+static void *refneb= NULL;
10908 -+my_bool event_flag= FALSE;
10909 -+static int volumeid= -1;
10910 -+
10911 -+ /* NEB event callback */
10912 -+unsigned long neb_event_callback(struct EventBlock *eblock);
10913 -+static void registerwithneb();
10914 -+static void getvolumename();
10915 -+static void getvolumeID(BYTE *volumeName);
10916 -+#endif /* __NETWARE__ */
10917 -+
10918 -+
10919 -+#ifdef _AIX41
10920 -+int initgroups(const char *,unsigned int);
10921 -+#endif
10922 -+
10923 -+#if defined(__FreeBSD__) && defined(HAVE_IEEEFP_H)
10924 -+#include <ieeefp.h>
10925 -+#ifdef HAVE_FP_EXCEPT // Fix type conflict
10926 -+typedef fp_except fp_except_t;
10927 -+#endif
10928 -+#endif /* __FreeBSD__ && HAVE_IEEEFP_H */
10929 -+#ifdef HAVE_SYS_FPU_H
10930 -+/* for IRIX to use set_fpc_csr() */
10931 -+#include <sys/fpu.h>
10932 -+#endif
10933 -+#ifdef HAVE_FPU_CONTROL_H
10934 -+#include <fpu_control.h>
10935 -+#endif
10936 -+#if defined(__i386__) && !defined(HAVE_FPU_CONTROL_H)
10937 -+# define fpu_control_t unsigned int
10938 -+# define _FPU_EXTENDED 0x300
10939 -+# define _FPU_DOUBLE 0x200
10940 -+# if defined(__GNUC__) || (defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x590)
10941 -+# define _FPU_GETCW(cw) asm volatile ("fnstcw %0" : "=m" (*&cw))
10942 -+# define _FPU_SETCW(cw) asm volatile ("fldcw %0" : : "m" (*&cw))
10943 -+# else
10944 -+# define _FPU_GETCW(cw) (cw= 0)
10945 -+# define _FPU_SETCW(cw)
10946 -+# endif
10947 -+#endif
10948 -+
10949 -+extern "C" my_bool reopen_fstreams(const char *filename,
10950 -+ FILE *outstream, FILE *errstream);
10951 -+
10952 -+inline void setup_fpu()
10953 -+{
10954 -+#if defined(__FreeBSD__) && defined(HAVE_IEEEFP_H)
10955 -+ /* We can't handle floating point exceptions with threads, so disable
10956 -+ this on freebsd
10957 -+ Don't fall for overflow, underflow,divide-by-zero or loss of precision
10958 -+ */
10959 -+#if defined(__i386__)
10960 -+ fpsetmask(~(FP_X_INV | FP_X_DNML | FP_X_OFL | FP_X_UFL | FP_X_DZ |
10961 -+ FP_X_IMP));
10962 -+#else
10963 -+ fpsetmask(~(FP_X_INV | FP_X_OFL | FP_X_UFL | FP_X_DZ |
10964 -+ FP_X_IMP));
10965 -+#endif /* __i386__ */
10966 -+#endif /* __FreeBSD__ && HAVE_IEEEFP_H */
10967 -+
10968 -+#ifdef HAVE_FESETROUND
10969 -+ /* Set FPU rounding mode to "round-to-nearest" */
10970 -+ fesetround(FE_TONEAREST);
10971 -+#endif /* HAVE_FESETROUND */
10972 -+
10973 -+ /*
10974 -+ x86 (32-bit) requires FPU precision to be explicitly set to 64 bit
10975 -+ (double precision) for portable results of floating point operations.
10976 -+ However, there is no need to do so if compiler is using SSE2 for floating
10977 -+ point, double values will be stored and processed in 64 bits anyway.
10978 -+ */
10979 -+#if defined(__i386__) && !defined(__SSE2_MATH__)
10980 -+#if defined(_WIN32)
10981 -+#if !defined(_WIN64)
10982 -+ _control87(_PC_53, MCW_PC);
10983 -+#endif /* !_WIN64 */
10984 -+#else /* !_WIN32 */
10985 -+ fpu_control_t cw;
10986 -+ _FPU_GETCW(cw);
10987 -+ cw= (cw & ~_FPU_EXTENDED) | _FPU_DOUBLE;
10988 -+ _FPU_SETCW(cw);
10989 -+#endif /* _WIN32 && */
10990 -+#endif /* __i386__ */
10991 -+
10992 -+#if defined(__sgi) && defined(HAVE_SYS_FPU_H)
10993 -+ /* Enable denormalized DOUBLE values support for IRIX */
10994 -+ union fpc_csr n;
10995 -+ n.fc_word = get_fpc_csr();
10996 -+ n.fc_struct.flush = 0;
10997 -+ set_fpc_csr(n.fc_word);
10998 -+#endif
10999 -+}
11000 -+
11001 -+} /* cplusplus */
11002 -+
11003 -+#define MYSQL_KILL_SIGNAL SIGTERM
11004 -+
11005 -+#ifdef HAVE_GLIBC2_STYLE_GETHOSTBYNAME_R
11006 -+#include <sys/types.h>
11007 -+#else
11008 -+#include <my_pthread.h> // For thr_setconcurency()
11009 -+#endif
11010 -+
11011 -+#ifdef SOLARIS
11012 -+extern "C" int gethostname(char *name, int namelen);
11013 -+#endif
11014 -+
11015 -+extern "C" sig_handler handle_segfault(int sig);
11016 -+
11017 -+#if defined(__linux__)
11018 -+#define ENABLE_TEMP_POOL 1
11019 -+#else
11020 -+#define ENABLE_TEMP_POOL 0
11021 -+#endif
11022 -+
11023 -+/* Constants */
11024 -+
11025 -+const char *show_comp_option_name[]= {"YES", "NO", "DISABLED"};
11026 -+/*
11027 -+ WARNING: When adding new SQL modes don't forget to update the
11028 -+ tables definitions that stores it's value.
11029 -+ (ie: mysql.event, mysql.proc)
11030 -+*/
11031 -+static const char *sql_mode_names[]=
11032 -+{
11033 -+ "REAL_AS_FLOAT", "PIPES_AS_CONCAT", "ANSI_QUOTES", "IGNORE_SPACE",
11034 -+ "?", "ONLY_FULL_GROUP_BY", "NO_UNSIGNED_SUBTRACTION",
11035 -+ "NO_DIR_IN_CREATE",
11036 -+ "POSTGRESQL", "ORACLE", "MSSQL", "DB2", "MAXDB", "NO_KEY_OPTIONS",
11037 -+ "NO_TABLE_OPTIONS", "NO_FIELD_OPTIONS", "MYSQL323", "MYSQL40", "ANSI",
11038 -+ "NO_AUTO_VALUE_ON_ZERO", "NO_BACKSLASH_ESCAPES", "STRICT_TRANS_TABLES",
11039 -+ "STRICT_ALL_TABLES",
11040 -+ "NO_ZERO_IN_DATE", "NO_ZERO_DATE", "ALLOW_INVALID_DATES",
11041 -+ "ERROR_FOR_DIVISION_BY_ZERO",
11042 -+ "TRADITIONAL", "NO_AUTO_CREATE_USER", "HIGH_NOT_PRECEDENCE",
11043 -+ "NO_ENGINE_SUBSTITUTION",
11044 -+ "PAD_CHAR_TO_FULL_LENGTH",
11045 -+ NullS
11046 -+};
11047 -+
11048 -+static const unsigned int sql_mode_names_len[]=
11049 -+{
11050 -+ /*REAL_AS_FLOAT*/ 13,
11051 -+ /*PIPES_AS_CONCAT*/ 15,
11052 -+ /*ANSI_QUOTES*/ 11,
11053 -+ /*IGNORE_SPACE*/ 12,
11054 -+ /*?*/ 1,
11055 -+ /*ONLY_FULL_GROUP_BY*/ 18,
11056 -+ /*NO_UNSIGNED_SUBTRACTION*/ 23,
11057 -+ /*NO_DIR_IN_CREATE*/ 16,
11058 -+ /*POSTGRESQL*/ 10,
11059 -+ /*ORACLE*/ 6,
11060 -+ /*MSSQL*/ 5,
11061 -+ /*DB2*/ 3,
11062 -+ /*MAXDB*/ 5,
11063 -+ /*NO_KEY_OPTIONS*/ 14,
11064 -+ /*NO_TABLE_OPTIONS*/ 16,
11065 -+ /*NO_FIELD_OPTIONS*/ 16,
11066 -+ /*MYSQL323*/ 8,
11067 -+ /*MYSQL40*/ 7,
11068 -+ /*ANSI*/ 4,
11069 -+ /*NO_AUTO_VALUE_ON_ZERO*/ 21,
11070 -+ /*NO_BACKSLASH_ESCAPES*/ 20,
11071 -+ /*STRICT_TRANS_TABLES*/ 19,
11072 -+ /*STRICT_ALL_TABLES*/ 17,
11073 -+ /*NO_ZERO_IN_DATE*/ 15,
11074 -+ /*NO_ZERO_DATE*/ 12,
11075 -+ /*ALLOW_INVALID_DATES*/ 19,
11076 -+ /*ERROR_FOR_DIVISION_BY_ZERO*/ 26,
11077 -+ /*TRADITIONAL*/ 11,
11078 -+ /*NO_AUTO_CREATE_USER*/ 19,
11079 -+ /*HIGH_NOT_PRECEDENCE*/ 19,
11080 -+ /*NO_ENGINE_SUBSTITUTION*/ 22,
11081 -+ /*PAD_CHAR_TO_FULL_LENGTH*/ 23
11082 -+};
11083 -+
11084 -+TYPELIB sql_mode_typelib= { array_elements(sql_mode_names)-1,"",
11085 -+ sql_mode_names,
11086 -+ (unsigned int *)sql_mode_names_len };
11087 -+
11088 -+static const char *optimizer_switch_names[]=
11089 -+{
11090 -+ "index_merge","index_merge_union","index_merge_sort_union",
11091 -+ "index_merge_intersection", "default", NullS
11092 -+};
11093 -+/* Corresponding defines are named OPTIMIZER_SWITCH_XXX */
11094 -+static const unsigned int optimizer_switch_names_len[]=
11095 -+{
11096 -+ sizeof("index_merge") - 1,
11097 -+ sizeof("index_merge_union") - 1,
11098 -+ sizeof("index_merge_sort_union") - 1,
11099 -+ sizeof("index_merge_intersection") - 1,
11100 -+ sizeof("default") - 1
11101 -+};
11102 -+TYPELIB optimizer_switch_typelib= { array_elements(optimizer_switch_names)-1,"",
11103 -+ optimizer_switch_names,
11104 -+ (unsigned int *)optimizer_switch_names_len };
11105 -+
11106 -+static const char *tc_heuristic_recover_names[]=
11107 -+{
11108 -+ "COMMIT", "ROLLBACK", NullS
11109 -+};
11110 -+static TYPELIB tc_heuristic_recover_typelib=
11111 -+{
11112 -+ array_elements(tc_heuristic_recover_names)-1,"",
11113 -+ tc_heuristic_recover_names, NULL
11114 -+};
11115 -+
11116 -+static const char *thread_handling_names[]=
11117 -+{ "one-thread-per-connection", "no-threads",
11118 -+#if HAVE_POOL_OF_THREADS == 1
11119 -+ "pool-of-threads",
11120 -+#endif
11121 -+ NullS};
11122 -+
11123 -+TYPELIB thread_handling_typelib=
11124 -+{
11125 -+ array_elements(thread_handling_names) - 1, "",
11126 -+ thread_handling_names, NULL
11127 -+};
11128 -+
11129 -+const char *first_keyword= "first", *binary_keyword= "BINARY";
11130 -+const char *my_localhost= "localhost", *delayed_user= "DELAYED";
11131 -+#if SIZEOF_OFF_T > 4 && defined(BIG_TABLES)
11132 -+#define GET_HA_ROWS GET_ULL
11133 -+#else
11134 -+#define GET_HA_ROWS GET_ULONG
11135 -+#endif
11136 -+
11137 -+bool opt_large_files= sizeof(my_off_t) > 4;
11138 -+
11139 -+/*
11140 -+ Used with --help for detailed option
11141 -+*/
11142 -+static my_bool opt_help= 0, opt_verbose= 0;
11143 -+
11144 -+arg_cmp_func Arg_comparator::comparator_matrix[5][2] =
11145 -+{{&Arg_comparator::compare_string, &Arg_comparator::compare_e_string},
11146 -+ {&Arg_comparator::compare_real, &Arg_comparator::compare_e_real},
11147 -+ {&Arg_comparator::compare_int_signed, &Arg_comparator::compare_e_int},
11148 -+ {&Arg_comparator::compare_row, &Arg_comparator::compare_e_row},
11149 -+ {&Arg_comparator::compare_decimal, &Arg_comparator::compare_e_decimal}};
11150 -+
11151 -+const char *log_output_names[] = { "NONE", "FILE", "TABLE", NullS};
11152 -+static const unsigned int log_output_names_len[]= { 4, 4, 5, 0 };
11153 -+TYPELIB log_output_typelib= {array_elements(log_output_names)-1,"",
11154 -+ log_output_names,
11155 -+ (unsigned int *) log_output_names_len};
11156 -+
11157 -+/* static variables */
11158 -+
11159 -+/* the default log output is log tables */
11160 -+static bool lower_case_table_names_used= 0;
11161 -+static bool max_long_data_size_used= false;
11162 -+static bool volatile select_thread_in_use, signal_thread_in_use;
11163 -+static bool volatile ready_to_exit;
11164 -+static my_bool opt_debugging= 0, opt_external_locking= 0, opt_console= 0;
11165 -+static my_bool opt_short_log_format= 0;
11166 -+static uint kill_cached_threads, wake_thread;
11167 -+static ulong killed_threads, thread_created;
11168 -+static ulong max_used_connections;
11169 -+static ulong my_bind_addr; /**< the address we bind to */
11170 -+static volatile ulong cached_thread_count= 0;
11171 -+static const char *sql_mode_str= "OFF";
11172 -+/* Text representation for OPTIMIZER_SWITCH_DEFAULT */
11173 -+static const char *optimizer_switch_str="index_merge=on,index_merge_union=on,"
11174 -+ "index_merge_sort_union=on,"
11175 -+ "index_merge_intersection=on";
11176 -+static char *mysqld_user, *mysqld_chroot, *log_error_file_ptr;
11177 -+static char *opt_init_slave, *language_ptr, *opt_init_connect;
11178 -+static char *default_character_set_name;
11179 -+static char *character_set_filesystem_name;
11180 -+static char *lc_time_names_name;
11181 -+static char *my_bind_addr_str;
11182 -+static char *default_collation_name;
11183 -+static char *default_storage_engine_str;
11184 -+static char compiled_default_collation_name[]= MYSQL_DEFAULT_COLLATION_NAME;
11185 -+static I_List<THD> thread_cache;
11186 -+static double long_query_time;
11187 -+
11188 -+static pthread_cond_t COND_thread_cache, COND_flush_thread_cache;
11189 -+
11190 -+/* Global variables */
11191 -+
11192 -+bool opt_update_log, opt_bin_log, opt_ignore_builtin_innodb= 0;
11193 -+my_bool opt_log, opt_slow_log;
11194 -+ulong log_output_options;
11195 -+my_bool opt_log_queries_not_using_indexes= 0;
11196 -+bool opt_error_log= IF_WIN(1,0);
11197 -+bool opt_disable_networking=0, opt_skip_show_db=0;
11198 -+bool opt_skip_name_resolve=0;
11199 -+my_bool opt_character_set_client_handshake= 1;
11200 -+bool server_id_supplied = 0;
11201 -+bool opt_endinfo, using_udf_functions;
11202 -+my_bool locked_in_memory;
11203 -+bool opt_using_transactions;
11204 -+bool volatile abort_loop;
11205 -+bool volatile shutdown_in_progress;
11206 -+/*
11207 -+ True if the bootstrap thread is running. Protected by LOCK_thread_count,
11208 -+ just like thread_count.
11209 -+ Used in bootstrap() function to determine if the bootstrap thread
11210 -+ has completed. Note, that we can't use 'thread_count' instead,
11211 -+ since in 5.1, in presence of the Event Scheduler, there may be
11212 -+ event threads running in parallel, so it's impossible to know
11213 -+ what value of 'thread_count' is a sign of completion of the
11214 -+ bootstrap thread.
11215 -+
11216 -+ At the same time, we can't start the event scheduler after
11217 -+ bootstrap either, since we want to be able to process event-related
11218 -+ SQL commands in the init file and in --bootstrap mode.
11219 -+*/
11220 -+bool in_bootstrap= FALSE;
11221 -+/**
11222 -+ @brief 'grant_option' is used to indicate if privileges needs
11223 -+ to be checked, in which case the lock, LOCK_grant, is used
11224 -+ to protect access to the grant table.
11225 -+ @note This flag is dropped in 5.1
11226 -+ @see grant_init()
11227 -+ */
11228 -+bool volatile grant_option;
11229 -+
11230 -+my_bool opt_skip_slave_start = 0; ///< If set, slave is not autostarted
11231 -+my_bool opt_reckless_slave = 0;
11232 -+my_bool opt_enable_named_pipe= 0;
11233 -+my_bool opt_local_infile, opt_slave_compressed_protocol;
11234 -+my_bool opt_safe_user_create = 0, opt_no_mix_types = 0;
11235 -+my_bool opt_show_slave_auth_info, opt_sql_bin_update = 0;
11236 -+my_bool opt_log_slave_updates= 0;
11237 -+bool slave_warning_issued = false;
11238 -+
11239 -+/*
11240 -+ Legacy global handlerton. These will be removed (please do not add more).
11241 -+*/
11242 -+handlerton *heap_hton;
11243 -+handlerton *myisam_hton;
11244 -+handlerton *partition_hton;
11245 -+
11246 -+#ifdef WITH_NDBCLUSTER_STORAGE_ENGINE
11247 -+const char *opt_ndbcluster_connectstring= 0;
11248 -+const char *opt_ndb_connectstring= 0;
11249 -+char opt_ndb_constrbuf[1024]= {0};
11250 -+unsigned opt_ndb_constrbuf_len= 0;
11251 -+my_bool opt_ndb_shm, opt_ndb_optimized_node_selection;
11252 -+ulong opt_ndb_cache_check_time;
11253 -+const char *opt_ndb_mgmd;
11254 -+ulong opt_ndb_nodeid;
11255 -+ulong ndb_extra_logging;
11256 -+#ifdef HAVE_NDB_BINLOG
11257 -+ulong ndb_report_thresh_binlog_epoch_slip;
11258 -+ulong ndb_report_thresh_binlog_mem_usage;
11259 -+#endif
11260 -+
11261 -+extern const char *ndb_distribution_names[];
11262 -+extern TYPELIB ndb_distribution_typelib;
11263 -+extern const char *opt_ndb_distribution;
11264 -+extern enum ndb_distribution opt_ndb_distribution_id;
11265 -+#endif
11266 -+my_bool opt_readonly, use_temp_pool, relay_log_purge;
11267 -+my_bool opt_sync_frm, opt_allow_suspicious_udfs;
11268 -+my_bool opt_secure_auth= 0;
11269 -+char* opt_secure_file_priv= 0;
11270 -+my_bool opt_log_slow_admin_statements= 0;
11271 -+my_bool opt_log_slow_slave_statements= 0;
11272 -+my_bool lower_case_file_system= 0;
11273 -+my_bool opt_large_pages= 0;
11274 -+my_bool opt_myisam_use_mmap= 0;
11275 -+uint opt_large_page_size= 0;
11276 -+#if defined(ENABLED_DEBUG_SYNC)
11277 -+uint opt_debug_sync_timeout= 0;
11278 -+#endif /* defined(ENABLED_DEBUG_SYNC) */
11279 -+my_bool opt_old_style_user_limits= 0, trust_function_creators= 0;
11280 -+/*
11281 -+ True if there is at least one per-hour limit for some user, so we should
11282 -+ check them before each query (and possibly reset counters when hour is
11283 -+ changed). False otherwise.
11284 -+*/
11285 -+volatile bool mqh_used = 0;
11286 -+my_bool opt_noacl;
11287 -+my_bool sp_automatic_privileges= 1;
11288 -+
11289 -+ulong opt_binlog_rows_event_max_size;
11290 -+const char *binlog_format_names[]= {"MIXED", "STATEMENT", "ROW", NullS};
11291 -+TYPELIB binlog_format_typelib=
11292 -+ { array_elements(binlog_format_names) - 1, "",
11293 -+ binlog_format_names, NULL };
11294 -+ulong opt_binlog_format_id= (ulong) BINLOG_FORMAT_UNSPEC;
11295 -+const char *opt_binlog_format= binlog_format_names[opt_binlog_format_id];
11296 -+#ifdef HAVE_INITGROUPS
11297 -+static bool calling_initgroups= FALSE; /**< Used in SIGSEGV handler. */
11298 -+#endif
11299 -+uint mysqld_port, test_flags, select_errors, dropping_tables, ha_open_options;
11300 -+uint mysqld_port_timeout;
11301 -+uint delay_key_write_options, protocol_version;
11302 -+uint lower_case_table_names;
11303 -+uint tc_heuristic_recover= 0;
11304 -+uint volatile thread_count, thread_running;
11305 -+ulonglong thd_startup_options;
11306 -+ulong back_log, connect_timeout, concurrency, server_id;
11307 -+ulong table_cache_size, table_def_size;
11308 -+ulong what_to_log;
11309 -+ulong query_buff_size, slow_launch_time, slave_open_temp_tables;
11310 -+ulong open_files_limit, max_binlog_size, max_relay_log_size;
11311 -+ulong slave_net_timeout, slave_trans_retries;
11312 -+ulong slave_exec_mode_options;
11313 -+static const char *slave_exec_mode_str= "STRICT";
11314 -+ulong thread_cache_size=0, thread_pool_size= 0;
11315 -+ulong binlog_cache_size=0;
11316 -+ulonglong max_binlog_cache_size=0;
11317 -+ulong query_cache_size=0;
11318 -+ulong refresh_version; /* Increments on each reload */
11319 -+query_id_t global_query_id;
11320 -+ulong aborted_threads, aborted_connects;
11321 -+ulong delayed_insert_timeout, delayed_insert_limit, delayed_queue_size;
11322 -+ulong delayed_insert_threads, delayed_insert_writes, delayed_rows_in_use;
11323 -+ulong delayed_insert_errors,flush_time;
11324 -+ulong specialflag=0;
11325 -+ulong binlog_cache_use= 0, binlog_cache_disk_use= 0;
11326 -+ulong max_connections, max_connect_errors;
11327 -+/*
11328 -+ Maximum length of parameter value which can be set through
11329 -+ mysql_send_long_data() call.
11330 -+*/
11331 -+ulong max_long_data_size;
11332 -+uint max_user_connections= 0;
11333 -+/**
11334 -+ Limit of the total number of prepared statements in the server.
11335 -+ Is necessary to protect the server against out-of-memory attacks.
11336 -+*/
11337 -+ulong max_prepared_stmt_count;
11338 -+/**
11339 -+ Current total number of prepared statements in the server. This number
11340 -+ is exact, and therefore may not be equal to the difference between
11341 -+ `com_stmt_prepare' and `com_stmt_close' (global status variables), as
11342 -+ the latter ones account for all registered attempts to prepare
11343 -+ a statement (including unsuccessful ones). Prepared statements are
11344 -+ currently connection-local: if the same SQL query text is prepared in
11345 -+ two different connections, this counts as two distinct prepared
11346 -+ statements.
11347 -+*/
11348 -+ulong prepared_stmt_count=0;
11349 -+ulong thread_id=1L,current_pid;
11350 -+ulong slow_launch_threads = 0, sync_binlog_period;
11351 -+ulong expire_logs_days = 0;
11352 -+ulong rpl_recovery_rank=0;
11353 -+const char *log_output_str= "FILE";
11354 -+
11355 -+time_t server_start_time, flush_status_time;
11356 -+
11357 -+char mysql_home[FN_REFLEN], pidfile_name[FN_REFLEN], system_time_zone[30];
11358 -+char *default_tz_name;
11359 -+char log_error_file[FN_REFLEN], glob_hostname[FN_REFLEN];
11360 -+char mysql_real_data_home[FN_REFLEN],
11361 -+ language[FN_REFLEN], reg_ext[FN_EXTLEN], mysql_charsets_dir[FN_REFLEN],
11362 -+ *opt_init_file, *opt_tc_log_file,
11363 -+ def_ft_boolean_syntax[sizeof(ft_boolean_syntax)];
11364 -+char mysql_unpacked_real_data_home[FN_REFLEN];
11365 -+int mysql_unpacked_real_data_home_len;
11366 -+uint reg_ext_length;
11367 -+const key_map key_map_empty(0);
11368 -+key_map key_map_full(0); // Will be initialized later
11369 -+
11370 -+const char *opt_date_time_formats[3];
11371 -+
11372 -+uint mysql_data_home_len;
11373 -+char mysql_data_home_buff[2], *mysql_data_home=mysql_real_data_home;
11374 -+char server_version[SERVER_VERSION_LENGTH];
11375 -+char *mysqld_unix_port, *opt_mysql_tmpdir;
11376 -+const char **errmesg; /**< Error messages */
11377 -+const char *myisam_recover_options_str="OFF";
11378 -+const char *myisam_stats_method_str="nulls_unequal";
11379 -+
11380 -+/** name of reference on left espression in rewritten IN subquery */
11381 -+const char *in_left_expr_name= "<left expr>";
11382 -+/** name of additional condition */
11383 -+const char *in_additional_cond= "<IN COND>";
11384 -+const char *in_having_cond= "<IN HAVING>";
11385 -+
11386 -+my_decimal decimal_zero;
11387 -+/* classes for comparation parsing/processing */
11388 -+Eq_creator eq_creator;
11389 -+Ne_creator ne_creator;
11390 -+Gt_creator gt_creator;
11391 -+Lt_creator lt_creator;
11392 -+Ge_creator ge_creator;
11393 -+Le_creator le_creator;
11394 -+
11395 -+FILE *bootstrap_file;
11396 -+int bootstrap_error;
11397 -+FILE *stderror_file=0;
11398 -+
11399 -+I_List<THD> threads;
11400 -+I_List<NAMED_LIST> key_caches;
11401 -+Rpl_filter* rpl_filter;
11402 -+Rpl_filter* binlog_filter;
11403 -+
11404 -+struct system_variables global_system_variables;
11405 -+struct system_variables max_system_variables;
11406 -+struct system_status_var global_status_var;
11407 -+
11408 -+MY_TMPDIR mysql_tmpdir_list;
11409 -+MY_BITMAP temp_pool;
11410 -+
11411 -+CHARSET_INFO *system_charset_info, *files_charset_info ;
11412 -+CHARSET_INFO *national_charset_info, *table_alias_charset;
11413 -+CHARSET_INFO *character_set_filesystem;
11414 -+
11415 -+MY_LOCALE *my_default_lc_time_names;
11416 -+
11417 -+SHOW_COMP_OPTION have_ssl, have_symlink, have_dlopen, have_query_cache;
11418 -+SHOW_COMP_OPTION have_geometry, have_rtree_keys;
11419 -+SHOW_COMP_OPTION have_crypt, have_compress;
11420 -+SHOW_COMP_OPTION have_community_features;
11421 -+
11422 -+/* Thread specific variables */
11423 -+
11424 -+pthread_key(MEM_ROOT**,THR_MALLOC);
11425 -+pthread_key(THD*, THR_THD);
11426 -+pthread_mutex_t LOCK_mysql_create_db, LOCK_Acl, LOCK_open, LOCK_thread_count,
11427 -+ LOCK_mapped_file, LOCK_status, LOCK_global_read_lock,
11428 -+ LOCK_error_log, LOCK_uuid_generator,
11429 -+ LOCK_delayed_insert, LOCK_delayed_status, LOCK_delayed_create,
11430 -+ LOCK_crypt, LOCK_bytes_sent, LOCK_bytes_received,
11431 -+ LOCK_global_system_variables,
11432 -+ LOCK_user_conn, LOCK_slave_list, LOCK_active_mi,
11433 -+ LOCK_connection_count;
11434 -+/**
11435 -+ The below lock protects access to two global server variables:
11436 -+ max_prepared_stmt_count and prepared_stmt_count. These variables
11437 -+ set the limit and hold the current total number of prepared statements
11438 -+ in the server, respectively. As PREPARE/DEALLOCATE rate in a loaded
11439 -+ server may be fairly high, we need a dedicated lock.
11440 -+*/
11441 -+pthread_mutex_t LOCK_prepared_stmt_count;
11442 -+#ifdef HAVE_OPENSSL
11443 -+pthread_mutex_t LOCK_des_key_file;
11444 -+#endif
11445 -+rw_lock_t LOCK_grant, LOCK_sys_init_connect, LOCK_sys_init_slave;
11446 -+rw_lock_t LOCK_system_variables_hash;
11447 -+pthread_cond_t COND_refresh, COND_thread_count, COND_global_read_lock;
11448 -+pthread_t signal_thread;
11449 -+pthread_attr_t connection_attrib;
11450 -+pthread_mutex_t LOCK_server_started;
11451 -+pthread_cond_t COND_server_started;
11452 -+
11453 -+int mysqld_server_started= 0;
11454 -+
11455 -+File_parser_dummy_hook file_parser_dummy_hook;
11456 -+
11457 -+/* replication parameters, if master_host is not NULL, we are a slave */
11458 -+uint master_port= MYSQL_PORT, master_connect_retry = 60;
11459 -+uint report_port= MYSQL_PORT;
11460 -+ulong master_retry_count=0;
11461 -+char *master_user, *master_password, *master_host, *master_info_file;
11462 -+char *relay_log_info_file, *report_user, *report_password, *report_host;
11463 -+char *opt_relay_logname = 0, *opt_relaylog_index_name=0;
11464 -+my_bool master_ssl;
11465 -+char *master_ssl_key, *master_ssl_cert;
11466 -+char *master_ssl_ca, *master_ssl_capath, *master_ssl_cipher;
11467 -+char *opt_logname, *opt_slow_logname;
11468 -+
11469 -+/* Static variables */
11470 -+
11471 -+static bool kill_in_progress, segfaulted;
11472 -+#ifdef HAVE_STACK_TRACE_ON_SEGV
11473 -+static my_bool opt_do_pstack;
11474 -+#endif /* HAVE_STACK_TRACE_ON_SEGV */
11475 -+static my_bool opt_bootstrap, opt_myisam_log;
11476 -+static int cleanup_done;
11477 -+static ulong opt_specialflag, opt_myisam_block_size;
11478 -+static char *opt_update_logname, *opt_binlog_index_name;
11479 -+static char *opt_tc_heuristic_recover;
11480 -+static char *mysql_home_ptr, *pidfile_name_ptr;
11481 -+static int defaults_argc;
11482 -+static char **defaults_argv;
11483 -+static char *opt_bin_logname;
11484 -+
11485 -+int orig_argc;
11486 -+char **orig_argv;
11487 -+
11488 -+static my_socket unix_sock,ip_sock;
11489 -+struct rand_struct sql_rand; ///< used by sql_class.cc:THD::THD()
11490 -+
11491 -+#ifndef EMBEDDED_LIBRARY
11492 -+struct passwd *user_info;
11493 -+static pthread_t select_thread;
11494 -+static uint thr_kill_signal;
11495 -+#endif
11496 -+
11497 -+/* OS specific variables */
11498 -+
11499 -+#ifdef __WIN__
11500 -+#undef getpid
11501 -+#include <process.h>
11502 -+
11503 -+static pthread_cond_t COND_handler_count;
11504 -+static uint handler_count;
11505 -+static bool start_mode=0, use_opt_args;
11506 -+static int opt_argc;
11507 -+static char **opt_argv;
11508 -+
11509 -+#if !defined(EMBEDDED_LIBRARY)
11510 -+static HANDLE hEventShutdown;
11511 -+static char shutdown_event_name[40];
11512 -+#include "nt_servc.h"
11513 -+static NTService Service; ///< Service object for WinNT
11514 -+#endif /* EMBEDDED_LIBRARY */
11515 -+#endif /* __WIN__ */
11516 -+
11517 -+#ifdef __NT__
11518 -+static char pipe_name[512];
11519 -+static SECURITY_ATTRIBUTES saPipeSecurity;
11520 -+static SECURITY_DESCRIPTOR sdPipeDescriptor;
11521 -+static HANDLE hPipe = INVALID_HANDLE_VALUE;
11522 -+#endif
11523 -+
11524 -+#ifndef EMBEDDED_LIBRARY
11525 -+bool mysqld_embedded=0;
11526 -+#else
11527 -+bool mysqld_embedded=1;
11528 -+#endif
11529 -+
11530 -+static my_bool plugins_are_initialized= FALSE;
11531 -+
11532 -+#ifndef DBUG_OFF
11533 -+static const char* default_dbug_option;
11534 -+#endif
11535 -+#ifdef HAVE_LIBWRAP
11536 -+const char *libwrapName= NULL;
11537 -+int allow_severity = LOG_INFO;
11538 -+int deny_severity = LOG_WARNING;
11539 -+#endif
11540 -+#ifdef HAVE_QUERY_CACHE
11541 -+static ulong query_cache_limit= 0;
11542 -+ulong query_cache_min_res_unit= QUERY_CACHE_MIN_RESULT_DATA_SIZE;
11543 -+Query_cache query_cache;
11544 -+#endif
11545 -+#ifdef HAVE_SMEM
11546 -+char *shared_memory_base_name= default_shared_memory_base_name;
11547 -+my_bool opt_enable_shared_memory;
11548 -+HANDLE smem_event_connect_request= 0;
11549 -+#endif
11550 -+
11551 -+scheduler_functions thread_scheduler;
11552 -+
11553 -+#define SSL_VARS_NOT_STATIC
11554 -+#include "sslopt-vars.h"
11555 -+#ifdef HAVE_OPENSSL
11556 -+#include <openssl/crypto.h>
11557 -+#ifndef HAVE_YASSL
11558 -+typedef struct CRYPTO_dynlock_value
11559 -+{
11560 -+ rw_lock_t lock;
11561 -+} openssl_lock_t;
11562 -+
11563 -+static openssl_lock_t *openssl_stdlocks;
11564 -+static openssl_lock_t *openssl_dynlock_create(const char *, int);
11565 -+static void openssl_dynlock_destroy(openssl_lock_t *, const char *, int);
11566 -+static void openssl_lock_function(int, int, const char *, int);
11567 -+static void openssl_lock(int, openssl_lock_t *, const char *, int);
11568 -+static unsigned long openssl_id_function();
11569 -+#endif
11570 -+char *des_key_file;
11571 -+struct st_VioSSLFd *ssl_acceptor_fd;
11572 -+#endif /* HAVE_OPENSSL */
11573 -+
11574 -+/**
11575 -+ Number of currently active user connections. The variable is protected by
11576 -+ LOCK_connection_count.
11577 -+*/
11578 -+uint connection_count= 0;
11579 -+
11580 -+/* Function declarations */
11581 -+
11582 -+pthread_handler_t signal_hand(void *arg);
11583 -+static int mysql_init_variables(void);
11584 -+static int get_options(int *argc,char **argv);
11585 -+extern "C" my_bool mysqld_get_one_option(int, const struct my_option *, char *);
11586 -+static void set_server_version(void);
11587 -+static int init_thread_environment();
11588 -+static char *get_relative_path(const char *path);
11589 -+static int fix_paths(void);
11590 -+pthread_handler_t handle_connections_sockets(void *arg);
11591 -+pthread_handler_t kill_server_thread(void *arg);
11592 -+static void bootstrap(FILE *file);
11593 -+static bool read_init_file(char *file_name);
11594 -+#ifdef __NT__
11595 -+pthread_handler_t handle_connections_namedpipes(void *arg);
11596 -+#endif
11597 -+#ifdef HAVE_SMEM
11598 -+pthread_handler_t handle_connections_shared_memory(void *arg);
11599 -+#endif
11600 -+pthread_handler_t handle_slave(void *arg);
11601 -+static ulong find_bit_type(const char *x, TYPELIB *bit_lib);
11602 -+static ulong find_bit_type_or_exit(const char *x, TYPELIB *bit_lib,
11603 -+ const char *option, int *error);
11604 -+static void clean_up(bool print_message);
11605 -+static int test_if_case_insensitive(const char *dir_name);
11606 -+
11607 -+#ifndef EMBEDDED_LIBRARY
11608 -+static void usage(void);
11609 -+static void start_signal_handler(void);
11610 -+static void close_server_sock();
11611 -+static void clean_up_mutexes(void);
11612 -+static void wait_for_signal_thread_to_end(void);
11613 -+static void create_pid_file();
11614 -+static void end_ssl();
11615 -+#endif
11616 -+
11617 -+
11618 -+#ifndef EMBEDDED_LIBRARY
11619 -+/****************************************************************************
11620 -+** Code to end mysqld
11621 -+****************************************************************************/
11622 -+
11623 -+static void close_connections(void)
11624 -+{
11625 -+#ifdef EXTRA_DEBUG
11626 -+ int count=0;
11627 -+#endif
11628 -+ DBUG_ENTER("close_connections");
11629 -+
11630 -+ /* Clear thread cache */
11631 -+ kill_cached_threads++;
11632 -+ flush_thread_cache();
11633 -+
11634 -+ /* kill connection thread */
11635 -+#if !defined(__WIN__) && !defined(__NETWARE__)
11636 -+ DBUG_PRINT("quit", ("waiting for select thread: 0x%lx",
11637 -+ (ulong) select_thread));
11638 -+ (void) pthread_mutex_lock(&LOCK_thread_count);
11639 -+
11640 -+ while (select_thread_in_use)
11641 -+ {
11642 -+ struct timespec abstime;
11643 -+ int error;
11644 -+ LINT_INIT(error);
11645 -+ DBUG_PRINT("info",("Waiting for select thread"));
11646 -+
11647 -+#ifndef DONT_USE_THR_ALARM
11648 -+ if (pthread_kill(select_thread, thr_client_alarm))
11649 -+ break; // allready dead
11650 -+#endif
11651 -+ set_timespec(abstime, 2);
11652 -+ for (uint tmp=0 ; tmp < 10 && select_thread_in_use; tmp++)
11653 -+ {
11654 -+ error=pthread_cond_timedwait(&COND_thread_count,&LOCK_thread_count,
11655 -+ &abstime);
11656 -+ if (error != EINTR)
11657 -+ break;
11658 -+ }
11659 -+#ifdef EXTRA_DEBUG
11660 -+ if (error != 0 && !count++)
11661 -+ sql_print_error("Got error %d from pthread_cond_timedwait",error);
11662 -+#endif
11663 -+ close_server_sock();
11664 -+ }
11665 -+ (void) pthread_mutex_unlock(&LOCK_thread_count);
11666 -+#endif /* __WIN__ */
11667 -+
11668 -+
11669 -+ /* Abort listening to new connections */
11670 -+ DBUG_PRINT("quit",("Closing sockets"));
11671 -+ if (!opt_disable_networking )
11672 -+ {
11673 -+ if (ip_sock != INVALID_SOCKET)
11674 -+ {
11675 -+ (void) shutdown(ip_sock, SHUT_RDWR);
11676 -+ (void) closesocket(ip_sock);
11677 -+ ip_sock= INVALID_SOCKET;
11678 -+ }
11679 -+ }
11680 -+#ifdef __NT__
11681 -+ if (hPipe != INVALID_HANDLE_VALUE && opt_enable_named_pipe)
11682 -+ {
11683 -+ HANDLE temp;
11684 -+ DBUG_PRINT("quit", ("Closing named pipes") );
11685 -+
11686 -+ /* Create connection to the handle named pipe handler to break the loop */
11687 -+ if ((temp = CreateFile(pipe_name,
11688 -+ GENERIC_READ | GENERIC_WRITE,
11689 -+ 0,
11690 -+ NULL,
11691 -+ OPEN_EXISTING,
11692 -+ 0,
11693 -+ NULL )) != INVALID_HANDLE_VALUE)
11694 -+ {
11695 -+ WaitNamedPipe(pipe_name, 1000);
11696 -+ DWORD dwMode = PIPE_READMODE_BYTE | PIPE_WAIT;
11697 -+ SetNamedPipeHandleState(temp, &dwMode, NULL, NULL);
11698 -+ CancelIo(temp);
11699 -+ DisconnectNamedPipe(temp);
11700 -+ CloseHandle(temp);
11701 -+ }
11702 -+ }
11703 -+#endif
11704 -+#ifdef HAVE_SYS_UN_H
11705 -+ if (unix_sock != INVALID_SOCKET)
11706 -+ {
11707 -+ (void) shutdown(unix_sock, SHUT_RDWR);
11708 -+ (void) closesocket(unix_sock);
11709 -+ (void) unlink(mysqld_unix_port);
11710 -+ unix_sock= INVALID_SOCKET;
11711 -+ }
11712 -+#endif
11713 -+ end_thr_alarm(0); // Abort old alarms.
11714 -+
11715 -+ /*
11716 -+ First signal all threads that it's time to die
11717 -+ This will give the threads some time to gracefully abort their
11718 -+ statements and inform their clients that the server is about to die.
11719 -+ */
11720 -+
11721 -+ THD *tmp;
11722 -+ (void) pthread_mutex_lock(&LOCK_thread_count); // For unlink from list
11723 -+
11724 -+ I_List_iterator<THD> it(threads);
11725 -+ while ((tmp=it++))
11726 -+ {
11727 -+ DBUG_PRINT("quit",("Informing thread %ld that it's time to die",
11728 -+ tmp->thread_id));
11729 -+ /* We skip slave threads & scheduler on this first loop through. */
11730 -+ if (tmp->slave_thread)
11731 -+ continue;
11732 -+
11733 -+ tmp->killed= THD::KILL_CONNECTION;
11734 -+ thread_scheduler.post_kill_notification(tmp);
11735 -+ if (tmp->mysys_var)
11736 -+ {
11737 -+ tmp->mysys_var->abort=1;
11738 -+ pthread_mutex_lock(&tmp->mysys_var->mutex);
11739 -+ if (tmp->mysys_var->current_cond)
11740 -+ {
11741 -+ pthread_mutex_lock(tmp->mysys_var->current_mutex);
11742 -+ pthread_cond_broadcast(tmp->mysys_var->current_cond);
11743 -+ pthread_mutex_unlock(tmp->mysys_var->current_mutex);
11744 -+ }
11745 -+ pthread_mutex_unlock(&tmp->mysys_var->mutex);
11746 -+ }
11747 -+ }
11748 -+ (void) pthread_mutex_unlock(&LOCK_thread_count); // For unlink from list
11749 -+
11750 -+ Events::deinit();
11751 -+ end_slave();
11752 -+
11753 -+ if (thread_count)
11754 -+ sleep(2); // Give threads time to die
11755 -+
11756 -+ /*
11757 -+ Force remaining threads to die by closing the connection to the client
11758 -+ This will ensure that threads that are waiting for a command from the
11759 -+ client on a blocking read call are aborted.
11760 -+ */
11761 -+
11762 -+ for (;;)
11763 -+ {
11764 -+ DBUG_PRINT("quit",("Locking LOCK_thread_count"));
11765 -+ (void) pthread_mutex_lock(&LOCK_thread_count); // For unlink from list
11766 -+ if (!(tmp=threads.get()))
11767 -+ {
11768 -+ DBUG_PRINT("quit",("Unlocking LOCK_thread_count"));
11769 -+ (void) pthread_mutex_unlock(&LOCK_thread_count);
11770 -+ break;
11771 -+ }
11772 -+#ifndef __bsdi__ // Bug in BSDI kernel
11773 -+ if (tmp->vio_ok())
11774 -+ {
11775 -+ if (global_system_variables.log_warnings)
11776 -+ sql_print_warning(ER(ER_FORCING_CLOSE),my_progname,
11777 -+ tmp->thread_id,
11778 -+ (tmp->main_security_ctx.user ?
11779 -+ tmp->main_security_ctx.user : ""));
11780 -+ close_connection(tmp,0,0);
11781 -+ }
11782 -+#endif
11783 -+ DBUG_PRINT("quit",("Unlocking LOCK_thread_count"));
11784 -+ (void) pthread_mutex_unlock(&LOCK_thread_count);
11785 -+ }
11786 -+ /* All threads has now been aborted */
11787 -+ DBUG_PRINT("quit",("Waiting for threads to die (count=%u)",thread_count));
11788 -+ (void) pthread_mutex_lock(&LOCK_thread_count);
11789 -+ while (thread_count)
11790 -+ {
11791 -+ (void) pthread_cond_wait(&COND_thread_count,&LOCK_thread_count);
11792 -+ DBUG_PRINT("quit",("One thread died (count=%u)",thread_count));
11793 -+ }
11794 -+ (void) pthread_mutex_unlock(&LOCK_thread_count);
11795 -+
11796 -+ close_active_mi();
11797 -+ DBUG_PRINT("quit",("close_connections thread"));
11798 -+ DBUG_VOID_RETURN;
11799 -+}
11800 -+
11801 -+
11802 -+static void close_server_sock()
11803 -+{
11804 -+#ifdef HAVE_CLOSE_SERVER_SOCK
11805 -+ DBUG_ENTER("close_server_sock");
11806 -+ my_socket tmp_sock;
11807 -+ tmp_sock=ip_sock;
11808 -+ if (tmp_sock != INVALID_SOCKET)
11809 -+ {
11810 -+ ip_sock=INVALID_SOCKET;
11811 -+ DBUG_PRINT("info",("calling shutdown on TCP/IP socket"));
11812 -+ VOID(shutdown(tmp_sock, SHUT_RDWR));
11813 -+#if defined(__NETWARE__)
11814 -+ /*
11815 -+ The following code is disabled for normal systems as it causes MySQL
11816 -+ to hang on AIX 4.3 during shutdown
11817 -+ */
11818 -+ DBUG_PRINT("info",("calling closesocket on TCP/IP socket"));
11819 -+ VOID(closesocket(tmp_sock));
11820 -+#endif
11821 -+ }
11822 -+ tmp_sock=unix_sock;
11823 -+ if (tmp_sock != INVALID_SOCKET)
11824 -+ {
11825 -+ unix_sock=INVALID_SOCKET;
11826 -+ DBUG_PRINT("info",("calling shutdown on unix socket"));
11827 -+ VOID(shutdown(tmp_sock, SHUT_RDWR));
11828 -+#if defined(__NETWARE__)
11829 -+ /*
11830 -+ The following code is disabled for normal systems as it may cause MySQL
11831 -+ to hang on AIX 4.3 during shutdown
11832 -+ */
11833 -+ DBUG_PRINT("info",("calling closesocket on unix/IP socket"));
11834 -+ VOID(closesocket(tmp_sock));
11835 -+#endif
11836 -+ VOID(unlink(mysqld_unix_port));
11837 -+ }
11838 -+ DBUG_VOID_RETURN;
11839 -+#endif
11840 -+}
11841 -+
11842 -+#endif /*EMBEDDED_LIBRARY*/
11843 -+
11844 -+
11845 -+void kill_mysql(void)
11846 -+{
11847 -+ DBUG_ENTER("kill_mysql");
11848 -+
11849 -+#if defined(SIGNALS_DONT_BREAK_READ) && !defined(EMBEDDED_LIBRARY)
11850 -+ abort_loop=1; // Break connection loops
11851 -+ close_server_sock(); // Force accept to wake up
11852 -+#endif
11853 -+
11854 -+#if defined(__WIN__)
11855 -+#if !defined(EMBEDDED_LIBRARY)
11856 -+ {
11857 -+ if (!SetEvent(hEventShutdown))
11858 -+ {
11859 -+ DBUG_PRINT("error",("Got error: %ld from SetEvent",GetLastError()));
11860 -+ }
11861 -+ /*
11862 -+ or:
11863 -+ HANDLE hEvent=OpenEvent(0, FALSE, "MySqlShutdown");
11864 -+ SetEvent(hEventShutdown);
11865 -+ CloseHandle(hEvent);
11866 -+ */
11867 -+ }
11868 -+#endif
11869 -+#elif defined(HAVE_PTHREAD_KILL)
11870 -+ if (pthread_kill(signal_thread, MYSQL_KILL_SIGNAL))
11871 -+ {
11872 -+ DBUG_PRINT("error",("Got error %d from pthread_kill",errno)); /* purecov: inspected */
11873 -+ }
11874 -+#elif !defined(SIGNALS_DONT_BREAK_READ)
11875 -+ kill(current_pid, MYSQL_KILL_SIGNAL);
11876 -+#endif
11877 -+ DBUG_PRINT("quit",("After pthread_kill"));
11878 -+ shutdown_in_progress=1; // Safety if kill didn't work
11879 -+#ifdef SIGNALS_DONT_BREAK_READ
11880 -+ if (!kill_in_progress)
11881 -+ {
11882 -+ pthread_t tmp;
11883 -+ abort_loop=1;
11884 -+ if (pthread_create(&tmp,&connection_attrib, kill_server_thread,
11885 -+ (void*) 0))
11886 -+ sql_print_error("Can't create thread to kill server");
11887 -+ }
11888 -+#endif
11889 -+ DBUG_VOID_RETURN;
11890 -+}
11891 -+
11892 -+/**
11893 -+ Force server down. Kill all connections and threads and exit.
11894 -+
11895 -+ @param sig_ptr Signal number that caused kill_server to be called.
11896 -+
11897 -+ @note
11898 -+ A signal number of 0 mean that the function was not called
11899 -+ from a signal handler and there is thus no signal to block
11900 -+ or stop, we just want to kill the server.
11901 -+*/
11902 -+
11903 -+#if defined(__NETWARE__)
11904 -+extern "C" void kill_server(int sig_ptr)
11905 -+#define RETURN_FROM_KILL_SERVER return
11906 -+#elif !defined(__WIN__)
11907 -+static void *kill_server(void *sig_ptr)
11908 -+#define RETURN_FROM_KILL_SERVER return 0
11909 -+#else
11910 -+static void __cdecl kill_server(int sig_ptr)
11911 -+#define RETURN_FROM_KILL_SERVER return
11912 -+#endif
11913 -+{
11914 -+ DBUG_ENTER("kill_server");
11915 -+#ifndef EMBEDDED_LIBRARY
11916 -+ int sig=(int) (long) sig_ptr; // This is passed a int
11917 -+ // if there is a signal during the kill in progress, ignore the other
11918 -+ if (kill_in_progress) // Safety
11919 -+ {
11920 -+ DBUG_LEAVE;
11921 -+ RETURN_FROM_KILL_SERVER;
11922 -+ }
11923 -+ kill_in_progress=TRUE;
11924 -+ abort_loop=1; // This should be set
11925 -+ if (sig != 0) // 0 is not a valid signal number
11926 -+ my_sigset(sig, SIG_IGN); /* purify inspected */
11927 -+ if (sig == MYSQL_KILL_SIGNAL || sig == 0)
11928 -+ sql_print_information(ER(ER_NORMAL_SHUTDOWN),my_progname);
11929 -+ else
11930 -+ sql_print_error(ER(ER_GOT_SIGNAL),my_progname,sig); /* purecov: inspected */
11931 -+
11932 -+#if defined(HAVE_SMEM) && defined(__WIN__)
11933 -+ /*
11934 -+ Send event to smem_event_connect_request for aborting
11935 -+ */
11936 -+ if (!SetEvent(smem_event_connect_request))
11937 -+ {
11938 -+ DBUG_PRINT("error",
11939 -+ ("Got error: %ld from SetEvent of smem_event_connect_request",
11940 -+ GetLastError()));
11941 -+ }
11942 -+#endif
11943 -+
11944 -+ close_connections();
11945 -+ if (sig != MYSQL_KILL_SIGNAL &&
11946 -+ sig != 0)
11947 -+ unireg_abort(1); /* purecov: inspected */
11948 -+ else
11949 -+ unireg_end();
11950 -+
11951 -+ /* purecov: begin deadcode */
11952 -+#ifdef __NETWARE__
11953 -+ if (!event_flag)
11954 -+ pthread_join(select_thread, NULL); // wait for main thread
11955 -+#endif /* __NETWARE__ */
11956 -+
11957 -+ DBUG_LEAVE; // Must match DBUG_ENTER()
11958 -+ my_thread_end();
11959 -+ pthread_exit(0);
11960 -+ /* purecov: end */
11961 -+
11962 -+ RETURN_FROM_KILL_SERVER; // Avoid compiler warnings
11963 -+
11964 -+#else /* EMBEDDED_LIBRARY*/
11965 -+
11966 -+ DBUG_LEAVE;
11967 -+ RETURN_FROM_KILL_SERVER;
11968 -+
11969 -+#endif /* EMBEDDED_LIBRARY */
11970 -+}
11971 -+
11972 -+
11973 -+#if defined(USE_ONE_SIGNAL_HAND) || (defined(__NETWARE__) && defined(SIGNALS_DONT_BREAK_READ))
11974 -+pthread_handler_t kill_server_thread(void *arg __attribute__((unused)))
11975 -+{
11976 -+ my_thread_init(); // Initialize new thread
11977 -+ kill_server(0);
11978 -+ /* purecov: begin deadcode */
11979 -+ my_thread_end();
11980 -+ pthread_exit(0);
11981 -+ return 0;
11982 -+ /* purecov: end */
11983 -+}
11984 -+#endif
11985 -+
11986 -+
11987 -+extern "C" sig_handler print_signal_warning(int sig)
11988 -+{
11989 -+ if (global_system_variables.log_warnings)
11990 -+ sql_print_warning("Got signal %d from thread %ld", sig,my_thread_id());
11991 -+#ifdef SIGNAL_HANDLER_RESET_ON_DELIVERY
11992 -+ my_sigset(sig,print_signal_warning); /* int. thread system calls */
11993 -+#endif
11994 -+#if !defined(__WIN__) && !defined(__NETWARE__)
11995 -+ if (sig == SIGALRM)
11996 -+ alarm(2); /* reschedule alarm */
11997 -+#endif
11998 -+}
11999 -+
12000 -+#ifndef EMBEDDED_LIBRARY
12001 -+
12002 -+/**
12003 -+ cleanup all memory and end program nicely.
12004 -+
12005 -+ If SIGNALS_DONT_BREAK_READ is defined, this function is called
12006 -+ by the main thread. To get MySQL to shut down nicely in this case
12007 -+ (Mac OS X) we have to call exit() instead if pthread_exit().
12008 -+
12009 -+ @note
12010 -+ This function never returns.
12011 -+*/
12012 -+void unireg_end(void)
12013 -+{
12014 -+ clean_up(1);
12015 -+ my_thread_end();
12016 -+#if defined(SIGNALS_DONT_BREAK_READ) && !defined(__NETWARE__)
12017 -+ exit(0);
12018 -+#else
12019 -+ pthread_exit(0); // Exit is in main thread
12020 -+#endif
12021 -+}
12022 -+
12023 -+extern "C" void unireg_abort(int exit_code)
12024 -+{
12025 -+ DBUG_ENTER("unireg_abort");
12026 -+
12027 -+ if (opt_help)
12028 -+ usage();
12029 -+ if (exit_code)
12030 -+ sql_print_error("Aborting\n");
12031 -+ clean_up(!opt_help && (exit_code || !opt_bootstrap)); /* purecov: inspected */
12032 -+ DBUG_PRINT("quit",("done with cleanup in unireg_abort"));
12033 -+ wait_for_signal_thread_to_end();
12034 -+ clean_up_mutexes();
12035 -+ my_end(opt_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0);
12036 -+ exit(exit_code); /* purecov: inspected */
12037 -+}
12038 -+
12039 -+#endif /*EMBEDDED_LIBRARY*/
12040 -+
12041 -+
12042 -+void clean_up(bool print_message)
12043 -+{
12044 -+ DBUG_PRINT("exit",("clean_up"));
12045 -+ if (cleanup_done++)
12046 -+ return; /* purecov: inspected */
12047 -+
12048 -+ stop_handle_manager();
12049 -+ release_ddl_log();
12050 -+
12051 -+ /*
12052 -+ make sure that handlers finish up
12053 -+ what they have that is dependent on the binlog
12054 -+ */
12055 -+ ha_binlog_end(current_thd);
12056 -+
12057 -+ logger.cleanup_base();
12058 -+
12059 -+ injector::free_instance();
12060 -+ mysql_bin_log.cleanup();
12061 -+
12062 -+#ifdef HAVE_REPLICATION
12063 -+ if (use_slave_mask)
12064 -+ bitmap_free(&slave_error_mask);
12065 -+#endif
12066 -+ my_tz_free();
12067 -+ my_database_names_free();
12068 -+#ifndef NO_EMBEDDED_ACCESS_CHECKS
12069 -+ servers_free(1);
12070 -+ acl_free(1);
12071 -+ grant_free();
12072 -+#endif
12073 -+ query_cache_destroy();
12074 -+ table_cache_free();
12075 -+ table_def_free();
12076 -+ hostname_cache_free();
12077 -+ item_user_lock_free();
12078 -+ lex_free(); /* Free some memory */
12079 -+ item_create_cleanup();
12080 -+ set_var_free();
12081 -+ free_charsets();
12082 -+ if (!opt_noacl)
12083 -+ {
12084 -+#ifdef HAVE_DLOPEN
12085 -+ udf_free();
12086 -+#endif
12087 -+ }
12088 -+ plugin_shutdown();
12089 -+ ha_end();
12090 -+ if (tc_log)
12091 -+ tc_log->close();
12092 -+ xid_cache_free();
12093 -+ delete_elements(&key_caches, (void (*)(const char*, uchar*)) free_key_cache);
12094 -+ multi_keycache_free();
12095 -+ free_status_vars();
12096 -+ end_thr_alarm(1); /* Free allocated memory */
12097 -+ my_free_open_file_info();
12098 -+ my_free((char*) global_system_variables.date_format,
12099 -+ MYF(MY_ALLOW_ZERO_PTR));
12100 -+ my_free((char*) global_system_variables.time_format,
12101 -+ MYF(MY_ALLOW_ZERO_PTR));
12102 -+ my_free((char*) global_system_variables.datetime_format,
12103 -+ MYF(MY_ALLOW_ZERO_PTR));
12104 -+ if (defaults_argv)
12105 -+ free_defaults(defaults_argv);
12106 -+ my_free(sys_init_connect.value, MYF(MY_ALLOW_ZERO_PTR));
12107 -+ my_free(sys_init_slave.value, MYF(MY_ALLOW_ZERO_PTR));
12108 -+ my_free(sys_var_general_log_path.value, MYF(MY_ALLOW_ZERO_PTR));
12109 -+ my_free(sys_var_slow_log_path.value, MYF(MY_ALLOW_ZERO_PTR));
12110 -+ free_tmpdir(&mysql_tmpdir_list);
12111 -+#ifdef HAVE_REPLICATION
12112 -+ my_free(slave_load_tmpdir,MYF(MY_ALLOW_ZERO_PTR));
12113 -+#endif
12114 -+ x_free(opt_bin_logname);
12115 -+ x_free(opt_relay_logname);
12116 -+ x_free(opt_secure_file_priv);
12117 -+ bitmap_free(&temp_pool);
12118 -+ free_max_user_conn();
12119 -+#ifdef HAVE_REPLICATION
12120 -+ end_slave_list();
12121 -+#endif
12122 -+ delete binlog_filter;
12123 -+ delete rpl_filter;
12124 -+#ifndef EMBEDDED_LIBRARY
12125 -+ end_ssl();
12126 -+#endif
12127 -+ vio_end();
12128 -+#ifdef USE_REGEX
12129 -+ my_regex_end();
12130 -+#endif
12131 -+#if defined(ENABLED_DEBUG_SYNC)
12132 -+ /* End the debug sync facility. See debug_sync.cc. */
12133 -+ debug_sync_end();
12134 -+#endif /* defined(ENABLED_DEBUG_SYNC) */
12135 -+
12136 -+#if !defined(EMBEDDED_LIBRARY)
12137 -+ if (!opt_bootstrap)
12138 -+ (void) my_delete(pidfile_name,MYF(0)); // This may not always exist
12139 -+#endif
12140 -+ if (print_message && errmesg && server_start_time)
12141 -+ sql_print_information(ER(ER_SHUTDOWN_COMPLETE),my_progname);
12142 -+ thread_scheduler.end();
12143 -+ finish_client_errs();
12144 -+ my_free((uchar*) my_error_unregister(ER_ERROR_FIRST, ER_ERROR_LAST),
12145 -+ MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR));
12146 -+ DBUG_PRINT("quit", ("Error messages freed"));
12147 -+ /* Tell main we are ready */
12148 -+ logger.cleanup_end();
12149 -+ (void) pthread_mutex_lock(&LOCK_thread_count);
12150 -+ DBUG_PRINT("quit", ("got thread count lock"));
12151 -+ ready_to_exit=1;
12152 -+ /* do the broadcast inside the lock to ensure that my_end() is not called */
12153 -+ (void) pthread_cond_broadcast(&COND_thread_count);
12154 -+ (void) pthread_mutex_unlock(&LOCK_thread_count);
12155 -+
12156 -+ /*
12157 -+ The following lines may never be executed as the main thread may have
12158 -+ killed us
12159 -+ */
12160 -+ DBUG_PRINT("quit", ("done with cleanup"));
12161 -+} /* clean_up */
12162 -+
12163 -+
12164 -+#ifndef EMBEDDED_LIBRARY
12165 -+
12166 -+/**
12167 -+ This is mainly needed when running with purify, but it's still nice to
12168 -+ know that all child threads have died when mysqld exits.
12169 -+*/
12170 -+static void wait_for_signal_thread_to_end()
12171 -+{
12172 -+#ifndef __NETWARE__
12173 -+ uint i;
12174 -+ /*
12175 -+ Wait up to 10 seconds for signal thread to die. We use this mainly to
12176 -+ avoid getting warnings that my_thread_end has not been called
12177 -+ */
12178 -+ for (i= 0 ; i < 100 && signal_thread_in_use; i++)
12179 -+ {
12180 -+ if (pthread_kill(signal_thread, MYSQL_KILL_SIGNAL) != ESRCH)
12181 -+ break;
12182 -+ my_sleep(100); // Give it time to die
12183 -+ }
12184 -+#endif
12185 -+}
12186 -+
12187 -+
12188 -+static void clean_up_mutexes()
12189 -+{
12190 -+ (void) pthread_mutex_destroy(&LOCK_mysql_create_db);
12191 -+ (void) pthread_mutex_destroy(&LOCK_lock_db);
12192 -+ (void) pthread_mutex_destroy(&LOCK_Acl);
12193 -+ (void) rwlock_destroy(&LOCK_grant);
12194 -+ (void) pthread_mutex_destroy(&LOCK_open);
12195 -+ (void) pthread_mutex_destroy(&LOCK_thread_count);
12196 -+ (void) pthread_mutex_destroy(&LOCK_mapped_file);
12197 -+ (void) pthread_mutex_destroy(&LOCK_status);
12198 -+ (void) pthread_mutex_destroy(&LOCK_error_log);
12199 -+ (void) pthread_mutex_destroy(&LOCK_delayed_insert);
12200 -+ (void) pthread_mutex_destroy(&LOCK_delayed_status);
12201 -+ (void) pthread_mutex_destroy(&LOCK_delayed_create);
12202 -+ (void) pthread_mutex_destroy(&LOCK_manager);
12203 -+ (void) pthread_mutex_destroy(&LOCK_crypt);
12204 -+ (void) pthread_mutex_destroy(&LOCK_bytes_sent);
12205 -+ (void) pthread_mutex_destroy(&LOCK_bytes_received);
12206 -+ (void) pthread_mutex_destroy(&LOCK_user_conn);
12207 -+ (void) pthread_mutex_destroy(&LOCK_connection_count);
12208 -+ Events::destroy_mutexes();
12209 -+#ifdef HAVE_OPENSSL
12210 -+ (void) pthread_mutex_destroy(&LOCK_des_key_file);
12211 -+#ifndef HAVE_YASSL
12212 -+ for (int i= 0; i < CRYPTO_num_locks(); ++i)
12213 -+ (void) rwlock_destroy(&openssl_stdlocks[i].lock);
12214 -+ OPENSSL_free(openssl_stdlocks);
12215 -+#endif
12216 -+#endif
12217 -+#ifdef HAVE_REPLICATION
12218 -+ (void) pthread_mutex_destroy(&LOCK_rpl_status);
12219 -+ (void) pthread_cond_destroy(&COND_rpl_status);
12220 -+#endif
12221 -+ (void) pthread_mutex_destroy(&LOCK_active_mi);
12222 -+ (void) rwlock_destroy(&LOCK_sys_init_connect);
12223 -+ (void) rwlock_destroy(&LOCK_sys_init_slave);
12224 -+ (void) pthread_mutex_destroy(&LOCK_global_system_variables);
12225 -+ (void) rwlock_destroy(&LOCK_system_variables_hash);
12226 -+ (void) pthread_mutex_destroy(&LOCK_global_read_lock);
12227 -+ (void) pthread_mutex_destroy(&LOCK_uuid_generator);
12228 -+ (void) pthread_mutex_destroy(&LOCK_prepared_stmt_count);
12229 -+ (void) pthread_cond_destroy(&COND_thread_count);
12230 -+ (void) pthread_cond_destroy(&COND_refresh);
12231 -+ (void) pthread_cond_destroy(&COND_global_read_lock);
12232 -+ (void) pthread_cond_destroy(&COND_thread_cache);
12233 -+ (void) pthread_cond_destroy(&COND_flush_thread_cache);
12234 -+ (void) pthread_cond_destroy(&COND_manager);
12235 -+}
12236 -+
12237 -+#endif /*EMBEDDED_LIBRARY*/
12238 -+
12239 -+
12240 -+/****************************************************************************
12241 -+** Init IP and UNIX socket
12242 -+****************************************************************************/
12243 -+
12244 -+#ifndef EMBEDDED_LIBRARY
12245 -+static void set_ports()
12246 -+{
12247 -+ char *env;
12248 -+ if (!mysqld_port && !opt_disable_networking)
12249 -+ { // Get port if not from commandline
12250 -+ mysqld_port= MYSQL_PORT;
12251 -+
12252 -+ /*
12253 -+ if builder specifically requested a default port, use that
12254 -+ (even if it coincides with our factory default).
12255 -+ only if they didn't do we check /etc/services (and, failing
12256 -+ on that, fall back to the factory default of 3306).
12257 -+ either default can be overridden by the environment variable
12258 -+ MYSQL_TCP_PORT, which in turn can be overridden with command
12259 -+ line options.
12260 -+ */
12261 -+
12262 -+#if MYSQL_PORT_DEFAULT == 0
12263 -+ struct servent *serv_ptr;
12264 -+ if ((serv_ptr= getservbyname("mysql", "tcp")))
12265 -+ mysqld_port= ntohs((u_short) serv_ptr->s_port); /* purecov: inspected */
12266 -+#endif
12267 -+ if ((env = getenv("MYSQL_TCP_PORT")))
12268 -+ mysqld_port= (uint) atoi(env); /* purecov: inspected */
12269 -+ }
12270 -+ if (!mysqld_unix_port)
12271 -+ {
12272 -+#ifdef __WIN__
12273 -+ mysqld_unix_port= (char*) MYSQL_NAMEDPIPE;
12274 -+#else
12275 -+ mysqld_unix_port= (char*) MYSQL_UNIX_ADDR;
12276 -+#endif
12277 -+ if ((env = getenv("MYSQL_UNIX_PORT")))
12278 -+ mysqld_unix_port= env; /* purecov: inspected */
12279 -+ }
12280 -+}
12281 -+
12282 -+/* Change to run as another user if started with --user */
12283 -+
12284 -+static struct passwd *check_user(const char *user)
12285 -+{
12286 -+#if !defined(__WIN__) && !defined(__NETWARE__)
12287 -+ struct passwd *tmp_user_info;
12288 -+ uid_t user_id= geteuid();
12289 -+
12290 -+ // Don't bother if we aren't superuser
12291 -+ if (user_id)
12292 -+ {
12293 -+ if (user)
12294 -+ {
12295 -+ /* Don't give a warning, if real user is same as given with --user */
12296 -+ /* purecov: begin tested */
12297 -+ tmp_user_info= getpwnam(user);
12298 -+ if ((!tmp_user_info || user_id != tmp_user_info->pw_uid) &&
12299 -+ global_system_variables.log_warnings)
12300 -+ sql_print_warning(
12301 -+ "One can only use the --user switch if running as root\n");
12302 -+ /* purecov: end */
12303 -+ }
12304 -+ return NULL;
12305 -+ }
12306 -+ if (!user)
12307 -+ {
12308 -+ if (!opt_bootstrap)
12309 -+ {
12310 -+ sql_print_error("Fatal error: Please read \"Security\" section of the manual to find out how to run mysqld as root!\n");
12311 -+ unireg_abort(1);
12312 -+ }
12313 -+ return NULL;
12314 -+ }
12315 -+ /* purecov: begin tested */
12316 -+ if (!strcmp(user,"root"))
12317 -+ return NULL; // Avoid problem with dynamic libraries
12318 -+
12319 -+ if (!(tmp_user_info= getpwnam(user)))
12320 -+ {
12321 -+ // Allow a numeric uid to be used
12322 -+ const char *pos;
12323 -+ for (pos= user; my_isdigit(mysqld_charset,*pos); pos++) ;
12324 -+ if (*pos) // Not numeric id
12325 -+ goto err;
12326 -+ if (!(tmp_user_info= getpwuid(atoi(user))))
12327 -+ goto err;
12328 -+ }
12329 -+ return tmp_user_info;
12330 -+ /* purecov: end */
12331 -+
12332 -+err:
12333 -+ sql_print_error("Fatal error: Can't change to run as user '%s' ; Please check that the user exists!\n",user);
12334 -+ unireg_abort(1);
12335 -+
12336 -+#ifdef PR_SET_DUMPABLE
12337 -+ if (test_flags & TEST_CORE_ON_SIGNAL)
12338 -+ {
12339 -+ /* inform kernel that process is dumpable */
12340 -+ (void) prctl(PR_SET_DUMPABLE, 1);
12341 -+ }
12342 -+#endif
12343 -+
12344 -+#endif
12345 -+ return NULL;
12346 -+}
12347 -+
12348 -+static void set_user(const char *user, struct passwd *user_info_arg)
12349 -+{
12350 -+ /* purecov: begin tested */
12351 -+#if !defined(__WIN__) && !defined(__NETWARE__)
12352 -+ DBUG_ASSERT(user_info_arg != 0);
12353 -+#ifdef HAVE_INITGROUPS
12354 -+ /*
12355 -+ We can get a SIGSEGV when calling initgroups() on some systems when NSS
12356 -+ is configured to use LDAP and the server is statically linked. We set
12357 -+ calling_initgroups as a flag to the SIGSEGV handler that is then used to
12358 -+ output a specific message to help the user resolve this problem.
12359 -+ */
12360 -+ calling_initgroups= TRUE;
12361 -+ initgroups((char*) user, user_info_arg->pw_gid);
12362 -+ calling_initgroups= FALSE;
12363 -+#endif
12364 -+ if (setgid(user_info_arg->pw_gid) == -1)
12365 -+ {
12366 -+ sql_perror("setgid");
12367 -+ unireg_abort(1);
12368 -+ }
12369 -+ if (setuid(user_info_arg->pw_uid) == -1)
12370 -+ {
12371 -+ sql_perror("setuid");
12372 -+ unireg_abort(1);
12373 -+ }
12374 -+#endif
12375 -+ /* purecov: end */
12376 -+}
12377 -+
12378 -+
12379 -+static void set_effective_user(struct passwd *user_info_arg)
12380 -+{
12381 -+#if !defined(__WIN__) && !defined(__NETWARE__)
12382 -+ DBUG_ASSERT(user_info_arg != 0);
12383 -+ if (setregid((gid_t)-1, user_info_arg->pw_gid) == -1)
12384 -+ {
12385 -+ sql_perror("setregid");
12386 -+ unireg_abort(1);
12387 -+ }
12388 -+ if (setreuid((uid_t)-1, user_info_arg->pw_uid) == -1)
12389 -+ {
12390 -+ sql_perror("setreuid");
12391 -+ unireg_abort(1);
12392 -+ }
12393 -+#endif
12394 -+}
12395 -+
12396 -+
12397 -+/** Change root user if started with @c --chroot . */
12398 -+static void set_root(const char *path)
12399 -+{
12400 -+#if !defined(__WIN__) && !defined(__NETWARE__)
12401 -+ if (chroot(path) == -1)
12402 -+ {
12403 -+ sql_perror("chroot");
12404 -+ unireg_abort(1);
12405 -+ }
12406 -+ my_setwd("/", MYF(0));
12407 -+#endif
12408 -+}
12409 -+
12410 -+static void network_init(void)
12411 -+{
12412 -+ struct sockaddr_in IPaddr;
12413 -+#ifdef HAVE_SYS_UN_H
12414 -+ struct sockaddr_un UNIXaddr;
12415 -+#endif
12416 -+ int arg=1;
12417 -+ int ret;
12418 -+ uint waited;
12419 -+ uint this_wait;
12420 -+ uint retry;
12421 -+ DBUG_ENTER("network_init");
12422 -+ LINT_INIT(ret);
12423 -+
12424 -+ if (thread_scheduler.init())
12425 -+ unireg_abort(1); /* purecov: inspected */
12426 -+
12427 -+ set_ports();
12428 -+
12429 -+ if (mysqld_port != 0 && !opt_disable_networking && !opt_bootstrap)
12430 -+ {
12431 -+ DBUG_PRINT("general",("IP Socket is %d",mysqld_port));
12432 -+ ip_sock = socket(AF_INET, SOCK_STREAM, 0);
12433 -+ if (ip_sock == INVALID_SOCKET)
12434 -+ {
12435 -+ DBUG_PRINT("error",("Got error: %d from socket()",socket_errno));
12436 -+ sql_perror(ER(ER_IPSOCK_ERROR)); /* purecov: tested */
12437 -+ unireg_abort(1); /* purecov: tested */
12438 -+ }
12439 -+ bzero((char*) &IPaddr, sizeof(IPaddr));
12440 -+ IPaddr.sin_family = AF_INET;
12441 -+ IPaddr.sin_addr.s_addr = my_bind_addr;
12442 -+ IPaddr.sin_port = (unsigned short) htons((unsigned short) mysqld_port);
12443 -+
12444 -+#ifndef __WIN__
12445 -+ /*
12446 -+ We should not use SO_REUSEADDR on windows as this would enable a
12447 -+ user to open two mysqld servers with the same TCP/IP port.
12448 -+ */
12449 -+ (void) setsockopt(ip_sock,SOL_SOCKET,SO_REUSEADDR,(char*)&arg,sizeof(arg));
12450 -+#endif /* __WIN__ */
12451 -+ /*
12452 -+ Sometimes the port is not released fast enough when stopping and
12453 -+ restarting the server. This happens quite often with the test suite
12454 -+ on busy Linux systems. Retry to bind the address at these intervals:
12455 -+ Sleep intervals: 1, 2, 4, 6, 9, 13, 17, 22, ...
12456 -+ Retry at second: 1, 3, 7, 13, 22, 35, 52, 74, ...
12457 -+ Limit the sequence by mysqld_port_timeout (set --port-open-timeout=#).
12458 -+ */
12459 -+ for (waited= 0, retry= 1; ; retry++, waited+= this_wait)
12460 -+ {
12461 -+ if (((ret= bind(ip_sock, my_reinterpret_cast(struct sockaddr *) (&IPaddr),
12462 -+ sizeof(IPaddr))) >= 0) ||
12463 -+ (socket_errno != SOCKET_EADDRINUSE) ||
12464 -+ (waited >= mysqld_port_timeout))
12465 -+ break;
12466 -+ sql_print_information("Retrying bind on TCP/IP port %u", mysqld_port);
12467 -+ this_wait= retry * retry / 3 + 1;
12468 -+ sleep(this_wait);
12469 -+ }
12470 -+ if (ret < 0)
12471 -+ {
12472 -+ DBUG_PRINT("error",("Got error: %d from bind",socket_errno));
12473 -+ sql_perror("Can't start server: Bind on TCP/IP port");
12474 -+ sql_print_error("Do you already have another mysqld server running on port: %d ?",mysqld_port);
12475 -+ unireg_abort(1);
12476 -+ }
12477 -+ if (listen(ip_sock,(int) back_log) < 0)
12478 -+ {
12479 -+ sql_perror("Can't start server: listen() on TCP/IP port");
12480 -+ sql_print_error("listen() on TCP/IP failed with error %d",
12481 -+ socket_errno);
12482 -+ unireg_abort(1);
12483 -+ }
12484 -+ }
12485 -+
12486 -+#ifdef __NT__
12487 -+ /* create named pipe */
12488 -+ if (Service.IsNT() && mysqld_unix_port[0] && !opt_bootstrap &&
12489 -+ opt_enable_named_pipe)
12490 -+ {
12491 -+
12492 -+ strxnmov(pipe_name, sizeof(pipe_name)-1, "\\\\.\\pipe\\",
12493 -+ mysqld_unix_port, NullS);
12494 -+ bzero((char*) &saPipeSecurity, sizeof(saPipeSecurity));
12495 -+ bzero((char*) &sdPipeDescriptor, sizeof(sdPipeDescriptor));
12496 -+ if (!InitializeSecurityDescriptor(&sdPipeDescriptor,
12497 -+ SECURITY_DESCRIPTOR_REVISION))
12498 -+ {
12499 -+ sql_perror("Can't start server : Initialize security descriptor");
12500 -+ unireg_abort(1);
12501 -+ }
12502 -+ if (!SetSecurityDescriptorDacl(&sdPipeDescriptor, TRUE, NULL, FALSE))
12503 -+ {
12504 -+ sql_perror("Can't start server : Set security descriptor");
12505 -+ unireg_abort(1);
12506 -+ }
12507 -+ saPipeSecurity.nLength = sizeof(SECURITY_ATTRIBUTES);
12508 -+ saPipeSecurity.lpSecurityDescriptor = &sdPipeDescriptor;
12509 -+ saPipeSecurity.bInheritHandle = FALSE;
12510 -+ if ((hPipe= CreateNamedPipe(pipe_name,
12511 -+ PIPE_ACCESS_DUPLEX|FILE_FLAG_OVERLAPPED,
12512 -+ PIPE_TYPE_BYTE |
12513 -+ PIPE_READMODE_BYTE |
12514 -+ PIPE_WAIT,
12515 -+ PIPE_UNLIMITED_INSTANCES,
12516 -+ (int) global_system_variables.net_buffer_length,
12517 -+ (int) global_system_variables.net_buffer_length,
12518 -+ NMPWAIT_USE_DEFAULT_WAIT,
12519 -+ &saPipeSecurity)) == INVALID_HANDLE_VALUE)
12520 -+ {
12521 -+ LPVOID lpMsgBuf;
12522 -+ int error=GetLastError();
12523 -+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
12524 -+ FORMAT_MESSAGE_FROM_SYSTEM,
12525 -+ NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
12526 -+ (LPTSTR) &lpMsgBuf, 0, NULL );
12527 -+ sql_perror((char *)lpMsgBuf);
12528 -+ LocalFree(lpMsgBuf);
12529 -+ unireg_abort(1);
12530 -+ }
12531 -+ }
12532 -+#endif
12533 -+
12534 -+#if defined(HAVE_SYS_UN_H)
12535 -+ /*
12536 -+ ** Create the UNIX socket
12537 -+ */
12538 -+ if (mysqld_unix_port[0] && !opt_bootstrap)
12539 -+ {
12540 -+ DBUG_PRINT("general",("UNIX Socket is %s",mysqld_unix_port));
12541 -+
12542 -+ if (strlen(mysqld_unix_port) > (sizeof(UNIXaddr.sun_path) - 1))
12543 -+ {
12544 -+ sql_print_error("The socket file path is too long (> %u): %s",
12545 -+ (uint) sizeof(UNIXaddr.sun_path) - 1, mysqld_unix_port);
12546 -+ unireg_abort(1);
12547 -+ }
12548 -+ if ((unix_sock= socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
12549 -+ {
12550 -+ sql_perror("Can't start server : UNIX Socket "); /* purecov: inspected */
12551 -+ unireg_abort(1); /* purecov: inspected */
12552 -+ }
12553 -+ bzero((char*) &UNIXaddr, sizeof(UNIXaddr));
12554 -+ UNIXaddr.sun_family = AF_UNIX;
12555 -+ strmov(UNIXaddr.sun_path, mysqld_unix_port);
12556 -+ (void) unlink(mysqld_unix_port);
12557 -+ (void) setsockopt(unix_sock,SOL_SOCKET,SO_REUSEADDR,(char*)&arg,
12558 -+ sizeof(arg));
12559 -+ umask(0);
12560 -+ if (bind(unix_sock, my_reinterpret_cast(struct sockaddr *) (&UNIXaddr),
12561 -+ sizeof(UNIXaddr)) < 0)
12562 -+ {
12563 -+ sql_perror("Can't start server : Bind on unix socket"); /* purecov: tested */
12564 -+ sql_print_error("Do you already have another mysqld server running on socket: %s ?",mysqld_unix_port);
12565 -+ unireg_abort(1); /* purecov: tested */
12566 -+ }
12567 -+ umask(((~my_umask) & 0666));
12568 -+#if defined(S_IFSOCK) && defined(SECURE_SOCKETS)
12569 -+ (void) chmod(mysqld_unix_port,S_IFSOCK); /* Fix solaris 2.6 bug */
12570 -+#endif
12571 -+ if (listen(unix_sock,(int) back_log) < 0)
12572 -+ sql_print_warning("listen() on Unix socket failed with error %d",
12573 -+ socket_errno);
12574 -+ }
12575 -+#endif
12576 -+ DBUG_PRINT("info",("server started"));
12577 -+ DBUG_VOID_RETURN;
12578 -+}
12579 -+
12580 -+#endif /*!EMBEDDED_LIBRARY*/
12581 -+
12582 -+
12583 -+#ifndef EMBEDDED_LIBRARY
12584 -+/**
12585 -+ Close a connection.
12586 -+
12587 -+ @param thd Thread handle
12588 -+ @param errcode Error code to print to console
12589 -+ @param lock 1 if we have have to lock LOCK_thread_count
12590 -+
12591 -+ @note
12592 -+ For the connection that is doing shutdown, this is called twice
12593 -+*/
12594 -+void close_connection(THD *thd, uint errcode, bool lock)
12595 -+{
12596 -+ st_vio *vio;
12597 -+ DBUG_ENTER("close_connection");
12598 -+ DBUG_PRINT("enter",("fd: %s error: '%s'",
12599 -+ thd->net.vio ? vio_description(thd->net.vio) :
12600 -+ "(not connected)",
12601 -+ errcode ? ER(errcode) : ""));
12602 -+ if (lock)
12603 -+ (void) pthread_mutex_lock(&LOCK_thread_count);
12604 -+ thd->killed= THD::KILL_CONNECTION;
12605 -+ if ((vio= thd->net.vio) != 0)
12606 -+ {
12607 -+ if (errcode)
12608 -+ net_send_error(thd, errcode, ER(errcode)); /* purecov: inspected */
12609 -+ vio_close(vio); /* vio is freed in delete thd */
12610 -+ }
12611 -+ if (lock)
12612 -+ (void) pthread_mutex_unlock(&LOCK_thread_count);
12613 -+ DBUG_VOID_RETURN;
12614 -+}
12615 -+#endif /* EMBEDDED_LIBRARY */
12616 -+
12617 -+
12618 -+/** Called when a thread is aborted. */
12619 -+/* ARGSUSED */
12620 -+extern "C" sig_handler end_thread_signal(int sig __attribute__((unused)))
12621 -+{
12622 -+ THD *thd=current_thd;
12623 -+ DBUG_ENTER("end_thread_signal");
12624 -+ if (thd && ! thd->bootstrap)
12625 -+ {
12626 -+ statistic_increment(killed_threads, &LOCK_status);
12627 -+ thread_scheduler.end_thread(thd,0); /* purecov: inspected */
12628 -+ }
12629 -+ DBUG_VOID_RETURN; /* purecov: deadcode */
12630 -+}
12631 -+
12632 -+
12633 -+/*
12634 -+ Unlink thd from global list of available connections and free thd
12635 -+
12636 -+ SYNOPSIS
12637 -+ unlink_thd()
12638 -+ thd Thread handler
12639 -+
12640 -+ NOTES
12641 -+ LOCK_thread_count is locked and left locked
12642 -+*/
12643 -+
12644 -+void unlink_thd(THD *thd)
12645 -+{
12646 -+ DBUG_ENTER("unlink_thd");
12647 -+ DBUG_PRINT("enter", ("thd: 0x%lx", (long) thd));
12648 -+ thd->cleanup();
12649 -+
12650 -+ pthread_mutex_lock(&LOCK_connection_count);
12651 -+ --connection_count;
12652 -+ pthread_mutex_unlock(&LOCK_connection_count);
12653 -+
12654 -+ (void) pthread_mutex_lock(&LOCK_thread_count);
12655 -+ thread_count--;
12656 -+ delete thd;
12657 -+ DBUG_VOID_RETURN;
12658 -+}
12659 -+
12660 -+
12661 -+/*
12662 -+ Store thread in cache for reuse by new connections
12663 -+
12664 -+ SYNOPSIS
12665 -+ cache_thread()
12666 -+
12667 -+ NOTES
12668 -+ LOCK_thread_count has to be locked
12669 -+
12670 -+ RETURN
12671 -+ 0 Thread was not put in cache
12672 -+ 1 Thread is to be reused by new connection.
12673 -+ (ie, caller should return, not abort with pthread_exit())
12674 -+*/
12675 -+
12676 -+
12677 -+static bool cache_thread()
12678 -+{
12679 -+ safe_mutex_assert_owner(&LOCK_thread_count);
12680 -+ if (cached_thread_count < thread_cache_size &&
12681 -+ ! abort_loop && !kill_cached_threads)
12682 -+ {
12683 -+ /* Don't kill the thread, just put it in cache for reuse */
12684 -+ DBUG_PRINT("info", ("Adding thread to cache"));
12685 -+ cached_thread_count++;
12686 -+ while (!abort_loop && ! wake_thread && ! kill_cached_threads)
12687 -+ (void) pthread_cond_wait(&COND_thread_cache, &LOCK_thread_count);
12688 -+ cached_thread_count--;
12689 -+ if (kill_cached_threads)
12690 -+ pthread_cond_signal(&COND_flush_thread_cache);
12691 -+ if (wake_thread)
12692 -+ {
12693 -+ THD *thd;
12694 -+ wake_thread--;
12695 -+ thd= thread_cache.get();
12696 -+ thd->thread_stack= (char*) &thd; // For store_globals
12697 -+ (void) thd->store_globals();
12698 -+ /*
12699 -+ THD::mysys_var::abort is associated with physical thread rather
12700 -+ than with THD object. So we need to reset this flag before using
12701 -+ this thread for handling of new THD object/connection.
12702 -+ */
12703 -+ thd->mysys_var->abort= 0;
12704 -+ thd->thr_create_utime= my_micro_time();
12705 -+ threads.append(thd);
12706 -+ return(1);
12707 -+ }
12708 -+ }
12709 -+ return(0);
12710 -+}
12711 -+
12712 -+
12713 -+/*
12714 -+ End thread for the current connection
12715 -+
12716 -+ SYNOPSIS
12717 -+ one_thread_per_connection_end()
12718 -+ thd Thread handler
12719 -+ put_in_cache Store thread in cache, if there is room in it
12720 -+ Normally this is true in all cases except when we got
12721 -+ out of resources initializing the current thread
12722 -+
12723 -+ NOTES
12724 -+ If thread is cached, we will wait until thread is scheduled to be
12725 -+ reused and then we will return.
12726 -+ If thread is not cached, we end the thread.
12727 -+
12728 -+ RETURN
12729 -+ 0 Signal to handle_one_connection to reuse connection
12730 -+*/
12731 -+
12732 -+bool one_thread_per_connection_end(THD *thd, bool put_in_cache)
12733 -+{
12734 -+ DBUG_ENTER("one_thread_per_connection_end");
12735 -+ unlink_thd(thd);
12736 -+ if (put_in_cache)
12737 -+ put_in_cache= cache_thread();
12738 -+ pthread_mutex_unlock(&LOCK_thread_count);
12739 -+ if (put_in_cache)
12740 -+ DBUG_RETURN(0); // Thread is reused
12741 -+
12742 -+ /* It's safe to broadcast outside a lock (COND... is not deleted here) */
12743 -+ DBUG_PRINT("signal", ("Broadcasting COND_thread_count"));
12744 -+ DBUG_LEAVE; // Must match DBUG_ENTER()
12745 -+ my_thread_end();
12746 -+ (void) pthread_cond_broadcast(&COND_thread_count);
12747 -+
12748 -+ pthread_exit(0);
12749 -+ return 0; // Avoid compiler warnings
12750 -+}
12751 -+
12752 -+
12753 -+void flush_thread_cache()
12754 -+{
12755 -+ (void) pthread_mutex_lock(&LOCK_thread_count);
12756 -+ kill_cached_threads++;
12757 -+ while (cached_thread_count)
12758 -+ {
12759 -+ pthread_cond_broadcast(&COND_thread_cache);
12760 -+ pthread_cond_wait(&COND_flush_thread_cache,&LOCK_thread_count);
12761 -+ }
12762 -+ kill_cached_threads--;
12763 -+ (void) pthread_mutex_unlock(&LOCK_thread_count);
12764 -+}
12765 -+
12766 -+
12767 -+#ifdef THREAD_SPECIFIC_SIGPIPE
12768 -+/**
12769 -+ Aborts a thread nicely. Comes here on SIGPIPE.
12770 -+
12771 -+ @todo
12772 -+ One should have to fix that thr_alarm know about this thread too.
12773 -+*/
12774 -+extern "C" sig_handler abort_thread(int sig __attribute__((unused)))
12775 -+{
12776 -+ THD *thd=current_thd;
12777 -+ DBUG_ENTER("abort_thread");
12778 -+ if (thd)
12779 -+ thd->killed= THD::KILL_CONNECTION;
12780 -+ DBUG_VOID_RETURN;
12781 -+}
12782 -+#endif
12783 -+
12784 -+
12785 -+/******************************************************************************
12786 -+ Setup a signal thread with handles all signals.
12787 -+ Because Linux doesn't support schemas use a mutex to check that
12788 -+ the signal thread is ready before continuing
12789 -+******************************************************************************/
12790 -+
12791 -+#if defined(__WIN__)
12792 -+
12793 -+
12794 -+/*
12795 -+ On Windows, we use native SetConsoleCtrlHandler for handle events like Ctrl-C
12796 -+ with graceful shutdown.
12797 -+ Also, we do not use signal(), but SetUnhandledExceptionFilter instead - as it
12798 -+ provides possibility to pass the exception to just-in-time debugger, collect
12799 -+ dumps and potentially also the exception and thread context used to output
12800 -+ callstack.
12801 -+*/
12802 -+
12803 -+static BOOL WINAPI console_event_handler( DWORD type )
12804 -+{
12805 -+ DBUG_ENTER("console_event_handler");
12806 -+#ifndef EMBEDDED_LIBRARY
12807 -+ if(type == CTRL_C_EVENT)
12808 -+ {
12809 -+ /*
12810 -+ Do not shutdown before startup is finished and shutdown
12811 -+ thread is initialized. Otherwise there is a race condition
12812 -+ between main thread doing initialization and CTRL-C thread doing
12813 -+ cleanup, which can result into crash.
12814 -+ */
12815 -+#ifndef EMBEDDED_LIBRARY
12816 -+ if(hEventShutdown)
12817 -+ kill_mysql();
12818 -+ else
12819 -+#endif
12820 -+ sql_print_warning("CTRL-C ignored during startup");
12821 -+ DBUG_RETURN(TRUE);
12822 -+ }
12823 -+#endif
12824 -+ DBUG_RETURN(FALSE);
12825 -+}
12826 -+
12827 -+
12828 -+/*
12829 -+ In Visual Studio 2005 and later, default SIGABRT handler will overwrite
12830 -+ any unhandled exception filter set by the application and will try to
12831 -+ call JIT debugger. This is not what we want, this we calling __debugbreak
12832 -+ to stop in debugger, if process is being debugged or to generate
12833 -+ EXCEPTION_BREAKPOINT and then handle_segfault will do its magic.
12834 -+*/
12835 -+
12836 -+#if (_MSC_VER >= 1400)
12837 -+static void my_sigabrt_handler(int sig)
12838 -+{
12839 -+ __debugbreak();
12840 -+}
12841 -+#endif /*_MSC_VER >=1400 */
12842 -+
12843 -+void win_install_sigabrt_handler(void)
12844 -+{
12845 -+#if (_MSC_VER >=1400)
12846 -+ /*abort() should not override our exception filter*/
12847 -+ _set_abort_behavior(0,_CALL_REPORTFAULT);
12848 -+ signal(SIGABRT,my_sigabrt_handler);
12849 -+#endif /* _MSC_VER >=1400 */
12850 -+}
12851 -+
12852 -+#ifdef DEBUG_UNHANDLED_EXCEPTION_FILTER
12853 -+#define DEBUGGER_ATTACH_TIMEOUT 120
12854 -+/*
12855 -+ Wait for debugger to attach and break into debugger. If debugger is not attached,
12856 -+ resume after timeout.
12857 -+*/
12858 -+static void wait_for_debugger(int timeout_sec)
12859 -+{
12860 -+ if(!IsDebuggerPresent())
12861 -+ {
12862 -+ int i;
12863 -+ printf("Waiting for debugger to attach, pid=%u\n",GetCurrentProcessId());
12864 -+ fflush(stdout);
12865 -+ for(i= 0; i < timeout_sec; i++)
12866 -+ {
12867 -+ Sleep(1000);
12868 -+ if(IsDebuggerPresent())
12869 -+ {
12870 -+ /* Break into debugger */
12871 -+ __debugbreak();
12872 -+ return;
12873 -+ }
12874 -+ }
12875 -+ printf("pid=%u, debugger not attached after %d seconds, resuming\n",GetCurrentProcessId(),
12876 -+ timeout_sec);
12877 -+ fflush(stdout);
12878 -+ }
12879 -+}
12880 -+#endif /* DEBUG_UNHANDLED_EXCEPTION_FILTER */
12881 -+
12882 -+LONG WINAPI my_unhandler_exception_filter(EXCEPTION_POINTERS *ex_pointers)
12883 -+{
12884 -+ static BOOL first_time= TRUE;
12885 -+ if(!first_time)
12886 -+ {
12887 -+ /*
12888 -+ This routine can be called twice, typically
12889 -+ when detaching in JIT debugger.
12890 -+ Return EXCEPTION_EXECUTE_HANDLER to terminate process.
12891 -+ */
12892 -+ return EXCEPTION_EXECUTE_HANDLER;
12893 -+ }
12894 -+ first_time= FALSE;
12895 -+#ifdef DEBUG_UNHANDLED_EXCEPTION_FILTER
12896 -+ /*
12897 -+ Unfortunately there is no clean way to debug unhandled exception filters,
12898 -+ as debugger does not stop there(also documented in MSDN)
12899 -+ To overcome, one could put a MessageBox, but this will not work in service.
12900 -+ Better solution is to print error message and sleep some minutes
12901 -+ until debugger is attached
12902 -+ */
12903 -+ wait_for_debugger(DEBUGGER_ATTACH_TIMEOUT);
12904 -+#endif /* DEBUG_UNHANDLED_EXCEPTION_FILTER */
12905 -+ __try
12906 -+ {
12907 -+ my_set_exception_pointers(ex_pointers);
12908 -+ handle_segfault(ex_pointers->ExceptionRecord->ExceptionCode);
12909 -+ }
12910 -+ __except(EXCEPTION_EXECUTE_HANDLER)
12911 -+ {
12912 -+ DWORD written;
12913 -+ const char msg[] = "Got exception in exception handler!\n";
12914 -+ WriteFile(GetStdHandle(STD_OUTPUT_HANDLE),msg, sizeof(msg)-1,
12915 -+ &written,NULL);
12916 -+ }
12917 -+ /*
12918 -+ Return EXCEPTION_CONTINUE_SEARCH to give JIT debugger
12919 -+ (drwtsn32 or vsjitdebugger) possibility to attach,
12920 -+ if JIT debugger is configured.
12921 -+ Windows Error reporting might generate a dump here.
12922 -+ */
12923 -+ return EXCEPTION_CONTINUE_SEARCH;
12924 -+}
12925 -+
12926 -+
12927 -+static void init_signals(void)
12928 -+{
12929 -+ win_install_sigabrt_handler();
12930 -+ if(opt_console)
12931 -+ SetConsoleCtrlHandler(console_event_handler,TRUE);
12932 -+
12933 -+ /* Avoid MessageBox()es*/
12934 -+ _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
12935 -+ _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
12936 -+ _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
12937 -+ _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
12938 -+ _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
12939 -+ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
12940 -+
12941 -+ /*
12942 -+ Do not use SEM_NOGPFAULTERRORBOX in the following SetErrorMode (),
12943 -+ because it would prevent JIT debugger and Windows error reporting
12944 -+ from working. We need WER or JIT-debugging, since our own unhandled
12945 -+ exception filter is not guaranteed to work in all situation
12946 -+ (like heap corruption or stack overflow)
12947 -+ */
12948 -+ SetErrorMode(SetErrorMode(0) | SEM_FAILCRITICALERRORS
12949 -+ | SEM_NOOPENFILEERRORBOX);
12950 -+ SetUnhandledExceptionFilter(my_unhandler_exception_filter);
12951 -+}
12952 -+
12953 -+
12954 -+static void start_signal_handler(void)
12955 -+{
12956 -+#ifndef EMBEDDED_LIBRARY
12957 -+ // Save vm id of this process
12958 -+ if (!opt_bootstrap)
12959 -+ create_pid_file();
12960 -+#endif /* EMBEDDED_LIBRARY */
12961 -+}
12962 -+
12963 -+
12964 -+static void check_data_home(const char *path)
12965 -+{}
12966 -+
12967 -+
12968 -+#elif defined(__NETWARE__)
12969 -+
12970 -+/// down server event callback.
12971 -+void mysql_down_server_cb(void *, void *)
12972 -+{
12973 -+ event_flag= TRUE;
12974 -+ kill_server(0);
12975 -+}
12976 -+
12977 -+
12978 -+/// destroy callback resources.
12979 -+void mysql_cb_destroy(void *)
12980 -+{
12981 -+ UnRegisterEventNotification(eh); // cleanup down event notification
12982 -+ NX_UNWRAP_INTERFACE(ref);
12983 -+ /* Deregister NSS volume deactivation event */
12984 -+ NX_UNWRAP_INTERFACE(refneb);
12985 -+ if (neb_consumer_id)
12986 -+ UnRegisterConsumer(neb_consumer_id, NULL);
12987 -+}
12988 -+
12989 -+
12990 -+/// initialize callbacks.
12991 -+void mysql_cb_init()
12992 -+{
12993 -+ // register for down server event
12994 -+ void *handle = getnlmhandle();
12995 -+ rtag_t rt= AllocateResourceTag(handle, "MySQL Down Server Callback",
12996 -+ EventSignature);
12997 -+ NX_WRAP_INTERFACE((void *)mysql_down_server_cb, 2, (void **)&ref);
12998 -+ eh= RegisterForEventNotification(rt, EVENT_PRE_DOWN_SERVER,
12999 -+ EVENT_PRIORITY_APPLICATION,
13000 -+ NULL, ref, NULL);
13001 -+
13002 -+ /*
13003 -+ Register for volume deactivation event
13004 -+ Wrap the callback function, as it is called by non-LibC thread
13005 -+ */
13006 -+ (void *) NX_WRAP_INTERFACE(neb_event_callback, 1, &refneb);
13007 -+ registerwithneb();
13008 -+
13009 -+ NXVmRegisterExitHandler(mysql_cb_destroy, NULL); // clean-up
13010 -+}
13011 -+
13012 -+
13013 -+/** To get the name of the NetWare volume having MySQL data folder. */
13014 -+static void getvolumename()
13015 -+{
13016 -+ char *p;
13017 -+ /*
13018 -+ We assume that data path is already set.
13019 -+ If not it won't come here. Terminate after volume name
13020 -+ */
13021 -+ if ((p= strchr(mysql_real_data_home, ':')))
13022 -+ strmake(datavolname, mysql_real_data_home,
13023 -+ (uint) (p - mysql_real_data_home));
13024 -+}
13025 -+
13026 -+
13027 -+/**
13028 -+ Registering with NEB for NSS Volume Deactivation event.
13029 -+*/
13030 -+
13031 -+static void registerwithneb()
13032 -+{
13033 -+
13034 -+ ConsumerRegistrationInfo reg_info;
13035 -+
13036 -+ /* Clear NEB registration structure */
13037 -+ bzero((char*) &reg_info, sizeof(struct ConsumerRegistrationInfo));
13038 -+
13039 -+ /* Fill the NEB consumer information structure */
13040 -+ reg_info.CRIVersion= 1; // NEB version
13041 -+ /* NEB Consumer name */
13042 -+ reg_info.CRIConsumerName= (BYTE *) "MySQL Database Server";
13043 -+ /* Event of interest */
13044 -+ reg_info.CRIEventName= (BYTE *) "NSS.ChangeVolState.Enter";
13045 -+ reg_info.CRIUserParameter= NULL; // Consumer Info
13046 -+ reg_info.CRIEventFlags= 0; // Event flags
13047 -+ /* Consumer NLM handle */
13048 -+ reg_info.CRIOwnerID= (LoadDefinitionStructure *)getnlmhandle();
13049 -+ reg_info.CRIConsumerESR= NULL; // No consumer ESR required
13050 -+ reg_info.CRISecurityToken= 0; // No security token for the event
13051 -+ reg_info.CRIConsumerFlags= 0; // SMP_ENABLED_BIT;
13052 -+ reg_info.CRIFilterName= 0; // No event filtering
13053 -+ reg_info.CRIFilterDataLength= 0; // No filtering data
13054 -+ reg_info.CRIFilterData= 0; // No filtering data
13055 -+ /* Callback function for the event */
13056 -+ (void *)reg_info.CRIConsumerCallback= (void *) refneb;
13057 -+ reg_info.CRIOrder= 0; // Event callback order
13058 -+ reg_info.CRIConsumerType= CHECK_CONSUMER; // Consumer type
13059 -+
13060 -+ /* Register for the event with NEB */
13061 -+ if (RegisterConsumer(&reg_info))
13062 -+ {
13063 -+ consoleprintf("Failed to register for NSS Volume Deactivation event \n");
13064 -+ return;
13065 -+ }
13066 -+ /* This ID is required for deregistration */
13067 -+ neb_consumer_id= reg_info.CRIConsumerID;
13068 -+
13069 -+ /* Get MySQL data volume name, stored in global variable datavolname */
13070 -+ getvolumename();
13071 -+
13072 -+ /*
13073 -+ Get the NSS volume ID of the MySQL Data volume.
13074 -+ Volume ID is stored in a global variable
13075 -+ */
13076 -+ getvolumeID((BYTE*) datavolname);
13077 -+}
13078 -+
13079 -+
13080 -+/**
13081 -+ Callback for NSS Volume Deactivation event.
13082 -+*/
13083 -+
13084 -+ulong neb_event_callback(struct EventBlock *eblock)
13085 -+{
13086 -+ EventChangeVolStateEnter_s *voldata;
13087 -+ extern bool nw_panic;
13088 -+
13089 -+ voldata= (EventChangeVolStateEnter_s *)eblock->EBEventData;
13090 -+
13091 -+ /* Deactivation of a volume */
13092 -+ if ((voldata->oldState == zVOLSTATE_ACTIVE &&
13093 -+ voldata->newState == zVOLSTATE_DEACTIVE ||
13094 -+ voldata->newState == zVOLSTATE_MAINTENANCE))
13095 -+ {
13096 -+ /*
13097 -+ Ensure that we bring down MySQL server only for MySQL data
13098 -+ volume deactivation
13099 -+ */
13100 -+ if (!memcmp(&voldata->volID, &datavolid, sizeof(VolumeID_t)))
13101 -+ {
13102 -+ consoleprintf("MySQL data volume is deactivated, shutting down MySQL Server \n");
13103 -+ event_flag= TRUE;
13104 -+ nw_panic = TRUE;
13105 -+ event_flag= TRUE;
13106 -+ kill_server(0);
13107 -+ }
13108 -+ }
13109 -+ return 0;
13110 -+}
13111 -+
13112 -+
13113 -+#define ADMIN_VOL_PATH "_ADMIN:/Volumes/"
13114 -+
13115 -+/**
13116 -+ Function to get NSS volume ID of the MySQL data.
13117 -+*/
13118 -+static void getvolumeID(BYTE *volumeName)
13119 -+{
13120 -+ char path[zMAX_FULL_NAME];
13121 -+ Key_t rootKey= 0, fileKey= 0;
13122 -+ QUAD getInfoMask;
13123 -+ zInfo_s info;
13124 -+ STATUS status;
13125 -+
13126 -+ /* Get the root key */
13127 -+ if ((status= zRootKey(0, &rootKey)) != zOK)
13128 -+ {
13129 -+ consoleprintf("\nGetNSSVolumeProperties - Failed to get root key, status: %d\n.", (int) status);
13130 -+ goto exit;
13131 -+ }
13132 -+
13133 -+ /*
13134 -+ Get the file key. This is the key to the volume object in the
13135 -+ NSS admin volumes directory.
13136 -+ */
13137 -+
13138 -+ strxmov(path, (const char *) ADMIN_VOL_PATH, (const char *) volumeName,
13139 -+ NullS);
13140 -+ if ((status= zOpen(rootKey, zNSS_TASK, zNSPACE_LONG|zMODE_UTF8,
13141 -+ (BYTE *) path, zRR_READ_ACCESS, &fileKey)) != zOK)
13142 -+ {
13143 -+ consoleprintf("\nGetNSSVolumeProperties - Failed to get file, status: %d\n.", (int) status);
13144 -+ goto exit;
13145 -+ }
13146 -+
13147 -+ getInfoMask= zGET_IDS | zGET_VOLUME_INFO ;
13148 -+ if ((status= zGetInfo(fileKey, getInfoMask, sizeof(info),
13149 -+ zINFO_VERSION_A, &info)) != zOK)
13150 -+ {
13151 -+ consoleprintf("\nGetNSSVolumeProperties - Failed in zGetInfo, status: %d\n.", (int) status);
13152 -+ goto exit;
13153 -+ }
13154 -+
13155 -+ /* Copy the data to global variable */
13156 -+ datavolid.timeLow= info.vol.volumeID.timeLow;
13157 -+ datavolid.timeMid= info.vol.volumeID.timeMid;
13158 -+ datavolid.timeHighAndVersion= info.vol.volumeID.timeHighAndVersion;
13159 -+ datavolid.clockSeqHighAndReserved= info.vol.volumeID.clockSeqHighAndReserved;
13160 -+ datavolid.clockSeqLow= info.vol.volumeID.clockSeqLow;
13161 -+ /* This is guranteed to be 6-byte length (but sizeof() would be better) */
13162 -+ memcpy(datavolid.node, info.vol.volumeID.node, (unsigned int) 6);
13163 -+
13164 -+exit:
13165 -+ if (rootKey)
13166 -+ zClose(rootKey);
13167 -+ if (fileKey)
13168 -+ zClose(fileKey);
13169 -+}
13170 -+
13171 -+
13172 -+static void init_signals(void)
13173 -+{
13174 -+ int signals[] = {SIGINT,SIGILL,SIGFPE,SIGSEGV,SIGTERM,SIGABRT};
13175 -+
13176 -+ for (uint i=0 ; i < sizeof(signals)/sizeof(int) ; i++)
13177 -+ signal(signals[i], kill_server);
13178 -+ mysql_cb_init(); // initialize callbacks
13179 -+
13180 -+}
13181 -+
13182 -+
13183 -+static void start_signal_handler(void)
13184 -+{
13185 -+ // Save vm id of this process
13186 -+ if (!opt_bootstrap)
13187 -+ create_pid_file();
13188 -+ // no signal handler
13189 -+}
13190 -+
13191 -+
13192 -+/**
13193 -+ Warn if the data is on a Traditional volume.
13194 -+
13195 -+ @note
13196 -+ Already done by mysqld_safe
13197 -+*/
13198 -+
13199 -+static void check_data_home(const char *path)
13200 -+{
13201 -+}
13202 -+
13203 -+#endif /*__WIN__ || __NETWARE */
13204 -+
13205 -+#ifdef HAVE_LINUXTHREADS
13206 -+#define UNSAFE_DEFAULT_LINUX_THREADS 200
13207 -+#endif
13208 -+
13209 -+
13210 -+#if BACKTRACE_DEMANGLE
13211 -+#include <cxxabi.h>
13212 -+extern "C" char *my_demangle(const char *mangled_name, int *status)
13213 -+{
13214 -+ return abi::__cxa_demangle(mangled_name, NULL, NULL, status);
13215 -+}
13216 -+#endif
13217 -+
13218 -+
13219 -+extern "C" sig_handler handle_segfault(int sig)
13220 -+{
13221 -+ time_t curr_time;
13222 -+ struct tm tm;
13223 -+
13224 -+ /*
13225 -+ Strictly speaking, one needs a mutex here
13226 -+ but since we have got SIGSEGV already, things are a mess
13227 -+ so not having the mutex is not as bad as possibly using a buggy
13228 -+ mutex - so we keep things simple
13229 -+ */
13230 -+ if (segfaulted)
13231 -+ {
13232 -+ fprintf(stderr, "Fatal " SIGNAL_FMT " while backtracing\n", sig);
13233 -+ exit(1);
13234 -+ }
13235 -+
13236 -+ segfaulted = 1;
13237 -+
13238 -+ curr_time= my_time(0);
13239 -+ localtime_r(&curr_time, &tm);
13240 -+
13241 -+ fprintf(stderr,"\
13242 -+%02d%02d%02d %2d:%02d:%02d - mysqld got " SIGNAL_FMT " ;\n\
13243 -+This could be because you hit a bug. It is also possible that this binary\n\
13244 -+or one of the libraries it was linked against is corrupt, improperly built,\n\
13245 -+or misconfigured. This error can also be caused by malfunctioning hardware.\n",
13246 -+ tm.tm_year % 100, tm.tm_mon+1, tm.tm_mday,
13247 -+ tm.tm_hour, tm.tm_min, tm.tm_sec,
13248 -+ sig);
13249 -+ fprintf(stderr, "\
13250 -+We will try our best to scrape up some info that will hopefully help diagnose\n\
13251 -+the problem, but since we have already crashed, something is definitely wrong\n\
13252 -+and this may fail.\n\n");
13253 -+ fprintf(stderr, "key_buffer_size=%lu\n",
13254 -+ (ulong) dflt_key_cache->key_cache_mem_size);
13255 -+ fprintf(stderr, "read_buffer_size=%ld\n", (long) global_system_variables.read_buff_size);
13256 -+ fprintf(stderr, "max_used_connections=%lu\n", max_used_connections);
13257 -+ fprintf(stderr, "max_threads=%u\n", thread_scheduler.max_threads);
13258 -+ fprintf(stderr, "threads_connected=%u\n", thread_count);
13259 -+ fprintf(stderr, "It is possible that mysqld could use up to \n\
13260 -+key_buffer_size + (read_buffer_size + sort_buffer_size)*max_threads = %lu K\n\
13261 -+bytes of memory\n", ((ulong) dflt_key_cache->key_cache_mem_size +
13262 -+ (global_system_variables.read_buff_size +
13263 -+ global_system_variables.sortbuff_size) *
13264 -+ thread_scheduler.max_threads +
13265 -+ max_connections * sizeof(THD)) / 1024);
13266 -+ fprintf(stderr, "Hope that's ok; if not, decrease some variables in the equation.\n\n");
13267 -+
13268 -+#if defined(HAVE_LINUXTHREADS)
13269 -+ if (sizeof(char*) == 4 && thread_count > UNSAFE_DEFAULT_LINUX_THREADS)
13270 -+ {
13271 -+ fprintf(stderr, "\
13272 -+You seem to be running 32-bit Linux and have %d concurrent connections.\n\
13273 -+If you have not changed STACK_SIZE in LinuxThreads and built the binary \n\
13274 -+yourself, LinuxThreads is quite likely to steal a part of the global heap for\n\
13275 -+the thread stack. Please read http://dev.mysql.com/doc/mysql/en/linux.html\n\n",
13276 -+ thread_count);
13277 -+ }
13278 -+#endif /* HAVE_LINUXTHREADS */
13279 -+
13280 -+#ifdef HAVE_STACKTRACE
13281 -+ THD *thd=current_thd;
13282 -+
13283 -+ if (!(test_flags & TEST_NO_STACKTRACE))
13284 -+ {
13285 -+ fprintf(stderr, "Thread pointer: 0x%lx\n", (long) thd);
13286 -+ fprintf(stderr, "Attempting backtrace. You can use the following "
13287 -+ "information to find out\nwhere mysqld died. If "
13288 -+ "you see no messages after this, something went\n"
13289 -+ "terribly wrong...\n");
13290 -+ my_print_stacktrace(thd ? (uchar*) thd->thread_stack : NULL,
13291 -+ my_thread_stack_size);
13292 -+ }
13293 -+ if (thd)
13294 -+ {
13295 -+ const char *kreason= "UNKNOWN";
13296 -+ switch (thd->killed) {
13297 -+ case THD::NOT_KILLED:
13298 -+ kreason= "NOT_KILLED";
13299 -+ break;
13300 -+ case THD::KILL_BAD_DATA:
13301 -+ kreason= "KILL_BAD_DATA";
13302 -+ break;
13303 -+ case THD::KILL_CONNECTION:
13304 -+ kreason= "KILL_CONNECTION";
13305 -+ break;
13306 -+ case THD::KILL_QUERY:
13307 -+ kreason= "KILL_QUERY";
13308 -+ break;
13309 -+ case THD::KILLED_NO_VALUE:
13310 -+ kreason= "KILLED_NO_VALUE";
13311 -+ break;
13312 -+ }
13313 -+ fprintf(stderr, "\nTrying to get some variables.\n"
13314 -+ "Some pointers may be invalid and cause the dump to abort.\n");
13315 -+ fprintf(stderr, "Query (%p): ", thd->query());
13316 -+ my_safe_print_str(thd->query(), min(1024, thd->query_length()));
13317 -+ fprintf(stderr, "Connection ID (thread ID): %lu\n", (ulong) thd->thread_id);
13318 -+ fprintf(stderr, "Status: %s\n", kreason);
13319 -+ fputc('\n', stderr);
13320 -+ }
13321 -+ fprintf(stderr, "\
13322 -+The manual page at http://dev.mysql.com/doc/mysql/en/crashing.html contains\n\
13323 -+information that should help you find out what is causing the crash.\n");
13324 -+ fflush(stderr);
13325 -+#endif /* HAVE_STACKTRACE */
13326 -+
13327 -+#ifdef HAVE_INITGROUPS
13328 -+ if (calling_initgroups)
13329 -+ fprintf(stderr, "\n\
13330 -+This crash occured while the server was calling initgroups(). This is\n\
13331 -+often due to the use of a mysqld that is statically linked against glibc\n\
13332 -+and configured to use LDAP in /etc/nsswitch.conf. You will need to either\n\
13333 -+upgrade to a version of glibc that does not have this problem (2.3.4 or\n\
13334 -+later when used with nscd), disable LDAP in your nsswitch.conf, or use a\n\
13335 -+mysqld that is not statically linked.\n");
13336 -+#endif
13337 -+
13338 -+#ifdef HAVE_NPTL
13339 -+ if (thd_lib_detected == THD_LIB_LT && !getenv("LD_ASSUME_KERNEL"))
13340 -+ fprintf(stderr,"\n\
13341 -+You are running a statically-linked LinuxThreads binary on an NPTL system.\n\
13342 -+This can result in crashes on some distributions due to LT/NPTL conflicts.\n\
13343 -+You should either build a dynamically-linked binary, or force LinuxThreads\n\
13344 -+to be used with the LD_ASSUME_KERNEL environment variable. Please consult\n\
13345 -+the documentation for your distribution on how to do that.\n");
13346 -+#endif
13347 -+
13348 -+ if (locked_in_memory)
13349 -+ {
13350 -+ fprintf(stderr, "\n\
13351 -+The \"--memlock\" argument, which was enabled, uses system calls that are\n\
13352 -+unreliable and unstable on some operating systems and operating-system\n\
13353 -+versions (notably, some versions of Linux). This crash could be due to use\n\
13354 -+of those buggy OS calls. You should consider whether you really need the\n\
13355 -+\"--memlock\" parameter and/or consult the OS distributer about \"mlockall\"\n\
13356 -+bugs.\n");
13357 -+ }
13358 -+
13359 -+#ifdef HAVE_WRITE_CORE
13360 -+ if (test_flags & TEST_CORE_ON_SIGNAL)
13361 -+ {
13362 -+ fprintf(stderr, "Writing a core file\n");
13363 -+ fflush(stderr);
13364 -+ my_write_core(sig);
13365 -+ }
13366 -+#endif
13367 -+
13368 -+#ifndef __WIN__
13369 -+ /* On Windows, do not terminate, but pass control to exception filter */
13370 -+ exit(1);
13371 -+#endif
13372 -+}
13373 -+
13374 -+#if !defined(__WIN__) && !defined(__NETWARE__)
13375 -+#ifndef SA_RESETHAND
13376 -+#define SA_RESETHAND 0
13377 -+#endif
13378 -+#ifndef SA_NODEFER
13379 -+#define SA_NODEFER 0
13380 -+#endif
13381 -+
13382 -+#ifndef EMBEDDED_LIBRARY
13383 -+
13384 -+static void init_signals(void)
13385 -+{
13386 -+ sigset_t set;
13387 -+ struct sigaction sa;
13388 -+ DBUG_ENTER("init_signals");
13389 -+
13390 -+ my_sigset(THR_SERVER_ALARM,print_signal_warning); // Should never be called!
13391 -+
13392 -+ if (!(test_flags & TEST_NO_STACKTRACE) || (test_flags & TEST_CORE_ON_SIGNAL))
13393 -+ {
13394 -+ sa.sa_flags = SA_RESETHAND | SA_NODEFER;
13395 -+ sigemptyset(&sa.sa_mask);
13396 -+ sigprocmask(SIG_SETMASK,&sa.sa_mask,NULL);
13397 -+
13398 -+#ifdef HAVE_STACKTRACE
13399 -+ my_init_stacktrace();
13400 -+#endif
13401 -+#if defined(__amiga__)
13402 -+ sa.sa_handler=(void(*)())handle_segfault;
13403 -+#else
13404 -+ sa.sa_handler=handle_segfault;
13405 -+#endif
13406 -+ sigaction(SIGSEGV, &sa, NULL);
13407 -+ sigaction(SIGABRT, &sa, NULL);
13408 -+#ifdef SIGBUS
13409 -+ sigaction(SIGBUS, &sa, NULL);
13410 -+#endif
13411 -+ sigaction(SIGILL, &sa, NULL);
13412 -+ sigaction(SIGFPE, &sa, NULL);
13413 -+ }
13414 -+
13415 -+#ifdef HAVE_GETRLIMIT
13416 -+ if (test_flags & TEST_CORE_ON_SIGNAL)
13417 -+ {
13418 -+ /* Change limits so that we will get a core file */
13419 -+ STRUCT_RLIMIT rl;
13420 -+ rl.rlim_cur = rl.rlim_max = RLIM_INFINITY;
13421 -+ if (setrlimit(RLIMIT_CORE, &rl) && global_system_variables.log_warnings)
13422 -+ sql_print_warning("setrlimit could not change the size of core files to 'infinity'; We may not be able to generate a core file on signals");
13423 -+ }
13424 -+#endif
13425 -+ (void) sigemptyset(&set);
13426 -+ my_sigset(SIGPIPE,SIG_IGN);
13427 -+ sigaddset(&set,SIGPIPE);
13428 -+#ifndef IGNORE_SIGHUP_SIGQUIT
13429 -+ sigaddset(&set,SIGQUIT);
13430 -+ sigaddset(&set,SIGHUP);
13431 -+#endif
13432 -+ sigaddset(&set,SIGTERM);
13433 -+
13434 -+ /* Fix signals if blocked by parents (can happen on Mac OS X) */
13435 -+ sigemptyset(&sa.sa_mask);
13436 -+ sa.sa_flags = 0;
13437 -+ sa.sa_handler = print_signal_warning;
13438 -+ sigaction(SIGTERM, &sa, (struct sigaction*) 0);
13439 -+ sa.sa_flags = 0;
13440 -+ sa.sa_handler = print_signal_warning;
13441 -+ sigaction(SIGHUP, &sa, (struct sigaction*) 0);
13442 -+#ifdef SIGTSTP
13443 -+ sigaddset(&set,SIGTSTP);
13444 -+#endif
13445 -+ if (thd_lib_detected != THD_LIB_LT)
13446 -+ sigaddset(&set,THR_SERVER_ALARM);
13447 -+ if (test_flags & TEST_SIGINT)
13448 -+ {
13449 -+ my_sigset(thr_kill_signal, end_thread_signal);
13450 -+ // May be SIGINT
13451 -+ sigdelset(&set, thr_kill_signal);
13452 -+ }
13453 -+ else
13454 -+ sigaddset(&set,SIGINT);
13455 -+ sigprocmask(SIG_SETMASK,&set,NULL);
13456 -+ pthread_sigmask(SIG_SETMASK,&set,NULL);
13457 -+ DBUG_VOID_RETURN;
13458 -+}
13459 -+
13460 -+
13461 -+static void start_signal_handler(void)
13462 -+{
13463 -+ int error;
13464 -+ pthread_attr_t thr_attr;
13465 -+ DBUG_ENTER("start_signal_handler");
13466 -+
13467 -+ (void) pthread_attr_init(&thr_attr);
13468 -+#if !defined(HAVE_DEC_3_2_THREADS)
13469 -+ pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_SYSTEM);
13470 -+ (void) pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED);
13471 -+ if (!(opt_specialflag & SPECIAL_NO_PRIOR))
13472 -+ my_pthread_attr_setprio(&thr_attr,INTERRUPT_PRIOR);
13473 -+#if defined(__ia64__) || defined(__ia64)
13474 -+ /*
13475 -+ Peculiar things with ia64 platforms - it seems we only have half the
13476 -+ stack size in reality, so we have to double it here
13477 -+ */
13478 -+ pthread_attr_setstacksize(&thr_attr,my_thread_stack_size*2);
13479 -+#else
13480 -+ pthread_attr_setstacksize(&thr_attr,my_thread_stack_size);
13481 -+#endif
13482 -+#endif
13483 -+
13484 -+ (void) pthread_mutex_lock(&LOCK_thread_count);
13485 -+ if ((error=pthread_create(&signal_thread,&thr_attr,signal_hand,0)))
13486 -+ {
13487 -+ sql_print_error("Can't create interrupt-thread (error %d, errno: %d)",
13488 -+ error,errno);
13489 -+ exit(1);
13490 -+ }
13491 -+ (void) pthread_cond_wait(&COND_thread_count,&LOCK_thread_count);
13492 -+ pthread_mutex_unlock(&LOCK_thread_count);
13493 -+
13494 -+ (void) pthread_attr_destroy(&thr_attr);
13495 -+ DBUG_VOID_RETURN;
13496 -+}
13497 -+
13498 -+
13499 -+/** This threads handles all signals and alarms. */
13500 -+/* ARGSUSED */
13501 -+pthread_handler_t signal_hand(void *arg __attribute__((unused)))
13502 -+{
13503 -+ sigset_t set;
13504 -+ int sig;
13505 -+ my_thread_init(); // Init new thread
13506 -+ DBUG_ENTER("signal_hand");
13507 -+ signal_thread_in_use= 1;
13508 -+
13509 -+ /*
13510 -+ Setup alarm handler
13511 -+ This should actually be '+ max_number_of_slaves' instead of +10,
13512 -+ but the +10 should be quite safe.
13513 -+ */
13514 -+ init_thr_alarm(thread_scheduler.max_threads +
13515 -+ global_system_variables.max_insert_delayed_threads + 10);
13516 -+ if (thd_lib_detected != THD_LIB_LT && (test_flags & TEST_SIGINT))
13517 -+ {
13518 -+ (void) sigemptyset(&set); // Setup up SIGINT for debug
13519 -+ (void) sigaddset(&set,SIGINT); // For debugging
13520 -+ (void) pthread_sigmask(SIG_UNBLOCK,&set,NULL);
13521 -+ }
13522 -+ (void) sigemptyset(&set); // Setup up SIGINT for debug
13523 -+#ifdef USE_ONE_SIGNAL_HAND
13524 -+ (void) sigaddset(&set,THR_SERVER_ALARM); // For alarms
13525 -+#endif
13526 -+#ifndef IGNORE_SIGHUP_SIGQUIT
13527 -+ (void) sigaddset(&set,SIGQUIT);
13528 -+ (void) sigaddset(&set,SIGHUP);
13529 -+#endif
13530 -+ (void) sigaddset(&set,SIGTERM);
13531 -+ (void) sigaddset(&set,SIGTSTP);
13532 -+
13533 -+ /* Save pid to this process (or thread on Linux) */
13534 -+ if (!opt_bootstrap)
13535 -+ create_pid_file();
13536 -+
13537 -+ /*
13538 -+ signal to start_signal_handler that we are ready
13539 -+ This works by waiting for start_signal_handler to free mutex,
13540 -+ after which we signal it that we are ready.
13541 -+ At this pointer there is no other threads running, so there
13542 -+ should not be any other pthread_cond_signal() calls.
13543 -+ */
13544 -+ (void) pthread_mutex_lock(&LOCK_thread_count);
13545 -+ (void) pthread_mutex_unlock(&LOCK_thread_count);
13546 -+ (void) pthread_cond_broadcast(&COND_thread_count);
13547 -+
13548 -+ (void) pthread_sigmask(SIG_BLOCK,&set,NULL);
13549 -+ for (;;)
13550 -+ {
13551 -+ int error; // Used when debugging
13552 -+ if (shutdown_in_progress && !abort_loop)
13553 -+ {
13554 -+ sig= SIGTERM;
13555 -+ error=0;
13556 -+ }
13557 -+ else
13558 -+ while ((error=my_sigwait(&set,&sig)) == EINTR) ;
13559 -+ if (cleanup_done)
13560 -+ {
13561 -+ DBUG_PRINT("quit",("signal_handler: calling my_thread_end()"));
13562 -+ my_thread_end();
13563 -+ signal_thread_in_use= 0;
13564 -+ DBUG_LEAVE; // Must match DBUG_ENTER()
13565 -+ pthread_exit(0); // Safety
13566 -+ return 0; // Avoid compiler warnings
13567 -+ }
13568 -+ switch (sig) {
13569 -+ case SIGTERM:
13570 -+ case SIGQUIT:
13571 -+ case SIGKILL:
13572 -+#ifdef EXTRA_DEBUG
13573 -+ sql_print_information("Got signal %d to shutdown mysqld",sig);
13574 -+#endif
13575 -+ /* switch to the old log message processing */
13576 -+ logger.set_handlers(LOG_FILE, opt_slow_log ? LOG_FILE:LOG_NONE,
13577 -+ opt_log ? LOG_FILE:LOG_NONE);
13578 -+ DBUG_PRINT("info",("Got signal: %d abort_loop: %d",sig,abort_loop));
13579 -+ if (!abort_loop)
13580 -+ {
13581 -+ abort_loop=1; // mark abort for threads
13582 -+#ifdef USE_ONE_SIGNAL_HAND
13583 -+ pthread_t tmp;
13584 -+ if (!(opt_specialflag & SPECIAL_NO_PRIOR))
13585 -+ my_pthread_attr_setprio(&connection_attrib,INTERRUPT_PRIOR);
13586 -+ if (pthread_create(&tmp,&connection_attrib, kill_server_thread,
13587 -+ (void*) &sig))
13588 -+ sql_print_error("Can't create thread to kill server");
13589 -+#else
13590 -+ kill_server((void*) sig); // MIT THREAD has a alarm thread
13591 -+#endif
13592 -+ }
13593 -+ break;
13594 -+ case SIGHUP:
13595 -+ if (!abort_loop)
13596 -+ {
13597 -+ int not_used;
13598 -+ mysql_print_status(); // Print some debug info
13599 -+ reload_acl_and_cache((THD*) 0,
13600 -+ (REFRESH_LOG | REFRESH_TABLES | REFRESH_FAST |
13601 -+ REFRESH_GRANT |
13602 -+ REFRESH_THREADS | REFRESH_HOSTS),
13603 -+ (TABLE_LIST*) 0, &not_used); // Flush logs
13604 -+ }
13605 -+ /* reenable logs after the options were reloaded */
13606 -+ if (log_output_options & LOG_NONE)
13607 -+ {
13608 -+ logger.set_handlers(LOG_FILE,
13609 -+ opt_slow_log ? LOG_TABLE : LOG_NONE,
13610 -+ opt_log ? LOG_TABLE : LOG_NONE);
13611 -+ }
13612 -+ else
13613 -+ {
13614 -+ logger.set_handlers(LOG_FILE,
13615 -+ opt_slow_log ? log_output_options : LOG_NONE,
13616 -+ opt_log ? log_output_options : LOG_NONE);
13617 -+ }
13618 -+ break;
13619 -+#ifdef USE_ONE_SIGNAL_HAND
13620 -+ case THR_SERVER_ALARM:
13621 -+ process_alarm(sig); // Trigger alarms.
13622 -+ break;
13623 -+#endif
13624 -+ default:
13625 -+#ifdef EXTRA_DEBUG
13626 -+ sql_print_warning("Got signal: %d error: %d",sig,error); /* purecov: tested */
13627 -+#endif
13628 -+ break; /* purecov: tested */
13629 -+ }
13630 -+ }
13631 -+ return(0); /* purecov: deadcode */
13632 -+}
13633 -+
13634 -+static void check_data_home(const char *path)
13635 -+{}
13636 -+
13637 -+#endif /*!EMBEDDED_LIBRARY*/
13638 -+#endif /* __WIN__*/
13639 -+
13640 -+
13641 -+/**
13642 -+ All global error messages are sent here where the first one is stored
13643 -+ for the client.
13644 -+*/
13645 -+/* ARGSUSED */
13646 -+extern "C" int my_message_sql(uint error, const char *str, myf MyFlags);
13647 -+
13648 -+int my_message_sql(uint error, const char *str, myf MyFlags)
13649 -+{
13650 -+ THD *thd;
13651 -+ DBUG_ENTER("my_message_sql");
13652 -+ DBUG_PRINT("error", ("error: %u message: '%s'", error, str));
13653 -+
13654 -+ DBUG_ASSERT(str != NULL);
13655 -+ /*
13656 -+ An error should have a valid error number (!= 0), so it can be caught
13657 -+ in stored procedures by SQL exception handlers.
13658 -+ Calling my_error() with error == 0 is a bug.
13659 -+ Remaining known places to fix:
13660 -+ - storage/myisam/mi_create.c, my_printf_error()
13661 -+ TODO:
13662 -+ DBUG_ASSERT(error != 0);
13663 -+ */
13664 -+
13665 -+ if (error == 0)
13666 -+ {
13667 -+ /* At least, prevent new abuse ... */
13668 -+ DBUG_ASSERT(strncmp(str, "MyISAM table", 12) == 0);
13669 -+ error= ER_UNKNOWN_ERROR;
13670 -+ }
13671 -+
13672 -+ if ((thd= current_thd))
13673 -+ {
13674 -+ /*
13675 -+ TODO: There are two exceptions mechanism (THD and sp_rcontext),
13676 -+ this could be improved by having a common stack of handlers.
13677 -+ */
13678 -+ if (thd->handle_error(error, str,
13679 -+ MYSQL_ERROR::WARN_LEVEL_ERROR))
13680 -+ DBUG_RETURN(0);
13681 -+
13682 -+ thd->is_slave_error= 1; // needed to catch query errors during replication
13683 -+
13684 -+ /*
13685 -+ thd->lex->current_select == 0 if lex structure is not inited
13686 -+ (not query command (COM_QUERY))
13687 -+ */
13688 -+ if (thd->lex->current_select &&
13689 -+ thd->lex->current_select->no_error && !thd->is_fatal_error)
13690 -+ {
13691 -+ DBUG_PRINT("error",
13692 -+ ("Error converted to warning: current_select: no_error %d "
13693 -+ "fatal_error: %d",
13694 -+ (thd->lex->current_select ?
13695 -+ thd->lex->current_select->no_error : 0),
13696 -+ (int) thd->is_fatal_error));
13697 -+ }
13698 -+ else
13699 -+ {
13700 -+ if (! thd->main_da.is_error()) // Return only first message
13701 -+ {
13702 -+ thd->main_da.set_error_status(thd, error, str);
13703 -+ }
13704 -+ query_cache_abort(&thd->net);
13705 -+ }
13706 -+ /*
13707 -+ If a continue handler is found, the error message will be cleared
13708 -+ by the stored procedures code.
13709 -+ */
13710 -+ if (thd->spcont &&
13711 -+ ! (MyFlags & ME_NO_SP_HANDLER) &&
13712 -+ thd->spcont->handle_error(error, MYSQL_ERROR::WARN_LEVEL_ERROR, thd))
13713 -+ {
13714 -+ /*
13715 -+ Do not push any warnings, a handled error must be completely
13716 -+ silenced.
13717 -+ */
13718 -+ DBUG_RETURN(0);
13719 -+ }
13720 -+
13721 -+ /* When simulating OOM, skip writing to error log to avoid mtr errors */
13722 -+ DBUG_EXECUTE_IF("simulate_out_of_memory", DBUG_RETURN(0););
13723 -+
13724 -+ if (!thd->no_warnings_for_error &&
13725 -+ !(MyFlags & ME_NO_WARNING_FOR_ERROR))
13726 -+ {
13727 -+ /*
13728 -+ Suppress infinite recursion if there a memory allocation error
13729 -+ inside push_warning.
13730 -+ */
13731 -+ thd->no_warnings_for_error= TRUE;
13732 -+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, error, str);
13733 -+ thd->no_warnings_for_error= FALSE;
13734 -+ }
13735 -+ }
13736 -+
13737 -+ /* When simulating OOM, skip writing to error log to avoid mtr errors */
13738 -+ DBUG_EXECUTE_IF("simulate_out_of_memory", DBUG_RETURN(0););
13739 -+
13740 -+ if (!thd || MyFlags & ME_NOREFRESH)
13741 -+ sql_print_error("%s: %s",my_progname,str); /* purecov: inspected */
13742 -+ DBUG_RETURN(0);
13743 -+}
13744 -+
13745 -+
13746 -+#ifndef EMBEDDED_LIBRARY
13747 -+extern "C" void *my_str_malloc_mysqld(size_t size);
13748 -+extern "C" void my_str_free_mysqld(void *ptr);
13749 -+
13750 -+void *my_str_malloc_mysqld(size_t size)
13751 -+{
13752 -+ return my_malloc(size, MYF(MY_FAE));
13753 -+}
13754 -+
13755 -+
13756 -+void my_str_free_mysqld(void *ptr)
13757 -+{
13758 -+ my_free((uchar*)ptr, MYF(MY_FAE));
13759 -+}
13760 -+#endif /* EMBEDDED_LIBRARY */
13761 -+
13762 -+
13763 -+#ifdef __WIN__
13764 -+
13765 -+pthread_handler_t handle_shutdown(void *arg)
13766 -+{
13767 -+ MSG msg;
13768 -+ my_thread_init();
13769 -+
13770 -+ /* this call should create the message queue for this thread */
13771 -+ PeekMessage(&msg, NULL, 1, 65534,PM_NOREMOVE);
13772 -+#if !defined(EMBEDDED_LIBRARY)
13773 -+ if (WaitForSingleObject(hEventShutdown,INFINITE)==WAIT_OBJECT_0)
13774 -+#endif /* EMBEDDED_LIBRARY */
13775 -+ kill_server(MYSQL_KILL_SIGNAL);
13776 -+ return 0;
13777 -+}
13778 -+#endif
13779 -+
13780 -+const char *load_default_groups[]= {
13781 -+#ifdef WITH_NDBCLUSTER_STORAGE_ENGINE
13782 -+"mysql_cluster",
13783 -+#endif
13784 -+"mysqld","server", MYSQL_BASE_VERSION, 0, 0};
13785 -+
13786 -+#if defined(__WIN__) && !defined(EMBEDDED_LIBRARY)
13787 -+static const int load_default_groups_sz=
13788 -+sizeof(load_default_groups)/sizeof(load_default_groups[0]);
13789 -+#endif
13790 -+
13791 -+
13792 -+#ifndef EMBEDDED_LIBRARY
13793 -+static
13794 -+int
13795 -+check_enough_stack_size()
13796 -+{
13797 -+ uchar stack_top;
13798 -+
13799 -+ return check_stack_overrun(current_thd, STACK_MIN_SIZE,
13800 -+ &stack_top);
13801 -+}
13802 -+#endif
13803 -+
13804 -+
13805 -+/**
13806 -+ Initialize one of the global date/time format variables.
13807 -+
13808 -+ @param format_type What kind of format should be supported
13809 -+ @param var_ptr Pointer to variable that should be updated
13810 -+
13811 -+ @note
13812 -+ The default value is taken from either opt_date_time_formats[] or
13813 -+ the ISO format (ANSI SQL)
13814 -+
13815 -+ @retval
13816 -+ 0 ok
13817 -+ @retval
13818 -+ 1 error
13819 -+*/
13820 -+
13821 -+static bool init_global_datetime_format(timestamp_type format_type,
13822 -+ DATE_TIME_FORMAT **var_ptr)
13823 -+{
13824 -+ /* Get command line option */
13825 -+ const char *str= opt_date_time_formats[format_type];
13826 -+
13827 -+ if (!str) // No specified format
13828 -+ {
13829 -+ str= get_date_time_format_str(&known_date_time_formats[ISO_FORMAT],
13830 -+ format_type);
13831 -+ /*
13832 -+ Set the "command line" option to point to the generated string so
13833 -+ that we can set global formats back to default
13834 -+ */
13835 -+ opt_date_time_formats[format_type]= str;
13836 -+ }
13837 -+ if (!(*var_ptr= date_time_format_make(format_type, str, strlen(str))))
13838 -+ {
13839 -+ fprintf(stderr, "Wrong date/time format specifier: %s\n", str);
13840 -+ return 1;
13841 -+ }
13842 -+ return 0;
13843 -+}
13844 -+
13845 -+SHOW_VAR com_status_vars[]= {
13846 -+ {"admin_commands", (char*) offsetof(STATUS_VAR, com_other), SHOW_LONG_STATUS},
13847 -+ {"assign_to_keycache", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ASSIGN_TO_KEYCACHE]), SHOW_LONG_STATUS},
13848 -+ {"alter_db", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_DB]), SHOW_LONG_STATUS},
13849 -+ {"alter_db_upgrade", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_DB_UPGRADE]), SHOW_LONG_STATUS},
13850 -+ {"alter_event", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_EVENT]), SHOW_LONG_STATUS},
13851 -+ {"alter_function", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_FUNCTION]), SHOW_LONG_STATUS},
13852 -+ {"alter_procedure", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_PROCEDURE]), SHOW_LONG_STATUS},
13853 -+ {"alter_server", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_SERVER]), SHOW_LONG_STATUS},
13854 -+ {"alter_table", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_TABLE]), SHOW_LONG_STATUS},
13855 -+ {"alter_tablespace", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_TABLESPACE]), SHOW_LONG_STATUS},
13856 -+ {"analyze", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ANALYZE]), SHOW_LONG_STATUS},
13857 -+ {"backup_table", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_BACKUP_TABLE]), SHOW_LONG_STATUS},
13858 -+ {"begin", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_BEGIN]), SHOW_LONG_STATUS},
13859 -+ {"binlog", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_BINLOG_BASE64_EVENT]), SHOW_LONG_STATUS},
13860 -+ {"call_procedure", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CALL]), SHOW_LONG_STATUS},
13861 -+ {"change_db", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CHANGE_DB]), SHOW_LONG_STATUS},
13862 -+ {"change_master", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CHANGE_MASTER]), SHOW_LONG_STATUS},
13863 -+ {"check", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CHECK]), SHOW_LONG_STATUS},
13864 -+ {"checksum", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CHECKSUM]), SHOW_LONG_STATUS},
13865 -+ {"commit", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_COMMIT]), SHOW_LONG_STATUS},
13866 -+ {"create_db", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_DB]), SHOW_LONG_STATUS},
13867 -+ {"create_event", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_EVENT]), SHOW_LONG_STATUS},
13868 -+ {"create_function", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_SPFUNCTION]), SHOW_LONG_STATUS},
13869 -+ {"create_index", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_INDEX]), SHOW_LONG_STATUS},
13870 -+ {"create_procedure", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_PROCEDURE]), SHOW_LONG_STATUS},
13871 -+ {"create_server", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_SERVER]), SHOW_LONG_STATUS},
13872 -+ {"create_table", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_TABLE]), SHOW_LONG_STATUS},
13873 -+ {"create_trigger", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_TRIGGER]), SHOW_LONG_STATUS},
13874 -+ {"create_udf", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_FUNCTION]), SHOW_LONG_STATUS},
13875 -+ {"create_user", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_USER]), SHOW_LONG_STATUS},
13876 -+ {"create_view", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_VIEW]), SHOW_LONG_STATUS},
13877 -+ {"dealloc_sql", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DEALLOCATE_PREPARE]), SHOW_LONG_STATUS},
13878 -+ {"delete", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DELETE]), SHOW_LONG_STATUS},
13879 -+ {"delete_multi", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DELETE_MULTI]), SHOW_LONG_STATUS},
13880 -+ {"do", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DO]), SHOW_LONG_STATUS},
13881 -+ {"drop_db", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_DB]), SHOW_LONG_STATUS},
13882 -+ {"drop_event", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_EVENT]), SHOW_LONG_STATUS},
13883 -+ {"drop_function", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_FUNCTION]), SHOW_LONG_STATUS},
13884 -+ {"drop_index", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_INDEX]), SHOW_LONG_STATUS},
13885 -+ {"drop_procedure", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_PROCEDURE]), SHOW_LONG_STATUS},
13886 -+ {"drop_server", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_SERVER]), SHOW_LONG_STATUS},
13887 -+ {"drop_table", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_TABLE]), SHOW_LONG_STATUS},
13888 -+ {"drop_trigger", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_TRIGGER]), SHOW_LONG_STATUS},
13889 -+ {"drop_user", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_USER]), SHOW_LONG_STATUS},
13890 -+ {"drop_view", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_VIEW]), SHOW_LONG_STATUS},
13891 -+ {"empty_query", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_EMPTY_QUERY]), SHOW_LONG_STATUS},
13892 -+ {"execute_sql", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_EXECUTE]), SHOW_LONG_STATUS},
13893 -+ {"flush", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_FLUSH]), SHOW_LONG_STATUS},
13894 -+ {"grant", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_GRANT]), SHOW_LONG_STATUS},
13895 -+ {"ha_close", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_HA_CLOSE]), SHOW_LONG_STATUS},
13896 -+ {"ha_open", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_HA_OPEN]), SHOW_LONG_STATUS},
13897 -+ {"ha_read", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_HA_READ]), SHOW_LONG_STATUS},
13898 -+ {"help", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_HELP]), SHOW_LONG_STATUS},
13899 -+ {"insert", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_INSERT]), SHOW_LONG_STATUS},
13900 -+ {"insert_select", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_INSERT_SELECT]), SHOW_LONG_STATUS},
13901 -+ {"install_plugin", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_INSTALL_PLUGIN]), SHOW_LONG_STATUS},
13902 -+ {"kill", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_KILL]), SHOW_LONG_STATUS},
13903 -+ {"load", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_LOAD]), SHOW_LONG_STATUS},
13904 -+ {"load_master_data", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_LOAD_MASTER_DATA]), SHOW_LONG_STATUS},
13905 -+ {"load_master_table", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_LOAD_MASTER_TABLE]), SHOW_LONG_STATUS},
13906 -+ {"lock_tables", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_LOCK_TABLES]), SHOW_LONG_STATUS},
13907 -+ {"optimize", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_OPTIMIZE]), SHOW_LONG_STATUS},
13908 -+ {"preload_keys", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_PRELOAD_KEYS]), SHOW_LONG_STATUS},
13909 -+ {"prepare_sql", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_PREPARE]), SHOW_LONG_STATUS},
13910 -+ {"purge", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_PURGE]), SHOW_LONG_STATUS},
13911 -+ {"purge_before_date", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_PURGE_BEFORE]), SHOW_LONG_STATUS},
13912 -+ {"release_savepoint", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_RELEASE_SAVEPOINT]), SHOW_LONG_STATUS},
13913 -+ {"rename_table", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_RENAME_TABLE]), SHOW_LONG_STATUS},
13914 -+ {"rename_user", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_RENAME_USER]), SHOW_LONG_STATUS},
13915 -+ {"repair", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REPAIR]), SHOW_LONG_STATUS},
13916 -+ {"replace", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REPLACE]), SHOW_LONG_STATUS},
13917 -+ {"replace_select", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REPLACE_SELECT]), SHOW_LONG_STATUS},
13918 -+ {"reset", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_RESET]), SHOW_LONG_STATUS},
13919 -+ {"restore_table", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_RESTORE_TABLE]), SHOW_LONG_STATUS},
13920 -+ {"revoke", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REVOKE]), SHOW_LONG_STATUS},
13921 -+ {"revoke_all", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REVOKE_ALL]), SHOW_LONG_STATUS},
13922 -+ {"rollback", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ROLLBACK]), SHOW_LONG_STATUS},
13923 -+ {"rollback_to_savepoint",(char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ROLLBACK_TO_SAVEPOINT]), SHOW_LONG_STATUS},
13924 -+ {"savepoint", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SAVEPOINT]), SHOW_LONG_STATUS},
13925 -+ {"select", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SELECT]), SHOW_LONG_STATUS},
13926 -+ {"set_option", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SET_OPTION]), SHOW_LONG_STATUS},
13927 -+ {"show_authors", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_AUTHORS]), SHOW_LONG_STATUS},
13928 -+ {"show_binlog_events", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_BINLOG_EVENTS]), SHOW_LONG_STATUS},
13929 -+ {"show_binlogs", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_BINLOGS]), SHOW_LONG_STATUS},
13930 -+ {"show_charsets", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CHARSETS]), SHOW_LONG_STATUS},
13931 -+ {"show_collations", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_COLLATIONS]), SHOW_LONG_STATUS},
13932 -+ {"show_column_types", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_COLUMN_TYPES]), SHOW_LONG_STATUS},
13933 -+ {"show_contributors", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CONTRIBUTORS]), SHOW_LONG_STATUS},
13934 -+ {"show_create_db", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CREATE_DB]), SHOW_LONG_STATUS},
13935 -+ {"show_create_event", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CREATE_EVENT]), SHOW_LONG_STATUS},
13936 -+ {"show_create_func", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CREATE_FUNC]), SHOW_LONG_STATUS},
13937 -+ {"show_create_proc", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CREATE_PROC]), SHOW_LONG_STATUS},
13938 -+ {"show_create_table", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CREATE]), SHOW_LONG_STATUS},
13939 -+ {"show_create_trigger", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CREATE_TRIGGER]), SHOW_LONG_STATUS},
13940 -+ {"show_databases", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_DATABASES]), SHOW_LONG_STATUS},
13941 -+ {"show_engine_logs", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_ENGINE_LOGS]), SHOW_LONG_STATUS},
13942 -+ {"show_engine_mutex", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_ENGINE_MUTEX]), SHOW_LONG_STATUS},
13943 -+ {"show_engine_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_ENGINE_STATUS]), SHOW_LONG_STATUS},
13944 -+ {"show_events", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_EVENTS]), SHOW_LONG_STATUS},
13945 -+ {"show_errors", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_ERRORS]), SHOW_LONG_STATUS},
13946 -+ {"show_fields", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_FIELDS]), SHOW_LONG_STATUS},
13947 -+#ifndef DBUG_OFF
13948 -+ {"show_function_code", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_FUNC_CODE]), SHOW_LONG_STATUS},
13949 -+#endif
13950 -+ {"show_function_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STATUS_FUNC]), SHOW_LONG_STATUS},
13951 -+ {"show_grants", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_GRANTS]), SHOW_LONG_STATUS},
13952 -+ {"show_keys", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_KEYS]), SHOW_LONG_STATUS},
13953 -+ {"show_master_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_MASTER_STAT]), SHOW_LONG_STATUS},
13954 -+ {"show_new_master", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_NEW_MASTER]), SHOW_LONG_STATUS},
13955 -+ {"show_open_tables", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_OPEN_TABLES]), SHOW_LONG_STATUS},
13956 -+ {"show_plugins", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PLUGINS]), SHOW_LONG_STATUS},
13957 -+ {"show_privileges", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PRIVILEGES]), SHOW_LONG_STATUS},
13958 -+#ifndef DBUG_OFF
13959 -+ {"show_procedure_code", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PROC_CODE]), SHOW_LONG_STATUS},
13960 -+#endif
13961 -+ {"show_procedure_status",(char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STATUS_PROC]), SHOW_LONG_STATUS},
13962 -+ {"show_processlist", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PROCESSLIST]), SHOW_LONG_STATUS},
13963 -+ {"show_profile", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PROFILE]), SHOW_LONG_STATUS},
13964 -+ {"show_profiles", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PROFILES]), SHOW_LONG_STATUS},
13965 -+ {"show_slave_hosts", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_SLAVE_HOSTS]), SHOW_LONG_STATUS},
13966 -+ {"show_slave_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_SLAVE_STAT]), SHOW_LONG_STATUS},
13967 -+ {"show_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STATUS]), SHOW_LONG_STATUS},
13968 -+ {"show_storage_engines", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STORAGE_ENGINES]), SHOW_LONG_STATUS},
13969 -+ {"show_table_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_TABLE_STATUS]), SHOW_LONG_STATUS},
13970 -+ {"show_tables", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_TABLES]), SHOW_LONG_STATUS},
13971 -+ {"show_triggers", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_TRIGGERS]), SHOW_LONG_STATUS},
13972 -+ {"show_variables", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_VARIABLES]), SHOW_LONG_STATUS},
13973 -+ {"show_warnings", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_WARNS]), SHOW_LONG_STATUS},
13974 -+ {"slave_start", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SLAVE_START]), SHOW_LONG_STATUS},
13975 -+ {"slave_stop", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SLAVE_STOP]), SHOW_LONG_STATUS},
13976 -+ {"stmt_close", (char*) offsetof(STATUS_VAR, com_stmt_close), SHOW_LONG_STATUS},
13977 -+ {"stmt_execute", (char*) offsetof(STATUS_VAR, com_stmt_execute), SHOW_LONG_STATUS},
13978 -+ {"stmt_fetch", (char*) offsetof(STATUS_VAR, com_stmt_fetch), SHOW_LONG_STATUS},
13979 -+ {"stmt_prepare", (char*) offsetof(STATUS_VAR, com_stmt_prepare), SHOW_LONG_STATUS},
13980 -+ {"stmt_reprepare", (char*) offsetof(STATUS_VAR, com_stmt_reprepare), SHOW_LONG_STATUS},
13981 -+ {"stmt_reset", (char*) offsetof(STATUS_VAR, com_stmt_reset), SHOW_LONG_STATUS},
13982 -+ {"stmt_send_long_data", (char*) offsetof(STATUS_VAR, com_stmt_send_long_data), SHOW_LONG_STATUS},
13983 -+ {"truncate", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_TRUNCATE]), SHOW_LONG_STATUS},
13984 -+ {"uninstall_plugin", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_UNINSTALL_PLUGIN]), SHOW_LONG_STATUS},
13985 -+ {"unlock_tables", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_UNLOCK_TABLES]), SHOW_LONG_STATUS},
13986 -+ {"update", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_UPDATE]), SHOW_LONG_STATUS},
13987 -+ {"update_multi", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_UPDATE_MULTI]), SHOW_LONG_STATUS},
13988 -+ {"xa_commit", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_COMMIT]),SHOW_LONG_STATUS},
13989 -+ {"xa_end", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_END]),SHOW_LONG_STATUS},
13990 -+ {"xa_prepare", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_PREPARE]),SHOW_LONG_STATUS},
13991 -+ {"xa_recover", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_RECOVER]),SHOW_LONG_STATUS},
13992 -+ {"xa_rollback", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_ROLLBACK]),SHOW_LONG_STATUS},
13993 -+ {"xa_start", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_START]),SHOW_LONG_STATUS},
13994 -+ {NullS, NullS, SHOW_LONG}
13995 -+};
13996 -+
13997 -+static int init_common_variables(const char *conf_file_name, int argc,
13998 -+ char **argv, const char **groups)
13999 -+{
14000 -+ char buff[FN_REFLEN], *s;
14001 -+ umask(((~my_umask) & 0666));
14002 -+ my_decimal_set_zero(&decimal_zero); // set decimal_zero constant;
14003 -+ tzset(); // Set tzname
14004 -+
14005 -+ max_system_variables.pseudo_thread_id= (ulong)~0;
14006 -+ server_start_time= flush_status_time= my_time(0);
14007 -+
14008 -+ rpl_filter= new Rpl_filter;
14009 -+ binlog_filter= new Rpl_filter;
14010 -+ if (!rpl_filter || !binlog_filter)
14011 -+ {
14012 -+ sql_perror("Could not allocate replication and binlog filters");
14013 -+ return 1;
14014 -+ }
14015 -+
14016 -+ if (init_thread_environment() ||
14017 -+ mysql_init_variables())
14018 -+ return 1;
14019 -+
14020 -+#ifdef HAVE_TZNAME
14021 -+ {
14022 -+ struct tm tm_tmp;
14023 -+ localtime_r(&server_start_time,&tm_tmp);
14024 -+ strmake(system_time_zone, tzname[tm_tmp.tm_isdst != 0 ? 1 : 0],
14025 -+ sizeof(system_time_zone)-1);
14026 -+
14027 -+ }
14028 -+#endif
14029 -+ /*
14030 -+ We set SYSTEM time zone as reasonable default and
14031 -+ also for failure of my_tz_init() and bootstrap mode.
14032 -+ If user explicitly set time zone with --default-time-zone
14033 -+ option we will change this value in my_tz_init().
14034 -+ */
14035 -+ global_system_variables.time_zone= my_tz_SYSTEM;
14036 -+
14037 -+ /*
14038 -+ Init mutexes for the global MYSQL_BIN_LOG objects.
14039 -+ As safe_mutex depends on what MY_INIT() does, we can't init the mutexes of
14040 -+ global MYSQL_BIN_LOGs in their constructors, because then they would be
14041 -+ inited before MY_INIT(). So we do it here.
14042 -+ */
14043 -+ mysql_bin_log.init_pthread_objects();
14044 -+
14045 -+ /* TODO: remove this when my_time_t is 64 bit compatible */
14046 -+ if (!IS_TIME_T_VALID_FOR_TIMESTAMP(server_start_time))
14047 -+ {
14048 -+ sql_print_error("This MySQL server doesn't support dates later then 2038");
14049 -+ return 1;
14050 -+ }
14051 -+
14052 -+ if (gethostname(glob_hostname,sizeof(glob_hostname)) < 0)
14053 -+ {
14054 -+ strmake(glob_hostname, STRING_WITH_LEN("localhost"));
14055 -+ sql_print_warning("gethostname failed, using '%s' as hostname",
14056 -+ glob_hostname);
14057 -+ strmake(pidfile_name, STRING_WITH_LEN("mysql"));
14058 -+ }
14059 -+ else
14060 -+ strmake(pidfile_name, glob_hostname, sizeof(pidfile_name)-5);
14061 -+ strmov(fn_ext(pidfile_name),".pid"); // Add proper extension
14062 -+
14063 -+ /*
14064 -+ Add server status variables to the dynamic list of
14065 -+ status variables that is shown by SHOW STATUS.
14066 -+ Later, in plugin_init, and mysql_install_plugin
14067 -+ new entries could be added to that list.
14068 -+ */
14069 -+ if (add_status_vars(status_vars))
14070 -+ return 1; // an error was already reported
14071 -+
14072 -+#ifndef DBUG_OFF
14073 -+ /*
14074 -+ We have few debug-only commands in com_status_vars, only visible in debug
14075 -+ builds. for simplicity we enable the assert only in debug builds
14076 -+
14077 -+ There are 8 Com_ variables which don't have corresponding SQLCOM_ values:
14078 -+ (TODO strictly speaking they shouldn't be here, should not have Com_ prefix
14079 -+ that is. Perhaps Stmt_ ? Comstmt_ ? Prepstmt_ ?)
14080 -+
14081 -+ Com_admin_commands => com_other
14082 -+ Com_stmt_close => com_stmt_close
14083 -+ Com_stmt_execute => com_stmt_execute
14084 -+ Com_stmt_fetch => com_stmt_fetch
14085 -+ Com_stmt_prepare => com_stmt_prepare
14086 -+ Com_stmt_reprepare => com_stmt_reprepare
14087 -+ Com_stmt_reset => com_stmt_reset
14088 -+ Com_stmt_send_long_data => com_stmt_send_long_data
14089 -+
14090 -+ With this correction the number of Com_ variables (number of elements in
14091 -+ the array, excluding the last element - terminator) must match the number
14092 -+ of SQLCOM_ constants.
14093 -+ */
14094 -+ compile_time_assert(sizeof(com_status_vars)/sizeof(com_status_vars[0]) - 1 ==
14095 -+ SQLCOM_END + 8);
14096 -+#endif
14097 -+
14098 -+ orig_argc=argc;
14099 -+ orig_argv=argv;
14100 -+ load_defaults(conf_file_name, groups, &argc, &argv);
14101 -+ defaults_argv=argv;
14102 -+ defaults_argc=argc;
14103 -+ if (get_options(&defaults_argc, defaults_argv))
14104 -+ return 1;
14105 -+ set_server_version();
14106 -+
14107 -+ DBUG_PRINT("info",("%s Ver %s for %s on %s\n",my_progname,
14108 -+ server_version, SYSTEM_TYPE,MACHINE_TYPE));
14109 -+
14110 -+#ifdef HAVE_LARGE_PAGES
14111 -+ /* Initialize large page size */
14112 -+ if (opt_large_pages && (opt_large_page_size= my_get_large_page_size()))
14113 -+ {
14114 -+ my_use_large_pages= 1;
14115 -+ my_large_page_size= opt_large_page_size;
14116 -+ }
14117 -+#endif /* HAVE_LARGE_PAGES */
14118 -+
14119 -+ /* connections and databases needs lots of files */
14120 -+ {
14121 -+ uint files, wanted_files, max_open_files;
14122 -+
14123 -+ /* MyISAM requires two file handles per table. */
14124 -+ wanted_files= 10+max_connections+table_cache_size*2;
14125 -+ /*
14126 -+ We are trying to allocate no less than max_connections*5 file
14127 -+ handles (i.e. we are trying to set the limit so that they will
14128 -+ be available). In addition, we allocate no less than how much
14129 -+ was already allocated. However below we report a warning and
14130 -+ recompute values only if we got less file handles than were
14131 -+ explicitly requested. No warning and re-computation occur if we
14132 -+ can't get max_connections*5 but still got no less than was
14133 -+ requested (value of wanted_files).
14134 -+ */
14135 -+ max_open_files= max(max(wanted_files, max_connections*5),
14136 -+ open_files_limit);
14137 -+ files= my_set_max_open_files(max_open_files);
14138 -+
14139 -+ if (files < wanted_files)
14140 -+ {
14141 -+ if (!open_files_limit)
14142 -+ {
14143 -+ /*
14144 -+ If we have requested too much file handles than we bring
14145 -+ max_connections in supported bounds.
14146 -+ */
14147 -+ max_connections= (ulong) min(files-10-TABLE_OPEN_CACHE_MIN*2,
14148 -+ max_connections);
14149 -+ /*
14150 -+ Decrease table_cache_size according to max_connections, but
14151 -+ not below TABLE_OPEN_CACHE_MIN. Outer min() ensures that we
14152 -+ never increase table_cache_size automatically (that could
14153 -+ happen if max_connections is decreased above).
14154 -+ */
14155 -+ table_cache_size= (ulong) min(max((files-10-max_connections)/2,
14156 -+ TABLE_OPEN_CACHE_MIN),
14157 -+ table_cache_size);
14158 -+ DBUG_PRINT("warning",
14159 -+ ("Changed limits: max_open_files: %u max_connections: %ld table_cache: %ld",
14160 -+ files, max_connections, table_cache_size));
14161 -+ if (global_system_variables.log_warnings)
14162 -+ sql_print_warning("Changed limits: max_open_files: %u max_connections: %ld table_cache: %ld",
14163 -+ files, max_connections, table_cache_size);
14164 -+ }
14165 -+ else if (global_system_variables.log_warnings)
14166 -+ sql_print_warning("Could not increase number of max_open_files to more than %u (request: %u)", files, wanted_files);
14167 -+ }
14168 -+ open_files_limit= files;
14169 -+ }
14170 -+ unireg_init(opt_specialflag); /* Set up extern variabels */
14171 -+ if (init_errmessage()) /* Read error messages from file */
14172 -+ return 1;
14173 -+ init_client_errs();
14174 -+ lex_init();
14175 -+ if (item_create_init())
14176 -+ return 1;
14177 -+ item_init();
14178 -+ if (set_var_init())
14179 -+ return 1;
14180 -+#ifdef HAVE_REPLICATION
14181 -+ if (init_replication_sys_vars())
14182 -+ return 1;
14183 -+#endif
14184 -+ mysys_uses_curses=0;
14185 -+#ifdef USE_REGEX
14186 -+#ifndef EMBEDDED_LIBRARY
14187 -+ my_regex_init(&my_charset_latin1, check_enough_stack_size);
14188 -+#else
14189 -+ my_regex_init(&my_charset_latin1, NULL);
14190 -+#endif
14191 -+#endif
14192 -+ /*
14193 -+ Process a comma-separated character set list and choose
14194 -+ the first available character set. This is mostly for
14195 -+ test purposes, to be able to start "mysqld" even if
14196 -+ the requested character set is not available (see bug#18743).
14197 -+ */
14198 -+ for (;;)
14199 -+ {
14200 -+ char *next_character_set_name= strchr(default_character_set_name, ',');
14201 -+ if (next_character_set_name)
14202 -+ *next_character_set_name++= '\0';
14203 -+ if (!(default_charset_info=
14204 -+ get_charset_by_csname(default_character_set_name,
14205 -+ MY_CS_PRIMARY, MYF(MY_WME))))
14206 -+ {
14207 -+ if (next_character_set_name)
14208 -+ {
14209 -+ default_character_set_name= next_character_set_name;
14210 -+ default_collation_name= 0; // Ignore collation
14211 -+ }
14212 -+ else
14213 -+ return 1; // Eof of the list
14214 -+ }
14215 -+ else
14216 -+ break;
14217 -+ }
14218 -+
14219 -+ if (default_collation_name)
14220 -+ {
14221 -+ CHARSET_INFO *default_collation;
14222 -+ default_collation= get_charset_by_name(default_collation_name, MYF(0));
14223 -+ if (!default_collation)
14224 -+ {
14225 -+ sql_print_error(ER(ER_UNKNOWN_COLLATION), default_collation_name);
14226 -+ return 1;
14227 -+ }
14228 -+ if (!my_charset_same(default_charset_info, default_collation))
14229 -+ {
14230 -+ sql_print_error(ER(ER_COLLATION_CHARSET_MISMATCH),
14231 -+ default_collation_name,
14232 -+ default_charset_info->csname);
14233 -+ return 1;
14234 -+ }
14235 -+ default_charset_info= default_collation;
14236 -+ }
14237 -+ /* Set collactions that depends on the default collation */
14238 -+ global_system_variables.collation_server= default_charset_info;
14239 -+ global_system_variables.collation_database= default_charset_info;
14240 -+ global_system_variables.collation_connection= default_charset_info;
14241 -+ global_system_variables.character_set_results= default_charset_info;
14242 -+ global_system_variables.character_set_client= default_charset_info;
14243 -+
14244 -+ if (!(character_set_filesystem=
14245 -+ get_charset_by_csname(character_set_filesystem_name,
14246 -+ MY_CS_PRIMARY, MYF(MY_WME))))
14247 -+ return 1;
14248 -+ global_system_variables.character_set_filesystem= character_set_filesystem;
14249 -+
14250 -+ if (!(my_default_lc_time_names=
14251 -+ my_locale_by_name(lc_time_names_name)))
14252 -+ {
14253 -+ sql_print_error("Unknown locale: '%s'", lc_time_names_name);
14254 -+ return 1;
14255 -+ }
14256 -+ global_system_variables.lc_time_names= my_default_lc_time_names;
14257 -+
14258 -+ sys_init_connect.value_length= 0;
14259 -+ if ((sys_init_connect.value= opt_init_connect))
14260 -+ sys_init_connect.value_length= strlen(opt_init_connect);
14261 -+ else
14262 -+ sys_init_connect.value=my_strdup("",MYF(0));
14263 -+ sys_init_connect.is_os_charset= TRUE;
14264 -+
14265 -+ sys_init_slave.value_length= 0;
14266 -+ if ((sys_init_slave.value= opt_init_slave))
14267 -+ sys_init_slave.value_length= strlen(opt_init_slave);
14268 -+ else
14269 -+ sys_init_slave.value=my_strdup("",MYF(0));
14270 -+ sys_init_slave.is_os_charset= TRUE;
14271 -+
14272 -+ /* check log options and issue warnings if needed */
14273 -+ if (opt_log && opt_logname && !(log_output_options & LOG_FILE) &&
14274 -+ !(log_output_options & LOG_NONE))
14275 -+ sql_print_warning("Although a path was specified for the "
14276 -+ "--log option, log tables are used. "
14277 -+ "To enable logging to files use the --log-output option.");
14278 -+
14279 -+ if (opt_slow_log && opt_slow_logname && !(log_output_options & LOG_FILE)
14280 -+ && !(log_output_options & LOG_NONE))
14281 -+ sql_print_warning("Although a path was specified for the "
14282 -+ "--log_slow_queries option, log tables are used. "
14283 -+ "To enable logging to files use the --log-output=file option.");
14284 -+
14285 -+ s= opt_logname ? opt_logname : make_default_log_name(buff, ".log");
14286 -+ sys_var_general_log_path.value= my_strdup(s, MYF(0));
14287 -+ sys_var_general_log_path.value_length= strlen(s);
14288 -+
14289 -+ s= opt_slow_logname ? opt_slow_logname : make_default_log_name(buff, "-slow.log");
14290 -+ sys_var_slow_log_path.value= my_strdup(s, MYF(0));
14291 -+ sys_var_slow_log_path.value_length= strlen(s);
14292 -+
14293 -+#if defined(ENABLED_DEBUG_SYNC)
14294 -+ /* Initialize the debug sync facility. See debug_sync.cc. */
14295 -+ if (debug_sync_init())
14296 -+ return 1; /* purecov: tested */
14297 -+#endif /* defined(ENABLED_DEBUG_SYNC) */
14298 -+
14299 -+#if (ENABLE_TEMP_POOL)
14300 -+ if (use_temp_pool && bitmap_init(&temp_pool,0,1024,1))
14301 -+ return 1;
14302 -+#else
14303 -+ use_temp_pool= 0;
14304 -+#endif
14305 -+
14306 -+ if (my_database_names_init())
14307 -+ return 1;
14308 -+
14309 -+ /*
14310 -+ Ensure that lower_case_table_names is set on system where we have case
14311 -+ insensitive names. If this is not done the users MyISAM tables will
14312 -+ get corrupted if accesses with names of different case.
14313 -+ */
14314 -+ DBUG_PRINT("info", ("lower_case_table_names: %d", lower_case_table_names));
14315 -+ lower_case_file_system= test_if_case_insensitive(mysql_real_data_home);
14316 -+ if (!lower_case_table_names && lower_case_file_system == 1)
14317 -+ {
14318 -+ if (lower_case_table_names_used)
14319 -+ {
14320 -+ if (global_system_variables.log_warnings)
14321 -+ sql_print_warning("\
14322 -+You have forced lower_case_table_names to 0 through a command-line \
14323 -+option, even though your file system '%s' is case insensitive. This means \
14324 -+that you can corrupt a MyISAM table by accessing it with different cases. \
14325 -+You should consider changing lower_case_table_names to 1 or 2",
14326 -+ mysql_real_data_home);
14327 -+ }
14328 -+ else
14329 -+ {
14330 -+ if (global_system_variables.log_warnings)
14331 -+ sql_print_warning("Setting lower_case_table_names=2 because file system for %s is case insensitive", mysql_real_data_home);
14332 -+ lower_case_table_names= 2;
14333 -+ }
14334 -+ }
14335 -+ else if (lower_case_table_names == 2 &&
14336 -+ !(lower_case_file_system=
14337 -+ (test_if_case_insensitive(mysql_real_data_home) == 1)))
14338 -+ {
14339 -+ if (global_system_variables.log_warnings)
14340 -+ sql_print_warning("lower_case_table_names was set to 2, even though your "
14341 -+ "the file system '%s' is case sensitive. Now setting "
14342 -+ "lower_case_table_names to 0 to avoid future problems.",
14343 -+ mysql_real_data_home);
14344 -+ lower_case_table_names= 0;
14345 -+ }
14346 -+ else
14347 -+ {
14348 -+ lower_case_file_system=
14349 -+ (test_if_case_insensitive(mysql_real_data_home) == 1);
14350 -+ }
14351 -+
14352 -+ /* Reset table_alias_charset, now that lower_case_table_names is set. */
14353 -+ table_alias_charset= (lower_case_table_names ?
14354 -+ files_charset_info :
14355 -+ &my_charset_bin);
14356 -+
14357 -+ return 0;
14358 -+}
14359 -+
14360 -+
14361 -+static int init_thread_environment()
14362 -+{
14363 -+ (void) pthread_mutex_init(&LOCK_mysql_create_db,MY_MUTEX_INIT_SLOW);
14364 -+ (void) pthread_mutex_init(&LOCK_lock_db,MY_MUTEX_INIT_SLOW);
14365 -+ (void) pthread_mutex_init(&LOCK_Acl,MY_MUTEX_INIT_SLOW);
14366 -+ (void) pthread_mutex_init(&LOCK_open, MY_MUTEX_INIT_FAST);
14367 -+ (void) pthread_mutex_init(&LOCK_thread_count,MY_MUTEX_INIT_FAST);
14368 -+ (void) pthread_mutex_init(&LOCK_mapped_file,MY_MUTEX_INIT_SLOW);
14369 -+ (void) pthread_mutex_init(&LOCK_status,MY_MUTEX_INIT_FAST);
14370 -+ (void) pthread_mutex_init(&LOCK_error_log,MY_MUTEX_INIT_FAST);
14371 -+ (void) pthread_mutex_init(&LOCK_delayed_insert,MY_MUTEX_INIT_FAST);
14372 -+ (void) pthread_mutex_init(&LOCK_delayed_status,MY_MUTEX_INIT_FAST);
14373 -+ (void) pthread_mutex_init(&LOCK_delayed_create,MY_MUTEX_INIT_SLOW);
14374 -+ (void) pthread_mutex_init(&LOCK_manager,MY_MUTEX_INIT_FAST);
14375 -+ (void) pthread_mutex_init(&LOCK_crypt,MY_MUTEX_INIT_FAST);
14376 -+ (void) pthread_mutex_init(&LOCK_bytes_sent,MY_MUTEX_INIT_FAST);
14377 -+ (void) pthread_mutex_init(&LOCK_bytes_received,MY_MUTEX_INIT_FAST);
14378 -+ (void) pthread_mutex_init(&LOCK_user_conn, MY_MUTEX_INIT_FAST);
14379 -+ (void) pthread_mutex_init(&LOCK_active_mi, MY_MUTEX_INIT_FAST);
14380 -+ (void) pthread_mutex_init(&LOCK_global_system_variables, MY_MUTEX_INIT_FAST);
14381 -+ (void) my_rwlock_init(&LOCK_system_variables_hash, NULL);
14382 -+ (void) pthread_mutex_init(&LOCK_global_read_lock, MY_MUTEX_INIT_FAST);
14383 -+ (void) pthread_mutex_init(&LOCK_prepared_stmt_count, MY_MUTEX_INIT_FAST);
14384 -+ (void) pthread_mutex_init(&LOCK_uuid_generator, MY_MUTEX_INIT_FAST);
14385 -+ (void) pthread_mutex_init(&LOCK_connection_count, MY_MUTEX_INIT_FAST);
14386 -+#ifdef HAVE_OPENSSL
14387 -+ (void) pthread_mutex_init(&LOCK_des_key_file,MY_MUTEX_INIT_FAST);
14388 -+#ifndef HAVE_YASSL
14389 -+ openssl_stdlocks= (openssl_lock_t*) OPENSSL_malloc(CRYPTO_num_locks() *
14390 -+ sizeof(openssl_lock_t));
14391 -+ for (int i= 0; i < CRYPTO_num_locks(); ++i)
14392 -+ (void) my_rwlock_init(&openssl_stdlocks[i].lock, NULL);
14393 -+ CRYPTO_set_dynlock_create_callback(openssl_dynlock_create);
14394 -+ CRYPTO_set_dynlock_destroy_callback(openssl_dynlock_destroy);
14395 -+ CRYPTO_set_dynlock_lock_callback(openssl_lock);
14396 -+ CRYPTO_set_locking_callback(openssl_lock_function);
14397 -+ CRYPTO_set_id_callback(openssl_id_function);
14398 -+#endif
14399 -+#endif
14400 -+ (void) my_rwlock_init(&LOCK_sys_init_connect, NULL);
14401 -+ (void) my_rwlock_init(&LOCK_sys_init_slave, NULL);
14402 -+ (void) my_rwlock_init(&LOCK_grant, NULL);
14403 -+ (void) pthread_cond_init(&COND_thread_count,NULL);
14404 -+ (void) pthread_cond_init(&COND_refresh,NULL);
14405 -+ (void) pthread_cond_init(&COND_global_read_lock,NULL);
14406 -+ (void) pthread_cond_init(&COND_thread_cache,NULL);
14407 -+ (void) pthread_cond_init(&COND_flush_thread_cache,NULL);
14408 -+ (void) pthread_cond_init(&COND_manager,NULL);
14409 -+#ifdef HAVE_REPLICATION
14410 -+ (void) pthread_mutex_init(&LOCK_rpl_status, MY_MUTEX_INIT_FAST);
14411 -+ (void) pthread_cond_init(&COND_rpl_status, NULL);
14412 -+#endif
14413 -+ (void) pthread_mutex_init(&LOCK_server_started, MY_MUTEX_INIT_FAST);
14414 -+ (void) pthread_cond_init(&COND_server_started,NULL);
14415 -+ sp_cache_init();
14416 -+#ifdef HAVE_EVENT_SCHEDULER
14417 -+ Events::init_mutexes();
14418 -+#endif
14419 -+ /* Parameter for threads created for connections */
14420 -+ (void) pthread_attr_init(&connection_attrib);
14421 -+ (void) pthread_attr_setdetachstate(&connection_attrib,
14422 -+ PTHREAD_CREATE_DETACHED);
14423 -+ pthread_attr_setscope(&connection_attrib, PTHREAD_SCOPE_SYSTEM);
14424 -+ if (!(opt_specialflag & SPECIAL_NO_PRIOR))
14425 -+ my_pthread_attr_setprio(&connection_attrib,WAIT_PRIOR);
14426 -+
14427 -+ if (pthread_key_create(&THR_THD,NULL) ||
14428 -+ pthread_key_create(&THR_MALLOC,NULL))
14429 -+ {
14430 -+ sql_print_error("Can't create thread-keys");
14431 -+ return 1;
14432 -+ }
14433 -+ return 0;
14434 -+}
14435 -+
14436 -+
14437 -+#if defined(HAVE_OPENSSL) && !defined(HAVE_YASSL)
14438 -+static unsigned long openssl_id_function()
14439 -+{
14440 -+ return (unsigned long) pthread_self();
14441 -+}
14442 -+
14443 -+
14444 -+static openssl_lock_t *openssl_dynlock_create(const char *file, int line)
14445 -+{
14446 -+ openssl_lock_t *lock= new openssl_lock_t;
14447 -+ my_rwlock_init(&lock->lock, NULL);
14448 -+ return lock;
14449 -+}
14450 -+
14451 -+
14452 -+static void openssl_dynlock_destroy(openssl_lock_t *lock, const char *file,
14453 -+ int line)
14454 -+{
14455 -+ rwlock_destroy(&lock->lock);
14456 -+ delete lock;
14457 -+}
14458 -+
14459 -+
14460 -+static void openssl_lock_function(int mode, int n, const char *file, int line)
14461 -+{
14462 -+ if (n < 0 || n > CRYPTO_num_locks())
14463 -+ {
14464 -+ /* Lock number out of bounds. */
14465 -+ sql_print_error("Fatal: OpenSSL interface problem (n = %d)", n);
14466 -+ abort();
14467 -+ }
14468 -+ openssl_lock(mode, &openssl_stdlocks[n], file, line);
14469 -+}
14470 -+
14471 -+
14472 -+static void openssl_lock(int mode, openssl_lock_t *lock, const char *file,
14473 -+ int line)
14474 -+{
14475 -+ int err;
14476 -+ char const *what;
14477 -+
14478 -+ switch (mode) {
14479 -+ case CRYPTO_LOCK|CRYPTO_READ:
14480 -+ what = "read lock";
14481 -+ err = rw_rdlock(&lock->lock);
14482 -+ break;
14483 -+ case CRYPTO_LOCK|CRYPTO_WRITE:
14484 -+ what = "write lock";
14485 -+ err = rw_wrlock(&lock->lock);
14486 -+ break;
14487 -+ case CRYPTO_UNLOCK|CRYPTO_READ:
14488 -+ case CRYPTO_UNLOCK|CRYPTO_WRITE:
14489 -+ what = "unlock";
14490 -+ err = rw_unlock(&lock->lock);
14491 -+ break;
14492 -+ default:
14493 -+ /* Unknown locking mode. */
14494 -+ sql_print_error("Fatal: OpenSSL interface problem (mode=0x%x)", mode);
14495 -+ abort();
14496 -+ }
14497 -+ if (err)
14498 -+ {
14499 -+ sql_print_error("Fatal: can't %s OpenSSL lock", what);
14500 -+ abort();
14501 -+ }
14502 -+}
14503 -+#endif /* HAVE_OPENSSL */
14504 -+
14505 -+
14506 -+#ifndef EMBEDDED_LIBRARY
14507 -+
14508 -+static void init_ssl()
14509 -+{
14510 -+#ifdef HAVE_OPENSSL
14511 -+ if (opt_use_ssl)
14512 -+ {
14513 -+ enum enum_ssl_init_error error= SSL_INITERR_NOERROR;
14514 -+
14515 -+ /* having ssl_acceptor_fd != 0 signals the use of SSL */
14516 -+ ssl_acceptor_fd= new_VioSSLAcceptorFd(opt_ssl_key, opt_ssl_cert,
14517 -+ opt_ssl_ca, opt_ssl_capath,
14518 -+ opt_ssl_cipher, &error);
14519 -+ DBUG_PRINT("info",("ssl_acceptor_fd: 0x%lx", (long) ssl_acceptor_fd));
14520 -+ if (!ssl_acceptor_fd)
14521 -+ {
14522 -+ sql_print_warning("Failed to setup SSL");
14523 -+ sql_print_warning("SSL error: %s", sslGetErrString(error));
14524 -+ opt_use_ssl = 0;
14525 -+ have_ssl= SHOW_OPTION_DISABLED;
14526 -+ }
14527 -+ }
14528 -+ else
14529 -+ {
14530 -+ have_ssl= SHOW_OPTION_DISABLED;
14531 -+ }
14532 -+ if (des_key_file)
14533 -+ load_des_key_file(des_key_file);
14534 -+#endif /* HAVE_OPENSSL */
14535 -+}
14536 -+
14537 -+
14538 -+static void end_ssl()
14539 -+{
14540 -+#ifdef HAVE_OPENSSL
14541 -+ if (ssl_acceptor_fd)
14542 -+ {
14543 -+ free_vio_ssl_acceptor_fd(ssl_acceptor_fd);
14544 -+ ssl_acceptor_fd= 0;
14545 -+ }
14546 -+#endif /* HAVE_OPENSSL */
14547 -+}
14548 -+
14549 -+#endif /* EMBEDDED_LIBRARY */
14550 -+
14551 -+
14552 -+static int init_server_components()
14553 -+{
14554 -+ DBUG_ENTER("init_server_components");
14555 -+ /*
14556 -+ We need to call each of these following functions to ensure that
14557 -+ all things are initialized so that unireg_abort() doesn't fail
14558 -+ */
14559 -+ if (table_cache_init() | table_def_init() | hostname_cache_init())
14560 -+ unireg_abort(1);
14561 -+
14562 -+ query_cache_result_size_limit(query_cache_limit);
14563 -+ query_cache_set_min_res_unit(query_cache_min_res_unit);
14564 -+ query_cache_init();
14565 -+ query_cache_resize(query_cache_size);
14566 -+ randominit(&sql_rand,(ulong) server_start_time,(ulong) server_start_time/2);
14567 -+ setup_fpu();
14568 -+ init_thr_lock();
14569 -+#ifdef HAVE_REPLICATION
14570 -+ init_slave_list();
14571 -+#endif
14572 -+
14573 -+ /* Setup logs */
14574 -+
14575 -+ /*
14576 -+ Enable old-fashioned error log, except when the user has requested
14577 -+ help information. Since the implementation of plugin server
14578 -+ variables the help output is now written much later.
14579 -+ */
14580 -+ if (opt_error_log && !opt_help)
14581 -+ {
14582 -+ if (!log_error_file_ptr[0])
14583 -+ fn_format(log_error_file, pidfile_name, mysql_data_home, ".err",
14584 -+ MY_REPLACE_EXT); /* replace '.<domain>' by '.err', bug#4997 */
14585 -+ else
14586 -+ fn_format(log_error_file, log_error_file_ptr, mysql_data_home, ".err",
14587 -+ MY_UNPACK_FILENAME | MY_SAFE_PATH);
14588 -+ if (!log_error_file[0])
14589 -+ opt_error_log= 1; // Too long file name
14590 -+ else
14591 -+ {
14592 -+ my_bool res;
14593 -+#ifndef EMBEDDED_LIBRARY
14594 -+ res= reopen_fstreams(log_error_file, stdout, stderr);
14595 -+#else
14596 -+ res= reopen_fstreams(log_error_file, NULL, stderr);
14597 -+#endif
14598 -+
14599 -+ if (!res)
14600 -+ setbuf(stderr, NULL);
14601 -+ }
14602 -+ }
14603 -+
14604 -+ if (xid_cache_init())
14605 -+ {
14606 -+ sql_print_error("Out of memory");
14607 -+ unireg_abort(1);
14608 -+ }
14609 -+
14610 -+ /* need to configure logging before initializing storage engines */
14611 -+ if (opt_update_log)
14612 -+ {
14613 -+ /*
14614 -+ Update log is removed since 5.0. But we still accept the option.
14615 -+ The idea is if the user already uses the binlog and the update log,
14616 -+ we completely ignore any option/variable related to the update log, like
14617 -+ if the update log did not exist. But if the user uses only the update
14618 -+ log, then we translate everything into binlog for him (with warnings).
14619 -+ Implementation of the above :
14620 -+ - If mysqld is started with --log-update and --log-bin,
14621 -+ ignore --log-update (print a warning), push a warning when SQL_LOG_UPDATE
14622 -+ is used, and turn off --sql-bin-update-same.
14623 -+ This will completely ignore SQL_LOG_UPDATE
14624 -+ - If mysqld is started with --log-update only,
14625 -+ change it to --log-bin (with the filename passed to log-update,
14626 -+ plus '-bin') (print a warning), push a warning when SQL_LOG_UPDATE is
14627 -+ used, and turn on --sql-bin-update-same.
14628 -+ This will translate SQL_LOG_UPDATE to SQL_LOG_BIN.
14629 -+
14630 -+ Note that we tell the user that --sql-bin-update-same is deprecated and
14631 -+ does nothing, and we don't take into account if he used this option or
14632 -+ not; but internally we give this variable a value to have the behaviour
14633 -+ we want (i.e. have SQL_LOG_UPDATE influence SQL_LOG_BIN or not).
14634 -+ As sql-bin-update-same, log-update and log-bin cannot be changed by the
14635 -+ user after starting the server (they are not variables), the user will
14636 -+ not later interfere with the settings we do here.
14637 -+ */
14638 -+ if (opt_bin_log)
14639 -+ {
14640 -+ opt_sql_bin_update= 0;
14641 -+ sql_print_error("The update log is no longer supported by MySQL in \
14642 -+version 5.0 and above. It is replaced by the binary log.");
14643 -+ }
14644 -+ else
14645 -+ {
14646 -+ opt_sql_bin_update= 1;
14647 -+ opt_bin_log= 1;
14648 -+ if (opt_update_logname)
14649 -+ {
14650 -+ /* as opt_bin_log==0, no need to free opt_bin_logname */
14651 -+ if (!(opt_bin_logname= my_strdup(opt_update_logname, MYF(MY_WME))))
14652 -+ {
14653 -+ sql_print_error("Out of memory");
14654 -+ return EXIT_OUT_OF_MEMORY;
14655 -+ }
14656 -+ sql_print_error("The update log is no longer supported by MySQL in \
14657 -+version 5.0 and above. It is replaced by the binary log. Now starting MySQL \
14658 -+with --log-bin='%s' instead.",opt_bin_logname);
14659 -+ }
14660 -+ else
14661 -+ sql_print_error("The update log is no longer supported by MySQL in \
14662 -+version 5.0 and above. It is replaced by the binary log. Now starting MySQL \
14663 -+with --log-bin instead.");
14664 -+ }
14665 -+ }
14666 -+ if (opt_log_slave_updates && !opt_bin_log)
14667 -+ {
14668 -+ sql_print_error("You need to use --log-bin to make "
14669 -+ "--log-slave-updates work.");
14670 -+ unireg_abort(1);
14671 -+ }
14672 -+ if (!opt_bin_log)
14673 -+ {
14674 -+ if (opt_binlog_format_id != BINLOG_FORMAT_UNSPEC)
14675 -+ {
14676 -+ sql_print_error("You need to use --log-bin to make "
14677 -+ "--binlog-format work.");
14678 -+ unireg_abort(1);
14679 -+ }
14680 -+ else
14681 -+ {
14682 -+ global_system_variables.binlog_format= BINLOG_FORMAT_STMT;
14683 -+ }
14684 -+ }
14685 -+ else
14686 -+ if (opt_binlog_format_id == BINLOG_FORMAT_UNSPEC)
14687 -+ global_system_variables.binlog_format= BINLOG_FORMAT_STMT;
14688 -+ else
14689 -+ {
14690 -+ DBUG_ASSERT(global_system_variables.binlog_format != BINLOG_FORMAT_UNSPEC);
14691 -+ }
14692 -+
14693 -+ /* Check that we have not let the format to unspecified at this point */
14694 -+ DBUG_ASSERT((uint)global_system_variables.binlog_format <=
14695 -+ array_elements(binlog_format_names)-1);
14696 -+
14697 -+#ifdef HAVE_REPLICATION
14698 -+ if (opt_log_slave_updates && replicate_same_server_id)
14699 -+ {
14700 -+ sql_print_error("\
14701 -+using --replicate-same-server-id in conjunction with \
14702 -+--log-slave-updates is impossible, it would lead to infinite loops in this \
14703 -+server.");
14704 -+ unireg_abort(1);
14705 -+ }
14706 -+#endif
14707 -+
14708 -+ if (opt_bin_log)
14709 -+ {
14710 -+ /* Reports an error and aborts, if the --log-bin's path
14711 -+ is a directory.*/
14712 -+ if (opt_bin_logname &&
14713 -+ opt_bin_logname[strlen(opt_bin_logname) - 1] == FN_LIBCHAR)
14714 -+ {
14715 -+ sql_print_error("Path '%s' is a directory name, please specify \
14716 -+a file name for --log-bin option", opt_bin_logname);
14717 -+ unireg_abort(1);
14718 -+ }
14719 -+
14720 -+ /* Reports an error and aborts, if the --log-bin-index's path
14721 -+ is a directory.*/
14722 -+ if (opt_binlog_index_name &&
14723 -+ opt_binlog_index_name[strlen(opt_binlog_index_name) - 1]
14724 -+ == FN_LIBCHAR)
14725 -+ {
14726 -+ sql_print_error("Path '%s' is a directory name, please specify \
14727 -+a file name for --log-bin-index option", opt_binlog_index_name);
14728 -+ unireg_abort(1);
14729 -+ }
14730 -+
14731 -+ char buf[FN_REFLEN];
14732 -+ const char *ln;
14733 -+ ln= mysql_bin_log.generate_name(opt_bin_logname, "-bin", 1, buf);
14734 -+ if (!opt_bin_logname && !opt_binlog_index_name)
14735 -+ {
14736 -+ /*
14737 -+ User didn't give us info to name the binlog index file.
14738 -+ Picking `hostname`-bin.index like did in 4.x, causes replication to
14739 -+ fail if the hostname is changed later. So, we would like to instead
14740 -+ require a name. But as we don't want to break many existing setups, we
14741 -+ only give warning, not error.
14742 -+ */
14743 -+ sql_print_warning("No argument was provided to --log-bin, and "
14744 -+ "--log-bin-index was not used; so replication "
14745 -+ "may break when this MySQL server acts as a "
14746 -+ "master and has his hostname changed!! Please "
14747 -+ "use '--log-bin=%s' to avoid this problem.", ln);
14748 -+ }
14749 -+ if (ln == buf)
14750 -+ {
14751 -+ my_free(opt_bin_logname, MYF(MY_ALLOW_ZERO_PTR));
14752 -+ opt_bin_logname=my_strdup(buf, MYF(0));
14753 -+ }
14754 -+ if (mysql_bin_log.open_index_file(opt_binlog_index_name, ln, TRUE))
14755 -+ {
14756 -+ unireg_abort(1);
14757 -+ }
14758 -+ }
14759 -+
14760 -+ /* call ha_init_key_cache() on all key caches to init them */
14761 -+ process_key_caches(&ha_init_key_cache);
14762 -+
14763 -+ /* Allow storage engine to give real error messages */
14764 -+ if (ha_init_errors())
14765 -+ DBUG_RETURN(1);
14766 -+
14767 -+ {
14768 -+ if (plugin_init(&defaults_argc, defaults_argv,
14769 -+ (opt_noacl ? PLUGIN_INIT_SKIP_PLUGIN_TABLE : 0) |
14770 -+ (opt_help ? PLUGIN_INIT_SKIP_INITIALIZATION : 0)))
14771 -+ {
14772 -+ sql_print_error("Failed to initialize plugins.");
14773 -+ unireg_abort(1);
14774 -+ }
14775 -+ plugins_are_initialized= TRUE; /* Don't separate from init function */
14776 -+ }
14777 -+
14778 -+ if (opt_help)
14779 -+ unireg_abort(0);
14780 -+
14781 -+ /* we do want to exit if there are any other unknown options */
14782 -+ if (defaults_argc > 1)
14783 -+ {
14784 -+ int ho_error;
14785 -+ char **tmp_argv= defaults_argv;
14786 -+ struct my_option no_opts[]=
14787 -+ {
14788 -+ {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
14789 -+ };
14790 -+ /*
14791 -+ We need to eat any 'loose' arguments first before we conclude
14792 -+ that there are unprocessed options.
14793 -+ But we need to preserve defaults_argv pointer intact for
14794 -+ free_defaults() to work. Thus we use a copy here.
14795 -+ */
14796 -+ my_getopt_skip_unknown= 0;
14797 -+
14798 -+ if ((ho_error= handle_options(&defaults_argc, &tmp_argv, no_opts,
14799 -+ mysqld_get_one_option)))
14800 -+ unireg_abort(ho_error);
14801 -+ my_getopt_skip_unknown= TRUE;
14802 -+
14803 -+ if (defaults_argc)
14804 -+ {
14805 -+ fprintf(stderr, "%s: Too many arguments (first extra is '%s').\n"
14806 -+ "Use --verbose --help to get a list of available options\n",
14807 -+ my_progname, *tmp_argv);
14808 -+ unireg_abort(1);
14809 -+ }
14810 -+ }
14811 -+
14812 -+ /* if the errmsg.sys is not loaded, terminate to maintain behaviour */
14813 -+ if (!errmesg[0][0])
14814 -+ unireg_abort(1);
14815 -+
14816 -+ /* We have to initialize the storage engines before CSV logging */
14817 -+ if (ha_init())
14818 -+ {
14819 -+ sql_print_error("Can't init databases");
14820 -+ unireg_abort(1);
14821 -+ }
14822 -+
14823 -+#ifdef WITH_CSV_STORAGE_ENGINE
14824 -+ if (opt_bootstrap)
14825 -+ log_output_options= LOG_FILE;
14826 -+ else
14827 -+ logger.init_log_tables();
14828 -+
14829 -+ if (log_output_options & LOG_NONE)
14830 -+ {
14831 -+ /*
14832 -+ Issue a warining if there were specified additional options to the
14833 -+ log-output along with NONE. Probably this wasn't what user wanted.
14834 -+ */
14835 -+ if ((log_output_options & LOG_NONE) && (log_output_options & ~LOG_NONE))
14836 -+ sql_print_warning("There were other values specified to "
14837 -+ "log-output besides NONE. Disabling slow "
14838 -+ "and general logs anyway.");
14839 -+ logger.set_handlers(LOG_FILE, LOG_NONE, LOG_NONE);
14840 -+ }
14841 -+ else
14842 -+ {
14843 -+ /* fall back to the log files if tables are not present */
14844 -+ LEX_STRING csv_name={C_STRING_WITH_LEN("csv")};
14845 -+ if (!plugin_is_ready(&csv_name, MYSQL_STORAGE_ENGINE_PLUGIN))
14846 -+ {
14847 -+ /* purecov: begin inspected */
14848 -+ sql_print_error("CSV engine is not present, falling back to the "
14849 -+ "log files");
14850 -+ log_output_options= (log_output_options & ~LOG_TABLE) | LOG_FILE;
14851 -+ /* purecov: end */
14852 -+ }
14853 -+
14854 -+ logger.set_handlers(LOG_FILE, opt_slow_log ? log_output_options:LOG_NONE,
14855 -+ opt_log ? log_output_options:LOG_NONE);
14856 -+ }
14857 -+#else
14858 -+ logger.set_handlers(LOG_FILE, opt_slow_log ? LOG_FILE:LOG_NONE,
14859 -+ opt_log ? LOG_FILE:LOG_NONE);
14860 -+#endif
14861 -+
14862 -+ /*
14863 -+ Check that the default storage engine is actually available.
14864 -+ */
14865 -+ if (default_storage_engine_str)
14866 -+ {
14867 -+ LEX_STRING name= { default_storage_engine_str,
14868 -+ strlen(default_storage_engine_str) };
14869 -+ plugin_ref plugin;
14870 -+ handlerton *hton;
14871 -+
14872 -+ if ((plugin= ha_resolve_by_name(0, &name)))
14873 -+ hton= plugin_data(plugin, handlerton*);
14874 -+ else
14875 -+ {
14876 -+ sql_print_error("Unknown/unsupported table type: %s",
14877 -+ default_storage_engine_str);
14878 -+ unireg_abort(1);
14879 -+ }
14880 -+ if (!ha_storage_engine_is_enabled(hton))
14881 -+ {
14882 -+ if (!opt_bootstrap)
14883 -+ {
14884 -+ sql_print_error("Default storage engine (%s) is not available",
14885 -+ default_storage_engine_str);
14886 -+ unireg_abort(1);
14887 -+ }
14888 -+ DBUG_ASSERT(global_system_variables.table_plugin);
14889 -+ }
14890 -+ else
14891 -+ {
14892 -+ /*
14893 -+ Need to unlock as global_system_variables.table_plugin
14894 -+ was acquired during plugin_init()
14895 -+ */
14896 -+ plugin_unlock(0, global_system_variables.table_plugin);
14897 -+ global_system_variables.table_plugin= plugin;
14898 -+ }
14899 -+ }
14900 -+
14901 -+ tc_log= (total_ha_2pc > 1 ? (opt_bin_log ?
14902 -+ (TC_LOG *) &mysql_bin_log :
14903 -+ (TC_LOG *) &tc_log_mmap) :
14904 -+ (TC_LOG *) &tc_log_dummy);
14905 -+
14906 -+ if (tc_log->open(opt_bin_log ? opt_bin_logname : opt_tc_log_file))
14907 -+ {
14908 -+ sql_print_error("Can't init tc log");
14909 -+ unireg_abort(1);
14910 -+ }
14911 -+
14912 -+ if (ha_recover(0))
14913 -+ {
14914 -+ unireg_abort(1);
14915 -+ }
14916 -+
14917 -+ if (opt_bin_log && mysql_bin_log.open(opt_bin_logname, LOG_BIN, 0,
14918 -+ WRITE_CACHE, 0, max_binlog_size, 0, TRUE))
14919 -+ unireg_abort(1);
14920 -+
14921 -+#ifdef HAVE_REPLICATION
14922 -+ if (opt_bin_log && expire_logs_days)
14923 -+ {
14924 -+ time_t purge_time= server_start_time - expire_logs_days*24*60*60;
14925 -+ if (purge_time >= 0)
14926 -+ mysql_bin_log.purge_logs_before_date(purge_time);
14927 -+ }
14928 -+#endif
14929 -+#ifdef __NETWARE__
14930 -+ /* Increasing stacksize of threads on NetWare */
14931 -+ pthread_attr_setstacksize(&connection_attrib, NW_THD_STACKSIZE);
14932 -+#endif
14933 -+
14934 -+ if (opt_myisam_log)
14935 -+ (void) mi_log(1);
14936 -+
14937 -+#if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT) && !defined(EMBEDDED_LIBRARY)
14938 -+ if (locked_in_memory && !getuid())
14939 -+ {
14940 -+ if (setreuid((uid_t)-1, 0) == -1)
14941 -+ { // this should never happen
14942 -+ sql_perror("setreuid");
14943 -+ unireg_abort(1);
14944 -+ }
14945 -+ if (mlockall(MCL_CURRENT))
14946 -+ {
14947 -+ if (global_system_variables.log_warnings)
14948 -+ sql_print_warning("Failed to lock memory. Errno: %d\n",errno);
14949 -+ locked_in_memory= 0;
14950 -+ }
14951 -+ if (user_info)
14952 -+ set_user(mysqld_user, user_info);
14953 -+ }
14954 -+ else
14955 -+#endif
14956 -+ locked_in_memory=0;
14957 -+
14958 -+ ft_init_stopwords();
14959 -+
14960 -+ init_max_user_conn();
14961 -+ init_update_queries();
14962 -+ DBUG_RETURN(0);
14963 -+}
14964 -+
14965 -+
14966 -+#ifndef EMBEDDED_LIBRARY
14967 -+
14968 -+static void create_shutdown_thread()
14969 -+{
14970 -+#ifdef __WIN__
14971 -+ hEventShutdown=CreateEvent(0, FALSE, FALSE, shutdown_event_name);
14972 -+ pthread_t hThread;
14973 -+ if (pthread_create(&hThread,&connection_attrib,handle_shutdown,0))
14974 -+ sql_print_warning("Can't create thread to handle shutdown requests");
14975 -+
14976 -+ // On "Stop Service" we have to do regular shutdown
14977 -+ Service.SetShutdownEvent(hEventShutdown);
14978 -+#endif /* __WIN__ */
14979 -+}
14980 -+
14981 -+#endif /* EMBEDDED_LIBRARY */
14982 -+
14983 -+
14984 -+#if (defined(__NT__) || defined(HAVE_SMEM)) && !defined(EMBEDDED_LIBRARY)
14985 -+static void handle_connections_methods()
14986 -+{
14987 -+ pthread_t hThread;
14988 -+ DBUG_ENTER("handle_connections_methods");
14989 -+#ifdef __NT__
14990 -+ if (hPipe == INVALID_HANDLE_VALUE &&
14991 -+ (!have_tcpip || opt_disable_networking) &&
14992 -+ !opt_enable_shared_memory)
14993 -+ {
14994 -+ sql_print_error("TCP/IP, --shared-memory, or --named-pipe should be configured on NT OS");
14995 -+ unireg_abort(1); // Will not return
14996 -+ }
14997 -+#endif
14998 -+
14999 -+ pthread_mutex_lock(&LOCK_thread_count);
15000 -+ (void) pthread_cond_init(&COND_handler_count,NULL);
15001 -+ handler_count=0;
15002 -+#ifdef __NT__
15003 -+ if (hPipe != INVALID_HANDLE_VALUE)
15004 -+ {
15005 -+ handler_count++;
15006 -+ if (pthread_create(&hThread,&connection_attrib,
15007 -+ handle_connections_namedpipes, 0))
15008 -+ {
15009 -+ sql_print_warning("Can't create thread to handle named pipes");
15010 -+ handler_count--;
15011 -+ }
15012 -+ }
15013 -+#endif /* __NT__ */
15014 -+ if (have_tcpip && !opt_disable_networking)
15015 -+ {
15016 -+ handler_count++;
15017 -+ if (pthread_create(&hThread,&connection_attrib,
15018 -+ handle_connections_sockets, 0))
15019 -+ {
15020 -+ sql_print_warning("Can't create thread to handle TCP/IP");
15021 -+ handler_count--;
15022 -+ }
15023 -+ }
15024 -+#ifdef HAVE_SMEM
15025 -+ if (opt_enable_shared_memory)
15026 -+ {
15027 -+ handler_count++;
15028 -+ if (pthread_create(&hThread,&connection_attrib,
15029 -+ handle_connections_shared_memory, 0))
15030 -+ {
15031 -+ sql_print_warning("Can't create thread to handle shared memory");
15032 -+ handler_count--;
15033 -+ }
15034 -+ }
15035 -+#endif
15036 -+
15037 -+ while (handler_count > 0)
15038 -+ pthread_cond_wait(&COND_handler_count,&LOCK_thread_count);
15039 -+ pthread_mutex_unlock(&LOCK_thread_count);
15040 -+ DBUG_VOID_RETURN;
15041 -+}
15042 -+
15043 -+void decrement_handler_count()
15044 -+{
15045 -+ pthread_mutex_lock(&LOCK_thread_count);
15046 -+ handler_count--;
15047 -+ pthread_cond_signal(&COND_handler_count);
15048 -+ pthread_mutex_unlock(&LOCK_thread_count);
15049 -+ my_thread_end();
15050 -+}
15051 -+#else
15052 -+#define decrement_handler_count()
15053 -+#endif /* defined(__NT__) || defined(HAVE_SMEM) */
15054 -+
15055 -+
15056 -+#ifndef EMBEDDED_LIBRARY
15057 -+#ifndef DBUG_OFF
15058 -+/*
15059 -+ Debugging helper function to keep the locale database
15060 -+ (see sql_locale.cc) and max_month_name_length and
15061 -+ max_day_name_length variable values in consistent state.
15062 -+*/
15063 -+static void test_lc_time_sz()
15064 -+{
15065 -+ DBUG_ENTER("test_lc_time_sz");
15066 -+ for (MY_LOCALE **loc= my_locales; *loc; loc++)
15067 -+ {
15068 -+ uint max_month_len= 0;
15069 -+ uint max_day_len = 0;
15070 -+ for (const char **month= (*loc)->month_names->type_names; *month; month++)
15071 -+ {
15072 -+ set_if_bigger(max_month_len,
15073 -+ my_numchars_mb(&my_charset_utf8_general_ci,
15074 -+ *month, *month + strlen(*month)));
15075 -+ }
15076 -+ for (const char **day= (*loc)->day_names->type_names; *day; day++)
15077 -+ {
15078 -+ set_if_bigger(max_day_len,
15079 -+ my_numchars_mb(&my_charset_utf8_general_ci,
15080 -+ *day, *day + strlen(*day)));
15081 -+ }
15082 -+ if ((*loc)->max_month_name_length != max_month_len ||
15083 -+ (*loc)->max_day_name_length != max_day_len)
15084 -+ {
15085 -+ DBUG_PRINT("Wrong max day name(or month name) length for locale:",
15086 -+ ("%s", (*loc)->name));
15087 -+ DBUG_ASSERT(0);
15088 -+ }
15089 -+ }
15090 -+ DBUG_VOID_RETURN;
15091 -+}
15092 -+#endif//DBUG_OFF
15093 -+
15094 -+
15095 -+#ifdef __WIN__
15096 -+int win_main(int argc, char **argv)
15097 -+#else
15098 -+int main(int argc, char **argv)
15099 -+#endif
15100 -+{
15101 -+ MY_INIT(argv[0]); // init my_sys library & pthreads
15102 -+ /* nothing should come before this line ^^^ */
15103 -+
15104 -+ /* Set signal used to kill MySQL */
15105 -+#if defined(SIGUSR2)
15106 -+ thr_kill_signal= thd_lib_detected == THD_LIB_LT ? SIGINT : SIGUSR2;
15107 -+#else
15108 -+ thr_kill_signal= SIGINT;
15109 -+#endif
15110 -+
15111 -+ /*
15112 -+ Perform basic logger initialization logger. Should be called after
15113 -+ MY_INIT, as it initializes mutexes. Log tables are inited later.
15114 -+ */
15115 -+ logger.init_base();
15116 -+
15117 -+#ifdef _CUSTOMSTARTUPCONFIG_
15118 -+ if (_cust_check_startup())
15119 -+ {
15120 -+ / * _cust_check_startup will report startup failure error * /
15121 -+ exit(1);
15122 -+ }
15123 -+#endif
15124 -+
15125 -+#ifdef __WIN__
15126 -+ /*
15127 -+ Before performing any socket operation (like retrieving hostname
15128 -+ in init_common_variables we have to call WSAStartup
15129 -+ */
15130 -+ {
15131 -+ WSADATA WsaData;
15132 -+ if (SOCKET_ERROR == WSAStartup (0x0101, &WsaData))
15133 -+ {
15134 -+ /* errors are not read yet, so we use english text here */
15135 -+ my_message(ER_WSAS_FAILED, "WSAStartup Failed", MYF(0));
15136 -+ unireg_abort(1);
15137 -+ }
15138 -+ }
15139 -+#endif /* __WIN__ */
15140 -+
15141 -+ if (init_common_variables(MYSQL_CONFIG_NAME,
15142 -+ argc, argv, load_default_groups))
15143 -+ unireg_abort(1); // Will do exit
15144 -+
15145 -+ init_signals();
15146 -+ if (!(opt_specialflag & SPECIAL_NO_PRIOR))
15147 -+ my_pthread_setprio(pthread_self(),CONNECT_PRIOR);
15148 -+#if defined(__ia64__) || defined(__ia64)
15149 -+ /*
15150 -+ Peculiar things with ia64 platforms - it seems we only have half the
15151 -+ stack size in reality, so we have to double it here
15152 -+ */
15153 -+ pthread_attr_setstacksize(&connection_attrib,my_thread_stack_size*2);
15154 -+#else
15155 -+ pthread_attr_setstacksize(&connection_attrib,my_thread_stack_size);
15156 -+#endif
15157 -+#ifdef HAVE_PTHREAD_ATTR_GETSTACKSIZE
15158 -+ {
15159 -+ /* Retrieve used stack size; Needed for checking stack overflows */
15160 -+ size_t stack_size= 0;
15161 -+ pthread_attr_getstacksize(&connection_attrib, &stack_size);
15162 -+#if defined(__ia64__) || defined(__ia64)
15163 -+ stack_size/= 2;
15164 -+#endif
15165 -+ /* We must check if stack_size = 0 as Solaris 2.9 can return 0 here */
15166 -+ if (stack_size && stack_size < my_thread_stack_size)
15167 -+ {
15168 -+ if (global_system_variables.log_warnings)
15169 -+ sql_print_warning("Asked for %lu thread stack, but got %ld",
15170 -+ my_thread_stack_size, (long) stack_size);
15171 -+#if defined(__ia64__) || defined(__ia64)
15172 -+ my_thread_stack_size= stack_size*2;
15173 -+#else
15174 -+ my_thread_stack_size= stack_size;
15175 -+#endif
15176 -+ }
15177 -+ }
15178 -+#endif
15179 -+#ifdef __NETWARE__
15180 -+ /* Increasing stacksize of threads on NetWare */
15181 -+ pthread_attr_setstacksize(&connection_attrib, NW_THD_STACKSIZE);
15182 -+#endif
15183 -+
15184 -+ (void) thr_setconcurrency(concurrency); // 10 by default
15185 -+
15186 -+ select_thread=pthread_self();
15187 -+ select_thread_in_use=1;
15188 -+
15189 -+#ifdef HAVE_LIBWRAP
15190 -+ libwrapName= my_progname+dirname_length(my_progname);
15191 -+ openlog(libwrapName, LOG_PID, LOG_AUTH);
15192 -+#endif
15193 -+
15194 -+#ifndef DBUG_OFF
15195 -+ test_lc_time_sz();
15196 -+#endif
15197 -+
15198 -+ /*
15199 -+ We have enough space for fiddling with the argv, continue
15200 -+ */
15201 -+ check_data_home(mysql_real_data_home);
15202 -+ if (my_setwd(mysql_real_data_home,MYF(MY_WME)) && !opt_help)
15203 -+ unireg_abort(1); /* purecov: inspected */
15204 -+ mysql_data_home= mysql_data_home_buff;
15205 -+ mysql_data_home[0]=FN_CURLIB; // all paths are relative from here
15206 -+ mysql_data_home[1]=0;
15207 -+ mysql_data_home_len= 2;
15208 -+
15209 -+ if ((user_info= check_user(mysqld_user)))
15210 -+ {
15211 -+#if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT)
15212 -+ if (locked_in_memory) // getuid() == 0 here
15213 -+ set_effective_user(user_info);
15214 -+ else
15215 -+#endif
15216 -+ set_user(mysqld_user, user_info);
15217 -+ }
15218 -+
15219 -+ if (opt_bin_log && !server_id)
15220 -+ {
15221 -+ server_id= !master_host ? 1 : 2;
15222 -+#ifdef EXTRA_DEBUG
15223 -+ switch (server_id) {
15224 -+ case 1:
15225 -+ sql_print_warning("\
15226 -+You have enabled the binary log, but you haven't set server-id to \
15227 -+a non-zero value: we force server id to 1; updates will be logged to the \
15228 -+binary log, but connections from slaves will not be accepted.");
15229 -+ break;
15230 -+ case 2:
15231 -+ sql_print_warning("\
15232 -+You should set server-id to a non-0 value if master_host is set; \
15233 -+we force server id to 2, but this MySQL server will not act as a slave.");
15234 -+ break;
15235 -+ }
15236 -+#endif
15237 -+ }
15238 -+
15239 -+ if (init_server_components())
15240 -+ unireg_abort(1);
15241 -+
15242 -+ init_ssl();
15243 -+ network_init();
15244 -+
15245 -+#ifdef __WIN__
15246 -+ if (!opt_console)
15247 -+ {
15248 -+ if (reopen_fstreams(log_error_file, stdout, stderr))
15249 -+ unireg_abort(1);
15250 -+ setbuf(stderr, NULL);
15251 -+ FreeConsole(); // Remove window
15252 -+ }
15253 -+#endif
15254 -+
15255 -+ /*
15256 -+ Initialize my_str_malloc() and my_str_free()
15257 -+ */
15258 -+ my_str_malloc= &my_str_malloc_mysqld;
15259 -+ my_str_free= &my_str_free_mysqld;
15260 -+
15261 -+ /*
15262 -+ init signals & alarm
15263 -+ After this we can't quit by a simple unireg_abort
15264 -+ */
15265 -+ error_handler_hook= my_message_sql;
15266 -+ start_signal_handler(); // Creates pidfile
15267 -+
15268 -+ if (mysql_rm_tmp_tables() || acl_init(opt_noacl) ||
15269 -+ my_tz_init((THD *)0, default_tz_name, opt_bootstrap))
15270 -+ {
15271 -+ abort_loop=1;
15272 -+ select_thread_in_use=0;
15273 -+#ifndef __NETWARE__
15274 -+ (void) pthread_kill(signal_thread, MYSQL_KILL_SIGNAL);
15275 -+#endif /* __NETWARE__ */
15276 -+
15277 -+ if (!opt_bootstrap)
15278 -+ (void) my_delete(pidfile_name,MYF(MY_WME)); // Not needed anymore
15279 -+
15280 -+ if (unix_sock != INVALID_SOCKET)
15281 -+ unlink(mysqld_unix_port);
15282 -+ exit(1);
15283 -+ }
15284 -+ if (!opt_noacl)
15285 -+ (void) grant_init();
15286 -+
15287 -+ if (!opt_bootstrap)
15288 -+ servers_init(0);
15289 -+
15290 -+ if (!opt_noacl)
15291 -+ {
15292 -+#ifdef HAVE_DLOPEN
15293 -+ udf_init();
15294 -+#endif
15295 -+ }
15296 -+
15297 -+ init_status_vars();
15298 -+ if (opt_bootstrap) /* If running with bootstrap, do not start replication. */
15299 -+ opt_skip_slave_start= 1;
15300 -+ /*
15301 -+ init_slave() must be called after the thread keys are created.
15302 -+ Some parts of the code (e.g. SHOW STATUS LIKE 'slave_running' and other
15303 -+ places) assume that active_mi != 0, so let's fail if it's 0 (out of
15304 -+ memory); a message has already been printed.
15305 -+ */
15306 -+ if (init_slave() && !active_mi)
15307 -+ {
15308 -+ unireg_abort(1);
15309 -+ }
15310 -+
15311 -+ execute_ddl_log_recovery();
15312 -+
15313 -+ if (Events::init(opt_noacl || opt_bootstrap))
15314 -+ unireg_abort(1);
15315 -+
15316 -+ if (opt_bootstrap)
15317 -+ {
15318 -+ select_thread_in_use= 0; // Allow 'kill' to work
15319 -+ bootstrap(stdin);
15320 -+ unireg_abort(bootstrap_error ? 1 : 0);
15321 -+ }
15322 -+ if (opt_init_file)
15323 -+ {
15324 -+ if (read_init_file(opt_init_file))
15325 -+ unireg_abort(1);
15326 -+ }
15327 -+
15328 -+ create_shutdown_thread();
15329 -+ start_handle_manager();
15330 -+
15331 -+ sql_print_information(ER(ER_STARTUP),my_progname,server_version,
15332 -+ ((unix_sock == INVALID_SOCKET) ? (char*) ""
15333 -+ : mysqld_unix_port),
15334 -+ mysqld_port,
15335 -+ MYSQL_COMPILATION_COMMENT);
15336 -+#if defined(_WIN32) && !defined(EMBEDDED_LIBRARY)
15337 -+ Service.SetRunning();
15338 -+#endif
15339 -+
15340 -+
15341 -+ /* Signal threads waiting for server to be started */
15342 -+ pthread_mutex_lock(&LOCK_server_started);
15343 -+ mysqld_server_started= 1;
15344 -+ pthread_cond_signal(&COND_server_started);
15345 -+ pthread_mutex_unlock(&LOCK_server_started);
15346 -+
15347 -+#if defined(__NT__) || defined(HAVE_SMEM)
15348 -+ handle_connections_methods();
15349 -+#else
15350 -+#ifdef __WIN__
15351 -+ if (!have_tcpip || opt_disable_networking)
15352 -+ {
15353 -+ sql_print_error("TCP/IP unavailable or disabled with --skip-networking; no available interfaces");
15354 -+ unireg_abort(1);
15355 -+ }
15356 -+#endif
15357 -+ handle_connections_sockets(0);
15358 -+#endif /* __NT__ */
15359 -+
15360 -+ /* (void) pthread_attr_destroy(&connection_attrib); */
15361 -+
15362 -+ DBUG_PRINT("quit",("Exiting main thread"));
15363 -+
15364 -+#ifndef __WIN__
15365 -+#ifdef EXTRA_DEBUG2
15366 -+ sql_print_error("Before Lock_thread_count");
15367 -+#endif
15368 -+ (void) pthread_mutex_lock(&LOCK_thread_count);
15369 -+ DBUG_PRINT("quit", ("Got thread_count mutex"));
15370 -+ select_thread_in_use=0; // For close_connections
15371 -+ (void) pthread_mutex_unlock(&LOCK_thread_count);
15372 -+ (void) pthread_cond_broadcast(&COND_thread_count);
15373 -+#ifdef EXTRA_DEBUG2
15374 -+ sql_print_error("After lock_thread_count");
15375 -+#endif
15376 -+#endif /* __WIN__ */
15377 -+
15378 -+ /* Wait until cleanup is done */
15379 -+ (void) pthread_mutex_lock(&LOCK_thread_count);
15380 -+ while (!ready_to_exit)
15381 -+ pthread_cond_wait(&COND_thread_count,&LOCK_thread_count);
15382 -+ (void) pthread_mutex_unlock(&LOCK_thread_count);
15383 -+
15384 -+#if defined(__WIN__) && !defined(EMBEDDED_LIBRARY)
15385 -+ if (Service.IsNT() && start_mode)
15386 -+ Service.Stop();
15387 -+ else
15388 -+ {
15389 -+ Service.SetShutdownEvent(0);
15390 -+ if (hEventShutdown)
15391 -+ CloseHandle(hEventShutdown);
15392 -+ }
15393 -+#endif
15394 -+ clean_up(1);
15395 -+ wait_for_signal_thread_to_end();
15396 -+ clean_up_mutexes();
15397 -+ my_end(opt_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0);
15398 -+
15399 -+ exit(0);
15400 -+ return(0); /* purecov: deadcode */
15401 -+}
15402 -+
15403 -+#endif /* EMBEDDED_LIBRARY */
15404 -+
15405 -+
15406 -+/****************************************************************************
15407 -+ Main and thread entry function for Win32
15408 -+ (all this is needed only to run mysqld as a service on WinNT)
15409 -+****************************************************************************/
15410 -+
15411 -+#if defined(__WIN__) && !defined(EMBEDDED_LIBRARY)
15412 -+int mysql_service(void *p)
15413 -+{
15414 -+ if (use_opt_args)
15415 -+ win_main(opt_argc, opt_argv);
15416 -+ else
15417 -+ win_main(Service.my_argc, Service.my_argv);
15418 -+ return 0;
15419 -+}
15420 -+
15421 -+
15422 -+/* Quote string if it contains space, else copy */
15423 -+
15424 -+static char *add_quoted_string(char *to, const char *from, char *to_end)
15425 -+{
15426 -+ uint length= (uint) (to_end-to);
15427 -+
15428 -+ if (!strchr(from, ' '))
15429 -+ return strmake(to, from, length-1);
15430 -+ return strxnmov(to, length-1, "\"", from, "\"", NullS);
15431 -+}
15432 -+
15433 -+
15434 -+/**
15435 -+ Handle basic handling of services, like installation and removal.
15436 -+
15437 -+ @param argv Pointer to argument list
15438 -+ @param servicename Internal name of service
15439 -+ @param displayname Display name of service (in taskbar ?)
15440 -+ @param file_path Path to this program
15441 -+ @param startup_option Startup option to mysqld
15442 -+
15443 -+ @retval
15444 -+ 0 option handled
15445 -+ @retval
15446 -+ 1 Could not handle option
15447 -+*/
15448 -+
15449 -+static bool
15450 -+default_service_handling(char **argv,
15451 -+ const char *servicename,
15452 -+ const char *displayname,
15453 -+ const char *file_path,
15454 -+ const char *extra_opt,
15455 -+ const char *account_name)
15456 -+{
15457 -+ char path_and_service[FN_REFLEN+FN_REFLEN+32], *pos, *end;
15458 -+ const char *opt_delim;
15459 -+ end= path_and_service + sizeof(path_and_service)-3;
15460 -+
15461 -+ /* We have to quote filename if it contains spaces */
15462 -+ pos= add_quoted_string(path_and_service, file_path, end);
15463 -+ if (*extra_opt)
15464 -+ {
15465 -+ /*
15466 -+ Add option after file_path. There will be zero or one extra option. It's
15467 -+ assumed to be --defaults-file=file but isn't checked. The variable (not
15468 -+ the option name) should be quoted if it contains a string.
15469 -+ */
15470 -+ *pos++= ' ';
15471 -+ if (opt_delim= strchr(extra_opt, '='))
15472 -+ {
15473 -+ size_t length= ++opt_delim - extra_opt;
15474 -+ pos= strnmov(pos, extra_opt, length);
15475 -+ }
15476 -+ else
15477 -+ opt_delim= extra_opt;
15478 -+
15479 -+ pos= add_quoted_string(pos, opt_delim, end);
15480 -+ }
15481 -+ /* We must have servicename last */
15482 -+ *pos++= ' ';
15483 -+ (void) add_quoted_string(pos, servicename, end);
15484 -+
15485 -+ if (Service.got_service_option(argv, "install"))
15486 -+ {
15487 -+ Service.Install(1, servicename, displayname, path_and_service,
15488 -+ account_name);
15489 -+ return 0;
15490 -+ }
15491 -+ if (Service.got_service_option(argv, "install-manual"))
15492 -+ {
15493 -+ Service.Install(0, servicename, displayname, path_and_service,
15494 -+ account_name);
15495 -+ return 0;
15496 -+ }
15497 -+ if (Service.got_service_option(argv, "remove"))
15498 -+ {
15499 -+ Service.Remove(servicename);
15500 -+ return 0;
15501 -+ }
15502 -+ return 1;
15503 -+}
15504 -+
15505 -+
15506 -+int main(int argc, char **argv)
15507 -+{
15508 -+ /*
15509 -+ When several instances are running on the same machine, we
15510 -+ need to have an unique named hEventShudown through the
15511 -+ application PID e.g.: MySQLShutdown1890; MySQLShutdown2342
15512 -+ */
15513 -+ int10_to_str((int) GetCurrentProcessId(),strmov(shutdown_event_name,
15514 -+ "MySQLShutdown"), 10);
15515 -+
15516 -+ /* Must be initialized early for comparison of service name */
15517 -+ system_charset_info= &my_charset_utf8_general_ci;
15518 -+
15519 -+ if (Service.GetOS()) /* true NT family */
15520 -+ {
15521 -+ char file_path[FN_REFLEN];
15522 -+ my_path(file_path, argv[0], ""); /* Find name in path */
15523 -+ fn_format(file_path,argv[0],file_path,"",
15524 -+ MY_REPLACE_DIR | MY_UNPACK_FILENAME | MY_RESOLVE_SYMLINKS);
15525 -+
15526 -+ if (argc == 2)
15527 -+ {
15528 -+ if (!default_service_handling(argv, MYSQL_SERVICENAME, MYSQL_SERVICENAME,
15529 -+ file_path, "", NULL))
15530 -+ return 0;
15531 -+ if (Service.IsService(argv[1])) /* Start an optional service */
15532 -+ {
15533 -+ /*
15534 -+ Only add the service name to the groups read from the config file
15535 -+ if it's not "MySQL". (The default service name should be 'mysqld'
15536 -+ but we started a bad tradition by calling it MySQL from the start
15537 -+ and we are now stuck with it.
15538 -+ */
15539 -+ if (my_strcasecmp(system_charset_info, argv[1],"mysql"))
15540 -+ load_default_groups[load_default_groups_sz-2]= argv[1];
15541 -+ start_mode= 1;
15542 -+ Service.Init(argv[1], mysql_service);
15543 -+ return 0;
15544 -+ }
15545 -+ }
15546 -+ else if (argc == 3) /* install or remove any optional service */
15547 -+ {
15548 -+ if (!default_service_handling(argv, argv[2], argv[2], file_path, "",
15549 -+ NULL))
15550 -+ return 0;
15551 -+ if (Service.IsService(argv[2]))
15552 -+ {
15553 -+ /*
15554 -+ mysqld was started as
15555 -+ mysqld --defaults-file=my_path\my.ini service-name
15556 -+ */
15557 -+ use_opt_args=1;
15558 -+ opt_argc= 2; // Skip service-name
15559 -+ opt_argv=argv;
15560 -+ start_mode= 1;
15561 -+ if (my_strcasecmp(system_charset_info, argv[2],"mysql"))
15562 -+ load_default_groups[load_default_groups_sz-2]= argv[2];
15563 -+ Service.Init(argv[2], mysql_service);
15564 -+ return 0;
15565 -+ }
15566 -+ }
15567 -+ else if (argc == 4 || argc == 5)
15568 -+ {
15569 -+ /*
15570 -+ This may seem strange, because we handle --local-service while
15571 -+ preserving 4.1's behavior of allowing any one other argument that is
15572 -+ passed to the service on startup. (The assumption is that this is
15573 -+ --defaults-file=file, but that was not enforced in 4.1, so we don't
15574 -+ enforce it here.)
15575 -+ */
15576 -+ const char *extra_opt= NullS;
15577 -+ const char *account_name = NullS;
15578 -+ int index;
15579 -+ for (index = 3; index < argc; index++)
15580 -+ {
15581 -+ if (!strcmp(argv[index], "--local-service"))
15582 -+ account_name= "NT AUTHORITY\\LocalService";
15583 -+ else
15584 -+ extra_opt= argv[index];
15585 -+ }
15586 -+
15587 -+ if (argc == 4 || account_name)
15588 -+ if (!default_service_handling(argv, argv[2], argv[2], file_path,
15589 -+ extra_opt, account_name))
15590 -+ return 0;
15591 -+ }
15592 -+ else if (argc == 1 && Service.IsService(MYSQL_SERVICENAME))
15593 -+ {
15594 -+ /* start the default service */
15595 -+ start_mode= 1;
15596 -+ Service.Init(MYSQL_SERVICENAME, mysql_service);
15597 -+ return 0;
15598 -+ }
15599 -+ }
15600 -+ /* Start as standalone server */
15601 -+ Service.my_argc=argc;
15602 -+ Service.my_argv=argv;
15603 -+ mysql_service(NULL);
15604 -+ return 0;
15605 -+}
15606 -+#endif
15607 -+
15608 -+
15609 -+/**
15610 -+ Execute all commands from a file. Used by the mysql_install_db script to
15611 -+ create MySQL privilege tables without having to start a full MySQL server.
15612 -+*/
15613 -+
15614 -+static void bootstrap(FILE *file)
15615 -+{
15616 -+ DBUG_ENTER("bootstrap");
15617 -+
15618 -+ THD *thd= new THD;
15619 -+ thd->bootstrap=1;
15620 -+ my_net_init(&thd->net,(st_vio*) 0);
15621 -+ thd->max_client_packet_length= thd->net.max_packet;
15622 -+ thd->security_ctx->master_access= ~(ulong)0;
15623 -+ thd->thread_id= thd->variables.pseudo_thread_id= thread_id++;
15624 -+ thread_count++;
15625 -+ in_bootstrap= TRUE;
15626 -+
15627 -+ bootstrap_file=file;
15628 -+#ifndef EMBEDDED_LIBRARY // TODO: Enable this
15629 -+ if (pthread_create(&thd->real_id,&connection_attrib,handle_bootstrap,
15630 -+ (void*) thd))
15631 -+ {
15632 -+ sql_print_warning("Can't create thread to handle bootstrap");
15633 -+ bootstrap_error=-1;
15634 -+ DBUG_VOID_RETURN;
15635 -+ }
15636 -+ /* Wait for thread to die */
15637 -+ (void) pthread_mutex_lock(&LOCK_thread_count);
15638 -+ while (in_bootstrap)
15639 -+ {
15640 -+ (void) pthread_cond_wait(&COND_thread_count,&LOCK_thread_count);
15641 -+ DBUG_PRINT("quit",("One thread died (count=%u)",thread_count));
15642 -+ }
15643 -+ (void) pthread_mutex_unlock(&LOCK_thread_count);
15644 -+#else
15645 -+ thd->mysql= 0;
15646 -+ handle_bootstrap((void *)thd);
15647 -+#endif
15648 -+
15649 -+ DBUG_VOID_RETURN;
15650 -+}
15651 -+
15652 -+
15653 -+static bool read_init_file(char *file_name)
15654 -+{
15655 -+ FILE *file;
15656 -+ DBUG_ENTER("read_init_file");
15657 -+ DBUG_PRINT("enter",("name: %s",file_name));
15658 -+ if (!(file=my_fopen(file_name,O_RDONLY,MYF(MY_WME))))
15659 -+ DBUG_RETURN(TRUE);
15660 -+ bootstrap(file);
15661 -+ (void) my_fclose(file,MYF(MY_WME));
15662 -+ DBUG_RETURN(FALSE);
15663 -+}
15664 -+
15665 -+
15666 -+#ifndef EMBEDDED_LIBRARY
15667 -+
15668 -+/*
15669 -+ Simple scheduler that use the main thread to handle the request
15670 -+
15671 -+ NOTES
15672 -+ This is only used for debugging, when starting mysqld with
15673 -+ --thread-handling=no-threads or --one-thread
15674 -+
15675 -+ When we enter this function, LOCK_thread_count is hold!
15676 -+*/
15677 -+
15678 -+void handle_connection_in_main_thread(THD *thd)
15679 -+{
15680 -+ safe_mutex_assert_owner(&LOCK_thread_count);
15681 -+ thread_cache_size=0; // Safety
15682 -+ threads.append(thd);
15683 -+ pthread_mutex_unlock(&LOCK_thread_count);
15684 -+ thd->start_utime= my_micro_time();
15685 -+ handle_one_connection(thd);
15686 -+}
15687 -+
15688 -+
15689 -+/*
15690 -+ Scheduler that uses one thread per connection
15691 -+*/
15692 -+
15693 -+void create_thread_to_handle_connection(THD *thd)
15694 -+{
15695 -+ if (cached_thread_count > wake_thread)
15696 -+ {
15697 -+ /* Get thread from cache */
15698 -+ thread_cache.append(thd);
15699 -+ wake_thread++;
15700 -+ pthread_cond_signal(&COND_thread_cache);
15701 -+ }
15702 -+ else
15703 -+ {
15704 -+ char error_message_buff[MYSQL_ERRMSG_SIZE];
15705 -+ /* Create new thread to handle connection */
15706 -+ int error;
15707 -+ thread_created++;
15708 -+ threads.append(thd);
15709 -+ DBUG_PRINT("info",(("creating thread %lu"), thd->thread_id));
15710 -+ thd->prior_thr_create_utime= thd->start_utime= my_micro_time();
15711 -+ if ((error=pthread_create(&thd->real_id,&connection_attrib,
15712 -+ handle_one_connection,
15713 -+ (void*) thd)))
15714 -+ {
15715 -+ /* purecov: begin inspected */
15716 -+ DBUG_PRINT("error",
15717 -+ ("Can't create thread to handle request (error %d)",
15718 -+ error));
15719 -+ thread_count--;
15720 -+ thd->killed= THD::KILL_CONNECTION; // Safety
15721 -+ (void) pthread_mutex_unlock(&LOCK_thread_count);
15722 -+
15723 -+ pthread_mutex_lock(&LOCK_connection_count);
15724 -+ --connection_count;
15725 -+ pthread_mutex_unlock(&LOCK_connection_count);
15726 -+
15727 -+ statistic_increment(aborted_connects,&LOCK_status);
15728 -+ /* Can't use my_error() since store_globals has not been called. */
15729 -+ my_snprintf(error_message_buff, sizeof(error_message_buff),
15730 -+ ER(ER_CANT_CREATE_THREAD), error);
15731 -+ net_send_error(thd, ER_CANT_CREATE_THREAD, error_message_buff);
15732 -+ (void) pthread_mutex_lock(&LOCK_thread_count);
15733 -+ close_connection(thd,0,0);
15734 -+ delete thd;
15735 -+ (void) pthread_mutex_unlock(&LOCK_thread_count);
15736 -+ return;
15737 -+ /* purecov: end */
15738 -+ }
15739 -+ }
15740 -+ (void) pthread_mutex_unlock(&LOCK_thread_count);
15741 -+ DBUG_PRINT("info",("Thread created"));
15742 -+}
15743 -+
15744 -+
15745 -+/**
15746 -+ Create new thread to handle incoming connection.
15747 -+
15748 -+ This function will create new thread to handle the incoming
15749 -+ connection. If there are idle cached threads one will be used.
15750 -+ 'thd' will be pushed into 'threads'.
15751 -+
15752 -+ In single-threaded mode (\#define ONE_THREAD) connection will be
15753 -+ handled inside this function.
15754 -+
15755 -+ @param[in,out] thd Thread handle of future thread.
15756 -+*/
15757 -+
15758 -+static void create_new_thread(THD *thd)
15759 -+{
15760 -+ NET *net=&thd->net;
15761 -+ DBUG_ENTER("create_new_thread");
15762 -+
15763 -+ if (protocol_version > 9)
15764 -+ net->return_errno=1;
15765 -+
15766 -+ /*
15767 -+ Don't allow too many connections. We roughly check here that we allow
15768 -+ only (max_connections + 1) connections.
15769 -+ */
15770 -+
15771 -+ pthread_mutex_lock(&LOCK_connection_count);
15772 -+
15773 -+ if (connection_count >= max_connections + 1 || abort_loop)
15774 -+ {
15775 -+ pthread_mutex_unlock(&LOCK_connection_count);
15776 -+
15777 -+ DBUG_PRINT("error",("Too many connections"));
15778 -+ close_connection(thd, ER_CON_COUNT_ERROR, 1);
15779 -+ delete thd;
15780 -+ DBUG_VOID_RETURN;
15781 -+ }
15782 -+
15783 -+ ++connection_count;
15784 -+
15785 -+ if (connection_count > max_used_connections)
15786 -+ max_used_connections= connection_count;
15787 -+
15788 -+ pthread_mutex_unlock(&LOCK_connection_count);
15789 -+
15790 -+ /* Start a new thread to handle connection. */
15791 -+
15792 -+ pthread_mutex_lock(&LOCK_thread_count);
15793 -+
15794 -+ /*
15795 -+ The initialization of thread_id is done in create_embedded_thd() for
15796 -+ the embedded library.
15797 -+ TODO: refactor this to avoid code duplication there
15798 -+ */
15799 -+ thd->thread_id= thd->variables.pseudo_thread_id= thread_id++;
15800 -+
15801 -+ thread_count++;
15802 -+
15803 -+ thread_scheduler.add_connection(thd);
15804 -+
15805 -+ DBUG_VOID_RETURN;
15806 -+}
15807 -+#endif /* EMBEDDED_LIBRARY */
15808 -+
15809 -+
15810 -+#ifdef SIGNALS_DONT_BREAK_READ
15811 -+inline void kill_broken_server()
15812 -+{
15813 -+ /* hack to get around signals ignored in syscalls for problem OS's */
15814 -+ if (
15815 -+#if !defined(__NETWARE__)
15816 -+ unix_sock == INVALID_SOCKET ||
15817 -+#endif
15818 -+ (!opt_disable_networking && ip_sock == INVALID_SOCKET))
15819 -+ {
15820 -+ select_thread_in_use = 0;
15821 -+ /* The following call will never return */
15822 -+ kill_server(IF_NETWARE(MYSQL_KILL_SIGNAL, (void*) MYSQL_KILL_SIGNAL));
15823 -+ }
15824 -+}
15825 -+#define MAYBE_BROKEN_SYSCALL kill_broken_server();
15826 -+#else
15827 -+#define MAYBE_BROKEN_SYSCALL
15828 -+#endif
15829 -+
15830 -+ /* Handle new connections and spawn new process to handle them */
15831 -+
15832 -+#ifndef EMBEDDED_LIBRARY
15833 -+pthread_handler_t handle_connections_sockets(void *arg __attribute__((unused)))
15834 -+{
15835 -+ my_socket sock,new_sock;
15836 -+ uint error_count=0;
15837 -+ uint max_used_connection= (uint) (max(ip_sock,unix_sock)+1);
15838 -+ fd_set readFDs,clientFDs;
15839 -+ THD *thd;
15840 -+ struct sockaddr_in cAddr;
15841 -+ int ip_flags=0,socket_flags=0,flags;
15842 -+ st_vio *vio_tmp;
15843 -+ DBUG_ENTER("handle_connections_sockets");
15844 -+
15845 -+ LINT_INIT(new_sock);
15846 -+
15847 -+ (void) my_pthread_getprio(pthread_self()); // For debugging
15848 -+
15849 -+ FD_ZERO(&clientFDs);
15850 -+ if (ip_sock != INVALID_SOCKET)
15851 -+ {
15852 -+ FD_SET(ip_sock,&clientFDs);
15853 -+#ifdef HAVE_FCNTL
15854 -+ ip_flags = fcntl(ip_sock, F_GETFL, 0);
15855 -+#endif
15856 -+ }
15857 -+#ifdef HAVE_SYS_UN_H
15858 -+ FD_SET(unix_sock,&clientFDs);
15859 -+#ifdef HAVE_FCNTL
15860 -+ socket_flags=fcntl(unix_sock, F_GETFL, 0);
15861 -+#endif
15862 -+#endif
15863 -+
15864 -+ DBUG_PRINT("general",("Waiting for connections."));
15865 -+ MAYBE_BROKEN_SYSCALL;
15866 -+ while (!abort_loop)
15867 -+ {
15868 -+ readFDs=clientFDs;
15869 -+#ifdef HPUX10
15870 -+ if (select(max_used_connection,(int*) &readFDs,0,0,0) < 0)
15871 -+ continue;
15872 -+#else
15873 -+ if (select((int) max_used_connection,&readFDs,0,0,0) < 0)
15874 -+ {
15875 -+ if (socket_errno != SOCKET_EINTR)
15876 -+ {
15877 -+ if (!select_errors++ && !abort_loop) /* purecov: inspected */
15878 -+ sql_print_error("mysqld: Got error %d from select",socket_errno); /* purecov: inspected */
15879 -+ }
15880 -+ MAYBE_BROKEN_SYSCALL
15881 -+ continue;
15882 -+ }
15883 -+#endif /* HPUX10 */
15884 -+ if (abort_loop)
15885 -+ {
15886 -+ MAYBE_BROKEN_SYSCALL;
15887 -+ break;
15888 -+ }
15889 -+
15890 -+ /* Is this a new connection request ? */
15891 -+#ifdef HAVE_SYS_UN_H
15892 -+ if (FD_ISSET(unix_sock,&readFDs))
15893 -+ {
15894 -+ sock = unix_sock;
15895 -+ flags= socket_flags;
15896 -+ }
15897 -+ else
15898 -+#endif
15899 -+ {
15900 -+ sock = ip_sock;
15901 -+ flags= ip_flags;
15902 -+ }
15903 -+
15904 -+#if !defined(NO_FCNTL_NONBLOCK)
15905 -+ if (!(test_flags & TEST_BLOCKING))
15906 -+ {
15907 -+#if defined(O_NONBLOCK)
15908 -+ fcntl(sock, F_SETFL, flags | O_NONBLOCK);
15909 -+#elif defined(O_NDELAY)
15910 -+ fcntl(sock, F_SETFL, flags | O_NDELAY);
15911 -+#endif
15912 -+ }
15913 -+#endif /* NO_FCNTL_NONBLOCK */
15914 -+ for (uint retry=0; retry < MAX_ACCEPT_RETRY; retry++)
15915 -+ {
15916 -+ size_socket length=sizeof(struct sockaddr_in);
15917 -+ new_sock = accept(sock, my_reinterpret_cast(struct sockaddr *) (&cAddr),
15918 -+ &length);
15919 -+#ifdef __NETWARE__
15920 -+ // TODO: temporary fix, waiting for TCP/IP fix - DEFECT000303149
15921 -+ if ((new_sock == INVALID_SOCKET) && (socket_errno == EINVAL))
15922 -+ {
15923 -+ kill_server(SIGTERM);
15924 -+ }
15925 -+#endif
15926 -+ if (new_sock != INVALID_SOCKET ||
15927 -+ (socket_errno != SOCKET_EINTR && socket_errno != SOCKET_EAGAIN))
15928 -+ break;
15929 -+ MAYBE_BROKEN_SYSCALL;
15930 -+#if !defined(NO_FCNTL_NONBLOCK)
15931 -+ if (!(test_flags & TEST_BLOCKING))
15932 -+ {
15933 -+ if (retry == MAX_ACCEPT_RETRY - 1)
15934 -+ fcntl(sock, F_SETFL, flags); // Try without O_NONBLOCK
15935 -+ }
15936 -+#endif
15937 -+ }
15938 -+#if !defined(NO_FCNTL_NONBLOCK)
15939 -+ if (!(test_flags & TEST_BLOCKING))
15940 -+ fcntl(sock, F_SETFL, flags);
15941 -+#endif
15942 -+ if (new_sock == INVALID_SOCKET)
15943 -+ {
15944 -+ if ((error_count++ & 255) == 0) // This can happen often
15945 -+ sql_perror("Error in accept");
15946 -+ MAYBE_BROKEN_SYSCALL;
15947 -+ if (socket_errno == SOCKET_ENFILE || socket_errno == SOCKET_EMFILE)
15948 -+ sleep(1); // Give other threads some time
15949 -+ continue;
15950 -+ }
15951 -+
15952 -+#ifdef HAVE_LIBWRAP
15953 -+ {
15954 -+ if (sock == ip_sock)
15955 -+ {
15956 -+ struct request_info req;
15957 -+ signal(SIGCHLD, SIG_DFL);
15958 -+ request_init(&req, RQ_DAEMON, libwrapName, RQ_FILE, new_sock, NULL);
15959 -+ my_fromhost(&req);
15960 -+ if (!my_hosts_access(&req))
15961 -+ {
15962 -+ /*
15963 -+ This may be stupid but refuse() includes an exit(0)
15964 -+ which we surely don't want...
15965 -+ clean_exit() - same stupid thing ...
15966 -+ */
15967 -+ syslog(deny_severity, "refused connect from %s",
15968 -+ my_eval_client(&req));
15969 -+
15970 -+ /*
15971 -+ C++ sucks (the gibberish in front just translates the supplied
15972 -+ sink function pointer in the req structure from a void (*sink)();
15973 -+ to a void(*sink)(int) if you omit the cast, the C++ compiler
15974 -+ will cry...
15975 -+ */
15976 -+ if (req.sink)
15977 -+ ((void (*)(int))req.sink)(req.fd);
15978 -+
15979 -+ (void) shutdown(new_sock, SHUT_RDWR);
15980 -+ (void) closesocket(new_sock);
15981 -+ continue;
15982 -+ }
15983 -+ }
15984 -+ }
15985 -+#endif /* HAVE_LIBWRAP */
15986 -+
15987 -+ {
15988 -+ size_socket dummyLen;
15989 -+ struct sockaddr dummy;
15990 -+ dummyLen = sizeof(struct sockaddr);
15991 -+ if (getsockname(new_sock,&dummy, &dummyLen) < 0)
15992 -+ {
15993 -+ sql_perror("Error on new connection socket");
15994 -+ (void) shutdown(new_sock, SHUT_RDWR);
15995 -+ (void) closesocket(new_sock);
15996 -+ continue;
15997 -+ }
15998 -+ }
15999 -+
16000 -+ /*
16001 -+ ** Don't allow too many connections
16002 -+ */
16003 -+
16004 -+ if (!(thd= new THD))
16005 -+ {
16006 -+ (void) shutdown(new_sock, SHUT_RDWR);
16007 -+ VOID(closesocket(new_sock));
16008 -+ continue;
16009 -+ }
16010 -+ if (!(vio_tmp=vio_new(new_sock,
16011 -+ sock == unix_sock ? VIO_TYPE_SOCKET :
16012 -+ VIO_TYPE_TCPIP,
16013 -+ sock == unix_sock ? VIO_LOCALHOST: 0)) ||
16014 -+ my_net_init(&thd->net,vio_tmp))
16015 -+ {
16016 -+ /*
16017 -+ Only delete the temporary vio if we didn't already attach it to the
16018 -+ NET object. The destructor in THD will delete any initialized net
16019 -+ structure.
16020 -+ */
16021 -+ if (vio_tmp && thd->net.vio != vio_tmp)
16022 -+ vio_delete(vio_tmp);
16023 -+ else
16024 -+ {
16025 -+ (void) shutdown(new_sock, SHUT_RDWR);
16026 -+ (void) closesocket(new_sock);
16027 -+ }
16028 -+ delete thd;
16029 -+ continue;
16030 -+ }
16031 -+ if (sock == unix_sock)
16032 -+ thd->security_ctx->host=(char*) my_localhost;
16033 -+
16034 -+ create_new_thread(thd);
16035 -+ }
16036 -+ DBUG_LEAVE;
16037 -+ decrement_handler_count();
16038 -+ return 0;
16039 -+}
16040 -+
16041 -+
16042 -+#ifdef __NT__
16043 -+pthread_handler_t handle_connections_namedpipes(void *arg)
16044 -+{
16045 -+ HANDLE hConnectedPipe;
16046 -+ OVERLAPPED connectOverlapped= {0};
16047 -+ THD *thd;
16048 -+ my_thread_init();
16049 -+ DBUG_ENTER("handle_connections_namedpipes");
16050 -+ connectOverlapped.hEvent= CreateEvent(NULL, TRUE, FALSE, NULL);
16051 -+ if (!connectOverlapped.hEvent)
16052 -+ {
16053 -+ sql_print_error("Can't create event, last error=%u", GetLastError());
16054 -+ unireg_abort(1);
16055 -+ }
16056 -+ DBUG_PRINT("general",("Waiting for named pipe connections."));
16057 -+ while (!abort_loop)
16058 -+ {
16059 -+ /* wait for named pipe connection */
16060 -+ BOOL fConnected= ConnectNamedPipe(hPipe, &connectOverlapped);
16061 -+ if (!fConnected && (GetLastError() == ERROR_IO_PENDING))
16062 -+ {
16063 -+ /*
16064 -+ ERROR_IO_PENDING says async IO has started but not yet finished.
16065 -+ GetOverlappedResult will wait for completion.
16066 -+ */
16067 -+ DWORD bytes;
16068 -+ fConnected= GetOverlappedResult(hPipe, &connectOverlapped,&bytes, TRUE);
16069 -+ }
16070 -+ if (abort_loop)
16071 -+ break;
16072 -+ if (!fConnected)
16073 -+ fConnected = GetLastError() == ERROR_PIPE_CONNECTED;
16074 -+ if (!fConnected)
16075 -+ {
16076 -+ CloseHandle(hPipe);
16077 -+ if ((hPipe= CreateNamedPipe(pipe_name,
16078 -+ PIPE_ACCESS_DUPLEX |
16079 -+ FILE_FLAG_OVERLAPPED,
16080 -+ PIPE_TYPE_BYTE |
16081 -+ PIPE_READMODE_BYTE |
16082 -+ PIPE_WAIT,
16083 -+ PIPE_UNLIMITED_INSTANCES,
16084 -+ (int) global_system_variables.
16085 -+ net_buffer_length,
16086 -+ (int) global_system_variables.
16087 -+ net_buffer_length,
16088 -+ NMPWAIT_USE_DEFAULT_WAIT,
16089 -+ &saPipeSecurity)) ==
16090 -+ INVALID_HANDLE_VALUE)
16091 -+ {
16092 -+ sql_perror("Can't create new named pipe!");
16093 -+ break; // Abort
16094 -+ }
16095 -+ }
16096 -+ hConnectedPipe = hPipe;
16097 -+ /* create new pipe for new connection */
16098 -+ if ((hPipe = CreateNamedPipe(pipe_name,
16099 -+ PIPE_ACCESS_DUPLEX |
16100 -+ FILE_FLAG_OVERLAPPED,
16101 -+ PIPE_TYPE_BYTE |
16102 -+ PIPE_READMODE_BYTE |
16103 -+ PIPE_WAIT,
16104 -+ PIPE_UNLIMITED_INSTANCES,
16105 -+ (int) global_system_variables.net_buffer_length,
16106 -+ (int) global_system_variables.net_buffer_length,
16107 -+ NMPWAIT_USE_DEFAULT_WAIT,
16108 -+ &saPipeSecurity)) ==
16109 -+ INVALID_HANDLE_VALUE)
16110 -+ {
16111 -+ sql_perror("Can't create new named pipe!");
16112 -+ hPipe=hConnectedPipe;
16113 -+ continue; // We have to try again
16114 -+ }
16115 -+
16116 -+ if (!(thd = new THD))
16117 -+ {
16118 -+ DisconnectNamedPipe(hConnectedPipe);
16119 -+ CloseHandle(hConnectedPipe);
16120 -+ continue;
16121 -+ }
16122 -+ if (!(thd->net.vio= vio_new_win32pipe(hConnectedPipe)) ||
16123 -+ my_net_init(&thd->net, thd->net.vio))
16124 -+ {
16125 -+ close_connection(thd, ER_OUT_OF_RESOURCES, 1);
16126 -+ delete thd;
16127 -+ continue;
16128 -+ }
16129 -+ /* Host is unknown */
16130 -+ thd->security_ctx->host= my_strdup(my_localhost, MYF(0));
16131 -+ create_new_thread(thd);
16132 -+ }
16133 -+ CloseHandle(connectOverlapped.hEvent);
16134 -+ DBUG_LEAVE;
16135 -+ decrement_handler_count();
16136 -+ return 0;
16137 -+}
16138 -+#endif /* __NT__ */
16139 -+
16140 -+
16141 -+#ifdef HAVE_SMEM
16142 -+
16143 -+/**
16144 -+ Thread of shared memory's service.
16145 -+
16146 -+ @param arg Arguments of thread
16147 -+*/
16148 -+pthread_handler_t handle_connections_shared_memory(void *arg)
16149 -+{
16150 -+ /* file-mapping object, use for create shared memory */
16151 -+ HANDLE handle_connect_file_map= 0;
16152 -+ char *handle_connect_map= 0; // pointer on shared memory
16153 -+ HANDLE event_connect_answer= 0;
16154 -+ ulong smem_buffer_length= shared_memory_buffer_length + 4;
16155 -+ ulong connect_number= 1;
16156 -+ char *tmp= NULL;
16157 -+ char *suffix_pos;
16158 -+ char connect_number_char[22], *p;
16159 -+ const char *errmsg= 0;
16160 -+ SECURITY_ATTRIBUTES *sa_event= 0, *sa_mapping= 0;
16161 -+ my_thread_init();
16162 -+ DBUG_ENTER("handle_connections_shared_memorys");
16163 -+ DBUG_PRINT("general",("Waiting for allocated shared memory."));
16164 -+
16165 -+ /*
16166 -+ get enough space base-name + '_' + longest suffix we might ever send
16167 -+ */
16168 -+ if (!(tmp= (char *)my_malloc(strlen(shared_memory_base_name) + 32L, MYF(MY_FAE))))
16169 -+ goto error;
16170 -+
16171 -+ if (my_security_attr_create(&sa_event, &errmsg,
16172 -+ GENERIC_ALL, SYNCHRONIZE | EVENT_MODIFY_STATE))
16173 -+ goto error;
16174 -+
16175 -+ if (my_security_attr_create(&sa_mapping, &errmsg,
16176 -+ GENERIC_ALL, FILE_MAP_READ | FILE_MAP_WRITE))
16177 -+ goto error;
16178 -+
16179 -+ /*
16180 -+ The name of event and file-mapping events create agree next rule:
16181 -+ shared_memory_base_name+unique_part
16182 -+ Where:
16183 -+ shared_memory_base_name is unique value for each server
16184 -+ unique_part is unique value for each object (events and file-mapping)
16185 -+ */
16186 -+ suffix_pos= strxmov(tmp,shared_memory_base_name,"_",NullS);
16187 -+ strmov(suffix_pos, "CONNECT_REQUEST");
16188 -+ if ((smem_event_connect_request= CreateEvent(sa_event,
16189 -+ FALSE, FALSE, tmp)) == 0)
16190 -+ {
16191 -+ errmsg= "Could not create request event";
16192 -+ goto error;
16193 -+ }
16194 -+ strmov(suffix_pos, "CONNECT_ANSWER");
16195 -+ if ((event_connect_answer= CreateEvent(sa_event, FALSE, FALSE, tmp)) == 0)
16196 -+ {
16197 -+ errmsg="Could not create answer event";
16198 -+ goto error;
16199 -+ }
16200 -+ strmov(suffix_pos, "CONNECT_DATA");
16201 -+ if ((handle_connect_file_map=
16202 -+ CreateFileMapping(INVALID_HANDLE_VALUE, sa_mapping,
16203 -+ PAGE_READWRITE, 0, sizeof(connect_number), tmp)) == 0)
16204 -+ {
16205 -+ errmsg= "Could not create file mapping";
16206 -+ goto error;
16207 -+ }
16208 -+ if ((handle_connect_map= (char *)MapViewOfFile(handle_connect_file_map,
16209 -+ FILE_MAP_WRITE,0,0,
16210 -+ sizeof(DWORD))) == 0)
16211 -+ {
16212 -+ errmsg= "Could not create shared memory service";
16213 -+ goto error;
16214 -+ }
16215 -+
16216 -+ while (!abort_loop)
16217 -+ {
16218 -+ /* Wait a request from client */
16219 -+ WaitForSingleObject(smem_event_connect_request,INFINITE);
16220 -+
16221 -+ /*
16222 -+ it can be after shutdown command
16223 -+ */
16224 -+ if (abort_loop)
16225 -+ goto error;
16226 -+
16227 -+ HANDLE handle_client_file_map= 0;
16228 -+ char *handle_client_map= 0;
16229 -+ HANDLE event_client_wrote= 0;
16230 -+ HANDLE event_client_read= 0; // for transfer data server <-> client
16231 -+ HANDLE event_server_wrote= 0;
16232 -+ HANDLE event_server_read= 0;
16233 -+ HANDLE event_conn_closed= 0;
16234 -+ THD *thd= 0;
16235 -+
16236 -+ p= int10_to_str(connect_number, connect_number_char, 10);
16237 -+ /*
16238 -+ The name of event and file-mapping events create agree next rule:
16239 -+ shared_memory_base_name+unique_part+number_of_connection
16240 -+ Where:
16241 -+ shared_memory_base_name is uniquel value for each server
16242 -+ unique_part is unique value for each object (events and file-mapping)
16243 -+ number_of_connection is connection-number between server and client
16244 -+ */
16245 -+ suffix_pos= strxmov(tmp,shared_memory_base_name,"_",connect_number_char,
16246 -+ "_",NullS);
16247 -+ strmov(suffix_pos, "DATA");
16248 -+ if ((handle_client_file_map=
16249 -+ CreateFileMapping(INVALID_HANDLE_VALUE, sa_mapping,
16250 -+ PAGE_READWRITE, 0, smem_buffer_length, tmp)) == 0)
16251 -+ {
16252 -+ errmsg= "Could not create file mapping";
16253 -+ goto errorconn;
16254 -+ }
16255 -+ if ((handle_client_map= (char*)MapViewOfFile(handle_client_file_map,
16256 -+ FILE_MAP_WRITE,0,0,
16257 -+ smem_buffer_length)) == 0)
16258 -+ {
16259 -+ errmsg= "Could not create memory map";
16260 -+ goto errorconn;
16261 -+ }
16262 -+ strmov(suffix_pos, "CLIENT_WROTE");
16263 -+ if ((event_client_wrote= CreateEvent(sa_event, FALSE, FALSE, tmp)) == 0)
16264 -+ {
16265 -+ errmsg= "Could not create client write event";
16266 -+ goto errorconn;
16267 -+ }
16268 -+ strmov(suffix_pos, "CLIENT_READ");
16269 -+ if ((event_client_read= CreateEvent(sa_event, FALSE, FALSE, tmp)) == 0)
16270 -+ {
16271 -+ errmsg= "Could not create client read event";
16272 -+ goto errorconn;
16273 -+ }
16274 -+ strmov(suffix_pos, "SERVER_READ");
16275 -+ if ((event_server_read= CreateEvent(sa_event, FALSE, FALSE, tmp)) == 0)
16276 -+ {
16277 -+ errmsg= "Could not create server read event";
16278 -+ goto errorconn;
16279 -+ }
16280 -+ strmov(suffix_pos, "SERVER_WROTE");
16281 -+ if ((event_server_wrote= CreateEvent(sa_event,
16282 -+ FALSE, FALSE, tmp)) == 0)
16283 -+ {
16284 -+ errmsg= "Could not create server write event";
16285 -+ goto errorconn;
16286 -+ }
16287 -+ strmov(suffix_pos, "CONNECTION_CLOSED");
16288 -+ if ((event_conn_closed= CreateEvent(sa_event,
16289 -+ TRUE, FALSE, tmp)) == 0)
16290 -+ {
16291 -+ errmsg= "Could not create closed connection event";
16292 -+ goto errorconn;
16293 -+ }
16294 -+ if (abort_loop)
16295 -+ goto errorconn;
16296 -+ if (!(thd= new THD))
16297 -+ goto errorconn;
16298 -+ /* Send number of connection to client */
16299 -+ int4store(handle_connect_map, connect_number);
16300 -+ if (!SetEvent(event_connect_answer))
16301 -+ {
16302 -+ errmsg= "Could not send answer event";
16303 -+ goto errorconn;
16304 -+ }
16305 -+ /* Set event that client should receive data */
16306 -+ if (!SetEvent(event_client_read))
16307 -+ {
16308 -+ errmsg= "Could not set client to read mode";
16309 -+ goto errorconn;
16310 -+ }
16311 -+ if (!(thd->net.vio= vio_new_win32shared_memory(handle_client_file_map,
16312 -+ handle_client_map,
16313 -+ event_client_wrote,
16314 -+ event_client_read,
16315 -+ event_server_wrote,
16316 -+ event_server_read,
16317 -+ event_conn_closed)) ||
16318 -+ my_net_init(&thd->net, thd->net.vio))
16319 -+ {
16320 -+ close_connection(thd, ER_OUT_OF_RESOURCES, 1);
16321 -+ errmsg= 0;
16322 -+ goto errorconn;
16323 -+ }
16324 -+ thd->security_ctx->host= my_strdup(my_localhost, MYF(0)); /* Host is unknown */
16325 -+ create_new_thread(thd);
16326 -+ connect_number++;
16327 -+ continue;
16328 -+
16329 -+errorconn:
16330 -+ /* Could not form connection; Free used handlers/memort and retry */
16331 -+ if (errmsg)
16332 -+ {
16333 -+ char buff[180];
16334 -+ strxmov(buff, "Can't create shared memory connection: ", errmsg, ".",
16335 -+ NullS);
16336 -+ sql_perror(buff);
16337 -+ }
16338 -+ if (handle_client_file_map)
16339 -+ CloseHandle(handle_client_file_map);
16340 -+ if (handle_client_map)
16341 -+ UnmapViewOfFile(handle_client_map);
16342 -+ if (event_server_wrote)
16343 -+ CloseHandle(event_server_wrote);
16344 -+ if (event_server_read)
16345 -+ CloseHandle(event_server_read);
16346 -+ if (event_client_wrote)
16347 -+ CloseHandle(event_client_wrote);
16348 -+ if (event_client_read)
16349 -+ CloseHandle(event_client_read);
16350 -+ if (event_conn_closed)
16351 -+ CloseHandle(event_conn_closed);
16352 -+ delete thd;
16353 -+ }
16354 -+
16355 -+ /* End shared memory handling */
16356 -+error:
16357 -+ if (tmp)
16358 -+ my_free(tmp, MYF(0));
16359 -+
16360 -+ if (errmsg)
16361 -+ {
16362 -+ char buff[180];
16363 -+ strxmov(buff, "Can't create shared memory service: ", errmsg, ".", NullS);
16364 -+ sql_perror(buff);
16365 -+ }
16366 -+ my_security_attr_free(sa_event);
16367 -+ my_security_attr_free(sa_mapping);
16368 -+ if (handle_connect_map) UnmapViewOfFile(handle_connect_map);
16369 -+ if (handle_connect_file_map) CloseHandle(handle_connect_file_map);
16370 -+ if (event_connect_answer) CloseHandle(event_connect_answer);
16371 -+ if (smem_event_connect_request) CloseHandle(smem_event_connect_request);
16372 -+ DBUG_LEAVE;
16373 -+ decrement_handler_count();
16374 -+ return 0;
16375 -+}
16376 -+#endif /* HAVE_SMEM */
16377 -+#endif /* EMBEDDED_LIBRARY */
16378 -+
16379 -+
16380 -+/****************************************************************************
16381 -+ Handle start options
16382 -+******************************************************************************/
16383 -+
16384 -+enum options_mysqld
16385 -+{
16386 -+ OPT_ISAM_LOG=256, OPT_SKIP_NEW,
16387 -+ OPT_SKIP_GRANT, OPT_SKIP_LOCK,
16388 -+ OPT_ENABLE_LOCK, OPT_USE_LOCKING,
16389 -+ OPT_SOCKET, OPT_UPDATE_LOG,
16390 -+ OPT_BIN_LOG, OPT_SKIP_RESOLVE,
16391 -+ OPT_SKIP_NETWORKING, OPT_BIN_LOG_INDEX,
16392 -+ OPT_BIND_ADDRESS, OPT_PID_FILE,
16393 -+ OPT_SKIP_PRIOR, OPT_BIG_TABLES,
16394 -+ OPT_STANDALONE, OPT_ONE_THREAD,
16395 -+ OPT_CONSOLE, OPT_LOW_PRIORITY_UPDATES,
16396 -+ OPT_SKIP_HOST_CACHE, OPT_SHORT_LOG_FORMAT,
16397 -+ OPT_FLUSH, OPT_SAFE,
16398 -+ OPT_BOOTSTRAP, OPT_SKIP_SHOW_DB,
16399 -+ OPT_STORAGE_ENGINE, OPT_INIT_FILE,
16400 -+ OPT_DELAY_KEY_WRITE_ALL, OPT_SLOW_QUERY_LOG,
16401 -+ OPT_DELAY_KEY_WRITE, OPT_CHARSETS_DIR,
16402 -+ OPT_MASTER_HOST, OPT_MASTER_USER,
16403 -+ OPT_MASTER_PASSWORD, OPT_MASTER_PORT,
16404 -+ OPT_MASTER_INFO_FILE, OPT_MASTER_CONNECT_RETRY,
16405 -+ OPT_MASTER_RETRY_COUNT, OPT_LOG_TC, OPT_LOG_TC_SIZE,
16406 -+ OPT_MASTER_SSL, OPT_MASTER_SSL_KEY,
16407 -+ OPT_MASTER_SSL_CERT, OPT_MASTER_SSL_CAPATH,
16408 -+ OPT_MASTER_SSL_CIPHER, OPT_MASTER_SSL_CA,
16409 -+ OPT_SQL_BIN_UPDATE_SAME, OPT_REPLICATE_DO_DB,
16410 -+ OPT_REPLICATE_IGNORE_DB, OPT_LOG_SLAVE_UPDATES,
16411 -+ OPT_BINLOG_DO_DB, OPT_BINLOG_IGNORE_DB,
16412 -+ OPT_BINLOG_FORMAT,
16413 -+#ifndef DBUG_OFF
16414 -+ OPT_BINLOG_SHOW_XID,
16415 -+#endif
16416 -+ OPT_BINLOG_ROWS_EVENT_MAX_SIZE,
16417 -+ OPT_WANT_CORE, OPT_CONCURRENT_INSERT,
16418 -+ OPT_MEMLOCK, OPT_MYISAM_RECOVER,
16419 -+ OPT_REPLICATE_REWRITE_DB, OPT_SERVER_ID,
16420 -+ OPT_SKIP_SLAVE_START, OPT_SAFE_SHOW_DB,
16421 -+ OPT_SAFEMALLOC_MEM_LIMIT, OPT_REPLICATE_DO_TABLE,
16422 -+ OPT_REPLICATE_IGNORE_TABLE, OPT_REPLICATE_WILD_DO_TABLE,
16423 -+ OPT_REPLICATE_WILD_IGNORE_TABLE, OPT_REPLICATE_SAME_SERVER_ID,
16424 -+ OPT_DISCONNECT_SLAVE_EVENT_COUNT, OPT_TC_HEURISTIC_RECOVER,
16425 -+ OPT_ABORT_SLAVE_EVENT_COUNT,
16426 -+ OPT_LOG_BIN_TRUST_FUNCTION_CREATORS,
16427 -+ OPT_LOG_BIN_TRUST_FUNCTION_CREATORS_OLD,
16428 -+ OPT_ENGINE_CONDITION_PUSHDOWN, OPT_NDB_CONNECTSTRING,
16429 -+ OPT_NDB_USE_EXACT_COUNT, OPT_NDB_USE_TRANSACTIONS,
16430 -+ OPT_NDB_FORCE_SEND, OPT_NDB_AUTOINCREMENT_PREFETCH_SZ,
16431 -+ OPT_NDB_SHM, OPT_NDB_OPTIMIZED_NODE_SELECTION, OPT_NDB_CACHE_CHECK_TIME,
16432 -+ OPT_NDB_MGMD, OPT_NDB_NODEID,
16433 -+ OPT_NDB_DISTRIBUTION,
16434 -+ OPT_NDB_INDEX_STAT_ENABLE,
16435 -+ OPT_NDB_EXTRA_LOGGING,
16436 -+ OPT_NDB_REPORT_THRESH_BINLOG_EPOCH_SLIP,
16437 -+ OPT_NDB_REPORT_THRESH_BINLOG_MEM_USAGE,
16438 -+ OPT_NDB_USE_COPYING_ALTER_TABLE,
16439 -+ OPT_SKIP_SAFEMALLOC,
16440 -+ OPT_TEMP_POOL, OPT_TX_ISOLATION, OPT_COMPLETION_TYPE,
16441 -+ OPT_SKIP_STACK_TRACE, OPT_SKIP_SYMLINKS,
16442 -+ OPT_MAX_BINLOG_DUMP_EVENTS, OPT_SPORADIC_BINLOG_DUMP_FAIL,
16443 -+ OPT_SAFE_USER_CREATE, OPT_SQL_MODE,
16444 -+ OPT_HAVE_NAMED_PIPE,
16445 -+ OPT_DO_PSTACK, OPT_EVENT_SCHEDULER, OPT_REPORT_HOST,
16446 -+ OPT_REPORT_USER, OPT_REPORT_PASSWORD, OPT_REPORT_PORT,
16447 -+ OPT_SHOW_SLAVE_AUTH_INFO,
16448 -+ OPT_SLAVE_LOAD_TMPDIR, OPT_NO_MIX_TYPE,
16449 -+ OPT_RPL_RECOVERY_RANK,OPT_INIT_RPL_ROLE,
16450 -+ OPT_RELAY_LOG, OPT_RELAY_LOG_INDEX, OPT_RELAY_LOG_INFO_FILE,
16451 -+ OPT_SLAVE_SKIP_ERRORS, OPT_DES_KEY_FILE, OPT_LOCAL_INFILE,
16452 -+ OPT_SSL_SSL, OPT_SSL_KEY, OPT_SSL_CERT, OPT_SSL_CA,
16453 -+ OPT_SSL_CAPATH, OPT_SSL_CIPHER,
16454 -+ OPT_BACK_LOG, OPT_BINLOG_CACHE_SIZE,
16455 -+ OPT_CONNECT_TIMEOUT, OPT_DELAYED_INSERT_TIMEOUT,
16456 -+ OPT_DELAYED_INSERT_LIMIT, OPT_DELAYED_QUEUE_SIZE,
16457 -+ OPT_FLUSH_TIME, OPT_FT_MIN_WORD_LEN, OPT_FT_BOOLEAN_SYNTAX,
16458 -+ OPT_FT_MAX_WORD_LEN, OPT_FT_QUERY_EXPANSION_LIMIT, OPT_FT_STOPWORD_FILE,
16459 -+ OPT_INTERACTIVE_TIMEOUT, OPT_JOIN_BUFF_SIZE,
16460 -+ OPT_KEY_BUFFER_SIZE, OPT_KEY_CACHE_BLOCK_SIZE,
16461 -+ OPT_KEY_CACHE_DIVISION_LIMIT, OPT_KEY_CACHE_AGE_THRESHOLD,
16462 -+ OPT_LONG_QUERY_TIME,
16463 -+ OPT_LOWER_CASE_TABLE_NAMES, OPT_MAX_ALLOWED_PACKET,
16464 -+ OPT_MAX_BINLOG_CACHE_SIZE, OPT_MAX_BINLOG_SIZE,
16465 -+ OPT_MAX_CONNECTIONS, OPT_MAX_CONNECT_ERRORS,
16466 -+ OPT_MAX_DELAYED_THREADS, OPT_MAX_HEP_TABLE_SIZE,
16467 -+ OPT_MAX_JOIN_SIZE, OPT_MAX_PREPARED_STMT_COUNT,
16468 -+ OPT_MAX_RELAY_LOG_SIZE, OPT_MAX_SORT_LENGTH,
16469 -+ OPT_MAX_SEEKS_FOR_KEY, OPT_MAX_TMP_TABLES, OPT_MAX_USER_CONNECTIONS,
16470 -+ OPT_MAX_LENGTH_FOR_SORT_DATA,
16471 -+ OPT_MAX_WRITE_LOCK_COUNT, OPT_BULK_INSERT_BUFFER_SIZE,
16472 -+ OPT_MAX_ERROR_COUNT, OPT_MULTI_RANGE_COUNT, OPT_MYISAM_DATA_POINTER_SIZE,
16473 -+ OPT_MYISAM_BLOCK_SIZE, OPT_MYISAM_MAX_EXTRA_SORT_FILE_SIZE,
16474 -+ OPT_MYISAM_MAX_SORT_FILE_SIZE, OPT_MYISAM_SORT_BUFFER_SIZE,
16475 -+ OPT_MYISAM_USE_MMAP, OPT_MYISAM_REPAIR_THREADS,
16476 -+ OPT_MYISAM_MMAP_SIZE,
16477 -+ OPT_MYISAM_STATS_METHOD,
16478 -+ OPT_NET_BUFFER_LENGTH, OPT_NET_RETRY_COUNT,
16479 -+ OPT_NET_READ_TIMEOUT, OPT_NET_WRITE_TIMEOUT,
16480 -+ OPT_OPEN_FILES_LIMIT,
16481 -+ OPT_PRELOAD_BUFFER_SIZE,
16482 -+ OPT_QUERY_CACHE_LIMIT, OPT_QUERY_CACHE_MIN_RES_UNIT, OPT_QUERY_CACHE_SIZE,
16483 -+ OPT_QUERY_CACHE_TYPE, OPT_QUERY_CACHE_WLOCK_INVALIDATE, OPT_RECORD_BUFFER,
16484 -+ OPT_RECORD_RND_BUFFER, OPT_DIV_PRECINCREMENT, OPT_RELAY_LOG_SPACE_LIMIT,
16485 -+ OPT_RELAY_LOG_PURGE,
16486 -+ OPT_SLAVE_NET_TIMEOUT, OPT_SLAVE_COMPRESSED_PROTOCOL, OPT_SLOW_LAUNCH_TIME,
16487 -+ OPT_SLAVE_TRANS_RETRIES, OPT_READONLY, OPT_DEBUGGING,
16488 -+ OPT_SORT_BUFFER, OPT_TABLE_OPEN_CACHE, OPT_TABLE_DEF_CACHE,
16489 -+ OPT_THREAD_CONCURRENCY, OPT_THREAD_CACHE_SIZE,
16490 -+ OPT_TMP_TABLE_SIZE, OPT_THREAD_STACK,
16491 -+ OPT_WAIT_TIMEOUT,
16492 -+ OPT_ERROR_LOG_FILE,
16493 -+ OPT_DEFAULT_WEEK_FORMAT,
16494 -+ OPT_RANGE_ALLOC_BLOCK_SIZE, OPT_ALLOW_SUSPICIOUS_UDFS,
16495 -+ OPT_QUERY_ALLOC_BLOCK_SIZE, OPT_QUERY_PREALLOC_SIZE,
16496 -+ OPT_TRANS_ALLOC_BLOCK_SIZE, OPT_TRANS_PREALLOC_SIZE,
16497 -+ OPT_SYNC_FRM, OPT_SYNC_BINLOG,
16498 -+ OPT_SYNC_REPLICATION,
16499 -+ OPT_SYNC_REPLICATION_SLAVE_ID,
16500 -+ OPT_SYNC_REPLICATION_TIMEOUT,
16501 -+ OPT_ENABLE_SHARED_MEMORY,
16502 -+ OPT_SHARED_MEMORY_BASE_NAME,
16503 -+ OPT_OLD_PASSWORDS,
16504 -+ OPT_OLD_ALTER_TABLE,
16505 -+ OPT_EXPIRE_LOGS_DAYS,
16506 -+ OPT_GROUP_CONCAT_MAX_LEN,
16507 -+ OPT_DEFAULT_COLLATION,
16508 -+ OPT_DEFAULT_COLLATION_OLD,
16509 -+ OPT_CHARACTER_SET_CLIENT_HANDSHAKE,
16510 -+ OPT_CHARACTER_SET_FILESYSTEM,
16511 -+ OPT_LC_TIME_NAMES,
16512 -+ OPT_INIT_CONNECT,
16513 -+ OPT_INIT_SLAVE,
16514 -+ OPT_SECURE_AUTH,
16515 -+ OPT_DATE_FORMAT,
16516 -+ OPT_TIME_FORMAT,
16517 -+ OPT_DATETIME_FORMAT,
16518 -+ OPT_LOG_QUERIES_NOT_USING_INDEXES,
16519 -+ OPT_DEFAULT_TIME_ZONE,
16520 -+ OPT_SYSDATE_IS_NOW,
16521 -+ OPT_OPTIMIZER_SEARCH_DEPTH,
16522 -+ OPT_OPTIMIZER_PRUNE_LEVEL,
16523 -+ OPT_OPTIMIZER_SWITCH,
16524 -+ OPT_UPDATABLE_VIEWS_WITH_LIMIT,
16525 -+ OPT_SP_AUTOMATIC_PRIVILEGES,
16526 -+ OPT_MAX_SP_RECURSION_DEPTH,
16527 -+ OPT_AUTO_INCREMENT, OPT_AUTO_INCREMENT_OFFSET,
16528 -+ OPT_ENABLE_LARGE_PAGES,
16529 -+ OPT_TIMED_MUTEXES,
16530 -+ OPT_OLD_STYLE_USER_LIMITS,
16531 -+ OPT_LOG_SLOW_ADMIN_STATEMENTS,
16532 -+ OPT_TABLE_LOCK_WAIT_TIMEOUT,
16533 -+ OPT_PLUGIN_LOAD,
16534 -+ OPT_PLUGIN_DIR,
16535 -+ OPT_SYMBOLIC_LINKS,
16536 -+ OPT_WARNINGS,
16537 -+ OPT_RECORD_BUFFER_OLD,
16538 -+ OPT_LOG_OUTPUT,
16539 -+ OPT_PORT_OPEN_TIMEOUT,
16540 -+ OPT_PROFILING,
16541 -+ OPT_KEEP_FILES_ON_CREATE,
16542 -+ OPT_GENERAL_LOG,
16543 -+ OPT_SLOW_LOG,
16544 -+ OPT_THREAD_HANDLING,
16545 -+ OPT_INNODB_ROLLBACK_ON_TIMEOUT,
16546 -+ OPT_SECURE_FILE_PRIV,
16547 -+ OPT_MIN_EXAMINED_ROW_LIMIT,
16548 -+ OPT_LOG_SLOW_SLAVE_STATEMENTS,
16549 -+#if defined(ENABLED_DEBUG_SYNC)
16550 -+ OPT_DEBUG_SYNC_TIMEOUT,
16551 -+#endif /* defined(ENABLED_DEBUG_SYNC) */
16552 -+ OPT_OLD_MODE,
16553 -+ OPT_SLAVE_EXEC_MODE,
16554 -+ OPT_GENERAL_LOG_FILE,
16555 -+ OPT_SLOW_QUERY_LOG_FILE,
16556 -+ OPT_IGNORE_BUILTIN_INNODB,
16557 -+ OPT_BINLOG_DIRECT_NON_TRANS_UPDATE,
16558 -+ OPT_DEFAULT_CHARACTER_SET_OLD,
16559 -+ OPT_MAX_LONG_DATA_SIZE
16560 -+};
16561 -+
16562 -+
16563 -+#define LONG_TIMEOUT ((ulong) 3600L*24L*365L)
16564 -+
16565 -+struct my_option my_long_options[] =
16566 -+{
16567 -+ {"help", '?', "Display this help and exit.",
16568 -+ &opt_help, &opt_help, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
16569 -+ 0, 0},
16570 -+#ifdef HAVE_REPLICATION
16571 -+ {"abort-slave-event-count", OPT_ABORT_SLAVE_EVENT_COUNT,
16572 -+ "Option used by mysql-test for debugging and testing of replication.",
16573 -+ &abort_slave_event_count, &abort_slave_event_count,
16574 -+ 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
16575 -+#endif /* HAVE_REPLICATION */
16576 -+ {"allow-suspicious-udfs", OPT_ALLOW_SUSPICIOUS_UDFS,
16577 -+ "Allows use of UDFs consisting of only one symbol xxx() "
16578 -+ "without corresponding xxx_init() or xxx_deinit(). That also means "
16579 -+ "that one can load any function from any library, for example exit() "
16580 -+ "from libc.so",
16581 -+ &opt_allow_suspicious_udfs, &opt_allow_suspicious_udfs,
16582 -+ 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
16583 -+ {"ansi", 'a', "Use ANSI SQL syntax instead of MySQL syntax. This mode "
16584 -+ "will also set transaction isolation level 'serializable'.", 0, 0, 0,
16585 -+ GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
16586 -+ {"auto-increment-increment", OPT_AUTO_INCREMENT,
16587 -+ "Auto-increment columns are incremented by this.",
16588 -+ &global_system_variables.auto_increment_increment,
16589 -+ &max_system_variables.auto_increment_increment, 0, GET_ULONG,
16590 -+ OPT_ARG, 1, 1, 65535, 0, 1, 0 },
16591 -+ {"auto-increment-offset", OPT_AUTO_INCREMENT_OFFSET,
16592 -+ "Offset added to Auto-increment columns. Used when auto-increment-increment != 1.",
16593 -+ &global_system_variables.auto_increment_offset,
16594 -+ &max_system_variables.auto_increment_offset, 0, GET_ULONG, OPT_ARG,
16595 -+ 1, 1, 65535, 0, 1, 0 },
16596 -+ {"automatic-sp-privileges", OPT_SP_AUTOMATIC_PRIVILEGES,
16597 -+ "Creating and dropping stored procedures alters ACLs. Disable with --skip-automatic-sp-privileges.",
16598 -+ &sp_automatic_privileges, &sp_automatic_privileges,
16599 -+ 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
16600 -+ {"basedir", 'b',
16601 -+ "Path to installation directory. All paths are usually resolved relative to this.",
16602 -+ &mysql_home_ptr, &mysql_home_ptr, 0, GET_STR, REQUIRED_ARG,
16603 -+ 0, 0, 0, 0, 0, 0},
16604 -+ {"big-tables", OPT_BIG_TABLES,
16605 -+ "Allow big result sets by saving all temporary sets on file (solves most 'table full' errors).",
16606 -+ 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
16607 -+ {"bind-address", OPT_BIND_ADDRESS, "IP address to bind to.",
16608 -+ &my_bind_addr_str, &my_bind_addr_str, 0, GET_STR,
16609 -+ REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
16610 -+ {"binlog_format", OPT_BINLOG_FORMAT,
16611 -+ "Does not have any effect without '--log-bin'. "
16612 -+ "Tell the master the form of binary logging to use: either 'row' for "
16613 -+ "row-based binary logging, 'statement' for statement-based binary "
16614 -+ "logging, or 'mixed'. 'mixed' is statement-based binary logging except "
16615 -+ "for statements where only row-based is correct: Statements that involve "
16616 -+ "user-defined functions (i.e., UDFs) or the UUID() function."
16617 -+#ifdef HAVE_NDB_BINLOG
16618 -+ "If ndbcluster is enabled and binlog_format is `mixed', the format switches"
16619 -+ " to 'row' and back implicitly per each query accessing a NDB table."
16620 -+#endif
16621 -+ , &opt_binlog_format, &opt_binlog_format,
16622 -+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
16623 -+ {"binlog-do-db", OPT_BINLOG_DO_DB,
16624 -+ "Tells the master it should log updates for the specified database, "
16625 -+ "and exclude all others not explicitly mentioned.",
16626 -+ 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
16627 -+ {"binlog-ignore-db", OPT_BINLOG_IGNORE_DB,
16628 -+ "Tells the master that updates to the given database should not be logged to the binary log.",
16629 -+ 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
16630 -+ {"binlog-row-event-max-size", OPT_BINLOG_ROWS_EVENT_MAX_SIZE,
16631 -+ "The maximum size of a row-based binary log event in bytes. Rows will be "
16632 -+ "grouped into events smaller than this size if possible. "
16633 -+ "The value has to be a multiple of 256.",
16634 -+ &opt_binlog_rows_event_max_size, &opt_binlog_rows_event_max_size,
16635 -+ 0, GET_ULONG, REQUIRED_ARG,
16636 -+ /* def_value */ 1024, /* min_value */ 256, /* max_value */ ULONG_MAX,
16637 -+ /* sub_size */ 0, /* block_size */ 256,
16638 -+ /* app_type */ 0
16639 -+ },
16640 -+#ifndef DISABLE_GRANT_OPTIONS
16641 -+ {"bootstrap", OPT_BOOTSTRAP, "Used by mysql installation scripts.", 0, 0, 0,
16642 -+ GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
16643 -+#endif
16644 -+ {"character-set-client-handshake", OPT_CHARACTER_SET_CLIENT_HANDSHAKE,
16645 -+ "Don't ignore client side character set value sent during handshake.",
16646 -+ &opt_character_set_client_handshake,
16647 -+ &opt_character_set_client_handshake,
16648 -+ 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
16649 -+ {"character-set-filesystem", OPT_CHARACTER_SET_FILESYSTEM,
16650 -+ "Set the filesystem character set.",
16651 -+ &character_set_filesystem_name,
16652 -+ &character_set_filesystem_name,
16653 -+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
16654 -+ {"character-set-server", 'C', "Set the default character set.",
16655 -+ &default_character_set_name, &default_character_set_name,
16656 -+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
16657 -+ {"character-sets-dir", OPT_CHARSETS_DIR,
16658 -+ "Directory where character sets are.", &charsets_dir,
16659 -+ &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
16660 -+ {"chroot", 'r', "Chroot mysqld daemon during startup.",
16661 -+ &mysqld_chroot, &mysqld_chroot, 0, GET_STR, REQUIRED_ARG,
16662 -+ 0, 0, 0, 0, 0, 0},
16663 -+ {"collation-server", OPT_DEFAULT_COLLATION, "Set the default collation.",
16664 -+ &default_collation_name, &default_collation_name,
16665 -+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
16666 -+ {"completion-type", OPT_COMPLETION_TYPE, "Default completion type.",
16667 -+ &global_system_variables.completion_type,
16668 -+ &max_system_variables.completion_type, 0, GET_ULONG,
16669 -+ REQUIRED_ARG, 0, 0, 2, 0, 1, 0},
16670 -+ {"concurrent-insert", OPT_CONCURRENT_INSERT,
16671 -+ "Use concurrent insert with MyISAM. Disable with --concurrent-insert=0.",
16672 -+ &myisam_concurrent_insert, &myisam_concurrent_insert,
16673 -+ 0, GET_ULONG, OPT_ARG, 1, 0, 2, 0, 0, 0},
16674 -+ {"console", OPT_CONSOLE, "Write error output on screen; don't remove the console window on windows.",
16675 -+ &opt_console, &opt_console, 0, GET_BOOL, NO_ARG, 0, 0, 0,
16676 -+ 0, 0, 0},
16677 -+ {"core-file", OPT_WANT_CORE, "Write core on errors.", 0, 0, 0, GET_NO_ARG,
16678 -+ NO_ARG, 0, 0, 0, 0, 0, 0},
16679 -+ {"datadir", 'h', "Path to the database root.", &mysql_data_home,
16680 -+ &mysql_data_home, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
16681 -+#ifndef DBUG_OFF
16682 -+ {"debug", '#', "Debug log.", &default_dbug_option,
16683 -+ &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
16684 -+#endif
16685 -+ {"default-character-set", OPT_DEFAULT_CHARACTER_SET_OLD,
16686 -+ "Set the default character set (deprecated option, use --character-set-server instead).",
16687 -+ &default_character_set_name, &default_character_set_name,
16688 -+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
16689 -+ {"default-collation", OPT_DEFAULT_COLLATION_OLD, "Set the default collation "
16690 -+ "(deprecated option, use --collation-server instead).",
16691 -+ &default_collation_name, &default_collation_name,
16692 -+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
16693 -+ {"default-storage-engine", OPT_STORAGE_ENGINE,
16694 -+ "Set the default storage engine (table type) for tables.",
16695 -+ &default_storage_engine_str, &default_storage_engine_str,
16696 -+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
16697 -+ {"default-table-type", OPT_STORAGE_ENGINE,
16698 -+ "(deprecated) Use --default-storage-engine.",
16699 -+ &default_storage_engine_str, &default_storage_engine_str,
16700 -+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
16701 -+ {"default-time-zone", OPT_DEFAULT_TIME_ZONE, "Set the default time zone.",
16702 -+ &default_tz_name, &default_tz_name,
16703 -+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
16704 -+ {"delay-key-write", OPT_DELAY_KEY_WRITE, "Type of DELAY_KEY_WRITE.",
16705 -+ 0,0,0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
16706 -+ {"delay-key-write-for-all-tables", OPT_DELAY_KEY_WRITE_ALL,
16707 -+ "Don't flush key buffers between writes for any MyISAM table. "
16708 -+ "(Deprecated option, use --delay-key-write=all instead.)",
16709 -+ 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
16710 -+#ifdef HAVE_OPENSSL
16711 -+ {"des-key-file", OPT_DES_KEY_FILE,
16712 -+ "Load keys for des_encrypt() and des_encrypt from given file.",
16713 -+ &des_key_file, &des_key_file, 0, GET_STR, REQUIRED_ARG,
16714 -+ 0, 0, 0, 0, 0, 0},
16715 -+#endif /* HAVE_OPENSSL */
16716 -+#ifdef HAVE_REPLICATION
16717 -+ {"disconnect-slave-event-count", OPT_DISCONNECT_SLAVE_EVENT_COUNT,
16718 -+ "Option used by mysql-test for debugging and testing of replication.",
16719 -+ &disconnect_slave_event_count, &disconnect_slave_event_count,
16720 -+ 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
16721 -+#endif /* HAVE_REPLICATION */
16722 -+ {"enable-locking", OPT_ENABLE_LOCK,
16723 -+ "Deprecated option, use --external-locking instead.",
16724 -+ &opt_external_locking, &opt_external_locking,
16725 -+ 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
16726 -+#ifdef __NT__
16727 -+ {"enable-named-pipe", OPT_HAVE_NAMED_PIPE, "Enable the named pipe (NT).",
16728 -+ &opt_enable_named_pipe, &opt_enable_named_pipe, 0, GET_BOOL,
16729 -+ NO_ARG, 0, 0, 0, 0, 0, 0},
16730 -+#endif
16731 -+#ifdef HAVE_STACK_TRACE_ON_SEGV
16732 -+ {"enable-pstack", OPT_DO_PSTACK, "Print a symbolic stack trace on failure. "
16733 -+ "This option is deprecated and has no effect; a symbolic stack trace will "
16734 -+ "be printed after a crash whenever possible.", &opt_do_pstack, &opt_do_pstack,
16735 -+ 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
16736 -+#endif /* HAVE_STACK_TRACE_ON_SEGV */
16737 -+ {"engine-condition-pushdown",
16738 -+ OPT_ENGINE_CONDITION_PUSHDOWN,
16739 -+ "Push supported query conditions to the storage engine.",
16740 -+ &global_system_variables.engine_condition_pushdown,
16741 -+ &global_system_variables.engine_condition_pushdown,
16742 -+ 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
16743 -+ /* See how it's handled in get_one_option() */
16744 -+ {"event-scheduler", OPT_EVENT_SCHEDULER, "Enable/disable the event scheduler.",
16745 -+ NULL, NULL, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
16746 -+ {"exit-info", 'T', "Used for debugging. Use at your own risk.", 0, 0, 0,
16747 -+ GET_LONG, OPT_ARG, 0, 0, 0, 0, 0, 0},
16748 -+ {"external-locking", OPT_USE_LOCKING, "Use system (external) locking "
16749 -+ "(disabled by default). With this option enabled you can run myisamchk "
16750 -+ "to test (not repair) tables while the MySQL server is running. "
16751 -+ "Disable with --skip-external-locking.",
16752 -+ &opt_external_locking, &opt_external_locking,
16753 -+ 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
16754 -+ {"flush", OPT_FLUSH, "Flush tables to disk between SQL commands.", 0, 0, 0,
16755 -+ GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
16756 -+ /* We must always support the next option to make scripts like mysqltest
16757 -+ easier to do */
16758 -+ {"gdb", OPT_DEBUGGING,
16759 -+ "Set up signals usable for debugging.",
16760 -+ &opt_debugging, &opt_debugging,
16761 -+ 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
16762 -+ {"general_log", OPT_GENERAL_LOG,
16763 -+ "Enable/disable general log.", &opt_log,
16764 -+ &opt_log, 0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0},
16765 -+#ifdef HAVE_LARGE_PAGES
16766 -+ {"large-pages", OPT_ENABLE_LARGE_PAGES, "Enable support for large pages. "
16767 -+ "Disable with --skip-large-pages.", &opt_large_pages, &opt_large_pages,
16768 -+ 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
16769 -+#endif
16770 -+ {"ignore-builtin-innodb", OPT_IGNORE_BUILTIN_INNODB ,
16771 -+ "Disable initialization of builtin InnoDB plugin.",
16772 -+ 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
16773 -+ {"init-connect", OPT_INIT_CONNECT,
16774 -+ "Command(s) that are executed for each new connection.",
16775 -+ &opt_init_connect, &opt_init_connect, 0, GET_STR_ALLOC,
16776 -+ REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
16777 -+#ifndef DISABLE_GRANT_OPTIONS
16778 -+ {"init-file", OPT_INIT_FILE, "Read SQL commands from this file at startup.",
16779 -+ &opt_init_file, &opt_init_file, 0, GET_STR, REQUIRED_ARG,
16780 -+ 0, 0, 0, 0, 0, 0},
16781 -+#endif
16782 -+ {"init-rpl-role", OPT_INIT_RPL_ROLE, "Set the replication role.", 0, 0, 0,
16783 -+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
16784 -+ {"init-slave", OPT_INIT_SLAVE, "Command(s) that are executed by a slave server \
16785 -+each time the SQL thread starts.",
16786 -+ &opt_init_slave, &opt_init_slave, 0, GET_STR_ALLOC,
16787 -+ REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
16788 -+ {"language", 'L',
16789 -+ "Client error messages in given language. May be given as a full path.",
16790 -+ &language_ptr, &language_ptr, 0, GET_STR, REQUIRED_ARG,
16791 -+ 0, 0, 0, 0, 0, 0},
16792 -+ {"lc-time-names", OPT_LC_TIME_NAMES,
16793 -+ "Set the language used for the month names and the days of the week.",
16794 -+ &lc_time_names_name, &lc_time_names_name,
16795 -+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
16796 -+ {"local-infile", OPT_LOCAL_INFILE,
16797 -+ "Enable/disable LOAD DATA LOCAL INFILE (takes values 1 or 0).",
16798 -+ &opt_local_infile, &opt_local_infile, 0, GET_BOOL, OPT_ARG,
16799 -+ 1, 0, 0, 0, 0, 0},
16800 -+ {"log", 'l', "Log connections and queries to file (deprecated option, use "
16801 -+ "--general_log/--general_log_file instead).", &opt_logname,
16802 -+ &opt_logname, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
16803 -+ {"general_log_file", OPT_GENERAL_LOG_FILE,
16804 -+ "Log connections and queries to given file.", &opt_logname,
16805 -+ &opt_logname, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
16806 -+ {"log-bin", OPT_BIN_LOG,
16807 -+ "Log update queries in binary format. Optional (but strongly recommended "
16808 -+ "to avoid replication problems if server's hostname changes) argument "
16809 -+ "should be the chosen location for the binary log files.",
16810 -+ &opt_bin_logname, &opt_bin_logname, 0, GET_STR_ALLOC,
16811 -+ OPT_ARG, 0, 0, 0, 0, 0, 0},
16812 -+ {"log-bin-index", OPT_BIN_LOG_INDEX,
16813 -+ "File that holds the names for last binary log files.",
16814 -+ &opt_binlog_index_name, &opt_binlog_index_name, 0, GET_STR,
16815 -+ REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
16816 -+#ifndef TO_BE_REMOVED_IN_5_1_OR_6_0
16817 -+ /*
16818 -+ In 5.0.6 we introduced the below option, then in 5.0.16 we renamed it to
16819 -+ log-bin-trust-function-creators but kept also the old name for
16820 -+ compatibility; the behaviour was also changed to apply only to functions
16821 -+ (and triggers). In a future release this old name could be removed.
16822 -+ */
16823 -+ {"log-bin-trust-routine-creators", OPT_LOG_BIN_TRUST_FUNCTION_CREATORS_OLD,
16824 -+ "(deprecated) Use log-bin-trust-function-creators.",
16825 -+ &trust_function_creators, &trust_function_creators, 0,
16826 -+ GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
16827 -+#endif
16828 -+ /*
16829 -+ This option starts with "log-bin" to emphasize that it is specific of
16830 -+ binary logging.
16831 -+ */
16832 -+ {"log-bin-trust-function-creators", OPT_LOG_BIN_TRUST_FUNCTION_CREATORS,
16833 -+ "If equal to 0 (the default), then when --log-bin is used, creation of "
16834 -+ "a stored function (or trigger) is allowed only to users having the SUPER "
16835 -+ "privilege, and only if this stored function (trigger) may not break "
16836 -+ "binary logging."
16837 -+ "Note that if ALL connections to this server ALWAYS use row-based binary "
16838 -+ "logging, the security issues do not exist and the binary logging cannot "
16839 -+ "break, so you can safely set this to 1."
16840 -+ ,&trust_function_creators, &trust_function_creators, 0,
16841 -+ GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
16842 -+ {"log-error", OPT_ERROR_LOG_FILE, "Error log file.",
16843 -+ &log_error_file_ptr, &log_error_file_ptr, 0, GET_STR,
16844 -+ OPT_ARG, 0, 0, 0, 0, 0, 0},
16845 -+ {"log-isam", OPT_ISAM_LOG, "Log all MyISAM changes to file.",
16846 -+ &myisam_log_filename, &myisam_log_filename, 0, GET_STR,
16847 -+ OPT_ARG, 0, 0, 0, 0, 0, 0},
16848 -+ {"log-long-format", '0',
16849 -+ "Log some extra information to update log. Please note that this option "
16850 -+ "is deprecated; see --log-short-format option.",
16851 -+ 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
16852 -+#ifdef WITH_CSV_STORAGE_ENGINE
16853 -+ {"log-output", OPT_LOG_OUTPUT,
16854 -+ "Syntax: log-output[=value[,value...]], where \"value\" could be TABLE, "
16855 -+ "FILE or NONE.",
16856 -+ &log_output_str, &log_output_str, 0,
16857 -+ GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
16858 -+#endif
16859 -+ {"log-queries-not-using-indexes", OPT_LOG_QUERIES_NOT_USING_INDEXES,
16860 -+ "Log queries that are executed without benefit of any index to the slow log if it is open.",
16861 -+ &opt_log_queries_not_using_indexes, &opt_log_queries_not_using_indexes,
16862 -+ 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
16863 -+ {"log-short-format", OPT_SHORT_LOG_FORMAT,
16864 -+ "Don't log extra information to update and slow-query logs.",
16865 -+ &opt_short_log_format, &opt_short_log_format,
16866 -+ 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
16867 -+ {"log-slave-updates", OPT_LOG_SLAVE_UPDATES,
16868 -+ "Tells the slave to log the updates from the slave thread to the binary log. "
16869 -+ "You will need to turn it on if you plan to daisy-chain the slaves.",
16870 -+ &opt_log_slave_updates, &opt_log_slave_updates, 0, GET_BOOL,
16871 -+ NO_ARG, 0, 0, 0, 0, 0, 0},
16872 -+ {"log-slow-admin-statements", OPT_LOG_SLOW_ADMIN_STATEMENTS,
16873 -+ "Log slow OPTIMIZE, ANALYZE, ALTER and other administrative statements "
16874 -+ "to the slow log if it is open.", &opt_log_slow_admin_statements,
16875 -+ &opt_log_slow_admin_statements, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
16876 -+ {"log-slow-slave-statements", OPT_LOG_SLOW_SLAVE_STATEMENTS,
16877 -+ "Log slow statements executed by slave thread to the slow log if it is open.",
16878 -+ &opt_log_slow_slave_statements,
16879 -+ &opt_log_slow_slave_statements,
16880 -+ 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
16881 -+ {"log_slow_queries", OPT_SLOW_QUERY_LOG,
16882 -+ "Log slow queries to a table or log file. Defaults logging to table "
16883 -+ "mysql.slow_log or hostname-slow.log if --log-output=file is used. "
16884 -+ "Must be enabled to activate other slow log options. "
16885 -+ "(deprecated option, use --slow_query_log/--slow_query_log_file instead)",
16886 -+ &opt_slow_logname, &opt_slow_logname, 0, GET_STR, OPT_ARG,
16887 -+ 0, 0, 0, 0, 0, 0},
16888 -+ {"slow_query_log_file", OPT_SLOW_QUERY_LOG_FILE,
16889 -+ "Log slow queries to given log file. Defaults logging to hostname-slow.log. "
16890 -+ "Must be enabled to activate other slow log options.",
16891 -+ &opt_slow_logname, &opt_slow_logname, 0, GET_STR,
16892 -+ REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
16893 -+ {"log-tc", OPT_LOG_TC,
16894 -+ "Path to transaction coordinator log (used for transactions that affect "
16895 -+ "more than one storage engine, when binary log is disabled).",
16896 -+ &opt_tc_log_file, &opt_tc_log_file, 0, GET_STR,
16897 -+ REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
16898 -+#ifdef HAVE_MMAP
16899 -+ {"log-tc-size", OPT_LOG_TC_SIZE, "Size of transaction coordinator log.",
16900 -+ &opt_tc_log_size, &opt_tc_log_size, 0, GET_ULONG,
16901 -+ REQUIRED_ARG, TC_LOG_MIN_SIZE, TC_LOG_MIN_SIZE, ULONG_MAX, 0,
16902 -+ TC_LOG_PAGE_SIZE, 0},
16903 -+#endif
16904 -+ {"log-update", OPT_UPDATE_LOG,
16905 -+ "The update log is deprecated since version 5.0, is replaced by the binary "
16906 -+ "log and this option just turns on --log-bin instead.",
16907 -+ &opt_update_logname, &opt_update_logname, 0, GET_STR,
16908 -+ OPT_ARG, 0, 0, 0, 0, 0, 0},
16909 -+ {"log-warnings", 'W', "Log some not critical warnings to the log file.",
16910 -+ &global_system_variables.log_warnings,
16911 -+ &max_system_variables.log_warnings, 0, GET_ULONG, OPT_ARG, 1, 0, 0,
16912 -+ 0, 0, 0},
16913 -+ {"low-priority-updates", OPT_LOW_PRIORITY_UPDATES,
16914 -+ "INSERT/DELETE/UPDATE has lower priority than selects.",
16915 -+ &global_system_variables.low_priority_updates,
16916 -+ &max_system_variables.low_priority_updates,
16917 -+ 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
16918 -+ {"master-connect-retry", OPT_MASTER_CONNECT_RETRY,
16919 -+ "The number of seconds the slave thread will sleep before retrying to "
16920 -+ "connect to the master, in case the master goes down or the connection "
16921 -+ "is lost.",
16922 -+ &master_connect_retry, &master_connect_retry, 0, GET_UINT,
16923 -+ REQUIRED_ARG, 60, 0, 0, 0, 0, 0},
16924 -+ {"master-host", OPT_MASTER_HOST,
16925 -+ "Master hostname or IP address for replication. If not set, the slave "
16926 -+ "thread will not be started. Note that the setting of master-host will "
16927 -+ "be ignored if there exists a valid master.info file.",
16928 -+ &master_host, &master_host, 0, GET_STR, REQUIRED_ARG, 0, 0,
16929 -+ 0, 0, 0, 0},
16930 -+ {"master-info-file", OPT_MASTER_INFO_FILE,
16931 -+ "The location and name of the file that remembers the master and where "
16932 -+ "the I/O replication thread is in the master's binlogs.",
16933 -+ &master_info_file, &master_info_file, 0, GET_STR,
16934 -+ REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
16935 -+ {"master-password", OPT_MASTER_PASSWORD,
16936 -+ "The password the slave thread will authenticate with when connecting to "
16937 -+ "the master. If not set, an empty password is assumed. The value in "
16938 -+ "master.info will take precedence if it can be read.",
16939 -+ &master_password, &master_password, 0,
16940 -+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
16941 -+ {"master-port", OPT_MASTER_PORT,
16942 -+ "The port the master is listening on. If not set, the compiled setting of "
16943 -+ "MYSQL_PORT is assumed. If you have not tinkered with configure options, "
16944 -+ "this should be 3306. The value in master.info will take precedence if it "
16945 -+ "can be read.", &master_port, &master_port, 0, GET_UINT, REQUIRED_ARG,
16946 -+ MYSQL_PORT, 0, 0, 0, 0, 0},
16947 -+ {"master-retry-count", OPT_MASTER_RETRY_COUNT,
16948 -+ "The number of tries the slave will make to connect to the master before giving up.",
16949 -+ &master_retry_count, &master_retry_count, 0, GET_ULONG,
16950 -+ REQUIRED_ARG, 3600*24, 0, 0, 0, 0, 0},
16951 -+ {"master-ssl", OPT_MASTER_SSL,
16952 -+ "Enable the slave to connect to the master using SSL.",
16953 -+ &master_ssl, &master_ssl, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
16954 -+ 0, 0},
16955 -+ {"master-ssl-ca", OPT_MASTER_SSL_CA,
16956 -+ "Master SSL CA file. Only applies if you have enabled master-ssl.",
16957 -+ &master_ssl_ca, &master_ssl_ca, 0, GET_STR, OPT_ARG,
16958 -+ 0, 0, 0, 0, 0, 0},
16959 -+ {"master-ssl-capath", OPT_MASTER_SSL_CAPATH,
16960 -+ "Master SSL CA path. Only applies if you have enabled master-ssl.",
16961 -+ &master_ssl_capath, &master_ssl_capath, 0, GET_STR, OPT_ARG,
16962 -+ 0, 0, 0, 0, 0, 0},
16963 -+ {"master-ssl-cert", OPT_MASTER_SSL_CERT,
16964 -+ "Master SSL certificate file name. Only applies if you have enabled "
16965 -+ "master-ssl.",
16966 -+ &master_ssl_cert, &master_ssl_cert, 0, GET_STR, OPT_ARG,
16967 -+ 0, 0, 0, 0, 0, 0},
16968 -+ {"master-ssl-cipher", OPT_MASTER_SSL_CIPHER,
16969 -+ "Master SSL cipher. Only applies if you have enabled master-ssl.",
16970 -+ &master_ssl_cipher, &master_ssl_capath, 0, GET_STR, OPT_ARG,
16971 -+ 0, 0, 0, 0, 0, 0},
16972 -+ {"master-ssl-key", OPT_MASTER_SSL_KEY,
16973 -+ "Master SSL keyfile name. Only applies if you have enabled master-ssl.",
16974 -+ &master_ssl_key, &master_ssl_key, 0, GET_STR, OPT_ARG,
16975 -+ 0, 0, 0, 0, 0, 0},
16976 -+ {"master-user", OPT_MASTER_USER,
16977 -+ "The username the slave thread will use for authentication when "
16978 -+ "connecting to the master. The user must have FILE privilege. "
16979 -+ "If the master user is not set, user test is assumed. The value "
16980 -+ "in master.info will take precedence if it can be read.",
16981 -+ &master_user, &master_user, 0, GET_STR, REQUIRED_ARG, 0, 0,
16982 -+ 0, 0, 0, 0},
16983 -+#ifdef HAVE_REPLICATION
16984 -+ {"max-binlog-dump-events", OPT_MAX_BINLOG_DUMP_EVENTS,
16985 -+ "Option used by mysql-test for debugging and testing of replication.",
16986 -+ &max_binlog_dump_events, &max_binlog_dump_events, 0,
16987 -+ GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
16988 -+#endif /* HAVE_REPLICATION */
16989 -+ {"memlock", OPT_MEMLOCK, "Lock mysqld in memory.", &locked_in_memory,
16990 -+ &locked_in_memory, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
16991 -+ {"myisam-recover", OPT_MYISAM_RECOVER,
16992 -+ "Syntax: myisam-recover[=option[,option...]], where option can be DEFAULT, BACKUP, FORCE or QUICK.",
16993 -+ &myisam_recover_options_str, &myisam_recover_options_str, 0,
16994 -+ GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
16995 -+#ifdef WITH_NDBCLUSTER_STORAGE_ENGINE
16996 -+ {"ndb-connectstring", OPT_NDB_CONNECTSTRING,
16997 -+ "Connect string for ndbcluster.",
16998 -+ &opt_ndb_connectstring, &opt_ndb_connectstring,
16999 -+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
17000 -+ {"ndb-mgmd-host", OPT_NDB_MGMD,
17001 -+ "Set host and port for ndb_mgmd. Syntax: hostname[:port]",
17002 -+ &opt_ndb_mgmd, &opt_ndb_mgmd,
17003 -+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
17004 -+ {"ndb-nodeid", OPT_NDB_NODEID,
17005 -+ "Nodeid for this mysqlserver in the cluster.",
17006 -+ &opt_ndb_nodeid,
17007 -+ &opt_ndb_nodeid,
17008 -+ 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
17009 -+ {"ndb-autoincrement-prefetch-sz", OPT_NDB_AUTOINCREMENT_PREFETCH_SZ,
17010 -+ "Specify number of autoincrement values that are prefetched.",
17011 -+ &global_system_variables.ndb_autoincrement_prefetch_sz,
17012 -+ &max_system_variables.ndb_autoincrement_prefetch_sz,
17013 -+ 0, GET_ULONG, REQUIRED_ARG, 1, 1, 256, 0, 0, 0},
17014 -+ {"ndb-force-send", OPT_NDB_FORCE_SEND,
17015 -+ "Force send of buffers to ndb immediately without waiting for "
17016 -+ "other threads.",
17017 -+ &global_system_variables.ndb_force_send,
17018 -+ &global_system_variables.ndb_force_send,
17019 -+ 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0},
17020 -+ {"ndb_force_send", OPT_NDB_FORCE_SEND,
17021 -+ "same as --ndb-force-send.",
17022 -+ &global_system_variables.ndb_force_send,
17023 -+ &global_system_variables.ndb_force_send,
17024 -+ 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0},
17025 -+ {"ndb-extra-logging", OPT_NDB_EXTRA_LOGGING,
17026 -+ "Turn on more logging in the error log.",
17027 -+ &ndb_extra_logging,
17028 -+ &ndb_extra_logging,
17029 -+ 0, GET_INT, OPT_ARG, 0, 0, 0, 0, 0, 0},
17030 -+#ifdef HAVE_NDB_BINLOG
17031 -+ {"ndb-report-thresh-binlog-epoch-slip", OPT_NDB_REPORT_THRESH_BINLOG_EPOCH_SLIP,
17032 -+ "Threshold on number of epochs to be behind before reporting binlog status. "
17033 -+ "E.g., 3 means that if the difference between what epoch has been received "
17034 -+ "from the storage nodes and what has been applied to the binlog is 3 or more, "
17035 -+ "a status message will be sent to the cluster log.",
17036 -+ &ndb_report_thresh_binlog_epoch_slip,
17037 -+ &ndb_report_thresh_binlog_epoch_slip,
17038 -+ 0, GET_ULONG, REQUIRED_ARG, 3, 0, 256, 0, 0, 0},
17039 -+ {"ndb-report-thresh-binlog-mem-usage", OPT_NDB_REPORT_THRESH_BINLOG_MEM_USAGE,
17040 -+ "Threshold on percentage of free memory before reporting binlog status. E.g., "
17041 -+ "10 means that if amount of available memory for receiving binlog data from "
17042 -+ "the storage nodes goes below 10%, "
17043 -+ "a status message will be sent to the cluster log.",
17044 -+ &ndb_report_thresh_binlog_mem_usage,
17045 -+ &ndb_report_thresh_binlog_mem_usage,
17046 -+ 0, GET_ULONG, REQUIRED_ARG, 10, 0, 100, 0, 0, 0},
17047 -+#endif
17048 -+ {"ndb-use-exact-count", OPT_NDB_USE_EXACT_COUNT,
17049 -+ "Use exact records count during query planning and for fast "
17050 -+ "select count(*), disable for faster queries.",
17051 -+ &global_system_variables.ndb_use_exact_count,
17052 -+ &global_system_variables.ndb_use_exact_count,
17053 -+ 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0},
17054 -+ {"ndb_use_exact_count", OPT_NDB_USE_EXACT_COUNT,
17055 -+ "Same as --ndb-use-exact-count.",
17056 -+ &global_system_variables.ndb_use_exact_count,
17057 -+ &global_system_variables.ndb_use_exact_count,
17058 -+ 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0},
17059 -+ {"ndb-use-transactions", OPT_NDB_USE_TRANSACTIONS,
17060 -+ "Use transactions for large inserts, if enabled then large "
17061 -+ "inserts will be split into several smaller transactions",
17062 -+ &global_system_variables.ndb_use_transactions,
17063 -+ &global_system_variables.ndb_use_transactions,
17064 -+ 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0},
17065 -+ {"ndb_use_transactions", OPT_NDB_USE_TRANSACTIONS,
17066 -+ "Same as --ndb-use-transactions.",
17067 -+ &global_system_variables.ndb_use_transactions,
17068 -+ &global_system_variables.ndb_use_transactions,
17069 -+ 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0},
17070 -+ {"ndb-shm", OPT_NDB_SHM,
17071 -+ "Use shared memory connections when available.",
17072 -+ &opt_ndb_shm, &opt_ndb_shm,
17073 -+ 0, GET_BOOL, OPT_ARG, OPT_NDB_SHM_DEFAULT, 0, 0, 0, 0, 0},
17074 -+ {"ndb-optimized-node-selection", OPT_NDB_OPTIMIZED_NODE_SELECTION,
17075 -+ "Select nodes for transactions in a more optimal way.",
17076 -+ &opt_ndb_optimized_node_selection,
17077 -+ &opt_ndb_optimized_node_selection,
17078 -+ 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0},
17079 -+ { "ndb-cache-check-time", OPT_NDB_CACHE_CHECK_TIME,
17080 -+ "A dedicated thread is created to, at the given milliseconds interval, "
17081 -+ "invalidate the query cache if another MySQL server in the cluster has "
17082 -+ "changed the data in the database.",
17083 -+ &opt_ndb_cache_check_time, &opt_ndb_cache_check_time, 0, GET_ULONG, REQUIRED_ARG,
17084 -+ 0, 0, LONG_TIMEOUT, 0, 1, 0},
17085 -+ {"ndb-index-stat-enable", OPT_NDB_INDEX_STAT_ENABLE,
17086 -+ "Use ndb index statistics in query optimization.",
17087 -+ &global_system_variables.ndb_index_stat_enable,
17088 -+ &max_system_variables.ndb_index_stat_enable,
17089 -+ 0, GET_BOOL, OPT_ARG, 0, 0, 1, 0, 0, 0},
17090 -+#endif
17091 -+ {"ndb-use-copying-alter-table",
17092 -+ OPT_NDB_USE_COPYING_ALTER_TABLE,
17093 -+ "Force ndbcluster to always copy tables at alter table "
17094 -+ "(should only be used if on-line alter table fails).",
17095 -+ &global_system_variables.ndb_use_copying_alter_table,
17096 -+ &global_system_variables.ndb_use_copying_alter_table,
17097 -+ 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
17098 -+ {"new", 'n', "Use very new, possibly 'unsafe', functions.",
17099 -+ &global_system_variables.new_mode,
17100 -+ &max_system_variables.new_mode,
17101 -+ 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
17102 -+#ifdef NOT_YET
17103 -+ {"no-mix-table-types", OPT_NO_MIX_TYPE,
17104 -+ "Don't allow commands that use two different table types.",
17105 -+ &opt_no_mix_types, &opt_no_mix_types, 0, GET_BOOL, NO_ARG,
17106 -+ 0, 0, 0, 0, 0, 0},
17107 -+#endif
17108 -+ {"old-alter-table", OPT_OLD_ALTER_TABLE,
17109 -+ "Use old, non-optimized alter table.",
17110 -+ &global_system_variables.old_alter_table,
17111 -+ &max_system_variables.old_alter_table, 0, GET_BOOL, NO_ARG,
17112 -+ 0, 0, 0, 0, 0, 0},
17113 -+ {"old-passwords", OPT_OLD_PASSWORDS, "Use old password "
17114 -+ "encryption method (needed for 4.0 and older clients).",
17115 -+ &global_system_variables.old_passwords,
17116 -+ &max_system_variables.old_passwords, 0, GET_BOOL, NO_ARG,
17117 -+ 0, 0, 0, 0, 0, 0},
17118 -+ {"one-thread", OPT_ONE_THREAD,
17119 -+ "(Deprecated): Only use one thread (for debugging under Linux). Use "
17120 -+ "thread-handling=no-threads instead.",
17121 -+ 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
17122 -+ {"old-style-user-limits", OPT_OLD_STYLE_USER_LIMITS,
17123 -+ "Enable old-style user limits (before 5.0.3, user resources were counted "
17124 -+ "per each user+host vs. per account).",
17125 -+ &opt_old_style_user_limits, &opt_old_style_user_limits,
17126 -+ 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
17127 -+ {"pid-file", OPT_PID_FILE, "Pid file used by safe_mysqld.",
17128 -+ &pidfile_name_ptr, &pidfile_name_ptr, 0, GET_STR,
17129 -+ REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
17130 -+ {"port", 'P', "Port number to use for connection or 0 for default to, in "
17131 -+ "order of preference, my.cnf, $MYSQL_TCP_PORT, "
17132 -+#if MYSQL_PORT_DEFAULT == 0
17133 -+ "/etc/services, "
17134 -+#endif
17135 -+ "built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").",
17136 -+ &mysqld_port,
17137 -+ &mysqld_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
17138 -+ {"port-open-timeout", OPT_PORT_OPEN_TIMEOUT,
17139 -+ "Maximum time in seconds to wait for the port to become free. "
17140 -+ "(Default: No wait).", &mysqld_port_timeout,
17141 -+ &mysqld_port_timeout, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
17142 -+#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
17143 -+ {"profiling_history_size", OPT_PROFILING, "Limit of query profiling memory.",
17144 -+ &global_system_variables.profiling_history_size,
17145 -+ &max_system_variables.profiling_history_size,
17146 -+ 0, GET_ULONG, REQUIRED_ARG, 15, 0, 100, 0, 0, 0},
17147 -+#endif
17148 -+ {"relay-log", OPT_RELAY_LOG,
17149 -+ "The location and name to use for relay logs.",
17150 -+ &opt_relay_logname, &opt_relay_logname, 0,
17151 -+ GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
17152 -+ {"relay-log-index", OPT_RELAY_LOG_INDEX,
17153 -+ "The location and name to use for the file that keeps a list of the last \
17154 -+relay logs.",
17155 -+ &opt_relaylog_index_name, &opt_relaylog_index_name, 0,
17156 -+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
17157 -+ {"relay-log-info-file", OPT_RELAY_LOG_INFO_FILE,
17158 -+ "The location and name of the file that remembers where the SQL replication \
17159 -+thread is in the relay logs.",
17160 -+ &relay_log_info_file, &relay_log_info_file, 0, GET_STR,
17161 -+ REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
17162 -+ {"replicate-do-db", OPT_REPLICATE_DO_DB,
17163 -+ "Tells the slave thread to restrict replication to the specified database. "
17164 -+ "To specify more than one database, use the directive multiple times, "
17165 -+ "once for each database. Note that this will only work if you do not use "
17166 -+ "cross-database queries such as UPDATE some_db.some_table SET foo='bar' "
17167 -+ "while having selected a different or no database. If you need cross "
17168 -+ "database updates to work, make sure you have 3.23.28 or later, and use "
17169 -+ "replicate-wild-do-table=db_name.%.",
17170 -+ 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
17171 -+ {"replicate-do-table", OPT_REPLICATE_DO_TABLE,
17172 -+ "Tells the slave thread to restrict replication to the specified table. "
17173 -+ "To specify more than one table, use the directive multiple times, once "
17174 -+ "for each table. This will work for cross-database updates, in contrast "
17175 -+ "to replicate-do-db.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
17176 -+ {"replicate-ignore-db", OPT_REPLICATE_IGNORE_DB,
17177 -+ "Tells the slave thread to not replicate to the specified database. To "
17178 -+ "specify more than one database to ignore, use the directive multiple "
17179 -+ "times, once for each database. This option will not work if you use "
17180 -+ "cross database updates. If you need cross database updates to work, "
17181 -+ "make sure you have 3.23.28 or later, and use replicate-wild-ignore-"
17182 -+ "table=db_name.%. ", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
17183 -+ {"replicate-ignore-table", OPT_REPLICATE_IGNORE_TABLE,
17184 -+ "Tells the slave thread to not replicate to the specified table. To specify "
17185 -+ "more than one table to ignore, use the directive multiple times, once for "
17186 -+ "each table. This will work for cross-database updates, in contrast to "
17187 -+ "replicate-ignore-db.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
17188 -+ {"replicate-rewrite-db", OPT_REPLICATE_REWRITE_DB,
17189 -+ "Updates to a database with a different name than the original. Example: "
17190 -+ "replicate-rewrite-db=master_db_name->slave_db_name.",
17191 -+ 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
17192 -+#ifdef HAVE_REPLICATION
17193 -+ {"replicate-same-server-id", OPT_REPLICATE_SAME_SERVER_ID,
17194 -+ "In replication, if set to 1, do not skip events having our server id. "
17195 -+ "Default value is 0 (to break infinite loops in circular replication). "
17196 -+ "Can't be set to 1 if --log-slave-updates is used.",
17197 -+ &replicate_same_server_id, &replicate_same_server_id,
17198 -+ 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
17199 -+#endif
17200 -+ {"replicate-wild-do-table", OPT_REPLICATE_WILD_DO_TABLE,
17201 -+ "Tells the slave thread to restrict replication to the tables that match "
17202 -+ "the specified wildcard pattern. To specify more than one table, use the "
17203 -+ "directive multiple times, once for each table. This will work for cross-"
17204 -+ "database updates. Example: replicate-wild-do-table=foo%.bar% will "
17205 -+ "replicate only updates to tables in all databases that start with foo "
17206 -+ "and whose table names start with bar.",
17207 -+ 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
17208 -+ {"replicate-wild-ignore-table", OPT_REPLICATE_WILD_IGNORE_TABLE,
17209 -+ "Tells the slave thread to not replicate to the tables that match the "
17210 -+ "given wildcard pattern. To specify more than one table to ignore, use "
17211 -+ "the directive multiple times, once for each table. This will work for "
17212 -+ "cross-database updates. Example: replicate-wild-ignore-table=foo%.bar% "
17213 -+ "will not do updates to tables in databases that start with foo and whose "
17214 -+ "table names start with bar.",
17215 -+ 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
17216 -+ // In replication, we may need to tell the other servers how to connect
17217 -+ {"report-host", OPT_REPORT_HOST,
17218 -+ "Hostname or IP of the slave to be reported to the master during slave "
17219 -+ "registration. Will appear in the output of SHOW SLAVE HOSTS. Leave unset "
17220 -+ "if you do not want the slave to register itself with the master. Note that "
17221 -+ "it is not sufficient for the master to simply read the IP of the slave "
17222 -+ "from the socket once the slave connects. Due to NAT and other routing "
17223 -+ "issues, that IP may not be valid for connecting to the slave from the "
17224 -+ "master or other hosts.",
17225 -+ &report_host, &report_host, 0, GET_STR, REQUIRED_ARG, 0, 0,
17226 -+ 0, 0, 0, 0},
17227 -+ {"report-password", OPT_REPORT_PASSWORD, "Undocumented.",
17228 -+ &report_password, &report_password, 0, GET_STR,
17229 -+ REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
17230 -+ {"report-port", OPT_REPORT_PORT,
17231 -+ "Port for connecting to slave reported to the master during slave "
17232 -+ "registration. Set it only if the slave is listening on a non-default "
17233 -+ "port or if you have a special tunnel from the master or other clients "
17234 -+ "to the slave. If not sure, leave this option unset.",
17235 -+ &report_port, &report_port, 0, GET_UINT, REQUIRED_ARG,
17236 -+ MYSQL_PORT, 0, 0, 0, 0, 0},
17237 -+ {"report-user", OPT_REPORT_USER, "Undocumented.", &report_user,
17238 -+ &report_user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
17239 -+ {"rpl-recovery-rank", OPT_RPL_RECOVERY_RANK, "Undocumented.",
17240 -+ &rpl_recovery_rank, &rpl_recovery_rank, 0, GET_ULONG,
17241 -+ REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
17242 -+ {"safe-mode", OPT_SAFE, "Skip some optimize stages (for testing).",
17243 -+ 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
17244 -+#ifndef TO_BE_DELETED
17245 -+ {"safe-show-database", OPT_SAFE_SHOW_DB,
17246 -+ "Deprecated option; use GRANT SHOW DATABASES instead.",
17247 -+ 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
17248 -+#endif
17249 -+ {"safe-user-create", OPT_SAFE_USER_CREATE,
17250 -+ "Don't allow new user creation by the user who has no write privileges to the mysql.user table.",
17251 -+ &opt_safe_user_create, &opt_safe_user_create, 0, GET_BOOL,
17252 -+ NO_ARG, 0, 0, 0, 0, 0, 0},
17253 -+ {"safemalloc-mem-limit", OPT_SAFEMALLOC_MEM_LIMIT,
17254 -+ "Simulate memory shortage when compiled with the --with-debug=full option.",
17255 -+ 0, 0, 0, GET_ULL, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
17256 -+ {"secure-auth", OPT_SECURE_AUTH, "Disallow authentication for accounts that have old (pre-4.1) passwords.",
17257 -+ &opt_secure_auth, &opt_secure_auth, 0, GET_BOOL, NO_ARG,
17258 -+ my_bool(0), 0, 0, 0, 0, 0},
17259 -+ {"secure-file-priv", OPT_SECURE_FILE_PRIV,
17260 -+ "Limit LOAD DATA, SELECT ... OUTFILE, and LOAD_FILE() to files within specified directory.",
17261 -+ &opt_secure_file_priv, &opt_secure_file_priv, 0,
17262 -+ GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
17263 -+ {"server-id", OPT_SERVER_ID,
17264 -+ "Uniquely identifies the server instance in the community of replication partners.",
17265 -+ &server_id, &server_id, 0, GET_ULONG, REQUIRED_ARG, 0, 0, UINT_MAX32,
17266 -+ 0, 0, 0},
17267 -+ {"set-variable", 'O',
17268 -+ "Change the value of a variable. Please note that this option is deprecated; "
17269 -+ "you can set variables directly with --variable-name=value.",
17270 -+ 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
17271 -+#ifdef HAVE_SMEM
17272 -+ {"shared-memory", OPT_ENABLE_SHARED_MEMORY,
17273 -+ "Enable the shared memory.",&opt_enable_shared_memory, &opt_enable_shared_memory,
17274 -+ 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
17275 -+#endif
17276 -+#ifdef HAVE_SMEM
17277 -+ {"shared-memory-base-name",OPT_SHARED_MEMORY_BASE_NAME,
17278 -+ "Base name of shared memory.", &shared_memory_base_name, &shared_memory_base_name,
17279 -+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
17280 -+#endif
17281 -+ {"show-slave-auth-info", OPT_SHOW_SLAVE_AUTH_INFO,
17282 -+ "Show user and password in SHOW SLAVE HOSTS on this master.",
17283 -+ &opt_show_slave_auth_info, &opt_show_slave_auth_info, 0,
17284 -+ GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
17285 -+#ifndef DISABLE_GRANT_OPTIONS
17286 -+ {"skip-grant-tables", OPT_SKIP_GRANT,
17287 -+ "Start without grant tables. This gives all users FULL ACCESS to all tables.",
17288 -+ &opt_noacl, &opt_noacl, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0,
17289 -+ 0},
17290 -+#endif
17291 -+ {"skip-host-cache", OPT_SKIP_HOST_CACHE, "Don't cache host names.", 0, 0, 0,
17292 -+ GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
17293 -+ {"skip-locking", OPT_SKIP_LOCK,
17294 -+ "Deprecated option, use --skip-external-locking instead.",
17295 -+ 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
17296 -+ {"skip-name-resolve", OPT_SKIP_RESOLVE,
17297 -+ "Don't resolve hostnames. All hostnames are IP's or 'localhost'.",
17298 -+ 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
17299 -+ {"skip-networking", OPT_SKIP_NETWORKING,
17300 -+ "Don't allow connection with TCP/IP.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0,
17301 -+ 0, 0, 0},
17302 -+ {"skip-new", OPT_SKIP_NEW, "Don't use new, possibly wrong routines.",
17303 -+ 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
17304 -+#ifndef DBUG_OFF
17305 -+#ifdef SAFEMALLOC
17306 -+ {"skip-safemalloc", OPT_SKIP_SAFEMALLOC,
17307 -+ "Don't use the memory allocation checking.", 0, 0, 0, GET_NO_ARG, NO_ARG,
17308 -+ 0, 0, 0, 0, 0, 0},
17309 -+#endif
17310 -+#endif
17311 -+ {"skip-show-database", OPT_SKIP_SHOW_DB,
17312 -+ "Don't allow 'SHOW DATABASE' commands.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0,
17313 -+ 0, 0, 0, 0},
17314 -+ {"skip-slave-start", OPT_SKIP_SLAVE_START,
17315 -+ "If set, slave is not autostarted.", &opt_skip_slave_start,
17316 -+ &opt_skip_slave_start, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
17317 -+ {"skip-stack-trace", OPT_SKIP_STACK_TRACE,
17318 -+ "Don't print a stack trace on failure.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0,
17319 -+ 0, 0, 0, 0},
17320 -+ {"skip-symlink", OPT_SKIP_SYMLINKS, "Don't allow symlinking of tables. "
17321 -+ "Deprecated option. Use --skip-symbolic-links instead.",
17322 -+ 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
17323 -+ {"skip-thread-priority", OPT_SKIP_PRIOR,
17324 -+ "Don't give threads different priorities. Deprecated option.", 0, 0, 0, GET_NO_ARG, NO_ARG,
17325 -+ DEFAULT_SKIP_THREAD_PRIORITY, 0, 0, 0, 0, 0},
17326 -+#ifdef HAVE_REPLICATION
17327 -+ {"slave-load-tmpdir", OPT_SLAVE_LOAD_TMPDIR,
17328 -+ "The location where the slave should put its temporary files when "
17329 -+ "replicating a LOAD DATA INFILE command.",
17330 -+ &slave_load_tmpdir, &slave_load_tmpdir, 0, GET_STR_ALLOC,
17331 -+ REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
17332 -+ {"slave-skip-errors", OPT_SLAVE_SKIP_ERRORS,
17333 -+ "Tells the slave thread to continue replication when a query event returns an error from the provided list.",
17334 -+ 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
17335 -+ {"slave-exec-mode", OPT_SLAVE_EXEC_MODE,
17336 -+ "Modes for how replication events should be executed. Legal values are "
17337 -+ "STRICT (default) and IDEMPOTENT. In IDEMPOTENT mode, replication will "
17338 -+ "not stop for operations that are idempotent. In STRICT mode, replication "
17339 -+ "will stop on any unexpected difference between the master and the slave.",
17340 -+ &slave_exec_mode_str, &slave_exec_mode_str, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
17341 -+#endif
17342 -+ {"slow-query-log", OPT_SLOW_LOG,
17343 -+ "Enable/disable slow query log.", &opt_slow_log,
17344 -+ &opt_slow_log, 0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0},
17345 -+ {"socket", OPT_SOCKET, "Socket file to use for connection.",
17346 -+ &mysqld_unix_port, &mysqld_unix_port, 0, GET_STR,
17347 -+ REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
17348 -+#ifdef HAVE_REPLICATION
17349 -+ {"sporadic-binlog-dump-fail", OPT_SPORADIC_BINLOG_DUMP_FAIL,
17350 -+ "Option used by mysql-test for debugging and testing of replication.",
17351 -+ &opt_sporadic_binlog_dump_fail,
17352 -+ &opt_sporadic_binlog_dump_fail, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0,
17353 -+ 0},
17354 -+#endif /* HAVE_REPLICATION */
17355 -+ {"sql-bin-update-same", OPT_SQL_BIN_UPDATE_SAME,
17356 -+ "The update log is deprecated since version 5.0, is replaced by the "
17357 -+ "binary log and this option does nothing anymore.",
17358 -+ 0, 0, 0, GET_DISABLED, NO_ARG, 0, 0, 0, 0, 0, 0},
17359 -+ {"sql-mode", OPT_SQL_MODE,
17360 -+ "Syntax: sql-mode=option[,option[,option...]] where option can be one "
17361 -+ "of: REAL_AS_FLOAT, PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, "
17362 -+ "ONLY_FULL_GROUP_BY, NO_UNSIGNED_SUBTRACTION.",
17363 -+ &sql_mode_str, &sql_mode_str, 0, GET_STR, REQUIRED_ARG, 0,
17364 -+ 0, 0, 0, 0, 0},
17365 -+#ifdef HAVE_OPENSSL
17366 -+#include "sslopt-longopts.h"
17367 -+#endif
17368 -+#ifdef __WIN__
17369 -+ {"standalone", OPT_STANDALONE,
17370 -+ "Dummy option to start as a standalone program (NT).", 0, 0, 0, GET_NO_ARG,
17371 -+ NO_ARG, 0, 0, 0, 0, 0, 0},
17372 -+#endif
17373 -+ {"symbolic-links", 's', "Enable symbolic link support.",
17374 -+ &my_use_symdir, &my_use_symdir, 0, GET_BOOL, NO_ARG,
17375 -+ /*
17376 -+ The system call realpath() produces warnings under valgrind and
17377 -+ purify. These are not suppressed: instead we disable symlinks
17378 -+ option if compiled with valgrind support.
17379 -+ */
17380 -+ IF_PURIFY(0,1), 0, 0, 0, 0, 0},
17381 -+ {"sysdate-is-now", OPT_SYSDATE_IS_NOW,
17382 -+ "Non-default option to alias SYSDATE() to NOW() to make it safe-replicable. "
17383 -+ "Since 5.0, SYSDATE() returns a `dynamic' value different for different "
17384 -+ "invocations, even within the same statement.",
17385 -+ &global_system_variables.sysdate_is_now,
17386 -+ 0, 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 1, 0},
17387 -+ {"tc-heuristic-recover", OPT_TC_HEURISTIC_RECOVER,
17388 -+ "Decision to use in heuristic recover process. Possible values are COMMIT "
17389 -+ "or ROLLBACK.", &opt_tc_heuristic_recover, &opt_tc_heuristic_recover,
17390 -+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
17391 -+#if defined(ENABLED_DEBUG_SYNC)
17392 -+ {"debug-sync-timeout", OPT_DEBUG_SYNC_TIMEOUT,
17393 -+ "Enable the debug sync facility "
17394 -+ "and optionally specify a default wait timeout in seconds. "
17395 -+ "A zero value keeps the facility disabled.",
17396 -+ &opt_debug_sync_timeout, 0,
17397 -+ 0, GET_UINT, OPT_ARG, 0, 0, UINT_MAX, 0, 0, 0},
17398 -+#endif /* defined(ENABLED_DEBUG_SYNC) */
17399 -+ {"temp-pool", OPT_TEMP_POOL,
17400 -+#if (ENABLE_TEMP_POOL)
17401 -+ "Using this option will cause most temporary files created to use a small "
17402 -+ "set of names, rather than a unique name for each new file.",
17403 -+#else
17404 -+ "This option is ignored on this OS.",
17405 -+#endif
17406 -+ &use_temp_pool, &use_temp_pool, 0, GET_BOOL, NO_ARG, 1,
17407 -+ 0, 0, 0, 0, 0},
17408 -+ {"timed_mutexes", OPT_TIMED_MUTEXES,
17409 -+ "Specify whether to time mutexes (only InnoDB mutexes are currently supported).",
17410 -+ &timed_mutexes, &timed_mutexes, 0, GET_BOOL, NO_ARG, 0,
17411 -+ 0, 0, 0, 0, 0},
17412 -+ {"tmpdir", 't',
17413 -+ "Path for temporary files. Several paths may be specified, separated by a "
17414 -+#if defined(__WIN__) || defined(__NETWARE__)
17415 -+ "semicolon (;)"
17416 -+#else
17417 -+ "colon (:)"
17418 -+#endif
17419 -+ ", in this case they are used in a round-robin fashion.",
17420 -+ &opt_mysql_tmpdir, &opt_mysql_tmpdir, 0, GET_STR, REQUIRED_ARG,
17421 -+ 0, 0, 0, 0, 0, 0},
17422 -+ {"transaction-isolation", OPT_TX_ISOLATION,
17423 -+ "Default transaction isolation level.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0,
17424 -+ 0, 0, 0, 0, 0},
17425 -+ {"use-symbolic-links", OPT_SYMBOLIC_LINKS, "Enable symbolic link support. "
17426 -+ "Deprecated option; use --symbolic-links instead.",
17427 -+ &my_use_symdir, &my_use_symdir, 0, GET_BOOL, NO_ARG,
17428 -+ IF_PURIFY(0,1), 0, 0, 0, 0, 0},
17429 -+ {"user", 'u', "Run mysqld daemon as user.", 0, 0, 0, GET_STR, REQUIRED_ARG,
17430 -+ 0, 0, 0, 0, 0, 0},
17431 -+ {"verbose", 'v', "Used with --help option for detailed help.",
17432 -+ &opt_verbose, &opt_verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
17433 -+ {"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG,
17434 -+ NO_ARG, 0, 0, 0, 0, 0, 0},
17435 -+ {"warnings", OPT_WARNINGS, "Deprecated; use --log-warnings instead.",
17436 -+ &global_system_variables.log_warnings,
17437 -+ &max_system_variables.log_warnings, 0, GET_ULONG, OPT_ARG,
17438 -+ 1, 0, ULONG_MAX, 0, 0, 0},
17439 -+ {"back_log", OPT_BACK_LOG,
17440 -+ "The number of outstanding connection requests MySQL can have. This "
17441 -+ "comes into play when the main MySQL thread gets very many connection "
17442 -+ "requests in a very short time.", &back_log, &back_log, 0, GET_ULONG,
17443 -+ REQUIRED_ARG, 50, 1, 65535, 0, 1, 0 },
17444 -+ {"binlog_cache_size", OPT_BINLOG_CACHE_SIZE,
17445 -+ "The size of the cache to hold the SQL statements for the binary log "
17446 -+ "during a transaction. If you often use big, multi-statement "
17447 -+ "transactions you can increase this to get more performance.",
17448 -+ &binlog_cache_size, &binlog_cache_size, 0, GET_ULONG,
17449 -+ REQUIRED_ARG, 32*1024L, IO_SIZE, ULONG_MAX, 0, IO_SIZE, 0},
17450 -+ {"bulk_insert_buffer_size", OPT_BULK_INSERT_BUFFER_SIZE,
17451 -+ "Size of tree cache used in bulk insert optimization. Note that this "
17452 -+ "is a limit per thread.", &global_system_variables.bulk_insert_buff_size,
17453 -+ &max_system_variables.bulk_insert_buff_size,
17454 -+ 0, GET_ULONG, REQUIRED_ARG, 8192*1024, 0, ULONG_MAX, 0, 1, 0},
17455 -+ {"connect_timeout", OPT_CONNECT_TIMEOUT,
17456 -+ "The number of seconds the mysqld server is waiting for a connect packet "
17457 -+ "before responding with 'Bad handshake'.", &connect_timeout, &connect_timeout,
17458 -+ 0, GET_ULONG, REQUIRED_ARG, CONNECT_TIMEOUT, 2, LONG_TIMEOUT, 0, 1, 0 },
17459 -+ { "date_format", OPT_DATE_FORMAT,
17460 -+ "The DATE format (for future).",
17461 -+ &opt_date_time_formats[MYSQL_TIMESTAMP_DATE],
17462 -+ &opt_date_time_formats[MYSQL_TIMESTAMP_DATE],
17463 -+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
17464 -+ { "datetime_format", OPT_DATETIME_FORMAT,
17465 -+ "The DATETIME/TIMESTAMP format (for future).",
17466 -+ &opt_date_time_formats[MYSQL_TIMESTAMP_DATETIME],
17467 -+ &opt_date_time_formats[MYSQL_TIMESTAMP_DATETIME],
17468 -+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
17469 -+ { "default_week_format", OPT_DEFAULT_WEEK_FORMAT,
17470 -+ "The default week format used by WEEK() functions.",
17471 -+ &global_system_variables.default_week_format,
17472 -+ &max_system_variables.default_week_format,
17473 -+ 0, GET_ULONG, REQUIRED_ARG, 0, 0, 7L, 0, 1, 0},
17474 -+ {"delayed_insert_limit", OPT_DELAYED_INSERT_LIMIT,
17475 -+ "After inserting delayed_insert_limit rows, the INSERT DELAYED handler "
17476 -+ "will check if there are any SELECT statements pending. If so, it allows "
17477 -+ "these to execute before continuing.",
17478 -+ &delayed_insert_limit, &delayed_insert_limit, 0, GET_ULONG,
17479 -+ REQUIRED_ARG, DELAYED_LIMIT, 1, ULONG_MAX, 0, 1, 0},
17480 -+ {"delayed_insert_timeout", OPT_DELAYED_INSERT_TIMEOUT,
17481 -+ "How long a INSERT DELAYED thread should wait for INSERT statements before terminating.",
17482 -+ &delayed_insert_timeout, &delayed_insert_timeout, 0,
17483 -+ GET_ULONG, REQUIRED_ARG, DELAYED_WAIT_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0},
17484 -+ { "delayed_queue_size", OPT_DELAYED_QUEUE_SIZE,
17485 -+ "What size queue (in rows) should be allocated for handling INSERT DELAYED. "
17486 -+ "If the queue becomes full, any client that does INSERT DELAYED will wait "
17487 -+ "until there is room in the queue again.",
17488 -+ &delayed_queue_size, &delayed_queue_size, 0, GET_ULONG,
17489 -+ REQUIRED_ARG, DELAYED_QUEUE_SIZE, 1, ULONG_MAX, 0, 1, 0},
17490 -+ {"div_precision_increment", OPT_DIV_PRECINCREMENT,
17491 -+ "Precision of the result of '/' operator will be increased on that value.",
17492 -+ &global_system_variables.div_precincrement,
17493 -+ &max_system_variables.div_precincrement, 0, GET_ULONG,
17494 -+ REQUIRED_ARG, 4, 0, DECIMAL_MAX_SCALE, 0, 0, 0},
17495 -+ {"expire_logs_days", OPT_EXPIRE_LOGS_DAYS,
17496 -+ "If non-zero, binary logs will be purged after expire_logs_days "
17497 -+ "days; possible purges happen at startup and at binary log rotation.",
17498 -+ &expire_logs_days, &expire_logs_days, 0, GET_ULONG,
17499 -+ REQUIRED_ARG, 0, 0, 99, 0, 1, 0},
17500 -+ { "flush_time", OPT_FLUSH_TIME,
17501 -+ "A dedicated thread is created to flush all tables at the given interval.",
17502 -+ &flush_time, &flush_time, 0, GET_ULONG, REQUIRED_ARG,
17503 -+ FLUSH_TIME, 0, LONG_TIMEOUT, 0, 1, 0},
17504 -+ { "ft_boolean_syntax", OPT_FT_BOOLEAN_SYNTAX,
17505 -+ "List of operators for MATCH ... AGAINST ( ... IN BOOLEAN MODE).",
17506 -+ 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
17507 -+ { "ft_max_word_len", OPT_FT_MAX_WORD_LEN,
17508 -+ "The maximum length of the word to be included in a FULLTEXT index. "
17509 -+ "Note: FULLTEXT indexes must be rebuilt after changing this variable.",
17510 -+ &ft_max_word_len, &ft_max_word_len, 0, GET_ULONG,
17511 -+ REQUIRED_ARG, HA_FT_MAXCHARLEN, 10, HA_FT_MAXCHARLEN, 0, 1, 0},
17512 -+ { "ft_min_word_len", OPT_FT_MIN_WORD_LEN,
17513 -+ "The minimum length of the word to be included in a FULLTEXT index. "
17514 -+ "Note: FULLTEXT indexes must be rebuilt after changing this variable.",
17515 -+ &ft_min_word_len, &ft_min_word_len, 0, GET_ULONG,
17516 -+ REQUIRED_ARG, 4, 1, HA_FT_MAXCHARLEN, 0, 1, 0},
17517 -+ { "ft_query_expansion_limit", OPT_FT_QUERY_EXPANSION_LIMIT,
17518 -+ "Number of best matches to use for query expansion.",
17519 -+ &ft_query_expansion_limit, &ft_query_expansion_limit, 0, GET_ULONG,
17520 -+ REQUIRED_ARG, 20, 0, 1000, 0, 1, 0},
17521 -+ { "ft_stopword_file", OPT_FT_STOPWORD_FILE,
17522 -+ "Use stopwords from this file instead of built-in list.",
17523 -+ &ft_stopword_file, &ft_stopword_file, 0, GET_STR,
17524 -+ REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
17525 -+ { "group_concat_max_len", OPT_GROUP_CONCAT_MAX_LEN,
17526 -+ "The maximum length of the result of function group_concat.",
17527 -+ &global_system_variables.group_concat_max_len,
17528 -+ &max_system_variables.group_concat_max_len, 0, GET_ULONG,
17529 -+ REQUIRED_ARG, 1024, 4, ULONG_MAX, 0, 1, 0},
17530 -+ {"interactive_timeout", OPT_INTERACTIVE_TIMEOUT,
17531 -+ "The number of seconds the server waits for activity on an interactive "
17532 -+ "connection before closing it.",
17533 -+ &global_system_variables.net_interactive_timeout,
17534 -+ &max_system_variables.net_interactive_timeout, 0,
17535 -+ GET_ULONG, REQUIRED_ARG, NET_WAIT_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0},
17536 -+ {"join_buffer_size", OPT_JOIN_BUFF_SIZE,
17537 -+ "The size of the buffer that is used for full joins.",
17538 -+ &global_system_variables.join_buff_size,
17539 -+ &max_system_variables.join_buff_size, 0, GET_ULONG,
17540 -+ REQUIRED_ARG, 128*1024L, IO_SIZE*2+MALLOC_OVERHEAD, ULONG_MAX,
17541 -+ MALLOC_OVERHEAD, IO_SIZE, 0},
17542 -+ {"keep_files_on_create", OPT_KEEP_FILES_ON_CREATE,
17543 -+ "Don't overwrite stale .MYD and .MYI even if no directory is specified.",
17544 -+ &global_system_variables.keep_files_on_create,
17545 -+ &max_system_variables.keep_files_on_create,
17546 -+ 0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0},
17547 -+ {"key_buffer_size", OPT_KEY_BUFFER_SIZE,
17548 -+ "The size of the buffer used for index blocks for MyISAM tables. Increase "
17549 -+ "this to get better index handling (for all reads and multiple writes) to "
17550 -+ "as much as you can afford; 1GB on a 4GB machine that mainly runs MySQL is "
17551 -+ "quite common.",
17552 -+ &dflt_key_cache_var.param_buff_size, NULL, NULL, (GET_ULL | GET_ASK_ADDR),
17553 -+ REQUIRED_ARG, KEY_CACHE_SIZE, 0, SIZE_T_MAX, MALLOC_OVERHEAD,
17554 -+ IO_SIZE, 0},
17555 -+ {"key_cache_age_threshold", OPT_KEY_CACHE_AGE_THRESHOLD,
17556 -+ "This characterizes the number of hits a hot block has to be untouched "
17557 -+ "until it is considered aged enough to be downgraded to a warm block. "
17558 -+ "This specifies the percentage ratio of that number of hits to the total "
17559 -+ "number of blocks in key cache.",
17560 -+ &dflt_key_cache_var.param_age_threshold, NULL, NULL,
17561 -+ (GET_ULONG | GET_ASK_ADDR), REQUIRED_ARG, 300, 100, ULONG_MAX, 0, 100, 0},
17562 -+ {"key_cache_block_size", OPT_KEY_CACHE_BLOCK_SIZE,
17563 -+ "The default size of key cache blocks.",
17564 -+ &dflt_key_cache_var.param_block_size, NULL, NULL, (GET_ULONG | GET_ASK_ADDR),
17565 -+ REQUIRED_ARG, KEY_CACHE_BLOCK_SIZE, 512, 1024 * 16, 0, 512, 0},
17566 -+ {"key_cache_division_limit", OPT_KEY_CACHE_DIVISION_LIMIT,
17567 -+ "The minimum percentage of warm blocks in key cache.",
17568 -+ &dflt_key_cache_var.param_division_limit, NULL, NULL,
17569 -+ (GET_ULONG | GET_ASK_ADDR) , REQUIRED_ARG, 100, 1, 100, 0, 1, 0},
17570 -+ {"long_query_time", OPT_LONG_QUERY_TIME,
17571 -+ "Log all queries that have taken more than long_query_time seconds to "
17572 -+ "execute. The argument will be treated as a decimal value with "
17573 -+ "microsecond precision.",
17574 -+ &long_query_time, &long_query_time, 0, GET_DOUBLE,
17575 -+ REQUIRED_ARG, 10, 0, LONG_TIMEOUT, 0, 0, 0},
17576 -+ {"lower_case_table_names", OPT_LOWER_CASE_TABLE_NAMES,
17577 -+ "If set to 1, table names are stored in lowercase on disk and table names "
17578 -+ "will be case-insensitive. Should be set to 2 if you are using a case-"
17579 -+ "insensitive file system.",
17580 -+ &lower_case_table_names, &lower_case_table_names, 0, GET_UINT, OPT_ARG,
17581 -+#ifdef FN_NO_CASE_SENCE
17582 -+ 1
17583 -+#else
17584 -+ 0
17585 -+#endif
17586 -+ , 0, 2, 0, 1, 0},
17587 -+ {"max_allowed_packet", OPT_MAX_ALLOWED_PACKET,
17588 -+ "The maximum packet length to send to or receive from server.",
17589 -+ &global_system_variables.max_allowed_packet,
17590 -+ &max_system_variables.max_allowed_packet, 0, GET_ULONG,
17591 -+ REQUIRED_ARG, 1024*1024L, 1024, 1024L*1024L*1024L, MALLOC_OVERHEAD, 1024, 0},
17592 -+ {"max_binlog_cache_size", OPT_MAX_BINLOG_CACHE_SIZE,
17593 -+ "Can be used to restrict the total size used to cache a multi-transaction query.",
17594 -+ &max_binlog_cache_size, &max_binlog_cache_size, 0,
17595 -+ GET_ULL, REQUIRED_ARG, ULONG_MAX, IO_SIZE, ULONGLONG_MAX, 0, IO_SIZE, 0},
17596 -+ {"max_binlog_size", OPT_MAX_BINLOG_SIZE,
17597 -+ "Binary log will be rotated automatically when the size exceeds this "
17598 -+ "value. Will also apply to relay logs if max_relay_log_size is 0. "
17599 -+ "The minimum value for this variable is 4096.",
17600 -+ &max_binlog_size, &max_binlog_size, 0, GET_ULONG,
17601 -+ REQUIRED_ARG, 1024*1024L*1024L, IO_SIZE, 1024*1024L*1024L, 0, IO_SIZE, 0},
17602 -+ {"max_connect_errors", OPT_MAX_CONNECT_ERRORS,
17603 -+ "If there is more than this number of interrupted connections from a host "
17604 -+ "this host will be blocked from further connections.",
17605 -+ &max_connect_errors, &max_connect_errors, 0, GET_ULONG,
17606 -+ REQUIRED_ARG, MAX_CONNECT_ERRORS, 1, ULONG_MAX, 0, 1, 0},
17607 -+ // Default max_connections of 151 is larger than Apache's default max
17608 -+ // children, to avoid "too many connections" error in a common setup
17609 -+ {"max_connections", OPT_MAX_CONNECTIONS,
17610 -+ "The number of simultaneous clients allowed.", &max_connections,
17611 -+ &max_connections, 0, GET_ULONG, REQUIRED_ARG, 151, 1, 100000, 0, 1, 0},
17612 -+ {"max_delayed_threads", OPT_MAX_DELAYED_THREADS,
17613 -+ "Don't start more than this number of threads to handle INSERT DELAYED "
17614 -+ "statements. If set to zero, which means INSERT DELAYED is not used.",
17615 -+ &global_system_variables.max_insert_delayed_threads,
17616 -+ &max_system_variables.max_insert_delayed_threads,
17617 -+ 0, GET_ULONG, REQUIRED_ARG, 20, 0, 16384, 0, 1, 0},
17618 -+ {"max_error_count", OPT_MAX_ERROR_COUNT,
17619 -+ "Max number of errors/warnings to store for a statement.",
17620 -+ &global_system_variables.max_error_count,
17621 -+ &max_system_variables.max_error_count,
17622 -+ 0, GET_ULONG, REQUIRED_ARG, DEFAULT_ERROR_COUNT, 0, 65535, 0, 1, 0},
17623 -+ {"max_heap_table_size", OPT_MAX_HEP_TABLE_SIZE,
17624 -+ "Don't allow creation of heap tables bigger than this.",
17625 -+ &global_system_variables.max_heap_table_size,
17626 -+ &max_system_variables.max_heap_table_size, 0, GET_ULL,
17627 -+ REQUIRED_ARG, 16*1024*1024L, 16384, MAX_MEM_TABLE_SIZE,
17628 -+ MALLOC_OVERHEAD, 1024, 0},
17629 -+ {"max_join_size", OPT_MAX_JOIN_SIZE,
17630 -+ "Joins that are probably going to read more than max_join_size records return an error.",
17631 -+ &global_system_variables.max_join_size,
17632 -+ &max_system_variables.max_join_size, 0, GET_HA_ROWS, REQUIRED_ARG,
17633 -+ HA_POS_ERROR, 1, HA_POS_ERROR, 0, 1, 0},
17634 -+ {"max_length_for_sort_data", OPT_MAX_LENGTH_FOR_SORT_DATA,
17635 -+ "Max number of bytes in sorted records.",
17636 -+ &global_system_variables.max_length_for_sort_data,
17637 -+ &max_system_variables.max_length_for_sort_data, 0, GET_ULONG,
17638 -+ REQUIRED_ARG, 1024, 4, 8192*1024L, 0, 1, 0},
17639 -+ {"max_long_data_size", OPT_MAX_LONG_DATA_SIZE,
17640 -+ "The maximum size of prepared statement parameter which can be provided "
17641 -+ "through mysql_send_long_data() API call. "
17642 -+ "Deprecated option; use max_allowed_packet instead.",
17643 -+ &max_long_data_size,
17644 -+ &max_long_data_size, 0, GET_ULONG,
17645 -+ REQUIRED_ARG, 1024*1024L, 1024, UINT_MAX32, MALLOC_OVERHEAD, 1, 0},
17646 -+ {"max_prepared_stmt_count", OPT_MAX_PREPARED_STMT_COUNT,
17647 -+ "Maximum number of prepared statements in the server.",
17648 -+ &max_prepared_stmt_count, &max_prepared_stmt_count,
17649 -+ 0, GET_ULONG, REQUIRED_ARG, 16382, 0, 1*1024*1024, 0, 1, 0},
17650 -+ {"max_relay_log_size", OPT_MAX_RELAY_LOG_SIZE,
17651 -+ "If non-zero: relay log will be rotated automatically when the size "
17652 -+ "exceeds this value; if zero (the default): when the size exceeds "
17653 -+ "max_binlog_size. 0 excepted, the minimum value for this variable is 4096.",
17654 -+ &max_relay_log_size, &max_relay_log_size, 0, GET_ULONG,
17655 -+ REQUIRED_ARG, 0L, 0L, 1024*1024L*1024L, 0, IO_SIZE, 0},
17656 -+ { "max_seeks_for_key", OPT_MAX_SEEKS_FOR_KEY,
17657 -+ "Limit assumed max number of seeks when looking up rows based on a key.",
17658 -+ &global_system_variables.max_seeks_for_key,
17659 -+ &max_system_variables.max_seeks_for_key, 0, GET_ULONG,
17660 -+ REQUIRED_ARG, ULONG_MAX, 1, ULONG_MAX, 0, 1, 0 },
17661 -+ {"max_sort_length", OPT_MAX_SORT_LENGTH,
17662 -+ "The number of bytes to use when sorting BLOB or TEXT values (only the "
17663 -+ "first max_sort_length bytes of each value are used; the rest are ignored).",
17664 -+ &global_system_variables.max_sort_length,
17665 -+ &max_system_variables.max_sort_length, 0, GET_ULONG,
17666 -+ REQUIRED_ARG, 1024, 4, 8192*1024L, 0, 1, 0},
17667 -+ {"max_sp_recursion_depth", OPT_MAX_SP_RECURSION_DEPTH,
17668 -+ "Maximum stored procedure recursion depth. (discussed with docs).",
17669 -+ &global_system_variables.max_sp_recursion_depth,
17670 -+ &max_system_variables.max_sp_recursion_depth, 0, GET_ULONG,
17671 -+ OPT_ARG, 0, 0, 255, 0, 1, 0 },
17672 -+ {"max_tmp_tables", OPT_MAX_TMP_TABLES,
17673 -+ "Maximum number of temporary tables a client can keep open at a time.",
17674 -+ &global_system_variables.max_tmp_tables,
17675 -+ &max_system_variables.max_tmp_tables, 0, GET_ULONG,
17676 -+ REQUIRED_ARG, 32, 1, ULONG_MAX, 0, 1, 0},
17677 -+ {"max_user_connections", OPT_MAX_USER_CONNECTIONS,
17678 -+ "The maximum number of active connections for a single user (0 = no limit).",
17679 -+ &max_user_connections, &max_user_connections, 0, GET_UINT,
17680 -+ REQUIRED_ARG, 0, 0, UINT_MAX, 0, 1, 0},
17681 -+ {"max_write_lock_count", OPT_MAX_WRITE_LOCK_COUNT,
17682 -+ "After this many write locks, allow some read locks to run in between.",
17683 -+ &max_write_lock_count, &max_write_lock_count, 0, GET_ULONG,
17684 -+ REQUIRED_ARG, ULONG_MAX, 1, ULONG_MAX, 0, 1, 0},
17685 -+ {"min_examined_row_limit", OPT_MIN_EXAMINED_ROW_LIMIT,
17686 -+ "Don't log queries which examine less than min_examined_row_limit rows to file.",
17687 -+ &global_system_variables.min_examined_row_limit,
17688 -+ &max_system_variables.min_examined_row_limit, 0, GET_ULONG,
17689 -+ REQUIRED_ARG, 0, 0, ULONG_MAX, 0, 1L, 0},
17690 -+ {"multi_range_count", OPT_MULTI_RANGE_COUNT,
17691 -+ "Number of key ranges to request at once.",
17692 -+ &global_system_variables.multi_range_count,
17693 -+ &max_system_variables.multi_range_count, 0,
17694 -+ GET_ULONG, REQUIRED_ARG, 256, 1, ULONG_MAX, 0, 1, 0},
17695 -+ {"myisam_block_size", OPT_MYISAM_BLOCK_SIZE,
17696 -+ "Block size to be used for MyISAM index pages.",
17697 -+ &opt_myisam_block_size, &opt_myisam_block_size, 0, GET_ULONG, REQUIRED_ARG,
17698 -+ MI_KEY_BLOCK_LENGTH, MI_MIN_KEY_BLOCK_LENGTH, MI_MAX_KEY_BLOCK_LENGTH,
17699 -+ 0, MI_MIN_KEY_BLOCK_LENGTH, 0},
17700 -+ {"myisam_data_pointer_size", OPT_MYISAM_DATA_POINTER_SIZE,
17701 -+ "Default pointer size to be used for MyISAM tables.",
17702 -+ &myisam_data_pointer_size,
17703 -+ &myisam_data_pointer_size, 0, GET_ULONG, REQUIRED_ARG,
17704 -+ 6, 2, 7, 0, 1, 0},
17705 -+ {"myisam_max_extra_sort_file_size", OPT_MYISAM_MAX_EXTRA_SORT_FILE_SIZE,
17706 -+ "This is a deprecated option that does nothing anymore. "
17707 -+ "It will be removed in MySQL " VER_CELOSIA,
17708 -+ &global_system_variables.myisam_max_extra_sort_file_size,
17709 -+ &max_system_variables.myisam_max_extra_sort_file_size,
17710 -+ 0, GET_ULL, REQUIRED_ARG, (ulonglong) INT_MAX32,
17711 -+ 0, (ulonglong) MAX_FILE_SIZE, 0, 1, 0},
17712 -+ {"myisam_max_sort_file_size", OPT_MYISAM_MAX_SORT_FILE_SIZE,
17713 -+ "Don't use the fast sort index method to created index if the temporary "
17714 -+ "file would get bigger than this.",
17715 -+ &global_system_variables.myisam_max_sort_file_size,
17716 -+ &max_system_variables.myisam_max_sort_file_size, 0,
17717 -+ GET_ULL, REQUIRED_ARG, (longlong) LONG_MAX, 0, (ulonglong) MAX_FILE_SIZE,
17718 -+ 0, 1024*1024, 0},
17719 -+ {"myisam_mmap_size", OPT_MYISAM_MMAP_SIZE,
17720 -+ "Can be used to restrict the total memory used for memory mmaping of myisam files",
17721 -+ &myisam_mmap_size, &myisam_mmap_size, 0,
17722 -+ GET_ULL, REQUIRED_ARG, SIZE_T_MAX, MEMMAP_EXTRA_MARGIN, SIZE_T_MAX, 0, 1, 0},
17723 -+ {"myisam_repair_threads", OPT_MYISAM_REPAIR_THREADS,
17724 -+ "Specifies whether several threads should be used when repairing MyISAM "
17725 -+ "tables. For values > 1, one thread is used per index. The value of 1 "
17726 -+ "disables parallel repair.",
17727 -+ &global_system_variables.myisam_repair_threads,
17728 -+ &max_system_variables.myisam_repair_threads, 0,
17729 -+ GET_ULONG, REQUIRED_ARG, 1, 1, ULONG_MAX, 0, 1, 0},
17730 -+ {"myisam_sort_buffer_size", OPT_MYISAM_SORT_BUFFER_SIZE,
17731 -+ "The buffer that is allocated when sorting the index when doing a REPAIR "
17732 -+ "or when creating indexes with CREATE INDEX or ALTER TABLE.",
17733 -+ &global_system_variables.myisam_sort_buff_size,
17734 -+ &max_system_variables.myisam_sort_buff_size, 0,
17735 -+ GET_ULONG, REQUIRED_ARG, 8192 * 1024, 4096, ~0L, 0, 1, 0},
17736 -+ {"myisam_use_mmap", OPT_MYISAM_USE_MMAP,
17737 -+ "Use memory mapping for reading and writing MyISAM tables.",
17738 -+ &opt_myisam_use_mmap, &opt_myisam_use_mmap, 0, GET_BOOL, NO_ARG,
17739 -+ 0, 0, 0, 0, 0, 0},
17740 -+ {"myisam_stats_method", OPT_MYISAM_STATS_METHOD,
17741 -+ "Specifies how MyISAM index statistics collection code should threat NULLs. "
17742 -+ "Possible values of name are \"nulls_unequal\" (default behavior for 4.1/5.0), "
17743 -+ "\"nulls_equal\" (emulate 4.0 behavior), and \"nulls_ignored\".",
17744 -+ &myisam_stats_method_str, &myisam_stats_method_str, 0,
17745 -+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
17746 -+ {"net_buffer_length", OPT_NET_BUFFER_LENGTH,
17747 -+ "Buffer length for TCP/IP and socket communication.",
17748 -+ &global_system_variables.net_buffer_length,
17749 -+ &max_system_variables.net_buffer_length, 0, GET_ULONG,
17750 -+ REQUIRED_ARG, 16384, 1024, 1024*1024L, 0, 1024, 0},
17751 -+ {"net_read_timeout", OPT_NET_READ_TIMEOUT,
17752 -+ "Number of seconds to wait for more data from a connection before aborting the read.",
17753 -+ &global_system_variables.net_read_timeout,
17754 -+ &max_system_variables.net_read_timeout, 0, GET_ULONG,
17755 -+ REQUIRED_ARG, NET_READ_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0},
17756 -+ {"net_retry_count", OPT_NET_RETRY_COUNT,
17757 -+ "If a read on a communication port is interrupted, retry this many times before giving up.",
17758 -+ &global_system_variables.net_retry_count,
17759 -+ &max_system_variables.net_retry_count,0,
17760 -+ GET_ULONG, REQUIRED_ARG, MYSQLD_NET_RETRY_COUNT, 1, ULONG_MAX, 0, 1, 0},
17761 -+ {"net_write_timeout", OPT_NET_WRITE_TIMEOUT,
17762 -+ "Number of seconds to wait for a block to be written to a connection before "
17763 -+ "aborting the write.",
17764 -+ &global_system_variables.net_write_timeout,
17765 -+ &max_system_variables.net_write_timeout, 0, GET_ULONG,
17766 -+ REQUIRED_ARG, NET_WRITE_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0},
17767 -+ { "old", OPT_OLD_MODE, "Use compatible behavior.",
17768 -+ &global_system_variables.old_mode,
17769 -+ &max_system_variables.old_mode, 0, GET_BOOL, NO_ARG,
17770 -+ 0, 0, 0, 0, 0, 0},
17771 -+ {"open_files_limit", OPT_OPEN_FILES_LIMIT,
17772 -+ "If this is not 0, then mysqld will use this value to reserve file "
17773 -+ "descriptors to use with setrlimit(). If this value is 0 then mysqld "
17774 -+ "will reserve max_connections*5 or max_connections + table_cache*2 "
17775 -+ "(whichever is larger) number of files.",
17776 -+ &open_files_limit, &open_files_limit, 0, GET_ULONG,
17777 -+ REQUIRED_ARG, 0, 0, OS_FILE_LIMIT, 0, 1, 0},
17778 -+ {"optimizer_prune_level", OPT_OPTIMIZER_PRUNE_LEVEL,
17779 -+ "Controls the heuristic(s) applied during query optimization to prune "
17780 -+ "less-promising partial plans from the optimizer search space. Meaning: "
17781 -+ "0 - do not apply any heuristic, thus perform exhaustive search; 1 - "
17782 -+ "prune plans based on number of retrieved rows.",
17783 -+ &global_system_variables.optimizer_prune_level,
17784 -+ &max_system_variables.optimizer_prune_level,
17785 -+ 0, GET_ULONG, OPT_ARG, 1, 0, 1, 0, 1, 0},
17786 -+ {"optimizer_search_depth", OPT_OPTIMIZER_SEARCH_DEPTH,
17787 -+ "Maximum depth of search performed by the query optimizer. Values larger "
17788 -+ "than the number of relations in a query result in better query plans, "
17789 -+ "but take longer to compile a query. Smaller values than the number of "
17790 -+ "tables in a relation result in faster optimization, but may produce "
17791 -+ "very bad query plans. If set to 0, the system will automatically pick "
17792 -+ "a reasonable value; if set to MAX_TABLES+2, the optimizer will switch "
17793 -+ "to the original find_best (used for testing/comparison).",
17794 -+ &global_system_variables.optimizer_search_depth,
17795 -+ &max_system_variables.optimizer_search_depth,
17796 -+ 0, GET_ULONG, OPT_ARG, MAX_TABLES+1, 0, MAX_TABLES+2, 0, 1, 0},
17797 -+ {"optimizer_switch", OPT_OPTIMIZER_SWITCH,
17798 -+ "optimizer_switch=option=val[,option=val...], where option={index_merge, "
17799 -+ "index_merge_union, index_merge_sort_union, index_merge_intersection} and "
17800 -+ "val={on, off, default}.",
17801 -+ &optimizer_switch_str, &optimizer_switch_str, 0, GET_STR, REQUIRED_ARG,
17802 -+ /*OPTIMIZER_SWITCH_DEFAULT*/0, 0, 0, 0, 0, 0},
17803 -+ {"plugin_dir", OPT_PLUGIN_DIR,
17804 -+ "Directory for plugins.",
17805 -+ &opt_plugin_dir_ptr, &opt_plugin_dir_ptr, 0,
17806 -+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
17807 -+ {"plugin-load", OPT_PLUGIN_LOAD,
17808 -+ "Optional semicolon-separated list of plugins to load, where each plugin is "
17809 -+ "identified as name=library, where name is the plugin name and library "
17810 -+ "is the plugin library in plugin_dir.",
17811 -+ &opt_plugin_load, &opt_plugin_load, 0,
17812 -+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
17813 -+ {"preload_buffer_size", OPT_PRELOAD_BUFFER_SIZE,
17814 -+ "The size of the buffer that is allocated when preloading indexes.",
17815 -+ &global_system_variables.preload_buff_size,
17816 -+ &max_system_variables.preload_buff_size, 0, GET_ULONG,
17817 -+ REQUIRED_ARG, 32*1024L, 1024, 1024*1024*1024L, 0, 1, 0},
17818 -+ {"query_alloc_block_size", OPT_QUERY_ALLOC_BLOCK_SIZE,
17819 -+ "Allocation block size for query parsing and execution.",
17820 -+ &global_system_variables.query_alloc_block_size,
17821 -+ &max_system_variables.query_alloc_block_size, 0, GET_ULONG,
17822 -+ REQUIRED_ARG, QUERY_ALLOC_BLOCK_SIZE, 1024, ULONG_MAX, 0, 1024, 0},
17823 -+#ifdef HAVE_QUERY_CACHE
17824 -+ {"query_cache_limit", OPT_QUERY_CACHE_LIMIT,
17825 -+ "Don't cache results that are bigger than this.",
17826 -+ &query_cache_limit, &query_cache_limit, 0, GET_ULONG,
17827 -+ REQUIRED_ARG, 1024*1024L, 0, ULONG_MAX, 0, 1, 0},
17828 -+ {"query_cache_min_res_unit", OPT_QUERY_CACHE_MIN_RES_UNIT,
17829 -+ "Minimal size of unit in which space for results is allocated (last unit "
17830 -+ "will be trimmed after writing all result data).",
17831 -+ &query_cache_min_res_unit, &query_cache_min_res_unit,
17832 -+ 0, GET_ULONG, REQUIRED_ARG, QUERY_CACHE_MIN_RESULT_DATA_SIZE,
17833 -+ 0, ULONG_MAX, 0, 1, 0},
17834 -+#endif /*HAVE_QUERY_CACHE*/
17835 -+ {"query_cache_size", OPT_QUERY_CACHE_SIZE,
17836 -+ "The memory allocated to store results from old queries.",
17837 -+ &query_cache_size, &query_cache_size, 0, GET_ULONG,
17838 -+ REQUIRED_ARG, 0, 0, (longlong) ULONG_MAX, 0, 1024, 0},
17839 -+#ifdef HAVE_QUERY_CACHE
17840 -+ {"query_cache_type", OPT_QUERY_CACHE_TYPE,
17841 -+ "0 = OFF = Don't cache or retrieve results. 1 = ON = Cache all results "
17842 -+ "except SELECT SQL_NO_CACHE ... queries. 2 = DEMAND = Cache only SELECT "
17843 -+ "SQL_CACHE ... queries.", &global_system_variables.query_cache_type,
17844 -+ &max_system_variables.query_cache_type,
17845 -+ 0, GET_ULONG, REQUIRED_ARG, 1, 0, 2, 0, 1, 0},
17846 -+ {"query_cache_wlock_invalidate", OPT_QUERY_CACHE_WLOCK_INVALIDATE,
17847 -+ "Invalidate queries in query cache on LOCK for write.",
17848 -+ &global_system_variables.query_cache_wlock_invalidate,
17849 -+ &max_system_variables.query_cache_wlock_invalidate,
17850 -+ 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 1, 0},
17851 -+#endif /*HAVE_QUERY_CACHE*/
17852 -+ {"query_prealloc_size", OPT_QUERY_PREALLOC_SIZE,
17853 -+ "Persistent buffer for query parsing and execution.",
17854 -+ &global_system_variables.query_prealloc_size,
17855 -+ &max_system_variables.query_prealloc_size, 0, GET_ULONG,
17856 -+ REQUIRED_ARG, QUERY_ALLOC_PREALLOC_SIZE, QUERY_ALLOC_PREALLOC_SIZE,
17857 -+ ULONG_MAX, 0, 1024, 0},
17858 -+ {"range_alloc_block_size", OPT_RANGE_ALLOC_BLOCK_SIZE,
17859 -+ "Allocation block size for storing ranges during optimization.",
17860 -+ &global_system_variables.range_alloc_block_size,
17861 -+ &max_system_variables.range_alloc_block_size, 0, GET_ULONG,
17862 -+ REQUIRED_ARG, RANGE_ALLOC_BLOCK_SIZE, RANGE_ALLOC_BLOCK_SIZE, ULONG_MAX,
17863 -+ 0, 1024, 0},
17864 -+ {"read_buffer_size", OPT_RECORD_BUFFER,
17865 -+ "Each thread that does a sequential scan allocates a buffer of this size "
17866 -+ "for each table it scans. If you do many sequential scans, you may want "
17867 -+ "to increase this value.", &global_system_variables.read_buff_size,
17868 -+ &max_system_variables.read_buff_size,0, GET_ULONG, REQUIRED_ARG,
17869 -+ 128*1024L, IO_SIZE*2+MALLOC_OVERHEAD, INT_MAX32, MALLOC_OVERHEAD, IO_SIZE,
17870 -+ 0},
17871 -+ {"read_only", OPT_READONLY,
17872 -+ "Make all non-temporary tables read-only, with the exception of replication "
17873 -+ "(slave) threads and users with the SUPER privilege.",
17874 -+ &opt_readonly,
17875 -+ &opt_readonly,
17876 -+ 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 1, 0},
17877 -+ {"read_rnd_buffer_size", OPT_RECORD_RND_BUFFER,
17878 -+ "When reading rows in sorted order after a sort, the rows are read through "
17879 -+ "this buffer to avoid disk seeks. If not set, then it's set to the value of "
17880 -+ "record_buffer.",
17881 -+ &global_system_variables.read_rnd_buff_size,
17882 -+ &max_system_variables.read_rnd_buff_size, 0,
17883 -+ GET_ULONG, REQUIRED_ARG, 256*1024L, IO_SIZE*2+MALLOC_OVERHEAD,
17884 -+ INT_MAX32, MALLOC_OVERHEAD, IO_SIZE, 0},
17885 -+ {"record_buffer", OPT_RECORD_BUFFER_OLD,
17886 -+ "Alias for read_buffer_size. This variable is deprecated and will be removed in a future release.",
17887 -+ &global_system_variables.read_buff_size,
17888 -+ &max_system_variables.read_buff_size,0, GET_ULONG, REQUIRED_ARG,
17889 -+ 128*1024L, IO_SIZE*2+MALLOC_OVERHEAD, INT_MAX32, MALLOC_OVERHEAD, IO_SIZE, 0},
17890 -+#ifdef HAVE_REPLICATION
17891 -+ {"relay_log_purge", OPT_RELAY_LOG_PURGE,
17892 -+ "0 = do not purge relay logs. 1 = purge them as soon as they are no more needed.",
17893 -+ &relay_log_purge,
17894 -+ &relay_log_purge, 0, GET_BOOL, NO_ARG,
17895 -+ 1, 0, 1, 0, 1, 0},
17896 -+ {"relay_log_space_limit", OPT_RELAY_LOG_SPACE_LIMIT,
17897 -+ "Maximum space to use for all relay logs.",
17898 -+ &relay_log_space_limit,
17899 -+ &relay_log_space_limit, 0, GET_ULL, REQUIRED_ARG, 0L, 0L,
17900 -+ (longlong) ULONG_MAX, 0, 1, 0},
17901 -+ {"slave_compressed_protocol", OPT_SLAVE_COMPRESSED_PROTOCOL,
17902 -+ "Use compression on master/slave protocol.",
17903 -+ &opt_slave_compressed_protocol,
17904 -+ &opt_slave_compressed_protocol,
17905 -+ 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 1, 0},
17906 -+ {"slave_net_timeout", OPT_SLAVE_NET_TIMEOUT,
17907 -+ "Number of seconds to wait for more data from a master/slave connection before aborting the read.",
17908 -+ &slave_net_timeout, &slave_net_timeout, 0,
17909 -+ GET_ULONG, REQUIRED_ARG, SLAVE_NET_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0},
17910 -+ {"slave_transaction_retries", OPT_SLAVE_TRANS_RETRIES,
17911 -+ "Number of times the slave SQL thread will retry a transaction in case "
17912 -+ "it failed with a deadlock or elapsed lock wait timeout, "
17913 -+ "before giving up and stopping.",
17914 -+ &slave_trans_retries, &slave_trans_retries, 0,
17915 -+ GET_ULONG, REQUIRED_ARG, 10L, 0L, (longlong) ULONG_MAX, 0, 1, 0},
17916 -+#endif /* HAVE_REPLICATION */
17917 -+ {"slow_launch_time", OPT_SLOW_LAUNCH_TIME,
17918 -+ "If creating the thread takes longer than this value (in seconds), "
17919 -+ "the Slow_launch_threads counter will be incremented.",
17920 -+ &slow_launch_time, &slow_launch_time, 0, GET_ULONG,
17921 -+ REQUIRED_ARG, 2L, 0L, LONG_TIMEOUT, 0, 1, 0},
17922 -+ {"sort_buffer_size", OPT_SORT_BUFFER,
17923 -+ "Each thread that needs to do a sort allocates a buffer of this size.",
17924 -+ &global_system_variables.sortbuff_size,
17925 -+ &max_system_variables.sortbuff_size, 0, GET_ULONG, REQUIRED_ARG,
17926 -+ MAX_SORT_MEMORY, MIN_SORT_MEMORY+MALLOC_OVERHEAD*2, ~0L, MALLOC_OVERHEAD,
17927 -+ 1, 0},
17928 -+ {"sync-binlog", OPT_SYNC_BINLOG,
17929 -+ "Synchronously flush binary log to disk after every #th event. "
17930 -+ "Use 0 (default) to disable synchronous flushing.",
17931 -+ &sync_binlog_period, &sync_binlog_period, 0, GET_ULONG,
17932 -+ REQUIRED_ARG, 0, 0, ULONG_MAX, 0, 1, 0},
17933 -+ {"sync-frm", OPT_SYNC_FRM, "Sync .frm to disk on create. Enabled by default.",
17934 -+ &opt_sync_frm, &opt_sync_frm, 0, GET_BOOL, NO_ARG, 1, 0,
17935 -+ 0, 0, 0, 0},
17936 -+ {"table_cache", OPT_TABLE_OPEN_CACHE,
17937 -+ "Deprecated; use --table_open_cache instead.",
17938 -+ &table_cache_size, &table_cache_size, 0, GET_ULONG,
17939 -+ REQUIRED_ARG, TABLE_OPEN_CACHE_DEFAULT, 1, 512*1024L, 0, 1, 0},
17940 -+ {"table_definition_cache", OPT_TABLE_DEF_CACHE,
17941 -+ "The number of cached table definitions.",
17942 -+ &table_def_size, &table_def_size,
17943 -+ 0, GET_ULONG, REQUIRED_ARG, TABLE_DEF_CACHE_DEFAULT, TABLE_DEF_CACHE_MIN,
17944 -+ 512*1024L, 0, 1, 0},
17945 -+ {"table_open_cache", OPT_TABLE_OPEN_CACHE,
17946 -+ "The number of cached open tables.",
17947 -+ &table_cache_size, &table_cache_size, 0, GET_ULONG,
17948 -+ REQUIRED_ARG, TABLE_OPEN_CACHE_DEFAULT, 1, 512*1024L, 0, 1, 0},
17949 -+ {"table_lock_wait_timeout", OPT_TABLE_LOCK_WAIT_TIMEOUT,
17950 -+ "Timeout in seconds to wait for a table level lock before returning an "
17951 -+ "error. Used only if the connection has active cursors.",
17952 -+ &table_lock_wait_timeout, &table_lock_wait_timeout,
17953 -+ 0, GET_ULONG, REQUIRED_ARG, 50, 1, 1024 * 1024 * 1024, 0, 1, 0},
17954 -+ {"thread_cache_size", OPT_THREAD_CACHE_SIZE,
17955 -+ "How many threads we should keep in a cache for reuse.",
17956 -+ &thread_cache_size, &thread_cache_size, 0, GET_ULONG,
17957 -+ REQUIRED_ARG, 0, 0, 16384, 0, 1, 0},
17958 -+ {"thread_concurrency", OPT_THREAD_CONCURRENCY,
17959 -+ "Permits the application to give the threads system a hint for the "
17960 -+ "desired number of threads that should be run at the same time.",
17961 -+ &concurrency, &concurrency, 0, GET_ULONG, REQUIRED_ARG,
17962 -+ DEFAULT_CONCURRENCY, 1, 512, 0, 1, 0},
17963 -+#if HAVE_POOL_OF_THREADS == 1
17964 -+ {"thread_pool_size", OPT_THREAD_CACHE_SIZE,
17965 -+ "How many threads we should create to handle query requests in case of "
17966 -+ "'thread_handling=pool-of-threads'.",
17967 -+ &thread_pool_size, &thread_pool_size, 0, GET_ULONG,
17968 -+ REQUIRED_ARG, 20, 1, 16384, 0, 1, 0},
17969 -+#endif
17970 -+ {"thread_stack", OPT_THREAD_STACK,
17971 -+ "The stack size for each thread.", &my_thread_stack_size,
17972 -+ &my_thread_stack_size, 0, GET_ULONG, REQUIRED_ARG,DEFAULT_THREAD_STACK,
17973 -+ 1024L*128L, ULONG_MAX, 0, 1024, 0},
17974 -+ { "time_format", OPT_TIME_FORMAT,
17975 -+ "The TIME format (for future).",
17976 -+ &opt_date_time_formats[MYSQL_TIMESTAMP_TIME],
17977 -+ &opt_date_time_formats[MYSQL_TIMESTAMP_TIME],
17978 -+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
17979 -+ {"tmp_table_size", OPT_TMP_TABLE_SIZE,
17980 -+ "If an internal in-memory temporary table exceeds this size, MySQL will"
17981 -+ " automatically convert it to an on-disk MyISAM table.",
17982 -+ &global_system_variables.tmp_table_size,
17983 -+ &max_system_variables.tmp_table_size, 0, GET_ULL,
17984 -+ REQUIRED_ARG, 16*1024*1024L, 1024, MAX_MEM_TABLE_SIZE, 0, 1, 0},
17985 -+ {"transaction_alloc_block_size", OPT_TRANS_ALLOC_BLOCK_SIZE,
17986 -+ "Allocation block size for transactions to be stored in binary log.",
17987 -+ &global_system_variables.trans_alloc_block_size,
17988 -+ &max_system_variables.trans_alloc_block_size, 0, GET_ULONG,
17989 -+ REQUIRED_ARG, QUERY_ALLOC_BLOCK_SIZE, 1024, ULONG_MAX, 0, 1024, 0},
17990 -+ {"transaction_prealloc_size", OPT_TRANS_PREALLOC_SIZE,
17991 -+ "Persistent buffer for transactions to be stored in binary log.",
17992 -+ &global_system_variables.trans_prealloc_size,
17993 -+ &max_system_variables.trans_prealloc_size, 0, GET_ULONG,
17994 -+ REQUIRED_ARG, TRANS_ALLOC_PREALLOC_SIZE, 1024, ULONG_MAX, 0, 1024, 0},
17995 -+ {"thread_handling", OPT_THREAD_HANDLING,
17996 -+ "Define threads usage for handling queries: "
17997 -+ "one-thread-per-connection or no-threads.", 0, 0,
17998 -+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
17999 -+ {"updatable_views_with_limit", OPT_UPDATABLE_VIEWS_WITH_LIMIT,
18000 -+ "1 = YES = Don't issue an error message (warning only) if a VIEW without "
18001 -+ "presence of a key of the underlying table is used in queries with a "
18002 -+ "LIMIT clause for updating. 0 = NO = Prohibit update of a VIEW, which "
18003 -+ "does not contain a key of the underlying table and the query uses a "
18004 -+ "LIMIT clause (usually get from GUI tools).",
18005 -+ &global_system_variables.updatable_views_with_limit,
18006 -+ &max_system_variables.updatable_views_with_limit,
18007 -+ 0, GET_ULONG, REQUIRED_ARG, 1, 0, 1, 0, 1, 0},
18008 -+ {"wait_timeout", OPT_WAIT_TIMEOUT,
18009 -+ "The number of seconds the server waits for activity on a connection before closing it.",
18010 -+ &global_system_variables.net_wait_timeout,
18011 -+ &max_system_variables.net_wait_timeout, 0, GET_ULONG,
18012 -+ REQUIRED_ARG, NET_WAIT_TIMEOUT, 1, IF_WIN(INT_MAX32/1000, LONG_TIMEOUT),
18013 -+ 0, 1, 0},
18014 -+ {"binlog-direct-non-transactional-updates", OPT_BINLOG_DIRECT_NON_TRANS_UPDATE,
18015 -+ "Causes updates to non-transactional engines using statement format to be "
18016 -+ "written directly to binary log. Before using this option, make sure that "
18017 -+ "there are no dependencies between transactional and non-transactional "
18018 -+ "tables such as in the statement INSERT INTO t_myisam SELECT * FROM "
18019 -+ "t_innodb; otherwise, slaves may diverge from the master.",
18020 -+ &global_system_variables.binlog_direct_non_trans_update,
18021 -+ &max_system_variables.binlog_direct_non_trans_update,
18022 -+ 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
18023 -+ {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
18024 -+};
18025 -+
18026 -+
18027 -+static int show_queries(THD *thd, SHOW_VAR *var, char *buff)
18028 -+{
18029 -+ var->type= SHOW_LONGLONG;
18030 -+ var->value= (char *)&thd->query_id;
18031 -+ return 0;
18032 -+}
18033 -+
18034 -+
18035 -+static int show_net_compression(THD *thd, SHOW_VAR *var, char *buff)
18036 -+{
18037 -+ var->type= SHOW_MY_BOOL;
18038 -+ var->value= (char *)&thd->net.compress;
18039 -+ return 0;
18040 -+}
18041 -+
18042 -+static int show_starttime(THD *thd, SHOW_VAR *var, char *buff)
18043 -+{
18044 -+ var->type= SHOW_LONG;
18045 -+ var->value= buff;
18046 -+ *((long *)buff)= (long) (thd->query_start() - server_start_time);
18047 -+ return 0;
18048 -+}
18049 -+
18050 -+#ifdef COMMUNITY_SERVER
18051 -+static int show_flushstatustime(THD *thd, SHOW_VAR *var, char *buff)
18052 -+{
18053 -+ var->type= SHOW_LONG;
18054 -+ var->value= buff;
18055 -+ *((long *)buff)= (long) (thd->query_start() - flush_status_time);
18056 -+ return 0;
18057 -+}
18058 -+#endif
18059 -+
18060 -+#ifdef HAVE_REPLICATION
18061 -+static int show_rpl_status(THD *thd, SHOW_VAR *var, char *buff)
18062 -+{
18063 -+ var->type= SHOW_CHAR;
18064 -+ var->value= const_cast<char*>(rpl_status_type[(int)rpl_status]);
18065 -+ return 0;
18066 -+}
18067 -+
18068 -+static int show_slave_running(THD *thd, SHOW_VAR *var, char *buff)
18069 -+{
18070 -+ var->type= SHOW_MY_BOOL;
18071 -+ pthread_mutex_lock(&LOCK_active_mi);
18072 -+ var->value= buff;
18073 -+ *((my_bool *)buff)= (my_bool) (active_mi &&
18074 -+ active_mi->slave_running == MYSQL_SLAVE_RUN_CONNECT &&
18075 -+ active_mi->rli.slave_running);
18076 -+ pthread_mutex_unlock(&LOCK_active_mi);
18077 -+ return 0;
18078 -+}
18079 -+
18080 -+static int show_slave_retried_trans(THD *thd, SHOW_VAR *var, char *buff)
18081 -+{
18082 -+ /*
18083 -+ TODO: with multimaster, have one such counter per line in
18084 -+ SHOW SLAVE STATUS, and have the sum over all lines here.
18085 -+ */
18086 -+ pthread_mutex_lock(&LOCK_active_mi);
18087 -+ if (active_mi)
18088 -+ {
18089 -+ var->type= SHOW_LONG;
18090 -+ var->value= buff;
18091 -+ pthread_mutex_lock(&active_mi->rli.data_lock);
18092 -+ *((long *)buff)= (long)active_mi->rli.retried_trans;
18093 -+ pthread_mutex_unlock(&active_mi->rli.data_lock);
18094 -+ }
18095 -+ else
18096 -+ var->type= SHOW_UNDEF;
18097 -+ pthread_mutex_unlock(&LOCK_active_mi);
18098 -+ return 0;
18099 -+}
18100 -+#endif /* HAVE_REPLICATION */
18101 -+
18102 -+static int show_open_tables(THD *thd, SHOW_VAR *var, char *buff)
18103 -+{
18104 -+ var->type= SHOW_LONG;
18105 -+ var->value= buff;
18106 -+ *((long *)buff)= (long)cached_open_tables();
18107 -+ return 0;
18108 -+}
18109 -+
18110 -+static int show_prepared_stmt_count(THD *thd, SHOW_VAR *var, char *buff)
18111 -+{
18112 -+ var->type= SHOW_LONG;
18113 -+ var->value= buff;
18114 -+ pthread_mutex_lock(&LOCK_prepared_stmt_count);
18115 -+ *((long *)buff)= (long)prepared_stmt_count;
18116 -+ pthread_mutex_unlock(&LOCK_prepared_stmt_count);
18117 -+ return 0;
18118 -+}
18119 -+
18120 -+static int show_table_definitions(THD *thd, SHOW_VAR *var, char *buff)
18121 -+{
18122 -+ var->type= SHOW_LONG;
18123 -+ var->value= buff;
18124 -+ *((long *)buff)= (long)cached_table_definitions();
18125 -+ return 0;
18126 -+}
18127 -+
18128 -+#ifdef HAVE_OPENSSL
18129 -+/* Functions relying on CTX */
18130 -+static int show_ssl_ctx_sess_accept(THD *thd, SHOW_VAR *var, char *buff)
18131 -+{
18132 -+ var->type= SHOW_LONG;
18133 -+ var->value= buff;
18134 -+ *((long *)buff)= (!ssl_acceptor_fd ? 0 :
18135 -+ SSL_CTX_sess_accept(ssl_acceptor_fd->ssl_context));
18136 -+ return 0;
18137 -+}
18138 -+
18139 -+static int show_ssl_ctx_sess_accept_good(THD *thd, SHOW_VAR *var, char *buff)
18140 -+{
18141 -+ var->type= SHOW_LONG;
18142 -+ var->value= buff;
18143 -+ *((long *)buff)= (!ssl_acceptor_fd ? 0 :
18144 -+ SSL_CTX_sess_accept_good(ssl_acceptor_fd->ssl_context));
18145 -+ return 0;
18146 -+}
18147 -+
18148 -+static int show_ssl_ctx_sess_connect_good(THD *thd, SHOW_VAR *var, char *buff)
18149 -+{
18150 -+ var->type= SHOW_LONG;
18151 -+ var->value= buff;
18152 -+ *((long *)buff)= (!ssl_acceptor_fd ? 0 :
18153 -+ SSL_CTX_sess_connect_good(ssl_acceptor_fd->ssl_context));
18154 -+ return 0;
18155 -+}
18156 -+
18157 -+static int show_ssl_ctx_sess_accept_renegotiate(THD *thd, SHOW_VAR *var, char *buff)
18158 -+{
18159 -+ var->type= SHOW_LONG;
18160 -+ var->value= buff;
18161 -+ *((long *)buff)= (!ssl_acceptor_fd ? 0 :
18162 -+ SSL_CTX_sess_accept_renegotiate(ssl_acceptor_fd->ssl_context));
18163 -+ return 0;
18164 -+}
18165 -+
18166 -+static int show_ssl_ctx_sess_connect_renegotiate(THD *thd, SHOW_VAR *var, char *buff)
18167 -+{
18168 -+ var->type= SHOW_LONG;
18169 -+ var->value= buff;
18170 -+ *((long *)buff)= (!ssl_acceptor_fd ? 0 :
18171 -+ SSL_CTX_sess_connect_renegotiate(ssl_acceptor_fd->ssl_context));
18172 -+ return 0;
18173 -+}
18174 -+
18175 -+static int show_ssl_ctx_sess_cb_hits(THD *thd, SHOW_VAR *var, char *buff)
18176 -+{
18177 -+ var->type= SHOW_LONG;
18178 -+ var->value= buff;
18179 -+ *((long *)buff)= (!ssl_acceptor_fd ? 0 :
18180 -+ SSL_CTX_sess_cb_hits(ssl_acceptor_fd->ssl_context));
18181 -+ return 0;
18182 -+}
18183 -+
18184 -+static int show_ssl_ctx_sess_hits(THD *thd, SHOW_VAR *var, char *buff)
18185 -+{
18186 -+ var->type= SHOW_LONG;
18187 -+ var->value= buff;
18188 -+ *((long *)buff)= (!ssl_acceptor_fd ? 0 :
18189 -+ SSL_CTX_sess_hits(ssl_acceptor_fd->ssl_context));
18190 -+ return 0;
18191 -+}
18192 -+
18193 -+static int show_ssl_ctx_sess_cache_full(THD *thd, SHOW_VAR *var, char *buff)
18194 -+{
18195 -+ var->type= SHOW_LONG;
18196 -+ var->value= buff;
18197 -+ *((long *)buff)= (!ssl_acceptor_fd ? 0 :
18198 -+ SSL_CTX_sess_cache_full(ssl_acceptor_fd->ssl_context));
18199 -+ return 0;
18200 -+}
18201 -+
18202 -+static int show_ssl_ctx_sess_misses(THD *thd, SHOW_VAR *var, char *buff)
18203 -+{
18204 -+ var->type= SHOW_LONG;
18205 -+ var->value= buff;
18206 -+ *((long *)buff)= (!ssl_acceptor_fd ? 0 :
18207 -+ SSL_CTX_sess_misses(ssl_acceptor_fd->ssl_context));
18208 -+ return 0;
18209 -+}
18210 -+
18211 -+static int show_ssl_ctx_sess_timeouts(THD *thd, SHOW_VAR *var, char *buff)
18212 -+{
18213 -+ var->type= SHOW_LONG;
18214 -+ var->value= buff;
18215 -+ *((long *)buff)= (!ssl_acceptor_fd ? 0 :
18216 -+ SSL_CTX_sess_timeouts(ssl_acceptor_fd->ssl_context));
18217 -+ return 0;
18218 -+}
18219 -+
18220 -+static int show_ssl_ctx_sess_number(THD *thd, SHOW_VAR *var, char *buff)
18221 -+{
18222 -+ var->type= SHOW_LONG;
18223 -+ var->value= buff;
18224 -+ *((long *)buff)= (!ssl_acceptor_fd ? 0 :
18225 -+ SSL_CTX_sess_number(ssl_acceptor_fd->ssl_context));
18226 -+ return 0;
18227 -+}
18228 -+
18229 -+static int show_ssl_ctx_sess_connect(THD *thd, SHOW_VAR *var, char *buff)
18230 -+{
18231 -+ var->type= SHOW_LONG;
18232 -+ var->value= buff;
18233 -+ *((long *)buff)= (!ssl_acceptor_fd ? 0 :
18234 -+ SSL_CTX_sess_connect(ssl_acceptor_fd->ssl_context));
18235 -+ return 0;
18236 -+}
18237 -+
18238 -+static int show_ssl_ctx_sess_get_cache_size(THD *thd, SHOW_VAR *var, char *buff)
18239 -+{
18240 -+ var->type= SHOW_LONG;
18241 -+ var->value= buff;
18242 -+ *((long *)buff)= (!ssl_acceptor_fd ? 0 :
18243 -+ SSL_CTX_sess_get_cache_size(ssl_acceptor_fd->ssl_context));
18244 -+ return 0;
18245 -+}
18246 -+
18247 -+static int show_ssl_ctx_get_verify_mode(THD *thd, SHOW_VAR *var, char *buff)
18248 -+{
18249 -+ var->type= SHOW_LONG;
18250 -+ var->value= buff;
18251 -+ *((long *)buff)= (!ssl_acceptor_fd ? 0 :
18252 -+ SSL_CTX_get_verify_mode(ssl_acceptor_fd->ssl_context));
18253 -+ return 0;
18254 -+}
18255 -+
18256 -+static int show_ssl_ctx_get_verify_depth(THD *thd, SHOW_VAR *var, char *buff)
18257 -+{
18258 -+ var->type= SHOW_LONG;
18259 -+ var->value= buff;
18260 -+ *((long *)buff)= (!ssl_acceptor_fd ? 0 :
18261 -+ SSL_CTX_get_verify_depth(ssl_acceptor_fd->ssl_context));
18262 -+ return 0;
18263 -+}
18264 -+
18265 -+static int show_ssl_ctx_get_session_cache_mode(THD *thd, SHOW_VAR *var, char *buff)
18266 -+{
18267 -+ var->type= SHOW_CHAR;
18268 -+ if (!ssl_acceptor_fd)
18269 -+ var->value= const_cast<char*>("NONE");
18270 -+ else
18271 -+ switch (SSL_CTX_get_session_cache_mode(ssl_acceptor_fd->ssl_context))
18272 -+ {
18273 -+ case SSL_SESS_CACHE_OFF:
18274 -+ var->value= const_cast<char*>("OFF"); break;
18275 -+ case SSL_SESS_CACHE_CLIENT:
18276 -+ var->value= const_cast<char*>("CLIENT"); break;
18277 -+ case SSL_SESS_CACHE_SERVER:
18278 -+ var->value= const_cast<char*>("SERVER"); break;
18279 -+ case SSL_SESS_CACHE_BOTH:
18280 -+ var->value= const_cast<char*>("BOTH"); break;
18281 -+ case SSL_SESS_CACHE_NO_AUTO_CLEAR:
18282 -+ var->value= const_cast<char*>("NO_AUTO_CLEAR"); break;
18283 -+ case SSL_SESS_CACHE_NO_INTERNAL_LOOKUP:
18284 -+ var->value= const_cast<char*>("NO_INTERNAL_LOOKUP"); break;
18285 -+ default:
18286 -+ var->value= const_cast<char*>("Unknown"); break;
18287 -+ }
18288 -+ return 0;
18289 -+}
18290 -+
18291 -+/*
18292 -+ Functions relying on SSL
18293 -+ Note: In the show_ssl_* functions, we need to check if we have a
18294 -+ valid vio-object since this isn't always true, specifically
18295 -+ when session_status or global_status is requested from
18296 -+ inside an Event.
18297 -+ */
18298 -+static int show_ssl_get_version(THD *thd, SHOW_VAR *var, char *buff)
18299 -+{
18300 -+ var->type= SHOW_CHAR;
18301 -+ if( thd->vio_ok() && thd->net.vio->ssl_arg )
18302 -+ var->value= const_cast<char*>(SSL_get_version((SSL*) thd->net.vio->ssl_arg));
18303 -+ else
18304 -+ var->value= (char *)"";
18305 -+ return 0;
18306 -+}
18307 -+
18308 -+static int show_ssl_session_reused(THD *thd, SHOW_VAR *var, char *buff)
18309 -+{
18310 -+ var->type= SHOW_LONG;
18311 -+ var->value= buff;
18312 -+ if( thd->vio_ok() && thd->net.vio->ssl_arg )
18313 -+ *((long *)buff)= (long)SSL_session_reused((SSL*) thd->net.vio->ssl_arg);
18314 -+ else
18315 -+ *((long *)buff)= 0;
18316 -+ return 0;
18317 -+}
18318 -+
18319 -+static int show_ssl_get_default_timeout(THD *thd, SHOW_VAR *var, char *buff)
18320 -+{
18321 -+ var->type= SHOW_LONG;
18322 -+ var->value= buff;
18323 -+ if( thd->vio_ok() && thd->net.vio->ssl_arg )
18324 -+ *((long *)buff)= (long)SSL_get_default_timeout((SSL*)thd->net.vio->ssl_arg);
18325 -+ else
18326 -+ *((long *)buff)= 0;
18327 -+ return 0;
18328 -+}
18329 -+
18330 -+static int show_ssl_get_verify_mode(THD *thd, SHOW_VAR *var, char *buff)
18331 -+{
18332 -+ var->type= SHOW_LONG;
18333 -+ var->value= buff;
18334 -+ if( thd->net.vio && thd->net.vio->ssl_arg )
18335 -+ *((long *)buff)= (long)SSL_get_verify_mode((SSL*)thd->net.vio->ssl_arg);
18336 -+ else
18337 -+ *((long *)buff)= 0;
18338 -+ return 0;
18339 -+}
18340 -+
18341 -+static int show_ssl_get_verify_depth(THD *thd, SHOW_VAR *var, char *buff)
18342 -+{
18343 -+ var->type= SHOW_LONG;
18344 -+ var->value= buff;
18345 -+ if( thd->vio_ok() && thd->net.vio->ssl_arg )
18346 -+ *((long *)buff)= (long)SSL_get_verify_depth((SSL*)thd->net.vio->ssl_arg);
18347 -+ else
18348 -+ *((long *)buff)= 0;
18349 -+ return 0;
18350 -+}
18351 -+
18352 -+static int show_ssl_get_cipher(THD *thd, SHOW_VAR *var, char *buff)
18353 -+{
18354 -+ var->type= SHOW_CHAR;
18355 -+ if( thd->vio_ok() && thd->net.vio->ssl_arg )
18356 -+ var->value= const_cast<char*>(SSL_get_cipher((SSL*) thd->net.vio->ssl_arg));
18357 -+ else
18358 -+ var->value= (char *)"";
18359 -+ return 0;
18360 -+}
18361 -+
18362 -+static int show_ssl_get_cipher_list(THD *thd, SHOW_VAR *var, char *buff)
18363 -+{
18364 -+ var->type= SHOW_CHAR;
18365 -+ var->value= buff;
18366 -+ if (thd->vio_ok() && thd->net.vio->ssl_arg)
18367 -+ {
18368 -+ int i;
18369 -+ const char *p;
18370 -+ char *end= buff + SHOW_VAR_FUNC_BUFF_SIZE;
18371 -+ for (i=0; (p= SSL_get_cipher_list((SSL*) thd->net.vio->ssl_arg,i)) &&
18372 -+ buff < end; i++)
18373 -+ {
18374 -+ buff= strnmov(buff, p, end-buff-1);
18375 -+ *buff++= ':';
18376 -+ }
18377 -+ if (i)
18378 -+ buff--;
18379 -+ }
18380 -+ *buff=0;
18381 -+ return 0;
18382 -+}
18383 -+
18384 -+#endif /* HAVE_OPENSSL */
18385 -+
18386 -+
18387 -+/*
18388 -+ Variables shown by SHOW STATUS in alphabetical order
18389 -+*/
18390 -+
18391 -+SHOW_VAR status_vars[]= {
18392 -+ {"Aborted_clients", (char*) &aborted_threads, SHOW_LONG},
18393 -+ {"Aborted_connects", (char*) &aborted_connects, SHOW_LONG},
18394 -+ {"Binlog_cache_disk_use", (char*) &binlog_cache_disk_use, SHOW_LONG},
18395 -+ {"Binlog_cache_use", (char*) &binlog_cache_use, SHOW_LONG},
18396 -+ {"Bytes_received", (char*) offsetof(STATUS_VAR, bytes_received), SHOW_LONGLONG_STATUS},
18397 -+ {"Bytes_sent", (char*) offsetof(STATUS_VAR, bytes_sent), SHOW_LONGLONG_STATUS},
18398 -+ {"Com", (char*) com_status_vars, SHOW_ARRAY},
18399 -+ {"Compression", (char*) &show_net_compression, SHOW_FUNC},
18400 -+ {"Connections", (char*) &thread_id, SHOW_LONG_NOFLUSH},
18401 -+ {"Created_tmp_disk_tables", (char*) offsetof(STATUS_VAR, created_tmp_disk_tables), SHOW_LONG_STATUS},
18402 -+ {"Created_tmp_files", (char*) &my_tmp_file_created, SHOW_LONG},
18403 -+ {"Created_tmp_tables", (char*) offsetof(STATUS_VAR, created_tmp_tables), SHOW_LONG_STATUS},
18404 -+ {"Delayed_errors", (char*) &delayed_insert_errors, SHOW_LONG},
18405 -+ {"Delayed_insert_threads", (char*) &delayed_insert_threads, SHOW_LONG_NOFLUSH},
18406 -+ {"Delayed_writes", (char*) &delayed_insert_writes, SHOW_LONG},
18407 -+ {"Flush_commands", (char*) &refresh_version, SHOW_LONG_NOFLUSH},
18408 -+ {"Handler_commit", (char*) offsetof(STATUS_VAR, ha_commit_count), SHOW_LONG_STATUS},
18409 -+ {"Handler_delete", (char*) offsetof(STATUS_VAR, ha_delete_count), SHOW_LONG_STATUS},
18410 -+ {"Handler_discover", (char*) offsetof(STATUS_VAR, ha_discover_count), SHOW_LONG_STATUS},
18411 -+ {"Handler_prepare", (char*) offsetof(STATUS_VAR, ha_prepare_count), SHOW_LONG_STATUS},
18412 -+ {"Handler_read_first", (char*) offsetof(STATUS_VAR, ha_read_first_count), SHOW_LONG_STATUS},
18413 -+ {"Handler_read_key", (char*) offsetof(STATUS_VAR, ha_read_key_count), SHOW_LONG_STATUS},
18414 -+ {"Handler_read_next", (char*) offsetof(STATUS_VAR, ha_read_next_count), SHOW_LONG_STATUS},
18415 -+ {"Handler_read_prev", (char*) offsetof(STATUS_VAR, ha_read_prev_count), SHOW_LONG_STATUS},
18416 -+ {"Handler_read_rnd", (char*) offsetof(STATUS_VAR, ha_read_rnd_count), SHOW_LONG_STATUS},
18417 -+ {"Handler_read_rnd_next", (char*) offsetof(STATUS_VAR, ha_read_rnd_next_count), SHOW_LONG_STATUS},
18418 -+ {"Handler_rollback", (char*) offsetof(STATUS_VAR, ha_rollback_count), SHOW_LONG_STATUS},
18419 -+ {"Handler_savepoint", (char*) offsetof(STATUS_VAR, ha_savepoint_count), SHOW_LONG_STATUS},
18420 -+ {"Handler_savepoint_rollback",(char*) offsetof(STATUS_VAR, ha_savepoint_rollback_count), SHOW_LONG_STATUS},
18421 -+ {"Handler_update", (char*) offsetof(STATUS_VAR, ha_update_count), SHOW_LONG_STATUS},
18422 -+ {"Handler_write", (char*) offsetof(STATUS_VAR, ha_write_count), SHOW_LONG_STATUS},
18423 -+ {"Key_blocks_not_flushed", (char*) offsetof(KEY_CACHE, global_blocks_changed), SHOW_KEY_CACHE_LONG},
18424 -+ {"Key_blocks_unused", (char*) offsetof(KEY_CACHE, blocks_unused), SHOW_KEY_CACHE_LONG},
18425 -+ {"Key_blocks_used", (char*) offsetof(KEY_CACHE, blocks_used), SHOW_KEY_CACHE_LONG},
18426 -+ {"Key_read_requests", (char*) offsetof(KEY_CACHE, global_cache_r_requests), SHOW_KEY_CACHE_LONGLONG},
18427 -+ {"Key_reads", (char*) offsetof(KEY_CACHE, global_cache_read), SHOW_KEY_CACHE_LONGLONG},
18428 -+ {"Key_write_requests", (char*) offsetof(KEY_CACHE, global_cache_w_requests), SHOW_KEY_CACHE_LONGLONG},
18429 -+ {"Key_writes", (char*) offsetof(KEY_CACHE, global_cache_write), SHOW_KEY_CACHE_LONGLONG},
18430 -+ {"Last_query_cost", (char*) offsetof(STATUS_VAR, last_query_cost), SHOW_DOUBLE_STATUS},
18431 -+ {"Max_used_connections", (char*) &max_used_connections, SHOW_LONG},
18432 -+ {"Not_flushed_delayed_rows", (char*) &delayed_rows_in_use, SHOW_LONG_NOFLUSH},
18433 -+ {"Open_files", (char*) &my_file_opened, SHOW_LONG_NOFLUSH},
18434 -+ {"Open_streams", (char*) &my_stream_opened, SHOW_LONG_NOFLUSH},
18435 -+ {"Open_table_definitions", (char*) &show_table_definitions, SHOW_FUNC},
18436 -+ {"Open_tables", (char*) &show_open_tables, SHOW_FUNC},
18437 -+ {"Opened_files", (char*) &my_file_total_opened, SHOW_LONG_NOFLUSH},
18438 -+ {"Opened_tables", (char*) offsetof(STATUS_VAR, opened_tables), SHOW_LONG_STATUS},
18439 -+ {"Opened_table_definitions", (char*) offsetof(STATUS_VAR, opened_shares), SHOW_LONG_STATUS},
18440 -+ {"Prepared_stmt_count", (char*) &show_prepared_stmt_count, SHOW_FUNC},
18441 -+#ifdef HAVE_QUERY_CACHE
18442 -+ {"Qcache_free_blocks", (char*) &query_cache.free_memory_blocks, SHOW_LONG_NOFLUSH},
18443 -+ {"Qcache_free_memory", (char*) &query_cache.free_memory, SHOW_LONG_NOFLUSH},
18444 -+ {"Qcache_hits", (char*) &query_cache.hits, SHOW_LONG},
18445 -+ {"Qcache_inserts", (char*) &query_cache.inserts, SHOW_LONG},
18446 -+ {"Qcache_lowmem_prunes", (char*) &query_cache.lowmem_prunes, SHOW_LONG},
18447 -+ {"Qcache_not_cached", (char*) &query_cache.refused, SHOW_LONG},
18448 -+ {"Qcache_queries_in_cache", (char*) &query_cache.queries_in_cache, SHOW_LONG_NOFLUSH},
18449 -+ {"Qcache_total_blocks", (char*) &query_cache.total_blocks, SHOW_LONG_NOFLUSH},
18450 -+#endif /*HAVE_QUERY_CACHE*/
18451 -+ {"Queries", (char*) &show_queries, SHOW_FUNC},
18452 -+ {"Questions", (char*) offsetof(STATUS_VAR, questions), SHOW_LONG_STATUS},
18453 -+#ifdef HAVE_REPLICATION
18454 -+ {"Rpl_status", (char*) &show_rpl_status, SHOW_FUNC},
18455 -+#endif
18456 -+ {"Select_full_join", (char*) offsetof(STATUS_VAR, select_full_join_count), SHOW_LONG_STATUS},
18457 -+ {"Select_full_range_join", (char*) offsetof(STATUS_VAR, select_full_range_join_count), SHOW_LONG_STATUS},
18458 -+ {"Select_range", (char*) offsetof(STATUS_VAR, select_range_count), SHOW_LONG_STATUS},
18459 -+ {"Select_range_check", (char*) offsetof(STATUS_VAR, select_range_check_count), SHOW_LONG_STATUS},
18460 -+ {"Select_scan", (char*) offsetof(STATUS_VAR, select_scan_count), SHOW_LONG_STATUS},
18461 -+ {"Slave_open_temp_tables", (char*) &slave_open_temp_tables, SHOW_LONG},
18462 -+#ifdef HAVE_REPLICATION
18463 -+ {"Slave_retried_transactions",(char*) &show_slave_retried_trans, SHOW_FUNC},
18464 -+ {"Slave_running", (char*) &show_slave_running, SHOW_FUNC},
18465 -+#endif
18466 -+ {"Slow_launch_threads", (char*) &slow_launch_threads, SHOW_LONG},
18467 -+ {"Slow_queries", (char*) offsetof(STATUS_VAR, long_query_count), SHOW_LONG_STATUS},
18468 -+ {"Sort_merge_passes", (char*) offsetof(STATUS_VAR, filesort_merge_passes), SHOW_LONG_STATUS},
18469 -+ {"Sort_range", (char*) offsetof(STATUS_VAR, filesort_range_count), SHOW_LONG_STATUS},
18470 -+ {"Sort_rows", (char*) offsetof(STATUS_VAR, filesort_rows), SHOW_LONG_STATUS},
18471 -+ {"Sort_scan", (char*) offsetof(STATUS_VAR, filesort_scan_count), SHOW_LONG_STATUS},
18472 -+#ifdef HAVE_OPENSSL
18473 -+ {"Ssl_accept_renegotiates", (char*) &show_ssl_ctx_sess_accept_renegotiate, SHOW_FUNC},
18474 -+ {"Ssl_accepts", (char*) &show_ssl_ctx_sess_accept, SHOW_FUNC},
18475 -+ {"Ssl_callback_cache_hits", (char*) &show_ssl_ctx_sess_cb_hits, SHOW_FUNC},
18476 -+ {"Ssl_cipher", (char*) &show_ssl_get_cipher, SHOW_FUNC},
18477 -+ {"Ssl_cipher_list", (char*) &show_ssl_get_cipher_list, SHOW_FUNC},
18478 -+ {"Ssl_client_connects", (char*) &show_ssl_ctx_sess_connect, SHOW_FUNC},
18479 -+ {"Ssl_connect_renegotiates", (char*) &show_ssl_ctx_sess_connect_renegotiate, SHOW_FUNC},
18480 -+ {"Ssl_ctx_verify_depth", (char*) &show_ssl_ctx_get_verify_depth, SHOW_FUNC},
18481 -+ {"Ssl_ctx_verify_mode", (char*) &show_ssl_ctx_get_verify_mode, SHOW_FUNC},
18482 -+ {"Ssl_default_timeout", (char*) &show_ssl_get_default_timeout, SHOW_FUNC},
18483 -+ {"Ssl_finished_accepts", (char*) &show_ssl_ctx_sess_accept_good, SHOW_FUNC},
18484 -+ {"Ssl_finished_connects", (char*) &show_ssl_ctx_sess_connect_good, SHOW_FUNC},
18485 -+ {"Ssl_session_cache_hits", (char*) &show_ssl_ctx_sess_hits, SHOW_FUNC},
18486 -+ {"Ssl_session_cache_misses", (char*) &show_ssl_ctx_sess_misses, SHOW_FUNC},
18487 -+ {"Ssl_session_cache_mode", (char*) &show_ssl_ctx_get_session_cache_mode, SHOW_FUNC},
18488 -+ {"Ssl_session_cache_overflows", (char*) &show_ssl_ctx_sess_cache_full, SHOW_FUNC},
18489 -+ {"Ssl_session_cache_size", (char*) &show_ssl_ctx_sess_get_cache_size, SHOW_FUNC},
18490 -+ {"Ssl_session_cache_timeouts", (char*) &show_ssl_ctx_sess_timeouts, SHOW_FUNC},
18491 -+ {"Ssl_sessions_reused", (char*) &show_ssl_session_reused, SHOW_FUNC},
18492 -+ {"Ssl_used_session_cache_entries",(char*) &show_ssl_ctx_sess_number, SHOW_FUNC},
18493 -+ {"Ssl_verify_depth", (char*) &show_ssl_get_verify_depth, SHOW_FUNC},
18494 -+ {"Ssl_verify_mode", (char*) &show_ssl_get_verify_mode, SHOW_FUNC},
18495 -+ {"Ssl_version", (char*) &show_ssl_get_version, SHOW_FUNC},
18496 -+#endif /* HAVE_OPENSSL */
18497 -+ {"Table_locks_immediate", (char*) &locks_immediate, SHOW_LONG},
18498 -+ {"Table_locks_waited", (char*) &locks_waited, SHOW_LONG},
18499 -+#ifdef HAVE_MMAP
18500 -+ {"Tc_log_max_pages_used", (char*) &tc_log_max_pages_used, SHOW_LONG},
18501 -+ {"Tc_log_page_size", (char*) &tc_log_page_size, SHOW_LONG},
18502 -+ {"Tc_log_page_waits", (char*) &tc_log_page_waits, SHOW_LONG},
18503 -+#endif
18504 -+ {"Threads_cached", (char*) &cached_thread_count, SHOW_LONG_NOFLUSH},
18505 -+ {"Threads_connected", (char*) &thread_count, SHOW_INT},
18506 -+ {"Threads_created", (char*) &thread_created, SHOW_LONG_NOFLUSH},
18507 -+ {"Threads_running", (char*) &thread_running, SHOW_INT},
18508 -+ {"Uptime", (char*) &show_starttime, SHOW_FUNC},
18509 -+#ifdef COMMUNITY_SERVER
18510 -+ {"Uptime_since_flush_status",(char*) &show_flushstatustime, SHOW_FUNC},
18511 -+#endif
18512 -+ {NullS, NullS, SHOW_LONG}
18513 -+};
18514 -+
18515 -+#ifndef EMBEDDED_LIBRARY
18516 -+static void print_version(void)
18517 -+{
18518 -+ set_server_version();
18519 -+ /*
18520 -+ Note: the instance manager keys off the string 'Ver' so it can find the
18521 -+ version from the output of 'mysqld --version', so don't change it!
18522 -+ */
18523 -+ printf("%s Ver %s for %s on %s (%s)\n",my_progname,
18524 -+ server_version,SYSTEM_TYPE,MACHINE_TYPE, MYSQL_COMPILATION_COMMENT);
18525 -+}
18526 -+
18527 -+static void usage(void)
18528 -+{
18529 -+ if (!(default_charset_info= get_charset_by_csname(default_character_set_name,
18530 -+ MY_CS_PRIMARY,
18531 -+ MYF(MY_WME))))
18532 -+ exit(1);
18533 -+ if (!default_collation_name)
18534 -+ default_collation_name= (char*) default_charset_info->name;
18535 -+ print_version();
18536 -+ puts("\
18537 -+Copyright (C) 2000-2008 MySQL AB, by Monty and others.\n\
18538 -+Copyright (C) 2008 Sun Microsystems, Inc.\n\
18539 -+This software comes with ABSOLUTELY NO WARRANTY. This is free software,\n\
18540 -+and you are welcome to modify and redistribute it under the GPL license\n\n\
18541 -+Starts the MySQL database server.\n");
18542 -+
18543 -+ printf("Usage: %s [OPTIONS]\n", my_progname);
18544 -+ if (!opt_verbose)
18545 -+ puts("\nFor more help options (several pages), use mysqld --verbose --help.");
18546 -+ else
18547 -+ {
18548 -+#ifdef __WIN__
18549 -+ puts("NT and Win32 specific options:\n\
18550 -+ --install Install the default service (NT).\n\
18551 -+ --install-manual Install the default service started manually (NT).\n\
18552 -+ --install service_name Install an optional service (NT).\n\
18553 -+ --install-manual service_name Install an optional service started manually (NT).\n\
18554 -+ --remove Remove the default service from the service list (NT).\n\
18555 -+ --remove service_name Remove the service_name from the service list (NT).\n\
18556 -+ --enable-named-pipe Only to be used for the default server (NT).\n\
18557 -+ --standalone Dummy option to start as a standalone server (NT).\
18558 -+");
18559 -+ puts("");
18560 -+#endif
18561 -+ print_defaults(MYSQL_CONFIG_NAME,load_default_groups);
18562 -+ puts("");
18563 -+ set_ports();
18564 -+
18565 -+ /* Print out all the options including plugin supplied options */
18566 -+ my_print_help_inc_plugins(my_long_options, sizeof(my_long_options)/sizeof(my_option));
18567 -+
18568 -+ if (! plugins_are_initialized)
18569 -+ {
18570 -+ puts("\n\
18571 -+Plugins have parameters that are not reflected in this list\n\
18572 -+because execution stopped before plugins were initialized.");
18573 -+ }
18574 -+
18575 -+ puts("\n\
18576 -+To see what values a running MySQL server is using, type\n\
18577 -+'mysqladmin variables' instead of 'mysqld --verbose --help'.");
18578 -+ }
18579 -+}
18580 -+#endif /*!EMBEDDED_LIBRARY*/
18581 -+
18582 -+
18583 -+/**
18584 -+ Initialize all MySQL global variables to default values.
18585 -+
18586 -+ We don't need to set numeric variables refered to in my_long_options
18587 -+ as these are initialized by my_getopt.
18588 -+
18589 -+ @note
18590 -+ The reason to set a lot of global variables to zero is to allow one to
18591 -+ restart the embedded server with a clean environment
18592 -+ It's also needed on some exotic platforms where global variables are
18593 -+ not set to 0 when a program starts.
18594 -+
18595 -+ We don't need to set numeric variables refered to in my_long_options
18596 -+ as these are initialized by my_getopt.
18597 -+*/
18598 -+
18599 -+static int mysql_init_variables(void)
18600 -+{
18601 -+ int error;
18602 -+ /* Things reset to zero */
18603 -+ opt_skip_slave_start= opt_reckless_slave = 0;
18604 -+ mysql_home[0]= pidfile_name[0]= log_error_file[0]= 0;
18605 -+ myisam_test_invalid_symlink= test_if_data_home_dir;
18606 -+ opt_log= opt_slow_log= 0;
18607 -+ opt_update_log= 0;
18608 -+ log_output_options= find_bit_type(log_output_str, &log_output_typelib);
18609 -+ opt_bin_log= 0;
18610 -+ opt_disable_networking= opt_skip_show_db=0;
18611 -+ opt_skip_name_resolve= 0;
18612 -+ opt_ignore_builtin_innodb= 0;
18613 -+ opt_logname= opt_update_logname= opt_binlog_index_name= opt_slow_logname= 0;
18614 -+ opt_tc_log_file= (char *)"tc.log"; // no hostname in tc_log file name !
18615 -+ opt_secure_auth= 0;
18616 -+ opt_secure_file_priv= 0;
18617 -+ opt_bootstrap= opt_myisam_log= 0;
18618 -+ mqh_used= 0;
18619 -+ segfaulted= kill_in_progress= 0;
18620 -+ cleanup_done= 0;
18621 -+ defaults_argc= 0;
18622 -+ defaults_argv= 0;
18623 -+ server_id_supplied= 0;
18624 -+ test_flags= select_errors= dropping_tables= ha_open_options=0;
18625 -+ thread_count= thread_running= kill_cached_threads= wake_thread=0;
18626 -+ slave_open_temp_tables= 0;
18627 -+ cached_thread_count= 0;
18628 -+ opt_endinfo= using_udf_functions= 0;
18629 -+ opt_using_transactions= 0;
18630 -+ abort_loop= select_thread_in_use= signal_thread_in_use= 0;
18631 -+ ready_to_exit= shutdown_in_progress= grant_option= 0;
18632 -+ aborted_threads= aborted_connects= 0;
18633 -+ delayed_insert_threads= delayed_insert_writes= delayed_rows_in_use= 0;
18634 -+ delayed_insert_errors= thread_created= 0;
18635 -+ specialflag= 0;
18636 -+ binlog_cache_use= binlog_cache_disk_use= 0;
18637 -+ max_used_connections= slow_launch_threads = 0;
18638 -+ mysqld_user= mysqld_chroot= opt_init_file= opt_bin_logname = 0;
18639 -+ prepared_stmt_count= 0;
18640 -+ errmesg= 0;
18641 -+ mysqld_unix_port= opt_mysql_tmpdir= my_bind_addr_str= NullS;
18642 -+ bzero((uchar*) &mysql_tmpdir_list, sizeof(mysql_tmpdir_list));
18643 -+ bzero((char *) &global_status_var, sizeof(global_status_var));
18644 -+ opt_large_pages= 0;
18645 -+#if defined(ENABLED_DEBUG_SYNC)
18646 -+ opt_debug_sync_timeout= 0;
18647 -+#endif /* defined(ENABLED_DEBUG_SYNC) */
18648 -+ key_map_full.set_all();
18649 -+
18650 -+ /* Character sets */
18651 -+ system_charset_info= &my_charset_utf8_general_ci;
18652 -+ files_charset_info= &my_charset_utf8_general_ci;
18653 -+ national_charset_info= &my_charset_utf8_general_ci;
18654 -+ table_alias_charset= &my_charset_bin;
18655 -+ character_set_filesystem= &my_charset_bin;
18656 -+
18657 -+ opt_date_time_formats[0]= opt_date_time_formats[1]= opt_date_time_formats[2]= 0;
18658 -+
18659 -+ /* Things with default values that are not zero */
18660 -+ delay_key_write_options= (uint) DELAY_KEY_WRITE_ON;
18661 -+ slave_exec_mode_options= find_bit_type_or_exit(slave_exec_mode_str,
18662 -+ &slave_exec_mode_typelib,
18663 -+ NULL, &error);
18664 -+ /* Default mode string must not yield a error. */
18665 -+ DBUG_ASSERT(!error);
18666 -+ if (error)
18667 -+ return 1;
18668 -+ opt_specialflag= SPECIAL_ENGLISH;
18669 -+ unix_sock= ip_sock= INVALID_SOCKET;
18670 -+ mysql_home_ptr= mysql_home;
18671 -+ pidfile_name_ptr= pidfile_name;
18672 -+ log_error_file_ptr= log_error_file;
18673 -+ language_ptr= language;
18674 -+ mysql_data_home= mysql_real_data_home;
18675 -+ thd_startup_options= (OPTION_AUTO_IS_NULL | OPTION_BIN_LOG |
18676 -+ OPTION_QUOTE_SHOW_CREATE | OPTION_SQL_NOTES);
18677 -+ protocol_version= PROTOCOL_VERSION;
18678 -+ what_to_log= ~ (1L << (uint) COM_TIME);
18679 -+ refresh_version= 1L; /* Increments on each reload */
18680 -+ global_query_id= thread_id= 1L;
18681 -+ strmov(server_version, MYSQL_SERVER_VERSION);
18682 -+ myisam_recover_options_str= sql_mode_str= "OFF";
18683 -+ myisam_stats_method_str= "nulls_unequal";
18684 -+ my_bind_addr = htonl(INADDR_ANY);
18685 -+ threads.empty();
18686 -+ thread_cache.empty();
18687 -+ key_caches.empty();
18688 -+ if (!(dflt_key_cache= get_or_create_key_cache(default_key_cache_base.str,
18689 -+ default_key_cache_base.length)))
18690 -+ {
18691 -+ sql_print_error("Cannot allocate the keycache");
18692 -+ return 1;
18693 -+ }
18694 -+ /* set key_cache_hash.default_value = dflt_key_cache */
18695 -+ multi_keycache_init();
18696 -+
18697 -+ /* Set directory paths */
18698 -+ strmake(language, LANGUAGE, sizeof(language)-1);
18699 -+ strmake(mysql_real_data_home, get_relative_path(MYSQL_DATADIR),
18700 -+ sizeof(mysql_real_data_home)-1);
18701 -+ mysql_data_home_buff[0]=FN_CURLIB; // all paths are relative from here
18702 -+ mysql_data_home_buff[1]=0;
18703 -+ mysql_data_home_len= 2;
18704 -+
18705 -+ /* Replication parameters */
18706 -+ master_user= (char*) "test";
18707 -+ master_password= master_host= 0;
18708 -+ master_info_file= (char*) "master.info",
18709 -+ relay_log_info_file= (char*) "relay-log.info";
18710 -+ master_ssl_key= master_ssl_cert= master_ssl_ca=
18711 -+ master_ssl_capath= master_ssl_cipher= 0;
18712 -+ report_user= report_password = report_host= 0; /* TO BE DELETED */
18713 -+ opt_relay_logname= opt_relaylog_index_name= 0;
18714 -+
18715 -+ /* Variables in libraries */
18716 -+ charsets_dir= 0;
18717 -+ default_character_set_name= (char*) MYSQL_DEFAULT_CHARSET_NAME;
18718 -+ default_collation_name= compiled_default_collation_name;
18719 -+ sys_charset_system.value= (char*) system_charset_info->csname;
18720 -+ character_set_filesystem_name= (char*) "binary";
18721 -+ lc_time_names_name= (char*) "en_US";
18722 -+ /* Set default values for some option variables */
18723 -+ default_storage_engine_str= (char*) "MyISAM";
18724 -+ global_system_variables.table_plugin= NULL;
18725 -+ global_system_variables.tx_isolation= ISO_REPEATABLE_READ;
18726 -+ global_system_variables.select_limit= (ulonglong) HA_POS_ERROR;
18727 -+ max_system_variables.select_limit= (ulonglong) HA_POS_ERROR;
18728 -+ global_system_variables.max_join_size= (ulonglong) HA_POS_ERROR;
18729 -+ max_system_variables.max_join_size= (ulonglong) HA_POS_ERROR;
18730 -+ global_system_variables.old_passwords= 0;
18731 -+ global_system_variables.old_alter_table= 0;
18732 -+ global_system_variables.binlog_format= BINLOG_FORMAT_UNSPEC;
18733 -+ /*
18734 -+ Default behavior for 4.1 and 5.0 is to treat NULL values as unequal
18735 -+ when collecting index statistics for MyISAM tables.
18736 -+ */
18737 -+ global_system_variables.myisam_stats_method= MI_STATS_METHOD_NULLS_NOT_EQUAL;
18738 -+
18739 -+ global_system_variables.optimizer_switch= OPTIMIZER_SWITCH_DEFAULT;
18740 -+ /* Variables that depends on compile options */
18741 -+#ifndef DBUG_OFF
18742 -+ default_dbug_option=IF_WIN("d:t:i:O,\\mysqld.trace",
18743 -+ "d:t:i:o,/tmp/mysqld.trace");
18744 -+#endif
18745 -+ opt_error_log= IF_WIN(1,0);
18746 -+#ifdef COMMUNITY_SERVER
18747 -+ have_community_features = SHOW_OPTION_YES;
18748 -+#else
18749 -+ have_community_features = SHOW_OPTION_NO;
18750 -+#endif
18751 -+ global_system_variables.ndb_index_stat_enable=FALSE;
18752 -+ max_system_variables.ndb_index_stat_enable=TRUE;
18753 -+ global_system_variables.ndb_index_stat_cache_entries=32;
18754 -+ max_system_variables.ndb_index_stat_cache_entries=~0L;
18755 -+ global_system_variables.ndb_index_stat_update_freq=20;
18756 -+ max_system_variables.ndb_index_stat_update_freq=~0L;
18757 -+#ifdef HAVE_OPENSSL
18758 -+ have_ssl=SHOW_OPTION_YES;
18759 -+#else
18760 -+ have_ssl=SHOW_OPTION_NO;
18761 -+#endif
18762 -+#ifdef HAVE_BROKEN_REALPATH
18763 -+ have_symlink=SHOW_OPTION_NO;
18764 -+#else
18765 -+ have_symlink=SHOW_OPTION_YES;
18766 -+#endif
18767 -+#ifdef HAVE_DLOPEN
18768 -+ have_dlopen=SHOW_OPTION_YES;
18769 -+#else
18770 -+ have_dlopen=SHOW_OPTION_NO;
18771 -+#endif
18772 -+#ifdef HAVE_QUERY_CACHE
18773 -+ have_query_cache=SHOW_OPTION_YES;
18774 -+#else
18775 -+ have_query_cache=SHOW_OPTION_NO;
18776 -+#endif
18777 -+#ifdef HAVE_SPATIAL
18778 -+ have_geometry=SHOW_OPTION_YES;
18779 -+#else
18780 -+ have_geometry=SHOW_OPTION_NO;
18781 -+#endif
18782 -+#ifdef HAVE_RTREE_KEYS
18783 -+ have_rtree_keys=SHOW_OPTION_YES;
18784 -+#else
18785 -+ have_rtree_keys=SHOW_OPTION_NO;
18786 -+#endif
18787 -+#ifdef HAVE_CRYPT
18788 -+ have_crypt=SHOW_OPTION_YES;
18789 -+#else
18790 -+ have_crypt=SHOW_OPTION_NO;
18791 -+#endif
18792 -+#ifdef HAVE_COMPRESS
18793 -+ have_compress= SHOW_OPTION_YES;
18794 -+#else
18795 -+ have_compress= SHOW_OPTION_NO;
18796 -+#endif
18797 -+#ifdef HAVE_LIBWRAP
18798 -+ libwrapName= NullS;
18799 -+#endif
18800 -+#ifdef HAVE_OPENSSL
18801 -+ des_key_file = 0;
18802 -+ ssl_acceptor_fd= 0;
18803 -+#endif
18804 -+#ifdef HAVE_SMEM
18805 -+ shared_memory_base_name= default_shared_memory_base_name;
18806 -+#endif
18807 -+#if !defined(my_pthread_setprio) && !defined(HAVE_PTHREAD_SETSCHEDPARAM)
18808 -+ opt_specialflag |= SPECIAL_NO_PRIOR;
18809 -+#endif
18810 -+
18811 -+#if defined(__WIN__) || defined(__NETWARE__)
18812 -+ /* Allow Win32 and NetWare users to move MySQL anywhere */
18813 -+ {
18814 -+ char prg_dev[LIBLEN];
18815 -+#if defined __WIN__
18816 -+ char executing_path_name[LIBLEN];
18817 -+ if (!test_if_hard_path(my_progname))
18818 -+ {
18819 -+ // we don't want to use GetModuleFileName inside of my_path since
18820 -+ // my_path is a generic path dereferencing function and here we care
18821 -+ // only about the executing binary.
18822 -+ GetModuleFileName(NULL, executing_path_name, sizeof(executing_path_name));
18823 -+ my_path(prg_dev, executing_path_name, NULL);
18824 -+ }
18825 -+ else
18826 -+#endif
18827 -+ my_path(prg_dev,my_progname,"mysql/bin");
18828 -+ strcat(prg_dev,"/../"); // Remove 'bin' to get base dir
18829 -+ cleanup_dirname(mysql_home,prg_dev);
18830 -+ }
18831 -+#else
18832 -+ const char *tmpenv;
18833 -+ if (!(tmpenv = getenv("MY_BASEDIR_VERSION")))
18834 -+ tmpenv = DEFAULT_MYSQL_HOME;
18835 -+ (void) strmake(mysql_home, tmpenv, sizeof(mysql_home)-1);
18836 -+#endif
18837 -+ return 0;
18838 -+}
18839 -+
18840 -+
18841 -+my_bool
18842 -+mysqld_get_one_option(int optid,
18843 -+ const struct my_option *opt __attribute__((unused)),
18844 -+ char *argument)
18845 -+{
18846 -+ int error;
18847 -+
18848 -+ switch(optid) {
18849 -+ case '#':
18850 -+#ifndef DBUG_OFF
18851 -+ DBUG_SET_INITIAL(argument ? argument : default_dbug_option);
18852 -+#endif
18853 -+ opt_endinfo=1; /* unireg: memory allocation */
18854 -+ break;
18855 -+ case '0':
18856 -+ WARN_DEPRECATED(NULL, VER_CELOSIA, "--log-long-format", "--log-short-format");
18857 -+ break;
18858 -+ case 'a':
18859 -+ global_system_variables.sql_mode= fix_sql_mode(MODE_ANSI);
18860 -+ global_system_variables.tx_isolation= ISO_SERIALIZABLE;
18861 -+ break;
18862 -+ case 'b':
18863 -+ strmake(mysql_home,argument,sizeof(mysql_home)-1);
18864 -+ break;
18865 -+ case OPT_DEFAULT_CHARACTER_SET_OLD: // --default-character-set
18866 -+ WARN_DEPRECATED(NULL, VER_CELOSIA,
18867 -+ "--default-character-set",
18868 -+ "--character-set-server");
18869 -+ /* Fall through */
18870 -+ case 'C':
18871 -+ if (default_collation_name == compiled_default_collation_name)
18872 -+ default_collation_name= 0;
18873 -+ break;
18874 -+ case 'l':
18875 -+ WARN_DEPRECATED(NULL, "7.0", "--log", "'--general_log'/'--general_log_file'");
18876 -+ opt_log=1;
18877 -+ break;
18878 -+ case 'h':
18879 -+ strmake(mysql_real_data_home,argument, sizeof(mysql_real_data_home)-1);
18880 -+ /* Correct pointer set by my_getopt (for embedded library) */
18881 -+ mysql_data_home= mysql_real_data_home;
18882 -+ mysql_data_home_len= strlen(mysql_data_home);
18883 -+ break;
18884 -+ case 'u':
18885 -+ if (!mysqld_user || !strcmp(mysqld_user, argument))
18886 -+ mysqld_user= argument;
18887 -+ else
18888 -+ sql_print_warning("Ignoring user change to '%s' because the user was set to '%s' earlier on the command line\n", argument, mysqld_user);
18889 -+ break;
18890 -+ case 'L':
18891 -+ strmake(language, argument, sizeof(language)-1);
18892 -+ break;
18893 -+ case 'O':
18894 -+ WARN_DEPRECATED(NULL, VER_CELOSIA, "--set-variable", "--variable-name=value");
18895 -+ break;
18896 -+#ifdef HAVE_REPLICATION
18897 -+ case OPT_SLAVE_SKIP_ERRORS:
18898 -+ init_slave_skip_errors(argument);
18899 -+ break;
18900 -+ case OPT_SLAVE_EXEC_MODE:
18901 -+ slave_exec_mode_options= find_bit_type_or_exit(argument,
18902 -+ &slave_exec_mode_typelib,
18903 -+ "", &error);
18904 -+ if (error)
18905 -+ return 1;
18906 -+ break;
18907 -+#endif
18908 -+ case OPT_SAFEMALLOC_MEM_LIMIT:
18909 -+#if !defined(DBUG_OFF) && defined(SAFEMALLOC)
18910 -+ sf_malloc_mem_limit = atoi(argument);
18911 -+#endif
18912 -+ break;
18913 -+#include <sslopt-case.h>
18914 -+#ifndef EMBEDDED_LIBRARY
18915 -+ case 'V':
18916 -+ print_version();
18917 -+ exit(0);
18918 -+#endif /*EMBEDDED_LIBRARY*/
18919 -+ case OPT_WARNINGS:
18920 -+ WARN_DEPRECATED(NULL, VER_CELOSIA, "--warnings", "--log-warnings");
18921 -+ /* Note: fall-through to 'W' */
18922 -+ case 'W':
18923 -+ if (!argument)
18924 -+ global_system_variables.log_warnings++;
18925 -+ else if (argument == disabled_my_option)
18926 -+ global_system_variables.log_warnings= 0L;
18927 -+ else
18928 -+ global_system_variables.log_warnings= atoi(argument);
18929 -+ break;
18930 -+ case 'T':
18931 -+ test_flags= argument ? (uint) atoi(argument) : 0;
18932 -+ opt_endinfo=1;
18933 -+ break;
18934 -+ case (int) OPT_DEFAULT_COLLATION_OLD:
18935 -+ WARN_DEPRECATED(NULL, VER_CELOSIA, "--default-collation", "--collation-server");
18936 -+ break;
18937 -+ case (int) OPT_SAFE_SHOW_DB:
18938 -+ WARN_DEPRECATED(NULL, VER_CELOSIA, "--safe-show-database", "GRANT SHOW DATABASES");
18939 -+ break;
18940 -+ case (int) OPT_LOG_BIN_TRUST_FUNCTION_CREATORS_OLD:
18941 -+ WARN_DEPRECATED(NULL, VER_CELOSIA, "--log-bin-trust-routine-creators", "--log-bin-trust-function-creators");
18942 -+ break;
18943 -+ case (int) OPT_ENABLE_LOCK:
18944 -+ WARN_DEPRECATED(NULL, VER_CELOSIA, "--enable-locking", "--external-locking");
18945 -+ break;
18946 -+ case (int) OPT_BIG_TABLES:
18947 -+ thd_startup_options|=OPTION_BIG_TABLES;
18948 -+ break;
18949 -+ case (int) OPT_IGNORE_BUILTIN_INNODB:
18950 -+ opt_ignore_builtin_innodb= 1;
18951 -+ break;
18952 -+ case (int) OPT_ISAM_LOG:
18953 -+ opt_myisam_log=1;
18954 -+ break;
18955 -+ case (int) OPT_UPDATE_LOG:
18956 -+ WARN_DEPRECATED(NULL, VER_CELOSIA, "--log-update", "--log-bin");
18957 -+ opt_update_log=1;
18958 -+ break;
18959 -+ case (int) OPT_BIN_LOG:
18960 -+ opt_bin_log= test(argument != disabled_my_option);
18961 -+ break;
18962 -+ case (int) OPT_ERROR_LOG_FILE:
18963 -+ opt_error_log= 1;
18964 -+ break;
18965 -+#ifdef HAVE_REPLICATION
18966 -+ case (int) OPT_INIT_RPL_ROLE:
18967 -+ {
18968 -+ int role;
18969 -+ role= find_type_or_exit(argument, &rpl_role_typelib, opt->name);
18970 -+ rpl_status = (role == 1) ? RPL_AUTH_MASTER : RPL_IDLE_SLAVE;
18971 -+ break;
18972 -+ }
18973 -+ case (int)OPT_REPLICATE_IGNORE_DB:
18974 -+ {
18975 -+ rpl_filter->add_ignore_db(argument);
18976 -+ break;
18977 -+ }
18978 -+ case (int)OPT_REPLICATE_DO_DB:
18979 -+ {
18980 -+ rpl_filter->add_do_db(argument);
18981 -+ break;
18982 -+ }
18983 -+ case (int)OPT_REPLICATE_REWRITE_DB:
18984 -+ {
18985 -+ char* key = argument,*p, *val;
18986 -+
18987 -+ if (!(p= strstr(argument, "->")))
18988 -+ {
18989 -+ sql_print_error("Bad syntax in replicate-rewrite-db - missing '->'!\n");
18990 -+ return 1;
18991 -+ }
18992 -+ val= p--;
18993 -+ while (my_isspace(mysqld_charset, *p) && p > argument)
18994 -+ *p-- = 0;
18995 -+ if (p == argument)
18996 -+ {
18997 -+ sql_print_error("Bad syntax in replicate-rewrite-db - empty FROM db!\n");
18998 -+ return 1;
18999 -+ }
19000 -+ *val= 0;
19001 -+ val+= 2;
19002 -+ while (*val && my_isspace(mysqld_charset, *val))
19003 -+ val++;
19004 -+ if (!*val)
19005 -+ {
19006 -+ sql_print_error("Bad syntax in replicate-rewrite-db - empty TO db!\n");
19007 -+ return 1;
19008 -+ }
19009 -+
19010 -+ rpl_filter->add_db_rewrite(key, val);
19011 -+ break;
19012 -+ }
19013 -+
19014 -+ case (int)OPT_BINLOG_IGNORE_DB:
19015 -+ {
19016 -+ binlog_filter->add_ignore_db(argument);
19017 -+ break;
19018 -+ }
19019 -+ case OPT_BINLOG_FORMAT:
19020 -+ {
19021 -+ int id;
19022 -+ id= find_type_or_exit(argument, &binlog_format_typelib, opt->name);
19023 -+ global_system_variables.binlog_format= opt_binlog_format_id= id - 1;
19024 -+ break;
19025 -+ }
19026 -+ case (int)OPT_BINLOG_DO_DB:
19027 -+ {
19028 -+ binlog_filter->add_do_db(argument);
19029 -+ break;
19030 -+ }
19031 -+ case (int)OPT_REPLICATE_DO_TABLE:
19032 -+ {
19033 -+ if (rpl_filter->add_do_table(argument))
19034 -+ {
19035 -+ sql_print_error("Could not add do table rule '%s'!\n", argument);
19036 -+ return 1;
19037 -+ }
19038 -+ break;
19039 -+ }
19040 -+ case (int)OPT_REPLICATE_WILD_DO_TABLE:
19041 -+ {
19042 -+ if (rpl_filter->add_wild_do_table(argument))
19043 -+ {
19044 -+ sql_print_error("Could not add do table rule '%s'!\n", argument);
19045 -+ return 1;
19046 -+ }
19047 -+ break;
19048 -+ }
19049 -+ case (int)OPT_REPLICATE_WILD_IGNORE_TABLE:
19050 -+ {
19051 -+ if (rpl_filter->add_wild_ignore_table(argument))
19052 -+ {
19053 -+ sql_print_error("Could not add ignore table rule '%s'!\n", argument);
19054 -+ return 1;
19055 -+ }
19056 -+ break;
19057 -+ }
19058 -+ case (int)OPT_REPLICATE_IGNORE_TABLE:
19059 -+ {
19060 -+ if (rpl_filter->add_ignore_table(argument))
19061 -+ {
19062 -+ sql_print_error("Could not add ignore table rule '%s'!\n", argument);
19063 -+ return 1;
19064 -+ }
19065 -+ break;
19066 -+ }
19067 -+#endif /* HAVE_REPLICATION */
19068 -+ case (int) OPT_SLOW_QUERY_LOG:
19069 -+ WARN_DEPRECATED(NULL, "7.0", "--log_slow_queries", "'--slow_query_log'/'--slow_query_log_file'");
19070 -+ opt_slow_log= 1;
19071 -+ break;
19072 -+#ifdef WITH_CSV_STORAGE_ENGINE
19073 -+ case OPT_LOG_OUTPUT:
19074 -+ {
19075 -+ if (!argument || !argument[0])
19076 -+ {
19077 -+ log_output_options= LOG_FILE;
19078 -+ log_output_str= log_output_typelib.type_names[1];
19079 -+ }
19080 -+ else
19081 -+ {
19082 -+ log_output_str= argument;
19083 -+ log_output_options=
19084 -+ find_bit_type_or_exit(argument, &log_output_typelib, opt->name, &error);
19085 -+ if (error)
19086 -+ return 1;
19087 -+ }
19088 -+ break;
19089 -+ }
19090 -+#endif
19091 -+ case OPT_EVENT_SCHEDULER:
19092 -+#ifndef HAVE_EVENT_SCHEDULER
19093 -+ sql_perror("Event scheduler is not supported in embedded build.");
19094 -+#else
19095 -+ if (Events::set_opt_event_scheduler(argument))
19096 -+ return 1;
19097 -+#endif
19098 -+ break;
19099 -+ case (int) OPT_SKIP_NEW:
19100 -+ opt_specialflag|= SPECIAL_NO_NEW_FUNC;
19101 -+ delay_key_write_options= (uint) DELAY_KEY_WRITE_NONE;
19102 -+ myisam_concurrent_insert=0;
19103 -+ myisam_recover_options= HA_RECOVER_NONE;
19104 -+ sp_automatic_privileges=0;
19105 -+ my_use_symdir=0;
19106 -+ ha_open_options&= ~(HA_OPEN_ABORT_IF_CRASHED | HA_OPEN_DELAY_KEY_WRITE);
19107 -+#ifdef HAVE_QUERY_CACHE
19108 -+ query_cache_size=0;
19109 -+#endif
19110 -+ break;
19111 -+ case (int) OPT_SAFE:
19112 -+ opt_specialflag|= SPECIAL_SAFE_MODE;
19113 -+ delay_key_write_options= (uint) DELAY_KEY_WRITE_NONE;
19114 -+ myisam_recover_options= HA_RECOVER_DEFAULT;
19115 -+ ha_open_options&= ~(HA_OPEN_DELAY_KEY_WRITE);
19116 -+ break;
19117 -+ case (int) OPT_SKIP_PRIOR:
19118 -+ opt_specialflag|= SPECIAL_NO_PRIOR;
19119 -+ sql_print_warning("The --skip-thread-priority startup option is deprecated "
19120 -+ "and will be removed in MySQL 7.0. MySQL 6.0 and up do not "
19121 -+ "give threads different priorities.");
19122 -+ break;
19123 -+ case (int) OPT_SKIP_LOCK:
19124 -+ WARN_DEPRECATED(NULL, VER_CELOSIA, "--skip-locking", "--skip-external-locking");
19125 -+ opt_external_locking=0;
19126 -+ break;
19127 -+ case (int) OPT_SQL_BIN_UPDATE_SAME:
19128 -+ WARN_DEPRECATED(NULL, VER_CELOSIA, "--sql-bin-update-same", "the binary log");
19129 -+ break;
19130 -+ case (int) OPT_RECORD_BUFFER_OLD:
19131 -+ WARN_DEPRECATED(NULL, VER_CELOSIA, "record_buffer", "read_buffer_size");
19132 -+ break;
19133 -+ case (int) OPT_SYMBOLIC_LINKS:
19134 -+ WARN_DEPRECATED(NULL, VER_CELOSIA, "--use-symbolic-links", "--symbolic-links");
19135 -+ break;
19136 -+ case (int) OPT_SKIP_HOST_CACHE:
19137 -+ opt_specialflag|= SPECIAL_NO_HOST_CACHE;
19138 -+ break;
19139 -+ case (int) OPT_SKIP_RESOLVE:
19140 -+ opt_skip_name_resolve= 1;
19141 -+ opt_specialflag|=SPECIAL_NO_RESOLVE;
19142 -+ break;
19143 -+ case (int) OPT_SKIP_NETWORKING:
19144 -+#if defined(__NETWARE__)
19145 -+ sql_perror("Can't start server: skip-networking option is currently not supported on NetWare");
19146 -+ return 1;
19147 -+#endif
19148 -+ opt_disable_networking=1;
19149 -+ mysqld_port=0;
19150 -+ break;
19151 -+ case (int) OPT_SKIP_SHOW_DB:
19152 -+ opt_skip_show_db=1;
19153 -+ opt_specialflag|=SPECIAL_SKIP_SHOW_DB;
19154 -+ break;
19155 -+ case (int) OPT_WANT_CORE:
19156 -+ test_flags |= TEST_CORE_ON_SIGNAL;
19157 -+ break;
19158 -+ case (int) OPT_SKIP_STACK_TRACE:
19159 -+ test_flags|=TEST_NO_STACKTRACE;
19160 -+ break;
19161 -+ case (int) OPT_SKIP_SYMLINKS:
19162 -+ WARN_DEPRECATED(NULL, VER_CELOSIA, "--skip-symlink", "--skip-symbolic-links");
19163 -+ my_use_symdir=0;
19164 -+ break;
19165 -+ case (int) OPT_BIND_ADDRESS:
19166 -+ if ((my_bind_addr= (ulong) inet_addr(argument)) == INADDR_NONE)
19167 -+ {
19168 -+ struct hostent *ent;
19169 -+ if (argument[0])
19170 -+ ent=gethostbyname(argument);
19171 -+ else
19172 -+ {
19173 -+ char myhostname[255];
19174 -+ if (gethostname(myhostname,sizeof(myhostname)) < 0)
19175 -+ {
19176 -+ sql_perror("Can't start server: cannot get my own hostname!");
19177 -+ return 1;
19178 -+ }
19179 -+ ent=gethostbyname(myhostname);
19180 -+ }
19181 -+ if (!ent)
19182 -+ {
19183 -+ sql_perror("Can't start server: cannot resolve hostname!");
19184 -+ return 1;
19185 -+ }
19186 -+ my_bind_addr = (ulong) ((in_addr*)ent->h_addr_list[0])->s_addr;
19187 -+ }
19188 -+ break;
19189 -+ case (int) OPT_PID_FILE:
19190 -+ strmake(pidfile_name, argument, sizeof(pidfile_name)-1);
19191 -+ break;
19192 -+#ifdef __WIN__
19193 -+ case (int) OPT_STANDALONE: /* Dummy option for NT */
19194 -+ break;
19195 -+#endif
19196 -+ /*
19197 -+ The following change issues a deprecation warning if the slave
19198 -+ configuration is specified either in the my.cnf file or on
19199 -+ the command-line. See BUG#21490.
19200 -+ */
19201 -+ case OPT_MASTER_HOST:
19202 -+ case OPT_MASTER_USER:
19203 -+ case OPT_MASTER_PASSWORD:
19204 -+ case OPT_MASTER_PORT:
19205 -+ case OPT_MASTER_CONNECT_RETRY:
19206 -+ case OPT_MASTER_SSL:
19207 -+ case OPT_MASTER_SSL_KEY:
19208 -+ case OPT_MASTER_SSL_CERT:
19209 -+ case OPT_MASTER_SSL_CAPATH:
19210 -+ case OPT_MASTER_SSL_CIPHER:
19211 -+ case OPT_MASTER_SSL_CA:
19212 -+ if (!slave_warning_issued) //only show the warning once
19213 -+ {
19214 -+ slave_warning_issued = true;
19215 -+ WARN_DEPRECATED(NULL, "6.0", "for replication startup options",
19216 -+ "'CHANGE MASTER'");
19217 -+ }
19218 -+ break;
19219 -+ case OPT_CONSOLE:
19220 -+ if (opt_console)
19221 -+ opt_error_log= 0; // Force logs to stdout
19222 -+ break;
19223 -+ case (int) OPT_FLUSH:
19224 -+ myisam_flush=1;
19225 -+ flush_time=0; // No auto flush
19226 -+ break;
19227 -+ case OPT_LOW_PRIORITY_UPDATES:
19228 -+ thr_upgraded_concurrent_insert_lock= TL_WRITE_LOW_PRIORITY;
19229 -+ global_system_variables.low_priority_updates=1;
19230 -+ break;
19231 -+ case OPT_BOOTSTRAP:
19232 -+ opt_noacl=opt_bootstrap=1;
19233 -+ break;
19234 -+ case OPT_SERVER_ID:
19235 -+ server_id_supplied = 1;
19236 -+ break;
19237 -+ case OPT_DELAY_KEY_WRITE_ALL:
19238 -+ WARN_DEPRECATED(NULL, VER_CELOSIA,
19239 -+ "--delay-key-write-for-all-tables",
19240 -+ "--delay-key-write=ALL");
19241 -+ if (argument != disabled_my_option)
19242 -+ argument= (char*) "ALL";
19243 -+ /* Fall through */
19244 -+ case OPT_DELAY_KEY_WRITE:
19245 -+ if (argument == disabled_my_option)
19246 -+ delay_key_write_options= (uint) DELAY_KEY_WRITE_NONE;
19247 -+ else if (! argument)
19248 -+ delay_key_write_options= (uint) DELAY_KEY_WRITE_ON;
19249 -+ else
19250 -+ {
19251 -+ int type;
19252 -+ type= find_type_or_exit(argument, &delay_key_write_typelib, opt->name);
19253 -+ delay_key_write_options= (uint) type-1;
19254 -+ }
19255 -+ break;
19256 -+ case OPT_MYISAM_MAX_EXTRA_SORT_FILE_SIZE:
19257 -+ sql_print_warning("--myisam_max_extra_sort_file_size is deprecated and "
19258 -+ "does nothing in this version. It will be removed in "
19259 -+ "a future release.");
19260 -+ break;
19261 -+ case OPT_CHARSETS_DIR:
19262 -+ strmake(mysql_charsets_dir, argument, sizeof(mysql_charsets_dir)-1);
19263 -+ charsets_dir = mysql_charsets_dir;
19264 -+ break;
19265 -+ case OPT_TX_ISOLATION:
19266 -+ {
19267 -+ int type;
19268 -+ type= find_type_or_exit(argument, &tx_isolation_typelib, opt->name);
19269 -+ global_system_variables.tx_isolation= (type-1);
19270 -+ break;
19271 -+ }
19272 -+#ifdef WITH_NDBCLUSTER_STORAGE_ENGINE
19273 -+ case OPT_NDB_MGMD:
19274 -+ case OPT_NDB_NODEID:
19275 -+ {
19276 -+ int len= my_snprintf(opt_ndb_constrbuf+opt_ndb_constrbuf_len,
19277 -+ sizeof(opt_ndb_constrbuf)-opt_ndb_constrbuf_len,
19278 -+ "%s%s%s",opt_ndb_constrbuf_len > 0 ? ",":"",
19279 -+ optid == OPT_NDB_NODEID ? "nodeid=" : "",
19280 -+ argument);
19281 -+ opt_ndb_constrbuf_len+= len;
19282 -+ }
19283 -+ /* fall through to add the connectstring to the end
19284 -+ * and set opt_ndbcluster_connectstring
19285 -+ */
19286 -+ case OPT_NDB_CONNECTSTRING:
19287 -+ if (opt_ndb_connectstring && opt_ndb_connectstring[0])
19288 -+ my_snprintf(opt_ndb_constrbuf+opt_ndb_constrbuf_len,
19289 -+ sizeof(opt_ndb_constrbuf)-opt_ndb_constrbuf_len,
19290 -+ "%s%s", opt_ndb_constrbuf_len > 0 ? ",":"",
19291 -+ opt_ndb_connectstring);
19292 -+ else
19293 -+ opt_ndb_constrbuf[opt_ndb_constrbuf_len]= 0;
19294 -+ opt_ndbcluster_connectstring= opt_ndb_constrbuf;
19295 -+ break;
19296 -+ case OPT_NDB_DISTRIBUTION:
19297 -+ int id;
19298 -+ id= find_type_or_exit(argument, &ndb_distribution_typelib, opt->name);
19299 -+ opt_ndb_distribution_id= (enum ndb_distribution)(id-1);
19300 -+ break;
19301 -+ case OPT_NDB_EXTRA_LOGGING:
19302 -+ if (!argument)
19303 -+ ndb_extra_logging++;
19304 -+ else if (argument == disabled_my_option)
19305 -+ ndb_extra_logging= 0L;
19306 -+ else
19307 -+ ndb_extra_logging= atoi(argument);
19308 -+ break;
19309 -+#endif
19310 -+ case OPT_MYISAM_RECOVER:
19311 -+ {
19312 -+ if (!argument)
19313 -+ {
19314 -+ myisam_recover_options= HA_RECOVER_DEFAULT;
19315 -+ myisam_recover_options_str= myisam_recover_typelib.type_names[0];
19316 -+ }
19317 -+ else if (!argument[0])
19318 -+ {
19319 -+ myisam_recover_options= HA_RECOVER_NONE;
19320 -+ myisam_recover_options_str= "OFF";
19321 -+ }
19322 -+ else
19323 -+ {
19324 -+ myisam_recover_options_str=argument;
19325 -+ myisam_recover_options=
19326 -+ find_bit_type_or_exit(argument, &myisam_recover_typelib, opt->name,
19327 -+ &error);
19328 -+ if (error)
19329 -+ return 1;
19330 -+ }
19331 -+ ha_open_options|=HA_OPEN_ABORT_IF_CRASHED;
19332 -+ break;
19333 -+ }
19334 -+ case OPT_CONCURRENT_INSERT:
19335 -+ /* The following code is mainly here to emulate old behavior */
19336 -+ if (!argument) /* --concurrent-insert */
19337 -+ myisam_concurrent_insert= 1;
19338 -+ else if (argument == disabled_my_option)
19339 -+ myisam_concurrent_insert= 0; /* --skip-concurrent-insert */
19340 -+ break;
19341 -+ case OPT_TC_HEURISTIC_RECOVER:
19342 -+ tc_heuristic_recover= find_type_or_exit(argument,
19343 -+ &tc_heuristic_recover_typelib,
19344 -+ opt->name);
19345 -+ break;
19346 -+ case OPT_MYISAM_STATS_METHOD:
19347 -+ {
19348 -+ ulong method_conv;
19349 -+ int method;
19350 -+ LINT_INIT(method_conv);
19351 -+
19352 -+ myisam_stats_method_str= argument;
19353 -+ method= find_type_or_exit(argument, &myisam_stats_method_typelib,
19354 -+ opt->name);
19355 -+ switch (method-1) {
19356 -+ case 2:
19357 -+ method_conv= MI_STATS_METHOD_IGNORE_NULLS;
19358 -+ break;
19359 -+ case 1:
19360 -+ method_conv= MI_STATS_METHOD_NULLS_EQUAL;
19361 -+ break;
19362 -+ case 0:
19363 -+ default:
19364 -+ method_conv= MI_STATS_METHOD_NULLS_NOT_EQUAL;
19365 -+ break;
19366 -+ }
19367 -+ global_system_variables.myisam_stats_method= method_conv;
19368 -+ break;
19369 -+ }
19370 -+ case OPT_SQL_MODE:
19371 -+ {
19372 -+ sql_mode_str= argument;
19373 -+ global_system_variables.sql_mode=
19374 -+ find_bit_type_or_exit(argument, &sql_mode_typelib, opt->name, &error);
19375 -+ if (error)
19376 -+ return 1;
19377 -+ global_system_variables.sql_mode= fix_sql_mode(global_system_variables.
19378 -+ sql_mode);
19379 -+ break;
19380 -+ }
19381 -+ case OPT_OPTIMIZER_SWITCH:
19382 -+ {
19383 -+ bool not_used;
19384 -+ char *error= 0;
19385 -+ uint error_len= 0;
19386 -+ optimizer_switch_str= argument;
19387 -+ global_system_variables.optimizer_switch=
19388 -+ (ulong)find_set_from_flags(&optimizer_switch_typelib,
19389 -+ optimizer_switch_typelib.count,
19390 -+ global_system_variables.optimizer_switch,
19391 -+ global_system_variables.optimizer_switch,
19392 -+ argument, strlen(argument), NULL,
19393 -+ &error, &error_len, &not_used);
19394 -+ if (error)
19395 -+ {
19396 -+ char buf[512];
19397 -+ char *cbuf= buf;
19398 -+ cbuf += my_snprintf(buf, 512, "Error in parsing optimizer_switch setting near %*s\n", error_len, error);
19399 -+ sql_perror(buf);
19400 -+ return 1;
19401 -+ }
19402 -+ break;
19403 -+ }
19404 -+ case OPT_ONE_THREAD:
19405 -+ global_system_variables.thread_handling=
19406 -+ SCHEDULER_ONE_THREAD_PER_CONNECTION;
19407 -+ break;
19408 -+ case OPT_THREAD_HANDLING:
19409 -+ {
19410 -+ global_system_variables.thread_handling=
19411 -+ find_type_or_exit(argument, &thread_handling_typelib, opt->name)-1;
19412 -+ break;
19413 -+ }
19414 -+ case OPT_FT_BOOLEAN_SYNTAX:
19415 -+ if (ft_boolean_check_syntax_string((uchar*) argument))
19416 -+ {
19417 -+ sql_print_error("Invalid ft-boolean-syntax string: %s\n", argument);
19418 -+ return 1;
19419 -+ }
19420 -+ strmake(ft_boolean_syntax, argument, sizeof(ft_boolean_syntax)-1);
19421 -+ break;
19422 -+ case OPT_SKIP_SAFEMALLOC:
19423 -+#ifdef SAFEMALLOC
19424 -+ sf_malloc_quick=1;
19425 -+#endif
19426 -+ break;
19427 -+ case OPT_LOWER_CASE_TABLE_NAMES:
19428 -+ lower_case_table_names= argument ? atoi(argument) : 1;
19429 -+ lower_case_table_names_used= 1;
19430 -+ break;
19431 -+#ifdef HAVE_STACK_TRACE_ON_SEGV
19432 -+ case OPT_DO_PSTACK:
19433 -+ sql_print_warning("'--enable-pstack' is deprecated and will be removed "
19434 -+ "in a future release. A symbolic stack trace will be "
19435 -+ "printed after a crash whenever possible.");
19436 -+ break;
19437 -+#endif
19438 -+#if defined(ENABLED_DEBUG_SYNC)
19439 -+ case OPT_DEBUG_SYNC_TIMEOUT:
19440 -+ /*
19441 -+ Debug Sync Facility. See debug_sync.cc.
19442 -+ Default timeout for WAIT_FOR action.
19443 -+ Default value is zero (facility disabled).
19444 -+ If option is given without an argument, supply a non-zero value.
19445 -+ */
19446 -+ if (!argument)
19447 -+ {
19448 -+ /* purecov: begin tested */
19449 -+ opt_debug_sync_timeout= DEBUG_SYNC_DEFAULT_WAIT_TIMEOUT;
19450 -+ /* purecov: end */
19451 -+ }
19452 -+ break;
19453 -+#endif /* defined(ENABLED_DEBUG_SYNC) */
19454 -+ case OPT_MAX_LONG_DATA_SIZE:
19455 -+ max_long_data_size_used= true;
19456 -+ WARN_DEPRECATED(NULL, VER_CELOSIA, "--max_long_data_size", "--max_allowed_packet");
19457 -+ break;
19458 -+ }
19459 -+ return 0;
19460 -+}
19461 -+
19462 -+
19463 -+/** Handle arguments for multiple key caches. */
19464 -+C_MODE_START
19465 -+static void* mysql_getopt_value(const char *, uint,
19466 -+ const struct my_option *, int *);
19467 -+C_MODE_END
19468 -+
19469 -+static void*
19470 -+mysql_getopt_value(const char *keyname, uint key_length,
19471 -+ const struct my_option *option, int *error)
19472 -+{
19473 -+ if (error)
19474 -+ *error= 0;
19475 -+ switch (option->id) {
19476 -+ case OPT_KEY_BUFFER_SIZE:
19477 -+ case OPT_KEY_CACHE_BLOCK_SIZE:
19478 -+ case OPT_KEY_CACHE_DIVISION_LIMIT:
19479 -+ case OPT_KEY_CACHE_AGE_THRESHOLD:
19480 -+ {
19481 -+ KEY_CACHE *key_cache;
19482 -+ if (!(key_cache= get_or_create_key_cache(keyname, key_length)))
19483 -+ {
19484 -+ if (error)
19485 -+ *error= EXIT_OUT_OF_MEMORY;
19486 -+ return 0;
19487 -+ }
19488 -+ switch (option->id) {
19489 -+ case OPT_KEY_BUFFER_SIZE:
19490 -+ return &key_cache->param_buff_size;
19491 -+ case OPT_KEY_CACHE_BLOCK_SIZE:
19492 -+ return &key_cache->param_block_size;
19493 -+ case OPT_KEY_CACHE_DIVISION_LIMIT:
19494 -+ return &key_cache->param_division_limit;
19495 -+ case OPT_KEY_CACHE_AGE_THRESHOLD:
19496 -+ return &key_cache->param_age_threshold;
19497 -+ }
19498 -+ }
19499 -+ }
19500 -+ return option->value;
19501 -+}
19502 -+
19503 -+
19504 -+extern "C" void option_error_reporter(enum loglevel level, const char *format, ...);
19505 -+
19506 -+void option_error_reporter(enum loglevel level, const char *format, ...)
19507 -+{
19508 -+ va_list args;
19509 -+ va_start(args, format);
19510 -+
19511 -+ /* Don't print warnings for --loose options during bootstrap */
19512 -+ if (level == ERROR_LEVEL || !opt_bootstrap ||
19513 -+ global_system_variables.log_warnings)
19514 -+ {
19515 -+ vprint_msg_to_log(level, format, args);
19516 -+ }
19517 -+ va_end(args);
19518 -+}
19519 -+
19520 -+
19521 -+/**
19522 -+ @todo
19523 -+ - FIXME add EXIT_TOO_MANY_ARGUMENTS to "mysys_err.h" and return that code?
19524 -+*/
19525 -+static int get_options(int *argc,char **argv)
19526 -+{
19527 -+ int ho_error;
19528 -+
19529 -+ my_getopt_register_get_addr(mysql_getopt_value);
19530 -+ strmake(def_ft_boolean_syntax, ft_boolean_syntax,
19531 -+ sizeof(ft_boolean_syntax)-1);
19532 -+ my_getopt_error_reporter= option_error_reporter;
19533 -+
19534 -+ /* Skip unknown options so that they may be processed later by plugins */
19535 -+ my_getopt_skip_unknown= TRUE;
19536 -+
19537 -+ if ((ho_error= handle_options(argc, &argv, my_long_options,
19538 -+ mysqld_get_one_option)))
19539 -+ return ho_error;
19540 -+ (*argc)++; /* add back one for the progname handle_options removes */
19541 -+ /* no need to do this for argv as we are discarding it. */
19542 -+
19543 -+ if ((opt_log_slow_admin_statements || opt_log_queries_not_using_indexes ||
19544 -+ opt_log_slow_slave_statements) &&
19545 -+ !opt_slow_log)
19546 -+ sql_print_warning("options --log-slow-admin-statements, --log-queries-not-using-indexes and --log-slow-slave-statements have no effect if --log_slow_queries is not set");
19547 -+ if (global_system_variables.net_buffer_length >
19548 -+ global_system_variables.max_allowed_packet)
19549 -+ {
19550 -+ sql_print_warning("net_buffer_length (%lu) is set to be larger "
19551 -+ "than max_allowed_packet (%lu). Please rectify.",
19552 -+ global_system_variables.net_buffer_length,
19553 -+ global_system_variables.max_allowed_packet);
19554 -+ }
19555 -+
19556 -+#if defined(HAVE_BROKEN_REALPATH)
19557 -+ my_use_symdir=0;
19558 -+ my_disable_symlinks=1;
19559 -+ have_symlink=SHOW_OPTION_NO;
19560 -+#else
19561 -+ if (!my_use_symdir)
19562 -+ {
19563 -+ my_disable_symlinks=1;
19564 -+ have_symlink=SHOW_OPTION_DISABLED;
19565 -+ }
19566 -+#endif
19567 -+ if (opt_debugging)
19568 -+ {
19569 -+ /* Allow break with SIGINT, no core or stack trace */
19570 -+ test_flags|= TEST_SIGINT | TEST_NO_STACKTRACE;
19571 -+ test_flags&= ~TEST_CORE_ON_SIGNAL;
19572 -+ }
19573 -+ /* Set global MyISAM variables from delay_key_write_options */
19574 -+ fix_delay_key_write((THD*) 0, OPT_GLOBAL);
19575 -+ /* Set global slave_exec_mode from its option */
19576 -+ fix_slave_exec_mode();
19577 -+
19578 -+#ifndef EMBEDDED_LIBRARY
19579 -+ if (mysqld_chroot)
19580 -+ set_root(mysqld_chroot);
19581 -+#else
19582 -+ global_system_variables.thread_handling = SCHEDULER_NO_THREADS;
19583 -+ max_allowed_packet= global_system_variables.max_allowed_packet;
19584 -+ net_buffer_length= global_system_variables.net_buffer_length;
19585 -+#endif
19586 -+ if (fix_paths())
19587 -+ return 1;
19588 -+
19589 -+ /*
19590 -+ Set some global variables from the global_system_variables
19591 -+ In most cases the global variables will not be used
19592 -+ */
19593 -+ my_disable_locking= myisam_single_user= test(opt_external_locking == 0);
19594 -+ my_default_record_cache_size=global_system_variables.read_buff_size;
19595 -+ myisam_max_temp_length=
19596 -+ (my_off_t) global_system_variables.myisam_max_sort_file_size;
19597 -+
19598 -+ /* Set global variables based on startup options */
19599 -+ myisam_block_size=(uint) 1 << my_bit_log2(opt_myisam_block_size);
19600 -+
19601 -+ /* long_query_time is in microseconds */
19602 -+ global_system_variables.long_query_time= max_system_variables.long_query_time=
19603 -+ (longlong) (long_query_time * 1000000.0);
19604 -+
19605 -+ if (opt_short_log_format)
19606 -+ opt_specialflag|= SPECIAL_SHORT_LOG_FORMAT;
19607 -+
19608 -+ if (init_global_datetime_format(MYSQL_TIMESTAMP_DATE,
19609 -+ &global_system_variables.date_format) ||
19610 -+ init_global_datetime_format(MYSQL_TIMESTAMP_TIME,
19611 -+ &global_system_variables.time_format) ||
19612 -+ init_global_datetime_format(MYSQL_TIMESTAMP_DATETIME,
19613 -+ &global_system_variables.datetime_format))
19614 -+ return 1;
19615 -+
19616 -+#ifdef EMBEDDED_LIBRARY
19617 -+ one_thread_scheduler(&thread_scheduler);
19618 -+#else
19619 -+ if (global_system_variables.thread_handling <=
19620 -+ SCHEDULER_ONE_THREAD_PER_CONNECTION)
19621 -+ one_thread_per_connection_scheduler(&thread_scheduler);
19622 -+ else if (global_system_variables.thread_handling == SCHEDULER_NO_THREADS)
19623 -+ one_thread_scheduler(&thread_scheduler);
19624 -+ else
19625 -+ pool_of_threads_scheduler(&thread_scheduler); /* purecov: tested */
19626 -+#endif
19627 -+
19628 -+ /*
19629 -+ If max_long_data_size is not specified explicitly use
19630 -+ value of max_allowed_packet.
19631 -+ */
19632 -+ if (!max_long_data_size_used)
19633 -+ max_long_data_size= global_system_variables.max_allowed_packet;
19634 -+
19635 -+ return 0;
19636 -+}
19637 -+
19638 -+
19639 -+/*
19640 -+ Create version name for running mysqld version
19641 -+ We automaticly add suffixes -debug, -embedded and -log to the version
19642 -+ name to make the version more descriptive.
19643 -+ (MYSQL_SERVER_SUFFIX is set by the compilation environment)
19644 -+*/
19645 -+
19646 -+static void set_server_version(void)
19647 -+{
19648 -+ char *end= strxmov(server_version, MYSQL_SERVER_VERSION,
19649 -+ MYSQL_SERVER_SUFFIX_STR, NullS);
19650 -+#ifdef EMBEDDED_LIBRARY
19651 -+ end= strmov(end, "-embedded");
19652 -+#endif
19653 -+#ifndef DBUG_OFF
19654 -+ if (!strstr(MYSQL_SERVER_SUFFIX_STR, "-debug"))
19655 -+ end= strmov(end, "-debug");
19656 -+#endif
19657 -+ if (opt_log || opt_update_log || opt_slow_log || opt_bin_log)
19658 -+ strmov(end, "-log"); // This may slow down system
19659 -+}
19660 -+
19661 -+
19662 -+static char *get_relative_path(const char *path)
19663 -+{
19664 -+ if (test_if_hard_path(path) &&
19665 -+ is_prefix(path,DEFAULT_MYSQL_HOME) &&
19666 -+ strcmp(DEFAULT_MYSQL_HOME,FN_ROOTDIR))
19667 -+ {
19668 -+ path+=(uint) strlen(DEFAULT_MYSQL_HOME);
19669 -+ while (*path == FN_LIBCHAR)
19670 -+ path++;
19671 -+ }
19672 -+ return (char*) path;
19673 -+}
19674 -+
19675 -+
19676 -+/**
19677 -+ Fix filename and replace extension where 'dir' is relative to
19678 -+ mysql_real_data_home.
19679 -+ @return
19680 -+ 1 if len(path) > FN_REFLEN
19681 -+*/
19682 -+
19683 -+bool
19684 -+fn_format_relative_to_data_home(char * to, const char *name,
19685 -+ const char *dir, const char *extension)
19686 -+{
19687 -+ char tmp_path[FN_REFLEN];
19688 -+ if (!test_if_hard_path(dir))
19689 -+ {
19690 -+ strxnmov(tmp_path,sizeof(tmp_path)-1, mysql_real_data_home,
19691 -+ dir, NullS);
19692 -+ dir=tmp_path;
19693 -+ }
19694 -+ return !fn_format(to, name, dir, extension,
19695 -+ MY_APPEND_EXT | MY_UNPACK_FILENAME | MY_SAFE_PATH);
19696 -+}
19697 -+
19698 -+
19699 -+/**
19700 -+ Test a file path to determine if the path is compatible with the secure file
19701 -+ path restriction.
19702 -+
19703 -+ @param path null terminated character string
19704 -+
19705 -+ @return
19706 -+ @retval TRUE The path is secure
19707 -+ @retval FALSE The path isn't secure
19708 -+*/
19709 -+
19710 -+bool is_secure_file_path(char *path)
19711 -+{
19712 -+ char buff1[FN_REFLEN], buff2[FN_REFLEN];
19713 -+ /*
19714 -+ All paths are secure if opt_secure_file_path is 0
19715 -+ */
19716 -+ if (!opt_secure_file_priv)
19717 -+ return TRUE;
19718 -+
19719 -+ if (strlen(path) >= FN_REFLEN)
19720 -+ return FALSE;
19721 -+
19722 -+ if (my_realpath(buff1, path, 0))
19723 -+ {
19724 -+ /*
19725 -+ The supplied file path might have been a file and not a directory.
19726 -+ */
19727 -+ int length= (int)dirname_length(path);
19728 -+ if (length >= FN_REFLEN)
19729 -+ return FALSE;
19730 -+ memcpy(buff2, path, length);
19731 -+ buff2[length]= '\0';
19732 -+ if (length == 0 || my_realpath(buff1, buff2, 0))
19733 -+ return FALSE;
19734 -+ }
19735 -+ convert_dirname(buff2, buff1, NullS);
19736 -+ if (strncmp(opt_secure_file_priv, buff2, strlen(opt_secure_file_priv)))
19737 -+ return FALSE;
19738 -+ return TRUE;
19739 -+}
19740 -+
19741 -+static int fix_paths(void)
19742 -+{
19743 -+ char buff[FN_REFLEN],*pos;
19744 -+ convert_dirname(mysql_home,mysql_home,NullS);
19745 -+ /* Resolve symlinks to allow 'mysql_home' to be a relative symlink */
19746 -+ my_realpath(mysql_home,mysql_home,MYF(0));
19747 -+ /* Ensure that mysql_home ends in FN_LIBCHAR */
19748 -+ pos=strend(mysql_home);
19749 -+ if (pos[-1] != FN_LIBCHAR)
19750 -+ {
19751 -+ pos[0]= FN_LIBCHAR;
19752 -+ pos[1]= 0;
19753 -+ }
19754 -+ convert_dirname(language,language,NullS);
19755 -+ convert_dirname(mysql_real_data_home,mysql_real_data_home,NullS);
19756 -+ (void) my_load_path(mysql_home,mysql_home,""); // Resolve current dir
19757 -+ (void) my_load_path(mysql_real_data_home,mysql_real_data_home,mysql_home);
19758 -+ (void) my_load_path(pidfile_name,pidfile_name,mysql_real_data_home);
19759 -+ (void) my_load_path(opt_plugin_dir, opt_plugin_dir_ptr ? opt_plugin_dir_ptr :
19760 -+ get_relative_path(PLUGINDIR), mysql_home);
19761 -+ opt_plugin_dir_ptr= opt_plugin_dir;
19762 -+
19763 -+ my_realpath(mysql_unpacked_real_data_home, mysql_real_data_home, MYF(0));
19764 -+ mysql_unpacked_real_data_home_len=
19765 -+ (int) strlen(mysql_unpacked_real_data_home);
19766 -+ if (mysql_unpacked_real_data_home[mysql_unpacked_real_data_home_len-1] == FN_LIBCHAR)
19767 -+ --mysql_unpacked_real_data_home_len;
19768 -+
19769 -+ char *sharedir=get_relative_path(SHAREDIR);
19770 -+ if (test_if_hard_path(sharedir))
19771 -+ strmake(buff,sharedir,sizeof(buff)-1); /* purecov: tested */
19772 -+ else
19773 -+ strxnmov(buff,sizeof(buff)-1,mysql_home,sharedir,NullS);
19774 -+ convert_dirname(buff,buff,NullS);
19775 -+ (void) my_load_path(language,language,buff);
19776 -+
19777 -+ /* If --character-sets-dir isn't given, use shared library dir */
19778 -+ if (charsets_dir != mysql_charsets_dir)
19779 -+ {
19780 -+ strxnmov(mysql_charsets_dir, sizeof(mysql_charsets_dir)-1, buff,
19781 -+ CHARSET_DIR, NullS);
19782 -+ }
19783 -+ (void) my_load_path(mysql_charsets_dir, mysql_charsets_dir, buff);
19784 -+ convert_dirname(mysql_charsets_dir, mysql_charsets_dir, NullS);
19785 -+ charsets_dir=mysql_charsets_dir;
19786 -+
19787 -+ if (init_tmpdir(&mysql_tmpdir_list, opt_mysql_tmpdir))
19788 -+ return 1;
19789 -+#ifdef HAVE_REPLICATION
19790 -+ if (!slave_load_tmpdir)
19791 -+ {
19792 -+ if (!(slave_load_tmpdir = (char*) my_strdup(mysql_tmpdir, MYF(MY_FAE))))
19793 -+ return 1;
19794 -+ }
19795 -+#endif /* HAVE_REPLICATION */
19796 -+ /*
19797 -+ Convert the secure-file-priv option to system format, allowing
19798 -+ a quick strcmp to check if read or write is in an allowed dir
19799 -+ */
19800 -+ if (opt_secure_file_priv)
19801 -+ {
19802 -+ if (*opt_secure_file_priv == 0)
19803 -+ {
19804 -+ opt_secure_file_priv= 0;
19805 -+ }
19806 -+ else
19807 -+ {
19808 -+ if (strlen(opt_secure_file_priv) >= FN_REFLEN)
19809 -+ opt_secure_file_priv[FN_REFLEN-1]= '\0';
19810 -+ if (my_realpath(buff, opt_secure_file_priv, 0))
19811 -+ {
19812 -+ sql_print_warning("Failed to normalize the argument for --secure-file-priv.");
19813 -+ return 1;
19814 -+ }
19815 -+ char *secure_file_real_path= (char *)my_malloc(FN_REFLEN, MYF(MY_FAE));
19816 -+ convert_dirname(secure_file_real_path, buff, NullS);
19817 -+ my_free(opt_secure_file_priv, MYF(0));
19818 -+ opt_secure_file_priv= secure_file_real_path;
19819 -+ }
19820 -+ }
19821 -+
19822 -+ return 0;
19823 -+}
19824 -+
19825 -+
19826 -+static ulong find_bit_type_or_exit(const char *x, TYPELIB *bit_lib,
19827 -+ const char *option, int *error)
19828 -+{
19829 -+ ulong result;
19830 -+ const char **ptr;
19831 -+
19832 -+ *error= 0;
19833 -+ if ((result= find_bit_type(x, bit_lib)) == ~(ulong) 0)
19834 -+ {
19835 -+ char *buff= (char *) my_alloca(2048);
19836 -+ char *cbuf;
19837 -+ ptr= bit_lib->type_names;
19838 -+ cbuf= buff + ((!*x) ?
19839 -+ my_snprintf(buff, 2048, "No option given to %s\n", option) :
19840 -+ my_snprintf(buff, 2048, "Wrong option to %s. Option(s) given: %s\n",
19841 -+ option, x));
19842 -+ cbuf+= my_snprintf(cbuf, 2048 - (cbuf-buff), "Alternatives are: '%s'", *ptr);
19843 -+ while (*++ptr)
19844 -+ cbuf+= my_snprintf(cbuf, 2048 - (cbuf-buff), ",'%s'", *ptr);
19845 -+ my_snprintf(cbuf, 2048 - (cbuf-buff), "\n");
19846 -+ sql_perror(buff);
19847 -+ *error= 1;
19848 -+ my_afree(buff);
19849 -+ return 0;
19850 -+ }
19851 -+
19852 -+ return result;
19853 -+}
19854 -+
19855 -+
19856 -+/**
19857 -+ @return
19858 -+ a bitfield from a string of substrings separated by ','
19859 -+ or
19860 -+ ~(ulong) 0 on error.
19861 -+*/
19862 -+
19863 -+static ulong find_bit_type(const char *x, TYPELIB *bit_lib)
19864 -+{
19865 -+ bool found_end;
19866 -+ int found_count;
19867 -+ const char *end,*i,*j;
19868 -+ const char **array, *pos;
19869 -+ ulong found,found_int,bit;
19870 -+ DBUG_ENTER("find_bit_type");
19871 -+ DBUG_PRINT("enter",("x: '%s'",x));
19872 -+
19873 -+ found=0;
19874 -+ found_end= 0;
19875 -+ pos=(char *) x;
19876 -+ while (*pos == ' ') pos++;
19877 -+ found_end= *pos == 0;
19878 -+ while (!found_end)
19879 -+ {
19880 -+ if (!*(end=strcend(pos,','))) /* Let end point at fieldend */
19881 -+ {
19882 -+ while (end > pos && end[-1] == ' ')
19883 -+ end--; /* Skip end-space */
19884 -+ found_end=1;
19885 -+ }
19886 -+ found_int=0; found_count=0;
19887 -+ for (array=bit_lib->type_names, bit=1 ; (i= *array++) ; bit<<=1)
19888 -+ {
19889 -+ j=pos;
19890 -+ while (j != end)
19891 -+ {
19892 -+ if (my_toupper(mysqld_charset,*i++) !=
19893 -+ my_toupper(mysqld_charset,*j++))
19894 -+ goto skip;
19895 -+ }
19896 -+ found_int=bit;
19897 -+ if (! *i)
19898 -+ {
19899 -+ found_count=1;
19900 -+ break;
19901 -+ }
19902 -+ else if (j != pos) // Half field found
19903 -+ {
19904 -+ found_count++; // Could be one of two values
19905 -+ }
19906 -+skip: ;
19907 -+ }
19908 -+ if (found_count != 1)
19909 -+ DBUG_RETURN(~(ulong) 0); // No unique value
19910 -+ found|=found_int;
19911 -+ pos=end+1;
19912 -+ }
19913 -+
19914 -+ DBUG_PRINT("exit",("bit-field: %ld",(ulong) found));
19915 -+ DBUG_RETURN(found);
19916 -+} /* find_bit_type */
19917 -+
19918 -+
19919 -+/**
19920 -+ Check if file system used for databases is case insensitive.
19921 -+
19922 -+ @param dir_name Directory to test
19923 -+
19924 -+ @retval
19925 -+ -1 Don't know (Test failed)
19926 -+ @retval
19927 -+ 0 File system is case sensitive
19928 -+ @retval
19929 -+ 1 File system is case insensitive
19930 -+*/
19931 -+
19932 -+static int test_if_case_insensitive(const char *dir_name)
19933 -+{
19934 -+ int result= 0;
19935 -+ File file;
19936 -+ char buff[FN_REFLEN], buff2[FN_REFLEN];
19937 -+ MY_STAT stat_info;
19938 -+ DBUG_ENTER("test_if_case_insensitive");
19939 -+
19940 -+ fn_format(buff, glob_hostname, dir_name, ".lower-test",
19941 -+ MY_UNPACK_FILENAME | MY_REPLACE_EXT | MY_REPLACE_DIR);
19942 -+ fn_format(buff2, glob_hostname, dir_name, ".LOWER-TEST",
19943 -+ MY_UNPACK_FILENAME | MY_REPLACE_EXT | MY_REPLACE_DIR);
19944 -+ (void) my_delete(buff2, MYF(0));
19945 -+ if ((file= my_create(buff, 0666, O_RDWR, MYF(0))) < 0)
19946 -+ {
19947 -+ sql_print_warning("Can't create test file %s", buff);
19948 -+ DBUG_RETURN(-1);
19949 -+ }
19950 -+ my_close(file, MYF(0));
19951 -+ if (my_stat(buff2, &stat_info, MYF(0)))
19952 -+ result= 1; // Can access file
19953 -+ (void) my_delete(buff, MYF(MY_WME));
19954 -+ DBUG_PRINT("exit", ("result: %d", result));
19955 -+ DBUG_RETURN(result);
19956 -+}
19957 -+
19958 -+
19959 -+#ifndef EMBEDDED_LIBRARY
19960 -+
19961 -+/**
19962 -+ Create file to store pid number.
19963 -+*/
19964 -+static void create_pid_file()
19965 -+{
19966 -+ File file;
19967 -+ if ((file = my_create(pidfile_name,0664,
19968 -+ O_WRONLY | O_TRUNC, MYF(MY_WME))) >= 0)
19969 -+ {
19970 -+ char buff[21], *end;
19971 -+ end= int10_to_str((long) getpid(), buff, 10);
19972 -+ *end++= '\n';
19973 -+ if (!my_write(file, (uchar*) buff, (uint) (end-buff), MYF(MY_WME | MY_NABP)))
19974 -+ {
19975 -+ (void) my_close(file, MYF(0));
19976 -+ return;
19977 -+ }
19978 -+ (void) my_close(file, MYF(0));
19979 -+ }
19980 -+ sql_perror("Can't start server: can't create PID file");
19981 -+ exit(1);
19982 -+}
19983 -+#endif /* EMBEDDED_LIBRARY */
19984 -+
19985 -+/** Clear most status variables. */
19986 -+void refresh_status(THD *thd)
19987 -+{
19988 -+ pthread_mutex_lock(&LOCK_status);
19989 -+
19990 -+ /* Add thread's status variabes to global status */
19991 -+ add_to_status(&global_status_var, &thd->status_var);
19992 -+
19993 -+ /* Reset thread's status variables */
19994 -+ bzero((uchar*) &thd->status_var, sizeof(thd->status_var));
19995 -+
19996 -+ /* Reset some global variables */
19997 -+ reset_status_vars();
19998 -+
19999 -+ /* Reset the counters of all key caches (default and named). */
20000 -+ process_key_caches(reset_key_cache_counters);
20001 -+#ifdef COMMUNITY_SERVER
20002 -+ flush_status_time= time((time_t*) 0);
20003 -+#endif
20004 -+ pthread_mutex_unlock(&LOCK_status);
20005 -+
20006 -+ /*
20007 -+ Set max_used_connections to the number of currently open
20008 -+ connections. Lock LOCK_thread_count out of LOCK_status to avoid
20009 -+ deadlocks. Status reset becomes not atomic, but status data is
20010 -+ not exact anyway.
20011 -+ */
20012 -+ pthread_mutex_lock(&LOCK_thread_count);
20013 -+ max_used_connections= thread_count-delayed_insert_threads;
20014 -+ pthread_mutex_unlock(&LOCK_thread_count);
20015 -+}
20016 -+
20017 -+
20018 -+/*****************************************************************************
20019 -+ Instantiate variables for missing storage engines
20020 -+ This section should go away soon
20021 -+*****************************************************************************/
20022 -+
20023 -+#ifndef WITH_NDBCLUSTER_STORAGE_ENGINE
20024 -+ulong ndb_cache_check_time;
20025 -+ulong ndb_extra_logging;
20026 -+#endif
20027 -+
20028 -+/*****************************************************************************
20029 -+ Instantiate templates
20030 -+*****************************************************************************/
20031 -+
20032 -+#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
20033 -+/* Used templates */
20034 -+template class I_List<THD>;
20035 -+template class I_List_iterator<THD>;
20036 -+template class I_List<i_string>;
20037 -+template class I_List<i_string_pair>;
20038 -+template class I_List<NAMED_LIST>;
20039 -+template class I_List<Statement>;
20040 -+template class I_List_iterator<Statement>;
20041 -+#endif
20042 diff -urN mysql-old/sql/net_serv.cc mysql/sql/net_serv.cc
20043 --- mysql-old/sql/net_serv.cc 2011-05-10 17:45:45.633349043 +0000
20044 +++ mysql/sql/net_serv.cc 2011-05-10 17:56:01.466682376 +0000
20045 @@ -21909,4367 +1921,6 @@ diff -urN mysql-old/sql/set_var.cc mysql/sql/set_var.cc
20046 goto err;
20047 }
20048 return FALSE;
20049 -diff -urN mysql-old/sql/set_var.cc.orig mysql/sql/set_var.cc.orig
20050 ---- mysql-old/sql/set_var.cc.orig 1969-12-31 23:00:00.000000000 -0100
20051 -+++ mysql/sql/set_var.cc.orig 2011-04-12 12:11:35.000000000 +0000
20052 -@@ -0,0 +1,4357 @@
20053 -+/* Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
20054 -+
20055 -+ This program is free software; you can redistribute it and/or modify
20056 -+ it under the terms of the GNU General Public License as published by
20057 -+ the Free Software Foundation; version 2 of the License.
20058 -+
20059 -+ This program is distributed in the hope that it will be useful,
20060 -+ but WITHOUT ANY WARRANTY; without even the implied warranty of
20061 -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20062 -+ GNU General Public License for more details.
20063 -+
20064 -+ You should have received a copy of the GNU General Public License
20065 -+ along with this program; if not, write to the Free Software
20066 -+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
20067 -+
20068 -+/**
20069 -+ @file
20070 -+
20071 -+ @brief
20072 -+ Handling of MySQL SQL variables
20073 -+
20074 -+ @details
20075 -+ To add a new variable, one has to do the following:
20076 -+
20077 -+ - Use one of the 'sys_var... classes from set_var.h or write a specific
20078 -+ one for the variable type.
20079 -+ - Define it in the 'variable definition list' in this file.
20080 -+ - If the variable is thread specific, add it to 'system_variables' struct.
20081 -+ If not, add it to mysqld.cc and an declaration in 'mysql_priv.h'
20082 -+ - If the variable should be changed from the command line, add a definition
20083 -+ of it in the my_option structure list in mysqld.cc
20084 -+ - Don't forget to initialize new fields in global_system_variables and
20085 -+ max_system_variables!
20086 -+
20087 -+ @todo
20088 -+ Add full support for the variable character_set (for 4.1)
20089 -+
20090 -+ @todo
20091 -+ When updating myisam_delay_key_write, we should do a 'flush tables'
20092 -+ of all MyISAM tables to ensure that they are reopen with the
20093 -+ new attribute.
20094 -+
20095 -+ @note
20096 -+ Be careful with var->save_result: sys_var::check() only updates
20097 -+ ulonglong_value; so other members of the union are garbage then; to use
20098 -+ them you must first assign a value to them (in specific ::check() for
20099 -+ example).
20100 -+*/
20101 -+
20102 -+#ifdef USE_PRAGMA_IMPLEMENTATION
20103 -+#pragma implementation // gcc: Class implementation
20104 -+#endif
20105 -+
20106 -+#include "mysql_priv.h"
20107 -+#include <mysql.h>
20108 -+#include "slave.h"
20109 -+#include "rpl_mi.h"
20110 -+#include <my_getopt.h>
20111 -+#include <thr_alarm.h>
20112 -+#include <myisam.h>
20113 -+#include <my_dir.h>
20114 -+
20115 -+#include "events.h"
20116 -+
20117 -+/* WITH_NDBCLUSTER_STORAGE_ENGINE */
20118 -+#ifdef WITH_NDBCLUSTER_STORAGE_ENGINE
20119 -+extern ulong ndb_cache_check_time;
20120 -+extern char opt_ndb_constrbuf[];
20121 -+extern ulong ndb_extra_logging;
20122 -+#endif
20123 -+
20124 -+#ifdef HAVE_NDB_BINLOG
20125 -+extern ulong ndb_report_thresh_binlog_epoch_slip;
20126 -+extern ulong ndb_report_thresh_binlog_mem_usage;
20127 -+#endif
20128 -+
20129 -+extern CHARSET_INFO *character_set_filesystem;
20130 -+
20131 -+
20132 -+static HASH system_variable_hash;
20133 -+
20134 -+const char *bool_type_names[]= { "OFF", "ON", NullS };
20135 -+TYPELIB bool_typelib=
20136 -+{
20137 -+ array_elements(bool_type_names)-1, "", bool_type_names, NULL
20138 -+};
20139 -+
20140 -+const char *delay_key_write_type_names[]= { "OFF", "ON", "ALL", NullS };
20141 -+TYPELIB delay_key_write_typelib=
20142 -+{
20143 -+ array_elements(delay_key_write_type_names)-1, "",
20144 -+ delay_key_write_type_names, NULL
20145 -+};
20146 -+
20147 -+static const char *slave_exec_mode_names[]= { "STRICT", "IDEMPOTENT", NullS };
20148 -+static unsigned int slave_exec_mode_names_len[]= { sizeof("STRICT") - 1,
20149 -+ sizeof("IDEMPOTENT") - 1, 0 };
20150 -+TYPELIB slave_exec_mode_typelib=
20151 -+{
20152 -+ array_elements(slave_exec_mode_names)-1, "",
20153 -+ slave_exec_mode_names, slave_exec_mode_names_len
20154 -+};
20155 -+
20156 -+static int sys_check_ftb_syntax(THD *thd, set_var *var);
20157 -+static bool sys_update_ftb_syntax(THD *thd, set_var * var);
20158 -+static void sys_default_ftb_syntax(THD *thd, enum_var_type type);
20159 -+static bool sys_update_init_connect(THD*, set_var*);
20160 -+static void sys_default_init_connect(THD*, enum_var_type type);
20161 -+static bool sys_update_init_slave(THD*, set_var*);
20162 -+static void sys_default_init_slave(THD*, enum_var_type type);
20163 -+static bool set_option_bit(THD *thd, set_var *var);
20164 -+static bool set_option_log_bin_bit(THD *thd, set_var *var);
20165 -+static bool set_option_autocommit(THD *thd, set_var *var);
20166 -+static int check_log_update(THD *thd, set_var *var);
20167 -+static bool set_log_update(THD *thd, set_var *var);
20168 -+static int check_pseudo_thread_id(THD *thd, set_var *var);
20169 -+void fix_binlog_format_after_update(THD *thd, enum_var_type type);
20170 -+static void fix_low_priority_updates(THD *thd, enum_var_type type);
20171 -+static int check_tx_isolation(THD *thd, set_var *var);
20172 -+static void fix_tx_isolation(THD *thd, enum_var_type type);
20173 -+static int check_completion_type(THD *thd, set_var *var);
20174 -+static void fix_completion_type(THD *thd, enum_var_type type);
20175 -+static void fix_net_read_timeout(THD *thd, enum_var_type type);
20176 -+static void fix_net_write_timeout(THD *thd, enum_var_type type);
20177 -+static void fix_net_retry_count(THD *thd, enum_var_type type);
20178 -+static void fix_max_join_size(THD *thd, enum_var_type type);
20179 -+static void fix_query_cache_size(THD *thd, enum_var_type type);
20180 -+static void fix_query_cache_min_res_unit(THD *thd, enum_var_type type);
20181 -+static void fix_myisam_max_sort_file_size(THD *thd, enum_var_type type);
20182 -+static void fix_max_binlog_size(THD *thd, enum_var_type type);
20183 -+static void fix_max_relay_log_size(THD *thd, enum_var_type type);
20184 -+static void fix_max_connections(THD *thd, enum_var_type type);
20185 -+static int check_max_delayed_threads(THD *thd, set_var *var);
20186 -+static void fix_thd_mem_root(THD *thd, enum_var_type type);
20187 -+static void fix_trans_mem_root(THD *thd, enum_var_type type);
20188 -+static void fix_server_id(THD *thd, enum_var_type type);
20189 -+bool throw_bounds_warning(THD *thd, bool fixed, bool unsignd,
20190 -+ const char *name, longlong val);
20191 -+static KEY_CACHE *create_key_cache(const char *name, uint length);
20192 -+void fix_sql_mode_var(THD *thd, enum_var_type type);
20193 -+static uchar *get_error_count(THD *thd);
20194 -+static uchar *get_warning_count(THD *thd);
20195 -+static uchar *get_tmpdir(THD *thd);
20196 -+static int sys_check_log_path(THD *thd, set_var *var);
20197 -+static bool sys_update_general_log_path(THD *thd, set_var * var);
20198 -+static void sys_default_general_log_path(THD *thd, enum_var_type type);
20199 -+static bool sys_update_slow_log_path(THD *thd, set_var * var);
20200 -+static void sys_default_slow_log_path(THD *thd, enum_var_type type);
20201 -+static uchar *get_myisam_mmap_size(THD *thd);
20202 -+static int check_max_allowed_packet(THD *thd, set_var *var);
20203 -+static int check_net_buffer_length(THD *thd, set_var *var);
20204 -+
20205 -+/*
20206 -+ Variable definition list
20207 -+
20208 -+ These are variables that can be set from the command line, in
20209 -+ alphabetic order.
20210 -+
20211 -+ The variables are linked into the list. A variable is added to
20212 -+ it in the constructor (see sys_var class for details).
20213 -+*/
20214 -+
20215 -+static sys_var_chain vars = { NULL, NULL };
20216 -+
20217 -+static sys_var_thd_ulong
20218 -+sys_auto_increment_increment(&vars, "auto_increment_increment",
20219 -+ &SV::auto_increment_increment, NULL, NULL,
20220 -+ sys_var::SESSION_VARIABLE_IN_BINLOG);
20221 -+static sys_var_thd_ulong
20222 -+sys_auto_increment_offset(&vars, "auto_increment_offset",
20223 -+ &SV::auto_increment_offset, NULL, NULL,
20224 -+ sys_var::SESSION_VARIABLE_IN_BINLOG);
20225 -+
20226 -+static sys_var_bool_ptr sys_automatic_sp_privileges(&vars, "automatic_sp_privileges",
20227 -+ &sp_automatic_privileges);
20228 -+
20229 -+static sys_var_const sys_back_log(&vars, "back_log",
20230 -+ OPT_GLOBAL, SHOW_LONG,
20231 -+ (uchar*) &back_log);
20232 -+static sys_var_const_os_str sys_basedir(&vars, "basedir", mysql_home);
20233 -+static sys_var_long_ptr sys_binlog_cache_size(&vars, "binlog_cache_size",
20234 -+ &binlog_cache_size);
20235 -+static sys_var_thd_binlog_format sys_binlog_format(&vars, "binlog_format",
20236 -+ &SV::binlog_format);
20237 -+static sys_var_thd_bool sys_binlog_direct_non_trans_update(&vars, "binlog_direct_non_transactional_updates",
20238 -+ &SV::binlog_direct_non_trans_update);
20239 -+static sys_var_thd_ulong sys_bulk_insert_buff_size(&vars, "bulk_insert_buffer_size",
20240 -+ &SV::bulk_insert_buff_size);
20241 -+static sys_var_const_os sys_character_sets_dir(&vars,
20242 -+ "character_sets_dir",
20243 -+ OPT_GLOBAL, SHOW_CHAR,
20244 -+ (uchar*)
20245 -+ mysql_charsets_dir);
20246 -+static sys_var_character_set_sv
20247 -+sys_character_set_server(&vars, "character_set_server",
20248 -+ &SV::collation_server, &default_charset_info, 0,
20249 -+ sys_var::SESSION_VARIABLE_IN_BINLOG);
20250 -+sys_var_const_str sys_charset_system(&vars, "character_set_system",
20251 -+ (char *)my_charset_utf8_general_ci.name);
20252 -+static sys_var_character_set_database
20253 -+sys_character_set_database(&vars, "character_set_database",
20254 -+ sys_var::SESSION_VARIABLE_IN_BINLOG);
20255 -+static sys_var_character_set_client
20256 -+sys_character_set_client(&vars, "character_set_client",
20257 -+ &SV::character_set_client,
20258 -+ &default_charset_info,
20259 -+ sys_var::SESSION_VARIABLE_IN_BINLOG);
20260 -+static sys_var_character_set_sv
20261 -+sys_character_set_connection(&vars, "character_set_connection",
20262 -+ &SV::collation_connection,
20263 -+ &default_charset_info, 0,
20264 -+ sys_var::SESSION_VARIABLE_IN_BINLOG);
20265 -+static sys_var_character_set_sv sys_character_set_results(&vars, "character_set_results",
20266 -+ &SV::character_set_results,
20267 -+ &default_charset_info, true);
20268 -+static sys_var_character_set_sv sys_character_set_filesystem(&vars, "character_set_filesystem",
20269 -+ &SV::character_set_filesystem,
20270 -+ &character_set_filesystem);
20271 -+static sys_var_thd_ulong sys_completion_type(&vars, "completion_type",
20272 -+ &SV::completion_type,
20273 -+ check_completion_type,
20274 -+ fix_completion_type);
20275 -+static sys_var_collation_sv
20276 -+sys_collation_connection(&vars, "collation_connection",
20277 -+ &SV::collation_connection, &default_charset_info,
20278 -+ sys_var::SESSION_VARIABLE_IN_BINLOG);
20279 -+static sys_var_collation_sv
20280 -+sys_collation_database(&vars, "collation_database", &SV::collation_database,
20281 -+ &default_charset_info,
20282 -+ sys_var::SESSION_VARIABLE_IN_BINLOG);
20283 -+static sys_var_collation_sv
20284 -+sys_collation_server(&vars, "collation_server", &SV::collation_server,
20285 -+ &default_charset_info,
20286 -+ sys_var::SESSION_VARIABLE_IN_BINLOG);
20287 -+static sys_var_long_ptr sys_concurrent_insert(&vars, "concurrent_insert",
20288 -+ &myisam_concurrent_insert);
20289 -+static sys_var_long_ptr sys_connect_timeout(&vars, "connect_timeout",
20290 -+ &connect_timeout);
20291 -+static sys_var_const_os_str sys_datadir(&vars, "datadir", mysql_real_data_home);
20292 -+#ifndef DBUG_OFF
20293 -+static sys_var_thd_dbug sys_dbug(&vars, "debug");
20294 -+#endif
20295 -+static sys_var_enum sys_delay_key_write(&vars, "delay_key_write",
20296 -+ &delay_key_write_options,
20297 -+ &delay_key_write_typelib,
20298 -+ fix_delay_key_write);
20299 -+static sys_var_long_ptr sys_delayed_insert_limit(&vars, "delayed_insert_limit",
20300 -+ &delayed_insert_limit);
20301 -+static sys_var_long_ptr sys_delayed_insert_timeout(&vars, "delayed_insert_timeout",
20302 -+ &delayed_insert_timeout);
20303 -+static sys_var_long_ptr sys_delayed_queue_size(&vars, "delayed_queue_size",
20304 -+ &delayed_queue_size);
20305 -+
20306 -+#ifdef HAVE_EVENT_SCHEDULER
20307 -+static sys_var_event_scheduler sys_event_scheduler(&vars, "event_scheduler");
20308 -+#endif
20309 -+
20310 -+static sys_var_long_ptr sys_expire_logs_days(&vars, "expire_logs_days",
20311 -+ &expire_logs_days);
20312 -+static sys_var_bool_ptr sys_flush(&vars, "flush", &myisam_flush);
20313 -+static sys_var_long_ptr sys_flush_time(&vars, "flush_time", &flush_time);
20314 -+static sys_var_str sys_ft_boolean_syntax(&vars, "ft_boolean_syntax",
20315 -+ sys_check_ftb_syntax,
20316 -+ sys_update_ftb_syntax,
20317 -+ sys_default_ftb_syntax,
20318 -+ ft_boolean_syntax);
20319 -+static sys_var_const sys_ft_max_word_len(&vars, "ft_max_word_len",
20320 -+ OPT_GLOBAL, SHOW_LONG,
20321 -+ (uchar*) &ft_max_word_len);
20322 -+static sys_var_const sys_ft_min_word_len(&vars, "ft_min_word_len",
20323 -+ OPT_GLOBAL, SHOW_LONG,
20324 -+ (uchar*) &ft_min_word_len);
20325 -+static sys_var_const sys_ft_query_expansion_limit(&vars,
20326 -+ "ft_query_expansion_limit",
20327 -+ OPT_GLOBAL, SHOW_LONG,
20328 -+ (uchar*)
20329 -+ &ft_query_expansion_limit);
20330 -+static sys_var_const sys_ft_stopword_file(&vars, "ft_stopword_file",
20331 -+ OPT_GLOBAL, SHOW_CHAR_PTR,
20332 -+ (uchar*) &ft_stopword_file);
20333 -+
20334 -+static sys_var_const sys_ignore_builtin_innodb(&vars, "ignore_builtin_innodb",
20335 -+ OPT_GLOBAL, SHOW_BOOL,
20336 -+ (uchar*) &opt_ignore_builtin_innodb);
20337 -+
20338 -+sys_var_str sys_init_connect(&vars, "init_connect", 0,
20339 -+ sys_update_init_connect,
20340 -+ sys_default_init_connect,0);
20341 -+static sys_var_const sys_init_file(&vars, "init_file",
20342 -+ OPT_GLOBAL, SHOW_CHAR_PTR,
20343 -+ (uchar*) &opt_init_file);
20344 -+sys_var_str sys_init_slave(&vars, "init_slave", 0,
20345 -+ sys_update_init_slave,
20346 -+ sys_default_init_slave,0);
20347 -+static sys_var_thd_ulong sys_interactive_timeout(&vars, "interactive_timeout",
20348 -+ &SV::net_interactive_timeout);
20349 -+static sys_var_thd_ulong sys_join_buffer_size(&vars, "join_buffer_size",
20350 -+ &SV::join_buff_size);
20351 -+static sys_var_key_buffer_size sys_key_buffer_size(&vars, "key_buffer_size");
20352 -+static sys_var_key_cache_long sys_key_cache_block_size(&vars, "key_cache_block_size",
20353 -+ offsetof(KEY_CACHE,
20354 -+ param_block_size));
20355 -+static sys_var_key_cache_long sys_key_cache_division_limit(&vars, "key_cache_division_limit",
20356 -+ offsetof(KEY_CACHE,
20357 -+ param_division_limit));
20358 -+static sys_var_key_cache_long sys_key_cache_age_threshold(&vars, "key_cache_age_threshold",
20359 -+ offsetof(KEY_CACHE,
20360 -+ param_age_threshold));
20361 -+static sys_var_const sys_language(&vars, "language",
20362 -+ OPT_GLOBAL, SHOW_CHAR,
20363 -+ (uchar*) language);
20364 -+static sys_var_const sys_large_files_support(&vars, "large_files_support",
20365 -+ OPT_GLOBAL, SHOW_BOOL,
20366 -+ (uchar*) &opt_large_files);
20367 -+static sys_var_const sys_large_page_size(&vars, "large_page_size",
20368 -+ OPT_GLOBAL, SHOW_INT,
20369 -+ (uchar*) &opt_large_page_size);
20370 -+static sys_var_const sys_large_pages(&vars, "large_pages",
20371 -+ OPT_GLOBAL, SHOW_MY_BOOL,
20372 -+ (uchar*) &opt_large_pages);
20373 -+static sys_var_bool_ptr sys_local_infile(&vars, "local_infile",
20374 -+ &opt_local_infile);
20375 -+#ifdef HAVE_MLOCKALL
20376 -+static sys_var_const sys_locked_in_memory(&vars, "locked_in_memory",
20377 -+ OPT_GLOBAL, SHOW_MY_BOOL,
20378 -+ (uchar*) &locked_in_memory);
20379 -+#endif
20380 -+static sys_var_const sys_log_bin(&vars, "log_bin",
20381 -+ OPT_GLOBAL, SHOW_BOOL,
20382 -+ (uchar*) &opt_bin_log);
20383 -+static sys_var_trust_routine_creators
20384 -+sys_trust_routine_creators(&vars, "log_bin_trust_routine_creators",
20385 -+ &trust_function_creators);
20386 -+static sys_var_bool_ptr
20387 -+sys_trust_function_creators(&vars, "log_bin_trust_function_creators",
20388 -+ &trust_function_creators);
20389 -+static sys_var_const sys_log_error(&vars, "log_error",
20390 -+ OPT_GLOBAL, SHOW_CHAR,
20391 -+ (uchar*) log_error_file);
20392 -+static sys_var_bool_ptr
20393 -+ sys_log_queries_not_using_indexes(&vars, "log_queries_not_using_indexes",
20394 -+ &opt_log_queries_not_using_indexes);
20395 -+static sys_var_thd_ulong sys_log_warnings(&vars, "log_warnings", &SV::log_warnings);
20396 -+static sys_var_microseconds sys_var_long_query_time(&vars, "long_query_time",
20397 -+ &SV::long_query_time);
20398 -+static sys_var_thd_bool sys_low_priority_updates(&vars, "low_priority_updates",
20399 -+ &SV::low_priority_updates,
20400 -+ fix_low_priority_updates);
20401 -+#ifndef TO_BE_DELETED /* Alias for the low_priority_updates */
20402 -+static sys_var_thd_bool sys_sql_low_priority_updates(&vars, "sql_low_priority_updates",
20403 -+ &SV::low_priority_updates,
20404 -+ fix_low_priority_updates);
20405 -+#endif
20406 -+static sys_var_const sys_lower_case_file_system(&vars,
20407 -+ "lower_case_file_system",
20408 -+ OPT_GLOBAL, SHOW_MY_BOOL,
20409 -+ (uchar*)
20410 -+ &lower_case_file_system);
20411 -+static sys_var_const sys_lower_case_table_names(&vars,
20412 -+ "lower_case_table_names",
20413 -+ OPT_GLOBAL, SHOW_INT,
20414 -+ (uchar*)
20415 -+ &lower_case_table_names);
20416 -+static sys_var_thd_ulong_session_readonly sys_max_allowed_packet(&vars, "max_allowed_packet",
20417 -+ &SV::max_allowed_packet,
20418 -+ check_max_allowed_packet);
20419 -+static sys_var_ulonglong_ptr sys_max_binlog_cache_size(&vars, "max_binlog_cache_size",
20420 -+ &max_binlog_cache_size);
20421 -+static sys_var_long_ptr sys_max_binlog_size(&vars, "max_binlog_size",
20422 -+ &max_binlog_size,
20423 -+ fix_max_binlog_size);
20424 -+static sys_var_long_ptr sys_max_connections(&vars, "max_connections",
20425 -+ &max_connections,
20426 -+ fix_max_connections);
20427 -+static sys_var_long_ptr sys_max_connect_errors(&vars, "max_connect_errors",
20428 -+ &max_connect_errors);
20429 -+static sys_var_thd_ulong sys_max_insert_delayed_threads(&vars, "max_insert_delayed_threads",
20430 -+ &SV::max_insert_delayed_threads,
20431 -+ check_max_delayed_threads,
20432 -+ fix_max_connections);
20433 -+static sys_var_thd_ulong sys_max_delayed_threads(&vars, "max_delayed_threads",
20434 -+ &SV::max_insert_delayed_threads,
20435 -+ check_max_delayed_threads,
20436 -+ fix_max_connections);
20437 -+static sys_var_thd_ulong sys_max_error_count(&vars, "max_error_count",
20438 -+ &SV::max_error_count);
20439 -+static sys_var_thd_ulonglong sys_max_heap_table_size(&vars, "max_heap_table_size",
20440 -+ &SV::max_heap_table_size);
20441 -+static sys_var_thd_ulong sys_pseudo_thread_id(&vars, "pseudo_thread_id",
20442 -+ &SV::pseudo_thread_id,
20443 -+ check_pseudo_thread_id, 0,
20444 -+ sys_var::SESSION_VARIABLE_IN_BINLOG);
20445 -+static sys_var_thd_ha_rows sys_max_join_size(&vars, "max_join_size",
20446 -+ &SV::max_join_size,
20447 -+ fix_max_join_size);
20448 -+static sys_var_thd_ulong sys_max_seeks_for_key(&vars, "max_seeks_for_key",
20449 -+ &SV::max_seeks_for_key);
20450 -+static sys_var_thd_ulong sys_max_length_for_sort_data(&vars, "max_length_for_sort_data",
20451 -+ &SV::max_length_for_sort_data);
20452 -+static sys_var_const sys_max_long_data_size(&vars,
20453 -+ "max_long_data_size",
20454 -+ OPT_GLOBAL, SHOW_LONG,
20455 -+ (uchar*)
20456 -+ &max_long_data_size);
20457 -+
20458 -+#ifndef TO_BE_DELETED /* Alias for max_join_size */
20459 -+static sys_var_thd_ha_rows sys_sql_max_join_size(&vars, "sql_max_join_size",
20460 -+ &SV::max_join_size,
20461 -+ fix_max_join_size);
20462 -+#endif
20463 -+static sys_var_long_ptr_global
20464 -+sys_max_prepared_stmt_count(&vars, "max_prepared_stmt_count",
20465 -+ &max_prepared_stmt_count,
20466 -+ &LOCK_prepared_stmt_count);
20467 -+static sys_var_long_ptr sys_max_relay_log_size(&vars, "max_relay_log_size",
20468 -+ &max_relay_log_size,
20469 -+ fix_max_relay_log_size);
20470 -+static sys_var_thd_ulong sys_max_sort_length(&vars, "max_sort_length",
20471 -+ &SV::max_sort_length);
20472 -+static sys_var_thd_ulong sys_max_sp_recursion_depth(&vars, "max_sp_recursion_depth",
20473 -+ &SV::max_sp_recursion_depth);
20474 -+static sys_var_max_user_conn sys_max_user_connections(&vars, "max_user_connections");
20475 -+static sys_var_thd_ulong sys_max_tmp_tables(&vars, "max_tmp_tables",
20476 -+ &SV::max_tmp_tables);
20477 -+static sys_var_long_ptr sys_max_write_lock_count(&vars, "max_write_lock_count",
20478 -+ &max_write_lock_count);
20479 -+static sys_var_thd_ulong sys_min_examined_row_limit(&vars, "min_examined_row_limit",
20480 -+ &SV::min_examined_row_limit);
20481 -+static sys_var_thd_ulong sys_multi_range_count(&vars, "multi_range_count",
20482 -+ &SV::multi_range_count);
20483 -+static sys_var_long_ptr sys_myisam_data_pointer_size(&vars, "myisam_data_pointer_size",
20484 -+ &myisam_data_pointer_size);
20485 -+static sys_var_thd_ulonglong sys_myisam_max_sort_file_size(&vars, "myisam_max_sort_file_size", &SV::myisam_max_sort_file_size, fix_myisam_max_sort_file_size, 1);
20486 -+static sys_var_const sys_myisam_recover_options(&vars, "myisam_recover_options",
20487 -+ OPT_GLOBAL, SHOW_CHAR_PTR,
20488 -+ (uchar*)
20489 -+ &myisam_recover_options_str);
20490 -+static sys_var_thd_ulong sys_myisam_repair_threads(&vars, "myisam_repair_threads", &SV::myisam_repair_threads);
20491 -+static sys_var_thd_ulong sys_myisam_sort_buffer_size(&vars, "myisam_sort_buffer_size", &SV::myisam_sort_buff_size);
20492 -+static sys_var_bool_ptr sys_myisam_use_mmap(&vars, "myisam_use_mmap",
20493 -+ &opt_myisam_use_mmap);
20494 -+
20495 -+static sys_var_thd_enum sys_myisam_stats_method(&vars, "myisam_stats_method",
20496 -+ &SV::myisam_stats_method,
20497 -+ &myisam_stats_method_typelib,
20498 -+ NULL);
20499 -+
20500 -+#ifdef __NT__
20501 -+/* purecov: begin inspected */
20502 -+static sys_var_const sys_named_pipe(&vars, "named_pipe",
20503 -+ OPT_GLOBAL, SHOW_MY_BOOL,
20504 -+ (uchar*) &opt_enable_named_pipe);
20505 -+/* purecov: end */
20506 -+#endif
20507 -+static sys_var_thd_ulong_session_readonly sys_net_buffer_length(&vars, "net_buffer_length",
20508 -+ &SV::net_buffer_length,
20509 -+ check_net_buffer_length);
20510 -+static sys_var_thd_ulong sys_net_read_timeout(&vars, "net_read_timeout",
20511 -+ &SV::net_read_timeout,
20512 -+ 0, fix_net_read_timeout);
20513 -+static sys_var_thd_ulong sys_net_write_timeout(&vars, "net_write_timeout",
20514 -+ &SV::net_write_timeout,
20515 -+ 0, fix_net_write_timeout);
20516 -+static sys_var_thd_ulong sys_net_retry_count(&vars, "net_retry_count",
20517 -+ &SV::net_retry_count,
20518 -+ 0, fix_net_retry_count);
20519 -+static sys_var_thd_bool sys_new_mode(&vars, "new", &SV::new_mode);
20520 -+static sys_var_bool_ptr_readonly sys_old_mode(&vars, "old",
20521 -+ &global_system_variables.old_mode);
20522 -+/* these two cannot be static */
20523 -+sys_var_thd_bool sys_old_alter_table(&vars, "old_alter_table",
20524 -+ &SV::old_alter_table);
20525 -+sys_var_thd_bool sys_old_passwords(&vars, "old_passwords", &SV::old_passwords);
20526 -+static sys_var_const sys_open_files_limit(&vars, "open_files_limit",
20527 -+ OPT_GLOBAL, SHOW_LONG,
20528 -+ (uchar*)
20529 -+ &open_files_limit);
20530 -+static sys_var_thd_ulong sys_optimizer_prune_level(&vars, "optimizer_prune_level",
20531 -+ &SV::optimizer_prune_level);
20532 -+static sys_var_thd_ulong sys_optimizer_search_depth(&vars, "optimizer_search_depth",
20533 -+ &SV::optimizer_search_depth);
20534 -+static sys_var_thd_optimizer_switch sys_optimizer_switch(&vars, "optimizer_switch",
20535 -+ &SV::optimizer_switch);
20536 -+static sys_var_const sys_pid_file(&vars, "pid_file",
20537 -+ OPT_GLOBAL, SHOW_CHAR,
20538 -+ (uchar*) pidfile_name);
20539 -+static sys_var_const_os sys_plugin_dir(&vars, "plugin_dir",
20540 -+ OPT_GLOBAL, SHOW_CHAR,
20541 -+ (uchar*) opt_plugin_dir);
20542 -+static sys_var_const sys_port(&vars, "port",
20543 -+ OPT_GLOBAL, SHOW_INT,
20544 -+ (uchar*) &mysqld_port);
20545 -+static sys_var_thd_ulong sys_preload_buff_size(&vars, "preload_buffer_size",
20546 -+ &SV::preload_buff_size);
20547 -+static sys_var_const sys_protocol_version(&vars, "protocol_version",
20548 -+ OPT_GLOBAL, SHOW_INT,
20549 -+ (uchar*)
20550 -+ &protocol_version);
20551 -+static sys_var_thd_ulong sys_read_buff_size(&vars, "read_buffer_size",
20552 -+ &SV::read_buff_size);
20553 -+static sys_var_opt_readonly sys_readonly(&vars, "read_only", &opt_readonly);
20554 -+static sys_var_thd_ulong sys_read_rnd_buff_size(&vars, "read_rnd_buffer_size",
20555 -+ &SV::read_rnd_buff_size);
20556 -+static sys_var_thd_ulong sys_div_precincrement(&vars, "div_precision_increment",
20557 -+ &SV::div_precincrement);
20558 -+static sys_var_long_ptr sys_rpl_recovery_rank(&vars, "rpl_recovery_rank",
20559 -+ &rpl_recovery_rank);
20560 -+static sys_var_long_ptr sys_query_cache_size(&vars, "query_cache_size",
20561 -+ &query_cache_size,
20562 -+ fix_query_cache_size);
20563 -+
20564 -+static sys_var_thd_ulong sys_range_alloc_block_size(&vars, "range_alloc_block_size",
20565 -+ &SV::range_alloc_block_size);
20566 -+static sys_var_thd_ulong sys_query_alloc_block_size(&vars, "query_alloc_block_size",
20567 -+ &SV::query_alloc_block_size,
20568 -+ 0, fix_thd_mem_root);
20569 -+static sys_var_thd_ulong sys_query_prealloc_size(&vars, "query_prealloc_size",
20570 -+ &SV::query_prealloc_size,
20571 -+ 0, fix_thd_mem_root);
20572 -+#ifdef HAVE_SMEM
20573 -+/* purecov: begin tested */
20574 -+static sys_var_const sys_shared_memory(&vars, "shared_memory",
20575 -+ OPT_GLOBAL, SHOW_MY_BOOL,
20576 -+ (uchar*)
20577 -+ &opt_enable_shared_memory);
20578 -+static sys_var_const sys_shared_memory_base_name(&vars,
20579 -+ "shared_memory_base_name",
20580 -+ OPT_GLOBAL, SHOW_CHAR_PTR,
20581 -+ (uchar*)
20582 -+ &shared_memory_base_name);
20583 -+/* purecov: end */
20584 -+#endif
20585 -+static sys_var_const sys_skip_external_locking(&vars,
20586 -+ "skip_external_locking",
20587 -+ OPT_GLOBAL, SHOW_MY_BOOL,
20588 -+ (uchar*)
20589 -+ &my_disable_locking);
20590 -+static sys_var_const sys_skip_networking(&vars, "skip_networking",
20591 -+ OPT_GLOBAL, SHOW_BOOL,
20592 -+ (uchar*) &opt_disable_networking);
20593 -+static sys_var_const sys_skip_show_database(&vars, "skip_show_database",
20594 -+ OPT_GLOBAL, SHOW_BOOL,
20595 -+ (uchar*) &opt_skip_show_db);
20596 -+
20597 -+static sys_var_const sys_skip_name_resolve(&vars, "skip_name_resolve",
20598 -+ OPT_GLOBAL, SHOW_BOOL,
20599 -+ (uchar*) &opt_skip_name_resolve);
20600 -+
20601 -+static sys_var_const sys_socket(&vars, "socket",
20602 -+ OPT_GLOBAL, SHOW_CHAR_PTR,
20603 -+ (uchar*) &mysqld_unix_port);
20604 -+
20605 -+#ifdef HAVE_THR_SETCONCURRENCY
20606 -+/* purecov: begin tested */
20607 -+static sys_var_const sys_thread_concurrency(&vars, "thread_concurrency",
20608 -+ OPT_GLOBAL, SHOW_LONG,
20609 -+ (uchar*) &concurrency);
20610 -+/* purecov: end */
20611 -+#endif
20612 -+static sys_var_const sys_thread_stack(&vars, "thread_stack",
20613 -+ OPT_GLOBAL, SHOW_LONG,
20614 -+ (uchar*) &my_thread_stack_size);
20615 -+static sys_var_readonly_os sys_tmpdir(&vars, "tmpdir", OPT_GLOBAL, SHOW_CHAR, get_tmpdir);
20616 -+static sys_var_thd_ulong sys_trans_alloc_block_size(&vars, "transaction_alloc_block_size",
20617 -+ &SV::trans_alloc_block_size,
20618 -+ 0, fix_trans_mem_root);
20619 -+static sys_var_thd_ulong sys_trans_prealloc_size(&vars, "transaction_prealloc_size",
20620 -+ &SV::trans_prealloc_size,
20621 -+ 0, fix_trans_mem_root);
20622 -+sys_var_enum_const sys_thread_handling(&vars, "thread_handling",
20623 -+ &SV::thread_handling,
20624 -+ &thread_handling_typelib,
20625 -+ NULL);
20626 -+
20627 -+#ifdef HAVE_QUERY_CACHE
20628 -+static sys_var_long_ptr sys_query_cache_limit(&vars, "query_cache_limit",
20629 -+ &query_cache.query_cache_limit);
20630 -+static sys_var_long_ptr sys_query_cache_min_res_unit(&vars, "query_cache_min_res_unit",
20631 -+ &query_cache_min_res_unit,
20632 -+ fix_query_cache_min_res_unit);
20633 -+static sys_var_thd_enum sys_query_cache_type(&vars, "query_cache_type",
20634 -+ &SV::query_cache_type,
20635 -+ &query_cache_type_typelib);
20636 -+static sys_var_thd_bool
20637 -+sys_query_cache_wlock_invalidate(&vars, "query_cache_wlock_invalidate",
20638 -+ &SV::query_cache_wlock_invalidate);
20639 -+#endif /* HAVE_QUERY_CACHE */
20640 -+static sys_var_bool_ptr sys_secure_auth(&vars, "secure_auth", &opt_secure_auth);
20641 -+static sys_var_const_str_ptr sys_secure_file_priv(&vars, "secure_file_priv",
20642 -+ &opt_secure_file_priv);
20643 -+static sys_var_long_ptr sys_server_id(&vars, "server_id", &server_id, fix_server_id);
20644 -+static sys_var_bool_ptr sys_slave_compressed_protocol(&vars, "slave_compressed_protocol",
20645 -+ &opt_slave_compressed_protocol);
20646 -+static sys_var_set_slave_mode slave_exec_mode(&vars,
20647 -+ "slave_exec_mode",
20648 -+ &slave_exec_mode_options,
20649 -+ &slave_exec_mode_typelib,
20650 -+ 0);
20651 -+static sys_var_long_ptr sys_slow_launch_time(&vars, "slow_launch_time",
20652 -+ &slow_launch_time);
20653 -+static sys_var_thd_ulong sys_sort_buffer(&vars, "sort_buffer_size",
20654 -+ &SV::sortbuff_size);
20655 -+/*
20656 -+ sql_mode should *not* have binlog_mode=SESSION_VARIABLE_IN_BINLOG:
20657 -+ even though it is written to the binlog, the slave ignores the
20658 -+ MODE_NO_DIR_IN_CREATE variable, so slave's value differs from
20659 -+ master's (see log_event.cc: Query_log_event::do_apply_event()).
20660 -+*/
20661 -+static sys_var_thd_sql_mode sys_sql_mode(&vars, "sql_mode",
20662 -+ &SV::sql_mode);
20663 -+#ifdef HAVE_OPENSSL
20664 -+extern char *opt_ssl_ca, *opt_ssl_capath, *opt_ssl_cert, *opt_ssl_cipher,
20665 -+ *opt_ssl_key;
20666 -+static sys_var_const_os_str_ptr sys_ssl_ca(&vars, "ssl_ca", &opt_ssl_ca);
20667 -+static sys_var_const_os_str_ptr sys_ssl_capath(&vars, "ssl_capath", &opt_ssl_capath);
20668 -+static sys_var_const_os_str_ptr sys_ssl_cert(&vars, "ssl_cert", &opt_ssl_cert);
20669 -+static sys_var_const_os_str_ptr sys_ssl_cipher(&vars, "ssl_cipher", &opt_ssl_cipher);
20670 -+static sys_var_const_os_str_ptr sys_ssl_key(&vars, "ssl_key", &opt_ssl_key);
20671 -+#else
20672 -+static sys_var_const_os_str sys_ssl_ca(&vars, "ssl_ca", NULL);
20673 -+static sys_var_const_os_str sys_ssl_capath(&vars, "ssl_capath", NULL);
20674 -+static sys_var_const_os_str sys_ssl_cert(&vars, "ssl_cert", NULL);
20675 -+static sys_var_const_os_str sys_ssl_cipher(&vars, "ssl_cipher", NULL);
20676 -+static sys_var_const_os_str sys_ssl_key(&vars, "ssl_key", NULL);
20677 -+#endif
20678 -+static sys_var_thd_enum
20679 -+sys_updatable_views_with_limit(&vars, "updatable_views_with_limit",
20680 -+ &SV::updatable_views_with_limit,
20681 -+ &updatable_views_with_limit_typelib);
20682 -+
20683 -+static sys_var_thd_table_type sys_table_type(&vars, "table_type",
20684 -+ &SV::table_plugin);
20685 -+static sys_var_thd_storage_engine sys_storage_engine(&vars, "storage_engine",
20686 -+ &SV::table_plugin);
20687 -+static sys_var_bool_ptr sys_sync_frm(&vars, "sync_frm", &opt_sync_frm);
20688 -+static sys_var_const_str sys_system_time_zone(&vars, "system_time_zone",
20689 -+ system_time_zone);
20690 -+static sys_var_long_ptr sys_table_def_size(&vars, "table_definition_cache",
20691 -+ &table_def_size);
20692 -+static sys_var_long_ptr sys_table_cache_size(&vars, "table_open_cache",
20693 -+ &table_cache_size);
20694 -+static sys_var_long_ptr sys_table_lock_wait_timeout(&vars, "table_lock_wait_timeout",
20695 -+ &table_lock_wait_timeout);
20696 -+
20697 -+#if defined(ENABLED_DEBUG_SYNC)
20698 -+/* Debug Sync Facility. Implemented in debug_sync.cc. */
20699 -+static sys_var_debug_sync sys_debug_sync(&vars, "debug_sync");
20700 -+#endif /* defined(ENABLED_DEBUG_SYNC) */
20701 -+
20702 -+static sys_var_long_ptr sys_thread_cache_size(&vars, "thread_cache_size",
20703 -+ &thread_cache_size);
20704 -+#if HAVE_POOL_OF_THREADS == 1
20705 -+sys_var_long_ptr sys_thread_pool_size(&vars, "thread_pool_size",
20706 -+ &thread_pool_size);
20707 -+#endif
20708 -+static sys_var_thd_enum sys_tx_isolation(&vars, "tx_isolation",
20709 -+ &SV::tx_isolation,
20710 -+ &tx_isolation_typelib,
20711 -+ fix_tx_isolation,
20712 -+ check_tx_isolation);
20713 -+static sys_var_thd_ulonglong sys_tmp_table_size(&vars, "tmp_table_size",
20714 -+ &SV::tmp_table_size);
20715 -+static sys_var_bool_ptr sys_timed_mutexes(&vars, "timed_mutexes",
20716 -+ &timed_mutexes);
20717 -+static sys_var_const_str sys_version(&vars, "version", server_version);
20718 -+static sys_var_const_str sys_version_comment(&vars, "version_comment",
20719 -+ MYSQL_COMPILATION_COMMENT);
20720 -+static sys_var_const_str sys_version_compile_machine(&vars, "version_compile_machine",
20721 -+ MACHINE_TYPE);
20722 -+static sys_var_const_str sys_version_compile_os(&vars, "version_compile_os",
20723 -+ SYSTEM_TYPE);
20724 -+static sys_var_thd_ulong sys_net_wait_timeout(&vars, "wait_timeout",
20725 -+ &SV::net_wait_timeout);
20726 -+
20727 -+/* Condition pushdown to storage engine */
20728 -+static sys_var_thd_bool
20729 -+sys_engine_condition_pushdown(&vars, "engine_condition_pushdown",
20730 -+ &SV::engine_condition_pushdown);
20731 -+
20732 -+#ifdef WITH_NDBCLUSTER_STORAGE_ENGINE
20733 -+/* ndb thread specific variable settings */
20734 -+static sys_var_thd_ulong
20735 -+sys_ndb_autoincrement_prefetch_sz(&vars, "ndb_autoincrement_prefetch_sz",
20736 -+ &SV::ndb_autoincrement_prefetch_sz);
20737 -+static sys_var_thd_bool
20738 -+sys_ndb_force_send(&vars, "ndb_force_send", &SV::ndb_force_send);
20739 -+#ifdef HAVE_NDB_BINLOG
20740 -+static sys_var_long_ptr
20741 -+sys_ndb_report_thresh_binlog_epoch_slip(&vars, "ndb_report_thresh_binlog_epoch_slip",
20742 -+ &ndb_report_thresh_binlog_epoch_slip);
20743 -+static sys_var_long_ptr
20744 -+sys_ndb_report_thresh_binlog_mem_usage(&vars, "ndb_report_thresh_binlog_mem_usage",
20745 -+ &ndb_report_thresh_binlog_mem_usage);
20746 -+#endif
20747 -+static sys_var_thd_bool
20748 -+sys_ndb_use_exact_count(&vars, "ndb_use_exact_count", &SV::ndb_use_exact_count);
20749 -+static sys_var_thd_bool
20750 -+sys_ndb_use_transactions(&vars, "ndb_use_transactions", &SV::ndb_use_transactions);
20751 -+static sys_var_long_ptr
20752 -+sys_ndb_cache_check_time(&vars, "ndb_cache_check_time", &ndb_cache_check_time);
20753 -+static sys_var_const_str
20754 -+sys_ndb_connectstring(&vars, "ndb_connectstring", opt_ndb_constrbuf);
20755 -+static sys_var_thd_bool
20756 -+sys_ndb_index_stat_enable(&vars, "ndb_index_stat_enable",
20757 -+ &SV::ndb_index_stat_enable);
20758 -+static sys_var_thd_ulong
20759 -+sys_ndb_index_stat_cache_entries(&vars, "ndb_index_stat_cache_entries",
20760 -+ &SV::ndb_index_stat_cache_entries);
20761 -+static sys_var_thd_ulong
20762 -+sys_ndb_index_stat_update_freq(&vars, "ndb_index_stat_update_freq",
20763 -+ &SV::ndb_index_stat_update_freq);
20764 -+static sys_var_long_ptr
20765 -+sys_ndb_extra_logging(&vars, "ndb_extra_logging", &ndb_extra_logging);
20766 -+static sys_var_thd_bool
20767 -+sys_ndb_use_copying_alter_table(&vars, "ndb_use_copying_alter_table", &SV::ndb_use_copying_alter_table);
20768 -+#endif //WITH_NDBCLUSTER_STORAGE_ENGINE
20769 -+
20770 -+/* Time/date/datetime formats */
20771 -+
20772 -+static sys_var_thd_date_time_format sys_time_format(&vars, "time_format",
20773 -+ &SV::time_format,
20774 -+ MYSQL_TIMESTAMP_TIME);
20775 -+static sys_var_thd_date_time_format sys_date_format(&vars, "date_format",
20776 -+ &SV::date_format,
20777 -+ MYSQL_TIMESTAMP_DATE);
20778 -+static sys_var_thd_date_time_format sys_datetime_format(&vars, "datetime_format",
20779 -+ &SV::datetime_format,
20780 -+ MYSQL_TIMESTAMP_DATETIME);
20781 -+
20782 -+/* Variables that are bits in THD */
20783 -+
20784 -+sys_var_thd_bit sys_autocommit(&vars, "autocommit", 0,
20785 -+ set_option_autocommit,
20786 -+ OPTION_NOT_AUTOCOMMIT,
20787 -+ 1);
20788 -+static sys_var_thd_bit sys_big_tables(&vars, "big_tables", 0,
20789 -+ set_option_bit,
20790 -+ OPTION_BIG_TABLES);
20791 -+#ifndef TO_BE_DELETED /* Alias for big_tables */
20792 -+static sys_var_thd_bit sys_sql_big_tables(&vars, "sql_big_tables", 0,
20793 -+ set_option_bit,
20794 -+ OPTION_BIG_TABLES);
20795 -+#endif
20796 -+static sys_var_thd_bit sys_big_selects(&vars, "sql_big_selects", 0,
20797 -+ set_option_bit,
20798 -+ OPTION_BIG_SELECTS);
20799 -+static sys_var_thd_bit sys_log_off(&vars, "sql_log_off",
20800 -+ check_log_update,
20801 -+ set_option_bit,
20802 -+ OPTION_LOG_OFF);
20803 -+static sys_var_thd_bit sys_log_update(&vars, "sql_log_update",
20804 -+ check_log_update,
20805 -+ set_log_update,
20806 -+ OPTION_BIN_LOG);
20807 -+static sys_var_thd_bit sys_log_binlog(&vars, "sql_log_bin",
20808 -+ check_log_update,
20809 -+ set_option_log_bin_bit,
20810 -+ OPTION_BIN_LOG);
20811 -+static sys_var_thd_bit sys_sql_warnings(&vars, "sql_warnings", 0,
20812 -+ set_option_bit,
20813 -+ OPTION_WARNINGS);
20814 -+static sys_var_thd_bit sys_sql_notes(&vars, "sql_notes", 0,
20815 -+ set_option_bit,
20816 -+ OPTION_SQL_NOTES);
20817 -+static sys_var_thd_bit sys_auto_is_null(&vars, "sql_auto_is_null", 0,
20818 -+ set_option_bit,
20819 -+ OPTION_AUTO_IS_NULL, 0,
20820 -+ sys_var::SESSION_VARIABLE_IN_BINLOG);
20821 -+static sys_var_thd_bit sys_safe_updates(&vars, "sql_safe_updates", 0,
20822 -+ set_option_bit,
20823 -+ OPTION_SAFE_UPDATES);
20824 -+static sys_var_thd_bit sys_buffer_results(&vars, "sql_buffer_result", 0,
20825 -+ set_option_bit,
20826 -+ OPTION_BUFFER_RESULT);
20827 -+static sys_var_thd_bit sys_quote_show_create(&vars, "sql_quote_show_create", 0,
20828 -+ set_option_bit,
20829 -+ OPTION_QUOTE_SHOW_CREATE);
20830 -+static sys_var_thd_bit sys_foreign_key_checks(&vars, "foreign_key_checks", 0,
20831 -+ set_option_bit,
20832 -+ OPTION_NO_FOREIGN_KEY_CHECKS,
20833 -+ 1, sys_var::SESSION_VARIABLE_IN_BINLOG);
20834 -+static sys_var_thd_bit sys_unique_checks(&vars, "unique_checks", 0,
20835 -+ set_option_bit,
20836 -+ OPTION_RELAXED_UNIQUE_CHECKS,
20837 -+ 1,
20838 -+ sys_var::SESSION_VARIABLE_IN_BINLOG);
20839 -+#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
20840 -+static sys_var_thd_bit sys_profiling(&vars, "profiling", NULL,
20841 -+ set_option_bit,
20842 -+ ulonglong(OPTION_PROFILING));
20843 -+static sys_var_thd_ulong sys_profiling_history_size(&vars, "profiling_history_size",
20844 -+ &SV::profiling_history_size);
20845 -+#endif
20846 -+
20847 -+/* Local state variables */
20848 -+
20849 -+static sys_var_thd_ha_rows sys_select_limit(&vars, "sql_select_limit",
20850 -+ &SV::select_limit);
20851 -+static sys_var_timestamp sys_timestamp(&vars, "timestamp",
20852 -+ sys_var::SESSION_VARIABLE_IN_BINLOG);
20853 -+static sys_var_last_insert_id
20854 -+sys_last_insert_id(&vars, "last_insert_id",
20855 -+ sys_var::SESSION_VARIABLE_IN_BINLOG);
20856 -+/*
20857 -+ identity is an alias for last_insert_id(), so that we are compatible
20858 -+ with Sybase
20859 -+*/
20860 -+static sys_var_last_insert_id
20861 -+sys_identity(&vars, "identity", sys_var::SESSION_VARIABLE_IN_BINLOG);
20862 -+
20863 -+static sys_var_thd_lc_time_names
20864 -+sys_lc_time_names(&vars, "lc_time_names", sys_var::SESSION_VARIABLE_IN_BINLOG);
20865 -+
20866 -+/*
20867 -+ insert_id should *not* be marked as written to the binlog (i.e., it
20868 -+ should *not* have binlog_status==SESSION_VARIABLE_IN_BINLOG),
20869 -+ because we want any statement that refers to insert_id explicitly to
20870 -+ be unsafe. (By "explicitly", we mean using @@session.insert_id,
20871 -+ whereas insert_id is used "implicitly" when NULL value is inserted
20872 -+ into an auto_increment column).
20873 -+
20874 -+ We want statements referring explicitly to @@session.insert_id to be
20875 -+ unsafe, because insert_id is modified internally by the slave sql
20876 -+ thread when NULL values are inserted in an AUTO_INCREMENT column.
20877 -+ This modification interfers with the value of the
20878 -+ @@session.insert_id variable if @@session.insert_id is referred
20879 -+ explicitly by an insert statement (as is seen by executing "SET
20880 -+ @@session.insert_id=0; CREATE TABLE t (a INT, b INT KEY
20881 -+ AUTO_INCREMENT); INSERT INTO t(a) VALUES (@@session.insert_id);" in
20882 -+ statement-based logging mode: t will be different on master and
20883 -+ slave).
20884 -+*/
20885 -+static sys_var_insert_id sys_insert_id(&vars, "insert_id");
20886 -+static sys_var_readonly sys_error_count(&vars, "error_count",
20887 -+ OPT_SESSION,
20888 -+ SHOW_LONG,
20889 -+ get_error_count);
20890 -+static sys_var_readonly sys_warning_count(&vars, "warning_count",
20891 -+ OPT_SESSION,
20892 -+ SHOW_LONG,
20893 -+ get_warning_count);
20894 -+
20895 -+static sys_var_rand_seed1 sys_rand_seed1(&vars, "rand_seed1",
20896 -+ sys_var::SESSION_VARIABLE_IN_BINLOG);
20897 -+static sys_var_rand_seed2 sys_rand_seed2(&vars, "rand_seed2",
20898 -+ sys_var::SESSION_VARIABLE_IN_BINLOG);
20899 -+
20900 -+static sys_var_thd_ulong sys_default_week_format(&vars, "default_week_format",
20901 -+ &SV::default_week_format);
20902 -+
20903 -+sys_var_thd_ulong sys_group_concat_max_len(&vars, "group_concat_max_len",
20904 -+ &SV::group_concat_max_len);
20905 -+
20906 -+sys_var_thd_time_zone sys_time_zone(&vars, "time_zone",
20907 -+ sys_var::SESSION_VARIABLE_IN_BINLOG);
20908 -+
20909 -+/* Global read-only variable containing hostname */
20910 -+static sys_var_const_str sys_hostname(&vars, "hostname", glob_hostname);
20911 -+
20912 -+#ifndef EMBEDDED_LIBRARY
20913 -+static sys_var_const_str_ptr sys_repl_report_host(&vars, "report_host", &report_host);
20914 -+static sys_var_const_str_ptr sys_repl_report_user(&vars, "report_user", &report_user);
20915 -+static sys_var_const_str_ptr sys_repl_report_password(&vars, "report_password", &report_password);
20916 -+
20917 -+static uchar *slave_get_report_port(THD *thd)
20918 -+{
20919 -+ thd->sys_var_tmp.long_value= report_port;
20920 -+ return (uchar*) &thd->sys_var_tmp.long_value;
20921 -+}
20922 -+
20923 -+static sys_var_readonly sys_repl_report_port(&vars, "report_port", OPT_GLOBAL, SHOW_LONG, slave_get_report_port);
20924 -+
20925 -+#endif
20926 -+
20927 -+sys_var_thd_bool sys_keep_files_on_create(&vars, "keep_files_on_create",
20928 -+ &SV::keep_files_on_create);
20929 -+/* Read only variables */
20930 -+
20931 -+static sys_var_have_variable sys_have_compress(&vars, "have_compress", &have_compress);
20932 -+static sys_var_have_variable sys_have_crypt(&vars, "have_crypt", &have_crypt);
20933 -+static sys_var_have_plugin sys_have_csv(&vars, "have_csv", C_STRING_WITH_LEN("csv"), MYSQL_STORAGE_ENGINE_PLUGIN);
20934 -+static sys_var_have_variable sys_have_dlopen(&vars, "have_dynamic_loading", &have_dlopen);
20935 -+static sys_var_have_variable sys_have_geometry(&vars, "have_geometry", &have_geometry);
20936 -+static sys_var_have_plugin sys_have_innodb(&vars, "have_innodb", C_STRING_WITH_LEN("innodb"), MYSQL_STORAGE_ENGINE_PLUGIN);
20937 -+static sys_var_have_plugin sys_have_ndbcluster(&vars, "have_ndbcluster", C_STRING_WITH_LEN("ndbcluster"), MYSQL_STORAGE_ENGINE_PLUGIN);
20938 -+static sys_var_have_variable sys_have_openssl(&vars, "have_openssl", &have_ssl);
20939 -+static sys_var_have_variable sys_have_ssl(&vars, "have_ssl", &have_ssl);
20940 -+static sys_var_have_plugin sys_have_partition_db(&vars, "have_partitioning", C_STRING_WITH_LEN("partition"), MYSQL_STORAGE_ENGINE_PLUGIN);
20941 -+static sys_var_have_variable sys_have_query_cache(&vars, "have_query_cache",
20942 -+ &have_query_cache);
20943 -+static sys_var_have_variable sys_have_community_features(&vars, "have_community_features", &have_community_features);
20944 -+static sys_var_have_variable sys_have_rtree_keys(&vars, "have_rtree_keys", &have_rtree_keys);
20945 -+static sys_var_have_variable sys_have_symlink(&vars, "have_symlink", &have_symlink);
20946 -+/* Global read-only variable describing server license */
20947 -+static sys_var_const_str sys_license(&vars, "license", STRINGIFY_ARG(LICENSE));
20948 -+/* Global variables which enable|disable logging */
20949 -+static sys_var_log_state sys_var_general_log(&vars, "general_log", &opt_log,
20950 -+ QUERY_LOG_GENERAL);
20951 -+/* Synonym of "general_log" for consistency with SHOW VARIABLES output */
20952 -+static sys_var_log_state sys_var_log(&vars, "log", &opt_log,
20953 -+ QUERY_LOG_GENERAL);
20954 -+static sys_var_log_state sys_var_slow_query_log(&vars, "slow_query_log", &opt_slow_log,
20955 -+ QUERY_LOG_SLOW);
20956 -+/* Synonym of "slow_query_log" for consistency with SHOW VARIABLES output */
20957 -+static sys_var_log_state sys_var_log_slow(&vars, "log_slow_queries",
20958 -+ &opt_slow_log, QUERY_LOG_SLOW);
20959 -+sys_var_str sys_var_general_log_path(&vars, "general_log_file", sys_check_log_path,
20960 -+ sys_update_general_log_path,
20961 -+ sys_default_general_log_path,
20962 -+ opt_logname);
20963 -+sys_var_str sys_var_slow_log_path(&vars, "slow_query_log_file", sys_check_log_path,
20964 -+ sys_update_slow_log_path,
20965 -+ sys_default_slow_log_path,
20966 -+ opt_slow_logname);
20967 -+static sys_var_log_output sys_var_log_output_state(&vars, "log_output", &log_output_options,
20968 -+ &log_output_typelib, 0);
20969 -+static sys_var_readonly sys_myisam_mmap_size(&vars, "myisam_mmap_size",
20970 -+ OPT_GLOBAL,
20971 -+ SHOW_LONGLONG,
20972 -+ get_myisam_mmap_size);
20973 -+
20974 -+
20975 -+bool sys_var::check(THD *thd, set_var *var)
20976 -+{
20977 -+ var->save_result.ulonglong_value= var->value->val_int();
20978 -+ return 0;
20979 -+}
20980 -+
20981 -+bool sys_var_str::check(THD *thd, set_var *var)
20982 -+{
20983 -+ int res;
20984 -+ if (!check_func)
20985 -+ return 0;
20986 -+
20987 -+ if ((res=(*check_func)(thd, var)) < 0)
20988 -+ my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0),
20989 -+ name, var->value->str_value.ptr());
20990 -+ return res;
20991 -+}
20992 -+
20993 -+/*
20994 -+ Functions to check and update variables
20995 -+*/
20996 -+
20997 -+
20998 -+/*
20999 -+ Update variables 'init_connect, init_slave'.
21000 -+
21001 -+ In case of 'DEFAULT' value
21002 -+ (for example: 'set GLOBAL init_connect=DEFAULT')
21003 -+ 'var' parameter is NULL pointer.
21004 -+*/
21005 -+
21006 -+bool update_sys_var_str(sys_var_str *var_str, rw_lock_t *var_mutex,
21007 -+ set_var *var)
21008 -+{
21009 -+ char *res= 0, *old_value=(char *)(var ? var->value->str_value.ptr() : 0);
21010 -+ uint new_length= (var ? var->value->str_value.length() : 0);
21011 -+ if (!old_value)
21012 -+ old_value= (char*) "";
21013 -+ if (!(res= my_strndup(old_value, new_length, MYF(0))))
21014 -+ return 1;
21015 -+ /*
21016 -+ Replace the old value in such a way that the any thread using
21017 -+ the value will work.
21018 -+ */
21019 -+ rw_wrlock(var_mutex);
21020 -+ old_value= var_str->value;
21021 -+ var_str->value= res;
21022 -+ var_str->value_length= new_length;
21023 -+ var_str->is_os_charset= FALSE;
21024 -+ rw_unlock(var_mutex);
21025 -+ my_free(old_value, MYF(MY_ALLOW_ZERO_PTR));
21026 -+ return 0;
21027 -+}
21028 -+
21029 -+
21030 -+static bool sys_update_init_connect(THD *thd, set_var *var)
21031 -+{
21032 -+ return update_sys_var_str(&sys_init_connect, &LOCK_sys_init_connect, var);
21033 -+}
21034 -+
21035 -+
21036 -+static void sys_default_init_connect(THD* thd, enum_var_type type)
21037 -+{
21038 -+ update_sys_var_str(&sys_init_connect, &LOCK_sys_init_connect, 0);
21039 -+}
21040 -+
21041 -+
21042 -+static bool sys_update_init_slave(THD *thd, set_var *var)
21043 -+{
21044 -+ return update_sys_var_str(&sys_init_slave, &LOCK_sys_init_slave, var);
21045 -+}
21046 -+
21047 -+
21048 -+static void sys_default_init_slave(THD* thd, enum_var_type type)
21049 -+{
21050 -+ update_sys_var_str(&sys_init_slave, &LOCK_sys_init_slave, 0);
21051 -+}
21052 -+
21053 -+static int sys_check_ftb_syntax(THD *thd, set_var *var)
21054 -+{
21055 -+ if (thd->security_ctx->master_access & SUPER_ACL)
21056 -+ return (ft_boolean_check_syntax_string((uchar*)
21057 -+ var->value->str_value.c_ptr()) ?
21058 -+ -1 : 0);
21059 -+ else
21060 -+ {
21061 -+ my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER");
21062 -+ return 1;
21063 -+ }
21064 -+}
21065 -+
21066 -+static bool sys_update_ftb_syntax(THD *thd, set_var * var)
21067 -+{
21068 -+ strmake(ft_boolean_syntax, var->value->str_value.c_ptr(),
21069 -+ sizeof(ft_boolean_syntax)-1);
21070 -+
21071 -+#ifdef HAVE_QUERY_CACHE
21072 -+ query_cache.flush();
21073 -+#endif /* HAVE_QUERY_CACHE */
21074 -+
21075 -+ return 0;
21076 -+}
21077 -+
21078 -+static void sys_default_ftb_syntax(THD *thd, enum_var_type type)
21079 -+{
21080 -+ strmake(ft_boolean_syntax, def_ft_boolean_syntax,
21081 -+ sizeof(ft_boolean_syntax)-1);
21082 -+}
21083 -+
21084 -+
21085 -+/**
21086 -+ If one sets the LOW_PRIORIY UPDATES flag, we also must change the
21087 -+ used lock type.
21088 -+*/
21089 -+
21090 -+static void fix_low_priority_updates(THD *thd, enum_var_type type)
21091 -+{
21092 -+ if (type == OPT_GLOBAL)
21093 -+ thr_upgraded_concurrent_insert_lock=
21094 -+ (global_system_variables.low_priority_updates ?
21095 -+ TL_WRITE_LOW_PRIORITY : TL_WRITE);
21096 -+ else
21097 -+ thd->update_lock_default= (thd->variables.low_priority_updates ?
21098 -+ TL_WRITE_LOW_PRIORITY : TL_WRITE);
21099 -+}
21100 -+
21101 -+
21102 -+static void
21103 -+fix_myisam_max_sort_file_size(THD *thd, enum_var_type type)
21104 -+{
21105 -+ myisam_max_temp_length=
21106 -+ (my_off_t) global_system_variables.myisam_max_sort_file_size;
21107 -+}
21108 -+
21109 -+/**
21110 -+ Set the OPTION_BIG_SELECTS flag if max_join_size == HA_POS_ERROR.
21111 -+*/
21112 -+
21113 -+static void fix_max_join_size(THD *thd, enum_var_type type)
21114 -+{
21115 -+ if (type != OPT_GLOBAL)
21116 -+ {
21117 -+ if (thd->variables.max_join_size == HA_POS_ERROR)
21118 -+ thd->options|= OPTION_BIG_SELECTS;
21119 -+ else
21120 -+ thd->options&= ~OPTION_BIG_SELECTS;
21121 -+ }
21122 -+}
21123 -+
21124 -+
21125 -+/**
21126 -+ Can't change the 'next' tx_isolation while we are already in
21127 -+ a transaction
21128 -+*/
21129 -+static int check_tx_isolation(THD *thd, set_var *var)
21130 -+{
21131 -+ if (var->type == OPT_DEFAULT && (thd->server_status & SERVER_STATUS_IN_TRANS))
21132 -+ {
21133 -+ my_error(ER_CANT_CHANGE_TX_ISOLATION, MYF(0));
21134 -+ return 1;
21135 -+ }
21136 -+ return 0;
21137 -+}
21138 -+
21139 -+/*
21140 -+ If one doesn't use the SESSION modifier, the isolation level
21141 -+ is only active for the next command.
21142 -+*/
21143 -+static void fix_tx_isolation(THD *thd, enum_var_type type)
21144 -+{
21145 -+ if (type == OPT_SESSION)
21146 -+ thd->session_tx_isolation= ((enum_tx_isolation)
21147 -+ thd->variables.tx_isolation);
21148 -+}
21149 -+
21150 -+static void fix_completion_type(THD *thd __attribute__((unused)),
21151 -+ enum_var_type type __attribute__((unused))) {}
21152 -+
21153 -+static int check_completion_type(THD *thd, set_var *var)
21154 -+{
21155 -+ longlong val= var->value->val_int();
21156 -+ if (val < 0 || val > 2)
21157 -+ {
21158 -+ char buf[64];
21159 -+ my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name, llstr(val, buf));
21160 -+ return 1;
21161 -+ }
21162 -+ return 0;
21163 -+}
21164 -+
21165 -+
21166 -+/*
21167 -+ If we are changing the thread variable, we have to copy it to NET too
21168 -+*/
21169 -+
21170 -+#ifdef HAVE_REPLICATION
21171 -+static void fix_net_read_timeout(THD *thd, enum_var_type type)
21172 -+{
21173 -+ if (type != OPT_GLOBAL)
21174 -+ my_net_set_read_timeout(&thd->net, thd->variables.net_read_timeout);
21175 -+}
21176 -+
21177 -+
21178 -+static void fix_net_write_timeout(THD *thd, enum_var_type type)
21179 -+{
21180 -+ if (type != OPT_GLOBAL)
21181 -+ my_net_set_write_timeout(&thd->net, thd->variables.net_write_timeout);
21182 -+}
21183 -+
21184 -+static void fix_net_retry_count(THD *thd, enum_var_type type)
21185 -+{
21186 -+ if (type != OPT_GLOBAL)
21187 -+ thd->net.retry_count=thd->variables.net_retry_count;
21188 -+}
21189 -+#else /* HAVE_REPLICATION */
21190 -+static void fix_net_read_timeout(THD *thd __attribute__((unused)),
21191 -+ enum_var_type type __attribute__((unused)))
21192 -+{}
21193 -+static void fix_net_write_timeout(THD *thd __attribute__((unused)),
21194 -+ enum_var_type type __attribute__((unused)))
21195 -+{}
21196 -+static void fix_net_retry_count(THD *thd __attribute__((unused)),
21197 -+ enum_var_type type __attribute__((unused)))
21198 -+{}
21199 -+#endif /* HAVE_REPLICATION */
21200 -+
21201 -+
21202 -+static void fix_query_cache_size(THD *thd, enum_var_type type)
21203 -+{
21204 -+#ifdef HAVE_QUERY_CACHE
21205 -+ ulong new_cache_size= query_cache.resize(query_cache_size);
21206 -+
21207 -+ /*
21208 -+ Note: query_cache_size is a global variable reflecting the
21209 -+ requested cache size. See also query_cache_size_arg
21210 -+ */
21211 -+
21212 -+ if (query_cache_size != new_cache_size)
21213 -+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
21214 -+ ER_WARN_QC_RESIZE, ER(ER_WARN_QC_RESIZE),
21215 -+ query_cache_size, new_cache_size);
21216 -+
21217 -+ query_cache_size= new_cache_size;
21218 -+#endif
21219 -+}
21220 -+
21221 -+
21222 -+#ifdef HAVE_QUERY_CACHE
21223 -+static void fix_query_cache_min_res_unit(THD *thd, enum_var_type type)
21224 -+{
21225 -+ query_cache_min_res_unit=
21226 -+ query_cache.set_min_res_unit(query_cache_min_res_unit);
21227 -+}
21228 -+#endif
21229 -+
21230 -+
21231 -+extern void fix_delay_key_write(THD *thd, enum_var_type type)
21232 -+{
21233 -+ switch ((enum_delay_key_write) delay_key_write_options) {
21234 -+ case DELAY_KEY_WRITE_NONE:
21235 -+ myisam_delay_key_write=0;
21236 -+ break;
21237 -+ case DELAY_KEY_WRITE_ON:
21238 -+ myisam_delay_key_write=1;
21239 -+ break;
21240 -+ case DELAY_KEY_WRITE_ALL:
21241 -+ myisam_delay_key_write=1;
21242 -+ ha_open_options|= HA_OPEN_DELAY_KEY_WRITE;
21243 -+ break;
21244 -+ }
21245 -+}
21246 -+
21247 -+bool sys_var_set::update(THD *thd, set_var *var)
21248 -+{
21249 -+ *value= var->save_result.ulong_value;
21250 -+ return 0;
21251 -+}
21252 -+
21253 -+uchar *sys_var_set::value_ptr(THD *thd, enum_var_type type,
21254 -+ LEX_STRING *base)
21255 -+{
21256 -+ char buff[256];
21257 -+ String tmp(buff, sizeof(buff), &my_charset_latin1);
21258 -+ ulong length;
21259 -+ ulong val= *value;
21260 -+
21261 -+ tmp.length(0);
21262 -+ for (uint i= 0; val; val>>= 1, i++)
21263 -+ {
21264 -+ if (val & 1)
21265 -+ {
21266 -+ tmp.append(enum_names->type_names[i],
21267 -+ enum_names->type_lengths[i]);
21268 -+ tmp.append(',');
21269 -+ }
21270 -+ }
21271 -+
21272 -+ if ((length= tmp.length()))
21273 -+ length--;
21274 -+ return (uchar*) thd->strmake(tmp.ptr(), length);
21275 -+}
21276 -+
21277 -+void sys_var_set_slave_mode::set_default(THD *thd, enum_var_type type)
21278 -+{
21279 -+ slave_exec_mode_options= SLAVE_EXEC_MODE_STRICT;
21280 -+}
21281 -+
21282 -+bool sys_var_set_slave_mode::check(THD *thd, set_var *var)
21283 -+{
21284 -+ bool rc= sys_var_set::check(thd, var);
21285 -+ if (!rc && (var->save_result.ulong_value & SLAVE_EXEC_MODE_STRICT) &&
21286 -+ (var->save_result.ulong_value & SLAVE_EXEC_MODE_IDEMPOTENT))
21287 -+ {
21288 -+ rc= true;
21289 -+ my_error(ER_SLAVE_AMBIGOUS_EXEC_MODE, MYF(0), "");
21290 -+ }
21291 -+ return rc;
21292 -+}
21293 -+
21294 -+bool sys_var_set_slave_mode::update(THD *thd, set_var *var)
21295 -+{
21296 -+ bool rc;
21297 -+ pthread_mutex_lock(&LOCK_global_system_variables);
21298 -+ rc= sys_var_set::update(thd, var);
21299 -+ pthread_mutex_unlock(&LOCK_global_system_variables);
21300 -+ return rc;
21301 -+}
21302 -+
21303 -+void fix_slave_exec_mode(void)
21304 -+{
21305 -+ DBUG_ENTER("fix_slave_exec_mode");
21306 -+
21307 -+ if ((slave_exec_mode_options & SLAVE_EXEC_MODE_STRICT) &&
21308 -+ (slave_exec_mode_options & SLAVE_EXEC_MODE_IDEMPOTENT))
21309 -+ {
21310 -+ sql_print_error("Ambiguous slave modes combination. STRICT will be used");
21311 -+ slave_exec_mode_options&= ~SLAVE_EXEC_MODE_IDEMPOTENT;
21312 -+ }
21313 -+ if (!(slave_exec_mode_options & SLAVE_EXEC_MODE_IDEMPOTENT))
21314 -+ slave_exec_mode_options|= SLAVE_EXEC_MODE_STRICT;
21315 -+ DBUG_VOID_RETURN;
21316 -+}
21317 -+
21318 -+
21319 -+bool sys_var_thd_binlog_format::check(THD *thd, set_var *var) {
21320 -+ /*
21321 -+ All variables that affect writing to binary log (either format or
21322 -+ turning logging on and off) use the same checking. We call the
21323 -+ superclass ::check function to assign the variable correctly, and
21324 -+ then check the value.
21325 -+ */
21326 -+ bool result= sys_var_thd_enum::check(thd, var);
21327 -+ if (!result)
21328 -+ result= check_log_update(thd, var);
21329 -+ return result;
21330 -+}
21331 -+
21332 -+
21333 -+bool sys_var_thd_binlog_format::is_readonly() const
21334 -+{
21335 -+ /*
21336 -+ Under certain circumstances, the variable is read-only (unchangeable):
21337 -+ */
21338 -+ THD *thd= current_thd;
21339 -+ /*
21340 -+ If RBR and open temporary tables, their CREATE TABLE may not be in the
21341 -+ binlog, so we can't toggle to SBR in this connection.
21342 -+ The test below will also prevent SET GLOBAL, well it was not easy to test
21343 -+ if global or not here.
21344 -+ And this test will also prevent switching from RBR to RBR (a no-op which
21345 -+ should not happen too often).
21346 -+
21347 -+ If we don't have row-based replication compiled in, the variable
21348 -+ is always read-only.
21349 -+ */
21350 -+ if ((thd->variables.binlog_format == BINLOG_FORMAT_ROW) &&
21351 -+ thd->temporary_tables)
21352 -+ {
21353 -+ my_error(ER_TEMP_TABLE_PREVENTS_SWITCH_OUT_OF_RBR, MYF(0));
21354 -+ return 1;
21355 -+ }
21356 -+ /*
21357 -+ if in a stored function/trigger, it's too late to change mode
21358 -+ */
21359 -+ if (thd->in_sub_stmt)
21360 -+ {
21361 -+ my_error(ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_FORMAT, MYF(0));
21362 -+ return 1;
21363 -+ }
21364 -+ return sys_var_thd_enum::is_readonly();
21365 -+}
21366 -+
21367 -+
21368 -+void fix_binlog_format_after_update(THD *thd, enum_var_type type)
21369 -+{
21370 -+ thd->reset_current_stmt_binlog_row_based();
21371 -+}
21372 -+
21373 -+
21374 -+static void fix_max_binlog_size(THD *thd, enum_var_type type)
21375 -+{
21376 -+ DBUG_ENTER("fix_max_binlog_size");
21377 -+ DBUG_PRINT("info",("max_binlog_size=%lu max_relay_log_size=%lu",
21378 -+ max_binlog_size, max_relay_log_size));
21379 -+ mysql_bin_log.set_max_size(max_binlog_size);
21380 -+#ifdef HAVE_REPLICATION
21381 -+ if (!max_relay_log_size)
21382 -+ active_mi->rli.relay_log.set_max_size(max_binlog_size);
21383 -+#endif
21384 -+ DBUG_VOID_RETURN;
21385 -+}
21386 -+
21387 -+static void fix_max_relay_log_size(THD *thd, enum_var_type type)
21388 -+{
21389 -+ DBUG_ENTER("fix_max_relay_log_size");
21390 -+ DBUG_PRINT("info",("max_binlog_size=%lu max_relay_log_size=%lu",
21391 -+ max_binlog_size, max_relay_log_size));
21392 -+#ifdef HAVE_REPLICATION
21393 -+ active_mi->rli.relay_log.set_max_size(max_relay_log_size ?
21394 -+ max_relay_log_size: max_binlog_size);
21395 -+#endif
21396 -+ DBUG_VOID_RETURN;
21397 -+}
21398 -+
21399 -+
21400 -+static int check_max_delayed_threads(THD *thd, set_var *var)
21401 -+{
21402 -+ longlong val= var->value->val_int();
21403 -+ if (var->type != OPT_GLOBAL && val != 0 &&
21404 -+ val != (longlong) global_system_variables.max_insert_delayed_threads)
21405 -+ {
21406 -+ char buf[64];
21407 -+ my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name, llstr(val, buf));
21408 -+ return 1;
21409 -+ }
21410 -+ return 0;
21411 -+}
21412 -+
21413 -+static void fix_max_connections(THD *thd, enum_var_type type)
21414 -+{
21415 -+#ifndef EMBEDDED_LIBRARY
21416 -+ resize_thr_alarm(max_connections +
21417 -+ global_system_variables.max_insert_delayed_threads + 10);
21418 -+#endif
21419 -+}
21420 -+
21421 -+
21422 -+static void fix_thd_mem_root(THD *thd, enum_var_type type)
21423 -+{
21424 -+ if (type != OPT_GLOBAL)
21425 -+ reset_root_defaults(thd->mem_root,
21426 -+ thd->variables.query_alloc_block_size,
21427 -+ thd->variables.query_prealloc_size);
21428 -+}
21429 -+
21430 -+
21431 -+static void fix_trans_mem_root(THD *thd, enum_var_type type)
21432 -+{
21433 -+#ifdef USING_TRANSACTIONS
21434 -+ if (type != OPT_GLOBAL)
21435 -+ reset_root_defaults(&thd->transaction.mem_root,
21436 -+ thd->variables.trans_alloc_block_size,
21437 -+ thd->variables.trans_prealloc_size);
21438 -+#endif
21439 -+}
21440 -+
21441 -+
21442 -+static void fix_server_id(THD *thd, enum_var_type type)
21443 -+{
21444 -+ server_id_supplied = 1;
21445 -+ thd->server_id= server_id;
21446 -+}
21447 -+
21448 -+
21449 -+/**
21450 -+ Throw warning (error in STRICT mode) if value for variable needed bounding.
21451 -+ Only call from check(), not update(), because an error in update() would be
21452 -+ bad mojo. Plug-in interface also uses this.
21453 -+
21454 -+ @param thd thread handle
21455 -+ @param fixed did we have to correct the value? (throw warn/err if so)
21456 -+ @param unsignd is value's type unsigned?
21457 -+ @param name variable's name
21458 -+ @param val variable's value
21459 -+
21460 -+ @retval TRUE on error, FALSE otherwise (warning or OK)
21461 -+ */
21462 -+bool throw_bounds_warning(THD *thd, bool fixed, bool unsignd,
21463 -+ const char *name, longlong val)
21464 -+{
21465 -+ if (fixed)
21466 -+ {
21467 -+ char buf[22];
21468 -+
21469 -+ if (unsignd)
21470 -+ ullstr((ulonglong) val, buf);
21471 -+ else
21472 -+ llstr(val, buf);
21473 -+
21474 -+ if (thd->variables.sql_mode & MODE_STRICT_ALL_TABLES)
21475 -+ {
21476 -+ my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, buf);
21477 -+ return TRUE;
21478 -+ }
21479 -+
21480 -+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
21481 -+ ER_TRUNCATED_WRONG_VALUE,
21482 -+ ER(ER_TRUNCATED_WRONG_VALUE), name, buf);
21483 -+ }
21484 -+ return FALSE;
21485 -+}
21486 -+
21487 -+
21488 -+/**
21489 -+ Get unsigned system-variable.
21490 -+ Negative value does not wrap around, but becomes zero.
21491 -+ Check user-supplied value for a systemvariable against bounds.
21492 -+ If we needed to adjust the value, throw a warning or error depending
21493 -+ on SQL-mode.
21494 -+
21495 -+ @param thd thread handle
21496 -+ @param var the system-variable to get
21497 -+ @param user_max a limit given with --maximum-variable-name=... or 0
21498 -+ @param var_type function will bound on systems where necessary.
21499 -+
21500 -+ @retval TRUE on error, FALSE otherwise (warning or OK)
21501 -+ */
21502 -+static bool get_unsigned(THD *thd, set_var *var, ulonglong user_max,
21503 -+ ulong var_type)
21504 -+{
21505 -+ int warnings= 0;
21506 -+ ulonglong unadjusted;
21507 -+ const struct my_option *limits= var->var->option_limits;
21508 -+ struct my_option fallback;
21509 -+
21510 -+ /* get_unsigned() */
21511 -+ if (var->value->unsigned_flag)
21512 -+ var->save_result.ulonglong_value= (ulonglong) var->value->val_int();
21513 -+ else
21514 -+ {
21515 -+ longlong v= var->value->val_int();
21516 -+ var->save_result.ulonglong_value= (ulonglong) ((v < 0) ? 0 : v);
21517 -+ if (v < 0)
21518 -+ {
21519 -+ warnings++;
21520 -+ if (throw_bounds_warning(thd, TRUE, FALSE, var->var->name, v))
21521 -+ return TRUE; /* warning was promoted to error, give up */
21522 -+ }
21523 -+ }
21524 -+
21525 -+ unadjusted= var->save_result.ulonglong_value;
21526 -+
21527 -+ /* max, if any */
21528 -+
21529 -+ if ((user_max > 0) && (unadjusted > user_max))
21530 -+ {
21531 -+ var->save_result.ulonglong_value= user_max;
21532 -+
21533 -+ if ((warnings == 0) && throw_bounds_warning(thd, TRUE, TRUE,
21534 -+ var->var->name,
21535 -+ (longlong) unadjusted))
21536 -+ return TRUE;
21537 -+
21538 -+ warnings++;
21539 -+ }
21540 -+
21541 -+ /*
21542 -+ if the sysvar doesn't have a proper bounds record but the check
21543 -+ function would like bounding to ULONG where its size differs from
21544 -+ that of ULONGLONG, we make up a bogus limits record here and let
21545 -+ the usual suspects handle the actual limiting.
21546 -+ */
21547 -+
21548 -+ if (!limits && var_type != GET_ULL)
21549 -+ {
21550 -+ bzero(&fallback, sizeof(fallback));
21551 -+ fallback.var_type= var_type;
21552 -+ limits= &fallback;
21553 -+ }
21554 -+
21555 -+ /* fix_unsigned() */
21556 -+ if (limits)
21557 -+ {
21558 -+ my_bool fixed;
21559 -+
21560 -+ var->save_result.ulonglong_value= getopt_ull_limit_value(var->save_result.
21561 -+ ulonglong_value,
21562 -+ limits, &fixed);
21563 -+
21564 -+ if ((warnings == 0) && throw_bounds_warning(thd, fixed, TRUE,
21565 -+ var->var->name,
21566 -+ (longlong) unadjusted))
21567 -+ return TRUE;
21568 -+ }
21569 -+
21570 -+ return FALSE;
21571 -+}
21572 -+
21573 -+
21574 -+sys_var_long_ptr::
21575 -+sys_var_long_ptr(sys_var_chain *chain, const char *name_arg, ulong *value_ptr_arg,
21576 -+ sys_after_update_func after_update_arg)
21577 -+ :sys_var_long_ptr_global(chain, name_arg, value_ptr_arg,
21578 -+ &LOCK_global_system_variables, after_update_arg)
21579 -+{}
21580 -+
21581 -+
21582 -+bool sys_var_long_ptr_global::check(THD *thd, set_var *var)
21583 -+{
21584 -+ return get_unsigned(thd, var, 0, GET_ULONG);
21585 -+}
21586 -+
21587 -+bool sys_var_long_ptr_global::update(THD *thd, set_var *var)
21588 -+{
21589 -+ pthread_mutex_lock(guard);
21590 -+ *value= (ulong) var->save_result.ulonglong_value;
21591 -+ pthread_mutex_unlock(guard);
21592 -+ return 0;
21593 -+}
21594 -+
21595 -+
21596 -+void sys_var_long_ptr_global::set_default(THD *thd, enum_var_type type)
21597 -+{
21598 -+ my_bool not_used;
21599 -+ pthread_mutex_lock(guard);
21600 -+ *value= (ulong) getopt_ull_limit_value((ulong) option_limits->def_value,
21601 -+ option_limits, &not_used);
21602 -+ pthread_mutex_unlock(guard);
21603 -+}
21604 -+
21605 -+
21606 -+bool sys_var_ulonglong_ptr::check(THD *thd, set_var *var)
21607 -+{
21608 -+ return get_unsigned(thd, var, 0, GET_ULL);
21609 -+}
21610 -+
21611 -+
21612 -+bool sys_var_ulonglong_ptr::update(THD *thd, set_var *var)
21613 -+{
21614 -+ ulonglong tmp= var->save_result.ulonglong_value;
21615 -+ pthread_mutex_lock(&LOCK_global_system_variables);
21616 -+ *value= (ulonglong) tmp;
21617 -+ pthread_mutex_unlock(&LOCK_global_system_variables);
21618 -+ return 0;
21619 -+}
21620 -+
21621 -+
21622 -+void sys_var_ulonglong_ptr::set_default(THD *thd, enum_var_type type)
21623 -+{
21624 -+ my_bool not_used;
21625 -+ pthread_mutex_lock(&LOCK_global_system_variables);
21626 -+ *value= getopt_ull_limit_value((ulonglong) option_limits->def_value,
21627 -+ option_limits, &not_used);
21628 -+ pthread_mutex_unlock(&LOCK_global_system_variables);
21629 -+}
21630 -+
21631 -+
21632 -+bool sys_var_bool_ptr::update(THD *thd, set_var *var)
21633 -+{
21634 -+ *value= (my_bool) var->save_result.ulong_value;
21635 -+ return 0;
21636 -+}
21637 -+
21638 -+
21639 -+void sys_var_bool_ptr::set_default(THD *thd, enum_var_type type)
21640 -+{
21641 -+ *value= (my_bool) option_limits->def_value;
21642 -+}
21643 -+
21644 -+
21645 -+bool sys_var_enum::update(THD *thd, set_var *var)
21646 -+{
21647 -+ *value= (uint) var->save_result.ulong_value;
21648 -+ return 0;
21649 -+}
21650 -+
21651 -+
21652 -+uchar *sys_var_enum::value_ptr(THD *thd, enum_var_type type, LEX_STRING *base)
21653 -+{
21654 -+ return (uchar*) enum_names->type_names[*value];
21655 -+}
21656 -+
21657 -+
21658 -+uchar *sys_var_enum_const::value_ptr(THD *thd, enum_var_type type,
21659 -+ LEX_STRING *base)
21660 -+{
21661 -+ return (uchar*) enum_names->type_names[global_system_variables.*offset];
21662 -+}
21663 -+
21664 -+bool sys_var_thd_ulong::check(THD *thd, set_var *var)
21665 -+{
21666 -+ if (get_unsigned(thd, var, max_system_variables.*offset, GET_ULONG))
21667 -+ return TRUE;
21668 -+ DBUG_ASSERT(var->save_result.ulonglong_value <= ULONG_MAX);
21669 -+ return ((check_func && (*check_func)(thd, var)));
21670 -+}
21671 -+
21672 -+bool sys_var_thd_ulong::update(THD *thd, set_var *var)
21673 -+{
21674 -+ if (var->type == OPT_GLOBAL)
21675 -+ global_system_variables.*offset= (ulong) var->save_result.ulonglong_value;
21676 -+ else
21677 -+ thd->variables.*offset= (ulong) var->save_result.ulonglong_value;
21678 -+
21679 -+ return 0;
21680 -+}
21681 -+
21682 -+
21683 -+void sys_var_thd_ulong::set_default(THD *thd, enum_var_type type)
21684 -+{
21685 -+ if (type == OPT_GLOBAL)
21686 -+ {
21687 -+ my_bool not_used;
21688 -+ /* We will not come here if option_limits is not set */
21689 -+ global_system_variables.*offset=
21690 -+ (ulong) getopt_ull_limit_value((ulong) option_limits->def_value,
21691 -+ option_limits, &not_used);
21692 -+ }
21693 -+ else
21694 -+ thd->variables.*offset= global_system_variables.*offset;
21695 -+}
21696 -+
21697 -+
21698 -+uchar *sys_var_thd_ulong::value_ptr(THD *thd, enum_var_type type,
21699 -+ LEX_STRING *base)
21700 -+{
21701 -+ if (type == OPT_GLOBAL)
21702 -+ return (uchar*) &(global_system_variables.*offset);
21703 -+ return (uchar*) &(thd->variables.*offset);
21704 -+}
21705 -+
21706 -+
21707 -+bool sys_var_thd_ha_rows::check(THD *thd, set_var *var)
21708 -+{
21709 -+ return get_unsigned(thd, var, max_system_variables.*offset,
21710 -+#ifdef BIG_TABLES
21711 -+ GET_ULL
21712 -+#else
21713 -+ GET_ULONG
21714 -+#endif
21715 -+ );
21716 -+}
21717 -+
21718 -+
21719 -+bool sys_var_thd_ha_rows::update(THD *thd, set_var *var)
21720 -+{
21721 -+ if (var->type == OPT_GLOBAL)
21722 -+ {
21723 -+ /* Lock is needed to make things safe on 32 bit systems */
21724 -+ pthread_mutex_lock(&LOCK_global_system_variables);
21725 -+ global_system_variables.*offset= (ha_rows)
21726 -+ var->save_result.ulonglong_value;
21727 -+ pthread_mutex_unlock(&LOCK_global_system_variables);
21728 -+ }
21729 -+ else
21730 -+ thd->variables.*offset= (ha_rows) var->save_result.ulonglong_value;
21731 -+ return 0;
21732 -+}
21733 -+
21734 -+
21735 -+void sys_var_thd_ha_rows::set_default(THD *thd, enum_var_type type)
21736 -+{
21737 -+ if (type == OPT_GLOBAL)
21738 -+ {
21739 -+ my_bool not_used;
21740 -+ /* We will not come here if option_limits is not set */
21741 -+ pthread_mutex_lock(&LOCK_global_system_variables);
21742 -+ global_system_variables.*offset=
21743 -+ (ha_rows) getopt_ull_limit_value((ha_rows) option_limits->def_value,
21744 -+ option_limits, &not_used);
21745 -+ pthread_mutex_unlock(&LOCK_global_system_variables);
21746 -+ }
21747 -+ else
21748 -+ thd->variables.*offset= global_system_variables.*offset;
21749 -+}
21750 -+
21751 -+
21752 -+uchar *sys_var_thd_ha_rows::value_ptr(THD *thd, enum_var_type type,
21753 -+ LEX_STRING *base)
21754 -+{
21755 -+ if (type == OPT_GLOBAL)
21756 -+ return (uchar*) &(global_system_variables.*offset);
21757 -+ return (uchar*) &(thd->variables.*offset);
21758 -+}
21759 -+
21760 -+bool sys_var_thd_ulonglong::check(THD *thd, set_var *var)
21761 -+{
21762 -+ return get_unsigned(thd, var, max_system_variables.*offset, GET_ULL);
21763 -+}
21764 -+
21765 -+bool sys_var_thd_ulonglong::update(THD *thd, set_var *var)
21766 -+{
21767 -+ if (var->type == OPT_GLOBAL)
21768 -+ {
21769 -+ /* Lock is needed to make things safe on 32 bit systems */
21770 -+ pthread_mutex_lock(&LOCK_global_system_variables);
21771 -+ global_system_variables.*offset= (ulonglong)
21772 -+ var->save_result.ulonglong_value;
21773 -+ pthread_mutex_unlock(&LOCK_global_system_variables);
21774 -+ }
21775 -+ else
21776 -+ thd->variables.*offset= (ulonglong) var->save_result.ulonglong_value;
21777 -+ return 0;
21778 -+}
21779 -+
21780 -+
21781 -+void sys_var_thd_ulonglong::set_default(THD *thd, enum_var_type type)
21782 -+{
21783 -+ if (type == OPT_GLOBAL)
21784 -+ {
21785 -+ my_bool not_used;
21786 -+ pthread_mutex_lock(&LOCK_global_system_variables);
21787 -+ global_system_variables.*offset=
21788 -+ getopt_ull_limit_value((ulonglong) option_limits->def_value,
21789 -+ option_limits, &not_used);
21790 -+ pthread_mutex_unlock(&LOCK_global_system_variables);
21791 -+ }
21792 -+ else
21793 -+ thd->variables.*offset= global_system_variables.*offset;
21794 -+}
21795 -+
21796 -+
21797 -+uchar *sys_var_thd_ulonglong::value_ptr(THD *thd, enum_var_type type,
21798 -+ LEX_STRING *base)
21799 -+{
21800 -+ if (type == OPT_GLOBAL)
21801 -+ return (uchar*) &(global_system_variables.*offset);
21802 -+ return (uchar*) &(thd->variables.*offset);
21803 -+}
21804 -+
21805 -+
21806 -+bool sys_var_thd_bool::update(THD *thd, set_var *var)
21807 -+{
21808 -+ if (var->type == OPT_GLOBAL)
21809 -+ global_system_variables.*offset= (my_bool) var->save_result.ulong_value;
21810 -+ else
21811 -+ thd->variables.*offset= (my_bool) var->save_result.ulong_value;
21812 -+ return 0;
21813 -+}
21814 -+
21815 -+
21816 -+void sys_var_thd_bool::set_default(THD *thd, enum_var_type type)
21817 -+{
21818 -+ if (type == OPT_GLOBAL)
21819 -+ global_system_variables.*offset= (my_bool) option_limits->def_value;
21820 -+ else
21821 -+ thd->variables.*offset= global_system_variables.*offset;
21822 -+}
21823 -+
21824 -+
21825 -+uchar *sys_var_thd_bool::value_ptr(THD *thd, enum_var_type type,
21826 -+ LEX_STRING *base)
21827 -+{
21828 -+ if (type == OPT_GLOBAL)
21829 -+ return (uchar*) &(global_system_variables.*offset);
21830 -+ return (uchar*) &(thd->variables.*offset);
21831 -+}
21832 -+
21833 -+
21834 -+bool sys_var::check_enum(THD *thd, set_var *var, const TYPELIB *enum_names)
21835 -+{
21836 -+ char buff[STRING_BUFFER_USUAL_SIZE];
21837 -+ const char *value;
21838 -+ String str(buff, sizeof(buff), system_charset_info), *res;
21839 -+
21840 -+ if (var->value->result_type() == STRING_RESULT)
21841 -+ {
21842 -+ if (!(res=var->value->val_str(&str)) ||
21843 -+ ((long) (var->save_result.ulong_value=
21844 -+ (ulong) find_type(enum_names, res->ptr(),
21845 -+ res->length(),1)-1)) < 0)
21846 -+ {
21847 -+ value= res ? res->c_ptr() : "NULL";
21848 -+ goto err;
21849 -+ }
21850 -+ }
21851 -+ else
21852 -+ {
21853 -+ ulonglong tmp=var->value->val_int();
21854 -+ if (tmp >= enum_names->count)
21855 -+ {
21856 -+ llstr(tmp,buff);
21857 -+ value=buff; // Wrong value is here
21858 -+ goto err;
21859 -+ }
21860 -+ var->save_result.ulong_value= (ulong) tmp; // Save for update
21861 -+ }
21862 -+ return 0;
21863 -+
21864 -+err:
21865 -+ my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, value);
21866 -+ return 1;
21867 -+}
21868 -+
21869 -+
21870 -+bool sys_var::check_set(THD *thd, set_var *var, TYPELIB *enum_names)
21871 -+{
21872 -+ bool not_used;
21873 -+ char buff[STRING_BUFFER_USUAL_SIZE], *error= 0;
21874 -+ uint error_len= 0;
21875 -+ String str(buff, sizeof(buff), system_charset_info), *res;
21876 -+
21877 -+ if (var->value->result_type() == STRING_RESULT)
21878 -+ {
21879 -+ if (!(res= var->value->val_str(&str)))
21880 -+ {
21881 -+ strmov(buff, "NULL");
21882 -+ goto err;
21883 -+ }
21884 -+
21885 -+ if (!m_allow_empty_value &&
21886 -+ res->length() == 0)
21887 -+ {
21888 -+ buff[0]= 0;
21889 -+ goto err;
21890 -+ }
21891 -+
21892 -+ var->save_result.ulong_value= ((ulong)
21893 -+ find_set(enum_names, res->c_ptr_safe(),
21894 -+ res->length(),
21895 -+ NULL,
21896 -+ &error, &error_len,
21897 -+ &not_used));
21898 -+ if (error_len)
21899 -+ {
21900 -+ strmake(buff, error, min(sizeof(buff) - 1, error_len));
21901 -+ goto err;
21902 -+ }
21903 -+ }
21904 -+ else
21905 -+ {
21906 -+ ulonglong tmp= var->value->val_int();
21907 -+
21908 -+ if (!m_allow_empty_value &&
21909 -+ tmp == 0)
21910 -+ {
21911 -+ buff[0]= '0';
21912 -+ buff[1]= 0;
21913 -+ goto err;
21914 -+ }
21915 -+
21916 -+ /*
21917 -+ For when the enum is made to contain 64 elements, as 1ULL<<64 is
21918 -+ undefined, we guard with a "count<64" test.
21919 -+ */
21920 -+ if (unlikely((tmp >= ((ULL(1)) << enum_names->count)) &&
21921 -+ (enum_names->count < 64)))
21922 -+ {
21923 -+ llstr(tmp, buff);
21924 -+ goto err;
21925 -+ }
21926 -+ var->save_result.ulong_value= (ulong) tmp; // Save for update
21927 -+ }
21928 -+ return 0;
21929 -+
21930 -+err:
21931 -+ my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, buff);
21932 -+ return 1;
21933 -+}
21934 -+
21935 -+
21936 -+CHARSET_INFO *sys_var::charset(THD *thd)
21937 -+{
21938 -+ return is_os_charset ? thd->variables.character_set_filesystem :
21939 -+ system_charset_info;
21940 -+}
21941 -+
21942 -+
21943 -+bool sys_var_thd_enum::update(THD *thd, set_var *var)
21944 -+{
21945 -+ if (var->type == OPT_GLOBAL)
21946 -+ global_system_variables.*offset= var->save_result.ulong_value;
21947 -+ else
21948 -+ thd->variables.*offset= var->save_result.ulong_value;
21949 -+ return 0;
21950 -+}
21951 -+
21952 -+
21953 -+void sys_var_thd_enum::set_default(THD *thd, enum_var_type type)
21954 -+{
21955 -+ if (type == OPT_GLOBAL)
21956 -+ global_system_variables.*offset= (ulong) option_limits->def_value;
21957 -+ else
21958 -+ thd->variables.*offset= global_system_variables.*offset;
21959 -+}
21960 -+
21961 -+
21962 -+uchar *sys_var_thd_enum::value_ptr(THD *thd, enum_var_type type,
21963 -+ LEX_STRING *base)
21964 -+{
21965 -+ ulong tmp= ((type == OPT_GLOBAL) ?
21966 -+ global_system_variables.*offset :
21967 -+ thd->variables.*offset);
21968 -+ return (uchar*) enum_names->type_names[tmp];
21969 -+}
21970 -+
21971 -+bool sys_var_thd_bit::check(THD *thd, set_var *var)
21972 -+{
21973 -+ return (check_enum(thd, var, &bool_typelib) ||
21974 -+ (check_func && (*check_func)(thd, var)));
21975 -+}
21976 -+
21977 -+bool sys_var_thd_bit::update(THD *thd, set_var *var)
21978 -+{
21979 -+ int res= (*update_func)(thd, var);
21980 -+ return res;
21981 -+}
21982 -+
21983 -+
21984 -+uchar *sys_var_thd_bit::value_ptr(THD *thd, enum_var_type type,
21985 -+ LEX_STRING *base)
21986 -+{
21987 -+ /*
21988 -+ If reverse is 0 (default) return 1 if bit is set.
21989 -+ If reverse is 1, return 0 if bit is set
21990 -+ */
21991 -+ thd->sys_var_tmp.my_bool_value= ((thd->options & bit_flag) ?
21992 -+ !reverse : reverse);
21993 -+ return (uchar*) &thd->sys_var_tmp.my_bool_value;
21994 -+}
21995 -+
21996 -+
21997 -+/** Update a date_time format variable based on given value. */
21998 -+
21999 -+void sys_var_thd_date_time_format::update2(THD *thd, enum_var_type type,
22000 -+ DATE_TIME_FORMAT *new_value)
22001 -+{
22002 -+ DATE_TIME_FORMAT *old;
22003 -+ DBUG_ENTER("sys_var_date_time_format::update2");
22004 -+ DBUG_DUMP("positions", (uchar*) new_value->positions,
22005 -+ sizeof(new_value->positions));
22006 -+
22007 -+ if (type == OPT_GLOBAL)
22008 -+ {
22009 -+ pthread_mutex_lock(&LOCK_global_system_variables);
22010 -+ old= (global_system_variables.*offset);
22011 -+ (global_system_variables.*offset)= new_value;
22012 -+ pthread_mutex_unlock(&LOCK_global_system_variables);
22013 -+ }
22014 -+ else
22015 -+ {
22016 -+ old= (thd->variables.*offset);
22017 -+ (thd->variables.*offset)= new_value;
22018 -+ }
22019 -+ my_free((char*) old, MYF(MY_ALLOW_ZERO_PTR));
22020 -+ DBUG_VOID_RETURN;
22021 -+}
22022 -+
22023 -+
22024 -+bool sys_var_thd_date_time_format::update(THD *thd, set_var *var)
22025 -+{
22026 -+ DATE_TIME_FORMAT *new_value;
22027 -+ /* We must make a copy of the last value to get it into normal memory */
22028 -+ new_value= date_time_format_copy((THD*) 0,
22029 -+ var->save_result.date_time_format);
22030 -+ if (!new_value)
22031 -+ return 1; // Out of memory
22032 -+ update2(thd, var->type, new_value); // Can't fail
22033 -+ return 0;
22034 -+}
22035 -+
22036 -+
22037 -+bool sys_var_thd_date_time_format::check(THD *thd, set_var *var)
22038 -+{
22039 -+ char buff[STRING_BUFFER_USUAL_SIZE];
22040 -+ String str(buff,sizeof(buff), system_charset_info), *res;
22041 -+ DATE_TIME_FORMAT *format;
22042 -+
22043 -+ if (!(res=var->value->val_str(&str)))
22044 -+ res= &my_empty_string;
22045 -+
22046 -+ if (!(format= date_time_format_make(date_time_type,
22047 -+ res->ptr(), res->length())))
22048 -+ {
22049 -+ my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, res->c_ptr());
22050 -+ return 1;
22051 -+ }
22052 -+
22053 -+ /*
22054 -+ We must copy result to thread space to not get a memory leak if
22055 -+ update is aborted
22056 -+ */
22057 -+ var->save_result.date_time_format= date_time_format_copy(thd, format);
22058 -+ my_free((char*) format, MYF(0));
22059 -+ return var->save_result.date_time_format == 0;
22060 -+}
22061 -+
22062 -+
22063 -+void sys_var_thd_date_time_format::set_default(THD *thd, enum_var_type type)
22064 -+{
22065 -+ DATE_TIME_FORMAT *res= 0;
22066 -+
22067 -+ if (type == OPT_GLOBAL)
22068 -+ {
22069 -+ const char *format;
22070 -+ if ((format= opt_date_time_formats[date_time_type]))
22071 -+ res= date_time_format_make(date_time_type, format, strlen(format));
22072 -+ }
22073 -+ else
22074 -+ {
22075 -+ /* Make copy with malloc */
22076 -+ res= date_time_format_copy((THD *) 0, global_system_variables.*offset);
22077 -+ }
22078 -+
22079 -+ if (res) // Should always be true
22080 -+ update2(thd, type, res);
22081 -+}
22082 -+
22083 -+
22084 -+uchar *sys_var_thd_date_time_format::value_ptr(THD *thd, enum_var_type type,
22085 -+ LEX_STRING *base)
22086 -+{
22087 -+ if (type == OPT_GLOBAL)
22088 -+ {
22089 -+ char *res;
22090 -+ /*
22091 -+ We do a copy here just to be sure things will work even if someone
22092 -+ is modifying the original string while the copy is accessed
22093 -+ (Can't happen now in SQL SHOW, but this is a good safety for the future)
22094 -+ */
22095 -+ res= thd->strmake((global_system_variables.*offset)->format.str,
22096 -+ (global_system_variables.*offset)->format.length);
22097 -+ return (uchar*) res;
22098 -+ }
22099 -+ return (uchar*) (thd->variables.*offset)->format.str;
22100 -+}
22101 -+
22102 -+
22103 -+typedef struct old_names_map_st
22104 -+{
22105 -+ const char *old_name;
22106 -+ const char *new_name;
22107 -+} my_old_conv;
22108 -+
22109 -+static my_old_conv old_conv[]=
22110 -+{
22111 -+ { "cp1251_koi8" , "cp1251" },
22112 -+ { "cp1250_latin2" , "cp1250" },
22113 -+ { "kam_latin2" , "keybcs2" },
22114 -+ { "mac_latin2" , "MacRoman" },
22115 -+ { "macce_latin2" , "MacCE" },
22116 -+ { "pc2_latin2" , "pclatin2" },
22117 -+ { "vga_latin2" , "pclatin1" },
22118 -+ { "koi8_cp1251" , "koi8r" },
22119 -+ { "win1251ukr_koi8_ukr" , "win1251ukr" },
22120 -+ { "koi8_ukr_win1251ukr" , "koi8u" },
22121 -+ { NULL , NULL }
22122 -+};
22123 -+
22124 -+CHARSET_INFO *get_old_charset_by_name(const char *name)
22125 -+{
22126 -+ my_old_conv *conv;
22127 -+
22128 -+ for (conv= old_conv; conv->old_name; conv++)
22129 -+ {
22130 -+ if (!my_strcasecmp(&my_charset_latin1, name, conv->old_name))
22131 -+ return get_charset_by_csname(conv->new_name, MY_CS_PRIMARY, MYF(0));
22132 -+ }
22133 -+ return NULL;
22134 -+}
22135 -+
22136 -+
22137 -+bool sys_var_collation::check(THD *thd, set_var *var)
22138 -+{
22139 -+ CHARSET_INFO *tmp;
22140 -+ LINT_INIT(tmp);
22141 -+
22142 -+ if (var->value->result_type() == STRING_RESULT)
22143 -+ {
22144 -+ char buff[STRING_BUFFER_USUAL_SIZE];
22145 -+ String str(buff,sizeof(buff), system_charset_info), *res;
22146 -+ if (!(res=var->value->val_str(&str)))
22147 -+ {
22148 -+ my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, "NULL");
22149 -+ return 1;
22150 -+ }
22151 -+ if (!(tmp=get_charset_by_name(res->c_ptr(),MYF(0))))
22152 -+ {
22153 -+ my_error(ER_UNKNOWN_COLLATION, MYF(0), res->c_ptr());
22154 -+ return 1;
22155 -+ }
22156 -+ }
22157 -+ else // INT_RESULT
22158 -+ {
22159 -+ if (!(tmp=get_charset((int) var->value->val_int(),MYF(0))))
22160 -+ {
22161 -+ char buf[20];
22162 -+ int10_to_str((int) var->value->val_int(), buf, -10);
22163 -+ my_error(ER_UNKNOWN_COLLATION, MYF(0), buf);
22164 -+ return 1;
22165 -+ }
22166 -+ }
22167 -+ var->save_result.charset= tmp; // Save for update
22168 -+ return 0;
22169 -+}
22170 -+
22171 -+
22172 -+bool sys_var_character_set::check(THD *thd, set_var *var)
22173 -+{
22174 -+ CHARSET_INFO *tmp;
22175 -+ LINT_INIT(tmp);
22176 -+
22177 -+ if (var->value->result_type() == STRING_RESULT)
22178 -+ {
22179 -+ char buff[STRING_BUFFER_USUAL_SIZE];
22180 -+ String str(buff,sizeof(buff), system_charset_info), *res;
22181 -+ if (!(res=var->value->val_str(&str)))
22182 -+ {
22183 -+ if (!nullable)
22184 -+ {
22185 -+ my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, "NULL");
22186 -+ return 1;
22187 -+ }
22188 -+ tmp= NULL;
22189 -+ }
22190 -+ else if (!(tmp=get_charset_by_csname(res->c_ptr(),MY_CS_PRIMARY,MYF(0))) &&
22191 -+ !(tmp=get_old_charset_by_name(res->c_ptr())))
22192 -+ {
22193 -+ my_error(ER_UNKNOWN_CHARACTER_SET, MYF(0), res->c_ptr());
22194 -+ return 1;
22195 -+ }
22196 -+ }
22197 -+ else // INT_RESULT
22198 -+ {
22199 -+ if (!(tmp=get_charset((int) var->value->val_int(),MYF(0))))
22200 -+ {
22201 -+ char buf[20];
22202 -+ int10_to_str((int) var->value->val_int(), buf, -10);
22203 -+ my_error(ER_UNKNOWN_CHARACTER_SET, MYF(0), buf);
22204 -+ return 1;
22205 -+ }
22206 -+ }
22207 -+ var->save_result.charset= tmp; // Save for update
22208 -+ return 0;
22209 -+}
22210 -+
22211 -+
22212 -+bool sys_var_character_set::update(THD *thd, set_var *var)
22213 -+{
22214 -+ ci_ptr(thd,var->type)[0]= var->save_result.charset;
22215 -+ thd->update_charset();
22216 -+ return 0;
22217 -+}
22218 -+
22219 -+
22220 -+uchar *sys_var_character_set::value_ptr(THD *thd, enum_var_type type,
22221 -+ LEX_STRING *base)
22222 -+{
22223 -+ CHARSET_INFO *cs= ci_ptr(thd,type)[0];
22224 -+ return cs ? (uchar*) cs->csname : (uchar*) NULL;
22225 -+}
22226 -+
22227 -+
22228 -+void sys_var_character_set_sv::set_default(THD *thd, enum_var_type type)
22229 -+{
22230 -+ if (type == OPT_GLOBAL)
22231 -+ global_system_variables.*offset= *global_default;
22232 -+ else
22233 -+ {
22234 -+ thd->variables.*offset= global_system_variables.*offset;
22235 -+ thd->update_charset();
22236 -+ }
22237 -+}
22238 -+CHARSET_INFO **sys_var_character_set_sv::ci_ptr(THD *thd, enum_var_type type)
22239 -+{
22240 -+ if (type == OPT_GLOBAL)
22241 -+ return &(global_system_variables.*offset);
22242 -+ else
22243 -+ return &(thd->variables.*offset);
22244 -+}
22245 -+
22246 -+
22247 -+bool sys_var_character_set_client::check(THD *thd, set_var *var)
22248 -+{
22249 -+ if (sys_var_character_set_sv::check(thd, var))
22250 -+ return 1;
22251 -+ /* Currently, UCS-2 cannot be used as a client character set */
22252 -+ if (!is_supported_parser_charset(var->save_result.charset))
22253 -+ {
22254 -+ my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name,
22255 -+ var->save_result.charset->csname);
22256 -+ return 1;
22257 -+ }
22258 -+ return 0;
22259 -+}
22260 -+
22261 -+
22262 -+CHARSET_INFO ** sys_var_character_set_database::ci_ptr(THD *thd,
22263 -+ enum_var_type type)
22264 -+{
22265 -+ if (type == OPT_GLOBAL)
22266 -+ return &global_system_variables.collation_database;
22267 -+ else
22268 -+ return &thd->variables.collation_database;
22269 -+}
22270 -+
22271 -+
22272 -+void sys_var_character_set_database::set_default(THD *thd, enum_var_type type)
22273 -+{
22274 -+ if (type == OPT_GLOBAL)
22275 -+ global_system_variables.collation_database= default_charset_info;
22276 -+ else
22277 -+ {
22278 -+ thd->variables.collation_database= thd->db_charset;
22279 -+ thd->update_charset();
22280 -+ }
22281 -+}
22282 -+
22283 -+
22284 -+bool sys_var_collation_sv::update(THD *thd, set_var *var)
22285 -+{
22286 -+ if (var->type == OPT_GLOBAL)
22287 -+ global_system_variables.*offset= var->save_result.charset;
22288 -+ else
22289 -+ {
22290 -+ thd->variables.*offset= var->save_result.charset;
22291 -+ thd->update_charset();
22292 -+ }
22293 -+ return 0;
22294 -+}
22295 -+
22296 -+
22297 -+void sys_var_collation_sv::set_default(THD *thd, enum_var_type type)
22298 -+{
22299 -+ if (type == OPT_GLOBAL)
22300 -+ global_system_variables.*offset= *global_default;
22301 -+ else
22302 -+ {
22303 -+ thd->variables.*offset= global_system_variables.*offset;
22304 -+ thd->update_charset();
22305 -+ }
22306 -+}
22307 -+
22308 -+
22309 -+uchar *sys_var_collation_sv::value_ptr(THD *thd, enum_var_type type,
22310 -+ LEX_STRING *base)
22311 -+{
22312 -+ CHARSET_INFO *cs= ((type == OPT_GLOBAL) ?
22313 -+ global_system_variables.*offset : thd->variables.*offset);
22314 -+ return cs ? (uchar*) cs->name : (uchar*) "NULL";
22315 -+}
22316 -+
22317 -+
22318 -+LEX_STRING default_key_cache_base= {(char *) "default", 7 };
22319 -+
22320 -+static KEY_CACHE zero_key_cache;
22321 -+
22322 -+KEY_CACHE *get_key_cache(LEX_STRING *cache_name)
22323 -+{
22324 -+ safe_mutex_assert_owner(&LOCK_global_system_variables);
22325 -+ if (!cache_name || ! cache_name->length)
22326 -+ cache_name= &default_key_cache_base;
22327 -+ return ((KEY_CACHE*) find_named(&key_caches,
22328 -+ cache_name->str, cache_name->length, 0));
22329 -+}
22330 -+
22331 -+
22332 -+uchar *sys_var_key_cache_param::value_ptr(THD *thd, enum_var_type type,
22333 -+ LEX_STRING *base)
22334 -+{
22335 -+ KEY_CACHE *key_cache= get_key_cache(base);
22336 -+ if (!key_cache)
22337 -+ key_cache= &zero_key_cache;
22338 -+ return (uchar*) key_cache + offset ;
22339 -+}
22340 -+
22341 -+
22342 -+bool sys_var_key_buffer_size::check(THD *thd, set_var *var)
22343 -+{
22344 -+ return get_unsigned(thd, var, 0, GET_ULL);
22345 -+}
22346 -+
22347 -+
22348 -+bool sys_var_key_buffer_size::update(THD *thd, set_var *var)
22349 -+{
22350 -+ ulonglong tmp= var->save_result.ulonglong_value;
22351 -+ LEX_STRING *base_name= &var->base;
22352 -+ KEY_CACHE *key_cache;
22353 -+ bool error= 0;
22354 -+
22355 -+ /* If no basename, assume it's for the key cache named 'default' */
22356 -+ if (!base_name->length)
22357 -+ base_name= &default_key_cache_base;
22358 -+
22359 -+ pthread_mutex_lock(&LOCK_global_system_variables);
22360 -+ key_cache= get_key_cache(base_name);
22361 -+
22362 -+ if (!key_cache)
22363 -+ {
22364 -+ /* Key cache didn't exist */
22365 -+ if (!tmp) // Tried to delete cache
22366 -+ goto end; // Ok, nothing to do
22367 -+ if (!(key_cache= create_key_cache(base_name->str, base_name->length)))
22368 -+ {
22369 -+ error= 1;
22370 -+ goto end;
22371 -+ }
22372 -+ }
22373 -+
22374 -+ /*
22375 -+ Abort if some other thread is changing the key cache
22376 -+ TODO: This should be changed so that we wait until the previous
22377 -+ assignment is done and then do the new assign
22378 -+ */
22379 -+ if (key_cache->in_init)
22380 -+ goto end;
22381 -+
22382 -+ if (!tmp) // Zero size means delete
22383 -+ {
22384 -+ if (key_cache == dflt_key_cache)
22385 -+ {
22386 -+ error= 1;
22387 -+ my_error(ER_WARN_CANT_DROP_DEFAULT_KEYCACHE, MYF(0));
22388 -+ goto end; // Ignore default key cache
22389 -+ }
22390 -+
22391 -+ if (key_cache->key_cache_inited) // If initied
22392 -+ {
22393 -+ /*
22394 -+ Move tables using this key cache to the default key cache
22395 -+ and clear the old key cache.
22396 -+ */
22397 -+ NAMED_LIST *list;
22398 -+ key_cache= (KEY_CACHE *) find_named(&key_caches, base_name->str,
22399 -+ base_name->length, &list);
22400 -+ key_cache->in_init= 1;
22401 -+ pthread_mutex_unlock(&LOCK_global_system_variables);
22402 -+ error= reassign_keycache_tables(thd, key_cache, dflt_key_cache);
22403 -+ pthread_mutex_lock(&LOCK_global_system_variables);
22404 -+ key_cache->in_init= 0;
22405 -+ }
22406 -+ /*
22407 -+ We don't delete the key cache as some running threads my still be
22408 -+ in the key cache code with a pointer to the deleted (empty) key cache
22409 -+ */
22410 -+ goto end;
22411 -+ }
22412 -+
22413 -+ key_cache->param_buff_size= (ulonglong) tmp;
22414 -+
22415 -+ /* If key cache didn't exist initialize it, else resize it */
22416 -+ key_cache->in_init= 1;
22417 -+ pthread_mutex_unlock(&LOCK_global_system_variables);
22418 -+
22419 -+ if (!key_cache->key_cache_inited)
22420 -+ error= (bool) (ha_init_key_cache("", key_cache));
22421 -+ else
22422 -+ error= (bool)(ha_resize_key_cache(key_cache));
22423 -+
22424 -+ pthread_mutex_lock(&LOCK_global_system_variables);
22425 -+ key_cache->in_init= 0;
22426 -+
22427 -+end:
22428 -+ pthread_mutex_unlock(&LOCK_global_system_variables);
22429 -+
22430 -+ var->save_result.ulonglong_value = SIZE_T_MAX;
22431 -+
22432 -+ return error;
22433 -+}
22434 -+
22435 -+
22436 -+bool sys_var_key_cache_long::check(THD *thd, set_var *var)
22437 -+{
22438 -+ return get_unsigned(thd, var, 0, GET_ULONG);
22439 -+}
22440 -+
22441 -+
22442 -+/**
22443 -+ @todo
22444 -+ Abort if some other thread is changing the key cache.
22445 -+ This should be changed so that we wait until the previous
22446 -+ assignment is done and then do the new assign
22447 -+*/
22448 -+bool sys_var_key_cache_long::update(THD *thd, set_var *var)
22449 -+{
22450 -+ LEX_STRING *base_name= &var->base;
22451 -+ bool error= 0;
22452 -+
22453 -+ if (!base_name->length)
22454 -+ base_name= &default_key_cache_base;
22455 -+
22456 -+ pthread_mutex_lock(&LOCK_global_system_variables);
22457 -+ KEY_CACHE *key_cache= get_key_cache(base_name);
22458 -+
22459 -+ if (!key_cache && !(key_cache= create_key_cache(base_name->str,
22460 -+ base_name->length)))
22461 -+ {
22462 -+ error= 1;
22463 -+ goto end;
22464 -+ }
22465 -+
22466 -+ /*
22467 -+ Abort if some other thread is changing the key cache
22468 -+ TODO: This should be changed so that we wait until the previous
22469 -+ assignment is done and then do the new assign
22470 -+ */
22471 -+ if (key_cache->in_init)
22472 -+ goto end;
22473 -+
22474 -+ *((ulong*) (((char*) key_cache) + offset))= (ulong)
22475 -+ var->save_result.ulonglong_value;
22476 -+
22477 -+ /*
22478 -+ Don't create a new key cache if it didn't exist
22479 -+ (key_caches are created only when the user sets block_size)
22480 -+ */
22481 -+ key_cache->in_init= 1;
22482 -+
22483 -+ pthread_mutex_unlock(&LOCK_global_system_variables);
22484 -+
22485 -+ error= (bool) (ha_resize_key_cache(key_cache));
22486 -+
22487 -+ pthread_mutex_lock(&LOCK_global_system_variables);
22488 -+ key_cache->in_init= 0;
22489 -+
22490 -+end:
22491 -+ pthread_mutex_unlock(&LOCK_global_system_variables);
22492 -+ return error;
22493 -+}
22494 -+
22495 -+
22496 -+bool sys_var_log_state::update(THD *thd, set_var *var)
22497 -+{
22498 -+ bool res;
22499 -+
22500 -+ if (this == &sys_var_log)
22501 -+ WARN_DEPRECATED(thd, "7.0", "@@log", "'@@general_log'");
22502 -+ else if (this == &sys_var_log_slow)
22503 -+ WARN_DEPRECATED(thd, "7.0", "@@log_slow_queries", "'@@slow_query_log'");
22504 -+
22505 -+ pthread_mutex_lock(&LOCK_global_system_variables);
22506 -+ if (!var->save_result.ulong_value)
22507 -+ {
22508 -+ logger.deactivate_log_handler(thd, log_type);
22509 -+ res= false;
22510 -+ }
22511 -+ else
22512 -+ res= logger.activate_log_handler(thd, log_type);
22513 -+ pthread_mutex_unlock(&LOCK_global_system_variables);
22514 -+ return res;
22515 -+}
22516 -+
22517 -+void sys_var_log_state::set_default(THD *thd, enum_var_type type)
22518 -+{
22519 -+ if (this == &sys_var_log)
22520 -+ WARN_DEPRECATED(thd, "7.0", "@@log", "'@@general_log'");
22521 -+ else if (this == &sys_var_log_slow)
22522 -+ WARN_DEPRECATED(thd, "7.0", "@@log_slow_queries", "'@@slow_query_log'");
22523 -+
22524 -+ pthread_mutex_lock(&LOCK_global_system_variables);
22525 -+ logger.deactivate_log_handler(thd, log_type);
22526 -+ pthread_mutex_unlock(&LOCK_global_system_variables);
22527 -+}
22528 -+
22529 -+
22530 -+static int sys_check_log_path(THD *thd, set_var *var)
22531 -+{
22532 -+ char path[FN_REFLEN], buff[FN_REFLEN];
22533 -+ MY_STAT f_stat;
22534 -+ String str(buff, sizeof(buff), system_charset_info), *res;
22535 -+ const char *log_file_str;
22536 -+ size_t path_length;
22537 -+
22538 -+ if (!(res= var->value->val_str(&str)))
22539 -+ goto err;
22540 -+
22541 -+ log_file_str= res->c_ptr();
22542 -+ bzero(&f_stat, sizeof(MY_STAT));
22543 -+
22544 -+ path_length= unpack_filename(path, log_file_str);
22545 -+
22546 -+ if (!path_length)
22547 -+ {
22548 -+ /* File name is empty. */
22549 -+
22550 -+ goto err;
22551 -+ }
22552 -+
22553 -+ if (my_stat(path, &f_stat, MYF(0)))
22554 -+ {
22555 -+ /*
22556 -+ A file system object exists. Check if argument is a file and we have
22557 -+ 'write' permission.
22558 -+ */
22559 -+
22560 -+ if (!MY_S_ISREG(f_stat.st_mode) ||
22561 -+ !(f_stat.st_mode & MY_S_IWRITE))
22562 -+ goto err;
22563 -+
22564 -+ return 0;
22565 -+ }
22566 -+
22567 -+ /* Get dirname of the file path. */
22568 -+ (void) dirname_part(path, log_file_str, &path_length);
22569 -+
22570 -+ /* Dirname is empty if file path is relative. */
22571 -+ if (!path_length)
22572 -+ return 0;
22573 -+
22574 -+ /*
22575 -+ Check if directory exists and we have permission to create file and
22576 -+ write to file.
22577 -+ */
22578 -+ if (my_access(path, (F_OK|W_OK)))
22579 -+ goto err;
22580 -+
22581 -+ return 0;
22582 -+
22583 -+err:
22584 -+ my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name,
22585 -+ res ? log_file_str : "NULL");
22586 -+ return 1;
22587 -+}
22588 -+
22589 -+
22590 -+bool update_sys_var_str_path(THD *thd, sys_var_str *var_str,
22591 -+ set_var *var, const char *log_ext,
22592 -+ bool log_state, uint log_type)
22593 -+{
22594 -+ MYSQL_QUERY_LOG *file_log;
22595 -+ char buff[FN_REFLEN];
22596 -+ char *res= 0, *old_value=(char *)(var ? var->value->str_value.ptr() : 0);
22597 -+ bool result= 0;
22598 -+ uint str_length= (var ? var->value->str_value.length() : 0);
22599 -+
22600 -+ switch (log_type) {
22601 -+ case QUERY_LOG_SLOW:
22602 -+ file_log= logger.get_slow_log_file_handler();
22603 -+ break;
22604 -+ case QUERY_LOG_GENERAL:
22605 -+ file_log= logger.get_log_file_handler();
22606 -+ break;
22607 -+ default:
22608 -+ MY_ASSERT_UNREACHABLE();
22609 -+ }
22610 -+
22611 -+ if (!old_value)
22612 -+ {
22613 -+ old_value= make_default_log_name(buff, log_ext);
22614 -+ str_length= strlen(old_value);
22615 -+ }
22616 -+ if (!(res= my_strndup(old_value, str_length, MYF(MY_FAE+MY_WME))))
22617 -+ {
22618 -+ result= 1;
22619 -+ goto err;
22620 -+ }
22621 -+
22622 -+ pthread_mutex_lock(&LOCK_global_system_variables);
22623 -+ logger.lock_exclusive();
22624 -+
22625 -+ if (file_log && log_state)
22626 -+ file_log->close(0);
22627 -+ old_value= var_str->value;
22628 -+ var_str->value= res;
22629 -+ var_str->value_length= str_length;
22630 -+ my_free(old_value, MYF(MY_ALLOW_ZERO_PTR));
22631 -+ if (file_log && log_state)
22632 -+ {
22633 -+ switch (log_type) {
22634 -+ case QUERY_LOG_SLOW:
22635 -+ file_log->open_slow_log(sys_var_slow_log_path.value);
22636 -+ break;
22637 -+ case QUERY_LOG_GENERAL:
22638 -+ file_log->open_query_log(sys_var_general_log_path.value);
22639 -+ break;
22640 -+ default:
22641 -+ DBUG_ASSERT(0);
22642 -+ }
22643 -+ }
22644 -+
22645 -+ logger.unlock();
22646 -+ pthread_mutex_unlock(&LOCK_global_system_variables);
22647 -+
22648 -+err:
22649 -+ return result;
22650 -+}
22651 -+
22652 -+
22653 -+static bool sys_update_general_log_path(THD *thd, set_var * var)
22654 -+{
22655 -+ return update_sys_var_str_path(thd, &sys_var_general_log_path,
22656 -+ var, ".log", opt_log, QUERY_LOG_GENERAL);
22657 -+}
22658 -+
22659 -+
22660 -+static void sys_default_general_log_path(THD *thd, enum_var_type type)
22661 -+{
22662 -+ (void) update_sys_var_str_path(thd, &sys_var_general_log_path,
22663 -+ 0, ".log", opt_log, QUERY_LOG_GENERAL);
22664 -+}
22665 -+
22666 -+
22667 -+static bool sys_update_slow_log_path(THD *thd, set_var * var)
22668 -+{
22669 -+ return update_sys_var_str_path(thd, &sys_var_slow_log_path,
22670 -+ var, "-slow.log", opt_slow_log,
22671 -+ QUERY_LOG_SLOW);
22672 -+}
22673 -+
22674 -+
22675 -+static void sys_default_slow_log_path(THD *thd, enum_var_type type)
22676 -+{
22677 -+ (void) update_sys_var_str_path(thd, &sys_var_slow_log_path,
22678 -+ 0, "-slow.log", opt_slow_log,
22679 -+ QUERY_LOG_SLOW);
22680 -+}
22681 -+
22682 -+
22683 -+bool sys_var_log_output::update(THD *thd, set_var *var)
22684 -+{
22685 -+ pthread_mutex_lock(&LOCK_global_system_variables);
22686 -+ logger.lock_exclusive();
22687 -+ logger.init_slow_log(var->save_result.ulong_value);
22688 -+ logger.init_general_log(var->save_result.ulong_value);
22689 -+ *value= var->save_result.ulong_value;
22690 -+ logger.unlock();
22691 -+ pthread_mutex_unlock(&LOCK_global_system_variables);
22692 -+ return 0;
22693 -+}
22694 -+
22695 -+
22696 -+void sys_var_log_output::set_default(THD *thd, enum_var_type type)
22697 -+{
22698 -+ pthread_mutex_lock(&LOCK_global_system_variables);
22699 -+ logger.lock_exclusive();
22700 -+ logger.init_slow_log(LOG_FILE);
22701 -+ logger.init_general_log(LOG_FILE);
22702 -+ *value= LOG_FILE;
22703 -+ logger.unlock();
22704 -+ pthread_mutex_unlock(&LOCK_global_system_variables);
22705 -+}
22706 -+
22707 -+
22708 -+uchar *sys_var_log_output::value_ptr(THD *thd, enum_var_type type,
22709 -+ LEX_STRING *base)
22710 -+{
22711 -+ char buff[256];
22712 -+ String tmp(buff, sizeof(buff), &my_charset_latin1);
22713 -+ ulong length;
22714 -+ ulong val= *value;
22715 -+
22716 -+ tmp.length(0);
22717 -+ for (uint i= 0; val; val>>= 1, i++)
22718 -+ {
22719 -+ if (val & 1)
22720 -+ {
22721 -+ tmp.append(log_output_typelib.type_names[i],
22722 -+ log_output_typelib.type_lengths[i]);
22723 -+ tmp.append(',');
22724 -+ }
22725 -+ }
22726 -+
22727 -+ if ((length= tmp.length()))
22728 -+ length--;
22729 -+ return (uchar*) thd->strmake(tmp.ptr(), length);
22730 -+}
22731 -+
22732 -+
22733 -+/*****************************************************************************
22734 -+ Functions to handle SET NAMES and SET CHARACTER SET
22735 -+*****************************************************************************/
22736 -+
22737 -+int set_var_collation_client::check(THD *thd)
22738 -+{
22739 -+ /* Currently, UCS-2 cannot be used as a client character set */
22740 -+ if (character_set_client->mbminlen > 1)
22741 -+ {
22742 -+ my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), "character_set_client",
22743 -+ character_set_client->csname);
22744 -+ return 1;
22745 -+ }
22746 -+ return 0;
22747 -+}
22748 -+
22749 -+int set_var_collation_client::update(THD *thd)
22750 -+{
22751 -+ thd->variables.character_set_client= character_set_client;
22752 -+ thd->variables.character_set_results= character_set_results;
22753 -+ thd->variables.collation_connection= collation_connection;
22754 -+ thd->update_charset();
22755 -+ thd->protocol_text.init(thd);
22756 -+ thd->protocol_binary.init(thd);
22757 -+ return 0;
22758 -+}
22759 -+
22760 -+/****************************************************************************/
22761 -+
22762 -+bool sys_var_timestamp::check(THD *thd, set_var *var)
22763 -+{
22764 -+ longlong val;
22765 -+ var->save_result.ulonglong_value= var->value->val_int();
22766 -+ val= (longlong) var->save_result.ulonglong_value;
22767 -+ if (val != 0 && // this is how you set the default value
22768 -+ (val < TIMESTAMP_MIN_VALUE || val > TIMESTAMP_MAX_VALUE))
22769 -+ {
22770 -+ char buf[64];
22771 -+ my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), "timestamp", llstr(val, buf));
22772 -+ return TRUE;
22773 -+ }
22774 -+ return FALSE;
22775 -+}
22776 -+
22777 -+
22778 -+bool sys_var_timestamp::update(THD *thd, set_var *var)
22779 -+{
22780 -+ thd->set_time((time_t) var->save_result.ulonglong_value);
22781 -+ return FALSE;
22782 -+}
22783 -+
22784 -+
22785 -+void sys_var_timestamp::set_default(THD *thd, enum_var_type type)
22786 -+{
22787 -+ thd->user_time=0;
22788 -+}
22789 -+
22790 -+
22791 -+uchar *sys_var_timestamp::value_ptr(THD *thd, enum_var_type type,
22792 -+ LEX_STRING *base)
22793 -+{
22794 -+ thd->sys_var_tmp.long_value= (long) thd->start_time;
22795 -+ return (uchar*) &thd->sys_var_tmp.long_value;
22796 -+}
22797 -+
22798 -+
22799 -+bool sys_var_last_insert_id::update(THD *thd, set_var *var)
22800 -+{
22801 -+ thd->first_successful_insert_id_in_prev_stmt=
22802 -+ var->save_result.ulonglong_value;
22803 -+ return 0;
22804 -+}
22805 -+
22806 -+
22807 -+uchar *sys_var_last_insert_id::value_ptr(THD *thd, enum_var_type type,
22808 -+ LEX_STRING *base)
22809 -+{
22810 -+ /*
22811 -+ this tmp var makes it robust againt change of type of
22812 -+ read_first_successful_insert_id_in_prev_stmt().
22813 -+ */
22814 -+ thd->sys_var_tmp.ulonglong_value=
22815 -+ thd->read_first_successful_insert_id_in_prev_stmt();
22816 -+ return (uchar*) &thd->sys_var_tmp.ulonglong_value;
22817 -+}
22818 -+
22819 -+
22820 -+bool sys_var_insert_id::update(THD *thd, set_var *var)
22821 -+{
22822 -+ thd->force_one_auto_inc_interval(var->save_result.ulonglong_value);
22823 -+ return 0;
22824 -+}
22825 -+
22826 -+
22827 -+uchar *sys_var_insert_id::value_ptr(THD *thd, enum_var_type type,
22828 -+ LEX_STRING *base)
22829 -+{
22830 -+ thd->sys_var_tmp.ulonglong_value=
22831 -+ thd->auto_inc_intervals_forced.minimum();
22832 -+ return (uchar*) &thd->sys_var_tmp.ulonglong_value;
22833 -+}
22834 -+
22835 -+
22836 -+bool sys_var_rand_seed1::update(THD *thd, set_var *var)
22837 -+{
22838 -+ thd->rand.seed1= (ulong) var->save_result.ulonglong_value;
22839 -+ return 0;
22840 -+}
22841 -+
22842 -+bool sys_var_rand_seed2::update(THD *thd, set_var *var)
22843 -+{
22844 -+ thd->rand.seed2= (ulong) var->save_result.ulonglong_value;
22845 -+ return 0;
22846 -+}
22847 -+
22848 -+
22849 -+bool sys_var_thd_time_zone::check(THD *thd, set_var *var)
22850 -+{
22851 -+ char buff[MAX_TIME_ZONE_NAME_LENGTH];
22852 -+ String str(buff, sizeof(buff), &my_charset_latin1);
22853 -+ String *res= var->value->val_str(&str);
22854 -+
22855 -+ if (!(var->save_result.time_zone= my_tz_find(thd, res)))
22856 -+ {
22857 -+ my_error(ER_UNKNOWN_TIME_ZONE, MYF(0), res ? res->c_ptr() : "NULL");
22858 -+ return 1;
22859 -+ }
22860 -+ return 0;
22861 -+}
22862 -+
22863 -+
22864 -+bool sys_var_thd_time_zone::update(THD *thd, set_var *var)
22865 -+{
22866 -+ /* We are using Time_zone object found during check() phase. */
22867 -+ if (var->type == OPT_GLOBAL)
22868 -+ {
22869 -+ pthread_mutex_lock(&LOCK_global_system_variables);
22870 -+ global_system_variables.time_zone= var->save_result.time_zone;
22871 -+ pthread_mutex_unlock(&LOCK_global_system_variables);
22872 -+ }
22873 -+ else
22874 -+ thd->variables.time_zone= var->save_result.time_zone;
22875 -+ return 0;
22876 -+}
22877 -+
22878 -+
22879 -+uchar *sys_var_thd_time_zone::value_ptr(THD *thd, enum_var_type type,
22880 -+ LEX_STRING *base)
22881 -+{
22882 -+ /*
22883 -+ We can use ptr() instead of c_ptr() here because String contaning
22884 -+ time zone name is guaranteed to be zero ended.
22885 -+ */
22886 -+ if (type == OPT_GLOBAL)
22887 -+ return (uchar *)(global_system_variables.time_zone->get_name()->ptr());
22888 -+ else
22889 -+ {
22890 -+ /*
22891 -+ This is an ugly fix for replication: we don't replicate properly queries
22892 -+ invoking system variables' values to update tables; but
22893 -+ CONVERT_TZ(,,@@session.time_zone) is so popular that we make it
22894 -+ replicable (i.e. we tell the binlog code to store the session
22895 -+ timezone). If it's the global value which was used we can't replicate
22896 -+ (binlog code stores session value only).
22897 -+ */
22898 -+ thd->time_zone_used= 1;
22899 -+ return (uchar *)(thd->variables.time_zone->get_name()->ptr());
22900 -+ }
22901 -+}
22902 -+
22903 -+
22904 -+void sys_var_thd_time_zone::set_default(THD *thd, enum_var_type type)
22905 -+{
22906 -+ pthread_mutex_lock(&LOCK_global_system_variables);
22907 -+ if (type == OPT_GLOBAL)
22908 -+ {
22909 -+ if (default_tz_name)
22910 -+ {
22911 -+ String str(default_tz_name, &my_charset_latin1);
22912 -+ /*
22913 -+ We are guaranteed to find this time zone since its existence
22914 -+ is checked during start-up.
22915 -+ */
22916 -+ global_system_variables.time_zone= my_tz_find(thd, &str);
22917 -+ }
22918 -+ else
22919 -+ global_system_variables.time_zone= my_tz_SYSTEM;
22920 -+ }
22921 -+ else
22922 -+ thd->variables.time_zone= global_system_variables.time_zone;
22923 -+ pthread_mutex_unlock(&LOCK_global_system_variables);
22924 -+}
22925 -+
22926 -+
22927 -+bool sys_var_max_user_conn::check(THD *thd, set_var *var)
22928 -+{
22929 -+ if (var->type == OPT_GLOBAL)
22930 -+ return sys_var_thd::check(thd, var);
22931 -+ else
22932 -+ {
22933 -+ /*
22934 -+ Per-session values of max_user_connections can't be set directly.
22935 -+ May be we should have a separate error message for this?
22936 -+ */
22937 -+ my_error(ER_GLOBAL_VARIABLE, MYF(0), name);
22938 -+ return TRUE;
22939 -+ }
22940 -+}
22941 -+
22942 -+bool sys_var_max_user_conn::update(THD *thd, set_var *var)
22943 -+{
22944 -+ DBUG_ASSERT(var->type == OPT_GLOBAL);
22945 -+ pthread_mutex_lock(&LOCK_global_system_variables);
22946 -+ max_user_connections= (uint)var->save_result.ulonglong_value;
22947 -+ pthread_mutex_unlock(&LOCK_global_system_variables);
22948 -+ return 0;
22949 -+}
22950 -+
22951 -+
22952 -+void sys_var_max_user_conn::set_default(THD *thd, enum_var_type type)
22953 -+{
22954 -+ DBUG_ASSERT(type == OPT_GLOBAL);
22955 -+ pthread_mutex_lock(&LOCK_global_system_variables);
22956 -+ max_user_connections= (ulong) option_limits->def_value;
22957 -+ pthread_mutex_unlock(&LOCK_global_system_variables);
22958 -+}
22959 -+
22960 -+
22961 -+uchar *sys_var_max_user_conn::value_ptr(THD *thd, enum_var_type type,
22962 -+ LEX_STRING *base)
22963 -+{
22964 -+ if (type != OPT_GLOBAL &&
22965 -+ thd->user_connect && thd->user_connect->user_resources.user_conn)
22966 -+ return (uchar*) &(thd->user_connect->user_resources.user_conn);
22967 -+ return (uchar*) &(max_user_connections);
22968 -+}
22969 -+
22970 -+
22971 -+bool sys_var_thd_ulong_session_readonly::check(THD *thd, set_var *var)
22972 -+{
22973 -+ if (var->type != OPT_GLOBAL)
22974 -+ {
22975 -+ my_error(ER_VARIABLE_IS_READONLY, MYF(0), "SESSION", name, "GLOBAL");
22976 -+ return TRUE;
22977 -+ }
22978 -+
22979 -+ return sys_var_thd_ulong::check(thd, var);
22980 -+}
22981 -+
22982 -+
22983 -+bool sys_var_thd_lc_time_names::check(THD *thd, set_var *var)
22984 -+{
22985 -+ MY_LOCALE *locale_match;
22986 -+
22987 -+ if (var->value->result_type() == INT_RESULT)
22988 -+ {
22989 -+ if (!(locale_match= my_locale_by_number((uint) var->value->val_int())))
22990 -+ {
22991 -+ char buf[20];
22992 -+ int10_to_str((int) var->value->val_int(), buf, -10);
22993 -+ my_printf_error(ER_UNKNOWN_ERROR, "Unknown locale: '%s'", MYF(0), buf);
22994 -+ return 1;
22995 -+ }
22996 -+ }
22997 -+ else // STRING_RESULT
22998 -+ {
22999 -+ char buff[6];
23000 -+ String str(buff, sizeof(buff), &my_charset_latin1), *res;
23001 -+ if (!(res=var->value->val_str(&str)))
23002 -+ {
23003 -+ my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, "NULL");
23004 -+ return 1;
23005 -+ }
23006 -+ const char *locale_str= res->c_ptr_safe();
23007 -+ if (!(locale_match= my_locale_by_name(locale_str)))
23008 -+ {
23009 -+ my_printf_error(ER_UNKNOWN_ERROR,
23010 -+ "Unknown locale: '%s'", MYF(0), locale_str);
23011 -+ return 1;
23012 -+ }
23013 -+ }
23014 -+
23015 -+ var->save_result.locale_value= locale_match;
23016 -+ return 0;
23017 -+}
23018 -+
23019 -+
23020 -+bool sys_var_thd_lc_time_names::update(THD *thd, set_var *var)
23021 -+{
23022 -+ if (var->type == OPT_GLOBAL)
23023 -+ global_system_variables.lc_time_names= var->save_result.locale_value;
23024 -+ else
23025 -+ thd->variables.lc_time_names= var->save_result.locale_value;
23026 -+ return 0;
23027 -+}
23028 -+
23029 -+
23030 -+uchar *sys_var_thd_lc_time_names::value_ptr(THD *thd, enum_var_type type,
23031 -+ LEX_STRING *base)
23032 -+{
23033 -+ return type == OPT_GLOBAL ?
23034 -+ (uchar *) global_system_variables.lc_time_names->name :
23035 -+ (uchar *) thd->variables.lc_time_names->name;
23036 -+}
23037 -+
23038 -+
23039 -+void sys_var_thd_lc_time_names::set_default(THD *thd, enum_var_type type)
23040 -+{
23041 -+ if (type == OPT_GLOBAL)
23042 -+ global_system_variables.lc_time_names= my_default_lc_time_names;
23043 -+ else
23044 -+ thd->variables.lc_time_names= global_system_variables.lc_time_names;
23045 -+}
23046 -+
23047 -+/*
23048 -+ Handling of microseoncds given as seconds.part_seconds
23049 -+
23050 -+ NOTES
23051 -+ The argument to long query time is in seconds in decimal
23052 -+ which is converted to ulonglong integer holding microseconds for storage.
23053 -+ This is used for handling long_query_time
23054 -+*/
23055 -+
23056 -+bool sys_var_microseconds::update(THD *thd, set_var *var)
23057 -+{
23058 -+ double num= var->value->val_real();
23059 -+ longlong microseconds;
23060 -+ if (num > (double) option_limits->max_value)
23061 -+ num= (double) option_limits->max_value;
23062 -+ if (num < (double) option_limits->min_value)
23063 -+ num= (double) option_limits->min_value;
23064 -+ microseconds= (longlong) (num * 1000000.0 + 0.5);
23065 -+ if (var->type == OPT_GLOBAL)
23066 -+ {
23067 -+ pthread_mutex_lock(&LOCK_global_system_variables);
23068 -+ (global_system_variables.*offset)= microseconds;
23069 -+ pthread_mutex_unlock(&LOCK_global_system_variables);
23070 -+ }
23071 -+ else
23072 -+ thd->variables.*offset= microseconds;
23073 -+ return 0;
23074 -+}
23075 -+
23076 -+
23077 -+void sys_var_microseconds::set_default(THD *thd, enum_var_type type)
23078 -+{
23079 -+ longlong microseconds= (longlong) (option_limits->def_value * 1000000.0);
23080 -+ if (type == OPT_GLOBAL)
23081 -+ {
23082 -+ pthread_mutex_lock(&LOCK_global_system_variables);
23083 -+ global_system_variables.*offset= microseconds;
23084 -+ pthread_mutex_unlock(&LOCK_global_system_variables);
23085 -+ }
23086 -+ else
23087 -+ thd->variables.*offset= microseconds;
23088 -+}
23089 -+
23090 -+
23091 -+uchar *sys_var_microseconds::value_ptr(THD *thd, enum_var_type type,
23092 -+ LEX_STRING *base)
23093 -+{
23094 -+ thd->tmp_double_value= (double) ((type == OPT_GLOBAL) ?
23095 -+ global_system_variables.*offset :
23096 -+ thd->variables.*offset) / 1000000.0;
23097 -+ return (uchar*) &thd->tmp_double_value;
23098 -+}
23099 -+
23100 -+
23101 -+/*
23102 -+ Functions to update thd->options bits
23103 -+*/
23104 -+
23105 -+static bool set_option_bit(THD *thd, set_var *var)
23106 -+{
23107 -+ sys_var_thd_bit *sys_var= ((sys_var_thd_bit*) var->var);
23108 -+ if ((var->save_result.ulong_value != 0) == sys_var->reverse)
23109 -+ thd->options&= ~sys_var->bit_flag;
23110 -+ else
23111 -+ thd->options|= sys_var->bit_flag;
23112 -+ return 0;
23113 -+}
23114 -+
23115 -+/*
23116 -+ Functions to be only used to update thd->options OPTION_BIN_LOG bit
23117 -+*/
23118 -+static bool set_option_log_bin_bit(THD *thd, set_var *var)
23119 -+{
23120 -+ set_option_bit(thd, var);
23121 -+ if (!thd->in_sub_stmt)
23122 -+ thd->sql_log_bin_toplevel= thd->options & OPTION_BIN_LOG;
23123 -+ return 0;
23124 -+}
23125 -+
23126 -+static bool set_option_autocommit(THD *thd, set_var *var)
23127 -+{
23128 -+ /* The test is negative as the flag we use is NOT autocommit */
23129 -+
23130 -+ ulonglong org_options= thd->options;
23131 -+
23132 -+ if (var->save_result.ulong_value != 0)
23133 -+ thd->options&= ~((sys_var_thd_bit*) var->var)->bit_flag;
23134 -+ else
23135 -+ thd->options|= ((sys_var_thd_bit*) var->var)->bit_flag;
23136 -+
23137 -+ if ((org_options ^ thd->options) & OPTION_NOT_AUTOCOMMIT)
23138 -+ {
23139 -+ if ((org_options & OPTION_NOT_AUTOCOMMIT))
23140 -+ {
23141 -+ /* We changed to auto_commit mode */
23142 -+ if (thd->transaction.xid_state.xa_state != XA_NOTR)
23143 -+ {
23144 -+ thd->options= org_options;
23145 -+ my_error(ER_XAER_RMFAIL, MYF(0),
23146 -+ xa_state_names[thd->transaction.xid_state.xa_state]);
23147 -+ return 1;
23148 -+ }
23149 -+ thd->options&= ~(ulonglong) (OPTION_BEGIN | OPTION_KEEP_LOG);
23150 -+ thd->transaction.all.modified_non_trans_table= FALSE;
23151 -+ thd->server_status|= SERVER_STATUS_AUTOCOMMIT;
23152 -+ if (ha_commit(thd))
23153 -+ return 1;
23154 -+ }
23155 -+ else
23156 -+ {
23157 -+ thd->transaction.all.modified_non_trans_table= FALSE;
23158 -+ thd->server_status&= ~SERVER_STATUS_AUTOCOMMIT;
23159 -+ }
23160 -+ }
23161 -+ return 0;
23162 -+}
23163 -+
23164 -+static int check_log_update(THD *thd, set_var *var)
23165 -+{
23166 -+#ifndef NO_EMBEDDED_ACCESS_CHECKS
23167 -+ if (!(thd->security_ctx->master_access & SUPER_ACL))
23168 -+ {
23169 -+ my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER");
23170 -+ return 1;
23171 -+ }
23172 -+#endif
23173 -+ return 0;
23174 -+}
23175 -+
23176 -+static bool set_log_update(THD *thd, set_var *var)
23177 -+{
23178 -+ /*
23179 -+ The update log is not supported anymore since 5.0.
23180 -+ See sql/mysqld.cc/, comments in function init_server_components() for an
23181 -+ explaination of the different warnings we send below
23182 -+ */
23183 -+
23184 -+ if (opt_sql_bin_update)
23185 -+ {
23186 -+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
23187 -+ ER_UPDATE_LOG_DEPRECATED_TRANSLATED,
23188 -+ ER(ER_UPDATE_LOG_DEPRECATED_TRANSLATED));
23189 -+ }
23190 -+ else
23191 -+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
23192 -+ ER_UPDATE_LOG_DEPRECATED_IGNORED,
23193 -+ ER(ER_UPDATE_LOG_DEPRECATED_IGNORED));
23194 -+ set_option_bit(thd, var);
23195 -+ return 0;
23196 -+}
23197 -+
23198 -+
23199 -+static int check_pseudo_thread_id(THD *thd, set_var *var)
23200 -+{
23201 -+ var->save_result.ulonglong_value= var->value->val_int();
23202 -+#ifndef NO_EMBEDDED_ACCESS_CHECKS
23203 -+ if (thd->security_ctx->master_access & SUPER_ACL)
23204 -+ return 0;
23205 -+ else
23206 -+ {
23207 -+ my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER");
23208 -+ return 1;
23209 -+ }
23210 -+#else
23211 -+ return 0;
23212 -+#endif
23213 -+}
23214 -+
23215 -+static uchar *get_warning_count(THD *thd)
23216 -+{
23217 -+ thd->sys_var_tmp.long_value=
23218 -+ (thd->warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_NOTE] +
23219 -+ thd->warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_ERROR] +
23220 -+ thd->warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_WARN]);
23221 -+ return (uchar*) &thd->sys_var_tmp.long_value;
23222 -+}
23223 -+
23224 -+static uchar *get_error_count(THD *thd)
23225 -+{
23226 -+ thd->sys_var_tmp.long_value=
23227 -+ thd->warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_ERROR];
23228 -+ return (uchar*) &thd->sys_var_tmp.long_value;
23229 -+}
23230 -+
23231 -+
23232 -+/**
23233 -+ Get the tmpdir that was specified or chosen by default.
23234 -+
23235 -+ This is necessary because if the user does not specify a temporary
23236 -+ directory via the command line, one is chosen based on the environment
23237 -+ or system defaults. But we can't just always use mysql_tmpdir, because
23238 -+ that is actually a call to my_tmpdir() which cycles among possible
23239 -+ temporary directories.
23240 -+
23241 -+ @param thd thread handle
23242 -+
23243 -+ @retval
23244 -+ ptr pointer to NUL-terminated string
23245 -+*/
23246 -+static uchar *get_tmpdir(THD *thd)
23247 -+{
23248 -+ if (opt_mysql_tmpdir)
23249 -+ return (uchar *)opt_mysql_tmpdir;
23250 -+ return (uchar*)mysql_tmpdir;
23251 -+}
23252 -+
23253 -+static uchar *get_myisam_mmap_size(THD *thd)
23254 -+{
23255 -+ return (uchar *)&myisam_mmap_size;
23256 -+}
23257 -+
23258 -+
23259 -+/****************************************************************************
23260 -+ Main handling of variables:
23261 -+ - Initialisation
23262 -+ - Searching during parsing
23263 -+ - Update loop
23264 -+****************************************************************************/
23265 -+
23266 -+/**
23267 -+ Find variable name in option my_getopt structure used for
23268 -+ command line args.
23269 -+
23270 -+ @param opt option structure array to search in
23271 -+ @param name variable name
23272 -+
23273 -+ @retval
23274 -+ 0 Error
23275 -+ @retval
23276 -+ ptr pointer to option structure
23277 -+*/
23278 -+
23279 -+static struct my_option *find_option(struct my_option *opt, const char *name)
23280 -+{
23281 -+ uint length=strlen(name);
23282 -+ for (; opt->name; opt++)
23283 -+ {
23284 -+ if (!getopt_compare_strings(opt->name, name, length) &&
23285 -+ !opt->name[length])
23286 -+ {
23287 -+ /*
23288 -+ Only accept the option if one can set values through it.
23289 -+ If not, there is no default value or limits in the option.
23290 -+ */
23291 -+ return (opt->value) ? opt : 0;
23292 -+ }
23293 -+ }
23294 -+ return 0;
23295 -+}
23296 -+
23297 -+
23298 -+/**
23299 -+ Return variable name and length for hashing of variables.
23300 -+*/
23301 -+
23302 -+static uchar *get_sys_var_length(const sys_var *var, size_t *length,
23303 -+ my_bool first)
23304 -+{
23305 -+ *length= var->name_length;
23306 -+ return (uchar*) var->name;
23307 -+}
23308 -+
23309 -+
23310 -+/*
23311 -+ Add variables to the dynamic hash of system variables
23312 -+
23313 -+ SYNOPSIS
23314 -+ mysql_add_sys_var_chain()
23315 -+ first Pointer to first system variable to add
23316 -+ long_opt (optional)command line arguments may be tied for limit checks.
23317 -+
23318 -+ RETURN VALUES
23319 -+ 0 SUCCESS
23320 -+ otherwise FAILURE
23321 -+*/
23322 -+
23323 -+
23324 -+int mysql_add_sys_var_chain(sys_var *first, struct my_option *long_options)
23325 -+{
23326 -+ sys_var *var;
23327 -+
23328 -+ /* A write lock should be held on LOCK_system_variables_hash */
23329 -+
23330 -+ for (var= first; var; var= var->next)
23331 -+ {
23332 -+ var->name_length= strlen(var->name);
23333 -+ /* this fails if there is a conflicting variable name. see HASH_UNIQUE */
23334 -+ if (my_hash_insert(&system_variable_hash, (uchar*) var))
23335 -+ goto error;
23336 -+ if (long_options)
23337 -+ var->option_limits= find_option(long_options, var->name);
23338 -+ }
23339 -+ return 0;
23340 -+
23341 -+error:
23342 -+ for (; first != var; first= first->next)
23343 -+ hash_delete(&system_variable_hash, (uchar*) first);
23344 -+ return 1;
23345 -+}
23346 -+
23347 -+
23348 -+/*
23349 -+ Remove variables to the dynamic hash of system variables
23350 -+
23351 -+ SYNOPSIS
23352 -+ mysql_del_sys_var_chain()
23353 -+ first Pointer to first system variable to remove
23354 -+
23355 -+ RETURN VALUES
23356 -+ 0 SUCCESS
23357 -+ otherwise FAILURE
23358 -+*/
23359 -+
23360 -+int mysql_del_sys_var_chain(sys_var *first)
23361 -+{
23362 -+ int result= 0;
23363 -+
23364 -+ /* A write lock should be held on LOCK_system_variables_hash */
23365 -+
23366 -+ for (sys_var *var= first; var; var= var->next)
23367 -+ result|= hash_delete(&system_variable_hash, (uchar*) var);
23368 -+
23369 -+ return result;
23370 -+}
23371 -+
23372 -+
23373 -+static int show_cmp(SHOW_VAR *a, SHOW_VAR *b)
23374 -+{
23375 -+ return strcmp(a->name, b->name);
23376 -+}
23377 -+
23378 -+
23379 -+/*
23380 -+ Constructs an array of system variables for display to the user.
23381 -+
23382 -+ SYNOPSIS
23383 -+ enumerate_sys_vars()
23384 -+ thd current thread
23385 -+ sorted If TRUE, the system variables should be sorted
23386 -+
23387 -+ RETURN VALUES
23388 -+ pointer Array of SHOW_VAR elements for display
23389 -+ NULL FAILURE
23390 -+*/
23391 -+
23392 -+SHOW_VAR* enumerate_sys_vars(THD *thd, bool sorted)
23393 -+{
23394 -+ int count= system_variable_hash.records, i;
23395 -+ int size= sizeof(SHOW_VAR) * (count + 1);
23396 -+ SHOW_VAR *result= (SHOW_VAR*) thd->alloc(size);
23397 -+
23398 -+ if (result)
23399 -+ {
23400 -+ SHOW_VAR *show= result;
23401 -+
23402 -+ for (i= 0; i < count; i++)
23403 -+ {
23404 -+ sys_var *var= (sys_var*) hash_element(&system_variable_hash, i);
23405 -+ show->name= var->name;
23406 -+ show->value= (char*) var;
23407 -+ show->type= SHOW_SYS;
23408 -+ show++;
23409 -+ }
23410 -+
23411 -+ /* sort into order */
23412 -+ if (sorted)
23413 -+ my_qsort(result, count, sizeof(SHOW_VAR),
23414 -+ (qsort_cmp) show_cmp);
23415 -+
23416 -+ /* make last element empty */
23417 -+ bzero(show, sizeof(SHOW_VAR));
23418 -+ }
23419 -+ return result;
23420 -+}
23421 -+
23422 -+
23423 -+/*
23424 -+ Initialize the system variables
23425 -+
23426 -+ SYNOPSIS
23427 -+ set_var_init()
23428 -+
23429 -+ RETURN VALUES
23430 -+ 0 SUCCESS
23431 -+ otherwise FAILURE
23432 -+*/
23433 -+
23434 -+int set_var_init()
23435 -+{
23436 -+ uint count= 0;
23437 -+ DBUG_ENTER("set_var_init");
23438 -+
23439 -+ for (sys_var *var=vars.first; var; var= var->next, count++) ;
23440 -+
23441 -+ if (hash_init(&system_variable_hash, system_charset_info, count, 0,
23442 -+ 0, (hash_get_key) get_sys_var_length, 0, HASH_UNIQUE))
23443 -+ goto error;
23444 -+
23445 -+ vars.last->next= NULL;
23446 -+ if (mysql_add_sys_var_chain(vars.first, my_long_options))
23447 -+ goto error;
23448 -+
23449 -+ /*
23450 -+ Special cases
23451 -+ Needed because MySQL can't find the limits for a variable it it has
23452 -+ a different name than the command line option.
23453 -+ As these variables are deprecated, this code will disappear soon...
23454 -+ */
23455 -+ sys_sql_max_join_size.option_limits= sys_max_join_size.option_limits;
23456 -+
23457 -+ DBUG_RETURN(0);
23458 -+
23459 -+error:
23460 -+ fprintf(stderr, "failed to initialize system variables");
23461 -+ DBUG_RETURN(1);
23462 -+}
23463 -+
23464 -+
23465 -+void set_var_free()
23466 -+{
23467 -+ hash_free(&system_variable_hash);
23468 -+}
23469 -+
23470 -+
23471 -+/**
23472 -+ Find a user set-table variable.
23473 -+
23474 -+ @param str Name of system variable to find
23475 -+ @param length Length of variable. zero means that we should use strlen()
23476 -+ on the variable
23477 -+ @param no_error Refuse to emit an error, even if one occurred.
23478 -+
23479 -+ @retval
23480 -+ pointer pointer to variable definitions
23481 -+ @retval
23482 -+ 0 Unknown variable (error message is given)
23483 -+*/
23484 -+
23485 -+sys_var *intern_find_sys_var(const char *str, uint length, bool no_error)
23486 -+{
23487 -+ sys_var *var;
23488 -+
23489 -+ /*
23490 -+ This function is only called from the sql_plugin.cc.
23491 -+ A lock on LOCK_system_variable_hash should be held
23492 -+ */
23493 -+ var= (sys_var*) hash_search(&system_variable_hash,
23494 -+ (uchar*) str, length ? length : strlen(str));
23495 -+ if (!(var || no_error))
23496 -+ my_error(ER_UNKNOWN_SYSTEM_VARIABLE, MYF(0), (char*) str);
23497 -+
23498 -+ return var;
23499 -+}
23500 -+
23501 -+
23502 -+/**
23503 -+ Execute update of all variables.
23504 -+
23505 -+ First run a check of all variables that all updates will go ok.
23506 -+ If yes, then execute all updates, returning an error if any one failed.
23507 -+
23508 -+ This should ensure that in all normal cases none all or variables are
23509 -+ updated.
23510 -+
23511 -+ @param THD Thread id
23512 -+ @param var_list List of variables to update
23513 -+
23514 -+ @retval
23515 -+ 0 ok
23516 -+ @retval
23517 -+ 1 ERROR, message sent (normally no variables was updated)
23518 -+ @retval
23519 -+ -1 ERROR, message not sent
23520 -+*/
23521 -+
23522 -+int sql_set_variables(THD *thd, List<set_var_base> *var_list)
23523 -+{
23524 -+ int error;
23525 -+ List_iterator_fast<set_var_base> it(*var_list);
23526 -+ DBUG_ENTER("sql_set_variables");
23527 -+
23528 -+ set_var_base *var;
23529 -+ while ((var=it++))
23530 -+ {
23531 -+ if ((error= var->check(thd)))
23532 -+ goto err;
23533 -+ }
23534 -+ if (!(error= test(thd->is_error())))
23535 -+ {
23536 -+ it.rewind();
23537 -+ while ((var= it++))
23538 -+ error|= var->update(thd); // Returns 0, -1 or 1
23539 -+ }
23540 -+
23541 -+err:
23542 -+ free_underlaid_joins(thd, &thd->lex->select_lex);
23543 -+ DBUG_RETURN(error);
23544 -+}
23545 -+
23546 -+
23547 -+/**
23548 -+ Say if all variables set by a SET support the ONE_SHOT keyword
23549 -+ (currently, only character set and collation do; later timezones
23550 -+ will).
23551 -+
23552 -+ @param var_list List of variables to update
23553 -+
23554 -+ @note
23555 -+ It has a "not_" because it makes faster tests (no need to "!")
23556 -+
23557 -+ @retval
23558 -+ 0 all variables of the list support ONE_SHOT
23559 -+ @retval
23560 -+ 1 at least one does not support ONE_SHOT
23561 -+*/
23562 -+
23563 -+bool not_all_support_one_shot(List<set_var_base> *var_list)
23564 -+{
23565 -+ List_iterator_fast<set_var_base> it(*var_list);
23566 -+ set_var_base *var;
23567 -+ while ((var= it++))
23568 -+ {
23569 -+ if (var->no_support_one_shot())
23570 -+ return 1;
23571 -+ }
23572 -+ return 0;
23573 -+}
23574 -+
23575 -+
23576 -+/*****************************************************************************
23577 -+ Functions to handle SET mysql_internal_variable=const_expr
23578 -+*****************************************************************************/
23579 -+
23580 -+int set_var::check(THD *thd)
23581 -+{
23582 -+ if (var->is_readonly())
23583 -+ {
23584 -+ my_error(ER_INCORRECT_GLOBAL_LOCAL_VAR, MYF(0), var->name, "read only");
23585 -+ return -1;
23586 -+ }
23587 -+ if (var->check_type(type))
23588 -+ {
23589 -+ int err= type == OPT_GLOBAL ? ER_LOCAL_VARIABLE : ER_GLOBAL_VARIABLE;
23590 -+ my_error(err, MYF(0), var->name);
23591 -+ return -1;
23592 -+ }
23593 -+ if ((type == OPT_GLOBAL && check_global_access(thd, SUPER_ACL)))
23594 -+ return 1;
23595 -+ /* value is a NULL pointer if we are using SET ... = DEFAULT */
23596 -+ if (!value)
23597 -+ {
23598 -+ if (var->check_default(type))
23599 -+ {
23600 -+ my_error(ER_NO_DEFAULT, MYF(0), var->name);
23601 -+ return -1;
23602 -+ }
23603 -+ return 0;
23604 -+ }
23605 -+
23606 -+ if ((!value->fixed &&
23607 -+ value->fix_fields(thd, &value)) || value->check_cols(1))
23608 -+ return -1;
23609 -+ if (var->check_update_type(value->result_type()))
23610 -+ {
23611 -+ my_error(ER_WRONG_TYPE_FOR_VAR, MYF(0), var->name);
23612 -+ return -1;
23613 -+ }
23614 -+ return var->check(thd, this) ? -1 : 0;
23615 -+}
23616 -+
23617 -+
23618 -+/**
23619 -+ Check variable, but without assigning value (used by PS).
23620 -+
23621 -+ @param thd thread handler
23622 -+
23623 -+ @retval
23624 -+ 0 ok
23625 -+ @retval
23626 -+ 1 ERROR, message sent (normally no variables was updated)
23627 -+ @retval
23628 -+ -1 ERROR, message not sent
23629 -+*/
23630 -+int set_var::light_check(THD *thd)
23631 -+{
23632 -+ if (var->check_type(type))
23633 -+ {
23634 -+ int err= type == OPT_GLOBAL ? ER_LOCAL_VARIABLE : ER_GLOBAL_VARIABLE;
23635 -+ my_error(err, MYF(0), var->name);
23636 -+ return -1;
23637 -+ }
23638 -+ if (type == OPT_GLOBAL && check_global_access(thd, SUPER_ACL))
23639 -+ return 1;
23640 -+
23641 -+ if (value && ((!value->fixed && value->fix_fields(thd, &value)) ||
23642 -+ value->check_cols(1)))
23643 -+ return -1;
23644 -+ return 0;
23645 -+}
23646 -+
23647 -+/**
23648 -+ Update variable
23649 -+
23650 -+ @param thd thread handler
23651 -+ @returns 0|1 ok or ERROR
23652 -+
23653 -+ @note ERROR can be only due to abnormal operations involving
23654 -+ the server's execution evironment such as
23655 -+ out of memory, hard disk failure or the computer blows up.
23656 -+ Consider set_var::check() method if there is a need to return
23657 -+ an error due to logics.
23658 -+*/
23659 -+int set_var::update(THD *thd)
23660 -+{
23661 -+ if (!value)
23662 -+ var->set_default(thd, type);
23663 -+ else if (var->update(thd, this))
23664 -+ return -1; // should never happen
23665 -+ if (var->after_update)
23666 -+ (*var->after_update)(thd, type);
23667 -+ return 0;
23668 -+}
23669 -+
23670 -+
23671 -+/*****************************************************************************
23672 -+ Functions to handle SET @user_variable=const_expr
23673 -+*****************************************************************************/
23674 -+
23675 -+int set_var_user::check(THD *thd)
23676 -+{
23677 -+ /*
23678 -+ Item_func_set_user_var can't substitute something else on its place =>
23679 -+ 0 can be passed as last argument (reference on item)
23680 -+ */
23681 -+ return (user_var_item->fix_fields(thd, (Item**) 0) ||
23682 -+ user_var_item->check(0)) ? -1 : 0;
23683 -+}
23684 -+
23685 -+
23686 -+/**
23687 -+ Check variable, but without assigning value (used by PS).
23688 -+
23689 -+ @param thd thread handler
23690 -+
23691 -+ @retval
23692 -+ 0 ok
23693 -+ @retval
23694 -+ 1 ERROR, message sent (normally no variables was updated)
23695 -+ @retval
23696 -+ -1 ERROR, message not sent
23697 -+*/
23698 -+int set_var_user::light_check(THD *thd)
23699 -+{
23700 -+ /*
23701 -+ Item_func_set_user_var can't substitute something else on its place =>
23702 -+ 0 can be passed as last argument (reference on item)
23703 -+ */
23704 -+ return (user_var_item->fix_fields(thd, (Item**) 0));
23705 -+}
23706 -+
23707 -+
23708 -+int set_var_user::update(THD *thd)
23709 -+{
23710 -+ if (user_var_item->update())
23711 -+ {
23712 -+ /* Give an error if it's not given already */
23713 -+ my_message(ER_SET_CONSTANTS_ONLY, ER(ER_SET_CONSTANTS_ONLY), MYF(0));
23714 -+ return -1;
23715 -+ }
23716 -+ return 0;
23717 -+}
23718 -+
23719 -+
23720 -+/*****************************************************************************
23721 -+ Functions to handle SET PASSWORD
23722 -+*****************************************************************************/
23723 -+
23724 -+int set_var_password::check(THD *thd)
23725 -+{
23726 -+#ifndef NO_EMBEDDED_ACCESS_CHECKS
23727 -+ if (!user->host.str)
23728 -+ {
23729 -+ DBUG_ASSERT(thd->security_ctx->priv_host);
23730 -+ if (*thd->security_ctx->priv_host != 0)
23731 -+ {
23732 -+ user->host.str= (char *) thd->security_ctx->priv_host;
23733 -+ user->host.length= strlen(thd->security_ctx->priv_host);
23734 -+ }
23735 -+ else
23736 -+ {
23737 -+ user->host.str= (char *)"%";
23738 -+ user->host.length= 1;
23739 -+ }
23740 -+ }
23741 -+ if (!user->user.str)
23742 -+ {
23743 -+ DBUG_ASSERT(thd->security_ctx->priv_user);
23744 -+ user->user.str= (char *) thd->security_ctx->priv_user;
23745 -+ user->user.length= strlen(thd->security_ctx->priv_user);
23746 -+ }
23747 -+ /* Returns 1 as the function sends error to client */
23748 -+ return check_change_password(thd, user->host.str, user->user.str,
23749 -+ password, strlen(password)) ? 1 : 0;
23750 -+#else
23751 -+ return 0;
23752 -+#endif
23753 -+}
23754 -+
23755 -+int set_var_password::update(THD *thd)
23756 -+{
23757 -+#ifndef NO_EMBEDDED_ACCESS_CHECKS
23758 -+ /* Returns 1 as the function sends error to client */
23759 -+ return change_password(thd, user->host.str, user->user.str, password) ?
23760 -+ 1 : 0;
23761 -+#else
23762 -+ return 0;
23763 -+#endif
23764 -+}
23765 -+
23766 -+/****************************************************************************
23767 -+ Functions to handle table_type
23768 -+****************************************************************************/
23769 -+
23770 -+/* Based upon sys_var::check_enum() */
23771 -+
23772 -+bool sys_var_thd_storage_engine::check(THD *thd, set_var *var)
23773 -+{
23774 -+ char buff[STRING_BUFFER_USUAL_SIZE];
23775 -+ const char *value;
23776 -+ String str(buff, sizeof(buff), &my_charset_latin1), *res;
23777 -+
23778 -+ var->save_result.plugin= NULL;
23779 -+ if (var->value->result_type() == STRING_RESULT)
23780 -+ {
23781 -+ LEX_STRING engine_name;
23782 -+ handlerton *hton;
23783 -+ if (!(res=var->value->val_str(&str)) ||
23784 -+ !(engine_name.str= (char *)res->ptr()) ||
23785 -+ !(engine_name.length= res->length()) ||
23786 -+ !(var->save_result.plugin= ha_resolve_by_name(thd, &engine_name)) ||
23787 -+ !(hton= plugin_data(var->save_result.plugin, handlerton *)) ||
23788 -+ ha_checktype(thd, ha_legacy_type(hton), 1, 0) != hton)
23789 -+ {
23790 -+ value= res ? res->c_ptr() : "NULL";
23791 -+ goto err;
23792 -+ }
23793 -+ return 0;
23794 -+ }
23795 -+ value= "unknown";
23796 -+
23797 -+err:
23798 -+ my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), value);
23799 -+ return 1;
23800 -+}
23801 -+
23802 -+
23803 -+uchar *sys_var_thd_storage_engine::value_ptr(THD *thd, enum_var_type type,
23804 -+ LEX_STRING *base)
23805 -+{
23806 -+ uchar* result;
23807 -+ handlerton *hton;
23808 -+ LEX_STRING *engine_name;
23809 -+ plugin_ref plugin= thd->variables.*offset;
23810 -+ if (type == OPT_GLOBAL)
23811 -+ plugin= my_plugin_lock(thd, &(global_system_variables.*offset));
23812 -+ hton= plugin_data(plugin, handlerton*);
23813 -+ engine_name= &hton2plugin[hton->slot]->name;
23814 -+ result= (uchar *) thd->strmake(engine_name->str, engine_name->length);
23815 -+ if (type == OPT_GLOBAL)
23816 -+ plugin_unlock(thd, plugin);
23817 -+ return result;
23818 -+}
23819 -+
23820 -+
23821 -+void sys_var_thd_storage_engine::set_default(THD *thd, enum_var_type type)
23822 -+{
23823 -+ plugin_ref old_value, new_value, *value;
23824 -+ if (type == OPT_GLOBAL)
23825 -+ {
23826 -+ value= &(global_system_variables.*offset);
23827 -+ new_value= ha_lock_engine(NULL, myisam_hton);
23828 -+ }
23829 -+ else
23830 -+ {
23831 -+ value= &(thd->variables.*offset);
23832 -+ new_value= my_plugin_lock(NULL, &(global_system_variables.*offset));
23833 -+ }
23834 -+ DBUG_ASSERT(new_value);
23835 -+ old_value= *value;
23836 -+ *value= new_value;
23837 -+ plugin_unlock(NULL, old_value);
23838 -+}
23839 -+
23840 -+
23841 -+bool sys_var_thd_storage_engine::update(THD *thd, set_var *var)
23842 -+{
23843 -+ plugin_ref *value= &(global_system_variables.*offset), old_value;
23844 -+ if (var->type != OPT_GLOBAL)
23845 -+ value= &(thd->variables.*offset);
23846 -+ old_value= *value;
23847 -+ if (old_value != var->save_result.plugin)
23848 -+ {
23849 -+ *value= my_plugin_lock(NULL, &var->save_result.plugin);
23850 -+ plugin_unlock(NULL, old_value);
23851 -+ }
23852 -+ return 0;
23853 -+}
23854 -+
23855 -+void sys_var_thd_table_type::warn_deprecated(THD *thd)
23856 -+{
23857 -+ WARN_DEPRECATED(thd, "6.0", "@@table_type", "'@@storage_engine'");
23858 -+}
23859 -+
23860 -+void sys_var_thd_table_type::set_default(THD *thd, enum_var_type type)
23861 -+{
23862 -+ warn_deprecated(thd);
23863 -+ sys_var_thd_storage_engine::set_default(thd, type);
23864 -+}
23865 -+
23866 -+bool sys_var_thd_table_type::update(THD *thd, set_var *var)
23867 -+{
23868 -+ warn_deprecated(thd);
23869 -+ return sys_var_thd_storage_engine::update(thd, var);
23870 -+}
23871 -+
23872 -+
23873 -+/****************************************************************************
23874 -+ Functions to handle sql_mode
23875 -+****************************************************************************/
23876 -+
23877 -+/**
23878 -+ Make string representation of mode.
23879 -+
23880 -+ @param[in] thd thread handler
23881 -+ @param[in] val sql_mode value
23882 -+ @param[out] len pointer on length of string
23883 -+
23884 -+ @return
23885 -+ pointer to string with sql_mode representation
23886 -+*/
23887 -+
23888 -+bool
23889 -+sys_var_thd_sql_mode::
23890 -+symbolic_mode_representation(THD *thd, ulonglong val, LEX_STRING *rep)
23891 -+{
23892 -+ char buff[STRING_BUFFER_USUAL_SIZE*8];
23893 -+ String tmp(buff, sizeof(buff), &my_charset_latin1);
23894 -+
23895 -+ tmp.length(0);
23896 -+
23897 -+ for (uint i= 0; val; val>>= 1, i++)
23898 -+ {
23899 -+ if (val & 1)
23900 -+ {
23901 -+ tmp.append(sql_mode_typelib.type_names[i],
23902 -+ sql_mode_typelib.type_lengths[i]);
23903 -+ tmp.append(',');
23904 -+ }
23905 -+ }
23906 -+
23907 -+ if (tmp.length())
23908 -+ tmp.length(tmp.length() - 1); /* trim the trailing comma */
23909 -+
23910 -+ rep->str= thd->strmake(tmp.ptr(), tmp.length());
23911 -+
23912 -+ rep->length= rep->str ? tmp.length() : 0;
23913 -+
23914 -+ return rep->length != tmp.length();
23915 -+}
23916 -+
23917 -+
23918 -+uchar *sys_var_thd_sql_mode::value_ptr(THD *thd, enum_var_type type,
23919 -+ LEX_STRING *base)
23920 -+{
23921 -+ LEX_STRING sql_mode;
23922 -+ ulonglong val= ((type == OPT_GLOBAL) ? global_system_variables.*offset :
23923 -+ thd->variables.*offset);
23924 -+ (void) symbolic_mode_representation(thd, val, &sql_mode);
23925 -+ return (uchar *) sql_mode.str;
23926 -+}
23927 -+
23928 -+
23929 -+void sys_var_thd_sql_mode::set_default(THD *thd, enum_var_type type)
23930 -+{
23931 -+ if (type == OPT_GLOBAL)
23932 -+ global_system_variables.*offset= 0;
23933 -+ else
23934 -+ thd->variables.*offset= global_system_variables.*offset;
23935 -+}
23936 -+
23937 -+
23938 -+void fix_sql_mode_var(THD *thd, enum_var_type type)
23939 -+{
23940 -+ if (type == OPT_GLOBAL)
23941 -+ global_system_variables.sql_mode=
23942 -+ fix_sql_mode(global_system_variables.sql_mode);
23943 -+ else
23944 -+ {
23945 -+ thd->variables.sql_mode= fix_sql_mode(thd->variables.sql_mode);
23946 -+ /*
23947 -+ Update thd->server_status
23948 -+ */
23949 -+ if (thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES)
23950 -+ thd->server_status|= SERVER_STATUS_NO_BACKSLASH_ESCAPES;
23951 -+ else
23952 -+ thd->server_status&= ~SERVER_STATUS_NO_BACKSLASH_ESCAPES;
23953 -+ }
23954 -+}
23955 -+
23956 -+/** Map database specific bits to function bits. */
23957 -+
23958 -+ulong fix_sql_mode(ulong sql_mode)
23959 -+{
23960 -+ /*
23961 -+ Note that we dont set
23962 -+ MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS | MODE_NO_FIELD_OPTIONS
23963 -+ to allow one to get full use of MySQL in this mode.
23964 -+ */
23965 -+
23966 -+ if (sql_mode & MODE_ANSI)
23967 -+ {
23968 -+ sql_mode|= (MODE_REAL_AS_FLOAT | MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES |
23969 -+ MODE_IGNORE_SPACE);
23970 -+ /*
23971 -+ MODE_ONLY_FULL_GROUP_BY removed from ANSI mode because it is currently
23972 -+ overly restrictive (see BUG#8510).
23973 -+ */
23974 -+ }
23975 -+ if (sql_mode & MODE_ORACLE)
23976 -+ sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES |
23977 -+ MODE_IGNORE_SPACE |
23978 -+ MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS |
23979 -+ MODE_NO_FIELD_OPTIONS | MODE_NO_AUTO_CREATE_USER);
23980 -+ if (sql_mode & MODE_MSSQL)
23981 -+ sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES |
23982 -+ MODE_IGNORE_SPACE |
23983 -+ MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS |
23984 -+ MODE_NO_FIELD_OPTIONS);
23985 -+ if (sql_mode & MODE_POSTGRESQL)
23986 -+ sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES |
23987 -+ MODE_IGNORE_SPACE |
23988 -+ MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS |
23989 -+ MODE_NO_FIELD_OPTIONS);
23990 -+ if (sql_mode & MODE_DB2)
23991 -+ sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES |
23992 -+ MODE_IGNORE_SPACE |
23993 -+ MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS |
23994 -+ MODE_NO_FIELD_OPTIONS);
23995 -+ if (sql_mode & MODE_MAXDB)
23996 -+ sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES |
23997 -+ MODE_IGNORE_SPACE |
23998 -+ MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS |
23999 -+ MODE_NO_FIELD_OPTIONS | MODE_NO_AUTO_CREATE_USER);
24000 -+ if (sql_mode & MODE_MYSQL40)
24001 -+ sql_mode|= MODE_HIGH_NOT_PRECEDENCE;
24002 -+ if (sql_mode & MODE_MYSQL323)
24003 -+ sql_mode|= MODE_HIGH_NOT_PRECEDENCE;
24004 -+ if (sql_mode & MODE_TRADITIONAL)
24005 -+ sql_mode|= (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES |
24006 -+ MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE |
24007 -+ MODE_ERROR_FOR_DIVISION_BY_ZERO | MODE_NO_AUTO_CREATE_USER);
24008 -+ return sql_mode;
24009 -+}
24010 -+
24011 -+
24012 -+bool
24013 -+sys_var_thd_optimizer_switch::
24014 -+symbolic_mode_representation(THD *thd, ulonglong val, LEX_STRING *rep)
24015 -+{
24016 -+ char buff[STRING_BUFFER_USUAL_SIZE*8];
24017 -+ String tmp(buff, sizeof(buff), &my_charset_latin1);
24018 -+ int i;
24019 -+ ulonglong bit;
24020 -+ tmp.length(0);
24021 -+
24022 -+ for (i= 0, bit=1; bit != OPTIMIZER_SWITCH_LAST; i++, bit= bit << 1)
24023 -+ {
24024 -+ tmp.append(optimizer_switch_typelib.type_names[i],
24025 -+ optimizer_switch_typelib.type_lengths[i]);
24026 -+ tmp.append('=');
24027 -+ tmp.append((val & bit)? "on":"off");
24028 -+ tmp.append(',');
24029 -+ }
24030 -+
24031 -+ if (tmp.length())
24032 -+ tmp.length(tmp.length() - 1); /* trim the trailing comma */
24033 -+
24034 -+ rep->str= thd->strmake(tmp.ptr(), tmp.length());
24035 -+
24036 -+ rep->length= rep->str ? tmp.length() : 0;
24037 -+
24038 -+ return rep->length != tmp.length();
24039 -+}
24040 -+
24041 -+
24042 -+uchar *sys_var_thd_optimizer_switch::value_ptr(THD *thd, enum_var_type type,
24043 -+ LEX_STRING *base)
24044 -+{
24045 -+ LEX_STRING opts;
24046 -+ ulonglong val= ((type == OPT_GLOBAL) ? global_system_variables.*offset :
24047 -+ thd->variables.*offset);
24048 -+ (void) symbolic_mode_representation(thd, val, &opts);
24049 -+ return (uchar *) opts.str;
24050 -+}
24051 -+
24052 -+
24053 -+/*
24054 -+ Check (and actually parse) string representation of @@optimizer_switch.
24055 -+*/
24056 -+
24057 -+bool sys_var_thd_optimizer_switch::check(THD *thd, set_var *var)
24058 -+{
24059 -+ bool not_used;
24060 -+ char buff[STRING_BUFFER_USUAL_SIZE], *error= 0;
24061 -+ uint error_len= 0;
24062 -+ String str(buff, sizeof(buff), system_charset_info), *res;
24063 -+
24064 -+ if (!(res= var->value->val_str(&str)))
24065 -+ {
24066 -+ strmov(buff, "NULL");
24067 -+ goto err;
24068 -+ }
24069 -+
24070 -+ if (res->length() == 0)
24071 -+ {
24072 -+ buff[0]= 0;
24073 -+ goto err;
24074 -+ }
24075 -+
24076 -+ var->save_result.ulong_value=
24077 -+ (ulong)find_set_from_flags(&optimizer_switch_typelib,
24078 -+ optimizer_switch_typelib.count,
24079 -+ thd->variables.optimizer_switch,
24080 -+ global_system_variables.optimizer_switch,
24081 -+ res->c_ptr_safe(), res->length(), NULL,
24082 -+ &error, &error_len, &not_used);
24083 -+ if (error_len)
24084 -+ {
24085 -+ strmake(buff, error, min(sizeof(buff) - 1, error_len));
24086 -+ goto err;
24087 -+ }
24088 -+ return FALSE;
24089 -+err:
24090 -+ my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, buff);
24091 -+ return TRUE;
24092 -+}
24093 -+
24094 -+
24095 -+void sys_var_thd_optimizer_switch::set_default(THD *thd, enum_var_type type)
24096 -+{
24097 -+ if (type == OPT_GLOBAL)
24098 -+ global_system_variables.*offset= OPTIMIZER_SWITCH_DEFAULT;
24099 -+ else
24100 -+ thd->variables.*offset= global_system_variables.*offset;
24101 -+}
24102 -+
24103 -+/****************************************************************************
24104 -+ Named list handling
24105 -+****************************************************************************/
24106 -+
24107 -+uchar* find_named(I_List<NAMED_LIST> *list, const char *name, uint length,
24108 -+ NAMED_LIST **found)
24109 -+{
24110 -+ I_List_iterator<NAMED_LIST> it(*list);
24111 -+ NAMED_LIST *element;
24112 -+ while ((element= it++))
24113 -+ {
24114 -+ if (element->cmp(name, length))
24115 -+ {
24116 -+ if (found)
24117 -+ *found= element;
24118 -+ return element->data;
24119 -+ }
24120 -+ }
24121 -+ return 0;
24122 -+}
24123 -+
24124 -+
24125 -+void delete_elements(I_List<NAMED_LIST> *list,
24126 -+ void (*free_element)(const char *name, uchar*))
24127 -+{
24128 -+ NAMED_LIST *element;
24129 -+ DBUG_ENTER("delete_elements");
24130 -+ while ((element= list->get()))
24131 -+ {
24132 -+ (*free_element)(element->name, element->data);
24133 -+ delete element;
24134 -+ }
24135 -+ DBUG_VOID_RETURN;
24136 -+}
24137 -+
24138 -+
24139 -+/* Key cache functions */
24140 -+
24141 -+static KEY_CACHE *create_key_cache(const char *name, uint length)
24142 -+{
24143 -+ KEY_CACHE *key_cache;
24144 -+ DBUG_ENTER("create_key_cache");
24145 -+ DBUG_PRINT("enter",("name: %.*s", length, name));
24146 -+
24147 -+ if ((key_cache= (KEY_CACHE*) my_malloc(sizeof(KEY_CACHE),
24148 -+ MYF(MY_ZEROFILL | MY_WME))))
24149 -+ {
24150 -+ if (!new NAMED_LIST(&key_caches, name, length, (uchar*) key_cache))
24151 -+ {
24152 -+ my_free((char*) key_cache, MYF(0));
24153 -+ key_cache= 0;
24154 -+ }
24155 -+ else
24156 -+ {
24157 -+ /*
24158 -+ Set default values for a key cache
24159 -+ The values in dflt_key_cache_var is set by my_getopt() at startup
24160 -+
24161 -+ We don't set 'buff_size' as this is used to enable the key cache
24162 -+ */
24163 -+ key_cache->param_block_size= dflt_key_cache_var.param_block_size;
24164 -+ key_cache->param_division_limit= dflt_key_cache_var.param_division_limit;
24165 -+ key_cache->param_age_threshold= dflt_key_cache_var.param_age_threshold;
24166 -+ }
24167 -+ }
24168 -+ DBUG_RETURN(key_cache);
24169 -+}
24170 -+
24171 -+
24172 -+KEY_CACHE *get_or_create_key_cache(const char *name, uint length)
24173 -+{
24174 -+ LEX_STRING key_cache_name;
24175 -+ KEY_CACHE *key_cache;
24176 -+
24177 -+ key_cache_name.str= (char *) name;
24178 -+ key_cache_name.length= length;
24179 -+ pthread_mutex_lock(&LOCK_global_system_variables);
24180 -+ if (!(key_cache= get_key_cache(&key_cache_name)))
24181 -+ key_cache= create_key_cache(name, length);
24182 -+ pthread_mutex_unlock(&LOCK_global_system_variables);
24183 -+ return key_cache;
24184 -+}
24185 -+
24186 -+
24187 -+void free_key_cache(const char *name, KEY_CACHE *key_cache)
24188 -+{
24189 -+ ha_end_key_cache(key_cache);
24190 -+ my_free((char*) key_cache, MYF(0));
24191 -+}
24192 -+
24193 -+
24194 -+bool process_key_caches(process_key_cache_t func)
24195 -+{
24196 -+ I_List_iterator<NAMED_LIST> it(key_caches);
24197 -+ NAMED_LIST *element;
24198 -+
24199 -+ while ((element= it++))
24200 -+ {
24201 -+ KEY_CACHE *key_cache= (KEY_CACHE *) element->data;
24202 -+ func(element->name, key_cache);
24203 -+ }
24204 -+ return 0;
24205 -+}
24206 -+
24207 -+
24208 -+void sys_var_trust_routine_creators::warn_deprecated(THD *thd)
24209 -+{
24210 -+ WARN_DEPRECATED(thd, VER_CELOSIA, "@@log_bin_trust_routine_creators",
24211 -+ "'@@log_bin_trust_function_creators'");
24212 -+}
24213 -+
24214 -+void sys_var_trust_routine_creators::set_default(THD *thd, enum_var_type type)
24215 -+{
24216 -+ warn_deprecated(thd);
24217 -+ sys_var_bool_ptr::set_default(thd, type);
24218 -+}
24219 -+
24220 -+bool sys_var_trust_routine_creators::update(THD *thd, set_var *var)
24221 -+{
24222 -+ warn_deprecated(thd);
24223 -+ return sys_var_bool_ptr::update(thd, var);
24224 -+}
24225 -+
24226 -+bool sys_var_opt_readonly::update(THD *thd, set_var *var)
24227 -+{
24228 -+ bool result;
24229 -+
24230 -+ DBUG_ENTER("sys_var_opt_readonly::update");
24231 -+
24232 -+ /* Prevent self dead-lock */
24233 -+ if (thd->locked_tables || thd->active_transaction())
24234 -+ {
24235 -+ my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0));
24236 -+ DBUG_RETURN(true);
24237 -+ }
24238 -+
24239 -+ if (thd->global_read_lock)
24240 -+ {
24241 -+ /*
24242 -+ This connection already holds the global read lock.
24243 -+ This can be the case with:
24244 -+ - FLUSH TABLES WITH READ LOCK
24245 -+ - SET GLOBAL READ_ONLY = 1
24246 -+ */
24247 -+ result= sys_var_bool_ptr::update(thd, var);
24248 -+ DBUG_RETURN(result);
24249 -+ }
24250 -+
24251 -+ /*
24252 -+ Perform a 'FLUSH TABLES WITH READ LOCK'.
24253 -+ This is a 3 step process:
24254 -+ - [1] lock_global_read_lock()
24255 -+ - [2] close_cached_tables()
24256 -+ - [3] make_global_read_lock_block_commit()
24257 -+ [1] prevents new connections from obtaining tables locked for write.
24258 -+ [2] waits until all existing connections close their tables.
24259 -+ [3] prevents transactions from being committed.
24260 -+ */
24261 -+
24262 -+ if (lock_global_read_lock(thd))
24263 -+ DBUG_RETURN(true);
24264 -+
24265 -+ /*
24266 -+ This call will be blocked by any connection holding a READ or WRITE lock.
24267 -+ Ideally, we want to wait only for pending WRITE locks, but since:
24268 -+ con 1> LOCK TABLE T FOR READ;
24269 -+ con 2> LOCK TABLE T FOR WRITE; (blocked by con 1)
24270 -+ con 3> SET GLOBAL READ ONLY=1; (blocked by con 2)
24271 -+ can cause to wait on a read lock, it's required for the client application
24272 -+ to unlock everything, and acceptable for the server to wait on all locks.
24273 -+ */
24274 -+ if ((result= close_cached_tables(thd, NULL, FALSE, TRUE, TRUE)))
24275 -+ goto end_with_read_lock;
24276 -+
24277 -+ if ((result= make_global_read_lock_block_commit(thd)))
24278 -+ goto end_with_read_lock;
24279 -+
24280 -+ /* Change the opt_readonly system variable, safe because the lock is held */
24281 -+ result= sys_var_bool_ptr::update(thd, var);
24282 -+
24283 -+end_with_read_lock:
24284 -+ /* Release the lock */
24285 -+ unlock_global_read_lock(thd);
24286 -+ DBUG_RETURN(result);
24287 -+}
24288 -+
24289 -+
24290 -+#ifndef DBUG_OFF
24291 -+/* even session variable here requires SUPER, because of -#o,file */
24292 -+bool sys_var_thd_dbug::check(THD *thd, set_var *var)
24293 -+{
24294 -+ return check_global_access(thd, SUPER_ACL);
24295 -+}
24296 -+
24297 -+bool sys_var_thd_dbug::update(THD *thd, set_var *var)
24298 -+{
24299 -+ char buf[256];
24300 -+ String str(buf, sizeof(buf), system_charset_info), *res;
24301 -+
24302 -+ res= var->value->val_str(&str);
24303 -+
24304 -+ if (var->type == OPT_GLOBAL)
24305 -+ DBUG_SET_INITIAL(res ? res->c_ptr() : "");
24306 -+ else
24307 -+ DBUG_SET(res ? res->c_ptr() : "");
24308 -+
24309 -+ return 0;
24310 -+}
24311 -+
24312 -+
24313 -+uchar *sys_var_thd_dbug::value_ptr(THD *thd, enum_var_type type, LEX_STRING *b)
24314 -+{
24315 -+ char buf[256];
24316 -+ if (type == OPT_GLOBAL)
24317 -+ DBUG_EXPLAIN_INITIAL(buf, sizeof(buf));
24318 -+ else
24319 -+ DBUG_EXPLAIN(buf, sizeof(buf));
24320 -+ return (uchar*) thd->strdup(buf);
24321 -+}
24322 -+#endif /* DBUG_OFF */
24323 -+
24324 -+
24325 -+#ifdef HAVE_EVENT_SCHEDULER
24326 -+bool sys_var_event_scheduler::check(THD *thd, set_var *var)
24327 -+{
24328 -+ return check_enum(thd, var, &Events::var_typelib);
24329 -+}
24330 -+
24331 -+/*
24332 -+ The update method of the global variable event_scheduler.
24333 -+ If event_scheduler is switched from 0 to 1 then the scheduler main
24334 -+ thread is resumed and if from 1 to 0 the scheduler thread is suspended
24335 -+
24336 -+ SYNOPSIS
24337 -+ sys_var_event_scheduler::update()
24338 -+ thd Thread context (unused)
24339 -+ var The new value
24340 -+
24341 -+ Returns
24342 -+ FALSE OK
24343 -+ TRUE Error
24344 -+*/
24345 -+
24346 -+bool
24347 -+sys_var_event_scheduler::update(THD *thd, set_var *var)
24348 -+{
24349 -+ int res;
24350 -+ /* here start the thread if not running. */
24351 -+ DBUG_ENTER("sys_var_event_scheduler::update");
24352 -+ DBUG_PRINT("info", ("new_value: %d", (int) var->save_result.ulong_value));
24353 -+
24354 -+ enum Events::enum_opt_event_scheduler
24355 -+ new_state=
24356 -+ (enum Events::enum_opt_event_scheduler) var->save_result.ulong_value;
24357 -+
24358 -+ res= Events::switch_event_scheduler_state(new_state);
24359 -+
24360 -+ DBUG_RETURN((bool) res);
24361 -+}
24362 -+
24363 -+
24364 -+uchar *sys_var_event_scheduler::value_ptr(THD *thd, enum_var_type type,
24365 -+ LEX_STRING *base)
24366 -+{
24367 -+ return (uchar *) Events::get_opt_event_scheduler_str();
24368 -+}
24369 -+#endif
24370 -+
24371 -+
24372 -+int
24373 -+check_max_allowed_packet(THD *thd, set_var *var)
24374 -+{
24375 -+ longlong val= var->value->val_int();
24376 -+ if (val < (longlong) global_system_variables.net_buffer_length)
24377 -+ {
24378 -+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
24379 -+ ER_UNKNOWN_ERROR,
24380 -+ "The value of 'max_allowed_packet' should be no less than "
24381 -+ "the value of 'net_buffer_length'");
24382 -+ }
24383 -+ return 0;
24384 -+}
24385 -+
24386 -+
24387 -+int
24388 -+check_net_buffer_length(THD *thd, set_var *var)
24389 -+{
24390 -+ longlong val= var->value->val_int();
24391 -+ if (val > (longlong) global_system_variables.max_allowed_packet)
24392 -+ {
24393 -+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
24394 -+ ER_UNKNOWN_ERROR,
24395 -+ "The value of 'max_allowed_packet' should be no less than "
24396 -+ "the value of 'net_buffer_length'");
24397 -+ }
24398 -+ return 0;
24399 -+}
24400 -+
24401 -+/****************************************************************************
24402 -+ Used templates
24403 -+****************************************************************************/
24404 -+
24405 -+#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
24406 -+template class List<set_var_base>;
24407 -+template class List_iterator_fast<set_var_base>;
24408 -+template class I_List_iterator<NAMED_LIST>;
24409 -+#endif
24410 diff -urN mysql-old/sql/slave.cc mysql/sql/slave.cc
24411 --- mysql-old/sql/slave.cc 2011-05-10 17:45:45.626682377 +0000
24412 +++ mysql/sql/slave.cc 2011-05-10 17:56:01.483349044 +0000
24413 @@ -26529,1325 +2180,6 @@ diff -urN mysql-old/sql/sql_connect.cc mysql/sql/sql_connect.cc
24414 HOSTNAME_LENGTH)]= 0;
24415 thd->main_security_ctx.host_or_ip= thd->main_security_ctx.host;
24416 }
24417 -diff -urN mysql-old/sql/sql_connect.cc.orig mysql/sql/sql_connect.cc.orig
24418 ---- mysql-old/sql/sql_connect.cc.orig 1969-12-31 23:00:00.000000000 -0100
24419 -+++ mysql/sql/sql_connect.cc.orig 2011-04-12 12:11:35.000000000 +0000
24420 -@@ -0,0 +1,1315 @@
24421 -+/* Copyright (C) 2007 MySQL AB
24422 -+
24423 -+ This program is free software; you can redistribute it and/or modify
24424 -+ it under the terms of the GNU General Public License as published by
24425 -+ the Free Software Foundation; version 2 of the License.
24426 -+
24427 -+ This program is distributed in the hope that it will be useful,
24428 -+ but WITHOUT ANY WARRANTY; without even the implied warranty of
24429 -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24430 -+ GNU General Public License for more details.
24431 -+
24432 -+ You should have received a copy of the GNU General Public License
24433 -+ along with this program; if not, write to the Free Software
24434 -+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
24435 -+
24436 -+
24437 -+/*
24438 -+ Functions to autenticate and handle reqests for a connection
24439 -+*/
24440 -+
24441 -+#include "mysql_priv.h"
24442 -+
24443 -+#ifdef HAVE_OPENSSL
24444 -+/*
24445 -+ Without SSL the handshake consists of one packet. This packet
24446 -+ has both client capabilites and scrambled password.
24447 -+ With SSL the handshake might consist of two packets. If the first
24448 -+ packet (client capabilities) has CLIENT_SSL flag set, we have to
24449 -+ switch to SSL and read the second packet. The scrambled password
24450 -+ is in the second packet and client_capabilites field will be ignored.
24451 -+ Maybe it is better to accept flags other than CLIENT_SSL from the
24452 -+ second packet?
24453 -+*/
24454 -+#define SSL_HANDSHAKE_SIZE 2
24455 -+#define NORMAL_HANDSHAKE_SIZE 6
24456 -+#define MIN_HANDSHAKE_SIZE 2
24457 -+#else
24458 -+#define MIN_HANDSHAKE_SIZE 6
24459 -+#endif /* HAVE_OPENSSL */
24460 -+
24461 -+#ifdef __WIN__
24462 -+extern void win_install_sigabrt_handler();
24463 -+#endif
24464 -+
24465 -+/*
24466 -+ Get structure for logging connection data for the current user
24467 -+*/
24468 -+
24469 -+#ifndef NO_EMBEDDED_ACCESS_CHECKS
24470 -+static HASH hash_user_connections;
24471 -+
24472 -+static int get_or_create_user_conn(THD *thd, const char *user,
24473 -+ const char *host,
24474 -+ USER_RESOURCES *mqh)
24475 -+{
24476 -+ int return_val= 0;
24477 -+ size_t temp_len, user_len;
24478 -+ char temp_user[USER_HOST_BUFF_SIZE];
24479 -+ struct user_conn *uc;
24480 -+
24481 -+ DBUG_ASSERT(user != 0);
24482 -+ DBUG_ASSERT(host != 0);
24483 -+
24484 -+ user_len= strlen(user);
24485 -+ temp_len= (strmov(strmov(temp_user, user)+1, host) - temp_user)+1;
24486 -+ (void) pthread_mutex_lock(&LOCK_user_conn);
24487 -+ if (!(uc = (struct user_conn *) hash_search(&hash_user_connections,
24488 -+ (uchar*) temp_user, temp_len)))
24489 -+ {
24490 -+ /* First connection for user; Create a user connection object */
24491 -+ if (!(uc= ((struct user_conn*)
24492 -+ my_malloc(sizeof(struct user_conn) + temp_len+1,
24493 -+ MYF(MY_WME)))))
24494 -+ {
24495 -+ /* MY_WME ensures an error is set in THD. */
24496 -+ return_val= 1;
24497 -+ goto end;
24498 -+ }
24499 -+ uc->user=(char*) (uc+1);
24500 -+ memcpy(uc->user,temp_user,temp_len+1);
24501 -+ uc->host= uc->user + user_len + 1;
24502 -+ uc->len= temp_len;
24503 -+ uc->connections= uc->questions= uc->updates= uc->conn_per_hour= 0;
24504 -+ uc->user_resources= *mqh;
24505 -+ uc->reset_utime= thd->thr_create_utime;
24506 -+ if (my_hash_insert(&hash_user_connections, (uchar*) uc))
24507 -+ {
24508 -+ /* The only possible error is out of memory, MY_WME sets an error. */
24509 -+ my_free((char*) uc,0);
24510 -+ return_val= 1;
24511 -+ goto end;
24512 -+ }
24513 -+ }
24514 -+ thd->user_connect=uc;
24515 -+ uc->connections++;
24516 -+end:
24517 -+ (void) pthread_mutex_unlock(&LOCK_user_conn);
24518 -+ return return_val;
24519 -+
24520 -+}
24521 -+
24522 -+
24523 -+/*
24524 -+ check if user has already too many connections
24525 -+
24526 -+ SYNOPSIS
24527 -+ check_for_max_user_connections()
24528 -+ thd Thread handle
24529 -+ uc User connect object
24530 -+
24531 -+ NOTES
24532 -+ If check fails, we decrease user connection count, which means one
24533 -+ shouldn't call decrease_user_connections() after this function.
24534 -+
24535 -+ RETURN
24536 -+ 0 ok
24537 -+ 1 error
24538 -+*/
24539 -+
24540 -+static
24541 -+int check_for_max_user_connections(THD *thd, USER_CONN *uc)
24542 -+{
24543 -+ int error=0;
24544 -+ DBUG_ENTER("check_for_max_user_connections");
24545 -+
24546 -+ (void) pthread_mutex_lock(&LOCK_user_conn);
24547 -+ if (max_user_connections && !uc->user_resources.user_conn &&
24548 -+ max_user_connections < (uint) uc->connections)
24549 -+ {
24550 -+ my_error(ER_TOO_MANY_USER_CONNECTIONS, MYF(0), uc->user);
24551 -+ error=1;
24552 -+ goto end;
24553 -+ }
24554 -+ time_out_user_resource_limits(thd, uc);
24555 -+ if (uc->user_resources.user_conn &&
24556 -+ uc->user_resources.user_conn < uc->connections)
24557 -+ {
24558 -+ my_error(ER_USER_LIMIT_REACHED, MYF(0), uc->user,
24559 -+ "max_user_connections",
24560 -+ (long) uc->user_resources.user_conn);
24561 -+ error= 1;
24562 -+ goto end;
24563 -+ }
24564 -+ if (uc->user_resources.conn_per_hour &&
24565 -+ uc->user_resources.conn_per_hour <= uc->conn_per_hour)
24566 -+ {
24567 -+ my_error(ER_USER_LIMIT_REACHED, MYF(0), uc->user,
24568 -+ "max_connections_per_hour",
24569 -+ (long) uc->user_resources.conn_per_hour);
24570 -+ error=1;
24571 -+ goto end;
24572 -+ }
24573 -+ uc->conn_per_hour++;
24574 -+
24575 -+end:
24576 -+ if (error)
24577 -+ uc->connections--; // no need for decrease_user_connections() here
24578 -+ (void) pthread_mutex_unlock(&LOCK_user_conn);
24579 -+ DBUG_RETURN(error);
24580 -+}
24581 -+
24582 -+
24583 -+/*
24584 -+ Decrease user connection count
24585 -+
24586 -+ SYNOPSIS
24587 -+ decrease_user_connections()
24588 -+ uc User connection object
24589 -+
24590 -+ NOTES
24591 -+ If there is a n user connection object for a connection
24592 -+ (which only happens if 'max_user_connections' is defined or
24593 -+ if someone has created a resource grant for a user), then
24594 -+ the connection count is always incremented on connect.
24595 -+
24596 -+ The user connect object is not freed if some users has
24597 -+ 'max connections per hour' defined as we need to be able to hold
24598 -+ count over the lifetime of the connection.
24599 -+*/
24600 -+
24601 -+void decrease_user_connections(USER_CONN *uc)
24602 -+{
24603 -+ DBUG_ENTER("decrease_user_connections");
24604 -+ (void) pthread_mutex_lock(&LOCK_user_conn);
24605 -+ DBUG_ASSERT(uc->connections);
24606 -+ if (!--uc->connections && !mqh_used)
24607 -+ {
24608 -+ /* Last connection for user; Delete it */
24609 -+ (void) hash_delete(&hash_user_connections,(uchar*) uc);
24610 -+ }
24611 -+ (void) pthread_mutex_unlock(&LOCK_user_conn);
24612 -+ DBUG_VOID_RETURN;
24613 -+}
24614 -+
24615 -+
24616 -+/*
24617 -+ Reset per-hour user resource limits when it has been more than
24618 -+ an hour since they were last checked
24619 -+
24620 -+ SYNOPSIS:
24621 -+ time_out_user_resource_limits()
24622 -+ thd Thread handler
24623 -+ uc User connection details
24624 -+
24625 -+ NOTE:
24626 -+ This assumes that the LOCK_user_conn mutex has been acquired, so it is
24627 -+ safe to test and modify members of the USER_CONN structure.
24628 -+*/
24629 -+
24630 -+void time_out_user_resource_limits(THD *thd, USER_CONN *uc)
24631 -+{
24632 -+ ulonglong check_time= thd->start_utime;
24633 -+ DBUG_ENTER("time_out_user_resource_limits");
24634 -+
24635 -+ /* If more than a hour since last check, reset resource checking */
24636 -+ if (check_time - uc->reset_utime >= LL(3600000000))
24637 -+ {
24638 -+ uc->questions=1;
24639 -+ uc->updates=0;
24640 -+ uc->conn_per_hour=0;
24641 -+ uc->reset_utime= check_time;
24642 -+ }
24643 -+
24644 -+ DBUG_VOID_RETURN;
24645 -+}
24646 -+
24647 -+/*
24648 -+ Check if maximum queries per hour limit has been reached
24649 -+ returns 0 if OK.
24650 -+*/
24651 -+
24652 -+bool check_mqh(THD *thd, uint check_command)
24653 -+{
24654 -+ bool error= 0;
24655 -+ USER_CONN *uc=thd->user_connect;
24656 -+ DBUG_ENTER("check_mqh");
24657 -+ DBUG_ASSERT(uc != 0);
24658 -+
24659 -+ (void) pthread_mutex_lock(&LOCK_user_conn);
24660 -+
24661 -+ time_out_user_resource_limits(thd, uc);
24662 -+
24663 -+ /* Check that we have not done too many questions / hour */
24664 -+ if (uc->user_resources.questions &&
24665 -+ uc->questions++ >= uc->user_resources.questions)
24666 -+ {
24667 -+ my_error(ER_USER_LIMIT_REACHED, MYF(0), uc->user, "max_questions",
24668 -+ (long) uc->user_resources.questions);
24669 -+ error=1;
24670 -+ goto end;
24671 -+ }
24672 -+ if (check_command < (uint) SQLCOM_END)
24673 -+ {
24674 -+ /* Check that we have not done too many updates / hour */
24675 -+ if (uc->user_resources.updates &&
24676 -+ (sql_command_flags[check_command] & CF_CHANGES_DATA) &&
24677 -+ uc->updates++ >= uc->user_resources.updates)
24678 -+ {
24679 -+ my_error(ER_USER_LIMIT_REACHED, MYF(0), uc->user, "max_updates",
24680 -+ (long) uc->user_resources.updates);
24681 -+ error=1;
24682 -+ goto end;
24683 -+ }
24684 -+ }
24685 -+end:
24686 -+ (void) pthread_mutex_unlock(&LOCK_user_conn);
24687 -+ DBUG_RETURN(error);
24688 -+}
24689 -+
24690 -+#endif /* NO_EMBEDDED_ACCESS_CHECKS */
24691 -+
24692 -+
24693 -+/**
24694 -+ Check if user exist and password supplied is correct.
24695 -+
24696 -+ @param thd thread handle, thd->security_ctx->{host,user,ip} are used
24697 -+ @param command originator of the check: now check_user is called
24698 -+ during connect and change user procedures; used for
24699 -+ logging.
24700 -+ @param passwd scrambled password received from client
24701 -+ @param passwd_len length of scrambled password
24702 -+ @param db database name to connect to, may be NULL
24703 -+ @param check_count TRUE if establishing a new connection. In this case
24704 -+ check that we have not exceeded the global
24705 -+ max_connections limist
24706 -+
24707 -+ @note Host, user and passwd may point to communication buffer.
24708 -+ Current implementation does not depend on that, but future changes
24709 -+ should be done with this in mind; 'thd' is INOUT, all other params
24710 -+ are 'IN'.
24711 -+
24712 -+ @retval 0 OK; thd->security_ctx->user/master_access/priv_user/db_access and
24713 -+ thd->db are updated; OK is sent to the client.
24714 -+ @retval 1 error, e.g. access denied or handshake error, not sent to
24715 -+ the client. A message is pushed into the error stack.
24716 -+*/
24717 -+
24718 -+int
24719 -+check_user(THD *thd, enum enum_server_command command,
24720 -+ const char *passwd, uint passwd_len, const char *db,
24721 -+ bool check_count)
24722 -+{
24723 -+ DBUG_ENTER("check_user");
24724 -+ LEX_STRING db_str= { (char *) db, db ? strlen(db) : 0 };
24725 -+
24726 -+ /*
24727 -+ Clear thd->db as it points to something, that will be freed when
24728 -+ connection is closed. We don't want to accidentally free a wrong
24729 -+ pointer if connect failed. Also in case of 'CHANGE USER' failure,
24730 -+ current database will be switched to 'no database selected'.
24731 -+ */
24732 -+ thd->reset_db(NULL, 0);
24733 -+
24734 -+#ifdef NO_EMBEDDED_ACCESS_CHECKS
24735 -+ thd->main_security_ctx.master_access= GLOBAL_ACLS; // Full rights
24736 -+ /* Change database if necessary */
24737 -+ if (db && db[0])
24738 -+ {
24739 -+ if (mysql_change_db(thd, &db_str, FALSE))
24740 -+ DBUG_RETURN(1);
24741 -+ }
24742 -+ my_ok(thd);
24743 -+ DBUG_RETURN(0);
24744 -+#else
24745 -+
24746 -+ my_bool opt_secure_auth_local;
24747 -+ pthread_mutex_lock(&LOCK_global_system_variables);
24748 -+ opt_secure_auth_local= opt_secure_auth;
24749 -+ pthread_mutex_unlock(&LOCK_global_system_variables);
24750 -+
24751 -+ /*
24752 -+ If the server is running in secure auth mode, short scrambles are
24753 -+ forbidden.
24754 -+ */
24755 -+ if (opt_secure_auth_local && passwd_len == SCRAMBLE_LENGTH_323)
24756 -+ {
24757 -+ my_error(ER_NOT_SUPPORTED_AUTH_MODE, MYF(0));
24758 -+ general_log_print(thd, COM_CONNECT, ER(ER_NOT_SUPPORTED_AUTH_MODE));
24759 -+ DBUG_RETURN(1);
24760 -+ }
24761 -+ if (passwd_len != 0 &&
24762 -+ passwd_len != SCRAMBLE_LENGTH &&
24763 -+ passwd_len != SCRAMBLE_LENGTH_323)
24764 -+ {
24765 -+ my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
24766 -+ DBUG_RETURN(1);
24767 -+ }
24768 -+
24769 -+ USER_RESOURCES ur;
24770 -+ int res= acl_getroot(thd, &ur, passwd, passwd_len);
24771 -+#ifndef EMBEDDED_LIBRARY
24772 -+ if (res == -1)
24773 -+ {
24774 -+ /*
24775 -+ This happens when client (new) sends password scrambled with
24776 -+ scramble(), but database holds old value (scrambled with
24777 -+ scramble_323()). Here we please client to send scrambled_password
24778 -+ in old format.
24779 -+ */
24780 -+ NET *net= &thd->net;
24781 -+ if (opt_secure_auth_local)
24782 -+ {
24783 -+ my_error(ER_SERVER_IS_IN_SECURE_AUTH_MODE, MYF(0),
24784 -+ thd->main_security_ctx.user,
24785 -+ thd->main_security_ctx.host_or_ip);
24786 -+ general_log_print(thd, COM_CONNECT, ER(ER_SERVER_IS_IN_SECURE_AUTH_MODE),
24787 -+ thd->main_security_ctx.user,
24788 -+ thd->main_security_ctx.host_or_ip);
24789 -+ DBUG_RETURN(1);
24790 -+ }
24791 -+ /* We have to read very specific packet size */
24792 -+ if (send_old_password_request(thd) ||
24793 -+ my_net_read(net) != SCRAMBLE_LENGTH_323 + 1)
24794 -+ {
24795 -+ inc_host_errors(&thd->remote.sin_addr);
24796 -+ my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
24797 -+ DBUG_RETURN(1);
24798 -+ }
24799 -+ /* Final attempt to check the user based on reply */
24800 -+ /* So as passwd is short, errcode is always >= 0 */
24801 -+ res= acl_getroot(thd, &ur, (char *) net->read_pos, SCRAMBLE_LENGTH_323);
24802 -+ }
24803 -+#endif /*EMBEDDED_LIBRARY*/
24804 -+ /* here res is always >= 0 */
24805 -+ if (res == 0)
24806 -+ {
24807 -+ if (!(thd->main_security_ctx.master_access &
24808 -+ NO_ACCESS)) // authentication is OK
24809 -+ {
24810 -+ DBUG_PRINT("info",
24811 -+ ("Capabilities: %lu packet_length: %ld Host: '%s' "
24812 -+ "Login user: '%s' Priv_user: '%s' Using password: %s "
24813 -+ "Access: %lu db: '%s'",
24814 -+ thd->client_capabilities,
24815 -+ thd->max_client_packet_length,
24816 -+ thd->main_security_ctx.host_or_ip,
24817 -+ thd->main_security_ctx.user,
24818 -+ thd->main_security_ctx.priv_user,
24819 -+ passwd_len ? "yes": "no",
24820 -+ thd->main_security_ctx.master_access,
24821 -+ (thd->db ? thd->db : "*none*")));
24822 -+
24823 -+ if (check_count)
24824 -+ {
24825 -+ pthread_mutex_lock(&LOCK_connection_count);
24826 -+ bool count_ok= connection_count <= max_connections ||
24827 -+ (thd->main_security_ctx.master_access & SUPER_ACL);
24828 -+ VOID(pthread_mutex_unlock(&LOCK_connection_count));
24829 -+
24830 -+ if (!count_ok)
24831 -+ { // too many connections
24832 -+ my_error(ER_CON_COUNT_ERROR, MYF(0));
24833 -+ DBUG_RETURN(1);
24834 -+ }
24835 -+ }
24836 -+
24837 -+ /*
24838 -+ Log the command before authentication checks, so that the user can
24839 -+ check the log for the tried login tried and also to detect
24840 -+ break-in attempts.
24841 -+ */
24842 -+ general_log_print(thd, command,
24843 -+ (thd->main_security_ctx.priv_user ==
24844 -+ thd->main_security_ctx.user ?
24845 -+ (char*) "%s@%s on %s" :
24846 -+ (char*) "%s@%s as anonymous on %s"),
24847 -+ thd->main_security_ctx.user,
24848 -+ thd->main_security_ctx.host_or_ip,
24849 -+ db ? db : (char*) "");
24850 -+
24851 -+ /*
24852 -+ This is the default access rights for the current database. It's
24853 -+ set to 0 here because we don't have an active database yet (and we
24854 -+ may not have an active database to set.
24855 -+ */
24856 -+ thd->main_security_ctx.db_access=0;
24857 -+
24858 -+ /* Don't allow user to connect if he has done too many queries */
24859 -+ if ((ur.questions || ur.updates || ur.conn_per_hour || ur.user_conn ||
24860 -+ max_user_connections) &&
24861 -+ get_or_create_user_conn(thd,
24862 -+ (opt_old_style_user_limits ? thd->main_security_ctx.user :
24863 -+ thd->main_security_ctx.priv_user),
24864 -+ (opt_old_style_user_limits ? thd->main_security_ctx.host_or_ip :
24865 -+ thd->main_security_ctx.priv_host),
24866 -+ &ur))
24867 -+ {
24868 -+ /* The error is set by get_or_create_user_conn(). */
24869 -+ DBUG_RETURN(1);
24870 -+ }
24871 -+ if (thd->user_connect &&
24872 -+ (thd->user_connect->user_resources.conn_per_hour ||
24873 -+ thd->user_connect->user_resources.user_conn ||
24874 -+ max_user_connections) &&
24875 -+ check_for_max_user_connections(thd, thd->user_connect))
24876 -+ {
24877 -+ /* The error is set in check_for_max_user_connections(). */
24878 -+ DBUG_RETURN(1);
24879 -+ }
24880 -+
24881 -+ /* Change database if necessary */
24882 -+ if (db && db[0])
24883 -+ {
24884 -+ if (mysql_change_db(thd, &db_str, FALSE))
24885 -+ {
24886 -+ /* mysql_change_db() has pushed the error message. */
24887 -+ if (thd->user_connect)
24888 -+ decrease_user_connections(thd->user_connect);
24889 -+ DBUG_RETURN(1);
24890 -+ }
24891 -+ }
24892 -+ my_ok(thd);
24893 -+ thd->password= test(passwd_len); // remember for error messages
24894 -+#ifndef EMBEDDED_LIBRARY
24895 -+ /*
24896 -+ Allow the network layer to skip big packets. Although a malicious
24897 -+ authenticated session might use this to trick the server to read
24898 -+ big packets indefinitely, this is a previously established behavior
24899 -+ that needs to be preserved as to not break backwards compatibility.
24900 -+ */
24901 -+ thd->net.skip_big_packet= TRUE;
24902 -+#endif
24903 -+ /* Ready to handle queries */
24904 -+ DBUG_RETURN(0);
24905 -+ }
24906 -+ }
24907 -+ else if (res == 2) // client gave short hash, server has long hash
24908 -+ {
24909 -+ my_error(ER_NOT_SUPPORTED_AUTH_MODE, MYF(0));
24910 -+ general_log_print(thd, COM_CONNECT, ER(ER_NOT_SUPPORTED_AUTH_MODE));
24911 -+ DBUG_RETURN(1);
24912 -+ }
24913 -+ my_error(ER_ACCESS_DENIED_ERROR, MYF(0),
24914 -+ thd->main_security_ctx.user,
24915 -+ thd->main_security_ctx.host_or_ip,
24916 -+ passwd_len ? ER(ER_YES) : ER(ER_NO));
24917 -+ general_log_print(thd, COM_CONNECT, ER(ER_ACCESS_DENIED_ERROR),
24918 -+ thd->main_security_ctx.user,
24919 -+ thd->main_security_ctx.host_or_ip,
24920 -+ passwd_len ? ER(ER_YES) : ER(ER_NO));
24921 -+ DBUG_RETURN(1);
24922 -+#endif /* NO_EMBEDDED_ACCESS_CHECKS */
24923 -+}
24924 -+
24925 -+
24926 -+/*
24927 -+ Check for maximum allowable user connections, if the mysqld server is
24928 -+ started with corresponding variable that is greater then 0.
24929 -+*/
24930 -+
24931 -+extern "C" uchar *get_key_conn(user_conn *buff, size_t *length,
24932 -+ my_bool not_used __attribute__((unused)))
24933 -+{
24934 -+ *length= buff->len;
24935 -+ return (uchar*) buff->user;
24936 -+}
24937 -+
24938 -+
24939 -+extern "C" void free_user(struct user_conn *uc)
24940 -+{
24941 -+ my_free((char*) uc,MYF(0));
24942 -+}
24943 -+
24944 -+
24945 -+void init_max_user_conn(void)
24946 -+{
24947 -+#ifndef NO_EMBEDDED_ACCESS_CHECKS
24948 -+ (void) hash_init(&hash_user_connections,system_charset_info,max_connections,
24949 -+ 0,0,
24950 -+ (hash_get_key) get_key_conn, (hash_free_key) free_user,
24951 -+ 0);
24952 -+#endif
24953 -+}
24954 -+
24955 -+
24956 -+void free_max_user_conn(void)
24957 -+{
24958 -+#ifndef NO_EMBEDDED_ACCESS_CHECKS
24959 -+ hash_free(&hash_user_connections);
24960 -+#endif /* NO_EMBEDDED_ACCESS_CHECKS */
24961 -+}
24962 -+
24963 -+
24964 -+void reset_mqh(LEX_USER *lu, bool get_them= 0)
24965 -+{
24966 -+#ifndef NO_EMBEDDED_ACCESS_CHECKS
24967 -+ (void) pthread_mutex_lock(&LOCK_user_conn);
24968 -+ if (lu) // for GRANT
24969 -+ {
24970 -+ USER_CONN *uc;
24971 -+ uint temp_len=lu->user.length+lu->host.length+2;
24972 -+ char temp_user[USER_HOST_BUFF_SIZE];
24973 -+
24974 -+ memcpy(temp_user,lu->user.str,lu->user.length);
24975 -+ memcpy(temp_user+lu->user.length+1,lu->host.str,lu->host.length);
24976 -+ temp_user[lu->user.length]='\0'; temp_user[temp_len-1]=0;
24977 -+ if ((uc = (struct user_conn *) hash_search(&hash_user_connections,
24978 -+ (uchar*) temp_user, temp_len)))
24979 -+ {
24980 -+ uc->questions=0;
24981 -+ get_mqh(temp_user,&temp_user[lu->user.length+1],uc);
24982 -+ uc->updates=0;
24983 -+ uc->conn_per_hour=0;
24984 -+ }
24985 -+ }
24986 -+ else
24987 -+ {
24988 -+ /* for FLUSH PRIVILEGES and FLUSH USER_RESOURCES */
24989 -+ for (uint idx=0;idx < hash_user_connections.records; idx++)
24990 -+ {
24991 -+ USER_CONN *uc=(struct user_conn *) hash_element(&hash_user_connections,
24992 -+ idx);
24993 -+ if (get_them)
24994 -+ get_mqh(uc->user,uc->host,uc);
24995 -+ uc->questions=0;
24996 -+ uc->updates=0;
24997 -+ uc->conn_per_hour=0;
24998 -+ }
24999 -+ }
25000 -+ (void) pthread_mutex_unlock(&LOCK_user_conn);
25001 -+#endif /* NO_EMBEDDED_ACCESS_CHECKS */
25002 -+}
25003 -+
25004 -+
25005 -+/**
25006 -+ Set thread character set variables from the given ID
25007 -+
25008 -+ @param thd thread handle
25009 -+ @param cs_number character set and collation ID
25010 -+
25011 -+ @retval 0 OK; character_set_client, collation_connection and
25012 -+ character_set_results are set to the new value,
25013 -+ or to the default global values.
25014 -+
25015 -+ @retval 1 error, e.g. the given ID is not supported by parser.
25016 -+ Corresponding SQL error is sent.
25017 -+*/
25018 -+
25019 -+bool thd_init_client_charset(THD *thd, uint cs_number)
25020 -+{
25021 -+ CHARSET_INFO *cs;
25022 -+ /*
25023 -+ Use server character set and collation if
25024 -+ - opt_character_set_client_handshake is not set
25025 -+ - client has not specified a character set
25026 -+ - client character set is the same as the servers
25027 -+ - client character set doesn't exists in server
25028 -+ */
25029 -+ if (!opt_character_set_client_handshake ||
25030 -+ !(cs= get_charset(cs_number, MYF(0))) ||
25031 -+ !my_strcasecmp(&my_charset_latin1,
25032 -+ global_system_variables.character_set_client->name,
25033 -+ cs->name))
25034 -+ {
25035 -+ thd->variables.character_set_client=
25036 -+ global_system_variables.character_set_client;
25037 -+ thd->variables.collation_connection=
25038 -+ global_system_variables.collation_connection;
25039 -+ thd->variables.character_set_results=
25040 -+ global_system_variables.character_set_results;
25041 -+ }
25042 -+ else
25043 -+ {
25044 -+ if (!is_supported_parser_charset(cs))
25045 -+ {
25046 -+ /* Disallow non-supported parser character sets: UCS2, UTF16, UTF32 */
25047 -+ my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), "character_set_client",
25048 -+ cs->csname);
25049 -+ return true;
25050 -+ }
25051 -+ thd->variables.character_set_results=
25052 -+ thd->variables.collation_connection=
25053 -+ thd->variables.character_set_client= cs;
25054 -+ }
25055 -+ return false;
25056 -+}
25057 -+
25058 -+
25059 -+/*
25060 -+ Initialize connection threads
25061 -+*/
25062 -+
25063 -+bool init_new_connection_handler_thread()
25064 -+{
25065 -+ pthread_detach_this_thread();
25066 -+#if defined(__WIN__)
25067 -+ win_install_sigabrt_handler();
25068 -+#else
25069 -+ /* Win32 calls this in pthread_create */
25070 -+ if (my_thread_init())
25071 -+ return 1;
25072 -+#endif /* __WIN__ */
25073 -+ return 0;
25074 -+}
25075 -+
25076 -+#ifndef EMBEDDED_LIBRARY
25077 -+/**
25078 -+ Get a null character terminated string from a user-supplied buffer.
25079 -+
25080 -+ @param buffer[in, out] Pointer to the buffer to be scanned.
25081 -+ @param max_bytes_available[in, out] Limit the bytes to scan.
25082 -+ @param string_length[out] The number of characters scanned not including
25083 -+ the null character.
25084 -+
25085 -+ @remark The string_length does not include the terminating null character.
25086 -+ However, after the call, the buffer is increased by string_length+1
25087 -+ bytes, beyond the null character if there still available bytes to
25088 -+ scan.
25089 -+
25090 -+ @return pointer to beginning of the string scanned.
25091 -+ @retval NULL The buffer content is malformed
25092 -+*/
25093 -+
25094 -+static
25095 -+char *get_null_terminated_string(char **buffer,
25096 -+ size_t *max_bytes_available,
25097 -+ size_t *string_length)
25098 -+{
25099 -+ char *str= (char *)memchr(*buffer, '\0', *max_bytes_available);
25100 -+
25101 -+ if (str == NULL)
25102 -+ return NULL;
25103 -+
25104 -+ *string_length= (size_t)(str - *buffer);
25105 -+ *max_bytes_available-= *string_length + 1;
25106 -+ str= *buffer;
25107 -+ *buffer += *string_length + 1;
25108 -+
25109 -+ return str;
25110 -+}
25111 -+
25112 -+
25113 -+/**
25114 -+ Get a length encoded string from a user-supplied buffer.
25115 -+
25116 -+ @param buffer[in, out] The buffer to scan; updates position after scan.
25117 -+ @param max_bytes_available[in, out] Limit the number of bytes to scan
25118 -+ @param string_length[out] Number of characters scanned
25119 -+
25120 -+ @remark In case the length is zero, then the total size of the string is
25121 -+ considered to be 1 byte; the size byte.
25122 -+
25123 -+ @return pointer to first byte after the header in buffer.
25124 -+ @retval NULL The buffer content is malformed
25125 -+*/
25126 -+
25127 -+static
25128 -+char *get_length_encoded_string(char **buffer,
25129 -+ size_t *max_bytes_available,
25130 -+ size_t *string_length)
25131 -+{
25132 -+ if (*max_bytes_available == 0)
25133 -+ return NULL;
25134 -+
25135 -+ /* Do double cast to prevent overflow from signed / unsigned conversion */
25136 -+ size_t str_len= (size_t)(unsigned char)**buffer;
25137 -+
25138 -+ /*
25139 -+ If the length encoded string has the length 0
25140 -+ the total size of the string is only one byte long (the size byte)
25141 -+ */
25142 -+ if (str_len == 0)
25143 -+ {
25144 -+ ++*buffer;
25145 -+ *string_length= 0;
25146 -+ /*
25147 -+ Return a pointer to the 0 character so the return value will be
25148 -+ an empty string.
25149 -+ */
25150 -+ return *buffer-1;
25151 -+ }
25152 -+
25153 -+ if (str_len >= *max_bytes_available)
25154 -+ return NULL;
25155 -+
25156 -+ char *str= *buffer+1;
25157 -+ *string_length= str_len;
25158 -+ *max_bytes_available-= *string_length + 1;
25159 -+ *buffer+= *string_length + 1;
25160 -+ return str;
25161 -+}
25162 -+
25163 -+
25164 -+/*
25165 -+ Perform handshake, authorize client and update thd ACL variables.
25166 -+
25167 -+ SYNOPSIS
25168 -+ check_connection()
25169 -+ thd thread handle
25170 -+
25171 -+ RETURN
25172 -+ 0 success, OK is sent to user, thd is updated.
25173 -+ -1 error, which is sent to user
25174 -+ > 0 error code (not sent to user)
25175 -+*/
25176 -+
25177 -+static int check_connection(THD *thd)
25178 -+{
25179 -+ uint connect_errors= 0;
25180 -+ NET *net= &thd->net;
25181 -+ ulong pkt_len= 0;
25182 -+ char *end;
25183 -+
25184 -+ DBUG_PRINT("info",
25185 -+ ("New connection received on %s", vio_description(net->vio)));
25186 -+#ifdef SIGNAL_WITH_VIO_CLOSE
25187 -+ thd->set_active_vio(net->vio);
25188 -+#endif
25189 -+
25190 -+ if (!thd->main_security_ctx.host) // If TCP/IP connection
25191 -+ {
25192 -+ char ip[30];
25193 -+
25194 -+ if (vio_peer_addr(net->vio, ip, &thd->peer_port))
25195 -+ {
25196 -+ my_error(ER_BAD_HOST_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
25197 -+ return 1;
25198 -+ }
25199 -+ if (!(thd->main_security_ctx.ip= my_strdup(ip,MYF(MY_WME))))
25200 -+ return 1; /* The error is set by my_strdup(). */
25201 -+ thd->main_security_ctx.host_or_ip= thd->main_security_ctx.ip;
25202 -+ vio_in_addr(net->vio,&thd->remote.sin_addr);
25203 -+ if (!(specialflag & SPECIAL_NO_RESOLVE))
25204 -+ {
25205 -+ vio_in_addr(net->vio,&thd->remote.sin_addr);
25206 -+ thd->main_security_ctx.host=
25207 -+ ip_to_hostname(&thd->remote.sin_addr, &connect_errors);
25208 -+ /* Cut very long hostnames to avoid possible overflows */
25209 -+ if (thd->main_security_ctx.host)
25210 -+ {
25211 -+ if (thd->main_security_ctx.host != my_localhost)
25212 -+ thd->main_security_ctx.host[min(strlen(thd->main_security_ctx.host),
25213 -+ HOSTNAME_LENGTH)]= 0;
25214 -+ thd->main_security_ctx.host_or_ip= thd->main_security_ctx.host;
25215 -+ }
25216 -+ if (connect_errors > max_connect_errors)
25217 -+ {
25218 -+ my_error(ER_HOST_IS_BLOCKED, MYF(0), thd->main_security_ctx.host_or_ip);
25219 -+ return 1;
25220 -+ }
25221 -+ }
25222 -+ DBUG_PRINT("info",("Host: %s ip: %s",
25223 -+ (thd->main_security_ctx.host ?
25224 -+ thd->main_security_ctx.host : "unknown host"),
25225 -+ (thd->main_security_ctx.ip ?
25226 -+ thd->main_security_ctx.ip : "unknown ip")));
25227 -+ if (acl_check_host(thd->main_security_ctx.host, thd->main_security_ctx.ip))
25228 -+ {
25229 -+ my_error(ER_HOST_NOT_PRIVILEGED, MYF(0),
25230 -+ thd->main_security_ctx.host_or_ip);
25231 -+ return 1;
25232 -+ }
25233 -+ }
25234 -+ else /* Hostname given means that the connection was on a socket */
25235 -+ {
25236 -+ DBUG_PRINT("info",("Host: %s", thd->main_security_ctx.host));
25237 -+ thd->main_security_ctx.host_or_ip= thd->main_security_ctx.host;
25238 -+ thd->main_security_ctx.ip= 0;
25239 -+ /* Reset sin_addr */
25240 -+ bzero((char*) &thd->remote, sizeof(thd->remote));
25241 -+ }
25242 -+ vio_keepalive(net->vio, TRUE);
25243 -+
25244 -+ ulong server_capabilites;
25245 -+ {
25246 -+ /* buff[] needs to big enough to hold the server_version variable */
25247 -+ char buff[SERVER_VERSION_LENGTH + 1 + SCRAMBLE_LENGTH + 1 + 64];
25248 -+ server_capabilites= CLIENT_BASIC_FLAGS;
25249 -+
25250 -+ if (opt_using_transactions)
25251 -+ server_capabilites|= CLIENT_TRANSACTIONS;
25252 -+#ifdef HAVE_COMPRESS
25253 -+ server_capabilites|= CLIENT_COMPRESS;
25254 -+#endif /* HAVE_COMPRESS */
25255 -+#ifdef HAVE_OPENSSL
25256 -+ if (ssl_acceptor_fd)
25257 -+ {
25258 -+ server_capabilites |= CLIENT_SSL; /* Wow, SSL is available! */
25259 -+ server_capabilites |= CLIENT_SSL_VERIFY_SERVER_CERT;
25260 -+ }
25261 -+#endif /* HAVE_OPENSSL */
25262 -+
25263 -+ end= strnmov(buff, server_version, SERVER_VERSION_LENGTH) + 1;
25264 -+ int4store((uchar*) end, thd->thread_id);
25265 -+ end+= 4;
25266 -+ /*
25267 -+ So as check_connection is the only entry point to authorization
25268 -+ procedure, scramble is set here. This gives us new scramble for
25269 -+ each handshake.
25270 -+ */
25271 -+ create_random_string(thd->scramble, SCRAMBLE_LENGTH, &thd->rand);
25272 -+ /*
25273 -+ Old clients does not understand long scrambles, but can ignore packet
25274 -+ tail: that's why first part of the scramble is placed here, and second
25275 -+ part at the end of packet.
25276 -+ */
25277 -+ end= strmake(end, thd->scramble, SCRAMBLE_LENGTH_323) + 1;
25278 -+
25279 -+ int2store(end, server_capabilites);
25280 -+ /* write server characteristics: up to 16 bytes allowed */
25281 -+ end[2]=(char) default_charset_info->number;
25282 -+ int2store(end+3, thd->server_status);
25283 -+ bzero(end+5, 13);
25284 -+ end+= 18;
25285 -+ /* write scramble tail */
25286 -+ end= strmake(end, thd->scramble + SCRAMBLE_LENGTH_323,
25287 -+ SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323) + 1;
25288 -+
25289 -+ /* At this point we write connection message and read reply */
25290 -+ if (net_write_command(net, (uchar) protocol_version, (uchar*) "", 0,
25291 -+ (uchar*) buff, (size_t) (end-buff)) ||
25292 -+ (pkt_len= my_net_read(net)) == packet_error ||
25293 -+ pkt_len < MIN_HANDSHAKE_SIZE)
25294 -+ {
25295 -+ inc_host_errors(&thd->remote.sin_addr);
25296 -+ my_error(ER_HANDSHAKE_ERROR, MYF(0),
25297 -+ thd->main_security_ctx.host_or_ip);
25298 -+ return 1;
25299 -+ }
25300 -+ }
25301 -+#ifdef _CUSTOMCONFIG_
25302 -+#include "_cust_sql_parse.h"
25303 -+#endif
25304 -+ if (connect_errors)
25305 -+ reset_host_errors(&thd->remote.sin_addr);
25306 -+ if (thd->packet.alloc(thd->variables.net_buffer_length))
25307 -+ return 1; /* The error is set by alloc(). */
25308 -+
25309 -+ thd->client_capabilities= uint2korr(net->read_pos);
25310 -+ if (thd->client_capabilities & CLIENT_PROTOCOL_41)
25311 -+ {
25312 -+ thd->client_capabilities|= ((ulong) uint2korr(net->read_pos+2)) << 16;
25313 -+ thd->max_client_packet_length= uint4korr(net->read_pos+4);
25314 -+ DBUG_PRINT("info", ("client_character_set: %d", (uint) net->read_pos[8]));
25315 -+ if (thd_init_client_charset(thd, (uint) net->read_pos[8]))
25316 -+ return 1;
25317 -+ thd->update_charset();
25318 -+ end= (char*) net->read_pos+32;
25319 -+ }
25320 -+ else
25321 -+ {
25322 -+ thd->max_client_packet_length= uint3korr(net->read_pos+2);
25323 -+ end= (char*) net->read_pos+5;
25324 -+ }
25325 -+ /*
25326 -+ Disable those bits which are not supported by the server.
25327 -+ This is a precautionary measure, if the client lies. See Bug#27944.
25328 -+ */
25329 -+ thd->client_capabilities&= server_capabilites;
25330 -+
25331 -+ if (thd->client_capabilities & CLIENT_IGNORE_SPACE)
25332 -+ thd->variables.sql_mode|= MODE_IGNORE_SPACE;
25333 -+#ifdef HAVE_OPENSSL
25334 -+ DBUG_PRINT("info", ("client capabilities: %lu", thd->client_capabilities));
25335 -+ if (thd->client_capabilities & CLIENT_SSL)
25336 -+ {
25337 -+ /* Do the SSL layering. */
25338 -+ if (!ssl_acceptor_fd)
25339 -+ {
25340 -+ inc_host_errors(&thd->remote.sin_addr);
25341 -+ my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
25342 -+ return 1;
25343 -+ }
25344 -+ DBUG_PRINT("info", ("IO layer change in progress..."));
25345 -+ if (sslaccept(ssl_acceptor_fd, net->vio, net->read_timeout))
25346 -+ {
25347 -+ DBUG_PRINT("error", ("Failed to accept new SSL connection"));
25348 -+ inc_host_errors(&thd->remote.sin_addr);
25349 -+ my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
25350 -+ return 1;
25351 -+ }
25352 -+ DBUG_PRINT("info", ("Reading user information over SSL layer"));
25353 -+ if ((pkt_len= my_net_read(net)) == packet_error ||
25354 -+ pkt_len < NORMAL_HANDSHAKE_SIZE)
25355 -+ {
25356 -+ DBUG_PRINT("error", ("Failed to read user information (pkt_len= %lu)",
25357 -+ pkt_len));
25358 -+ inc_host_errors(&thd->remote.sin_addr);
25359 -+ my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
25360 -+ return 1;
25361 -+ }
25362 -+ }
25363 -+#endif /* HAVE_OPENSSL */
25364 -+
25365 -+ if (end > (char *)net->read_pos + pkt_len)
25366 -+ {
25367 -+ inc_host_errors(&thd->remote.sin_addr);
25368 -+ my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
25369 -+ return 1;
25370 -+ }
25371 -+
25372 -+ if (thd->client_capabilities & CLIENT_INTERACTIVE)
25373 -+ thd->variables.net_wait_timeout= thd->variables.net_interactive_timeout;
25374 -+ if ((thd->client_capabilities & CLIENT_TRANSACTIONS) &&
25375 -+ opt_using_transactions)
25376 -+ net->return_status= &thd->server_status;
25377 -+
25378 -+ /*
25379 -+ In order to safely scan a head for '\0' string terminators
25380 -+ we must keep track of how many bytes remain in the allocated
25381 -+ buffer or we might read past the end of the buffer.
25382 -+ */
25383 -+ size_t bytes_remaining_in_packet= pkt_len - (end - (char *)net->read_pos);
25384 -+
25385 -+ size_t user_len;
25386 -+ char *user= get_null_terminated_string(&end, &bytes_remaining_in_packet,
25387 -+ &user_len);
25388 -+ if (user == NULL)
25389 -+ {
25390 -+ inc_host_errors(&thd->remote.sin_addr);
25391 -+ my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
25392 -+ return 1;
25393 -+ }
25394 -+
25395 -+ /*
25396 -+ Old clients send a null-terminated string as password; new clients send
25397 -+ the size (1 byte) + string (not null-terminated). Hence in case of empty
25398 -+ password both send '\0'.
25399 -+ */
25400 -+ size_t passwd_len= 0;
25401 -+ char *passwd= NULL;
25402 -+
25403 -+ if (thd->client_capabilities & CLIENT_SECURE_CONNECTION)
25404 -+ {
25405 -+ /*
25406 -+ 4.1+ password. First byte is password length.
25407 -+ */
25408 -+ passwd= get_length_encoded_string(&end, &bytes_remaining_in_packet,
25409 -+ &passwd_len);
25410 -+ }
25411 -+ else
25412 -+ {
25413 -+ /*
25414 -+ Old passwords are zero terminated strings.
25415 -+ */
25416 -+ passwd= get_null_terminated_string(&end, &bytes_remaining_in_packet,
25417 -+ &passwd_len);
25418 -+ }
25419 -+
25420 -+ if (passwd == NULL)
25421 -+ {
25422 -+ inc_host_errors(&thd->remote.sin_addr);
25423 -+ my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
25424 -+ return 1;
25425 -+ }
25426 -+
25427 -+ size_t db_len= 0;
25428 -+ char *db= NULL;
25429 -+
25430 -+ if (thd->client_capabilities & CLIENT_CONNECT_WITH_DB)
25431 -+ {
25432 -+ db= get_null_terminated_string(&end, &bytes_remaining_in_packet,
25433 -+ &db_len);
25434 -+ if (db == NULL)
25435 -+ {
25436 -+ inc_host_errors(&thd->remote.sin_addr);
25437 -+ my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
25438 -+ return 1;
25439 -+ }
25440 -+ }
25441 -+
25442 -+ char db_buff[NAME_LEN + 1]; // buffer to store db in utf8
25443 -+ char user_buff[USERNAME_LENGTH + 1]; // buffer to store user in utf8
25444 -+ uint dummy_errors;
25445 -+
25446 -+ /* Since 4.1 all database names are stored in utf8 */
25447 -+ if (db)
25448 -+ {
25449 -+ db_buff[copy_and_convert(db_buff, sizeof(db_buff)-1,
25450 -+ system_charset_info,
25451 -+ db, db_len,
25452 -+ thd->charset(), &dummy_errors)]= 0;
25453 -+ db= db_buff;
25454 -+ }
25455 -+
25456 -+ user_buff[user_len= copy_and_convert(user_buff, sizeof(user_buff)-1,
25457 -+ system_charset_info, user, user_len,
25458 -+ thd->charset(), &dummy_errors)]= '\0';
25459 -+ user= user_buff;
25460 -+
25461 -+ /* If username starts and ends in "'", chop them off */
25462 -+ if (user_len > 1 && user[0] == '\'' && user[user_len - 1] == '\'')
25463 -+ {
25464 -+ user[user_len-1]= 0;
25465 -+ user++;
25466 -+ user_len-= 2;
25467 -+ }
25468 -+
25469 -+ /*
25470 -+ Clip username to allowed length in characters (not bytes). This is
25471 -+ mostly for backward compatibility.
25472 -+ */
25473 -+ {
25474 -+ CHARSET_INFO *cs= system_charset_info;
25475 -+ int err;
25476 -+
25477 -+ user_len= (uint) cs->cset->well_formed_len(cs, user, user + user_len,
25478 -+ USERNAME_CHAR_LENGTH, &err);
25479 -+ user[user_len]= '\0';
25480 -+ }
25481 -+
25482 -+ if (thd->main_security_ctx.user)
25483 -+ x_free(thd->main_security_ctx.user);
25484 -+ if (!(thd->main_security_ctx.user= my_strdup(user, MYF(MY_WME))))
25485 -+ return 1; /* The error is set by my_strdup(). */
25486 -+ return check_user(thd, COM_CONNECT, passwd, passwd_len, db, TRUE);
25487 -+}
25488 -+
25489 -+
25490 -+/*
25491 -+ Setup thread to be used with the current thread
25492 -+
25493 -+ SYNOPSIS
25494 -+ bool setup_connection_thread_globals()
25495 -+ thd Thread/connection handler
25496 -+
25497 -+ RETURN
25498 -+ 0 ok
25499 -+ 1 Error (out of memory)
25500 -+ In this case we will close the connection and increment status
25501 -+*/
25502 -+
25503 -+bool setup_connection_thread_globals(THD *thd)
25504 -+{
25505 -+ if (thd->store_globals())
25506 -+ {
25507 -+ close_connection(thd, ER_OUT_OF_RESOURCES, 1);
25508 -+ statistic_increment(aborted_connects,&LOCK_status);
25509 -+ thread_scheduler.end_thread(thd, 0);
25510 -+ return 1; // Error
25511 -+ }
25512 -+ return 0;
25513 -+}
25514 -+
25515 -+
25516 -+/*
25517 -+ Autenticate user, with error reporting
25518 -+
25519 -+ SYNOPSIS
25520 -+ login_connection()
25521 -+ thd Thread handler
25522 -+
25523 -+ NOTES
25524 -+ Connection is not closed in case of errors
25525 -+
25526 -+ RETURN
25527 -+ 0 ok
25528 -+ 1 error
25529 -+*/
25530 -+
25531 -+
25532 -+static bool login_connection(THD *thd)
25533 -+{
25534 -+ NET *net= &thd->net;
25535 -+ int error;
25536 -+ DBUG_ENTER("login_connection");
25537 -+ DBUG_PRINT("info", ("login_connection called by thread %lu",
25538 -+ thd->thread_id));
25539 -+
25540 -+ /* Use "connect_timeout" value during connection phase */
25541 -+ my_net_set_read_timeout(net, connect_timeout);
25542 -+ my_net_set_write_timeout(net, connect_timeout);
25543 -+
25544 -+ error= check_connection(thd);
25545 -+ net_end_statement(thd);
25546 -+
25547 -+ if (error)
25548 -+ { // Wrong permissions
25549 -+#ifdef __NT__
25550 -+ if (vio_type(net->vio) == VIO_TYPE_NAMEDPIPE)
25551 -+ my_sleep(1000); /* must wait after eof() */
25552 -+#endif
25553 -+ statistic_increment(aborted_connects,&LOCK_status);
25554 -+ DBUG_RETURN(1);
25555 -+ }
25556 -+ /* Connect completed, set read/write timeouts back to default */
25557 -+ my_net_set_read_timeout(net, thd->variables.net_read_timeout);
25558 -+ my_net_set_write_timeout(net, thd->variables.net_write_timeout);
25559 -+ DBUG_RETURN(0);
25560 -+}
25561 -+
25562 -+
25563 -+/*
25564 -+ Close an established connection
25565 -+
25566 -+ NOTES
25567 -+ This mainly updates status variables
25568 -+*/
25569 -+
25570 -+static void end_connection(THD *thd)
25571 -+{
25572 -+ NET *net= &thd->net;
25573 -+ plugin_thdvar_cleanup(thd);
25574 -+ if (thd->user_connect)
25575 -+ decrease_user_connections(thd->user_connect);
25576 -+
25577 -+ if (thd->killed || (net->error && net->vio != 0))
25578 -+ {
25579 -+ statistic_increment(aborted_threads,&LOCK_status);
25580 -+ }
25581 -+
25582 -+ if (net->error && net->vio != 0)
25583 -+ {
25584 -+ if (!thd->killed && thd->variables.log_warnings > 1)
25585 -+ {
25586 -+ Security_context *sctx= thd->security_ctx;
25587 -+
25588 -+ sql_print_warning(ER(ER_NEW_ABORTING_CONNECTION),
25589 -+ thd->thread_id,(thd->db ? thd->db : "unconnected"),
25590 -+ sctx->user ? sctx->user : "unauthenticated",
25591 -+ sctx->host_or_ip,
25592 -+ (thd->main_da.is_error() ? thd->main_da.message() :
25593 -+ ER(ER_UNKNOWN_ERROR)));
25594 -+ }
25595 -+ }
25596 -+}
25597 -+
25598 -+
25599 -+/*
25600 -+ Initialize THD to handle queries
25601 -+*/
25602 -+
25603 -+static void prepare_new_connection_state(THD* thd)
25604 -+{
25605 -+ Security_context *sctx= thd->security_ctx;
25606 -+
25607 -+#ifdef __NETWARE__
25608 -+ netware_reg_user(sctx->ip, sctx->user, "MySQL");
25609 -+#endif
25610 -+
25611 -+ if (thd->variables.max_join_size == HA_POS_ERROR)
25612 -+ thd->options |= OPTION_BIG_SELECTS;
25613 -+ if (thd->client_capabilities & CLIENT_COMPRESS)
25614 -+ thd->net.compress=1; // Use compression
25615 -+
25616 -+ /*
25617 -+ Much of this is duplicated in create_embedded_thd() for the
25618 -+ embedded server library.
25619 -+ TODO: refactor this to avoid code duplication there
25620 -+ */
25621 -+ thd->version= refresh_version;
25622 -+ thd->proc_info= 0;
25623 -+ thd->command= COM_SLEEP;
25624 -+ thd->set_time();
25625 -+ thd->init_for_queries();
25626 -+
25627 -+ if (sys_init_connect.value_length && !(sctx->master_access & SUPER_ACL))
25628 -+ {
25629 -+ execute_init_command(thd, &sys_init_connect, &LOCK_sys_init_connect);
25630 -+ if (thd->is_error())
25631 -+ {
25632 -+ thd->killed= THD::KILL_CONNECTION;
25633 -+ sql_print_warning(ER(ER_NEW_ABORTING_CONNECTION),
25634 -+ thd->thread_id,(thd->db ? thd->db : "unconnected"),
25635 -+ sctx->user ? sctx->user : "unauthenticated",
25636 -+ sctx->host_or_ip, "init_connect command failed");
25637 -+ sql_print_warning("%s", thd->main_da.message());
25638 -+ }
25639 -+ thd->proc_info=0;
25640 -+ thd->set_time();
25641 -+ thd->init_for_queries();
25642 -+ }
25643 -+}
25644 -+
25645 -+
25646 -+/*
25647 -+ Thread handler for a connection
25648 -+
25649 -+ SYNOPSIS
25650 -+ handle_one_connection()
25651 -+ arg Connection object (THD)
25652 -+
25653 -+ IMPLEMENTATION
25654 -+ This function (normally) does the following:
25655 -+ - Initialize thread
25656 -+ - Initialize THD to be used with this thread
25657 -+ - Authenticate user
25658 -+ - Execute all queries sent on the connection
25659 -+ - Take connection down
25660 -+ - End thread / Handle next connection using thread from thread cache
25661 -+*/
25662 -+
25663 -+pthread_handler_t handle_one_connection(void *arg)
25664 -+{
25665 -+ THD *thd= (THD*) arg;
25666 -+
25667 -+ thd->thr_create_utime= my_micro_time();
25668 -+
25669 -+ if (thread_scheduler.init_new_connection_thread())
25670 -+ {
25671 -+ close_connection(thd, ER_OUT_OF_RESOURCES, 1);
25672 -+ statistic_increment(aborted_connects,&LOCK_status);
25673 -+ thread_scheduler.end_thread(thd,0);
25674 -+ return 0;
25675 -+ }
25676 -+
25677 -+ /*
25678 -+ If a thread was created to handle this connection:
25679 -+ increment slow_launch_threads counter if it took more than
25680 -+ slow_launch_time seconds to create the thread.
25681 -+ */
25682 -+ if (thd->prior_thr_create_utime)
25683 -+ {
25684 -+ ulong launch_time= (ulong) (thd->thr_create_utime -
25685 -+ thd->prior_thr_create_utime);
25686 -+ if (launch_time >= slow_launch_time*1000000L)
25687 -+ statistic_increment(slow_launch_threads, &LOCK_status);
25688 -+ thd->prior_thr_create_utime= 0;
25689 -+ }
25690 -+
25691 -+ /*
25692 -+ handle_one_connection() is normally the only way a thread would
25693 -+ start and would always be on the very high end of the stack ,
25694 -+ therefore, the thread stack always starts at the address of the
25695 -+ first local variable of handle_one_connection, which is thd. We
25696 -+ need to know the start of the stack so that we could check for
25697 -+ stack overruns.
25698 -+ */
25699 -+ thd->thread_stack= (char*) &thd;
25700 -+ if (setup_connection_thread_globals(thd))
25701 -+ return 0;
25702 -+
25703 -+ for (;;)
25704 -+ {
25705 -+ NET *net= &thd->net;
25706 -+
25707 -+ lex_start(thd);
25708 -+ if (login_connection(thd))
25709 -+ goto end_thread;
25710 -+
25711 -+ prepare_new_connection_state(thd);
25712 -+
25713 -+ while (!net->error && net->vio != 0 &&
25714 -+ !(thd->killed == THD::KILL_CONNECTION))
25715 -+ {
25716 -+ if (do_command(thd))
25717 -+ break;
25718 -+ }
25719 -+ end_connection(thd);
25720 -+
25721 -+end_thread:
25722 -+ close_connection(thd, 0, 1);
25723 -+ if (thread_scheduler.end_thread(thd,1))
25724 -+ return 0; // Probably no-threads
25725 -+
25726 -+ /*
25727 -+ If end_thread() returns, we are either running with
25728 -+ thread-handler=no-threads or this thread has been schedule to
25729 -+ handle the next connection.
25730 -+ */
25731 -+ thd= current_thd;
25732 -+ thd->thread_stack= (char*) &thd;
25733 -+ }
25734 -+}
25735 -+#endif /* EMBEDDED_LIBRARY */
25736 diff -urN mysql-old/sql/sql_load.cc mysql/sql/sql_load.cc
25737 --- mysql-old/sql/sql_load.cc 2011-05-10 17:45:45.626682377 +0000
25738 +++ mysql/sql/sql_load.cc 2011-05-10 17:56:01.503349042 +0000
25739 @@ -27881,8007 +2213,6 @@ diff -urN mysql-old/sql/sql_parse.cc mysql/sql/sql_parse.cc
25740 my_error(ER_CANT_USE_OPTION_HERE, MYF(0), command);
25741 return 1;
25742 }
25743 -diff -urN mysql-old/sql/sql_parse.cc.orig mysql/sql/sql_parse.cc.orig
25744 ---- mysql-old/sql/sql_parse.cc.orig 1969-12-31 23:00:00.000000000 -0100
25745 -+++ mysql/sql/sql_parse.cc.orig 2011-04-12 12:11:38.000000000 +0000
25746 -@@ -0,0 +1,7997 @@
25747 -+/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
25748 -+
25749 -+ This program is free software; you can redistribute it and/or modify
25750 -+ it under the terms of the GNU General Public License as published by
25751 -+ the Free Software Foundation; version 2 of the License.
25752 -+
25753 -+ This program is distributed in the hope that it will be useful,
25754 -+ but WITHOUT ANY WARRANTY; without even the implied warranty of
25755 -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25756 -+ GNU General Public License for more details.
25757 -+
25758 -+ You should have received a copy of the GNU General Public License
25759 -+ along with this program; if not, write to the Free Software
25760 -+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
25761 -+
25762 -+#define MYSQL_LEX 1
25763 -+#include "mysql_priv.h"
25764 -+#include "sql_repl.h"
25765 -+#include "rpl_filter.h"
25766 -+#include "repl_failsafe.h"
25767 -+#include <m_ctype.h>
25768 -+#include <myisam.h>
25769 -+#include <my_dir.h>
25770 -+
25771 -+#include "sp_head.h"
25772 -+#include "sp.h"
25773 -+#include "sp_cache.h"
25774 -+#include "events.h"
25775 -+#include "sql_trigger.h"
25776 -+#include "debug_sync.h"
25777 -+
25778 -+/**
25779 -+ @defgroup Runtime_Environment Runtime Environment
25780 -+ @{
25781 -+*/
25782 -+
25783 -+/* Used in error handling only */
25784 -+#define SP_TYPE_STRING(LP) \
25785 -+ ((LP)->sphead->m_type == TYPE_ENUM_FUNCTION ? "FUNCTION" : "PROCEDURE")
25786 -+#define SP_COM_STRING(LP) \
25787 -+ ((LP)->sql_command == SQLCOM_CREATE_SPFUNCTION || \
25788 -+ (LP)->sql_command == SQLCOM_ALTER_FUNCTION || \
25789 -+ (LP)->sql_command == SQLCOM_SHOW_CREATE_FUNC || \
25790 -+ (LP)->sql_command == SQLCOM_DROP_FUNCTION ? \
25791 -+ "FUNCTION" : "PROCEDURE")
25792 -+
25793 -+static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables);
25794 -+static bool check_show_create_table_access(THD *thd, TABLE_LIST *table);
25795 -+
25796 -+const char *any_db="*any*"; // Special symbol for check_access
25797 -+
25798 -+const LEX_STRING command_name[]={
25799 -+ { C_STRING_WITH_LEN("Sleep") },
25800 -+ { C_STRING_WITH_LEN("Quit") },
25801 -+ { C_STRING_WITH_LEN("Init DB") },
25802 -+ { C_STRING_WITH_LEN("Query") },
25803 -+ { C_STRING_WITH_LEN("Field List") },
25804 -+ { C_STRING_WITH_LEN("Create DB") },
25805 -+ { C_STRING_WITH_LEN("Drop DB") },
25806 -+ { C_STRING_WITH_LEN("Refresh") },
25807 -+ { C_STRING_WITH_LEN("Shutdown") },
25808 -+ { C_STRING_WITH_LEN("Statistics") },
25809 -+ { C_STRING_WITH_LEN("Processlist") },
25810 -+ { C_STRING_WITH_LEN("Connect") },
25811 -+ { C_STRING_WITH_LEN("Kill") },
25812 -+ { C_STRING_WITH_LEN("Debug") },
25813 -+ { C_STRING_WITH_LEN("Ping") },
25814 -+ { C_STRING_WITH_LEN("Time") },
25815 -+ { C_STRING_WITH_LEN("Delayed insert") },
25816 -+ { C_STRING_WITH_LEN("Change user") },
25817 -+ { C_STRING_WITH_LEN("Binlog Dump") },
25818 -+ { C_STRING_WITH_LEN("Table Dump") },
25819 -+ { C_STRING_WITH_LEN("Connect Out") },
25820 -+ { C_STRING_WITH_LEN("Register Slave") },
25821 -+ { C_STRING_WITH_LEN("Prepare") },
25822 -+ { C_STRING_WITH_LEN("Execute") },
25823 -+ { C_STRING_WITH_LEN("Long Data") },
25824 -+ { C_STRING_WITH_LEN("Close stmt") },
25825 -+ { C_STRING_WITH_LEN("Reset stmt") },
25826 -+ { C_STRING_WITH_LEN("Set option") },
25827 -+ { C_STRING_WITH_LEN("Fetch") },
25828 -+ { C_STRING_WITH_LEN("Daemon") },
25829 -+ { C_STRING_WITH_LEN("Error") } // Last command number
25830 -+};
25831 -+
25832 -+const char *xa_state_names[]={
25833 -+ "NON-EXISTING", "ACTIVE", "IDLE", "PREPARED", "ROLLBACK ONLY"
25834 -+};
25835 -+
25836 -+/**
25837 -+ Mark a XA transaction as rollback-only if the RM unilaterally
25838 -+ rolled back the transaction branch.
25839 -+
25840 -+ @note If a rollback was requested by the RM, this function sets
25841 -+ the appropriate rollback error code and transits the state
25842 -+ to XA_ROLLBACK_ONLY.
25843 -+
25844 -+ @return TRUE if transaction was rolled back or if the transaction
25845 -+ state is XA_ROLLBACK_ONLY. FALSE otherwise.
25846 -+*/
25847 -+static bool xa_trans_rolled_back(XID_STATE *xid_state)
25848 -+{
25849 -+ if (xid_state->rm_error)
25850 -+ {
25851 -+ switch (xid_state->rm_error) {
25852 -+ case ER_LOCK_WAIT_TIMEOUT:
25853 -+ my_error(ER_XA_RBTIMEOUT, MYF(0));
25854 -+ break;
25855 -+ case ER_LOCK_DEADLOCK:
25856 -+ my_error(ER_XA_RBDEADLOCK, MYF(0));
25857 -+ break;
25858 -+ default:
25859 -+ my_error(ER_XA_RBROLLBACK, MYF(0));
25860 -+ }
25861 -+ xid_state->xa_state= XA_ROLLBACK_ONLY;
25862 -+ }
25863 -+
25864 -+ return (xid_state->xa_state == XA_ROLLBACK_ONLY);
25865 -+}
25866 -+
25867 -+/**
25868 -+ Rollback work done on behalf of at ransaction branch.
25869 -+*/
25870 -+static bool xa_trans_rollback(THD *thd)
25871 -+{
25872 -+ /*
25873 -+ Resource Manager error is meaningless at this point, as we perform
25874 -+ explicit rollback request by user. We must reset rm_error before
25875 -+ calling ha_rollback(), so thd->transaction.xid structure gets reset
25876 -+ by ha_rollback()/THD::transaction::cleanup().
25877 -+ */
25878 -+ thd->transaction.xid_state.rm_error= 0;
25879 -+
25880 -+ bool status= test(ha_rollback(thd));
25881 -+
25882 -+ thd->options&= ~(ulong) OPTION_BEGIN;
25883 -+ thd->transaction.all.modified_non_trans_table= FALSE;
25884 -+ thd->server_status&= ~SERVER_STATUS_IN_TRANS;
25885 -+ xid_cache_delete(&thd->transaction.xid_state);
25886 -+ thd->transaction.xid_state.xa_state= XA_NOTR;
25887 -+
25888 -+ return status;
25889 -+}
25890 -+
25891 -+static void unlock_locked_tables(THD *thd)
25892 -+{
25893 -+ if (thd->locked_tables)
25894 -+ {
25895 -+ thd->lock=thd->locked_tables;
25896 -+ thd->locked_tables=0; // Will be automatically closed
25897 -+ close_thread_tables(thd); // Free tables
25898 -+ }
25899 -+}
25900 -+
25901 -+
25902 -+bool end_active_trans(THD *thd)
25903 -+{
25904 -+ int error=0;
25905 -+ DBUG_ENTER("end_active_trans");
25906 -+ if (unlikely(thd->in_sub_stmt))
25907 -+ {
25908 -+ my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
25909 -+ DBUG_RETURN(1);
25910 -+ }
25911 -+ if (thd->transaction.xid_state.xa_state != XA_NOTR)
25912 -+ {
25913 -+ my_error(ER_XAER_RMFAIL, MYF(0),
25914 -+ xa_state_names[thd->transaction.xid_state.xa_state]);
25915 -+ DBUG_RETURN(1);
25916 -+ }
25917 -+ if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN |
25918 -+ OPTION_TABLE_LOCK))
25919 -+ {
25920 -+ DBUG_PRINT("info",("options: 0x%llx", thd->options));
25921 -+ /* Safety if one did "drop table" on locked tables */
25922 -+ if (!thd->locked_tables)
25923 -+ thd->options&= ~OPTION_TABLE_LOCK;
25924 -+ thd->server_status&= ~SERVER_STATUS_IN_TRANS;
25925 -+ if (ha_commit(thd))
25926 -+ error=1;
25927 -+ }
25928 -+ thd->options&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
25929 -+ thd->transaction.all.modified_non_trans_table= FALSE;
25930 -+ DBUG_RETURN(error);
25931 -+}
25932 -+
25933 -+
25934 -+bool begin_trans(THD *thd)
25935 -+{
25936 -+ int error=0;
25937 -+ if (unlikely(thd->in_sub_stmt))
25938 -+ {
25939 -+ my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
25940 -+ return 1;
25941 -+ }
25942 -+ if (thd->locked_tables)
25943 -+ {
25944 -+ thd->lock=thd->locked_tables;
25945 -+ thd->locked_tables=0; // Will be automatically closed
25946 -+ close_thread_tables(thd); // Free tables
25947 -+ }
25948 -+ if (end_active_trans(thd))
25949 -+ error= -1;
25950 -+ else
25951 -+ {
25952 -+ thd->options|= OPTION_BEGIN;
25953 -+ thd->server_status|= SERVER_STATUS_IN_TRANS;
25954 -+ }
25955 -+ return error;
25956 -+}
25957 -+
25958 -+#ifdef HAVE_REPLICATION
25959 -+/**
25960 -+ Returns true if all tables should be ignored.
25961 -+*/
25962 -+inline bool all_tables_not_ok(THD *thd, TABLE_LIST *tables)
25963 -+{
25964 -+ return rpl_filter->is_on() && tables && !thd->spcont &&
25965 -+ !rpl_filter->tables_ok(thd->db, tables);
25966 -+}
25967 -+#endif
25968 -+
25969 -+
25970 -+static bool some_non_temp_table_to_be_updated(THD *thd, TABLE_LIST *tables)
25971 -+{
25972 -+ for (TABLE_LIST *table= tables; table; table= table->next_global)
25973 -+ {
25974 -+ DBUG_ASSERT(table->db && table->table_name);
25975 -+ if (table->updating &&
25976 -+ !find_temporary_table(thd, table->db, table->table_name))
25977 -+ return 1;
25978 -+ }
25979 -+ return 0;
25980 -+}
25981 -+
25982 -+
25983 -+/**
25984 -+ Mark all commands that somehow changes a table.
25985 -+
25986 -+ This is used to check number of updates / hour.
25987 -+
25988 -+ sql_command is actually set to SQLCOM_END sometimes
25989 -+ so we need the +1 to include it in the array.
25990 -+
25991 -+ See COMMAND_FLAG_xxx for different type of commands
25992 -+ 2 - query that returns meaningful ROW_COUNT() -
25993 -+ a number of modified rows
25994 -+*/
25995 -+
25996 -+uint sql_command_flags[SQLCOM_END+1];
25997 -+
25998 -+void init_update_queries(void)
25999 -+{
26000 -+ bzero((uchar*) &sql_command_flags, sizeof(sql_command_flags));
26001 -+
26002 -+ sql_command_flags[SQLCOM_CREATE_TABLE]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE;
26003 -+ sql_command_flags[SQLCOM_CREATE_INDEX]= CF_CHANGES_DATA;
26004 -+ sql_command_flags[SQLCOM_ALTER_TABLE]= CF_CHANGES_DATA | CF_WRITE_LOGS_COMMAND;
26005 -+ sql_command_flags[SQLCOM_TRUNCATE]= CF_CHANGES_DATA | CF_WRITE_LOGS_COMMAND;
26006 -+ sql_command_flags[SQLCOM_DROP_TABLE]= CF_CHANGES_DATA;
26007 -+ sql_command_flags[SQLCOM_LOAD]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE;
26008 -+ sql_command_flags[SQLCOM_CREATE_DB]= CF_CHANGES_DATA;
26009 -+ sql_command_flags[SQLCOM_DROP_DB]= CF_CHANGES_DATA;
26010 -+ sql_command_flags[SQLCOM_RENAME_TABLE]= CF_CHANGES_DATA;
26011 -+ sql_command_flags[SQLCOM_BACKUP_TABLE]= CF_CHANGES_DATA;
26012 -+ sql_command_flags[SQLCOM_RESTORE_TABLE]= CF_CHANGES_DATA;
26013 -+ sql_command_flags[SQLCOM_DROP_INDEX]= CF_CHANGES_DATA;
26014 -+ sql_command_flags[SQLCOM_CREATE_VIEW]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE;
26015 -+ sql_command_flags[SQLCOM_DROP_VIEW]= CF_CHANGES_DATA;
26016 -+ sql_command_flags[SQLCOM_CREATE_EVENT]= CF_CHANGES_DATA;
26017 -+ sql_command_flags[SQLCOM_ALTER_EVENT]= CF_CHANGES_DATA;
26018 -+ sql_command_flags[SQLCOM_DROP_EVENT]= CF_CHANGES_DATA;
26019 -+
26020 -+ sql_command_flags[SQLCOM_UPDATE]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT |
26021 -+ CF_REEXECUTION_FRAGILE;
26022 -+ sql_command_flags[SQLCOM_UPDATE_MULTI]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT |
26023 -+ CF_REEXECUTION_FRAGILE;
26024 -+ sql_command_flags[SQLCOM_INSERT]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT |
26025 -+ CF_REEXECUTION_FRAGILE;
26026 -+ sql_command_flags[SQLCOM_INSERT_SELECT]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT |
26027 -+ CF_REEXECUTION_FRAGILE;
26028 -+ sql_command_flags[SQLCOM_DELETE]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT |
26029 -+ CF_REEXECUTION_FRAGILE;
26030 -+ sql_command_flags[SQLCOM_DELETE_MULTI]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT |
26031 -+ CF_REEXECUTION_FRAGILE;
26032 -+ sql_command_flags[SQLCOM_REPLACE]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT |
26033 -+ CF_REEXECUTION_FRAGILE;
26034 -+ sql_command_flags[SQLCOM_REPLACE_SELECT]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT |
26035 -+ CF_REEXECUTION_FRAGILE;
26036 -+ sql_command_flags[SQLCOM_SELECT]= CF_REEXECUTION_FRAGILE;
26037 -+ sql_command_flags[SQLCOM_SET_OPTION]= CF_REEXECUTION_FRAGILE;
26038 -+ sql_command_flags[SQLCOM_DO]= CF_REEXECUTION_FRAGILE;
26039 -+
26040 -+ sql_command_flags[SQLCOM_SHOW_STATUS_PROC]= CF_STATUS_COMMAND | CF_REEXECUTION_FRAGILE;
26041 -+ sql_command_flags[SQLCOM_SHOW_STATUS]= CF_STATUS_COMMAND | CF_REEXECUTION_FRAGILE;
26042 -+ sql_command_flags[SQLCOM_SHOW_DATABASES]= CF_STATUS_COMMAND | CF_REEXECUTION_FRAGILE;
26043 -+ sql_command_flags[SQLCOM_SHOW_TRIGGERS]= CF_STATUS_COMMAND | CF_REEXECUTION_FRAGILE;
26044 -+ sql_command_flags[SQLCOM_SHOW_EVENTS]= CF_STATUS_COMMAND | CF_REEXECUTION_FRAGILE;
26045 -+ sql_command_flags[SQLCOM_SHOW_OPEN_TABLES]= CF_STATUS_COMMAND | CF_REEXECUTION_FRAGILE;
26046 -+ sql_command_flags[SQLCOM_SHOW_PLUGINS]= CF_STATUS_COMMAND;
26047 -+ sql_command_flags[SQLCOM_SHOW_FIELDS]= CF_STATUS_COMMAND | CF_REEXECUTION_FRAGILE;
26048 -+ sql_command_flags[SQLCOM_SHOW_KEYS]= CF_STATUS_COMMAND | CF_REEXECUTION_FRAGILE;
26049 -+ sql_command_flags[SQLCOM_SHOW_VARIABLES]= CF_STATUS_COMMAND | CF_REEXECUTION_FRAGILE;
26050 -+ sql_command_flags[SQLCOM_SHOW_CHARSETS]= CF_STATUS_COMMAND | CF_REEXECUTION_FRAGILE;
26051 -+ sql_command_flags[SQLCOM_SHOW_COLLATIONS]= CF_STATUS_COMMAND | CF_REEXECUTION_FRAGILE;
26052 -+ sql_command_flags[SQLCOM_SHOW_NEW_MASTER]= CF_STATUS_COMMAND;
26053 -+ sql_command_flags[SQLCOM_SHOW_BINLOGS]= CF_STATUS_COMMAND;
26054 -+ sql_command_flags[SQLCOM_SHOW_SLAVE_HOSTS]= CF_STATUS_COMMAND;
26055 -+ sql_command_flags[SQLCOM_SHOW_BINLOG_EVENTS]= CF_STATUS_COMMAND;
26056 -+ sql_command_flags[SQLCOM_SHOW_COLUMN_TYPES]= CF_STATUS_COMMAND;
26057 -+ sql_command_flags[SQLCOM_SHOW_STORAGE_ENGINES]= CF_STATUS_COMMAND;
26058 -+ sql_command_flags[SQLCOM_SHOW_AUTHORS]= CF_STATUS_COMMAND;
26059 -+ sql_command_flags[SQLCOM_SHOW_CONTRIBUTORS]= CF_STATUS_COMMAND;
26060 -+ sql_command_flags[SQLCOM_SHOW_PRIVILEGES]= CF_STATUS_COMMAND;
26061 -+ sql_command_flags[SQLCOM_SHOW_WARNS]= CF_STATUS_COMMAND;
26062 -+ sql_command_flags[SQLCOM_SHOW_ERRORS]= CF_STATUS_COMMAND;
26063 -+ sql_command_flags[SQLCOM_SHOW_ENGINE_STATUS]= CF_STATUS_COMMAND;
26064 -+ sql_command_flags[SQLCOM_SHOW_ENGINE_MUTEX]= CF_STATUS_COMMAND;
26065 -+ sql_command_flags[SQLCOM_SHOW_ENGINE_LOGS]= CF_STATUS_COMMAND;
26066 -+ sql_command_flags[SQLCOM_SHOW_PROCESSLIST]= CF_STATUS_COMMAND;
26067 -+ sql_command_flags[SQLCOM_SHOW_GRANTS]= CF_STATUS_COMMAND;
26068 -+ sql_command_flags[SQLCOM_SHOW_CREATE_DB]= CF_STATUS_COMMAND;
26069 -+ sql_command_flags[SQLCOM_SHOW_CREATE]= CF_STATUS_COMMAND;
26070 -+ sql_command_flags[SQLCOM_SHOW_MASTER_STAT]= CF_STATUS_COMMAND;
26071 -+ sql_command_flags[SQLCOM_SHOW_SLAVE_STAT]= CF_STATUS_COMMAND;
26072 -+ sql_command_flags[SQLCOM_SHOW_CREATE_PROC]= CF_STATUS_COMMAND;
26073 -+ sql_command_flags[SQLCOM_SHOW_CREATE_FUNC]= CF_STATUS_COMMAND;
26074 -+ sql_command_flags[SQLCOM_SHOW_CREATE_TRIGGER]= CF_STATUS_COMMAND;
26075 -+ sql_command_flags[SQLCOM_SHOW_STATUS_FUNC]= CF_STATUS_COMMAND | CF_REEXECUTION_FRAGILE;
26076 -+ sql_command_flags[SQLCOM_SHOW_PROC_CODE]= CF_STATUS_COMMAND;
26077 -+ sql_command_flags[SQLCOM_SHOW_FUNC_CODE]= CF_STATUS_COMMAND;
26078 -+ sql_command_flags[SQLCOM_SHOW_CREATE_EVENT]= CF_STATUS_COMMAND;
26079 -+ sql_command_flags[SQLCOM_SHOW_PROFILES]= CF_STATUS_COMMAND;
26080 -+ sql_command_flags[SQLCOM_SHOW_PROFILE]= CF_STATUS_COMMAND;
26081 -+
26082 -+ sql_command_flags[SQLCOM_SHOW_TABLES]= (CF_STATUS_COMMAND |
26083 -+ CF_SHOW_TABLE_COMMAND |
26084 -+ CF_REEXECUTION_FRAGILE);
26085 -+ sql_command_flags[SQLCOM_SHOW_TABLE_STATUS]= (CF_STATUS_COMMAND |
26086 -+ CF_SHOW_TABLE_COMMAND |
26087 -+ CF_REEXECUTION_FRAGILE);
26088 -+
26089 -+ /*
26090 -+ The following is used to preserver CF_ROW_COUNT during the
26091 -+ a CALL or EXECUTE statement, so the value generated by the
26092 -+ last called (or executed) statement is preserved.
26093 -+ See mysql_execute_command() for how CF_ROW_COUNT is used.
26094 -+ */
26095 -+ sql_command_flags[SQLCOM_CALL]= CF_HAS_ROW_COUNT | CF_REEXECUTION_FRAGILE;
26096 -+ sql_command_flags[SQLCOM_EXECUTE]= CF_HAS_ROW_COUNT;
26097 -+
26098 -+ /*
26099 -+ The following admin table operations are allowed
26100 -+ on log tables.
26101 -+ */
26102 -+ sql_command_flags[SQLCOM_REPAIR]= CF_WRITE_LOGS_COMMAND;
26103 -+ sql_command_flags[SQLCOM_OPTIMIZE]= CF_WRITE_LOGS_COMMAND;
26104 -+ sql_command_flags[SQLCOM_ANALYZE]= CF_WRITE_LOGS_COMMAND;
26105 -+}
26106 -+
26107 -+
26108 -+bool is_update_query(enum enum_sql_command command)
26109 -+{
26110 -+ DBUG_ASSERT(command >= 0 && command <= SQLCOM_END);
26111 -+ return (sql_command_flags[command] & CF_CHANGES_DATA) != 0;
26112 -+}
26113 -+
26114 -+/**
26115 -+ Check if a sql command is allowed to write to log tables.
26116 -+ @param command The SQL command
26117 -+ @return true if writing is allowed
26118 -+*/
26119 -+bool is_log_table_write_query(enum enum_sql_command command)
26120 -+{
26121 -+ DBUG_ASSERT(command >= 0 && command <= SQLCOM_END);
26122 -+ return (sql_command_flags[command] & CF_WRITE_LOGS_COMMAND) != 0;
26123 -+}
26124 -+
26125 -+void execute_init_command(THD *thd, sys_var_str *init_command_var,
26126 -+ rw_lock_t *var_mutex)
26127 -+{
26128 -+ Vio* save_vio;
26129 -+ ulong save_client_capabilities;
26130 -+
26131 -+#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
26132 -+ thd->profiling.start_new_query();
26133 -+ thd->profiling.set_query_source(init_command_var->value,
26134 -+ init_command_var->value_length);
26135 -+#endif
26136 -+
26137 -+ thd_proc_info(thd, "Execution of init_command");
26138 -+ /*
26139 -+ We need to lock init_command_var because
26140 -+ during execution of init_command_var query
26141 -+ values of init_command_var can't be changed
26142 -+ */
26143 -+ rw_rdlock(var_mutex);
26144 -+ save_client_capabilities= thd->client_capabilities;
26145 -+ thd->client_capabilities|= CLIENT_MULTI_QUERIES;
26146 -+ /*
26147 -+ We don't need return result of execution to client side.
26148 -+ To forbid this we should set thd->net.vio to 0.
26149 -+ */
26150 -+ save_vio= thd->net.vio;
26151 -+ thd->net.vio= 0;
26152 -+ dispatch_command(COM_QUERY, thd,
26153 -+ init_command_var->value,
26154 -+ init_command_var->value_length);
26155 -+ rw_unlock(var_mutex);
26156 -+ thd->client_capabilities= save_client_capabilities;
26157 -+ thd->net.vio= save_vio;
26158 -+
26159 -+#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
26160 -+ thd->profiling.finish_current_query();
26161 -+#endif
26162 -+}
26163 -+
26164 -+
26165 -+static void handle_bootstrap_impl(THD *thd)
26166 -+{
26167 -+ FILE *file=bootstrap_file;
26168 -+ char *buff;
26169 -+ const char* found_semicolon= NULL;
26170 -+
26171 -+ DBUG_ENTER("handle_bootstrap");
26172 -+
26173 -+#ifndef EMBEDDED_LIBRARY
26174 -+ pthread_detach_this_thread();
26175 -+ thd->thread_stack= (char*) &thd;
26176 -+#endif /* EMBEDDED_LIBRARY */
26177 -+
26178 -+ if (thd->variables.max_join_size == HA_POS_ERROR)
26179 -+ thd->options |= OPTION_BIG_SELECTS;
26180 -+
26181 -+ thd_proc_info(thd, 0);
26182 -+ thd->version=refresh_version;
26183 -+ thd->security_ctx->priv_user=
26184 -+ thd->security_ctx->user= (char*) my_strdup("boot", MYF(MY_WME));
26185 -+ thd->security_ctx->priv_host[0]=0;
26186 -+ /*
26187 -+ Make the "client" handle multiple results. This is necessary
26188 -+ to enable stored procedures with SELECTs and Dynamic SQL
26189 -+ in init-file.
26190 -+ */
26191 -+ thd->client_capabilities|= CLIENT_MULTI_RESULTS;
26192 -+
26193 -+ buff= (char*) thd->net.buff;
26194 -+ thd->init_for_queries();
26195 -+ while (fgets(buff, thd->net.max_packet, file))
26196 -+ {
26197 -+ char *query, *res;
26198 -+ /* strlen() can't be deleted because fgets() doesn't return length */
26199 -+ ulong length= (ulong) strlen(buff);
26200 -+ while (buff[length-1] != '\n' && !feof(file))
26201 -+ {
26202 -+ /*
26203 -+ We got only a part of the current string. Will try to increase
26204 -+ net buffer then read the rest of the current string.
26205 -+ */
26206 -+ /* purecov: begin tested */
26207 -+ if (net_realloc(&(thd->net), 2 * thd->net.max_packet))
26208 -+ {
26209 -+ net_end_statement(thd);
26210 -+ bootstrap_error= 1;
26211 -+ break;
26212 -+ }
26213 -+ buff= (char*) thd->net.buff;
26214 -+ res= fgets(buff + length, thd->net.max_packet - length, file);
26215 -+ if (!res && !feof(file))
26216 -+ {
26217 -+ net_end_statement(thd);
26218 -+ bootstrap_error= 1;
26219 -+ break;
26220 -+ }
26221 -+ length+= (ulong) strlen(buff + length);
26222 -+ /* purecov: end */
26223 -+ }
26224 -+ if (bootstrap_error)
26225 -+ break; /* purecov: inspected */
26226 -+
26227 -+ while (length && (my_isspace(thd->charset(), buff[length-1]) ||
26228 -+ buff[length-1] == ';'))
26229 -+ length--;
26230 -+ buff[length]=0;
26231 -+
26232 -+ /* Skip lines starting with delimiter */
26233 -+ if (strncmp(buff, STRING_WITH_LEN("delimiter")) == 0)
26234 -+ continue;
26235 -+
26236 -+ query= (char *) thd->memdup_w_gap(buff, length + 1,
26237 -+ thd->db_length + 1 +
26238 -+ QUERY_CACHE_FLAGS_SIZE);
26239 -+ thd->set_query(query, length);
26240 -+ DBUG_PRINT("query",("%-.4096s", thd->query()));
26241 -+#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
26242 -+ thd->profiling.start_new_query();
26243 -+ thd->profiling.set_query_source(thd->query(), length);
26244 -+#endif
26245 -+
26246 -+ /*
26247 -+ We don't need to obtain LOCK_thread_count here because in bootstrap
26248 -+ mode we have only one thread.
26249 -+ */
26250 -+ thd->query_id=next_query_id();
26251 -+ thd->set_time();
26252 -+ mysql_parse(thd, thd->query(), length, & found_semicolon);
26253 -+ close_thread_tables(thd); // Free tables
26254 -+
26255 -+ bootstrap_error= thd->is_error();
26256 -+ net_end_statement(thd);
26257 -+
26258 -+#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
26259 -+ thd->profiling.finish_current_query();
26260 -+#endif
26261 -+
26262 -+ if (bootstrap_error)
26263 -+ break;
26264 -+
26265 -+ free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC));
26266 -+#ifdef USING_TRANSACTIONS
26267 -+ free_root(&thd->transaction.mem_root,MYF(MY_KEEP_PREALLOC));
26268 -+#endif
26269 -+ }
26270 -+
26271 -+ DBUG_VOID_RETURN;
26272 -+}
26273 -+
26274 -+
26275 -+/**
26276 -+ Execute commands from bootstrap_file.
26277 -+
26278 -+ Used when creating the initial grant tables.
26279 -+*/
26280 -+
26281 -+pthread_handler_t handle_bootstrap(void *arg)
26282 -+{
26283 -+ THD *thd=(THD*) arg;
26284 -+
26285 -+ /* The following must be called before DBUG_ENTER */
26286 -+ thd->thread_stack= (char*) &thd;
26287 -+ if (my_thread_init() || thd->store_globals())
26288 -+ {
26289 -+#ifndef EMBEDDED_LIBRARY
26290 -+ close_connection(thd, ER_OUT_OF_RESOURCES, 1);
26291 -+#endif
26292 -+ thd->fatal_error();
26293 -+ goto end;
26294 -+ }
26295 -+
26296 -+ handle_bootstrap_impl(thd);
26297 -+
26298 -+end:
26299 -+ net_end(&thd->net);
26300 -+ thd->cleanup();
26301 -+ delete thd;
26302 -+
26303 -+#ifndef EMBEDDED_LIBRARY
26304 -+ (void) pthread_mutex_lock(&LOCK_thread_count);
26305 -+ thread_count--;
26306 -+ in_bootstrap= FALSE;
26307 -+ (void) pthread_cond_broadcast(&COND_thread_count);
26308 -+ (void) pthread_mutex_unlock(&LOCK_thread_count);
26309 -+ my_thread_end();
26310 -+ pthread_exit(0);
26311 -+#endif
26312 -+
26313 -+ return 0;
26314 -+}
26315 -+
26316 -+
26317 -+/**
26318 -+ @brief Check access privs for a MERGE table and fix children lock types.
26319 -+
26320 -+ @param[in] thd thread handle
26321 -+ @param[in] db database name
26322 -+ @param[in,out] table_list list of child tables (merge_list)
26323 -+ lock_type and optionally db set per table
26324 -+
26325 -+ @return status
26326 -+ @retval 0 OK
26327 -+ @retval != 0 Error
26328 -+
26329 -+ @detail
26330 -+ This function is used for write access to MERGE tables only
26331 -+ (CREATE TABLE, ALTER TABLE ... UNION=(...)). Set TL_WRITE for
26332 -+ every child. Set 'db' for every child if not present.
26333 -+*/
26334 -+#ifndef NO_EMBEDDED_ACCESS_CHECKS
26335 -+static bool check_merge_table_access(THD *thd, char *db,
26336 -+ TABLE_LIST *table_list)
26337 -+{
26338 -+ int error= 0;
26339 -+
26340 -+ if (table_list)
26341 -+ {
26342 -+ /* Check that all tables use the current database */
26343 -+ TABLE_LIST *tlist;
26344 -+
26345 -+ for (tlist= table_list; tlist; tlist= tlist->next_local)
26346 -+ {
26347 -+ if (!tlist->db || !tlist->db[0])
26348 -+ tlist->db= db; /* purecov: inspected */
26349 -+ }
26350 -+ error= check_table_access(thd, SELECT_ACL | UPDATE_ACL | DELETE_ACL,
26351 -+ table_list, UINT_MAX, FALSE);
26352 -+ }
26353 -+ return error;
26354 -+}
26355 -+#endif
26356 -+
26357 -+/* This works because items are allocated with sql_alloc() */
26358 -+
26359 -+void free_items(Item *item)
26360 -+{
26361 -+ Item *next;
26362 -+ DBUG_ENTER("free_items");
26363 -+ for (; item ; item=next)
26364 -+ {
26365 -+ next=item->next;
26366 -+ item->delete_self();
26367 -+ }
26368 -+ DBUG_VOID_RETURN;
26369 -+}
26370 -+
26371 -+/**
26372 -+ This works because items are allocated with sql_alloc().
26373 -+ @note The function also handles null pointers (empty list).
26374 -+*/
26375 -+void cleanup_items(Item *item)
26376 -+{
26377 -+ DBUG_ENTER("cleanup_items");
26378 -+ for (; item ; item=item->next)
26379 -+ item->cleanup();
26380 -+ DBUG_VOID_RETURN;
26381 -+}
26382 -+
26383 -+/**
26384 -+ Handle COM_TABLE_DUMP command.
26385 -+
26386 -+ @param thd thread handle
26387 -+ @param db database name or an empty string. If empty,
26388 -+ the current database of the connection is used
26389 -+ @param tbl_name name of the table to dump
26390 -+
26391 -+ @note
26392 -+ This function is written to handle one specific command only.
26393 -+
26394 -+ @retval
26395 -+ 0 success
26396 -+ @retval
26397 -+ 1 error, the error message is set in THD
26398 -+*/
26399 -+
26400 -+static
26401 -+int mysql_table_dump(THD *thd, LEX_STRING *db, LEX_STRING *table_name)
26402 -+{
26403 -+ TABLE* table;
26404 -+ TABLE_LIST* table_list;
26405 -+ int error = 0;
26406 -+ DBUG_ENTER("mysql_table_dump");
26407 -+ if (db->length == 0)
26408 -+ {
26409 -+ db->str= thd->db; /* purecov: inspected */
26410 -+ db->length= thd->db_length; /* purecov: inspected */
26411 -+ }
26412 -+ if (!(table_list = (TABLE_LIST*) thd->calloc(sizeof(TABLE_LIST))))
26413 -+ DBUG_RETURN(1); // out of memory
26414 -+ table_list->db= db->str;
26415 -+ table_list->table_name= table_list->alias= table_name->str;
26416 -+ table_list->lock_type= TL_READ_NO_INSERT;
26417 -+ table_list->prev_global= &table_list; // can be removed after merge with 4.1
26418 -+
26419 -+ if (check_db_name(db))
26420 -+ {
26421 -+ /* purecov: begin inspected */
26422 -+ my_error(ER_WRONG_DB_NAME ,MYF(0), db->str ? db->str : "NULL");
26423 -+ goto err;
26424 -+ /* purecov: end */
26425 -+ }
26426 -+ if (!table_name->length ||
26427 -+ check_table_name(table_name->str, table_name->length, TRUE))
26428 -+ {
26429 -+ my_error(ER_WRONG_TABLE_NAME, MYF(0),
26430 -+ table_name->str ? table_name->str : "NULL");
26431 -+ error= 1;
26432 -+ goto err;
26433 -+ }
26434 -+ if (lower_case_table_names)
26435 -+ my_casedn_str(files_charset_info, table_name->str);
26436 -+
26437 -+ if (!(table=open_ltable(thd, table_list, TL_READ_NO_INSERT, 0)))
26438 -+ DBUG_RETURN(1);
26439 -+
26440 -+ if (check_one_table_access(thd, SELECT_ACL, table_list))
26441 -+ goto err;
26442 -+ thd->free_list = 0;
26443 -+ thd->set_query(table_name->str, table_name->length);
26444 -+ if ((error = mysqld_dump_create_info(thd, table_list, -1)))
26445 -+ {
26446 -+ my_error(ER_GET_ERRNO, MYF(0), my_errno);
26447 -+ goto err;
26448 -+ }
26449 -+ net_flush(&thd->net);
26450 -+ if ((error= table->file->dump(thd,-1)))
26451 -+ my_error(ER_GET_ERRNO, MYF(0), error);
26452 -+
26453 -+err:
26454 -+ DBUG_RETURN(error);
26455 -+}
26456 -+
26457 -+/**
26458 -+ Ends the current transaction and (maybe) begin the next.
26459 -+
26460 -+ @param thd Current thread
26461 -+ @param completion Completion type
26462 -+
26463 -+ @retval
26464 -+ 0 OK
26465 -+*/
26466 -+
26467 -+int end_trans(THD *thd, enum enum_mysql_completiontype completion)
26468 -+{
26469 -+ bool do_release= 0;
26470 -+ int res= 0;
26471 -+ DBUG_ENTER("end_trans");
26472 -+
26473 -+ if (unlikely(thd->in_sub_stmt))
26474 -+ {
26475 -+ my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
26476 -+ DBUG_RETURN(1);
26477 -+ }
26478 -+ if (thd->transaction.xid_state.xa_state != XA_NOTR)
26479 -+ {
26480 -+ my_error(ER_XAER_RMFAIL, MYF(0),
26481 -+ xa_state_names[thd->transaction.xid_state.xa_state]);
26482 -+ DBUG_RETURN(1);
26483 -+ }
26484 -+ switch (completion) {
26485 -+ case COMMIT:
26486 -+ /*
26487 -+ We don't use end_active_trans() here to ensure that this works
26488 -+ even if there is a problem with the OPTION_AUTO_COMMIT flag
26489 -+ (Which of course should never happen...)
26490 -+ */
26491 -+ thd->server_status&= ~SERVER_STATUS_IN_TRANS;
26492 -+ res= ha_commit(thd);
26493 -+ thd->options&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
26494 -+ thd->transaction.all.modified_non_trans_table= FALSE;
26495 -+ break;
26496 -+ case COMMIT_RELEASE:
26497 -+ do_release= 1; /* fall through */
26498 -+ case COMMIT_AND_CHAIN:
26499 -+ res= end_active_trans(thd);
26500 -+ if (!res && completion == COMMIT_AND_CHAIN)
26501 -+ res= begin_trans(thd);
26502 -+ break;
26503 -+ case ROLLBACK_RELEASE:
26504 -+ do_release= 1; /* fall through */
26505 -+ case ROLLBACK:
26506 -+ case ROLLBACK_AND_CHAIN:
26507 -+ {
26508 -+ thd->server_status&= ~SERVER_STATUS_IN_TRANS;
26509 -+ if (ha_rollback(thd))
26510 -+ res= -1;
26511 -+ thd->options&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
26512 -+ thd->transaction.all.modified_non_trans_table= FALSE;
26513 -+ if (!res && (completion == ROLLBACK_AND_CHAIN))
26514 -+ res= begin_trans(thd);
26515 -+ break;
26516 -+ }
26517 -+ default:
26518 -+ res= -1;
26519 -+ my_error(ER_UNKNOWN_COM_ERROR, MYF(0));
26520 -+ DBUG_RETURN(-1);
26521 -+ }
26522 -+
26523 -+ if (res < 0)
26524 -+ my_error(thd->killed_errno(), MYF(0));
26525 -+ else if ((res == 0) && do_release)
26526 -+ thd->killed= THD::KILL_CONNECTION;
26527 -+
26528 -+ DBUG_RETURN(res);
26529 -+}
26530 -+
26531 -+#ifndef EMBEDDED_LIBRARY
26532 -+
26533 -+/**
26534 -+ Read one command from connection and execute it (query or simple command).
26535 -+ This function is called in loop from thread function.
26536 -+
26537 -+ For profiling to work, it must never be called recursively.
26538 -+
26539 -+ @retval
26540 -+ 0 success
26541 -+ @retval
26542 -+ 1 request of thread shutdown (see dispatch_command() description)
26543 -+*/
26544 -+
26545 -+bool do_command(THD *thd)
26546 -+{
26547 -+ bool return_value;
26548 -+ char *packet= 0;
26549 -+ ulong packet_length;
26550 -+ NET *net= &thd->net;
26551 -+ enum enum_server_command command;
26552 -+ DBUG_ENTER("do_command");
26553 -+
26554 -+ /*
26555 -+ indicator of uninitialized lex => normal flow of errors handling
26556 -+ (see my_message_sql)
26557 -+ */
26558 -+ thd->lex->current_select= 0;
26559 -+
26560 -+ /*
26561 -+ This thread will do a blocking read from the client which
26562 -+ will be interrupted when the next command is received from
26563 -+ the client, the connection is closed or "net_wait_timeout"
26564 -+ number of seconds has passed
26565 -+ */
26566 -+ my_net_set_read_timeout(net, thd->variables.net_wait_timeout);
26567 -+
26568 -+ /*
26569 -+ XXX: this code is here only to clear possible errors of init_connect.
26570 -+ Consider moving to init_connect() instead.
26571 -+ */
26572 -+ thd->clear_error(); // Clear error message
26573 -+ thd->main_da.reset_diagnostics_area();
26574 -+
26575 -+ net_new_transaction(net);
26576 -+
26577 -+ packet_length= my_net_read(net);
26578 -+#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
26579 -+ thd->profiling.start_new_query();
26580 -+#endif
26581 -+ if (packet_length == packet_error)
26582 -+ {
26583 -+ DBUG_PRINT("info",("Got error %d reading command from socket %s",
26584 -+ net->error,
26585 -+ vio_description(net->vio)));
26586 -+
26587 -+ /* Check if we can continue without closing the connection */
26588 -+
26589 -+ /* The error must be set. */
26590 -+ DBUG_ASSERT(thd->is_error());
26591 -+ net_end_statement(thd);
26592 -+
26593 -+ if (net->error != 3)
26594 -+ {
26595 -+ return_value= TRUE; // We have to close it.
26596 -+ goto out;
26597 -+ }
26598 -+
26599 -+ net->error= 0;
26600 -+ return_value= FALSE;
26601 -+ goto out;
26602 -+ }
26603 -+
26604 -+ packet= (char*) net->read_pos;
26605 -+ /*
26606 -+ 'packet_length' contains length of data, as it was stored in packet
26607 -+ header. In case of malformed header, my_net_read returns zero.
26608 -+ If packet_length is not zero, my_net_read ensures that the returned
26609 -+ number of bytes was actually read from network.
26610 -+ There is also an extra safety measure in my_net_read:
26611 -+ it sets packet[packet_length]= 0, but only for non-zero packets.
26612 -+ */
26613 -+ if (packet_length == 0) /* safety */
26614 -+ {
26615 -+ /* Initialize with COM_SLEEP packet */
26616 -+ packet[0]= (uchar) COM_SLEEP;
26617 -+ packet_length= 1;
26618 -+ }
26619 -+ /* Do not rely on my_net_read, extra safety against programming errors. */
26620 -+ packet[packet_length]= '\0'; /* safety */
26621 -+
26622 -+ command= (enum enum_server_command) (uchar) packet[0];
26623 -+
26624 -+ if (command >= COM_END)
26625 -+ command= COM_END; // Wrong command
26626 -+
26627 -+ DBUG_PRINT("info",("Command on %s = %d (%s)",
26628 -+ vio_description(net->vio), command,
26629 -+ command_name[command].str));
26630 -+
26631 -+ /* Restore read timeout value */
26632 -+ my_net_set_read_timeout(net, thd->variables.net_read_timeout);
26633 -+
26634 -+ DBUG_ASSERT(packet_length);
26635 -+ return_value= dispatch_command(command, thd, packet+1, (uint) (packet_length-1));
26636 -+
26637 -+out:
26638 -+#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
26639 -+ thd->profiling.finish_current_query();
26640 -+#endif
26641 -+ DBUG_RETURN(return_value);
26642 -+}
26643 -+#endif /* EMBEDDED_LIBRARY */
26644 -+
26645 -+/**
26646 -+ @brief Determine if an attempt to update a non-temporary table while the
26647 -+ read-only option was enabled has been made.
26648 -+
26649 -+ This is a helper function to mysql_execute_command.
26650 -+
26651 -+ @note SQLCOM_MULTI_UPDATE is an exception and delt with elsewhere.
26652 -+
26653 -+ @see mysql_execute_command
26654 -+ @returns Status code
26655 -+ @retval TRUE The statement should be denied.
26656 -+ @retval FALSE The statement isn't updating any relevant tables.
26657 -+*/
26658 -+
26659 -+static my_bool deny_updates_if_read_only_option(THD *thd,
26660 -+ TABLE_LIST *all_tables)
26661 -+{
26662 -+ DBUG_ENTER("deny_updates_if_read_only_option");
26663 -+
26664 -+ if (!opt_readonly)
26665 -+ DBUG_RETURN(FALSE);
26666 -+
26667 -+ LEX *lex= thd->lex;
26668 -+
26669 -+ const my_bool user_is_super=
26670 -+ ((ulong)(thd->security_ctx->master_access & SUPER_ACL) ==
26671 -+ (ulong)SUPER_ACL);
26672 -+
26673 -+ if (user_is_super)
26674 -+ DBUG_RETURN(FALSE);
26675 -+
26676 -+ if (!(sql_command_flags[lex->sql_command] & CF_CHANGES_DATA))
26677 -+ DBUG_RETURN(FALSE);
26678 -+
26679 -+ /* Multi update is an exception and is dealt with later. */
26680 -+ if (lex->sql_command == SQLCOM_UPDATE_MULTI)
26681 -+ DBUG_RETURN(FALSE);
26682 -+
26683 -+ const my_bool create_temp_tables=
26684 -+ (lex->sql_command == SQLCOM_CREATE_TABLE) &&
26685 -+ (lex->create_info.options & HA_LEX_CREATE_TMP_TABLE);
26686 -+
26687 -+ const my_bool drop_temp_tables=
26688 -+ (lex->sql_command == SQLCOM_DROP_TABLE) &&
26689 -+ lex->drop_temporary;
26690 -+
26691 -+ const my_bool update_real_tables=
26692 -+ some_non_temp_table_to_be_updated(thd, all_tables) &&
26693 -+ !(create_temp_tables || drop_temp_tables);
26694 -+
26695 -+
26696 -+ const my_bool create_or_drop_databases=
26697 -+ (lex->sql_command == SQLCOM_CREATE_DB) ||
26698 -+ (lex->sql_command == SQLCOM_DROP_DB);
26699 -+
26700 -+ if (update_real_tables || create_or_drop_databases)
26701 -+ {
26702 -+ /*
26703 -+ An attempt was made to modify one or more non-temporary tables.
26704 -+ */
26705 -+ DBUG_RETURN(TRUE);
26706 -+ }
26707 -+
26708 -+
26709 -+ /* Assuming that only temporary tables are modified. */
26710 -+ DBUG_RETURN(FALSE);
26711 -+}
26712 -+
26713 -+/**
26714 -+ Perform one connection-level (COM_XXXX) command.
26715 -+
26716 -+ @param command type of command to perform
26717 -+ @param thd connection handle
26718 -+ @param packet data for the command, packet is always null-terminated
26719 -+ @param packet_length length of packet + 1 (to show that data is
26720 -+ null-terminated) except for COM_SLEEP, where it
26721 -+ can be zero.
26722 -+
26723 -+ @todo
26724 -+ set thd->lex->sql_command to SQLCOM_END here.
26725 -+ @todo
26726 -+ The following has to be changed to an 8 byte integer
26727 -+
26728 -+ @retval
26729 -+ 0 ok
26730 -+ @retval
26731 -+ 1 request of thread shutdown, i. e. if command is
26732 -+ COM_QUIT/COM_SHUTDOWN
26733 -+*/
26734 -+bool dispatch_command(enum enum_server_command command, THD *thd,
26735 -+ char* packet, uint packet_length)
26736 -+{
26737 -+ NET *net= &thd->net;
26738 -+ bool error= 0;
26739 -+ DBUG_ENTER("dispatch_command");
26740 -+ DBUG_PRINT("info",("packet: '%*.s'; command: %d", packet_length, packet, command));
26741 -+
26742 -+ thd->command=command;
26743 -+ /*
26744 -+ Commands which always take a long time are logged into
26745 -+ the slow log only if opt_log_slow_admin_statements is set.
26746 -+ */
26747 -+ thd->enable_slow_log= TRUE;
26748 -+ thd->lex->sql_command= SQLCOM_END; /* to avoid confusing VIEW detectors */
26749 -+ thd->set_time();
26750 -+ if (!thd->is_valid_time())
26751 -+ {
26752 -+ /*
26753 -+ If the time has got past 2038 we need to shut this server down
26754 -+ We do this by making sure every command is a shutdown and we
26755 -+ have enough privileges to shut the server down
26756 -+
26757 -+ TODO: remove this when we have full 64 bit my_time_t support
26758 -+ */
26759 -+ thd->security_ctx->master_access|= SHUTDOWN_ACL;
26760 -+ command= COM_SHUTDOWN;
26761 -+ }
26762 -+
26763 -+ VOID(pthread_mutex_lock(&LOCK_thread_count));
26764 -+ thd->query_id= global_query_id;
26765 -+
26766 -+ switch( command ) {
26767 -+ /* Ignore these statements. */
26768 -+ case COM_STATISTICS:
26769 -+ case COM_PING:
26770 -+ break;
26771 -+ /* Only increase id on these statements but don't count them. */
26772 -+ case COM_STMT_PREPARE:
26773 -+ case COM_STMT_CLOSE:
26774 -+ case COM_STMT_RESET:
26775 -+ next_query_id();
26776 -+ break;
26777 -+ /* Increase id and count all other statements. */
26778 -+ default:
26779 -+ statistic_increment(thd->status_var.questions, &LOCK_status);
26780 -+ next_query_id();
26781 -+ }
26782 -+
26783 -+ thread_running++;
26784 -+ /* TODO: set thd->lex->sql_command to SQLCOM_END here */
26785 -+ VOID(pthread_mutex_unlock(&LOCK_thread_count));
26786 -+
26787 -+ /**
26788 -+ Clear the set of flags that are expected to be cleared at the
26789 -+ beginning of each command.
26790 -+ */
26791 -+ thd->server_status&= ~SERVER_STATUS_CLEAR_SET;
26792 -+ switch (command) {
26793 -+ case COM_INIT_DB:
26794 -+ {
26795 -+ LEX_STRING tmp;
26796 -+ status_var_increment(thd->status_var.com_stat[SQLCOM_CHANGE_DB]);
26797 -+ thd->convert_string(&tmp, system_charset_info,
26798 -+ packet, packet_length, thd->charset());
26799 -+ if (!mysql_change_db(thd, &tmp, FALSE))
26800 -+ {
26801 -+ general_log_write(thd, command, thd->db, thd->db_length);
26802 -+ my_ok(thd);
26803 -+ }
26804 -+ break;
26805 -+ }
26806 -+#ifdef HAVE_REPLICATION
26807 -+ case COM_REGISTER_SLAVE:
26808 -+ {
26809 -+ if (!register_slave(thd, (uchar*)packet, packet_length))
26810 -+ my_ok(thd);
26811 -+ break;
26812 -+ }
26813 -+#endif
26814 -+ case COM_TABLE_DUMP:
26815 -+ {
26816 -+ LEX_STRING db, table;
26817 -+ /* Safe because there is always a trailing \0 at the end of the packet */
26818 -+ uint db_len= *(uchar*) packet;
26819 -+ if (db_len + 1 > packet_length || db_len > NAME_LEN)
26820 -+ {
26821 -+ my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0));
26822 -+ break;
26823 -+ }
26824 -+ /* Safe because there is always a trailing \0 at the end of the packet */
26825 -+ uint tbl_len= *(uchar*) (packet + db_len + 1);
26826 -+ if (db_len + tbl_len + 2 > packet_length || tbl_len > NAME_LEN)
26827 -+ {
26828 -+ my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0));
26829 -+ break;
26830 -+ }
26831 -+
26832 -+ status_var_increment(thd->status_var.com_other);
26833 -+ thd->enable_slow_log= opt_log_slow_admin_statements;
26834 -+ db.str= (char*) thd->alloc(db_len + tbl_len + 2);
26835 -+ if (!db.str)
26836 -+ {
26837 -+ my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
26838 -+ break;
26839 -+ }
26840 -+ db.length= db_len;
26841 -+ table.length= tbl_len;
26842 -+ table.str= strmake(db.str, packet + 1, db_len) + 1;
26843 -+ strmake(table.str, packet + db_len + 2, tbl_len);
26844 -+ if (mysql_table_dump(thd, &db, &table) == 0)
26845 -+ thd->main_da.disable_status();
26846 -+ break;
26847 -+ }
26848 -+ case COM_CHANGE_USER:
26849 -+ {
26850 -+ status_var_increment(thd->status_var.com_other);
26851 -+ char *user= (char*) packet, *packet_end= packet + packet_length;
26852 -+ /* Safe because there is always a trailing \0 at the end of the packet */
26853 -+ char *passwd= strend(user)+1;
26854 -+
26855 -+ thd->change_user();
26856 -+ thd->clear_error(); // if errors from rollback
26857 -+
26858 -+ /*
26859 -+ Old clients send null-terminated string ('\0' for empty string) for
26860 -+ password. New clients send the size (1 byte) + string (not null
26861 -+ terminated, so also '\0' for empty string).
26862 -+
26863 -+ Cast *passwd to an unsigned char, so that it doesn't extend the sign
26864 -+ for *passwd > 127 and become 2**32-127 after casting to uint.
26865 -+ */
26866 -+ char db_buff[NAME_LEN+1]; // buffer to store db in utf8
26867 -+ char *db= passwd;
26868 -+ char *save_db;
26869 -+ /*
26870 -+ If there is no password supplied, the packet must contain '\0',
26871 -+ in any type of handshake (4.1 or pre-4.1).
26872 -+ */
26873 -+ if (passwd >= packet_end)
26874 -+ {
26875 -+ my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0));
26876 -+ break;
26877 -+ }
26878 -+ uint passwd_len= (thd->client_capabilities & CLIENT_SECURE_CONNECTION ?
26879 -+ (uchar)(*passwd++) : strlen(passwd));
26880 -+ uint dummy_errors, save_db_length, db_length;
26881 -+ int res;
26882 -+ Security_context save_security_ctx= *thd->security_ctx;
26883 -+ USER_CONN *save_user_connect;
26884 -+
26885 -+ db+= passwd_len + 1;
26886 -+ /*
26887 -+ Database name is always NUL-terminated, so in case of empty database
26888 -+ the packet must contain at least the trailing '\0'.
26889 -+ */
26890 -+ if (db >= packet_end)
26891 -+ {
26892 -+ my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0));
26893 -+ break;
26894 -+ }
26895 -+ db_length= strlen(db);
26896 -+
26897 -+ char *ptr= db + db_length + 1;
26898 -+ uint cs_number= 0;
26899 -+
26900 -+ if (ptr < packet_end)
26901 -+ {
26902 -+ CHARSET_INFO *cs;
26903 -+ if (ptr + 2 > packet_end)
26904 -+ {
26905 -+ my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0));
26906 -+ break;
26907 -+ }
26908 -+
26909 -+ if ((cs_number= uint2korr(ptr)) &&
26910 -+ (cs= get_charset(cs_number, MYF(0))) &&
26911 -+ !is_supported_parser_charset(cs))
26912 -+ {
26913 -+ /* Disallow non-supported parser character sets: UCS2, UTF16, UTF32 */
26914 -+ my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), "character_set_client",
26915 -+ cs->csname);
26916 -+ break;
26917 -+ }
26918 -+ }
26919 -+
26920 -+ /* Convert database name to utf8 */
26921 -+ db_buff[copy_and_convert(db_buff, sizeof(db_buff)-1,
26922 -+ system_charset_info, db, db_length,
26923 -+ thd->charset(), &dummy_errors)]= 0;
26924 -+ db= db_buff;
26925 -+
26926 -+ /* Save user and privileges */
26927 -+ save_db_length= thd->db_length;
26928 -+ save_db= thd->db;
26929 -+ save_user_connect= thd->user_connect;
26930 -+
26931 -+ if (!(thd->security_ctx->user= my_strdup(user, MYF(0))))
26932 -+ {
26933 -+ thd->security_ctx->user= save_security_ctx.user;
26934 -+ my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
26935 -+ break;
26936 -+ }
26937 -+
26938 -+ /* Clear variables that are allocated */
26939 -+ thd->user_connect= 0;
26940 -+ thd->security_ctx->priv_user= thd->security_ctx->user;
26941 -+ res= check_user(thd, COM_CHANGE_USER, passwd, passwd_len, db, FALSE);
26942 -+
26943 -+ if (res)
26944 -+ {
26945 -+ x_free(thd->security_ctx->user);
26946 -+ *thd->security_ctx= save_security_ctx;
26947 -+ thd->user_connect= save_user_connect;
26948 -+ thd->db= save_db;
26949 -+ thd->db_length= save_db_length;
26950 -+ }
26951 -+ else
26952 -+ {
26953 -+#ifndef NO_EMBEDDED_ACCESS_CHECKS
26954 -+ /* we've authenticated new user */
26955 -+ if (save_user_connect)
26956 -+ decrease_user_connections(save_user_connect);
26957 -+#endif /* NO_EMBEDDED_ACCESS_CHECKS */
26958 -+ x_free(save_db);
26959 -+ x_free(save_security_ctx.user);
26960 -+
26961 -+ if (cs_number)
26962 -+ {
26963 -+ /*
26964 -+ We have checked charset earlier,
26965 -+ so thd_init_client_charset cannot fail.
26966 -+ */
26967 -+ if (thd_init_client_charset(thd, cs_number))
26968 -+ DBUG_ASSERT(0);
26969 -+ thd->update_charset();
26970 -+ }
26971 -+ }
26972 -+ break;
26973 -+ }
26974 -+ case COM_STMT_EXECUTE:
26975 -+ {
26976 -+ mysqld_stmt_execute(thd, packet, packet_length);
26977 -+ break;
26978 -+ }
26979 -+ case COM_STMT_FETCH:
26980 -+ {
26981 -+ mysqld_stmt_fetch(thd, packet, packet_length);
26982 -+ break;
26983 -+ }
26984 -+ case COM_STMT_SEND_LONG_DATA:
26985 -+ {
26986 -+ mysql_stmt_get_longdata(thd, packet, packet_length);
26987 -+ break;
26988 -+ }
26989 -+ case COM_STMT_PREPARE:
26990 -+ {
26991 -+ mysqld_stmt_prepare(thd, packet, packet_length);
26992 -+ break;
26993 -+ }
26994 -+ case COM_STMT_CLOSE:
26995 -+ {
26996 -+ mysqld_stmt_close(thd, packet);
26997 -+ break;
26998 -+ }
26999 -+ case COM_STMT_RESET:
27000 -+ {
27001 -+ mysqld_stmt_reset(thd, packet);
27002 -+ break;
27003 -+ }
27004 -+ case COM_QUERY:
27005 -+ {
27006 -+ if (alloc_query(thd, packet, packet_length))
27007 -+ break; // fatal error is set
27008 -+ char *packet_end= thd->query() + thd->query_length();
27009 -+ /* 'b' stands for 'buffer' parameter', special for 'my_snprintf' */
27010 -+ const char* end_of_stmt= NULL;
27011 -+
27012 -+ general_log_write(thd, command, thd->query(), thd->query_length());
27013 -+ DBUG_PRINT("query",("%-.4096s",thd->query()));
27014 -+#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
27015 -+ thd->profiling.set_query_source(thd->query(), thd->query_length());
27016 -+#endif
27017 -+
27018 -+ if (!(specialflag & SPECIAL_NO_PRIOR))
27019 -+ my_pthread_setprio(pthread_self(),QUERY_PRIOR);
27020 -+
27021 -+ mysql_parse(thd, thd->query(), thd->query_length(), &end_of_stmt);
27022 -+
27023 -+ while (!thd->killed && (end_of_stmt != NULL) && ! thd->is_error())
27024 -+ {
27025 -+ char *beginning_of_next_stmt= (char*) end_of_stmt;
27026 -+
27027 -+ net_end_statement(thd);
27028 -+ query_cache_end_of_result(thd);
27029 -+ /*
27030 -+ Multiple queries exits, execute them individually
27031 -+ */
27032 -+ close_thread_tables(thd);
27033 -+ ulong length= (ulong)(packet_end - beginning_of_next_stmt);
27034 -+
27035 -+ log_slow_statement(thd);
27036 -+
27037 -+ /* Remove garbage at start of query */
27038 -+ while (length > 0 && my_isspace(thd->charset(), *beginning_of_next_stmt))
27039 -+ {
27040 -+ beginning_of_next_stmt++;
27041 -+ length--;
27042 -+ }
27043 -+
27044 -+#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
27045 -+ thd->profiling.finish_current_query();
27046 -+ thd->profiling.start_new_query("continuing");
27047 -+ thd->profiling.set_query_source(beginning_of_next_stmt, length);
27048 -+#endif
27049 -+
27050 -+ thd->set_query(beginning_of_next_stmt, length);
27051 -+ VOID(pthread_mutex_lock(&LOCK_thread_count));
27052 -+ /*
27053 -+ Count each statement from the client.
27054 -+ */
27055 -+ statistic_increment(thd->status_var.questions, &LOCK_status);
27056 -+ thd->query_id= next_query_id();
27057 -+ thd->set_time(); /* Reset the query start time. */
27058 -+ /* TODO: set thd->lex->sql_command to SQLCOM_END here */
27059 -+ VOID(pthread_mutex_unlock(&LOCK_thread_count));
27060 -+ mysql_parse(thd, beginning_of_next_stmt, length, &end_of_stmt);
27061 -+ }
27062 -+
27063 -+ if (!(specialflag & SPECIAL_NO_PRIOR))
27064 -+ my_pthread_setprio(pthread_self(),WAIT_PRIOR);
27065 -+ DBUG_PRINT("info",("query ready"));
27066 -+ break;
27067 -+ }
27068 -+ case COM_FIELD_LIST: // This isn't actually needed
27069 -+#ifdef DONT_ALLOW_SHOW_COMMANDS
27070 -+ my_message(ER_NOT_ALLOWED_COMMAND, ER(ER_NOT_ALLOWED_COMMAND),
27071 -+ MYF(0)); /* purecov: inspected */
27072 -+ break;
27073 -+#else
27074 -+ {
27075 -+ char *fields, *packet_end= packet + packet_length, *arg_end;
27076 -+ /* Locked closure of all tables */
27077 -+ TABLE_LIST table_list;
27078 -+ LEX_STRING conv_name;
27079 -+
27080 -+ /* used as fields initializator */
27081 -+ lex_start(thd);
27082 -+
27083 -+ status_var_increment(thd->status_var.com_stat[SQLCOM_SHOW_FIELDS]);
27084 -+ bzero((char*) &table_list,sizeof(table_list));
27085 -+ if (thd->copy_db_to(&table_list.db, &table_list.db_length))
27086 -+ break;
27087 -+ /*
27088 -+ We have name + wildcard in packet, separated by endzero
27089 -+ */
27090 -+ arg_end= strend(packet);
27091 -+ uint arg_length= arg_end - packet;
27092 -+
27093 -+ /* Check given table name length. */
27094 -+ if (arg_length >= packet_length || arg_length > NAME_LEN)
27095 -+ {
27096 -+ my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0));
27097 -+ break;
27098 -+ }
27099 -+ thd->convert_string(&conv_name, system_charset_info,
27100 -+ packet, arg_length, thd->charset());
27101 -+ if (check_table_name(conv_name.str, conv_name.length, FALSE))
27102 -+ {
27103 -+ /* this is OK due to convert_string() null-terminating the string */
27104 -+ my_error(ER_WRONG_TABLE_NAME, MYF(0), conv_name.str);
27105 -+ break;
27106 -+ }
27107 -+
27108 -+ table_list.alias= table_list.table_name= conv_name.str;
27109 -+ packet= arg_end + 1;
27110 -+
27111 -+ if (is_schema_db(table_list.db, table_list.db_length))
27112 -+ {
27113 -+ ST_SCHEMA_TABLE *schema_table= find_schema_table(thd, table_list.alias);
27114 -+ if (schema_table)
27115 -+ table_list.schema_table= schema_table;
27116 -+ }
27117 -+
27118 -+ uint query_length= (uint) (packet_end - packet); // Don't count end \0
27119 -+ if (!(fields= (char *) thd->memdup(packet, query_length + 1)))
27120 -+ break;
27121 -+ thd->set_query(fields, query_length);
27122 -+ general_log_print(thd, command, "%s %s", table_list.table_name, fields);
27123 -+ if (lower_case_table_names)
27124 -+ my_casedn_str(files_charset_info, table_list.table_name);
27125 -+
27126 -+ if (check_access(thd,SELECT_ACL,table_list.db,&table_list.grant.privilege,
27127 -+ 0, 0, test(table_list.schema_table)))
27128 -+ break;
27129 -+ if (check_grant(thd, SELECT_ACL, &table_list, 2, UINT_MAX, 0))
27130 -+ break;
27131 -+ /* init structures for VIEW processing */
27132 -+ table_list.select_lex= &(thd->lex->select_lex);
27133 -+
27134 -+ lex_start(thd);
27135 -+ mysql_reset_thd_for_next_command(thd);
27136 -+
27137 -+ thd->lex->
27138 -+ select_lex.table_list.link_in_list(&table_list,
27139 -+ &table_list.next_local);
27140 -+ thd->lex->add_to_query_tables(&table_list);
27141 -+
27142 -+ /* switch on VIEW optimisation: do not fill temporary tables */
27143 -+ thd->lex->sql_command= SQLCOM_SHOW_FIELDS;
27144 -+ mysqld_list_fields(thd,&table_list,fields);
27145 -+ thd->lex->unit.cleanup();
27146 -+ thd->cleanup_after_query();
27147 -+ break;
27148 -+ }
27149 -+#endif
27150 -+ case COM_QUIT:
27151 -+ /* We don't calculate statistics for this command */
27152 -+ general_log_print(thd, command, NullS);
27153 -+ net->error=0; // Don't give 'abort' message
27154 -+ thd->main_da.disable_status(); // Don't send anything back
27155 -+ error=TRUE; // End server
27156 -+ break;
27157 -+
27158 -+#ifdef REMOVED
27159 -+ case COM_CREATE_DB: // QQ: To be removed
27160 -+ {
27161 -+ LEX_STRING db, alias;
27162 -+ HA_CREATE_INFO create_info;
27163 -+
27164 -+ status_var_increment(thd->status_var.com_stat[SQLCOM_CREATE_DB]);
27165 -+ if (thd->make_lex_string(&db, packet, packet_length, FALSE) ||
27166 -+ thd->make_lex_string(&alias, db.str, db.length, FALSE) ||
27167 -+ check_db_name(&db))
27168 -+ {
27169 -+ my_error(ER_WRONG_DB_NAME, MYF(0), db.str ? db.str : "NULL");
27170 -+ break;
27171 -+ }
27172 -+ if (check_access(thd, CREATE_ACL, db.str , 0, 1, 0,
27173 -+ is_schema_db(db.str, db.length)))
27174 -+ break;
27175 -+ general_log_print(thd, command, "%.*s", db.length, db.str);
27176 -+ bzero(&create_info, sizeof(create_info));
27177 -+ mysql_create_db(thd, (lower_case_table_names == 2 ? alias.str : db.str),
27178 -+ &create_info, 0);
27179 -+ break;
27180 -+ }
27181 -+ case COM_DROP_DB: // QQ: To be removed
27182 -+ {
27183 -+ status_var_increment(thd->status_var.com_stat[SQLCOM_DROP_DB]);
27184 -+ LEX_STRING db;
27185 -+
27186 -+ if (thd->make_lex_string(&db, packet, packet_length, FALSE) ||
27187 -+ check_db_name(&db))
27188 -+ {
27189 -+ my_error(ER_WRONG_DB_NAME, MYF(0), db.str ? db.str : "NULL");
27190 -+ break;
27191 -+ }
27192 -+ if (check_access(thd, DROP_ACL, db.str, 0, 1, 0,
27193 -+ is_schema_db(db.str, db.length)))
27194 -+ break;
27195 -+ if (thd->locked_tables || thd->active_transaction())
27196 -+ {
27197 -+ my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
27198 -+ ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
27199 -+ break;
27200 -+ }
27201 -+ general_log_write(thd, command, "%.*s", db.length, db.str);
27202 -+ mysql_rm_db(thd, db.str, 0, 0);
27203 -+ break;
27204 -+ }
27205 -+#endif
27206 -+#ifndef EMBEDDED_LIBRARY
27207 -+ case COM_BINLOG_DUMP:
27208 -+ {
27209 -+ ulong pos;
27210 -+ ushort flags;
27211 -+ uint32 slave_server_id;
27212 -+
27213 -+ status_var_increment(thd->status_var.com_other);
27214 -+ thd->enable_slow_log= opt_log_slow_admin_statements;
27215 -+ if (check_global_access(thd, REPL_SLAVE_ACL))
27216 -+ break;
27217 -+
27218 -+ /* TODO: The following has to be changed to an 8 byte integer */
27219 -+ pos = uint4korr(packet);
27220 -+ flags = uint2korr(packet + 4);
27221 -+ thd->server_id=0; /* avoid suicide */
27222 -+ if ((slave_server_id= uint4korr(packet+6))) // mysqlbinlog.server_id==0
27223 -+ kill_zombie_dump_threads(slave_server_id);
27224 -+ thd->server_id = slave_server_id;
27225 -+
27226 -+ general_log_print(thd, command, "Log: '%s' Pos: %ld", packet+10,
27227 -+ (long) pos);
27228 -+ mysql_binlog_send(thd, thd->strdup(packet + 10), (my_off_t) pos, flags);
27229 -+ unregister_slave(thd,1,1);
27230 -+ /* fake COM_QUIT -- if we get here, the thread needs to terminate */
27231 -+ error = TRUE;
27232 -+ break;
27233 -+ }
27234 -+#endif
27235 -+ case COM_REFRESH:
27236 -+ {
27237 -+ int not_used;
27238 -+ status_var_increment(thd->status_var.com_stat[SQLCOM_FLUSH]);
27239 -+ ulong options= (ulong) (uchar) packet[0];
27240 -+ if (check_global_access(thd,RELOAD_ACL))
27241 -+ break;
27242 -+ general_log_print(thd, command, NullS);
27243 -+#ifndef DBUG_OFF
27244 -+ bool debug_simulate= FALSE;
27245 -+ DBUG_EXECUTE_IF("simulate_detached_thread_refresh", debug_simulate= TRUE;);
27246 -+ if (debug_simulate)
27247 -+ {
27248 -+ /*
27249 -+ Simulate a reload without a attached thread session.
27250 -+ Provides a environment similar to that of when the
27251 -+ server receives a SIGHUP signal and reloads caches
27252 -+ and flushes tables.
27253 -+ */
27254 -+ bool res;
27255 -+ my_pthread_setspecific_ptr(THR_THD, NULL);
27256 -+ res= reload_acl_and_cache(NULL, options | REFRESH_FAST,
27257 -+ NULL, &not_used);
27258 -+ my_pthread_setspecific_ptr(THR_THD, thd);
27259 -+ if (!res)
27260 -+ my_ok(thd);
27261 -+ break;
27262 -+ }
27263 -+#endif
27264 -+ if (!reload_acl_and_cache(thd, options, NULL, &not_used))
27265 -+ my_ok(thd);
27266 -+ break;
27267 -+ }
27268 -+#ifndef EMBEDDED_LIBRARY
27269 -+ case COM_SHUTDOWN:
27270 -+ {
27271 -+ status_var_increment(thd->status_var.com_other);
27272 -+ if (check_global_access(thd,SHUTDOWN_ACL))
27273 -+ break; /* purecov: inspected */
27274 -+ /*
27275 -+ If the client is < 4.1.3, it is going to send us no argument; then
27276 -+ packet_length is 0, packet[0] is the end 0 of the packet. Note that
27277 -+ SHUTDOWN_DEFAULT is 0. If client is >= 4.1.3, the shutdown level is in
27278 -+ packet[0].
27279 -+ */
27280 -+ enum mysql_enum_shutdown_level level;
27281 -+ if (!thd->is_valid_time())
27282 -+ level= SHUTDOWN_DEFAULT;
27283 -+ else
27284 -+ level= (enum mysql_enum_shutdown_level) (uchar) packet[0];
27285 -+ if (level == SHUTDOWN_DEFAULT)
27286 -+ level= SHUTDOWN_WAIT_ALL_BUFFERS; // soon default will be configurable
27287 -+ else if (level != SHUTDOWN_WAIT_ALL_BUFFERS)
27288 -+ {
27289 -+ my_error(ER_NOT_SUPPORTED_YET, MYF(0), "this shutdown level");
27290 -+ break;
27291 -+ }
27292 -+ DBUG_PRINT("quit",("Got shutdown command for level %u", level));
27293 -+ general_log_print(thd, command, NullS);
27294 -+ my_eof(thd);
27295 -+ close_thread_tables(thd); // Free before kill
27296 -+ kill_mysql();
27297 -+ error=TRUE;
27298 -+ break;
27299 -+ }
27300 -+#endif
27301 -+ case COM_STATISTICS:
27302 -+ {
27303 -+ STATUS_VAR current_global_status_var;
27304 -+ ulong uptime;
27305 -+ uint length __attribute__((unused));
27306 -+ ulonglong queries_per_second1000;
27307 -+ char buff[250];
27308 -+ uint buff_len= sizeof(buff);
27309 -+
27310 -+ general_log_print(thd, command, NullS);
27311 -+ status_var_increment(thd->status_var.com_stat[SQLCOM_SHOW_STATUS]);
27312 -+ calc_sum_of_all_status(&current_global_status_var);
27313 -+ if (!(uptime= (ulong) (thd->start_time - server_start_time)))
27314 -+ queries_per_second1000= 0;
27315 -+ else
27316 -+ queries_per_second1000= thd->query_id * LL(1000) / uptime;
27317 -+
27318 -+ length= my_snprintf(buff, buff_len - 1,
27319 -+ "Uptime: %lu Threads: %d Questions: %lu "
27320 -+ "Slow queries: %lu Opens: %lu Flush tables: %lu "
27321 -+ "Open tables: %u Queries per second avg: %u.%u",
27322 -+ uptime,
27323 -+ (int) thread_count, (ulong) thd->query_id,
27324 -+ current_global_status_var.long_query_count,
27325 -+ current_global_status_var.opened_tables,
27326 -+ refresh_version,
27327 -+ cached_open_tables(),
27328 -+ (uint) (queries_per_second1000 / 1000),
27329 -+ (uint) (queries_per_second1000 % 1000));
27330 -+#ifdef SAFEMALLOC
27331 -+ if (sf_malloc_cur_memory) // Using SAFEMALLOC
27332 -+ {
27333 -+ char *end= buff + length;
27334 -+ length+= my_snprintf(end, buff_len - length - 1,
27335 -+ end," Memory in use: %ldK Max memory used: %ldK",
27336 -+ (sf_malloc_cur_memory+1023L)/1024L,
27337 -+ (sf_malloc_max_memory+1023L)/1024L);
27338 -+ }
27339 -+#endif
27340 -+#ifndef EMBEDDED_LIBRARY
27341 -+ VOID(my_net_write(net, (uchar*) buff, length));
27342 -+ VOID(net_flush(net));
27343 -+ thd->main_da.disable_status();
27344 -+#else
27345 -+ /* Store the buffer in permanent memory */
27346 -+ my_ok(thd, 0, 0, buff);
27347 -+#endif
27348 -+ break;
27349 -+ }
27350 -+ case COM_PING:
27351 -+ status_var_increment(thd->status_var.com_other);
27352 -+ my_ok(thd); // Tell client we are alive
27353 -+ break;
27354 -+ case COM_PROCESS_INFO:
27355 -+ status_var_increment(thd->status_var.com_stat[SQLCOM_SHOW_PROCESSLIST]);
27356 -+ if (!thd->security_ctx->priv_user[0] &&
27357 -+ check_global_access(thd, PROCESS_ACL))
27358 -+ break;
27359 -+ general_log_print(thd, command, NullS);
27360 -+ mysqld_list_processes(thd,
27361 -+ thd->security_ctx->master_access & PROCESS_ACL ?
27362 -+ NullS : thd->security_ctx->priv_user, 0);
27363 -+ break;
27364 -+ case COM_PROCESS_KILL:
27365 -+ {
27366 -+ status_var_increment(thd->status_var.com_stat[SQLCOM_KILL]);
27367 -+ ulong id=(ulong) uint4korr(packet);
27368 -+ sql_kill(thd,id,false);
27369 -+ break;
27370 -+ }
27371 -+ case COM_SET_OPTION:
27372 -+ {
27373 -+ status_var_increment(thd->status_var.com_stat[SQLCOM_SET_OPTION]);
27374 -+ uint opt_command= uint2korr(packet);
27375 -+
27376 -+ switch (opt_command) {
27377 -+ case (int) MYSQL_OPTION_MULTI_STATEMENTS_ON:
27378 -+ thd->client_capabilities|= CLIENT_MULTI_STATEMENTS;
27379 -+ my_eof(thd);
27380 -+ break;
27381 -+ case (int) MYSQL_OPTION_MULTI_STATEMENTS_OFF:
27382 -+ thd->client_capabilities&= ~CLIENT_MULTI_STATEMENTS;
27383 -+ my_eof(thd);
27384 -+ break;
27385 -+ default:
27386 -+ my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0));
27387 -+ break;
27388 -+ }
27389 -+ break;
27390 -+ }
27391 -+ case COM_DEBUG:
27392 -+ status_var_increment(thd->status_var.com_other);
27393 -+ if (check_global_access(thd, SUPER_ACL))
27394 -+ break; /* purecov: inspected */
27395 -+ mysql_print_status();
27396 -+ general_log_print(thd, command, NullS);
27397 -+ my_eof(thd);
27398 -+ break;
27399 -+ case COM_SLEEP:
27400 -+ case COM_CONNECT: // Impossible here
27401 -+ case COM_TIME: // Impossible from client
27402 -+ case COM_DELAYED_INSERT:
27403 -+ case COM_END:
27404 -+ default:
27405 -+ my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0));
27406 -+ break;
27407 -+ }
27408 -+
27409 -+ /* report error issued during command execution */
27410 -+ if (thd->killed_errno())
27411 -+ {
27412 -+ if (! thd->main_da.is_set())
27413 -+ thd->send_kill_message();
27414 -+ }
27415 -+ if (thd->killed == THD::KILL_QUERY || thd->killed == THD::KILL_BAD_DATA)
27416 -+ {
27417 -+ thd->killed= THD::NOT_KILLED;
27418 -+ thd->mysys_var->abort= 0;
27419 -+ }
27420 -+
27421 -+ /* If commit fails, we should be able to reset the OK status. */
27422 -+ thd->main_da.can_overwrite_status= TRUE;
27423 -+ ha_autocommit_or_rollback(thd, thd->is_error());
27424 -+ thd->main_da.can_overwrite_status= FALSE;
27425 -+
27426 -+ thd->transaction.stmt.reset();
27427 -+
27428 -+ net_end_statement(thd);
27429 -+ query_cache_end_of_result(thd);
27430 -+
27431 -+ thd->proc_info= "closing tables";
27432 -+ /* Free tables */
27433 -+ close_thread_tables(thd);
27434 -+
27435 -+ log_slow_statement(thd);
27436 -+
27437 -+ thd_proc_info(thd, "cleaning up");
27438 -+ thd->set_query(NULL, 0);
27439 -+ thd->command=COM_SLEEP;
27440 -+ VOID(pthread_mutex_lock(&LOCK_thread_count)); // For process list
27441 -+ thread_running--;
27442 -+ VOID(pthread_mutex_unlock(&LOCK_thread_count));
27443 -+ thd_proc_info(thd, 0);
27444 -+ thd->packet.shrink(thd->variables.net_buffer_length); // Reclaim some memory
27445 -+ free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC));
27446 -+ DBUG_RETURN(error);
27447 -+}
27448 -+
27449 -+
27450 -+void log_slow_statement(THD *thd)
27451 -+{
27452 -+ DBUG_ENTER("log_slow_statement");
27453 -+
27454 -+ /*
27455 -+ The following should never be true with our current code base,
27456 -+ but better to keep this here so we don't accidently try to log a
27457 -+ statement in a trigger or stored function
27458 -+ */
27459 -+ if (unlikely(thd->in_sub_stmt))
27460 -+ DBUG_VOID_RETURN; // Don't set time for sub stmt
27461 -+
27462 -+ /*
27463 -+ Do not log administrative statements unless the appropriate option is
27464 -+ set.
27465 -+ */
27466 -+ if (thd->enable_slow_log)
27467 -+ {
27468 -+ ulonglong end_utime_of_query= thd->current_utime();
27469 -+ thd_proc_info(thd, "logging slow query");
27470 -+
27471 -+ if (((end_utime_of_query - thd->utime_after_lock) >
27472 -+ thd->variables.long_query_time ||
27473 -+ ((thd->server_status &
27474 -+ (SERVER_QUERY_NO_INDEX_USED | SERVER_QUERY_NO_GOOD_INDEX_USED)) &&
27475 -+ opt_log_queries_not_using_indexes &&
27476 -+ !(sql_command_flags[thd->lex->sql_command] & CF_STATUS_COMMAND))) &&
27477 -+ thd->examined_row_count >= thd->variables.min_examined_row_limit)
27478 -+ {
27479 -+ thd_proc_info(thd, "logging slow query");
27480 -+ thd->status_var.long_query_count++;
27481 -+ slow_log_print(thd, thd->query(), thd->query_length(),
27482 -+ end_utime_of_query);
27483 -+ }
27484 -+ }
27485 -+ DBUG_VOID_RETURN;
27486 -+}
27487 -+
27488 -+
27489 -+/**
27490 -+ Create a TABLE_LIST object for an INFORMATION_SCHEMA table.
27491 -+
27492 -+ This function is used in the parser to convert a SHOW or DESCRIBE
27493 -+ table_name command to a SELECT from INFORMATION_SCHEMA.
27494 -+ It prepares a SELECT_LEX and a TABLE_LIST object to represent the
27495 -+ given command as a SELECT parse tree.
27496 -+
27497 -+ @param thd thread handle
27498 -+ @param lex current lex
27499 -+ @param table_ident table alias if it's used
27500 -+ @param schema_table_idx the type of the INFORMATION_SCHEMA table to be
27501 -+ created
27502 -+
27503 -+ @note
27504 -+ Due to the way this function works with memory and LEX it cannot
27505 -+ be used outside the parser (parse tree transformations outside
27506 -+ the parser break PS and SP).
27507 -+
27508 -+ @retval
27509 -+ 0 success
27510 -+ @retval
27511 -+ 1 out of memory or SHOW commands are not allowed
27512 -+ in this version of the server.
27513 -+*/
27514 -+
27515 -+int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident,
27516 -+ enum enum_schema_tables schema_table_idx)
27517 -+{
27518 -+ SELECT_LEX *schema_select_lex= NULL;
27519 -+ DBUG_ENTER("prepare_schema_table");
27520 -+
27521 -+ switch (schema_table_idx) {
27522 -+ case SCH_SCHEMATA:
27523 -+#if defined(DONT_ALLOW_SHOW_COMMANDS)
27524 -+ my_message(ER_NOT_ALLOWED_COMMAND,
27525 -+ ER(ER_NOT_ALLOWED_COMMAND), MYF(0)); /* purecov: inspected */
27526 -+ DBUG_RETURN(1);
27527 -+#else
27528 -+ break;
27529 -+#endif
27530 -+
27531 -+ case SCH_TABLE_NAMES:
27532 -+ case SCH_TABLES:
27533 -+ case SCH_VIEWS:
27534 -+ case SCH_TRIGGERS:
27535 -+ case SCH_EVENTS:
27536 -+#ifdef DONT_ALLOW_SHOW_COMMANDS
27537 -+ my_message(ER_NOT_ALLOWED_COMMAND,
27538 -+ ER(ER_NOT_ALLOWED_COMMAND), MYF(0)); /* purecov: inspected */
27539 -+ DBUG_RETURN(1);
27540 -+#else
27541 -+ {
27542 -+ LEX_STRING db;
27543 -+ size_t dummy;
27544 -+ if (lex->select_lex.db == NULL &&
27545 -+ lex->copy_db_to(&lex->select_lex.db, &dummy))
27546 -+ {
27547 -+ DBUG_RETURN(1);
27548 -+ }
27549 -+ schema_select_lex= new SELECT_LEX();
27550 -+ db.str= schema_select_lex->db= lex->select_lex.db;
27551 -+ schema_select_lex->table_list.first= NULL;
27552 -+ db.length= strlen(db.str);
27553 -+
27554 -+ if (check_db_name(&db))
27555 -+ {
27556 -+ my_error(ER_WRONG_DB_NAME, MYF(0), db.str);
27557 -+ DBUG_RETURN(1);
27558 -+ }
27559 -+ break;
27560 -+ }
27561 -+#endif
27562 -+ case SCH_COLUMNS:
27563 -+ case SCH_STATISTICS:
27564 -+ {
27565 -+#ifdef DONT_ALLOW_SHOW_COMMANDS
27566 -+ my_message(ER_NOT_ALLOWED_COMMAND,
27567 -+ ER(ER_NOT_ALLOWED_COMMAND), MYF(0)); /* purecov: inspected */
27568 -+ DBUG_RETURN(1);
27569 -+#else
27570 -+ DBUG_ASSERT(table_ident);
27571 -+ TABLE_LIST **query_tables_last= lex->query_tables_last;
27572 -+ schema_select_lex= new SELECT_LEX();
27573 -+ /* 'parent_lex' is used in init_query() so it must be before it. */
27574 -+ schema_select_lex->parent_lex= lex;
27575 -+ schema_select_lex->init_query();
27576 -+ if (!schema_select_lex->add_table_to_list(thd, table_ident, 0, 0, TL_READ))
27577 -+ DBUG_RETURN(1);
27578 -+ lex->query_tables_last= query_tables_last;
27579 -+ break;
27580 -+ }
27581 -+#endif
27582 -+ case SCH_PROFILES:
27583 -+ /*
27584 -+ Mark this current profiling record to be discarded. We don't
27585 -+ wish to have SHOW commands show up in profiling.
27586 -+ */
27587 -+#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
27588 -+ thd->profiling.discard_current_query();
27589 -+#endif
27590 -+ break;
27591 -+ case SCH_OPEN_TABLES:
27592 -+ case SCH_VARIABLES:
27593 -+ case SCH_STATUS:
27594 -+ case SCH_PROCEDURES:
27595 -+ case SCH_CHARSETS:
27596 -+ case SCH_ENGINES:
27597 -+ case SCH_COLLATIONS:
27598 -+ case SCH_COLLATION_CHARACTER_SET_APPLICABILITY:
27599 -+ case SCH_USER_PRIVILEGES:
27600 -+ case SCH_SCHEMA_PRIVILEGES:
27601 -+ case SCH_TABLE_PRIVILEGES:
27602 -+ case SCH_COLUMN_PRIVILEGES:
27603 -+ case SCH_TABLE_CONSTRAINTS:
27604 -+ case SCH_KEY_COLUMN_USAGE:
27605 -+ default:
27606 -+ break;
27607 -+ }
27608 -+
27609 -+ SELECT_LEX *select_lex= lex->current_select;
27610 -+ if (make_schema_select(thd, select_lex, schema_table_idx))
27611 -+ {
27612 -+ DBUG_RETURN(1);
27613 -+ }
27614 -+ TABLE_LIST *table_list= select_lex->table_list.first;
27615 -+ table_list->schema_select_lex= schema_select_lex;
27616 -+ table_list->schema_table_reformed= 1;
27617 -+ DBUG_RETURN(0);
27618 -+}
27619 -+
27620 -+
27621 -+/**
27622 -+ Read query from packet and store in thd->query.
27623 -+ Used in COM_QUERY and COM_STMT_PREPARE.
27624 -+
27625 -+ Sets the following THD variables:
27626 -+ - query
27627 -+ - query_length
27628 -+
27629 -+ @retval
27630 -+ FALSE ok
27631 -+ @retval
27632 -+ TRUE error; In this case thd->fatal_error is set
27633 -+*/
27634 -+
27635 -+bool alloc_query(THD *thd, const char *packet, uint packet_length)
27636 -+{
27637 -+ char *query;
27638 -+ /* Remove garbage at start and end of query */
27639 -+ while (packet_length > 0 && my_isspace(thd->charset(), packet[0]))
27640 -+ {
27641 -+ packet++;
27642 -+ packet_length--;
27643 -+ }
27644 -+ const char *pos= packet + packet_length; // Point at end null
27645 -+ while (packet_length > 0 &&
27646 -+ (pos[-1] == ';' || my_isspace(thd->charset() ,pos[-1])))
27647 -+ {
27648 -+ pos--;
27649 -+ packet_length--;
27650 -+ }
27651 -+ /* We must allocate some extra memory for query cache */
27652 -+ if (! (query= (char*) thd->memdup_w_gap(packet,
27653 -+ packet_length,
27654 -+ 1 + thd->db_length +
27655 -+ QUERY_CACHE_FLAGS_SIZE)))
27656 -+ return TRUE;
27657 -+ query[packet_length]= '\0';
27658 -+ thd->set_query(query, packet_length);
27659 -+
27660 -+ /* Reclaim some memory */
27661 -+ thd->packet.shrink(thd->variables.net_buffer_length);
27662 -+ thd->convert_buffer.shrink(thd->variables.net_buffer_length);
27663 -+
27664 -+ return FALSE;
27665 -+}
27666 -+
27667 -+static void reset_one_shot_variables(THD *thd)
27668 -+{
27669 -+ thd->variables.character_set_client=
27670 -+ global_system_variables.character_set_client;
27671 -+ thd->variables.collation_connection=
27672 -+ global_system_variables.collation_connection;
27673 -+ thd->variables.collation_database=
27674 -+ global_system_variables.collation_database;
27675 -+ thd->variables.collation_server=
27676 -+ global_system_variables.collation_server;
27677 -+ thd->update_charset();
27678 -+ thd->variables.time_zone=
27679 -+ global_system_variables.time_zone;
27680 -+ thd->variables.lc_time_names= &my_locale_en_US;
27681 -+ thd->one_shot_set= 0;
27682 -+}
27683 -+
27684 -+
27685 -+static
27686 -+bool sp_process_definer(THD *thd)
27687 -+{
27688 -+ DBUG_ENTER("sp_process_definer");
27689 -+
27690 -+ LEX *lex= thd->lex;
27691 -+
27692 -+ /*
27693 -+ If the definer is not specified, this means that CREATE-statement missed
27694 -+ DEFINER-clause. DEFINER-clause can be missed in two cases:
27695 -+
27696 -+ - The user submitted a statement w/o the clause. This is a normal
27697 -+ case, we should assign CURRENT_USER as definer.
27698 -+
27699 -+ - Our slave received an updated from the master, that does not
27700 -+ replicate definer for stored rountines. We should also assign
27701 -+ CURRENT_USER as definer here, but also we should mark this routine
27702 -+ as NON-SUID. This is essential for the sake of backward
27703 -+ compatibility.
27704 -+
27705 -+ The problem is the slave thread is running under "special" user (@),
27706 -+ that actually does not exist. In the older versions we do not fail
27707 -+ execution of a stored routine if its definer does not exist and
27708 -+ continue the execution under the authorization of the invoker
27709 -+ (BUG#13198). And now if we try to switch to slave-current-user (@),
27710 -+ we will fail.
27711 -+
27712 -+ Actually, this leads to the inconsistent state of master and
27713 -+ slave (different definers, different SUID behaviour), but it seems,
27714 -+ this is the best we can do.
27715 -+ */
27716 -+
27717 -+ if (!lex->definer)
27718 -+ {
27719 -+ Query_arena original_arena;
27720 -+ Query_arena *ps_arena= thd->activate_stmt_arena_if_needed(&original_arena);
27721 -+
27722 -+ lex->definer= create_default_definer(thd);
27723 -+
27724 -+ if (ps_arena)
27725 -+ thd->restore_active_arena(ps_arena, &original_arena);
27726 -+
27727 -+ /* Error has been already reported. */
27728 -+ if (lex->definer == NULL)
27729 -+ DBUG_RETURN(TRUE);
27730 -+
27731 -+ if (thd->slave_thread && lex->sphead)
27732 -+ lex->sphead->m_chistics->suid= SP_IS_NOT_SUID;
27733 -+ }
27734 -+ else
27735 -+ {
27736 -+ /*
27737 -+ If the specified definer differs from the current user, we
27738 -+ should check that the current user has SUPER privilege (in order
27739 -+ to create a stored routine under another user one must have
27740 -+ SUPER privilege).
27741 -+ */
27742 -+ if ((strcmp(lex->definer->user.str, thd->security_ctx->priv_user) ||
27743 -+ my_strcasecmp(system_charset_info, lex->definer->host.str,
27744 -+ thd->security_ctx->priv_host)) &&
27745 -+ check_global_access(thd, SUPER_ACL))
27746 -+ {
27747 -+ my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER");
27748 -+ DBUG_RETURN(TRUE);
27749 -+ }
27750 -+ }
27751 -+
27752 -+ /* Check that the specified definer exists. Emit a warning if not. */
27753 -+
27754 -+#ifndef NO_EMBEDDED_ACCESS_CHECKS
27755 -+ if (!is_acl_user(lex->definer->host.str, lex->definer->user.str))
27756 -+ {
27757 -+ push_warning_printf(thd,
27758 -+ MYSQL_ERROR::WARN_LEVEL_NOTE,
27759 -+ ER_NO_SUCH_USER,
27760 -+ ER(ER_NO_SUCH_USER),
27761 -+ lex->definer->user.str,
27762 -+ lex->definer->host.str);
27763 -+ }
27764 -+#endif /* NO_EMBEDDED_ACCESS_CHECKS */
27765 -+
27766 -+ DBUG_RETURN(FALSE);
27767 -+}
27768 -+
27769 -+
27770 -+/**
27771 -+ Execute command saved in thd and lex->sql_command.
27772 -+
27773 -+ Before every operation that can request a write lock for a table
27774 -+ wait if a global read lock exists. However do not wait if this
27775 -+ thread has locked tables already. No new locks can be requested
27776 -+ until the other locks are released. The thread that requests the
27777 -+ global read lock waits for write locked tables to become unlocked.
27778 -+
27779 -+ Note that wait_if_global_read_lock() sets a protection against a new
27780 -+ global read lock when it succeeds. This needs to be released by
27781 -+ start_waiting_global_read_lock() after the operation.
27782 -+
27783 -+ @param thd Thread handle
27784 -+
27785 -+ @todo
27786 -+ - Invalidate the table in the query cache if something changed
27787 -+ after unlocking when changes become visible.
27788 -+ TODO: this is workaround. right way will be move invalidating in
27789 -+ the unlock procedure.
27790 -+ - TODO: use check_change_password()
27791 -+ - JOIN is not supported yet. TODO
27792 -+ - SUSPEND and FOR MIGRATE are not supported yet. TODO
27793 -+
27794 -+ @retval
27795 -+ FALSE OK
27796 -+ @retval
27797 -+ TRUE Error
27798 -+*/
27799 -+
27800 -+int
27801 -+mysql_execute_command(THD *thd)
27802 -+{
27803 -+ int res= FALSE;
27804 -+ bool need_start_waiting= FALSE; // have protection against global read lock
27805 -+ int up_result= 0;
27806 -+ LEX *lex= thd->lex;
27807 -+ /* first SELECT_LEX (have special meaning for many of non-SELECTcommands) */
27808 -+ SELECT_LEX *select_lex= &lex->select_lex;
27809 -+ /* first table of first SELECT_LEX */
27810 -+ TABLE_LIST *first_table= select_lex->table_list.first;
27811 -+ /* list of all tables in query */
27812 -+ TABLE_LIST *all_tables;
27813 -+ /* most outer SELECT_LEX_UNIT of query */
27814 -+ SELECT_LEX_UNIT *unit= &lex->unit;
27815 -+#ifdef HAVE_REPLICATION
27816 -+ /* have table map for update for multi-update statement (BUG#37051) */
27817 -+ bool have_table_map_for_update= FALSE;
27818 -+#endif
27819 -+ /* Saved variable value */
27820 -+ DBUG_ENTER("mysql_execute_command");
27821 -+#ifdef WITH_PARTITION_STORAGE_ENGINE
27822 -+ thd->work_part_info= 0;
27823 -+#endif
27824 -+
27825 -+ /*
27826 -+ In many cases first table of main SELECT_LEX have special meaning =>
27827 -+ check that it is first table in global list and relink it first in
27828 -+ queries_tables list if it is necessary (we need such relinking only
27829 -+ for queries with subqueries in select list, in this case tables of
27830 -+ subqueries will go to global list first)
27831 -+
27832 -+ all_tables will differ from first_table only if most upper SELECT_LEX
27833 -+ do not contain tables.
27834 -+
27835 -+ Because of above in place where should be at least one table in most
27836 -+ outer SELECT_LEX we have following check:
27837 -+ DBUG_ASSERT(first_table == all_tables);
27838 -+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
27839 -+ */
27840 -+ lex->first_lists_tables_same();
27841 -+ /* should be assigned after making first tables same */
27842 -+ all_tables= lex->query_tables;
27843 -+ /* set context for commands which do not use setup_tables */
27844 -+ select_lex->
27845 -+ context.resolve_in_table_list_only(select_lex->
27846 -+ table_list.first);
27847 -+
27848 -+ /*
27849 -+ Reset warning count for each query that uses tables
27850 -+ A better approach would be to reset this for any commands
27851 -+ that is not a SHOW command or a select that only access local
27852 -+ variables, but for now this is probably good enough.
27853 -+ Don't reset warnings when executing a stored routine.
27854 -+ */
27855 -+ if ((all_tables || !lex->is_single_level_stmt()) && !thd->spcont)
27856 -+ mysql_reset_errors(thd, 0);
27857 -+
27858 -+#ifdef HAVE_REPLICATION
27859 -+ if (unlikely(thd->slave_thread))
27860 -+ {
27861 -+ if (lex->sql_command == SQLCOM_DROP_TRIGGER)
27862 -+ {
27863 -+ /*
27864 -+ When dropping a trigger, we need to load its table name
27865 -+ before checking slave filter rules.
27866 -+ */
27867 -+ add_table_for_trigger(thd, thd->lex->spname, 1, &all_tables);
27868 -+
27869 -+ if (!all_tables)
27870 -+ {
27871 -+ /*
27872 -+ If table name cannot be loaded,
27873 -+ it means the trigger does not exists possibly because
27874 -+ CREATE TRIGGER was previously skipped for this trigger
27875 -+ according to slave filtering rules.
27876 -+ Returning success without producing any errors in this case.
27877 -+ */
27878 -+ DBUG_RETURN(0);
27879 -+ }
27880 -+
27881 -+ // force searching in slave.cc:tables_ok()
27882 -+ all_tables->updating= 1;
27883 -+ }
27884 -+
27885 -+ /*
27886 -+ For fix of BUG#37051, the master stores the table map for update
27887 -+ in the Query_log_event, and the value is assigned to
27888 -+ thd->variables.table_map_for_update before executing the update
27889 -+ query.
27890 -+
27891 -+ If thd->variables.table_map_for_update is set, then we are
27892 -+ replicating from a new master, we can use this value to apply
27893 -+ filter rules without opening all the tables. However If
27894 -+ thd->variables.table_map_for_update is not set, then we are
27895 -+ replicating from an old master, so we just skip this and
27896 -+ continue with the old method. And of course, the bug would still
27897 -+ exist for old masters.
27898 -+ */
27899 -+ if (lex->sql_command == SQLCOM_UPDATE_MULTI &&
27900 -+ thd->table_map_for_update)
27901 -+ {
27902 -+ have_table_map_for_update= TRUE;
27903 -+ table_map table_map_for_update= thd->table_map_for_update;
27904 -+ uint nr= 0;
27905 -+ TABLE_LIST *table;
27906 -+ for (table=all_tables; table; table=table->next_global, nr++)
27907 -+ {
27908 -+ if (table_map_for_update & ((table_map)1 << nr))
27909 -+ table->updating= TRUE;
27910 -+ else
27911 -+ table->updating= FALSE;
27912 -+ }
27913 -+
27914 -+ if (all_tables_not_ok(thd, all_tables))
27915 -+ {
27916 -+ /* we warn the slave SQL thread */
27917 -+ my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0));
27918 -+ if (thd->one_shot_set)
27919 -+ reset_one_shot_variables(thd);
27920 -+ DBUG_RETURN(0);
27921 -+ }
27922 -+
27923 -+ for (table=all_tables; table; table=table->next_global)
27924 -+ table->updating= TRUE;
27925 -+ }
27926 -+
27927 -+ /*
27928 -+ Check if statment should be skipped because of slave filtering
27929 -+ rules
27930 -+
27931 -+ Exceptions are:
27932 -+ - UPDATE MULTI: For this statement, we want to check the filtering
27933 -+ rules later in the code
27934 -+ - SET: we always execute it (Not that many SET commands exists in
27935 -+ the binary log anyway -- only 4.1 masters write SET statements,
27936 -+ in 5.0 there are no SET statements in the binary log)
27937 -+ - DROP TEMPORARY TABLE IF EXISTS: we always execute it (otherwise we
27938 -+ have stale files on slave caused by exclusion of one tmp table).
27939 -+ */
27940 -+ if (!(lex->sql_command == SQLCOM_UPDATE_MULTI) &&
27941 -+ !(lex->sql_command == SQLCOM_SET_OPTION) &&
27942 -+ !(lex->sql_command == SQLCOM_DROP_TABLE &&
27943 -+ lex->drop_temporary && lex->drop_if_exists) &&
27944 -+ all_tables_not_ok(thd, all_tables))
27945 -+ {
27946 -+ /* we warn the slave SQL thread */
27947 -+ my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0));
27948 -+ if (thd->one_shot_set)
27949 -+ {
27950 -+ /*
27951 -+ It's ok to check thd->one_shot_set here:
27952 -+
27953 -+ The charsets in a MySQL 5.0 slave can change by both a binlogged
27954 -+ SET ONE_SHOT statement and the event-internal charset setting,
27955 -+ and these two ways to change charsets do not seems to work
27956 -+ together.
27957 -+
27958 -+ At least there seems to be problems in the rli cache for
27959 -+ charsets if we are using ONE_SHOT. Note that this is normally no
27960 -+ problem because either the >= 5.0 slave reads a 4.1 binlog (with
27961 -+ ONE_SHOT) *or* or 5.0 binlog (without ONE_SHOT) but never both."
27962 -+ */
27963 -+ reset_one_shot_variables(thd);
27964 -+ }
27965 -+ DBUG_RETURN(0);
27966 -+ }
27967 -+ }
27968 -+ else
27969 -+ {
27970 -+#endif /* HAVE_REPLICATION */
27971 -+ /*
27972 -+ When option readonly is set deny operations which change non-temporary
27973 -+ tables. Except for the replication thread and the 'super' users.
27974 -+ */
27975 -+ if (deny_updates_if_read_only_option(thd, all_tables))
27976 -+ {
27977 -+ my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only");
27978 -+ DBUG_RETURN(-1);
27979 -+ }
27980 -+#ifdef HAVE_REPLICATION
27981 -+ } /* endif unlikely slave */
27982 -+#endif
27983 -+ status_var_increment(thd->status_var.com_stat[lex->sql_command]);
27984 -+
27985 -+ DBUG_ASSERT(thd->transaction.stmt.modified_non_trans_table == FALSE);
27986 -+
27987 -+ switch (lex->sql_command) {
27988 -+
27989 -+ case SQLCOM_SHOW_EVENTS:
27990 -+#ifndef HAVE_EVENT_SCHEDULER
27991 -+ my_error(ER_NOT_SUPPORTED_YET, MYF(0), "embedded server");
27992 -+ break;
27993 -+#endif
27994 -+ case SQLCOM_SHOW_STATUS_PROC:
27995 -+ case SQLCOM_SHOW_STATUS_FUNC:
27996 -+ if (!(res= check_table_access(thd, SELECT_ACL, all_tables, UINT_MAX, FALSE)))
27997 -+ res= execute_sqlcom_select(thd, all_tables);
27998 -+ break;
27999 -+ case SQLCOM_SHOW_STATUS:
28000 -+ {
28001 -+ system_status_var old_status_var= thd->status_var;
28002 -+ thd->initial_status_var= &old_status_var;
28003 -+ if (!(res= check_table_access(thd, SELECT_ACL, all_tables, UINT_MAX, FALSE)))
28004 -+ res= execute_sqlcom_select(thd, all_tables);
28005 -+ /* Don't log SHOW STATUS commands to slow query log */
28006 -+ thd->server_status&= ~(SERVER_QUERY_NO_INDEX_USED |
28007 -+ SERVER_QUERY_NO_GOOD_INDEX_USED);
28008 -+ /*
28009 -+ restore status variables, as we don't want 'show status' to cause
28010 -+ changes
28011 -+ */
28012 -+ pthread_mutex_lock(&LOCK_status);
28013 -+ add_diff_to_status(&global_status_var, &thd->status_var,
28014 -+ &old_status_var);
28015 -+ thd->status_var= old_status_var;
28016 -+ pthread_mutex_unlock(&LOCK_status);
28017 -+ break;
28018 -+ }
28019 -+ case SQLCOM_SHOW_DATABASES:
28020 -+ case SQLCOM_SHOW_TABLES:
28021 -+ case SQLCOM_SHOW_TRIGGERS:
28022 -+ case SQLCOM_SHOW_TABLE_STATUS:
28023 -+ case SQLCOM_SHOW_OPEN_TABLES:
28024 -+ case SQLCOM_SHOW_PLUGINS:
28025 -+ case SQLCOM_SHOW_FIELDS:
28026 -+ case SQLCOM_SHOW_KEYS:
28027 -+ case SQLCOM_SHOW_VARIABLES:
28028 -+ case SQLCOM_SHOW_CHARSETS:
28029 -+ case SQLCOM_SHOW_COLLATIONS:
28030 -+ case SQLCOM_SHOW_STORAGE_ENGINES:
28031 -+ case SQLCOM_SHOW_PROFILE:
28032 -+ case SQLCOM_SELECT:
28033 -+ thd->status_var.last_query_cost= 0.0;
28034 -+ if (all_tables)
28035 -+ {
28036 -+ res= check_table_access(thd,
28037 -+ lex->exchange ? SELECT_ACL | FILE_ACL :
28038 -+ SELECT_ACL,
28039 -+ all_tables, UINT_MAX, FALSE);
28040 -+ }
28041 -+ else
28042 -+ res= check_access(thd,
28043 -+ lex->exchange ? SELECT_ACL | FILE_ACL : SELECT_ACL,
28044 -+ any_db, 0, 0, 0, 0);
28045 -+
28046 -+ if (res)
28047 -+ break;
28048 -+
28049 -+ if (!thd->locked_tables && lex->protect_against_global_read_lock &&
28050 -+ !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
28051 -+ break;
28052 -+
28053 -+ res= execute_sqlcom_select(thd, all_tables);
28054 -+ break;
28055 -+ case SQLCOM_PREPARE:
28056 -+ {
28057 -+ mysql_sql_stmt_prepare(thd);
28058 -+ break;
28059 -+ }
28060 -+ case SQLCOM_EXECUTE:
28061 -+ {
28062 -+ mysql_sql_stmt_execute(thd);
28063 -+ break;
28064 -+ }
28065 -+ case SQLCOM_DEALLOCATE_PREPARE:
28066 -+ {
28067 -+ mysql_sql_stmt_close(thd);
28068 -+ break;
28069 -+ }
28070 -+ case SQLCOM_DO:
28071 -+ if (check_table_access(thd, SELECT_ACL, all_tables, UINT_MAX, FALSE) ||
28072 -+ open_and_lock_tables(thd, all_tables))
28073 -+ goto error;
28074 -+
28075 -+ res= mysql_do(thd, *lex->insert_list);
28076 -+ break;
28077 -+
28078 -+ case SQLCOM_EMPTY_QUERY:
28079 -+ my_ok(thd);
28080 -+ break;
28081 -+
28082 -+ case SQLCOM_HELP:
28083 -+ res= mysqld_help(thd,lex->help_arg);
28084 -+ break;
28085 -+
28086 -+#ifndef EMBEDDED_LIBRARY
28087 -+ case SQLCOM_PURGE:
28088 -+ {
28089 -+ if (check_global_access(thd, SUPER_ACL))
28090 -+ goto error;
28091 -+ /* PURGE MASTER LOGS TO 'file' */
28092 -+ res = purge_master_logs(thd, lex->to_log);
28093 -+ break;
28094 -+ }
28095 -+ case SQLCOM_PURGE_BEFORE:
28096 -+ {
28097 -+ Item *it;
28098 -+
28099 -+ if (check_global_access(thd, SUPER_ACL))
28100 -+ goto error;
28101 -+ /* PURGE MASTER LOGS BEFORE 'data' */
28102 -+ it= (Item *)lex->value_list.head();
28103 -+ if ((!it->fixed && it->fix_fields(lex->thd, &it)) ||
28104 -+ it->check_cols(1))
28105 -+ {
28106 -+ my_error(ER_WRONG_ARGUMENTS, MYF(0), "PURGE LOGS BEFORE");
28107 -+ goto error;
28108 -+ }
28109 -+ it= new Item_func_unix_timestamp(it);
28110 -+ /*
28111 -+ it is OK only emulate fix_fieds, because we need only
28112 -+ value of constant
28113 -+ */
28114 -+ it->quick_fix_field();
28115 -+ res = purge_master_logs_before_date(thd, (ulong)it->val_int());
28116 -+ break;
28117 -+ }
28118 -+#endif
28119 -+ case SQLCOM_SHOW_WARNS:
28120 -+ {
28121 -+ res= mysqld_show_warnings(thd, (ulong)
28122 -+ ((1L << (uint) MYSQL_ERROR::WARN_LEVEL_NOTE) |
28123 -+ (1L << (uint) MYSQL_ERROR::WARN_LEVEL_WARN) |
28124 -+ (1L << (uint) MYSQL_ERROR::WARN_LEVEL_ERROR)
28125 -+ ));
28126 -+ break;
28127 -+ }
28128 -+ case SQLCOM_SHOW_ERRORS:
28129 -+ {
28130 -+ res= mysqld_show_warnings(thd, (ulong)
28131 -+ (1L << (uint) MYSQL_ERROR::WARN_LEVEL_ERROR));
28132 -+ break;
28133 -+ }
28134 -+ case SQLCOM_SHOW_PROFILES:
28135 -+ {
28136 -+#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
28137 -+ thd->profiling.discard_current_query();
28138 -+ res= thd->profiling.show_profiles();
28139 -+ if (res)
28140 -+ goto error;
28141 -+#else
28142 -+ my_error(ER_FEATURE_DISABLED, MYF(0), "SHOW PROFILES", "enable-profiling");
28143 -+ goto error;
28144 -+#endif
28145 -+ break;
28146 -+ }
28147 -+ case SQLCOM_SHOW_NEW_MASTER:
28148 -+ {
28149 -+ if (check_global_access(thd, REPL_SLAVE_ACL))
28150 -+ goto error;
28151 -+ /* This query don't work now. See comment in repl_failsafe.cc */
28152 -+#ifndef WORKING_NEW_MASTER
28153 -+ my_error(ER_NOT_SUPPORTED_YET, MYF(0), "SHOW NEW MASTER");
28154 -+ goto error;
28155 -+#else
28156 -+ res = show_new_master(thd);
28157 -+ break;
28158 -+#endif
28159 -+ }
28160 -+
28161 -+#ifdef HAVE_REPLICATION
28162 -+ case SQLCOM_SHOW_SLAVE_HOSTS:
28163 -+ {
28164 -+ if (check_global_access(thd, REPL_SLAVE_ACL))
28165 -+ goto error;
28166 -+ res = show_slave_hosts(thd);
28167 -+ break;
28168 -+ }
28169 -+ case SQLCOM_SHOW_BINLOG_EVENTS:
28170 -+ {
28171 -+ if (check_global_access(thd, REPL_SLAVE_ACL))
28172 -+ goto error;
28173 -+ res = mysql_show_binlog_events(thd);
28174 -+ break;
28175 -+ }
28176 -+#endif
28177 -+
28178 -+ case SQLCOM_BACKUP_TABLE:
28179 -+ {
28180 -+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
28181 -+ if (check_table_access(thd, SELECT_ACL, all_tables, UINT_MAX, FALSE) ||
28182 -+ check_global_access(thd, FILE_ACL))
28183 -+ goto error; /* purecov: inspected */
28184 -+ thd->enable_slow_log= opt_log_slow_admin_statements;
28185 -+ res = mysql_backup_table(thd, first_table);
28186 -+ select_lex->table_list.first= first_table;
28187 -+ lex->query_tables=all_tables;
28188 -+ break;
28189 -+ }
28190 -+ case SQLCOM_RESTORE_TABLE:
28191 -+ {
28192 -+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
28193 -+ if (check_table_access(thd, INSERT_ACL, all_tables, UINT_MAX, FALSE) ||
28194 -+ check_global_access(thd, FILE_ACL))
28195 -+ goto error; /* purecov: inspected */
28196 -+ thd->enable_slow_log= opt_log_slow_admin_statements;
28197 -+ res = mysql_restore_table(thd, first_table);
28198 -+ select_lex->table_list.first= first_table;
28199 -+ lex->query_tables=all_tables;
28200 -+ break;
28201 -+ }
28202 -+ case SQLCOM_ASSIGN_TO_KEYCACHE:
28203 -+ {
28204 -+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
28205 -+ if (check_access(thd, INDEX_ACL, first_table->db,
28206 -+ &first_table->grant.privilege, 0, 0,
28207 -+ test(first_table->schema_table)))
28208 -+ goto error;
28209 -+ res= mysql_assign_to_keycache(thd, first_table, &lex->ident);
28210 -+ break;
28211 -+ }
28212 -+ case SQLCOM_PRELOAD_KEYS:
28213 -+ {
28214 -+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
28215 -+ if (check_access(thd, INDEX_ACL, first_table->db,
28216 -+ &first_table->grant.privilege, 0, 0,
28217 -+ test(first_table->schema_table)))
28218 -+ goto error;
28219 -+ res = mysql_preload_keys(thd, first_table);
28220 -+ break;
28221 -+ }
28222 -+#ifdef HAVE_REPLICATION
28223 -+ case SQLCOM_CHANGE_MASTER:
28224 -+ {
28225 -+ if (check_global_access(thd, SUPER_ACL))
28226 -+ goto error;
28227 -+ pthread_mutex_lock(&LOCK_active_mi);
28228 -+ res = change_master(thd,active_mi);
28229 -+ pthread_mutex_unlock(&LOCK_active_mi);
28230 -+ break;
28231 -+ }
28232 -+ case SQLCOM_SHOW_SLAVE_STAT:
28233 -+ {
28234 -+ /* Accept one of two privileges */
28235 -+ if (check_global_access(thd, SUPER_ACL | REPL_CLIENT_ACL))
28236 -+ goto error;
28237 -+ pthread_mutex_lock(&LOCK_active_mi);
28238 -+ if (active_mi != NULL)
28239 -+ {
28240 -+ res = show_master_info(thd, active_mi);
28241 -+ }
28242 -+ else
28243 -+ {
28244 -+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
28245 -+ WARN_NO_MASTER_INFO, ER(WARN_NO_MASTER_INFO));
28246 -+ my_ok(thd);
28247 -+ }
28248 -+ pthread_mutex_unlock(&LOCK_active_mi);
28249 -+ break;
28250 -+ }
28251 -+ case SQLCOM_SHOW_MASTER_STAT:
28252 -+ {
28253 -+ /* Accept one of two privileges */
28254 -+ if (check_global_access(thd, SUPER_ACL | REPL_CLIENT_ACL))
28255 -+ goto error;
28256 -+ res = show_binlog_info(thd);
28257 -+ break;
28258 -+ }
28259 -+
28260 -+ case SQLCOM_LOAD_MASTER_DATA: // sync with master
28261 -+ if (check_global_access(thd, SUPER_ACL))
28262 -+ goto error;
28263 -+ if (end_active_trans(thd))
28264 -+ goto error;
28265 -+ res = load_master_data(thd);
28266 -+ break;
28267 -+#endif /* HAVE_REPLICATION */
28268 -+ case SQLCOM_SHOW_ENGINE_STATUS:
28269 -+ {
28270 -+ if (check_global_access(thd, PROCESS_ACL))
28271 -+ goto error;
28272 -+ res = ha_show_status(thd, lex->create_info.db_type, HA_ENGINE_STATUS);
28273 -+ break;
28274 -+ }
28275 -+ case SQLCOM_SHOW_ENGINE_MUTEX:
28276 -+ {
28277 -+ if (check_global_access(thd, PROCESS_ACL))
28278 -+ goto error;
28279 -+ res = ha_show_status(thd, lex->create_info.db_type, HA_ENGINE_MUTEX);
28280 -+ break;
28281 -+ }
28282 -+#ifdef HAVE_REPLICATION
28283 -+ case SQLCOM_LOAD_MASTER_TABLE:
28284 -+ {
28285 -+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
28286 -+ DBUG_ASSERT(first_table->db); /* Must be set in the parser */
28287 -+
28288 -+ if (check_access(thd, CREATE_ACL, first_table->db,
28289 -+ &first_table->grant.privilege, 0, 0,
28290 -+ test(first_table->schema_table)))
28291 -+ goto error; /* purecov: inspected */
28292 -+ /* Check that the first table has CREATE privilege */
28293 -+ if (check_grant(thd, CREATE_ACL, all_tables, 0, 1, 0))
28294 -+ goto error;
28295 -+
28296 -+ pthread_mutex_lock(&LOCK_active_mi);
28297 -+ /*
28298 -+ fetch_master_table will send the error to the client on failure.
28299 -+ Give error if the table already exists.
28300 -+ */
28301 -+ if (!fetch_master_table(thd, first_table->db, first_table->table_name,
28302 -+ active_mi, 0, 0))
28303 -+ {
28304 -+ my_ok(thd);
28305 -+ }
28306 -+ pthread_mutex_unlock(&LOCK_active_mi);
28307 -+ break;
28308 -+ }
28309 -+#endif /* HAVE_REPLICATION */
28310 -+
28311 -+ case SQLCOM_CREATE_TABLE:
28312 -+ {
28313 -+ /* If CREATE TABLE of non-temporary table, do implicit commit */
28314 -+ if (!(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE))
28315 -+ {
28316 -+ if (end_active_trans(thd))
28317 -+ {
28318 -+ res= -1;
28319 -+ break;
28320 -+ }
28321 -+ }
28322 -+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
28323 -+ bool link_to_local;
28324 -+ // Skip first table, which is the table we are creating
28325 -+ TABLE_LIST *create_table= lex->unlink_first_table(&link_to_local);
28326 -+ TABLE_LIST *select_tables= lex->query_tables;
28327 -+ /*
28328 -+ Code below (especially in mysql_create_table() and select_create
28329 -+ methods) may modify HA_CREATE_INFO structure in LEX, so we have to
28330 -+ use a copy of this structure to make execution prepared statement-
28331 -+ safe. A shallow copy is enough as this code won't modify any memory
28332 -+ referenced from this structure.
28333 -+ */
28334 -+ HA_CREATE_INFO create_info(lex->create_info);
28335 -+ /*
28336 -+ We need to copy alter_info for the same reasons of re-execution
28337 -+ safety, only in case of Alter_info we have to do (almost) a deep
28338 -+ copy.
28339 -+ */
28340 -+ Alter_info alter_info(lex->alter_info, thd->mem_root);
28341 -+
28342 -+ if (thd->is_fatal_error)
28343 -+ {
28344 -+ /* If out of memory when creating a copy of alter_info. */
28345 -+ res= 1;
28346 -+ goto end_with_restore_list;
28347 -+ }
28348 -+
28349 -+ if ((res= create_table_precheck(thd, select_tables, create_table)))
28350 -+ goto end_with_restore_list;
28351 -+
28352 -+ /* Might have been updated in create_table_precheck */
28353 -+ create_info.alias= create_table->alias;
28354 -+
28355 -+#ifdef HAVE_READLINK
28356 -+ /* Fix names if symlinked tables */
28357 -+ if (append_file_to_dir(thd, &create_info.data_file_name,
28358 -+ create_table->table_name) ||
28359 -+ append_file_to_dir(thd, &create_info.index_file_name,
28360 -+ create_table->table_name))
28361 -+ goto end_with_restore_list;
28362 -+#endif
28363 -+ /*
28364 -+ If we are using SET CHARSET without DEFAULT, add an implicit
28365 -+ DEFAULT to not confuse old users. (This may change).
28366 -+ */
28367 -+ if ((create_info.used_fields &
28368 -+ (HA_CREATE_USED_DEFAULT_CHARSET | HA_CREATE_USED_CHARSET)) ==
28369 -+ HA_CREATE_USED_CHARSET)
28370 -+ {
28371 -+ create_info.used_fields&= ~HA_CREATE_USED_CHARSET;
28372 -+ create_info.used_fields|= HA_CREATE_USED_DEFAULT_CHARSET;
28373 -+ create_info.default_table_charset= create_info.table_charset;
28374 -+ create_info.table_charset= 0;
28375 -+ }
28376 -+ /*
28377 -+ The create-select command will open and read-lock the select table
28378 -+ and then create, open and write-lock the new table. If a global
28379 -+ read lock steps in, we get a deadlock. The write lock waits for
28380 -+ the global read lock, while the global read lock waits for the
28381 -+ select table to be closed. So we wait until the global readlock is
28382 -+ gone before starting both steps. Note that
28383 -+ wait_if_global_read_lock() sets a protection against a new global
28384 -+ read lock when it succeeds. This needs to be released by
28385 -+ start_waiting_global_read_lock(). We protect the normal CREATE
28386 -+ TABLE in the same way. That way we avoid that a new table is
28387 -+ created during a gobal read lock.
28388 -+ */
28389 -+ if (!thd->locked_tables &&
28390 -+ !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
28391 -+ {
28392 -+ res= 1;
28393 -+ goto end_with_restore_list;
28394 -+ }
28395 -+#ifdef WITH_PARTITION_STORAGE_ENGINE
28396 -+ {
28397 -+ partition_info *part_info= thd->lex->part_info;
28398 -+ if (part_info && !(part_info= thd->lex->part_info->get_clone()))
28399 -+ {
28400 -+ res= -1;
28401 -+ goto end_with_restore_list;
28402 -+ }
28403 -+ thd->work_part_info= part_info;
28404 -+ }
28405 -+#endif
28406 -+ if (select_lex->item_list.elements) // With select
28407 -+ {
28408 -+ select_result *result;
28409 -+
28410 -+ /*
28411 -+ If:
28412 -+ a) we inside an SP and there was NAME_CONST substitution,
28413 -+ b) binlogging is on (STMT mode),
28414 -+ c) we log the SP as separate statements
28415 -+ raise a warning, as it may cause problems
28416 -+ (see 'NAME_CONST issues' in 'Binary Logging of Stored Programs')
28417 -+ */
28418 -+ if (thd->query_name_consts &&
28419 -+ mysql_bin_log.is_open() &&
28420 -+ thd->variables.binlog_format == BINLOG_FORMAT_STMT &&
28421 -+ !mysql_bin_log.is_query_in_union(thd, thd->query_id))
28422 -+ {
28423 -+ List_iterator_fast<Item> it(select_lex->item_list);
28424 -+ Item *item;
28425 -+ uint splocal_refs= 0;
28426 -+ /* Count SP local vars in the top-level SELECT list */
28427 -+ while ((item= it++))
28428 -+ {
28429 -+ if (item->is_splocal())
28430 -+ splocal_refs++;
28431 -+ }
28432 -+ /*
28433 -+ If it differs from number of NAME_CONST substitution applied,
28434 -+ we may have a SOME_FUNC(NAME_CONST()) in the SELECT list,
28435 -+ that may cause a problem with binary log (see BUG#35383),
28436 -+ raise a warning.
28437 -+ */
28438 -+ if (splocal_refs != thd->query_name_consts)
28439 -+ push_warning(thd,
28440 -+ MYSQL_ERROR::WARN_LEVEL_WARN,
28441 -+ ER_UNKNOWN_ERROR,
28442 -+"Invoked routine ran a statement that may cause problems with "
28443 -+"binary log, see 'NAME_CONST issues' in 'Binary Logging of Stored Programs' "
28444 -+"section of the manual.");
28445 -+ }
28446 -+
28447 -+ select_lex->options|= SELECT_NO_UNLOCK;
28448 -+ unit->set_limit(select_lex);
28449 -+
28450 -+ /*
28451 -+ Disable non-empty MERGE tables with CREATE...SELECT. Too
28452 -+ complicated. See Bug #26379. Empty MERGE tables are read-only
28453 -+ and don't allow CREATE...SELECT anyway.
28454 -+ */
28455 -+ if (create_info.used_fields & HA_CREATE_USED_UNION)
28456 -+ {
28457 -+ my_error(ER_WRONG_OBJECT, MYF(0), create_table->db,
28458 -+ create_table->table_name, "BASE TABLE");
28459 -+ res= 1;
28460 -+ goto end_with_restore_list;
28461 -+ }
28462 -+
28463 -+ if (!(create_info.options & HA_LEX_CREATE_TMP_TABLE))
28464 -+ {
28465 -+ lex->link_first_table_back(create_table, link_to_local);
28466 -+ create_table->create= TRUE;
28467 -+ /* Base table and temporary table are not in the same name space. */
28468 -+ create_table->skip_temporary= 1;
28469 -+ }
28470 -+
28471 -+ if (!(res= open_and_lock_tables(thd, lex->query_tables)))
28472 -+ {
28473 -+ /*
28474 -+ Is table which we are changing used somewhere in other parts
28475 -+ of query
28476 -+ */
28477 -+ if (!(create_info.options & HA_LEX_CREATE_TMP_TABLE))
28478 -+ {
28479 -+ TABLE_LIST *duplicate;
28480 -+ create_table= lex->unlink_first_table(&link_to_local);
28481 -+
28482 -+ if (create_table->view)
28483 -+ {
28484 -+ if (create_info.options & HA_LEX_CREATE_IF_NOT_EXISTS)
28485 -+ {
28486 -+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
28487 -+ ER_TABLE_EXISTS_ERROR,
28488 -+ ER(ER_TABLE_EXISTS_ERROR),
28489 -+ create_info.alias);
28490 -+ my_ok(thd);
28491 -+ }
28492 -+ else
28493 -+ {
28494 -+ my_error(ER_TABLE_EXISTS_ERROR, MYF(0), create_info.alias);
28495 -+ res= 1;
28496 -+ }
28497 -+ goto end_with_restore_list;
28498 -+ }
28499 -+
28500 -+ if ((duplicate= unique_table(thd, create_table, select_tables, 0)))
28501 -+ {
28502 -+ update_non_unique_table_error(create_table, "CREATE", duplicate);
28503 -+ res= 1;
28504 -+ goto end_with_restore_list;
28505 -+ }
28506 -+ }
28507 -+ /* If we create merge table, we have to test tables in merge, too */
28508 -+ if (create_info.used_fields & HA_CREATE_USED_UNION)
28509 -+ {
28510 -+ TABLE_LIST *tab;
28511 -+ for (tab= create_info.merge_list.first;
28512 -+ tab;
28513 -+ tab= tab->next_local)
28514 -+ {
28515 -+ TABLE_LIST *duplicate;
28516 -+ if ((duplicate= unique_table(thd, tab, select_tables, 0)))
28517 -+ {
28518 -+ update_non_unique_table_error(tab, "CREATE", duplicate);
28519 -+ res= 1;
28520 -+ goto end_with_restore_list;
28521 -+ }
28522 -+ }
28523 -+ }
28524 -+
28525 -+ /* So that CREATE TEMPORARY TABLE gets to binlog at commit/rollback */
28526 -+ if (create_info.options & HA_LEX_CREATE_TMP_TABLE)
28527 -+ thd->options|= OPTION_KEEP_LOG;
28528 -+
28529 -+ /*
28530 -+ select_create is currently not re-execution friendly and
28531 -+ needs to be created for every execution of a PS/SP.
28532 -+ */
28533 -+ if ((result= new select_create(create_table,
28534 -+ &create_info,
28535 -+ &alter_info,
28536 -+ select_lex->item_list,
28537 -+ lex->duplicates,
28538 -+ lex->ignore,
28539 -+ select_tables)))
28540 -+ {
28541 -+ /*
28542 -+ CREATE from SELECT give its SELECT_LEX for SELECT,
28543 -+ and item_list belong to SELECT
28544 -+ */
28545 -+ res= handle_select(thd, lex, result, 0);
28546 -+ delete result;
28547 -+ }
28548 -+ }
28549 -+ else if (!(create_info.options & HA_LEX_CREATE_TMP_TABLE))
28550 -+ create_table= lex->unlink_first_table(&link_to_local);
28551 -+
28552 -+ }
28553 -+ else
28554 -+ {
28555 -+ /* So that CREATE TEMPORARY TABLE gets to binlog at commit/rollback */
28556 -+ if (create_info.options & HA_LEX_CREATE_TMP_TABLE)
28557 -+ thd->options|= OPTION_KEEP_LOG;
28558 -+ /* regular create */
28559 -+ if (create_info.options & HA_LEX_CREATE_TABLE_LIKE)
28560 -+ res= mysql_create_like_table(thd, create_table, select_tables,
28561 -+ &create_info);
28562 -+ else
28563 -+ {
28564 -+ res= mysql_create_table(thd, create_table->db,
28565 -+ create_table->table_name, &create_info,
28566 -+ &alter_info, 0, 0);
28567 -+ }
28568 -+ if (!res)
28569 -+ my_ok(thd);
28570 -+ }
28571 -+
28572 -+ /* put tables back for PS rexecuting */
28573 -+end_with_restore_list:
28574 -+ lex->link_first_table_back(create_table, link_to_local);
28575 -+ break;
28576 -+ }
28577 -+ case SQLCOM_CREATE_INDEX:
28578 -+ /* Fall through */
28579 -+ case SQLCOM_DROP_INDEX:
28580 -+ /*
28581 -+ CREATE INDEX and DROP INDEX are implemented by calling ALTER
28582 -+ TABLE with proper arguments.
28583 -+
28584 -+ In the future ALTER TABLE will notice that the request is to
28585 -+ only add indexes and create these one by one for the existing
28586 -+ table without having to do a full rebuild.
28587 -+ */
28588 -+ {
28589 -+ /* Prepare stack copies to be re-execution safe */
28590 -+ HA_CREATE_INFO create_info;
28591 -+ Alter_info alter_info(lex->alter_info, thd->mem_root);
28592 -+
28593 -+ if (thd->is_fatal_error) /* out of memory creating a copy of alter_info */
28594 -+ goto error;
28595 -+
28596 -+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
28597 -+ if (check_one_table_access(thd, INDEX_ACL, all_tables))
28598 -+ goto error; /* purecov: inspected */
28599 -+ if (end_active_trans(thd))
28600 -+ goto error;
28601 -+ /*
28602 -+ Currently CREATE INDEX or DROP INDEX cause a full table rebuild
28603 -+ and thus classify as slow administrative statements just like
28604 -+ ALTER TABLE.
28605 -+ */
28606 -+ thd->enable_slow_log= opt_log_slow_admin_statements;
28607 -+
28608 -+ bzero((char*) &create_info, sizeof(create_info));
28609 -+ create_info.db_type= 0;
28610 -+ create_info.row_type= ROW_TYPE_NOT_USED;
28611 -+ create_info.default_table_charset= thd->variables.collation_database;
28612 -+
28613 -+ res= mysql_alter_table(thd, first_table->db, first_table->table_name,
28614 -+ &create_info, first_table, &alter_info,
28615 -+ 0, (ORDER*) 0, 0);
28616 -+ break;
28617 -+ }
28618 -+#ifdef HAVE_REPLICATION
28619 -+ case SQLCOM_SLAVE_START:
28620 -+ {
28621 -+ pthread_mutex_lock(&LOCK_active_mi);
28622 -+ start_slave(thd,active_mi,1 /* net report*/);
28623 -+ pthread_mutex_unlock(&LOCK_active_mi);
28624 -+ break;
28625 -+ }
28626 -+ case SQLCOM_SLAVE_STOP:
28627 -+ /*
28628 -+ If the client thread has locked tables, a deadlock is possible.
28629 -+ Assume that
28630 -+ - the client thread does LOCK TABLE t READ.
28631 -+ - then the master updates t.
28632 -+ - then the SQL slave thread wants to update t,
28633 -+ so it waits for the client thread because t is locked by it.
28634 -+ - then the client thread does SLAVE STOP.
28635 -+ SLAVE STOP waits for the SQL slave thread to terminate its
28636 -+ update t, which waits for the client thread because t is locked by it.
28637 -+ To prevent that, refuse SLAVE STOP if the
28638 -+ client thread has locked tables
28639 -+ */
28640 -+ if (thd->locked_tables || thd->active_transaction() || thd->global_read_lock)
28641 -+ {
28642 -+ my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
28643 -+ ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
28644 -+ goto error;
28645 -+ }
28646 -+ {
28647 -+ pthread_mutex_lock(&LOCK_active_mi);
28648 -+ stop_slave(thd,active_mi,1/* net report*/);
28649 -+ pthread_mutex_unlock(&LOCK_active_mi);
28650 -+ break;
28651 -+ }
28652 -+#endif /* HAVE_REPLICATION */
28653 -+
28654 -+ case SQLCOM_ALTER_TABLE:
28655 -+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
28656 -+ {
28657 -+ ulong priv=0;
28658 -+ ulong priv_needed= ALTER_ACL;
28659 -+ /*
28660 -+ Code in mysql_alter_table() may modify its HA_CREATE_INFO argument,
28661 -+ so we have to use a copy of this structure to make execution
28662 -+ prepared statement- safe. A shallow copy is enough as no memory
28663 -+ referenced from this structure will be modified.
28664 -+ */
28665 -+ HA_CREATE_INFO create_info(lex->create_info);
28666 -+ Alter_info alter_info(lex->alter_info, thd->mem_root);
28667 -+
28668 -+ if (thd->is_fatal_error) /* out of memory creating a copy of alter_info */
28669 -+ goto error;
28670 -+ /*
28671 -+ We also require DROP priv for ALTER TABLE ... DROP PARTITION, as well
28672 -+ as for RENAME TO, as being done by SQLCOM_RENAME_TABLE
28673 -+ */
28674 -+ if (alter_info.flags & (ALTER_DROP_PARTITION | ALTER_RENAME))
28675 -+ priv_needed|= DROP_ACL;
28676 -+
28677 -+ /* Must be set in the parser */
28678 -+ DBUG_ASSERT(select_lex->db);
28679 -+ if (check_access(thd, priv_needed, first_table->db,
28680 -+ &first_table->grant.privilege, 0, 0,
28681 -+ test(first_table->schema_table)) ||
28682 -+ check_access(thd,INSERT_ACL | CREATE_ACL,select_lex->db,&priv,0,0,
28683 -+ is_schema_db(select_lex->db))||
28684 -+ check_merge_table_access(thd, first_table->db,
28685 -+ create_info.merge_list.first))
28686 -+ goto error; /* purecov: inspected */
28687 -+ if (check_grant(thd, priv_needed, all_tables, 0, UINT_MAX, 0))
28688 -+ goto error;
28689 -+ if (lex->name.str && !test_all_bits(priv,INSERT_ACL | CREATE_ACL))
28690 -+ { // Rename of table
28691 -+ TABLE_LIST tmp_table;
28692 -+ bzero((char*) &tmp_table,sizeof(tmp_table));
28693 -+ tmp_table.table_name= lex->name.str;
28694 -+ tmp_table.db=select_lex->db;
28695 -+ tmp_table.grant.privilege=priv;
28696 -+ if (check_grant(thd, INSERT_ACL | CREATE_ACL, &tmp_table, 0,
28697 -+ UINT_MAX, 0))
28698 -+ goto error;
28699 -+ }
28700 -+
28701 -+ /* Don't yet allow changing of symlinks with ALTER TABLE */
28702 -+ if (create_info.data_file_name)
28703 -+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
28704 -+ WARN_OPTION_IGNORED, ER(WARN_OPTION_IGNORED),
28705 -+ "DATA DIRECTORY");
28706 -+ if (create_info.index_file_name)
28707 -+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
28708 -+ WARN_OPTION_IGNORED, ER(WARN_OPTION_IGNORED),
28709 -+ "INDEX DIRECTORY");
28710 -+ create_info.data_file_name= create_info.index_file_name= NULL;
28711 -+ /* ALTER TABLE ends previous transaction */
28712 -+ if (end_active_trans(thd))
28713 -+ goto error;
28714 -+
28715 -+ if (!thd->locked_tables &&
28716 -+ !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
28717 -+ {
28718 -+ res= 1;
28719 -+ break;
28720 -+ }
28721 -+
28722 -+ thd->enable_slow_log= opt_log_slow_admin_statements;
28723 -+ res= mysql_alter_table(thd, select_lex->db, lex->name.str,
28724 -+ &create_info,
28725 -+ first_table,
28726 -+ &alter_info,
28727 -+ select_lex->order_list.elements,
28728 -+ (ORDER *) select_lex->order_list.first,
28729 -+ lex->ignore);
28730 -+ break;
28731 -+ }
28732 -+ case SQLCOM_RENAME_TABLE:
28733 -+ {
28734 -+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
28735 -+ TABLE_LIST *table;
28736 -+ for (table= first_table; table; table= table->next_local->next_local)
28737 -+ {
28738 -+ if (check_access(thd, ALTER_ACL | DROP_ACL, table->db,
28739 -+ &table->grant.privilege,0,0, test(table->schema_table)) ||
28740 -+ check_access(thd, INSERT_ACL | CREATE_ACL, table->next_local->db,
28741 -+ &table->next_local->grant.privilege, 0, 0,
28742 -+ test(table->next_local->schema_table)))
28743 -+ goto error;
28744 -+ TABLE_LIST old_list, new_list;
28745 -+ /*
28746 -+ we do not need initialize old_list and new_list because we will
28747 -+ come table[0] and table->next[0] there
28748 -+ */
28749 -+ old_list= table[0];
28750 -+ new_list= table->next_local[0];
28751 -+ if (check_grant(thd, ALTER_ACL | DROP_ACL, &old_list, 0, 1, 0) ||
28752 -+ (!test_all_bits(table->next_local->grant.privilege,
28753 -+ INSERT_ACL | CREATE_ACL) &&
28754 -+ check_grant(thd, INSERT_ACL | CREATE_ACL, &new_list, 0, 1, 0)))
28755 -+ goto error;
28756 -+ }
28757 -+
28758 -+ if (end_active_trans(thd) || mysql_rename_tables(thd, first_table, 0))
28759 -+ goto error;
28760 -+ break;
28761 -+ }
28762 -+#ifndef EMBEDDED_LIBRARY
28763 -+ case SQLCOM_SHOW_BINLOGS:
28764 -+#ifdef DONT_ALLOW_SHOW_COMMANDS
28765 -+ my_message(ER_NOT_ALLOWED_COMMAND, ER(ER_NOT_ALLOWED_COMMAND),
28766 -+ MYF(0)); /* purecov: inspected */
28767 -+ goto error;
28768 -+#else
28769 -+ {
28770 -+ if (check_global_access(thd, SUPER_ACL))
28771 -+ goto error;
28772 -+ res = show_binlogs(thd);
28773 -+ break;
28774 -+ }
28775 -+#endif
28776 -+#endif /* EMBEDDED_LIBRARY */
28777 -+ case SQLCOM_SHOW_CREATE:
28778 -+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
28779 -+#ifdef DONT_ALLOW_SHOW_COMMANDS
28780 -+ my_message(ER_NOT_ALLOWED_COMMAND, ER(ER_NOT_ALLOWED_COMMAND),
28781 -+ MYF(0)); /* purecov: inspected */
28782 -+ goto error;
28783 -+#else
28784 -+ {
28785 -+ /* Ignore temporary tables if this is "SHOW CREATE VIEW" */
28786 -+ if (lex->only_view)
28787 -+ first_table->skip_temporary= 1;
28788 -+ if (check_show_create_table_access(thd, first_table))
28789 -+ goto error;
28790 -+ res= mysqld_show_create(thd, first_table);
28791 -+ break;
28792 -+ }
28793 -+#endif
28794 -+ case SQLCOM_CHECKSUM:
28795 -+ {
28796 -+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
28797 -+ if (check_table_access(thd, SELECT_ACL | EXTRA_ACL, all_tables,
28798 -+ UINT_MAX, FALSE))
28799 -+ goto error; /* purecov: inspected */
28800 -+ res = mysql_checksum_table(thd, first_table, &lex->check_opt);
28801 -+ break;
28802 -+ }
28803 -+ case SQLCOM_REPAIR:
28804 -+ {
28805 -+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
28806 -+ if (check_table_access(thd, SELECT_ACL | INSERT_ACL, all_tables,
28807 -+ UINT_MAX, FALSE))
28808 -+ goto error; /* purecov: inspected */
28809 -+ thd->enable_slow_log= opt_log_slow_admin_statements;
28810 -+ res= mysql_repair_table(thd, first_table, &lex->check_opt);
28811 -+ /* ! we write after unlocking the table */
28812 -+ if (!res && !lex->no_write_to_binlog)
28813 -+ {
28814 -+ /*
28815 -+ Presumably, REPAIR and binlog writing doesn't require synchronization
28816 -+ */
28817 -+ res= write_bin_log(thd, TRUE, thd->query(), thd->query_length());
28818 -+ }
28819 -+ select_lex->table_list.first= first_table;
28820 -+ lex->query_tables=all_tables;
28821 -+ break;
28822 -+ }
28823 -+ case SQLCOM_CHECK:
28824 -+ {
28825 -+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
28826 -+ if (check_table_access(thd, SELECT_ACL | EXTRA_ACL , all_tables,
28827 -+ UINT_MAX, FALSE))
28828 -+ goto error; /* purecov: inspected */
28829 -+ thd->enable_slow_log= opt_log_slow_admin_statements;
28830 -+ res = mysql_check_table(thd, first_table, &lex->check_opt);
28831 -+ select_lex->table_list.first= first_table;
28832 -+ lex->query_tables=all_tables;
28833 -+ break;
28834 -+ }
28835 -+ case SQLCOM_ANALYZE:
28836 -+ {
28837 -+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
28838 -+ if (check_table_access(thd, SELECT_ACL | INSERT_ACL, all_tables,
28839 -+ UINT_MAX, FALSE))
28840 -+ goto error; /* purecov: inspected */
28841 -+ thd->enable_slow_log= opt_log_slow_admin_statements;
28842 -+ res= mysql_analyze_table(thd, first_table, &lex->check_opt);
28843 -+ /* ! we write after unlocking the table */
28844 -+ if (!res && !lex->no_write_to_binlog)
28845 -+ {
28846 -+ /*
28847 -+ Presumably, ANALYZE and binlog writing doesn't require synchronization
28848 -+ */
28849 -+ res= write_bin_log(thd, TRUE, thd->query(), thd->query_length());
28850 -+ }
28851 -+ select_lex->table_list.first= first_table;
28852 -+ lex->query_tables=all_tables;
28853 -+ break;
28854 -+ }
28855 -+
28856 -+ case SQLCOM_OPTIMIZE:
28857 -+ {
28858 -+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
28859 -+ if (check_table_access(thd, SELECT_ACL | INSERT_ACL, all_tables,
28860 -+ UINT_MAX, FALSE))
28861 -+ goto error; /* purecov: inspected */
28862 -+ thd->enable_slow_log= opt_log_slow_admin_statements;
28863 -+ res= (specialflag & (SPECIAL_SAFE_MODE | SPECIAL_NO_NEW_FUNC)) ?
28864 -+ mysql_recreate_table(thd, first_table) :
28865 -+ mysql_optimize_table(thd, first_table, &lex->check_opt);
28866 -+ /* ! we write after unlocking the table */
28867 -+ if (!res && !lex->no_write_to_binlog)
28868 -+ {
28869 -+ /*
28870 -+ Presumably, OPTIMIZE and binlog writing doesn't require synchronization
28871 -+ */
28872 -+ res= write_bin_log(thd, TRUE, thd->query(), thd->query_length());
28873 -+ }
28874 -+ select_lex->table_list.first= first_table;
28875 -+ lex->query_tables=all_tables;
28876 -+ break;
28877 -+ }
28878 -+ case SQLCOM_UPDATE:
28879 -+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
28880 -+ if (update_precheck(thd, all_tables))
28881 -+ break;
28882 -+ if (!thd->locked_tables &&
28883 -+ !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
28884 -+ goto error;
28885 -+ DBUG_ASSERT(select_lex->offset_limit == 0);
28886 -+ unit->set_limit(select_lex);
28887 -+ res= (up_result= mysql_update(thd, all_tables,
28888 -+ select_lex->item_list,
28889 -+ lex->value_list,
28890 -+ select_lex->where,
28891 -+ select_lex->order_list.elements,
28892 -+ select_lex->order_list.first,
28893 -+ unit->select_limit_cnt,
28894 -+ lex->duplicates, lex->ignore));
28895 -+ /* mysql_update return 2 if we need to switch to multi-update */
28896 -+ if (up_result != 2)
28897 -+ break;
28898 -+ /* Fall through */
28899 -+ case SQLCOM_UPDATE_MULTI:
28900 -+ {
28901 -+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
28902 -+ /* if we switched from normal update, rights are checked */
28903 -+ if (up_result != 2)
28904 -+ {
28905 -+ if ((res= multi_update_precheck(thd, all_tables)))
28906 -+ break;
28907 -+ }
28908 -+ else
28909 -+ res= 0;
28910 -+
28911 -+ /*
28912 -+ Protection might have already been risen if its a fall through
28913 -+ from the SQLCOM_UPDATE case above.
28914 -+ */
28915 -+ if (!thd->locked_tables &&
28916 -+ lex->sql_command == SQLCOM_UPDATE_MULTI &&
28917 -+ !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
28918 -+ goto error;
28919 -+
28920 -+ res= mysql_multi_update_prepare(thd);
28921 -+
28922 -+#ifdef HAVE_REPLICATION
28923 -+ /* Check slave filtering rules */
28924 -+ if (unlikely(thd->slave_thread && !have_table_map_for_update))
28925 -+ {
28926 -+ if (all_tables_not_ok(thd, all_tables))
28927 -+ {
28928 -+ if (res!= 0)
28929 -+ {
28930 -+ res= 0; /* don't care of prev failure */
28931 -+ thd->clear_error(); /* filters are of highest prior */
28932 -+ }
28933 -+ /* we warn the slave SQL thread */
28934 -+ my_error(ER_SLAVE_IGNORED_TABLE, MYF(0));
28935 -+ break;
28936 -+ }
28937 -+ if (res)
28938 -+ break;
28939 -+ }
28940 -+ else
28941 -+ {
28942 -+#endif /* HAVE_REPLICATION */
28943 -+ if (res)
28944 -+ break;
28945 -+ if (opt_readonly &&
28946 -+ !(thd->security_ctx->master_access & SUPER_ACL) &&
28947 -+ some_non_temp_table_to_be_updated(thd, all_tables))
28948 -+ {
28949 -+ my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only");
28950 -+ break;
28951 -+ }
28952 -+#ifdef HAVE_REPLICATION
28953 -+ } /* unlikely */
28954 -+#endif
28955 -+
28956 -+ res= mysql_multi_update(thd, all_tables,
28957 -+ &select_lex->item_list,
28958 -+ &lex->value_list,
28959 -+ select_lex->where,
28960 -+ select_lex->options,
28961 -+ lex->duplicates, lex->ignore, unit, select_lex);
28962 -+ break;
28963 -+ }
28964 -+ case SQLCOM_REPLACE:
28965 -+#ifndef DBUG_OFF
28966 -+ if (mysql_bin_log.is_open())
28967 -+ {
28968 -+ /*
28969 -+ Generate an incident log event before writing the real event
28970 -+ to the binary log. We put this event is before the statement
28971 -+ since that makes it simpler to check that the statement was
28972 -+ not executed on the slave (since incidents usually stop the
28973 -+ slave).
28974 -+
28975 -+ Observe that any row events that are generated will be
28976 -+ generated before.
28977 -+
28978 -+ This is only for testing purposes and will not be present in a
28979 -+ release build.
28980 -+ */
28981 -+
28982 -+ Incident incident= INCIDENT_NONE;
28983 -+ DBUG_PRINT("debug", ("Just before generate_incident()"));
28984 -+ DBUG_EXECUTE_IF("incident_database_resync_on_replace",
28985 -+ incident= INCIDENT_LOST_EVENTS;);
28986 -+ if (incident)
28987 -+ {
28988 -+ Incident_log_event ev(thd, incident);
28989 -+ (void) mysql_bin_log.write(&ev); /* error is ignored */
28990 -+ if (mysql_bin_log.rotate_and_purge(RP_FORCE_ROTATE))
28991 -+ {
28992 -+ res= 1;
28993 -+ break;
28994 -+ }
28995 -+ }
28996 -+ DBUG_PRINT("debug", ("Just after generate_incident()"));
28997 -+ }
28998 -+#endif
28999 -+ case SQLCOM_INSERT:
29000 -+ {
29001 -+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
29002 -+ if ((res= insert_precheck(thd, all_tables)))
29003 -+ break;
29004 -+
29005 -+ if (!thd->locked_tables &&
29006 -+ !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
29007 -+ {
29008 -+ res= 1;
29009 -+ break;
29010 -+ }
29011 -+
29012 -+ res= mysql_insert(thd, all_tables, lex->field_list, lex->many_values,
29013 -+ lex->update_list, lex->value_list,
29014 -+ lex->duplicates, lex->ignore);
29015 -+
29016 -+ /*
29017 -+ If we have inserted into a VIEW, and the base table has
29018 -+ AUTO_INCREMENT column, but this column is not accessible through
29019 -+ a view, then we should restore LAST_INSERT_ID to the value it
29020 -+ had before the statement.
29021 -+ */
29022 -+ if (first_table->view && !first_table->contain_auto_increment)
29023 -+ thd->first_successful_insert_id_in_cur_stmt=
29024 -+ thd->first_successful_insert_id_in_prev_stmt;
29025 -+
29026 -+ DBUG_EXECUTE_IF("after_mysql_insert",
29027 -+ {
29028 -+ const char act[]=
29029 -+ "now "
29030 -+ "wait_for signal.continue";
29031 -+ DBUG_ASSERT(opt_debug_sync_timeout > 0);
29032 -+ DBUG_ASSERT(!debug_sync_set_action(current_thd,
29033 -+ STRING_WITH_LEN(act)));
29034 -+ };);
29035 -+ break;
29036 -+ }
29037 -+ case SQLCOM_REPLACE_SELECT:
29038 -+ case SQLCOM_INSERT_SELECT:
29039 -+ {
29040 -+ select_result *sel_result;
29041 -+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
29042 -+ if ((res= insert_precheck(thd, all_tables)))
29043 -+ break;
29044 -+
29045 -+ /* Fix lock for first table */
29046 -+ if (first_table->lock_type == TL_WRITE_DELAYED)
29047 -+ first_table->lock_type= TL_WRITE;
29048 -+
29049 -+ /* Don't unlock tables until command is written to binary log */
29050 -+ select_lex->options|= SELECT_NO_UNLOCK;
29051 -+
29052 -+ unit->set_limit(select_lex);
29053 -+
29054 -+ if (! thd->locked_tables &&
29055 -+ ! (need_start_waiting= ! wait_if_global_read_lock(thd, 0, 1)))
29056 -+ {
29057 -+ res= 1;
29058 -+ break;
29059 -+ }
29060 -+
29061 -+ if (!(res= open_and_lock_tables(thd, all_tables)))
29062 -+ {
29063 -+ /* Skip first table, which is the table we are inserting in */
29064 -+ TABLE_LIST *second_table= first_table->next_local;
29065 -+ select_lex->table_list.first= second_table;
29066 -+ select_lex->context.table_list=
29067 -+ select_lex->context.first_name_resolution_table= second_table;
29068 -+ res= mysql_insert_select_prepare(thd);
29069 -+ if (!res && (sel_result= new select_insert(first_table,
29070 -+ first_table->table,
29071 -+ &lex->field_list,
29072 -+ &lex->update_list,
29073 -+ &lex->value_list,
29074 -+ lex->duplicates,
29075 -+ lex->ignore)))
29076 -+ {
29077 -+ res= handle_select(thd, lex, sel_result, OPTION_SETUP_TABLES_DONE);
29078 -+ /*
29079 -+ Invalidate the table in the query cache if something changed
29080 -+ after unlocking when changes become visible.
29081 -+ TODO: this is workaround. right way will be move invalidating in
29082 -+ the unlock procedure.
29083 -+ */
29084 -+ if (!res && first_table->lock_type == TL_WRITE_CONCURRENT_INSERT &&
29085 -+ thd->lock)
29086 -+ {
29087 -+ /* INSERT ... SELECT should invalidate only the very first table */
29088 -+ TABLE_LIST *save_table= first_table->next_local;
29089 -+ first_table->next_local= 0;
29090 -+ query_cache_invalidate3(thd, first_table, 1);
29091 -+ first_table->next_local= save_table;
29092 -+ }
29093 -+ delete sel_result;
29094 -+ }
29095 -+ /* revert changes for SP */
29096 -+ select_lex->table_list.first= first_table;
29097 -+ }
29098 -+
29099 -+ /*
29100 -+ If we have inserted into a VIEW, and the base table has
29101 -+ AUTO_INCREMENT column, but this column is not accessible through
29102 -+ a view, then we should restore LAST_INSERT_ID to the value it
29103 -+ had before the statement.
29104 -+ */
29105 -+ if (first_table->view && !first_table->contain_auto_increment)
29106 -+ thd->first_successful_insert_id_in_cur_stmt=
29107 -+ thd->first_successful_insert_id_in_prev_stmt;
29108 -+
29109 -+ break;
29110 -+ }
29111 -+ case SQLCOM_TRUNCATE:
29112 -+ if (end_active_trans(thd))
29113 -+ {
29114 -+ res= -1;
29115 -+ break;
29116 -+ }
29117 -+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
29118 -+ if (check_one_table_access(thd, DROP_ACL, all_tables))
29119 -+ goto error;
29120 -+ /*
29121 -+ Don't allow this within a transaction because we want to use
29122 -+ re-generate table
29123 -+ */
29124 -+ if (thd->locked_tables || thd->active_transaction())
29125 -+ {
29126 -+ my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
29127 -+ ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
29128 -+ goto error;
29129 -+ }
29130 -+ if (!(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
29131 -+ goto error;
29132 -+ res= mysql_truncate(thd, first_table, 0);
29133 -+ break;
29134 -+ case SQLCOM_DELETE:
29135 -+ {
29136 -+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
29137 -+ if ((res= delete_precheck(thd, all_tables)))
29138 -+ break;
29139 -+ DBUG_ASSERT(select_lex->offset_limit == 0);
29140 -+ unit->set_limit(select_lex);
29141 -+
29142 -+ if (!thd->locked_tables &&
29143 -+ !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
29144 -+ {
29145 -+ res= 1;
29146 -+ break;
29147 -+ }
29148 -+
29149 -+ res = mysql_delete(thd, all_tables, select_lex->where,
29150 -+ &select_lex->order_list,
29151 -+ unit->select_limit_cnt, select_lex->options,
29152 -+ FALSE);
29153 -+ break;
29154 -+ }
29155 -+ case SQLCOM_DELETE_MULTI:
29156 -+ {
29157 -+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
29158 -+ TABLE_LIST *aux_tables= thd->lex->auxiliary_table_list.first;
29159 -+ multi_delete *del_result;
29160 -+
29161 -+ if (!thd->locked_tables &&
29162 -+ !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
29163 -+ {
29164 -+ res= 1;
29165 -+ break;
29166 -+ }
29167 -+
29168 -+ if ((res= multi_delete_precheck(thd, all_tables)))
29169 -+ break;
29170 -+
29171 -+ /* condition will be TRUE on SP re-excuting */
29172 -+ if (select_lex->item_list.elements != 0)
29173 -+ select_lex->item_list.empty();
29174 -+ if (add_item_to_list(thd, new Item_null()))
29175 -+ goto error;
29176 -+
29177 -+ thd_proc_info(thd, "init");
29178 -+ if ((res= open_and_lock_tables(thd, all_tables)))
29179 -+ break;
29180 -+
29181 -+ if ((res= mysql_multi_delete_prepare(thd)))
29182 -+ goto error;
29183 -+
29184 -+ if (!thd->is_fatal_error &&
29185 -+ (del_result= new multi_delete(aux_tables, lex->table_count)))
29186 -+ {
29187 -+ res= mysql_select(thd, &select_lex->ref_pointer_array,
29188 -+ select_lex->get_table_list(),
29189 -+ select_lex->with_wild,
29190 -+ select_lex->item_list,
29191 -+ select_lex->where,
29192 -+ 0, (ORDER *)NULL, (ORDER *)NULL, (Item *)NULL,
29193 -+ (ORDER *)NULL,
29194 -+ (select_lex->options | thd->options |
29195 -+ SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK |
29196 -+ OPTION_SETUP_TABLES_DONE) & ~OPTION_BUFFER_RESULT,
29197 -+ del_result, unit, select_lex);
29198 -+ res|= thd->is_error();
29199 -+ if (res)
29200 -+ del_result->abort();
29201 -+ delete del_result;
29202 -+ }
29203 -+ else
29204 -+ res= TRUE; // Error
29205 -+ break;
29206 -+ }
29207 -+ case SQLCOM_DROP_TABLE:
29208 -+ {
29209 -+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
29210 -+ if (!lex->drop_temporary)
29211 -+ {
29212 -+ if (check_table_access(thd, DROP_ACL, all_tables, UINT_MAX, FALSE))
29213 -+ goto error; /* purecov: inspected */
29214 -+ if (end_active_trans(thd))
29215 -+ goto error;
29216 -+ }
29217 -+ else
29218 -+ {
29219 -+ /* So that DROP TEMPORARY TABLE gets to binlog at commit/rollback */
29220 -+ thd->options|= OPTION_KEEP_LOG;
29221 -+ }
29222 -+ /* DDL and binlog write order protected by LOCK_open */
29223 -+ res= mysql_rm_table(thd, first_table, lex->drop_if_exists,
29224 -+ lex->drop_temporary);
29225 -+ }
29226 -+ break;
29227 -+ case SQLCOM_SHOW_PROCESSLIST:
29228 -+ if (!thd->security_ctx->priv_user[0] &&
29229 -+ check_global_access(thd,PROCESS_ACL))
29230 -+ break;
29231 -+ mysqld_list_processes(thd,
29232 -+ (thd->security_ctx->master_access & PROCESS_ACL ?
29233 -+ NullS :
29234 -+ thd->security_ctx->priv_user),
29235 -+ lex->verbose);
29236 -+ break;
29237 -+ case SQLCOM_SHOW_AUTHORS:
29238 -+ res= mysqld_show_authors(thd);
29239 -+ break;
29240 -+ case SQLCOM_SHOW_CONTRIBUTORS:
29241 -+ res= mysqld_show_contributors(thd);
29242 -+ break;
29243 -+ case SQLCOM_SHOW_PRIVILEGES:
29244 -+ res= mysqld_show_privileges(thd);
29245 -+ break;
29246 -+ case SQLCOM_SHOW_COLUMN_TYPES:
29247 -+ res= mysqld_show_column_types(thd);
29248 -+ break;
29249 -+ case SQLCOM_SHOW_ENGINE_LOGS:
29250 -+#ifdef DONT_ALLOW_SHOW_COMMANDS
29251 -+ my_message(ER_NOT_ALLOWED_COMMAND, ER(ER_NOT_ALLOWED_COMMAND),
29252 -+ MYF(0)); /* purecov: inspected */
29253 -+ goto error;
29254 -+#else
29255 -+ {
29256 -+ if (check_access(thd, FILE_ACL, any_db,0,0,0,0))
29257 -+ goto error;
29258 -+ res= ha_show_status(thd, lex->create_info.db_type, HA_ENGINE_LOGS);
29259 -+ break;
29260 -+ }
29261 -+#endif
29262 -+ case SQLCOM_CHANGE_DB:
29263 -+ {
29264 -+ LEX_STRING db_str= { (char *) select_lex->db, strlen(select_lex->db) };
29265 -+
29266 -+ if (!mysql_change_db(thd, &db_str, FALSE))
29267 -+ my_ok(thd);
29268 -+
29269 -+ break;
29270 -+ }
29271 -+
29272 -+ case SQLCOM_LOAD:
29273 -+ {
29274 -+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
29275 -+ uint privilege= (lex->duplicates == DUP_REPLACE ?
29276 -+ INSERT_ACL | DELETE_ACL : INSERT_ACL) |
29277 -+ (lex->local_file ? 0 : FILE_ACL);
29278 -+
29279 -+ if (lex->local_file)
29280 -+ {
29281 -+ if (!(thd->client_capabilities & CLIENT_LOCAL_FILES) ||
29282 -+ !opt_local_infile)
29283 -+ {
29284 -+ my_message(ER_NOT_ALLOWED_COMMAND, ER(ER_NOT_ALLOWED_COMMAND), MYF(0));
29285 -+ goto error;
29286 -+ }
29287 -+ }
29288 -+
29289 -+ if (check_one_table_access(thd, privilege, all_tables))
29290 -+ goto error;
29291 -+
29292 -+ if (!thd->locked_tables &&
29293 -+ !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
29294 -+ goto error;
29295 -+
29296 -+ res= mysql_load(thd, lex->exchange, first_table, lex->field_list,
29297 -+ lex->update_list, lex->value_list, lex->duplicates,
29298 -+ lex->ignore, (bool) lex->local_file);
29299 -+ break;
29300 -+ }
29301 -+
29302 -+ case SQLCOM_SET_OPTION:
29303 -+ {
29304 -+ List<set_var_base> *lex_var_list= &lex->var_list;
29305 -+
29306 -+ if (lex->autocommit && end_active_trans(thd))
29307 -+ goto error;
29308 -+
29309 -+ if ((check_table_access(thd, SELECT_ACL, all_tables, UINT_MAX, FALSE) ||
29310 -+ open_and_lock_tables(thd, all_tables)))
29311 -+ goto error;
29312 -+ if (lex->one_shot_set && not_all_support_one_shot(lex_var_list))
29313 -+ {
29314 -+ my_error(ER_RESERVED_SYNTAX, MYF(0), "SET ONE_SHOT");
29315 -+ goto error;
29316 -+ }
29317 -+ if (!(res= sql_set_variables(thd, lex_var_list)))
29318 -+ {
29319 -+ /*
29320 -+ If the previous command was a SET ONE_SHOT, we don't want to forget
29321 -+ about the ONE_SHOT property of that SET. So we use a |= instead of = .
29322 -+ */
29323 -+ thd->one_shot_set|= lex->one_shot_set;
29324 -+ my_ok(thd);
29325 -+ }
29326 -+ else
29327 -+ {
29328 -+ /*
29329 -+ We encountered some sort of error, but no message was sent.
29330 -+ Send something semi-generic here since we don't know which
29331 -+ assignment in the list caused the error.
29332 -+ */
29333 -+ if (!thd->is_error())
29334 -+ my_error(ER_WRONG_ARGUMENTS,MYF(0),"SET");
29335 -+ goto error;
29336 -+ }
29337 -+
29338 -+ break;
29339 -+ }
29340 -+
29341 -+ case SQLCOM_UNLOCK_TABLES:
29342 -+ /*
29343 -+ It is critical for mysqldump --single-transaction --master-data that
29344 -+ UNLOCK TABLES does not implicitely commit a connection which has only
29345 -+ done FLUSH TABLES WITH READ LOCK + BEGIN. If this assumption becomes
29346 -+ false, mysqldump will not work.
29347 -+ */
29348 -+ unlock_locked_tables(thd);
29349 -+ if (thd->options & OPTION_TABLE_LOCK)
29350 -+ {
29351 -+ end_active_trans(thd);
29352 -+ thd->options&= ~(OPTION_TABLE_LOCK);
29353 -+ }
29354 -+ if (thd->global_read_lock)
29355 -+ unlock_global_read_lock(thd);
29356 -+ my_ok(thd);
29357 -+ break;
29358 -+ case SQLCOM_LOCK_TABLES:
29359 -+ unlock_locked_tables(thd);
29360 -+ /* we must end the trasaction first, regardless of anything */
29361 -+ if (end_active_trans(thd))
29362 -+ goto error;
29363 -+ if (check_table_access(thd, LOCK_TABLES_ACL | SELECT_ACL, all_tables,
29364 -+ UINT_MAX, FALSE))
29365 -+ goto error;
29366 -+ if (lex->protect_against_global_read_lock &&
29367 -+ !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
29368 -+ goto error;
29369 -+ thd->in_lock_tables=1;
29370 -+ thd->options|= OPTION_TABLE_LOCK;
29371 -+
29372 -+ if (!(res= simple_open_n_lock_tables(thd, all_tables)))
29373 -+ {
29374 -+#ifdef HAVE_QUERY_CACHE
29375 -+ if (thd->variables.query_cache_wlock_invalidate)
29376 -+ query_cache.invalidate_locked_for_write(first_table);
29377 -+#endif /*HAVE_QUERY_CACHE*/
29378 -+ thd->locked_tables=thd->lock;
29379 -+ thd->lock=0;
29380 -+ my_ok(thd);
29381 -+ }
29382 -+ else
29383 -+ {
29384 -+ /*
29385 -+ Need to end the current transaction, so the storage engine (InnoDB)
29386 -+ can free its locks if LOCK TABLES locked some tables before finding
29387 -+ that it can't lock a table in its list
29388 -+ */
29389 -+ ha_autocommit_or_rollback(thd, 1);
29390 -+ end_active_trans(thd);
29391 -+ thd->options&= ~(OPTION_TABLE_LOCK);
29392 -+ }
29393 -+ thd->in_lock_tables=0;
29394 -+ break;
29395 -+ case SQLCOM_CREATE_DB:
29396 -+ {
29397 -+ /*
29398 -+ As mysql_create_db() may modify HA_CREATE_INFO structure passed to
29399 -+ it, we need to use a copy of LEX::create_info to make execution
29400 -+ prepared statement- safe.
29401 -+ */
29402 -+ HA_CREATE_INFO create_info(lex->create_info);
29403 -+ if (end_active_trans(thd))
29404 -+ {
29405 -+ res= -1;
29406 -+ break;
29407 -+ }
29408 -+ char *alias;
29409 -+ if (!(alias=thd->strmake(lex->name.str, lex->name.length)) ||
29410 -+ check_db_name(&lex->name))
29411 -+ {
29412 -+ my_error(ER_WRONG_DB_NAME, MYF(0), lex->name.str);
29413 -+ break;
29414 -+ }
29415 -+ /*
29416 -+ If in a slave thread :
29417 -+ CREATE DATABASE DB was certainly not preceded by USE DB.
29418 -+ For that reason, db_ok() in sql/slave.cc did not check the
29419 -+ do_db/ignore_db. And as this query involves no tables, tables_ok()
29420 -+ above was not called. So we have to check rules again here.
29421 -+ */
29422 -+#ifdef HAVE_REPLICATION
29423 -+ if (thd->slave_thread &&
29424 -+ (!rpl_filter->db_ok(lex->name.str) ||
29425 -+ !rpl_filter->db_ok_with_wild_table(lex->name.str)))
29426 -+ {
29427 -+ my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0));
29428 -+ break;
29429 -+ }
29430 -+#endif
29431 -+ if (check_access(thd,CREATE_ACL,lex->name.str, 0, 1, 0,
29432 -+ is_schema_db(lex->name.str, lex->name.length)))
29433 -+ break;
29434 -+ res= mysql_create_db(thd,(lower_case_table_names == 2 ? alias :
29435 -+ lex->name.str), &create_info, 0);
29436 -+ break;
29437 -+ }
29438 -+ case SQLCOM_DROP_DB:
29439 -+ {
29440 -+ if (end_active_trans(thd))
29441 -+ {
29442 -+ res= -1;
29443 -+ break;
29444 -+ }
29445 -+ if (check_db_name(&lex->name))
29446 -+ {
29447 -+ my_error(ER_WRONG_DB_NAME, MYF(0), lex->name.str);
29448 -+ break;
29449 -+ }
29450 -+ /*
29451 -+ If in a slave thread :
29452 -+ DROP DATABASE DB may not be preceded by USE DB.
29453 -+ For that reason, maybe db_ok() in sql/slave.cc did not check the
29454 -+ do_db/ignore_db. And as this query involves no tables, tables_ok()
29455 -+ above was not called. So we have to check rules again here.
29456 -+ */
29457 -+#ifdef HAVE_REPLICATION
29458 -+ if (thd->slave_thread &&
29459 -+ (!rpl_filter->db_ok(lex->name.str) ||
29460 -+ !rpl_filter->db_ok_with_wild_table(lex->name.str)))
29461 -+ {
29462 -+ my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0));
29463 -+ break;
29464 -+ }
29465 -+#endif
29466 -+ if (check_access(thd,DROP_ACL,lex->name.str,0,1,0,
29467 -+ is_schema_db(lex->name.str, lex->name.length)))
29468 -+ break;
29469 -+ if (thd->locked_tables || thd->active_transaction())
29470 -+ {
29471 -+ my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
29472 -+ ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
29473 -+ goto error;
29474 -+ }
29475 -+ res= mysql_rm_db(thd, lex->name.str, lex->drop_if_exists, 0);
29476 -+ break;
29477 -+ }
29478 -+ case SQLCOM_ALTER_DB_UPGRADE:
29479 -+ {
29480 -+ LEX_STRING *db= & lex->name;
29481 -+ if (end_active_trans(thd))
29482 -+ {
29483 -+ res= 1;
29484 -+ break;
29485 -+ }
29486 -+#ifdef HAVE_REPLICATION
29487 -+ if (thd->slave_thread &&
29488 -+ (!rpl_filter->db_ok(db->str) ||
29489 -+ !rpl_filter->db_ok_with_wild_table(db->str)))
29490 -+ {
29491 -+ res= 1;
29492 -+ my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0));
29493 -+ break;
29494 -+ }
29495 -+#endif
29496 -+ if (check_db_name(db))
29497 -+ {
29498 -+ my_error(ER_WRONG_DB_NAME, MYF(0), db->str);
29499 -+ break;
29500 -+ }
29501 -+ if (check_access(thd, ALTER_ACL, db->str, 0, 1, 0,
29502 -+ is_schema_db(db->str, db->length)) ||
29503 -+ check_access(thd, DROP_ACL, db->str, 0, 1, 0,
29504 -+ is_schema_db(db->str, db->length)) ||
29505 -+ check_access(thd, CREATE_ACL, db->str, 0, 1, 0,
29506 -+ is_schema_db(db->str, db->length)))
29507 -+ {
29508 -+ res= 1;
29509 -+ break;
29510 -+ }
29511 -+ if (thd->locked_tables || thd->active_transaction())
29512 -+ {
29513 -+ res= 1;
29514 -+ my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
29515 -+ ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
29516 -+ goto error;
29517 -+ }
29518 -+
29519 -+ res= mysql_upgrade_db(thd, db);
29520 -+ if (!res)
29521 -+ my_ok(thd);
29522 -+ break;
29523 -+ }
29524 -+ case SQLCOM_ALTER_DB:
29525 -+ {
29526 -+ LEX_STRING *db= &lex->name;
29527 -+ HA_CREATE_INFO create_info(lex->create_info);
29528 -+ if (check_db_name(db))
29529 -+ {
29530 -+ my_error(ER_WRONG_DB_NAME, MYF(0), db->str);
29531 -+ break;
29532 -+ }
29533 -+ /*
29534 -+ If in a slave thread :
29535 -+ ALTER DATABASE DB may not be preceded by USE DB.
29536 -+ For that reason, maybe db_ok() in sql/slave.cc did not check the
29537 -+ do_db/ignore_db. And as this query involves no tables, tables_ok()
29538 -+ above was not called. So we have to check rules again here.
29539 -+ */
29540 -+#ifdef HAVE_REPLICATION
29541 -+ if (thd->slave_thread &&
29542 -+ (!rpl_filter->db_ok(db->str) ||
29543 -+ !rpl_filter->db_ok_with_wild_table(db->str)))
29544 -+ {
29545 -+ my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0));
29546 -+ break;
29547 -+ }
29548 -+#endif
29549 -+ if (check_access(thd, ALTER_ACL, db->str, 0, 1, 0,
29550 -+ is_schema_db(db->str, db->length)))
29551 -+ break;
29552 -+ if (thd->locked_tables || thd->active_transaction())
29553 -+ {
29554 -+ my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
29555 -+ ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
29556 -+ goto error;
29557 -+ }
29558 -+ res= mysql_alter_db(thd, db->str, &create_info);
29559 -+ break;
29560 -+ }
29561 -+ case SQLCOM_SHOW_CREATE_DB:
29562 -+ {
29563 -+ DBUG_EXECUTE_IF("4x_server_emul",
29564 -+ my_error(ER_UNKNOWN_ERROR, MYF(0)); goto error;);
29565 -+ if (check_db_name(&lex->name))
29566 -+ {
29567 -+ my_error(ER_WRONG_DB_NAME, MYF(0), lex->name.str);
29568 -+ break;
29569 -+ }
29570 -+ res= mysqld_show_create_db(thd, lex->name.str, &lex->create_info);
29571 -+ break;
29572 -+ }
29573 -+ case SQLCOM_CREATE_EVENT:
29574 -+ case SQLCOM_ALTER_EVENT:
29575 -+ #ifdef HAVE_EVENT_SCHEDULER
29576 -+ do
29577 -+ {
29578 -+ DBUG_ASSERT(lex->event_parse_data);
29579 -+ if (lex->table_or_sp_used())
29580 -+ {
29581 -+ my_error(ER_NOT_SUPPORTED_YET, MYF(0), "Usage of subqueries or stored "
29582 -+ "function calls as part of this statement");
29583 -+ break;
29584 -+ }
29585 -+
29586 -+ res= sp_process_definer(thd);
29587 -+ if (res)
29588 -+ break;
29589 -+
29590 -+ switch (lex->sql_command) {
29591 -+ case SQLCOM_CREATE_EVENT:
29592 -+ {
29593 -+ bool if_not_exists= (lex->create_info.options &
29594 -+ HA_LEX_CREATE_IF_NOT_EXISTS);
29595 -+ res= Events::create_event(thd, lex->event_parse_data, if_not_exists);
29596 -+ break;
29597 -+ }
29598 -+ case SQLCOM_ALTER_EVENT:
29599 -+ res= Events::update_event(thd, lex->event_parse_data,
29600 -+ lex->spname ? &lex->spname->m_db : NULL,
29601 -+ lex->spname ? &lex->spname->m_name : NULL);
29602 -+ break;
29603 -+ default:
29604 -+ DBUG_ASSERT(0);
29605 -+ }
29606 -+ DBUG_PRINT("info",("DDL error code=%d", res));
29607 -+ if (!res)
29608 -+ my_ok(thd);
29609 -+
29610 -+ } while (0);
29611 -+ /* Don't do it, if we are inside a SP */
29612 -+ if (!thd->spcont)
29613 -+ {
29614 -+ delete lex->sphead;
29615 -+ lex->sphead= NULL;
29616 -+ }
29617 -+ /* lex->unit.cleanup() is called outside, no need to call it here */
29618 -+ break;
29619 -+ case SQLCOM_SHOW_CREATE_EVENT:
29620 -+ res= Events::show_create_event(thd, lex->spname->m_db,
29621 -+ lex->spname->m_name);
29622 -+ break;
29623 -+ case SQLCOM_DROP_EVENT:
29624 -+ if (!(res= Events::drop_event(thd,
29625 -+ lex->spname->m_db, lex->spname->m_name,
29626 -+ lex->drop_if_exists)))
29627 -+ my_ok(thd);
29628 -+ break;
29629 -+#else
29630 -+ my_error(ER_NOT_SUPPORTED_YET,MYF(0),"embedded server");
29631 -+ break;
29632 -+#endif
29633 -+ case SQLCOM_CREATE_FUNCTION: // UDF function
29634 -+ {
29635 -+ if (check_access(thd,INSERT_ACL,"mysql",0,1,0,0))
29636 -+ break;
29637 -+#ifdef HAVE_DLOPEN
29638 -+ if (!(res = mysql_create_function(thd, &lex->udf)))
29639 -+ my_ok(thd);
29640 -+#else
29641 -+ my_error(ER_CANT_OPEN_LIBRARY, MYF(0), lex->udf.dl, 0, "feature disabled");
29642 -+ res= TRUE;
29643 -+#endif
29644 -+ break;
29645 -+ }
29646 -+#ifndef NO_EMBEDDED_ACCESS_CHECKS
29647 -+ case SQLCOM_CREATE_USER:
29648 -+ {
29649 -+ if (check_access(thd, INSERT_ACL, "mysql", 0, 1, 1, 0) &&
29650 -+ check_global_access(thd,CREATE_USER_ACL))
29651 -+ break;
29652 -+ if (end_active_trans(thd))
29653 -+ goto error;
29654 -+ /* Conditionally writes to binlog */
29655 -+ if (!(res= mysql_create_user(thd, lex->users_list)))
29656 -+ my_ok(thd);
29657 -+ break;
29658 -+ }
29659 -+ case SQLCOM_DROP_USER:
29660 -+ {
29661 -+ if (check_access(thd, DELETE_ACL, "mysql", 0, 1, 1, 0) &&
29662 -+ check_global_access(thd,CREATE_USER_ACL))
29663 -+ break;
29664 -+ if (end_active_trans(thd))
29665 -+ goto error;
29666 -+ /* Conditionally writes to binlog */
29667 -+ if (!(res= mysql_drop_user(thd, lex->users_list)))
29668 -+ my_ok(thd);
29669 -+ break;
29670 -+ }
29671 -+ case SQLCOM_RENAME_USER:
29672 -+ {
29673 -+ if (check_access(thd, UPDATE_ACL, "mysql", 0, 1, 1, 0) &&
29674 -+ check_global_access(thd,CREATE_USER_ACL))
29675 -+ break;
29676 -+ if (end_active_trans(thd))
29677 -+ goto error;
29678 -+ /* Conditionally writes to binlog */
29679 -+ if (!(res= mysql_rename_user(thd, lex->users_list)))
29680 -+ my_ok(thd);
29681 -+ break;
29682 -+ }
29683 -+ case SQLCOM_REVOKE_ALL:
29684 -+ {
29685 -+ if (end_active_trans(thd))
29686 -+ goto error;
29687 -+ if (check_access(thd, UPDATE_ACL, "mysql", 0, 1, 1, 0) &&
29688 -+ check_global_access(thd,CREATE_USER_ACL))
29689 -+ break;
29690 -+
29691 -+ /* Replicate current user as grantor */
29692 -+ thd->binlog_invoker();
29693 -+
29694 -+ /* Conditionally writes to binlog */
29695 -+ if (!(res = mysql_revoke_all(thd, lex->users_list)))
29696 -+ my_ok(thd);
29697 -+ break;
29698 -+ }
29699 -+ case SQLCOM_REVOKE:
29700 -+ case SQLCOM_GRANT:
29701 -+ {
29702 -+ if (end_active_trans(thd))
29703 -+ goto error;
29704 -+
29705 -+ if (check_access(thd, lex->grant | lex->grant_tot_col | GRANT_ACL,
29706 -+ first_table ? first_table->db : select_lex->db,
29707 -+ first_table ? &first_table->grant.privilege : 0,
29708 -+ first_table ? 0 : 1, 0,
29709 -+ first_table ? (bool) first_table->schema_table :
29710 -+ select_lex->db ?
29711 -+ is_schema_db(select_lex->db) : 0))
29712 -+ goto error;
29713 -+
29714 -+ /* Replicate current user as grantor */
29715 -+ thd->binlog_invoker();
29716 -+
29717 -+ if (thd->security_ctx->user) // If not replication
29718 -+ {
29719 -+ LEX_USER *user, *tmp_user;
29720 -+
29721 -+ List_iterator <LEX_USER> user_list(lex->users_list);
29722 -+ while ((tmp_user= user_list++))
29723 -+ {
29724 -+ if (!(user= get_current_user(thd, tmp_user)))
29725 -+ goto error;
29726 -+ if (specialflag & SPECIAL_NO_RESOLVE &&
29727 -+ hostname_requires_resolving(user->host.str))
29728 -+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
29729 -+ ER_WARN_HOSTNAME_WONT_WORK,
29730 -+ ER(ER_WARN_HOSTNAME_WONT_WORK),
29731 -+ user->host.str);
29732 -+ // Are we trying to change a password of another user
29733 -+ DBUG_ASSERT(user->host.str != 0);
29734 -+ if (strcmp(thd->security_ctx->user, user->user.str) ||
29735 -+ my_strcasecmp(system_charset_info,
29736 -+ user->host.str, thd->security_ctx->host_or_ip))
29737 -+ {
29738 -+ // TODO: use check_change_password()
29739 -+ if (is_acl_user(user->host.str, user->user.str) &&
29740 -+ user->password.str &&
29741 -+ check_access(thd, UPDATE_ACL,"mysql",0,1,1,0))
29742 -+ {
29743 -+ my_message(ER_PASSWORD_NOT_ALLOWED,
29744 -+ ER(ER_PASSWORD_NOT_ALLOWED), MYF(0));
29745 -+ goto error;
29746 -+ }
29747 -+ }
29748 -+ }
29749 -+ }
29750 -+ if (first_table)
29751 -+ {
29752 -+ if (lex->type == TYPE_ENUM_PROCEDURE ||
29753 -+ lex->type == TYPE_ENUM_FUNCTION)
29754 -+ {
29755 -+ uint grants= lex->all_privileges
29756 -+ ? (PROC_ACLS & ~GRANT_ACL) | (lex->grant & GRANT_ACL)
29757 -+ : lex->grant;
29758 -+ if (check_grant_routine(thd, grants | GRANT_ACL, all_tables,
29759 -+ lex->type == TYPE_ENUM_PROCEDURE, 0))
29760 -+ goto error;
29761 -+ /* Conditionally writes to binlog */
29762 -+ res= mysql_routine_grant(thd, all_tables,
29763 -+ lex->type == TYPE_ENUM_PROCEDURE,
29764 -+ lex->users_list, grants,
29765 -+ lex->sql_command == SQLCOM_REVOKE, TRUE);
29766 -+ if (!res)
29767 -+ my_ok(thd);
29768 -+ }
29769 -+ else
29770 -+ {
29771 -+ if (check_grant(thd,(lex->grant | lex->grant_tot_col | GRANT_ACL),
29772 -+ all_tables, 0, UINT_MAX, 0))
29773 -+ goto error;
29774 -+ /* Conditionally writes to binlog */
29775 -+ res= mysql_table_grant(thd, all_tables, lex->users_list,
29776 -+ lex->columns, lex->grant,
29777 -+ lex->sql_command == SQLCOM_REVOKE);
29778 -+ }
29779 -+ }
29780 -+ else
29781 -+ {
29782 -+ if (lex->columns.elements || lex->type)
29783 -+ {
29784 -+ my_message(ER_ILLEGAL_GRANT_FOR_TABLE, ER(ER_ILLEGAL_GRANT_FOR_TABLE),
29785 -+ MYF(0));
29786 -+ goto error;
29787 -+ }
29788 -+ else
29789 -+ /* Conditionally writes to binlog */
29790 -+ res = mysql_grant(thd, select_lex->db, lex->users_list, lex->grant,
29791 -+ lex->sql_command == SQLCOM_REVOKE);
29792 -+ if (!res)
29793 -+ {
29794 -+ if (lex->sql_command == SQLCOM_GRANT)
29795 -+ {
29796 -+ List_iterator <LEX_USER> str_list(lex->users_list);
29797 -+ LEX_USER *user, *tmp_user;
29798 -+ while ((tmp_user=str_list++))
29799 -+ {
29800 -+ if (!(user= get_current_user(thd, tmp_user)))
29801 -+ goto error;
29802 -+ reset_mqh(user, 0);
29803 -+ }
29804 -+ }
29805 -+ }
29806 -+ }
29807 -+ break;
29808 -+ }
29809 -+#endif /*!NO_EMBEDDED_ACCESS_CHECKS*/
29810 -+ case SQLCOM_RESET:
29811 -+ /*
29812 -+ RESET commands are never written to the binary log, so we have to
29813 -+ initialize this variable because RESET shares the same code as FLUSH
29814 -+ */
29815 -+ lex->no_write_to_binlog= 1;
29816 -+ case SQLCOM_FLUSH:
29817 -+ {
29818 -+ int write_to_binlog;
29819 -+ if (check_global_access(thd,RELOAD_ACL))
29820 -+ goto error;
29821 -+
29822 -+ /*
29823 -+ reload_acl_and_cache() will tell us if we are allowed to write to the
29824 -+ binlog or not.
29825 -+ */
29826 -+ if (!reload_acl_and_cache(thd, lex->type, first_table, &write_to_binlog))
29827 -+ {
29828 -+ /*
29829 -+ We WANT to write and we CAN write.
29830 -+ ! we write after unlocking the table.
29831 -+ */
29832 -+ /*
29833 -+ Presumably, RESET and binlog writing doesn't require synchronization
29834 -+ */
29835 -+
29836 -+ if (write_to_binlog > 0) // we should write
29837 -+ {
29838 -+ if (!lex->no_write_to_binlog)
29839 -+ res= write_bin_log(thd, FALSE, thd->query(), thd->query_length());
29840 -+ } else if (write_to_binlog < 0)
29841 -+ {
29842 -+ /*
29843 -+ We should not write, but rather report error because
29844 -+ reload_acl_and_cache binlog interactions failed
29845 -+ */
29846 -+ res= 1;
29847 -+ }
29848 -+
29849 -+ if (!res)
29850 -+ my_ok(thd);
29851 -+ }
29852 -+
29853 -+ break;
29854 -+ }
29855 -+ case SQLCOM_KILL:
29856 -+ {
29857 -+ Item *it= (Item *)lex->value_list.head();
29858 -+
29859 -+ if (lex->table_or_sp_used())
29860 -+ {
29861 -+ my_error(ER_NOT_SUPPORTED_YET, MYF(0), "Usage of subqueries or stored "
29862 -+ "function calls as part of this statement");
29863 -+ break;
29864 -+ }
29865 -+
29866 -+ if ((!it->fixed && it->fix_fields(lex->thd, &it)) || it->check_cols(1))
29867 -+ {
29868 -+ my_message(ER_SET_CONSTANTS_ONLY, ER(ER_SET_CONSTANTS_ONLY),
29869 -+ MYF(0));
29870 -+ goto error;
29871 -+ }
29872 -+ sql_kill(thd, (ulong)it->val_int(), lex->type & ONLY_KILL_QUERY);
29873 -+ break;
29874 -+ }
29875 -+#ifndef NO_EMBEDDED_ACCESS_CHECKS
29876 -+ case SQLCOM_SHOW_GRANTS:
29877 -+ {
29878 -+ LEX_USER *grant_user= get_current_user(thd, lex->grant_user);
29879 -+ if (!grant_user)
29880 -+ goto error;
29881 -+ if ((thd->security_ctx->priv_user &&
29882 -+ !strcmp(thd->security_ctx->priv_user, grant_user->user.str)) ||
29883 -+ !check_access(thd, SELECT_ACL, "mysql",0,1,0,0))
29884 -+ {
29885 -+ res = mysql_show_grants(thd, grant_user);
29886 -+ }
29887 -+ break;
29888 -+ }
29889 -+#endif
29890 -+ case SQLCOM_HA_OPEN:
29891 -+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
29892 -+ if (check_table_access(thd, SELECT_ACL, all_tables, UINT_MAX, FALSE))
29893 -+ goto error;
29894 -+ res= mysql_ha_open(thd, first_table, 0);
29895 -+ break;
29896 -+ case SQLCOM_HA_CLOSE:
29897 -+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
29898 -+ res= mysql_ha_close(thd, first_table);
29899 -+ break;
29900 -+ case SQLCOM_HA_READ:
29901 -+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
29902 -+ /*
29903 -+ There is no need to check for table permissions here, because
29904 -+ if a user has no permissions to read a table, he won't be
29905 -+ able to open it (with SQLCOM_HA_OPEN) in the first place.
29906 -+ */
29907 -+ unit->set_limit(select_lex);
29908 -+ res= mysql_ha_read(thd, first_table, lex->ha_read_mode, lex->ident.str,
29909 -+ lex->insert_list, lex->ha_rkey_mode, select_lex->where,
29910 -+ unit->select_limit_cnt, unit->offset_limit_cnt);
29911 -+ break;
29912 -+
29913 -+ case SQLCOM_BEGIN:
29914 -+ if (thd->transaction.xid_state.xa_state != XA_NOTR)
29915 -+ {
29916 -+ my_error(ER_XAER_RMFAIL, MYF(0),
29917 -+ xa_state_names[thd->transaction.xid_state.xa_state]);
29918 -+ break;
29919 -+ }
29920 -+ if (begin_trans(thd))
29921 -+ goto error;
29922 -+ if (lex->start_transaction_opt & MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT)
29923 -+ {
29924 -+ if (ha_start_consistent_snapshot(thd))
29925 -+ goto error;
29926 -+ }
29927 -+ my_ok(thd);
29928 -+ break;
29929 -+ case SQLCOM_COMMIT:
29930 -+ if (end_trans(thd, lex->tx_release ? COMMIT_RELEASE :
29931 -+ lex->tx_chain ? COMMIT_AND_CHAIN : COMMIT))
29932 -+ goto error;
29933 -+ my_ok(thd);
29934 -+ break;
29935 -+ case SQLCOM_ROLLBACK:
29936 -+ if (end_trans(thd, lex->tx_release ? ROLLBACK_RELEASE :
29937 -+ lex->tx_chain ? ROLLBACK_AND_CHAIN : ROLLBACK))
29938 -+ goto error;
29939 -+ my_ok(thd);
29940 -+ break;
29941 -+ case SQLCOM_RELEASE_SAVEPOINT:
29942 -+ {
29943 -+ SAVEPOINT *sv;
29944 -+ for (sv=thd->transaction.savepoints; sv; sv=sv->prev)
29945 -+ {
29946 -+ if (my_strnncoll(system_charset_info,
29947 -+ (uchar *)lex->ident.str, lex->ident.length,
29948 -+ (uchar *)sv->name, sv->length) == 0)
29949 -+ break;
29950 -+ }
29951 -+ if (sv)
29952 -+ {
29953 -+ if (ha_release_savepoint(thd, sv))
29954 -+ res= TRUE; // cannot happen
29955 -+ else
29956 -+ my_ok(thd);
29957 -+ thd->transaction.savepoints=sv->prev;
29958 -+ }
29959 -+ else
29960 -+ my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "SAVEPOINT", lex->ident.str);
29961 -+ break;
29962 -+ }
29963 -+ case SQLCOM_ROLLBACK_TO_SAVEPOINT:
29964 -+ {
29965 -+ SAVEPOINT *sv;
29966 -+ for (sv=thd->transaction.savepoints; sv; sv=sv->prev)
29967 -+ {
29968 -+ if (my_strnncoll(system_charset_info,
29969 -+ (uchar *)lex->ident.str, lex->ident.length,
29970 -+ (uchar *)sv->name, sv->length) == 0)
29971 -+ break;
29972 -+ }
29973 -+ if (sv)
29974 -+ {
29975 -+ if (ha_rollback_to_savepoint(thd, sv))
29976 -+ res= TRUE; // cannot happen
29977 -+ else
29978 -+ {
29979 -+ if (((thd->options & OPTION_KEEP_LOG) ||
29980 -+ thd->transaction.all.modified_non_trans_table) &&
29981 -+ !thd->slave_thread)
29982 -+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
29983 -+ ER_WARNING_NOT_COMPLETE_ROLLBACK,
29984 -+ ER(ER_WARNING_NOT_COMPLETE_ROLLBACK));
29985 -+ my_ok(thd);
29986 -+ }
29987 -+ thd->transaction.savepoints=sv;
29988 -+ }
29989 -+ else
29990 -+ my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "SAVEPOINT", lex->ident.str);
29991 -+ break;
29992 -+ }
29993 -+ case SQLCOM_SAVEPOINT:
29994 -+ if (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN) ||
29995 -+ thd->in_sub_stmt) || !opt_using_transactions)
29996 -+ my_ok(thd);
29997 -+ else
29998 -+ {
29999 -+ SAVEPOINT **sv, *newsv;
30000 -+ for (sv=&thd->transaction.savepoints; *sv; sv=&(*sv)->prev)
30001 -+ {
30002 -+ if (my_strnncoll(system_charset_info,
30003 -+ (uchar *)lex->ident.str, lex->ident.length,
30004 -+ (uchar *)(*sv)->name, (*sv)->length) == 0)
30005 -+ break;
30006 -+ }
30007 -+ if (*sv) /* old savepoint of the same name exists */
30008 -+ {
30009 -+ newsv=*sv;
30010 -+ ha_release_savepoint(thd, *sv); // it cannot fail
30011 -+ *sv=(*sv)->prev;
30012 -+ }
30013 -+ else if ((newsv=(SAVEPOINT *) alloc_root(&thd->transaction.mem_root,
30014 -+ savepoint_alloc_size)) == 0)
30015 -+ {
30016 -+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
30017 -+ break;
30018 -+ }
30019 -+ newsv->name=strmake_root(&thd->transaction.mem_root,
30020 -+ lex->ident.str, lex->ident.length);
30021 -+ newsv->length=lex->ident.length;
30022 -+ /*
30023 -+ if we'll get an error here, don't add new savepoint to the list.
30024 -+ we'll lose a little bit of memory in transaction mem_root, but it'll
30025 -+ be free'd when transaction ends anyway
30026 -+ */
30027 -+ if (ha_savepoint(thd, newsv))
30028 -+ res= TRUE;
30029 -+ else
30030 -+ {
30031 -+ newsv->prev=thd->transaction.savepoints;
30032 -+ thd->transaction.savepoints=newsv;
30033 -+ my_ok(thd);
30034 -+ }
30035 -+ }
30036 -+ break;
30037 -+ case SQLCOM_CREATE_PROCEDURE:
30038 -+ case SQLCOM_CREATE_SPFUNCTION:
30039 -+ {
30040 -+ uint namelen;
30041 -+ char *name;
30042 -+ int sp_result= SP_INTERNAL_ERROR;
30043 -+
30044 -+ DBUG_ASSERT(lex->sphead != 0);
30045 -+ DBUG_ASSERT(lex->sphead->m_db.str); /* Must be initialized in the parser */
30046 -+ /*
30047 -+ Verify that the database name is allowed, optionally
30048 -+ lowercase it.
30049 -+ */
30050 -+ if (check_db_name(&lex->sphead->m_db))
30051 -+ {
30052 -+ my_error(ER_WRONG_DB_NAME, MYF(0), lex->sphead->m_db.str);
30053 -+ goto create_sp_error;
30054 -+ }
30055 -+
30056 -+ /*
30057 -+ Check that a database directory with this name
30058 -+ exists. Design note: This won't work on virtual databases
30059 -+ like information_schema.
30060 -+ */
30061 -+ if (check_db_dir_existence(lex->sphead->m_db.str))
30062 -+ {
30063 -+ my_error(ER_BAD_DB_ERROR, MYF(0), lex->sphead->m_db.str);
30064 -+ goto create_sp_error;
30065 -+ }
30066 -+
30067 -+ if (check_access(thd, CREATE_PROC_ACL, lex->sphead->m_db.str, 0, 0, 0,
30068 -+ is_schema_db(lex->sphead->m_db.str,
30069 -+ lex->sphead->m_db.length)))
30070 -+ goto create_sp_error;
30071 -+
30072 -+ if (end_active_trans(thd))
30073 -+ goto create_sp_error;
30074 -+
30075 -+ name= lex->sphead->name(&namelen);
30076 -+#ifdef HAVE_DLOPEN
30077 -+ if (lex->sphead->m_type == TYPE_ENUM_FUNCTION)
30078 -+ {
30079 -+ udf_func *udf = find_udf(name, namelen);
30080 -+
30081 -+ if (udf)
30082 -+ {
30083 -+ my_error(ER_UDF_EXISTS, MYF(0), name);
30084 -+ goto create_sp_error;
30085 -+ }
30086 -+ }
30087 -+#endif
30088 -+
30089 -+ if (sp_process_definer(thd))
30090 -+ goto create_sp_error;
30091 -+
30092 -+ res= (sp_result= lex->sphead->create(thd));
30093 -+ switch (sp_result) {
30094 -+ case SP_OK: {
30095 -+#ifndef NO_EMBEDDED_ACCESS_CHECKS
30096 -+ /* only add privileges if really neccessary */
30097 -+
30098 -+ Security_context security_context;
30099 -+ bool restore_backup_context= false;
30100 -+ Security_context *backup= NULL;
30101 -+ LEX_USER *definer= thd->lex->definer;
30102 -+ /*
30103 -+ Check if the definer exists on slave,
30104 -+ then use definer privilege to insert routine privileges to mysql.procs_priv.
30105 -+
30106 -+ For current user of SQL thread has GLOBAL_ACL privilege,
30107 -+ which doesn't any check routine privileges,
30108 -+ so no routine privilege record will insert into mysql.procs_priv.
30109 -+ */
30110 -+ if (thd->slave_thread && is_acl_user(definer->host.str, definer->user.str))
30111 -+ {
30112 -+ security_context.change_security_context(thd,
30113 -+ &thd->lex->definer->user,
30114 -+ &thd->lex->definer->host,
30115 -+ &thd->lex->sphead->m_db,
30116 -+ &backup);
30117 -+ restore_backup_context= true;
30118 -+ }
30119 -+
30120 -+ if (sp_automatic_privileges && !opt_noacl &&
30121 -+ check_routine_access(thd, DEFAULT_CREATE_PROC_ACLS,
30122 -+ lex->sphead->m_db.str, name,
30123 -+ lex->sql_command == SQLCOM_CREATE_PROCEDURE, 1))
30124 -+ {
30125 -+ if (sp_grant_privileges(thd, lex->sphead->m_db.str, name,
30126 -+ lex->sql_command == SQLCOM_CREATE_PROCEDURE))
30127 -+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
30128 -+ ER_PROC_AUTO_GRANT_FAIL,
30129 -+ ER(ER_PROC_AUTO_GRANT_FAIL));
30130 -+ }
30131 -+
30132 -+ /*
30133 -+ Restore current user with GLOBAL_ACL privilege of SQL thread
30134 -+ */
30135 -+ if (restore_backup_context)
30136 -+ {
30137 -+ DBUG_ASSERT(thd->slave_thread == 1);
30138 -+ thd->security_ctx->restore_security_context(thd, backup);
30139 -+ }
30140 -+
30141 -+#endif
30142 -+ break;
30143 -+ }
30144 -+ case SP_WRITE_ROW_FAILED:
30145 -+ my_error(ER_SP_ALREADY_EXISTS, MYF(0), SP_TYPE_STRING(lex), name);
30146 -+ break;
30147 -+ case SP_BAD_IDENTIFIER:
30148 -+ my_error(ER_TOO_LONG_IDENT, MYF(0), name);
30149 -+ break;
30150 -+ case SP_BODY_TOO_LONG:
30151 -+ my_error(ER_TOO_LONG_BODY, MYF(0), name);
30152 -+ break;
30153 -+ case SP_FLD_STORE_FAILED:
30154 -+ my_error(ER_CANT_CREATE_SROUTINE, MYF(0), name);
30155 -+ break;
30156 -+ default:
30157 -+ my_error(ER_SP_STORE_FAILED, MYF(0), SP_TYPE_STRING(lex), name);
30158 -+ break;
30159 -+ } /* end switch */
30160 -+
30161 -+ /*
30162 -+ Capture all errors within this CASE and
30163 -+ clean up the environment.
30164 -+ */
30165 -+create_sp_error:
30166 -+ if (sp_result != SP_OK )
30167 -+ goto error;
30168 -+ my_ok(thd);
30169 -+ break; /* break super switch */
30170 -+ } /* end case group bracket */
30171 -+ case SQLCOM_CALL:
30172 -+ {
30173 -+ sp_head *sp;
30174 -+
30175 -+ /*
30176 -+ This will cache all SP and SF and open and lock all tables
30177 -+ required for execution.
30178 -+ */
30179 -+ if (check_table_access(thd, SELECT_ACL, all_tables, UINT_MAX, FALSE) ||
30180 -+ open_and_lock_tables(thd, all_tables))
30181 -+ goto error;
30182 -+
30183 -+ /*
30184 -+ By this moment all needed SPs should be in cache so no need to look
30185 -+ into DB.
30186 -+ */
30187 -+ if (!(sp= sp_find_routine(thd, TYPE_ENUM_PROCEDURE, lex->spname,
30188 -+ &thd->sp_proc_cache, TRUE)))
30189 -+ {
30190 -+ my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "PROCEDURE",
30191 -+ lex->spname->m_qname.str);
30192 -+ goto error;
30193 -+ }
30194 -+ else
30195 -+ {
30196 -+ ha_rows select_limit;
30197 -+ /* bits that should be cleared in thd->server_status */
30198 -+ uint bits_to_be_cleared= 0;
30199 -+ /*
30200 -+ Check that the stored procedure doesn't contain Dynamic SQL
30201 -+ and doesn't return result sets: such stored procedures can't
30202 -+ be called from a function or trigger.
30203 -+ */
30204 -+ if (thd->in_sub_stmt)
30205 -+ {
30206 -+ const char *where= (thd->in_sub_stmt & SUB_STMT_TRIGGER ?
30207 -+ "trigger" : "function");
30208 -+ if (sp->is_not_allowed_in_function(where))
30209 -+ goto error;
30210 -+ }
30211 -+
30212 -+ if (sp->m_flags & sp_head::MULTI_RESULTS)
30213 -+ {
30214 -+ if (! (thd->client_capabilities & CLIENT_MULTI_RESULTS))
30215 -+ {
30216 -+ /*
30217 -+ The client does not support multiple result sets being sent
30218 -+ back
30219 -+ */
30220 -+ my_error(ER_SP_BADSELECT, MYF(0), sp->m_qname.str);
30221 -+ goto error;
30222 -+ }
30223 -+ /*
30224 -+ If SERVER_MORE_RESULTS_EXISTS is not set,
30225 -+ then remember that it should be cleared
30226 -+ */
30227 -+ bits_to_be_cleared= (~thd->server_status &
30228 -+ SERVER_MORE_RESULTS_EXISTS);
30229 -+ thd->server_status|= SERVER_MORE_RESULTS_EXISTS;
30230 -+ }
30231 -+
30232 -+ if (check_routine_access(thd, EXECUTE_ACL,
30233 -+ sp->m_db.str, sp->m_name.str, TRUE, FALSE))
30234 -+ {
30235 -+ goto error;
30236 -+ }
30237 -+ select_limit= thd->variables.select_limit;
30238 -+ thd->variables.select_limit= HA_POS_ERROR;
30239 -+
30240 -+ /*
30241 -+ We never write CALL statements into binlog:
30242 -+ - If the mode is non-prelocked, each statement will be logged
30243 -+ separately.
30244 -+ - If the mode is prelocked, the invoking statement will care
30245 -+ about writing into binlog.
30246 -+ So just execute the statement.
30247 -+ */
30248 -+ res= sp->execute_procedure(thd, &lex->value_list);
30249 -+ /*
30250 -+ If warnings have been cleared, we have to clear total_warn_count
30251 -+ too, otherwise the clients get confused.
30252 -+ */
30253 -+ if (thd->warn_list.is_empty())
30254 -+ thd->total_warn_count= 0;
30255 -+
30256 -+ thd->variables.select_limit= select_limit;
30257 -+
30258 -+ thd->server_status&= ~bits_to_be_cleared;
30259 -+
30260 -+ if (!res)
30261 -+ my_ok(thd, (ulong) (thd->row_count_func < 0 ? 0 :
30262 -+ thd->row_count_func));
30263 -+ else
30264 -+ {
30265 -+ DBUG_ASSERT(thd->is_error() || thd->killed);
30266 -+ goto error; // Substatement should already have sent error
30267 -+ }
30268 -+ }
30269 -+ break;
30270 -+ }
30271 -+ case SQLCOM_ALTER_PROCEDURE:
30272 -+ case SQLCOM_ALTER_FUNCTION:
30273 -+ {
30274 -+ int sp_result;
30275 -+ sp_head *sp;
30276 -+ st_sp_chistics chistics;
30277 -+
30278 -+ memcpy(&chistics, &lex->sp_chistics, sizeof(chistics));
30279 -+ if (lex->sql_command == SQLCOM_ALTER_PROCEDURE)
30280 -+ sp= sp_find_routine(thd, TYPE_ENUM_PROCEDURE, lex->spname,
30281 -+ &thd->sp_proc_cache, FALSE);
30282 -+ else
30283 -+ sp= sp_find_routine(thd, TYPE_ENUM_FUNCTION, lex->spname,
30284 -+ &thd->sp_func_cache, FALSE);
30285 -+ mysql_reset_errors(thd, 0);
30286 -+ if (! sp)
30287 -+ {
30288 -+ if (lex->spname->m_db.str)
30289 -+ sp_result= SP_KEY_NOT_FOUND;
30290 -+ else
30291 -+ {
30292 -+ my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
30293 -+ goto error;
30294 -+ }
30295 -+ }
30296 -+ else
30297 -+ {
30298 -+ if (check_routine_access(thd, ALTER_PROC_ACL, sp->m_db.str,
30299 -+ sp->m_name.str,
30300 -+ lex->sql_command == SQLCOM_ALTER_PROCEDURE, 0))
30301 -+ goto error;
30302 -+
30303 -+ if (end_active_trans(thd))
30304 -+ goto error;
30305 -+ memcpy(&lex->sp_chistics, &chistics, sizeof(lex->sp_chistics));
30306 -+ if ((sp->m_type == TYPE_ENUM_FUNCTION) &&
30307 -+ !trust_function_creators && mysql_bin_log.is_open() &&
30308 -+ !sp->m_chistics->detistic &&
30309 -+ (chistics.daccess == SP_CONTAINS_SQL ||
30310 -+ chistics.daccess == SP_MODIFIES_SQL_DATA))
30311 -+ {
30312 -+ my_message(ER_BINLOG_UNSAFE_ROUTINE,
30313 -+ ER(ER_BINLOG_UNSAFE_ROUTINE), MYF(0));
30314 -+ sp_result= SP_INTERNAL_ERROR;
30315 -+ }
30316 -+ else
30317 -+ {
30318 -+ /*
30319 -+ Note that if you implement the capability of ALTER FUNCTION to
30320 -+ alter the body of the function, this command should be made to
30321 -+ follow the restrictions that log-bin-trust-function-creators=0
30322 -+ already puts on CREATE FUNCTION.
30323 -+ */
30324 -+ /* Conditionally writes to binlog */
30325 -+
30326 -+ int type= lex->sql_command == SQLCOM_ALTER_PROCEDURE ?
30327 -+ TYPE_ENUM_PROCEDURE :
30328 -+ TYPE_ENUM_FUNCTION;
30329 -+
30330 -+ sp_result= sp_update_routine(thd,
30331 -+ type,
30332 -+ lex->spname,
30333 -+ &lex->sp_chistics);
30334 -+ }
30335 -+ }
30336 -+ switch (sp_result)
30337 -+ {
30338 -+ case SP_OK:
30339 -+ my_ok(thd);
30340 -+ break;
30341 -+ case SP_KEY_NOT_FOUND:
30342 -+ my_error(ER_SP_DOES_NOT_EXIST, MYF(0),
30343 -+ SP_COM_STRING(lex), lex->spname->m_qname.str);
30344 -+ goto error;
30345 -+ default:
30346 -+ my_error(ER_SP_CANT_ALTER, MYF(0),
30347 -+ SP_COM_STRING(lex), lex->spname->m_qname.str);
30348 -+ goto error;
30349 -+ }
30350 -+ break;
30351 -+ }
30352 -+ case SQLCOM_DROP_PROCEDURE:
30353 -+ case SQLCOM_DROP_FUNCTION:
30354 -+ {
30355 -+ int sp_result;
30356 -+ int type= (lex->sql_command == SQLCOM_DROP_PROCEDURE ?
30357 -+ TYPE_ENUM_PROCEDURE : TYPE_ENUM_FUNCTION);
30358 -+
30359 -+ sp_result= sp_routine_exists_in_table(thd, type, lex->spname);
30360 -+ mysql_reset_errors(thd, 0);
30361 -+ if (sp_result == SP_OK)
30362 -+ {
30363 -+ char *db= lex->spname->m_db.str;
30364 -+ char *name= lex->spname->m_name.str;
30365 -+
30366 -+ if (check_routine_access(thd, ALTER_PROC_ACL, db, name,
30367 -+ lex->sql_command == SQLCOM_DROP_PROCEDURE, 0))
30368 -+ goto error;
30369 -+
30370 -+ if (end_active_trans(thd))
30371 -+ goto error;
30372 -+#ifndef NO_EMBEDDED_ACCESS_CHECKS
30373 -+ if (sp_automatic_privileges && !opt_noacl &&
30374 -+ sp_revoke_privileges(thd, db, name,
30375 -+ lex->sql_command == SQLCOM_DROP_PROCEDURE))
30376 -+ {
30377 -+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
30378 -+ ER_PROC_AUTO_REVOKE_FAIL,
30379 -+ ER(ER_PROC_AUTO_REVOKE_FAIL));
30380 -+ }
30381 -+#endif
30382 -+ /* Conditionally writes to binlog */
30383 -+
30384 -+ int type= lex->sql_command == SQLCOM_DROP_PROCEDURE ?
30385 -+ TYPE_ENUM_PROCEDURE :
30386 -+ TYPE_ENUM_FUNCTION;
30387 -+
30388 -+ sp_result= sp_drop_routine(thd, type, lex->spname);
30389 -+ }
30390 -+ else
30391 -+ {
30392 -+#ifdef HAVE_DLOPEN
30393 -+ if (lex->sql_command == SQLCOM_DROP_FUNCTION)
30394 -+ {
30395 -+ udf_func *udf = find_udf(lex->spname->m_name.str,
30396 -+ lex->spname->m_name.length);
30397 -+ if (udf)
30398 -+ {
30399 -+ if (check_access(thd, DELETE_ACL, "mysql", 0, 1, 0, 0))
30400 -+ goto error;
30401 -+
30402 -+ if (!(res = mysql_drop_function(thd, &lex->spname->m_name)))
30403 -+ {
30404 -+ my_ok(thd);
30405 -+ break;
30406 -+ }
30407 -+ }
30408 -+ }
30409 -+#endif
30410 -+ if (lex->spname->m_db.str)
30411 -+ sp_result= SP_KEY_NOT_FOUND;
30412 -+ else
30413 -+ {
30414 -+ my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
30415 -+ goto error;
30416 -+ }
30417 -+ }
30418 -+ res= sp_result;
30419 -+ switch (sp_result) {
30420 -+ case SP_OK:
30421 -+ my_ok(thd);
30422 -+ break;
30423 -+ case SP_KEY_NOT_FOUND:
30424 -+ if (lex->drop_if_exists)
30425 -+ {
30426 -+ res= write_bin_log(thd, TRUE, thd->query(), thd->query_length());
30427 -+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
30428 -+ ER_SP_DOES_NOT_EXIST, ER(ER_SP_DOES_NOT_EXIST),
30429 -+ SP_COM_STRING(lex), lex->spname->m_name.str);
30430 -+ if (!res)
30431 -+ my_ok(thd);
30432 -+ break;
30433 -+ }
30434 -+ my_error(ER_SP_DOES_NOT_EXIST, MYF(0),
30435 -+ SP_COM_STRING(lex), lex->spname->m_qname.str);
30436 -+ goto error;
30437 -+ default:
30438 -+ my_error(ER_SP_DROP_FAILED, MYF(0),
30439 -+ SP_COM_STRING(lex), lex->spname->m_qname.str);
30440 -+ goto error;
30441 -+ }
30442 -+ break;
30443 -+ }
30444 -+ case SQLCOM_SHOW_CREATE_PROC:
30445 -+ {
30446 -+ if (sp_show_create_routine(thd, TYPE_ENUM_PROCEDURE, lex->spname))
30447 -+ {
30448 -+ my_error(ER_SP_DOES_NOT_EXIST, MYF(0),
30449 -+ SP_COM_STRING(lex), lex->spname->m_name.str);
30450 -+ goto error;
30451 -+ }
30452 -+ break;
30453 -+ }
30454 -+ case SQLCOM_SHOW_CREATE_FUNC:
30455 -+ {
30456 -+ if (sp_show_create_routine(thd, TYPE_ENUM_FUNCTION, lex->spname))
30457 -+ {
30458 -+ my_error(ER_SP_DOES_NOT_EXIST, MYF(0),
30459 -+ SP_COM_STRING(lex), lex->spname->m_name.str);
30460 -+ goto error;
30461 -+ }
30462 -+ break;
30463 -+ }
30464 -+#ifndef DBUG_OFF
30465 -+ case SQLCOM_SHOW_PROC_CODE:
30466 -+ case SQLCOM_SHOW_FUNC_CODE:
30467 -+ {
30468 -+ sp_head *sp;
30469 -+
30470 -+ if (lex->sql_command == SQLCOM_SHOW_PROC_CODE)
30471 -+ sp= sp_find_routine(thd, TYPE_ENUM_PROCEDURE, lex->spname,
30472 -+ &thd->sp_proc_cache, FALSE);
30473 -+ else
30474 -+ sp= sp_find_routine(thd, TYPE_ENUM_FUNCTION, lex->spname,
30475 -+ &thd->sp_func_cache, FALSE);
30476 -+ if (!sp || sp->show_routine_code(thd))
30477 -+ {
30478 -+ /* We don't distinguish between errors for now */
30479 -+ my_error(ER_SP_DOES_NOT_EXIST, MYF(0),
30480 -+ SP_COM_STRING(lex), lex->spname->m_name.str);
30481 -+ goto error;
30482 -+ }
30483 -+ break;
30484 -+ }
30485 -+#endif // ifndef DBUG_OFF
30486 -+ case SQLCOM_SHOW_CREATE_TRIGGER:
30487 -+ {
30488 -+ if (lex->spname->m_name.length > NAME_LEN)
30489 -+ {
30490 -+ my_error(ER_TOO_LONG_IDENT, MYF(0), lex->spname->m_name.str);
30491 -+ goto error;
30492 -+ }
30493 -+
30494 -+ if (show_create_trigger(thd, lex->spname))
30495 -+ goto error; /* Error has been already logged. */
30496 -+
30497 -+ break;
30498 -+ }
30499 -+ case SQLCOM_CREATE_VIEW:
30500 -+ {
30501 -+ /*
30502 -+ Note: SQLCOM_CREATE_VIEW also handles 'ALTER VIEW' commands
30503 -+ as specified through the thd->lex->create_view_mode flag.
30504 -+ */
30505 -+ if (end_active_trans(thd))
30506 -+ goto error;
30507 -+
30508 -+ res= mysql_create_view(thd, first_table, thd->lex->create_view_mode);
30509 -+ break;
30510 -+ }
30511 -+ case SQLCOM_DROP_VIEW:
30512 -+ {
30513 -+ if (check_table_access(thd, DROP_ACL, all_tables, UINT_MAX, FALSE) ||
30514 -+ end_active_trans(thd))
30515 -+ goto error;
30516 -+ /* Conditionally writes to binlog. */
30517 -+ res= mysql_drop_view(thd, first_table, thd->lex->drop_mode);
30518 -+ break;
30519 -+ }
30520 -+ case SQLCOM_CREATE_TRIGGER:
30521 -+ {
30522 -+ if (end_active_trans(thd))
30523 -+ goto error;
30524 -+
30525 -+ /* Conditionally writes to binlog. */
30526 -+ res= mysql_create_or_drop_trigger(thd, all_tables, 1);
30527 -+
30528 -+ break;
30529 -+ }
30530 -+ case SQLCOM_DROP_TRIGGER:
30531 -+ {
30532 -+ if (end_active_trans(thd))
30533 -+ goto error;
30534 -+
30535 -+ /* Conditionally writes to binlog. */
30536 -+ res= mysql_create_or_drop_trigger(thd, all_tables, 0);
30537 -+ break;
30538 -+ }
30539 -+ case SQLCOM_XA_START:
30540 -+ if (thd->transaction.xid_state.xa_state == XA_IDLE &&
30541 -+ thd->lex->xa_opt == XA_RESUME)
30542 -+ {
30543 -+ if (! thd->transaction.xid_state.xid.eq(thd->lex->xid))
30544 -+ {
30545 -+ my_error(ER_XAER_NOTA, MYF(0));
30546 -+ break;
30547 -+ }
30548 -+ thd->transaction.xid_state.xa_state= XA_ACTIVE;
30549 -+ my_ok(thd);
30550 -+ break;
30551 -+ }
30552 -+ if (thd->lex->xa_opt != XA_NONE)
30553 -+ { // JOIN is not supported yet. TODO
30554 -+ my_error(ER_XAER_INVAL, MYF(0));
30555 -+ break;
30556 -+ }
30557 -+ if (thd->transaction.xid_state.xa_state != XA_NOTR)
30558 -+ {
30559 -+ my_error(ER_XAER_RMFAIL, MYF(0),
30560 -+ xa_state_names[thd->transaction.xid_state.xa_state]);
30561 -+ break;
30562 -+ }
30563 -+ if (thd->active_transaction() || thd->locked_tables)
30564 -+ {
30565 -+ my_error(ER_XAER_OUTSIDE, MYF(0));
30566 -+ break;
30567 -+ }
30568 -+ DBUG_ASSERT(thd->transaction.xid_state.xid.is_null());
30569 -+ thd->transaction.xid_state.xa_state= XA_ACTIVE;
30570 -+ thd->transaction.xid_state.rm_error= 0;
30571 -+ thd->transaction.xid_state.xid.set(thd->lex->xid);
30572 -+ if (xid_cache_insert(&thd->transaction.xid_state))
30573 -+ {
30574 -+ thd->transaction.xid_state.xa_state= XA_NOTR;
30575 -+ thd->transaction.xid_state.xid.null();
30576 -+ break;
30577 -+ }
30578 -+ thd->transaction.all.modified_non_trans_table= FALSE;
30579 -+ thd->options= ((thd->options & ~(OPTION_KEEP_LOG)) | OPTION_BEGIN);
30580 -+ thd->server_status|= SERVER_STATUS_IN_TRANS;
30581 -+ my_ok(thd);
30582 -+ break;
30583 -+ case SQLCOM_XA_END:
30584 -+ /* fake it */
30585 -+ if (thd->lex->xa_opt != XA_NONE)
30586 -+ { // SUSPEND and FOR MIGRATE are not supported yet. TODO
30587 -+ my_error(ER_XAER_INVAL, MYF(0));
30588 -+ break;
30589 -+ }
30590 -+ if (thd->transaction.xid_state.xa_state != XA_ACTIVE)
30591 -+ {
30592 -+ my_error(ER_XAER_RMFAIL, MYF(0),
30593 -+ xa_state_names[thd->transaction.xid_state.xa_state]);
30594 -+ break;
30595 -+ }
30596 -+ if (!thd->transaction.xid_state.xid.eq(thd->lex->xid))
30597 -+ {
30598 -+ my_error(ER_XAER_NOTA, MYF(0));
30599 -+ break;
30600 -+ }
30601 -+ if (xa_trans_rolled_back(&thd->transaction.xid_state))
30602 -+ break;
30603 -+ thd->transaction.xid_state.xa_state=XA_IDLE;
30604 -+ my_ok(thd);
30605 -+ break;
30606 -+ case SQLCOM_XA_PREPARE:
30607 -+ if (thd->transaction.xid_state.xa_state != XA_IDLE)
30608 -+ {
30609 -+ my_error(ER_XAER_RMFAIL, MYF(0),
30610 -+ xa_state_names[thd->transaction.xid_state.xa_state]);
30611 -+ break;
30612 -+ }
30613 -+ if (!thd->transaction.xid_state.xid.eq(thd->lex->xid))
30614 -+ {
30615 -+ my_error(ER_XAER_NOTA, MYF(0));
30616 -+ break;
30617 -+ }
30618 -+ if (ha_prepare(thd))
30619 -+ {
30620 -+ my_error(ER_XA_RBROLLBACK, MYF(0));
30621 -+ xid_cache_delete(&thd->transaction.xid_state);
30622 -+ thd->transaction.xid_state.xa_state=XA_NOTR;
30623 -+ break;
30624 -+ }
30625 -+ thd->transaction.xid_state.xa_state=XA_PREPARED;
30626 -+ my_ok(thd);
30627 -+ break;
30628 -+ case SQLCOM_XA_COMMIT:
30629 -+ if (!thd->transaction.xid_state.xid.eq(thd->lex->xid))
30630 -+ {
30631 -+ /*
30632 -+ xid_state.in_thd is always true beside of xa recovery
30633 -+ procedure. Note, that there is no race condition here
30634 -+ between xid_cache_search and xid_cache_delete, since we're always
30635 -+ deleting our own XID (thd->lex->xid == thd->transaction.xid_state.xid).
30636 -+ The only case when thd->lex->xid != thd->transaction.xid_state.xid
30637 -+ and xid_state->in_thd == 0 is in ha_recover() functionality,
30638 -+ which is called before starting client connections, and thus is
30639 -+ always single-threaded.
30640 -+ */
30641 -+ XID_STATE *xs=xid_cache_search(thd->lex->xid);
30642 -+ if (!xs || xs->in_thd)
30643 -+ my_error(ER_XAER_NOTA, MYF(0));
30644 -+ else if (xa_trans_rolled_back(xs))
30645 -+ {
30646 -+ ha_commit_or_rollback_by_xid(thd->lex->xid, 0);
30647 -+ xid_cache_delete(xs);
30648 -+ break;
30649 -+ }
30650 -+ else
30651 -+ {
30652 -+ ha_commit_or_rollback_by_xid(thd->lex->xid, 1);
30653 -+ xid_cache_delete(xs);
30654 -+ my_ok(thd);
30655 -+ }
30656 -+ break;
30657 -+ }
30658 -+ if (xa_trans_rolled_back(&thd->transaction.xid_state))
30659 -+ {
30660 -+ xa_trans_rollback(thd);
30661 -+ break;
30662 -+ }
30663 -+ if (thd->transaction.xid_state.xa_state == XA_IDLE &&
30664 -+ thd->lex->xa_opt == XA_ONE_PHASE)
30665 -+ {
30666 -+ int r;
30667 -+ if ((r= ha_commit(thd)))
30668 -+ my_error(r == 1 ? ER_XA_RBROLLBACK : ER_XAER_RMERR, MYF(0));
30669 -+ else
30670 -+ my_ok(thd);
30671 -+ }
30672 -+ else if (thd->transaction.xid_state.xa_state == XA_PREPARED &&
30673 -+ thd->lex->xa_opt == XA_NONE)
30674 -+ {
30675 -+ if (wait_if_global_read_lock(thd, 0, 0))
30676 -+ {
30677 -+ ha_rollback(thd);
30678 -+ my_error(ER_XAER_RMERR, MYF(0));
30679 -+ }
30680 -+ else
30681 -+ {
30682 -+ if (ha_commit_one_phase(thd, 1))
30683 -+ my_error(ER_XAER_RMERR, MYF(0));
30684 -+ else
30685 -+ my_ok(thd);
30686 -+ start_waiting_global_read_lock(thd);
30687 -+ }
30688 -+ }
30689 -+ else
30690 -+ {
30691 -+ my_error(ER_XAER_RMFAIL, MYF(0),
30692 -+ xa_state_names[thd->transaction.xid_state.xa_state]);
30693 -+ break;
30694 -+ }
30695 -+ thd->options&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
30696 -+ thd->transaction.all.modified_non_trans_table= FALSE;
30697 -+ thd->server_status&= ~SERVER_STATUS_IN_TRANS;
30698 -+ xid_cache_delete(&thd->transaction.xid_state);
30699 -+ thd->transaction.xid_state.xa_state=XA_NOTR;
30700 -+ break;
30701 -+ case SQLCOM_XA_ROLLBACK:
30702 -+ if (!thd->transaction.xid_state.xid.eq(thd->lex->xid))
30703 -+ {
30704 -+ XID_STATE *xs=xid_cache_search(thd->lex->xid);
30705 -+ if (!xs || xs->in_thd)
30706 -+ my_error(ER_XAER_NOTA, MYF(0));
30707 -+ else
30708 -+ {
30709 -+ bool ok= !xa_trans_rolled_back(xs);
30710 -+ ha_commit_or_rollback_by_xid(thd->lex->xid, 0);
30711 -+ xid_cache_delete(xs);
30712 -+ if (ok)
30713 -+ my_ok(thd);
30714 -+ }
30715 -+ break;
30716 -+ }
30717 -+ if (thd->transaction.xid_state.xa_state != XA_IDLE &&
30718 -+ thd->transaction.xid_state.xa_state != XA_PREPARED &&
30719 -+ thd->transaction.xid_state.xa_state != XA_ROLLBACK_ONLY)
30720 -+ {
30721 -+ my_error(ER_XAER_RMFAIL, MYF(0),
30722 -+ xa_state_names[thd->transaction.xid_state.xa_state]);
30723 -+ break;
30724 -+ }
30725 -+ if (xa_trans_rollback(thd))
30726 -+ my_error(ER_XAER_RMERR, MYF(0));
30727 -+ else
30728 -+ my_ok(thd);
30729 -+ break;
30730 -+ case SQLCOM_XA_RECOVER:
30731 -+ res= mysql_xa_recover(thd);
30732 -+ break;
30733 -+ case SQLCOM_ALTER_TABLESPACE:
30734 -+ if (check_access(thd, ALTER_ACL, thd->db, 0, 1, 0,
30735 -+ thd->db ? is_schema_db(thd->db, thd->db_length) : 0))
30736 -+ break;
30737 -+ if (!(res= mysql_alter_tablespace(thd, lex->alter_tablespace_info)))
30738 -+ my_ok(thd);
30739 -+ break;
30740 -+ case SQLCOM_INSTALL_PLUGIN:
30741 -+ if (! (res= mysql_install_plugin(thd, &thd->lex->comment,
30742 -+ &thd->lex->ident)))
30743 -+ my_ok(thd);
30744 -+ break;
30745 -+ case SQLCOM_UNINSTALL_PLUGIN:
30746 -+ if (! (res= mysql_uninstall_plugin(thd, &thd->lex->comment)))
30747 -+ my_ok(thd);
30748 -+ break;
30749 -+ case SQLCOM_BINLOG_BASE64_EVENT:
30750 -+ {
30751 -+#ifndef EMBEDDED_LIBRARY
30752 -+ mysql_client_binlog_statement(thd);
30753 -+#else /* EMBEDDED_LIBRARY */
30754 -+ my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "embedded");
30755 -+#endif /* EMBEDDED_LIBRARY */
30756 -+ break;
30757 -+ }
30758 -+ case SQLCOM_CREATE_SERVER:
30759 -+ {
30760 -+ int error;
30761 -+ LEX *lex= thd->lex;
30762 -+ DBUG_PRINT("info", ("case SQLCOM_CREATE_SERVER"));
30763 -+
30764 -+ if (check_global_access(thd, SUPER_ACL))
30765 -+ break;
30766 -+
30767 -+ if ((error= create_server(thd, &lex->server_options)))
30768 -+ {
30769 -+ DBUG_PRINT("info", ("problem creating server <%s>",
30770 -+ lex->server_options.server_name));
30771 -+ my_error(error, MYF(0), lex->server_options.server_name);
30772 -+ break;
30773 -+ }
30774 -+ my_ok(thd, 1);
30775 -+ break;
30776 -+ }
30777 -+ case SQLCOM_ALTER_SERVER:
30778 -+ {
30779 -+ int error;
30780 -+ LEX *lex= thd->lex;
30781 -+ DBUG_PRINT("info", ("case SQLCOM_ALTER_SERVER"));
30782 -+
30783 -+ if (check_global_access(thd, SUPER_ACL))
30784 -+ break;
30785 -+
30786 -+ if ((error= alter_server(thd, &lex->server_options)))
30787 -+ {
30788 -+ DBUG_PRINT("info", ("problem altering server <%s>",
30789 -+ lex->server_options.server_name));
30790 -+ my_error(error, MYF(0), lex->server_options.server_name);
30791 -+ break;
30792 -+ }
30793 -+ my_ok(thd, 1);
30794 -+ break;
30795 -+ }
30796 -+ case SQLCOM_DROP_SERVER:
30797 -+ {
30798 -+ int err_code;
30799 -+ LEX *lex= thd->lex;
30800 -+ DBUG_PRINT("info", ("case SQLCOM_DROP_SERVER"));
30801 -+
30802 -+ if (check_global_access(thd, SUPER_ACL))
30803 -+ break;
30804 -+
30805 -+ if ((err_code= drop_server(thd, &lex->server_options)))
30806 -+ {
30807 -+ if (! lex->drop_if_exists && err_code == ER_FOREIGN_SERVER_DOESNT_EXIST)
30808 -+ {
30809 -+ DBUG_PRINT("info", ("problem dropping server %s",
30810 -+ lex->server_options.server_name));
30811 -+ my_error(err_code, MYF(0), lex->server_options.server_name);
30812 -+ }
30813 -+ else
30814 -+ {
30815 -+ my_ok(thd, 0);
30816 -+ }
30817 -+ break;
30818 -+ }
30819 -+ my_ok(thd, 1);
30820 -+ break;
30821 -+ }
30822 -+ default:
30823 -+#ifndef EMBEDDED_LIBRARY
30824 -+ DBUG_ASSERT(0); /* Impossible */
30825 -+#endif
30826 -+ my_ok(thd);
30827 -+ break;
30828 -+ }
30829 -+ thd_proc_info(thd, "query end");
30830 -+
30831 -+ /*
30832 -+ Binlog-related cleanup:
30833 -+ Reset system variables temporarily modified by SET ONE SHOT.
30834 -+
30835 -+ Exception: If this is a SET, do nothing. This is to allow
30836 -+ mysqlbinlog to print many SET commands (in this case we want the
30837 -+ charset temp setting to live until the real query). This is also
30838 -+ needed so that SET CHARACTER_SET_CLIENT... does not cancel itself
30839 -+ immediately.
30840 -+ */
30841 -+ if (thd->one_shot_set && lex->sql_command != SQLCOM_SET_OPTION)
30842 -+ reset_one_shot_variables(thd);
30843 -+
30844 -+ /*
30845 -+ The return value for ROW_COUNT() is "implementation dependent" if the
30846 -+ statement is not DELETE, INSERT or UPDATE, but -1 is what JDBC and ODBC
30847 -+ wants. We also keep the last value in case of SQLCOM_CALL or
30848 -+ SQLCOM_EXECUTE.
30849 -+ */
30850 -+ if (!(sql_command_flags[lex->sql_command] & CF_HAS_ROW_COUNT))
30851 -+ thd->row_count_func= -1;
30852 -+
30853 -+ goto finish;
30854 -+
30855 -+error:
30856 -+ res= TRUE;
30857 -+
30858 -+finish:
30859 -+ if (need_start_waiting)
30860 -+ {
30861 -+ /*
30862 -+ Release the protection against the global read lock and wake
30863 -+ everyone, who might want to set a global read lock.
30864 -+ */
30865 -+ start_waiting_global_read_lock(thd);
30866 -+ }
30867 -+ DBUG_RETURN(res || thd->is_error());
30868 -+}
30869 -+
30870 -+
30871 -+static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables)
30872 -+{
30873 -+ LEX *lex= thd->lex;
30874 -+ select_result *result=lex->result;
30875 -+ bool res;
30876 -+ /* assign global limit variable if limit is not given */
30877 -+ {
30878 -+ SELECT_LEX *param= lex->unit.global_parameters;
30879 -+ if (!param->explicit_limit)
30880 -+ param->select_limit=
30881 -+ new Item_int((ulonglong) thd->variables.select_limit);
30882 -+ }
30883 -+ if (!(res= open_and_lock_tables(thd, all_tables)))
30884 -+ {
30885 -+ if (lex->describe)
30886 -+ {
30887 -+ /*
30888 -+ We always use select_send for EXPLAIN, even if it's an EXPLAIN
30889 -+ for SELECT ... INTO OUTFILE: a user application should be able
30890 -+ to prepend EXPLAIN to any query and receive output for it,
30891 -+ even if the query itself redirects the output.
30892 -+ */
30893 -+ if (!(result= new select_send()))
30894 -+ return 1; /* purecov: inspected */
30895 -+ thd->send_explain_fields(result);
30896 -+ res= mysql_explain_union(thd, &thd->lex->unit, result);
30897 -+ if (lex->describe & DESCRIBE_EXTENDED)
30898 -+ {
30899 -+ char buff[1024];
30900 -+ String str(buff,(uint32) sizeof(buff), system_charset_info);
30901 -+ str.length(0);
30902 -+ thd->lex->unit.print(&str, QT_ORDINARY);
30903 -+ str.append('\0');
30904 -+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
30905 -+ ER_YES, str.ptr());
30906 -+ }
30907 -+ if (res)
30908 -+ result->abort();
30909 -+ else
30910 -+ result->send_eof();
30911 -+ delete result;
30912 -+ }
30913 -+ else
30914 -+ {
30915 -+ if (!result && !(result= new select_send()))
30916 -+ return 1; /* purecov: inspected */
30917 -+ query_cache_store_query(thd, all_tables);
30918 -+ res= handle_select(thd, lex, result, 0);
30919 -+ if (result != lex->result)
30920 -+ delete result;
30921 -+ }
30922 -+ }
30923 -+ return res;
30924 -+}
30925 -+
30926 -+
30927 -+#ifndef NO_EMBEDDED_ACCESS_CHECKS
30928 -+/**
30929 -+ Check grants for commands which work only with one table.
30930 -+
30931 -+ @param thd Thread handler
30932 -+ @param privilege requested privilege
30933 -+ @param all_tables global table list of query
30934 -+ @param no_errors FALSE/TRUE - report/don't report error to
30935 -+ the client (using my_error() call).
30936 -+
30937 -+ @retval
30938 -+ 0 OK
30939 -+ @retval
30940 -+ 1 access denied, error is sent to client
30941 -+*/
30942 -+
30943 -+bool check_single_table_access(THD *thd, ulong privilege,
30944 -+ TABLE_LIST *all_tables, bool no_errors)
30945 -+{
30946 -+ Security_context * backup_ctx= thd->security_ctx;
30947 -+
30948 -+ /* we need to switch to the saved context (if any) */
30949 -+ if (all_tables->security_ctx)
30950 -+ thd->security_ctx= all_tables->security_ctx;
30951 -+
30952 -+ const char *db_name;
30953 -+ if ((all_tables->view || all_tables->field_translation) &&
30954 -+ !all_tables->schema_table)
30955 -+ db_name= all_tables->view_db.str;
30956 -+ else
30957 -+ db_name= all_tables->db;
30958 -+
30959 -+ if (check_access(thd, privilege, db_name,
30960 -+ &all_tables->grant.privilege, 0, no_errors,
30961 -+ test(all_tables->schema_table)))
30962 -+ goto deny;
30963 -+
30964 -+ /* Show only 1 table for check_grant */
30965 -+ if (!(all_tables->belong_to_view &&
30966 -+ (thd->lex->sql_command == SQLCOM_SHOW_FIELDS)) &&
30967 -+ check_grant(thd, privilege, all_tables, 0, 1, no_errors))
30968 -+ goto deny;
30969 -+
30970 -+ thd->security_ctx= backup_ctx;
30971 -+ return 0;
30972 -+
30973 -+deny:
30974 -+ thd->security_ctx= backup_ctx;
30975 -+ return 1;
30976 -+}
30977 -+
30978 -+/**
30979 -+ Check grants for commands which work only with one table and all other
30980 -+ tables belonging to subselects or implicitly opened tables.
30981 -+
30982 -+ @param thd Thread handler
30983 -+ @param privilege requested privilege
30984 -+ @param all_tables global table list of query
30985 -+
30986 -+ @retval
30987 -+ 0 OK
30988 -+ @retval
30989 -+ 1 access denied, error is sent to client
30990 -+*/
30991 -+
30992 -+bool check_one_table_access(THD *thd, ulong privilege, TABLE_LIST *all_tables)
30993 -+{
30994 -+ if (check_single_table_access (thd,privilege,all_tables, FALSE))
30995 -+ return 1;
30996 -+
30997 -+ /* Check rights on tables of subselects and implictly opened tables */
30998 -+ TABLE_LIST *subselects_tables, *view= all_tables->view ? all_tables : 0;
30999 -+ if ((subselects_tables= all_tables->next_global))
31000 -+ {
31001 -+ /*
31002 -+ Access rights asked for the first table of a view should be the same
31003 -+ as for the view
31004 -+ */
31005 -+ if (view && subselects_tables->belong_to_view == view)
31006 -+ {
31007 -+ if (check_single_table_access (thd, privilege, subselects_tables, FALSE))
31008 -+ return 1;
31009 -+ subselects_tables= subselects_tables->next_global;
31010 -+ }
31011 -+ if (subselects_tables &&
31012 -+ (check_table_access(thd, SELECT_ACL, subselects_tables, UINT_MAX, FALSE)))
31013 -+ return 1;
31014 -+ }
31015 -+ return 0;
31016 -+}
31017 -+
31018 -+
31019 -+/**
31020 -+ Get the user (global) and database privileges for all used tables.
31021 -+
31022 -+ @param save_priv In this we store global and db level grants for the
31023 -+ table. Note that we don't store db level grants if the
31024 -+ global grants is enough to satisfy the request and the
31025 -+ global grants contains a SELECT grant.
31026 -+
31027 -+ @note
31028 -+ The idea of EXTRA_ACL is that one will be granted access to the table if
31029 -+ one has the asked privilege on any column combination of the table; For
31030 -+ example to be able to check a table one needs to have SELECT privilege on
31031 -+ any column of the table.
31032 -+
31033 -+ @retval
31034 -+ 0 ok
31035 -+ @retval
31036 -+ 1 If we can't get the privileges and we don't use table/column
31037 -+ grants.
31038 -+*/
31039 -+bool
31040 -+check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
31041 -+ bool dont_check_global_grants, bool no_errors, bool schema_db)
31042 -+{
31043 -+ Security_context *sctx= thd->security_ctx;
31044 -+ ulong db_access;
31045 -+ /*
31046 -+ GRANT command:
31047 -+ In case of database level grant the database name may be a pattern,
31048 -+ in case of table|column level grant the database name can not be a pattern.
31049 -+ We use 'dont_check_global_grants' as a flag to determine
31050 -+ if it's database level grant command
31051 -+ (see SQLCOM_GRANT case, mysql_execute_command() function) and
31052 -+ set db_is_pattern according to 'dont_check_global_grants' value.
31053 -+ */
31054 -+ bool db_is_pattern= (test(want_access & GRANT_ACL) &&
31055 -+ dont_check_global_grants);
31056 -+ ulong dummy;
31057 -+ DBUG_ENTER("check_access");
31058 -+ DBUG_PRINT("enter",("db: %s want_access: %lu master_access: %lu",
31059 -+ db ? db : "", want_access, sctx->master_access));
31060 -+ if (save_priv)
31061 -+ *save_priv=0;
31062 -+ else
31063 -+ save_priv= &dummy;
31064 -+
31065 -+ thd_proc_info(thd, "checking permissions");
31066 -+ if ((!db || !db[0]) && !thd->db && !dont_check_global_grants)
31067 -+ {
31068 -+ DBUG_PRINT("error",("No database"));
31069 -+ if (!no_errors)
31070 -+ my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR),
31071 -+ MYF(0)); /* purecov: tested */
31072 -+ DBUG_RETURN(TRUE); /* purecov: tested */
31073 -+ }
31074 -+
31075 -+ if (schema_db)
31076 -+ {
31077 -+ if ((!(sctx->master_access & FILE_ACL) && (want_access & FILE_ACL)) ||
31078 -+ (want_access & ~(SELECT_ACL | EXTRA_ACL | FILE_ACL)))
31079 -+ {
31080 -+ if (!no_errors)
31081 -+ {
31082 -+ const char *db_name= db ? db : thd->db;
31083 -+ my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
31084 -+ sctx->priv_user, sctx->priv_host, db_name);
31085 -+ }
31086 -+ DBUG_RETURN(TRUE);
31087 -+ }
31088 -+ else
31089 -+ {
31090 -+ *save_priv= SELECT_ACL;
31091 -+ DBUG_RETURN(FALSE);
31092 -+ }
31093 -+ }
31094 -+
31095 -+ if ((sctx->master_access & want_access) == want_access)
31096 -+ {
31097 -+ /*
31098 -+ If we don't have a global SELECT privilege, we have to get the database
31099 -+ specific access rights to be able to handle queries of type
31100 -+ UPDATE t1 SET a=1 WHERE b > 0
31101 -+ */
31102 -+ db_access= sctx->db_access;
31103 -+ if (!(sctx->master_access & SELECT_ACL) &&
31104 -+ (db && (!thd->db || db_is_pattern || strcmp(db,thd->db))))
31105 -+ db_access=acl_get(sctx->host, sctx->ip, sctx->priv_user, db,
31106 -+ db_is_pattern);
31107 -+ *save_priv=sctx->master_access | db_access;
31108 -+ DBUG_RETURN(FALSE);
31109 -+ }
31110 -+ if (((want_access & ~sctx->master_access) & ~(DB_ACLS | EXTRA_ACL)) ||
31111 -+ (! db && dont_check_global_grants))
31112 -+ { // We can never grant this
31113 -+ DBUG_PRINT("error",("No possible access"));
31114 -+ if (!no_errors)
31115 -+ my_error(ER_ACCESS_DENIED_ERROR, MYF(0),
31116 -+ sctx->priv_user,
31117 -+ sctx->priv_host,
31118 -+ (thd->password ?
31119 -+ ER(ER_YES) :
31120 -+ ER(ER_NO))); /* purecov: tested */
31121 -+ DBUG_RETURN(TRUE); /* purecov: tested */
31122 -+ }
31123 -+
31124 -+ if (db == any_db)
31125 -+ DBUG_RETURN(FALSE); // Allow select on anything
31126 -+
31127 -+ if (db && (!thd->db || db_is_pattern || strcmp(db,thd->db)))
31128 -+ db_access= acl_get(sctx->host, sctx->ip, sctx->priv_user, db,
31129 -+ db_is_pattern);
31130 -+ else
31131 -+ db_access= sctx->db_access;
31132 -+ DBUG_PRINT("info",("db_access: %lu", db_access));
31133 -+ /* Remove SHOW attribute and access rights we already have */
31134 -+ want_access &= ~(sctx->master_access | EXTRA_ACL);
31135 -+ DBUG_PRINT("info",("db_access: %lu want_access: %lu",
31136 -+ db_access, want_access));
31137 -+ db_access= ((*save_priv=(db_access | sctx->master_access)) & want_access);
31138 -+
31139 -+ if (db_access == want_access ||
31140 -+ (!dont_check_global_grants &&
31141 -+ !(want_access & ~(db_access | TABLE_ACLS | PROC_ACLS))))
31142 -+ DBUG_RETURN(FALSE); /* Ok */
31143 -+
31144 -+ DBUG_PRINT("error",("Access denied"));
31145 -+ if (!no_errors)
31146 -+ my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
31147 -+ sctx->priv_user, sctx->priv_host,
31148 -+ (db ? db : (thd->db ?
31149 -+ thd->db :
31150 -+ "unknown"))); /* purecov: tested */
31151 -+ DBUG_RETURN(TRUE); /* purecov: tested */
31152 -+}
31153 -+
31154 -+
31155 -+static bool check_show_access(THD *thd, TABLE_LIST *table)
31156 -+{
31157 -+ switch (get_schema_table_idx(table->schema_table)) {
31158 -+ case SCH_SCHEMATA:
31159 -+ return (specialflag & SPECIAL_SKIP_SHOW_DB) &&
31160 -+ check_global_access(thd, SHOW_DB_ACL);
31161 -+
31162 -+ case SCH_TABLE_NAMES:
31163 -+ case SCH_TABLES:
31164 -+ case SCH_VIEWS:
31165 -+ case SCH_TRIGGERS:
31166 -+ case SCH_EVENTS:
31167 -+ {
31168 -+ const char *dst_db_name= table->schema_select_lex->db;
31169 -+
31170 -+ DBUG_ASSERT(dst_db_name);
31171 -+
31172 -+ if (check_access(thd, SELECT_ACL, dst_db_name,
31173 -+ &thd->col_access, FALSE, FALSE,
31174 -+ is_schema_db(dst_db_name)))
31175 -+ return TRUE;
31176 -+
31177 -+ if (!thd->col_access && check_grant_db(thd, dst_db_name))
31178 -+ {
31179 -+ my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
31180 -+ thd->security_ctx->priv_user,
31181 -+ thd->security_ctx->priv_host,
31182 -+ dst_db_name);
31183 -+ return TRUE;
31184 -+ }
31185 -+
31186 -+ return FALSE;
31187 -+ }
31188 -+
31189 -+ case SCH_COLUMNS:
31190 -+ case SCH_STATISTICS:
31191 -+ {
31192 -+ TABLE_LIST *dst_table;
31193 -+ dst_table= table->schema_select_lex->table_list.first;
31194 -+
31195 -+ DBUG_ASSERT(dst_table);
31196 -+
31197 -+ if (check_access(thd, SELECT_ACL | EXTRA_ACL,
31198 -+ dst_table->db,
31199 -+ &dst_table->grant.privilege,
31200 -+ FALSE, FALSE,
31201 -+ test(dst_table->schema_table)))
31202 -+ return FALSE;
31203 -+
31204 -+ return (check_grant(thd, SELECT_ACL, dst_table, 2, UINT_MAX, FALSE));
31205 -+ }
31206 -+ default:
31207 -+ break;
31208 -+ }
31209 -+
31210 -+ return FALSE;
31211 -+}
31212 -+
31213 -+
31214 -+/**
31215 -+ Check the privilege for all used tables.
31216 -+
31217 -+ @param thd Thread context
31218 -+ @param want_access Privileges requested
31219 -+ @param tables List of tables to be checked
31220 -+ @param number Check at most this number of tables.
31221 -+ @param no_errors FALSE/TRUE - report/don't report error to
31222 -+ the client (using my_error() call).
31223 -+
31224 -+ @note
31225 -+ Table privileges are cached in the table list for GRANT checking.
31226 -+ This functions assumes that table list used and
31227 -+ thd->lex->query_tables_own_last value correspond to each other
31228 -+ (the latter should be either 0 or point to next_global member
31229 -+ of one of elements of this table list).
31230 -+
31231 -+ @retval FALSE OK
31232 -+ @retval TRUE Access denied
31233 -+*/
31234 -+
31235 -+bool
31236 -+check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables,
31237 -+ uint number, bool no_errors)
31238 -+{
31239 -+ TABLE_LIST *org_tables= tables;
31240 -+ TABLE_LIST *first_not_own_table= thd->lex->first_not_own_table();
31241 -+ uint i= 0;
31242 -+ Security_context *sctx= thd->security_ctx, *backup_ctx= thd->security_ctx;
31243 -+ /*
31244 -+ The check that first_not_own_table is not reached is for the case when
31245 -+ the given table list refers to the list for prelocking (contains tables
31246 -+ of other queries). For simple queries first_not_own_table is 0.
31247 -+ */
31248 -+ for (; i < number && tables != first_not_own_table;
31249 -+ tables= tables->next_global, i++)
31250 -+ {
31251 -+ if (tables->security_ctx)
31252 -+ sctx= tables->security_ctx;
31253 -+ else
31254 -+ sctx= backup_ctx;
31255 -+
31256 -+ if (tables->schema_table &&
31257 -+ (want_access & ~(SELECT_ACL | EXTRA_ACL | FILE_ACL)))
31258 -+ {
31259 -+ if (!no_errors)
31260 -+ my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
31261 -+ sctx->priv_user, sctx->priv_host,
31262 -+ INFORMATION_SCHEMA_NAME.str);
31263 -+ return TRUE;
31264 -+ }
31265 -+ /*
31266 -+ Register access for view underlying table.
31267 -+ Remove SHOW_VIEW_ACL, because it will be checked during making view
31268 -+ */
31269 -+ tables->grant.orig_want_privilege= (want_access & ~SHOW_VIEW_ACL);
31270 -+
31271 -+ if (tables->schema_table_reformed)
31272 -+ {
31273 -+ if (check_show_access(thd, tables))
31274 -+ goto deny;
31275 -+
31276 -+ continue;
31277 -+ }
31278 -+
31279 -+ if (tables->is_anonymous_derived_table() ||
31280 -+ (tables->table && (int)tables->table->s->tmp_table))
31281 -+ continue;
31282 -+ thd->security_ctx= sctx;
31283 -+ if ((sctx->master_access & want_access) ==
31284 -+ (want_access & ~EXTRA_ACL) &&
31285 -+ thd->db)
31286 -+ tables->grant.privilege= want_access;
31287 -+ else if (tables->db && thd->db && strcmp(tables->db, thd->db) == 0)
31288 -+ {
31289 -+ if (check_access(thd, want_access, tables->get_db_name(),
31290 -+ &tables->grant.privilege, 0, no_errors,
31291 -+ test(tables->schema_table)))
31292 -+ goto deny; // Access denied
31293 -+ }
31294 -+ else if (check_access(thd, want_access, tables->get_db_name(),
31295 -+ &tables->grant.privilege, 0, no_errors,
31296 -+ test(tables->schema_table)))
31297 -+ goto deny;
31298 -+ }
31299 -+ thd->security_ctx= backup_ctx;
31300 -+ return check_grant(thd,want_access & ~EXTRA_ACL,org_tables,
31301 -+ test(want_access & EXTRA_ACL), number, no_errors);
31302 -+deny:
31303 -+ thd->security_ctx= backup_ctx;
31304 -+ return TRUE;
31305 -+}
31306 -+
31307 -+
31308 -+bool
31309 -+check_routine_access(THD *thd, ulong want_access,char *db, char *name,
31310 -+ bool is_proc, bool no_errors)
31311 -+{
31312 -+ TABLE_LIST tables[1];
31313 -+
31314 -+ bzero((char *)tables, sizeof(TABLE_LIST));
31315 -+ tables->db= db;
31316 -+ tables->table_name= tables->alias= name;
31317 -+
31318 -+ /*
31319 -+ The following test is just a shortcut for check_access() (to avoid
31320 -+ calculating db_access) under the assumption that it's common to
31321 -+ give persons global right to execute all stored SP (but not
31322 -+ necessary to create them).
31323 -+ */
31324 -+ if ((thd->security_ctx->master_access & want_access) == want_access)
31325 -+ tables->grant.privilege= want_access;
31326 -+ else if (check_access(thd,want_access,db,&tables->grant.privilege,
31327 -+ 0, no_errors, 0))
31328 -+ return TRUE;
31329 -+
31330 -+ return check_grant_routine(thd, want_access, tables, is_proc, no_errors);
31331 -+}
31332 -+
31333 -+
31334 -+/**
31335 -+ Check if the routine has any of the routine privileges.
31336 -+
31337 -+ @param thd Thread handler
31338 -+ @param db Database name
31339 -+ @param name Routine name
31340 -+
31341 -+ @retval
31342 -+ 0 ok
31343 -+ @retval
31344 -+ 1 error
31345 -+*/
31346 -+
31347 -+bool check_some_routine_access(THD *thd, const char *db, const char *name,
31348 -+ bool is_proc)
31349 -+{
31350 -+ ulong save_priv;
31351 -+ if (thd->security_ctx->master_access & SHOW_PROC_ACLS)
31352 -+ return FALSE;
31353 -+ /*
31354 -+ There are no routines in information_schema db. So we can safely
31355 -+ pass zero to last paramter of check_access function
31356 -+ */
31357 -+ if (!check_access(thd, SHOW_PROC_ACLS, db, &save_priv, 0, 1, 0) ||
31358 -+ (save_priv & SHOW_PROC_ACLS))
31359 -+ return FALSE;
31360 -+ return check_routine_level_acl(thd, db, name, is_proc);
31361 -+}
31362 -+
31363 -+
31364 -+/*
31365 -+ Check if the given table has any of the asked privileges
31366 -+
31367 -+ @param thd Thread handler
31368 -+ @param want_access Bitmap of possible privileges to check for
31369 -+
31370 -+ @retval
31371 -+ 0 ok
31372 -+ @retval
31373 -+ 1 error
31374 -+*/
31375 -+
31376 -+bool check_some_access(THD *thd, ulong want_access, TABLE_LIST *table)
31377 -+{
31378 -+ ulong access;
31379 -+ DBUG_ENTER("check_some_access");
31380 -+
31381 -+ /* This loop will work as long as we have less than 32 privileges */
31382 -+ for (access= 1; access < want_access ; access<<= 1)
31383 -+ {
31384 -+ if (access & want_access)
31385 -+ {
31386 -+ if (!check_access(thd, access, table->db,
31387 -+ &table->grant.privilege, 0, 1,
31388 -+ test(table->schema_table)) &&
31389 -+ !check_grant(thd, access, table, 0, 1, 1))
31390 -+ DBUG_RETURN(0);
31391 -+ }
31392 -+ }
31393 -+ DBUG_PRINT("exit",("no matching access rights"));
31394 -+ DBUG_RETURN(1);
31395 -+}
31396 -+
31397 -+#endif /*NO_EMBEDDED_ACCESS_CHECKS*/
31398 -+
31399 -+
31400 -+/**
31401 -+ check for global access and give descriptive error message if it fails.
31402 -+
31403 -+ @param thd Thread handler
31404 -+ @param want_access Use should have any of these global rights
31405 -+
31406 -+ @warning
31407 -+ One gets access right if one has ANY of the rights in want_access.
31408 -+ This is useful as one in most cases only need one global right,
31409 -+ but in some case we want to check if the user has SUPER or
31410 -+ REPL_CLIENT_ACL rights.
31411 -+
31412 -+ @retval
31413 -+ 0 ok
31414 -+ @retval
31415 -+ 1 Access denied. In this case an error is sent to the client
31416 -+*/
31417 -+
31418 -+bool check_global_access(THD *thd, ulong want_access)
31419 -+{
31420 -+#ifndef NO_EMBEDDED_ACCESS_CHECKS
31421 -+ char command[128];
31422 -+ if ((thd->security_ctx->master_access & want_access))
31423 -+ return 0;
31424 -+ get_privilege_desc(command, sizeof(command), want_access);
31425 -+ my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), command);
31426 -+ return 1;
31427 -+#else
31428 -+ return 0;
31429 -+#endif
31430 -+}
31431 -+
31432 -+/****************************************************************************
31433 -+ Check stack size; Send error if there isn't enough stack to continue
31434 -+****************************************************************************/
31435 -+
31436 -+#ifndef EMBEDDED_LIBRARY
31437 -+
31438 -+#if STACK_DIRECTION < 0
31439 -+#define used_stack(A,B) (long) (A - B)
31440 -+#else
31441 -+#define used_stack(A,B) (long) (B - A)
31442 -+#endif
31443 -+
31444 -+#ifndef DBUG_OFF
31445 -+long max_stack_used;
31446 -+#endif
31447 -+
31448 -+/**
31449 -+ @note
31450 -+ Note: The 'buf' parameter is necessary, even if it is unused here.
31451 -+ - fix_fields functions has a "dummy" buffer large enough for the
31452 -+ corresponding exec. (Thus we only have to check in fix_fields.)
31453 -+ - Passing to check_stack_overrun() prevents the compiler from removing it.
31454 -+*/
31455 -+bool check_stack_overrun(THD *thd, long margin,
31456 -+ uchar *buf __attribute__((unused)))
31457 -+{
31458 -+ long stack_used;
31459 -+ DBUG_ASSERT(thd == current_thd);
31460 -+ if ((stack_used=used_stack(thd->thread_stack,(char*) &stack_used)) >=
31461 -+ (long) (my_thread_stack_size - margin))
31462 -+ {
31463 -+ char ebuff[MYSQL_ERRMSG_SIZE];
31464 -+ my_snprintf(ebuff, sizeof(ebuff), ER(ER_STACK_OVERRUN_NEED_MORE),
31465 -+ stack_used, my_thread_stack_size, margin);
31466 -+ my_message(ER_STACK_OVERRUN_NEED_MORE, ebuff, MYF(ME_FATALERROR));
31467 -+ thd->fatal_error();
31468 -+ return 1;
31469 -+ }
31470 -+#ifndef DBUG_OFF
31471 -+ max_stack_used= max(max_stack_used, stack_used);
31472 -+#endif
31473 -+ return 0;
31474 -+}
31475 -+#endif /* EMBEDDED_LIBRARY */
31476 -+
31477 -+#define MY_YACC_INIT 1000 // Start with big alloc
31478 -+#define MY_YACC_MAX 32000 // Because of 'short'
31479 -+
31480 -+bool my_yyoverflow(short **yyss, YYSTYPE **yyvs, ulong *yystacksize)
31481 -+{
31482 -+ Yacc_state *state= & current_thd->m_parser_state->m_yacc;
31483 -+ ulong old_info=0;
31484 -+ DBUG_ASSERT(state);
31485 -+ if ((uint) *yystacksize >= MY_YACC_MAX)
31486 -+ return 1;
31487 -+ if (!state->yacc_yyvs)
31488 -+ old_info= *yystacksize;
31489 -+ *yystacksize= set_zone((*yystacksize)*2,MY_YACC_INIT,MY_YACC_MAX);
31490 -+ if (!(state->yacc_yyvs= (uchar*)
31491 -+ my_realloc(state->yacc_yyvs,
31492 -+ *yystacksize*sizeof(**yyvs),
31493 -+ MYF(MY_ALLOW_ZERO_PTR | MY_FREE_ON_ERROR))) ||
31494 -+ !(state->yacc_yyss= (uchar*)
31495 -+ my_realloc(state->yacc_yyss,
31496 -+ *yystacksize*sizeof(**yyss),
31497 -+ MYF(MY_ALLOW_ZERO_PTR | MY_FREE_ON_ERROR))))
31498 -+ return 1;
31499 -+ if (old_info)
31500 -+ {
31501 -+ /*
31502 -+ Only copy the old stack on the first call to my_yyoverflow(),
31503 -+ when replacing a static stack (YYINITDEPTH) by a dynamic stack.
31504 -+ For subsequent calls, my_realloc already did preserve the old stack.
31505 -+ */
31506 -+ memcpy(state->yacc_yyss, *yyss, old_info*sizeof(**yyss));
31507 -+ memcpy(state->yacc_yyvs, *yyvs, old_info*sizeof(**yyvs));
31508 -+ }
31509 -+ *yyss= (short*) state->yacc_yyss;
31510 -+ *yyvs= (YYSTYPE*) state->yacc_yyvs;
31511 -+ return 0;
31512 -+}
31513 -+
31514 -+
31515 -+/**
31516 -+ Reset THD part responsible for command processing state.
31517 -+
31518 -+ This needs to be called before execution of every statement
31519 -+ (prepared or conventional).
31520 -+ It is not called by substatements of routines.
31521 -+
31522 -+ @todo
31523 -+ Make it a method of THD and align its name with the rest of
31524 -+ reset/end/start/init methods.
31525 -+ @todo
31526 -+ Call it after we use THD for queries, not before.
31527 -+*/
31528 -+
31529 -+void mysql_reset_thd_for_next_command(THD *thd)
31530 -+{
31531 -+ DBUG_ENTER("mysql_reset_thd_for_next_command");
31532 -+ DBUG_ASSERT(!thd->spcont); /* not for substatements of routines */
31533 -+ DBUG_ASSERT(! thd->in_sub_stmt);
31534 -+ thd->free_list= 0;
31535 -+ thd->select_number= 1;
31536 -+ /*
31537 -+ Those two lines below are theoretically unneeded as
31538 -+ THD::cleanup_after_query() should take care of this already.
31539 -+ */
31540 -+ thd->auto_inc_intervals_in_cur_stmt_for_binlog.empty();
31541 -+ thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt= 0;
31542 -+
31543 -+ thd->query_start_used= 0;
31544 -+ thd->is_fatal_error= thd->time_zone_used= 0;
31545 -+ /*
31546 -+ Clear the status flag that are expected to be cleared at the
31547 -+ beginning of each SQL statement.
31548 -+ */
31549 -+ thd->server_status&= ~SERVER_STATUS_CLEAR_SET;
31550 -+ /*
31551 -+ If in autocommit mode and not in a transaction, reset
31552 -+ OPTION_STATUS_NO_TRANS_UPDATE | OPTION_KEEP_LOG to not get warnings
31553 -+ in ha_rollback_trans() about some tables couldn't be rolled back.
31554 -+ */
31555 -+ if (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))
31556 -+ {
31557 -+ thd->options&= ~OPTION_KEEP_LOG;
31558 -+ thd->transaction.all.modified_non_trans_table= FALSE;
31559 -+ }
31560 -+ DBUG_ASSERT(thd->security_ctx== &thd->main_security_ctx);
31561 -+ thd->thread_specific_used= FALSE;
31562 -+
31563 -+ if (opt_bin_log)
31564 -+ {
31565 -+ reset_dynamic(&thd->user_var_events);
31566 -+ thd->user_var_events_alloc= thd->mem_root;
31567 -+ }
31568 -+ thd->clear_error();
31569 -+ thd->main_da.reset_diagnostics_area();
31570 -+ thd->total_warn_count=0; // Warnings for this query
31571 -+ thd->rand_used= 0;
31572 -+ thd->sent_row_count= thd->examined_row_count= 0;
31573 -+
31574 -+ /*
31575 -+ Because we come here only for start of top-statements, binlog format is
31576 -+ constant inside a complex statement (using stored functions) etc.
31577 -+ */
31578 -+ thd->reset_current_stmt_binlog_row_based();
31579 -+
31580 -+ DBUG_PRINT("debug",
31581 -+ ("current_stmt_binlog_row_based: %d",
31582 -+ thd->current_stmt_binlog_row_based));
31583 -+
31584 -+ DBUG_VOID_RETURN;
31585 -+}
31586 -+
31587 -+
31588 -+/**
31589 -+ Resets the lex->current_select object.
31590 -+ @note It is assumed that lex->current_select != NULL
31591 -+
31592 -+ This function is a wrapper around select_lex->init_select() with an added
31593 -+ check for the special situation when using INTO OUTFILE and LOAD DATA.
31594 -+*/
31595 -+
31596 -+void
31597 -+mysql_init_select(LEX *lex)
31598 -+{
31599 -+ SELECT_LEX *select_lex= lex->current_select;
31600 -+ select_lex->init_select();
31601 -+ lex->wild= 0;
31602 -+ if (select_lex == &lex->select_lex)
31603 -+ {
31604 -+ DBUG_ASSERT(lex->result == 0);
31605 -+ lex->exchange= 0;
31606 -+ }
31607 -+}
31608 -+
31609 -+
31610 -+/**
31611 -+ Used to allocate a new SELECT_LEX object on the current thd mem_root and
31612 -+ link it into the relevant lists.
31613 -+
31614 -+ This function is always followed by mysql_init_select.
31615 -+
31616 -+ @see mysql_init_select
31617 -+
31618 -+ @retval TRUE An error occurred
31619 -+ @retval FALSE The new SELECT_LEX was successfully allocated.
31620 -+*/
31621 -+
31622 -+bool
31623 -+mysql_new_select(LEX *lex, bool move_down)
31624 -+{
31625 -+ SELECT_LEX *select_lex;
31626 -+ THD *thd= lex->thd;
31627 -+ DBUG_ENTER("mysql_new_select");
31628 -+
31629 -+ if (!(select_lex= new (thd->mem_root) SELECT_LEX()))
31630 -+ DBUG_RETURN(1);
31631 -+ select_lex->select_number= ++thd->select_number;
31632 -+ select_lex->parent_lex= lex; /* Used in init_query. */
31633 -+ select_lex->init_query();
31634 -+ select_lex->init_select();
31635 -+ lex->nest_level++;
31636 -+ if (lex->nest_level > (int) MAX_SELECT_NESTING)
31637 -+ {
31638 -+ my_error(ER_TOO_HIGH_LEVEL_OF_NESTING_FOR_SELECT,MYF(0),MAX_SELECT_NESTING);
31639 -+ DBUG_RETURN(1);
31640 -+ }
31641 -+ select_lex->nest_level= lex->nest_level;
31642 -+ if (move_down)
31643 -+ {
31644 -+ SELECT_LEX_UNIT *unit;
31645 -+ lex->subqueries= TRUE;
31646 -+ /* first select_lex of subselect or derived table */
31647 -+ if (!(unit= new (thd->mem_root) SELECT_LEX_UNIT()))
31648 -+ DBUG_RETURN(1);
31649 -+
31650 -+ unit->init_query();
31651 -+ unit->init_select();
31652 -+ unit->thd= thd;
31653 -+ unit->include_down(lex->current_select);
31654 -+ unit->link_next= 0;
31655 -+ unit->link_prev= 0;
31656 -+ unit->return_to= lex->current_select;
31657 -+ select_lex->include_down(unit);
31658 -+ /*
31659 -+ By default we assume that it is usual subselect and we have outer name
31660 -+ resolution context, if no we will assign it to 0 later
31661 -+ */
31662 -+ select_lex->context.outer_context= &select_lex->outer_select()->context;
31663 -+ }
31664 -+ else
31665 -+ {
31666 -+ if (lex->current_select->order_list.first && !lex->current_select->braces)
31667 -+ {
31668 -+ my_error(ER_WRONG_USAGE, MYF(0), "UNION", "ORDER BY");
31669 -+ DBUG_RETURN(1);
31670 -+ }
31671 -+ select_lex->include_neighbour(lex->current_select);
31672 -+ SELECT_LEX_UNIT *unit= select_lex->master_unit();
31673 -+ if (!unit->fake_select_lex && unit->add_fake_select_lex(lex->thd))
31674 -+ DBUG_RETURN(1);
31675 -+ select_lex->context.outer_context=
31676 -+ unit->first_select()->context.outer_context;
31677 -+ }
31678 -+
31679 -+ select_lex->master_unit()->global_parameters= select_lex;
31680 -+ select_lex->include_global((st_select_lex_node**)&lex->all_selects_list);
31681 -+ lex->current_select= select_lex;
31682 -+ /*
31683 -+ in subquery is SELECT query and we allow resolution of names in SELECT
31684 -+ list
31685 -+ */
31686 -+ select_lex->context.resolve_in_select_list= TRUE;
31687 -+ DBUG_RETURN(0);
31688 -+}
31689 -+
31690 -+/**
31691 -+ Create a select to return the same output as 'SELECT @@var_name'.
31692 -+
31693 -+ Used for SHOW COUNT(*) [ WARNINGS | ERROR].
31694 -+
31695 -+ This will crash with a core dump if the variable doesn't exists.
31696 -+
31697 -+ @param var_name Variable name
31698 -+*/
31699 -+
31700 -+void create_select_for_variable(const char *var_name)
31701 -+{
31702 -+ THD *thd;
31703 -+ LEX *lex;
31704 -+ LEX_STRING tmp, null_lex_string;
31705 -+ Item *var;
31706 -+ char buff[MAX_SYS_VAR_LENGTH*2+4+8], *end;
31707 -+ DBUG_ENTER("create_select_for_variable");
31708 -+
31709 -+ thd= current_thd;
31710 -+ lex= thd->lex;
31711 -+ mysql_init_select(lex);
31712 -+ lex->sql_command= SQLCOM_SELECT;
31713 -+ tmp.str= (char*) var_name;
31714 -+ tmp.length=strlen(var_name);
31715 -+ bzero((char*) &null_lex_string.str, sizeof(null_lex_string));
31716 -+ /*
31717 -+ We set the name of Item to @@session.var_name because that then is used
31718 -+ as the column name in the output.
31719 -+ */
31720 -+ if ((var= get_system_var(thd, OPT_SESSION, tmp, null_lex_string)))
31721 -+ {
31722 -+ end= strxmov(buff, "@@session.", var_name, NullS);
31723 -+ var->set_name(buff, end-buff, system_charset_info);
31724 -+ add_item_to_list(thd, var);
31725 -+ }
31726 -+ DBUG_VOID_RETURN;
31727 -+}
31728 -+
31729 -+
31730 -+void mysql_init_multi_delete(LEX *lex)
31731 -+{
31732 -+ lex->sql_command= SQLCOM_DELETE_MULTI;
31733 -+ mysql_init_select(lex);
31734 -+ lex->select_lex.select_limit= 0;
31735 -+ lex->unit.select_limit_cnt= HA_POS_ERROR;
31736 -+ lex->select_lex.table_list.save_and_clear(&lex->auxiliary_table_list);
31737 -+ lex->lock_option= TL_READ_DEFAULT;
31738 -+ lex->query_tables= 0;
31739 -+ lex->query_tables_last= &lex->query_tables;
31740 -+}
31741 -+
31742 -+
31743 -+/*
31744 -+ When you modify mysql_parse(), you may need to mofify
31745 -+ mysql_test_parse_for_slave() in this same file.
31746 -+*/
31747 -+
31748 -+/**
31749 -+ Parse a query.
31750 -+
31751 -+ @param thd Current thread
31752 -+ @param rawbuf Begining of the query text
31753 -+ @param length Length of the query text
31754 -+ @param[out] found_semicolon For multi queries, position of the character of
31755 -+ the next query in the query text.
31756 -+*/
31757 -+
31758 -+void mysql_parse(THD *thd, char *rawbuf, uint length,
31759 -+ const char ** found_semicolon)
31760 -+{
31761 -+ DBUG_ENTER("mysql_parse");
31762 -+
31763 -+ DBUG_EXECUTE_IF("parser_debug", turn_parser_debug_on(););
31764 -+
31765 -+ /*
31766 -+ Warning.
31767 -+ The purpose of query_cache_send_result_to_client() is to lookup the
31768 -+ query in the query cache first, to avoid parsing and executing it.
31769 -+ So, the natural implementation would be to:
31770 -+ - first, call query_cache_send_result_to_client,
31771 -+ - second, if caching failed, initialise the lexical and syntactic parser.
31772 -+ The problem is that the query cache depends on a clean initialization
31773 -+ of (among others) lex->safe_to_cache_query and thd->server_status,
31774 -+ which are reset respectively in
31775 -+ - lex_start()
31776 -+ - mysql_reset_thd_for_next_command()
31777 -+ So, initializing the lexical analyser *before* using the query cache
31778 -+ is required for the cache to work properly.
31779 -+ FIXME: cleanup the dependencies in the code to simplify this.
31780 -+ */
31781 -+ lex_start(thd);
31782 -+ mysql_reset_thd_for_next_command(thd);
31783 -+
31784 -+ if (query_cache_send_result_to_client(thd, rawbuf, length) <= 0)
31785 -+ {
31786 -+ LEX *lex= thd->lex;
31787 -+
31788 -+ sp_cache_flush_obsolete(&thd->sp_proc_cache);
31789 -+ sp_cache_flush_obsolete(&thd->sp_func_cache);
31790 -+
31791 -+ Parser_state parser_state;
31792 -+ bool err;
31793 -+ if (!(err= parser_state.init(thd, rawbuf, length)))
31794 -+ {
31795 -+ err= parse_sql(thd, & parser_state, NULL);
31796 -+ *found_semicolon= parser_state.m_lip.found_semicolon;
31797 -+ }
31798 -+ else
31799 -+ *found_semicolon= NULL;
31800 -+
31801 -+ if (!err)
31802 -+ {
31803 -+#ifndef NO_EMBEDDED_ACCESS_CHECKS
31804 -+ if (mqh_used && thd->user_connect &&
31805 -+ check_mqh(thd, lex->sql_command))
31806 -+ {
31807 -+ thd->net.error = 0;
31808 -+ }
31809 -+ else
31810 -+#endif
31811 -+ {
31812 -+ if (! thd->is_error())
31813 -+ {
31814 -+ /*
31815 -+ Binlog logs a string starting from thd->query and having length
31816 -+ thd->query_length; so we set thd->query_length correctly (to not
31817 -+ log several statements in one event, when we executed only first).
31818 -+ We set it to not see the ';' (otherwise it would get into binlog
31819 -+ and Query_log_event::print() would give ';;' output).
31820 -+ This also helps display only the current query in SHOW
31821 -+ PROCESSLIST.
31822 -+ Note that we don't need LOCK_thread_count to modify query_length.
31823 -+ */
31824 -+ if (*found_semicolon && (ulong) (*found_semicolon - thd->query()))
31825 -+ thd->set_query_inner(thd->query(),
31826 -+ (uint32) (*found_semicolon -
31827 -+ thd->query() - 1));
31828 -+ /* Actually execute the query */
31829 -+ if (*found_semicolon)
31830 -+ {
31831 -+ lex->safe_to_cache_query= 0;
31832 -+ thd->server_status|= SERVER_MORE_RESULTS_EXISTS;
31833 -+ }
31834 -+ lex->set_trg_event_type_for_tables();
31835 -+ mysql_execute_command(thd);
31836 -+ }
31837 -+ }
31838 -+ }
31839 -+ else
31840 -+ {
31841 -+ DBUG_ASSERT(thd->is_error());
31842 -+ DBUG_PRINT("info",("Command aborted. Fatal_error: %d",
31843 -+ thd->is_fatal_error));
31844 -+
31845 -+ query_cache_abort(&thd->net);
31846 -+ }
31847 -+ if (thd->lex->sphead)
31848 -+ {
31849 -+ delete thd->lex->sphead;
31850 -+ thd->lex->sphead= 0;
31851 -+ }
31852 -+ lex->unit.cleanup();
31853 -+ thd_proc_info(thd, "freeing items");
31854 -+ thd->end_statement();
31855 -+ thd->cleanup_after_query();
31856 -+ DBUG_ASSERT(thd->change_list.is_empty());
31857 -+ }
31858 -+ else
31859 -+ {
31860 -+ /* There are no multi queries in the cache. */
31861 -+ *found_semicolon= NULL;
31862 -+ }
31863 -+
31864 -+ DBUG_VOID_RETURN;
31865 -+}
31866 -+
31867 -+
31868 -+#ifdef HAVE_REPLICATION
31869 -+/*
31870 -+ Usable by the replication SQL thread only: just parse a query to know if it
31871 -+ can be ignored because of replicate-*-table rules.
31872 -+
31873 -+ @retval
31874 -+ 0 cannot be ignored
31875 -+ @retval
31876 -+ 1 can be ignored
31877 -+*/
31878 -+
31879 -+bool mysql_test_parse_for_slave(THD *thd, char *rawbuf, uint length)
31880 -+{
31881 -+ LEX *lex= thd->lex;
31882 -+ bool error= 0;
31883 -+ DBUG_ENTER("mysql_test_parse_for_slave");
31884 -+
31885 -+ Parser_state parser_state;
31886 -+ if (!(error= parser_state.init(thd, rawbuf, length)))
31887 -+ {
31888 -+ lex_start(thd);
31889 -+ mysql_reset_thd_for_next_command(thd);
31890 -+
31891 -+ if (!parse_sql(thd, & parser_state, NULL) &&
31892 -+ all_tables_not_ok(thd, lex->select_lex.table_list.first))
31893 -+ error= 1; /* Ignore question */
31894 -+ thd->end_statement();
31895 -+ }
31896 -+ thd->cleanup_after_query();
31897 -+ DBUG_RETURN(error);
31898 -+}
31899 -+#endif
31900 -+
31901 -+
31902 -+
31903 -+/**
31904 -+ Store field definition for create.
31905 -+
31906 -+ @return
31907 -+ Return 0 if ok
31908 -+*/
31909 -+
31910 -+bool add_field_to_list(THD *thd, LEX_STRING *field_name, enum_field_types type,
31911 -+ char *length, char *decimals,
31912 -+ uint type_modifier,
31913 -+ Item *default_value, Item *on_update_value,
31914 -+ LEX_STRING *comment,
31915 -+ char *change,
31916 -+ List<String> *interval_list, CHARSET_INFO *cs,
31917 -+ uint uint_geom_type)
31918 -+{
31919 -+ register Create_field *new_field;
31920 -+ LEX *lex= thd->lex;
31921 -+ DBUG_ENTER("add_field_to_list");
31922 -+
31923 -+ if (check_string_char_length(field_name, "", NAME_CHAR_LEN,
31924 -+ system_charset_info, 1))
31925 -+ {
31926 -+ my_error(ER_TOO_LONG_IDENT, MYF(0), field_name->str); /* purecov: inspected */
31927 -+ DBUG_RETURN(1); /* purecov: inspected */
31928 -+ }
31929 -+ if (type_modifier & PRI_KEY_FLAG)
31930 -+ {
31931 -+ Key *key;
31932 -+ lex->col_list.push_back(new Key_part_spec(field_name->str, 0));
31933 -+ key= new Key(Key::PRIMARY, NullS,
31934 -+ &default_key_create_info,
31935 -+ 0, lex->col_list);
31936 -+ lex->alter_info.key_list.push_back(key);
31937 -+ lex->col_list.empty();
31938 -+ }
31939 -+ if (type_modifier & (UNIQUE_FLAG | UNIQUE_KEY_FLAG))
31940 -+ {
31941 -+ Key *key;
31942 -+ lex->col_list.push_back(new Key_part_spec(field_name->str, 0));
31943 -+ key= new Key(Key::UNIQUE, NullS,
31944 -+ &default_key_create_info, 0,
31945 -+ lex->col_list);
31946 -+ lex->alter_info.key_list.push_back(key);
31947 -+ lex->col_list.empty();
31948 -+ }
31949 -+
31950 -+ if (default_value)
31951 -+ {
31952 -+ /*
31953 -+ Default value should be literal => basic constants =>
31954 -+ no need fix_fields()
31955 -+
31956 -+ We allow only one function as part of default value -
31957 -+ NOW() as default for TIMESTAMP type.
31958 -+ */
31959 -+ if (default_value->type() == Item::FUNC_ITEM &&
31960 -+ !(((Item_func*)default_value)->functype() == Item_func::NOW_FUNC &&
31961 -+ type == MYSQL_TYPE_TIMESTAMP))
31962 -+ {
31963 -+ my_error(ER_INVALID_DEFAULT, MYF(0), field_name->str);
31964 -+ DBUG_RETURN(1);
31965 -+ }
31966 -+ else if (default_value->type() == Item::NULL_ITEM)
31967 -+ {
31968 -+ default_value= 0;
31969 -+ if ((type_modifier & (NOT_NULL_FLAG | AUTO_INCREMENT_FLAG)) ==
31970 -+ NOT_NULL_FLAG)
31971 -+ {
31972 -+ my_error(ER_INVALID_DEFAULT, MYF(0), field_name->str);
31973 -+ DBUG_RETURN(1);
31974 -+ }
31975 -+ }
31976 -+ else if (type_modifier & AUTO_INCREMENT_FLAG)
31977 -+ {
31978 -+ my_error(ER_INVALID_DEFAULT, MYF(0), field_name->str);
31979 -+ DBUG_RETURN(1);
31980 -+ }
31981 -+ }
31982 -+
31983 -+ if (on_update_value && type != MYSQL_TYPE_TIMESTAMP)
31984 -+ {
31985 -+ my_error(ER_INVALID_ON_UPDATE, MYF(0), field_name->str);
31986 -+ DBUG_RETURN(1);
31987 -+ }
31988 -+
31989 -+ if (type == MYSQL_TYPE_TIMESTAMP && length)
31990 -+ {
31991 -+ /* Display widths are no longer supported for TIMSTAMP as of MySQL 4.1.
31992 -+ In other words, for declarations such as TIMESTAMP(2), TIMESTAMP(4),
31993 -+ and so on, the display width is ignored.
31994 -+ */
31995 -+ char buf[32];
31996 -+ my_snprintf(buf, sizeof(buf), "TIMESTAMP(%s)", length);
31997 -+ WARN_DEPRECATED(thd, "6.0", buf, "'TIMESTAMP'");
31998 -+ }
31999 -+
32000 -+ if (!(new_field= new Create_field()) ||
32001 -+ new_field->init(thd, field_name->str, type, length, decimals, type_modifier,
32002 -+ default_value, on_update_value, comment, change,
32003 -+ interval_list, cs, uint_geom_type))
32004 -+ DBUG_RETURN(1);
32005 -+
32006 -+ lex->alter_info.create_list.push_back(new_field);
32007 -+ lex->last_field=new_field;
32008 -+ DBUG_RETURN(0);
32009 -+}
32010 -+
32011 -+
32012 -+/** Store position for column in ALTER TABLE .. ADD column. */
32013 -+
32014 -+void store_position_for_column(const char *name)
32015 -+{
32016 -+ current_thd->lex->last_field->after=my_const_cast(char*) (name);
32017 -+}
32018 -+
32019 -+bool
32020 -+add_proc_to_list(THD* thd, Item *item)
32021 -+{
32022 -+ ORDER *order;
32023 -+ Item **item_ptr;
32024 -+
32025 -+ if (!(order = (ORDER *) thd->alloc(sizeof(ORDER)+sizeof(Item*))))
32026 -+ return 1;
32027 -+ item_ptr = (Item**) (order+1);
32028 -+ *item_ptr= item;
32029 -+ order->item=item_ptr;
32030 -+ order->free_me=0;
32031 -+ thd->lex->proc_list.link_in_list(order, &order->next);
32032 -+ return 0;
32033 -+}
32034 -+
32035 -+
32036 -+/**
32037 -+ save order by and tables in own lists.
32038 -+*/
32039 -+
32040 -+bool add_to_list(THD *thd, SQL_I_List<ORDER> &list, Item *item,bool asc)
32041 -+{
32042 -+ ORDER *order;
32043 -+ DBUG_ENTER("add_to_list");
32044 -+ if (!(order = (ORDER *) thd->alloc(sizeof(ORDER))))
32045 -+ DBUG_RETURN(1);
32046 -+ order->item_ptr= item;
32047 -+ order->item= &order->item_ptr;
32048 -+ order->asc = asc;
32049 -+ order->free_me=0;
32050 -+ order->used=0;
32051 -+ order->counter_used= 0;
32052 -+ list.link_in_list(order, &order->next);
32053 -+ DBUG_RETURN(0);
32054 -+}
32055 -+
32056 -+
32057 -+/**
32058 -+ Add a table to list of used tables.
32059 -+
32060 -+ @param table Table to add
32061 -+ @param alias alias for table (or null if no alias)
32062 -+ @param table_options A set of the following bits:
32063 -+ - TL_OPTION_UPDATING : Table will be updated
32064 -+ - TL_OPTION_FORCE_INDEX : Force usage of index
32065 -+ - TL_OPTION_ALIAS : an alias in multi table DELETE
32066 -+ @param lock_type How table should be locked
32067 -+ @param use_index List of indexed used in USE INDEX
32068 -+ @param ignore_index List of indexed used in IGNORE INDEX
32069 -+
32070 -+ @retval
32071 -+ 0 Error
32072 -+ @retval
32073 -+ \# Pointer to TABLE_LIST element added to the total table list
32074 -+*/
32075 -+
32076 -+TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
32077 -+ Table_ident *table,
32078 -+ LEX_STRING *alias,
32079 -+ ulong table_options,
32080 -+ thr_lock_type lock_type,
32081 -+ List<Index_hint> *index_hints_arg,
32082 -+ LEX_STRING *option)
32083 -+{
32084 -+ register TABLE_LIST *ptr;
32085 -+ TABLE_LIST *previous_table_ref; /* The table preceding the current one. */
32086 -+ char *alias_str;
32087 -+ LEX *lex= thd->lex;
32088 -+ DBUG_ENTER("add_table_to_list");
32089 -+ LINT_INIT(previous_table_ref);
32090 -+
32091 -+ if (!table)
32092 -+ DBUG_RETURN(0); // End of memory
32093 -+ alias_str= alias ? alias->str : table->table.str;
32094 -+ if (!test(table_options & TL_OPTION_ALIAS) &&
32095 -+ check_table_name(table->table.str, table->table.length, FALSE))
32096 -+ {
32097 -+ my_error(ER_WRONG_TABLE_NAME, MYF(0), table->table.str);
32098 -+ DBUG_RETURN(0);
32099 -+ }
32100 -+
32101 -+ if (table->is_derived_table() == FALSE && table->db.str &&
32102 -+ check_db_name(&table->db))
32103 -+ {
32104 -+ my_error(ER_WRONG_DB_NAME, MYF(0), table->db.str);
32105 -+ DBUG_RETURN(0);
32106 -+ }
32107 -+
32108 -+ if (!alias) /* Alias is case sensitive */
32109 -+ {
32110 -+ if (table->sel)
32111 -+ {
32112 -+ my_message(ER_DERIVED_MUST_HAVE_ALIAS,
32113 -+ ER(ER_DERIVED_MUST_HAVE_ALIAS), MYF(0));
32114 -+ DBUG_RETURN(0);
32115 -+ }
32116 -+ if (!(alias_str= (char*) thd->memdup(alias_str,table->table.length+1)))
32117 -+ DBUG_RETURN(0);
32118 -+ }
32119 -+ if (!(ptr = (TABLE_LIST *) thd->calloc(sizeof(TABLE_LIST))))
32120 -+ DBUG_RETURN(0); /* purecov: inspected */
32121 -+ if (table->db.str)
32122 -+ {
32123 -+ ptr->db= table->db.str;
32124 -+ ptr->db_length= table->db.length;
32125 -+ }
32126 -+ else if (lex->copy_db_to(&ptr->db, &ptr->db_length))
32127 -+ DBUG_RETURN(0);
32128 -+
32129 -+ ptr->alias= alias_str;
32130 -+ if (lower_case_table_names && table->table.length)
32131 -+ table->table.length= my_casedn_str(files_charset_info, table->table.str);
32132 -+ ptr->table_name=table->table.str;
32133 -+ ptr->table_name_length=table->table.length;
32134 -+ ptr->lock_type= lock_type;
32135 -+ ptr->updating= test(table_options & TL_OPTION_UPDATING);
32136 -+ /* TODO: remove TL_OPTION_FORCE_INDEX as it looks like it's not used */
32137 -+ ptr->force_index= test(table_options & TL_OPTION_FORCE_INDEX);
32138 -+ ptr->ignore_leaves= test(table_options & TL_OPTION_IGNORE_LEAVES);
32139 -+ ptr->derived= table->sel;
32140 -+ if (!ptr->derived && is_schema_db(ptr->db, ptr->db_length))
32141 -+ {
32142 -+ ST_SCHEMA_TABLE *schema_table= find_schema_table(thd, ptr->table_name);
32143 -+ if (!schema_table ||
32144 -+ (schema_table->hidden &&
32145 -+ ((sql_command_flags[lex->sql_command] & CF_STATUS_COMMAND) == 0 ||
32146 -+ /*
32147 -+ this check is used for show columns|keys from I_S hidden table
32148 -+ */
32149 -+ lex->sql_command == SQLCOM_SHOW_FIELDS ||
32150 -+ lex->sql_command == SQLCOM_SHOW_KEYS)))
32151 -+ {
32152 -+ my_error(ER_UNKNOWN_TABLE, MYF(0),
32153 -+ ptr->table_name, INFORMATION_SCHEMA_NAME.str);
32154 -+ DBUG_RETURN(0);
32155 -+ }
32156 -+ ptr->schema_table_name= ptr->table_name;
32157 -+ ptr->schema_table= schema_table;
32158 -+ }
32159 -+ ptr->select_lex= lex->current_select;
32160 -+ ptr->cacheable_table= 1;
32161 -+ ptr->index_hints= index_hints_arg;
32162 -+ ptr->option= option ? option->str : 0;
32163 -+ /* check that used name is unique */
32164 -+ if (lock_type != TL_IGNORE)
32165 -+ {
32166 -+ TABLE_LIST *first_table= table_list.first;
32167 -+ if (lex->sql_command == SQLCOM_CREATE_VIEW)
32168 -+ first_table= first_table ? first_table->next_local : NULL;
32169 -+ for (TABLE_LIST *tables= first_table ;
32170 -+ tables ;
32171 -+ tables=tables->next_local)
32172 -+ {
32173 -+ if (!my_strcasecmp(table_alias_charset, alias_str, tables->alias) &&
32174 -+ !strcmp(ptr->db, tables->db))
32175 -+ {
32176 -+ my_error(ER_NONUNIQ_TABLE, MYF(0), alias_str); /* purecov: tested */
32177 -+ DBUG_RETURN(0); /* purecov: tested */
32178 -+ }
32179 -+ }
32180 -+ }
32181 -+ /* Store the table reference preceding the current one. */
32182 -+ if (table_list.elements > 0)
32183 -+ {
32184 -+ /*
32185 -+ table_list.next points to the last inserted TABLE_LIST->next_local'
32186 -+ element
32187 -+ We don't use the offsetof() macro here to avoid warnings from gcc
32188 -+ */
32189 -+ previous_table_ref= (TABLE_LIST*) ((char*) table_list.next -
32190 -+ ((char*) &(ptr->next_local) -
32191 -+ (char*) ptr));
32192 -+ /*
32193 -+ Set next_name_resolution_table of the previous table reference to point
32194 -+ to the current table reference. In effect the list
32195 -+ TABLE_LIST::next_name_resolution_table coincides with
32196 -+ TABLE_LIST::next_local. Later this may be changed in
32197 -+ store_top_level_join_columns() for NATURAL/USING joins.
32198 -+ */
32199 -+ previous_table_ref->next_name_resolution_table= ptr;
32200 -+ }
32201 -+
32202 -+ /*
32203 -+ Link the current table reference in a local list (list for current select).
32204 -+ Notice that as a side effect here we set the next_local field of the
32205 -+ previous table reference to 'ptr'. Here we also add one element to the
32206 -+ list 'table_list'.
32207 -+ */
32208 -+ table_list.link_in_list(ptr, &ptr->next_local);
32209 -+ ptr->next_name_resolution_table= NULL;
32210 -+ /* Link table in global list (all used tables) */
32211 -+ lex->add_to_query_tables(ptr);
32212 -+ DBUG_RETURN(ptr);
32213 -+}
32214 -+
32215 -+
32216 -+/**
32217 -+ Initialize a new table list for a nested join.
32218 -+
32219 -+ The function initializes a structure of the TABLE_LIST type
32220 -+ for a nested join. It sets up its nested join list as empty.
32221 -+ The created structure is added to the front of the current
32222 -+ join list in the st_select_lex object. Then the function
32223 -+ changes the current nest level for joins to refer to the newly
32224 -+ created empty list after having saved the info on the old level
32225 -+ in the initialized structure.
32226 -+
32227 -+ @param thd current thread
32228 -+
32229 -+ @retval
32230 -+ 0 if success
32231 -+ @retval
32232 -+ 1 otherwise
32233 -+*/
32234 -+
32235 -+bool st_select_lex::init_nested_join(THD *thd)
32236 -+{
32237 -+ TABLE_LIST *ptr;
32238 -+ NESTED_JOIN *nested_join;
32239 -+ DBUG_ENTER("init_nested_join");
32240 -+
32241 -+ if (!(ptr= (TABLE_LIST*) thd->calloc(ALIGN_SIZE(sizeof(TABLE_LIST))+
32242 -+ sizeof(NESTED_JOIN))))
32243 -+ DBUG_RETURN(1);
32244 -+ nested_join= ptr->nested_join=
32245 -+ ((NESTED_JOIN*) ((uchar*) ptr + ALIGN_SIZE(sizeof(TABLE_LIST))));
32246 -+
32247 -+ join_list->push_front(ptr);
32248 -+ ptr->embedding= embedding;
32249 -+ ptr->join_list= join_list;
32250 -+ ptr->alias= (char*) "(nested_join)";
32251 -+ embedding= ptr;
32252 -+ join_list= &nested_join->join_list;
32253 -+ join_list->empty();
32254 -+ DBUG_RETURN(0);
32255 -+}
32256 -+
32257 -+
32258 -+/**
32259 -+ End a nested join table list.
32260 -+
32261 -+ The function returns to the previous join nest level.
32262 -+ If the current level contains only one member, the function
32263 -+ moves it one level up, eliminating the nest.
32264 -+
32265 -+ @param thd current thread
32266 -+
32267 -+ @return
32268 -+ - Pointer to TABLE_LIST element added to the total table list, if success
32269 -+ - 0, otherwise
32270 -+*/
32271 -+
32272 -+TABLE_LIST *st_select_lex::end_nested_join(THD *thd)
32273 -+{
32274 -+ TABLE_LIST *ptr;
32275 -+ NESTED_JOIN *nested_join;
32276 -+ DBUG_ENTER("end_nested_join");
32277 -+
32278 -+ DBUG_ASSERT(embedding);
32279 -+ ptr= embedding;
32280 -+ join_list= ptr->join_list;
32281 -+ embedding= ptr->embedding;
32282 -+ nested_join= ptr->nested_join;
32283 -+ if (nested_join->join_list.elements == 1)
32284 -+ {
32285 -+ TABLE_LIST *embedded= nested_join->join_list.head();
32286 -+ join_list->pop();
32287 -+ embedded->join_list= join_list;
32288 -+ embedded->embedding= embedding;
32289 -+ join_list->push_front(embedded);
32290 -+ ptr= embedded;
32291 -+ }
32292 -+ else if (nested_join->join_list.elements == 0)
32293 -+ {
32294 -+ join_list->pop();
32295 -+ ptr= 0; // return value
32296 -+ }
32297 -+ DBUG_RETURN(ptr);
32298 -+}
32299 -+
32300 -+
32301 -+/**
32302 -+ Nest last join operation.
32303 -+
32304 -+ The function nest last join operation as if it was enclosed in braces.
32305 -+
32306 -+ @param thd current thread
32307 -+
32308 -+ @retval
32309 -+ 0 Error
32310 -+ @retval
32311 -+ \# Pointer to TABLE_LIST element created for the new nested join
32312 -+*/
32313 -+
32314 -+TABLE_LIST *st_select_lex::nest_last_join(THD *thd)
32315 -+{
32316 -+ TABLE_LIST *ptr;
32317 -+ NESTED_JOIN *nested_join;
32318 -+ List<TABLE_LIST> *embedded_list;
32319 -+ DBUG_ENTER("nest_last_join");
32320 -+
32321 -+ if (!(ptr= (TABLE_LIST*) thd->calloc(ALIGN_SIZE(sizeof(TABLE_LIST))+
32322 -+ sizeof(NESTED_JOIN))))
32323 -+ DBUG_RETURN(0);
32324 -+ nested_join= ptr->nested_join=
32325 -+ ((NESTED_JOIN*) ((uchar*) ptr + ALIGN_SIZE(sizeof(TABLE_LIST))));
32326 -+
32327 -+ ptr->embedding= embedding;
32328 -+ ptr->join_list= join_list;
32329 -+ ptr->alias= (char*) "(nest_last_join)";
32330 -+ embedded_list= &nested_join->join_list;
32331 -+ embedded_list->empty();
32332 -+
32333 -+ for (uint i=0; i < 2; i++)
32334 -+ {
32335 -+ TABLE_LIST *table= join_list->pop();
32336 -+ table->join_list= embedded_list;
32337 -+ table->embedding= ptr;
32338 -+ embedded_list->push_back(table);
32339 -+ if (table->natural_join)
32340 -+ {
32341 -+ ptr->is_natural_join= TRUE;
32342 -+ /*
32343 -+ If this is a JOIN ... USING, move the list of joined fields to the
32344 -+ table reference that describes the join.
32345 -+ */
32346 -+ if (prev_join_using)
32347 -+ ptr->join_using_fields= prev_join_using;
32348 -+ }
32349 -+ }
32350 -+ join_list->push_front(ptr);
32351 -+ nested_join->used_tables= nested_join->not_null_tables= (table_map) 0;
32352 -+ DBUG_RETURN(ptr);
32353 -+}
32354 -+
32355 -+
32356 -+/**
32357 -+ Add a table to the current join list.
32358 -+
32359 -+ The function puts a table in front of the current join list
32360 -+ of st_select_lex object.
32361 -+ Thus, joined tables are put into this list in the reverse order
32362 -+ (the most outer join operation follows first).
32363 -+
32364 -+ @param table the table to add
32365 -+
32366 -+ @return
32367 -+ None
32368 -+*/
32369 -+
32370 -+void st_select_lex::add_joined_table(TABLE_LIST *table)
32371 -+{
32372 -+ DBUG_ENTER("add_joined_table");
32373 -+ join_list->push_front(table);
32374 -+ table->join_list= join_list;
32375 -+ table->embedding= embedding;
32376 -+ DBUG_VOID_RETURN;
32377 -+}
32378 -+
32379 -+
32380 -+/**
32381 -+ Convert a right join into equivalent left join.
32382 -+
32383 -+ The function takes the current join list t[0],t[1] ... and
32384 -+ effectively converts it into the list t[1],t[0] ...
32385 -+ Although the outer_join flag for the new nested table contains
32386 -+ JOIN_TYPE_RIGHT, it will be handled as the inner table of a left join
32387 -+ operation.
32388 -+
32389 -+ EXAMPLES
32390 -+ @verbatim
32391 -+ SELECT * FROM t1 RIGHT JOIN t2 ON on_expr =>
32392 -+ SELECT * FROM t2 LEFT JOIN t1 ON on_expr
32393 -+
32394 -+ SELECT * FROM t1,t2 RIGHT JOIN t3 ON on_expr =>
32395 -+ SELECT * FROM t1,t3 LEFT JOIN t2 ON on_expr
32396 -+
32397 -+ SELECT * FROM t1,t2 RIGHT JOIN (t3,t4) ON on_expr =>
32398 -+ SELECT * FROM t1,(t3,t4) LEFT JOIN t2 ON on_expr
32399 -+
32400 -+ SELECT * FROM t1 LEFT JOIN t2 ON on_expr1 RIGHT JOIN t3 ON on_expr2 =>
32401 -+ SELECT * FROM t3 LEFT JOIN (t1 LEFT JOIN t2 ON on_expr2) ON on_expr1
32402 -+ @endverbatim
32403 -+
32404 -+ @param thd current thread
32405 -+
32406 -+ @return
32407 -+ - Pointer to the table representing the inner table, if success
32408 -+ - 0, otherwise
32409 -+*/
32410 -+
32411 -+TABLE_LIST *st_select_lex::convert_right_join()
32412 -+{
32413 -+ TABLE_LIST *tab2= join_list->pop();
32414 -+ TABLE_LIST *tab1= join_list->pop();
32415 -+ DBUG_ENTER("convert_right_join");
32416 -+
32417 -+ join_list->push_front(tab2);
32418 -+ join_list->push_front(tab1);
32419 -+ tab1->outer_join|= JOIN_TYPE_RIGHT;
32420 -+
32421 -+ DBUG_RETURN(tab1);
32422 -+}
32423 -+
32424 -+/**
32425 -+ Set lock for all tables in current select level.
32426 -+
32427 -+ @param lock_type Lock to set for tables
32428 -+
32429 -+ @note
32430 -+ If lock is a write lock, then tables->updating is set 1
32431 -+ This is to get tables_ok to know that the table is updated by the
32432 -+ query
32433 -+*/
32434 -+
32435 -+void st_select_lex::set_lock_for_tables(thr_lock_type lock_type)
32436 -+{
32437 -+ bool for_update= lock_type >= TL_READ_NO_INSERT;
32438 -+ DBUG_ENTER("set_lock_for_tables");
32439 -+ DBUG_PRINT("enter", ("lock_type: %d for_update: %d", lock_type,
32440 -+ for_update));
32441 -+ for (TABLE_LIST *tables= table_list.first;
32442 -+ tables;
32443 -+ tables= tables->next_local)
32444 -+ {
32445 -+ tables->lock_type= lock_type;
32446 -+ tables->updating= for_update;
32447 -+ }
32448 -+ DBUG_VOID_RETURN;
32449 -+}
32450 -+
32451 -+
32452 -+/**
32453 -+ Create a fake SELECT_LEX for a unit.
32454 -+
32455 -+ The method create a fake SELECT_LEX object for a unit.
32456 -+ This object is created for any union construct containing a union
32457 -+ operation and also for any single select union construct of the form
32458 -+ @verbatim
32459 -+ (SELECT ... ORDER BY order_list [LIMIT n]) ORDER BY ...
32460 -+ @endvarbatim
32461 -+ or of the form
32462 -+ @varbatim
32463 -+ (SELECT ... ORDER BY LIMIT n) ORDER BY ...
32464 -+ @endvarbatim
32465 -+
32466 -+ @param thd_arg thread handle
32467 -+
32468 -+ @note
32469 -+ The object is used to retrieve rows from the temporary table
32470 -+ where the result on the union is obtained.
32471 -+
32472 -+ @retval
32473 -+ 1 on failure to create the object
32474 -+ @retval
32475 -+ 0 on success
32476 -+*/
32477 -+
32478 -+bool st_select_lex_unit::add_fake_select_lex(THD *thd_arg)
32479 -+{
32480 -+ SELECT_LEX *first_sl= first_select();
32481 -+ DBUG_ENTER("add_fake_select_lex");
32482 -+ DBUG_ASSERT(!fake_select_lex);
32483 -+
32484 -+ if (!(fake_select_lex= new (thd_arg->mem_root) SELECT_LEX()))
32485 -+ DBUG_RETURN(1);
32486 -+ fake_select_lex->include_standalone(this,
32487 -+ (SELECT_LEX_NODE**)&fake_select_lex);
32488 -+ fake_select_lex->select_number= INT_MAX;
32489 -+ fake_select_lex->parent_lex= thd_arg->lex; /* Used in init_query. */
32490 -+ fake_select_lex->make_empty_select();
32491 -+ fake_select_lex->linkage= GLOBAL_OPTIONS_TYPE;
32492 -+ fake_select_lex->select_limit= 0;
32493 -+
32494 -+ fake_select_lex->context.outer_context=first_sl->context.outer_context;
32495 -+ /* allow item list resolving in fake select for ORDER BY */
32496 -+ fake_select_lex->context.resolve_in_select_list= TRUE;
32497 -+ fake_select_lex->context.select_lex= fake_select_lex;
32498 -+
32499 -+ if (!is_union())
32500 -+ {
32501 -+ /*
32502 -+ This works only for
32503 -+ (SELECT ... ORDER BY list [LIMIT n]) ORDER BY order_list [LIMIT m],
32504 -+ (SELECT ... LIMIT n) ORDER BY order_list [LIMIT m]
32505 -+ just before the parser starts processing order_list
32506 -+ */
32507 -+ global_parameters= fake_select_lex;
32508 -+ fake_select_lex->no_table_names_allowed= 1;
32509 -+ thd_arg->lex->current_select= fake_select_lex;
32510 -+ }
32511 -+ thd_arg->lex->pop_context();
32512 -+ DBUG_RETURN(0);
32513 -+}
32514 -+
32515 -+
32516 -+/**
32517 -+ Push a new name resolution context for a JOIN ... ON clause to the
32518 -+ context stack of a query block.
32519 -+
32520 -+ Create a new name resolution context for a JOIN ... ON clause,
32521 -+ set the first and last leaves of the list of table references
32522 -+ to be used for name resolution, and push the newly created
32523 -+ context to the stack of contexts of the query.
32524 -+
32525 -+ @param thd pointer to current thread
32526 -+ @param left_op left operand of the JOIN
32527 -+ @param right_op rigth operand of the JOIN
32528 -+
32529 -+ @retval
32530 -+ FALSE if all is OK
32531 -+ @retval
32532 -+ TRUE if a memory allocation error occured
32533 -+*/
32534 -+
32535 -+bool
32536 -+push_new_name_resolution_context(THD *thd,
32537 -+ TABLE_LIST *left_op, TABLE_LIST *right_op)
32538 -+{
32539 -+ Name_resolution_context *on_context;
32540 -+ if (!(on_context= new (thd->mem_root) Name_resolution_context))
32541 -+ return TRUE;
32542 -+ on_context->init();
32543 -+ on_context->first_name_resolution_table=
32544 -+ left_op->first_leaf_for_name_resolution();
32545 -+ on_context->last_name_resolution_table=
32546 -+ right_op->last_leaf_for_name_resolution();
32547 -+ return thd->lex->push_context(on_context);
32548 -+}
32549 -+
32550 -+
32551 -+/**
32552 -+ Add an ON condition to the second operand of a JOIN ... ON.
32553 -+
32554 -+ Add an ON condition to the right operand of a JOIN ... ON clause.
32555 -+
32556 -+ @param b the second operand of a JOIN ... ON
32557 -+ @param expr the condition to be added to the ON clause
32558 -+
32559 -+ @retval
32560 -+ FALSE if there was some error
32561 -+ @retval
32562 -+ TRUE if all is OK
32563 -+*/
32564 -+
32565 -+void add_join_on(TABLE_LIST *b, Item *expr)
32566 -+{
32567 -+ if (expr)
32568 -+ {
32569 -+ if (!b->on_expr)
32570 -+ b->on_expr= expr;
32571 -+ else
32572 -+ {
32573 -+ /*
32574 -+ If called from the parser, this happens if you have both a
32575 -+ right and left join. If called later, it happens if we add more
32576 -+ than one condition to the ON clause.
32577 -+ */
32578 -+ b->on_expr= new Item_cond_and(b->on_expr,expr);
32579 -+ }
32580 -+ b->on_expr->top_level_item();
32581 -+ }
32582 -+}
32583 -+
32584 -+
32585 -+/**
32586 -+ Mark that there is a NATURAL JOIN or JOIN ... USING between two
32587 -+ tables.
32588 -+
32589 -+ This function marks that table b should be joined with a either via
32590 -+ a NATURAL JOIN or via JOIN ... USING. Both join types are special
32591 -+ cases of each other, so we treat them together. The function
32592 -+ setup_conds() creates a list of equal condition between all fields
32593 -+ of the same name for NATURAL JOIN or the fields in 'using_fields'
32594 -+ for JOIN ... USING. The list of equality conditions is stored
32595 -+ either in b->on_expr, or in JOIN::conds, depending on whether there
32596 -+ was an outer join.
32597 -+
32598 -+ EXAMPLE
32599 -+ @verbatim
32600 -+ SELECT * FROM t1 NATURAL LEFT JOIN t2
32601 -+ <=>
32602 -+ SELECT * FROM t1 LEFT JOIN t2 ON (t1.i=t2.i and t1.j=t2.j ... )
32603 -+
32604 -+ SELECT * FROM t1 NATURAL JOIN t2 WHERE <some_cond>
32605 -+ <=>
32606 -+ SELECT * FROM t1, t2 WHERE (t1.i=t2.i and t1.j=t2.j and <some_cond>)
32607 -+
32608 -+ SELECT * FROM t1 JOIN t2 USING(j) WHERE <some_cond>
32609 -+ <=>
32610 -+ SELECT * FROM t1, t2 WHERE (t1.j=t2.j and <some_cond>)
32611 -+ @endverbatim
32612 -+
32613 -+ @param a Left join argument
32614 -+ @param b Right join argument
32615 -+ @param using_fields Field names from USING clause
32616 -+*/
32617 -+
32618 -+void add_join_natural(TABLE_LIST *a, TABLE_LIST *b, List<String> *using_fields,
32619 -+ SELECT_LEX *lex)
32620 -+{
32621 -+ b->natural_join= a;
32622 -+ lex->prev_join_using= using_fields;
32623 -+}
32624 -+
32625 -+
32626 -+/**
32627 -+ Reload/resets privileges and the different caches.
32628 -+
32629 -+ @param thd Thread handler (can be NULL!)
32630 -+ @param options What should be reset/reloaded (tables, privileges, slave...)
32631 -+ @param tables Tables to flush (if any)
32632 -+ @param write_to_binlog < 0 if there was an error while interacting with the binary log inside
32633 -+ reload_acl_and_cache,
32634 -+ 0 if we should not write to the binary log,
32635 -+ > 0 if we can write to the binlog.
32636 -+
32637 -+ @note Depending on 'options', it may be very bad to write the
32638 -+ query to the binlog (e.g. FLUSH SLAVE); this is a
32639 -+ pointer where reload_acl_and_cache() will put 0 if
32640 -+ it thinks we really should not write to the binlog.
32641 -+ Otherwise it will put 1.
32642 -+
32643 -+ @return Error status code
32644 -+ @retval 0 Ok
32645 -+ @retval !=0 Error; thd->killed is set or thd->is_error() is true
32646 -+*/
32647 -+
32648 -+bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
32649 -+ int *write_to_binlog)
32650 -+{
32651 -+ bool result=0;
32652 -+ select_errors=0; /* Write if more errors */
32653 -+ int tmp_write_to_binlog= *write_to_binlog= 1;
32654 -+
32655 -+ DBUG_ASSERT(!thd || !thd->in_sub_stmt);
32656 -+
32657 -+#ifndef NO_EMBEDDED_ACCESS_CHECKS
32658 -+ if (options & REFRESH_GRANT)
32659 -+ {
32660 -+ THD *tmp_thd= 0;
32661 -+ /*
32662 -+ If reload_acl_and_cache() is called from SIGHUP handler we have to
32663 -+ allocate temporary THD for execution of acl_reload()/grant_reload().
32664 -+ */
32665 -+ if (!thd && (thd= (tmp_thd= new THD)))
32666 -+ {
32667 -+ thd->thread_stack= (char*) &tmp_thd;
32668 -+ thd->store_globals();
32669 -+ lex_start(thd);
32670 -+ }
32671 -+
32672 -+ if (thd)
32673 -+ {
32674 -+ bool reload_acl_failed= acl_reload(thd);
32675 -+ bool reload_grants_failed= grant_reload(thd);
32676 -+ bool reload_servers_failed= servers_reload(thd);
32677 -+
32678 -+ if (reload_acl_failed || reload_grants_failed || reload_servers_failed)
32679 -+ {
32680 -+ result= 1;
32681 -+ /*
32682 -+ When an error is returned, my_message may have not been called and
32683 -+ the client will hang waiting for a response.
32684 -+ */
32685 -+ my_error(ER_UNKNOWN_ERROR, MYF(0), "FLUSH PRIVILEGES failed");
32686 -+ }
32687 -+ }
32688 -+
32689 -+ if (tmp_thd)
32690 -+ {
32691 -+ delete tmp_thd;
32692 -+ /* Remember that we don't have a THD */
32693 -+ my_pthread_setspecific_ptr(THR_THD, 0);
32694 -+ thd= 0;
32695 -+ }
32696 -+ reset_mqh((LEX_USER *)NULL, TRUE);
32697 -+ }
32698 -+#endif
32699 -+ if (options & REFRESH_LOG)
32700 -+ {
32701 -+ /*
32702 -+ Flush the normal query log, the update log, the binary log,
32703 -+ the slow query log, the relay log (if it exists) and the log
32704 -+ tables.
32705 -+ */
32706 -+
32707 -+ /*
32708 -+ Writing this command to the binlog may result in infinite loops
32709 -+ when doing mysqlbinlog|mysql, and anyway it does not really make
32710 -+ sense to log it automatically (would cause more trouble to users
32711 -+ than it would help them)
32712 -+ */
32713 -+ tmp_write_to_binlog= 0;
32714 -+ if( mysql_bin_log.is_open() )
32715 -+ {
32716 -+ if (mysql_bin_log.rotate_and_purge(RP_FORCE_ROTATE))
32717 -+ *write_to_binlog= -1;
32718 -+ }
32719 -+#ifdef HAVE_REPLICATION
32720 -+ int rotate_error= 0;
32721 -+ pthread_mutex_lock(&LOCK_active_mi);
32722 -+ rotate_error= rotate_relay_log(active_mi);
32723 -+ pthread_mutex_unlock(&LOCK_active_mi);
32724 -+ if (rotate_error)
32725 -+ *write_to_binlog= -1;
32726 -+#endif
32727 -+
32728 -+ /* flush slow and general logs */
32729 -+ logger.flush_logs(thd);
32730 -+
32731 -+ if (ha_flush_logs(NULL))
32732 -+ result=1;
32733 -+ if (flush_error_log())
32734 -+ result=1;
32735 -+ }
32736 -+#ifdef HAVE_QUERY_CACHE
32737 -+ if (options & REFRESH_QUERY_CACHE_FREE)
32738 -+ {
32739 -+ query_cache.pack(); // FLUSH QUERY CACHE
32740 -+ options &= ~REFRESH_QUERY_CACHE; // Don't flush cache, just free memory
32741 -+ }
32742 -+ if (options & (REFRESH_TABLES | REFRESH_QUERY_CACHE))
32743 -+ {
32744 -+ query_cache.flush(); // RESET QUERY CACHE
32745 -+ }
32746 -+#endif /*HAVE_QUERY_CACHE*/
32747 -+ /*
32748 -+ Note that if REFRESH_READ_LOCK bit is set then REFRESH_TABLES is set too
32749 -+ (see sql_yacc.yy)
32750 -+ */
32751 -+ if (options & (REFRESH_TABLES | REFRESH_READ_LOCK))
32752 -+ {
32753 -+ if ((options & REFRESH_READ_LOCK) && thd)
32754 -+ {
32755 -+ /*
32756 -+ We must not try to aspire a global read lock if we have a write
32757 -+ locked table. This would lead to a deadlock when trying to
32758 -+ reopen (and re-lock) the table after the flush.
32759 -+ */
32760 -+ if (thd->locked_tables)
32761 -+ {
32762 -+ THR_LOCK_DATA **lock_p= thd->locked_tables->locks;
32763 -+ THR_LOCK_DATA **end_p= lock_p + thd->locked_tables->lock_count;
32764 -+
32765 -+ for (; lock_p < end_p; lock_p++)
32766 -+ {
32767 -+ if ((*lock_p)->type >= TL_WRITE_ALLOW_WRITE)
32768 -+ {
32769 -+ my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0));
32770 -+ return 1;
32771 -+ }
32772 -+ }
32773 -+ }
32774 -+ /*
32775 -+ Writing to the binlog could cause deadlocks, as we don't log
32776 -+ UNLOCK TABLES
32777 -+ */
32778 -+ tmp_write_to_binlog= 0;
32779 -+ if (lock_global_read_lock(thd))
32780 -+ return 1; // Killed
32781 -+ if (close_cached_tables(thd, tables, FALSE, (options & REFRESH_FAST) ?
32782 -+ FALSE : TRUE, TRUE))
32783 -+ result= 1;
32784 -+
32785 -+ if (make_global_read_lock_block_commit(thd)) // Killed
32786 -+ {
32787 -+ /* Don't leave things in a half-locked state */
32788 -+ unlock_global_read_lock(thd);
32789 -+ return 1;
32790 -+ }
32791 -+ }
32792 -+ else
32793 -+ {
32794 -+ if (close_cached_tables(thd, tables, FALSE, (options & REFRESH_FAST) ?
32795 -+ FALSE : TRUE, FALSE))
32796 -+ result= 1;
32797 -+ }
32798 -+ my_dbopt_cleanup();
32799 -+ }
32800 -+ if (options & REFRESH_HOSTS)
32801 -+ hostname_cache_refresh();
32802 -+ if (thd && (options & REFRESH_STATUS))
32803 -+ refresh_status(thd);
32804 -+ if (options & REFRESH_THREADS)
32805 -+ flush_thread_cache();
32806 -+#ifdef HAVE_REPLICATION
32807 -+ if (options & REFRESH_MASTER)
32808 -+ {
32809 -+ DBUG_ASSERT(thd);
32810 -+ tmp_write_to_binlog= 0;
32811 -+ if (reset_master(thd))
32812 -+ {
32813 -+ result=1;
32814 -+ }
32815 -+ }
32816 -+#endif
32817 -+#ifdef OPENSSL
32818 -+ if (options & REFRESH_DES_KEY_FILE)
32819 -+ {
32820 -+ if (des_key_file && load_des_key_file(des_key_file))
32821 -+ result= 1;
32822 -+ }
32823 -+#endif
32824 -+#ifdef HAVE_REPLICATION
32825 -+ if (options & REFRESH_SLAVE)
32826 -+ {
32827 -+ tmp_write_to_binlog= 0;
32828 -+ pthread_mutex_lock(&LOCK_active_mi);
32829 -+ if (reset_slave(thd, active_mi))
32830 -+ result=1;
32831 -+ pthread_mutex_unlock(&LOCK_active_mi);
32832 -+ }
32833 -+#endif
32834 -+ if (options & REFRESH_USER_RESOURCES)
32835 -+ reset_mqh((LEX_USER *) NULL, 0); /* purecov: inspected */
32836 -+ if (*write_to_binlog != -1)
32837 -+ *write_to_binlog= tmp_write_to_binlog;
32838 -+ /*
32839 -+ If the query was killed then this function must fail.
32840 -+ */
32841 -+ return result || (thd ? thd->killed : 0);
32842 -+}
32843 -+
32844 -+
32845 -+/**
32846 -+ kill on thread.
32847 -+
32848 -+ @param thd Thread class
32849 -+ @param id Thread id
32850 -+ @param only_kill_query Should it kill the query or the connection
32851 -+
32852 -+ @note
32853 -+ This is written such that we have a short lock on LOCK_thread_count
32854 -+*/
32855 -+
32856 -+uint kill_one_thread(THD *thd, ulong id, bool only_kill_query)
32857 -+{
32858 -+ THD *tmp;
32859 -+ uint error=ER_NO_SUCH_THREAD;
32860 -+ DBUG_ENTER("kill_one_thread");
32861 -+ DBUG_PRINT("enter", ("id=%lu only_kill=%d", id, only_kill_query));
32862 -+ VOID(pthread_mutex_lock(&LOCK_thread_count)); // For unlink from list
32863 -+ I_List_iterator<THD> it(threads);
32864 -+ while ((tmp=it++))
32865 -+ {
32866 -+ if (tmp->command == COM_DAEMON)
32867 -+ continue;
32868 -+ if (tmp->thread_id == id)
32869 -+ {
32870 -+ pthread_mutex_lock(&tmp->LOCK_thd_data); // Lock from delete
32871 -+ break;
32872 -+ }
32873 -+ }
32874 -+ VOID(pthread_mutex_unlock(&LOCK_thread_count));
32875 -+ if (tmp)
32876 -+ {
32877 -+
32878 -+ /*
32879 -+ If we're SUPER, we can KILL anything, including system-threads.
32880 -+ No further checks.
32881 -+
32882 -+ KILLer: thd->security_ctx->user could in theory be NULL while
32883 -+ we're still in "unauthenticated" state. This is a theoretical
32884 -+ case (the code suggests this could happen, so we play it safe).
32885 -+
32886 -+ KILLee: tmp->security_ctx->user will be NULL for system threads.
32887 -+ We need to check so Jane Random User doesn't crash the server
32888 -+ when trying to kill a) system threads or b) unauthenticated users'
32889 -+ threads (Bug#43748).
32890 -+
32891 -+ If user of both killer and killee are non-NULL, proceed with
32892 -+ slayage if both are string-equal.
32893 -+ */
32894 -+
32895 -+ if ((thd->security_ctx->master_access & SUPER_ACL) ||
32896 -+ thd->security_ctx->user_matches(tmp->security_ctx))
32897 -+ {
32898 -+ tmp->awake(only_kill_query ? THD::KILL_QUERY : THD::KILL_CONNECTION);
32899 -+ error=0;
32900 -+ }
32901 -+ else
32902 -+ error=ER_KILL_DENIED_ERROR;
32903 -+ pthread_mutex_unlock(&tmp->LOCK_thd_data);
32904 -+ }
32905 -+ DBUG_PRINT("exit", ("%d", error));
32906 -+ DBUG_RETURN(error);
32907 -+}
32908 -+
32909 -+
32910 -+/*
32911 -+ kills a thread and sends response
32912 -+
32913 -+ SYNOPSIS
32914 -+ sql_kill()
32915 -+ thd Thread class
32916 -+ id Thread id
32917 -+ only_kill_query Should it kill the query or the connection
32918 -+*/
32919 -+
32920 -+void sql_kill(THD *thd, ulong id, bool only_kill_query)
32921 -+{
32922 -+ uint error;
32923 -+ if (!(error= kill_one_thread(thd, id, only_kill_query)))
32924 -+ my_ok(thd);
32925 -+ else
32926 -+ my_error(error, MYF(0), id);
32927 -+}
32928 -+
32929 -+
32930 -+/** If pointer is not a null pointer, append filename to it. */
32931 -+
32932 -+bool append_file_to_dir(THD *thd, const char **filename_ptr,
32933 -+ const char *table_name)
32934 -+{
32935 -+ char buff[FN_REFLEN],*ptr, *end;
32936 -+ if (!*filename_ptr)
32937 -+ return 0; // nothing to do
32938 -+
32939 -+ /* Check that the filename is not too long and it's a hard path */
32940 -+ if (strlen(*filename_ptr)+strlen(table_name) >= FN_REFLEN-1 ||
32941 -+ !test_if_hard_path(*filename_ptr))
32942 -+ {
32943 -+ my_error(ER_WRONG_TABLE_NAME, MYF(0), *filename_ptr);
32944 -+ return 1;
32945 -+ }
32946 -+ /* Fix is using unix filename format on dos */
32947 -+ strmov(buff,*filename_ptr);
32948 -+ end=convert_dirname(buff, *filename_ptr, NullS);
32949 -+ if (!(ptr= (char*) thd->alloc((size_t) (end-buff) + strlen(table_name)+1)))
32950 -+ return 1; // End of memory
32951 -+ *filename_ptr=ptr;
32952 -+ strxmov(ptr,buff,table_name,NullS);
32953 -+ return 0;
32954 -+}
32955 -+
32956 -+
32957 -+/**
32958 -+ Check if the select is a simple select (not an union).
32959 -+
32960 -+ @retval
32961 -+ 0 ok
32962 -+ @retval
32963 -+ 1 error ; In this case the error messege is sent to the client
32964 -+*/
32965 -+
32966 -+bool check_simple_select()
32967 -+{
32968 -+ THD *thd= current_thd;
32969 -+ LEX *lex= thd->lex;
32970 -+ if (lex->current_select != &lex->select_lex)
32971 -+ {
32972 -+ char command[80];
32973 -+ Lex_input_stream *lip= & thd->m_parser_state->m_lip;
32974 -+ strmake(command, lip->yylval->symbol.str,
32975 -+ min(lip->yylval->symbol.length, sizeof(command)-1));
32976 -+ my_error(ER_CANT_USE_OPTION_HERE, MYF(0), command);
32977 -+ return 1;
32978 -+ }
32979 -+ return 0;
32980 -+}
32981 -+
32982 -+
32983 -+Comp_creator *comp_eq_creator(bool invert)
32984 -+{
32985 -+ return invert?(Comp_creator *)&ne_creator:(Comp_creator *)&eq_creator;
32986 -+}
32987 -+
32988 -+
32989 -+Comp_creator *comp_ge_creator(bool invert)
32990 -+{
32991 -+ return invert?(Comp_creator *)&lt_creator:(Comp_creator *)&ge_creator;
32992 -+}
32993 -+
32994 -+
32995 -+Comp_creator *comp_gt_creator(bool invert)
32996 -+{
32997 -+ return invert?(Comp_creator *)&le_creator:(Comp_creator *)&gt_creator;
32998 -+}
32999 -+
33000 -+
33001 -+Comp_creator *comp_le_creator(bool invert)
33002 -+{
33003 -+ return invert?(Comp_creator *)&gt_creator:(Comp_creator *)&le_creator;
33004 -+}
33005 -+
33006 -+
33007 -+Comp_creator *comp_lt_creator(bool invert)
33008 -+{
33009 -+ return invert?(Comp_creator *)&ge_creator:(Comp_creator *)&lt_creator;
33010 -+}
33011 -+
33012 -+
33013 -+Comp_creator *comp_ne_creator(bool invert)
33014 -+{
33015 -+ return invert?(Comp_creator *)&eq_creator:(Comp_creator *)&ne_creator;
33016 -+}
33017 -+
33018 -+
33019 -+/**
33020 -+ Construct ALL/ANY/SOME subquery Item.
33021 -+
33022 -+ @param left_expr pointer to left expression
33023 -+ @param cmp compare function creator
33024 -+ @param all true if we create ALL subquery
33025 -+ @param select_lex pointer on parsed subquery structure
33026 -+
33027 -+ @return
33028 -+ constructed Item (or 0 if out of memory)
33029 -+*/
33030 -+Item * all_any_subquery_creator(Item *left_expr,
33031 -+ chooser_compare_func_creator cmp,
33032 -+ bool all,
33033 -+ SELECT_LEX *select_lex)
33034 -+{
33035 -+ if ((cmp == &comp_eq_creator) && !all) // = ANY <=> IN
33036 -+ return new Item_in_subselect(left_expr, select_lex);
33037 -+
33038 -+ if ((cmp == &comp_ne_creator) && all) // <> ALL <=> NOT IN
33039 -+ return new Item_func_not(new Item_in_subselect(left_expr, select_lex));
33040 -+
33041 -+ Item_allany_subselect *it=
33042 -+ new Item_allany_subselect(left_expr, cmp, select_lex, all);
33043 -+ if (all)
33044 -+ return it->upper_item= new Item_func_not_all(it); /* ALL */
33045 -+
33046 -+ return it->upper_item= new Item_func_nop_all(it); /* ANY/SOME */
33047 -+}
33048 -+
33049 -+
33050 -+/**
33051 -+ Multi update query pre-check.
33052 -+
33053 -+ @param thd Thread handler
33054 -+ @param tables Global/local table list (have to be the same)
33055 -+
33056 -+ @retval
33057 -+ FALSE OK
33058 -+ @retval
33059 -+ TRUE Error
33060 -+*/
33061 -+
33062 -+bool multi_update_precheck(THD *thd, TABLE_LIST *tables)
33063 -+{
33064 -+ const char *msg= 0;
33065 -+ TABLE_LIST *table;
33066 -+ LEX *lex= thd->lex;
33067 -+ SELECT_LEX *select_lex= &lex->select_lex;
33068 -+ DBUG_ENTER("multi_update_precheck");
33069 -+
33070 -+ if (select_lex->item_list.elements != lex->value_list.elements)
33071 -+ {
33072 -+ my_message(ER_WRONG_VALUE_COUNT, ER(ER_WRONG_VALUE_COUNT), MYF(0));
33073 -+ DBUG_RETURN(TRUE);
33074 -+ }
33075 -+ /*
33076 -+ Ensure that we have UPDATE or SELECT privilege for each table
33077 -+ The exact privilege is checked in mysql_multi_update()
33078 -+ */
33079 -+ for (table= tables; table; table= table->next_local)
33080 -+ {
33081 -+ if (table->derived)
33082 -+ table->grant.privilege= SELECT_ACL;
33083 -+ else if ((check_access(thd, UPDATE_ACL, table->db,
33084 -+ &table->grant.privilege, 0, 1,
33085 -+ test(table->schema_table)) ||
33086 -+ check_grant(thd, UPDATE_ACL, table, 0, 1, 1)) &&
33087 -+ (check_access(thd, SELECT_ACL, table->db,
33088 -+ &table->grant.privilege, 0, 0,
33089 -+ test(table->schema_table)) ||
33090 -+ check_grant(thd, SELECT_ACL, table, 0, 1, 0)))
33091 -+ DBUG_RETURN(TRUE);
33092 -+
33093 -+ table->table_in_first_from_clause= 1;
33094 -+ }
33095 -+ /*
33096 -+ Is there tables of subqueries?
33097 -+ */
33098 -+ if (&lex->select_lex != lex->all_selects_list)
33099 -+ {
33100 -+ DBUG_PRINT("info",("Checking sub query list"));
33101 -+ for (table= tables; table; table= table->next_global)
33102 -+ {
33103 -+ if (!table->table_in_first_from_clause)
33104 -+ {
33105 -+ if (check_access(thd, SELECT_ACL, table->db,
33106 -+ &table->grant.privilege, 0, 0,
33107 -+ test(table->schema_table)) ||
33108 -+ check_grant(thd, SELECT_ACL, table, 0, 1, 0))
33109 -+ DBUG_RETURN(TRUE);
33110 -+ }
33111 -+ }
33112 -+ }
33113 -+
33114 -+ if (select_lex->order_list.elements)
33115 -+ msg= "ORDER BY";
33116 -+ else if (select_lex->select_limit)
33117 -+ msg= "LIMIT";
33118 -+ if (msg)
33119 -+ {
33120 -+ my_error(ER_WRONG_USAGE, MYF(0), "UPDATE", msg);
33121 -+ DBUG_RETURN(TRUE);
33122 -+ }
33123 -+ DBUG_RETURN(FALSE);
33124 -+}
33125 -+
33126 -+/**
33127 -+ Multi delete query pre-check.
33128 -+
33129 -+ @param thd Thread handler
33130 -+ @param tables Global/local table list
33131 -+
33132 -+ @retval
33133 -+ FALSE OK
33134 -+ @retval
33135 -+ TRUE error
33136 -+*/
33137 -+
33138 -+bool multi_delete_precheck(THD *thd, TABLE_LIST *tables)
33139 -+{
33140 -+ SELECT_LEX *select_lex= &thd->lex->select_lex;
33141 -+ TABLE_LIST *aux_tables= thd->lex->auxiliary_table_list.first;
33142 -+ TABLE_LIST **save_query_tables_own_last= thd->lex->query_tables_own_last;
33143 -+ DBUG_ENTER("multi_delete_precheck");
33144 -+
33145 -+ /* sql_yacc guarantees that tables and aux_tables are not zero */
33146 -+ DBUG_ASSERT(aux_tables != 0);
33147 -+ if (check_table_access(thd, SELECT_ACL, tables, UINT_MAX, FALSE))
33148 -+ DBUG_RETURN(TRUE);
33149 -+
33150 -+ /*
33151 -+ Since aux_tables list is not part of LEX::query_tables list we
33152 -+ have to juggle with LEX::query_tables_own_last value to be able
33153 -+ call check_table_access() safely.
33154 -+ */
33155 -+ thd->lex->query_tables_own_last= 0;
33156 -+ if (check_table_access(thd, DELETE_ACL, aux_tables, UINT_MAX, FALSE))
33157 -+ {
33158 -+ thd->lex->query_tables_own_last= save_query_tables_own_last;
33159 -+ DBUG_RETURN(TRUE);
33160 -+ }
33161 -+ thd->lex->query_tables_own_last= save_query_tables_own_last;
33162 -+
33163 -+ if ((thd->options & OPTION_SAFE_UPDATES) && !select_lex->where)
33164 -+ {
33165 -+ my_message(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE,
33166 -+ ER(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE), MYF(0));
33167 -+ DBUG_RETURN(TRUE);
33168 -+ }
33169 -+ DBUG_RETURN(FALSE);
33170 -+}
33171 -+
33172 -+
33173 -+/**
33174 -+ Link tables in auxilary table list of multi-delete with corresponding
33175 -+ elements in main table list, and set proper locks for them.
33176 -+
33177 -+ @param lex pointer to LEX representing multi-delete
33178 -+
33179 -+ @retval
33180 -+ FALSE success
33181 -+ @retval
33182 -+ TRUE error
33183 -+*/
33184 -+
33185 -+bool multi_delete_set_locks_and_link_aux_tables(LEX *lex)
33186 -+{
33187 -+ TABLE_LIST *tables= lex->select_lex.table_list.first;
33188 -+ TABLE_LIST *target_tbl;
33189 -+ DBUG_ENTER("multi_delete_set_locks_and_link_aux_tables");
33190 -+
33191 -+ lex->table_count= 0;
33192 -+
33193 -+ for (target_tbl= lex->auxiliary_table_list.first;
33194 -+ target_tbl; target_tbl= target_tbl->next_local)
33195 -+ {
33196 -+ lex->table_count++;
33197 -+ /* All tables in aux_tables must be found in FROM PART */
33198 -+ TABLE_LIST *walk;
33199 -+ for (walk= tables; walk; walk= walk->next_local)
33200 -+ {
33201 -+ if (!my_strcasecmp(table_alias_charset,
33202 -+ target_tbl->alias, walk->alias) &&
33203 -+ !strcmp(walk->db, target_tbl->db))
33204 -+ break;
33205 -+ }
33206 -+ if (!walk)
33207 -+ {
33208 -+ my_error(ER_UNKNOWN_TABLE, MYF(0),
33209 -+ target_tbl->table_name, "MULTI DELETE");
33210 -+ DBUG_RETURN(TRUE);
33211 -+ }
33212 -+ if (!walk->derived)
33213 -+ {
33214 -+ target_tbl->table_name= walk->table_name;
33215 -+ target_tbl->table_name_length= walk->table_name_length;
33216 -+ }
33217 -+ walk->updating= target_tbl->updating;
33218 -+ walk->lock_type= target_tbl->lock_type;
33219 -+ target_tbl->correspondent_table= walk; // Remember corresponding table
33220 -+ }
33221 -+ DBUG_RETURN(FALSE);
33222 -+}
33223 -+
33224 -+
33225 -+/**
33226 -+ simple UPDATE query pre-check.
33227 -+
33228 -+ @param thd Thread handler
33229 -+ @param tables Global table list
33230 -+
33231 -+ @retval
33232 -+ FALSE OK
33233 -+ @retval
33234 -+ TRUE Error
33235 -+*/
33236 -+
33237 -+bool update_precheck(THD *thd, TABLE_LIST *tables)
33238 -+{
33239 -+ DBUG_ENTER("update_precheck");
33240 -+ if (thd->lex->select_lex.item_list.elements != thd->lex->value_list.elements)
33241 -+ {
33242 -+ my_message(ER_WRONG_VALUE_COUNT, ER(ER_WRONG_VALUE_COUNT), MYF(0));
33243 -+ DBUG_RETURN(TRUE);
33244 -+ }
33245 -+ DBUG_RETURN(check_one_table_access(thd, UPDATE_ACL, tables));
33246 -+}
33247 -+
33248 -+
33249 -+/**
33250 -+ simple DELETE query pre-check.
33251 -+
33252 -+ @param thd Thread handler
33253 -+ @param tables Global table list
33254 -+
33255 -+ @retval
33256 -+ FALSE OK
33257 -+ @retval
33258 -+ TRUE error
33259 -+*/
33260 -+
33261 -+bool delete_precheck(THD *thd, TABLE_LIST *tables)
33262 -+{
33263 -+ DBUG_ENTER("delete_precheck");
33264 -+ if (check_one_table_access(thd, DELETE_ACL, tables))
33265 -+ DBUG_RETURN(TRUE);
33266 -+ /* Set privilege for the WHERE clause */
33267 -+ tables->grant.want_privilege=(SELECT_ACL & ~tables->grant.privilege);
33268 -+ DBUG_RETURN(FALSE);
33269 -+}
33270 -+
33271 -+
33272 -+/**
33273 -+ simple INSERT query pre-check.
33274 -+
33275 -+ @param thd Thread handler
33276 -+ @param tables Global table list
33277 -+
33278 -+ @retval
33279 -+ FALSE OK
33280 -+ @retval
33281 -+ TRUE error
33282 -+*/
33283 -+
33284 -+bool insert_precheck(THD *thd, TABLE_LIST *tables)
33285 -+{
33286 -+ LEX *lex= thd->lex;
33287 -+ DBUG_ENTER("insert_precheck");
33288 -+
33289 -+ /*
33290 -+ Check that we have modify privileges for the first table and
33291 -+ select privileges for the rest
33292 -+ */
33293 -+ ulong privilege= (INSERT_ACL |
33294 -+ (lex->duplicates == DUP_REPLACE ? DELETE_ACL : 0) |
33295 -+ (lex->value_list.elements ? UPDATE_ACL : 0));
33296 -+
33297 -+ if (check_one_table_access(thd, privilege, tables))
33298 -+ DBUG_RETURN(TRUE);
33299 -+
33300 -+ if (lex->update_list.elements != lex->value_list.elements)
33301 -+ {
33302 -+ my_message(ER_WRONG_VALUE_COUNT, ER(ER_WRONG_VALUE_COUNT), MYF(0));
33303 -+ DBUG_RETURN(TRUE);
33304 -+ }
33305 -+ DBUG_RETURN(FALSE);
33306 -+}
33307 -+
33308 -+
33309 -+/**
33310 -+ @brief Check privileges for SHOW CREATE TABLE statement.
33311 -+
33312 -+ @param thd Thread context
33313 -+ @param table Target table
33314 -+
33315 -+ @retval TRUE Failure
33316 -+ @retval FALSE Success
33317 -+*/
33318 -+
33319 -+static bool check_show_create_table_access(THD *thd, TABLE_LIST *table)
33320 -+{
33321 -+ return check_access(thd, SELECT_ACL | EXTRA_ACL, table->db,
33322 -+ &table->grant.privilege, 0, 0,
33323 -+ test(table->schema_table)) ||
33324 -+ check_grant(thd, SELECT_ACL, table, 2, UINT_MAX, 0);
33325 -+}
33326 -+
33327 -+
33328 -+/**
33329 -+ CREATE TABLE query pre-check.
33330 -+
33331 -+ @param thd Thread handler
33332 -+ @param tables Global table list
33333 -+ @param create_table Table which will be created
33334 -+
33335 -+ @retval
33336 -+ FALSE OK
33337 -+ @retval
33338 -+ TRUE Error
33339 -+*/
33340 -+
33341 -+bool create_table_precheck(THD *thd, TABLE_LIST *tables,
33342 -+ TABLE_LIST *create_table)
33343 -+{
33344 -+ LEX *lex= thd->lex;
33345 -+ SELECT_LEX *select_lex= &lex->select_lex;
33346 -+ ulong want_priv;
33347 -+ bool error= TRUE; // Error message is given
33348 -+ DBUG_ENTER("create_table_precheck");
33349 -+
33350 -+ /*
33351 -+ Require CREATE [TEMPORARY] privilege on new table; for
33352 -+ CREATE TABLE ... SELECT, also require INSERT.
33353 -+ */
33354 -+
33355 -+ want_priv= ((lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) ?
33356 -+ CREATE_TMP_ACL : CREATE_ACL) |
33357 -+ (select_lex->item_list.elements ? INSERT_ACL : 0);
33358 -+
33359 -+ if (check_access(thd, want_priv, create_table->db,
33360 -+ &create_table->grant.privilege, 0, 0,
33361 -+ test(create_table->schema_table)) ||
33362 -+ check_merge_table_access(thd, create_table->db,
33363 -+ lex->create_info.merge_list.first))
33364 -+ goto err;
33365 -+ if (want_priv != CREATE_TMP_ACL &&
33366 -+ check_grant(thd, want_priv, create_table, 0, 1, 0))
33367 -+ goto err;
33368 -+
33369 -+ if (select_lex->item_list.elements)
33370 -+ {
33371 -+ /* Check permissions for used tables in CREATE TABLE ... SELECT */
33372 -+
33373 -+#ifdef NOT_NECESSARY_TO_CHECK_CREATE_TABLE_EXIST_WHEN_PREPARING_STATEMENT
33374 -+ /* This code throws an ill error for CREATE TABLE t1 SELECT * FROM t1 */
33375 -+ /*
33376 -+ Only do the check for PS, because we on execute we have to check that
33377 -+ against the opened tables to ensure we don't use a table that is part
33378 -+ of the view (which can only be done after the table has been opened).
33379 -+ */
33380 -+ if (thd->stmt_arena->is_stmt_prepare_or_first_sp_execute())
33381 -+ {
33382 -+ /*
33383 -+ For temporary tables we don't have to check if the created table exists
33384 -+ */
33385 -+ if (!(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) &&
33386 -+ find_table_in_global_list(tables, create_table->db,
33387 -+ create_table->table_name))
33388 -+ {
33389 -+ error= FALSE;
33390 -+ goto err;
33391 -+ }
33392 -+ }
33393 -+#endif
33394 -+ if (tables && check_table_access(thd, SELECT_ACL, tables, UINT_MAX, FALSE))
33395 -+ goto err;
33396 -+ }
33397 -+ else if (lex->create_info.options & HA_LEX_CREATE_TABLE_LIKE)
33398 -+ {
33399 -+ if (check_show_create_table_access(thd, tables))
33400 -+ goto err;
33401 -+ }
33402 -+ error= FALSE;
33403 -+
33404 -+err:
33405 -+ DBUG_RETURN(error);
33406 -+}
33407 -+
33408 -+
33409 -+/**
33410 -+ negate given expression.
33411 -+
33412 -+ @param thd thread handler
33413 -+ @param expr expression for negation
33414 -+
33415 -+ @return
33416 -+ negated expression
33417 -+*/
33418 -+
33419 -+Item *negate_expression(THD *thd, Item *expr)
33420 -+{
33421 -+ Item *negated;
33422 -+ if (expr->type() == Item::FUNC_ITEM &&
33423 -+ ((Item_func *) expr)->functype() == Item_func::NOT_FUNC)
33424 -+ {
33425 -+ /* it is NOT(NOT( ... )) */
33426 -+ Item *arg= ((Item_func *) expr)->arguments()[0];
33427 -+ enum_parsing_place place= thd->lex->current_select->parsing_place;
33428 -+ if (arg->is_bool_func() || place == IN_WHERE || place == IN_HAVING)
33429 -+ return arg;
33430 -+ /*
33431 -+ if it is not boolean function then we have to emulate value of
33432 -+ not(not(a)), it will be a != 0
33433 -+ */
33434 -+ return new Item_func_ne(arg, new Item_int((char*) "0", 0, 1));
33435 -+ }
33436 -+
33437 -+ if ((negated= expr->neg_transformer(thd)) != 0)
33438 -+ return negated;
33439 -+ return new Item_func_not(expr);
33440 -+}
33441 -+
33442 -+/**
33443 -+ Set the specified definer to the default value, which is the
33444 -+ current user in the thread.
33445 -+
33446 -+ @param[in] thd thread handler
33447 -+ @param[out] definer definer
33448 -+*/
33449 -+
33450 -+void get_default_definer(THD *thd, LEX_USER *definer)
33451 -+{
33452 -+ const Security_context *sctx= thd->security_ctx;
33453 -+
33454 -+ definer->user.str= (char *) sctx->priv_user;
33455 -+ definer->user.length= strlen(definer->user.str);
33456 -+
33457 -+ definer->host.str= (char *) sctx->priv_host;
33458 -+ definer->host.length= strlen(definer->host.str);
33459 -+
33460 -+ definer->password.str= NULL;
33461 -+ definer->password.length= 0;
33462 -+}
33463 -+
33464 -+
33465 -+/**
33466 -+ Create default definer for the specified THD.
33467 -+
33468 -+ @param[in] thd thread handler
33469 -+
33470 -+ @return
33471 -+ - On success, return a valid pointer to the created and initialized
33472 -+ LEX_USER, which contains definer information.
33473 -+ - On error, return 0.
33474 -+*/
33475 -+
33476 -+LEX_USER *create_default_definer(THD *thd)
33477 -+{
33478 -+ LEX_USER *definer;
33479 -+
33480 -+ if (! (definer= (LEX_USER*) thd->alloc(sizeof(LEX_USER))))
33481 -+ return 0;
33482 -+
33483 -+ thd->get_definer(definer);
33484 -+
33485 -+ return definer;
33486 -+}
33487 -+
33488 -+
33489 -+/**
33490 -+ Create definer with the given user and host names.
33491 -+
33492 -+ @param[in] thd thread handler
33493 -+ @param[in] user_name user name
33494 -+ @param[in] host_name host name
33495 -+
33496 -+ @return
33497 -+ - On success, return a valid pointer to the created and initialized
33498 -+ LEX_USER, which contains definer information.
33499 -+ - On error, return 0.
33500 -+*/
33501 -+
33502 -+LEX_USER *create_definer(THD *thd, LEX_STRING *user_name, LEX_STRING *host_name)
33503 -+{
33504 -+ LEX_USER *definer;
33505 -+
33506 -+ /* Create and initialize. */
33507 -+
33508 -+ if (! (definer= (LEX_USER*) thd->alloc(sizeof(LEX_USER))))
33509 -+ return 0;
33510 -+
33511 -+ definer->user= *user_name;
33512 -+ definer->host= *host_name;
33513 -+ definer->password.str= NULL;
33514 -+ definer->password.length= 0;
33515 -+
33516 -+ return definer;
33517 -+}
33518 -+
33519 -+
33520 -+/**
33521 -+ Retuns information about user or current user.
33522 -+
33523 -+ @param[in] thd thread handler
33524 -+ @param[in] user user
33525 -+
33526 -+ @return
33527 -+ - On success, return a valid pointer to initialized
33528 -+ LEX_USER, which contains user information.
33529 -+ - On error, return 0.
33530 -+*/
33531 -+
33532 -+LEX_USER *get_current_user(THD *thd, LEX_USER *user)
33533 -+{
33534 -+ if (!user->user.str) // current_user
33535 -+ return create_default_definer(thd);
33536 -+
33537 -+ return user;
33538 -+}
33539 -+
33540 -+
33541 -+/**
33542 -+ Check that byte length of a string does not exceed some limit.
33543 -+
33544 -+ @param str string to be checked
33545 -+ @param err_msg error message to be displayed if the string is too long
33546 -+ @param max_length max length
33547 -+
33548 -+ @retval
33549 -+ FALSE the passed string is not longer than max_length
33550 -+ @retval
33551 -+ TRUE the passed string is longer than max_length
33552 -+
33553 -+ NOTE
33554 -+ The function is not used in existing code but can be useful later?
33555 -+*/
33556 -+
33557 -+bool check_string_byte_length(LEX_STRING *str, const char *err_msg,
33558 -+ uint max_byte_length)
33559 -+{
33560 -+ if (str->length <= max_byte_length)
33561 -+ return FALSE;
33562 -+
33563 -+ my_error(ER_WRONG_STRING_LENGTH, MYF(0), str->str, err_msg, max_byte_length);
33564 -+
33565 -+ return TRUE;
33566 -+}
33567 -+
33568 -+
33569 -+/*
33570 -+ Check that char length of a string does not exceed some limit.
33571 -+
33572 -+ SYNOPSIS
33573 -+ check_string_char_length()
33574 -+ str string to be checked
33575 -+ err_msg error message to be displayed if the string is too long
33576 -+ max_char_length max length in symbols
33577 -+ cs string charset
33578 -+
33579 -+ RETURN
33580 -+ FALSE the passed string is not longer than max_char_length
33581 -+ TRUE the passed string is longer than max_char_length
33582 -+*/
33583 -+
33584 -+
33585 -+bool check_string_char_length(LEX_STRING *str, const char *err_msg,
33586 -+ uint max_char_length, CHARSET_INFO *cs,
33587 -+ bool no_error)
33588 -+{
33589 -+ int well_formed_error;
33590 -+ uint res= cs->cset->well_formed_len(cs, str->str, str->str + str->length,
33591 -+ max_char_length, &well_formed_error);
33592 -+
33593 -+ if (!well_formed_error && str->length == res)
33594 -+ return FALSE;
33595 -+
33596 -+ if (!no_error)
33597 -+ my_error(ER_WRONG_STRING_LENGTH, MYF(0), str->str, err_msg, max_char_length);
33598 -+ return TRUE;
33599 -+}
33600 -+
33601 -+
33602 -+/*
33603 -+ Check if path does not contain mysql data home directory
33604 -+ SYNOPSIS
33605 -+ test_if_data_home_dir()
33606 -+ dir directory
33607 -+ conv_home_dir converted data home directory
33608 -+ home_dir_len converted data home directory length
33609 -+
33610 -+ RETURN VALUES
33611 -+ 0 ok
33612 -+ 1 error
33613 -+*/
33614 -+C_MODE_START
33615 -+
33616 -+int test_if_data_home_dir(const char *dir)
33617 -+{
33618 -+ char path[FN_REFLEN];
33619 -+ int dir_len;
33620 -+ DBUG_ENTER("test_if_data_home_dir");
33621 -+
33622 -+ if (!dir)
33623 -+ DBUG_RETURN(0);
33624 -+
33625 -+ (void) fn_format(path, dir, "", "",
33626 -+ (MY_RETURN_REAL_PATH|MY_RESOLVE_SYMLINKS));
33627 -+ dir_len= strlen(path);
33628 -+ if (mysql_unpacked_real_data_home_len<= dir_len)
33629 -+ {
33630 -+ if (dir_len > mysql_unpacked_real_data_home_len &&
33631 -+ path[mysql_unpacked_real_data_home_len] != FN_LIBCHAR)
33632 -+ DBUG_RETURN(0);
33633 -+
33634 -+ if (lower_case_file_system)
33635 -+ {
33636 -+ if (!my_strnncoll(default_charset_info, (const uchar*) path,
33637 -+ mysql_unpacked_real_data_home_len,
33638 -+ (const uchar*) mysql_unpacked_real_data_home,
33639 -+ mysql_unpacked_real_data_home_len))
33640 -+ DBUG_RETURN(1);
33641 -+ }
33642 -+ else if (!memcmp(path, mysql_unpacked_real_data_home,
33643 -+ mysql_unpacked_real_data_home_len))
33644 -+ DBUG_RETURN(1);
33645 -+ }
33646 -+ DBUG_RETURN(0);
33647 -+}
33648 -+
33649 -+C_MODE_END
33650 -+
33651 -+
33652 -+/**
33653 -+ Check that host name string is valid.
33654 -+
33655 -+ @param[in] str string to be checked
33656 -+
33657 -+ @return Operation status
33658 -+ @retval FALSE host name is ok
33659 -+ @retval TRUE host name string is longer than max_length or
33660 -+ has invalid symbols
33661 -+*/
33662 -+
33663 -+bool check_host_name(LEX_STRING *str)
33664 -+{
33665 -+ const char *name= str->str;
33666 -+ const char *end= str->str + str->length;
33667 -+ if (check_string_byte_length(str, ER(ER_HOSTNAME), HOSTNAME_LENGTH))
33668 -+ return TRUE;
33669 -+
33670 -+ while (name != end)
33671 -+ {
33672 -+ if (*name == '@')
33673 -+ {
33674 -+ my_printf_error(ER_UNKNOWN_ERROR,
33675 -+ "Malformed hostname (illegal symbol: '%c')", MYF(0),
33676 -+ *name);
33677 -+ return TRUE;
33678 -+ }
33679 -+ name++;
33680 -+ }
33681 -+ return FALSE;
33682 -+}
33683 -+
33684 -+
33685 -+extern int MYSQLparse(void *thd); // from sql_yacc.cc
33686 -+
33687 -+
33688 -+/**
33689 -+ This is a wrapper of MYSQLparse(). All the code should call parse_sql()
33690 -+ instead of MYSQLparse().
33691 -+
33692 -+ @param thd Thread context.
33693 -+ @param parser_state Parser state.
33694 -+ @param creation_ctx Object creation context.
33695 -+
33696 -+ @return Error status.
33697 -+ @retval FALSE on success.
33698 -+ @retval TRUE on parsing error.
33699 -+*/
33700 -+
33701 -+bool parse_sql(THD *thd,
33702 -+ Parser_state *parser_state,
33703 -+ Object_creation_ctx *creation_ctx)
33704 -+{
33705 -+ DBUG_ASSERT(thd->m_parser_state == NULL);
33706 -+
33707 -+ /* Backup creation context. */
33708 -+
33709 -+ Object_creation_ctx *backup_ctx= NULL;
33710 -+
33711 -+ if (creation_ctx)
33712 -+ backup_ctx= creation_ctx->set_n_backup(thd);
33713 -+
33714 -+ /* Set parser state. */
33715 -+
33716 -+ thd->m_parser_state= parser_state;
33717 -+
33718 -+ /* Parse the query. */
33719 -+
33720 -+ bool mysql_parse_status= MYSQLparse(thd) != 0;
33721 -+
33722 -+ /* Check that if MYSQLparse() failed, thd->is_error() is set. */
33723 -+
33724 -+ DBUG_ASSERT(!mysql_parse_status ||
33725 -+ (mysql_parse_status && thd->is_error()));
33726 -+
33727 -+ /* Reset parser state. */
33728 -+
33729 -+ thd->m_parser_state= NULL;
33730 -+
33731 -+ /* Restore creation context. */
33732 -+
33733 -+ if (creation_ctx)
33734 -+ creation_ctx->restore_env(thd, backup_ctx);
33735 -+
33736 -+ /* That's it. */
33737 -+
33738 -+ return mysql_parse_status || thd->is_fatal_error;
33739 -+}
33740 -+
33741 -+/**
33742 -+ @} (end of group Runtime_Environment)
33743 -+*/
33744 diff -urN mysql-old/sql/sql_partition.cc mysql/sql/sql_partition.cc
33745 --- mysql-old/sql/sql_partition.cc 2011-05-10 17:45:45.636682376 +0000
33746 +++ mysql/sql/sql_partition.cc 2011-05-10 17:56:01.513349044 +0000
33747 @@ -36104,17362 +2435,6 @@ diff -urN mysql-old/sql/sql_select.cc mysql/sql/sql_select.cc
33748 if (!(cache->buff=(uchar*) my_malloc(size,MYF(0))))
33749 DBUG_RETURN(1); /* Don't use cache */ /* purecov: inspected */
33750 cache->end=cache->buff+size;
33751 -diff -urN mysql-old/sql/sql_select.cc.orig mysql/sql/sql_select.cc.orig
33752 ---- mysql-old/sql/sql_select.cc.orig 1969-12-31 23:00:00.000000000 -0100
33753 -+++ mysql/sql/sql_select.cc.orig 2011-04-12 12:11:38.000000000 +0000
33754 -@@ -0,0 +1,17352 @@
33755 -+/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
33756 -+
33757 -+ This program is free software; you can redistribute it and/or modify
33758 -+ it under the terms of the GNU General Public License as published by
33759 -+ the Free Software Foundation; version 2 of the License.
33760 -+
33761 -+ This program is distributed in the hope that it will be useful,
33762 -+ but WITHOUT ANY WARRANTY; without even the implied warranty of
33763 -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33764 -+ GNU General Public License for more details.
33765 -+
33766 -+ You should have received a copy of the GNU General Public License
33767 -+ along with this program; if not, write to the Free Software
33768 -+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
33769 -+
33770 -+/**
33771 -+ @file
33772 -+
33773 -+ @brief
33774 -+ mysql_select and join optimization
33775 -+
33776 -+
33777 -+ @defgroup Query_Optimizer Query Optimizer
33778 -+ @{
33779 -+*/
33780 -+
33781 -+#ifdef USE_PRAGMA_IMPLEMENTATION
33782 -+#pragma implementation // gcc: Class implementation
33783 -+#endif
33784 -+
33785 -+#include "mysql_priv.h"
33786 -+#include "sql_select.h"
33787 -+#include "sql_cursor.h"
33788 -+
33789 -+#include <m_ctype.h>
33790 -+#include <my_bit.h>
33791 -+#include <hash.h>
33792 -+#include <ft_global.h>
33793 -+
33794 -+const char *join_type_str[]={ "UNKNOWN","system","const","eq_ref","ref",
33795 -+ "MAYBE_REF","ALL","range","index","fulltext",
33796 -+ "ref_or_null","unique_subquery","index_subquery",
33797 -+ "index_merge"
33798 -+};
33799 -+
33800 -+struct st_sargable_param;
33801 -+
33802 -+static void optimize_keyuse(JOIN *join, DYNAMIC_ARRAY *keyuse_array);
33803 -+static bool make_join_statistics(JOIN *join, TABLE_LIST *leaves, COND *conds,
33804 -+ DYNAMIC_ARRAY *keyuse);
33805 -+static bool update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,
33806 -+ JOIN_TAB *join_tab,
33807 -+ uint tables, COND *conds,
33808 -+ COND_EQUAL *cond_equal,
33809 -+ table_map table_map, SELECT_LEX *select_lex,
33810 -+ st_sargable_param **sargables);
33811 -+static int sort_keyuse(KEYUSE *a,KEYUSE *b);
33812 -+static void set_position(JOIN *join,uint index,JOIN_TAB *table,KEYUSE *key);
33813 -+static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
33814 -+ table_map used_tables);
33815 -+static bool choose_plan(JOIN *join,table_map join_tables);
33816 -+
33817 -+static void best_access_path(JOIN *join, JOIN_TAB *s, THD *thd,
33818 -+ table_map remaining_tables, uint idx,
33819 -+ double record_count, double read_time);
33820 -+static void optimize_straight_join(JOIN *join, table_map join_tables);
33821 -+static bool greedy_search(JOIN *join, table_map remaining_tables,
33822 -+ uint depth, uint prune_level);
33823 -+static bool best_extension_by_limited_search(JOIN *join,
33824 -+ table_map remaining_tables,
33825 -+ uint idx, double record_count,
33826 -+ double read_time, uint depth,
33827 -+ uint prune_level);
33828 -+static uint determine_search_depth(JOIN* join);
33829 -+static int join_tab_cmp(const void* ptr1, const void* ptr2);
33830 -+static int join_tab_cmp_straight(const void* ptr1, const void* ptr2);
33831 -+/*
33832 -+ TODO: 'find_best' is here only temporarily until 'greedy_search' is
33833 -+ tested and approved.
33834 -+*/
33835 -+static bool find_best(JOIN *join,table_map rest_tables,uint index,
33836 -+ double record_count,double read_time);
33837 -+static uint cache_record_length(JOIN *join,uint index);
33838 -+static double prev_record_reads(JOIN *join, uint idx, table_map found_ref);
33839 -+static bool get_best_combination(JOIN *join);
33840 -+static store_key *get_store_key(THD *thd,
33841 -+ KEYUSE *keyuse, table_map used_tables,
33842 -+ KEY_PART_INFO *key_part, uchar *key_buff,
33843 -+ uint maybe_null);
33844 -+static void make_outerjoin_info(JOIN *join);
33845 -+static bool make_join_select(JOIN *join,SQL_SELECT *select,COND *item);
33846 -+static void make_join_readinfo(JOIN *join, ulonglong options);
33847 -+static bool only_eq_ref_tables(JOIN *join, ORDER *order, table_map tables);
33848 -+static void update_depend_map(JOIN *join);
33849 -+static void update_depend_map(JOIN *join, ORDER *order);
33850 -+static ORDER *remove_const(JOIN *join,ORDER *first_order,COND *cond,
33851 -+ bool change_list, bool *simple_order);
33852 -+static int return_zero_rows(JOIN *join, select_result *res,TABLE_LIST *tables,
33853 -+ List<Item> &fields, bool send_row,
33854 -+ ulonglong select_options, const char *info,
33855 -+ Item *having);
33856 -+static COND *build_equal_items(THD *thd, COND *cond,
33857 -+ COND_EQUAL *inherited,
33858 -+ List<TABLE_LIST> *join_list,
33859 -+ COND_EQUAL **cond_equal_ref);
33860 -+static COND* substitute_for_best_equal_field(COND *cond,
33861 -+ COND_EQUAL *cond_equal,
33862 -+ void *table_join_idx);
33863 -+static COND *simplify_joins(JOIN *join, List<TABLE_LIST> *join_list,
33864 -+ COND *conds, bool top);
33865 -+static bool check_interleaving_with_nj(JOIN_TAB *next);
33866 -+static void restore_prev_nj_state(JOIN_TAB *last);
33867 -+static void reset_nj_counters(List<TABLE_LIST> *join_list);
33868 -+static uint build_bitmap_for_nested_joins(List<TABLE_LIST> *join_list,
33869 -+ uint first_unused);
33870 -+
33871 -+static COND *optimize_cond(JOIN *join, COND *conds,
33872 -+ List<TABLE_LIST> *join_list,
33873 -+ Item::cond_result *cond_value);
33874 -+static bool const_expression_in_where(COND *conds,Item *item, Item **comp_item);
33875 -+static bool open_tmp_table(TABLE *table);
33876 -+static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param,
33877 -+ ulonglong options);
33878 -+static int do_select(JOIN *join,List<Item> *fields,TABLE *tmp_table,
33879 -+ Procedure *proc);
33880 -+
33881 -+static enum_nested_loop_state
33882 -+evaluate_join_record(JOIN *join, JOIN_TAB *join_tab,
33883 -+ int error);
33884 -+static enum_nested_loop_state
33885 -+evaluate_null_complemented_join_record(JOIN *join, JOIN_TAB *join_tab);
33886 -+static enum_nested_loop_state
33887 -+flush_cached_records(JOIN *join, JOIN_TAB *join_tab, bool skip_last);
33888 -+static enum_nested_loop_state
33889 -+end_send(JOIN *join, JOIN_TAB *join_tab, bool end_of_records);
33890 -+static enum_nested_loop_state
33891 -+end_send_group(JOIN *join, JOIN_TAB *join_tab, bool end_of_records);
33892 -+static enum_nested_loop_state
33893 -+end_write(JOIN *join, JOIN_TAB *join_tab, bool end_of_records);
33894 -+static enum_nested_loop_state
33895 -+end_update(JOIN *join, JOIN_TAB *join_tab, bool end_of_records);
33896 -+static enum_nested_loop_state
33897 -+end_unique_update(JOIN *join, JOIN_TAB *join_tab, bool end_of_records);
33898 -+static enum_nested_loop_state
33899 -+end_write_group(JOIN *join, JOIN_TAB *join_tab, bool end_of_records);
33900 -+
33901 -+static int test_if_group_changed(List<Cached_item> &list);
33902 -+static int join_read_const_table(JOIN_TAB *tab, POSITION *pos);
33903 -+static int join_read_system(JOIN_TAB *tab);
33904 -+static int join_read_const(JOIN_TAB *tab);
33905 -+static int join_read_key(JOIN_TAB *tab);
33906 -+static void join_read_key_unlock_row(st_join_table *tab);
33907 -+static int join_read_always_key(JOIN_TAB *tab);
33908 -+static int join_read_last_key(JOIN_TAB *tab);
33909 -+static int join_no_more_records(READ_RECORD *info);
33910 -+static int join_read_next(READ_RECORD *info);
33911 -+static int join_init_quick_read_record(JOIN_TAB *tab);
33912 -+static int test_if_quick_select(JOIN_TAB *tab);
33913 -+static int join_init_read_record(JOIN_TAB *tab);
33914 -+static int join_read_first(JOIN_TAB *tab);
33915 -+static int join_read_next(READ_RECORD *info);
33916 -+static int join_read_next_same(READ_RECORD *info);
33917 -+static int join_read_last(JOIN_TAB *tab);
33918 -+static int join_read_prev_same(READ_RECORD *info);
33919 -+static int join_read_prev(READ_RECORD *info);
33920 -+static int join_ft_read_first(JOIN_TAB *tab);
33921 -+static int join_ft_read_next(READ_RECORD *info);
33922 -+int join_read_always_key_or_null(JOIN_TAB *tab);
33923 -+int join_read_next_same_or_null(READ_RECORD *info);
33924 -+static COND *make_cond_for_table(COND *cond,table_map table,
33925 -+ table_map used_table);
33926 -+static Item* part_of_refkey(TABLE *form,Field *field);
33927 -+uint find_shortest_key(TABLE *table, const key_map *usable_keys);
33928 -+static bool test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,
33929 -+ ha_rows select_limit, bool no_changes,
33930 -+ key_map *map);
33931 -+static bool list_contains_unique_index(TABLE *table,
33932 -+ bool (*find_func) (Field *, void *), void *data);
33933 -+static bool find_field_in_item_list (Field *field, void *data);
33934 -+static bool find_field_in_order_list (Field *field, void *data);
33935 -+static int create_sort_index(THD *thd, JOIN *join, ORDER *order,
33936 -+ ha_rows filesort_limit, ha_rows select_limit,
33937 -+ bool is_order_by);
33938 -+static int remove_duplicates(JOIN *join,TABLE *entry,List<Item> &fields,
33939 -+ Item *having);
33940 -+static int remove_dup_with_compare(THD *thd, TABLE *entry, Field **field,
33941 -+ ulong offset,Item *having);
33942 -+static int remove_dup_with_hash_index(THD *thd,TABLE *table,
33943 -+ uint field_count, Field **first_field,
33944 -+
33945 -+ ulong key_length,Item *having);
33946 -+static int join_init_cache(THD *thd,JOIN_TAB *tables,uint table_count);
33947 -+static ulong used_blob_length(CACHE_FIELD **ptr);
33948 -+static bool store_record_in_cache(JOIN_CACHE *cache);
33949 -+static void reset_cache_read(JOIN_CACHE *cache);
33950 -+static void reset_cache_write(JOIN_CACHE *cache);
33951 -+static void read_cached_record(JOIN_TAB *tab);
33952 -+static bool cmp_buffer_with_ref(JOIN_TAB *tab);
33953 -+static bool setup_new_fields(THD *thd, List<Item> &fields,
33954 -+ List<Item> &all_fields, ORDER *new_order);
33955 -+static ORDER *create_distinct_group(THD *thd, Item **ref_pointer_array,
33956 -+ ORDER *order, List<Item> &fields,
33957 -+ List<Item> &all_fields,
33958 -+ bool *all_order_by_fields_used);
33959 -+static bool test_if_subpart(ORDER *a,ORDER *b);
33960 -+static TABLE *get_sort_by_table(ORDER *a,ORDER *b,TABLE_LIST *tables);
33961 -+static void calc_group_buffer(JOIN *join,ORDER *group);
33962 -+static bool make_group_fields(JOIN *main_join, JOIN *curr_join);
33963 -+static bool alloc_group_fields(JOIN *join,ORDER *group);
33964 -+// Create list for using with tempory table
33965 -+static bool change_to_use_tmp_fields(THD *thd, Item **ref_pointer_array,
33966 -+ List<Item> &new_list1,
33967 -+ List<Item> &new_list2,
33968 -+ uint elements, List<Item> &items);
33969 -+// Create list for using with tempory table
33970 -+static bool change_refs_to_tmp_fields(THD *thd, Item **ref_pointer_array,
33971 -+ List<Item> &new_list1,
33972 -+ List<Item> &new_list2,
33973 -+ uint elements, List<Item> &items);
33974 -+static void init_tmptable_sum_functions(Item_sum **func);
33975 -+static void update_tmptable_sum_func(Item_sum **func,TABLE *tmp_table);
33976 -+static void copy_sum_funcs(Item_sum **func_ptr, Item_sum **end);
33977 -+static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab);
33978 -+static bool setup_sum_funcs(THD *thd, Item_sum **func_ptr);
33979 -+static bool init_sum_functions(Item_sum **func, Item_sum **end);
33980 -+static bool update_sum_func(Item_sum **func);
33981 -+static void select_describe(JOIN *join, bool need_tmp_table,bool need_order,
33982 -+ bool distinct, const char *message=NullS);
33983 -+static Item *remove_additional_cond(Item* conds);
33984 -+static void add_group_and_distinct_keys(JOIN *join, JOIN_TAB *join_tab);
33985 -+static bool test_if_ref(Item_field *left_item,Item *right_item);
33986 -+
33987 -+
33988 -+/**
33989 -+ This handles SELECT with and without UNION.
33990 -+*/
33991 -+
33992 -+bool handle_select(THD *thd, LEX *lex, select_result *result,
33993 -+ ulong setup_tables_done_option)
33994 -+{
33995 -+ bool res;
33996 -+ register SELECT_LEX *select_lex = &lex->select_lex;
33997 -+ DBUG_ENTER("handle_select");
33998 -+
33999 -+ if (select_lex->master_unit()->is_union() ||
34000 -+ select_lex->master_unit()->fake_select_lex)
34001 -+ res= mysql_union(thd, lex, result, &lex->unit, setup_tables_done_option);
34002 -+ else
34003 -+ {
34004 -+ SELECT_LEX_UNIT *unit= &lex->unit;
34005 -+ unit->set_limit(unit->global_parameters);
34006 -+ /*
34007 -+ 'options' of mysql_select will be set in JOIN, as far as JOIN for
34008 -+ every PS/SP execution new, we will not need reset this flag if
34009 -+ setup_tables_done_option changed for next rexecution
34010 -+ */
34011 -+ res= mysql_select(thd, &select_lex->ref_pointer_array,
34012 -+ select_lex->table_list.first,
34013 -+ select_lex->with_wild, select_lex->item_list,
34014 -+ select_lex->where,
34015 -+ select_lex->order_list.elements +
34016 -+ select_lex->group_list.elements,
34017 -+ select_lex->order_list.first,
34018 -+ select_lex->group_list.first,
34019 -+ select_lex->having,
34020 -+ lex->proc_list.first,
34021 -+ select_lex->options | thd->options |
34022 -+ setup_tables_done_option,
34023 -+ result, unit, select_lex);
34024 -+ }
34025 -+ DBUG_PRINT("info",("res: %d report_error: %d", res,
34026 -+ thd->is_error()));
34027 -+ res|= thd->is_error();
34028 -+ if (unlikely(res))
34029 -+ result->abort();
34030 -+
34031 -+ DBUG_RETURN(res);
34032 -+}
34033 -+
34034 -+
34035 -+/**
34036 -+ Fix fields referenced from inner selects.
34037 -+
34038 -+ @param thd Thread handle
34039 -+ @param all_fields List of all fields used in select
34040 -+ @param select Current select
34041 -+ @param ref_pointer_array Array of references to Items used in current select
34042 -+ @param group_list GROUP BY list (is NULL by default)
34043 -+
34044 -+ @details
34045 -+ The function serves 3 purposes
34046 -+
34047 -+ - adds fields referenced from inner query blocks to the current select list
34048 -+
34049 -+ - Decides which class to use to reference the items (Item_ref or
34050 -+ Item_direct_ref)
34051 -+
34052 -+ - fixes references (Item_ref objects) to these fields.
34053 -+
34054 -+ If a field isn't already on the select list and the ref_pointer_array
34055 -+ is provided then it is added to the all_fields list and the pointer to
34056 -+ it is saved in the ref_pointer_array.
34057 -+
34058 -+ The class to access the outer field is determined by the following rules:
34059 -+
34060 -+ -#. If the outer field isn't used under an aggregate function then the
34061 -+ Item_ref class should be used.
34062 -+
34063 -+ -#. If the outer field is used under an aggregate function and this
34064 -+ function is, in turn, aggregated in the query block where the outer
34065 -+ field was resolved or some query nested therein, then the
34066 -+ Item_direct_ref class should be used. Also it should be used if we are
34067 -+ grouping by a subquery containing the outer field.
34068 -+
34069 -+ The resolution is done here and not at the fix_fields() stage as
34070 -+ it can be done only after aggregate functions are fixed and pulled up to
34071 -+ selects where they are to be aggregated.
34072 -+
34073 -+ When the class is chosen it substitutes the original field in the
34074 -+ Item_outer_ref object.
34075 -+
34076 -+ After this we proceed with fixing references (Item_outer_ref objects) to
34077 -+ this field from inner subqueries.
34078 -+
34079 -+ @return Status
34080 -+ @retval true An error occured.
34081 -+ @retval false OK.
34082 -+ */
34083 -+
34084 -+bool
34085 -+fix_inner_refs(THD *thd, List<Item> &all_fields, SELECT_LEX *select,
34086 -+ Item **ref_pointer_array, ORDER *group_list)
34087 -+{
34088 -+ Item_outer_ref *ref;
34089 -+
34090 -+ List_iterator<Item_outer_ref> ref_it(select->inner_refs_list);
34091 -+ while ((ref= ref_it++))
34092 -+ {
34093 -+ bool direct_ref= false;
34094 -+ Item *item= ref->outer_ref;
34095 -+ Item **item_ref= ref->ref;
34096 -+ Item_ref *new_ref;
34097 -+ /*
34098 -+ TODO: this field item already might be present in the select list.
34099 -+ In this case instead of adding new field item we could use an
34100 -+ existing one. The change will lead to less operations for copying fields,
34101 -+ smaller temporary tables and less data passed through filesort.
34102 -+ */
34103 -+ if (ref_pointer_array && !ref->found_in_select_list)
34104 -+ {
34105 -+ int el= all_fields.elements;
34106 -+ ref_pointer_array[el]= item;
34107 -+ /* Add the field item to the select list of the current select. */
34108 -+ all_fields.push_front(item);
34109 -+ /*
34110 -+ If it's needed reset each Item_ref item that refers this field with
34111 -+ a new reference taken from ref_pointer_array.
34112 -+ */
34113 -+ item_ref= ref_pointer_array + el;
34114 -+ }
34115 -+
34116 -+ if (ref->in_sum_func)
34117 -+ {
34118 -+ Item_sum *sum_func;
34119 -+ if (ref->in_sum_func->nest_level > select->nest_level)
34120 -+ direct_ref= TRUE;
34121 -+ else
34122 -+ {
34123 -+ for (sum_func= ref->in_sum_func; sum_func &&
34124 -+ sum_func->aggr_level >= select->nest_level;
34125 -+ sum_func= sum_func->in_sum_func)
34126 -+ {
34127 -+ if (sum_func->aggr_level == select->nest_level)
34128 -+ {
34129 -+ direct_ref= TRUE;
34130 -+ break;
34131 -+ }
34132 -+ }
34133 -+ }
34134 -+ }
34135 -+ else
34136 -+ {
34137 -+ /*
34138 -+ Check if GROUP BY item trees contain the outer ref:
34139 -+ in this case we have to use Item_direct_ref instead of Item_ref.
34140 -+ */
34141 -+ for (ORDER *group= group_list; group; group= group->next)
34142 -+ {
34143 -+ if ((*group->item)->walk(&Item::find_item_processor, TRUE,
34144 -+ (uchar *) ref))
34145 -+ {
34146 -+ direct_ref= TRUE;
34147 -+ break;
34148 -+ }
34149 -+ }
34150 -+ }
34151 -+ new_ref= direct_ref ?
34152 -+ new Item_direct_ref(ref->context, item_ref, ref->table_name,
34153 -+ ref->field_name, ref->alias_name_used) :
34154 -+ new Item_ref(ref->context, item_ref, ref->table_name,
34155 -+ ref->field_name, ref->alias_name_used);
34156 -+ if (!new_ref)
34157 -+ return TRUE;
34158 -+ ref->outer_ref= new_ref;
34159 -+ ref->ref= &ref->outer_ref;
34160 -+
34161 -+ if (!ref->fixed && ref->fix_fields(thd, 0))
34162 -+ return TRUE;
34163 -+ thd->used_tables|= item->used_tables();
34164 -+ }
34165 -+ return false;
34166 -+}
34167 -+
34168 -+/**
34169 -+ Function to setup clauses without sum functions.
34170 -+*/
34171 -+inline int setup_without_group(THD *thd, Item **ref_pointer_array,
34172 -+ TABLE_LIST *tables,
34173 -+ TABLE_LIST *leaves,
34174 -+ List<Item> &fields,
34175 -+ List<Item> &all_fields,
34176 -+ COND **conds,
34177 -+ ORDER *order,
34178 -+ ORDER *group, bool *hidden_group_fields)
34179 -+{
34180 -+ int res;
34181 -+ nesting_map save_allow_sum_func=thd->lex->allow_sum_func ;
34182 -+ /*
34183 -+ Need to save the value, so we can turn off only the new NON_AGG_FIELD
34184 -+ additions coming from the WHERE
34185 -+ */
34186 -+ uint8 saved_flag= thd->lex->current_select->full_group_by_flag;
34187 -+ DBUG_ENTER("setup_without_group");
34188 -+
34189 -+ thd->lex->allow_sum_func&= ~(1 << thd->lex->current_select->nest_level);
34190 -+ res= setup_conds(thd, tables, leaves, conds);
34191 -+
34192 -+ /* it's not wrong to have non-aggregated columns in a WHERE */
34193 -+ if (thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY)
34194 -+ thd->lex->current_select->full_group_by_flag= saved_flag |
34195 -+ (thd->lex->current_select->full_group_by_flag & ~NON_AGG_FIELD_USED);
34196 -+
34197 -+ thd->lex->allow_sum_func|= 1 << thd->lex->current_select->nest_level;
34198 -+ res= res || setup_order(thd, ref_pointer_array, tables, fields, all_fields,
34199 -+ order);
34200 -+ thd->lex->allow_sum_func&= ~(1 << thd->lex->current_select->nest_level);
34201 -+ res= res || setup_group(thd, ref_pointer_array, tables, fields, all_fields,
34202 -+ group, hidden_group_fields);
34203 -+ thd->lex->allow_sum_func= save_allow_sum_func;
34204 -+ DBUG_RETURN(res);
34205 -+}
34206 -+
34207 -+/*****************************************************************************
34208 -+ Check fields, find best join, do the select and output fields.
34209 -+ mysql_select assumes that all tables are already opened
34210 -+*****************************************************************************/
34211 -+
34212 -+/**
34213 -+ Prepare of whole select (including sub queries in future).
34214 -+
34215 -+ @todo
34216 -+ Add check of calculation of GROUP functions and fields:
34217 -+ SELECT COUNT(*)+table.col1 from table1;
34218 -+
34219 -+ @retval
34220 -+ -1 on error
34221 -+ @retval
34222 -+ 0 on success
34223 -+*/
34224 -+int
34225 -+JOIN::prepare(Item ***rref_pointer_array,
34226 -+ TABLE_LIST *tables_init,
34227 -+ uint wild_num, COND *conds_init, uint og_num,
34228 -+ ORDER *order_init, ORDER *group_init,
34229 -+ Item *having_init,
34230 -+ ORDER *proc_param_init, SELECT_LEX *select_lex_arg,
34231 -+ SELECT_LEX_UNIT *unit_arg)
34232 -+{
34233 -+ DBUG_ENTER("JOIN::prepare");
34234 -+
34235 -+ // to prevent double initialization on EXPLAIN
34236 -+ if (optimized)
34237 -+ DBUG_RETURN(0);
34238 -+
34239 -+ conds= conds_init;
34240 -+ order= order_init;
34241 -+ group_list= group_init;
34242 -+ having= having_init;
34243 -+ proc_param= proc_param_init;
34244 -+ tables_list= tables_init;
34245 -+ select_lex= select_lex_arg;
34246 -+ select_lex->join= this;
34247 -+ join_list= &select_lex->top_join_list;
34248 -+ union_part= unit_arg->is_union();
34249 -+
34250 -+ thd->lex->current_select->is_item_list_lookup= 1;
34251 -+ /*
34252 -+ If we have already executed SELECT, then it have not sense to prevent
34253 -+ its table from update (see unique_table())
34254 -+ */
34255 -+ if (thd->derived_tables_processing)
34256 -+ select_lex->exclude_from_table_unique_test= TRUE;
34257 -+
34258 -+ /* Check that all tables, fields, conds and order are ok */
34259 -+
34260 -+ if (!(select_options & OPTION_SETUP_TABLES_DONE) &&
34261 -+ setup_tables_and_check_access(thd, &select_lex->context, join_list,
34262 -+ tables_list, &select_lex->leaf_tables,
34263 -+ FALSE, SELECT_ACL, SELECT_ACL))
34264 -+ DBUG_RETURN(-1);
34265 -+
34266 -+ TABLE_LIST *table_ptr;
34267 -+ for (table_ptr= select_lex->leaf_tables;
34268 -+ table_ptr;
34269 -+ table_ptr= table_ptr->next_leaf)
34270 -+ tables++;
34271 -+
34272 -+ if (setup_wild(thd, tables_list, fields_list, &all_fields, wild_num) ||
34273 -+ select_lex->setup_ref_array(thd, og_num) ||
34274 -+ setup_fields(thd, (*rref_pointer_array), fields_list, MARK_COLUMNS_READ,
34275 -+ &all_fields, 1) ||
34276 -+ setup_without_group(thd, (*rref_pointer_array), tables_list,
34277 -+ select_lex->leaf_tables, fields_list,
34278 -+ all_fields, &conds, order, group_list,
34279 -+ &hidden_group_fields))
34280 -+ DBUG_RETURN(-1); /* purecov: inspected */
34281 -+
34282 -+ ref_pointer_array= *rref_pointer_array;
34283 -+
34284 -+ if (having)
34285 -+ {
34286 -+ nesting_map save_allow_sum_func= thd->lex->allow_sum_func;
34287 -+ thd->where="having clause";
34288 -+ thd->lex->allow_sum_func|= 1 << select_lex_arg->nest_level;
34289 -+ select_lex->having_fix_field= 1;
34290 -+ bool having_fix_rc= (!having->fixed &&
34291 -+ (having->fix_fields(thd, &having) ||
34292 -+ having->check_cols(1)));
34293 -+ select_lex->having_fix_field= 0;
34294 -+ if (having_fix_rc || thd->is_error())
34295 -+ DBUG_RETURN(-1); /* purecov: inspected */
34296 -+ thd->lex->allow_sum_func= save_allow_sum_func;
34297 -+ }
34298 -+
34299 -+ if (!(thd->lex->context_analysis_only & CONTEXT_ANALYSIS_ONLY_VIEW) &&
34300 -+ !(select_options & SELECT_DESCRIBE))
34301 -+ {
34302 -+ Item_subselect *subselect;
34303 -+ /* Is it subselect? */
34304 -+ if ((subselect= select_lex->master_unit()->item))
34305 -+ {
34306 -+ Item_subselect::trans_res res;
34307 -+ if ((res= subselect->select_transformer(this)) !=
34308 -+ Item_subselect::RES_OK)
34309 -+ {
34310 -+ select_lex->fix_prepare_information(thd, &conds, &having);
34311 -+ DBUG_RETURN((res == Item_subselect::RES_ERROR));
34312 -+ }
34313 -+ }
34314 -+ }
34315 -+
34316 -+ select_lex->fix_prepare_information(thd, &conds, &having);
34317 -+
34318 -+ if (order)
34319 -+ {
34320 -+ bool real_order= FALSE;
34321 -+ ORDER *ord;
34322 -+ for (ord= order; ord; ord= ord->next)
34323 -+ {
34324 -+ Item *item= *ord->item;
34325 -+ /*
34326 -+ Disregard sort order if there's only
34327 -+ zero length NOT NULL fields (e.g. {VAR}CHAR(0) NOT NULL") or
34328 -+ zero length NOT NULL string functions there.
34329 -+ Such tuples don't contain any data to sort.
34330 -+ */
34331 -+ if (!real_order &&
34332 -+ /* Not a zero length NOT NULL field */
34333 -+ ((item->type() != Item::FIELD_ITEM ||
34334 -+ ((Item_field *) item)->field->maybe_null() ||
34335 -+ ((Item_field *) item)->field->sort_length()) &&
34336 -+ /* AND not a zero length NOT NULL string function. */
34337 -+ (item->type() != Item::FUNC_ITEM ||
34338 -+ item->maybe_null ||
34339 -+ item->result_type() != STRING_RESULT ||
34340 -+ item->max_length)))
34341 -+ real_order= TRUE;
34342 -+
34343 -+ if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM)
34344 -+ item->split_sum_func(thd, ref_pointer_array, all_fields);
34345 -+ }
34346 -+ if (!real_order)
34347 -+ order= NULL;
34348 -+ }
34349 -+
34350 -+ if (having && having->with_sum_func)
34351 -+ having->split_sum_func2(thd, ref_pointer_array, all_fields,
34352 -+ &having, TRUE);
34353 -+ if (select_lex->inner_sum_func_list)
34354 -+ {
34355 -+ Item_sum *end=select_lex->inner_sum_func_list;
34356 -+ Item_sum *item_sum= end;
34357 -+ do
34358 -+ {
34359 -+ item_sum= item_sum->next;
34360 -+ item_sum->split_sum_func2(thd, ref_pointer_array,
34361 -+ all_fields, item_sum->ref_by, FALSE);
34362 -+ } while (item_sum != end);
34363 -+ }
34364 -+
34365 -+ if (select_lex->inner_refs_list.elements &&
34366 -+ fix_inner_refs(thd, all_fields, select_lex, ref_pointer_array,
34367 -+ group_list))
34368 -+ DBUG_RETURN(-1);
34369 -+
34370 -+ if (group_list)
34371 -+ {
34372 -+ /*
34373 -+ Because HEAP tables can't index BIT fields we need to use an
34374 -+ additional hidden field for grouping because later it will be
34375 -+ converted to a LONG field. Original field will remain of the
34376 -+ BIT type and will be returned to a client.
34377 -+ */
34378 -+ for (ORDER *ord= group_list; ord; ord= ord->next)
34379 -+ {
34380 -+ if ((*ord->item)->type() == Item::FIELD_ITEM &&
34381 -+ (*ord->item)->field_type() == MYSQL_TYPE_BIT)
34382 -+ {
34383 -+ Item_field *field= new Item_field(thd, *(Item_field**)ord->item);
34384 -+ int el= all_fields.elements;
34385 -+ ref_pointer_array[el]= field;
34386 -+ all_fields.push_front(field);
34387 -+ ord->item= ref_pointer_array + el;
34388 -+ }
34389 -+ }
34390 -+ }
34391 -+
34392 -+ if (setup_ftfuncs(select_lex)) /* should be after having->fix_fields */
34393 -+ DBUG_RETURN(-1);
34394 -+
34395 -+
34396 -+ /*
34397 -+ Check if there are references to un-aggregated columns when computing
34398 -+ aggregate functions with implicit grouping (there is no GROUP BY).
34399 -+ */
34400 -+ if (thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY && !group_list &&
34401 -+ select_lex->full_group_by_flag == (NON_AGG_FIELD_USED | SUM_FUNC_USED))
34402 -+ {
34403 -+ my_message(ER_MIX_OF_GROUP_FUNC_AND_FIELDS,
34404 -+ ER(ER_MIX_OF_GROUP_FUNC_AND_FIELDS), MYF(0));
34405 -+ DBUG_RETURN(-1);
34406 -+ }
34407 -+ {
34408 -+ /* Caclulate the number of groups */
34409 -+ send_group_parts= 0;
34410 -+ for (ORDER *group_tmp= group_list ; group_tmp ; group_tmp= group_tmp->next)
34411 -+ send_group_parts++;
34412 -+ }
34413 -+
34414 -+ procedure= setup_procedure(thd, proc_param, result, fields_list, &error);
34415 -+ if (error)
34416 -+ goto err; /* purecov: inspected */
34417 -+ if (procedure)
34418 -+ {
34419 -+ if (setup_new_fields(thd, fields_list, all_fields,
34420 -+ procedure->param_fields))
34421 -+ goto err; /* purecov: inspected */
34422 -+ if (procedure->group)
34423 -+ {
34424 -+ if (!test_if_subpart(procedure->group,group_list))
34425 -+ { /* purecov: inspected */
34426 -+ my_message(ER_DIFF_GROUPS_PROC, ER(ER_DIFF_GROUPS_PROC),
34427 -+ MYF(0)); /* purecov: inspected */
34428 -+ goto err; /* purecov: inspected */
34429 -+ }
34430 -+ }
34431 -+ if (order && (procedure->flags & PROC_NO_SORT))
34432 -+ { /* purecov: inspected */
34433 -+ my_message(ER_ORDER_WITH_PROC, ER(ER_ORDER_WITH_PROC),
34434 -+ MYF(0)); /* purecov: inspected */
34435 -+ goto err; /* purecov: inspected */
34436 -+ }
34437 -+ if (thd->lex->derived_tables)
34438 -+ {
34439 -+ my_error(ER_WRONG_USAGE, MYF(0), "PROCEDURE",
34440 -+ thd->lex->derived_tables & DERIVED_VIEW ?
34441 -+ "view" : "subquery");
34442 -+ goto err;
34443 -+ }
34444 -+ if (thd->lex->sql_command != SQLCOM_SELECT)
34445 -+ {
34446 -+ my_error(ER_WRONG_USAGE, MYF(0), "PROCEDURE", "non-SELECT");
34447 -+ goto err;
34448 -+ }
34449 -+ }
34450 -+
34451 -+ if (!procedure && result && result->prepare(fields_list, unit_arg))
34452 -+ goto err; /* purecov: inspected */
34453 -+
34454 -+ /* Init join struct */
34455 -+ count_field_types(select_lex, &tmp_table_param, all_fields, 0);
34456 -+ ref_pointer_array_size= all_fields.elements*sizeof(Item*);
34457 -+ this->group= group_list != 0;
34458 -+ unit= unit_arg;
34459 -+
34460 -+ if (tmp_table_param.sum_func_count && !group_list)
34461 -+ implicit_grouping= TRUE;
34462 -+
34463 -+#ifdef RESTRICTED_GROUP
34464 -+ if (implicit_grouping)
34465 -+ {
34466 -+ my_message(ER_WRONG_SUM_SELECT,ER(ER_WRONG_SUM_SELECT),MYF(0));
34467 -+ goto err;
34468 -+ }
34469 -+#endif
34470 -+ if (select_lex->olap == ROLLUP_TYPE && rollup_init())
34471 -+ goto err;
34472 -+ if (alloc_func_list())
34473 -+ goto err;
34474 -+
34475 -+ DBUG_RETURN(0); // All OK
34476 -+
34477 -+err:
34478 -+ delete procedure; /* purecov: inspected */
34479 -+ procedure= 0;
34480 -+ DBUG_RETURN(-1); /* purecov: inspected */
34481 -+}
34482 -+
34483 -+
34484 -+/*
34485 -+ Remove the predicates pushed down into the subquery
34486 -+
34487 -+ SYNOPSIS
34488 -+ JOIN::remove_subq_pushed_predicates()
34489 -+ where IN Must be NULL
34490 -+ OUT The remaining WHERE condition, or NULL
34491 -+
34492 -+ DESCRIPTION
34493 -+ Given that this join will be executed using (unique|index)_subquery,
34494 -+ without "checking NULL", remove the predicates that were pushed down
34495 -+ into the subquery.
34496 -+
34497 -+ If the subquery compares scalar values, we can remove the condition that
34498 -+ was wrapped into trig_cond (it will be checked when needed by the subquery
34499 -+ engine)
34500 -+
34501 -+ If the subquery compares row values, we need to keep the wrapped
34502 -+ equalities in the WHERE clause: when the left (outer) tuple has both NULL
34503 -+ and non-NULL values, we'll do a full table scan and will rely on the
34504 -+ equalities corresponding to non-NULL parts of left tuple to filter out
34505 -+ non-matching records.
34506 -+
34507 -+ TODO: We can remove the equalities that will be guaranteed to be true by the
34508 -+ fact that subquery engine will be using index lookup. This must be done only
34509 -+ for cases where there are no conversion errors of significance, e.g. 257
34510 -+ that is searched in a byte. But this requires homogenization of the return
34511 -+ codes of all Field*::store() methods.
34512 -+*/
34513 -+
34514 -+void JOIN::remove_subq_pushed_predicates(Item **where)
34515 -+{
34516 -+ if (conds->type() == Item::FUNC_ITEM &&
34517 -+ ((Item_func *)this->conds)->functype() == Item_func::EQ_FUNC &&
34518 -+ ((Item_func *)conds)->arguments()[0]->type() == Item::REF_ITEM &&
34519 -+ ((Item_func *)conds)->arguments()[1]->type() == Item::FIELD_ITEM &&
34520 -+ test_if_ref ((Item_field *)((Item_func *)conds)->arguments()[1],
34521 -+ ((Item_func *)conds)->arguments()[0]))
34522 -+ {
34523 -+ *where= 0;
34524 -+ return;
34525 -+ }
34526 -+}
34527 -+
34528 -+
34529 -+/*
34530 -+ Index lookup-based subquery: save some flags for EXPLAIN output
34531 -+
34532 -+ SYNOPSIS
34533 -+ save_index_subquery_explain_info()
34534 -+ join_tab Subquery's join tab (there is only one as index lookup is
34535 -+ only used for subqueries that are single-table SELECTs)
34536 -+ where Subquery's WHERE clause
34537 -+
34538 -+ DESCRIPTION
34539 -+ For index lookup-based subquery (i.e. one executed with
34540 -+ subselect_uniquesubquery_engine or subselect_indexsubquery_engine),
34541 -+ check its EXPLAIN output row should contain
34542 -+ "Using index" (TAB_INFO_FULL_SCAN_ON_NULL)
34543 -+ "Using Where" (TAB_INFO_USING_WHERE)
34544 -+ "Full scan on NULL key" (TAB_INFO_FULL_SCAN_ON_NULL)
34545 -+ and set appropriate flags in join_tab->packed_info.
34546 -+*/
34547 -+
34548 -+static void save_index_subquery_explain_info(JOIN_TAB *join_tab, Item* where)
34549 -+{
34550 -+ join_tab->packed_info= TAB_INFO_HAVE_VALUE;
34551 -+ if (join_tab->table->covering_keys.is_set(join_tab->ref.key))
34552 -+ join_tab->packed_info |= TAB_INFO_USING_INDEX;
34553 -+ if (where)
34554 -+ join_tab->packed_info |= TAB_INFO_USING_WHERE;
34555 -+ for (uint i = 0; i < join_tab->ref.key_parts; i++)
34556 -+ {
34557 -+ if (join_tab->ref.cond_guards[i])
34558 -+ {
34559 -+ join_tab->packed_info |= TAB_INFO_FULL_SCAN_ON_NULL;
34560 -+ break;
34561 -+ }
34562 -+ }
34563 -+}
34564 -+
34565 -+
34566 -+/**
34567 -+ global select optimisation.
34568 -+
34569 -+ @note
34570 -+ error code saved in field 'error'
34571 -+
34572 -+ @retval
34573 -+ 0 success
34574 -+ @retval
34575 -+ 1 error
34576 -+*/
34577 -+
34578 -+int
34579 -+JOIN::optimize()
34580 -+{
34581 -+ DBUG_ENTER("JOIN::optimize");
34582 -+ // to prevent double initialization on EXPLAIN
34583 -+ if (optimized)
34584 -+ DBUG_RETURN(0);
34585 -+ optimized= 1;
34586 -+
34587 -+ thd_proc_info(thd, "optimizing");
34588 -+ row_limit= ((select_distinct || order || group_list) ? HA_POS_ERROR :
34589 -+ unit->select_limit_cnt);
34590 -+ /* select_limit is used to decide if we are likely to scan the whole table */
34591 -+ select_limit= unit->select_limit_cnt;
34592 -+ if (having || (select_options & OPTION_FOUND_ROWS))
34593 -+ select_limit= HA_POS_ERROR;
34594 -+ do_send_rows = (unit->select_limit_cnt) ? 1 : 0;
34595 -+ // Ignore errors of execution if option IGNORE present
34596 -+ if (thd->lex->ignore)
34597 -+ thd->lex->current_select->no_error= 1;
34598 -+#ifdef HAVE_REF_TO_FIELDS // Not done yet
34599 -+ /* Add HAVING to WHERE if possible */
34600 -+ if (having && !group_list && !sum_func_count)
34601 -+ {
34602 -+ if (!conds)
34603 -+ {
34604 -+ conds= having;
34605 -+ having= 0;
34606 -+ }
34607 -+ else if ((conds=new Item_cond_and(conds,having)))
34608 -+ {
34609 -+ /*
34610 -+ Item_cond_and can't be fixed after creation, so we do not check
34611 -+ conds->fixed
34612 -+ */
34613 -+ conds->fix_fields(thd, &conds);
34614 -+ conds->change_ref_to_fields(thd, tables_list);
34615 -+ conds->top_level_item();
34616 -+ having= 0;
34617 -+ }
34618 -+ }
34619 -+#endif
34620 -+ SELECT_LEX *sel= thd->lex->current_select;
34621 -+ if (sel->first_cond_optimization)
34622 -+ {
34623 -+ /*
34624 -+ The following code will allocate the new items in a permanent
34625 -+ MEMROOT for prepared statements and stored procedures.
34626 -+ */
34627 -+
34628 -+ Query_arena *arena= thd->stmt_arena, backup;
34629 -+ if (arena->is_conventional())
34630 -+ arena= 0; // For easier test
34631 -+ else
34632 -+ thd->set_n_backup_active_arena(arena, &backup);
34633 -+
34634 -+ sel->first_cond_optimization= 0;
34635 -+
34636 -+ /* Convert all outer joins to inner joins if possible */
34637 -+ conds= simplify_joins(this, join_list, conds, TRUE);
34638 -+ build_bitmap_for_nested_joins(join_list, 0);
34639 -+
34640 -+ sel->prep_where= conds ? conds->copy_andor_structure(thd) : 0;
34641 -+
34642 -+ if (arena)
34643 -+ thd->restore_active_arena(arena, &backup);
34644 -+ }
34645 -+
34646 -+ conds= optimize_cond(this, conds, join_list, &cond_value);
34647 -+ if (thd->is_error())
34648 -+ {
34649 -+ error= 1;
34650 -+ DBUG_PRINT("error",("Error from optimize_cond"));
34651 -+ DBUG_RETURN(1);
34652 -+ }
34653 -+
34654 -+ {
34655 -+ having= optimize_cond(this, having, join_list, &having_value);
34656 -+ if (thd->is_error())
34657 -+ {
34658 -+ error= 1;
34659 -+ DBUG_PRINT("error",("Error from optimize_cond"));
34660 -+ DBUG_RETURN(1);
34661 -+ }
34662 -+ if (select_lex->where)
34663 -+ select_lex->cond_value= cond_value;
34664 -+ if (select_lex->having)
34665 -+ select_lex->having_value= having_value;
34666 -+
34667 -+ if (cond_value == Item::COND_FALSE || having_value == Item::COND_FALSE ||
34668 -+ (!unit->select_limit_cnt && !(select_options & OPTION_FOUND_ROWS)))
34669 -+ { /* Impossible cond */
34670 -+ DBUG_PRINT("info", (having_value == Item::COND_FALSE ?
34671 -+ "Impossible HAVING" : "Impossible WHERE"));
34672 -+ zero_result_cause= having_value == Item::COND_FALSE ?
34673 -+ "Impossible HAVING" : "Impossible WHERE";
34674 -+ tables= 0;
34675 -+ error= 0;
34676 -+ DBUG_RETURN(0);
34677 -+ }
34678 -+ }
34679 -+
34680 -+#ifdef WITH_PARTITION_STORAGE_ENGINE
34681 -+ {
34682 -+ TABLE_LIST *tbl;
34683 -+ for (tbl= select_lex->leaf_tables; tbl; tbl= tbl->next_leaf)
34684 -+ {
34685 -+ /*
34686 -+ If tbl->embedding!=NULL that means that this table is in the inner
34687 -+ part of the nested outer join, and we can't do partition pruning
34688 -+ (TODO: check if this limitation can be lifted)
34689 -+ */
34690 -+ if (!tbl->embedding)
34691 -+ {
34692 -+ Item *prune_cond= tbl->on_expr? tbl->on_expr : conds;
34693 -+ tbl->table->no_partitions_used= prune_partitions(thd, tbl->table,
34694 -+ prune_cond);
34695 -+ }
34696 -+ }
34697 -+ }
34698 -+#endif
34699 -+
34700 -+ /*
34701 -+ Try to optimize count(*), min() and max() to const fields if
34702 -+ there is implicit grouping (aggregate functions but no
34703 -+ group_list). In this case, the result set shall only contain one
34704 -+ row.
34705 -+ */
34706 -+ if (tables_list && implicit_grouping)
34707 -+ {
34708 -+ int res;
34709 -+ /*
34710 -+ opt_sum_query() returns HA_ERR_KEY_NOT_FOUND if no rows match
34711 -+ to the WHERE conditions,
34712 -+ or 1 if all items were resolved (optimized away),
34713 -+ or 0, or an error number HA_ERR_...
34714 -+
34715 -+ If all items were resolved by opt_sum_query, there is no need to
34716 -+ open any tables.
34717 -+ */
34718 -+ if ((res=opt_sum_query(select_lex->leaf_tables, all_fields, conds)))
34719 -+ {
34720 -+ if (res == HA_ERR_KEY_NOT_FOUND)
34721 -+ {
34722 -+ DBUG_PRINT("info",("No matching min/max row"));
34723 -+ zero_result_cause= "No matching min/max row";
34724 -+ tables= 0;
34725 -+ error=0;
34726 -+ DBUG_RETURN(0);
34727 -+ }
34728 -+ if (res > 1)
34729 -+ {
34730 -+ error= res;
34731 -+ DBUG_PRINT("error",("Error from opt_sum_query"));
34732 -+ DBUG_RETURN(1);
34733 -+ }
34734 -+ if (res < 0)
34735 -+ {
34736 -+ DBUG_PRINT("info",("No matching min/max row"));
34737 -+ zero_result_cause= "No matching min/max row";
34738 -+ tables= 0;
34739 -+ error=0;
34740 -+ DBUG_RETURN(0);
34741 -+ }
34742 -+ DBUG_PRINT("info",("Select tables optimized away"));
34743 -+ zero_result_cause= "Select tables optimized away";
34744 -+ tables_list= 0; // All tables resolved
34745 -+ const_tables= tables;
34746 -+ /*
34747 -+ Extract all table-independent conditions and replace the WHERE
34748 -+ clause with them. All other conditions were computed by opt_sum_query
34749 -+ and the MIN/MAX/COUNT function(s) have been replaced by constants,
34750 -+ so there is no need to compute the whole WHERE clause again.
34751 -+ Notice that make_cond_for_table() will always succeed to remove all
34752 -+ computed conditions, because opt_sum_query() is applicable only to
34753 -+ conjunctions.
34754 -+ Preserve conditions for EXPLAIN.
34755 -+ */
34756 -+ if (conds && !(thd->lex->describe & DESCRIBE_EXTENDED))
34757 -+ {
34758 -+ COND *table_independent_conds=
34759 -+ make_cond_for_table(conds, PSEUDO_TABLE_BITS, 0);
34760 -+ DBUG_EXECUTE("where",
34761 -+ print_where(table_independent_conds,
34762 -+ "where after opt_sum_query()",
34763 -+ QT_ORDINARY););
34764 -+ conds= table_independent_conds;
34765 -+ }
34766 -+ }
34767 -+ }
34768 -+ if (!tables_list)
34769 -+ {
34770 -+ DBUG_PRINT("info",("No tables"));
34771 -+ error= 0;
34772 -+ DBUG_RETURN(0);
34773 -+ }
34774 -+ error= -1; // Error is sent to client
34775 -+ sort_by_table= get_sort_by_table(order, group_list, select_lex->leaf_tables);
34776 -+
34777 -+ /* Calculate how to do the join */
34778 -+ thd_proc_info(thd, "statistics");
34779 -+ if (make_join_statistics(this, select_lex->leaf_tables, conds, &keyuse) ||
34780 -+ thd->is_fatal_error)
34781 -+ {
34782 -+ DBUG_PRINT("error",("Error: make_join_statistics() failed"));
34783 -+ DBUG_RETURN(1);
34784 -+ }
34785 -+
34786 -+ if (rollup.state != ROLLUP::STATE_NONE)
34787 -+ {
34788 -+ if (rollup_process_const_fields())
34789 -+ {
34790 -+ DBUG_PRINT("error", ("Error: rollup_process_fields() failed"));
34791 -+ DBUG_RETURN(1);
34792 -+ }
34793 -+ }
34794 -+ else
34795 -+ {
34796 -+ /* Remove distinct if only const tables */
34797 -+ select_distinct= select_distinct && (const_tables != tables);
34798 -+ }
34799 -+
34800 -+ thd_proc_info(thd, "preparing");
34801 -+ if (result->initialize_tables(this))
34802 -+ {
34803 -+ DBUG_PRINT("error",("Error: initialize_tables() failed"));
34804 -+ DBUG_RETURN(1); // error == -1
34805 -+ }
34806 -+ if (const_table_map != found_const_table_map &&
34807 -+ !(select_options & SELECT_DESCRIBE) &&
34808 -+ (!conds ||
34809 -+ !(conds->used_tables() & RAND_TABLE_BIT) ||
34810 -+ select_lex->master_unit() == &thd->lex->unit)) // upper level SELECT
34811 -+ {
34812 -+ zero_result_cause= "no matching row in const table";
34813 -+ DBUG_PRINT("error",("Error: %s", zero_result_cause));
34814 -+ error= 0;
34815 -+ DBUG_RETURN(0);
34816 -+ }
34817 -+ if (!(thd->options & OPTION_BIG_SELECTS) &&
34818 -+ best_read > (double) thd->variables.max_join_size &&
34819 -+ !(select_options & SELECT_DESCRIBE))
34820 -+ { /* purecov: inspected */
34821 -+ my_message(ER_TOO_BIG_SELECT, ER(ER_TOO_BIG_SELECT), MYF(0));
34822 -+ error= -1;
34823 -+ DBUG_RETURN(1);
34824 -+ }
34825 -+ if (const_tables && !thd->locked_tables &&
34826 -+ !(select_options & SELECT_NO_UNLOCK))
34827 -+ mysql_unlock_some_tables(thd, table, const_tables);
34828 -+ if (!conds && outer_join)
34829 -+ {
34830 -+ /* Handle the case where we have an OUTER JOIN without a WHERE */
34831 -+ conds=new Item_int((longlong) 1,1); // Always true
34832 -+ }
34833 -+ select= make_select(*table, const_table_map,
34834 -+ const_table_map, conds, 1, &error);
34835 -+ if (error)
34836 -+ { /* purecov: inspected */
34837 -+ error= -1; /* purecov: inspected */
34838 -+ DBUG_PRINT("error",("Error: make_select() failed"));
34839 -+ DBUG_RETURN(1);
34840 -+ }
34841 -+
34842 -+ reset_nj_counters(join_list);
34843 -+ make_outerjoin_info(this);
34844 -+
34845 -+ /*
34846 -+ Among the equal fields belonging to the same multiple equality
34847 -+ choose the one that is to be retrieved first and substitute
34848 -+ all references to these in where condition for a reference for
34849 -+ the selected field.
34850 -+ */
34851 -+ if (conds)
34852 -+ {
34853 -+ conds= substitute_for_best_equal_field(conds, cond_equal, map2table);
34854 -+ conds->update_used_tables();
34855 -+ DBUG_EXECUTE("where",
34856 -+ print_where(conds,
34857 -+ "after substitute_best_equal",
34858 -+ QT_ORDINARY););
34859 -+ }
34860 -+
34861 -+ /*
34862 -+ Permorm the the optimization on fields evaluation mentioned above
34863 -+ for all on expressions.
34864 -+ */
34865 -+ for (JOIN_TAB *tab= join_tab + const_tables; tab < join_tab + tables ; tab++)
34866 -+ {
34867 -+ if (*tab->on_expr_ref)
34868 -+ {
34869 -+ *tab->on_expr_ref= substitute_for_best_equal_field(*tab->on_expr_ref,
34870 -+ tab->cond_equal,
34871 -+ map2table);
34872 -+ (*tab->on_expr_ref)->update_used_tables();
34873 -+ }
34874 -+ }
34875 -+
34876 -+ if (conds && const_table_map != found_const_table_map &&
34877 -+ (select_options & SELECT_DESCRIBE))
34878 -+ {
34879 -+ conds=new Item_int((longlong) 0,1); // Always false
34880 -+ }
34881 -+
34882 -+ /*
34883 -+ It's necessary to check const part of HAVING cond as
34884 -+ there is a chance that some cond parts may become
34885 -+ const items after make_join_statisctics(for example
34886 -+ when Item is a reference to cost table field from
34887 -+ outer join).
34888 -+ This check is performed only for those conditions
34889 -+ which do not use aggregate functions. In such case
34890 -+ temporary table may not be used and const condition
34891 -+ elements may be lost during further having
34892 -+ condition transformation in JOIN::exec.
34893 -+ */
34894 -+ if (having && const_table_map && !having->with_sum_func)
34895 -+ {
34896 -+ having->update_used_tables();
34897 -+ having= remove_eq_conds(thd, having, &having_value);
34898 -+ if (having_value == Item::COND_FALSE)
34899 -+ {
34900 -+ having= new Item_int((longlong) 0,1);
34901 -+ zero_result_cause= "Impossible HAVING noticed after reading const tables";
34902 -+ DBUG_RETURN(0);
34903 -+ }
34904 -+ }
34905 -+
34906 -+ if (make_join_select(this, select, conds))
34907 -+ {
34908 -+ zero_result_cause=
34909 -+ "Impossible WHERE noticed after reading const tables";
34910 -+ DBUG_RETURN(0); // error == 0
34911 -+ }
34912 -+
34913 -+ error= -1; /* if goto err */
34914 -+
34915 -+ /* Optimize distinct away if possible */
34916 -+ {
34917 -+ ORDER *org_order= order;
34918 -+ order=remove_const(this, order,conds,1, &simple_order);
34919 -+ if (thd->is_error())
34920 -+ {
34921 -+ error= 1;
34922 -+ DBUG_PRINT("error",("Error from remove_const"));
34923 -+ DBUG_RETURN(1);
34924 -+ }
34925 -+
34926 -+ /*
34927 -+ If we are using ORDER BY NULL or ORDER BY const_expression,
34928 -+ return result in any order (even if we are using a GROUP BY)
34929 -+ */
34930 -+ if (!order && org_order)
34931 -+ skip_sort_order= 1;
34932 -+ }
34933 -+ /*
34934 -+ Check if we can optimize away GROUP BY/DISTINCT.
34935 -+ We can do that if there are no aggregate functions, the
34936 -+ fields in DISTINCT clause (if present) and/or columns in GROUP BY
34937 -+ (if present) contain direct references to all key parts of
34938 -+ an unique index (in whatever order) and if the key parts of the
34939 -+ unique index cannot contain NULLs.
34940 -+ Note that the unique keys for DISTINCT and GROUP BY should not
34941 -+ be the same (as long as they are unique).
34942 -+
34943 -+ The FROM clause must contain a single non-constant table.
34944 -+ */
34945 -+ if (tables - const_tables == 1 && (group_list || select_distinct) &&
34946 -+ !tmp_table_param.sum_func_count &&
34947 -+ (!join_tab[const_tables].select ||
34948 -+ !join_tab[const_tables].select->quick ||
34949 -+ join_tab[const_tables].select->quick->get_type() !=
34950 -+ QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX))
34951 -+ {
34952 -+ if (group_list && rollup.state == ROLLUP::STATE_NONE &&
34953 -+ list_contains_unique_index(join_tab[const_tables].table,
34954 -+ find_field_in_order_list,
34955 -+ (void *) group_list))
34956 -+ {
34957 -+ /*
34958 -+ We have found that grouping can be removed since groups correspond to
34959 -+ only one row anyway, but we still have to guarantee correct result
34960 -+ order. The line below effectively rewrites the query from GROUP BY
34961 -+ <fields> to ORDER BY <fields>. There are two exceptions:
34962 -+ - if skip_sort_order is set (see above), then we can simply skip
34963 -+ GROUP BY;
34964 -+ - we can only rewrite ORDER BY if the ORDER BY fields are 'compatible'
34965 -+ with the GROUP BY ones, i.e. either one is a prefix of another.
34966 -+ We only check if the ORDER BY is a prefix of GROUP BY. In this case
34967 -+ test_if_subpart() copies the ASC/DESC attributes from the original
34968 -+ ORDER BY fields.
34969 -+ If GROUP BY is a prefix of ORDER BY, then it is safe to leave
34970 -+ 'order' as is.
34971 -+ */
34972 -+ if (!order || test_if_subpart(group_list, order))
34973 -+ order= skip_sort_order ? 0 : group_list;
34974 -+ /*
34975 -+ If we have an IGNORE INDEX FOR GROUP BY(fields) clause, this must be
34976 -+ rewritten to IGNORE INDEX FOR ORDER BY(fields).
34977 -+ */
34978 -+ join_tab->table->keys_in_use_for_order_by=
34979 -+ join_tab->table->keys_in_use_for_group_by;
34980 -+ group_list= 0;
34981 -+ group= 0;
34982 -+ }
34983 -+ if (select_distinct &&
34984 -+ list_contains_unique_index(join_tab[const_tables].table,
34985 -+ find_field_in_item_list,
34986 -+ (void *) &fields_list))
34987 -+ {
34988 -+ select_distinct= 0;
34989 -+ }
34990 -+ }
34991 -+ if (group_list || tmp_table_param.sum_func_count)
34992 -+ {
34993 -+ if (! hidden_group_fields && rollup.state == ROLLUP::STATE_NONE)
34994 -+ select_distinct=0;
34995 -+ }
34996 -+ else if (select_distinct && tables - const_tables == 1 &&
34997 -+ rollup.state == ROLLUP::STATE_NONE)
34998 -+ {
34999 -+ /*
35000 -+ We are only using one table. In this case we change DISTINCT to a
35001 -+ GROUP BY query if:
35002 -+ - The GROUP BY can be done through indexes (no sort) and the ORDER
35003 -+ BY only uses selected fields.
35004 -+ (In this case we can later optimize away GROUP BY and ORDER BY)
35005 -+ - We are scanning the whole table without LIMIT
35006 -+ This can happen if:
35007 -+ - We are using CALC_FOUND_ROWS
35008 -+ - We are using an ORDER BY that can't be optimized away.
35009 -+
35010 -+ We don't want to use this optimization when we are using LIMIT
35011 -+ because in this case we can just create a temporary table that
35012 -+ holds LIMIT rows and stop when this table is full.
35013 -+ */
35014 -+ JOIN_TAB *tab= &join_tab[const_tables];
35015 -+ bool all_order_fields_used;
35016 -+ if (order)
35017 -+ skip_sort_order= test_if_skip_sort_order(tab, order, select_limit, 1,
35018 -+ &tab->table->keys_in_use_for_order_by);
35019 -+ if ((group_list=create_distinct_group(thd, select_lex->ref_pointer_array,
35020 -+ order, fields_list, all_fields,
35021 -+ &all_order_fields_used)))
35022 -+ {
35023 -+ bool skip_group= (skip_sort_order &&
35024 -+ test_if_skip_sort_order(tab, group_list, select_limit, 1,
35025 -+ &tab->table->keys_in_use_for_group_by) != 0);
35026 -+ count_field_types(select_lex, &tmp_table_param, all_fields, 0);
35027 -+ if ((skip_group && all_order_fields_used) ||
35028 -+ select_limit == HA_POS_ERROR ||
35029 -+ (order && !skip_sort_order))
35030 -+ {
35031 -+ /* Change DISTINCT to GROUP BY */
35032 -+ select_distinct= 0;
35033 -+ no_order= !order;
35034 -+ if (all_order_fields_used)
35035 -+ {
35036 -+ if (order && skip_sort_order)
35037 -+ {
35038 -+ /*
35039 -+ Force MySQL to read the table in sorted order to get result in
35040 -+ ORDER BY order.
35041 -+ */
35042 -+ tmp_table_param.quick_group=0;
35043 -+ }
35044 -+ order=0;
35045 -+ }
35046 -+ group=1; // For end_write_group
35047 -+ }
35048 -+ else
35049 -+ group_list= 0;
35050 -+ }
35051 -+ else if (thd->is_fatal_error) // End of memory
35052 -+ DBUG_RETURN(1);
35053 -+ }
35054 -+ simple_group= 0;
35055 -+ {
35056 -+ ORDER *old_group_list;
35057 -+ group_list= remove_const(this, (old_group_list= group_list), conds,
35058 -+ rollup.state == ROLLUP::STATE_NONE,
35059 -+ &simple_group);
35060 -+ if (thd->is_error())
35061 -+ {
35062 -+ error= 1;
35063 -+ DBUG_PRINT("error",("Error from remove_const"));
35064 -+ DBUG_RETURN(1);
35065 -+ }
35066 -+ if (old_group_list && !group_list)
35067 -+ select_distinct= 0;
35068 -+ }
35069 -+ if (!group_list && group)
35070 -+ {
35071 -+ order=0; // The output has only one row
35072 -+ simple_order=1;
35073 -+ select_distinct= 0; // No need in distinct for 1 row
35074 -+ group_optimized_away= 1;
35075 -+ }
35076 -+
35077 -+ calc_group_buffer(this, group_list);
35078 -+ send_group_parts= tmp_table_param.group_parts; /* Save org parts */
35079 -+ if (procedure && procedure->group)
35080 -+ {
35081 -+ group_list= procedure->group= remove_const(this, procedure->group, conds,
35082 -+ 1, &simple_group);
35083 -+ if (thd->is_error())
35084 -+ {
35085 -+ error= 1;
35086 -+ DBUG_PRINT("error",("Error from remove_const"));
35087 -+ DBUG_RETURN(1);
35088 -+ }
35089 -+ calc_group_buffer(this, group_list);
35090 -+ }
35091 -+
35092 -+ if (test_if_subpart(group_list, order) ||
35093 -+ (!group_list && tmp_table_param.sum_func_count))
35094 -+ order=0;
35095 -+
35096 -+ // Can't use sort on head table if using join buffering
35097 -+ if (full_join)
35098 -+ {
35099 -+ TABLE *stable= (sort_by_table == (TABLE *) 1 ?
35100 -+ join_tab[const_tables].table : sort_by_table);
35101 -+ /*
35102 -+ FORCE INDEX FOR ORDER BY can be used to prevent join buffering when
35103 -+ sorting on the first table.
35104 -+ */
35105 -+ if (!stable || !stable->force_index_order)
35106 -+ {
35107 -+ if (group_list)
35108 -+ simple_group= 0;
35109 -+ if (order)
35110 -+ simple_order= 0;
35111 -+ }
35112 -+ }
35113 -+
35114 -+ /*
35115 -+ Check if we need to create a temporary table.
35116 -+ This has to be done if all tables are not already read (const tables)
35117 -+ and one of the following conditions holds:
35118 -+ - We are using DISTINCT (simple distinct's are already optimized away)
35119 -+ - We are using an ORDER BY or GROUP BY on fields not in the first table
35120 -+ - We are using different ORDER BY and GROUP BY orders
35121 -+ - The user wants us to buffer the result.
35122 -+ When the WITH ROLLUP modifier is present, we cannot skip temporary table
35123 -+ creation for the DISTINCT clause just because there are only const tables.
35124 -+ */
35125 -+ need_tmp= ((const_tables != tables &&
35126 -+ ((select_distinct || !simple_order || !simple_group) ||
35127 -+ (group_list && order) ||
35128 -+ test(select_options & OPTION_BUFFER_RESULT))) ||
35129 -+ (rollup.state != ROLLUP::STATE_NONE && select_distinct));
35130 -+
35131 -+ // No cache for MATCH
35132 -+ make_join_readinfo(this,
35133 -+ (select_options & (SELECT_DESCRIBE |
35134 -+ SELECT_NO_JOIN_CACHE)) |
35135 -+ (select_lex->ftfunc_list->elements ?
35136 -+ SELECT_NO_JOIN_CACHE : 0));
35137 -+
35138 -+ /* Perform FULLTEXT search before all regular searches */
35139 -+ if (!(select_options & SELECT_DESCRIBE))
35140 -+ init_ftfuncs(thd, select_lex, test(order));
35141 -+
35142 -+ /*
35143 -+ is this simple IN subquery?
35144 -+ */
35145 -+ if (!group_list && !order &&
35146 -+ unit->item && unit->item->substype() == Item_subselect::IN_SUBS &&
35147 -+ tables == 1 && conds &&
35148 -+ !unit->is_union())
35149 -+ {
35150 -+ if (!having)
35151 -+ {
35152 -+ Item *where= conds;
35153 -+ if (join_tab[0].type == JT_EQ_REF &&
35154 -+ join_tab[0].ref.items[0]->name == in_left_expr_name)
35155 -+ {
35156 -+ remove_subq_pushed_predicates(&where);
35157 -+ save_index_subquery_explain_info(join_tab, where);
35158 -+ join_tab[0].type= JT_UNIQUE_SUBQUERY;
35159 -+ error= 0;
35160 -+ DBUG_RETURN(unit->item->
35161 -+ change_engine(new
35162 -+ subselect_uniquesubquery_engine(thd,
35163 -+ join_tab,
35164 -+ unit->item,
35165 -+ where)));
35166 -+ }
35167 -+ else if (join_tab[0].type == JT_REF &&
35168 -+ join_tab[0].ref.items[0]->name == in_left_expr_name)
35169 -+ {
35170 -+ remove_subq_pushed_predicates(&where);
35171 -+ save_index_subquery_explain_info(join_tab, where);
35172 -+ join_tab[0].type= JT_INDEX_SUBQUERY;
35173 -+ error= 0;
35174 -+ DBUG_RETURN(unit->item->
35175 -+ change_engine(new
35176 -+ subselect_indexsubquery_engine(thd,
35177 -+ join_tab,
35178 -+ unit->item,
35179 -+ where,
35180 -+ NULL,
35181 -+ 0)));
35182 -+ }
35183 -+ } else if (join_tab[0].type == JT_REF_OR_NULL &&
35184 -+ join_tab[0].ref.items[0]->name == in_left_expr_name &&
35185 -+ having->name == in_having_cond)
35186 -+ {
35187 -+ join_tab[0].type= JT_INDEX_SUBQUERY;
35188 -+ error= 0;
35189 -+ conds= remove_additional_cond(conds);
35190 -+ save_index_subquery_explain_info(join_tab, conds);
35191 -+ DBUG_RETURN(unit->item->
35192 -+ change_engine(new subselect_indexsubquery_engine(thd,
35193 -+ join_tab,
35194 -+ unit->item,
35195 -+ conds,
35196 -+ having,
35197 -+ 1)));
35198 -+ }
35199 -+
35200 -+ }
35201 -+ /*
35202 -+ Need to tell handlers that to play it safe, it should fetch all
35203 -+ columns of the primary key of the tables: this is because MySQL may
35204 -+ build row pointers for the rows, and for all columns of the primary key
35205 -+ the read set has not necessarily been set by the server code.
35206 -+ */
35207 -+ if (need_tmp || select_distinct || group_list || order)
35208 -+ {
35209 -+ for (uint i = const_tables; i < tables; i++)
35210 -+ join_tab[i].table->prepare_for_position();
35211 -+ }
35212 -+
35213 -+ DBUG_EXECUTE("info",TEST_join(this););
35214 -+
35215 -+ if (const_tables != tables)
35216 -+ {
35217 -+ /*
35218 -+ Because filesort always does a full table scan or a quick range scan
35219 -+ we must add the removed reference to the select for the table.
35220 -+ We only need to do this when we have a simple_order or simple_group
35221 -+ as in other cases the join is done before the sort.
35222 -+ */
35223 -+ if ((order || group_list) &&
35224 -+ join_tab[const_tables].type != JT_ALL &&
35225 -+ join_tab[const_tables].type != JT_FT &&
35226 -+ join_tab[const_tables].type != JT_REF_OR_NULL &&
35227 -+ ((order && simple_order) || (group_list && simple_group)))
35228 -+ {
35229 -+ if (add_ref_to_table_cond(thd,&join_tab[const_tables])) {
35230 -+ DBUG_RETURN(1);
35231 -+ }
35232 -+ }
35233 -+
35234 -+ if (!(select_options & SELECT_BIG_RESULT) &&
35235 -+ ((group_list &&
35236 -+ (!simple_group ||
35237 -+ !test_if_skip_sort_order(&join_tab[const_tables], group_list,
35238 -+ unit->select_limit_cnt, 0,
35239 -+ &join_tab[const_tables].table->
35240 -+ keys_in_use_for_group_by))) ||
35241 -+ select_distinct) &&
35242 -+ tmp_table_param.quick_group && !procedure)
35243 -+ {
35244 -+ need_tmp=1; simple_order=simple_group=0; // Force tmp table without sort
35245 -+ }
35246 -+ if (order)
35247 -+ {
35248 -+ /*
35249 -+ Do we need a temporary table due to the ORDER BY not being equal to
35250 -+ the GROUP BY? The call to test_if_skip_sort_order above tests for the
35251 -+ GROUP BY clause only and hence is not valid in this case. So the
35252 -+ estimated number of rows to be read from the first table is not valid.
35253 -+ We clear it here so that it doesn't show up in EXPLAIN.
35254 -+ */
35255 -+ if (need_tmp && (select_options & SELECT_DESCRIBE) != 0)
35256 -+ join_tab[const_tables].limit= 0;
35257 -+ /*
35258 -+ Force using of tmp table if sorting by a SP or UDF function due to
35259 -+ their expensive and probably non-deterministic nature.
35260 -+ */
35261 -+ for (ORDER *tmp_order= order; tmp_order ; tmp_order=tmp_order->next)
35262 -+ {
35263 -+ Item *item= *tmp_order->item;
35264 -+ if (item->walk(&Item::is_expensive_processor, 0, (uchar*)0))
35265 -+ {
35266 -+ /* Force tmp table without sort */
35267 -+ need_tmp=1; simple_order=simple_group=0;
35268 -+ break;
35269 -+ }
35270 -+ }
35271 -+ }
35272 -+ }
35273 -+
35274 -+ tmp_having= having;
35275 -+ if (select_options & SELECT_DESCRIBE)
35276 -+ {
35277 -+ error= 0;
35278 -+ DBUG_RETURN(0);
35279 -+ }
35280 -+ having= 0;
35281 -+
35282 -+ /*
35283 -+ The loose index scan access method guarantees that all grouping or
35284 -+ duplicate row elimination (for distinct) is already performed
35285 -+ during data retrieval, and that all MIN/MAX functions are already
35286 -+ computed for each group. Thus all MIN/MAX functions should be
35287 -+ treated as regular functions, and there is no need to perform
35288 -+ grouping in the main execution loop.
35289 -+ Notice that currently loose index scan is applicable only for
35290 -+ single table queries, thus it is sufficient to test only the first
35291 -+ join_tab element of the plan for its access method.
35292 -+ */
35293 -+ if (join_tab->is_using_loose_index_scan())
35294 -+ tmp_table_param.precomputed_group_by= TRUE;
35295 -+
35296 -+ /* Create a tmp table if distinct or if the sort is too complicated */
35297 -+ if (need_tmp)
35298 -+ {
35299 -+ DBUG_PRINT("info",("Creating tmp table"));
35300 -+ thd_proc_info(thd, "Creating tmp table");
35301 -+
35302 -+ init_items_ref_array();
35303 -+
35304 -+ tmp_table_param.hidden_field_count= (all_fields.elements -
35305 -+ fields_list.elements);
35306 -+ ORDER *tmp_group= ((!simple_group && !procedure &&
35307 -+ !(test_flags & TEST_NO_KEY_GROUP)) ? group_list :
35308 -+ (ORDER*) 0);
35309 -+ /*
35310 -+ Pushing LIMIT to the temporary table creation is not applicable
35311 -+ when there is ORDER BY or GROUP BY or there is no GROUP BY, but
35312 -+ there are aggregate functions, because in all these cases we need
35313 -+ all result rows.
35314 -+ */
35315 -+ ha_rows tmp_rows_limit= ((order == 0 || skip_sort_order) &&
35316 -+ !tmp_group &&
35317 -+ !thd->lex->current_select->with_sum_func) ?
35318 -+ select_limit : HA_POS_ERROR;
35319 -+
35320 -+ if (!(exec_tmp_table1=
35321 -+ create_tmp_table(thd, &tmp_table_param, all_fields,
35322 -+ tmp_group,
35323 -+ group_list ? 0 : select_distinct,
35324 -+ group_list && simple_group,
35325 -+ select_options,
35326 -+ tmp_rows_limit,
35327 -+ (char *) "")))
35328 -+ {
35329 -+ DBUG_RETURN(1);
35330 -+ }
35331 -+
35332 -+ /*
35333 -+ We don't have to store rows in temp table that doesn't match HAVING if:
35334 -+ - we are sorting the table and writing complete group rows to the
35335 -+ temp table.
35336 -+ - We are using DISTINCT without resolving the distinct as a GROUP BY
35337 -+ on all columns.
35338 -+
35339 -+ If having is not handled here, it will be checked before the row
35340 -+ is sent to the client.
35341 -+ */
35342 -+ if (tmp_having &&
35343 -+ (sort_and_group || (exec_tmp_table1->distinct && !group_list)))
35344 -+ having= tmp_having;
35345 -+
35346 -+ /* if group or order on first table, sort first */
35347 -+ if (group_list && simple_group)
35348 -+ {
35349 -+ DBUG_PRINT("info",("Sorting for group"));
35350 -+ thd_proc_info(thd, "Sorting for group");
35351 -+ if (create_sort_index(thd, this, group_list,
35352 -+ HA_POS_ERROR, HA_POS_ERROR, FALSE) ||
35353 -+ alloc_group_fields(this, group_list) ||
35354 -+ make_sum_func_list(all_fields, fields_list, 1) ||
35355 -+ setup_sum_funcs(thd, sum_funcs))
35356 -+ {
35357 -+ DBUG_RETURN(1);
35358 -+ }
35359 -+ group_list=0;
35360 -+ }
35361 -+ else
35362 -+ {
35363 -+ if (make_sum_func_list(all_fields, fields_list, 0) ||
35364 -+ setup_sum_funcs(thd, sum_funcs))
35365 -+ {
35366 -+ DBUG_RETURN(1);
35367 -+ }
35368 -+
35369 -+ if (!group_list && ! exec_tmp_table1->distinct && order && simple_order)
35370 -+ {
35371 -+ thd_proc_info(thd, "Sorting for order");
35372 -+ if (create_sort_index(thd, this, order,
35373 -+ HA_POS_ERROR, HA_POS_ERROR, TRUE))
35374 -+ {
35375 -+ DBUG_RETURN(1);
35376 -+ }
35377 -+ order=0;
35378 -+ }
35379 -+ }
35380 -+
35381 -+ /*
35382 -+ Optimize distinct when used on some of the tables
35383 -+ SELECT DISTINCT t1.a FROM t1,t2 WHERE t1.b=t2.b
35384 -+ In this case we can stop scanning t2 when we have found one t1.a
35385 -+ */
35386 -+
35387 -+ if (exec_tmp_table1->distinct)
35388 -+ {
35389 -+ table_map used_tables= thd->used_tables;
35390 -+ JOIN_TAB *last_join_tab= join_tab+tables-1;
35391 -+ do
35392 -+ {
35393 -+ if (used_tables & last_join_tab->table->map)
35394 -+ break;
35395 -+ last_join_tab->not_used_in_distinct=1;
35396 -+ } while (last_join_tab-- != join_tab);
35397 -+ /* Optimize "select distinct b from t1 order by key_part_1 limit #" */
35398 -+ if (order && skip_sort_order)
35399 -+ {
35400 -+ /* Should always succeed */
35401 -+ if (test_if_skip_sort_order(&join_tab[const_tables],
35402 -+ order, unit->select_limit_cnt, 0,
35403 -+ &join_tab[const_tables].table->
35404 -+ keys_in_use_for_order_by))
35405 -+ order=0;
35406 -+ }
35407 -+ }
35408 -+
35409 -+ /* If this join belongs to an uncacheable query save the original join */
35410 -+ if (select_lex->uncacheable && init_save_join_tab())
35411 -+ DBUG_RETURN(-1); /* purecov: inspected */
35412 -+ }
35413 -+
35414 -+ error= 0;
35415 -+ DBUG_RETURN(0);
35416 -+}
35417 -+
35418 -+
35419 -+/**
35420 -+ Restore values in temporary join.
35421 -+*/
35422 -+void JOIN::restore_tmp()
35423 -+{
35424 -+ memcpy(tmp_join, this, (size_t) sizeof(JOIN));
35425 -+}
35426 -+
35427 -+
35428 -+int
35429 -+JOIN::reinit()
35430 -+{
35431 -+ DBUG_ENTER("JOIN::reinit");
35432 -+
35433 -+ unit->offset_limit_cnt= (ha_rows)(select_lex->offset_limit ?
35434 -+ select_lex->offset_limit->val_uint() :
35435 -+ ULL(0));
35436 -+
35437 -+ first_record= 0;
35438 -+
35439 -+ if (exec_tmp_table1)
35440 -+ {
35441 -+ exec_tmp_table1->file->extra(HA_EXTRA_RESET_STATE);
35442 -+ exec_tmp_table1->file->ha_delete_all_rows();
35443 -+ free_io_cache(exec_tmp_table1);
35444 -+ filesort_free_buffers(exec_tmp_table1,0);
35445 -+ }
35446 -+ if (exec_tmp_table2)
35447 -+ {
35448 -+ exec_tmp_table2->file->extra(HA_EXTRA_RESET_STATE);
35449 -+ exec_tmp_table2->file->ha_delete_all_rows();
35450 -+ free_io_cache(exec_tmp_table2);
35451 -+ filesort_free_buffers(exec_tmp_table2,0);
35452 -+ }
35453 -+ if (items0)
35454 -+ set_items_ref_array(items0);
35455 -+
35456 -+ if (join_tab_save)
35457 -+ memcpy(join_tab, join_tab_save, sizeof(JOIN_TAB) * tables);
35458 -+
35459 -+ /* need to reset ref access state (see join_read_key) */
35460 -+ if (join_tab)
35461 -+ for (uint i= 0; i < tables; i++)
35462 -+ join_tab[i].ref.key_err= TRUE;
35463 -+
35464 -+ if (tmp_join)
35465 -+ restore_tmp();
35466 -+
35467 -+ /* Reset of sum functions */
35468 -+ if (sum_funcs)
35469 -+ {
35470 -+ Item_sum *func, **func_ptr= sum_funcs;
35471 -+ while ((func= *(func_ptr++)))
35472 -+ func->clear();
35473 -+ }
35474 -+
35475 -+ if (!(select_options & SELECT_DESCRIBE))
35476 -+ init_ftfuncs(thd, select_lex, test(order));
35477 -+
35478 -+ DBUG_RETURN(0);
35479 -+}
35480 -+
35481 -+/**
35482 -+ @brief Save the original join layout
35483 -+
35484 -+ @details Saves the original join layout so it can be reused in
35485 -+ re-execution and for EXPLAIN.
35486 -+
35487 -+ @return Operation status
35488 -+ @retval 0 success.
35489 -+ @retval 1 error occurred.
35490 -+*/
35491 -+
35492 -+bool
35493 -+JOIN::init_save_join_tab()
35494 -+{
35495 -+ if (!(tmp_join= (JOIN*)thd->alloc(sizeof(JOIN))))
35496 -+ return 1; /* purecov: inspected */
35497 -+ error= 0; // Ensure that tmp_join.error= 0
35498 -+ restore_tmp();
35499 -+ return 0;
35500 -+}
35501 -+
35502 -+
35503 -+bool
35504 -+JOIN::save_join_tab()
35505 -+{
35506 -+ if (!join_tab_save && select_lex->master_unit()->uncacheable)
35507 -+ {
35508 -+ if (!(join_tab_save= (JOIN_TAB*)thd->memdup((uchar*) join_tab,
35509 -+ sizeof(JOIN_TAB) * tables)))
35510 -+ return 1;
35511 -+ }
35512 -+ return 0;
35513 -+}
35514 -+
35515 -+
35516 -+/**
35517 -+ Exec select.
35518 -+
35519 -+ @todo
35520 -+ Note, that create_sort_index calls test_if_skip_sort_order and may
35521 -+ finally replace sorting with index scan if there is a LIMIT clause in
35522 -+ the query. It's never shown in EXPLAIN!
35523 -+
35524 -+ @todo
35525 -+ When can we have here thd->net.report_error not zero?
35526 -+*/
35527 -+void
35528 -+JOIN::exec()
35529 -+{
35530 -+ List<Item> *columns_list= &fields_list;
35531 -+ int tmp_error;
35532 -+ DBUG_ENTER("JOIN::exec");
35533 -+
35534 -+ thd_proc_info(thd, "executing");
35535 -+ error= 0;
35536 -+ if (procedure)
35537 -+ {
35538 -+ procedure_fields_list= fields_list;
35539 -+ if (procedure->change_columns(procedure_fields_list) ||
35540 -+ result->prepare(procedure_fields_list, unit))
35541 -+ {
35542 -+ thd->limit_found_rows= thd->examined_row_count= 0;
35543 -+ DBUG_VOID_RETURN;
35544 -+ }
35545 -+ columns_list= &procedure_fields_list;
35546 -+ }
35547 -+ (void) result->prepare2(); // Currently, this cannot fail.
35548 -+
35549 -+ if (!tables_list && (tables || !select_lex->with_sum_func))
35550 -+ { // Only test of functions
35551 -+ if (select_options & SELECT_DESCRIBE)
35552 -+ select_describe(this, FALSE, FALSE, FALSE,
35553 -+ (zero_result_cause?zero_result_cause:"No tables used"));
35554 -+ else
35555 -+ {
35556 -+ if (result->send_fields(*columns_list,
35557 -+ Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
35558 -+ {
35559 -+ DBUG_VOID_RETURN;
35560 -+ }
35561 -+ /*
35562 -+ We have to test for 'conds' here as the WHERE may not be constant
35563 -+ even if we don't have any tables for prepared statements or if
35564 -+ conds uses something like 'rand()'.
35565 -+ If the HAVING clause is either impossible or always true, then
35566 -+ JOIN::having is set to NULL by optimize_cond.
35567 -+ In this case JOIN::exec must check for JOIN::having_value, in the
35568 -+ same way it checks for JOIN::cond_value.
35569 -+ */
35570 -+ if (cond_value != Item::COND_FALSE &&
35571 -+ having_value != Item::COND_FALSE &&
35572 -+ (!conds || conds->val_int()) &&
35573 -+ (!having || having->val_int()))
35574 -+ {
35575 -+ if (do_send_rows &&
35576 -+ (procedure ? (procedure->send_row(procedure_fields_list) ||
35577 -+ procedure->end_of_records()) : result->send_data(fields_list)))
35578 -+ error= 1;
35579 -+ else
35580 -+ {
35581 -+ error= (int) result->send_eof();
35582 -+ send_records= ((select_options & OPTION_FOUND_ROWS) ? 1 :
35583 -+ thd->sent_row_count);
35584 -+ }
35585 -+ }
35586 -+ else
35587 -+ {
35588 -+ error=(int) result->send_eof();
35589 -+ send_records= 0;
35590 -+ }
35591 -+ }
35592 -+ /* Single select (without union) always returns 0 or 1 row */
35593 -+ thd->limit_found_rows= send_records;
35594 -+ thd->examined_row_count= 0;
35595 -+ DBUG_VOID_RETURN;
35596 -+ }
35597 -+ /*
35598 -+ Don't reset the found rows count if there're no tables as
35599 -+ FOUND_ROWS() may be called. Never reset the examined row count here.
35600 -+ It must be accumulated from all join iterations of all join parts.
35601 -+ */
35602 -+ if (tables)
35603 -+ thd->limit_found_rows= 0;
35604 -+
35605 -+ if (zero_result_cause)
35606 -+ {
35607 -+ (void) return_zero_rows(this, result, select_lex->leaf_tables,
35608 -+ *columns_list,
35609 -+ send_row_on_empty_set(),
35610 -+ select_options,
35611 -+ zero_result_cause,
35612 -+ having);
35613 -+ DBUG_VOID_RETURN;
35614 -+ }
35615 -+
35616 -+ if ((this->select_lex->options & OPTION_SCHEMA_TABLE) &&
35617 -+ get_schema_tables_result(this, PROCESSED_BY_JOIN_EXEC))
35618 -+ DBUG_VOID_RETURN;
35619 -+
35620 -+ if (select_options & SELECT_DESCRIBE)
35621 -+ {
35622 -+ /*
35623 -+ Check if we managed to optimize ORDER BY away and don't use temporary
35624 -+ table to resolve ORDER BY: in that case, we only may need to do
35625 -+ filesort for GROUP BY.
35626 -+ */
35627 -+ if (!order && !no_order && (!skip_sort_order || !need_tmp))
35628 -+ {
35629 -+ /*
35630 -+ Reset 'order' to 'group_list' and reinit variables describing
35631 -+ 'order'
35632 -+ */
35633 -+ order= group_list;
35634 -+ simple_order= simple_group;
35635 -+ skip_sort_order= 0;
35636 -+ }
35637 -+ if (order &&
35638 -+ (order != group_list || !(select_options & SELECT_BIG_RESULT)) &&
35639 -+ (const_tables == tables ||
35640 -+ ((simple_order || skip_sort_order) &&
35641 -+ test_if_skip_sort_order(&join_tab[const_tables], order,
35642 -+ select_limit, 0,
35643 -+ &join_tab[const_tables].table->
35644 -+ keys_in_use_for_query))))
35645 -+ order=0;
35646 -+ having= tmp_having;
35647 -+ select_describe(this, need_tmp,
35648 -+ order != 0 && !skip_sort_order,
35649 -+ select_distinct,
35650 -+ !tables ? "No tables used" : NullS);
35651 -+ DBUG_VOID_RETURN;
35652 -+ }
35653 -+
35654 -+ JOIN *curr_join= this;
35655 -+ List<Item> *curr_all_fields= &all_fields;
35656 -+ List<Item> *curr_fields_list= &fields_list;
35657 -+ TABLE *curr_tmp_table= 0;
35658 -+ /*
35659 -+ Initialize examined rows here because the values from all join parts
35660 -+ must be accumulated in examined_row_count. Hence every join
35661 -+ iteration must count from zero.
35662 -+ */
35663 -+ curr_join->examined_rows= 0;
35664 -+
35665 -+ /* Create a tmp table if distinct or if the sort is too complicated */
35666 -+ if (need_tmp)
35667 -+ {
35668 -+ if (tmp_join)
35669 -+ {
35670 -+ /*
35671 -+ We are in a non cacheable sub query. Get the saved join structure
35672 -+ after optimization.
35673 -+ (curr_join may have been modified during last exection and we need
35674 -+ to reset it)
35675 -+ */
35676 -+ curr_join= tmp_join;
35677 -+ }
35678 -+ curr_tmp_table= exec_tmp_table1;
35679 -+
35680 -+ /* Copy data to the temporary table */
35681 -+ thd_proc_info(thd, "Copying to tmp table");
35682 -+ DBUG_PRINT("info", ("%s", thd->proc_info));
35683 -+ if (!curr_join->sort_and_group &&
35684 -+ curr_join->const_tables != curr_join->tables)
35685 -+ curr_join->join_tab[curr_join->const_tables].sorted= 0;
35686 -+ if ((tmp_error= do_select(curr_join, (List<Item> *) 0, curr_tmp_table, 0)))
35687 -+ {
35688 -+ error= tmp_error;
35689 -+ DBUG_VOID_RETURN;
35690 -+ }
35691 -+ curr_tmp_table->file->info(HA_STATUS_VARIABLE);
35692 -+
35693 -+ if (curr_join->having)
35694 -+ curr_join->having= curr_join->tmp_having= 0; // Allready done
35695 -+
35696 -+ /* Change sum_fields reference to calculated fields in tmp_table */
35697 -+ if (curr_join != this)
35698 -+ curr_join->all_fields= *curr_all_fields;
35699 -+ if (!items1)
35700 -+ {
35701 -+ items1= items0 + all_fields.elements;
35702 -+ if (sort_and_group || curr_tmp_table->group ||
35703 -+ tmp_table_param.precomputed_group_by)
35704 -+ {
35705 -+ if (change_to_use_tmp_fields(thd, items1,
35706 -+ tmp_fields_list1, tmp_all_fields1,
35707 -+ fields_list.elements, all_fields))
35708 -+ DBUG_VOID_RETURN;
35709 -+ }
35710 -+ else
35711 -+ {
35712 -+ if (change_refs_to_tmp_fields(thd, items1,
35713 -+ tmp_fields_list1, tmp_all_fields1,
35714 -+ fields_list.elements, all_fields))
35715 -+ DBUG_VOID_RETURN;
35716 -+ }
35717 -+ if (curr_join != this)
35718 -+ {
35719 -+ curr_join->tmp_all_fields1= tmp_all_fields1;
35720 -+ curr_join->tmp_fields_list1= tmp_fields_list1;
35721 -+ }
35722 -+ curr_join->items1= items1;
35723 -+ }
35724 -+ curr_all_fields= &tmp_all_fields1;
35725 -+ curr_fields_list= &tmp_fields_list1;
35726 -+ curr_join->set_items_ref_array(items1);
35727 -+
35728 -+ if (sort_and_group || curr_tmp_table->group)
35729 -+ {
35730 -+ curr_join->tmp_table_param.field_count+=
35731 -+ curr_join->tmp_table_param.sum_func_count+
35732 -+ curr_join->tmp_table_param.func_count;
35733 -+ curr_join->tmp_table_param.sum_func_count=
35734 -+ curr_join->tmp_table_param.func_count= 0;
35735 -+ }
35736 -+ else
35737 -+ {
35738 -+ curr_join->tmp_table_param.field_count+=
35739 -+ curr_join->tmp_table_param.func_count;
35740 -+ curr_join->tmp_table_param.func_count= 0;
35741 -+ }
35742 -+
35743 -+ // procedure can't be used inside subselect => we do nothing special for it
35744 -+ if (procedure)
35745 -+ procedure->update_refs();
35746 -+
35747 -+ if (curr_tmp_table->group)
35748 -+ { // Already grouped
35749 -+ if (!curr_join->order && !curr_join->no_order && !skip_sort_order)
35750 -+ curr_join->order= curr_join->group_list; /* order by group */
35751 -+ curr_join->group_list= 0;
35752 -+ }
35753 -+
35754 -+ /*
35755 -+ If we have different sort & group then we must sort the data by group
35756 -+ and copy it to another tmp table
35757 -+ This code is also used if we are using distinct something
35758 -+ we haven't been able to store in the temporary table yet
35759 -+ like SEC_TO_TIME(SUM(...)).
35760 -+ */
35761 -+
35762 -+ if ((curr_join->group_list && (!test_if_subpart(curr_join->group_list,
35763 -+ curr_join->order) ||
35764 -+ curr_join->select_distinct)) ||
35765 -+ (curr_join->select_distinct &&
35766 -+ curr_join->tmp_table_param.using_indirect_summary_function))
35767 -+ { /* Must copy to another table */
35768 -+ DBUG_PRINT("info",("Creating group table"));
35769 -+
35770 -+ /* Free first data from old join */
35771 -+ curr_join->join_free();
35772 -+ if (curr_join->make_simple_join(this, curr_tmp_table))
35773 -+ DBUG_VOID_RETURN;
35774 -+ calc_group_buffer(curr_join, group_list);
35775 -+ count_field_types(select_lex, &curr_join->tmp_table_param,
35776 -+ curr_join->tmp_all_fields1,
35777 -+ curr_join->select_distinct && !curr_join->group_list);
35778 -+ curr_join->tmp_table_param.hidden_field_count=
35779 -+ (curr_join->tmp_all_fields1.elements-
35780 -+ curr_join->tmp_fields_list1.elements);
35781 -+
35782 -+
35783 -+ if (exec_tmp_table2)
35784 -+ curr_tmp_table= exec_tmp_table2;
35785 -+ else
35786 -+ {
35787 -+ /* group data to new table */
35788 -+
35789 -+ /*
35790 -+ If the access method is loose index scan then all MIN/MAX
35791 -+ functions are precomputed, and should be treated as regular
35792 -+ functions. See extended comment in JOIN::exec.
35793 -+ */
35794 -+ if (curr_join->join_tab->is_using_loose_index_scan())
35795 -+ curr_join->tmp_table_param.precomputed_group_by= TRUE;
35796 -+
35797 -+ if (!(curr_tmp_table=
35798 -+ exec_tmp_table2= create_tmp_table(thd,
35799 -+ &curr_join->tmp_table_param,
35800 -+ *curr_all_fields,
35801 -+ (ORDER*) 0,
35802 -+ curr_join->select_distinct &&
35803 -+ !curr_join->group_list,
35804 -+ 1, curr_join->select_options,
35805 -+ HA_POS_ERROR,
35806 -+ (char *) "")))
35807 -+ DBUG_VOID_RETURN;
35808 -+ curr_join->exec_tmp_table2= exec_tmp_table2;
35809 -+ }
35810 -+ if (curr_join->group_list)
35811 -+ {
35812 -+ thd_proc_info(thd, "Creating sort index");
35813 -+ if (curr_join->join_tab == join_tab && save_join_tab())
35814 -+ {
35815 -+ DBUG_VOID_RETURN;
35816 -+ }
35817 -+ if (create_sort_index(thd, curr_join, curr_join->group_list,
35818 -+ HA_POS_ERROR, HA_POS_ERROR, FALSE) ||
35819 -+ make_group_fields(this, curr_join))
35820 -+ {
35821 -+ DBUG_VOID_RETURN;
35822 -+ }
35823 -+ sortorder= curr_join->sortorder;
35824 -+ }
35825 -+
35826 -+ thd_proc_info(thd, "Copying to group table");
35827 -+ DBUG_PRINT("info", ("%s", thd->proc_info));
35828 -+ tmp_error= -1;
35829 -+ if (curr_join != this)
35830 -+ {
35831 -+ if (sum_funcs2)
35832 -+ {
35833 -+ curr_join->sum_funcs= sum_funcs2;
35834 -+ curr_join->sum_funcs_end= sum_funcs_end2;
35835 -+ }
35836 -+ else
35837 -+ {
35838 -+ curr_join->alloc_func_list();
35839 -+ sum_funcs2= curr_join->sum_funcs;
35840 -+ sum_funcs_end2= curr_join->sum_funcs_end;
35841 -+ }
35842 -+ }
35843 -+ if (curr_join->make_sum_func_list(*curr_all_fields, *curr_fields_list,
35844 -+ 1, TRUE))
35845 -+ DBUG_VOID_RETURN;
35846 -+ curr_join->group_list= 0;
35847 -+ if (!curr_join->sort_and_group &&
35848 -+ curr_join->const_tables != curr_join->tables)
35849 -+ curr_join->join_tab[curr_join->const_tables].sorted= 0;
35850 -+ if (setup_sum_funcs(curr_join->thd, curr_join->sum_funcs) ||
35851 -+ (tmp_error= do_select(curr_join, (List<Item> *) 0, curr_tmp_table,
35852 -+ 0)))
35853 -+ {
35854 -+ error= tmp_error;
35855 -+ DBUG_VOID_RETURN;
35856 -+ }
35857 -+ end_read_record(&curr_join->join_tab->read_record);
35858 -+ curr_join->const_tables= curr_join->tables; // Mark free for cleanup()
35859 -+ curr_join->join_tab[0].table= 0; // Table is freed
35860 -+
35861 -+ // No sum funcs anymore
35862 -+ if (!items2)
35863 -+ {
35864 -+ items2= items1 + all_fields.elements;
35865 -+ if (change_to_use_tmp_fields(thd, items2,
35866 -+ tmp_fields_list2, tmp_all_fields2,
35867 -+ fields_list.elements, tmp_all_fields1))
35868 -+ DBUG_VOID_RETURN;
35869 -+ if (curr_join != this)
35870 -+ {
35871 -+ curr_join->tmp_fields_list2= tmp_fields_list2;
35872 -+ curr_join->tmp_all_fields2= tmp_all_fields2;
35873 -+ }
35874 -+ }
35875 -+ curr_fields_list= &curr_join->tmp_fields_list2;
35876 -+ curr_all_fields= &curr_join->tmp_all_fields2;
35877 -+ curr_join->set_items_ref_array(items2);
35878 -+ curr_join->tmp_table_param.field_count+=
35879 -+ curr_join->tmp_table_param.sum_func_count;
35880 -+ curr_join->tmp_table_param.sum_func_count= 0;
35881 -+ }
35882 -+ if (curr_tmp_table->distinct)
35883 -+ curr_join->select_distinct=0; /* Each row is unique */
35884 -+
35885 -+ curr_join->join_free(); /* Free quick selects */
35886 -+ if (curr_join->select_distinct && ! curr_join->group_list)
35887 -+ {
35888 -+ thd_proc_info(thd, "Removing duplicates");
35889 -+ if (curr_join->tmp_having)
35890 -+ curr_join->tmp_having->update_used_tables();
35891 -+ if (remove_duplicates(curr_join, curr_tmp_table,
35892 -+ *curr_fields_list, curr_join->tmp_having))
35893 -+ DBUG_VOID_RETURN;
35894 -+ curr_join->tmp_having=0;
35895 -+ curr_join->select_distinct=0;
35896 -+ }
35897 -+ curr_tmp_table->reginfo.lock_type= TL_UNLOCK;
35898 -+ if (curr_join->make_simple_join(this, curr_tmp_table))
35899 -+ DBUG_VOID_RETURN;
35900 -+ calc_group_buffer(curr_join, curr_join->group_list);
35901 -+ count_field_types(select_lex, &curr_join->tmp_table_param,
35902 -+ *curr_all_fields, 0);
35903 -+
35904 -+ }
35905 -+ if (procedure)
35906 -+ count_field_types(select_lex, &curr_join->tmp_table_param,
35907 -+ *curr_all_fields, 0);
35908 -+
35909 -+ if (curr_join->group || curr_join->implicit_grouping ||
35910 -+ curr_join->tmp_table_param.sum_func_count ||
35911 -+ (procedure && (procedure->flags & PROC_GROUP)))
35912 -+ {
35913 -+ if (make_group_fields(this, curr_join))
35914 -+ {
35915 -+ DBUG_VOID_RETURN;
35916 -+ }
35917 -+ if (!items3)
35918 -+ {
35919 -+ if (!items0)
35920 -+ init_items_ref_array();
35921 -+ items3= ref_pointer_array + (all_fields.elements*4);
35922 -+ setup_copy_fields(thd, &curr_join->tmp_table_param,
35923 -+ items3, tmp_fields_list3, tmp_all_fields3,
35924 -+ curr_fields_list->elements, *curr_all_fields);
35925 -+ tmp_table_param.save_copy_funcs= curr_join->tmp_table_param.copy_funcs;
35926 -+ tmp_table_param.save_copy_field= curr_join->tmp_table_param.copy_field;
35927 -+ tmp_table_param.save_copy_field_end=
35928 -+ curr_join->tmp_table_param.copy_field_end;
35929 -+ if (curr_join != this)
35930 -+ {
35931 -+ curr_join->tmp_all_fields3= tmp_all_fields3;
35932 -+ curr_join->tmp_fields_list3= tmp_fields_list3;
35933 -+ }
35934 -+ }
35935 -+ else
35936 -+ {
35937 -+ curr_join->tmp_table_param.copy_funcs= tmp_table_param.save_copy_funcs;
35938 -+ curr_join->tmp_table_param.copy_field= tmp_table_param.save_copy_field;
35939 -+ curr_join->tmp_table_param.copy_field_end=
35940 -+ tmp_table_param.save_copy_field_end;
35941 -+ }
35942 -+ curr_fields_list= &tmp_fields_list3;
35943 -+ curr_all_fields= &tmp_all_fields3;
35944 -+ curr_join->set_items_ref_array(items3);
35945 -+
35946 -+ if (curr_join->make_sum_func_list(*curr_all_fields, *curr_fields_list,
35947 -+ 1, TRUE) ||
35948 -+ setup_sum_funcs(curr_join->thd, curr_join->sum_funcs) ||
35949 -+ thd->is_fatal_error)
35950 -+ DBUG_VOID_RETURN;
35951 -+ }
35952 -+ if (curr_join->group_list || curr_join->order)
35953 -+ {
35954 -+ DBUG_PRINT("info",("Sorting for send_fields"));
35955 -+ thd_proc_info(thd, "Sorting result");
35956 -+ /* If we have already done the group, add HAVING to sorted table */
35957 -+ if (curr_join->tmp_having && ! curr_join->group_list &&
35958 -+ ! curr_join->sort_and_group)
35959 -+ {
35960 -+ // Some tables may have been const
35961 -+ curr_join->tmp_having->update_used_tables();
35962 -+ JOIN_TAB *curr_table= &curr_join->join_tab[curr_join->const_tables];
35963 -+ table_map used_tables= (curr_join->const_table_map |
35964 -+ curr_table->table->map);
35965 -+
35966 -+ Item* sort_table_cond= make_cond_for_table(curr_join->tmp_having,
35967 -+ used_tables,
35968 -+ used_tables);
35969 -+ if (sort_table_cond)
35970 -+ {
35971 -+ if (!curr_table->select)
35972 -+ if (!(curr_table->select= new SQL_SELECT))
35973 -+ DBUG_VOID_RETURN;
35974 -+ if (!curr_table->select->cond)
35975 -+ curr_table->select->cond= sort_table_cond;
35976 -+ else
35977 -+ {
35978 -+ if (!(curr_table->select->cond=
35979 -+ new Item_cond_and(curr_table->select->cond,
35980 -+ sort_table_cond)))
35981 -+ DBUG_VOID_RETURN;
35982 -+ curr_table->select->cond->fix_fields(thd, 0);
35983 -+ }
35984 -+ curr_table->select_cond= curr_table->select->cond;
35985 -+ curr_table->select_cond->top_level_item();
35986 -+ DBUG_EXECUTE("where",print_where(curr_table->select->cond,
35987 -+ "select and having",
35988 -+ QT_ORDINARY););
35989 -+ curr_join->tmp_having= make_cond_for_table(curr_join->tmp_having,
35990 -+ ~ (table_map) 0,
35991 -+ ~used_tables);
35992 -+ DBUG_EXECUTE("where",print_where(curr_join->tmp_having,
35993 -+ "having after sort",
35994 -+ QT_ORDINARY););
35995 -+ }
35996 -+ }
35997 -+ {
35998 -+ if (group)
35999 -+ curr_join->select_limit= HA_POS_ERROR;
36000 -+ else
36001 -+ {
36002 -+ /*
36003 -+ We can abort sorting after thd->select_limit rows if we there is no
36004 -+ WHERE clause for any tables after the sorted one.
36005 -+ */
36006 -+ JOIN_TAB *curr_table= &curr_join->join_tab[curr_join->const_tables+1];
36007 -+ JOIN_TAB *end_table= &curr_join->join_tab[curr_join->tables];
36008 -+ for (; curr_table < end_table ; curr_table++)
36009 -+ {
36010 -+ /*
36011 -+ table->keyuse is set in the case there was an original WHERE clause
36012 -+ on the table that was optimized away.
36013 -+ */
36014 -+ if (curr_table->select_cond ||
36015 -+ (curr_table->keyuse && !curr_table->first_inner))
36016 -+ {
36017 -+ /* We have to sort all rows */
36018 -+ curr_join->select_limit= HA_POS_ERROR;
36019 -+ break;
36020 -+ }
36021 -+ }
36022 -+ }
36023 -+ if (curr_join->join_tab == join_tab && save_join_tab())
36024 -+ {
36025 -+ DBUG_VOID_RETURN;
36026 -+ }
36027 -+ /*
36028 -+ Here we sort rows for ORDER BY/GROUP BY clause, if the optimiser
36029 -+ chose FILESORT to be faster than INDEX SCAN or there is no
36030 -+ suitable index present.
36031 -+ Note, that create_sort_index calls test_if_skip_sort_order and may
36032 -+ finally replace sorting with index scan if there is a LIMIT clause in
36033 -+ the query. XXX: it's never shown in EXPLAIN!
36034 -+ OPTION_FOUND_ROWS supersedes LIMIT and is taken into account.
36035 -+ */
36036 -+ if (create_sort_index(thd, curr_join,
36037 -+ curr_join->group_list ?
36038 -+ curr_join->group_list : curr_join->order,
36039 -+ curr_join->select_limit,
36040 -+ (select_options & OPTION_FOUND_ROWS ?
36041 -+ HA_POS_ERROR : unit->select_limit_cnt),
36042 -+ curr_join->group_list ? TRUE : FALSE))
36043 -+ DBUG_VOID_RETURN;
36044 -+ sortorder= curr_join->sortorder;
36045 -+ if (curr_join->const_tables != curr_join->tables &&
36046 -+ !curr_join->join_tab[curr_join->const_tables].table->sort.io_cache)
36047 -+ {
36048 -+ /*
36049 -+ If no IO cache exists for the first table then we are using an
36050 -+ INDEX SCAN and no filesort. Thus we should not remove the sorted
36051 -+ attribute on the INDEX SCAN.
36052 -+ */
36053 -+ skip_sort_order= 1;
36054 -+ }
36055 -+ }
36056 -+ }
36057 -+ /* XXX: When can we have here thd->is_error() not zero? */
36058 -+ if (thd->is_error())
36059 -+ {
36060 -+ error= thd->is_error();
36061 -+ DBUG_VOID_RETURN;
36062 -+ }
36063 -+ curr_join->having= curr_join->tmp_having;
36064 -+ curr_join->fields= curr_fields_list;
36065 -+ curr_join->procedure= procedure;
36066 -+
36067 -+ if (is_top_level_join() && thd->cursor && tables != const_tables)
36068 -+ {
36069 -+ /*
36070 -+ We are here if this is JOIN::exec for the last select of the main unit
36071 -+ and the client requested to open a cursor.
36072 -+ We check that not all tables are constant because this case is not
36073 -+ handled by do_select() separately, and this case is not implemented
36074 -+ for cursors yet.
36075 -+ */
36076 -+ DBUG_ASSERT(error == 0);
36077 -+ /*
36078 -+ curr_join is used only for reusable joins - that is,
36079 -+ to perform SELECT for each outer row (like in subselects).
36080 -+ This join is main, so we know for sure that curr_join == join.
36081 -+ */
36082 -+ DBUG_ASSERT(curr_join == this);
36083 -+ /* Open cursor for the last join sweep */
36084 -+ error= thd->cursor->open(this);
36085 -+ }
36086 -+ else
36087 -+ {
36088 -+ thd_proc_info(thd, "Sending data");
36089 -+ DBUG_PRINT("info", ("%s", thd->proc_info));
36090 -+ result->send_fields((procedure ? curr_join->procedure_fields_list :
36091 -+ *curr_fields_list),
36092 -+ Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF);
36093 -+ error= do_select(curr_join, curr_fields_list, NULL, procedure);
36094 -+ thd->limit_found_rows= curr_join->send_records;
36095 -+ }
36096 -+
36097 -+ /* Accumulate the counts from all join iterations of all join parts. */
36098 -+ thd->examined_row_count+= curr_join->examined_rows;
36099 -+ DBUG_PRINT("counts", ("thd->examined_row_count: %lu",
36100 -+ (ulong) thd->examined_row_count));
36101 -+
36102 -+ /*
36103 -+ With EXPLAIN EXTENDED we have to restore original ref_array
36104 -+ for a derived table which is always materialized.
36105 -+ We also need to do this when we have temp table(s).
36106 -+ Otherwise we would not be able to print the query correctly.
36107 -+ */
36108 -+ if (items0 && (thd->lex->describe & DESCRIBE_EXTENDED) &&
36109 -+ (select_lex->linkage == DERIVED_TABLE_TYPE ||
36110 -+ exec_tmp_table1 || exec_tmp_table2))
36111 -+ set_items_ref_array(items0);
36112 -+
36113 -+ DBUG_VOID_RETURN;
36114 -+}
36115 -+
36116 -+
36117 -+/**
36118 -+ Clean up join.
36119 -+
36120 -+ @return
36121 -+ Return error that hold JOIN.
36122 -+*/
36123 -+
36124 -+int
36125 -+JOIN::destroy()
36126 -+{
36127 -+ DBUG_ENTER("JOIN::destroy");
36128 -+ select_lex->join= 0;
36129 -+
36130 -+ if (tmp_join)
36131 -+ {
36132 -+ if (join_tab != tmp_join->join_tab)
36133 -+ {
36134 -+ JOIN_TAB *tab, *end;
36135 -+ for (tab= join_tab, end= tab+tables ; tab != end ; tab++)
36136 -+ tab->cleanup();
36137 -+ }
36138 -+ tmp_join->tmp_join= 0;
36139 -+ /*
36140 -+ We need to clean up tmp_table_param for reusable JOINs (having non-zero
36141 -+ and different from self tmp_join) because it's not being cleaned up
36142 -+ anywhere else (as we need to keep the join is reusable).
36143 -+ */
36144 -+ tmp_table_param.cleanup();
36145 -+ tmp_table_param.copy_field= tmp_join->tmp_table_param.copy_field= 0;
36146 -+ DBUG_RETURN(tmp_join->destroy());
36147 -+ }
36148 -+ cond_equal= 0;
36149 -+
36150 -+ cleanup(1);
36151 -+ /* Cleanup items referencing temporary table columns */
36152 -+ cleanup_item_list(tmp_all_fields1);
36153 -+ cleanup_item_list(tmp_all_fields3);
36154 -+ if (exec_tmp_table1)
36155 -+ free_tmp_table(thd, exec_tmp_table1);
36156 -+ if (exec_tmp_table2)
36157 -+ free_tmp_table(thd, exec_tmp_table2);
36158 -+ delete select;
36159 -+ delete_dynamic(&keyuse);
36160 -+ delete procedure;
36161 -+ DBUG_RETURN(error);
36162 -+}
36163 -+
36164 -+
36165 -+void JOIN::cleanup_item_list(List<Item> &items) const
36166 -+{
36167 -+ if (!items.is_empty())
36168 -+ {
36169 -+ List_iterator_fast<Item> it(items);
36170 -+ Item *item;
36171 -+ while ((item= it++))
36172 -+ item->cleanup();
36173 -+ }
36174 -+}
36175 -+
36176 -+
36177 -+/**
36178 -+ An entry point to single-unit select (a select without UNION).
36179 -+
36180 -+ @param thd thread handler
36181 -+ @param rref_pointer_array a reference to ref_pointer_array of
36182 -+ the top-level select_lex for this query
36183 -+ @param tables list of all tables used in this query.
36184 -+ The tables have been pre-opened.
36185 -+ @param wild_num number of wildcards used in the top level
36186 -+ select of this query.
36187 -+ For example statement
36188 -+ SELECT *, t1.*, catalog.t2.* FROM t0, t1, t2;
36189 -+ has 3 wildcards.
36190 -+ @param fields list of items in SELECT list of the top-level
36191 -+ select
36192 -+ e.g. SELECT a, b, c FROM t1 will have Item_field
36193 -+ for a, b and c in this list.
36194 -+ @param conds top level item of an expression representing
36195 -+ WHERE clause of the top level select
36196 -+ @param og_num total number of ORDER BY and GROUP BY clauses
36197 -+ arguments
36198 -+ @param order linked list of ORDER BY agruments
36199 -+ @param group linked list of GROUP BY arguments
36200 -+ @param having top level item of HAVING expression
36201 -+ @param proc_param list of PROCEDUREs
36202 -+ @param select_options select options (BIG_RESULT, etc)
36203 -+ @param result an instance of result set handling class.
36204 -+ This object is responsible for send result
36205 -+ set rows to the client or inserting them
36206 -+ into a table.
36207 -+ @param select_lex the only SELECT_LEX of this query
36208 -+ @param unit top-level UNIT of this query
36209 -+ UNIT is an artificial object created by the
36210 -+ parser for every SELECT clause.
36211 -+ e.g.
36212 -+ SELECT * FROM t1 WHERE a1 IN (SELECT * FROM t2)
36213 -+ has 2 unions.
36214 -+
36215 -+ @retval
36216 -+ FALSE success
36217 -+ @retval
36218 -+ TRUE an error
36219 -+*/
36220 -+
36221 -+bool
36222 -+mysql_select(THD *thd, Item ***rref_pointer_array,
36223 -+ TABLE_LIST *tables, uint wild_num, List<Item> &fields,
36224 -+ COND *conds, uint og_num, ORDER *order, ORDER *group,
36225 -+ Item *having, ORDER *proc_param, ulonglong select_options,
36226 -+ select_result *result, SELECT_LEX_UNIT *unit,
36227 -+ SELECT_LEX *select_lex)
36228 -+{
36229 -+ bool err;
36230 -+ bool free_join= 1;
36231 -+ DBUG_ENTER("mysql_select");
36232 -+
36233 -+ select_lex->context.resolve_in_select_list= TRUE;
36234 -+ JOIN *join;
36235 -+ if (select_lex->join != 0)
36236 -+ {
36237 -+ join= select_lex->join;
36238 -+ /*
36239 -+ is it single SELECT in derived table, called in derived table
36240 -+ creation
36241 -+ */
36242 -+ if (select_lex->linkage != DERIVED_TABLE_TYPE ||
36243 -+ (select_options & SELECT_DESCRIBE))
36244 -+ {
36245 -+ if (select_lex->linkage != GLOBAL_OPTIONS_TYPE)
36246 -+ {
36247 -+ //here is EXPLAIN of subselect or derived table
36248 -+ if (join->change_result(result))
36249 -+ {
36250 -+ DBUG_RETURN(TRUE);
36251 -+ }
36252 -+ /*
36253 -+ Original join tabs might be overwritten at first
36254 -+ subselect execution. So we need to restore them.
36255 -+ */
36256 -+ Item_subselect *subselect= select_lex->master_unit()->item;
36257 -+ if (subselect && subselect->is_uncacheable() && join->reinit())
36258 -+ DBUG_RETURN(TRUE);
36259 -+ }
36260 -+ else
36261 -+ {
36262 -+ err= join->prepare(rref_pointer_array, tables, wild_num,
36263 -+ conds, og_num, order, group, having, proc_param,
36264 -+ select_lex, unit);
36265 -+ if (err)
36266 -+ {
36267 -+ goto err;
36268 -+ }
36269 -+ }
36270 -+ }
36271 -+ free_join= 0;
36272 -+ join->select_options= select_options;
36273 -+ }
36274 -+ else
36275 -+ {
36276 -+ if (!(join= new JOIN(thd, fields, select_options, result)))
36277 -+ DBUG_RETURN(TRUE);
36278 -+ thd_proc_info(thd, "init");
36279 -+ thd->used_tables=0; // Updated by setup_fields
36280 -+ err= join->prepare(rref_pointer_array, tables, wild_num,
36281 -+ conds, og_num, order, group, having, proc_param,
36282 -+ select_lex, unit);
36283 -+ if (err)
36284 -+ {
36285 -+ goto err;
36286 -+ }
36287 -+ }
36288 -+
36289 -+ if ((err= join->optimize()))
36290 -+ {
36291 -+ goto err; // 1
36292 -+ }
36293 -+
36294 -+ if (thd->lex->describe & DESCRIBE_EXTENDED)
36295 -+ {
36296 -+ join->conds_history= join->conds;
36297 -+ join->having_history= (join->having?join->having:join->tmp_having);
36298 -+ }
36299 -+
36300 -+ if (thd->is_error())
36301 -+ goto err;
36302 -+
36303 -+ join->exec();
36304 -+
36305 -+ if (thd->cursor && thd->cursor->is_open())
36306 -+ {
36307 -+ /*
36308 -+ A cursor was opened for the last sweep in exec().
36309 -+ We are here only if this is mysql_select for top-level SELECT_LEX_UNIT
36310 -+ and there were no error.
36311 -+ */
36312 -+ free_join= 0;
36313 -+ }
36314 -+
36315 -+ if (thd->lex->describe & DESCRIBE_EXTENDED)
36316 -+ {
36317 -+ select_lex->where= join->conds_history;
36318 -+ select_lex->having= join->having_history;
36319 -+ }
36320 -+
36321 -+err:
36322 -+ if (free_join)
36323 -+ {
36324 -+ thd_proc_info(thd, "end");
36325 -+ err|= select_lex->cleanup();
36326 -+ DBUG_RETURN(err || thd->is_error());
36327 -+ }
36328 -+ DBUG_RETURN(join->error);
36329 -+}
36330 -+
36331 -+/*****************************************************************************
36332 -+ Create JOIN_TABS, make a guess about the table types,
36333 -+ Approximate how many records will be used in each table
36334 -+*****************************************************************************/
36335 -+
36336 -+static ha_rows get_quick_record_count(THD *thd, SQL_SELECT *select,
36337 -+ TABLE *table,
36338 -+ const key_map *keys,ha_rows limit)
36339 -+{
36340 -+ int error;
36341 -+ DBUG_ENTER("get_quick_record_count");
36342 -+#ifndef EMBEDDED_LIBRARY // Avoid compiler warning
36343 -+ uchar buff[STACK_BUFF_ALLOC];
36344 -+#endif
36345 -+ if (check_stack_overrun(thd, STACK_MIN_SIZE, buff))
36346 -+ DBUG_RETURN(0); // Fatal error flag is set
36347 -+ if (select)
36348 -+ {
36349 -+ select->head=table;
36350 -+ if ((error= select->test_quick_select(thd, *(key_map *)keys,(table_map) 0,
36351 -+ limit, 0)) == 1)
36352 -+ DBUG_RETURN(select->quick->records);
36353 -+ if (error == -1)
36354 -+ {
36355 -+ table->reginfo.impossible_range=1;
36356 -+ DBUG_RETURN(0);
36357 -+ }
36358 -+ DBUG_PRINT("warning",("Couldn't use record count on const keypart"));
36359 -+ }
36360 -+ DBUG_RETURN(HA_POS_ERROR); /* This shouldn't happend */
36361 -+}
36362 -+
36363 -+/*
36364 -+ This structure is used to collect info on potentially sargable
36365 -+ predicates in order to check whether they become sargable after
36366 -+ reading const tables.
36367 -+ We form a bitmap of indexes that can be used for sargable predicates.
36368 -+ Only such indexes are involved in range analysis.
36369 -+*/
36370 -+typedef struct st_sargable_param
36371 -+{
36372 -+ Field *field; /* field against which to check sargability */
36373 -+ Item **arg_value; /* values of potential keys for lookups */
36374 -+ uint num_values; /* number of values in the above array */
36375 -+} SARGABLE_PARAM;
36376 -+
36377 -+/**
36378 -+ Calculate the best possible join and initialize the join structure.
36379 -+
36380 -+ @retval
36381 -+ 0 ok
36382 -+ @retval
36383 -+ 1 Fatal error
36384 -+*/
36385 -+
36386 -+static bool
36387 -+make_join_statistics(JOIN *join, TABLE_LIST *tables_arg, COND *conds,
36388 -+ DYNAMIC_ARRAY *keyuse_array)
36389 -+{
36390 -+ int error;
36391 -+ TABLE *table;
36392 -+ TABLE_LIST *tables= tables_arg;
36393 -+ uint i,table_count,const_count,key;
36394 -+ table_map found_const_table_map, all_table_map, found_ref, refs;
36395 -+ key_map const_ref, eq_part;
36396 -+ TABLE **table_vector;
36397 -+ JOIN_TAB *stat,*stat_end,*s,**stat_ref;
36398 -+ KEYUSE *keyuse,*start_keyuse;
36399 -+ table_map outer_join=0;
36400 -+ SARGABLE_PARAM *sargables= 0;
36401 -+ JOIN_TAB *stat_vector[MAX_TABLES+1];
36402 -+ DBUG_ENTER("make_join_statistics");
36403 -+
36404 -+ table_count=join->tables;
36405 -+ stat=(JOIN_TAB*) join->thd->calloc(sizeof(JOIN_TAB)*table_count);
36406 -+ stat_ref=(JOIN_TAB**) join->thd->alloc(sizeof(JOIN_TAB*)*MAX_TABLES);
36407 -+ table_vector=(TABLE**) join->thd->alloc(sizeof(TABLE*)*(table_count*2));
36408 -+ if (!stat || !stat_ref || !table_vector)
36409 -+ DBUG_RETURN(1); // Eom /* purecov: inspected */
36410 -+
36411 -+ join->best_ref=stat_vector;
36412 -+
36413 -+ stat_end=stat+table_count;
36414 -+ found_const_table_map= all_table_map=0;
36415 -+ const_count=0;
36416 -+
36417 -+ for (s= stat, i= 0;
36418 -+ tables;
36419 -+ s++, tables= tables->next_leaf, i++)
36420 -+ {
36421 -+ TABLE_LIST *embedding= tables->embedding;
36422 -+ stat_vector[i]=s;
36423 -+ s->keys.init();
36424 -+ s->const_keys.init();
36425 -+ s->checked_keys.init();
36426 -+ s->needed_reg.init();
36427 -+ table_vector[i]=s->table=table=tables->table;
36428 -+ table->pos_in_table_list= tables;
36429 -+ error= table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
36430 -+ if (error)
36431 -+ {
36432 -+ table->file->print_error(error, MYF(0));
36433 -+ goto error;
36434 -+ }
36435 -+ table->quick_keys.clear_all();
36436 -+ table->reginfo.join_tab=s;
36437 -+ table->reginfo.not_exists_optimize=0;
36438 -+ bzero((char*) table->const_key_parts, sizeof(key_part_map)*table->s->keys);
36439 -+ all_table_map|= table->map;
36440 -+ s->join=join;
36441 -+ s->info=0; // For describe
36442 -+
36443 -+ s->dependent= tables->dep_tables;
36444 -+ s->key_dependent= 0;
36445 -+ if (tables->schema_table)
36446 -+ table->file->stats.records= 2;
36447 -+ table->quick_condition_rows= table->file->stats.records;
36448 -+
36449 -+ s->on_expr_ref= &tables->on_expr;
36450 -+ if (*s->on_expr_ref)
36451 -+ {
36452 -+ /* s is the only inner table of an outer join */
36453 -+#ifdef WITH_PARTITION_STORAGE_ENGINE
36454 -+ if ((!table->file->stats.records || table->no_partitions_used) && !embedding)
36455 -+#else
36456 -+ if (!table->file->stats.records && !embedding)
36457 -+#endif
36458 -+ { // Empty table
36459 -+ s->dependent= 0; // Ignore LEFT JOIN depend.
36460 -+ set_position(join,const_count++,s,(KEYUSE*) 0);
36461 -+ continue;
36462 -+ }
36463 -+ outer_join|= table->map;
36464 -+ s->embedding_map= 0;
36465 -+ for (;embedding; embedding= embedding->embedding)
36466 -+ s->embedding_map|= embedding->nested_join->nj_map;
36467 -+ continue;
36468 -+ }
36469 -+ if (embedding)
36470 -+ {
36471 -+ /* s belongs to a nested join, maybe to several embedded joins */
36472 -+ s->embedding_map= 0;
36473 -+ do
36474 -+ {
36475 -+ NESTED_JOIN *nested_join= embedding->nested_join;
36476 -+ s->embedding_map|=nested_join->nj_map;
36477 -+ s->dependent|= embedding->dep_tables;
36478 -+ embedding= embedding->embedding;
36479 -+ outer_join|= nested_join->used_tables;
36480 -+ }
36481 -+ while (embedding);
36482 -+ continue;
36483 -+ }
36484 -+#ifdef WITH_PARTITION_STORAGE_ENGINE
36485 -+ const bool no_partitions_used= table->no_partitions_used;
36486 -+#else
36487 -+ const bool no_partitions_used= FALSE;
36488 -+#endif
36489 -+ if ((table->s->system || table->file->stats.records <= 1 ||
36490 -+ no_partitions_used) &&
36491 -+ !s->dependent &&
36492 -+ (table->file->ha_table_flags() & HA_STATS_RECORDS_IS_EXACT) &&
36493 -+ !table->fulltext_searched && !join->no_const_tables)
36494 -+ {
36495 -+ set_position(join,const_count++,s,(KEYUSE*) 0);
36496 -+ }
36497 -+ }
36498 -+ stat_vector[i]=0;
36499 -+ join->outer_join=outer_join;
36500 -+
36501 -+ if (join->outer_join)
36502 -+ {
36503 -+ /*
36504 -+ Build transitive closure for relation 'to be dependent on'.
36505 -+ This will speed up the plan search for many cases with outer joins,
36506 -+ as well as allow us to catch illegal cross references.
36507 -+ Warshall's algorithm is used to build the transitive closure.
36508 -+ As we may restart the outer loop upto 'table_count' times, the
36509 -+ complexity of the algorithm is O((number of tables)^3).
36510 -+ However, most of the iterations will be shortcircuited when
36511 -+ there are no pedendencies to propogate.
36512 -+ */
36513 -+ for (i= 0 ; i < table_count ; i++)
36514 -+ {
36515 -+ uint j;
36516 -+ table= stat[i].table;
36517 -+
36518 -+ if (!table->reginfo.join_tab->dependent)
36519 -+ continue;
36520 -+
36521 -+ /* Add my dependencies to other tables depending on me */
36522 -+ for (j= 0, s= stat ; j < table_count ; j++, s++)
36523 -+ {
36524 -+ if (s->dependent & table->map)
36525 -+ {
36526 -+ table_map was_dependent= s->dependent;
36527 -+ s->dependent |= table->reginfo.join_tab->dependent;
36528 -+ /*
36529 -+ If we change dependencies for a table we already have
36530 -+ processed: Redo dependency propagation from this table.
36531 -+ */
36532 -+ if (i > j && s->dependent != was_dependent)
36533 -+ {
36534 -+ i = j-1;
36535 -+ break;
36536 -+ }
36537 -+ }
36538 -+ }
36539 -+ }
36540 -+
36541 -+ for (i= 0, s= stat ; i < table_count ; i++, s++)
36542 -+ {
36543 -+ /* Catch illegal cross references for outer joins */
36544 -+ if (s->dependent & s->table->map)
36545 -+ {
36546 -+ join->tables=0; // Don't use join->table
36547 -+ my_message(ER_WRONG_OUTER_JOIN, ER(ER_WRONG_OUTER_JOIN), MYF(0));
36548 -+ goto error;
36549 -+ }
36550 -+
36551 -+ if (outer_join & s->table->map)
36552 -+ s->table->maybe_null= 1;
36553 -+ s->key_dependent= s->dependent;
36554 -+ }
36555 -+ }
36556 -+
36557 -+ if (conds || outer_join)
36558 -+ if (update_ref_and_keys(join->thd, keyuse_array, stat, join->tables,
36559 -+ conds, join->cond_equal,
36560 -+ ~outer_join, join->select_lex, &sargables))
36561 -+ goto error;
36562 -+
36563 -+ /* Read tables with 0 or 1 rows (system tables) */
36564 -+ join->const_table_map= 0;
36565 -+
36566 -+ for (POSITION *p_pos=join->positions, *p_end=p_pos+const_count;
36567 -+ p_pos < p_end ;
36568 -+ p_pos++)
36569 -+ {
36570 -+ int tmp;
36571 -+ s= p_pos->table;
36572 -+ s->type=JT_SYSTEM;
36573 -+ join->const_table_map|=s->table->map;
36574 -+ if ((tmp=join_read_const_table(s, p_pos)))
36575 -+ {
36576 -+ if (tmp > 0)
36577 -+ goto error; // Fatal error
36578 -+ }
36579 -+ else
36580 -+ found_const_table_map|= s->table->map;
36581 -+ }
36582 -+
36583 -+ /* loop until no more const tables are found */
36584 -+ int ref_changed;
36585 -+ do
36586 -+ {
36587 -+ more_const_tables_found:
36588 -+ ref_changed = 0;
36589 -+ found_ref=0;
36590 -+
36591 -+ /*
36592 -+ We only have to loop from stat_vector + const_count as
36593 -+ set_position() will move all const_tables first in stat_vector
36594 -+ */
36595 -+
36596 -+ for (JOIN_TAB **pos=stat_vector+const_count ; (s= *pos) ; pos++)
36597 -+ {
36598 -+ table=s->table;
36599 -+
36600 -+ /*
36601 -+ If equi-join condition by a key is null rejecting and after a
36602 -+ substitution of a const table the key value happens to be null
36603 -+ then we can state that there are no matches for this equi-join.
36604 -+ */
36605 -+ if ((keyuse= s->keyuse) && *s->on_expr_ref && !s->embedding_map)
36606 -+ {
36607 -+ /*
36608 -+ When performing an outer join operation if there are no matching rows
36609 -+ for the single row of the outer table all the inner tables are to be
36610 -+ null complemented and thus considered as constant tables.
36611 -+ Here we apply this consideration to the case of outer join operations
36612 -+ with a single inner table only because the case with nested tables
36613 -+ would require a more thorough analysis.
36614 -+ TODO. Apply single row substitution to null complemented inner tables
36615 -+ for nested outer join operations.
36616 -+ */
36617 -+ while (keyuse->table == table)
36618 -+ {
36619 -+ if (!(keyuse->val->used_tables() & ~join->const_table_map) &&
36620 -+ keyuse->val->is_null() && keyuse->null_rejecting)
36621 -+ {
36622 -+ s->type= JT_CONST;
36623 -+ mark_as_null_row(table);
36624 -+ found_const_table_map|= table->map;
36625 -+ join->const_table_map|= table->map;
36626 -+ set_position(join,const_count++,s,(KEYUSE*) 0);
36627 -+ goto more_const_tables_found;
36628 -+ }
36629 -+ keyuse++;
36630 -+ }
36631 -+ }
36632 -+
36633 -+ if (s->dependent) // If dependent on some table
36634 -+ {
36635 -+ // All dep. must be constants
36636 -+ if (s->dependent & ~(found_const_table_map))
36637 -+ continue;
36638 -+ if (table->file->stats.records <= 1L &&
36639 -+ (table->file->ha_table_flags() & HA_STATS_RECORDS_IS_EXACT) &&
36640 -+ !table->pos_in_table_list->embedding)
36641 -+ { // system table
36642 -+ int tmp= 0;
36643 -+ s->type=JT_SYSTEM;
36644 -+ join->const_table_map|=table->map;
36645 -+ set_position(join,const_count++,s,(KEYUSE*) 0);
36646 -+ if ((tmp= join_read_const_table(s, join->positions+const_count-1)))
36647 -+ {
36648 -+ if (tmp > 0)
36649 -+ goto error; // Fatal error
36650 -+ }
36651 -+ else
36652 -+ found_const_table_map|= table->map;
36653 -+ continue;
36654 -+ }
36655 -+ }
36656 -+ /* check if table can be read by key or table only uses const refs */
36657 -+ if ((keyuse=s->keyuse))
36658 -+ {
36659 -+ s->type= JT_REF;
36660 -+ while (keyuse->table == table)
36661 -+ {
36662 -+ start_keyuse=keyuse;
36663 -+ key=keyuse->key;
36664 -+ s->keys.set_bit(key); // QQ: remove this ?
36665 -+
36666 -+ refs=0;
36667 -+ const_ref.clear_all();
36668 -+ eq_part.clear_all();
36669 -+ do
36670 -+ {
36671 -+ if (keyuse->val->type() != Item::NULL_ITEM && !keyuse->optimize)
36672 -+ {
36673 -+ if (!((~found_const_table_map) & keyuse->used_tables))
36674 -+ const_ref.set_bit(keyuse->keypart);
36675 -+ else
36676 -+ refs|=keyuse->used_tables;
36677 -+ eq_part.set_bit(keyuse->keypart);
36678 -+ }
36679 -+ keyuse++;
36680 -+ } while (keyuse->table == table && keyuse->key == key);
36681 -+
36682 -+ if (eq_part.is_prefix(table->key_info[key].key_parts) &&
36683 -+ !table->fulltext_searched &&
36684 -+ !table->pos_in_table_list->embedding)
36685 -+ {
36686 -+ if ((table->key_info[key].flags & (HA_NOSAME | HA_END_SPACE_KEY))
36687 -+ == HA_NOSAME)
36688 -+ {
36689 -+ if (const_ref == eq_part)
36690 -+ { // Found everything for ref.
36691 -+ int tmp;
36692 -+ ref_changed = 1;
36693 -+ s->type= JT_CONST;
36694 -+ join->const_table_map|=table->map;
36695 -+ set_position(join,const_count++,s,start_keyuse);
36696 -+ if (create_ref_for_key(join, s, start_keyuse,
36697 -+ found_const_table_map))
36698 -+ goto error;
36699 -+ if ((tmp=join_read_const_table(s,
36700 -+ join->positions+const_count-1)))
36701 -+ {
36702 -+ if (tmp > 0)
36703 -+ goto error; // Fatal error
36704 -+ }
36705 -+ else
36706 -+ found_const_table_map|= table->map;
36707 -+ break;
36708 -+ }
36709 -+ else
36710 -+ found_ref|= refs; // Table is const if all refs are const
36711 -+ }
36712 -+ else if (const_ref == eq_part)
36713 -+ s->const_keys.set_bit(key);
36714 -+ }
36715 -+ }
36716 -+ }
36717 -+ }
36718 -+ } while (join->const_table_map & found_ref && ref_changed);
36719 -+
36720 -+ /*
36721 -+ Update info on indexes that can be used for search lookups as
36722 -+ reading const tables may has added new sargable predicates.
36723 -+ */
36724 -+ if (const_count && sargables)
36725 -+ {
36726 -+ for( ; sargables->field ; sargables++)
36727 -+ {
36728 -+ Field *field= sargables->field;
36729 -+ JOIN_TAB *join_tab= field->table->reginfo.join_tab;
36730 -+ key_map possible_keys= field->key_start;
36731 -+ possible_keys.intersect(field->table->keys_in_use_for_query);
36732 -+ bool is_const= 1;
36733 -+ for (uint j=0; j < sargables->num_values; j++)
36734 -+ is_const&= sargables->arg_value[j]->const_item();
36735 -+ if (is_const)
36736 -+ join_tab[0].const_keys.merge(possible_keys);
36737 -+ }
36738 -+ }
36739 -+
36740 -+ /* Calc how many (possible) matched records in each table */
36741 -+
36742 -+ for (s=stat ; s < stat_end ; s++)
36743 -+ {
36744 -+ if (s->type == JT_SYSTEM || s->type == JT_CONST)
36745 -+ {
36746 -+ /* Only one matching row */
36747 -+ s->found_records=s->records=s->read_time=1; s->worst_seeks=1.0;
36748 -+ continue;
36749 -+ }
36750 -+ /* Approximate found rows and time to read them */
36751 -+ s->found_records=s->records=s->table->file->stats.records;
36752 -+ s->read_time=(ha_rows) s->table->file->scan_time();
36753 -+
36754 -+ /*
36755 -+ Set a max range of how many seeks we can expect when using keys
36756 -+ This is can't be to high as otherwise we are likely to use
36757 -+ table scan.
36758 -+ */
36759 -+ s->worst_seeks= min((double) s->found_records / 10,
36760 -+ (double) s->read_time*3);
36761 -+ if (s->worst_seeks < 2.0) // Fix for small tables
36762 -+ s->worst_seeks=2.0;
36763 -+
36764 -+ /*
36765 -+ Add to stat->const_keys those indexes for which all group fields or
36766 -+ all select distinct fields participate in one index.
36767 -+ */
36768 -+ add_group_and_distinct_keys(join, s);
36769 -+
36770 -+ if (!s->const_keys.is_clear_all() &&
36771 -+ !s->table->pos_in_table_list->embedding)
36772 -+ {
36773 -+ ha_rows records;
36774 -+ SQL_SELECT *select;
36775 -+ select= make_select(s->table, found_const_table_map,
36776 -+ found_const_table_map,
36777 -+ *s->on_expr_ref ? *s->on_expr_ref : conds,
36778 -+ 1, &error);
36779 -+ if (!select)
36780 -+ goto error;
36781 -+ records= get_quick_record_count(join->thd, select, s->table,
36782 -+ &s->const_keys, join->row_limit);
36783 -+ s->quick=select->quick;
36784 -+ s->needed_reg=select->needed_reg;
36785 -+ select->quick=0;
36786 -+ if (records == 0 && s->table->reginfo.impossible_range)
36787 -+ {
36788 -+ /*
36789 -+ Impossible WHERE or ON expression
36790 -+ In case of ON, we mark that the we match one empty NULL row.
36791 -+ In case of WHERE, don't set found_const_table_map to get the
36792 -+ caller to abort with a zero row result.
36793 -+ */
36794 -+ join->const_table_map|= s->table->map;
36795 -+ set_position(join,const_count++,s,(KEYUSE*) 0);
36796 -+ s->type= JT_CONST;
36797 -+ if (*s->on_expr_ref)
36798 -+ {
36799 -+ /* Generate empty row */
36800 -+ s->info= "Impossible ON condition";
36801 -+ found_const_table_map|= s->table->map;
36802 -+ s->type= JT_CONST;
36803 -+ mark_as_null_row(s->table); // All fields are NULL
36804 -+ }
36805 -+ }
36806 -+ if (records != HA_POS_ERROR)
36807 -+ {
36808 -+ s->found_records=records;
36809 -+ s->read_time= (ha_rows) (s->quick ? s->quick->read_time : 0.0);
36810 -+ }
36811 -+ delete select;
36812 -+ }
36813 -+ }
36814 -+
36815 -+ join->join_tab=stat;
36816 -+ join->map2table=stat_ref;
36817 -+ join->table= join->all_tables=table_vector;
36818 -+ join->const_tables=const_count;
36819 -+ join->found_const_table_map=found_const_table_map;
36820 -+
36821 -+ /* Find an optimal join order of the non-constant tables. */
36822 -+ if (join->const_tables != join->tables)
36823 -+ {
36824 -+ optimize_keyuse(join, keyuse_array);
36825 -+ if (choose_plan(join, all_table_map & ~join->const_table_map))
36826 -+ goto error;
36827 -+ }
36828 -+ else
36829 -+ {
36830 -+ memcpy((uchar*) join->best_positions,(uchar*) join->positions,
36831 -+ sizeof(POSITION)*join->const_tables);
36832 -+ join->best_read=1.0;
36833 -+ }
36834 -+ /* Generate an execution plan from the found optimal join order. */
36835 -+ DBUG_RETURN(join->thd->killed || get_best_combination(join));
36836 -+
36837 -+error:
36838 -+ /*
36839 -+ Need to clean up join_tab from TABLEs in case of error.
36840 -+ They won't get cleaned up by JOIN::cleanup() because JOIN::join_tab
36841 -+ may not be assigned yet by this function (which is building join_tab).
36842 -+ Dangling TABLE::reginfo.join_tab may cause part_of_refkey to choke.
36843 -+ */
36844 -+ for (tables= tables_arg; tables; tables= tables->next_leaf)
36845 -+ tables->table->reginfo.join_tab= NULL;
36846 -+ DBUG_RETURN (1);
36847 -+}
36848 -+
36849 -+
36850 -+/*****************************************************************************
36851 -+ Check with keys are used and with tables references with tables
36852 -+ Updates in stat:
36853 -+ keys Bitmap of all used keys
36854 -+ const_keys Bitmap of all keys with may be used with quick_select
36855 -+ keyuse Pointer to possible keys
36856 -+*****************************************************************************/
36857 -+
36858 -+/// Used when finding key fields
36859 -+typedef struct key_field_t {
36860 -+ Field *field;
36861 -+ Item *val; ///< May be empty if diff constant
36862 -+ uint level;
36863 -+ uint optimize;
36864 -+ bool eq_func;
36865 -+ /**
36866 -+ If true, the condition this struct represents will not be satisfied
36867 -+ when val IS NULL.
36868 -+ */
36869 -+ bool null_rejecting;
36870 -+ bool *cond_guard; /* See KEYUSE::cond_guard */
36871 -+} KEY_FIELD;
36872 -+
36873 -+/* Values in optimize */
36874 -+#define KEY_OPTIMIZE_EXISTS 1
36875 -+#define KEY_OPTIMIZE_REF_OR_NULL 2
36876 -+
36877 -+/**
36878 -+ Merge new key definitions to old ones, remove those not used in both.
36879 -+
36880 -+ This is called for OR between different levels.
36881 -+
36882 -+ To be able to do 'ref_or_null' we merge a comparison of a column
36883 -+ and 'column IS NULL' to one test. This is useful for sub select queries
36884 -+ that are internally transformed to something like:.
36885 -+
36886 -+ @code
36887 -+ SELECT * FROM t1 WHERE t1.key=outer_ref_field or t1.key IS NULL
36888 -+ @endcode
36889 -+
36890 -+ KEY_FIELD::null_rejecting is processed as follows: @n
36891 -+ result has null_rejecting=true if it is set for both ORed references.
36892 -+ for example:
36893 -+ - (t2.key = t1.field OR t2.key = t1.field) -> null_rejecting=true
36894 -+ - (t2.key = t1.field OR t2.key <=> t1.field) -> null_rejecting=false
36895 -+
36896 -+ @todo
36897 -+ The result of this is that we're missing some 'ref' accesses.
36898 -+ OptimizerTeam: Fix this
36899 -+*/
36900 -+
36901 -+static KEY_FIELD *
36902 -+merge_key_fields(KEY_FIELD *start,KEY_FIELD *new_fields,KEY_FIELD *end,
36903 -+ uint and_level)
36904 -+{
36905 -+ if (start == new_fields)
36906 -+ return start; // Impossible or
36907 -+ if (new_fields == end)
36908 -+ return start; // No new fields, skip all
36909 -+
36910 -+ KEY_FIELD *first_free=new_fields;
36911 -+
36912 -+ /* Mark all found fields in old array */
36913 -+ for (; new_fields != end ; new_fields++)
36914 -+ {
36915 -+ for (KEY_FIELD *old=start ; old != first_free ; old++)
36916 -+ {
36917 -+ if (old->field == new_fields->field)
36918 -+ {
36919 -+ /*
36920 -+ NOTE: below const_item() call really works as "!used_tables()", i.e.
36921 -+ it can return FALSE where it is feasible to make it return TRUE.
36922 -+
36923 -+ The cause is as follows: Some of the tables are already known to be
36924 -+ const tables (the detection code is in make_join_statistics(),
36925 -+ above the update_ref_and_keys() call), but we didn't propagate
36926 -+ information about this: TABLE::const_table is not set to TRUE, and
36927 -+ Item::update_used_tables() hasn't been called for each item.
36928 -+ The result of this is that we're missing some 'ref' accesses.
36929 -+ TODO: OptimizerTeam: Fix this
36930 -+ */
36931 -+ if (!new_fields->val->const_item())
36932 -+ {
36933 -+ /*
36934 -+ If the value matches, we can use the key reference.
36935 -+ If not, we keep it until we have examined all new values
36936 -+ */
36937 -+ if (old->val->eq(new_fields->val, old->field->binary()))
36938 -+ {
36939 -+ old->level= and_level;
36940 -+ old->optimize= ((old->optimize & new_fields->optimize &
36941 -+ KEY_OPTIMIZE_EXISTS) |
36942 -+ ((old->optimize | new_fields->optimize) &
36943 -+ KEY_OPTIMIZE_REF_OR_NULL));
36944 -+ old->null_rejecting= (old->null_rejecting &&
36945 -+ new_fields->null_rejecting);
36946 -+ }
36947 -+ }
36948 -+ else if (old->eq_func && new_fields->eq_func &&
36949 -+ old->val->eq_by_collation(new_fields->val,
36950 -+ old->field->binary(),
36951 -+ old->field->charset()))
36952 -+
36953 -+ {
36954 -+ old->level= and_level;
36955 -+ old->optimize= ((old->optimize & new_fields->optimize &
36956 -+ KEY_OPTIMIZE_EXISTS) |
36957 -+ ((old->optimize | new_fields->optimize) &
36958 -+ KEY_OPTIMIZE_REF_OR_NULL));
36959 -+ old->null_rejecting= (old->null_rejecting &&
36960 -+ new_fields->null_rejecting);
36961 -+ }
36962 -+ else if (old->eq_func && new_fields->eq_func &&
36963 -+ ((old->val->const_item() && old->val->is_null()) ||
36964 -+ new_fields->val->is_null()))
36965 -+ {
36966 -+ /* field = expression OR field IS NULL */
36967 -+ old->level= and_level;
36968 -+ old->optimize= KEY_OPTIMIZE_REF_OR_NULL;
36969 -+ /*
36970 -+ Remember the NOT NULL value unless the value does not depend
36971 -+ on other tables.
36972 -+ */
36973 -+ if (!old->val->used_tables() && old->val->is_null())
36974 -+ old->val= new_fields->val;
36975 -+ /* The referred expression can be NULL: */
36976 -+ old->null_rejecting= 0;
36977 -+ }
36978 -+ else
36979 -+ {
36980 -+ /*
36981 -+ We are comparing two different const. In this case we can't
36982 -+ use a key-lookup on this so it's better to remove the value
36983 -+ and let the range optimzier handle it
36984 -+ */
36985 -+ if (old == --first_free) // If last item
36986 -+ break;
36987 -+ *old= *first_free; // Remove old value
36988 -+ old--; // Retry this value
36989 -+ }
36990 -+ }
36991 -+ }
36992 -+ }
36993 -+ /* Remove all not used items */
36994 -+ for (KEY_FIELD *old=start ; old != first_free ;)
36995 -+ {
36996 -+ if (old->level != and_level)
36997 -+ { // Not used in all levels
36998 -+ if (old == --first_free)
36999 -+ break;
37000 -+ *old= *first_free; // Remove old value
37001 -+ continue;
37002 -+ }
37003 -+ old++;
37004 -+ }
37005 -+ return first_free;
37006 -+}
37007 -+
37008 -+
37009 -+/**
37010 -+ Add a possible key to array of possible keys if it's usable as a key
37011 -+
37012 -+ @param key_fields Pointer to add key, if usable
37013 -+ @param and_level And level, to be stored in KEY_FIELD
37014 -+ @param cond Condition predicate
37015 -+ @param field Field used in comparision
37016 -+ @param eq_func True if we used =, <=> or IS NULL
37017 -+ @param value Value used for comparison with field
37018 -+ @param usable_tables Tables which can be used for key optimization
37019 -+ @param sargables IN/OUT Array of found sargable candidates
37020 -+
37021 -+ @note
37022 -+ If we are doing a NOT NULL comparison on a NOT NULL field in a outer join
37023 -+ table, we store this to be able to do not exists optimization later.
37024 -+
37025 -+ @returns
37026 -+ *key_fields is incremented if we stored a key in the array
37027 -+*/
37028 -+
37029 -+static void
37030 -+add_key_field(KEY_FIELD **key_fields,uint and_level, Item_func *cond,
37031 -+ Field *field, bool eq_func, Item **value, uint num_values,
37032 -+ table_map usable_tables, SARGABLE_PARAM **sargables)
37033 -+{
37034 -+ uint exists_optimize= 0;
37035 -+ if (!(field->flags & PART_KEY_FLAG))
37036 -+ {
37037 -+ // Don't remove column IS NULL on a LEFT JOIN table
37038 -+ if (!eq_func || (*value)->type() != Item::NULL_ITEM ||
37039 -+ !field->table->maybe_null || field->null_ptr)
37040 -+ return; // Not a key. Skip it
37041 -+ exists_optimize= KEY_OPTIMIZE_EXISTS;
37042 -+ DBUG_ASSERT(num_values == 1);
37043 -+ }
37044 -+ else
37045 -+ {
37046 -+ table_map used_tables=0;
37047 -+ bool optimizable=0;
37048 -+ for (uint i=0; i<num_values; i++)
37049 -+ {
37050 -+ used_tables|=(value[i])->used_tables();
37051 -+ if (!((value[i])->used_tables() & (field->table->map | RAND_TABLE_BIT)))
37052 -+ optimizable=1;
37053 -+ }
37054 -+ if (!optimizable)
37055 -+ return;
37056 -+ if (!(usable_tables & field->table->map))
37057 -+ {
37058 -+ if (!eq_func || (*value)->type() != Item::NULL_ITEM ||
37059 -+ !field->table->maybe_null || field->null_ptr)
37060 -+ return; // Can't use left join optimize
37061 -+ exists_optimize= KEY_OPTIMIZE_EXISTS;
37062 -+ }
37063 -+ else
37064 -+ {
37065 -+ JOIN_TAB *stat=field->table->reginfo.join_tab;
37066 -+ key_map possible_keys=field->key_start;
37067 -+ possible_keys.intersect(field->table->keys_in_use_for_query);
37068 -+ stat[0].keys.merge(possible_keys); // Add possible keys
37069 -+
37070 -+ /*
37071 -+ Save the following cases:
37072 -+ Field op constant
37073 -+ Field LIKE constant where constant doesn't start with a wildcard
37074 -+ Field = field2 where field2 is in a different table
37075 -+ Field op formula
37076 -+ Field IS NULL
37077 -+ Field IS NOT NULL
37078 -+ Field BETWEEN ...
37079 -+ Field IN ...
37080 -+ */
37081 -+ stat[0].key_dependent|=used_tables;
37082 -+
37083 -+ bool is_const=1;
37084 -+ for (uint i=0; i<num_values; i++)
37085 -+ {
37086 -+ if (!(is_const&= value[i]->const_item()))
37087 -+ break;
37088 -+ }
37089 -+ if (is_const)
37090 -+ stat[0].const_keys.merge(possible_keys);
37091 -+ else if (!eq_func)
37092 -+ {
37093 -+ /*
37094 -+ Save info to be able check whether this predicate can be
37095 -+ considered as sargable for range analisis after reading const tables.
37096 -+ We do not save info about equalities as update_const_equal_items
37097 -+ will take care of updating info on keys from sargable equalities.
37098 -+ */
37099 -+ (*sargables)--;
37100 -+ (*sargables)->field= field;
37101 -+ (*sargables)->arg_value= value;
37102 -+ (*sargables)->num_values= num_values;
37103 -+ }
37104 -+ /*
37105 -+ We can't always use indexes when comparing a string index to a
37106 -+ number. cmp_type() is checked to allow compare of dates to numbers.
37107 -+ eq_func is NEVER true when num_values > 1
37108 -+ */
37109 -+ if (!eq_func)
37110 -+ return;
37111 -+ if (field->result_type() == STRING_RESULT)
37112 -+ {
37113 -+ if ((*value)->result_type() != STRING_RESULT)
37114 -+ {
37115 -+ if (field->cmp_type() != (*value)->result_type())
37116 -+ return;
37117 -+ }
37118 -+ else
37119 -+ {
37120 -+ /*
37121 -+ We can't use indexes if the effective collation
37122 -+ of the operation differ from the field collation.
37123 -+ */
37124 -+ if (field->cmp_type() == STRING_RESULT &&
37125 -+ ((Field_str*)field)->charset() != cond->compare_collation())
37126 -+ return;
37127 -+ }
37128 -+ }
37129 -+ }
37130 -+ }
37131 -+ /*
37132 -+ For the moment eq_func is always true. This slot is reserved for future
37133 -+ extensions where we want to remembers other things than just eq comparisons
37134 -+ */
37135 -+ DBUG_ASSERT(eq_func);
37136 -+ /* Store possible eq field */
37137 -+ (*key_fields)->field= field;
37138 -+ (*key_fields)->eq_func= eq_func;
37139 -+ (*key_fields)->val= *value;
37140 -+ (*key_fields)->level= and_level;
37141 -+ (*key_fields)->optimize= exists_optimize;
37142 -+ /*
37143 -+ If the condition has form "tbl.keypart = othertbl.field" and
37144 -+ othertbl.field can be NULL, there will be no matches if othertbl.field
37145 -+ has NULL value.
37146 -+ We use null_rejecting in add_not_null_conds() to add
37147 -+ 'othertbl.field IS NOT NULL' to tab->select_cond.
37148 -+ */
37149 -+ (*key_fields)->null_rejecting= ((cond->functype() == Item_func::EQ_FUNC ||
37150 -+ cond->functype() == Item_func::MULT_EQUAL_FUNC) &&
37151 -+ ((*value)->type() == Item::FIELD_ITEM) &&
37152 -+ ((Item_field*)*value)->field->maybe_null());
37153 -+ (*key_fields)->cond_guard= NULL;
37154 -+ (*key_fields)++;
37155 -+}
37156 -+
37157 -+/**
37158 -+ Add possible keys to array of possible keys originated from a simple
37159 -+ predicate.
37160 -+
37161 -+ @param key_fields Pointer to add key, if usable
37162 -+ @param and_level And level, to be stored in KEY_FIELD
37163 -+ @param cond Condition predicate
37164 -+ @param field Field used in comparision
37165 -+ @param eq_func True if we used =, <=> or IS NULL
37166 -+ @param value Value used for comparison with field
37167 -+ Is NULL for BETWEEN and IN
37168 -+ @param usable_tables Tables which can be used for key optimization
37169 -+ @param sargables IN/OUT Array of found sargable candidates
37170 -+
37171 -+ @note
37172 -+ If field items f1 and f2 belong to the same multiple equality and
37173 -+ a key is added for f1, the the same key is added for f2.
37174 -+
37175 -+ @returns
37176 -+ *key_fields is incremented if we stored a key in the array
37177 -+*/
37178 -+
37179 -+static void
37180 -+add_key_equal_fields(KEY_FIELD **key_fields, uint and_level,
37181 -+ Item_func *cond, Item_field *field_item,
37182 -+ bool eq_func, Item **val,
37183 -+ uint num_values, table_map usable_tables,
37184 -+ SARGABLE_PARAM **sargables)
37185 -+{
37186 -+ Field *field= field_item->field;
37187 -+ add_key_field(key_fields, and_level, cond, field,
37188 -+ eq_func, val, num_values, usable_tables, sargables);
37189 -+ Item_equal *item_equal= field_item->item_equal;
37190 -+ if (item_equal)
37191 -+ {
37192 -+ /*
37193 -+ Add to the set of possible key values every substitution of
37194 -+ the field for an equal field included into item_equal
37195 -+ */
37196 -+ Item_equal_iterator it(*item_equal);
37197 -+ Item_field *item;
37198 -+ while ((item= it++))
37199 -+ {
37200 -+ if (!field->eq(item->field))
37201 -+ {
37202 -+ add_key_field(key_fields, and_level, cond, item->field,
37203 -+ eq_func, val, num_values, usable_tables,
37204 -+ sargables);
37205 -+ }
37206 -+ }
37207 -+ }
37208 -+}
37209 -+
37210 -+
37211 -+/**
37212 -+ Check if an expression is a non-outer field.
37213 -+
37214 -+ Checks if an expression is a field and belongs to the current select.
37215 -+
37216 -+ @param field Item expression to check
37217 -+
37218 -+ @return boolean
37219 -+ @retval TRUE the expression is a local field
37220 -+ @retval FALSE it's something else
37221 -+*/
37222 -+
37223 -+static bool
37224 -+is_local_field (Item *field)
37225 -+{
37226 -+ return field->real_item()->type() == Item::FIELD_ITEM
37227 -+ && !(field->used_tables() & OUTER_REF_TABLE_BIT)
37228 -+ && !((Item_field *)field->real_item())->depended_from;
37229 -+}
37230 -+
37231 -+
37232 -+static void
37233 -+add_key_fields(JOIN *join, KEY_FIELD **key_fields, uint *and_level,
37234 -+ COND *cond, table_map usable_tables,
37235 -+ SARGABLE_PARAM **sargables)
37236 -+{
37237 -+ if (cond->type() == Item_func::COND_ITEM)
37238 -+ {
37239 -+ List_iterator_fast<Item> li(*((Item_cond*) cond)->argument_list());
37240 -+ KEY_FIELD *org_key_fields= *key_fields;
37241 -+
37242 -+ if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
37243 -+ {
37244 -+ Item *item;
37245 -+ while ((item=li++))
37246 -+ add_key_fields(join, key_fields, and_level, item, usable_tables,
37247 -+ sargables);
37248 -+ for (; org_key_fields != *key_fields ; org_key_fields++)
37249 -+ org_key_fields->level= *and_level;
37250 -+ }
37251 -+ else
37252 -+ {
37253 -+ (*and_level)++;
37254 -+ add_key_fields(join, key_fields, and_level, li++, usable_tables,
37255 -+ sargables);
37256 -+ Item *item;
37257 -+ while ((item=li++))
37258 -+ {
37259 -+ KEY_FIELD *start_key_fields= *key_fields;
37260 -+ (*and_level)++;
37261 -+ add_key_fields(join, key_fields, and_level, item, usable_tables,
37262 -+ sargables);
37263 -+ *key_fields=merge_key_fields(org_key_fields,start_key_fields,
37264 -+ *key_fields,++(*and_level));
37265 -+ }
37266 -+ }
37267 -+ return;
37268 -+ }
37269 -+
37270 -+ /*
37271 -+ Subquery optimization: Conditions that are pushed down into subqueries
37272 -+ are wrapped into Item_func_trig_cond. We process the wrapped condition
37273 -+ but need to set cond_guard for KEYUSE elements generated from it.
37274 -+ */
37275 -+ {
37276 -+ if (cond->type() == Item::FUNC_ITEM &&
37277 -+ ((Item_func*)cond)->functype() == Item_func::TRIG_COND_FUNC)
37278 -+ {
37279 -+ Item *cond_arg= ((Item_func*)cond)->arguments()[0];
37280 -+ if (!join->group_list && !join->order &&
37281 -+ join->unit->item &&
37282 -+ join->unit->item->substype() == Item_subselect::IN_SUBS &&
37283 -+ !join->unit->is_union())
37284 -+ {
37285 -+ KEY_FIELD *save= *key_fields;
37286 -+ add_key_fields(join, key_fields, and_level, cond_arg, usable_tables,
37287 -+ sargables);
37288 -+ // Indicate that this ref access candidate is for subquery lookup:
37289 -+ for (; save != *key_fields; save++)
37290 -+ save->cond_guard= ((Item_func_trig_cond*)cond)->get_trig_var();
37291 -+ }
37292 -+ return;
37293 -+ }
37294 -+ }
37295 -+
37296 -+ /* If item is of type 'field op field/constant' add it to key_fields */
37297 -+ if (cond->type() != Item::FUNC_ITEM)
37298 -+ return;
37299 -+ Item_func *cond_func= (Item_func*) cond;
37300 -+ switch (cond_func->select_optimize()) {
37301 -+ case Item_func::OPTIMIZE_NONE:
37302 -+ break;
37303 -+ case Item_func::OPTIMIZE_KEY:
37304 -+ {
37305 -+ Item **values;
37306 -+ /*
37307 -+ Build list of possible keys for 'a BETWEEN low AND high'.
37308 -+ It is handled similar to the equivalent condition
37309 -+ 'a >= low AND a <= high':
37310 -+ */
37311 -+ if (cond_func->functype() == Item_func::BETWEEN)
37312 -+ {
37313 -+ Item_field *field_item;
37314 -+ bool equal_func= FALSE;
37315 -+ uint num_values= 2;
37316 -+ values= cond_func->arguments();
37317 -+
37318 -+ bool binary_cmp= (values[0]->real_item()->type() == Item::FIELD_ITEM)
37319 -+ ? ((Item_field*)values[0]->real_item())->field->binary()
37320 -+ : TRUE;
37321 -+
37322 -+ /*
37323 -+ Additional optimization: If 'low = high':
37324 -+ Handle as if the condition was "t.key = low".
37325 -+ */
37326 -+ if (!((Item_func_between*)cond_func)->negated &&
37327 -+ values[1]->eq(values[2], binary_cmp))
37328 -+ {
37329 -+ equal_func= TRUE;
37330 -+ num_values= 1;
37331 -+ }
37332 -+
37333 -+ /*
37334 -+ Append keys for 'field <cmp> value[]' if the
37335 -+ condition is of the form::
37336 -+ '<field> BETWEEN value[1] AND value[2]'
37337 -+ */
37338 -+ if (is_local_field (values[0]))
37339 -+ {
37340 -+ field_item= (Item_field *) (values[0]->real_item());
37341 -+ add_key_equal_fields(key_fields, *and_level, cond_func,
37342 -+ field_item, equal_func, &values[1],
37343 -+ num_values, usable_tables, sargables);
37344 -+ }
37345 -+ /*
37346 -+ Append keys for 'value[0] <cmp> field' if the
37347 -+ condition is of the form:
37348 -+ 'value[0] BETWEEN field1 AND field2'
37349 -+ */
37350 -+ for (uint i= 1; i <= num_values; i++)
37351 -+ {
37352 -+ if (is_local_field (values[i]))
37353 -+ {
37354 -+ field_item= (Item_field *) (values[i]->real_item());
37355 -+ add_key_equal_fields(key_fields, *and_level, cond_func,
37356 -+ field_item, equal_func, values,
37357 -+ 1, usable_tables, sargables);
37358 -+ }
37359 -+ }
37360 -+ } // if ( ... Item_func::BETWEEN)
37361 -+
37362 -+ // IN, NE
37363 -+ else if (is_local_field (cond_func->key_item()) &&
37364 -+ !(cond_func->used_tables() & OUTER_REF_TABLE_BIT))
37365 -+ {
37366 -+ values= cond_func->arguments()+1;
37367 -+ if (cond_func->functype() == Item_func::NE_FUNC &&
37368 -+ is_local_field (cond_func->arguments()[1]))
37369 -+ values--;
37370 -+ DBUG_ASSERT(cond_func->functype() != Item_func::IN_FUNC ||
37371 -+ cond_func->argument_count() != 2);
37372 -+ add_key_equal_fields(key_fields, *and_level, cond_func,
37373 -+ (Item_field*) (cond_func->key_item()->real_item()),
37374 -+ 0, values,
37375 -+ cond_func->argument_count()-1,
37376 -+ usable_tables, sargables);
37377 -+ }
37378 -+ break;
37379 -+ }
37380 -+ case Item_func::OPTIMIZE_OP:
37381 -+ {
37382 -+ bool equal_func=(cond_func->functype() == Item_func::EQ_FUNC ||
37383 -+ cond_func->functype() == Item_func::EQUAL_FUNC);
37384 -+
37385 -+ if (is_local_field (cond_func->arguments()[0]))
37386 -+ {
37387 -+ add_key_equal_fields(key_fields, *and_level, cond_func,
37388 -+ (Item_field*) (cond_func->arguments()[0])->real_item(),
37389 -+ equal_func,
37390 -+ cond_func->arguments()+1, 1, usable_tables,
37391 -+ sargables);
37392 -+ }
37393 -+ if (is_local_field (cond_func->arguments()[1]) &&
37394 -+ cond_func->functype() != Item_func::LIKE_FUNC)
37395 -+ {
37396 -+ add_key_equal_fields(key_fields, *and_level, cond_func,
37397 -+ (Item_field*) (cond_func->arguments()[1])->real_item(),
37398 -+ equal_func,
37399 -+ cond_func->arguments(),1,usable_tables,
37400 -+ sargables);
37401 -+ }
37402 -+ break;
37403 -+ }
37404 -+ case Item_func::OPTIMIZE_NULL:
37405 -+ /* column_name IS [NOT] NULL */
37406 -+ if (is_local_field (cond_func->arguments()[0]) &&
37407 -+ !(cond_func->used_tables() & OUTER_REF_TABLE_BIT))
37408 -+ {
37409 -+ Item *tmp=new Item_null;
37410 -+ if (unlikely(!tmp)) // Should never be true
37411 -+ return;
37412 -+ add_key_equal_fields(key_fields, *and_level, cond_func,
37413 -+ (Item_field*) (cond_func->arguments()[0])->real_item(),
37414 -+ cond_func->functype() == Item_func::ISNULL_FUNC,
37415 -+ &tmp, 1, usable_tables, sargables);
37416 -+ }
37417 -+ break;
37418 -+ case Item_func::OPTIMIZE_EQUAL:
37419 -+ Item_equal *item_equal= (Item_equal *) cond;
37420 -+ Item *const_item= item_equal->get_const();
37421 -+ Item_equal_iterator it(*item_equal);
37422 -+ Item_field *item;
37423 -+ if (const_item)
37424 -+ {
37425 -+ /*
37426 -+ For each field field1 from item_equal consider the equality
37427 -+ field1=const_item as a condition allowing an index access of the table
37428 -+ with field1 by the keys value of field1.
37429 -+ */
37430 -+ while ((item= it++))
37431 -+ {
37432 -+ add_key_field(key_fields, *and_level, cond_func, item->field,
37433 -+ TRUE, &const_item, 1, usable_tables, sargables);
37434 -+ }
37435 -+ }
37436 -+ else
37437 -+ {
37438 -+ /*
37439 -+ Consider all pairs of different fields included into item_equal.
37440 -+ For each of them (field1, field1) consider the equality
37441 -+ field1=field2 as a condition allowing an index access of the table
37442 -+ with field1 by the keys value of field2.
37443 -+ */
37444 -+ Item_equal_iterator fi(*item_equal);
37445 -+ while ((item= fi++))
37446 -+ {
37447 -+ Field *field= item->field;
37448 -+ while ((item= it++))
37449 -+ {
37450 -+ if (!field->eq(item->field))
37451 -+ {
37452 -+ add_key_field(key_fields, *and_level, cond_func, field,
37453 -+ TRUE, (Item **) &item, 1, usable_tables,
37454 -+ sargables);
37455 -+ }
37456 -+ }
37457 -+ it.rewind();
37458 -+ }
37459 -+ }
37460 -+ break;
37461 -+ }
37462 -+}
37463 -+
37464 -+
37465 -+static uint
37466 -+max_part_bit(key_part_map bits)
37467 -+{
37468 -+ uint found;
37469 -+ for (found=0; bits & 1 ; found++,bits>>=1) ;
37470 -+ return found;
37471 -+}
37472 -+
37473 -+/*
37474 -+ Add all keys with uses 'field' for some keypart
37475 -+ If field->and_level != and_level then only mark key_part as const_part
37476 -+
37477 -+ RETURN
37478 -+ 0 - OK
37479 -+ 1 - Out of memory.
37480 -+*/
37481 -+
37482 -+static bool
37483 -+add_key_part(DYNAMIC_ARRAY *keyuse_array,KEY_FIELD *key_field)
37484 -+{
37485 -+ Field *field=key_field->field;
37486 -+ TABLE *form= field->table;
37487 -+ KEYUSE keyuse;
37488 -+
37489 -+ if (key_field->eq_func && !(key_field->optimize & KEY_OPTIMIZE_EXISTS))
37490 -+ {
37491 -+ for (uint key=0 ; key < form->s->keys ; key++)
37492 -+ {
37493 -+ if (!(form->keys_in_use_for_query.is_set(key)))
37494 -+ continue;
37495 -+ if (form->key_info[key].flags & (HA_FULLTEXT | HA_SPATIAL))
37496 -+ continue; // ToDo: ft-keys in non-ft queries. SerG
37497 -+
37498 -+ uint key_parts= (uint) form->key_info[key].key_parts;
37499 -+ for (uint part=0 ; part < key_parts ; part++)
37500 -+ {
37501 -+ if (field->eq(form->key_info[key].key_part[part].field))
37502 -+ {
37503 -+ keyuse.table= field->table;
37504 -+ keyuse.val = key_field->val;
37505 -+ keyuse.key = key;
37506 -+ keyuse.keypart=part;
37507 -+ keyuse.keypart_map= (key_part_map) 1 << part;
37508 -+ keyuse.used_tables=key_field->val->used_tables();
37509 -+ keyuse.optimize= key_field->optimize & KEY_OPTIMIZE_REF_OR_NULL;
37510 -+ keyuse.null_rejecting= key_field->null_rejecting;
37511 -+ keyuse.cond_guard= key_field->cond_guard;
37512 -+ if (insert_dynamic(keyuse_array,(uchar*) &keyuse))
37513 -+ return TRUE;
37514 -+ }
37515 -+ }
37516 -+ }
37517 -+ }
37518 -+ return FALSE;
37519 -+}
37520 -+
37521 -+
37522 -+#define FT_KEYPART (MAX_REF_PARTS+10)
37523 -+
37524 -+static bool
37525 -+add_ft_keys(DYNAMIC_ARRAY *keyuse_array,
37526 -+ JOIN_TAB *stat,COND *cond,table_map usable_tables)
37527 -+{
37528 -+ Item_func_match *cond_func=NULL;
37529 -+
37530 -+ if (!cond)
37531 -+ return FALSE;
37532 -+
37533 -+ if (cond->type() == Item::FUNC_ITEM)
37534 -+ {
37535 -+ Item_func *func=(Item_func *)cond;
37536 -+ Item_func::Functype functype= func->functype();
37537 -+ if (functype == Item_func::FT_FUNC)
37538 -+ cond_func=(Item_func_match *)cond;
37539 -+ else if (func->arg_count == 2)
37540 -+ {
37541 -+ Item *arg0= func->arguments()[0],
37542 -+ *arg1= func->arguments()[1];
37543 -+ if (arg1->const_item() && arg1->cols() == 1 &&
37544 -+ ((functype == Item_func::GE_FUNC && arg1->val_real() > 0) ||
37545 -+ (functype == Item_func::GT_FUNC && arg1->val_real() >= 0)) &&
37546 -+ arg0->type() == Item::FUNC_ITEM &&
37547 -+ ((Item_func *) arg0)->functype() == Item_func::FT_FUNC)
37548 -+ cond_func= (Item_func_match *) arg0;
37549 -+ else if (arg0->const_item() && arg0->cols() == 1 &&
37550 -+ ((functype == Item_func::LE_FUNC && arg0->val_real() > 0) ||
37551 -+ (functype == Item_func::LT_FUNC && arg0->val_real() >= 0)) &&
37552 -+ arg1->type() == Item::FUNC_ITEM &&
37553 -+ ((Item_func *) arg1)->functype() == Item_func::FT_FUNC)
37554 -+ cond_func= (Item_func_match *) arg1;
37555 -+ }
37556 -+ }
37557 -+ else if (cond->type() == Item::COND_ITEM)
37558 -+ {
37559 -+ List_iterator_fast<Item> li(*((Item_cond*) cond)->argument_list());
37560 -+
37561 -+ if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
37562 -+ {
37563 -+ Item *item;
37564 -+ while ((item=li++))
37565 -+ {
37566 -+ if (add_ft_keys(keyuse_array,stat,item,usable_tables))
37567 -+ return TRUE;
37568 -+ }
37569 -+ }
37570 -+ }
37571 -+
37572 -+ if (!cond_func || cond_func->key == NO_SUCH_KEY ||
37573 -+ !(usable_tables & cond_func->table->map))
37574 -+ return FALSE;
37575 -+
37576 -+ KEYUSE keyuse;
37577 -+ keyuse.table= cond_func->table;
37578 -+ keyuse.val = cond_func;
37579 -+ keyuse.key = cond_func->key;
37580 -+ keyuse.keypart= FT_KEYPART;
37581 -+ keyuse.used_tables=cond_func->key_item()->used_tables();
37582 -+ keyuse.optimize= 0;
37583 -+ keyuse.keypart_map= 0;
37584 -+ return insert_dynamic(keyuse_array,(uchar*) &keyuse);
37585 -+}
37586 -+
37587 -+
37588 -+static int
37589 -+sort_keyuse(KEYUSE *a,KEYUSE *b)
37590 -+{
37591 -+ int res;
37592 -+ if (a->table->tablenr != b->table->tablenr)
37593 -+ return (int) (a->table->tablenr - b->table->tablenr);
37594 -+ if (a->key != b->key)
37595 -+ return (int) (a->key - b->key);
37596 -+ if (a->keypart != b->keypart)
37597 -+ return (int) (a->keypart - b->keypart);
37598 -+ // Place const values before other ones
37599 -+ if ((res= test((a->used_tables & ~OUTER_REF_TABLE_BIT)) -
37600 -+ test((b->used_tables & ~OUTER_REF_TABLE_BIT))))
37601 -+ return res;
37602 -+ /* Place rows that are not 'OPTIMIZE_REF_OR_NULL' first */
37603 -+ return (int) ((a->optimize & KEY_OPTIMIZE_REF_OR_NULL) -
37604 -+ (b->optimize & KEY_OPTIMIZE_REF_OR_NULL));
37605 -+}
37606 -+
37607 -+
37608 -+/*
37609 -+ Add to KEY_FIELD array all 'ref' access candidates within nested join.
37610 -+
37611 -+ This function populates KEY_FIELD array with entries generated from the
37612 -+ ON condition of the given nested join, and does the same for nested joins
37613 -+ contained within this nested join.
37614 -+
37615 -+ @param[in] nested_join_table Nested join pseudo-table to process
37616 -+ @param[in,out] end End of the key field array
37617 -+ @param[in,out] and_level And-level
37618 -+ @param[in,out] sargables Array of found sargable candidates
37619 -+
37620 -+
37621 -+ @note
37622 -+ We can add accesses to the tables that are direct children of this nested
37623 -+ join (1), and are not inner tables w.r.t their neighbours (2).
37624 -+
37625 -+ Example for #1 (outer brackets pair denotes nested join this function is
37626 -+ invoked for):
37627 -+ @code
37628 -+ ... LEFT JOIN (t1 LEFT JOIN (t2 ... ) ) ON cond
37629 -+ @endcode
37630 -+ Example for #2:
37631 -+ @code
37632 -+ ... LEFT JOIN (t1 LEFT JOIN t2 ) ON cond
37633 -+ @endcode
37634 -+ In examples 1-2 for condition cond, we can add 'ref' access candidates to
37635 -+ t1 only.
37636 -+ Example #3:
37637 -+ @code
37638 -+ ... LEFT JOIN (t1, t2 LEFT JOIN t3 ON inner_cond) ON cond
37639 -+ @endcode
37640 -+ Here we can add 'ref' access candidates for t1 and t2, but not for t3.
37641 -+*/
37642 -+
37643 -+static void add_key_fields_for_nj(JOIN *join, TABLE_LIST *nested_join_table,
37644 -+ KEY_FIELD **end, uint *and_level,
37645 -+ SARGABLE_PARAM **sargables)
37646 -+{
37647 -+ List_iterator<TABLE_LIST> li(nested_join_table->nested_join->join_list);
37648 -+ table_map tables= 0;
37649 -+ TABLE_LIST *table;
37650 -+ DBUG_ASSERT(nested_join_table->nested_join);
37651 -+
37652 -+ while ((table= li++))
37653 -+ {
37654 -+ if (table->nested_join)
37655 -+ add_key_fields_for_nj(join, table, end, and_level, sargables);
37656 -+ else
37657 -+ if (!table->on_expr)
37658 -+ tables |= table->table->map;
37659 -+ }
37660 -+ add_key_fields(join, end, and_level, nested_join_table->on_expr, tables,
37661 -+ sargables);
37662 -+}
37663 -+
37664 -+
37665 -+/**
37666 -+ Update keyuse array with all possible keys we can use to fetch rows.
37667 -+
37668 -+ @param thd
37669 -+ @param[out] keyuse Put here ordered array of KEYUSE structures
37670 -+ @param join_tab Array in tablenr_order
37671 -+ @param tables Number of tables in join
37672 -+ @param cond WHERE condition (note that the function analyzes
37673 -+ join_tab[i]->on_expr too)
37674 -+ @param normal_tables Tables not inner w.r.t some outer join (ones
37675 -+ for which we can make ref access based the WHERE
37676 -+ clause)
37677 -+ @param select_lex current SELECT
37678 -+ @param[out] sargables Array of found sargable candidates
37679 -+
37680 -+ @retval
37681 -+ 0 OK
37682 -+ @retval
37683 -+ 1 Out of memory.
37684 -+*/
37685 -+
37686 -+static bool
37687 -+update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
37688 -+ uint tables, COND *cond, COND_EQUAL *cond_equal,
37689 -+ table_map normal_tables, SELECT_LEX *select_lex,
37690 -+ SARGABLE_PARAM **sargables)
37691 -+{
37692 -+ uint and_level,i,found_eq_constant;
37693 -+ KEY_FIELD *key_fields, *end, *field;
37694 -+ uint sz;
37695 -+ uint m= max(select_lex->max_equal_elems,1);
37696 -+
37697 -+ /*
37698 -+ We use the same piece of memory to store both KEY_FIELD
37699 -+ and SARGABLE_PARAM structure.
37700 -+ KEY_FIELD values are placed at the beginning this memory
37701 -+ while SARGABLE_PARAM values are put at the end.
37702 -+ All predicates that are used to fill arrays of KEY_FIELD
37703 -+ and SARGABLE_PARAM structures have at most 2 arguments
37704 -+ except BETWEEN predicates that have 3 arguments and
37705 -+ IN predicates.
37706 -+ This any predicate if it's not BETWEEN/IN can be used
37707 -+ directly to fill at most 2 array elements, either of KEY_FIELD
37708 -+ or SARGABLE_PARAM type. For a BETWEEN predicate 3 elements
37709 -+ can be filled as this predicate is considered as
37710 -+ saragable with respect to each of its argument.
37711 -+ An IN predicate can require at most 1 element as currently
37712 -+ it is considered as sargable only for its first argument.
37713 -+ Multiple equality can add elements that are filled after
37714 -+ substitution of field arguments by equal fields. There
37715 -+ can be not more than select_lex->max_equal_elems such
37716 -+ substitutions.
37717 -+ */
37718 -+ sz= max(sizeof(KEY_FIELD),sizeof(SARGABLE_PARAM))*
37719 -+ (((thd->lex->current_select->cond_count+1)*2 +
37720 -+ thd->lex->current_select->between_count)*m+1);
37721 -+ if (!(key_fields=(KEY_FIELD*) thd->alloc(sz)))
37722 -+ return TRUE; /* purecov: inspected */
37723 -+ and_level= 0;
37724 -+ field= end= key_fields;
37725 -+ *sargables= (SARGABLE_PARAM *) key_fields +
37726 -+ (sz - sizeof((*sargables)[0].field))/sizeof(SARGABLE_PARAM);
37727 -+ /* set a barrier for the array of SARGABLE_PARAM */
37728 -+ (*sargables)[0].field= 0;
37729 -+
37730 -+ if (my_init_dynamic_array(keyuse,sizeof(KEYUSE),20,64))
37731 -+ return TRUE;
37732 -+ if (cond)
37733 -+ {
37734 -+ add_key_fields(join_tab->join, &end, &and_level, cond, normal_tables,
37735 -+ sargables);
37736 -+ for (; field != end ; field++)
37737 -+ {
37738 -+ if (add_key_part(keyuse,field))
37739 -+ return TRUE;
37740 -+ /* Mark that we can optimize LEFT JOIN */
37741 -+ if (field->val->type() == Item::NULL_ITEM &&
37742 -+ !field->field->real_maybe_null())
37743 -+ field->field->table->reginfo.not_exists_optimize=1;
37744 -+ }
37745 -+ }
37746 -+ for (i=0 ; i < tables ; i++)
37747 -+ {
37748 -+ /*
37749 -+ Block the creation of keys for inner tables of outer joins.
37750 -+ Here only the outer joins that can not be converted to
37751 -+ inner joins are left and all nests that can be eliminated
37752 -+ are flattened.
37753 -+ In the future when we introduce conditional accesses
37754 -+ for inner tables in outer joins these keys will be taken
37755 -+ into account as well.
37756 -+ */
37757 -+ if (*join_tab[i].on_expr_ref)
37758 -+ add_key_fields(join_tab->join, &end, &and_level,
37759 -+ *join_tab[i].on_expr_ref,
37760 -+ join_tab[i].table->map, sargables);
37761 -+ }
37762 -+
37763 -+ /* Process ON conditions for the nested joins */
37764 -+ {
37765 -+ List_iterator<TABLE_LIST> li(*join_tab->join->join_list);
37766 -+ TABLE_LIST *table;
37767 -+ while ((table= li++))
37768 -+ {
37769 -+ if (table->nested_join)
37770 -+ add_key_fields_for_nj(join_tab->join, table, &end, &and_level,
37771 -+ sargables);
37772 -+ }
37773 -+ }
37774 -+
37775 -+ /* fill keyuse with found key parts */
37776 -+ for ( ; field != end ; field++)
37777 -+ {
37778 -+ if (add_key_part(keyuse,field))
37779 -+ return TRUE;
37780 -+ }
37781 -+
37782 -+ if (select_lex->ftfunc_list->elements)
37783 -+ {
37784 -+ if (add_ft_keys(keyuse,join_tab,cond,normal_tables))
37785 -+ return TRUE;
37786 -+ }
37787 -+
37788 -+ /*
37789 -+ Sort the array of possible keys and remove the following key parts:
37790 -+ - ref if there is a keypart which is a ref and a const.
37791 -+ (e.g. if there is a key(a,b) and the clause is a=3 and b=7 and b=t2.d,
37792 -+ then we skip the key part corresponding to b=t2.d)
37793 -+ - keyparts without previous keyparts
37794 -+ (e.g. if there is a key(a,b,c) but only b < 5 (or a=2 and c < 3) is
37795 -+ used in the query, we drop the partial key parts from consideration).
37796 -+ Special treatment for ft-keys.
37797 -+ */
37798 -+ if (keyuse->elements)
37799 -+ {
37800 -+ KEYUSE key_end,*prev,*save_pos,*use;
37801 -+
37802 -+ my_qsort(keyuse->buffer,keyuse->elements,sizeof(KEYUSE),
37803 -+ (qsort_cmp) sort_keyuse);
37804 -+
37805 -+ bzero((char*) &key_end,sizeof(key_end)); /* Add for easy testing */
37806 -+ if (insert_dynamic(keyuse,(uchar*) &key_end))
37807 -+ return TRUE;
37808 -+
37809 -+ use=save_pos=dynamic_element(keyuse,0,KEYUSE*);
37810 -+ prev= &key_end;
37811 -+ found_eq_constant=0;
37812 -+ for (i=0 ; i < keyuse->elements-1 ; i++,use++)
37813 -+ {
37814 -+ if (!use->used_tables && use->optimize != KEY_OPTIMIZE_REF_OR_NULL)
37815 -+ use->table->const_key_parts[use->key]|= use->keypart_map;
37816 -+ if (use->keypart != FT_KEYPART)
37817 -+ {
37818 -+ if (use->key == prev->key && use->table == prev->table)
37819 -+ {
37820 -+ if (prev->keypart+1 < use->keypart ||
37821 -+ (prev->keypart == use->keypart && found_eq_constant))
37822 -+ continue; /* remove */
37823 -+ }
37824 -+ else if (use->keypart != 0) // First found must be 0
37825 -+ continue;
37826 -+ }
37827 -+
37828 -+#if defined(__GNUC__) && !MY_GNUC_PREREQ(4,4)
37829 -+ /*
37830 -+ Old gcc used a memcpy(), which is undefined if save_pos==use:
37831 -+ http://gcc.gnu.org/bugzilla/show_bug.cgi?id=19410
37832 -+ http://gcc.gnu.org/bugzilla/show_bug.cgi?id=39480
37833 -+ */
37834 -+ if (save_pos != use)
37835 -+#endif
37836 -+ *save_pos= *use;
37837 -+ prev=use;
37838 -+ found_eq_constant= !use->used_tables;
37839 -+ /* Save ptr to first use */
37840 -+ if (!use->table->reginfo.join_tab->keyuse)
37841 -+ use->table->reginfo.join_tab->keyuse=save_pos;
37842 -+ use->table->reginfo.join_tab->checked_keys.set_bit(use->key);
37843 -+ save_pos++;
37844 -+ }
37845 -+ i=(uint) (save_pos-(KEYUSE*) keyuse->buffer);
37846 -+ VOID(set_dynamic(keyuse,(uchar*) &key_end,i));
37847 -+ keyuse->elements=i;
37848 -+ }
37849 -+ return FALSE;
37850 -+}
37851 -+
37852 -+/**
37853 -+ Update some values in keyuse for faster choose_plan() loop.
37854 -+*/
37855 -+
37856 -+static void optimize_keyuse(JOIN *join, DYNAMIC_ARRAY *keyuse_array)
37857 -+{
37858 -+ KEYUSE *end,*keyuse= dynamic_element(keyuse_array, 0, KEYUSE*);
37859 -+
37860 -+ for (end= keyuse+ keyuse_array->elements ; keyuse < end ; keyuse++)
37861 -+ {
37862 -+ table_map map;
37863 -+ /*
37864 -+ If we find a ref, assume this table matches a proportional
37865 -+ part of this table.
37866 -+ For example 100 records matching a table with 5000 records
37867 -+ gives 5000/100 = 50 records per key
37868 -+ Constant tables are ignored.
37869 -+ To avoid bad matches, we don't make ref_table_rows less than 100.
37870 -+ */
37871 -+ keyuse->ref_table_rows= ~(ha_rows) 0; // If no ref
37872 -+ if (keyuse->used_tables &
37873 -+ (map= (keyuse->used_tables & ~join->const_table_map &
37874 -+ ~OUTER_REF_TABLE_BIT)))
37875 -+ {
37876 -+ uint tablenr;
37877 -+ for (tablenr=0 ; ! (map & 1) ; map>>=1, tablenr++) ;
37878 -+ if (map == 1) // Only one table
37879 -+ {
37880 -+ TABLE *tmp_table=join->all_tables[tablenr];
37881 -+ keyuse->ref_table_rows= max(tmp_table->file->stats.records, 100);
37882 -+ }
37883 -+ }
37884 -+ /*
37885 -+ Outer reference (external field) is constant for single executing
37886 -+ of subquery
37887 -+ */
37888 -+ if (keyuse->used_tables == OUTER_REF_TABLE_BIT)
37889 -+ keyuse->ref_table_rows= 1;
37890 -+ }
37891 -+}
37892 -+
37893 -+
37894 -+/**
37895 -+ Discover the indexes that can be used for GROUP BY or DISTINCT queries.
37896 -+
37897 -+ If the query has a GROUP BY clause, find all indexes that contain all
37898 -+ GROUP BY fields, and add those indexes to join->const_keys.
37899 -+
37900 -+ If the query has a DISTINCT clause, find all indexes that contain all
37901 -+ SELECT fields, and add those indexes to join->const_keys.
37902 -+ This allows later on such queries to be processed by a
37903 -+ QUICK_GROUP_MIN_MAX_SELECT.
37904 -+
37905 -+ @param join
37906 -+ @param join_tab
37907 -+
37908 -+ @return
37909 -+ None
37910 -+*/
37911 -+
37912 -+static void
37913 -+add_group_and_distinct_keys(JOIN *join, JOIN_TAB *join_tab)
37914 -+{
37915 -+ List<Item_field> indexed_fields;
37916 -+ List_iterator<Item_field> indexed_fields_it(indexed_fields);
37917 -+ ORDER *cur_group;
37918 -+ Item_field *cur_item;
37919 -+ key_map possible_keys(0);
37920 -+
37921 -+ if (join->group_list)
37922 -+ { /* Collect all query fields referenced in the GROUP clause. */
37923 -+ for (cur_group= join->group_list; cur_group; cur_group= cur_group->next)
37924 -+ (*cur_group->item)->walk(&Item::collect_item_field_processor, 0,
37925 -+ (uchar*) &indexed_fields);
37926 -+ }
37927 -+ else if (join->select_distinct)
37928 -+ { /* Collect all query fields referenced in the SELECT clause. */
37929 -+ List<Item> &select_items= join->fields_list;
37930 -+ List_iterator<Item> select_items_it(select_items);
37931 -+ Item *item;
37932 -+ while ((item= select_items_it++))
37933 -+ item->walk(&Item::collect_item_field_processor, 0,
37934 -+ (uchar*) &indexed_fields);
37935 -+ }
37936 -+ else
37937 -+ return;
37938 -+
37939 -+ if (indexed_fields.elements == 0)
37940 -+ return;
37941 -+
37942 -+ /* Intersect the keys of all group fields. */
37943 -+ cur_item= indexed_fields_it++;
37944 -+ possible_keys.merge(cur_item->field->part_of_key);
37945 -+ while ((cur_item= indexed_fields_it++))
37946 -+ {
37947 -+ possible_keys.intersect(cur_item->field->part_of_key);
37948 -+ }
37949 -+
37950 -+ if (!possible_keys.is_clear_all())
37951 -+ join_tab->const_keys.merge(possible_keys);
37952 -+}
37953 -+
37954 -+
37955 -+/*****************************************************************************
37956 -+ Go through all combinations of not marked tables and find the one
37957 -+ which uses least records
37958 -+*****************************************************************************/
37959 -+
37960 -+/** Save const tables first as used tables. */
37961 -+
37962 -+static void
37963 -+set_position(JOIN *join,uint idx,JOIN_TAB *table,KEYUSE *key)
37964 -+{
37965 -+ join->positions[idx].table= table;
37966 -+ join->positions[idx].key=key;
37967 -+ join->positions[idx].records_read=1.0; /* This is a const table */
37968 -+ join->positions[idx].ref_depend_map= 0;
37969 -+
37970 -+ /* Move the const table as down as possible in best_ref */
37971 -+ JOIN_TAB **pos=join->best_ref+idx+1;
37972 -+ JOIN_TAB *next=join->best_ref[idx];
37973 -+ for (;next != table ; pos++)
37974 -+ {
37975 -+ JOIN_TAB *tmp=pos[0];
37976 -+ pos[0]=next;
37977 -+ next=tmp;
37978 -+ }
37979 -+ join->best_ref[idx]=table;
37980 -+}
37981 -+
37982 -+
37983 -+/**
37984 -+ Find the best access path for an extension of a partial execution
37985 -+ plan and add this path to the plan.
37986 -+
37987 -+ The function finds the best access path to table 's' from the passed
37988 -+ partial plan where an access path is the general term for any means to
37989 -+ access the data in 's'. An access path may use either an index or a scan,
37990 -+ whichever is cheaper. The input partial plan is passed via the array
37991 -+ 'join->positions' of length 'idx'. The chosen access method for 's' and its
37992 -+ cost are stored in 'join->positions[idx]'.
37993 -+
37994 -+ @param join pointer to the structure providing all context info
37995 -+ for the query
37996 -+ @param s the table to be joined by the function
37997 -+ @param thd thread for the connection that submitted the query
37998 -+ @param remaining_tables set of tables not included into the partial plan yet
37999 -+ @param idx the length of the partial plan
38000 -+ @param record_count estimate for the number of records returned by the
38001 -+ partial plan
38002 -+ @param read_time the cost of the partial plan
38003 -+
38004 -+ @return
38005 -+ None
38006 -+*/
38007 -+
38008 -+static void
38009 -+best_access_path(JOIN *join,
38010 -+ JOIN_TAB *s,
38011 -+ THD *thd,
38012 -+ table_map remaining_tables,
38013 -+ uint idx,
38014 -+ double record_count,
38015 -+ double read_time)
38016 -+{
38017 -+ KEYUSE *best_key= 0;
38018 -+ uint best_max_key_part= 0;
38019 -+ my_bool found_constraint= 0;
38020 -+ double best= DBL_MAX;
38021 -+ double best_time= DBL_MAX;
38022 -+ double records= DBL_MAX;
38023 -+ table_map best_ref_depends_map= 0;
38024 -+ double tmp;
38025 -+ ha_rows rec;
38026 -+ DBUG_ENTER("best_access_path");
38027 -+
38028 -+ if (s->keyuse)
38029 -+ { /* Use key if possible */
38030 -+ TABLE *table= s->table;
38031 -+ KEYUSE *keyuse,*start_key=0;
38032 -+ double best_records= DBL_MAX;
38033 -+ uint max_key_part=0;
38034 -+
38035 -+ /* Test how we can use keys */
38036 -+ rec= s->records/MATCHING_ROWS_IN_OTHER_TABLE; // Assumed records/key
38037 -+ for (keyuse=s->keyuse ; keyuse->table == table ;)
38038 -+ {
38039 -+ key_part_map found_part= 0;
38040 -+ table_map found_ref= 0;
38041 -+ uint key= keyuse->key;
38042 -+ KEY *keyinfo= table->key_info+key;
38043 -+ bool ft_key= (keyuse->keypart == FT_KEYPART);
38044 -+ /* Bitmap of keyparts where the ref access is over 'keypart=const': */
38045 -+ key_part_map const_part= 0;
38046 -+ /* The or-null keypart in ref-or-null access: */
38047 -+ key_part_map ref_or_null_part= 0;
38048 -+
38049 -+ /* Calculate how many key segments of the current key we can use */
38050 -+ start_key= keyuse;
38051 -+
38052 -+ do /* For each keypart */
38053 -+ {
38054 -+ uint keypart= keyuse->keypart;
38055 -+ table_map best_part_found_ref= 0;
38056 -+ double best_prev_record_reads= DBL_MAX;
38057 -+
38058 -+ do /* For each way to access the keypart */
38059 -+ {
38060 -+
38061 -+ /*
38062 -+ if 1. expression doesn't refer to forward tables
38063 -+ 2. we won't get two ref-or-null's
38064 -+ */
38065 -+ if (!(remaining_tables & keyuse->used_tables) &&
38066 -+ !(ref_or_null_part && (keyuse->optimize &
38067 -+ KEY_OPTIMIZE_REF_OR_NULL)))
38068 -+ {
38069 -+ found_part|= keyuse->keypart_map;
38070 -+ if (!(keyuse->used_tables & ~join->const_table_map))
38071 -+ const_part|= keyuse->keypart_map;
38072 -+
38073 -+ double tmp2= prev_record_reads(join, idx, (found_ref |
38074 -+ keyuse->used_tables));
38075 -+ if (tmp2 < best_prev_record_reads)
38076 -+ {
38077 -+ best_part_found_ref= keyuse->used_tables & ~join->const_table_map;
38078 -+ best_prev_record_reads= tmp2;
38079 -+ }
38080 -+ if (rec > keyuse->ref_table_rows)
38081 -+ rec= keyuse->ref_table_rows;
38082 -+ /*
38083 -+ If there is one 'key_column IS NULL' expression, we can
38084 -+ use this ref_or_null optimisation of this field
38085 -+ */
38086 -+ if (keyuse->optimize & KEY_OPTIMIZE_REF_OR_NULL)
38087 -+ ref_or_null_part |= keyuse->keypart_map;
38088 -+ }
38089 -+ keyuse++;
38090 -+ } while (keyuse->table == table && keyuse->key == key &&
38091 -+ keyuse->keypart == keypart);
38092 -+ found_ref|= best_part_found_ref;
38093 -+ } while (keyuse->table == table && keyuse->key == key);
38094 -+
38095 -+ /*
38096 -+ Assume that that each key matches a proportional part of table.
38097 -+ */
38098 -+ if (!found_part && !ft_key)
38099 -+ continue; // Nothing usable found
38100 -+
38101 -+ if (rec < MATCHING_ROWS_IN_OTHER_TABLE)
38102 -+ rec= MATCHING_ROWS_IN_OTHER_TABLE; // Fix for small tables
38103 -+
38104 -+ /*
38105 -+ ft-keys require special treatment
38106 -+ */
38107 -+ if (ft_key)
38108 -+ {
38109 -+ /*
38110 -+ Really, there should be records=0.0 (yes!)
38111 -+ but 1.0 would be probably safer
38112 -+ */
38113 -+ tmp= prev_record_reads(join, idx, found_ref);
38114 -+ records= 1.0;
38115 -+ }
38116 -+ else
38117 -+ {
38118 -+ found_constraint= 1;
38119 -+ /*
38120 -+ Check if we found full key
38121 -+ */
38122 -+ if (found_part == PREV_BITS(uint,keyinfo->key_parts) &&
38123 -+ !ref_or_null_part)
38124 -+ { /* use eq key */
38125 -+ max_key_part= (uint) ~0;
38126 -+ if ((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY)) == HA_NOSAME)
38127 -+ {
38128 -+ tmp = prev_record_reads(join, idx, found_ref);
38129 -+ records=1.0;
38130 -+ }
38131 -+ else
38132 -+ {
38133 -+ if (!found_ref)
38134 -+ { /* We found a const key */
38135 -+ /*
38136 -+ ReuseRangeEstimateForRef-1:
38137 -+ We get here if we've found a ref(const) (c_i are constants):
38138 -+ "(keypart1=c1) AND ... AND (keypartN=cN)" [ref_const_cond]
38139 -+
38140 -+ If range optimizer was able to construct a "range"
38141 -+ access on this index, then its condition "quick_cond" was
38142 -+ eqivalent to ref_const_cond (*), and we can re-use E(#rows)
38143 -+ from the range optimizer.
38144 -+
38145 -+ Proof of (*): By properties of range and ref optimizers
38146 -+ quick_cond will be equal or tighther than ref_const_cond.
38147 -+ ref_const_cond already covers "smallest" possible interval -
38148 -+ a singlepoint interval over all keyparts. Therefore,
38149 -+ quick_cond is equivalent to ref_const_cond (if it was an
38150 -+ empty interval we wouldn't have got here).
38151 -+ */
38152 -+ if (table->quick_keys.is_set(key))
38153 -+ records= (double) table->quick_rows[key];
38154 -+ else
38155 -+ {
38156 -+ /* quick_range couldn't use key! */
38157 -+ records= (double) s->records/rec;
38158 -+ }
38159 -+ }
38160 -+ else
38161 -+ {
38162 -+ if (!(records=keyinfo->rec_per_key[keyinfo->key_parts-1]))
38163 -+ { /* Prefer longer keys */
38164 -+ records=
38165 -+ ((double) s->records / (double) rec *
38166 -+ (1.0 +
38167 -+ ((double) (table->s->max_key_length-keyinfo->key_length) /
38168 -+ (double) table->s->max_key_length)));
38169 -+ if (records < 2.0)
38170 -+ records=2.0; /* Can't be as good as a unique */
38171 -+ }
38172 -+ /*
38173 -+ ReuseRangeEstimateForRef-2: We get here if we could not reuse
38174 -+ E(#rows) from range optimizer. Make another try:
38175 -+
38176 -+ If range optimizer produced E(#rows) for a prefix of the ref
38177 -+ access we're considering, and that E(#rows) is lower then our
38178 -+ current estimate, make an adjustment. The criteria of when we
38179 -+ can make an adjustment is a special case of the criteria used
38180 -+ in ReuseRangeEstimateForRef-3.
38181 -+ */
38182 -+ if (table->quick_keys.is_set(key) &&
38183 -+ const_part & (1 << table->quick_key_parts[key]) &&
38184 -+ table->quick_n_ranges[key] == 1 &&
38185 -+ records > (double) table->quick_rows[key])
38186 -+ {
38187 -+ records= (double) table->quick_rows[key];
38188 -+ }
38189 -+ }
38190 -+ /* Limit the number of matched rows */
38191 -+ tmp= records;
38192 -+ set_if_smaller(tmp, (double) thd->variables.max_seeks_for_key);
38193 -+ if (table->covering_keys.is_set(key))
38194 -+ {
38195 -+ /* we can use only index tree */
38196 -+ uint keys_per_block= table->file->stats.block_size/2/
38197 -+ (keyinfo->key_length+table->file->ref_length)+1;
38198 -+ tmp= record_count*(tmp+keys_per_block-1)/keys_per_block;
38199 -+ }
38200 -+ else
38201 -+ tmp= record_count*min(tmp,s->worst_seeks);
38202 -+ }
38203 -+ }
38204 -+ else
38205 -+ {
38206 -+ /*
38207 -+ Use as much key-parts as possible and a uniq key is better
38208 -+ than a not unique key
38209 -+ Set tmp to (previous record count) * (records / combination)
38210 -+ */
38211 -+ if ((found_part & 1) &&
38212 -+ (!(table->file->index_flags(key, 0, 0) & HA_ONLY_WHOLE_INDEX) ||
38213 -+ found_part == PREV_BITS(uint,keyinfo->key_parts)))
38214 -+ {
38215 -+ max_key_part= max_part_bit(found_part);
38216 -+ /*
38217 -+ ReuseRangeEstimateForRef-3:
38218 -+ We're now considering a ref[or_null] access via
38219 -+ (t.keypart1=e1 AND ... AND t.keypartK=eK) [ OR
38220 -+ (same-as-above but with one cond replaced
38221 -+ with "t.keypart_i IS NULL")] (**)
38222 -+
38223 -+ Try re-using E(#rows) from "range" optimizer:
38224 -+ We can do so if "range" optimizer used the same intervals as
38225 -+ in (**). The intervals used by range optimizer may be not
38226 -+ available at this point (as "range" access might have choosen to
38227 -+ create quick select over another index), so we can't compare
38228 -+ them to (**). We'll make indirect judgements instead.
38229 -+ The sufficient conditions for re-use are:
38230 -+ (C1) All e_i in (**) are constants, i.e. found_ref==FALSE. (if
38231 -+ this is not satisfied we have no way to know which ranges
38232 -+ will be actually scanned by 'ref' until we execute the
38233 -+ join)
38234 -+ (C2) max #key parts in 'range' access == K == max_key_part (this
38235 -+ is apparently a necessary requirement)
38236 -+
38237 -+ We also have a property that "range optimizer produces equal or
38238 -+ tighter set of scan intervals than ref(const) optimizer". Each
38239 -+ of the intervals in (**) are "tightest possible" intervals when
38240 -+ one limits itself to using keyparts 1..K (which we do in #2).
38241 -+ From here it follows that range access used either one, or
38242 -+ both of the (I1) and (I2) intervals:
38243 -+
38244 -+ (t.keypart1=c1 AND ... AND t.keypartK=eK) (I1)
38245 -+ (same-as-above but with one cond replaced
38246 -+ with "t.keypart_i IS NULL") (I2)
38247 -+
38248 -+ The remaining part is to exclude the situation where range
38249 -+ optimizer used one interval while we're considering
38250 -+ ref-or-null and looking for estimate for two intervals. This
38251 -+ is done by last limitation:
38252 -+
38253 -+ (C3) "range optimizer used (have ref_or_null?2:1) intervals"
38254 -+ */
38255 -+ if (table->quick_keys.is_set(key) && !found_ref && //(C1)
38256 -+ table->quick_key_parts[key] == max_key_part && //(C2)
38257 -+ table->quick_n_ranges[key] == 1+test(ref_or_null_part)) //(C3)
38258 -+ {
38259 -+ tmp= records= (double) table->quick_rows[key];
38260 -+ }
38261 -+ else
38262 -+ {
38263 -+ /* Check if we have statistic about the distribution */
38264 -+ if ((records= keyinfo->rec_per_key[max_key_part-1]))
38265 -+ {
38266 -+ /*
38267 -+ Fix for the case where the index statistics is too
38268 -+ optimistic: If
38269 -+ (1) We're considering ref(const) and there is quick select
38270 -+ on the same index,
38271 -+ (2) and that quick select uses more keyparts (i.e. it will
38272 -+ scan equal/smaller interval then this ref(const))
38273 -+ (3) and E(#rows) for quick select is higher then our
38274 -+ estimate,
38275 -+ Then
38276 -+ We'll use E(#rows) from quick select.
38277 -+
38278 -+ Q: Why do we choose to use 'ref'? Won't quick select be
38279 -+ cheaper in some cases ?
38280 -+ TODO: figure this out and adjust the plan choice if needed.
38281 -+ */
38282 -+ if (!found_ref && table->quick_keys.is_set(key) && // (1)
38283 -+ table->quick_key_parts[key] > max_key_part && // (2)
38284 -+ records < (double)table->quick_rows[key]) // (3)
38285 -+ records= (double)table->quick_rows[key];
38286 -+
38287 -+ tmp= records;
38288 -+ }
38289 -+ else
38290 -+ {
38291 -+ /*
38292 -+ Assume that the first key part matches 1% of the file
38293 -+ and that the whole key matches 10 (duplicates) or 1
38294 -+ (unique) records.
38295 -+ Assume also that more key matches proportionally more
38296 -+ records
38297 -+ This gives the formula:
38298 -+ records = (x * (b-a) + a*c-b)/(c-1)
38299 -+
38300 -+ b = records matched by whole key
38301 -+ a = records matched by first key part (1% of all records?)
38302 -+ c = number of key parts in key
38303 -+ x = used key parts (1 <= x <= c)
38304 -+ */
38305 -+ double rec_per_key;
38306 -+ if (!(rec_per_key=(double)
38307 -+ keyinfo->rec_per_key[keyinfo->key_parts-1]))
38308 -+ rec_per_key=(double) s->records/rec+1;
38309 -+
38310 -+ if (!s->records)
38311 -+ tmp = 0;
38312 -+ else if (rec_per_key/(double) s->records >= 0.01)
38313 -+ tmp = rec_per_key;
38314 -+ else
38315 -+ {
38316 -+ double a=s->records*0.01;
38317 -+ if (keyinfo->key_parts > 1)
38318 -+ tmp= (max_key_part * (rec_per_key - a) +
38319 -+ a*keyinfo->key_parts - rec_per_key)/
38320 -+ (keyinfo->key_parts-1);
38321 -+ else
38322 -+ tmp= a;
38323 -+ set_if_bigger(tmp,1.0);
38324 -+ }
38325 -+ records = (ulong) tmp;
38326 -+ }
38327 -+
38328 -+ if (ref_or_null_part)
38329 -+ {
38330 -+ /* We need to do two key searches to find key */
38331 -+ tmp *= 2.0;
38332 -+ records *= 2.0;
38333 -+ }
38334 -+
38335 -+ /*
38336 -+ ReuseRangeEstimateForRef-4: We get here if we could not reuse
38337 -+ E(#rows) from range optimizer. Make another try:
38338 -+
38339 -+ If range optimizer produced E(#rows) for a prefix of the ref
38340 -+ access we're considering, and that E(#rows) is lower then our
38341 -+ current estimate, make the adjustment.
38342 -+
38343 -+ The decision whether we can re-use the estimate from the range
38344 -+ optimizer is the same as in ReuseRangeEstimateForRef-3,
38345 -+ applied to first table->quick_key_parts[key] key parts.
38346 -+ */
38347 -+ if (table->quick_keys.is_set(key) &&
38348 -+ table->quick_key_parts[key] <= max_key_part &&
38349 -+ const_part & (1 << table->quick_key_parts[key]) &&
38350 -+ table->quick_n_ranges[key] == 1 + test(ref_or_null_part &
38351 -+ const_part) &&
38352 -+ records > (double) table->quick_rows[key])
38353 -+ {
38354 -+ tmp= records= (double) table->quick_rows[key];
38355 -+ }
38356 -+ }
38357 -+
38358 -+ /* Limit the number of matched rows */
38359 -+ set_if_smaller(tmp, (double) thd->variables.max_seeks_for_key);
38360 -+ if (table->covering_keys.is_set(key))
38361 -+ {
38362 -+ /* we can use only index tree */
38363 -+ uint keys_per_block= table->file->stats.block_size/2/
38364 -+ (keyinfo->key_length+table->file->ref_length)+1;
38365 -+ tmp= record_count*(tmp+keys_per_block-1)/keys_per_block;
38366 -+ }
38367 -+ else
38368 -+ tmp= record_count*min(tmp,s->worst_seeks);
38369 -+ }
38370 -+ else
38371 -+ tmp= best_time; // Do nothing
38372 -+ }
38373 -+ } /* not ft_key */
38374 -+ if (tmp < best_time - records/(double) TIME_FOR_COMPARE)
38375 -+ {
38376 -+ best_time= tmp + records/(double) TIME_FOR_COMPARE;
38377 -+ best= tmp;
38378 -+ best_records= records;
38379 -+ best_key= start_key;
38380 -+ best_max_key_part= max_key_part;
38381 -+ best_ref_depends_map= found_ref;
38382 -+ }
38383 -+ }
38384 -+ records= best_records;
38385 -+ }
38386 -+
38387 -+ /*
38388 -+ Don't test table scan if it can't be better.
38389 -+ Prefer key lookup if we would use the same key for scanning.
38390 -+
38391 -+ Don't do a table scan on InnoDB tables, if we can read the used
38392 -+ parts of the row from any of the used index.
38393 -+ This is because table scans uses index and we would not win
38394 -+ anything by using a table scan.
38395 -+
38396 -+ A word for word translation of the below if-statement in psergey's
38397 -+ understanding: we check if we should use table scan if:
38398 -+ (1) The found 'ref' access produces more records than a table scan
38399 -+ (or index scan, or quick select), or 'ref' is more expensive than
38400 -+ any of them.
38401 -+ (2) This doesn't hold: the best way to perform table scan is to to perform
38402 -+ 'range' access using index IDX, and the best way to perform 'ref'
38403 -+ access is to use the same index IDX, with the same or more key parts.
38404 -+ (note: it is not clear how this rule is/should be extended to
38405 -+ index_merge quick selects)
38406 -+ (3) See above note about InnoDB.
38407 -+ (4) NOT ("FORCE INDEX(...)" is used for table and there is 'ref' access
38408 -+ path, but there is no quick select)
38409 -+ If the condition in the above brackets holds, then the only possible
38410 -+ "table scan" access method is ALL/index (there is no quick select).
38411 -+ Since we have a 'ref' access path, and FORCE INDEX instructs us to
38412 -+ choose it over ALL/index, there is no need to consider a full table
38413 -+ scan.
38414 -+ */
38415 -+ if ((records >= s->found_records || best > s->read_time) && // (1)
38416 -+ !(s->quick && best_key && s->quick->index == best_key->key && // (2)
38417 -+ best_max_key_part >= s->table->quick_key_parts[best_key->key]) &&// (2)
38418 -+ !((s->table->file->ha_table_flags() & HA_TABLE_SCAN_ON_INDEX) && // (3)
38419 -+ ! s->table->covering_keys.is_clear_all() && best_key && !s->quick) &&// (3)
38420 -+ !(s->table->force_index && best_key && !s->quick)) // (4)
38421 -+ { // Check full join
38422 -+ ha_rows rnd_records= s->found_records;
38423 -+ /*
38424 -+ If there is a filtering condition on the table (i.e. ref analyzer found
38425 -+ at least one "table.keyXpartY= exprZ", where exprZ refers only to tables
38426 -+ preceding this table in the join order we're now considering), then
38427 -+ assume that 25% of the rows will be filtered out by this condition.
38428 -+
38429 -+ This heuristic is supposed to force tables used in exprZ to be before
38430 -+ this table in join order.
38431 -+ */
38432 -+ if (found_constraint)
38433 -+ rnd_records-= rnd_records/4;
38434 -+
38435 -+ /*
38436 -+ If applicable, get a more accurate estimate. Don't use the two
38437 -+ heuristics at once.
38438 -+ */
38439 -+ if (s->table->quick_condition_rows != s->found_records)
38440 -+ rnd_records= s->table->quick_condition_rows;
38441 -+
38442 -+ /*
38443 -+ Range optimizer never proposes a RANGE if it isn't better
38444 -+ than FULL: so if RANGE is present, it's always preferred to FULL.
38445 -+ Here we estimate its cost.
38446 -+ */
38447 -+ if (s->quick)
38448 -+ {
38449 -+ /*
38450 -+ For each record we:
38451 -+ - read record range through 'quick'
38452 -+ - skip rows which does not satisfy WHERE constraints
38453 -+ TODO:
38454 -+ We take into account possible use of join cache for ALL/index
38455 -+ access (see first else-branch below), but we don't take it into
38456 -+ account here for range/index_merge access. Find out why this is so.
38457 -+ */
38458 -+ tmp= record_count *
38459 -+ (s->quick->read_time +
38460 -+ (s->found_records - rnd_records)/(double) TIME_FOR_COMPARE);
38461 -+ }
38462 -+ else
38463 -+ {
38464 -+ /* Estimate cost of reading table. */
38465 -+ tmp= s->table->file->scan_time();
38466 -+ if (s->table->map & join->outer_join) // Can't use join cache
38467 -+ {
38468 -+ /*
38469 -+ For each record we have to:
38470 -+ - read the whole table record
38471 -+ - skip rows which does not satisfy join condition
38472 -+ */
38473 -+ tmp= record_count *
38474 -+ (tmp +
38475 -+ (s->records - rnd_records)/(double) TIME_FOR_COMPARE);
38476 -+ }
38477 -+ else
38478 -+ {
38479 -+ /* We read the table as many times as join buffer becomes full. */
38480 -+ tmp*= (1.0 + floor((double) cache_record_length(join,idx) *
38481 -+ record_count /
38482 -+ (double) thd->variables.join_buff_size));
38483 -+ /*
38484 -+ We don't make full cartesian product between rows in the scanned
38485 -+ table and existing records because we skip all rows from the
38486 -+ scanned table, which does not satisfy join condition when
38487 -+ we read the table (see flush_cached_records for details). Here we
38488 -+ take into account cost to read and skip these records.
38489 -+ */
38490 -+ tmp+= (s->records - rnd_records)/(double) TIME_FOR_COMPARE;
38491 -+ }
38492 -+ }
38493 -+
38494 -+ /*
38495 -+ We estimate the cost of evaluating WHERE clause for found records
38496 -+ as record_count * rnd_records / TIME_FOR_COMPARE. This cost plus
38497 -+ tmp give us total cost of using TABLE SCAN
38498 -+ */
38499 -+ if (best == DBL_MAX ||
38500 -+ (tmp + record_count/(double) TIME_FOR_COMPARE*rnd_records <
38501 -+ best + record_count/(double) TIME_FOR_COMPARE*records))
38502 -+ {
38503 -+ /*
38504 -+ If the table has a range (s->quick is set) make_join_select()
38505 -+ will ensure that this will be used
38506 -+ */
38507 -+ best= tmp;
38508 -+ records= rows2double(rnd_records);
38509 -+ best_key= 0;
38510 -+ /* range/index_merge/ALL/index access method are "independent", so: */
38511 -+ best_ref_depends_map= 0;
38512 -+ }
38513 -+ }
38514 -+
38515 -+ /* Update the cost information for the current partial plan */
38516 -+ join->positions[idx].records_read= records;
38517 -+ join->positions[idx].read_time= best;
38518 -+ join->positions[idx].key= best_key;
38519 -+ join->positions[idx].table= s;
38520 -+ join->positions[idx].ref_depend_map= best_ref_depends_map;
38521 -+
38522 -+ if (!best_key &&
38523 -+ idx == join->const_tables &&
38524 -+ s->table == join->sort_by_table &&
38525 -+ join->unit->select_limit_cnt >= records)
38526 -+ join->sort_by_table= (TABLE*) 1; // Must use temporary table
38527 -+
38528 -+ DBUG_VOID_RETURN;
38529 -+}
38530 -+
38531 -+
38532 -+/**
38533 -+ Selects and invokes a search strategy for an optimal query plan.
38534 -+
38535 -+ The function checks user-configurable parameters that control the search
38536 -+ strategy for an optimal plan, selects the search method and then invokes
38537 -+ it. Each specific optimization procedure stores the final optimal plan in
38538 -+ the array 'join->best_positions', and the cost of the plan in
38539 -+ 'join->best_read'.
38540 -+
38541 -+ @param join pointer to the structure providing all context info for
38542 -+ the query
38543 -+ @param join_tables set of the tables in the query
38544 -+
38545 -+ @todo
38546 -+ 'MAX_TABLES+2' denotes the old implementation of find_best before
38547 -+ the greedy version. Will be removed when greedy_search is approved.
38548 -+
38549 -+ @retval
38550 -+ FALSE ok
38551 -+ @retval
38552 -+ TRUE Fatal error
38553 -+*/
38554 -+
38555 -+static bool
38556 -+choose_plan(JOIN *join, table_map join_tables)
38557 -+{
38558 -+ uint search_depth= join->thd->variables.optimizer_search_depth;
38559 -+ uint prune_level= join->thd->variables.optimizer_prune_level;
38560 -+ bool straight_join= test(join->select_options & SELECT_STRAIGHT_JOIN);
38561 -+ DBUG_ENTER("choose_plan");
38562 -+
38563 -+ join->cur_embedding_map= 0;
38564 -+ reset_nj_counters(join->join_list);
38565 -+ /*
38566 -+ if (SELECT_STRAIGHT_JOIN option is set)
38567 -+ reorder tables so dependent tables come after tables they depend
38568 -+ on, otherwise keep tables in the order they were specified in the query
38569 -+ else
38570 -+ Apply heuristic: pre-sort all access plans with respect to the number of
38571 -+ records accessed.
38572 -+ */
38573 -+ my_qsort(join->best_ref + join->const_tables,
38574 -+ join->tables - join->const_tables, sizeof(JOIN_TAB*),
38575 -+ straight_join ? join_tab_cmp_straight : join_tab_cmp);
38576 -+
38577 -+ if (straight_join)
38578 -+ {
38579 -+ optimize_straight_join(join, join_tables);
38580 -+ }
38581 -+ else
38582 -+ {
38583 -+ if (search_depth == MAX_TABLES+2)
38584 -+ { /*
38585 -+ TODO: 'MAX_TABLES+2' denotes the old implementation of find_best before
38586 -+ the greedy version. Will be removed when greedy_search is approved.
38587 -+ */
38588 -+ join->best_read= DBL_MAX;
38589 -+ if (find_best(join, join_tables, join->const_tables, 1.0, 0.0))
38590 -+ DBUG_RETURN(TRUE);
38591 -+ }
38592 -+ else
38593 -+ {
38594 -+ if (search_depth == 0)
38595 -+ /* Automatically determine a reasonable value for 'search_depth' */
38596 -+ search_depth= determine_search_depth(join);
38597 -+ if (greedy_search(join, join_tables, search_depth, prune_level))
38598 -+ DBUG_RETURN(TRUE);
38599 -+ }
38600 -+ }
38601 -+
38602 -+ /*
38603 -+ Store the cost of this query into a user variable
38604 -+ Don't update last_query_cost for statements that are not "flat joins" :
38605 -+ i.e. they have subqueries, unions or call stored procedures.
38606 -+ TODO: calculate a correct cost for a query with subqueries and UNIONs.
38607 -+ */
38608 -+ if (join->thd->lex->is_single_level_stmt())
38609 -+ join->thd->status_var.last_query_cost= join->best_read;
38610 -+ DBUG_RETURN(FALSE);
38611 -+}
38612 -+
38613 -+
38614 -+/**
38615 -+ Compare two JOIN_TAB objects based on the number of accessed records.
38616 -+
38617 -+ @param ptr1 pointer to first JOIN_TAB object
38618 -+ @param ptr2 pointer to second JOIN_TAB object
38619 -+
38620 -+ NOTES
38621 -+ The order relation implemented by join_tab_cmp() is not transitive,
38622 -+ i.e. it is possible to choose such a, b and c that (a < b) && (b < c)
38623 -+ but (c < a). This implies that result of a sort using the relation
38624 -+ implemented by join_tab_cmp() depends on the order in which
38625 -+ elements are compared, i.e. the result is implementation-specific.
38626 -+ Example:
38627 -+ a: dependent = 0x0 table->map = 0x1 found_records = 3 ptr = 0x907e6b0
38628 -+ b: dependent = 0x0 table->map = 0x2 found_records = 3 ptr = 0x907e838
38629 -+ c: dependent = 0x6 table->map = 0x10 found_records = 2 ptr = 0x907ecd0
38630 -+
38631 -+ @retval
38632 -+ 1 if first is bigger
38633 -+ @retval
38634 -+ -1 if second is bigger
38635 -+ @retval
38636 -+ 0 if equal
38637 -+*/
38638 -+
38639 -+static int
38640 -+join_tab_cmp(const void* ptr1, const void* ptr2)
38641 -+{
38642 -+ JOIN_TAB *jt1= *(JOIN_TAB**) ptr1;
38643 -+ JOIN_TAB *jt2= *(JOIN_TAB**) ptr2;
38644 -+
38645 -+ if (jt1->dependent & jt2->table->map)
38646 -+ return 1;
38647 -+ if (jt2->dependent & jt1->table->map)
38648 -+ return -1;
38649 -+ if (jt1->found_records > jt2->found_records)
38650 -+ return 1;
38651 -+ if (jt1->found_records < jt2->found_records)
38652 -+ return -1;
38653 -+ return jt1 > jt2 ? 1 : (jt1 < jt2 ? -1 : 0);
38654 -+}
38655 -+
38656 -+
38657 -+/**
38658 -+ Same as join_tab_cmp, but for use with SELECT_STRAIGHT_JOIN.
38659 -+*/
38660 -+
38661 -+static int
38662 -+join_tab_cmp_straight(const void* ptr1, const void* ptr2)
38663 -+{
38664 -+ JOIN_TAB *jt1= *(JOIN_TAB**) ptr1;
38665 -+ JOIN_TAB *jt2= *(JOIN_TAB**) ptr2;
38666 -+
38667 -+ if (jt1->dependent & jt2->table->map)
38668 -+ return 1;
38669 -+ if (jt2->dependent & jt1->table->map)
38670 -+ return -1;
38671 -+ return jt1 > jt2 ? 1 : (jt1 < jt2 ? -1 : 0);
38672 -+}
38673 -+
38674 -+/**
38675 -+ Heuristic procedure to automatically guess a reasonable degree of
38676 -+ exhaustiveness for the greedy search procedure.
38677 -+
38678 -+ The procedure estimates the optimization time and selects a search depth
38679 -+ big enough to result in a near-optimal QEP, that doesn't take too long to
38680 -+ find. If the number of tables in the query exceeds some constant, then
38681 -+ search_depth is set to this constant.
38682 -+
38683 -+ @param join pointer to the structure providing all context info for
38684 -+ the query
38685 -+
38686 -+ @note
38687 -+ This is an extremely simplistic implementation that serves as a stub for a
38688 -+ more advanced analysis of the join. Ideally the search depth should be
38689 -+ determined by learning from previous query optimizations, because it will
38690 -+ depend on the CPU power (and other factors).
38691 -+
38692 -+ @todo
38693 -+ this value should be determined dynamically, based on statistics:
38694 -+ uint max_tables_for_exhaustive_opt= 7;
38695 -+
38696 -+ @todo
38697 -+ this value could be determined by some mapping of the form:
38698 -+ depth : table_count -> [max_tables_for_exhaustive_opt..MAX_EXHAUSTIVE]
38699 -+
38700 -+ @return
38701 -+ A positive integer that specifies the search depth (and thus the
38702 -+ exhaustiveness) of the depth-first search algorithm used by
38703 -+ 'greedy_search'.
38704 -+*/
38705 -+
38706 -+static uint
38707 -+determine_search_depth(JOIN *join)
38708 -+{
38709 -+ uint table_count= join->tables - join->const_tables;
38710 -+ uint search_depth;
38711 -+ /* TODO: this value should be determined dynamically, based on statistics: */
38712 -+ uint max_tables_for_exhaustive_opt= 7;
38713 -+
38714 -+ if (table_count <= max_tables_for_exhaustive_opt)
38715 -+ search_depth= table_count+1; // use exhaustive for small number of tables
38716 -+ else
38717 -+ /*
38718 -+ TODO: this value could be determined by some mapping of the form:
38719 -+ depth : table_count -> [max_tables_for_exhaustive_opt..MAX_EXHAUSTIVE]
38720 -+ */
38721 -+ search_depth= max_tables_for_exhaustive_opt; // use greedy search
38722 -+
38723 -+ return search_depth;
38724 -+}
38725 -+
38726 -+
38727 -+/**
38728 -+ Select the best ways to access the tables in a query without reordering them.
38729 -+
38730 -+ Find the best access paths for each query table and compute their costs
38731 -+ according to their order in the array 'join->best_ref' (thus without
38732 -+ reordering the join tables). The function calls sequentially
38733 -+ 'best_access_path' for each table in the query to select the best table
38734 -+ access method. The final optimal plan is stored in the array
38735 -+ 'join->best_positions', and the corresponding cost in 'join->best_read'.
38736 -+
38737 -+ @param join pointer to the structure providing all context info for
38738 -+ the query
38739 -+ @param join_tables set of the tables in the query
38740 -+
38741 -+ @note
38742 -+ This function can be applied to:
38743 -+ - queries with STRAIGHT_JOIN
38744 -+ - internally to compute the cost of an arbitrary QEP
38745 -+ @par
38746 -+ Thus 'optimize_straight_join' can be used at any stage of the query
38747 -+ optimization process to finalize a QEP as it is.
38748 -+*/
38749 -+
38750 -+static void
38751 -+optimize_straight_join(JOIN *join, table_map join_tables)
38752 -+{
38753 -+ JOIN_TAB *s;
38754 -+ uint idx= join->const_tables;
38755 -+ double record_count= 1.0;
38756 -+ double read_time= 0.0;
38757 -+
38758 -+ for (JOIN_TAB **pos= join->best_ref + idx ; (s= *pos) ; pos++)
38759 -+ {
38760 -+ /* Find the best access method from 's' to the current partial plan */
38761 -+ best_access_path(join, s, join->thd, join_tables, idx,
38762 -+ record_count, read_time);
38763 -+ /* compute the cost of the new plan extended with 's' */
38764 -+ record_count*= join->positions[idx].records_read;
38765 -+ read_time+= join->positions[idx].read_time;
38766 -+ join_tables&= ~(s->table->map);
38767 -+ ++idx;
38768 -+ }
38769 -+
38770 -+ read_time+= record_count / (double) TIME_FOR_COMPARE;
38771 -+ if (join->sort_by_table &&
38772 -+ join->sort_by_table != join->positions[join->const_tables].table->table)
38773 -+ read_time+= record_count; // We have to make a temp table
38774 -+ memcpy((uchar*) join->best_positions, (uchar*) join->positions,
38775 -+ sizeof(POSITION)*idx);
38776 -+ join->best_read= read_time;
38777 -+}
38778 -+
38779 -+
38780 -+/**
38781 -+ Find a good, possibly optimal, query execution plan (QEP) by a greedy search.
38782 -+
38783 -+ The search procedure uses a hybrid greedy/exhaustive search with controlled
38784 -+ exhaustiveness. The search is performed in N = card(remaining_tables)
38785 -+ steps. Each step evaluates how promising is each of the unoptimized tables,
38786 -+ selects the most promising table, and extends the current partial QEP with
38787 -+ that table. Currenly the most 'promising' table is the one with least
38788 -+ expensive extension.\
38789 -+
38790 -+ There are two extreme cases:
38791 -+ -# When (card(remaining_tables) < search_depth), the estimate finds the
38792 -+ best complete continuation of the partial QEP. This continuation can be
38793 -+ used directly as a result of the search.
38794 -+ -# When (search_depth == 1) the 'best_extension_by_limited_search'
38795 -+ consideres the extension of the current QEP with each of the remaining
38796 -+ unoptimized tables.
38797 -+
38798 -+ All other cases are in-between these two extremes. Thus the parameter
38799 -+ 'search_depth' controlls the exhaustiveness of the search. The higher the
38800 -+ value, the longer the optimizaton time and possibly the better the
38801 -+ resulting plan. The lower the value, the fewer alternative plans are
38802 -+ estimated, but the more likely to get a bad QEP.
38803 -+
38804 -+ All intermediate and final results of the procedure are stored in 'join':
38805 -+ - join->positions : modified for every partial QEP that is explored
38806 -+ - join->best_positions: modified for the current best complete QEP
38807 -+ - join->best_read : modified for the current best complete QEP
38808 -+ - join->best_ref : might be partially reordered
38809 -+
38810 -+ The final optimal plan is stored in 'join->best_positions', and its
38811 -+ corresponding cost in 'join->best_read'.
38812 -+
38813 -+ @note
38814 -+ The following pseudocode describes the algorithm of 'greedy_search':
38815 -+
38816 -+ @code
38817 -+ procedure greedy_search
38818 -+ input: remaining_tables
38819 -+ output: pplan;
38820 -+ {
38821 -+ pplan = <>;
38822 -+ do {
38823 -+ (t, a) = best_extension(pplan, remaining_tables);
38824 -+ pplan = concat(pplan, (t, a));
38825 -+ remaining_tables = remaining_tables - t;
38826 -+ } while (remaining_tables != {})
38827 -+ return pplan;
38828 -+ }
38829 -+
38830 -+ @endcode
38831 -+ where 'best_extension' is a placeholder for a procedure that selects the
38832 -+ most "promising" of all tables in 'remaining_tables'.
38833 -+ Currently this estimate is performed by calling
38834 -+ 'best_extension_by_limited_search' to evaluate all extensions of the
38835 -+ current QEP of size 'search_depth', thus the complexity of 'greedy_search'
38836 -+ mainly depends on that of 'best_extension_by_limited_search'.
38837 -+
38838 -+ @par
38839 -+ If 'best_extension()' == 'best_extension_by_limited_search()', then the
38840 -+ worst-case complexity of this algorithm is <=
38841 -+ O(N*N^search_depth/search_depth). When serch_depth >= N, then the
38842 -+ complexity of greedy_search is O(N!).
38843 -+
38844 -+ @par
38845 -+ In the future, 'greedy_search' might be extended to support other
38846 -+ implementations of 'best_extension', e.g. some simpler quadratic procedure.
38847 -+
38848 -+ @param join pointer to the structure providing all context info
38849 -+ for the query
38850 -+ @param remaining_tables set of tables not included into the partial plan yet
38851 -+ @param search_depth controlls the exhaustiveness of the search
38852 -+ @param prune_level the pruning heuristics that should be applied during
38853 -+ search
38854 -+
38855 -+ @retval
38856 -+ FALSE ok
38857 -+ @retval
38858 -+ TRUE Fatal error
38859 -+*/
38860 -+
38861 -+static bool
38862 -+greedy_search(JOIN *join,
38863 -+ table_map remaining_tables,
38864 -+ uint search_depth,
38865 -+ uint prune_level)
38866 -+{
38867 -+ double record_count= 1.0;
38868 -+ double read_time= 0.0;
38869 -+ uint idx= join->const_tables; // index into 'join->best_ref'
38870 -+ uint best_idx;
38871 -+ uint size_remain; // cardinality of remaining_tables
38872 -+ POSITION best_pos;
38873 -+ JOIN_TAB *best_table; // the next plan node to be added to the curr QEP
38874 -+
38875 -+ DBUG_ENTER("greedy_search");
38876 -+
38877 -+ /* number of tables that remain to be optimized */
38878 -+ size_remain= my_count_bits(remaining_tables);
38879 -+
38880 -+ do {
38881 -+ /* Find the extension of the current QEP with the lowest cost */
38882 -+ join->best_read= DBL_MAX;
38883 -+ if (best_extension_by_limited_search(join, remaining_tables, idx, record_count,
38884 -+ read_time, search_depth, prune_level))
38885 -+ DBUG_RETURN(TRUE);
38886 -+ /*
38887 -+ 'best_read < DBL_MAX' means that optimizer managed to find
38888 -+ some plan and updated 'best_positions' array accordingly.
38889 -+ */
38890 -+ DBUG_ASSERT(join->best_read < DBL_MAX);
38891 -+
38892 -+ if (size_remain <= search_depth)
38893 -+ {
38894 -+ /*
38895 -+ 'join->best_positions' contains a complete optimal extension of the
38896 -+ current partial QEP.
38897 -+ */
38898 -+ DBUG_EXECUTE("opt", print_plan(join, join->tables,
38899 -+ record_count, read_time, read_time,
38900 -+ "optimal"););
38901 -+ DBUG_RETURN(FALSE);
38902 -+ }
38903 -+
38904 -+ /* select the first table in the optimal extension as most promising */
38905 -+ best_pos= join->best_positions[idx];
38906 -+ best_table= best_pos.table;
38907 -+ /*
38908 -+ Each subsequent loop of 'best_extension_by_limited_search' uses
38909 -+ 'join->positions' for cost estimates, therefore we have to update its
38910 -+ value.
38911 -+ */
38912 -+ join->positions[idx]= best_pos;
38913 -+
38914 -+ /*
38915 -+ Update the interleaving state after extending the current partial plan
38916 -+ with a new table.
38917 -+ We are doing this here because best_extension_by_limited_search reverts
38918 -+ the interleaving state to the one of the non-extended partial plan
38919 -+ on exit.
38920 -+ */
38921 -+ IF_DBUG(bool is_interleave_error= )
38922 -+ check_interleaving_with_nj (best_table);
38923 -+ /* This has been already checked by best_extension_by_limited_search */
38924 -+ DBUG_ASSERT(!is_interleave_error);
38925 -+
38926 -+ /* find the position of 'best_table' in 'join->best_ref' */
38927 -+ best_idx= idx;
38928 -+ JOIN_TAB *pos= join->best_ref[best_idx];
38929 -+ while (pos && best_table != pos)
38930 -+ pos= join->best_ref[++best_idx];
38931 -+ DBUG_ASSERT((pos != NULL)); // should always find 'best_table'
38932 -+ /* move 'best_table' at the first free position in the array of joins */
38933 -+ swap_variables(JOIN_TAB*, join->best_ref[idx], join->best_ref[best_idx]);
38934 -+
38935 -+ /* compute the cost of the new plan extended with 'best_table' */
38936 -+ record_count*= join->positions[idx].records_read;
38937 -+ read_time+= join->positions[idx].read_time;
38938 -+
38939 -+ remaining_tables&= ~(best_table->table->map);
38940 -+ --size_remain;
38941 -+ ++idx;
38942 -+
38943 -+ DBUG_EXECUTE("opt", print_plan(join, idx,
38944 -+ record_count, read_time, read_time,
38945 -+ "extended"););
38946 -+ } while (TRUE);
38947 -+}
38948 -+
38949 -+
38950 -+/**
38951 -+ Find a good, possibly optimal, query execution plan (QEP) by a possibly
38952 -+ exhaustive search.
38953 -+
38954 -+ The procedure searches for the optimal ordering of the query tables in set
38955 -+ 'remaining_tables' of size N, and the corresponding optimal access paths to
38956 -+ each table. The choice of a table order and an access path for each table
38957 -+ constitutes a query execution plan (QEP) that fully specifies how to
38958 -+ execute the query.
38959 -+
38960 -+ The maximal size of the found plan is controlled by the parameter
38961 -+ 'search_depth'. When search_depth == N, the resulting plan is complete and
38962 -+ can be used directly as a QEP. If search_depth < N, the found plan consists
38963 -+ of only some of the query tables. Such "partial" optimal plans are useful
38964 -+ only as input to query optimization procedures, and cannot be used directly
38965 -+ to execute a query.
38966 -+
38967 -+ The algorithm begins with an empty partial plan stored in 'join->positions'
38968 -+ and a set of N tables - 'remaining_tables'. Each step of the algorithm
38969 -+ evaluates the cost of the partial plan extended by all access plans for
38970 -+ each of the relations in 'remaining_tables', expands the current partial
38971 -+ plan with the access plan that results in lowest cost of the expanded
38972 -+ partial plan, and removes the corresponding relation from
38973 -+ 'remaining_tables'. The algorithm continues until it either constructs a
38974 -+ complete optimal plan, or constructs an optimal plartial plan with size =
38975 -+ search_depth.
38976 -+
38977 -+ The final optimal plan is stored in 'join->best_positions'. The
38978 -+ corresponding cost of the optimal plan is in 'join->best_read'.
38979 -+
38980 -+ @note
38981 -+ The procedure uses a recursive depth-first search where the depth of the
38982 -+ recursion (and thus the exhaustiveness of the search) is controlled by the
38983 -+ parameter 'search_depth'.
38984 -+
38985 -+ @note
38986 -+ The pseudocode below describes the algorithm of
38987 -+ 'best_extension_by_limited_search'. The worst-case complexity of this
38988 -+ algorithm is O(N*N^search_depth/search_depth). When serch_depth >= N, then
38989 -+ the complexity of greedy_search is O(N!).
38990 -+
38991 -+ @code
38992 -+ procedure best_extension_by_limited_search(
38993 -+ pplan in, // in, partial plan of tables-joined-so-far
38994 -+ pplan_cost, // in, cost of pplan
38995 -+ remaining_tables, // in, set of tables not referenced in pplan
38996 -+ best_plan_so_far, // in/out, best plan found so far
38997 -+ best_plan_so_far_cost,// in/out, cost of best_plan_so_far
38998 -+ search_depth) // in, maximum size of the plans being considered
38999 -+ {
39000 -+ for each table T from remaining_tables
39001 -+ {
39002 -+ // Calculate the cost of using table T as above
39003 -+ cost = complex-series-of-calculations;
39004 -+
39005 -+ // Add the cost to the cost so far.
39006 -+ pplan_cost+= cost;
39007 -+
39008 -+ if (pplan_cost >= best_plan_so_far_cost)
39009 -+ // pplan_cost already too great, stop search
39010 -+ continue;
39011 -+
39012 -+ pplan= expand pplan by best_access_method;
39013 -+ remaining_tables= remaining_tables - table T;
39014 -+ if (remaining_tables is not an empty set
39015 -+ and
39016 -+ search_depth > 1)
39017 -+ {
39018 -+ best_extension_by_limited_search(pplan, pplan_cost,
39019 -+ remaining_tables,
39020 -+ best_plan_so_far,
39021 -+ best_plan_so_far_cost,
39022 -+ search_depth - 1);
39023 -+ }
39024 -+ else
39025 -+ {
39026 -+ best_plan_so_far_cost= pplan_cost;
39027 -+ best_plan_so_far= pplan;
39028 -+ }
39029 -+ }
39030 -+ }
39031 -+ @endcode
39032 -+
39033 -+ @note
39034 -+ When 'best_extension_by_limited_search' is called for the first time,
39035 -+ 'join->best_read' must be set to the largest possible value (e.g. DBL_MAX).
39036 -+ The actual implementation provides a way to optionally use pruning
39037 -+ heuristic (controlled by the parameter 'prune_level') to reduce the search
39038 -+ space by skipping some partial plans.
39039 -+
39040 -+ @note
39041 -+ The parameter 'search_depth' provides control over the recursion
39042 -+ depth, and thus the size of the resulting optimal plan.
39043 -+
39044 -+ @param join pointer to the structure providing all context info
39045 -+ for the query
39046 -+ @param remaining_tables set of tables not included into the partial plan yet
39047 -+ @param idx length of the partial QEP in 'join->positions';
39048 -+ since a depth-first search is used, also corresponds
39049 -+ to the current depth of the search tree;
39050 -+ also an index in the array 'join->best_ref';
39051 -+ @param record_count estimate for the number of records returned by the
39052 -+ best partial plan
39053 -+ @param read_time the cost of the best partial plan
39054 -+ @param search_depth maximum depth of the recursion and thus size of the
39055 -+ found optimal plan
39056 -+ (0 < search_depth <= join->tables+1).
39057 -+ @param prune_level pruning heuristics that should be applied during
39058 -+ optimization
39059 -+ (values: 0 = EXHAUSTIVE, 1 = PRUNE_BY_TIME_OR_ROWS)
39060 -+
39061 -+ @retval
39062 -+ FALSE ok
39063 -+ @retval
39064 -+ TRUE Fatal error
39065 -+*/
39066 -+
39067 -+static bool
39068 -+best_extension_by_limited_search(JOIN *join,
39069 -+ table_map remaining_tables,
39070 -+ uint idx,
39071 -+ double record_count,
39072 -+ double read_time,
39073 -+ uint search_depth,
39074 -+ uint prune_level)
39075 -+{
39076 -+ DBUG_ENTER("best_extension_by_limited_search");
39077 -+
39078 -+ THD *thd= join->thd;
39079 -+ if (thd->killed) // Abort
39080 -+ DBUG_RETURN(TRUE);
39081 -+
39082 -+ DBUG_EXECUTE("opt", print_plan(join, idx, read_time, record_count, idx,
39083 -+ "SOFAR:"););
39084 -+
39085 -+ /*
39086 -+ 'join' is a partial plan with lower cost than the best plan so far,
39087 -+ so continue expanding it further with the tables in 'remaining_tables'.
39088 -+ */
39089 -+ JOIN_TAB *s;
39090 -+ double best_record_count= DBL_MAX;
39091 -+ double best_read_time= DBL_MAX;
39092 -+
39093 -+ DBUG_EXECUTE("opt", print_plan(join, idx, record_count, read_time, read_time,
39094 -+ "part_plan"););
39095 -+
39096 -+ for (JOIN_TAB **pos= join->best_ref + idx ; (s= *pos) ; pos++)
39097 -+ {
39098 -+ table_map real_table_bit= s->table->map;
39099 -+ if ((remaining_tables & real_table_bit) &&
39100 -+ !(remaining_tables & s->dependent) &&
39101 -+ (!idx || !check_interleaving_with_nj(s)))
39102 -+ {
39103 -+ double current_record_count, current_read_time;
39104 -+
39105 -+ /* Find the best access method from 's' to the current partial plan */
39106 -+ best_access_path(join, s, thd, remaining_tables, idx,
39107 -+ record_count, read_time);
39108 -+ /* Compute the cost of extending the plan with 's' */
39109 -+ current_record_count= record_count * join->positions[idx].records_read;
39110 -+ current_read_time= read_time + join->positions[idx].read_time;
39111 -+
39112 -+ /* Expand only partial plans with lower cost than the best QEP so far */
39113 -+ if ((current_read_time +
39114 -+ current_record_count / (double) TIME_FOR_COMPARE) >= join->best_read)
39115 -+ {
39116 -+ DBUG_EXECUTE("opt", print_plan(join, idx+1,
39117 -+ current_record_count,
39118 -+ read_time,
39119 -+ (current_read_time +
39120 -+ current_record_count /
39121 -+ (double) TIME_FOR_COMPARE),
39122 -+ "prune_by_cost"););
39123 -+ restore_prev_nj_state(s);
39124 -+ continue;
39125 -+ }
39126 -+
39127 -+ /*
39128 -+ Prune some less promising partial plans. This heuristic may miss
39129 -+ the optimal QEPs, thus it results in a non-exhaustive search.
39130 -+ */
39131 -+ if (prune_level == 1)
39132 -+ {
39133 -+ if (best_record_count > current_record_count ||
39134 -+ best_read_time > current_read_time ||
39135 -+ (idx == join->const_tables && // 's' is the first table in the QEP
39136 -+ s->table == join->sort_by_table))
39137 -+ {
39138 -+ if (best_record_count >= current_record_count &&
39139 -+ best_read_time >= current_read_time &&
39140 -+ /* TODO: What is the reasoning behind this condition? */
39141 -+ (!(s->key_dependent & remaining_tables) ||
39142 -+ join->positions[idx].records_read < 2.0))
39143 -+ {
39144 -+ best_record_count= current_record_count;
39145 -+ best_read_time= current_read_time;
39146 -+ }
39147 -+ }
39148 -+ else
39149 -+ {
39150 -+ DBUG_EXECUTE("opt", print_plan(join, idx+1,
39151 -+ current_record_count,
39152 -+ read_time,
39153 -+ current_read_time,
39154 -+ "pruned_by_heuristic"););
39155 -+ restore_prev_nj_state(s);
39156 -+ continue;
39157 -+ }
39158 -+ }
39159 -+
39160 -+ if ( (search_depth > 1) && (remaining_tables & ~real_table_bit) )
39161 -+ { /* Recursively expand the current partial plan */
39162 -+ swap_variables(JOIN_TAB*, join->best_ref[idx], *pos);
39163 -+ if (best_extension_by_limited_search(join,
39164 -+ remaining_tables & ~real_table_bit,
39165 -+ idx + 1,
39166 -+ current_record_count,
39167 -+ current_read_time,
39168 -+ search_depth - 1,
39169 -+ prune_level))
39170 -+ DBUG_RETURN(TRUE);
39171 -+ swap_variables(JOIN_TAB*, join->best_ref[idx], *pos);
39172 -+ }
39173 -+ else
39174 -+ { /*
39175 -+ 'join' is either the best partial QEP with 'search_depth' relations,
39176 -+ or the best complete QEP so far, whichever is smaller.
39177 -+ */
39178 -+ current_read_time+= current_record_count / (double) TIME_FOR_COMPARE;
39179 -+ if (join->sort_by_table &&
39180 -+ join->sort_by_table !=
39181 -+ join->positions[join->const_tables].table->table)
39182 -+ /* We have to make a temp table */
39183 -+ current_read_time+= current_record_count;
39184 -+ if ((search_depth == 1) || (current_read_time < join->best_read))
39185 -+ {
39186 -+ memcpy((uchar*) join->best_positions, (uchar*) join->positions,
39187 -+ sizeof(POSITION) * (idx + 1));
39188 -+ join->best_read= current_read_time - 0.001;
39189 -+ }
39190 -+ DBUG_EXECUTE("opt", print_plan(join, idx+1,
39191 -+ current_record_count,
39192 -+ read_time,
39193 -+ current_read_time,
39194 -+ "full_plan"););
39195 -+ }
39196 -+ restore_prev_nj_state(s);
39197 -+ }
39198 -+ }
39199 -+ DBUG_RETURN(FALSE);
39200 -+}
39201 -+
39202 -+
39203 -+/**
39204 -+ @todo
39205 -+ - TODO: this function is here only temporarily until 'greedy_search' is
39206 -+ tested and accepted.
39207 -+
39208 -+ RETURN VALUES
39209 -+ FALSE ok
39210 -+ TRUE Fatal error
39211 -+*/
39212 -+static bool
39213 -+find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
39214 -+ double read_time)
39215 -+{
39216 -+ DBUG_ENTER("find_best");
39217 -+ THD *thd= join->thd;
39218 -+ if (thd->killed)
39219 -+ DBUG_RETURN(TRUE);
39220 -+ if (!rest_tables)
39221 -+ {
39222 -+ DBUG_PRINT("best",("read_time: %g record_count: %g",read_time,
39223 -+ record_count));
39224 -+
39225 -+ read_time+=record_count/(double) TIME_FOR_COMPARE;
39226 -+ if (join->sort_by_table &&
39227 -+ join->sort_by_table !=
39228 -+ join->positions[join->const_tables].table->table)
39229 -+ read_time+=record_count; // We have to make a temp table
39230 -+ if (read_time < join->best_read)
39231 -+ {
39232 -+ memcpy((uchar*) join->best_positions,(uchar*) join->positions,
39233 -+ sizeof(POSITION)*idx);
39234 -+ join->best_read= read_time - 0.001;
39235 -+ }
39236 -+ DBUG_RETURN(FALSE);
39237 -+ }
39238 -+ if (read_time+record_count/(double) TIME_FOR_COMPARE >= join->best_read)
39239 -+ DBUG_RETURN(FALSE); /* Found better before */
39240 -+
39241 -+ JOIN_TAB *s;
39242 -+ double best_record_count=DBL_MAX,best_read_time=DBL_MAX;
39243 -+ for (JOIN_TAB **pos=join->best_ref+idx ; (s=*pos) ; pos++)
39244 -+ {
39245 -+ table_map real_table_bit=s->table->map;
39246 -+ if ((rest_tables & real_table_bit) && !(rest_tables & s->dependent) &&
39247 -+ (!idx|| !check_interleaving_with_nj(s)))
39248 -+ {
39249 -+ double records, best;
39250 -+ best_access_path(join, s, thd, rest_tables, idx, record_count,
39251 -+ read_time);
39252 -+ records= join->positions[idx].records_read;
39253 -+ best= join->positions[idx].read_time;
39254 -+ /*
39255 -+ Go to the next level only if there hasn't been a better key on
39256 -+ this level! This will cut down the search for a lot simple cases!
39257 -+ */
39258 -+ double current_record_count=record_count*records;
39259 -+ double current_read_time=read_time+best;
39260 -+ if (best_record_count > current_record_count ||
39261 -+ best_read_time > current_read_time ||
39262 -+ (idx == join->const_tables && s->table == join->sort_by_table))
39263 -+ {
39264 -+ if (best_record_count >= current_record_count &&
39265 -+ best_read_time >= current_read_time &&
39266 -+ (!(s->key_dependent & rest_tables) || records < 2.0))
39267 -+ {
39268 -+ best_record_count=current_record_count;
39269 -+ best_read_time=current_read_time;
39270 -+ }
39271 -+ swap_variables(JOIN_TAB*, join->best_ref[idx], *pos);
39272 -+ if (find_best(join,rest_tables & ~real_table_bit,idx+1,
39273 -+ current_record_count,current_read_time))
39274 -+ DBUG_RETURN(TRUE);
39275 -+ swap_variables(JOIN_TAB*, join->best_ref[idx], *pos);
39276 -+ }
39277 -+ restore_prev_nj_state(s);
39278 -+ if (join->select_options & SELECT_STRAIGHT_JOIN)
39279 -+ break; // Don't test all combinations
39280 -+ }
39281 -+ }
39282 -+ DBUG_RETURN(FALSE);
39283 -+}
39284 -+
39285 -+
39286 -+/**
39287 -+ Find how much space the prevous read not const tables takes in cache.
39288 -+*/
39289 -+
39290 -+static void calc_used_field_length(THD *thd, JOIN_TAB *join_tab)
39291 -+{
39292 -+ uint null_fields,blobs,fields,rec_length;
39293 -+ Field **f_ptr,*field;
39294 -+ MY_BITMAP *read_set= join_tab->table->read_set;;
39295 -+
39296 -+ null_fields= blobs= fields= rec_length=0;
39297 -+ for (f_ptr=join_tab->table->field ; (field= *f_ptr) ; f_ptr++)
39298 -+ {
39299 -+ if (bitmap_is_set(read_set, field->field_index))
39300 -+ {
39301 -+ uint flags=field->flags;
39302 -+ fields++;
39303 -+ rec_length+=field->pack_length();
39304 -+ if (flags & BLOB_FLAG)
39305 -+ blobs++;
39306 -+ if (!(flags & NOT_NULL_FLAG))
39307 -+ null_fields++;
39308 -+ }
39309 -+ }
39310 -+ if (null_fields)
39311 -+ rec_length+=(join_tab->table->s->null_fields+7)/8;
39312 -+ if (join_tab->table->maybe_null)
39313 -+ rec_length+=sizeof(my_bool);
39314 -+ if (blobs)
39315 -+ {
39316 -+ uint blob_length=(uint) (join_tab->table->file->stats.mean_rec_length-
39317 -+ (join_tab->table->s->reclength- rec_length));
39318 -+ rec_length+=(uint) max(4,blob_length);
39319 -+ }
39320 -+ join_tab->used_fields=fields;
39321 -+ join_tab->used_fieldlength=rec_length;
39322 -+ join_tab->used_blobs=blobs;
39323 -+}
39324 -+
39325 -+
39326 -+static uint
39327 -+cache_record_length(JOIN *join,uint idx)
39328 -+{
39329 -+ uint length=0;
39330 -+ JOIN_TAB **pos,**end;
39331 -+ THD *thd=join->thd;
39332 -+
39333 -+ for (pos=join->best_ref+join->const_tables,end=join->best_ref+idx ;
39334 -+ pos != end ;
39335 -+ pos++)
39336 -+ {
39337 -+ JOIN_TAB *join_tab= *pos;
39338 -+ if (!join_tab->used_fieldlength) /* Not calced yet */
39339 -+ calc_used_field_length(thd, join_tab);
39340 -+ length+=join_tab->used_fieldlength;
39341 -+ }
39342 -+ return length;
39343 -+}
39344 -+
39345 -+
39346 -+/*
39347 -+ Get the number of different row combinations for subset of partial join
39348 -+
39349 -+ SYNOPSIS
39350 -+ prev_record_reads()
39351 -+ join The join structure
39352 -+ idx Number of tables in the partial join order (i.e. the
39353 -+ partial join order is in join->positions[0..idx-1])
39354 -+ found_ref Bitmap of tables for which we need to find # of distinct
39355 -+ row combinations.
39356 -+
39357 -+ DESCRIPTION
39358 -+ Given a partial join order (in join->positions[0..idx-1]) and a subset of
39359 -+ tables within that join order (specified in found_ref), find out how many
39360 -+ distinct row combinations of subset tables will be in the result of the
39361 -+ partial join order.
39362 -+
39363 -+ This is used as follows: Suppose we have a table accessed with a ref-based
39364 -+ method. The ref access depends on current rows of tables in found_ref.
39365 -+ We want to count # of different ref accesses. We assume two ref accesses
39366 -+ will be different if at least one of access parameters is different.
39367 -+ Example: consider a query
39368 -+
39369 -+ SELECT * FROM t1, t2, t3 WHERE t1.key=c1 AND t2.key=c2 AND t3.key=t1.field
39370 -+
39371 -+ and a join order:
39372 -+ t1, ref access on t1.key=c1
39373 -+ t2, ref access on t2.key=c2
39374 -+ t3, ref access on t3.key=t1.field
39375 -+
39376 -+ For t1: n_ref_scans = 1, n_distinct_ref_scans = 1
39377 -+ For t2: n_ref_scans = records_read(t1), n_distinct_ref_scans=1
39378 -+ For t3: n_ref_scans = records_read(t1)*records_read(t2)
39379 -+ n_distinct_ref_scans = #records_read(t1)
39380 -+
39381 -+ The reason for having this function (at least the latest version of it)
39382 -+ is that we need to account for buffering in join execution.
39383 -+
39384 -+ An edge-case example: if we have a non-first table in join accessed via
39385 -+ ref(const) or ref(param) where there is a small number of different
39386 -+ values of param, then the access will likely hit the disk cache and will
39387 -+ not require any disk seeks.
39388 -+
39389 -+ The proper solution would be to assume an LRU disk cache of some size,
39390 -+ calculate probability of cache hits, etc. For now we just count
39391 -+ identical ref accesses as one.
39392 -+
39393 -+ RETURN
39394 -+ Expected number of row combinations
39395 -+*/
39396 -+
39397 -+static double
39398 -+prev_record_reads(JOIN *join, uint idx, table_map found_ref)
39399 -+{
39400 -+ double found=1.0;
39401 -+ POSITION *pos_end= join->positions - 1;
39402 -+ for (POSITION *pos= join->positions + idx - 1; pos != pos_end; pos--)
39403 -+ {
39404 -+ if (pos->table->table->map & found_ref)
39405 -+ {
39406 -+ found_ref|= pos->ref_depend_map;
39407 -+ /*
39408 -+ For the case of "t1 LEFT JOIN t2 ON ..." where t2 is a const table
39409 -+ with no matching row we will get position[t2].records_read==0.
39410 -+ Actually the size of output is one null-complemented row, therefore
39411 -+ we will use value of 1 whenever we get records_read==0.
39412 -+
39413 -+ Note
39414 -+ - the above case can't occur if inner part of outer join has more
39415 -+ than one table: table with no matches will not be marked as const.
39416 -+
39417 -+ - Ideally we should add 1 to records_read for every possible null-
39418 -+ complemented row. We're not doing it because: 1. it will require
39419 -+ non-trivial code and add overhead. 2. The value of records_read
39420 -+ is an inprecise estimate and adding 1 (or, in the worst case,
39421 -+ #max_nested_outer_joins=64-1) will not make it any more precise.
39422 -+ */
39423 -+ if (pos->records_read)
39424 -+ found*= pos->records_read;
39425 -+ }
39426 -+ }
39427 -+ return found;
39428 -+}
39429 -+
39430 -+
39431 -+/**
39432 -+ Set up join struct according to best position.
39433 -+*/
39434 -+
39435 -+static bool
39436 -+get_best_combination(JOIN *join)
39437 -+{
39438 -+ uint i,tablenr;
39439 -+ table_map used_tables;
39440 -+ JOIN_TAB *join_tab,*j;
39441 -+ KEYUSE *keyuse;
39442 -+ uint table_count;
39443 -+ THD *thd=join->thd;
39444 -+ DBUG_ENTER("get_best_combination");
39445 -+
39446 -+ table_count=join->tables;
39447 -+ if (!(join->join_tab=join_tab=
39448 -+ (JOIN_TAB*) thd->alloc(sizeof(JOIN_TAB)*table_count)))
39449 -+ DBUG_RETURN(TRUE);
39450 -+
39451 -+ join->full_join=0;
39452 -+
39453 -+ used_tables= OUTER_REF_TABLE_BIT; // Outer row is already read
39454 -+ for (j=join_tab, tablenr=0 ; tablenr < table_count ; tablenr++,j++)
39455 -+ {
39456 -+ TABLE *form;
39457 -+ *j= *join->best_positions[tablenr].table;
39458 -+ form=join->table[tablenr]=j->table;
39459 -+ used_tables|= form->map;
39460 -+ form->reginfo.join_tab=j;
39461 -+ if (!*j->on_expr_ref)
39462 -+ form->reginfo.not_exists_optimize=0; // Only with LEFT JOIN
39463 -+ DBUG_PRINT("info",("type: %d", j->type));
39464 -+ if (j->type == JT_CONST)
39465 -+ continue; // Handled in make_join_stat..
39466 -+
39467 -+ j->ref.key = -1;
39468 -+ j->ref.key_parts=0;
39469 -+
39470 -+ if (j->type == JT_SYSTEM)
39471 -+ continue;
39472 -+ if (j->keys.is_clear_all() || !(keyuse= join->best_positions[tablenr].key))
39473 -+ {
39474 -+ j->type=JT_ALL;
39475 -+ if (tablenr != join->const_tables)
39476 -+ join->full_join=1;
39477 -+ }
39478 -+ else if (create_ref_for_key(join, j, keyuse, used_tables))
39479 -+ DBUG_RETURN(TRUE); // Something went wrong
39480 -+ }
39481 -+
39482 -+ for (i=0 ; i < table_count ; i++)
39483 -+ join->map2table[join->join_tab[i].table->tablenr]=join->join_tab+i;
39484 -+ update_depend_map(join);
39485 -+ DBUG_RETURN(0);
39486 -+}
39487 -+
39488 -+
39489 -+static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
39490 -+ table_map used_tables)
39491 -+{
39492 -+ KEYUSE *keyuse=org_keyuse;
39493 -+ bool ftkey=(keyuse->keypart == FT_KEYPART);
39494 -+ THD *thd= join->thd;
39495 -+ uint keyparts,length,key;
39496 -+ TABLE *table;
39497 -+ KEY *keyinfo;
39498 -+ DBUG_ENTER("create_ref_for_key");
39499 -+
39500 -+ /* Use best key from find_best */
39501 -+ table=j->table;
39502 -+ key=keyuse->key;
39503 -+ keyinfo=table->key_info+key;
39504 -+
39505 -+ if (ftkey)
39506 -+ {
39507 -+ Item_func_match *ifm=(Item_func_match *)keyuse->val;
39508 -+
39509 -+ length=0;
39510 -+ keyparts=1;
39511 -+ ifm->join_key=1;
39512 -+ }
39513 -+ else
39514 -+ {
39515 -+ keyparts=length=0;
39516 -+ uint found_part_ref_or_null= 0;
39517 -+ /*
39518 -+ Calculate length for the used key
39519 -+ Stop if there is a missing key part or when we find second key_part
39520 -+ with KEY_OPTIMIZE_REF_OR_NULL
39521 -+ */
39522 -+ do
39523 -+ {
39524 -+ if (!(~used_tables & keyuse->used_tables))
39525 -+ {
39526 -+ if (keyparts == keyuse->keypart &&
39527 -+ !(found_part_ref_or_null & keyuse->optimize))
39528 -+ {
39529 -+ keyparts++;
39530 -+ length+= keyinfo->key_part[keyuse->keypart].store_length;
39531 -+ found_part_ref_or_null|= keyuse->optimize;
39532 -+ }
39533 -+ }
39534 -+ keyuse++;
39535 -+ } while (keyuse->table == table && keyuse->key == key);
39536 -+ } /* not ftkey */
39537 -+
39538 -+ /* set up fieldref */
39539 -+ keyinfo=table->key_info+key;
39540 -+ j->ref.key_parts=keyparts;
39541 -+ j->ref.key_length=length;
39542 -+ j->ref.key=(int) key;
39543 -+ if (!(j->ref.key_buff= (uchar*) thd->calloc(ALIGN_SIZE(length)*2)) ||
39544 -+ !(j->ref.key_copy= (store_key**) thd->alloc((sizeof(store_key*) *
39545 -+ (keyparts+1)))) ||
39546 -+ !(j->ref.items= (Item**) thd->alloc(sizeof(Item*)*keyparts)) ||
39547 -+ !(j->ref.cond_guards= (bool**) thd->alloc(sizeof(uint*)*keyparts)))
39548 -+ {
39549 -+ DBUG_RETURN(TRUE);
39550 -+ }
39551 -+ j->ref.key_buff2=j->ref.key_buff+ALIGN_SIZE(length);
39552 -+ j->ref.key_err=1;
39553 -+ j->ref.has_record= FALSE;
39554 -+ j->ref.null_rejecting= 0;
39555 -+ j->ref.use_count= 0;
39556 -+ keyuse=org_keyuse;
39557 -+
39558 -+ store_key **ref_key= j->ref.key_copy;
39559 -+ uchar *key_buff=j->ref.key_buff, *null_ref_key= 0;
39560 -+ bool keyuse_uses_no_tables= TRUE;
39561 -+ if (ftkey)
39562 -+ {
39563 -+ j->ref.items[0]=((Item_func*)(keyuse->val))->key_item();
39564 -+ /* Predicates pushed down into subquery can't be used FT access */
39565 -+ j->ref.cond_guards[0]= NULL;
39566 -+ if (keyuse->used_tables)
39567 -+ DBUG_RETURN(TRUE); // not supported yet. SerG
39568 -+
39569 -+ j->type=JT_FT;
39570 -+ }
39571 -+ else
39572 -+ {
39573 -+ uint i;
39574 -+ for (i=0 ; i < keyparts ; keyuse++,i++)
39575 -+ {
39576 -+ while (keyuse->keypart != i ||
39577 -+ ((~used_tables) & keyuse->used_tables))
39578 -+ keyuse++; /* Skip other parts */
39579 -+
39580 -+ uint maybe_null= test(keyinfo->key_part[i].null_bit);
39581 -+ j->ref.items[i]=keyuse->val; // Save for cond removal
39582 -+ j->ref.cond_guards[i]= keyuse->cond_guard;
39583 -+ if (keyuse->null_rejecting)
39584 -+ j->ref.null_rejecting |= 1 << i;
39585 -+ keyuse_uses_no_tables= keyuse_uses_no_tables && !keyuse->used_tables;
39586 -+ if (!keyuse->used_tables &&
39587 -+ !(join->select_options & SELECT_DESCRIBE))
39588 -+ { // Compare against constant
39589 -+ store_key_item tmp(thd, keyinfo->key_part[i].field,
39590 -+ key_buff + maybe_null,
39591 -+ maybe_null ? key_buff : 0,
39592 -+ keyinfo->key_part[i].length, keyuse->val);
39593 -+ if (thd->is_fatal_error)
39594 -+ DBUG_RETURN(TRUE);
39595 -+ tmp.copy();
39596 -+ }
39597 -+ else
39598 -+ *ref_key++= get_store_key(thd,
39599 -+ keyuse,join->const_table_map,
39600 -+ &keyinfo->key_part[i],
39601 -+ key_buff, maybe_null);
39602 -+ /*
39603 -+ Remember if we are going to use REF_OR_NULL
39604 -+ But only if field _really_ can be null i.e. we force JT_REF
39605 -+ instead of JT_REF_OR_NULL in case if field can't be null
39606 -+ */
39607 -+ if ((keyuse->optimize & KEY_OPTIMIZE_REF_OR_NULL) && maybe_null)
39608 -+ null_ref_key= key_buff;
39609 -+ key_buff+=keyinfo->key_part[i].store_length;
39610 -+ }
39611 -+ } /* not ftkey */
39612 -+ *ref_key=0; // end_marker
39613 -+ if (j->type == JT_FT)
39614 -+ DBUG_RETURN(0);
39615 -+ if (j->type == JT_CONST)
39616 -+ j->table->const_table= 1;
39617 -+ else if (((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY |
39618 -+ HA_END_SPACE_KEY)) != HA_NOSAME) ||
39619 -+ keyparts != keyinfo->key_parts || null_ref_key)
39620 -+ {
39621 -+ /* Must read with repeat */
39622 -+ j->type= null_ref_key ? JT_REF_OR_NULL : JT_REF;
39623 -+ j->ref.null_ref_key= null_ref_key;
39624 -+ }
39625 -+ else if (keyuse_uses_no_tables)
39626 -+ {
39627 -+ /*
39628 -+ This happen if we are using a constant expression in the ON part
39629 -+ of an LEFT JOIN.
39630 -+ SELECT * FROM a LEFT JOIN b ON b.key=30
39631 -+ Here we should not mark the table as a 'const' as a field may
39632 -+ have a 'normal' value or a NULL value.
39633 -+ */
39634 -+ j->type=JT_CONST;
39635 -+ }
39636 -+ else
39637 -+ j->type=JT_EQ_REF;
39638 -+ DBUG_RETURN(0);
39639 -+}
39640 -+
39641 -+
39642 -+
39643 -+static store_key *
39644 -+get_store_key(THD *thd, KEYUSE *keyuse, table_map used_tables,
39645 -+ KEY_PART_INFO *key_part, uchar *key_buff, uint maybe_null)
39646 -+{
39647 -+ if (!((~used_tables) & keyuse->used_tables)) // if const item
39648 -+ {
39649 -+ return new store_key_const_item(thd,
39650 -+ key_part->field,
39651 -+ key_buff + maybe_null,
39652 -+ maybe_null ? key_buff : 0,
39653 -+ key_part->length,
39654 -+ keyuse->val);
39655 -+ }
39656 -+ else if (keyuse->val->type() == Item::FIELD_ITEM ||
39657 -+ (keyuse->val->type() == Item::REF_ITEM &&
39658 -+ ((Item_ref*)keyuse->val)->ref_type() == Item_ref::OUTER_REF &&
39659 -+ (*(Item_ref**)((Item_ref*)keyuse->val)->ref)->ref_type() ==
39660 -+ Item_ref::DIRECT_REF &&
39661 -+ keyuse->val->real_item()->type() == Item::FIELD_ITEM))
39662 -+ return new store_key_field(thd,
39663 -+ key_part->field,
39664 -+ key_buff + maybe_null,
39665 -+ maybe_null ? key_buff : 0,
39666 -+ key_part->length,
39667 -+ ((Item_field*) keyuse->val->real_item())->field,
39668 -+ keyuse->val->full_name());
39669 -+ return new store_key_item(thd,
39670 -+ key_part->field,
39671 -+ key_buff + maybe_null,
39672 -+ maybe_null ? key_buff : 0,
39673 -+ key_part->length,
39674 -+ keyuse->val);
39675 -+}
39676 -+
39677 -+/**
39678 -+ This function is only called for const items on fields which are keys.
39679 -+
39680 -+ @return
39681 -+ returns 1 if there was some conversion made when the field was stored.
39682 -+*/
39683 -+
39684 -+bool
39685 -+store_val_in_field(Field *field, Item *item, enum_check_fields check_flag)
39686 -+{
39687 -+ bool error;
39688 -+ TABLE *table= field->table;
39689 -+ THD *thd= table->in_use;
39690 -+ ha_rows cuted_fields=thd->cuted_fields;
39691 -+ my_bitmap_map *old_map= dbug_tmp_use_all_columns(table,
39692 -+ table->write_set);
39693 -+
39694 -+ /*
39695 -+ we should restore old value of count_cuted_fields because
39696 -+ store_val_in_field can be called from mysql_insert
39697 -+ with select_insert, which make count_cuted_fields= 1
39698 -+ */
39699 -+ enum_check_fields old_count_cuted_fields= thd->count_cuted_fields;
39700 -+ thd->count_cuted_fields= check_flag;
39701 -+ error= item->save_in_field(field, 1);
39702 -+ thd->count_cuted_fields= old_count_cuted_fields;
39703 -+ dbug_tmp_restore_column_map(table->write_set, old_map);
39704 -+ return error || cuted_fields != thd->cuted_fields;
39705 -+}
39706 -+
39707 -+
39708 -+/**
39709 -+ @details Initialize a JOIN as a query execution plan
39710 -+ that accesses a single table via a table scan.
39711 -+
39712 -+ @param parent contains JOIN_TAB and TABLE object buffers for this join
39713 -+ @param tmp_table temporary table
39714 -+
39715 -+ @retval FALSE success
39716 -+ @retval TRUE error occurred
39717 -+*/
39718 -+bool
39719 -+JOIN::make_simple_join(JOIN *parent, TABLE *temp_table)
39720 -+{
39721 -+ DBUG_ENTER("JOIN::make_simple_join");
39722 -+
39723 -+ /*
39724 -+ Reuse TABLE * and JOIN_TAB if already allocated by a previous call
39725 -+ to this function through JOIN::exec (may happen for sub-queries).
39726 -+ */
39727 -+ if (!parent->join_tab_reexec &&
39728 -+ !(parent->join_tab_reexec= (JOIN_TAB*) thd->alloc(sizeof(JOIN_TAB))))
39729 -+ DBUG_RETURN(TRUE); /* purecov: inspected */
39730 -+
39731 -+ join_tab= parent->join_tab_reexec;
39732 -+ table= &parent->table_reexec[0]; parent->table_reexec[0]= temp_table;
39733 -+ tables= 1;
39734 -+ const_tables= 0;
39735 -+ const_table_map= 0;
39736 -+ tmp_table_param.field_count= tmp_table_param.sum_func_count=
39737 -+ tmp_table_param.func_count= 0;
39738 -+ /*
39739 -+ We need to destruct the copy_field (allocated in create_tmp_table())
39740 -+ before setting it to 0 if the join is not "reusable".
39741 -+ */
39742 -+ if (!tmp_join || tmp_join != this)
39743 -+ tmp_table_param.cleanup();
39744 -+ tmp_table_param.copy_field= tmp_table_param.copy_field_end=0;
39745 -+ first_record= sort_and_group=0;
39746 -+ send_records= (ha_rows) 0;
39747 -+ group= 0;
39748 -+ row_limit= unit->select_limit_cnt;
39749 -+ do_send_rows= row_limit ? 1 : 0;
39750 -+
39751 -+ join_tab->cache.buff=0; /* No caching */
39752 -+ join_tab->table=temp_table;
39753 -+ join_tab->select=0;
39754 -+ join_tab->select_cond=0;
39755 -+ join_tab->quick=0;
39756 -+ join_tab->type= JT_ALL; /* Map through all records */
39757 -+ join_tab->keys.init();
39758 -+ join_tab->keys.set_all(); /* test everything in quick */
39759 -+ join_tab->info=0;
39760 -+ join_tab->on_expr_ref=0;
39761 -+ join_tab->last_inner= 0;
39762 -+ join_tab->first_unmatched= 0;
39763 -+ join_tab->ref.key = -1;
39764 -+ join_tab->not_used_in_distinct=0;
39765 -+ join_tab->read_first_record= join_init_read_record;
39766 -+ join_tab->join= this;
39767 -+ join_tab->ref.key_parts= 0;
39768 -+ bzero((char*) &join_tab->read_record,sizeof(join_tab->read_record));
39769 -+ temp_table->status=0;
39770 -+ temp_table->null_row=0;
39771 -+ DBUG_RETURN(FALSE);
39772 -+}
39773 -+
39774 -+
39775 -+inline void add_cond_and_fix(Item **e1, Item *e2)
39776 -+{
39777 -+ if (*e1)
39778 -+ {
39779 -+ Item *res;
39780 -+ if ((res= new Item_cond_and(*e1, e2)))
39781 -+ {
39782 -+ *e1= res;
39783 -+ res->quick_fix_field();
39784 -+ res->update_used_tables();
39785 -+ }
39786 -+ }
39787 -+ else
39788 -+ *e1= e2;
39789 -+}
39790 -+
39791 -+
39792 -+/**
39793 -+ Add to join_tab->select_cond[i] "table.field IS NOT NULL" conditions
39794 -+ we've inferred from ref/eq_ref access performed.
39795 -+
39796 -+ This function is a part of "Early NULL-values filtering for ref access"
39797 -+ optimization.
39798 -+
39799 -+ Example of this optimization:
39800 -+ For query SELECT * FROM t1,t2 WHERE t2.key=t1.field @n
39801 -+ and plan " any-access(t1), ref(t2.key=t1.field) " @n
39802 -+ add "t1.field IS NOT NULL" to t1's table condition. @n
39803 -+
39804 -+ Description of the optimization:
39805 -+
39806 -+ We look through equalities choosen to perform ref/eq_ref access,
39807 -+ pick equalities that have form "tbl.part_of_key = othertbl.field"
39808 -+ (where othertbl is a non-const table and othertbl.field may be NULL)
39809 -+ and add them to conditions on correspoding tables (othertbl in this
39810 -+ example).
39811 -+
39812 -+ Exception from that is the case when referred_tab->join != join.
39813 -+ I.e. don't add NOT NULL constraints from any embedded subquery.
39814 -+ Consider this query:
39815 -+ @code
39816 -+ SELECT A.f2 FROM t1 LEFT JOIN t2 A ON A.f2 = f1
39817 -+ WHERE A.f3=(SELECT MIN(f3) FROM t2 C WHERE A.f4 = C.f4) OR A.f3 IS NULL;
39818 -+ @endocde
39819 -+ Here condition A.f3 IS NOT NULL is going to be added to the WHERE
39820 -+ condition of the embedding query.
39821 -+ Another example:
39822 -+ SELECT * FROM t10, t11 WHERE (t10.a < 10 OR t10.a IS NULL)
39823 -+ AND t11.b <=> t10.b AND (t11.a = (SELECT MAX(a) FROM t12
39824 -+ WHERE t12.b = t10.a ));
39825 -+ Here condition t10.a IS NOT NULL is going to be added.
39826 -+ In both cases addition of NOT NULL condition will erroneously reject
39827 -+ some rows of the result set.
39828 -+ referred_tab->join != join constraint would disallow such additions.
39829 -+
39830 -+ This optimization doesn't affect the choices that ref, range, or join
39831 -+ optimizer make. This was intentional because this was added after 4.1
39832 -+ was GA.
39833 -+
39834 -+ Implementation overview
39835 -+ 1. update_ref_and_keys() accumulates info about null-rejecting
39836 -+ predicates in in KEY_FIELD::null_rejecting
39837 -+ 1.1 add_key_part saves these to KEYUSE.
39838 -+ 2. create_ref_for_key copies them to TABLE_REF.
39839 -+ 3. add_not_null_conds adds "x IS NOT NULL" to join_tab->select_cond of
39840 -+ appropiate JOIN_TAB members.
39841 -+*/
39842 -+
39843 -+static void add_not_null_conds(JOIN *join)
39844 -+{
39845 -+ DBUG_ENTER("add_not_null_conds");
39846 -+ for (uint i=join->const_tables ; i < join->tables ; i++)
39847 -+ {
39848 -+ JOIN_TAB *tab=join->join_tab+i;
39849 -+ if ((tab->type == JT_REF || tab->type == JT_EQ_REF ||
39850 -+ tab->type == JT_REF_OR_NULL) &&
39851 -+ !tab->table->maybe_null)
39852 -+ {
39853 -+ for (uint keypart= 0; keypart < tab->ref.key_parts; keypart++)
39854 -+ {
39855 -+ if (tab->ref.null_rejecting & (1 << keypart))
39856 -+ {
39857 -+ Item *item= tab->ref.items[keypart];
39858 -+ Item *notnull;
39859 -+ DBUG_ASSERT(item->type() == Item::FIELD_ITEM);
39860 -+ Item_field *not_null_item= (Item_field*)item;
39861 -+ JOIN_TAB *referred_tab= not_null_item->field->table->reginfo.join_tab;
39862 -+ /*
39863 -+ For UPDATE queries such as:
39864 -+ UPDATE t1 SET t1.f2=(SELECT MAX(t2.f4) FROM t2 WHERE t2.f3=t1.f1);
39865 -+ not_null_item is the t1.f1, but it's referred_tab is 0.
39866 -+ */
39867 -+ if (!referred_tab || referred_tab->join != join)
39868 -+ continue;
39869 -+ if (!(notnull= new Item_func_isnotnull(not_null_item)))
39870 -+ DBUG_VOID_RETURN;
39871 -+ /*
39872 -+ We need to do full fix_fields() call here in order to have correct
39873 -+ notnull->const_item(). This is needed e.g. by test_quick_select
39874 -+ when it is called from make_join_select after this function is
39875 -+ called.
39876 -+ */
39877 -+ if (notnull->fix_fields(join->thd, &notnull))
39878 -+ DBUG_VOID_RETURN;
39879 -+ DBUG_EXECUTE("where",print_where(notnull,
39880 -+ referred_tab->table->alias,
39881 -+ QT_ORDINARY););
39882 -+ add_cond_and_fix(&referred_tab->select_cond, notnull);
39883 -+ }
39884 -+ }
39885 -+ }
39886 -+ }
39887 -+ DBUG_VOID_RETURN;
39888 -+}
39889 -+
39890 -+/**
39891 -+ Build a predicate guarded by match variables for embedding outer joins.
39892 -+ The function recursively adds guards for predicate cond
39893 -+ assending from tab to the first inner table next embedding
39894 -+ nested outer join and so on until it reaches root_tab
39895 -+ (root_tab can be 0).
39896 -+
39897 -+ @param tab the first inner table for most nested outer join
39898 -+ @param cond the predicate to be guarded (must be set)
39899 -+ @param root_tab the first inner table to stop
39900 -+
39901 -+ @return
39902 -+ - pointer to the guarded predicate, if success
39903 -+ - 0, otherwise
39904 -+*/
39905 -+
39906 -+static COND*
39907 -+add_found_match_trig_cond(JOIN_TAB *tab, COND *cond, JOIN_TAB *root_tab)
39908 -+{
39909 -+ COND *tmp;
39910 -+ DBUG_ASSERT(cond != 0);
39911 -+ if (tab == root_tab)
39912 -+ return cond;
39913 -+ if ((tmp= add_found_match_trig_cond(tab->first_upper, cond, root_tab)))
39914 -+ tmp= new Item_func_trig_cond(tmp, &tab->found);
39915 -+ if (tmp)
39916 -+ {
39917 -+ tmp->quick_fix_field();
39918 -+ tmp->update_used_tables();
39919 -+ }
39920 -+ return tmp;
39921 -+}
39922 -+
39923 -+
39924 -+/**
39925 -+ Fill in outer join related info for the execution plan structure.
39926 -+
39927 -+ For each outer join operation left after simplification of the
39928 -+ original query the function set up the following pointers in the linear
39929 -+ structure join->join_tab representing the selected execution plan.
39930 -+ The first inner table t0 for the operation is set to refer to the last
39931 -+ inner table tk through the field t0->last_inner.
39932 -+ Any inner table ti for the operation are set to refer to the first
39933 -+ inner table ti->first_inner.
39934 -+ The first inner table t0 for the operation is set to refer to the
39935 -+ first inner table of the embedding outer join operation, if there is any,
39936 -+ through the field t0->first_upper.
39937 -+ The on expression for the outer join operation is attached to the
39938 -+ corresponding first inner table through the field t0->on_expr_ref.
39939 -+ Here ti are structures of the JOIN_TAB type.
39940 -+
39941 -+ EXAMPLE. For the query:
39942 -+ @code
39943 -+ SELECT * FROM t1
39944 -+ LEFT JOIN
39945 -+ (t2, t3 LEFT JOIN t4 ON t3.a=t4.a)
39946 -+ ON (t1.a=t2.a AND t1.b=t3.b)
39947 -+ WHERE t1.c > 5,
39948 -+ @endcode
39949 -+
39950 -+ given the execution plan with the table order t1,t2,t3,t4
39951 -+ is selected, the following references will be set;
39952 -+ t4->last_inner=[t4], t4->first_inner=[t4], t4->first_upper=[t2]
39953 -+ t2->last_inner=[t4], t2->first_inner=t3->first_inner=[t2],
39954 -+ on expression (t1.a=t2.a AND t1.b=t3.b) will be attached to
39955 -+ *t2->on_expr_ref, while t3.a=t4.a will be attached to *t4->on_expr_ref.
39956 -+
39957 -+ @param join reference to the info fully describing the query
39958 -+
39959 -+ @note
39960 -+ The function assumes that the simplification procedure has been
39961 -+ already applied to the join query (see simplify_joins).
39962 -+ This function can be called only after the execution plan
39963 -+ has been chosen.
39964 -+*/
39965 -+
39966 -+static void
39967 -+make_outerjoin_info(JOIN *join)
39968 -+{
39969 -+ DBUG_ENTER("make_outerjoin_info");
39970 -+ for (uint i=join->const_tables ; i < join->tables ; i++)
39971 -+ {
39972 -+ JOIN_TAB *tab=join->join_tab+i;
39973 -+ TABLE *table=tab->table;
39974 -+ TABLE_LIST *tbl= table->pos_in_table_list;
39975 -+ TABLE_LIST *embedding= tbl->embedding;
39976 -+
39977 -+ if (tbl->outer_join)
39978 -+ {
39979 -+ /*
39980 -+ Table tab is the only one inner table for outer join.
39981 -+ (Like table t4 for the table reference t3 LEFT JOIN t4 ON t3.a=t4.a
39982 -+ is in the query above.)
39983 -+ */
39984 -+ tab->last_inner= tab->first_inner= tab;
39985 -+ tab->on_expr_ref= &tbl->on_expr;
39986 -+ tab->cond_equal= tbl->cond_equal;
39987 -+ if (embedding)
39988 -+ tab->first_upper= embedding->nested_join->first_nested;
39989 -+ }
39990 -+ for ( ; embedding ; embedding= embedding->embedding)
39991 -+ {
39992 -+ NESTED_JOIN *nested_join= embedding->nested_join;
39993 -+ if (!nested_join->counter)
39994 -+ {
39995 -+ /*
39996 -+ Table tab is the first inner table for nested_join.
39997 -+ Save reference to it in the nested join structure.
39998 -+ */
39999 -+ nested_join->first_nested= tab;
40000 -+ tab->on_expr_ref= &embedding->on_expr;
40001 -+ tab->cond_equal= tbl->cond_equal;
40002 -+ if (embedding->embedding)
40003 -+ tab->first_upper= embedding->embedding->nested_join->first_nested;
40004 -+ }
40005 -+ if (!tab->first_inner)
40006 -+ tab->first_inner= nested_join->first_nested;
40007 -+ if (++nested_join->counter < nested_join->join_list.elements)
40008 -+ break;
40009 -+ /* Table tab is the last inner table for nested join. */
40010 -+ nested_join->first_nested->last_inner= tab;
40011 -+ }
40012 -+ }
40013 -+ DBUG_VOID_RETURN;
40014 -+}
40015 -+
40016 -+
40017 -+static bool
40018 -+make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
40019 -+{
40020 -+ THD *thd= join->thd;
40021 -+ DBUG_ENTER("make_join_select");
40022 -+ if (select)
40023 -+ {
40024 -+ add_not_null_conds(join);
40025 -+ table_map used_tables;
40026 -+ if (cond) /* Because of QUICK_GROUP_MIN_MAX_SELECT */
40027 -+ { /* there may be a select without a cond. */
40028 -+ if (join->tables > 1)
40029 -+ cond->update_used_tables(); // Tablenr may have changed
40030 -+ if (join->const_tables == join->tables &&
40031 -+ thd->lex->current_select->master_unit() ==
40032 -+ &thd->lex->unit) // not upper level SELECT
40033 -+ join->const_table_map|=RAND_TABLE_BIT;
40034 -+ { // Check const tables
40035 -+ COND *const_cond=
40036 -+ make_cond_for_table(cond,
40037 -+ join->const_table_map,
40038 -+ (table_map) 0);
40039 -+ DBUG_EXECUTE("where",print_where(const_cond,"constants", QT_ORDINARY););
40040 -+ for (JOIN_TAB *tab= join->join_tab+join->const_tables;
40041 -+ tab < join->join_tab+join->tables ; tab++)
40042 -+ {
40043 -+ if (*tab->on_expr_ref)
40044 -+ {
40045 -+ JOIN_TAB *cond_tab= tab->first_inner;
40046 -+ COND *tmp= make_cond_for_table(*tab->on_expr_ref,
40047 -+ join->const_table_map,
40048 -+ ( table_map) 0);
40049 -+ if (!tmp)
40050 -+ continue;
40051 -+ tmp= new Item_func_trig_cond(tmp, &cond_tab->not_null_compl);
40052 -+ if (!tmp)
40053 -+ DBUG_RETURN(1);
40054 -+ tmp->quick_fix_field();
40055 -+ cond_tab->select_cond= !cond_tab->select_cond ? tmp :
40056 -+ new Item_cond_and(cond_tab->select_cond,
40057 -+ tmp);
40058 -+ if (!cond_tab->select_cond)
40059 -+ DBUG_RETURN(1);
40060 -+ cond_tab->select_cond->quick_fix_field();
40061 -+ }
40062 -+ }
40063 -+ if (const_cond && !const_cond->val_int())
40064 -+ {
40065 -+ DBUG_PRINT("info",("Found impossible WHERE condition"));
40066 -+ DBUG_RETURN(1); // Impossible const condition
40067 -+ }
40068 -+ }
40069 -+ }
40070 -+ used_tables=((select->const_tables=join->const_table_map) |
40071 -+ OUTER_REF_TABLE_BIT | RAND_TABLE_BIT);
40072 -+ for (uint i=join->const_tables ; i < join->tables ; i++)
40073 -+ {
40074 -+ JOIN_TAB *tab=join->join_tab+i;
40075 -+ /*
40076 -+ first_inner is the X in queries like:
40077 -+ SELECT * FROM t1 LEFT OUTER JOIN (t2 JOIN t3) ON X
40078 -+ */
40079 -+ JOIN_TAB *first_inner_tab= tab->first_inner;
40080 -+ table_map current_map= tab->table->map;
40081 -+ bool use_quick_range=0;
40082 -+ COND *tmp;
40083 -+
40084 -+ /*
40085 -+ Following force including random expression in last table condition.
40086 -+ It solve problem with select like SELECT * FROM t1 WHERE rand() > 0.5
40087 -+ */
40088 -+ if (i == join->tables-1)
40089 -+ current_map|= OUTER_REF_TABLE_BIT | RAND_TABLE_BIT;
40090 -+ used_tables|=current_map;
40091 -+
40092 -+ if (tab->type == JT_REF && tab->quick &&
40093 -+ (uint) tab->ref.key == tab->quick->index &&
40094 -+ tab->ref.key_length < tab->quick->max_used_key_length)
40095 -+ {
40096 -+ /* Range uses longer key; Use this instead of ref on key */
40097 -+ tab->type=JT_ALL;
40098 -+ use_quick_range=1;
40099 -+ tab->use_quick=1;
40100 -+ tab->ref.key= -1;
40101 -+ tab->ref.key_parts=0; // Don't use ref key.
40102 -+ join->best_positions[i].records_read= rows2double(tab->quick->records);
40103 -+ /*
40104 -+ We will use join cache here : prevent sorting of the first
40105 -+ table only and sort at the end.
40106 -+ */
40107 -+ if (i != join->const_tables && join->tables > join->const_tables + 1)
40108 -+ join->full_join= 1;
40109 -+ }
40110 -+
40111 -+ tmp= NULL;
40112 -+ if (cond)
40113 -+ tmp= make_cond_for_table(cond,used_tables,current_map);
40114 -+ if (cond && !tmp && tab->quick)
40115 -+ { // Outer join
40116 -+ if (tab->type != JT_ALL)
40117 -+ {
40118 -+ /*
40119 -+ Don't use the quick method
40120 -+ We come here in the case where we have 'key=constant' and
40121 -+ the test is removed by make_cond_for_table()
40122 -+ */
40123 -+ delete tab->quick;
40124 -+ tab->quick= 0;
40125 -+ }
40126 -+ else
40127 -+ {
40128 -+ /*
40129 -+ Hack to handle the case where we only refer to a table
40130 -+ in the ON part of an OUTER JOIN. In this case we want the code
40131 -+ below to check if we should use 'quick' instead.
40132 -+ */
40133 -+ DBUG_PRINT("info", ("Item_int"));
40134 -+ tmp= new Item_int((longlong) 1,1); // Always true
40135 -+ }
40136 -+
40137 -+ }
40138 -+ if (tmp || !cond || tab->type == JT_REF)
40139 -+ {
40140 -+ DBUG_EXECUTE("where",print_where(tmp,tab->table->alias, QT_ORDINARY););
40141 -+ SQL_SELECT *sel= tab->select= ((SQL_SELECT*)
40142 -+ thd->memdup((uchar*) select,
40143 -+ sizeof(*select)));
40144 -+ if (!sel)
40145 -+ DBUG_RETURN(1); // End of memory
40146 -+ /*
40147 -+ If tab is an inner table of an outer join operation,
40148 -+ add a match guard to the pushed down predicate.
40149 -+ The guard will turn the predicate on only after
40150 -+ the first match for outer tables is encountered.
40151 -+ */
40152 -+ if (cond && tmp)
40153 -+ {
40154 -+ /*
40155 -+ Because of QUICK_GROUP_MIN_MAX_SELECT there may be a select without
40156 -+ a cond, so neutralize the hack above.
40157 -+ */
40158 -+ if (!(tmp= add_found_match_trig_cond(first_inner_tab, tmp, 0)))
40159 -+ DBUG_RETURN(1);
40160 -+ tab->select_cond=sel->cond=tmp;
40161 -+ /* Push condition to storage engine if this is enabled
40162 -+ and the condition is not guarded */
40163 -+ if (thd->variables.engine_condition_pushdown)
40164 -+ {
40165 -+ COND *push_cond=
40166 -+ make_cond_for_table(tmp, current_map, current_map);
40167 -+ if (push_cond)
40168 -+ {
40169 -+ /* Push condition to handler */
40170 -+ if (!tab->table->file->cond_push(push_cond))
40171 -+ tab->table->file->pushed_cond= push_cond;
40172 -+ }
40173 -+ }
40174 -+ }
40175 -+ else
40176 -+ tab->select_cond= sel->cond= NULL;
40177 -+
40178 -+ sel->head=tab->table;
40179 -+ DBUG_EXECUTE("where",print_where(tmp,tab->table->alias, QT_ORDINARY););
40180 -+ if (tab->quick)
40181 -+ {
40182 -+ /* Use quick key read if it's a constant and it's not used
40183 -+ with key reading */
40184 -+ if (tab->needed_reg.is_clear_all() && tab->type != JT_EQ_REF
40185 -+ && tab->type != JT_FT && (tab->type != JT_REF ||
40186 -+ (uint) tab->ref.key == tab->quick->index))
40187 -+ {
40188 -+ sel->quick=tab->quick; // Use value from get_quick_...
40189 -+ sel->quick_keys.clear_all();
40190 -+ sel->needed_reg.clear_all();
40191 -+ }
40192 -+ else
40193 -+ {
40194 -+ delete tab->quick;
40195 -+ }
40196 -+ tab->quick=0;
40197 -+ }
40198 -+ uint ref_key=(uint) sel->head->reginfo.join_tab->ref.key+1;
40199 -+ if (i == join->const_tables && ref_key)
40200 -+ {
40201 -+ if (!tab->const_keys.is_clear_all() &&
40202 -+ tab->table->reginfo.impossible_range)
40203 -+ DBUG_RETURN(1);
40204 -+ }
40205 -+ else if (tab->type == JT_ALL && ! use_quick_range)
40206 -+ {
40207 -+ if (!tab->const_keys.is_clear_all() &&
40208 -+ tab->table->reginfo.impossible_range)
40209 -+ DBUG_RETURN(1); // Impossible range
40210 -+ /*
40211 -+ We plan to scan all rows.
40212 -+ Check again if we should use an index.
40213 -+ We could have used an column from a previous table in
40214 -+ the index if we are using limit and this is the first table
40215 -+ */
40216 -+
40217 -+ if ((cond &&
40218 -+ !tab->keys.is_subset(tab->const_keys) && i > 0) ||
40219 -+ (!tab->const_keys.is_clear_all() && i == join->const_tables &&
40220 -+ join->unit->select_limit_cnt <
40221 -+ join->best_positions[i].records_read &&
40222 -+ !(join->select_options & OPTION_FOUND_ROWS)))
40223 -+ {
40224 -+ /* Join with outer join condition */
40225 -+ COND *orig_cond=sel->cond;
40226 -+ sel->cond= and_conds(sel->cond, *tab->on_expr_ref);
40227 -+
40228 -+ /*
40229 -+ We can't call sel->cond->fix_fields,
40230 -+ as it will break tab->on_expr if it's AND condition
40231 -+ (fix_fields currently removes extra AND/OR levels).
40232 -+ Yet attributes of the just built condition are not needed.
40233 -+ Thus we call sel->cond->quick_fix_field for safety.
40234 -+ */
40235 -+ if (sel->cond && !sel->cond->fixed)
40236 -+ sel->cond->quick_fix_field();
40237 -+
40238 -+ if (sel->test_quick_select(thd, tab->keys,
40239 -+ used_tables & ~ current_map,
40240 -+ (join->select_options &
40241 -+ OPTION_FOUND_ROWS ?
40242 -+ HA_POS_ERROR :
40243 -+ join->unit->select_limit_cnt), 0) < 0)
40244 -+ {
40245 -+ /*
40246 -+ Before reporting "Impossible WHERE" for the whole query
40247 -+ we have to check isn't it only "impossible ON" instead
40248 -+ */
40249 -+ sel->cond=orig_cond;
40250 -+ if (!*tab->on_expr_ref ||
40251 -+ sel->test_quick_select(thd, tab->keys,
40252 -+ used_tables & ~ current_map,
40253 -+ (join->select_options &
40254 -+ OPTION_FOUND_ROWS ?
40255 -+ HA_POS_ERROR :
40256 -+ join->unit->select_limit_cnt),0) < 0)
40257 -+ DBUG_RETURN(1); // Impossible WHERE
40258 -+ }
40259 -+ else
40260 -+ sel->cond=orig_cond;
40261 -+
40262 -+ /* Fix for EXPLAIN */
40263 -+ if (sel->quick)
40264 -+ join->best_positions[i].records_read= (double)sel->quick->records;
40265 -+ }
40266 -+ else
40267 -+ {
40268 -+ sel->needed_reg=tab->needed_reg;
40269 -+ sel->quick_keys.clear_all();
40270 -+ }
40271 -+ if (!sel->quick_keys.is_subset(tab->checked_keys) ||
40272 -+ !sel->needed_reg.is_subset(tab->checked_keys))
40273 -+ {
40274 -+ tab->keys=sel->quick_keys;
40275 -+ tab->keys.merge(sel->needed_reg);
40276 -+ tab->use_quick= (!sel->needed_reg.is_clear_all() &&
40277 -+ (select->quick_keys.is_clear_all() ||
40278 -+ (select->quick &&
40279 -+ (select->quick->records >= 100L)))) ?
40280 -+ 2 : 1;
40281 -+ sel->read_tables= used_tables & ~current_map;
40282 -+ }
40283 -+ if (i != join->const_tables && tab->use_quick != 2)
40284 -+ { /* Read with cache */
40285 -+ if (cond &&
40286 -+ (tmp=make_cond_for_table(cond,
40287 -+ join->const_table_map |
40288 -+ current_map,
40289 -+ current_map)))
40290 -+ {
40291 -+ DBUG_EXECUTE("where",print_where(tmp,"cache", QT_ORDINARY););
40292 -+ tab->cache.select=(SQL_SELECT*)
40293 -+ thd->memdup((uchar*) sel, sizeof(SQL_SELECT));
40294 -+ tab->cache.select->cond=tmp;
40295 -+ tab->cache.select->read_tables=join->const_table_map;
40296 -+ }
40297 -+ }
40298 -+ }
40299 -+ }
40300 -+
40301 -+ /*
40302 -+ Push down conditions from all on expressions.
40303 -+ Each of these conditions are guarded by a variable
40304 -+ that turns if off just before null complemented row for
40305 -+ outer joins is formed. Thus, the condition from an
40306 -+ 'on expression' are guaranteed not to be checked for
40307 -+ the null complemented row.
40308 -+ */
40309 -+
40310 -+ /* First push down constant conditions from on expressions */
40311 -+ for (JOIN_TAB *join_tab= join->join_tab+join->const_tables;
40312 -+ join_tab < join->join_tab+join->tables ; join_tab++)
40313 -+ {
40314 -+ if (*join_tab->on_expr_ref)
40315 -+ {
40316 -+ JOIN_TAB *cond_tab= join_tab->first_inner;
40317 -+ COND *tmp= make_cond_for_table(*join_tab->on_expr_ref,
40318 -+ join->const_table_map,
40319 -+ (table_map) 0);
40320 -+ if (!tmp)
40321 -+ continue;
40322 -+ tmp= new Item_func_trig_cond(tmp, &cond_tab->not_null_compl);
40323 -+ if (!tmp)
40324 -+ DBUG_RETURN(1);
40325 -+ tmp->quick_fix_field();
40326 -+ cond_tab->select_cond= !cond_tab->select_cond ? tmp :
40327 -+ new Item_cond_and(cond_tab->select_cond,tmp);
40328 -+ if (!cond_tab->select_cond)
40329 -+ DBUG_RETURN(1);
40330 -+ cond_tab->select_cond->quick_fix_field();
40331 -+ }
40332 -+ }
40333 -+
40334 -+ /* Push down non-constant conditions from on expressions */
40335 -+ JOIN_TAB *last_tab= tab;
40336 -+ while (first_inner_tab && first_inner_tab->last_inner == last_tab)
40337 -+ {
40338 -+ /*
40339 -+ Table tab is the last inner table of an outer join.
40340 -+ An on expression is always attached to it.
40341 -+ */
40342 -+ COND *on_expr= *first_inner_tab->on_expr_ref;
40343 -+
40344 -+ table_map used_tables2= (join->const_table_map |
40345 -+ OUTER_REF_TABLE_BIT | RAND_TABLE_BIT);
40346 -+ for (tab= join->join_tab+join->const_tables; tab <= last_tab ; tab++)
40347 -+ {
40348 -+ current_map= tab->table->map;
40349 -+ used_tables2|= current_map;
40350 -+ COND *tmp_cond= make_cond_for_table(on_expr, used_tables2,
40351 -+ current_map);
40352 -+ if (tmp_cond)
40353 -+ {
40354 -+ JOIN_TAB *cond_tab= tab < first_inner_tab ? first_inner_tab : tab;
40355 -+ /*
40356 -+ First add the guards for match variables of
40357 -+ all embedding outer join operations.
40358 -+ */
40359 -+ if (!(tmp_cond= add_found_match_trig_cond(cond_tab->first_inner,
40360 -+ tmp_cond,
40361 -+ first_inner_tab)))
40362 -+ DBUG_RETURN(1);
40363 -+ /*
40364 -+ Now add the guard turning the predicate off for
40365 -+ the null complemented row.
40366 -+ */
40367 -+ DBUG_PRINT("info", ("Item_func_trig_cond"));
40368 -+ tmp_cond= new Item_func_trig_cond(tmp_cond,
40369 -+ &first_inner_tab->
40370 -+ not_null_compl);
40371 -+ DBUG_PRINT("info", ("Item_func_trig_cond 0x%lx",
40372 -+ (ulong) tmp_cond));
40373 -+ if (tmp_cond)
40374 -+ tmp_cond->quick_fix_field();
40375 -+ /* Add the predicate to other pushed down predicates */
40376 -+ DBUG_PRINT("info", ("Item_cond_and"));
40377 -+ cond_tab->select_cond= !cond_tab->select_cond ? tmp_cond :
40378 -+ new Item_cond_and(cond_tab->select_cond,
40379 -+ tmp_cond);
40380 -+ DBUG_PRINT("info", ("Item_cond_and 0x%lx",
40381 -+ (ulong)cond_tab->select_cond));
40382 -+ if (!cond_tab->select_cond)
40383 -+ DBUG_RETURN(1);
40384 -+ cond_tab->select_cond->quick_fix_field();
40385 -+ }
40386 -+ }
40387 -+ first_inner_tab= first_inner_tab->first_upper;
40388 -+ }
40389 -+ }
40390 -+ }
40391 -+ DBUG_RETURN(0);
40392 -+}
40393 -+
40394 -+
40395 -+/**
40396 -+ The default implementation of unlock-row method of READ_RECORD,
40397 -+ used in all access methods.
40398 -+*/
40399 -+
40400 -+void rr_unlock_row(st_join_table *tab)
40401 -+{
40402 -+ READ_RECORD *info= &tab->read_record;
40403 -+ info->file->unlock_row();
40404 -+}
40405 -+
40406 -+
40407 -+
40408 -+/**
40409 -+ Pick the appropriate access method functions
40410 -+
40411 -+ Sets the functions for the selected table access method
40412 -+
40413 -+ @param tab Table reference to put access method
40414 -+*/
40415 -+
40416 -+static void
40417 -+pick_table_access_method(JOIN_TAB *tab)
40418 -+{
40419 -+ switch (tab->type)
40420 -+ {
40421 -+ case JT_REF:
40422 -+ tab->read_first_record= join_read_always_key;
40423 -+ tab->read_record.read_record= join_read_next_same;
40424 -+ break;
40425 -+
40426 -+ case JT_REF_OR_NULL:
40427 -+ tab->read_first_record= join_read_always_key_or_null;
40428 -+ tab->read_record.read_record= join_read_next_same_or_null;
40429 -+ break;
40430 -+
40431 -+ case JT_CONST:
40432 -+ tab->read_first_record= join_read_const;
40433 -+ tab->read_record.read_record= join_no_more_records;
40434 -+ break;
40435 -+
40436 -+ case JT_EQ_REF:
40437 -+ tab->read_first_record= join_read_key;
40438 -+ tab->read_record.read_record= join_no_more_records;
40439 -+ break;
40440 -+
40441 -+ case JT_FT:
40442 -+ tab->read_first_record= join_ft_read_first;
40443 -+ tab->read_record.read_record= join_ft_read_next;
40444 -+ break;
40445 -+
40446 -+ case JT_SYSTEM:
40447 -+ tab->read_first_record= join_read_system;
40448 -+ tab->read_record.read_record= join_no_more_records;
40449 -+ break;
40450 -+
40451 -+ /* keep gcc happy */
40452 -+ default:
40453 -+ break;
40454 -+ }
40455 -+}
40456 -+
40457 -+
40458 -+static void
40459 -+make_join_readinfo(JOIN *join, ulonglong options)
40460 -+{
40461 -+ uint i;
40462 -+ bool statistics= test(!(join->select_options & SELECT_DESCRIBE));
40463 -+ bool ordered_set= 0;
40464 -+ bool sorted= 1;
40465 -+ DBUG_ENTER("make_join_readinfo");
40466 -+
40467 -+ for (i=join->const_tables ; i < join->tables ; i++)
40468 -+ {
40469 -+ JOIN_TAB *tab=join->join_tab+i;
40470 -+ TABLE *table=tab->table;
40471 -+ tab->read_record.table= table;
40472 -+ tab->read_record.file=table->file;
40473 -+ tab->read_record.unlock_row= rr_unlock_row;
40474 -+ tab->next_select=sub_select; /* normal select */
40475 -+
40476 -+ /*
40477 -+ Determine if the set is already ordered for ORDER BY, so it can
40478 -+ disable join cache because it will change the ordering of the results.
40479 -+ Code handles sort table that is at any location (not only first after
40480 -+ the const tables) despite the fact that it's currently prohibited.
40481 -+ We must disable join cache if the first non-const table alone is
40482 -+ ordered. If there is a temp table the ordering is done as a last
40483 -+ operation and doesn't prevent join cache usage.
40484 -+ */
40485 -+ if (!ordered_set && !join->need_tmp &&
40486 -+ (table == join->sort_by_table ||
40487 -+ (join->sort_by_table == (TABLE *) 1 && i != join->const_tables)))
40488 -+ ordered_set= 1;
40489 -+
40490 -+ tab->sorted= sorted;
40491 -+ sorted= 0; // only first must be sorted
40492 -+ table->status=STATUS_NO_RECORD;
40493 -+ pick_table_access_method (tab);
40494 -+
40495 -+ switch (tab->type) {
40496 -+ case JT_EQ_REF:
40497 -+ tab->read_record.unlock_row= join_read_key_unlock_row;
40498 -+ /* fall through */
40499 -+ case JT_REF_OR_NULL:
40500 -+ case JT_REF:
40501 -+ if (tab->select)
40502 -+ {
40503 -+ delete tab->select->quick;
40504 -+ tab->select->quick=0;
40505 -+ }
40506 -+ delete tab->quick;
40507 -+ tab->quick=0;
40508 -+ /* fall through */
40509 -+ case JT_CONST: // Only happens with left join
40510 -+ if (table->covering_keys.is_set(tab->ref.key) &&
40511 -+ !table->no_keyread)
40512 -+ table->set_keyread(TRUE);
40513 -+ break;
40514 -+ case JT_ALL:
40515 -+ /*
40516 -+ If previous table use cache
40517 -+ If the incoming data set is already sorted don't use cache.
40518 -+ */
40519 -+ if (i != join->const_tables && !(options & SELECT_NO_JOIN_CACHE) &&
40520 -+ tab->use_quick != 2 && !tab->first_inner && !ordered_set)
40521 -+ {
40522 -+ if ((options & SELECT_DESCRIBE) ||
40523 -+ !join_init_cache(join->thd,join->join_tab+join->const_tables,
40524 -+ i-join->const_tables))
40525 -+ {
40526 -+ tab[-1].next_select=sub_select_cache; /* Patch previous */
40527 -+ }
40528 -+ }
40529 -+ /* These init changes read_record */
40530 -+ if (tab->use_quick == 2)
40531 -+ {
40532 -+ join->thd->server_status|=SERVER_QUERY_NO_GOOD_INDEX_USED;
40533 -+ tab->read_first_record= join_init_quick_read_record;
40534 -+ if (statistics)
40535 -+ status_var_increment(join->thd->status_var.select_range_check_count);
40536 -+ }
40537 -+ else
40538 -+ {
40539 -+ tab->read_first_record= join_init_read_record;
40540 -+ if (i == join->const_tables)
40541 -+ {
40542 -+ if (tab->select && tab->select->quick)
40543 -+ {
40544 -+ if (statistics)
40545 -+ status_var_increment(join->thd->status_var.select_range_count);
40546 -+ }
40547 -+ else
40548 -+ {
40549 -+ join->thd->server_status|=SERVER_QUERY_NO_INDEX_USED;
40550 -+ if (statistics)
40551 -+ status_var_increment(join->thd->status_var.select_scan_count);
40552 -+ }
40553 -+ }
40554 -+ else
40555 -+ {
40556 -+ if (tab->select && tab->select->quick)
40557 -+ {
40558 -+ if (statistics)
40559 -+ status_var_increment(join->thd->status_var.select_full_range_join_count);
40560 -+ }
40561 -+ else
40562 -+ {
40563 -+ join->thd->server_status|=SERVER_QUERY_NO_INDEX_USED;
40564 -+ if (statistics)
40565 -+ status_var_increment(join->thd->status_var.select_full_join_count);
40566 -+ }
40567 -+ }
40568 -+ if (!table->no_keyread)
40569 -+ {
40570 -+ if (tab->select && tab->select->quick &&
40571 -+ tab->select->quick->index != MAX_KEY && //not index_merge
40572 -+ table->covering_keys.is_set(tab->select->quick->index))
40573 -+ table->set_keyread(TRUE);
40574 -+ else if (!table->covering_keys.is_clear_all() &&
40575 -+ !(tab->select && tab->select->quick))
40576 -+ { // Only read index tree
40577 -+ /*
40578 -+ It has turned out that the below change, while speeding things
40579 -+ up for disk-bound loads, slows them down for cases when the data
40580 -+ is in disk cache (see BUG#35850):
40581 -+ // See bug #26447: "Using the clustered index for a table scan
40582 -+ // is always faster than using a secondary index".
40583 -+ if (table->s->primary_key != MAX_KEY &&
40584 -+ table->file->primary_key_is_clustered())
40585 -+ tab->index= table->s->primary_key;
40586 -+ else
40587 -+ */
40588 -+ tab->index=find_shortest_key(table, & table->covering_keys);
40589 -+ tab->read_first_record= join_read_first;
40590 -+ tab->type=JT_NEXT; // Read with index_first / index_next
40591 -+ }
40592 -+ }
40593 -+ }
40594 -+ break;
40595 -+ case JT_FT:
40596 -+ case JT_SYSTEM:
40597 -+ break;
40598 -+ default:
40599 -+ DBUG_PRINT("error",("Table type %d found",tab->type)); /* purecov: deadcode */
40600 -+ break; /* purecov: deadcode */
40601 -+ case JT_UNKNOWN:
40602 -+ case JT_MAYBE_REF:
40603 -+ abort(); /* purecov: deadcode */
40604 -+ }
40605 -+ }
40606 -+ join->join_tab[join->tables-1].next_select=0; /* Set by do_select */
40607 -+ DBUG_VOID_RETURN;
40608 -+}
40609 -+
40610 -+
40611 -+/**
40612 -+ Give error if we some tables are done with a full join.
40613 -+
40614 -+ This is used by multi_table_update and multi_table_delete when running
40615 -+ in safe mode.
40616 -+
40617 -+ @param join Join condition
40618 -+
40619 -+ @retval
40620 -+ 0 ok
40621 -+ @retval
40622 -+ 1 Error (full join used)
40623 -+*/
40624 -+
40625 -+bool error_if_full_join(JOIN *join)
40626 -+{
40627 -+ for (JOIN_TAB *tab=join->join_tab, *end=join->join_tab+join->tables;
40628 -+ tab < end;
40629 -+ tab++)
40630 -+ {
40631 -+ if (tab->type == JT_ALL && (!tab->select || !tab->select->quick))
40632 -+ {
40633 -+ /* This error should not be ignored. */
40634 -+ join->select_lex->no_error= FALSE;
40635 -+ my_message(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE,
40636 -+ ER(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE), MYF(0));
40637 -+ return(1);
40638 -+ }
40639 -+ }
40640 -+ return(0);
40641 -+}
40642 -+
40643 -+
40644 -+/**
40645 -+ cleanup JOIN_TAB.
40646 -+*/
40647 -+
40648 -+void JOIN_TAB::cleanup()
40649 -+{
40650 -+ delete select;
40651 -+ select= 0;
40652 -+ delete quick;
40653 -+ quick= 0;
40654 -+ x_free(cache.buff);
40655 -+ cache.buff= 0;
40656 -+ limit= 0;
40657 -+ if (table)
40658 -+ {
40659 -+ table->set_keyread(FALSE);
40660 -+ table->file->ha_index_or_rnd_end();
40661 -+ /*
40662 -+ We need to reset this for next select
40663 -+ (Tested in part_of_refkey)
40664 -+ */
40665 -+ table->reginfo.join_tab= 0;
40666 -+ }
40667 -+ end_read_record(&read_record);
40668 -+}
40669 -+
40670 -+
40671 -+/**
40672 -+ Partially cleanup JOIN after it has executed: close index or rnd read
40673 -+ (table cursors), free quick selects.
40674 -+
40675 -+ This function is called in the end of execution of a JOIN, before the used
40676 -+ tables are unlocked and closed.
40677 -+
40678 -+ For a join that is resolved using a temporary table, the first sweep is
40679 -+ performed against actual tables and an intermediate result is inserted
40680 -+ into the temprorary table.
40681 -+ The last sweep is performed against the temporary table. Therefore,
40682 -+ the base tables and associated buffers used to fill the temporary table
40683 -+ are no longer needed, and this function is called to free them.
40684 -+
40685 -+ For a join that is performed without a temporary table, this function
40686 -+ is called after all rows are sent, but before EOF packet is sent.
40687 -+
40688 -+ For a simple SELECT with no subqueries this function performs a full
40689 -+ cleanup of the JOIN and calls mysql_unlock_read_tables to free used base
40690 -+ tables.
40691 -+
40692 -+ If a JOIN is executed for a subquery or if it has a subquery, we can't
40693 -+ do the full cleanup and need to do a partial cleanup only.
40694 -+ - If a JOIN is not the top level join, we must not unlock the tables
40695 -+ because the outer select may not have been evaluated yet, and we
40696 -+ can't unlock only selected tables of a query.
40697 -+ - Additionally, if this JOIN corresponds to a correlated subquery, we
40698 -+ should not free quick selects and join buffers because they will be
40699 -+ needed for the next execution of the correlated subquery.
40700 -+ - However, if this is a JOIN for a [sub]select, which is not
40701 -+ a correlated subquery itself, but has subqueries, we can free it
40702 -+ fully and also free JOINs of all its subqueries. The exception
40703 -+ is a subquery in SELECT list, e.g: @n
40704 -+ SELECT a, (select max(b) from t1) group by c @n
40705 -+ This subquery will not be evaluated at first sweep and its value will
40706 -+ not be inserted into the temporary table. Instead, it's evaluated
40707 -+ when selecting from the temporary table. Therefore, it can't be freed
40708 -+ here even though it's not correlated.
40709 -+
40710 -+ @todo
40711 -+ Unlock tables even if the join isn't top level select in the tree
40712 -+*/
40713 -+
40714 -+void JOIN::join_free()
40715 -+{
40716 -+ SELECT_LEX_UNIT *tmp_unit;
40717 -+ SELECT_LEX *sl;
40718 -+ /*
40719 -+ Optimization: if not EXPLAIN and we are done with the JOIN,
40720 -+ free all tables.
40721 -+ */
40722 -+ bool full= (!select_lex->uncacheable && !thd->lex->describe);
40723 -+ bool can_unlock= full;
40724 -+ DBUG_ENTER("JOIN::join_free");
40725 -+
40726 -+ cleanup(full);
40727 -+
40728 -+ for (tmp_unit= select_lex->first_inner_unit();
40729 -+ tmp_unit;
40730 -+ tmp_unit= tmp_unit->next_unit())
40731 -+ for (sl= tmp_unit->first_select(); sl; sl= sl->next_select())
40732 -+ {
40733 -+ Item_subselect *subselect= sl->master_unit()->item;
40734 -+ bool full_local= full && (!subselect || subselect->is_evaluated());
40735 -+ /*
40736 -+ If this join is evaluated, we can fully clean it up and clean up all
40737 -+ its underlying joins even if they are correlated -- they will not be
40738 -+ used any more anyway.
40739 -+ If this join is not yet evaluated, we still must clean it up to
40740 -+ close its table cursors -- it may never get evaluated, as in case of
40741 -+ ... HAVING FALSE OR a IN (SELECT ...))
40742 -+ but all table cursors must be closed before the unlock.
40743 -+ */
40744 -+ sl->cleanup_all_joins(full_local);
40745 -+ /* Can't unlock if at least one JOIN is still needed */
40746 -+ can_unlock= can_unlock && full_local;
40747 -+ }
40748 -+
40749 -+ /*
40750 -+ We are not using tables anymore
40751 -+ Unlock all tables. We may be in an INSERT .... SELECT statement.
40752 -+ */
40753 -+ if (can_unlock && lock && thd->lock &&
40754 -+ !(select_options & SELECT_NO_UNLOCK) &&
40755 -+ !select_lex->subquery_in_having &&
40756 -+ (select_lex == (thd->lex->unit.fake_select_lex ?
40757 -+ thd->lex->unit.fake_select_lex : &thd->lex->select_lex)))
40758 -+ {
40759 -+ /*
40760 -+ TODO: unlock tables even if the join isn't top level select in the
40761 -+ tree.
40762 -+ */
40763 -+ mysql_unlock_read_tables(thd, lock); // Don't free join->lock
40764 -+ lock= 0;
40765 -+ }
40766 -+
40767 -+ DBUG_VOID_RETURN;
40768 -+}
40769 -+
40770 -+
40771 -+/**
40772 -+ Free resources of given join.
40773 -+
40774 -+ @param fill true if we should free all resources, call with full==1
40775 -+ should be last, before it this function can be called with
40776 -+ full==0
40777 -+
40778 -+ @note
40779 -+ With subquery this function definitely will be called several times,
40780 -+ but even for simple query it can be called several times.
40781 -+*/
40782 -+
40783 -+void JOIN::cleanup(bool full)
40784 -+{
40785 -+ DBUG_ENTER("JOIN::cleanup");
40786 -+
40787 -+ if (table)
40788 -+ {
40789 -+ JOIN_TAB *tab,*end;
40790 -+ /*
40791 -+ Only a sorted table may be cached. This sorted table is always the
40792 -+ first non const table in join->table
40793 -+ */
40794 -+ if (tables > const_tables) // Test for not-const tables
40795 -+ {
40796 -+ free_io_cache(table[const_tables]);
40797 -+ filesort_free_buffers(table[const_tables],full);
40798 -+ }
40799 -+
40800 -+ if (full)
40801 -+ {
40802 -+ for (tab= join_tab, end= tab+tables; tab != end; tab++)
40803 -+ tab->cleanup();
40804 -+ table= 0;
40805 -+ }
40806 -+ else
40807 -+ {
40808 -+ for (tab= join_tab, end= tab+tables; tab != end; tab++)
40809 -+ {
40810 -+ if (tab->table)
40811 -+ tab->table->file->ha_index_or_rnd_end();
40812 -+ }
40813 -+ }
40814 -+ }
40815 -+ /*
40816 -+ We are not using tables anymore
40817 -+ Unlock all tables. We may be in an INSERT .... SELECT statement.
40818 -+ */
40819 -+ if (full)
40820 -+ {
40821 -+ if (tmp_join)
40822 -+ tmp_table_param.copy_field= 0;
40823 -+ group_fields.delete_elements();
40824 -+ /*
40825 -+ Ensure that the above delete_elements() would not be called
40826 -+ twice for the same list.
40827 -+ */
40828 -+ if (tmp_join && tmp_join != this)
40829 -+ tmp_join->group_fields= group_fields;
40830 -+ /*
40831 -+ We can't call delete_elements() on copy_funcs as this will cause
40832 -+ problems in free_elements() as some of the elements are then deleted.
40833 -+ */
40834 -+ tmp_table_param.copy_funcs.empty();
40835 -+ /*
40836 -+ If we have tmp_join and 'this' JOIN is not tmp_join and
40837 -+ tmp_table_param.copy_field's of them are equal then we have to remove
40838 -+ pointer to tmp_table_param.copy_field from tmp_join, because it qill
40839 -+ be removed in tmp_table_param.cleanup().
40840 -+ */
40841 -+ if (tmp_join &&
40842 -+ tmp_join != this &&
40843 -+ tmp_join->tmp_table_param.copy_field ==
40844 -+ tmp_table_param.copy_field)
40845 -+ {
40846 -+ tmp_join->tmp_table_param.copy_field=
40847 -+ tmp_join->tmp_table_param.save_copy_field= 0;
40848 -+ }
40849 -+ tmp_table_param.cleanup();
40850 -+ }
40851 -+ DBUG_VOID_RETURN;
40852 -+}
40853 -+
40854 -+
40855 -+/**
40856 -+ Remove the following expressions from ORDER BY and GROUP BY:
40857 -+ Constant expressions @n
40858 -+ Expression that only uses tables that are of type EQ_REF and the reference
40859 -+ is in the ORDER list or if all refereed tables are of the above type.
40860 -+
40861 -+ In the following, the X field can be removed:
40862 -+ @code
40863 -+ SELECT * FROM t1,t2 WHERE t1.a=t2.a ORDER BY t1.a,t2.X
40864 -+ SELECT * FROM t1,t2,t3 WHERE t1.a=t2.a AND t2.b=t3.b ORDER BY t1.a,t3.X
40865 -+ @endcode
40866 -+
40867 -+ These can't be optimized:
40868 -+ @code
40869 -+ SELECT * FROM t1,t2 WHERE t1.a=t2.a ORDER BY t2.X,t1.a
40870 -+ SELECT * FROM t1,t2 WHERE t1.a=t2.a AND t1.b=t2.b ORDER BY t1.a,t2.c
40871 -+ SELECT * FROM t1,t2 WHERE t1.a=t2.a ORDER BY t2.b,t1.a
40872 -+ @endcode
40873 -+*/
40874 -+
40875 -+static bool
40876 -+eq_ref_table(JOIN *join, ORDER *start_order, JOIN_TAB *tab)
40877 -+{
40878 -+ if (tab->cached_eq_ref_table) // If cached
40879 -+ return tab->eq_ref_table;
40880 -+ tab->cached_eq_ref_table=1;
40881 -+ /* We can skip const tables only if not an outer table */
40882 -+ if (tab->type == JT_CONST && !tab->first_inner)
40883 -+ return (tab->eq_ref_table=1); /* purecov: inspected */
40884 -+ if (tab->type != JT_EQ_REF || tab->table->maybe_null)
40885 -+ return (tab->eq_ref_table=0); // We must use this
40886 -+ Item **ref_item=tab->ref.items;
40887 -+ Item **end=ref_item+tab->ref.key_parts;
40888 -+ uint found=0;
40889 -+ table_map map=tab->table->map;
40890 -+
40891 -+ for (; ref_item != end ; ref_item++)
40892 -+ {
40893 -+ if (! (*ref_item)->const_item())
40894 -+ { // Not a const ref
40895 -+ ORDER *order;
40896 -+ for (order=start_order ; order ; order=order->next)
40897 -+ {
40898 -+ if ((*ref_item)->eq(order->item[0],0))
40899 -+ break;
40900 -+ }
40901 -+ if (order)
40902 -+ {
40903 -+ if (!(order->used & map))
40904 -+ {
40905 -+ found++;
40906 -+ order->used|= map;
40907 -+ }
40908 -+ continue; // Used in ORDER BY
40909 -+ }
40910 -+ if (!only_eq_ref_tables(join,start_order, (*ref_item)->used_tables()))
40911 -+ return (tab->eq_ref_table=0);
40912 -+ }
40913 -+ }
40914 -+ /* Check that there was no reference to table before sort order */
40915 -+ for (; found && start_order ; start_order=start_order->next)
40916 -+ {
40917 -+ if (start_order->used & map)
40918 -+ {
40919 -+ found--;
40920 -+ continue;
40921 -+ }
40922 -+ if (start_order->depend_map & map)
40923 -+ return (tab->eq_ref_table=0);
40924 -+ }
40925 -+ return tab->eq_ref_table=1;
40926 -+}
40927 -+
40928 -+
40929 -+static bool
40930 -+only_eq_ref_tables(JOIN *join,ORDER *order,table_map tables)
40931 -+{
40932 -+ if (specialflag & SPECIAL_SAFE_MODE)
40933 -+ return 0; // skip this optimize /* purecov: inspected */
40934 -+ tables&= ~PSEUDO_TABLE_BITS;
40935 -+ for (JOIN_TAB **tab=join->map2table ; tables ; tab++, tables>>=1)
40936 -+ {
40937 -+ if (tables & 1 && !eq_ref_table(join, order, *tab))
40938 -+ return 0;
40939 -+ }
40940 -+ return 1;
40941 -+}
40942 -+
40943 -+
40944 -+/** Update the dependency map for the tables. */
40945 -+
40946 -+static void update_depend_map(JOIN *join)
40947 -+{
40948 -+ JOIN_TAB *join_tab=join->join_tab, *end=join_tab+join->tables;
40949 -+
40950 -+ for (; join_tab != end ; join_tab++)
40951 -+ {
40952 -+ TABLE_REF *ref= &join_tab->ref;
40953 -+ table_map depend_map=0;
40954 -+ Item **item=ref->items;
40955 -+ uint i;
40956 -+ for (i=0 ; i < ref->key_parts ; i++,item++)
40957 -+ depend_map|=(*item)->used_tables();
40958 -+ ref->depend_map=depend_map & ~OUTER_REF_TABLE_BIT;
40959 -+ depend_map&= ~OUTER_REF_TABLE_BIT;
40960 -+ for (JOIN_TAB **tab=join->map2table;
40961 -+ depend_map ;
40962 -+ tab++,depend_map>>=1 )
40963 -+ {
40964 -+ if (depend_map & 1)
40965 -+ ref->depend_map|=(*tab)->ref.depend_map;
40966 -+ }
40967 -+ }
40968 -+}
40969 -+
40970 -+
40971 -+/** Update the dependency map for the sort order. */
40972 -+
40973 -+static void update_depend_map(JOIN *join, ORDER *order)
40974 -+{
40975 -+ for (; order ; order=order->next)
40976 -+ {
40977 -+ table_map depend_map;
40978 -+ order->item[0]->update_used_tables();
40979 -+ order->depend_map=depend_map=order->item[0]->used_tables();
40980 -+ order->used= 0;
40981 -+ // Not item_sum(), RAND() and no reference to table outside of sub select
40982 -+ if (!(order->depend_map & (OUTER_REF_TABLE_BIT | RAND_TABLE_BIT))
40983 -+ && !order->item[0]->with_sum_func)
40984 -+ {
40985 -+ for (JOIN_TAB **tab=join->map2table;
40986 -+ depend_map ;
40987 -+ tab++, depend_map>>=1)
40988 -+ {
40989 -+ if (depend_map & 1)
40990 -+ order->depend_map|=(*tab)->ref.depend_map;
40991 -+ }
40992 -+ }
40993 -+ }
40994 -+}
40995 -+
40996 -+
40997 -+/**
40998 -+ Remove all constants and check if ORDER only contains simple
40999 -+ expressions.
41000 -+
41001 -+ simple_order is set to 1 if sort_order only uses fields from head table
41002 -+ and the head table is not a LEFT JOIN table.
41003 -+
41004 -+ @param join Join handler
41005 -+ @param first_order List of SORT or GROUP order
41006 -+ @param cond WHERE statement
41007 -+ @param change_list Set to 1 if we should remove things from list.
41008 -+ If this is not set, then only simple_order is
41009 -+ calculated.
41010 -+ @param simple_order Set to 1 if we are only using simple expressions
41011 -+
41012 -+ @return
41013 -+ Returns new sort order
41014 -+*/
41015 -+
41016 -+static ORDER *
41017 -+remove_const(JOIN *join,ORDER *first_order, COND *cond,
41018 -+ bool change_list, bool *simple_order)
41019 -+{
41020 -+ if (join->tables == join->const_tables)
41021 -+ return change_list ? 0 : first_order; // No need to sort
41022 -+
41023 -+ ORDER *order,**prev_ptr;
41024 -+ table_map first_table= join->join_tab[join->const_tables].table->map;
41025 -+ table_map not_const_tables= ~join->const_table_map;
41026 -+ table_map ref;
41027 -+ DBUG_ENTER("remove_const");
41028 -+
41029 -+ prev_ptr= &first_order;
41030 -+ *simple_order= *join->join_tab[join->const_tables].on_expr_ref ? 0 : 1;
41031 -+
41032 -+ /* NOTE: A variable of not_const_tables ^ first_table; breaks gcc 2.7 */
41033 -+
41034 -+ update_depend_map(join, first_order);
41035 -+ for (order=first_order; order ; order=order->next)
41036 -+ {
41037 -+ table_map order_tables=order->item[0]->used_tables();
41038 -+ if (order->item[0]->with_sum_func ||
41039 -+ /*
41040 -+ If the outer table of an outer join is const (either by itself or
41041 -+ after applying WHERE condition), grouping on a field from such a
41042 -+ table will be optimized away and filesort without temporary table
41043 -+ will be used unless we prevent that now. Filesort is not fit to
41044 -+ handle joins and the join condition is not applied. We can't detect
41045 -+ the case without an expensive test, however, so we force temporary
41046 -+ table for all queries containing more than one table, ROLLUP, and an
41047 -+ outer join.
41048 -+ */
41049 -+ (join->tables > 1 && join->rollup.state == ROLLUP::STATE_INITED &&
41050 -+ join->outer_join))
41051 -+ *simple_order=0; // Must do a temp table to sort
41052 -+ else if (!(order_tables & not_const_tables))
41053 -+ {
41054 -+ if (order->item[0]->with_subselect &&
41055 -+ !(join->select_lex->options & SELECT_DESCRIBE))
41056 -+ order->item[0]->val_str(&order->item[0]->str_value);
41057 -+ DBUG_PRINT("info",("removing: %s", order->item[0]->full_name()));
41058 -+ continue; // skip const item
41059 -+ }
41060 -+ else
41061 -+ {
41062 -+ if (order_tables & (RAND_TABLE_BIT | OUTER_REF_TABLE_BIT))
41063 -+ *simple_order=0;
41064 -+ else
41065 -+ {
41066 -+ Item *comp_item=0;
41067 -+ if (cond && const_expression_in_where(cond,order->item[0], &comp_item))
41068 -+ {
41069 -+ DBUG_PRINT("info",("removing: %s", order->item[0]->full_name()));
41070 -+ continue;
41071 -+ }
41072 -+ if ((ref=order_tables & (not_const_tables ^ first_table)))
41073 -+ {
41074 -+ if (!(order_tables & first_table) &&
41075 -+ only_eq_ref_tables(join,first_order, ref))
41076 -+ {
41077 -+ DBUG_PRINT("info",("removing: %s", order->item[0]->full_name()));
41078 -+ continue;
41079 -+ }
41080 -+ *simple_order=0; // Must do a temp table to sort
41081 -+ }
41082 -+ }
41083 -+ }
41084 -+ if (change_list)
41085 -+ *prev_ptr= order; // use this entry
41086 -+ prev_ptr= &order->next;
41087 -+ }
41088 -+ if (change_list)
41089 -+ *prev_ptr=0;
41090 -+ if (prev_ptr == &first_order) // Nothing to sort/group
41091 -+ *simple_order=1;
41092 -+ DBUG_PRINT("exit",("simple_order: %d",(int) *simple_order));
41093 -+ DBUG_RETURN(first_order);
41094 -+}
41095 -+
41096 -+
41097 -+static int
41098 -+return_zero_rows(JOIN *join, select_result *result,TABLE_LIST *tables,
41099 -+ List<Item> &fields, bool send_row, ulonglong select_options,
41100 -+ const char *info, Item *having)
41101 -+{
41102 -+ DBUG_ENTER("return_zero_rows");
41103 -+
41104 -+ if (select_options & SELECT_DESCRIBE)
41105 -+ {
41106 -+ select_describe(join, FALSE, FALSE, FALSE, info);
41107 -+ DBUG_RETURN(0);
41108 -+ }
41109 -+
41110 -+ join->join_free();
41111 -+
41112 -+ if (send_row)
41113 -+ {
41114 -+ for (TABLE_LIST *table= tables; table; table= table->next_leaf)
41115 -+ mark_as_null_row(table->table); // All fields are NULL
41116 -+ if (having && having->val_int() == 0)
41117 -+ send_row=0;
41118 -+ }
41119 -+ if (!(result->send_fields(fields,
41120 -+ Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)))
41121 -+ {
41122 -+ bool send_error= FALSE;
41123 -+ if (send_row)
41124 -+ {
41125 -+ List_iterator_fast<Item> it(fields);
41126 -+ Item *item;
41127 -+ while ((item= it++))
41128 -+ item->no_rows_in_result();
41129 -+ send_error= result->send_data(fields);
41130 -+ }
41131 -+ if (!send_error)
41132 -+ result->send_eof(); // Should be safe
41133 -+ }
41134 -+ /* Update results for FOUND_ROWS */
41135 -+ join->thd->limit_found_rows= join->thd->examined_row_count= 0;
41136 -+ DBUG_RETURN(0);
41137 -+}
41138 -+
41139 -+/*
41140 -+ used only in JOIN::clear
41141 -+*/
41142 -+static void clear_tables(JOIN *join)
41143 -+{
41144 -+ /*
41145 -+ must clear only the non-const tables, as const tables
41146 -+ are not re-calculated.
41147 -+ */
41148 -+ for (uint i=join->const_tables ; i < join->tables ; i++)
41149 -+ mark_as_null_row(join->table[i]); // All fields are NULL
41150 -+}
41151 -+
41152 -+/*****************************************************************************
41153 -+ Make som simple condition optimization:
41154 -+ If there is a test 'field = const' change all refs to 'field' to 'const'
41155 -+ Remove all dummy tests 'item = item', 'const op const'.
41156 -+ Remove all 'item is NULL', when item can never be null!
41157 -+ item->marker should be 0 for all items on entry
41158 -+ Return in cond_value FALSE if condition is impossible (1 = 2)
41159 -+*****************************************************************************/
41160 -+
41161 -+class COND_CMP :public ilink {
41162 -+public:
41163 -+ static void *operator new(size_t size)
41164 -+ {
41165 -+ return (void*) sql_alloc((uint) size);
41166 -+ }
41167 -+ static void operator delete(void *ptr __attribute__((unused)),
41168 -+ size_t size __attribute__((unused)))
41169 -+ { TRASH(ptr, size); }
41170 -+
41171 -+ Item *and_level;
41172 -+ Item_func *cmp_func;
41173 -+ COND_CMP(Item *a,Item_func *b) :and_level(a),cmp_func(b) {}
41174 -+};
41175 -+
41176 -+#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
41177 -+template class I_List<COND_CMP>;
41178 -+template class I_List_iterator<COND_CMP>;
41179 -+template class List<Item_func_match>;
41180 -+template class List_iterator<Item_func_match>;
41181 -+#endif
41182 -+
41183 -+
41184 -+/**
41185 -+ Find the multiple equality predicate containing a field.
41186 -+
41187 -+ The function retrieves the multiple equalities accessed through
41188 -+ the con_equal structure from current level and up looking for
41189 -+ an equality containing field. It stops retrieval as soon as the equality
41190 -+ is found and set up inherited_fl to TRUE if it's found on upper levels.
41191 -+
41192 -+ @param cond_equal multiple equalities to search in
41193 -+ @param field field to look for
41194 -+ @param[out] inherited_fl set up to TRUE if multiple equality is found
41195 -+ on upper levels (not on current level of
41196 -+ cond_equal)
41197 -+
41198 -+ @return
41199 -+ - Item_equal for the found multiple equality predicate if a success;
41200 -+ - NULL otherwise.
41201 -+*/
41202 -+
41203 -+Item_equal *find_item_equal(COND_EQUAL *cond_equal, Field *field,
41204 -+ bool *inherited_fl)
41205 -+{
41206 -+ Item_equal *item= 0;
41207 -+ bool in_upper_level= FALSE;
41208 -+ while (cond_equal)
41209 -+ {
41210 -+ List_iterator_fast<Item_equal> li(cond_equal->current_level);
41211 -+ while ((item= li++))
41212 -+ {
41213 -+ if (item->contains(field))
41214 -+ goto finish;
41215 -+ }
41216 -+ in_upper_level= TRUE;
41217 -+ cond_equal= cond_equal->upper_levels;
41218 -+ }
41219 -+ in_upper_level= FALSE;
41220 -+finish:
41221 -+ *inherited_fl= in_upper_level;
41222 -+ return item;
41223 -+}
41224 -+
41225 -+
41226 -+/**
41227 -+ Check whether an equality can be used to build multiple equalities.
41228 -+
41229 -+ This function first checks whether the equality (left_item=right_item)
41230 -+ is a simple equality i.e. the one that equates a field with another field
41231 -+ or a constant (field=field_item or field=const_item).
41232 -+ If this is the case the function looks for a multiple equality
41233 -+ in the lists referenced directly or indirectly by cond_equal inferring
41234 -+ the given simple equality. If it doesn't find any, it builds a multiple
41235 -+ equality that covers the predicate, i.e. the predicate can be inferred
41236 -+ from this multiple equality.
41237 -+ The built multiple equality could be obtained in such a way:
41238 -+ create a binary multiple equality equivalent to the predicate, then
41239 -+ merge it, if possible, with one of old multiple equalities.
41240 -+ This guarantees that the set of multiple equalities covering equality
41241 -+ predicates will be minimal.
41242 -+
41243 -+ EXAMPLE:
41244 -+ For the where condition
41245 -+ @code
41246 -+ WHERE a=b AND b=c AND
41247 -+ (b=2 OR f=e)
41248 -+ @endcode
41249 -+ the check_equality will be called for the following equality
41250 -+ predicates a=b, b=c, b=2 and f=e.
41251 -+ - For a=b it will be called with *cond_equal=(0,[]) and will transform
41252 -+ *cond_equal into (0,[Item_equal(a,b)]).
41253 -+ - For b=c it will be called with *cond_equal=(0,[Item_equal(a,b)])
41254 -+ and will transform *cond_equal into CE=(0,[Item_equal(a,b,c)]).
41255 -+ - For b=2 it will be called with *cond_equal=(ptr(CE),[])
41256 -+ and will transform *cond_equal into (ptr(CE),[Item_equal(2,a,b,c)]).
41257 -+ - For f=e it will be called with *cond_equal=(ptr(CE), [])
41258 -+ and will transform *cond_equal into (ptr(CE),[Item_equal(f,e)]).
41259 -+
41260 -+ @note
41261 -+ Now only fields that have the same type definitions (verified by
41262 -+ the Field::eq_def method) are placed to the same multiple equalities.
41263 -+ Because of this some equality predicates are not eliminated and
41264 -+ can be used in the constant propagation procedure.
41265 -+ We could weeken the equlity test as soon as at least one of the
41266 -+ equal fields is to be equal to a constant. It would require a
41267 -+ more complicated implementation: we would have to store, in
41268 -+ general case, its own constant for each fields from the multiple
41269 -+ equality. But at the same time it would allow us to get rid
41270 -+ of constant propagation completely: it would be done by the call
41271 -+ to build_equal_items_for_cond.
41272 -+
41273 -+
41274 -+ The implementation does not follow exactly the above rules to
41275 -+ build a new multiple equality for the equality predicate.
41276 -+ If it processes the equality of the form field1=field2, it
41277 -+ looks for multiple equalities me1 containig field1 and me2 containing
41278 -+ field2. If only one of them is found the fuction expands it with
41279 -+ the lacking field. If multiple equalities for both fields are
41280 -+ found they are merged. If both searches fail a new multiple equality
41281 -+ containing just field1 and field2 is added to the existing
41282 -+ multiple equalities.
41283 -+ If the function processes the predicate of the form field1=const,
41284 -+ it looks for a multiple equality containing field1. If found, the
41285 -+ function checks the constant of the multiple equality. If the value
41286 -+ is unknown, it is setup to const. Otherwise the value is compared with
41287 -+ const and the evaluation of the equality predicate is performed.
41288 -+ When expanding/merging equality predicates from the upper levels
41289 -+ the function first copies them for the current level. It looks
41290 -+ acceptable, as this happens rarely. The implementation without
41291 -+ copying would be much more complicated.
41292 -+
41293 -+ @param left_item left term of the quality to be checked
41294 -+ @param right_item right term of the equality to be checked
41295 -+ @param item equality item if the equality originates from a condition
41296 -+ predicate, 0 if the equality is the result of row
41297 -+ elimination
41298 -+ @param cond_equal multiple equalities that must hold together with the
41299 -+ equality
41300 -+
41301 -+ @retval
41302 -+ TRUE if the predicate is a simple equality predicate to be used
41303 -+ for building multiple equalities
41304 -+ @retval
41305 -+ FALSE otherwise
41306 -+*/
41307 -+
41308 -+static bool check_simple_equality(Item *left_item, Item *right_item,
41309 -+ Item *item, COND_EQUAL *cond_equal)
41310 -+{
41311 -+ if (left_item->type() == Item::REF_ITEM &&
41312 -+ ((Item_ref*)left_item)->ref_type() == Item_ref::VIEW_REF)
41313 -+ {
41314 -+ if (((Item_ref*)left_item)->depended_from)
41315 -+ return FALSE;
41316 -+ left_item= left_item->real_item();
41317 -+ }
41318 -+ if (right_item->type() == Item::REF_ITEM &&
41319 -+ ((Item_ref*)right_item)->ref_type() == Item_ref::VIEW_REF)
41320 -+ {
41321 -+ if (((Item_ref*)right_item)->depended_from)
41322 -+ return FALSE;
41323 -+ right_item= right_item->real_item();
41324 -+ }
41325 -+ if (left_item->type() == Item::FIELD_ITEM &&
41326 -+ right_item->type() == Item::FIELD_ITEM &&
41327 -+ !((Item_field*)left_item)->depended_from &&
41328 -+ !((Item_field*)right_item)->depended_from)
41329 -+ {
41330 -+ /* The predicate the form field1=field2 is processed */
41331 -+
41332 -+ Field *left_field= ((Item_field*) left_item)->field;
41333 -+ Field *right_field= ((Item_field*) right_item)->field;
41334 -+
41335 -+ if (!left_field->eq_def(right_field))
41336 -+ return FALSE;
41337 -+
41338 -+ /* Search for multiple equalities containing field1 and/or field2 */
41339 -+ bool left_copyfl, right_copyfl;
41340 -+ Item_equal *left_item_equal=
41341 -+ find_item_equal(cond_equal, left_field, &left_copyfl);
41342 -+ Item_equal *right_item_equal=
41343 -+ find_item_equal(cond_equal, right_field, &right_copyfl);
41344 -+
41345 -+ /* As (NULL=NULL) != TRUE we can't just remove the predicate f=f */
41346 -+ if (left_field->eq(right_field)) /* f = f */
41347 -+ return (!(left_field->maybe_null() && !left_item_equal));
41348 -+
41349 -+ if (left_item_equal && left_item_equal == right_item_equal)
41350 -+ {
41351 -+ /*
41352 -+ The equality predicate is inference of one of the existing
41353 -+ multiple equalities, i.e the condition is already covered
41354 -+ by upper level equalities
41355 -+ */
41356 -+ return TRUE;
41357 -+ }
41358 -+
41359 -+ /* Copy the found multiple equalities at the current level if needed */
41360 -+ if (left_copyfl)
41361 -+ {
41362 -+ /* left_item_equal of an upper level contains left_item */
41363 -+ left_item_equal= new Item_equal(left_item_equal);
41364 -+ cond_equal->current_level.push_back(left_item_equal);
41365 -+ }
41366 -+ if (right_copyfl)
41367 -+ {
41368 -+ /* right_item_equal of an upper level contains right_item */
41369 -+ right_item_equal= new Item_equal(right_item_equal);
41370 -+ cond_equal->current_level.push_back(right_item_equal);
41371 -+ }
41372 -+
41373 -+ if (left_item_equal)
41374 -+ {
41375 -+ /* left item was found in the current or one of the upper levels */
41376 -+ if (! right_item_equal)
41377 -+ left_item_equal->add((Item_field *) right_item);
41378 -+ else
41379 -+ {
41380 -+ /* Merge two multiple equalities forming a new one */
41381 -+ left_item_equal->merge(right_item_equal);
41382 -+ /* Remove the merged multiple equality from the list */
41383 -+ List_iterator<Item_equal> li(cond_equal->current_level);
41384 -+ while ((li++) != right_item_equal) ;
41385 -+ li.remove();
41386 -+ }
41387 -+ }
41388 -+ else
41389 -+ {
41390 -+ /* left item was not found neither the current nor in upper levels */
41391 -+ if (right_item_equal)
41392 -+ right_item_equal->add((Item_field *) left_item);
41393 -+ else
41394 -+ {
41395 -+ /* None of the fields was found in multiple equalities */
41396 -+ Item_equal *item_equal= new Item_equal((Item_field *) left_item,
41397 -+ (Item_field *) right_item);
41398 -+ cond_equal->current_level.push_back(item_equal);
41399 -+ }
41400 -+ }
41401 -+ return TRUE;
41402 -+ }
41403 -+
41404 -+ {
41405 -+ /* The predicate of the form field=const/const=field is processed */
41406 -+ Item *const_item= 0;
41407 -+ Item_field *field_item= 0;
41408 -+ if (left_item->type() == Item::FIELD_ITEM &&
41409 -+ !((Item_field*)left_item)->depended_from &&
41410 -+ right_item->const_item())
41411 -+ {
41412 -+ field_item= (Item_field*) left_item;
41413 -+ const_item= right_item;
41414 -+ }
41415 -+ else if (right_item->type() == Item::FIELD_ITEM &&
41416 -+ !((Item_field*)right_item)->depended_from &&
41417 -+ left_item->const_item())
41418 -+ {
41419 -+ field_item= (Item_field*) right_item;
41420 -+ const_item= left_item;
41421 -+ }
41422 -+
41423 -+ if (const_item &&
41424 -+ field_item->result_type() == const_item->result_type())
41425 -+ {
41426 -+ bool copyfl;
41427 -+
41428 -+ if (field_item->result_type() == STRING_RESULT)
41429 -+ {
41430 -+ CHARSET_INFO *cs= ((Field_str*) field_item->field)->charset();
41431 -+ if (!item)
41432 -+ {
41433 -+ Item_func_eq *eq_item;
41434 -+ if ((eq_item= new Item_func_eq(left_item, right_item)))
41435 -+ return FALSE;
41436 -+ eq_item->set_cmp_func();
41437 -+ eq_item->quick_fix_field();
41438 -+ item= eq_item;
41439 -+ }
41440 -+ if ((cs != ((Item_func *) item)->compare_collation()) ||
41441 -+ !cs->coll->propagate(cs, 0, 0))
41442 -+ return FALSE;
41443 -+ }
41444 -+
41445 -+ Item_equal *item_equal = find_item_equal(cond_equal,
41446 -+ field_item->field, &copyfl);
41447 -+ if (copyfl)
41448 -+ {
41449 -+ item_equal= new Item_equal(item_equal);
41450 -+ cond_equal->current_level.push_back(item_equal);
41451 -+ }
41452 -+ if (item_equal)
41453 -+ {
41454 -+ /*
41455 -+ The flag cond_false will be set to 1 after this, if item_equal
41456 -+ already contains a constant and its value is not equal to
41457 -+ the value of const_item.
41458 -+ */
41459 -+ item_equal->add(const_item, field_item);
41460 -+ }
41461 -+ else
41462 -+ {
41463 -+ item_equal= new Item_equal(const_item, field_item);
41464 -+ cond_equal->current_level.push_back(item_equal);
41465 -+ }
41466 -+ return TRUE;
41467 -+ }
41468 -+ }
41469 -+ return FALSE;
41470 -+}
41471 -+
41472 -+
41473 -+/**
41474 -+ Convert row equalities into a conjunction of regular equalities.
41475 -+
41476 -+ The function converts a row equality of the form (E1,...,En)=(E'1,...,E'n)
41477 -+ into a list of equalities E1=E'1,...,En=E'n. For each of these equalities
41478 -+ Ei=E'i the function checks whether it is a simple equality or a row
41479 -+ equality. If it is a simple equality it is used to expand multiple
41480 -+ equalities of cond_equal. If it is a row equality it converted to a
41481 -+ sequence of equalities between row elements. If Ei=E'i is neither a
41482 -+ simple equality nor a row equality the item for this predicate is added
41483 -+ to eq_list.
41484 -+
41485 -+ @param thd thread handle
41486 -+ @param left_row left term of the row equality to be processed
41487 -+ @param right_row right term of the row equality to be processed
41488 -+ @param cond_equal multiple equalities that must hold together with the
41489 -+ predicate
41490 -+ @param eq_list results of conversions of row equalities that are not
41491 -+ simple enough to form multiple equalities
41492 -+
41493 -+ @retval
41494 -+ TRUE if conversion has succeeded (no fatal error)
41495 -+ @retval
41496 -+ FALSE otherwise
41497 -+*/
41498 -+
41499 -+static bool check_row_equality(THD *thd, Item *left_row, Item_row *right_row,
41500 -+ COND_EQUAL *cond_equal, List<Item>* eq_list)
41501 -+{
41502 -+ uint n= left_row->cols();
41503 -+ for (uint i= 0 ; i < n; i++)
41504 -+ {
41505 -+ bool is_converted;
41506 -+ Item *left_item= left_row->element_index(i);
41507 -+ Item *right_item= right_row->element_index(i);
41508 -+ if (left_item->type() == Item::ROW_ITEM &&
41509 -+ right_item->type() == Item::ROW_ITEM)
41510 -+ {
41511 -+ is_converted= check_row_equality(thd,
41512 -+ (Item_row *) left_item,
41513 -+ (Item_row *) right_item,
41514 -+ cond_equal, eq_list);
41515 -+ if (!is_converted)
41516 -+ thd->lex->current_select->cond_count++;
41517 -+ }
41518 -+ else
41519 -+ {
41520 -+ is_converted= check_simple_equality(left_item, right_item, 0, cond_equal);
41521 -+ thd->lex->current_select->cond_count++;
41522 -+ }
41523 -+
41524 -+ if (!is_converted)
41525 -+ {
41526 -+ Item_func_eq *eq_item;
41527 -+ if (!(eq_item= new Item_func_eq(left_item, right_item)))
41528 -+ return FALSE;
41529 -+ eq_item->set_cmp_func();
41530 -+ eq_item->quick_fix_field();
41531 -+ eq_list->push_back(eq_item);
41532 -+ }
41533 -+ }
41534 -+ return TRUE;
41535 -+}
41536 -+
41537 -+
41538 -+/**
41539 -+ Eliminate row equalities and form multiple equalities predicates.
41540 -+
41541 -+ This function checks whether the item is a simple equality
41542 -+ i.e. the one that equates a field with another field or a constant
41543 -+ (field=field_item or field=constant_item), or, a row equality.
41544 -+ For a simple equality the function looks for a multiple equality
41545 -+ in the lists referenced directly or indirectly by cond_equal inferring
41546 -+ the given simple equality. If it doesn't find any, it builds/expands
41547 -+ multiple equality that covers the predicate.
41548 -+ Row equalities are eliminated substituted for conjunctive regular
41549 -+ equalities which are treated in the same way as original equality
41550 -+ predicates.
41551 -+
41552 -+ @param thd thread handle
41553 -+ @param item predicate to process
41554 -+ @param cond_equal multiple equalities that must hold together with the
41555 -+ predicate
41556 -+ @param eq_list results of conversions of row equalities that are not
41557 -+ simple enough to form multiple equalities
41558 -+
41559 -+ @retval
41560 -+ TRUE if re-writing rules have been applied
41561 -+ @retval
41562 -+ FALSE otherwise, i.e.
41563 -+ if the predicate is not an equality,
41564 -+ or, if the equality is neither a simple one nor a row equality,
41565 -+ or, if the procedure fails by a fatal error.
41566 -+*/
41567 -+
41568 -+static bool check_equality(THD *thd, Item *item, COND_EQUAL *cond_equal,
41569 -+ List<Item> *eq_list)
41570 -+{
41571 -+ if (item->type() == Item::FUNC_ITEM &&
41572 -+ ((Item_func*) item)->functype() == Item_func::EQ_FUNC)
41573 -+ {
41574 -+ Item *left_item= ((Item_func*) item)->arguments()[0];
41575 -+ Item *right_item= ((Item_func*) item)->arguments()[1];
41576 -+
41577 -+ if (left_item->type() == Item::ROW_ITEM &&
41578 -+ right_item->type() == Item::ROW_ITEM)
41579 -+ {
41580 -+ thd->lex->current_select->cond_count--;
41581 -+ return check_row_equality(thd,
41582 -+ (Item_row *) left_item,
41583 -+ (Item_row *) right_item,
41584 -+ cond_equal, eq_list);
41585 -+ }
41586 -+ else
41587 -+ return check_simple_equality(left_item, right_item, item, cond_equal);
41588 -+ }
41589 -+ return FALSE;
41590 -+}
41591 -+
41592 -+
41593 -+/**
41594 -+ Replace all equality predicates in a condition by multiple equality items.
41595 -+
41596 -+ At each 'and' level the function detects items for equality predicates
41597 -+ and replaced them by a set of multiple equality items of class Item_equal,
41598 -+ taking into account inherited equalities from upper levels.
41599 -+ If an equality predicate is used not in a conjunction it's just
41600 -+ replaced by a multiple equality predicate.
41601 -+ For each 'and' level the function set a pointer to the inherited
41602 -+ multiple equalities in the cond_equal field of the associated
41603 -+ object of the type Item_cond_and.
41604 -+ The function also traverses the cond tree and and for each field reference
41605 -+ sets a pointer to the multiple equality item containing the field, if there
41606 -+ is any. If this multiple equality equates fields to a constant the
41607 -+ function replaces the field reference by the constant in the cases
41608 -+ when the field is not of a string type or when the field reference is
41609 -+ just an argument of a comparison predicate.
41610 -+ The function also determines the maximum number of members in
41611 -+ equality lists of each Item_cond_and object assigning it to
41612 -+ thd->lex->current_select->max_equal_elems.
41613 -+
41614 -+ @note
41615 -+ Multiple equality predicate =(f1,..fn) is equivalent to the conjuction of
41616 -+ f1=f2, .., fn-1=fn. It substitutes any inference from these
41617 -+ equality predicates that is equivalent to the conjunction.
41618 -+ Thus, =(a1,a2,a3) can substitute for ((a1=a3) AND (a2=a3) AND (a2=a1)) as
41619 -+ it is equivalent to ((a1=a2) AND (a2=a3)).
41620 -+ The function always makes a substitution of all equality predicates occured
41621 -+ in a conjuction for a minimal set of multiple equality predicates.
41622 -+ This set can be considered as a canonical representation of the
41623 -+ sub-conjunction of the equality predicates.
41624 -+ E.g. (t1.a=t2.b AND t2.b>5 AND t1.a=t3.c) is replaced by
41625 -+ (=(t1.a,t2.b,t3.c) AND t2.b>5), not by
41626 -+ (=(t1.a,t2.b) AND =(t1.a,t3.c) AND t2.b>5);
41627 -+ while (t1.a=t2.b AND t2.b>5 AND t3.c=t4.d) is replaced by
41628 -+ (=(t1.a,t2.b) AND =(t3.c=t4.d) AND t2.b>5),
41629 -+ but if additionally =(t4.d,t2.b) is inherited, it
41630 -+ will be replaced by (=(t1.a,t2.b,t3.c,t4.d) AND t2.b>5)
41631 -+
41632 -+ The function performs the substitution in a recursive descent by
41633 -+ the condtion tree, passing to the next AND level a chain of multiple
41634 -+ equality predicates which have been built at the upper levels.
41635 -+ The Item_equal items built at the level are attached to other
41636 -+ non-equality conjucts as a sublist. The pointer to the inherited
41637 -+ multiple equalities is saved in the and condition object (Item_cond_and).
41638 -+ This chain allows us for any field reference occurence easyly to find a
41639 -+ multiple equality that must be held for this occurence.
41640 -+ For each AND level we do the following:
41641 -+ - scan it for all equality predicate (=) items
41642 -+ - join them into disjoint Item_equal() groups
41643 -+ - process the included OR conditions recursively to do the same for
41644 -+ lower AND levels.
41645 -+
41646 -+ We need to do things in this order as lower AND levels need to know about
41647 -+ all possible Item_equal objects in upper levels.
41648 -+
41649 -+ @param thd thread handle
41650 -+ @param cond condition(expression) where to make replacement
41651 -+ @param inherited path to all inherited multiple equality items
41652 -+
41653 -+ @return
41654 -+ pointer to the transformed condition
41655 -+*/
41656 -+
41657 -+static COND *build_equal_items_for_cond(THD *thd, COND *cond,
41658 -+ COND_EQUAL *inherited)
41659 -+{
41660 -+ Item_equal *item_equal;
41661 -+ COND_EQUAL cond_equal;
41662 -+ cond_equal.upper_levels= inherited;
41663 -+
41664 -+ if (cond->type() == Item::COND_ITEM)
41665 -+ {
41666 -+ List<Item> eq_list;
41667 -+ bool and_level= ((Item_cond*) cond)->functype() ==
41668 -+ Item_func::COND_AND_FUNC;
41669 -+ List<Item> *args= ((Item_cond*) cond)->argument_list();
41670 -+
41671 -+ List_iterator<Item> li(*args);
41672 -+ Item *item;
41673 -+
41674 -+ if (and_level)
41675 -+ {
41676 -+ /*
41677 -+ Retrieve all conjuncts of this level detecting the equality
41678 -+ that are subject to substitution by multiple equality items and
41679 -+ removing each such predicate from the conjunction after having
41680 -+ found/created a multiple equality whose inference the predicate is.
41681 -+ */
41682 -+ while ((item= li++))
41683 -+ {
41684 -+ /*
41685 -+ PS/SP note: we can safely remove a node from AND-OR
41686 -+ structure here because it's restored before each
41687 -+ re-execution of any prepared statement/stored procedure.
41688 -+ */
41689 -+ if (check_equality(thd, item, &cond_equal, &eq_list))
41690 -+ li.remove();
41691 -+ }
41692 -+
41693 -+ /*
41694 -+ Check if we eliminated all the predicates of the level, e.g.
41695 -+ (a=a AND b=b AND a=a).
41696 -+ */
41697 -+ if (!args->elements &&
41698 -+ !cond_equal.current_level.elements &&
41699 -+ !eq_list.elements)
41700 -+ return new Item_int((longlong) 1, 1);
41701 -+
41702 -+ List_iterator_fast<Item_equal> it(cond_equal.current_level);
41703 -+ while ((item_equal= it++))
41704 -+ {
41705 -+ item_equal->fix_length_and_dec();
41706 -+ item_equal->update_used_tables();
41707 -+ set_if_bigger(thd->lex->current_select->max_equal_elems,
41708 -+ item_equal->members());
41709 -+ }
41710 -+
41711 -+ ((Item_cond_and*)cond)->cond_equal= cond_equal;
41712 -+ inherited= &(((Item_cond_and*)cond)->cond_equal);
41713 -+ }
41714 -+ /*
41715 -+ Make replacement of equality predicates for lower levels
41716 -+ of the condition expression.
41717 -+ */
41718 -+ li.rewind();
41719 -+ while ((item= li++))
41720 -+ {
41721 -+ Item *new_item;
41722 -+ if ((new_item= build_equal_items_for_cond(thd, item, inherited)) != item)
41723 -+ {
41724 -+ /* This replacement happens only for standalone equalities */
41725 -+ /*
41726 -+ This is ok with PS/SP as the replacement is done for
41727 -+ arguments of an AND/OR item, which are restored for each
41728 -+ execution of PS/SP.
41729 -+ */
41730 -+ li.replace(new_item);
41731 -+ }
41732 -+ }
41733 -+ if (and_level)
41734 -+ {
41735 -+ args->concat(&eq_list);
41736 -+ args->concat((List<Item> *)&cond_equal.current_level);
41737 -+ }
41738 -+ }
41739 -+ else if (cond->type() == Item::FUNC_ITEM)
41740 -+ {
41741 -+ List<Item> eq_list;
41742 -+ /*
41743 -+ If an equality predicate forms the whole and level,
41744 -+ we call it standalone equality and it's processed here.
41745 -+ E.g. in the following where condition
41746 -+ WHERE a=5 AND (b=5 or a=c)
41747 -+ (b=5) and (a=c) are standalone equalities.
41748 -+ In general we can't leave alone standalone eqalities:
41749 -+ for WHERE a=b AND c=d AND (b=c OR d=5)
41750 -+ b=c is replaced by =(a,b,c,d).
41751 -+ */
41752 -+ if (check_equality(thd, cond, &cond_equal, &eq_list))
41753 -+ {
41754 -+ int n= cond_equal.current_level.elements + eq_list.elements;
41755 -+ if (n == 0)
41756 -+ return new Item_int((longlong) 1,1);
41757 -+ else if (n == 1)
41758 -+ {
41759 -+ if ((item_equal= cond_equal.current_level.pop()))
41760 -+ {
41761 -+ item_equal->fix_length_and_dec();
41762 -+ item_equal->update_used_tables();
41763 -+ set_if_bigger(thd->lex->current_select->max_equal_elems,
41764 -+ item_equal->members());
41765 -+ return item_equal;
41766 -+ }
41767 -+
41768 -+ return eq_list.pop();
41769 -+ }
41770 -+ else
41771 -+ {
41772 -+ /*
41773 -+ Here a new AND level must be created. It can happen only
41774 -+ when a row equality is processed as a standalone predicate.
41775 -+ */
41776 -+ Item_cond_and *and_cond= new Item_cond_and(eq_list);
41777 -+ and_cond->quick_fix_field();
41778 -+ List<Item> *args= and_cond->argument_list();
41779 -+ List_iterator_fast<Item_equal> it(cond_equal.current_level);
41780 -+ while ((item_equal= it++))
41781 -+ {
41782 -+ item_equal->fix_length_and_dec();
41783 -+ item_equal->update_used_tables();
41784 -+ set_if_bigger(thd->lex->current_select->max_equal_elems,
41785 -+ item_equal->members());
41786 -+ }
41787 -+ and_cond->cond_equal= cond_equal;
41788 -+ args->concat((List<Item> *)&cond_equal.current_level);
41789 -+
41790 -+ return and_cond;
41791 -+ }
41792 -+ }
41793 -+ /*
41794 -+ For each field reference in cond, not from equal item predicates,
41795 -+ set a pointer to the multiple equality it belongs to (if there is any)
41796 -+ as soon the field is not of a string type or the field reference is
41797 -+ an argument of a comparison predicate.
41798 -+ */
41799 -+ uchar *is_subst_valid= (uchar *) 1;
41800 -+ cond= cond->compile(&Item::subst_argument_checker,
41801 -+ &is_subst_valid,
41802 -+ &Item::equal_fields_propagator,
41803 -+ (uchar *) inherited);
41804 -+ cond->update_used_tables();
41805 -+ }
41806 -+ return cond;
41807 -+}
41808 -+
41809 -+
41810 -+/**
41811 -+ Build multiple equalities for a condition and all on expressions that
41812 -+ inherit these multiple equalities.
41813 -+
41814 -+ The function first applies the build_equal_items_for_cond function
41815 -+ to build all multiple equalities for condition cond utilizing equalities
41816 -+ referred through the parameter inherited. The extended set of
41817 -+ equalities is returned in the structure referred by the cond_equal_ref
41818 -+ parameter. After this the function calls itself recursively for
41819 -+ all on expressions whose direct references can be found in join_list
41820 -+ and who inherit directly the multiple equalities just having built.
41821 -+
41822 -+ @note
41823 -+ The on expression used in an outer join operation inherits all equalities
41824 -+ from the on expression of the embedding join, if there is any, or
41825 -+ otherwise - from the where condition.
41826 -+ This fact is not obvious, but presumably can be proved.
41827 -+ Consider the following query:
41828 -+ @code
41829 -+ SELECT * FROM (t1,t2) LEFT JOIN (t3,t4) ON t1.a=t3.a AND t2.a=t4.a
41830 -+ WHERE t1.a=t2.a;
41831 -+ @endcode
41832 -+ If the on expression in the query inherits =(t1.a,t2.a), then we
41833 -+ can build the multiple equality =(t1.a,t2.a,t3.a,t4.a) that infers
41834 -+ the equality t3.a=t4.a. Although the on expression
41835 -+ t1.a=t3.a AND t2.a=t4.a AND t3.a=t4.a is not equivalent to the one
41836 -+ in the query the latter can be replaced by the former: the new query
41837 -+ will return the same result set as the original one.
41838 -+
41839 -+ Interesting that multiple equality =(t1.a,t2.a,t3.a,t4.a) allows us
41840 -+ to use t1.a=t3.a AND t3.a=t4.a under the on condition:
41841 -+ @code
41842 -+ SELECT * FROM (t1,t2) LEFT JOIN (t3,t4) ON t1.a=t3.a AND t3.a=t4.a
41843 -+ WHERE t1.a=t2.a
41844 -+ @endcode
41845 -+ This query equivalent to:
41846 -+ @code
41847 -+ SELECT * FROM (t1 LEFT JOIN (t3,t4) ON t1.a=t3.a AND t3.a=t4.a),t2
41848 -+ WHERE t1.a=t2.a
41849 -+ @endcode
41850 -+ Similarly the original query can be rewritten to the query:
41851 -+ @code
41852 -+ SELECT * FROM (t1,t2) LEFT JOIN (t3,t4) ON t2.a=t4.a AND t3.a=t4.a
41853 -+ WHERE t1.a=t2.a
41854 -+ @endcode
41855 -+ that is equivalent to:
41856 -+ @code
41857 -+ SELECT * FROM (t2 LEFT JOIN (t3,t4)ON t2.a=t4.a AND t3.a=t4.a), t1
41858 -+ WHERE t1.a=t2.a
41859 -+ @endcode
41860 -+ Thus, applying equalities from the where condition we basically
41861 -+ can get more freedom in performing join operations.
41862 -+ Althogh we don't use this property now, it probably makes sense to use
41863 -+ it in the future.
41864 -+ @param thd Thread handler
41865 -+ @param cond condition to build the multiple equalities for
41866 -+ @param inherited path to all inherited multiple equality items
41867 -+ @param join_list list of join tables to which the condition
41868 -+ refers to
41869 -+ @param[out] cond_equal_ref pointer to the structure to place built
41870 -+ equalities in
41871 -+
41872 -+ @return
41873 -+ pointer to the transformed condition containing multiple equalities
41874 -+*/
41875 -+
41876 -+static COND *build_equal_items(THD *thd, COND *cond,
41877 -+ COND_EQUAL *inherited,
41878 -+ List<TABLE_LIST> *join_list,
41879 -+ COND_EQUAL **cond_equal_ref)
41880 -+{
41881 -+ COND_EQUAL *cond_equal= 0;
41882 -+
41883 -+ if (cond)
41884 -+ {
41885 -+ cond= build_equal_items_for_cond(thd, cond, inherited);
41886 -+ cond->update_used_tables();
41887 -+ if (cond->type() == Item::COND_ITEM &&
41888 -+ ((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
41889 -+ cond_equal= &((Item_cond_and*) cond)->cond_equal;
41890 -+ else if (cond->type() == Item::FUNC_ITEM &&
41891 -+ ((Item_cond*) cond)->functype() == Item_func::MULT_EQUAL_FUNC)
41892 -+ {
41893 -+ cond_equal= new COND_EQUAL;
41894 -+ cond_equal->current_level.push_back((Item_equal *) cond);
41895 -+ }
41896 -+ }
41897 -+ if (cond_equal)
41898 -+ {
41899 -+ cond_equal->upper_levels= inherited;
41900 -+ inherited= cond_equal;
41901 -+ }
41902 -+ *cond_equal_ref= cond_equal;
41903 -+
41904 -+ if (join_list)
41905 -+ {
41906 -+ TABLE_LIST *table;
41907 -+ List_iterator<TABLE_LIST> li(*join_list);
41908 -+
41909 -+ while ((table= li++))
41910 -+ {
41911 -+ if (table->on_expr)
41912 -+ {
41913 -+ List<TABLE_LIST> *nested_join_list= table->nested_join ?
41914 -+ &table->nested_join->join_list : NULL;
41915 -+ /*
41916 -+ We can modify table->on_expr because its old value will
41917 -+ be restored before re-execution of PS/SP.
41918 -+ */
41919 -+ table->on_expr= build_equal_items(thd, table->on_expr, inherited,
41920 -+ nested_join_list,
41921 -+ &table->cond_equal);
41922 -+ }
41923 -+ }
41924 -+ }
41925 -+
41926 -+ return cond;
41927 -+}
41928 -+
41929 -+
41930 -+/**
41931 -+ Compare field items by table order in the execution plan.
41932 -+
41933 -+ field1 considered as better than field2 if the table containing
41934 -+ field1 is accessed earlier than the table containing field2.
41935 -+ The function finds out what of two fields is better according
41936 -+ this criteria.
41937 -+
41938 -+ @param field1 first field item to compare
41939 -+ @param field2 second field item to compare
41940 -+ @param table_join_idx index to tables determining table order
41941 -+
41942 -+ @retval
41943 -+ 1 if field1 is better than field2
41944 -+ @retval
41945 -+ -1 if field2 is better than field1
41946 -+ @retval
41947 -+ 0 otherwise
41948 -+*/
41949 -+
41950 -+static int compare_fields_by_table_order(Item_field *field1,
41951 -+ Item_field *field2,
41952 -+ void *table_join_idx)
41953 -+{
41954 -+ int cmp= 0;
41955 -+ bool outer_ref= 0;
41956 -+ if (field2->used_tables() & OUTER_REF_TABLE_BIT)
41957 -+ {
41958 -+ outer_ref= 1;
41959 -+ cmp= -1;
41960 -+ }
41961 -+ if (field2->used_tables() & OUTER_REF_TABLE_BIT)
41962 -+ {
41963 -+ outer_ref= 1;
41964 -+ cmp++;
41965 -+ }
41966 -+ if (outer_ref)
41967 -+ return cmp;
41968 -+ JOIN_TAB **idx= (JOIN_TAB **) table_join_idx;
41969 -+ cmp= idx[field2->field->table->tablenr]-idx[field1->field->table->tablenr];
41970 -+ return cmp < 0 ? -1 : (cmp ? 1 : 0);
41971 -+}
41972 -+
41973 -+
41974 -+/**
41975 -+ Generate minimal set of simple equalities equivalent to a multiple equality.
41976 -+
41977 -+ The function retrieves the fields of the multiple equality item
41978 -+ item_equal and for each field f:
41979 -+ - if item_equal contains const it generates the equality f=const_item;
41980 -+ - otherwise, if f is not the first field, generates the equality
41981 -+ f=item_equal->get_first().
41982 -+ All generated equality are added to the cond conjunction.
41983 -+
41984 -+ @param cond condition to add the generated equality to
41985 -+ @param upper_levels structure to access multiple equality of upper levels
41986 -+ @param item_equal multiple equality to generate simple equality from
41987 -+
41988 -+ @note
41989 -+ Before generating an equality function checks that it has not
41990 -+ been generated for multiple equalities of the upper levels.
41991 -+ E.g. for the following where condition
41992 -+ WHERE a=5 AND ((a=b AND b=c) OR c>4)
41993 -+ the upper level AND condition will contain =(5,a),
41994 -+ while the lower level AND condition will contain =(5,a,b,c).
41995 -+ When splitting =(5,a,b,c) into a separate equality predicates
41996 -+ we should omit 5=a, as we have it already in the upper level.
41997 -+ The following where condition gives us a more complicated case:
41998 -+ WHERE t1.a=t2.b AND t3.c=t4.d AND (t2.b=t3.c OR t4.e>5 ...) AND ...
41999 -+ Given the tables are accessed in the order t1->t2->t3->t4 for
42000 -+ the selected query execution plan the lower level multiple
42001 -+ equality =(t1.a,t2.b,t3.c,t4.d) formally should be converted to
42002 -+ t1.a=t2.b AND t1.a=t3.c AND t1.a=t4.d. But t1.a=t2.a will be
42003 -+ generated for the upper level. Also t3.c=t4.d will be generated there.
42004 -+ So only t1.a=t3.c should be left in the lower level.
42005 -+ If cond is equal to 0, then not more then one equality is generated
42006 -+ and a pointer to it is returned as the result of the function.
42007 -+
42008 -+ @return
42009 -+ - The condition with generated simple equalities or
42010 -+ a pointer to the simple generated equality, if success.
42011 -+ - 0, otherwise.
42012 -+*/
42013 -+
42014 -+static Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels,
42015 -+ Item_equal *item_equal)
42016 -+{
42017 -+ List<Item> eq_list;
42018 -+ Item_func_eq *eq_item= 0;
42019 -+ if (((Item *) item_equal)->const_item() && !item_equal->val_int())
42020 -+ return new Item_int((longlong) 0,1);
42021 -+ Item *item_const= item_equal->get_const();
42022 -+ Item_equal_iterator it(*item_equal);
42023 -+ Item *head;
42024 -+ if (item_const)
42025 -+ head= item_const;
42026 -+ else
42027 -+ {
42028 -+ head= item_equal->get_first();
42029 -+ it++;
42030 -+ }
42031 -+ Item_field *item_field;
42032 -+ while ((item_field= it++))
42033 -+ {
42034 -+ Item_equal *upper= item_field->find_item_equal(upper_levels);
42035 -+ Item_field *item= item_field;
42036 -+ if (upper)
42037 -+ {
42038 -+ if (item_const && upper->get_const())
42039 -+ item= 0;
42040 -+ else
42041 -+ {
42042 -+ Item_equal_iterator li(*item_equal);
42043 -+ while ((item= li++) != item_field)
42044 -+ {
42045 -+ if (item->find_item_equal(upper_levels) == upper)
42046 -+ break;
42047 -+ }
42048 -+ }
42049 -+ }
42050 -+ if (item == item_field)
42051 -+ {
42052 -+ if (eq_item)
42053 -+ eq_list.push_back(eq_item);
42054 -+ eq_item= new Item_func_eq(item_field, head);
42055 -+ if (!eq_item)
42056 -+ return 0;
42057 -+ eq_item->set_cmp_func();
42058 -+ eq_item->quick_fix_field();
42059 -+ }
42060 -+ }
42061 -+
42062 -+ if (!cond && !eq_list.head())
42063 -+ {
42064 -+ if (!eq_item)
42065 -+ return new Item_int((longlong) 1,1);
42066 -+ return eq_item;
42067 -+ }
42068 -+
42069 -+ if (eq_item)
42070 -+ eq_list.push_back(eq_item);
42071 -+ if (!cond)
42072 -+ cond= new Item_cond_and(eq_list);
42073 -+ else
42074 -+ {
42075 -+ DBUG_ASSERT(cond->type() == Item::COND_ITEM);
42076 -+ if (eq_list.elements)
42077 -+ ((Item_cond *) cond)->add_at_head(&eq_list);
42078 -+ }
42079 -+
42080 -+ cond->quick_fix_field();
42081 -+ cond->update_used_tables();
42082 -+
42083 -+ return cond;
42084 -+}
42085 -+
42086 -+
42087 -+/**
42088 -+ Substitute every field reference in a condition by the best equal field
42089 -+ and eliminate all multiple equality predicates.
42090 -+
42091 -+ The function retrieves the cond condition and for each encountered
42092 -+ multiple equality predicate it sorts the field references in it
42093 -+ according to the order of tables specified by the table_join_idx
42094 -+ parameter. Then it eliminates the multiple equality predicate it
42095 -+ replacing it by the conjunction of simple equality predicates
42096 -+ equating every field from the multiple equality to the first
42097 -+ field in it, or to the constant, if there is any.
42098 -+ After this the function retrieves all other conjuncted
42099 -+ predicates substitute every field reference by the field reference
42100 -+ to the first equal field or equal constant if there are any.
42101 -+ @param cond condition to process
42102 -+ @param cond_equal multiple equalities to take into consideration
42103 -+ @param table_join_idx index to tables determining field preference
42104 -+
42105 -+ @note
42106 -+ At the first glance full sort of fields in multiple equality
42107 -+ seems to be an overkill. Yet it's not the case due to possible
42108 -+ new fields in multiple equality item of lower levels. We want
42109 -+ the order in them to comply with the order of upper levels.
42110 -+
42111 -+ @return
42112 -+ The transformed condition
42113 -+*/
42114 -+
42115 -+static COND* substitute_for_best_equal_field(COND *cond,
42116 -+ COND_EQUAL *cond_equal,
42117 -+ void *table_join_idx)
42118 -+{
42119 -+ Item_equal *item_equal;
42120 -+
42121 -+ if (cond->type() == Item::COND_ITEM)
42122 -+ {
42123 -+ List<Item> *cond_list= ((Item_cond*) cond)->argument_list();
42124 -+
42125 -+ bool and_level= ((Item_cond*) cond)->functype() ==
42126 -+ Item_func::COND_AND_FUNC;
42127 -+ if (and_level)
42128 -+ {
42129 -+ cond_equal= &((Item_cond_and *) cond)->cond_equal;
42130 -+ cond_list->disjoin((List<Item> *) &cond_equal->current_level);
42131 -+
42132 -+ List_iterator_fast<Item_equal> it(cond_equal->current_level);
42133 -+ while ((item_equal= it++))
42134 -+ {
42135 -+ item_equal->sort(&compare_fields_by_table_order, table_join_idx);
42136 -+ }
42137 -+ }
42138 -+
42139 -+ List_iterator<Item> li(*cond_list);
42140 -+ Item *item;
42141 -+ while ((item= li++))
42142 -+ {
42143 -+ Item *new_item =substitute_for_best_equal_field(item, cond_equal,
42144 -+ table_join_idx);
42145 -+ /*
42146 -+ This works OK with PS/SP re-execution as changes are made to
42147 -+ the arguments of AND/OR items only
42148 -+ */
42149 -+ if (new_item != item)
42150 -+ li.replace(new_item);
42151 -+ }
42152 -+
42153 -+ if (and_level)
42154 -+ {
42155 -+ List_iterator_fast<Item_equal> it(cond_equal->current_level);
42156 -+ while ((item_equal= it++))
42157 -+ {
42158 -+ cond= eliminate_item_equal(cond, cond_equal->upper_levels, item_equal);
42159 -+ // This occurs when eliminate_item_equal() founds that cond is
42160 -+ // always false and substitutes it with Item_int 0.
42161 -+ // Due to this, value of item_equal will be 0, so just return it.
42162 -+ if (cond->type() != Item::COND_ITEM)
42163 -+ break;
42164 -+ }
42165 -+ }
42166 -+ if (cond->type() == Item::COND_ITEM &&
42167 -+ !((Item_cond*)cond)->argument_list()->elements)
42168 -+ cond= new Item_int((int32)cond->val_bool());
42169 -+
42170 -+ }
42171 -+ else if (cond->type() == Item::FUNC_ITEM &&
42172 -+ ((Item_cond*) cond)->functype() == Item_func::MULT_EQUAL_FUNC)
42173 -+ {
42174 -+ item_equal= (Item_equal *) cond;
42175 -+ item_equal->sort(&compare_fields_by_table_order, table_join_idx);
42176 -+ if (cond_equal && cond_equal->current_level.head() == item_equal)
42177 -+ cond_equal= 0;
42178 -+ return eliminate_item_equal(0, cond_equal, item_equal);
42179 -+ }
42180 -+ else
42181 -+ cond->transform(&Item::replace_equal_field, 0);
42182 -+ return cond;
42183 -+}
42184 -+
42185 -+
42186 -+/**
42187 -+ Check appearance of new constant items in multiple equalities
42188 -+ of a condition after reading a constant table.
42189 -+
42190 -+ The function retrieves the cond condition and for each encountered
42191 -+ multiple equality checks whether new constants have appeared after
42192 -+ reading the constant (single row) table tab. If so it adjusts
42193 -+ the multiple equality appropriately.
42194 -+
42195 -+ @param cond condition whose multiple equalities are to be checked
42196 -+ @param table constant table that has been read
42197 -+*/
42198 -+
42199 -+static void update_const_equal_items(COND *cond, JOIN_TAB *tab)
42200 -+{
42201 -+ if (!(cond->used_tables() & tab->table->map))
42202 -+ return;
42203 -+
42204 -+ if (cond->type() == Item::COND_ITEM)
42205 -+ {
42206 -+ List<Item> *cond_list= ((Item_cond*) cond)->argument_list();
42207 -+ List_iterator_fast<Item> li(*cond_list);
42208 -+ Item *item;
42209 -+ while ((item= li++))
42210 -+ update_const_equal_items(item, tab);
42211 -+ }
42212 -+ else if (cond->type() == Item::FUNC_ITEM &&
42213 -+ ((Item_cond*) cond)->functype() == Item_func::MULT_EQUAL_FUNC)
42214 -+ {
42215 -+ Item_equal *item_equal= (Item_equal *) cond;
42216 -+ bool contained_const= item_equal->get_const() != NULL;
42217 -+ item_equal->update_const();
42218 -+ if (!contained_const && item_equal->get_const())
42219 -+ {
42220 -+ /* Update keys for range analysis */
42221 -+ Item_equal_iterator it(*item_equal);
42222 -+ Item_field *item_field;
42223 -+ while ((item_field= it++))
42224 -+ {
42225 -+ Field *field= item_field->field;
42226 -+ JOIN_TAB *stat= field->table->reginfo.join_tab;
42227 -+ key_map possible_keys= field->key_start;
42228 -+ possible_keys.intersect(field->table->keys_in_use_for_query);
42229 -+ stat[0].const_keys.merge(possible_keys);
42230 -+
42231 -+ /*
42232 -+ For each field in the multiple equality (for which we know that it
42233 -+ is a constant) we have to find its corresponding key part, and set
42234 -+ that key part in const_key_parts.
42235 -+ */
42236 -+ if (!possible_keys.is_clear_all())
42237 -+ {
42238 -+ TABLE *tab= field->table;
42239 -+ KEYUSE *use;
42240 -+ for (use= stat->keyuse; use && use->table == tab; use++)
42241 -+ if (possible_keys.is_set(use->key) &&
42242 -+ tab->key_info[use->key].key_part[use->keypart].field ==
42243 -+ field)
42244 -+ tab->const_key_parts[use->key]|= use->keypart_map;
42245 -+ }
42246 -+ }
42247 -+ }
42248 -+ }
42249 -+}
42250 -+
42251 -+
42252 -+/*
42253 -+ change field = field to field = const for each found field = const in the
42254 -+ and_level
42255 -+*/
42256 -+
42257 -+static void
42258 -+change_cond_ref_to_const(THD *thd, I_List<COND_CMP> *save_list,
42259 -+ Item *and_father, Item *cond,
42260 -+ Item *field, Item *value)
42261 -+{
42262 -+ if (cond->type() == Item::COND_ITEM)
42263 -+ {
42264 -+ bool and_level= ((Item_cond*) cond)->functype() ==
42265 -+ Item_func::COND_AND_FUNC;
42266 -+ List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
42267 -+ Item *item;
42268 -+ while ((item=li++))
42269 -+ change_cond_ref_to_const(thd, save_list,and_level ? cond : item, item,
42270 -+ field, value);
42271 -+ return;
42272 -+ }
42273 -+ if (cond->eq_cmp_result() == Item::COND_OK)
42274 -+ return; // Not a boolean function
42275 -+
42276 -+ Item_bool_func2 *func= (Item_bool_func2*) cond;
42277 -+ Item **args= func->arguments();
42278 -+ Item *left_item= args[0];
42279 -+ Item *right_item= args[1];
42280 -+ Item_func::Functype functype= func->functype();
42281 -+
42282 -+ if (right_item->eq(field,0) && left_item != value &&
42283 -+ right_item->cmp_context == field->cmp_context &&
42284 -+ (left_item->result_type() != STRING_RESULT ||
42285 -+ value->result_type() != STRING_RESULT ||
42286 -+ left_item->collation.collation == value->collation.collation))
42287 -+ {
42288 -+ Item *tmp=value->clone_item();
42289 -+ tmp->collation.set(right_item->collation);
42290 -+
42291 -+ if (tmp)
42292 -+ {
42293 -+ thd->change_item_tree(args + 1, tmp);
42294 -+ func->update_used_tables();
42295 -+ if ((functype == Item_func::EQ_FUNC || functype == Item_func::EQUAL_FUNC)
42296 -+ && and_father != cond && !left_item->const_item())
42297 -+ {
42298 -+ cond->marker=1;
42299 -+ COND_CMP *tmp2;
42300 -+ if ((tmp2=new COND_CMP(and_father,func)))
42301 -+ save_list->push_back(tmp2);
42302 -+ }
42303 -+ func->set_cmp_func();
42304 -+ }
42305 -+ }
42306 -+ else if (left_item->eq(field,0) && right_item != value &&
42307 -+ left_item->cmp_context == field->cmp_context &&
42308 -+ (right_item->result_type() != STRING_RESULT ||
42309 -+ value->result_type() != STRING_RESULT ||
42310 -+ right_item->collation.collation == value->collation.collation))
42311 -+ {
42312 -+ Item *tmp= value->clone_item();
42313 -+ tmp->collation.set(left_item->collation);
42314 -+
42315 -+ if (tmp)
42316 -+ {
42317 -+ thd->change_item_tree(args, tmp);
42318 -+ value= tmp;
42319 -+ func->update_used_tables();
42320 -+ if ((functype == Item_func::EQ_FUNC || functype == Item_func::EQUAL_FUNC)
42321 -+ && and_father != cond && !right_item->const_item())
42322 -+ {
42323 -+ args[0]= args[1]; // For easy check
42324 -+ thd->change_item_tree(args + 1, value);
42325 -+ cond->marker=1;
42326 -+ COND_CMP *tmp2;
42327 -+ if ((tmp2=new COND_CMP(and_father,func)))
42328 -+ save_list->push_back(tmp2);
42329 -+ }
42330 -+ func->set_cmp_func();
42331 -+ }
42332 -+ }
42333 -+}
42334 -+
42335 -+/**
42336 -+ Remove additional condition inserted by IN/ALL/ANY transformation.
42337 -+
42338 -+ @param conds condition for processing
42339 -+
42340 -+ @return
42341 -+ new conditions
42342 -+*/
42343 -+
42344 -+static Item *remove_additional_cond(Item* conds)
42345 -+{
42346 -+ if (conds->name == in_additional_cond)
42347 -+ return 0;
42348 -+ if (conds->type() == Item::COND_ITEM)
42349 -+ {
42350 -+ Item_cond *cnd= (Item_cond*) conds;
42351 -+ List_iterator<Item> li(*(cnd->argument_list()));
42352 -+ Item *item;
42353 -+ while ((item= li++))
42354 -+ {
42355 -+ if (item->name == in_additional_cond)
42356 -+ {
42357 -+ li.remove();
42358 -+ if (cnd->argument_list()->elements == 1)
42359 -+ return cnd->argument_list()->head();
42360 -+ return conds;
42361 -+ }
42362 -+ }
42363 -+ }
42364 -+ return conds;
42365 -+}
42366 -+
42367 -+static void
42368 -+propagate_cond_constants(THD *thd, I_List<COND_CMP> *save_list,
42369 -+ COND *and_father, COND *cond)
42370 -+{
42371 -+ if (cond->type() == Item::COND_ITEM)
42372 -+ {
42373 -+ bool and_level= ((Item_cond*) cond)->functype() ==
42374 -+ Item_func::COND_AND_FUNC;
42375 -+ List_iterator_fast<Item> li(*((Item_cond*) cond)->argument_list());
42376 -+ Item *item;
42377 -+ I_List<COND_CMP> save;
42378 -+ while ((item=li++))
42379 -+ {
42380 -+ propagate_cond_constants(thd, &save,and_level ? cond : item, item);
42381 -+ }
42382 -+ if (and_level)
42383 -+ { // Handle other found items
42384 -+ I_List_iterator<COND_CMP> cond_itr(save);
42385 -+ COND_CMP *cond_cmp;
42386 -+ while ((cond_cmp=cond_itr++))
42387 -+ {
42388 -+ Item **args= cond_cmp->cmp_func->arguments();
42389 -+ if (!args[0]->const_item())
42390 -+ change_cond_ref_to_const(thd, &save,cond_cmp->and_level,
42391 -+ cond_cmp->and_level, args[0], args[1]);
42392 -+ }
42393 -+ }
42394 -+ }
42395 -+ else if (and_father != cond && !cond->marker) // In a AND group
42396 -+ {
42397 -+ if (cond->type() == Item::FUNC_ITEM &&
42398 -+ (((Item_func*) cond)->functype() == Item_func::EQ_FUNC ||
42399 -+ ((Item_func*) cond)->functype() == Item_func::EQUAL_FUNC))
42400 -+ {
42401 -+ Item_func_eq *func=(Item_func_eq*) cond;
42402 -+ Item **args= func->arguments();
42403 -+ bool left_const= args[0]->const_item();
42404 -+ bool right_const= args[1]->const_item();
42405 -+ if (!(left_const && right_const) &&
42406 -+ args[0]->result_type() == args[1]->result_type())
42407 -+ {
42408 -+ if (right_const)
42409 -+ {
42410 -+ resolve_const_item(thd, &args[1], args[0]);
42411 -+ func->update_used_tables();
42412 -+ change_cond_ref_to_const(thd, save_list, and_father, and_father,
42413 -+ args[0], args[1]);
42414 -+ }
42415 -+ else if (left_const)
42416 -+ {
42417 -+ resolve_const_item(thd, &args[0], args[1]);
42418 -+ func->update_used_tables();
42419 -+ change_cond_ref_to_const(thd, save_list, and_father, and_father,
42420 -+ args[1], args[0]);
42421 -+ }
42422 -+ }
42423 -+ }
42424 -+ }
42425 -+}
42426 -+
42427 -+
42428 -+/**
42429 -+ Simplify joins replacing outer joins by inner joins whenever it's
42430 -+ possible.
42431 -+
42432 -+ The function, during a retrieval of join_list, eliminates those
42433 -+ outer joins that can be converted into inner join, possibly nested.
42434 -+ It also moves the on expressions for the converted outer joins
42435 -+ and from inner joins to conds.
42436 -+ The function also calculates some attributes for nested joins:
42437 -+ - used_tables
42438 -+ - not_null_tables
42439 -+ - dep_tables.
42440 -+ - on_expr_dep_tables
42441 -+ The first two attributes are used to test whether an outer join can
42442 -+ be substituted for an inner join. The third attribute represents the
42443 -+ relation 'to be dependent on' for tables. If table t2 is dependent
42444 -+ on table t1, then in any evaluated execution plan table access to
42445 -+ table t2 must precede access to table t2. This relation is used also
42446 -+ to check whether the query contains invalid cross-references.
42447 -+ The forth attribute is an auxiliary one and is used to calculate
42448 -+ dep_tables.
42449 -+ As the attribute dep_tables qualifies possibles orders of tables in the
42450 -+ execution plan, the dependencies required by the straight join
42451 -+ modifiers are reflected in this attribute as well.
42452 -+ The function also removes all braces that can be removed from the join
42453 -+ expression without changing its meaning.
42454 -+
42455 -+ @note
42456 -+ An outer join can be replaced by an inner join if the where condition
42457 -+ or the on expression for an embedding nested join contains a conjunctive
42458 -+ predicate rejecting null values for some attribute of the inner tables.
42459 -+
42460 -+ E.g. in the query:
42461 -+ @code
42462 -+ SELECT * FROM t1 LEFT JOIN t2 ON t2.a=t1.a WHERE t2.b < 5
42463 -+ @endcode
42464 -+ the predicate t2.b < 5 rejects nulls.
42465 -+ The query is converted first to:
42466 -+ @code
42467 -+ SELECT * FROM t1 INNER JOIN t2 ON t2.a=t1.a WHERE t2.b < 5
42468 -+ @endcode
42469 -+ then to the equivalent form:
42470 -+ @code
42471 -+ SELECT * FROM t1, t2 ON t2.a=t1.a WHERE t2.b < 5 AND t2.a=t1.a
42472 -+ @endcode
42473 -+
42474 -+
42475 -+ Similarly the following query:
42476 -+ @code
42477 -+ SELECT * from t1 LEFT JOIN (t2, t3) ON t2.a=t1.a t3.b=t1.b
42478 -+ WHERE t2.c < 5
42479 -+ @endcode
42480 -+ is converted to:
42481 -+ @code
42482 -+ SELECT * FROM t1, (t2, t3) WHERE t2.c < 5 AND t2.a=t1.a t3.b=t1.b
42483 -+
42484 -+ @endcode
42485 -+
42486 -+ One conversion might trigger another:
42487 -+ @code
42488 -+ SELECT * FROM t1 LEFT JOIN t2 ON t2.a=t1.a
42489 -+ LEFT JOIN t3 ON t3.b=t2.b
42490 -+ WHERE t3 IS NOT NULL =>
42491 -+ SELECT * FROM t1 LEFT JOIN t2 ON t2.a=t1.a, t3
42492 -+ WHERE t3 IS NOT NULL AND t3.b=t2.b =>
42493 -+ SELECT * FROM t1, t2, t3
42494 -+ WHERE t3 IS NOT NULL AND t3.b=t2.b AND t2.a=t1.a
42495 -+ @endcode
42496 -+
42497 -+ The function removes all unnecessary braces from the expression
42498 -+ produced by the conversions.
42499 -+ E.g.
42500 -+ @code
42501 -+ SELECT * FROM t1, (t2, t3) WHERE t2.c < 5 AND t2.a=t1.a AND t3.b=t1.b
42502 -+ @endcode
42503 -+ finally is converted to:
42504 -+ @code
42505 -+ SELECT * FROM t1, t2, t3 WHERE t2.c < 5 AND t2.a=t1.a AND t3.b=t1.b
42506 -+
42507 -+ @endcode
42508 -+
42509 -+
42510 -+ It also will remove braces from the following queries:
42511 -+ @code
42512 -+ SELECT * from (t1 LEFT JOIN t2 ON t2.a=t1.a) LEFT JOIN t3 ON t3.b=t2.b
42513 -+ SELECT * from (t1, (t2,t3)) WHERE t1.a=t2.a AND t2.b=t3.b.
42514 -+ @endcode
42515 -+
42516 -+ The benefit of this simplification procedure is that it might return
42517 -+ a query for which the optimizer can evaluate execution plan with more
42518 -+ join orders. With a left join operation the optimizer does not
42519 -+ consider any plan where one of the inner tables is before some of outer
42520 -+ tables.
42521 -+
42522 -+
42523 -+ The function is implemented by a recursive procedure. On the recursive
42524 -+ ascent all attributes are calculated, all outer joins that can be
42525 -+ converted are replaced and then all unnecessary braces are removed.
42526 -+ As join list contains join tables in the reverse order sequential
42527 -+ elimination of outer joins does not require extra recursive calls.
42528 -+
42529 -+ Here is an example of a join query with invalid cross references:
42530 -+ @code
42531 -+ SELECT * FROM t1 LEFT JOIN t2 ON t2.a=t3.a LEFT JOIN t3 ON t3.b=t1.b
42532 -+ @endcode
42533 -+
42534 -+ @param join reference to the query info
42535 -+ @param join_list list representation of the join to be converted
42536 -+ @param conds conditions to add on expressions for converted joins
42537 -+ @param top true <=> conds is the where condition
42538 -+
42539 -+ @return
42540 -+ - The new condition, if success
42541 -+ - 0, otherwise
42542 -+*/
42543 -+
42544 -+static COND *
42545 -+simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top)
42546 -+{
42547 -+ TABLE_LIST *table;
42548 -+ NESTED_JOIN *nested_join;
42549 -+ TABLE_LIST *prev_table= 0;
42550 -+ List_iterator<TABLE_LIST> li(*join_list);
42551 -+ bool straight_join= test(join->select_options & SELECT_STRAIGHT_JOIN);
42552 -+ DBUG_ENTER("simplify_joins");
42553 -+
42554 -+ /*
42555 -+ Try to simplify join operations from join_list.
42556 -+ The most outer join operation is checked for conversion first.
42557 -+ */
42558 -+ while ((table= li++))
42559 -+ {
42560 -+ table_map used_tables;
42561 -+ table_map not_null_tables= (table_map) 0;
42562 -+
42563 -+ if ((nested_join= table->nested_join))
42564 -+ {
42565 -+ /*
42566 -+ If the element of join_list is a nested join apply
42567 -+ the procedure to its nested join list first.
42568 -+ */
42569 -+ if (table->on_expr)
42570 -+ {
42571 -+ Item *expr= table->on_expr;
42572 -+ /*
42573 -+ If an on expression E is attached to the table,
42574 -+ check all null rejected predicates in this expression.
42575 -+ If such a predicate over an attribute belonging to
42576 -+ an inner table of an embedded outer join is found,
42577 -+ the outer join is converted to an inner join and
42578 -+ the corresponding on expression is added to E.
42579 -+ */
42580 -+ expr= simplify_joins(join, &nested_join->join_list,
42581 -+ expr, FALSE);
42582 -+
42583 -+ if (!table->prep_on_expr || expr != table->on_expr)
42584 -+ {
42585 -+ DBUG_ASSERT(expr);
42586 -+
42587 -+ table->on_expr= expr;
42588 -+ table->prep_on_expr= expr->copy_andor_structure(join->thd);
42589 -+ }
42590 -+ }
42591 -+ nested_join->used_tables= (table_map) 0;
42592 -+ nested_join->not_null_tables=(table_map) 0;
42593 -+ conds= simplify_joins(join, &nested_join->join_list, conds, top);
42594 -+ used_tables= nested_join->used_tables;
42595 -+ not_null_tables= nested_join->not_null_tables;
42596 -+ }
42597 -+ else
42598 -+ {
42599 -+ if (!table->prep_on_expr)
42600 -+ table->prep_on_expr= table->on_expr;
42601 -+ used_tables= table->table->map;
42602 -+ if (conds)
42603 -+ not_null_tables= conds->not_null_tables();
42604 -+ }
42605 -+
42606 -+ if (table->embedding)
42607 -+ {
42608 -+ table->embedding->nested_join->used_tables|= used_tables;
42609 -+ table->embedding->nested_join->not_null_tables|= not_null_tables;
42610 -+ }
42611 -+
42612 -+ if (!table->outer_join || (used_tables & not_null_tables))
42613 -+ {
42614 -+ /*
42615 -+ For some of the inner tables there are conjunctive predicates
42616 -+ that reject nulls => the outer join can be replaced by an inner join.
42617 -+ */
42618 -+ table->outer_join= 0;
42619 -+ if (table->on_expr)
42620 -+ {
42621 -+ /* Add on expression to the where condition. */
42622 -+ if (conds)
42623 -+ {
42624 -+ conds= and_conds(conds, table->on_expr);
42625 -+ conds->top_level_item();
42626 -+ /* conds is always a new item as both cond and on_expr existed */
42627 -+ DBUG_ASSERT(!conds->fixed);
42628 -+ conds->fix_fields(join->thd, &conds);
42629 -+ }
42630 -+ else
42631 -+ conds= table->on_expr;
42632 -+ table->prep_on_expr= table->on_expr= 0;
42633 -+ }
42634 -+ }
42635 -+
42636 -+ if (!top)
42637 -+ continue;
42638 -+
42639 -+ /*
42640 -+ Only inner tables of non-convertible outer joins
42641 -+ remain with on_expr.
42642 -+ */
42643 -+ if (table->on_expr)
42644 -+ {
42645 -+ table->dep_tables|= table->on_expr->used_tables();
42646 -+ if (table->embedding)
42647 -+ {
42648 -+ table->dep_tables&= ~table->embedding->nested_join->used_tables;
42649 -+ /*
42650 -+ Embedding table depends on tables used
42651 -+ in embedded on expressions.
42652 -+ */
42653 -+ table->embedding->on_expr_dep_tables|= table->on_expr->used_tables();
42654 -+ }
42655 -+ else
42656 -+ table->dep_tables&= ~table->table->map;
42657 -+ }
42658 -+
42659 -+ if (prev_table)
42660 -+ {
42661 -+ /* The order of tables is reverse: prev_table follows table */
42662 -+ if (prev_table->straight || straight_join)
42663 -+ prev_table->dep_tables|= used_tables;
42664 -+ if (prev_table->on_expr)
42665 -+ {
42666 -+ prev_table->dep_tables|= table->on_expr_dep_tables;
42667 -+ table_map prev_used_tables= prev_table->nested_join ?
42668 -+ prev_table->nested_join->used_tables :
42669 -+ prev_table->table->map;
42670 -+ /*
42671 -+ If on expression contains only references to inner tables
42672 -+ we still make the inner tables dependent on the outer tables.
42673 -+ It would be enough to set dependency only on one outer table
42674 -+ for them. Yet this is really a rare case.
42675 -+ Note:
42676 -+ RAND_TABLE_BIT mask should not be counted as it
42677 -+ prevents update of inner table dependences.
42678 -+ For example it might happen if RAND() function
42679 -+ is used in JOIN ON clause.
42680 -+ */
42681 -+ if (!((prev_table->on_expr->used_tables() & ~RAND_TABLE_BIT) &
42682 -+ ~prev_used_tables))
42683 -+ prev_table->dep_tables|= used_tables;
42684 -+ }
42685 -+ }
42686 -+ prev_table= table;
42687 -+ }
42688 -+
42689 -+ /* Flatten nested joins that can be flattened. */
42690 -+ TABLE_LIST *right_neighbor= NULL;
42691 -+ li.rewind();
42692 -+ while ((table= li++))
42693 -+ {
42694 -+ bool fix_name_res= FALSE;
42695 -+ nested_join= table->nested_join;
42696 -+ if (nested_join && !table->on_expr)
42697 -+ {
42698 -+ TABLE_LIST *tbl;
42699 -+ List_iterator<TABLE_LIST> it(nested_join->join_list);
42700 -+ while ((tbl= it++))
42701 -+ {
42702 -+ tbl->embedding= table->embedding;
42703 -+ tbl->join_list= table->join_list;
42704 -+ }
42705 -+ li.replace(nested_join->join_list);
42706 -+ /* Need to update the name resolution table chain when flattening joins */
42707 -+ fix_name_res= TRUE;
42708 -+ table= *li.ref();
42709 -+ }
42710 -+ if (fix_name_res)
42711 -+ table->next_name_resolution_table= right_neighbor ?
42712 -+ right_neighbor->first_leaf_for_name_resolution() :
42713 -+ NULL;
42714 -+ right_neighbor= table;
42715 -+ }
42716 -+ DBUG_RETURN(conds);
42717 -+}
42718 -+
42719 -+
42720 -+/**
42721 -+ Assign each nested join structure a bit in nested_join_map.
42722 -+
42723 -+ Assign each nested join structure (except "confluent" ones - those that
42724 -+ embed only one element) a bit in nested_join_map.
42725 -+
42726 -+ @param join Join being processed
42727 -+ @param join_list List of tables
42728 -+ @param first_unused Number of first unused bit in nested_join_map before the
42729 -+ call
42730 -+
42731 -+ @note
42732 -+ This function is called after simplify_joins(), when there are no
42733 -+ redundant nested joins, #non_confluent_nested_joins <= #tables_in_join so
42734 -+ we will not run out of bits in nested_join_map.
42735 -+
42736 -+ @return
42737 -+ First unused bit in nested_join_map after the call.
42738 -+*/
42739 -+
42740 -+static uint build_bitmap_for_nested_joins(List<TABLE_LIST> *join_list,
42741 -+ uint first_unused)
42742 -+{
42743 -+ List_iterator<TABLE_LIST> li(*join_list);
42744 -+ TABLE_LIST *table;
42745 -+ DBUG_ENTER("build_bitmap_for_nested_joins");
42746 -+ while ((table= li++))
42747 -+ {
42748 -+ NESTED_JOIN *nested_join;
42749 -+ if ((nested_join= table->nested_join))
42750 -+ {
42751 -+ /*
42752 -+ It is guaranteed by simplify_joins() function that a nested join
42753 -+ that has only one child represents a single table VIEW (and the child
42754 -+ is an underlying table). We don't assign bits to such nested join
42755 -+ structures because
42756 -+ 1. it is redundant (a "sequence" of one table cannot be interleaved
42757 -+ with anything)
42758 -+ 2. we could run out bits in nested_join_map otherwise.
42759 -+ */
42760 -+ if (nested_join->join_list.elements != 1)
42761 -+ {
42762 -+ nested_join->nj_map= (nested_join_map) 1 << first_unused++;
42763 -+ first_unused= build_bitmap_for_nested_joins(&nested_join->join_list,
42764 -+ first_unused);
42765 -+ }
42766 -+ }
42767 -+ }
42768 -+ DBUG_RETURN(first_unused);
42769 -+}
42770 -+
42771 -+
42772 -+/**
42773 -+ Set NESTED_JOIN::counter=0 in all nested joins in passed list.
42774 -+
42775 -+ Recursively set NESTED_JOIN::counter=0 for all nested joins contained in
42776 -+ the passed join_list.
42777 -+
42778 -+ @param join_list List of nested joins to process. It may also contain base
42779 -+ tables which will be ignored.
42780 -+*/
42781 -+
42782 -+static void reset_nj_counters(List<TABLE_LIST> *join_list)
42783 -+{
42784 -+ List_iterator<TABLE_LIST> li(*join_list);
42785 -+ TABLE_LIST *table;
42786 -+ DBUG_ENTER("reset_nj_counters");
42787 -+ while ((table= li++))
42788 -+ {
42789 -+ NESTED_JOIN *nested_join;
42790 -+ if ((nested_join= table->nested_join))
42791 -+ {
42792 -+ nested_join->counter= 0;
42793 -+ reset_nj_counters(&nested_join->join_list);
42794 -+ }
42795 -+ }
42796 -+ DBUG_VOID_RETURN;
42797 -+}
42798 -+
42799 -+
42800 -+/**
42801 -+ Check interleaving with an inner tables of an outer join for
42802 -+ extension table.
42803 -+
42804 -+ Check if table next_tab can be added to current partial join order, and
42805 -+ if yes, record that it has been added.
42806 -+
42807 -+ The function assumes that both current partial join order and its
42808 -+ extension with next_tab are valid wrt table dependencies.
42809 -+
42810 -+ @verbatim
42811 -+ IMPLEMENTATION
42812 -+ LIMITATIONS ON JOIN ORDER
42813 -+ The nested [outer] joins executioner algorithm imposes these limitations
42814 -+ on join order:
42815 -+ 1. "Outer tables first" - any "outer" table must be before any
42816 -+ corresponding "inner" table.
42817 -+ 2. "No interleaving" - tables inside a nested join must form a continuous
42818 -+ sequence in join order (i.e. the sequence must not be interrupted by
42819 -+ tables that are outside of this nested join).
42820 -+
42821 -+ #1 is checked elsewhere, this function checks #2 provided that #1 has
42822 -+ been already checked.
42823 -+
42824 -+ WHY NEED NON-INTERLEAVING
42825 -+ Consider an example:
42826 -+
42827 -+ select * from t0 join t1 left join (t2 join t3) on cond1
42828 -+
42829 -+ The join order "t1 t2 t0 t3" is invalid:
42830 -+
42831 -+ table t0 is outside of the nested join, so WHERE condition for t0 is
42832 -+ attached directly to t0 (without triggers, and it may be used to access
42833 -+ t0). Applying WHERE(t0) to (t2,t0,t3) record is invalid as we may miss
42834 -+ combinations of (t1, t2, t3) that satisfy condition cond1, and produce a
42835 -+ null-complemented (t1, t2.NULLs, t3.NULLs) row, which should not have
42836 -+ been produced.
42837 -+
42838 -+ If table t0 is not between t2 and t3, the problem doesn't exist:
42839 -+ If t0 is located after (t2,t3), WHERE(t0) is applied after nested join
42840 -+ processing has finished.
42841 -+ If t0 is located before (t2,t3), predicates like WHERE_cond(t0, t2) are
42842 -+ wrapped into condition triggers, which takes care of correct nested
42843 -+ join processing.
42844 -+
42845 -+ HOW IT IS IMPLEMENTED
42846 -+ The limitations on join order can be rephrased as follows: for valid
42847 -+ join order one must be able to:
42848 -+ 1. write down the used tables in the join order on one line.
42849 -+ 2. for each nested join, put one '(' and one ')' on the said line
42850 -+ 3. write "LEFT JOIN" and "ON (...)" where appropriate
42851 -+ 4. get a query equivalent to the query we're trying to execute.
42852 -+
42853 -+ Calls to check_interleaving_with_nj() are equivalent to writing the
42854 -+ above described line from left to right.
42855 -+ A single check_interleaving_with_nj(A,B) call is equivalent to writing
42856 -+ table B and appropriate brackets on condition that table A and
42857 -+ appropriate brackets is the last what was written. Graphically the
42858 -+ transition is as follows:
42859 -+
42860 -+ +---- current position
42861 -+ |
42862 -+ ... last_tab ))) | ( next_tab ) )..) | ...
42863 -+ X Y Z |
42864 -+ +- need to move to this
42865 -+ position.
42866 -+
42867 -+ Notes about the position:
42868 -+ The caller guarantees that there is no more then one X-bracket by
42869 -+ checking "!(remaining_tables & s->dependent)" before calling this
42870 -+ function. X-bracket may have a pair in Y-bracket.
42871 -+
42872 -+ When "writing" we store/update this auxilary info about the current
42873 -+ position:
42874 -+ 1. join->cur_embedding_map - bitmap of pairs of brackets (aka nested
42875 -+ joins) we've opened but didn't close.
42876 -+ 2. {each NESTED_JOIN structure not simplified away}->counter - number
42877 -+ of this nested join's children that have already been added to to
42878 -+ the partial join order.
42879 -+ @endverbatim
42880 -+
42881 -+ @param next_tab Table we're going to extend the current partial join with
42882 -+
42883 -+ @retval
42884 -+ FALSE Join order extended, nested joins info about current join
42885 -+ order (see NOTE section) updated.
42886 -+ @retval
42887 -+ TRUE Requested join order extension not allowed.
42888 -+*/
42889 -+
42890 -+static bool check_interleaving_with_nj(JOIN_TAB *next_tab)
42891 -+{
42892 -+ TABLE_LIST *next_emb= next_tab->table->pos_in_table_list->embedding;
42893 -+ JOIN *join= next_tab->join;
42894 -+
42895 -+ if (join->cur_embedding_map & ~next_tab->embedding_map)
42896 -+ {
42897 -+ /*
42898 -+ next_tab is outside of the "pair of brackets" we're currently in.
42899 -+ Cannot add it.
42900 -+ */
42901 -+ return TRUE;
42902 -+ }
42903 -+
42904 -+ /*
42905 -+ Do update counters for "pairs of brackets" that we've left (marked as
42906 -+ X,Y,Z in the above picture)
42907 -+ */
42908 -+ for (;next_emb; next_emb= next_emb->embedding)
42909 -+ {
42910 -+ next_emb->nested_join->counter++;
42911 -+ if (next_emb->nested_join->counter == 1)
42912 -+ {
42913 -+ /*
42914 -+ next_emb is the first table inside a nested join we've "entered". In
42915 -+ the picture above, we're looking at the 'X' bracket. Don't exit yet as
42916 -+ X bracket might have Y pair bracket.
42917 -+ */
42918 -+ join->cur_embedding_map |= next_emb->nested_join->nj_map;
42919 -+ }
42920 -+
42921 -+ if (next_emb->nested_join->join_list.elements !=
42922 -+ next_emb->nested_join->counter)
42923 -+ break;
42924 -+
42925 -+ /*
42926 -+ We're currently at Y or Z-bracket as depicted in the above picture.
42927 -+ Mark that we've left it and continue walking up the brackets hierarchy.
42928 -+ */
42929 -+ join->cur_embedding_map &= ~next_emb->nested_join->nj_map;
42930 -+ }
42931 -+ return FALSE;
42932 -+}
42933 -+
42934 -+
42935 -+/**
42936 -+ Nested joins perspective: Remove the last table from the join order.
42937 -+
42938 -+ The algorithm is the reciprocal of check_interleaving_with_nj(), hence
42939 -+ parent join nest nodes are updated only when the last table in its child
42940 -+ node is removed. The ASCII graphic below will clarify.
42941 -+
42942 -+ %A table nesting such as <tt> t1 x [ ( t2 x t3 ) x ( t4 x t5 ) ] </tt>is
42943 -+ represented by the below join nest tree.
42944 -+
42945 -+ @verbatim
42946 -+ NJ1
42947 -+ _/ / \
42948 -+ _/ / NJ2
42949 -+ _/ / / \
42950 -+ / / / \
42951 -+ t1 x [ (t2 x t3) x (t4 x t5) ]
42952 -+ @endverbatim
42953 -+
42954 -+ At the point in time when check_interleaving_with_nj() adds the table t5 to
42955 -+ the query execution plan, QEP, it also directs the node named NJ2 to mark
42956 -+ the table as covered. NJ2 does so by incrementing its @c counter
42957 -+ member. Since all of NJ2's tables are now covered by the QEP, the algorithm
42958 -+ proceeds up the tree to NJ1, incrementing its counter as well. All join
42959 -+ nests are now completely covered by the QEP.
42960 -+
42961 -+ restore_prev_nj_state() does the above in reverse. As seen above, the node
42962 -+ NJ1 contains the nodes t2, t3, and NJ2. Its counter being equal to 3 means
42963 -+ that the plan covers t2, t3, and NJ2, @e and that the sub-plan (t4 x t5)
42964 -+ completely covers NJ2. The removal of t5 from the partial plan will first
42965 -+ decrement NJ2's counter to 1. It will then detect that NJ2 went from being
42966 -+ completely to partially covered, and hence the algorithm must continue
42967 -+ upwards to NJ1 and decrement its counter to 2. %A subsequent removal of t4
42968 -+ will however not influence NJ1 since it did not un-cover the last table in
42969 -+ NJ2.
42970 -+
42971 -+ SYNOPSIS
42972 -+ restore_prev_nj_state()
42973 -+ last join table to remove, it is assumed to be the last in current
42974 -+ partial join order.
42975 -+
42976 -+ DESCRIPTION
42977 -+
42978 -+ Remove the last table from the partial join order and update the nested
42979 -+ joins counters and join->cur_embedding_map. It is ok to call this
42980 -+ function for the first table in join order (for which
42981 -+ check_interleaving_with_nj has not been called)
42982 -+
42983 -+ @param last join table to remove, it is assumed to be the last in current
42984 -+ partial join order.
42985 -+*/
42986 -+
42987 -+static void restore_prev_nj_state(JOIN_TAB *last)
42988 -+{
42989 -+ TABLE_LIST *last_emb= last->table->pos_in_table_list->embedding;
42990 -+ JOIN *join= last->join;
42991 -+ for (;last_emb != NULL; last_emb= last_emb->embedding)
42992 -+ {
42993 -+ NESTED_JOIN *nest= last_emb->nested_join;
42994 -+ DBUG_ASSERT(nest->counter > 0);
42995 -+
42996 -+ bool was_fully_covered= nest->is_fully_covered();
42997 -+
42998 -+ if (--nest->counter == 0)
42999 -+ join->cur_embedding_map&= ~nest->nj_map;
43000 -+
43001 -+ if (!was_fully_covered)
43002 -+ break;
43003 -+
43004 -+ join->cur_embedding_map|= nest->nj_map;
43005 -+ }
43006 -+}
43007 -+
43008 -+
43009 -+static COND *
43010 -+optimize_cond(JOIN *join, COND *conds, List<TABLE_LIST> *join_list,
43011 -+ Item::cond_result *cond_value)
43012 -+{
43013 -+ THD *thd= join->thd;
43014 -+ DBUG_ENTER("optimize_cond");
43015 -+
43016 -+ if (!conds)
43017 -+ *cond_value= Item::COND_TRUE;
43018 -+ else
43019 -+ {
43020 -+ /*
43021 -+ Build all multiple equality predicates and eliminate equality
43022 -+ predicates that can be inferred from these multiple equalities.
43023 -+ For each reference of a field included into a multiple equality
43024 -+ that occurs in a function set a pointer to the multiple equality
43025 -+ predicate. Substitute a constant instead of this field if the
43026 -+ multiple equality contains a constant.
43027 -+ */
43028 -+ DBUG_EXECUTE("where", print_where(conds, "original", QT_ORDINARY););
43029 -+ conds= build_equal_items(join->thd, conds, NULL, join_list,
43030 -+ &join->cond_equal);
43031 -+ DBUG_EXECUTE("where",print_where(conds,"after equal_items", QT_ORDINARY););
43032 -+
43033 -+ /* change field = field to field = const for each found field = const */
43034 -+ propagate_cond_constants(thd, (I_List<COND_CMP> *) 0, conds, conds);
43035 -+ /*
43036 -+ Remove all instances of item == item
43037 -+ Remove all and-levels where CONST item != CONST item
43038 -+ */
43039 -+ DBUG_EXECUTE("where",print_where(conds,"after const change", QT_ORDINARY););
43040 -+ conds= remove_eq_conds(thd, conds, cond_value) ;
43041 -+ DBUG_EXECUTE("info",print_where(conds,"after remove", QT_ORDINARY););
43042 -+ }
43043 -+ DBUG_RETURN(conds);
43044 -+}
43045 -+
43046 -+
43047 -+/**
43048 -+ Remove const and eq items.
43049 -+
43050 -+ @return
43051 -+ Return new item, or NULL if no condition @n
43052 -+ cond_value is set to according:
43053 -+ - COND_OK : query is possible (field = constant)
43054 -+ - COND_TRUE : always true ( 1 = 1 )
43055 -+ - COND_FALSE : always false ( 1 = 2 )
43056 -+*/
43057 -+
43058 -+COND *
43059 -+remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value)
43060 -+{
43061 -+ if (cond->type() == Item::COND_ITEM)
43062 -+ {
43063 -+ bool and_level= ((Item_cond*) cond)->functype()
43064 -+ == Item_func::COND_AND_FUNC;
43065 -+ List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
43066 -+ Item::cond_result tmp_cond_value;
43067 -+ bool should_fix_fields=0;
43068 -+
43069 -+ *cond_value=Item::COND_UNDEF;
43070 -+ Item *item;
43071 -+ while ((item=li++))
43072 -+ {
43073 -+ Item *new_item=remove_eq_conds(thd, item, &tmp_cond_value);
43074 -+ if (!new_item)
43075 -+ li.remove();
43076 -+ else if (item != new_item)
43077 -+ {
43078 -+ VOID(li.replace(new_item));
43079 -+ should_fix_fields=1;
43080 -+ }
43081 -+ if (*cond_value == Item::COND_UNDEF)
43082 -+ *cond_value=tmp_cond_value;
43083 -+ switch (tmp_cond_value) {
43084 -+ case Item::COND_OK: // Not TRUE or FALSE
43085 -+ if (and_level || *cond_value == Item::COND_FALSE)
43086 -+ *cond_value=tmp_cond_value;
43087 -+ break;
43088 -+ case Item::COND_FALSE:
43089 -+ if (and_level)
43090 -+ {
43091 -+ *cond_value=tmp_cond_value;
43092 -+ return (COND*) 0; // Always false
43093 -+ }
43094 -+ break;
43095 -+ case Item::COND_TRUE:
43096 -+ if (!and_level)
43097 -+ {
43098 -+ *cond_value= tmp_cond_value;
43099 -+ return (COND*) 0; // Always true
43100 -+ }
43101 -+ break;
43102 -+ case Item::COND_UNDEF: // Impossible
43103 -+ break; /* purecov: deadcode */
43104 -+ }
43105 -+ }
43106 -+ if (should_fix_fields)
43107 -+ cond->update_used_tables();
43108 -+
43109 -+ if (!((Item_cond*) cond)->argument_list()->elements ||
43110 -+ *cond_value != Item::COND_OK)
43111 -+ return (COND*) 0;
43112 -+ if (((Item_cond*) cond)->argument_list()->elements == 1)
43113 -+ { // Remove list
43114 -+ item= ((Item_cond*) cond)->argument_list()->head();
43115 -+ ((Item_cond*) cond)->argument_list()->empty();
43116 -+ return item;
43117 -+ }
43118 -+ }
43119 -+ else if (cond->type() == Item::FUNC_ITEM &&
43120 -+ ((Item_func*) cond)->functype() == Item_func::ISNULL_FUNC)
43121 -+ {
43122 -+ /*
43123 -+ Handles this special case for some ODBC applications:
43124 -+ The are requesting the row that was just updated with a auto_increment
43125 -+ value with this construct:
43126 -+
43127 -+ SELECT * from table_name where auto_increment_column IS NULL
43128 -+ This will be changed to:
43129 -+ SELECT * from table_name where auto_increment_column = LAST_INSERT_ID
43130 -+ */
43131 -+
43132 -+ Item_func_isnull *func=(Item_func_isnull*) cond;
43133 -+ Item **args= func->arguments();
43134 -+ if (args[0]->type() == Item::FIELD_ITEM)
43135 -+ {
43136 -+ Field *field=((Item_field*) args[0])->field;
43137 -+ if (field->flags & AUTO_INCREMENT_FLAG && !field->table->maybe_null &&
43138 -+ (thd->options & OPTION_AUTO_IS_NULL) &&
43139 -+ (thd->first_successful_insert_id_in_prev_stmt > 0 &&
43140 -+ thd->substitute_null_with_insert_id))
43141 -+ {
43142 -+#ifdef HAVE_QUERY_CACHE
43143 -+ query_cache_abort(&thd->net);
43144 -+#endif
43145 -+ COND *new_cond;
43146 -+ if ((new_cond= new Item_func_eq(args[0],
43147 -+ new Item_int("last_insert_id()",
43148 -+ thd->read_first_successful_insert_id_in_prev_stmt(),
43149 -+ MY_INT64_NUM_DECIMAL_DIGITS))))
43150 -+ {
43151 -+ cond=new_cond;
43152 -+ /*
43153 -+ Item_func_eq can't be fixed after creation so we do not check
43154 -+ cond->fixed, also it do not need tables so we use 0 as second
43155 -+ argument.
43156 -+ */
43157 -+ cond->fix_fields(thd, &cond);
43158 -+ }
43159 -+ /*
43160 -+ IS NULL should be mapped to LAST_INSERT_ID only for first row, so
43161 -+ clear for next row
43162 -+ */
43163 -+ thd->substitute_null_with_insert_id= FALSE;
43164 -+ }
43165 -+ /* fix to replace 'NULL' dates with '0' (shreeve@×××.edu) */
43166 -+ else if (((field->type() == MYSQL_TYPE_DATE) ||
43167 -+ (field->type() == MYSQL_TYPE_DATETIME)) &&
43168 -+ (field->flags & NOT_NULL_FLAG) &&
43169 -+ !field->table->maybe_null)
43170 -+ {
43171 -+ COND *new_cond;
43172 -+ if ((new_cond= new Item_func_eq(args[0],new Item_int("0", 0, 2))))
43173 -+ {
43174 -+ cond=new_cond;
43175 -+ /*
43176 -+ Item_func_eq can't be fixed after creation so we do not check
43177 -+ cond->fixed, also it do not need tables so we use 0 as second
43178 -+ argument.
43179 -+ */
43180 -+ cond->fix_fields(thd, &cond);
43181 -+ }
43182 -+ }
43183 -+ }
43184 -+ if (cond->const_item())
43185 -+ {
43186 -+ *cond_value= eval_const_cond(cond) ? Item::COND_TRUE : Item::COND_FALSE;
43187 -+ return (COND*) 0;
43188 -+ }
43189 -+ }
43190 -+ else if (cond->const_item())
43191 -+ {
43192 -+ *cond_value= eval_const_cond(cond) ? Item::COND_TRUE : Item::COND_FALSE;
43193 -+ return (COND*) 0;
43194 -+ }
43195 -+ else if ((*cond_value= cond->eq_cmp_result()) != Item::COND_OK)
43196 -+ { // boolan compare function
43197 -+ Item *left_item= ((Item_func*) cond)->arguments()[0];
43198 -+ Item *right_item= ((Item_func*) cond)->arguments()[1];
43199 -+ if (left_item->eq(right_item,1))
43200 -+ {
43201 -+ if (!left_item->maybe_null ||
43202 -+ ((Item_func*) cond)->functype() == Item_func::EQUAL_FUNC)
43203 -+ return (COND*) 0; // Compare of identical items
43204 -+ }
43205 -+ }
43206 -+ *cond_value=Item::COND_OK;
43207 -+ return cond; // Point at next and level
43208 -+}
43209 -+
43210 -+/*
43211 -+ Check if equality can be used in removing components of GROUP BY/DISTINCT
43212 -+
43213 -+ SYNOPSIS
43214 -+ test_if_equality_guarantees_uniqueness()
43215 -+ l the left comparison argument (a field if any)
43216 -+ r the right comparison argument (a const of any)
43217 -+
43218 -+ DESCRIPTION
43219 -+ Checks if an equality predicate can be used to take away
43220 -+ DISTINCT/GROUP BY because it is known to be true for exactly one
43221 -+ distinct value (e.g. <expr> == <const>).
43222 -+ Arguments must be of the same type because e.g.
43223 -+ <string_field> = <int_const> may match more than 1 distinct value from
43224 -+ the column.
43225 -+ We must take into consideration and the optimization done for various
43226 -+ string constants when compared to dates etc (see Item_int_with_ref) as
43227 -+ well as the collation of the arguments.
43228 -+
43229 -+ RETURN VALUE
43230 -+ TRUE can be used
43231 -+ FALSE cannot be used
43232 -+*/
43233 -+static bool
43234 -+test_if_equality_guarantees_uniqueness(Item *l, Item *r)
43235 -+{
43236 -+ return r->const_item() &&
43237 -+ /* elements must be compared as dates */
43238 -+ (Arg_comparator::can_compare_as_dates(l, r, 0) ||
43239 -+ /* or of the same result type */
43240 -+ (r->result_type() == l->result_type() &&
43241 -+ /* and must have the same collation if compared as strings */
43242 -+ (l->result_type() != STRING_RESULT ||
43243 -+ l->collation.collation == r->collation.collation)));
43244 -+}
43245 -+
43246 -+/**
43247 -+ Return TRUE if the item is a const value in all the WHERE clause.
43248 -+*/
43249 -+
43250 -+static bool
43251 -+const_expression_in_where(COND *cond, Item *comp_item, Item **const_item)
43252 -+{
43253 -+ if (cond->type() == Item::COND_ITEM)
43254 -+ {
43255 -+ bool and_level= (((Item_cond*) cond)->functype()
43256 -+ == Item_func::COND_AND_FUNC);
43257 -+ List_iterator_fast<Item> li(*((Item_cond*) cond)->argument_list());
43258 -+ Item *item;
43259 -+ while ((item=li++))
43260 -+ {
43261 -+ bool res=const_expression_in_where(item, comp_item, const_item);
43262 -+ if (res) // Is a const value
43263 -+ {
43264 -+ if (and_level)
43265 -+ return 1;
43266 -+ }
43267 -+ else if (!and_level)
43268 -+ return 0;
43269 -+ }
43270 -+ return and_level ? 0 : 1;
43271 -+ }
43272 -+ else if (cond->eq_cmp_result() != Item::COND_OK)
43273 -+ { // boolan compare function
43274 -+ Item_func* func= (Item_func*) cond;
43275 -+ if (func->functype() != Item_func::EQUAL_FUNC &&
43276 -+ func->functype() != Item_func::EQ_FUNC)
43277 -+ return 0;
43278 -+ Item *left_item= ((Item_func*) cond)->arguments()[0];
43279 -+ Item *right_item= ((Item_func*) cond)->arguments()[1];
43280 -+ if (left_item->eq(comp_item,1))
43281 -+ {
43282 -+ if (test_if_equality_guarantees_uniqueness (left_item, right_item))
43283 -+ {
43284 -+ if (*const_item)
43285 -+ return right_item->eq(*const_item, 1);
43286 -+ *const_item=right_item;
43287 -+ return 1;
43288 -+ }
43289 -+ }
43290 -+ else if (right_item->eq(comp_item,1))
43291 -+ {
43292 -+ if (test_if_equality_guarantees_uniqueness (right_item, left_item))
43293 -+ {
43294 -+ if (*const_item)
43295 -+ return left_item->eq(*const_item, 1);
43296 -+ *const_item=left_item;
43297 -+ return 1;
43298 -+ }
43299 -+ }
43300 -+ }
43301 -+ return 0;
43302 -+}
43303 -+
43304 -+/****************************************************************************
43305 -+ Create internal temporary table
43306 -+****************************************************************************/
43307 -+
43308 -+/**
43309 -+ Create field for temporary table from given field.
43310 -+
43311 -+ @param thd Thread handler
43312 -+ @param org_field field from which new field will be created
43313 -+ @param name New field name
43314 -+ @param table Temporary table
43315 -+ @param item !=NULL if item->result_field should point to new field.
43316 -+ This is relevant for how fill_record() is going to work:
43317 -+ If item != NULL then fill_record() will update
43318 -+ the record in the original table.
43319 -+ If item == NULL then fill_record() will update
43320 -+ the temporary table
43321 -+ @param convert_blob_length If >0 create a varstring(convert_blob_length)
43322 -+ field instead of blob.
43323 -+
43324 -+ @retval
43325 -+ NULL on error
43326 -+ @retval
43327 -+ new_created field
43328 -+*/
43329 -+
43330 -+Field *create_tmp_field_from_field(THD *thd, Field *org_field,
43331 -+ const char *name, TABLE *table,
43332 -+ Item_field *item, uint convert_blob_length)
43333 -+{
43334 -+ Field *new_field;
43335 -+
43336 -+ /*
43337 -+ Make sure that the blob fits into a Field_varstring which has
43338 -+ 2-byte lenght.
43339 -+ */
43340 -+ if (convert_blob_length && convert_blob_length <= Field_varstring::MAX_SIZE &&
43341 -+ (org_field->flags & BLOB_FLAG))
43342 -+ new_field= new Field_varstring(convert_blob_length,
43343 -+ org_field->maybe_null(),
43344 -+ org_field->field_name, table->s,
43345 -+ org_field->charset());
43346 -+ else
43347 -+ new_field= org_field->new_field(thd->mem_root, table,
43348 -+ table == org_field->table);
43349 -+ if (new_field)
43350 -+ {
43351 -+ new_field->init(table);
43352 -+ new_field->orig_table= org_field->orig_table;
43353 -+ if (item)
43354 -+ item->result_field= new_field;
43355 -+ else
43356 -+ new_field->field_name= name;
43357 -+ new_field->flags|= (org_field->flags & NO_DEFAULT_VALUE_FLAG);
43358 -+ if (org_field->maybe_null() || (item && item->maybe_null))
43359 -+ new_field->flags&= ~NOT_NULL_FLAG; // Because of outer join
43360 -+ if (org_field->type() == MYSQL_TYPE_VAR_STRING ||
43361 -+ org_field->type() == MYSQL_TYPE_VARCHAR)
43362 -+ table->s->db_create_options|= HA_OPTION_PACK_RECORD;
43363 -+ else if (org_field->type() == FIELD_TYPE_DOUBLE)
43364 -+ ((Field_double *) new_field)->not_fixed= TRUE;
43365 -+ }
43366 -+ return new_field;
43367 -+}
43368 -+
43369 -+/**
43370 -+ Create field for temporary table using type of given item.
43371 -+
43372 -+ @param thd Thread handler
43373 -+ @param item Item to create a field for
43374 -+ @param table Temporary table
43375 -+ @param copy_func If set and item is a function, store copy of
43376 -+ item in this array
43377 -+ @param modify_item 1 if item->result_field should point to new
43378 -+ item. This is relevent for how fill_record()
43379 -+ is going to work:
43380 -+ If modify_item is 1 then fill_record() will
43381 -+ update the record in the original table.
43382 -+ If modify_item is 0 then fill_record() will
43383 -+ update the temporary table
43384 -+ @param convert_blob_length If >0 create a varstring(convert_blob_length)
43385 -+ field instead of blob.
43386 -+
43387 -+ @retval
43388 -+ 0 on error
43389 -+ @retval
43390 -+ new_created field
43391 -+*/
43392 -+
43393 -+static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table,
43394 -+ Item ***copy_func, bool modify_item,
43395 -+ uint convert_blob_length)
43396 -+{
43397 -+ bool maybe_null= item->maybe_null;
43398 -+ Field *new_field;
43399 -+ LINT_INIT(new_field);
43400 -+
43401 -+ switch (item->result_type()) {
43402 -+ case REAL_RESULT:
43403 -+ new_field= new Field_double(item->max_length, maybe_null,
43404 -+ item->name, item->decimals, TRUE);
43405 -+ break;
43406 -+ case INT_RESULT:
43407 -+ /*
43408 -+ Select an integer type with the minimal fit precision.
43409 -+ MY_INT32_NUM_DECIMAL_DIGITS is sign inclusive, don't consider the sign.
43410 -+ Values with MY_INT32_NUM_DECIMAL_DIGITS digits may or may not fit into
43411 -+ Field_long : make them Field_longlong.
43412 -+ */
43413 -+ if (item->max_length >= (MY_INT32_NUM_DECIMAL_DIGITS - 1))
43414 -+ new_field=new Field_longlong(item->max_length, maybe_null,
43415 -+ item->name, item->unsigned_flag);
43416 -+ else
43417 -+ new_field=new Field_long(item->max_length, maybe_null,
43418 -+ item->name, item->unsigned_flag);
43419 -+ break;
43420 -+ case STRING_RESULT:
43421 -+ DBUG_ASSERT(item->collation.collation);
43422 -+
43423 -+ enum enum_field_types type;
43424 -+ /*
43425 -+ DATE/TIME and GEOMETRY fields have STRING_RESULT result type.
43426 -+ To preserve type they needed to be handled separately.
43427 -+ */
43428 -+ if ((type= item->field_type()) == MYSQL_TYPE_DATETIME ||
43429 -+ type == MYSQL_TYPE_TIME || type == MYSQL_TYPE_DATE ||
43430 -+ type == MYSQL_TYPE_NEWDATE ||
43431 -+ type == MYSQL_TYPE_TIMESTAMP || type == MYSQL_TYPE_GEOMETRY)
43432 -+ new_field= item->tmp_table_field_from_field_type(table, 1);
43433 -+ /*
43434 -+ Make sure that the blob fits into a Field_varstring which has
43435 -+ 2-byte lenght.
43436 -+ */
43437 -+ else if (item->max_length/item->collation.collation->mbmaxlen > 255 &&
43438 -+ convert_blob_length <= Field_varstring::MAX_SIZE &&
43439 -+ convert_blob_length)
43440 -+ new_field= new Field_varstring(convert_blob_length, maybe_null,
43441 -+ item->name, table->s,
43442 -+ item->collation.collation);
43443 -+ else
43444 -+ new_field= item->make_string_field(table);
43445 -+ new_field->set_derivation(item->collation.derivation);
43446 -+ break;
43447 -+ case DECIMAL_RESULT:
43448 -+ new_field= Field_new_decimal::create_from_item(item);
43449 -+ break;
43450 -+ case ROW_RESULT:
43451 -+ default:
43452 -+ // This case should never be choosen
43453 -+ DBUG_ASSERT(0);
43454 -+ new_field= 0;
43455 -+ break;
43456 -+ }
43457 -+ if (new_field)
43458 -+ new_field->init(table);
43459 -+
43460 -+ if (copy_func && item->is_result_field())
43461 -+ *((*copy_func)++) = item; // Save for copy_funcs
43462 -+ if (modify_item)
43463 -+ item->set_result_field(new_field);
43464 -+ if (item->type() == Item::NULL_ITEM)
43465 -+ new_field->is_created_from_null_item= TRUE;
43466 -+ return new_field;
43467 -+}
43468 -+
43469 -+
43470 -+/**
43471 -+ Create field for information schema table.
43472 -+
43473 -+ @param thd Thread handler
43474 -+ @param table Temporary table
43475 -+ @param item Item to create a field for
43476 -+
43477 -+ @retval
43478 -+ 0 on error
43479 -+ @retval
43480 -+ new_created field
43481 -+*/
43482 -+
43483 -+Field *create_tmp_field_for_schema(THD *thd, Item *item, TABLE *table)
43484 -+{
43485 -+ if (item->field_type() == MYSQL_TYPE_VARCHAR)
43486 -+ {
43487 -+ Field *field;
43488 -+ if (item->max_length > MAX_FIELD_VARCHARLENGTH)
43489 -+ field= new Field_blob(item->max_length, item->maybe_null,
43490 -+ item->name, item->collation.collation);
43491 -+ else
43492 -+ field= new Field_varstring(item->max_length, item->maybe_null,
43493 -+ item->name,
43494 -+ table->s, item->collation.collation);
43495 -+ if (field)
43496 -+ field->init(table);
43497 -+ return field;
43498 -+ }
43499 -+ return item->tmp_table_field_from_field_type(table, 0);
43500 -+}
43501 -+
43502 -+
43503 -+/**
43504 -+ Create field for temporary table.
43505 -+
43506 -+ @param thd Thread handler
43507 -+ @param table Temporary table
43508 -+ @param item Item to create a field for
43509 -+ @param type Type of item (normally item->type)
43510 -+ @param copy_func If set and item is a function, store copy of item
43511 -+ in this array
43512 -+ @param from_field if field will be created using other field as example,
43513 -+ pointer example field will be written here
43514 -+ @param default_field If field has a default value field, store it here
43515 -+ @param group 1 if we are going to do a relative group by on result
43516 -+ @param modify_item 1 if item->result_field should point to new item.
43517 -+ This is relevent for how fill_record() is going to
43518 -+ work:
43519 -+ If modify_item is 1 then fill_record() will update
43520 -+ the record in the original table.
43521 -+ If modify_item is 0 then fill_record() will update
43522 -+ the temporary table
43523 -+ @param convert_blob_length If >0 create a varstring(convert_blob_length)
43524 -+ field instead of blob.
43525 -+
43526 -+ @retval
43527 -+ 0 on error
43528 -+ @retval
43529 -+ new_created field
43530 -+*/
43531 -+
43532 -+Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
43533 -+ Item ***copy_func, Field **from_field,
43534 -+ Field **default_field,
43535 -+ bool group, bool modify_item,
43536 -+ bool table_cant_handle_bit_fields,
43537 -+ bool make_copy_field,
43538 -+ uint convert_blob_length)
43539 -+{
43540 -+ Field *result;
43541 -+ Item::Type orig_type= type;
43542 -+ Item *orig_item= 0;
43543 -+
43544 -+ if (type != Item::FIELD_ITEM &&
43545 -+ item->real_item()->type() == Item::FIELD_ITEM)
43546 -+ {
43547 -+ orig_item= item;
43548 -+ item= item->real_item();
43549 -+ type= Item::FIELD_ITEM;
43550 -+ }
43551 -+
43552 -+ switch (type) {
43553 -+ case Item::SUM_FUNC_ITEM:
43554 -+ {
43555 -+ Item_sum *item_sum=(Item_sum*) item;
43556 -+ result= item_sum->create_tmp_field(group, table, convert_blob_length);
43557 -+ if (!result)
43558 -+ thd->fatal_error();
43559 -+ return result;
43560 -+ }
43561 -+ case Item::FIELD_ITEM:
43562 -+ case Item::DEFAULT_VALUE_ITEM:
43563 -+ {
43564 -+ Item_field *field= (Item_field*) item;
43565 -+ bool orig_modify= modify_item;
43566 -+ if (orig_type == Item::REF_ITEM)
43567 -+ modify_item= 0;
43568 -+ /*
43569 -+ If item have to be able to store NULLs but underlaid field can't do it,
43570 -+ create_tmp_field_from_field() can't be used for tmp field creation.
43571 -+ */
43572 -+ if (field->maybe_null && !field->field->maybe_null())
43573 -+ {
43574 -+ result= create_tmp_field_from_item(thd, item, table, NULL,
43575 -+ modify_item, convert_blob_length);
43576 -+ *from_field= field->field;
43577 -+ if (result && modify_item)
43578 -+ field->result_field= result;
43579 -+ }
43580 -+ else if (table_cant_handle_bit_fields && field->field->type() ==
43581 -+ MYSQL_TYPE_BIT)
43582 -+ {
43583 -+ *from_field= field->field;
43584 -+ result= create_tmp_field_from_item(thd, item, table, copy_func,
43585 -+ modify_item, convert_blob_length);
43586 -+ if (result && modify_item)
43587 -+ field->result_field= result;
43588 -+ }
43589 -+ else
43590 -+ result= create_tmp_field_from_field(thd, (*from_field= field->field),
43591 -+ orig_item ? orig_item->name :
43592 -+ item->name,
43593 -+ table,
43594 -+ modify_item ? field :
43595 -+ NULL,
43596 -+ convert_blob_length);
43597 -+ if (orig_type == Item::REF_ITEM && orig_modify)
43598 -+ ((Item_ref*)orig_item)->set_result_field(result);
43599 -+ /*
43600 -+ Fields that are used as arguments to the DEFAULT() function already have
43601 -+ their data pointers set to the default value during name resulotion. See
43602 -+ Item_default_value::fix_fields.
43603 -+ */
43604 -+ if (orig_type != Item::DEFAULT_VALUE_ITEM && field->field->eq_def(result))
43605 -+ *default_field= field->field;
43606 -+ return result;
43607 -+ }
43608 -+ /* Fall through */
43609 -+ case Item::FUNC_ITEM:
43610 -+ if (((Item_func *) item)->functype() == Item_func::FUNC_SP)
43611 -+ {
43612 -+ Item_func_sp *item_func_sp= (Item_func_sp *) item;
43613 -+ Field *sp_result_field= item_func_sp->get_sp_result_field();
43614 -+
43615 -+ if (make_copy_field)
43616 -+ {
43617 -+ DBUG_ASSERT(item_func_sp->result_field);
43618 -+ *from_field= item_func_sp->result_field;
43619 -+ }
43620 -+ else
43621 -+ {
43622 -+ *((*copy_func)++)= item;
43623 -+ }
43624 -+
43625 -+ Field *result_field=
43626 -+ create_tmp_field_from_field(thd,
43627 -+ sp_result_field,
43628 -+ item_func_sp->name,
43629 -+ table,
43630 -+ NULL,
43631 -+ convert_blob_length);
43632 -+
43633 -+ if (modify_item)
43634 -+ item->set_result_field(result_field);
43635 -+
43636 -+ return result_field;
43637 -+ }
43638 -+
43639 -+ /* Fall through */
43640 -+ case Item::COND_ITEM:
43641 -+ case Item::FIELD_AVG_ITEM:
43642 -+ case Item::FIELD_STD_ITEM:
43643 -+ case Item::SUBSELECT_ITEM:
43644 -+ /* The following can only happen with 'CREATE TABLE ... SELECT' */
43645 -+ case Item::PROC_ITEM:
43646 -+ case Item::INT_ITEM:
43647 -+ case Item::REAL_ITEM:
43648 -+ case Item::DECIMAL_ITEM:
43649 -+ case Item::STRING_ITEM:
43650 -+ case Item::REF_ITEM:
43651 -+ case Item::NULL_ITEM:
43652 -+ case Item::VARBIN_ITEM:
43653 -+ if (make_copy_field)
43654 -+ {
43655 -+ DBUG_ASSERT(((Item_result_field*)item)->result_field);
43656 -+ *from_field= ((Item_result_field*)item)->result_field;
43657 -+ }
43658 -+ return create_tmp_field_from_item(thd, item, table,
43659 -+ (make_copy_field ? 0 : copy_func),
43660 -+ modify_item, convert_blob_length);
43661 -+ case Item::TYPE_HOLDER:
43662 -+ result= ((Item_type_holder *)item)->make_field_by_type(table);
43663 -+ result->set_derivation(item->collation.derivation);
43664 -+ return result;
43665 -+ default: // Dosen't have to be stored
43666 -+ return 0;
43667 -+ }
43668 -+}
43669 -+
43670 -+/*
43671 -+ Set up column usage bitmaps for a temporary table
43672 -+
43673 -+ IMPLEMENTATION
43674 -+ For temporary tables, we need one bitmap with all columns set and
43675 -+ a tmp_set bitmap to be used by things like filesort.
43676 -+*/
43677 -+
43678 -+void setup_tmp_table_column_bitmaps(TABLE *table, uchar *bitmaps)
43679 -+{
43680 -+ uint field_count= table->s->fields;
43681 -+ bitmap_init(&table->def_read_set, (my_bitmap_map*) bitmaps, field_count,
43682 -+ FALSE);
43683 -+ bitmap_init(&table->tmp_set,
43684 -+ (my_bitmap_map*) (bitmaps+ bitmap_buffer_size(field_count)),
43685 -+ field_count, FALSE);
43686 -+ /* write_set and all_set are copies of read_set */
43687 -+ table->def_write_set= table->def_read_set;
43688 -+ table->s->all_set= table->def_read_set;
43689 -+ bitmap_set_all(&table->s->all_set);
43690 -+ table->default_column_bitmaps();
43691 -+}
43692 -+
43693 -+
43694 -+/**
43695 -+ Create a temp table according to a field list.
43696 -+
43697 -+ Given field pointers are changed to point at tmp_table for
43698 -+ send_fields. The table object is self contained: it's
43699 -+ allocated in its own memory root, as well as Field objects
43700 -+ created for table columns.
43701 -+ This function will replace Item_sum items in 'fields' list with
43702 -+ corresponding Item_field items, pointing at the fields in the
43703 -+ temporary table, unless this was prohibited by TRUE
43704 -+ value of argument save_sum_fields. The Item_field objects
43705 -+ are created in THD memory root.
43706 -+
43707 -+ @param thd thread handle
43708 -+ @param param a description used as input to create the table
43709 -+ @param fields list of items that will be used to define
43710 -+ column types of the table (also see NOTES)
43711 -+ @param group TODO document
43712 -+ @param distinct should table rows be distinct
43713 -+ @param save_sum_fields see NOTES
43714 -+ @param select_options
43715 -+ @param rows_limit
43716 -+ @param table_alias possible name of the temporary table that can
43717 -+ be used for name resolving; can be "".
43718 -+*/
43719 -+
43720 -+#define STRING_TOTAL_LENGTH_TO_PACK_ROWS 128
43721 -+#define AVG_STRING_LENGTH_TO_PACK_ROWS 64
43722 -+#define RATIO_TO_PACK_ROWS 2
43723 -+#define MIN_STRING_LENGTH_TO_PACK_ROWS 10
43724 -+
43725 -+TABLE *
43726 -+create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
43727 -+ ORDER *group, bool distinct, bool save_sum_fields,
43728 -+ ulonglong select_options, ha_rows rows_limit,
43729 -+ char *table_alias)
43730 -+{
43731 -+ MEM_ROOT *mem_root_save, own_root;
43732 -+ TABLE *table;
43733 -+ TABLE_SHARE *share;
43734 -+ uint i,field_count,null_count,null_pack_length;
43735 -+ uint copy_func_count= param->func_count;
43736 -+ uint hidden_null_count, hidden_null_pack_length, hidden_field_count;
43737 -+ uint blob_count,group_null_items, string_count;
43738 -+ uint temp_pool_slot=MY_BIT_NONE;
43739 -+ uint fieldnr= 0;
43740 -+ ulong reclength, string_total_length;
43741 -+ bool using_unique_constraint= 0;
43742 -+ bool use_packed_rows= 0;
43743 -+ bool not_all_columns= !(select_options & TMP_TABLE_ALL_COLUMNS);
43744 -+ char *tmpname,path[FN_REFLEN];
43745 -+ uchar *pos, *group_buff, *bitmaps;
43746 -+ uchar *null_flags;
43747 -+ Field **reg_field, **from_field, **default_field;
43748 -+ uint *blob_field;
43749 -+ Copy_field *copy=0;
43750 -+ KEY *keyinfo;
43751 -+ KEY_PART_INFO *key_part_info;
43752 -+ Item **copy_func;
43753 -+ MI_COLUMNDEF *recinfo;
43754 -+ /*
43755 -+ total_uneven_bit_length is uneven bit length for visible fields
43756 -+ hidden_uneven_bit_length is uneven bit length for hidden fields
43757 -+ */
43758 -+ uint total_uneven_bit_length= 0, hidden_uneven_bit_length= 0;
43759 -+ bool force_copy_fields= param->force_copy_fields;
43760 -+ /* Treat sum functions as normal ones when loose index scan is used. */
43761 -+ save_sum_fields|= param->precomputed_group_by;
43762 -+ DBUG_ENTER("create_tmp_table");
43763 -+ DBUG_PRINT("enter",
43764 -+ ("distinct: %d save_sum_fields: %d rows_limit: %lu group: %d",
43765 -+ (int) distinct, (int) save_sum_fields,
43766 -+ (ulong) rows_limit,test(group)));
43767 -+
43768 -+ status_var_increment(thd->status_var.created_tmp_tables);
43769 -+
43770 -+ if (use_temp_pool && !(test_flags & TEST_KEEP_TMP_TABLES))
43771 -+ temp_pool_slot = bitmap_lock_set_next(&temp_pool);
43772 -+
43773 -+ if (temp_pool_slot != MY_BIT_NONE) // we got a slot
43774 -+ sprintf(path, "%s_%lx_%i", tmp_file_prefix,
43775 -+ current_pid, temp_pool_slot);
43776 -+ else
43777 -+ {
43778 -+ /* if we run out of slots or we are not using tempool */
43779 -+ sprintf(path,"%s%lx_%lx_%x", tmp_file_prefix,current_pid,
43780 -+ thd->thread_id, thd->tmp_table++);
43781 -+ }
43782 -+
43783 -+ /*
43784 -+ No need to change table name to lower case as we are only creating
43785 -+ MyISAM or HEAP tables here
43786 -+ */
43787 -+ fn_format(path, path, mysql_tmpdir, "", MY_REPLACE_EXT|MY_UNPACK_FILENAME);
43788 -+
43789 -+
43790 -+ if (group)
43791 -+ {
43792 -+ if (!param->quick_group)
43793 -+ group=0; // Can't use group key
43794 -+ else for (ORDER *tmp=group ; tmp ; tmp=tmp->next)
43795 -+ {
43796 -+ (*tmp->item)->marker=4; // Store null in key
43797 -+ if ((*tmp->item)->max_length >= CONVERT_IF_BIGGER_TO_BLOB)
43798 -+ using_unique_constraint=1;
43799 -+ }
43800 -+ if (param->group_length >= MAX_BLOB_WIDTH)
43801 -+ using_unique_constraint=1;
43802 -+ if (group)
43803 -+ distinct=0; // Can't use distinct
43804 -+ }
43805 -+
43806 -+ field_count=param->field_count+param->func_count+param->sum_func_count;
43807 -+ hidden_field_count=param->hidden_field_count;
43808 -+
43809 -+ /*
43810 -+ When loose index scan is employed as access method, it already
43811 -+ computes all groups and the result of all aggregate functions. We
43812 -+ make space for the items of the aggregate function in the list of
43813 -+ functions TMP_TABLE_PARAM::items_to_copy, so that the values of
43814 -+ these items are stored in the temporary table.
43815 -+ */
43816 -+ if (param->precomputed_group_by)
43817 -+ copy_func_count+= param->sum_func_count;
43818 -+
43819 -+ init_sql_alloc(&own_root, TABLE_ALLOC_BLOCK_SIZE, 0);
43820 -+
43821 -+ if (!multi_alloc_root(&own_root,
43822 -+ &table, sizeof(*table),
43823 -+ &share, sizeof(*share),
43824 -+ &reg_field, sizeof(Field*) * (field_count+1),
43825 -+ &default_field, sizeof(Field*) * (field_count),
43826 -+ &blob_field, sizeof(uint)*(field_count+1),
43827 -+ &from_field, sizeof(Field*)*field_count,
43828 -+ &copy_func, sizeof(*copy_func)*(copy_func_count+1),
43829 -+ &param->keyinfo, sizeof(*param->keyinfo),
43830 -+ &key_part_info,
43831 -+ sizeof(*key_part_info)*(param->group_parts+1),
43832 -+ &param->start_recinfo,
43833 -+ sizeof(*param->recinfo)*(field_count*2+4),
43834 -+ &tmpname, (uint) strlen(path)+1,
43835 -+ &group_buff, (group && ! using_unique_constraint ?
43836 -+ param->group_length : 0),
43837 -+ &bitmaps, bitmap_buffer_size(field_count)*2,
43838 -+ NullS))
43839 -+ {
43840 -+ if (temp_pool_slot != MY_BIT_NONE)
43841 -+ bitmap_lock_clear_bit(&temp_pool, temp_pool_slot);
43842 -+ DBUG_RETURN(NULL); /* purecov: inspected */
43843 -+ }
43844 -+ /* Copy_field belongs to TMP_TABLE_PARAM, allocate it in THD mem_root */
43845 -+ if (!(param->copy_field= copy= new (thd->mem_root) Copy_field[field_count]))
43846 -+ {
43847 -+ if (temp_pool_slot != MY_BIT_NONE)
43848 -+ bitmap_lock_clear_bit(&temp_pool, temp_pool_slot);
43849 -+ free_root(&own_root, MYF(0)); /* purecov: inspected */
43850 -+ DBUG_RETURN(NULL); /* purecov: inspected */
43851 -+ }
43852 -+ param->items_to_copy= copy_func;
43853 -+ strmov(tmpname,path);
43854 -+ /* make table according to fields */
43855 -+
43856 -+ bzero((char*) table,sizeof(*table));
43857 -+ bzero((char*) reg_field,sizeof(Field*)*(field_count+1));
43858 -+ bzero((char*) default_field, sizeof(Field*) * (field_count));
43859 -+ bzero((char*) from_field,sizeof(Field*)*field_count);
43860 -+
43861 -+ table->mem_root= own_root;
43862 -+ mem_root_save= thd->mem_root;
43863 -+ thd->mem_root= &table->mem_root;
43864 -+
43865 -+ table->field=reg_field;
43866 -+ table->alias= table_alias;
43867 -+ table->reginfo.lock_type=TL_WRITE; /* Will be updated */
43868 -+ table->db_stat=HA_OPEN_KEYFILE+HA_OPEN_RNDFILE;
43869 -+ table->map=1;
43870 -+ table->temp_pool_slot = temp_pool_slot;
43871 -+ table->copy_blobs= 1;
43872 -+ table->in_use= thd;
43873 -+ table->quick_keys.init();
43874 -+ table->covering_keys.init();
43875 -+ table->merge_keys.init();
43876 -+ table->keys_in_use_for_query.init();
43877 -+
43878 -+ table->s= share;
43879 -+ init_tmp_table_share(thd, share, "", 0, tmpname, tmpname);
43880 -+ share->blob_field= blob_field;
43881 -+ share->blob_ptr_size= portable_sizeof_char_ptr;
43882 -+ share->db_low_byte_first=1; // True for HEAP and MyISAM
43883 -+ share->table_charset= param->table_charset;
43884 -+ share->primary_key= MAX_KEY; // Indicate no primary key
43885 -+ share->keys_for_keyread.init();
43886 -+ share->keys_in_use.init();
43887 -+
43888 -+ /* Calculate which type of fields we will store in the temporary table */
43889 -+
43890 -+ reclength= string_total_length= 0;
43891 -+ blob_count= string_count= null_count= hidden_null_count= group_null_items= 0;
43892 -+ param->using_indirect_summary_function=0;
43893 -+
43894 -+ List_iterator_fast<Item> li(fields);
43895 -+ Item *item;
43896 -+ Field **tmp_from_field=from_field;
43897 -+ while ((item=li++))
43898 -+ {
43899 -+ Item::Type type=item->type();
43900 -+ if (not_all_columns)
43901 -+ {
43902 -+ if (item->with_sum_func && type != Item::SUM_FUNC_ITEM)
43903 -+ {
43904 -+ if (item->used_tables() & OUTER_REF_TABLE_BIT)
43905 -+ item->update_used_tables();
43906 -+ if (type == Item::SUBSELECT_ITEM ||
43907 -+ (item->used_tables() & ~OUTER_REF_TABLE_BIT))
43908 -+ {
43909 -+ /*
43910 -+ Mark that the we have ignored an item that refers to a summary
43911 -+ function. We need to know this if someone is going to use
43912 -+ DISTINCT on the result.
43913 -+ */
43914 -+ param->using_indirect_summary_function=1;
43915 -+ continue;
43916 -+ }
43917 -+ }
43918 -+ if (item->const_item() && (int) hidden_field_count <= 0)
43919 -+ continue; // We don't have to store this
43920 -+ }
43921 -+ if (type == Item::SUM_FUNC_ITEM && !group && !save_sum_fields)
43922 -+ { /* Can't calc group yet */
43923 -+ Item_sum *sum_item= (Item_sum *) item;
43924 -+ sum_item->result_field=0;
43925 -+ for (i=0 ; i < sum_item->get_arg_count() ; i++)
43926 -+ {
43927 -+ Item *arg= sum_item->get_arg(i);
43928 -+ if (!arg->const_item())
43929 -+ {
43930 -+ Field *new_field=
43931 -+ create_tmp_field(thd, table, arg, arg->type(), &copy_func,
43932 -+ tmp_from_field, &default_field[fieldnr],
43933 -+ group != 0,not_all_columns,
43934 -+ distinct, 0,
43935 -+ param->convert_blob_length);
43936 -+ if (!new_field)
43937 -+ goto err; // Should be OOM
43938 -+ tmp_from_field++;
43939 -+ reclength+=new_field->pack_length();
43940 -+ if (new_field->flags & BLOB_FLAG)
43941 -+ {
43942 -+ *blob_field++= fieldnr;
43943 -+ blob_count++;
43944 -+ }
43945 -+ if (new_field->type() == MYSQL_TYPE_BIT)
43946 -+ total_uneven_bit_length+= new_field->field_length & 7;
43947 -+ *(reg_field++)= new_field;
43948 -+ if (new_field->real_type() == MYSQL_TYPE_STRING ||
43949 -+ new_field->real_type() == MYSQL_TYPE_VARCHAR)
43950 -+ {
43951 -+ string_count++;
43952 -+ string_total_length+= new_field->pack_length();
43953 -+ }
43954 -+ thd->mem_root= mem_root_save;
43955 -+ arg= sum_item->set_arg(i, thd, new Item_field(new_field));
43956 -+ thd->mem_root= &table->mem_root;
43957 -+ if (!(new_field->flags & NOT_NULL_FLAG))
43958 -+ {
43959 -+ null_count++;
43960 -+ /*
43961 -+ new_field->maybe_null() is still false, it will be
43962 -+ changed below. But we have to setup Item_field correctly
43963 -+ */
43964 -+ arg->maybe_null=1;
43965 -+ }
43966 -+ new_field->field_index= fieldnr++;
43967 -+ }
43968 -+ }
43969 -+ }
43970 -+ else
43971 -+ {
43972 -+ /*
43973 -+ The last parameter to create_tmp_field() is a bit tricky:
43974 -+
43975 -+ We need to set it to 0 in union, to get fill_record() to modify the
43976 -+ temporary table.
43977 -+ We need to set it to 1 on multi-table-update and in select to
43978 -+ write rows to the temporary table.
43979 -+ We here distinguish between UNION and multi-table-updates by the fact
43980 -+ that in the later case group is set to the row pointer.
43981 -+
43982 -+ The test for item->marker == 4 is ensure we don't create a group-by
43983 -+ key over a bit field as heap tables can't handle that.
43984 -+ */
43985 -+ Field *new_field= (param->schema_table) ?
43986 -+ create_tmp_field_for_schema(thd, item, table) :
43987 -+ create_tmp_field(thd, table, item, type, &copy_func,
43988 -+ tmp_from_field, &default_field[fieldnr],
43989 -+ group != 0,
43990 -+ !force_copy_fields &&
43991 -+ (not_all_columns || group !=0),
43992 -+ item->marker == 4, force_copy_fields,
43993 -+ param->convert_blob_length);
43994 -+
43995 -+ if (!new_field)
43996 -+ {
43997 -+ if (thd->is_fatal_error)
43998 -+ goto err; // Got OOM
43999 -+ continue; // Some kindf of const item
44000 -+ }
44001 -+ if (type == Item::SUM_FUNC_ITEM)
44002 -+ ((Item_sum *) item)->result_field= new_field;
44003 -+ tmp_from_field++;
44004 -+ reclength+=new_field->pack_length();
44005 -+ if (!(new_field->flags & NOT_NULL_FLAG))
44006 -+ null_count++;
44007 -+ if (new_field->type() == MYSQL_TYPE_BIT)
44008 -+ total_uneven_bit_length+= new_field->field_length & 7;
44009 -+ if (new_field->flags & BLOB_FLAG)
44010 -+ {
44011 -+ *blob_field++= fieldnr;
44012 -+ blob_count++;
44013 -+ }
44014 -+ if (item->marker == 4 && item->maybe_null)
44015 -+ {
44016 -+ group_null_items++;
44017 -+ new_field->flags|= GROUP_FLAG;
44018 -+ }
44019 -+ new_field->field_index= fieldnr++;
44020 -+ *(reg_field++)= new_field;
44021 -+ }
44022 -+ if (!--hidden_field_count)
44023 -+ {
44024 -+ /*
44025 -+ This was the last hidden field; Remember how many hidden fields could
44026 -+ have null
44027 -+ */
44028 -+ hidden_null_count=null_count;
44029 -+ /*
44030 -+ We need to update hidden_field_count as we may have stored group
44031 -+ functions with constant arguments
44032 -+ */
44033 -+ param->hidden_field_count= fieldnr;
44034 -+ null_count= 0;
44035 -+ /*
44036 -+ On last hidden field we store uneven bit length in
44037 -+ hidden_uneven_bit_length and proceed calculation of
44038 -+ uneven bits for visible fields into
44039 -+ total_uneven_bit_length variable.
44040 -+ */
44041 -+ hidden_uneven_bit_length= total_uneven_bit_length;
44042 -+ total_uneven_bit_length= 0;
44043 -+ }
44044 -+ }
44045 -+ DBUG_ASSERT(fieldnr == (uint) (reg_field - table->field));
44046 -+ DBUG_ASSERT(field_count >= (uint) (reg_field - table->field));
44047 -+ field_count= fieldnr;
44048 -+ *reg_field= 0;
44049 -+ *blob_field= 0; // End marker
44050 -+ share->fields= field_count;
44051 -+
44052 -+ /* If result table is small; use a heap */
44053 -+ /* future: storage engine selection can be made dynamic? */
44054 -+ if (blob_count || using_unique_constraint ||
44055 -+ (select_options & (OPTION_BIG_TABLES | SELECT_SMALL_RESULT)) ==
44056 -+ OPTION_BIG_TABLES || (select_options & TMP_TABLE_FORCE_MYISAM))
44057 -+ {
44058 -+ share->db_plugin= ha_lock_engine(0, myisam_hton);
44059 -+ table->file= get_new_handler(share, &table->mem_root,
44060 -+ share->db_type());
44061 -+ if (group &&
44062 -+ (param->group_parts > table->file->max_key_parts() ||
44063 -+ param->group_length > table->file->max_key_length()))
44064 -+ using_unique_constraint=1;
44065 -+ }
44066 -+ else
44067 -+ {
44068 -+ share->db_plugin= ha_lock_engine(0, heap_hton);
44069 -+ table->file= get_new_handler(share, &table->mem_root,
44070 -+ share->db_type());
44071 -+ }
44072 -+ if (!table->file)
44073 -+ goto err;
44074 -+
44075 -+
44076 -+ if (!using_unique_constraint)
44077 -+ reclength+= group_null_items; // null flag is stored separately
44078 -+
44079 -+ share->blob_fields= blob_count;
44080 -+ if (blob_count == 0)
44081 -+ {
44082 -+ /* We need to ensure that first byte is not 0 for the delete link */
44083 -+ if (param->hidden_field_count)
44084 -+ hidden_null_count++;
44085 -+ else
44086 -+ null_count++;
44087 -+ }
44088 -+ hidden_null_pack_length= (hidden_null_count + 7 +
44089 -+ hidden_uneven_bit_length) / 8;
44090 -+ null_pack_length= (hidden_null_pack_length +
44091 -+ (null_count + total_uneven_bit_length + 7) / 8);
44092 -+ reclength+=null_pack_length;
44093 -+ if (!reclength)
44094 -+ reclength=1; // Dummy select
44095 -+ /* Use packed rows if there is blobs or a lot of space to gain */
44096 -+ if (blob_count ||
44097 -+ (string_total_length >= STRING_TOTAL_LENGTH_TO_PACK_ROWS &&
44098 -+ (reclength / string_total_length <= RATIO_TO_PACK_ROWS ||
44099 -+ string_total_length / string_count >= AVG_STRING_LENGTH_TO_PACK_ROWS)))
44100 -+ use_packed_rows= 1;
44101 -+
44102 -+ share->reclength= reclength;
44103 -+ {
44104 -+ uint alloc_length=ALIGN_SIZE(reclength+MI_UNIQUE_HASH_LENGTH+1);
44105 -+ share->rec_buff_length= alloc_length;
44106 -+ if (!(table->record[0]= (uchar*)
44107 -+ alloc_root(&table->mem_root, alloc_length*3)))
44108 -+ goto err;
44109 -+ table->record[1]= table->record[0]+alloc_length;
44110 -+ share->default_values= table->record[1]+alloc_length;
44111 -+ }
44112 -+ copy_func[0]=0; // End marker
44113 -+ param->func_count= copy_func - param->items_to_copy;
44114 -+
44115 -+ setup_tmp_table_column_bitmaps(table, bitmaps);
44116 -+
44117 -+ recinfo=param->start_recinfo;
44118 -+ null_flags=(uchar*) table->record[0];
44119 -+ pos=table->record[0]+ null_pack_length;
44120 -+ if (null_pack_length)
44121 -+ {
44122 -+ bzero((uchar*) recinfo,sizeof(*recinfo));
44123 -+ recinfo->type=FIELD_NORMAL;
44124 -+ recinfo->length=null_pack_length;
44125 -+ recinfo++;
44126 -+ bfill(null_flags,null_pack_length,255); // Set null fields
44127 -+
44128 -+ table->null_flags= (uchar*) table->record[0];
44129 -+ share->null_fields= null_count+ hidden_null_count;
44130 -+ share->null_bytes= null_pack_length;
44131 -+ }
44132 -+ null_count= (blob_count == 0) ? 1 : 0;
44133 -+ hidden_field_count=param->hidden_field_count;
44134 -+ for (i=0,reg_field=table->field; i < field_count; i++,reg_field++,recinfo++)
44135 -+ {
44136 -+ Field *field= *reg_field;
44137 -+ uint length;
44138 -+ bzero((uchar*) recinfo,sizeof(*recinfo));
44139 -+
44140 -+ if (!(field->flags & NOT_NULL_FLAG))
44141 -+ {
44142 -+ if (field->flags & GROUP_FLAG && !using_unique_constraint)
44143 -+ {
44144 -+ /*
44145 -+ We have to reserve one byte here for NULL bits,
44146 -+ as this is updated by 'end_update()'
44147 -+ */
44148 -+ *pos++=0; // Null is stored here
44149 -+ recinfo->length=1;
44150 -+ recinfo->type=FIELD_NORMAL;
44151 -+ recinfo++;
44152 -+ bzero((uchar*) recinfo,sizeof(*recinfo));
44153 -+ }
44154 -+ else
44155 -+ {
44156 -+ recinfo->null_bit= 1 << (null_count & 7);
44157 -+ recinfo->null_pos= null_count/8;
44158 -+ }
44159 -+ field->move_field(pos,null_flags+null_count/8,
44160 -+ 1 << (null_count & 7));
44161 -+ null_count++;
44162 -+ }
44163 -+ else
44164 -+ field->move_field(pos,(uchar*) 0,0);
44165 -+ if (field->type() == MYSQL_TYPE_BIT)
44166 -+ {
44167 -+ /* We have to reserve place for extra bits among null bits */
44168 -+ ((Field_bit*) field)->set_bit_ptr(null_flags + null_count / 8,
44169 -+ null_count & 7);
44170 -+ null_count+= (field->field_length & 7);
44171 -+ }
44172 -+ field->reset();
44173 -+
44174 -+ /*
44175 -+ Test if there is a default field value. The test for ->ptr is to skip
44176 -+ 'offset' fields generated by initalize_tables
44177 -+ */
44178 -+ if (default_field[i] && default_field[i]->ptr)
44179 -+ {
44180 -+ /*
44181 -+ default_field[i] is set only in the cases when 'field' can
44182 -+ inherit the default value that is defined for the field referred
44183 -+ by the Item_field object from which 'field' has been created.
44184 -+ */
44185 -+ my_ptrdiff_t diff;
44186 -+ Field *orig_field= default_field[i];
44187 -+ /* Get the value from default_values */
44188 -+ diff= (my_ptrdiff_t) (orig_field->table->s->default_values-
44189 -+ orig_field->table->record[0]);
44190 -+ orig_field->move_field_offset(diff); // Points now at default_values
44191 -+ if (orig_field->is_real_null())
44192 -+ field->set_null();
44193 -+ else
44194 -+ {
44195 -+ field->set_notnull();
44196 -+ memcpy(field->ptr, orig_field->ptr, field->pack_length());
44197 -+ }
44198 -+ orig_field->move_field_offset(-diff); // Back to record[0]
44199 -+ }
44200 -+
44201 -+ if (from_field[i])
44202 -+ { /* Not a table Item */
44203 -+ copy->set(field,from_field[i],save_sum_fields);
44204 -+ copy++;
44205 -+ }
44206 -+ length=field->pack_length();
44207 -+ pos+= length;
44208 -+
44209 -+ /* Make entry for create table */
44210 -+ recinfo->length=length;
44211 -+ if (field->flags & BLOB_FLAG)
44212 -+ recinfo->type= (int) FIELD_BLOB;
44213 -+ else if (use_packed_rows &&
44214 -+ field->real_type() == MYSQL_TYPE_STRING &&
44215 -+ length >= MIN_STRING_LENGTH_TO_PACK_ROWS)
44216 -+ recinfo->type=FIELD_SKIP_ENDSPACE;
44217 -+ else
44218 -+ recinfo->type=FIELD_NORMAL;
44219 -+ if (!--hidden_field_count)
44220 -+ null_count=(null_count+7) & ~7; // move to next byte
44221 -+
44222 -+ // fix table name in field entry
44223 -+ field->table_name= &table->alias;
44224 -+ }
44225 -+
44226 -+ param->copy_field_end=copy;
44227 -+ param->recinfo=recinfo;
44228 -+ store_record(table,s->default_values); // Make empty default record
44229 -+
44230 -+ if (thd->variables.tmp_table_size == ~ (ulonglong) 0) // No limit
44231 -+ share->max_rows= ~(ha_rows) 0;
44232 -+ else
44233 -+ share->max_rows= (ha_rows) (((share->db_type() == heap_hton) ?
44234 -+ min(thd->variables.tmp_table_size,
44235 -+ thd->variables.max_heap_table_size) :
44236 -+ thd->variables.tmp_table_size) /
44237 -+ share->reclength);
44238 -+ set_if_bigger(share->max_rows,1); // For dummy start options
44239 -+ /*
44240 -+ Push the LIMIT clause to the temporary table creation, so that we
44241 -+ materialize only up to 'rows_limit' records instead of all result records.
44242 -+ */
44243 -+ set_if_smaller(share->max_rows, rows_limit);
44244 -+ param->end_write_records= rows_limit;
44245 -+
44246 -+ keyinfo= param->keyinfo;
44247 -+
44248 -+ if (group)
44249 -+ {
44250 -+ DBUG_PRINT("info",("Creating group key in temporary table"));
44251 -+ table->group=group; /* Table is grouped by key */
44252 -+ param->group_buff=group_buff;
44253 -+ share->keys=1;
44254 -+ share->uniques= test(using_unique_constraint);
44255 -+ table->key_info=keyinfo;
44256 -+ keyinfo->key_part=key_part_info;
44257 -+ keyinfo->flags=HA_NOSAME;
44258 -+ keyinfo->usable_key_parts=keyinfo->key_parts= param->group_parts;
44259 -+ keyinfo->key_length=0;
44260 -+ keyinfo->rec_per_key=0;
44261 -+ keyinfo->algorithm= HA_KEY_ALG_UNDEF;
44262 -+ keyinfo->name= (char*) "group_key";
44263 -+ ORDER *cur_group= group;
44264 -+ for (; cur_group ; cur_group= cur_group->next, key_part_info++)
44265 -+ {
44266 -+ Field *field=(*cur_group->item)->get_tmp_table_field();
44267 -+ DBUG_ASSERT(field->table == table);
44268 -+ bool maybe_null=(*cur_group->item)->maybe_null;
44269 -+ key_part_info->null_bit=0;
44270 -+ key_part_info->field= field;
44271 -+ key_part_info->offset= field->offset(table->record[0]);
44272 -+ key_part_info->length= (uint16) field->key_length();
44273 -+ key_part_info->type= (uint8) field->key_type();
44274 -+ key_part_info->key_type =
44275 -+ ((ha_base_keytype) key_part_info->type == HA_KEYTYPE_TEXT ||
44276 -+ (ha_base_keytype) key_part_info->type == HA_KEYTYPE_VARTEXT1 ||
44277 -+ (ha_base_keytype) key_part_info->type == HA_KEYTYPE_VARTEXT2) ?
44278 -+ 0 : FIELDFLAG_BINARY;
44279 -+ if (!using_unique_constraint)
44280 -+ {
44281 -+ cur_group->buff=(char*) group_buff;
44282 -+ if (!(cur_group->field= field->new_key_field(thd->mem_root,table,
44283 -+ group_buff +
44284 -+ test(maybe_null),
44285 -+ field->null_ptr,
44286 -+ field->null_bit)))
44287 -+ goto err; /* purecov: inspected */
44288 -+ if (maybe_null)
44289 -+ {
44290 -+ /*
44291 -+ To be able to group on NULL, we reserved place in group_buff
44292 -+ for the NULL flag just before the column. (see above).
44293 -+ The field data is after this flag.
44294 -+ The NULL flag is updated in 'end_update()' and 'end_write()'
44295 -+ */
44296 -+ keyinfo->flags|= HA_NULL_ARE_EQUAL; // def. that NULL == NULL
44297 -+ key_part_info->null_bit=field->null_bit;
44298 -+ key_part_info->null_offset= (uint) (field->null_ptr -
44299 -+ (uchar*) table->record[0]);
44300 -+ cur_group->buff++; // Pointer to field data
44301 -+ group_buff++; // Skipp null flag
44302 -+ }
44303 -+ /* In GROUP BY 'a' and 'a ' are equal for VARCHAR fields */
44304 -+ key_part_info->key_part_flag|= HA_END_SPACE_ARE_EQUAL;
44305 -+ group_buff+= cur_group->field->pack_length();
44306 -+ }
44307 -+ keyinfo->key_length+= key_part_info->length;
44308 -+ }
44309 -+ }
44310 -+
44311 -+ if (distinct && field_count != param->hidden_field_count)
44312 -+ {
44313 -+ /*
44314 -+ Create an unique key or an unique constraint over all columns
44315 -+ that should be in the result. In the temporary table, there are
44316 -+ 'param->hidden_field_count' extra columns, whose null bits are stored
44317 -+ in the first 'hidden_null_pack_length' bytes of the row.
44318 -+ */
44319 -+ DBUG_PRINT("info",("hidden_field_count: %d", param->hidden_field_count));
44320 -+
44321 -+ null_pack_length-=hidden_null_pack_length;
44322 -+ keyinfo->key_parts= ((field_count-param->hidden_field_count)+
44323 -+ test(null_pack_length));
44324 -+ table->distinct= 1;
44325 -+ share->keys= 1;
44326 -+ if (blob_count)
44327 -+ {
44328 -+ using_unique_constraint=1;
44329 -+ share->uniques= 1;
44330 -+ }
44331 -+ if (!(key_part_info= (KEY_PART_INFO*)
44332 -+ alloc_root(&table->mem_root,
44333 -+ keyinfo->key_parts * sizeof(KEY_PART_INFO))))
44334 -+ goto err;
44335 -+ bzero((void*) key_part_info, keyinfo->key_parts * sizeof(KEY_PART_INFO));
44336 -+ table->key_info=keyinfo;
44337 -+ keyinfo->key_part=key_part_info;
44338 -+ keyinfo->flags=HA_NOSAME | HA_NULL_ARE_EQUAL;
44339 -+ keyinfo->key_length=(uint16) reclength;
44340 -+ keyinfo->name= (char*) "distinct_key";
44341 -+ keyinfo->algorithm= HA_KEY_ALG_UNDEF;
44342 -+ keyinfo->rec_per_key=0;
44343 -+ if (null_pack_length)
44344 -+ {
44345 -+ key_part_info->null_bit=0;
44346 -+ key_part_info->offset=hidden_null_pack_length;
44347 -+ key_part_info->length=null_pack_length;
44348 -+ key_part_info->field= new Field_string(table->record[0],
44349 -+ (uint32) key_part_info->length,
44350 -+ (uchar*) 0,
44351 -+ (uint) 0,
44352 -+ Field::NONE,
44353 -+ NullS, &my_charset_bin);
44354 -+ if (!key_part_info->field)
44355 -+ goto err;
44356 -+ key_part_info->field->init(table);
44357 -+ key_part_info->key_type=FIELDFLAG_BINARY;
44358 -+ key_part_info->type= HA_KEYTYPE_BINARY;
44359 -+ key_part_info++;
44360 -+ }
44361 -+ /* Create a distinct key over the columns we are going to return */
44362 -+ for (i=param->hidden_field_count, reg_field=table->field + i ;
44363 -+ i < field_count;
44364 -+ i++, reg_field++, key_part_info++)
44365 -+ {
44366 -+ key_part_info->null_bit=0;
44367 -+ key_part_info->field= *reg_field;
44368 -+ key_part_info->offset= (*reg_field)->offset(table->record[0]);
44369 -+ key_part_info->length= (uint16) (*reg_field)->pack_length();
44370 -+ key_part_info->type= (uint8) (*reg_field)->key_type();
44371 -+ key_part_info->key_type =
44372 -+ ((ha_base_keytype) key_part_info->type == HA_KEYTYPE_TEXT ||
44373 -+ (ha_base_keytype) key_part_info->type == HA_KEYTYPE_VARTEXT1 ||
44374 -+ (ha_base_keytype) key_part_info->type == HA_KEYTYPE_VARTEXT2) ?
44375 -+ 0 : FIELDFLAG_BINARY;
44376 -+ }
44377 -+ }
44378 -+
44379 -+ if (thd->is_fatal_error) // If end of memory
44380 -+ goto err; /* purecov: inspected */
44381 -+ share->db_record_offset= 1;
44382 -+ if (share->db_type() == myisam_hton)
44383 -+ {
44384 -+ if (create_myisam_tmp_table(table,param,select_options))
44385 -+ goto err;
44386 -+ }
44387 -+ if (open_tmp_table(table))
44388 -+ goto err;
44389 -+
44390 -+ thd->mem_root= mem_root_save;
44391 -+
44392 -+ DBUG_RETURN(table);
44393 -+
44394 -+err:
44395 -+ thd->mem_root= mem_root_save;
44396 -+ free_tmp_table(thd,table); /* purecov: inspected */
44397 -+ if (temp_pool_slot != MY_BIT_NONE)
44398 -+ bitmap_lock_clear_bit(&temp_pool, temp_pool_slot);
44399 -+ DBUG_RETURN(NULL); /* purecov: inspected */
44400 -+}
44401 -+
44402 -+
44403 -+/****************************************************************************/
44404 -+
44405 -+/**
44406 -+ Create a reduced TABLE object with properly set up Field list from a
44407 -+ list of field definitions.
44408 -+
44409 -+ The created table doesn't have a table handler associated with
44410 -+ it, has no keys, no group/distinct, no copy_funcs array.
44411 -+ The sole purpose of this TABLE object is to use the power of Field
44412 -+ class to read/write data to/from table->record[0]. Then one can store
44413 -+ the record in any container (RB tree, hash, etc).
44414 -+ The table is created in THD mem_root, so are the table's fields.
44415 -+ Consequently, if you don't BLOB fields, you don't need to free it.
44416 -+
44417 -+ @param thd connection handle
44418 -+ @param field_list list of column definitions
44419 -+
44420 -+ @return
44421 -+ 0 if out of memory, TABLE object in case of success
44422 -+*/
44423 -+
44424 -+TABLE *create_virtual_tmp_table(THD *thd, List<Create_field> &field_list)
44425 -+{
44426 -+ uint field_count= field_list.elements;
44427 -+ uint blob_count= 0;
44428 -+ Field **field;
44429 -+ Create_field *cdef; /* column definition */
44430 -+ uint record_length= 0;
44431 -+ uint null_count= 0; /* number of columns which may be null */
44432 -+ uint null_pack_length; /* NULL representation array length */
44433 -+ uint *blob_field;
44434 -+ uchar *bitmaps;
44435 -+ TABLE *table;
44436 -+ TABLE_SHARE *share;
44437 -+
44438 -+ if (!multi_alloc_root(thd->mem_root,
44439 -+ &table, sizeof(*table),
44440 -+ &share, sizeof(*share),
44441 -+ &field, (field_count + 1) * sizeof(Field*),
44442 -+ &blob_field, (field_count+1) *sizeof(uint),
44443 -+ &bitmaps, bitmap_buffer_size(field_count)*2,
44444 -+ NullS))
44445 -+ return 0;
44446 -+
44447 -+ bzero(table, sizeof(*table));
44448 -+ bzero(share, sizeof(*share));
44449 -+ table->field= field;
44450 -+ table->s= share;
44451 -+ share->blob_field= blob_field;
44452 -+ share->fields= field_count;
44453 -+ share->blob_ptr_size= portable_sizeof_char_ptr;
44454 -+ setup_tmp_table_column_bitmaps(table, bitmaps);
44455 -+
44456 -+ /* Create all fields and calculate the total length of record */
44457 -+ List_iterator_fast<Create_field> it(field_list);
44458 -+ while ((cdef= it++))
44459 -+ {
44460 -+ *field= make_field(share, 0, cdef->length,
44461 -+ (uchar*) (f_maybe_null(cdef->pack_flag) ? "" : 0),
44462 -+ f_maybe_null(cdef->pack_flag) ? 1 : 0,
44463 -+ cdef->pack_flag, cdef->sql_type, cdef->charset,
44464 -+ cdef->geom_type, cdef->unireg_check,
44465 -+ cdef->interval, cdef->field_name);
44466 -+ if (!*field)
44467 -+ goto error;
44468 -+ (*field)->init(table);
44469 -+ record_length+= (*field)->pack_length();
44470 -+ if (! ((*field)->flags & NOT_NULL_FLAG))
44471 -+ null_count++;
44472 -+
44473 -+ if ((*field)->flags & BLOB_FLAG)
44474 -+ share->blob_field[blob_count++]= (uint) (field - table->field);
44475 -+
44476 -+ field++;
44477 -+ }
44478 -+ *field= NULL; /* mark the end of the list */
44479 -+ share->blob_field[blob_count]= 0; /* mark the end of the list */
44480 -+ share->blob_fields= blob_count;
44481 -+
44482 -+ null_pack_length= (null_count + 7)/8;
44483 -+ share->reclength= record_length + null_pack_length;
44484 -+ share->rec_buff_length= ALIGN_SIZE(share->reclength + 1);
44485 -+ table->record[0]= (uchar*) thd->alloc(share->rec_buff_length);
44486 -+ if (!table->record[0])
44487 -+ goto error;
44488 -+
44489 -+ if (null_pack_length)
44490 -+ {
44491 -+ table->null_flags= (uchar*) table->record[0];
44492 -+ share->null_fields= null_count;
44493 -+ share->null_bytes= null_pack_length;
44494 -+ }
44495 -+
44496 -+ table->in_use= thd; /* field->reset() may access table->in_use */
44497 -+ {
44498 -+ /* Set up field pointers */
44499 -+ uchar *null_pos= table->record[0];
44500 -+ uchar *field_pos= null_pos + share->null_bytes;
44501 -+ uint null_bit= 1;
44502 -+
44503 -+ for (field= table->field; *field; ++field)
44504 -+ {
44505 -+ Field *cur_field= *field;
44506 -+ if ((cur_field->flags & NOT_NULL_FLAG))
44507 -+ cur_field->move_field(field_pos);
44508 -+ else
44509 -+ {
44510 -+ cur_field->move_field(field_pos, (uchar*) null_pos, null_bit);
44511 -+ null_bit<<= 1;
44512 -+ if (null_bit == (1 << 8))
44513 -+ {
44514 -+ ++null_pos;
44515 -+ null_bit= 1;
44516 -+ }
44517 -+ }
44518 -+ cur_field->reset();
44519 -+
44520 -+ field_pos+= cur_field->pack_length();
44521 -+ }
44522 -+ }
44523 -+ return table;
44524 -+error:
44525 -+ for (field= table->field; *field; ++field)
44526 -+ delete *field; /* just invokes field destructor */
44527 -+ return 0;
44528 -+}
44529 -+
44530 -+
44531 -+static bool open_tmp_table(TABLE *table)
44532 -+{
44533 -+ int error;
44534 -+ if ((error=table->file->ha_open(table, table->s->table_name.str,O_RDWR,
44535 -+ HA_OPEN_TMP_TABLE | HA_OPEN_INTERNAL_TABLE)))
44536 -+ {
44537 -+ table->file->print_error(error,MYF(0)); /* purecov: inspected */
44538 -+ table->db_stat=0;
44539 -+ return(1);
44540 -+ }
44541 -+ (void) table->file->extra(HA_EXTRA_QUICK); /* Faster */
44542 -+ return(0);
44543 -+}
44544 -+
44545 -+
44546 -+static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param,
44547 -+ ulonglong options)
44548 -+{
44549 -+ int error;
44550 -+ MI_KEYDEF keydef;
44551 -+ MI_UNIQUEDEF uniquedef;
44552 -+ KEY *keyinfo=param->keyinfo;
44553 -+ TABLE_SHARE *share= table->s;
44554 -+ DBUG_ENTER("create_myisam_tmp_table");
44555 -+
44556 -+ if (share->keys)
44557 -+ { // Get keys for ni_create
44558 -+ bool using_unique_constraint=0;
44559 -+ HA_KEYSEG *seg= (HA_KEYSEG*) alloc_root(&table->mem_root,
44560 -+ sizeof(*seg) * keyinfo->key_parts);
44561 -+ if (!seg)
44562 -+ goto err;
44563 -+
44564 -+ bzero(seg, sizeof(*seg) * keyinfo->key_parts);
44565 -+ if (keyinfo->key_length >= table->file->max_key_length() ||
44566 -+ keyinfo->key_parts > table->file->max_key_parts() ||
44567 -+ share->uniques)
44568 -+ {
44569 -+ /* Can't create a key; Make a unique constraint instead of a key */
44570 -+ share->keys= 0;
44571 -+ share->uniques= 1;
44572 -+ using_unique_constraint=1;
44573 -+ bzero((char*) &uniquedef,sizeof(uniquedef));
44574 -+ uniquedef.keysegs=keyinfo->key_parts;
44575 -+ uniquedef.seg=seg;
44576 -+ uniquedef.null_are_equal=1;
44577 -+
44578 -+ /* Create extra column for hash value */
44579 -+ bzero((uchar*) param->recinfo,sizeof(*param->recinfo));
44580 -+ param->recinfo->type= FIELD_CHECK;
44581 -+ param->recinfo->length=MI_UNIQUE_HASH_LENGTH;
44582 -+ param->recinfo++;
44583 -+ share->reclength+=MI_UNIQUE_HASH_LENGTH;
44584 -+ }
44585 -+ else
44586 -+ {
44587 -+ /* Create an unique key */
44588 -+ bzero((char*) &keydef,sizeof(keydef));
44589 -+ keydef.flag=HA_NOSAME | HA_BINARY_PACK_KEY | HA_PACK_KEY;
44590 -+ keydef.keysegs= keyinfo->key_parts;
44591 -+ keydef.seg= seg;
44592 -+ }
44593 -+ for (uint i=0; i < keyinfo->key_parts ; i++,seg++)
44594 -+ {
44595 -+ Field *field=keyinfo->key_part[i].field;
44596 -+ seg->flag= 0;
44597 -+ seg->language= field->charset()->number;
44598 -+ seg->length= keyinfo->key_part[i].length;
44599 -+ seg->start= keyinfo->key_part[i].offset;
44600 -+ if (field->flags & BLOB_FLAG)
44601 -+ {
44602 -+ seg->type=
44603 -+ ((keyinfo->key_part[i].key_type & FIELDFLAG_BINARY) ?
44604 -+ HA_KEYTYPE_VARBINARY2 : HA_KEYTYPE_VARTEXT2);
44605 -+ seg->bit_start= (uint8)(field->pack_length() - share->blob_ptr_size);
44606 -+ seg->flag= HA_BLOB_PART;
44607 -+ seg->length=0; // Whole blob in unique constraint
44608 -+ }
44609 -+ else
44610 -+ {
44611 -+ seg->type= keyinfo->key_part[i].type;
44612 -+ /* Tell handler if it can do suffic space compression */
44613 -+ if (field->real_type() == MYSQL_TYPE_STRING &&
44614 -+ keyinfo->key_part[i].length > 4)
44615 -+ seg->flag|= HA_SPACE_PACK;
44616 -+ }
44617 -+ if (!(field->flags & NOT_NULL_FLAG))
44618 -+ {
44619 -+ seg->null_bit= field->null_bit;
44620 -+ seg->null_pos= (uint) (field->null_ptr - (uchar*) table->record[0]);
44621 -+ /*
44622 -+ We are using a GROUP BY on something that contains NULL
44623 -+ In this case we have to tell MyISAM that two NULL should
44624 -+ on INSERT be regarded at the same value
44625 -+ */
44626 -+ if (!using_unique_constraint)
44627 -+ keydef.flag|= HA_NULL_ARE_EQUAL;
44628 -+ }
44629 -+ }
44630 -+ }
44631 -+ MI_CREATE_INFO create_info;
44632 -+ bzero((char*) &create_info,sizeof(create_info));
44633 -+
44634 -+ if ((options & (OPTION_BIG_TABLES | SELECT_SMALL_RESULT)) ==
44635 -+ OPTION_BIG_TABLES)
44636 -+ create_info.data_file_length= ~(ulonglong) 0;
44637 -+
44638 -+ if ((error=mi_create(share->table_name.str, share->keys, &keydef,
44639 -+ (uint) (param->recinfo-param->start_recinfo),
44640 -+ param->start_recinfo,
44641 -+ share->uniques, &uniquedef,
44642 -+ &create_info,
44643 -+ HA_CREATE_TMP_TABLE)))
44644 -+ {
44645 -+ table->file->print_error(error,MYF(0)); /* purecov: inspected */
44646 -+ table->db_stat=0;
44647 -+ goto err;
44648 -+ }
44649 -+ status_var_increment(table->in_use->status_var.created_tmp_disk_tables);
44650 -+ share->db_record_offset= 1;
44651 -+ DBUG_RETURN(0);
44652 -+ err:
44653 -+ DBUG_RETURN(1);
44654 -+}
44655 -+
44656 -+
44657 -+void
44658 -+free_tmp_table(THD *thd, TABLE *entry)
44659 -+{
44660 -+ MEM_ROOT own_root= entry->mem_root;
44661 -+ const char *save_proc_info;
44662 -+ DBUG_ENTER("free_tmp_table");
44663 -+ DBUG_PRINT("enter",("table: %s",entry->alias));
44664 -+
44665 -+ save_proc_info=thd->proc_info;
44666 -+ thd_proc_info(thd, "removing tmp table");
44667 -+
44668 -+ // Release latches since this can take a long time
44669 -+ ha_release_temporary_latches(thd);
44670 -+
44671 -+ if (entry->file)
44672 -+ {
44673 -+ if (entry->db_stat)
44674 -+ entry->file->ha_drop_table(entry->s->table_name.str);
44675 -+ else
44676 -+ entry->file->ha_delete_table(entry->s->table_name.str);
44677 -+ delete entry->file;
44678 -+ }
44679 -+
44680 -+ /* free blobs */
44681 -+ for (Field **ptr=entry->field ; *ptr ; ptr++)
44682 -+ (*ptr)->free();
44683 -+ free_io_cache(entry);
44684 -+
44685 -+ if (entry->temp_pool_slot != MY_BIT_NONE)
44686 -+ bitmap_lock_clear_bit(&temp_pool, entry->temp_pool_slot);
44687 -+
44688 -+ plugin_unlock(0, entry->s->db_plugin);
44689 -+
44690 -+ free_root(&own_root, MYF(0)); /* the table is allocated in its own root */
44691 -+ thd_proc_info(thd, save_proc_info);
44692 -+
44693 -+ DBUG_VOID_RETURN;
44694 -+}
44695 -+
44696 -+/**
44697 -+ If a HEAP table gets full, create a MyISAM table and copy all rows
44698 -+ to this.
44699 -+*/
44700 -+
44701 -+bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param,
44702 -+ int error, bool ignore_last_dupp_key_error)
44703 -+{
44704 -+ TABLE new_table;
44705 -+ TABLE_SHARE share;
44706 -+ const char *save_proc_info;
44707 -+ int write_err;
44708 -+ DBUG_ENTER("create_myisam_from_heap");
44709 -+
44710 -+ if (table->s->db_type() != heap_hton ||
44711 -+ error != HA_ERR_RECORD_FILE_FULL)
44712 -+ {
44713 -+ /*
44714 -+ We don't want this error to be converted to a warning, e.g. in case of
44715 -+ INSERT IGNORE ... SELECT.
44716 -+ */
44717 -+ thd->fatal_error();
44718 -+ table->file->print_error(error,MYF(0));
44719 -+ DBUG_RETURN(1);
44720 -+ }
44721 -+
44722 -+ // Release latches since this can take a long time
44723 -+ ha_release_temporary_latches(thd);
44724 -+
44725 -+ new_table= *table;
44726 -+ share= *table->s;
44727 -+ new_table.s= &share;
44728 -+ new_table.s->db_plugin= ha_lock_engine(thd, myisam_hton);
44729 -+ if (!(new_table.file= get_new_handler(&share, &new_table.mem_root,
44730 -+ new_table.s->db_type())))
44731 -+ DBUG_RETURN(1); // End of memory
44732 -+
44733 -+ save_proc_info=thd->proc_info;
44734 -+ thd_proc_info(thd, "converting HEAP to MyISAM");
44735 -+
44736 -+ if (create_myisam_tmp_table(&new_table, param,
44737 -+ thd->lex->select_lex.options | thd->options))
44738 -+ goto err2;
44739 -+ if (open_tmp_table(&new_table))
44740 -+ goto err1;
44741 -+ if (table->file->indexes_are_disabled())
44742 -+ new_table.file->ha_disable_indexes(HA_KEY_SWITCH_ALL);
44743 -+ table->file->ha_index_or_rnd_end();
44744 -+ table->file->ha_rnd_init(1);
44745 -+ if (table->no_rows)
44746 -+ {
44747 -+ new_table.file->extra(HA_EXTRA_NO_ROWS);
44748 -+ new_table.no_rows=1;
44749 -+ }
44750 -+
44751 -+#ifdef TO_BE_DONE_LATER_IN_4_1
44752 -+ /*
44753 -+ To use start_bulk_insert() (which is new in 4.1) we need to find
44754 -+ all places where a corresponding end_bulk_insert() should be put.
44755 -+ */
44756 -+ table->file->info(HA_STATUS_VARIABLE); /* update table->file->stats.records */
44757 -+ new_table.file->ha_start_bulk_insert(table->file->stats.records);
44758 -+#else
44759 -+ /* HA_EXTRA_WRITE_CACHE can stay until close, no need to disable it */
44760 -+ new_table.file->extra(HA_EXTRA_WRITE_CACHE);
44761 -+#endif
44762 -+
44763 -+ /*
44764 -+ copy all old rows from heap table to MyISAM table
44765 -+ This is the only code that uses record[1] to read/write but this
44766 -+ is safe as this is a temporary MyISAM table without timestamp/autoincrement
44767 -+ or partitioning.
44768 -+ */
44769 -+ while (!table->file->rnd_next(new_table.record[1]))
44770 -+ {
44771 -+ write_err= new_table.file->ha_write_row(new_table.record[1]);
44772 -+ DBUG_EXECUTE_IF("raise_error", write_err= HA_ERR_FOUND_DUPP_KEY ;);
44773 -+ if (write_err)
44774 -+ goto err;
44775 -+ }
44776 -+ /* copy row that filled HEAP table */
44777 -+ if ((write_err=new_table.file->ha_write_row(table->record[0])))
44778 -+ {
44779 -+ if (new_table.file->is_fatal_error(write_err, HA_CHECK_DUP) ||
44780 -+ !ignore_last_dupp_key_error)
44781 -+ goto err;
44782 -+ }
44783 -+
44784 -+ /* remove heap table and change to use myisam table */
44785 -+ (void) table->file->ha_rnd_end();
44786 -+ (void) table->file->close(); // This deletes the table !
44787 -+ delete table->file;
44788 -+ table->file=0;
44789 -+ plugin_unlock(0, table->s->db_plugin);
44790 -+ share.db_plugin= my_plugin_lock(0, &share.db_plugin);
44791 -+ new_table.s= table->s; // Keep old share
44792 -+ *table= new_table;
44793 -+ *table->s= share;
44794 -+
44795 -+ table->file->change_table_ptr(table, table->s);
44796 -+ table->use_all_columns();
44797 -+ if (save_proc_info)
44798 -+ thd_proc_info(thd, (!strcmp(save_proc_info,"Copying to tmp table") ?
44799 -+ "Copying to tmp table on disk" : save_proc_info));
44800 -+ DBUG_RETURN(0);
44801 -+
44802 -+ err:
44803 -+ DBUG_PRINT("error",("Got error: %d",write_err));
44804 -+ table->file->print_error(write_err, MYF(0));
44805 -+ (void) table->file->ha_rnd_end();
44806 -+ (void) new_table.file->close();
44807 -+ err1:
44808 -+ new_table.file->ha_delete_table(new_table.s->table_name.str);
44809 -+ err2:
44810 -+ delete new_table.file;
44811 -+ thd_proc_info(thd, save_proc_info);
44812 -+ table->mem_root= new_table.mem_root;
44813 -+ DBUG_RETURN(1);
44814 -+}
44815 -+
44816 -+
44817 -+/**
44818 -+ @details
44819 -+ Rows produced by a join sweep may end up in a temporary table or be sent
44820 -+ to a client. Setup the function of the nested loop join algorithm which
44821 -+ handles final fully constructed and matched records.
44822 -+
44823 -+ @param join join to setup the function for.
44824 -+
44825 -+ @return
44826 -+ end_select function to use. This function can't fail.
44827 -+*/
44828 -+
44829 -+Next_select_func setup_end_select_func(JOIN *join)
44830 -+{
44831 -+ TABLE *table= join->tmp_table;
44832 -+ TMP_TABLE_PARAM *tmp_tbl= &join->tmp_table_param;
44833 -+ Next_select_func end_select;
44834 -+
44835 -+ /* Set up select_end */
44836 -+ if (table)
44837 -+ {
44838 -+ if (table->group && tmp_tbl->sum_func_count &&
44839 -+ !tmp_tbl->precomputed_group_by)
44840 -+ {
44841 -+ if (table->s->keys)
44842 -+ {
44843 -+ DBUG_PRINT("info",("Using end_update"));
44844 -+ end_select=end_update;
44845 -+ }
44846 -+ else
44847 -+ {
44848 -+ DBUG_PRINT("info",("Using end_unique_update"));
44849 -+ end_select=end_unique_update;
44850 -+ }
44851 -+ }
44852 -+ else if (join->sort_and_group && !tmp_tbl->precomputed_group_by)
44853 -+ {
44854 -+ DBUG_PRINT("info",("Using end_write_group"));
44855 -+ end_select=end_write_group;
44856 -+ }
44857 -+ else
44858 -+ {
44859 -+ DBUG_PRINT("info",("Using end_write"));
44860 -+ end_select=end_write;
44861 -+ if (tmp_tbl->precomputed_group_by)
44862 -+ {
44863 -+ /*
44864 -+ A preceding call to create_tmp_table in the case when loose
44865 -+ index scan is used guarantees that
44866 -+ TMP_TABLE_PARAM::items_to_copy has enough space for the group
44867 -+ by functions. It is OK here to use memcpy since we copy
44868 -+ Item_sum pointers into an array of Item pointers.
44869 -+ */
44870 -+ memcpy(tmp_tbl->items_to_copy + tmp_tbl->func_count,
44871 -+ join->sum_funcs,
44872 -+ sizeof(Item*)*tmp_tbl->sum_func_count);
44873 -+ tmp_tbl->items_to_copy[tmp_tbl->func_count+tmp_tbl->sum_func_count]= 0;
44874 -+ }
44875 -+ }
44876 -+ }
44877 -+ else
44878 -+ {
44879 -+ /*
44880 -+ Choose method for presenting result to user. Use end_send_group
44881 -+ if the query requires grouping (has a GROUP BY clause and/or one or
44882 -+ more aggregate functions). Use end_send if the query should not
44883 -+ be grouped.
44884 -+ */
44885 -+ if ((join->sort_and_group ||
44886 -+ (join->procedure && join->procedure->flags & PROC_GROUP)) &&
44887 -+ !tmp_tbl->precomputed_group_by)
44888 -+ end_select= end_send_group;
44889 -+ else
44890 -+ end_select= end_send;
44891 -+ }
44892 -+ return end_select;
44893 -+}
44894 -+
44895 -+
44896 -+/**
44897 -+ Make a join of all tables and write it on socket or to table.
44898 -+
44899 -+ @retval
44900 -+ 0 if ok
44901 -+ @retval
44902 -+ 1 if error is sent
44903 -+ @retval
44904 -+ -1 if error should be sent
44905 -+*/
44906 -+
44907 -+static int
44908 -+do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
44909 -+{
44910 -+ int rc= 0;
44911 -+ enum_nested_loop_state error= NESTED_LOOP_OK;
44912 -+ JOIN_TAB *join_tab= NULL;
44913 -+ DBUG_ENTER("do_select");
44914 -+
44915 -+ join->procedure=procedure;
44916 -+ join->tmp_table= table; /* Save for easy recursion */
44917 -+ join->fields= fields;
44918 -+
44919 -+ if (table)
44920 -+ {
44921 -+ VOID(table->file->extra(HA_EXTRA_WRITE_CACHE));
44922 -+ empty_record(table);
44923 -+ if (table->group && join->tmp_table_param.sum_func_count &&
44924 -+ table->s->keys && !table->file->inited)
44925 -+ table->file->ha_index_init(0, 0);
44926 -+ }
44927 -+ /* Set up select_end */
44928 -+ Next_select_func end_select= setup_end_select_func(join);
44929 -+ if (join->tables)
44930 -+ {
44931 -+ join->join_tab[join->tables-1].next_select= end_select;
44932 -+
44933 -+ join_tab=join->join_tab+join->const_tables;
44934 -+ }
44935 -+ join->send_records=0;
44936 -+ if (join->tables == join->const_tables)
44937 -+ {
44938 -+ /*
44939 -+ HAVING will be checked after processing aggregate functions,
44940 -+ But WHERE should checkd here (we alredy have read tables)
44941 -+ */
44942 -+ if (!join->conds || join->conds->val_int())
44943 -+ {
44944 -+ error= (*end_select)(join, 0, 0);
44945 -+ if (error == NESTED_LOOP_OK || error == NESTED_LOOP_QUERY_LIMIT)
44946 -+ error= (*end_select)(join, 0, 1);
44947 -+
44948 -+ /*
44949 -+ If we don't go through evaluate_join_record(), do the counting
44950 -+ here. join->send_records is increased on success in end_send(),
44951 -+ so we don't touch it here.
44952 -+ */
44953 -+ join->examined_rows++;
44954 -+ join->thd->row_count++;
44955 -+ DBUG_ASSERT(join->examined_rows <= 1);
44956 -+ }
44957 -+ else if (join->send_row_on_empty_set())
44958 -+ {
44959 -+ List<Item> *columns_list= (procedure ? &join->procedure_fields_list :
44960 -+ fields);
44961 -+ rc= join->result->send_data(*columns_list);
44962 -+ }
44963 -+ }
44964 -+ else
44965 -+ {
44966 -+ DBUG_ASSERT(join->tables);
44967 -+ error= sub_select(join,join_tab,0);
44968 -+ if (error == NESTED_LOOP_OK || error == NESTED_LOOP_NO_MORE_ROWS)
44969 -+ error= sub_select(join,join_tab,1);
44970 -+ if (error == NESTED_LOOP_QUERY_LIMIT)
44971 -+ error= NESTED_LOOP_OK; /* select_limit used */
44972 -+ }
44973 -+ if (error == NESTED_LOOP_NO_MORE_ROWS)
44974 -+ error= NESTED_LOOP_OK;
44975 -+
44976 -+ if (table == NULL) // If sending data to client
44977 -+ /*
44978 -+ The following will unlock all cursors if the command wasn't an
44979 -+ update command
44980 -+ */
44981 -+ join->join_free(); // Unlock all cursors
44982 -+ if (error == NESTED_LOOP_OK)
44983 -+ {
44984 -+ /*
44985 -+ Sic: this branch works even if rc != 0, e.g. when
44986 -+ send_data above returns an error.
44987 -+ */
44988 -+ if (table == NULL && join->result->send_eof()) // If sending data to client
44989 -+ rc= 1; // Don't send error
44990 -+ DBUG_PRINT("info",("%ld records output", (long) join->send_records));
44991 -+ }
44992 -+ else
44993 -+ rc= -1;
44994 -+ if (table)
44995 -+ {
44996 -+ int tmp, new_errno= 0;
44997 -+ if ((tmp=table->file->extra(HA_EXTRA_NO_CACHE)))
44998 -+ {
44999 -+ DBUG_PRINT("error",("extra(HA_EXTRA_NO_CACHE) failed"));
45000 -+ new_errno= tmp;
45001 -+ }
45002 -+ if ((tmp=table->file->ha_index_or_rnd_end()))
45003 -+ {
45004 -+ DBUG_PRINT("error",("ha_index_or_rnd_end() failed"));
45005 -+ new_errno= tmp;
45006 -+ }
45007 -+ if (new_errno)
45008 -+ table->file->print_error(new_errno,MYF(0));
45009 -+ }
45010 -+#ifndef DBUG_OFF
45011 -+ if (rc)
45012 -+ {
45013 -+ DBUG_PRINT("error",("Error: do_select() failed"));
45014 -+ }
45015 -+#endif
45016 -+ DBUG_RETURN(join->thd->is_error() ? -1 : rc);
45017 -+}
45018 -+
45019 -+
45020 -+enum_nested_loop_state
45021 -+sub_select_cache(JOIN *join,JOIN_TAB *join_tab,bool end_of_records)
45022 -+{
45023 -+ enum_nested_loop_state rc;
45024 -+
45025 -+ if (end_of_records)
45026 -+ {
45027 -+ rc= flush_cached_records(join,join_tab,FALSE);
45028 -+ if (rc == NESTED_LOOP_OK || rc == NESTED_LOOP_NO_MORE_ROWS)
45029 -+ rc= sub_select(join,join_tab,end_of_records);
45030 -+ return rc;
45031 -+ }
45032 -+ if (join->thd->killed) // If aborted by user
45033 -+ {
45034 -+ join->thd->send_kill_message();
45035 -+ return NESTED_LOOP_KILLED; /* purecov: inspected */
45036 -+ }
45037 -+ if (join_tab->use_quick != 2 || test_if_quick_select(join_tab) <= 0)
45038 -+ {
45039 -+ if (!store_record_in_cache(&join_tab->cache))
45040 -+ return NESTED_LOOP_OK; // There is more room in cache
45041 -+ return flush_cached_records(join,join_tab,FALSE);
45042 -+ }
45043 -+ rc= flush_cached_records(join, join_tab, TRUE);
45044 -+ if (rc == NESTED_LOOP_OK || rc == NESTED_LOOP_NO_MORE_ROWS)
45045 -+ rc= sub_select(join, join_tab, end_of_records);
45046 -+ return rc;
45047 -+}
45048 -+
45049 -+/**
45050 -+ Retrieve records ends with a given beginning from the result of a join.
45051 -+
45052 -+ For a given partial join record consisting of records from the tables
45053 -+ preceding the table join_tab in the execution plan, the function
45054 -+ retrieves all matching full records from the result set and
45055 -+ send them to the result set stream.
45056 -+
45057 -+ @note
45058 -+ The function effectively implements the final (n-k) nested loops
45059 -+ of nested loops join algorithm, where k is the ordinal number of
45060 -+ the join_tab table and n is the total number of tables in the join query.
45061 -+ It performs nested loops joins with all conjunctive predicates from
45062 -+ the where condition pushed as low to the tables as possible.
45063 -+ E.g. for the query
45064 -+ @code
45065 -+ SELECT * FROM t1,t2,t3
45066 -+ WHERE t1.a=t2.a AND t2.b=t3.b AND t1.a BETWEEN 5 AND 9
45067 -+ @endcode
45068 -+ the predicate (t1.a BETWEEN 5 AND 9) will be pushed to table t1,
45069 -+ given the selected plan prescribes to nest retrievals of the
45070 -+ joined tables in the following order: t1,t2,t3.
45071 -+ A pushed down predicate are attached to the table which it pushed to,
45072 -+ at the field join_tab->select_cond.
45073 -+ When executing a nested loop of level k the function runs through
45074 -+ the rows of 'join_tab' and for each row checks the pushed condition
45075 -+ attached to the table.
45076 -+ If it is false the function moves to the next row of the
45077 -+ table. If the condition is true the function recursively executes (n-k-1)
45078 -+ remaining embedded nested loops.
45079 -+ The situation becomes more complicated if outer joins are involved in
45080 -+ the execution plan. In this case the pushed down predicates can be
45081 -+ checked only at certain conditions.
45082 -+ Suppose for the query
45083 -+ @code
45084 -+ SELECT * FROM t1 LEFT JOIN (t2,t3) ON t3.a=t1.a
45085 -+ WHERE t1>2 AND (t2.b>5 OR t2.b IS NULL)
45086 -+ @endcode
45087 -+ the optimizer has chosen a plan with the table order t1,t2,t3.
45088 -+ The predicate P1=t1>2 will be pushed down to the table t1, while the
45089 -+ predicate P2=(t2.b>5 OR t2.b IS NULL) will be attached to the table
45090 -+ t2. But the second predicate can not be unconditionally tested right
45091 -+ after a row from t2 has been read. This can be done only after the
45092 -+ first row with t3.a=t1.a has been encountered.
45093 -+ Thus, the second predicate P2 is supplied with a guarded value that are
45094 -+ stored in the field 'found' of the first inner table for the outer join
45095 -+ (table t2). When the first row with t3.a=t1.a for the current row
45096 -+ of table t1 appears, the value becomes true. For now on the predicate
45097 -+ is evaluated immediately after the row of table t2 has been read.
45098 -+ When the first row with t3.a=t1.a has been encountered all
45099 -+ conditions attached to the inner tables t2,t3 must be evaluated.
45100 -+ Only when all of them are true the row is sent to the output stream.
45101 -+ If not, the function returns to the lowest nest level that has a false
45102 -+ attached condition.
45103 -+ The predicates from on expressions are also pushed down. If in the
45104 -+ the above example the on expression were (t3.a=t1.a AND t2.a=t1.a),
45105 -+ then t1.a=t2.a would be pushed down to table t2, and without any
45106 -+ guard.
45107 -+ If after the run through all rows of table t2, the first inner table
45108 -+ for the outer join operation, it turns out that no matches are
45109 -+ found for the current row of t1, then current row from table t1
45110 -+ is complemented by nulls for t2 and t3. Then the pushed down predicates
45111 -+ are checked for the composed row almost in the same way as it had
45112 -+ been done for the first row with a match. The only difference is
45113 -+ the predicates from on expressions are not checked.
45114 -+
45115 -+ @par
45116 -+ @b IMPLEMENTATION
45117 -+ @par
45118 -+ The function forms output rows for a current partial join of k
45119 -+ tables tables recursively.
45120 -+ For each partial join record ending with a certain row from
45121 -+ join_tab it calls sub_select that builds all possible matching
45122 -+ tails from the result set.
45123 -+ To be able check predicates conditionally items of the class
45124 -+ Item_func_trig_cond are employed.
45125 -+ An object of this class is constructed from an item of class COND
45126 -+ and a pointer to a guarding boolean variable.
45127 -+ When the value of the guard variable is true the value of the object
45128 -+ is the same as the value of the predicate, otherwise it's just returns
45129 -+ true.
45130 -+ To carry out a return to a nested loop level of join table t the pointer
45131 -+ to t is remembered in the field 'return_tab' of the join structure.
45132 -+ Consider the following query:
45133 -+ @code
45134 -+ SELECT * FROM t1,
45135 -+ LEFT JOIN
45136 -+ (t2, t3 LEFT JOIN (t4,t5) ON t5.a=t3.a)
45137 -+ ON t4.a=t2.a
45138 -+ WHERE (t2.b=5 OR t2.b IS NULL) AND (t4.b=2 OR t4.b IS NULL)
45139 -+ @endcode
45140 -+ Suppose the chosen execution plan dictates the order t1,t2,t3,t4,t5
45141 -+ and suppose for a given joined rows from tables t1,t2,t3 there are
45142 -+ no rows in the result set yet.
45143 -+ When first row from t5 that satisfies the on condition
45144 -+ t5.a=t3.a is found, the pushed down predicate t4.b=2 OR t4.b IS NULL
45145 -+ becomes 'activated', as well the predicate t4.a=t2.a. But
45146 -+ the predicate (t2.b=5 OR t2.b IS NULL) can not be checked until
45147 -+ t4.a=t2.a becomes true.
45148 -+ In order not to re-evaluate the predicates that were already evaluated
45149 -+ as attached pushed down predicates, a pointer to the the first
45150 -+ most inner unmatched table is maintained in join_tab->first_unmatched.
45151 -+ Thus, when the first row from t5 with t5.a=t3.a is found
45152 -+ this pointer for t5 is changed from t4 to t2.
45153 -+
45154 -+ @par
45155 -+ @b STRUCTURE @b NOTES
45156 -+ @par
45157 -+ join_tab->first_unmatched points always backwards to the first inner
45158 -+ table of the embedding nested join, if any.
45159 -+
45160 -+ @param join pointer to the structure providing all context info for
45161 -+ the query
45162 -+ @param join_tab the first next table of the execution plan to be retrieved
45163 -+ @param end_records true when we need to perform final steps of retrival
45164 -+
45165 -+ @return
45166 -+ return one of enum_nested_loop_state, except NESTED_LOOP_NO_MORE_ROWS.
45167 -+*/
45168 -+
45169 -+enum_nested_loop_state
45170 -+sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records)
45171 -+{
45172 -+ join_tab->table->null_row=0;
45173 -+ if (end_of_records)
45174 -+ return (*join_tab->next_select)(join,join_tab+1,end_of_records);
45175 -+
45176 -+ int error;
45177 -+ enum_nested_loop_state rc;
45178 -+ READ_RECORD *info= &join_tab->read_record;
45179 -+
45180 -+ if (join->resume_nested_loop)
45181 -+ {
45182 -+ /* If not the last table, plunge down the nested loop */
45183 -+ if (join_tab < join->join_tab + join->tables - 1)
45184 -+ rc= (*join_tab->next_select)(join, join_tab + 1, 0);
45185 -+ else
45186 -+ {
45187 -+ join->resume_nested_loop= FALSE;
45188 -+ rc= NESTED_LOOP_OK;
45189 -+ }
45190 -+ }
45191 -+ else
45192 -+ {
45193 -+ join->return_tab= join_tab;
45194 -+
45195 -+ if (join_tab->last_inner)
45196 -+ {
45197 -+ /* join_tab is the first inner table for an outer join operation. */
45198 -+
45199 -+ /* Set initial state of guard variables for this table.*/
45200 -+ join_tab->found=0;
45201 -+ join_tab->not_null_compl= 1;
45202 -+
45203 -+ /* Set first_unmatched for the last inner table of this group */
45204 -+ join_tab->last_inner->first_unmatched= join_tab;
45205 -+ }
45206 -+ join->thd->row_count= 0;
45207 -+
45208 -+ error= (*join_tab->read_first_record)(join_tab);
45209 -+ rc= evaluate_join_record(join, join_tab, error);
45210 -+ }
45211 -+
45212 -+ while (rc == NESTED_LOOP_OK)
45213 -+ {
45214 -+ error= info->read_record(info);
45215 -+ rc= evaluate_join_record(join, join_tab, error);
45216 -+ }
45217 -+
45218 -+ if (rc == NESTED_LOOP_NO_MORE_ROWS &&
45219 -+ join_tab->last_inner && !join_tab->found)
45220 -+ rc= evaluate_null_complemented_join_record(join, join_tab);
45221 -+
45222 -+ if (rc == NESTED_LOOP_NO_MORE_ROWS)
45223 -+ rc= NESTED_LOOP_OK;
45224 -+ return rc;
45225 -+}
45226 -+
45227 -+
45228 -+/**
45229 -+ Process one record of the nested loop join.
45230 -+
45231 -+ This function will evaluate parts of WHERE/ON clauses that are
45232 -+ applicable to the partial record on hand and in case of success
45233 -+ submit this record to the next level of the nested loop.
45234 -+*/
45235 -+
45236 -+static enum_nested_loop_state
45237 -+evaluate_join_record(JOIN *join, JOIN_TAB *join_tab,
45238 -+ int error)
45239 -+{
45240 -+ bool not_used_in_distinct=join_tab->not_used_in_distinct;
45241 -+ ha_rows found_records=join->found_records;
45242 -+ COND *select_cond= join_tab->select_cond;
45243 -+ bool select_cond_result= TRUE;
45244 -+
45245 -+ if (error > 0 || (join->thd->is_error())) // Fatal error
45246 -+ return NESTED_LOOP_ERROR;
45247 -+ if (error < 0)
45248 -+ return NESTED_LOOP_NO_MORE_ROWS;
45249 -+ if (join->thd->killed) // Aborted by user
45250 -+ {
45251 -+ join->thd->send_kill_message();
45252 -+ return NESTED_LOOP_KILLED; /* purecov: inspected */
45253 -+ }
45254 -+ DBUG_PRINT("info", ("select cond 0x%lx", (ulong)select_cond));
45255 -+
45256 -+ if (select_cond)
45257 -+ {
45258 -+ select_cond_result= test(select_cond->val_int());
45259 -+
45260 -+ /* check for errors evaluating the condition */
45261 -+ if (join->thd->is_error())
45262 -+ return NESTED_LOOP_ERROR;
45263 -+ }
45264 -+
45265 -+ if (!select_cond || select_cond_result)
45266 -+ {
45267 -+ /*
45268 -+ There is no select condition or the attached pushed down
45269 -+ condition is true => a match is found.
45270 -+ */
45271 -+ bool found= 1;
45272 -+ while (join_tab->first_unmatched && found)
45273 -+ {
45274 -+ /*
45275 -+ The while condition is always false if join_tab is not
45276 -+ the last inner join table of an outer join operation.
45277 -+ */
45278 -+ JOIN_TAB *first_unmatched= join_tab->first_unmatched;
45279 -+ /*
45280 -+ Mark that a match for current outer table is found.
45281 -+ This activates push down conditional predicates attached
45282 -+ to the all inner tables of the outer join.
45283 -+ */
45284 -+ first_unmatched->found= 1;
45285 -+ for (JOIN_TAB *tab= first_unmatched; tab <= join_tab; tab++)
45286 -+ {
45287 -+ if (tab->table->reginfo.not_exists_optimize)
45288 -+ return NESTED_LOOP_NO_MORE_ROWS;
45289 -+ /* Check all predicates that has just been activated. */
45290 -+ /*
45291 -+ Actually all predicates non-guarded by first_unmatched->found
45292 -+ will be re-evaluated again. It could be fixed, but, probably,
45293 -+ it's not worth doing now.
45294 -+ */
45295 -+ if (tab->select_cond && !tab->select_cond->val_int())
45296 -+ {
45297 -+ /* The condition attached to table tab is false */
45298 -+ if (tab == join_tab)
45299 -+ found= 0;
45300 -+ else
45301 -+ {
45302 -+ /*
45303 -+ Set a return point if rejected predicate is attached
45304 -+ not to the last table of the current nest level.
45305 -+ */
45306 -+ join->return_tab= tab;
45307 -+ return NESTED_LOOP_OK;
45308 -+ }
45309 -+ }
45310 -+ }
45311 -+ /*
45312 -+ Check whether join_tab is not the last inner table
45313 -+ for another embedding outer join.
45314 -+ */
45315 -+ if ((first_unmatched= first_unmatched->first_upper) &&
45316 -+ first_unmatched->last_inner != join_tab)
45317 -+ first_unmatched= 0;
45318 -+ join_tab->first_unmatched= first_unmatched;
45319 -+ }
45320 -+
45321 -+ /*
45322 -+ It was not just a return to lower loop level when one
45323 -+ of the newly activated predicates is evaluated as false
45324 -+ (See above join->return_tab= tab).
45325 -+ */
45326 -+ join->examined_rows++;
45327 -+ join->thd->row_count++;
45328 -+ DBUG_PRINT("counts", ("join->examined_rows++: %lu",
45329 -+ (ulong) join->examined_rows));
45330 -+
45331 -+ if (found)
45332 -+ {
45333 -+ enum enum_nested_loop_state rc;
45334 -+ /* A match from join_tab is found for the current partial join. */
45335 -+ rc= (*join_tab->next_select)(join, join_tab+1, 0);
45336 -+ if (rc != NESTED_LOOP_OK && rc != NESTED_LOOP_NO_MORE_ROWS)
45337 -+ return rc;
45338 -+ if (join->return_tab < join_tab)
45339 -+ return NESTED_LOOP_OK;
45340 -+ /*
45341 -+ Test if this was a SELECT DISTINCT query on a table that
45342 -+ was not in the field list; In this case we can abort if
45343 -+ we found a row, as no new rows can be added to the result.
45344 -+ */
45345 -+ if (not_used_in_distinct && found_records != join->found_records)
45346 -+ return NESTED_LOOP_NO_MORE_ROWS;
45347 -+ }
45348 -+ else
45349 -+ join_tab->read_record.unlock_row(join_tab);
45350 -+ }
45351 -+ else
45352 -+ {
45353 -+ /*
45354 -+ The condition pushed down to the table join_tab rejects all rows
45355 -+ with the beginning coinciding with the current partial join.
45356 -+ */
45357 -+ join->examined_rows++;
45358 -+ join->thd->row_count++;
45359 -+ join_tab->read_record.unlock_row(join_tab);
45360 -+ }
45361 -+ return NESTED_LOOP_OK;
45362 -+}
45363 -+
45364 -+
45365 -+/**
45366 -+
45367 -+ @details
45368 -+ Construct a NULL complimented partial join record and feed it to the next
45369 -+ level of the nested loop. This function is used in case we have
45370 -+ an OUTER join and no matching record was found.
45371 -+*/
45372 -+
45373 -+static enum_nested_loop_state
45374 -+evaluate_null_complemented_join_record(JOIN *join, JOIN_TAB *join_tab)
45375 -+{
45376 -+ /*
45377 -+ The table join_tab is the first inner table of a outer join operation
45378 -+ and no matches has been found for the current outer row.
45379 -+ */
45380 -+ JOIN_TAB *last_inner_tab= join_tab->last_inner;
45381 -+ /* Cache variables for faster loop */
45382 -+ COND *select_cond;
45383 -+ for ( ; join_tab <= last_inner_tab ; join_tab++)
45384 -+ {
45385 -+ /* Change the the values of guard predicate variables. */
45386 -+ join_tab->found= 1;
45387 -+ join_tab->not_null_compl= 0;
45388 -+ /* The outer row is complemented by nulls for each inner tables */
45389 -+ restore_record(join_tab->table,s->default_values); // Make empty record
45390 -+ mark_as_null_row(join_tab->table); // For group by without error
45391 -+ select_cond= join_tab->select_cond;
45392 -+ /* Check all attached conditions for inner table rows. */
45393 -+ if (select_cond && !select_cond->val_int())
45394 -+ return NESTED_LOOP_OK;
45395 -+ }
45396 -+ join_tab--;
45397 -+ /*
45398 -+ The row complemented by nulls might be the first row
45399 -+ of embedding outer joins.
45400 -+ If so, perform the same actions as in the code
45401 -+ for the first regular outer join row above.
45402 -+ */
45403 -+ for ( ; ; )
45404 -+ {
45405 -+ JOIN_TAB *first_unmatched= join_tab->first_unmatched;
45406 -+ if ((first_unmatched= first_unmatched->first_upper) &&
45407 -+ first_unmatched->last_inner != join_tab)
45408 -+ first_unmatched= 0;
45409 -+ join_tab->first_unmatched= first_unmatched;
45410 -+ if (!first_unmatched)
45411 -+ break;
45412 -+ first_unmatched->found= 1;
45413 -+ for (JOIN_TAB *tab= first_unmatched; tab <= join_tab; tab++)
45414 -+ {
45415 -+ if (tab->select_cond && !tab->select_cond->val_int())
45416 -+ {
45417 -+ join->return_tab= tab;
45418 -+ return NESTED_LOOP_OK;
45419 -+ }
45420 -+ }
45421 -+ }
45422 -+ /*
45423 -+ The row complemented by nulls satisfies all conditions
45424 -+ attached to inner tables.
45425 -+ Send the row complemented by nulls to be joined with the
45426 -+ remaining tables.
45427 -+ */
45428 -+ return (*join_tab->next_select)(join, join_tab+1, 0);
45429 -+}
45430 -+
45431 -+
45432 -+static enum_nested_loop_state
45433 -+flush_cached_records(JOIN *join,JOIN_TAB *join_tab,bool skip_last)
45434 -+{
45435 -+ enum_nested_loop_state rc= NESTED_LOOP_OK;
45436 -+ int error;
45437 -+ READ_RECORD *info;
45438 -+
45439 -+ join_tab->table->null_row= 0;
45440 -+ if (!join_tab->cache.records)
45441 -+ return NESTED_LOOP_OK; /* Nothing to do */
45442 -+ if (skip_last)
45443 -+ (void) store_record_in_cache(&join_tab->cache); // Must save this for later
45444 -+ if (join_tab->use_quick == 2)
45445 -+ {
45446 -+ if (join_tab->select->quick)
45447 -+ { /* Used quick select last. reset it */
45448 -+ delete join_tab->select->quick;
45449 -+ join_tab->select->quick=0;
45450 -+ }
45451 -+ }
45452 -+ /* read through all records */
45453 -+ if ((error=join_init_read_record(join_tab)))
45454 -+ {
45455 -+ reset_cache_write(&join_tab->cache);
45456 -+ return error < 0 ? NESTED_LOOP_NO_MORE_ROWS: NESTED_LOOP_ERROR;
45457 -+ }
45458 -+
45459 -+ for (JOIN_TAB *tmp=join->join_tab; tmp != join_tab ; tmp++)
45460 -+ {
45461 -+ tmp->status=tmp->table->status;
45462 -+ tmp->table->status=0;
45463 -+ }
45464 -+
45465 -+ info= &join_tab->read_record;
45466 -+ do
45467 -+ {
45468 -+ if (join->thd->killed)
45469 -+ {
45470 -+ join->thd->send_kill_message();
45471 -+ return NESTED_LOOP_KILLED; // Aborted by user /* purecov: inspected */
45472 -+ }
45473 -+ SQL_SELECT *select=join_tab->select;
45474 -+ if (rc == NESTED_LOOP_OK)
45475 -+ {
45476 -+ bool skip_record= FALSE;
45477 -+ if (join_tab->cache.select &&
45478 -+ join_tab->cache.select->skip_record(join->thd, &skip_record))
45479 -+ {
45480 -+ reset_cache_write(&join_tab->cache);
45481 -+ return NESTED_LOOP_ERROR;
45482 -+ }
45483 -+
45484 -+ if (!skip_record)
45485 -+ {
45486 -+ uint i;
45487 -+ reset_cache_read(&join_tab->cache);
45488 -+ for (i=(join_tab->cache.records- (skip_last ? 1 : 0)) ; i-- > 0 ;)
45489 -+ {
45490 -+ read_cached_record(join_tab);
45491 -+ skip_record= FALSE;
45492 -+ if (select && select->skip_record(join->thd, &skip_record))
45493 -+ {
45494 -+ reset_cache_write(&join_tab->cache);
45495 -+ return NESTED_LOOP_ERROR;
45496 -+ }
45497 -+ if (!skip_record)
45498 -+ {
45499 -+ rc= (join_tab->next_select)(join,join_tab+1,0);
45500 -+ if (rc != NESTED_LOOP_OK && rc != NESTED_LOOP_NO_MORE_ROWS)
45501 -+ {
45502 -+ reset_cache_write(&join_tab->cache);
45503 -+ return rc;
45504 -+ }
45505 -+ }
45506 -+ }
45507 -+ }
45508 -+ }
45509 -+ } while (!(error=info->read_record(info)));
45510 -+
45511 -+ if (skip_last)
45512 -+ read_cached_record(join_tab); // Restore current record
45513 -+ reset_cache_write(&join_tab->cache);
45514 -+ if (error > 0) // Fatal error
45515 -+ return NESTED_LOOP_ERROR; /* purecov: inspected */
45516 -+ for (JOIN_TAB *tmp2=join->join_tab; tmp2 != join_tab ; tmp2++)
45517 -+ tmp2->table->status=tmp2->status;
45518 -+ return NESTED_LOOP_OK;
45519 -+}
45520 -+
45521 -+
45522 -+/*****************************************************************************
45523 -+ The different ways to read a record
45524 -+ Returns -1 if row was not found, 0 if row was found and 1 on errors
45525 -+*****************************************************************************/
45526 -+
45527 -+/** Help function when we get some an error from the table handler. */
45528 -+
45529 -+int report_error(TABLE *table, int error)
45530 -+{
45531 -+ if (error == HA_ERR_END_OF_FILE || error == HA_ERR_KEY_NOT_FOUND)
45532 -+ {
45533 -+ table->status= STATUS_GARBAGE;
45534 -+ return -1; // key not found; ok
45535 -+ }
45536 -+ /*
45537 -+ Locking reads can legally return also these errors, do not
45538 -+ print them to the .err log
45539 -+ */
45540 -+ if (error != HA_ERR_LOCK_DEADLOCK && error != HA_ERR_LOCK_WAIT_TIMEOUT)
45541 -+ sql_print_error("Got error %d when reading table '%s'",
45542 -+ error, table->s->path.str);
45543 -+ table->file->print_error(error,MYF(0));
45544 -+ return 1;
45545 -+}
45546 -+
45547 -+
45548 -+int safe_index_read(JOIN_TAB *tab)
45549 -+{
45550 -+ int error;
45551 -+ TABLE *table= tab->table;
45552 -+ if ((error=table->file->index_read_map(table->record[0],
45553 -+ tab->ref.key_buff,
45554 -+ make_prev_keypart_map(tab->ref.key_parts),
45555 -+ HA_READ_KEY_EXACT)))
45556 -+ return report_error(table, error);
45557 -+ return 0;
45558 -+}
45559 -+
45560 -+
45561 -+static int
45562 -+join_read_const_table(JOIN_TAB *tab, POSITION *pos)
45563 -+{
45564 -+ int error;
45565 -+ DBUG_ENTER("join_read_const_table");
45566 -+ TABLE *table=tab->table;
45567 -+ table->const_table=1;
45568 -+ table->null_row=0;
45569 -+ table->status=STATUS_NO_RECORD;
45570 -+
45571 -+ if (tab->type == JT_SYSTEM)
45572 -+ {
45573 -+ if ((error=join_read_system(tab)))
45574 -+ { // Info for DESCRIBE
45575 -+ tab->info="const row not found";
45576 -+ /* Mark for EXPLAIN that the row was not found */
45577 -+ pos->records_read=0.0;
45578 -+ pos->ref_depend_map= 0;
45579 -+ if (!table->maybe_null || error > 0)
45580 -+ DBUG_RETURN(error);
45581 -+ }
45582 -+ }
45583 -+ else
45584 -+ {
45585 -+ if (!table->key_read && table->covering_keys.is_set(tab->ref.key) &&
45586 -+ !table->no_keyread &&
45587 -+ (int) table->reginfo.lock_type <= (int) TL_READ_HIGH_PRIORITY)
45588 -+ {
45589 -+ table->set_keyread(TRUE);
45590 -+ tab->index= tab->ref.key;
45591 -+ }
45592 -+ error=join_read_const(tab);
45593 -+ table->set_keyread(FALSE);
45594 -+ if (error)
45595 -+ {
45596 -+ tab->info="unique row not found";
45597 -+ /* Mark for EXPLAIN that the row was not found */
45598 -+ pos->records_read=0.0;
45599 -+ pos->ref_depend_map= 0;
45600 -+ if (!table->maybe_null || error > 0)
45601 -+ DBUG_RETURN(error);
45602 -+ }
45603 -+ }
45604 -+ if (*tab->on_expr_ref && !table->null_row)
45605 -+ {
45606 -+ if ((table->null_row= test((*tab->on_expr_ref)->val_int() == 0)))
45607 -+ mark_as_null_row(table);
45608 -+ }
45609 -+ if (!table->null_row)
45610 -+ table->maybe_null=0;
45611 -+
45612 -+ /* Check appearance of new constant items in Item_equal objects */
45613 -+ JOIN *join= tab->join;
45614 -+ if (join->conds)
45615 -+ update_const_equal_items(join->conds, tab);
45616 -+ TABLE_LIST *tbl;
45617 -+ for (tbl= join->select_lex->leaf_tables; tbl; tbl= tbl->next_leaf)
45618 -+ {
45619 -+ TABLE_LIST *embedded;
45620 -+ TABLE_LIST *embedding= tbl;
45621 -+ do
45622 -+ {
45623 -+ embedded= embedding;
45624 -+ if (embedded->on_expr)
45625 -+ update_const_equal_items(embedded->on_expr, tab);
45626 -+ embedding= embedded->embedding;
45627 -+ }
45628 -+ while (embedding &&
45629 -+ embedding->nested_join->join_list.head() == embedded);
45630 -+ }
45631 -+
45632 -+ DBUG_RETURN(0);
45633 -+}
45634 -+
45635 -+
45636 -+static int
45637 -+join_read_system(JOIN_TAB *tab)
45638 -+{
45639 -+ TABLE *table= tab->table;
45640 -+ int error;
45641 -+ if (table->status & STATUS_GARBAGE) // If first read
45642 -+ {
45643 -+ if ((error=table->file->read_first_row(table->record[0],
45644 -+ table->s->primary_key)))
45645 -+ {
45646 -+ if (error != HA_ERR_END_OF_FILE)
45647 -+ return report_error(table, error);
45648 -+ mark_as_null_row(tab->table);
45649 -+ empty_record(table); // Make empty record
45650 -+ return -1;
45651 -+ }
45652 -+ store_record(table,record[1]);
45653 -+ }
45654 -+ else if (!table->status) // Only happens with left join
45655 -+ restore_record(table,record[1]); // restore old record
45656 -+ table->null_row=0;
45657 -+ return table->status ? -1 : 0;
45658 -+}
45659 -+
45660 -+
45661 -+/**
45662 -+ Read a table when there is at most one matching row.
45663 -+
45664 -+ @param tab Table to read
45665 -+
45666 -+ @retval
45667 -+ 0 Row was found
45668 -+ @retval
45669 -+ -1 Row was not found
45670 -+ @retval
45671 -+ 1 Got an error (other than row not found) during read
45672 -+*/
45673 -+
45674 -+static int
45675 -+join_read_const(JOIN_TAB *tab)
45676 -+{
45677 -+ int error;
45678 -+ TABLE *table= tab->table;
45679 -+ if (table->status & STATUS_GARBAGE) // If first read
45680 -+ {
45681 -+ table->status= 0;
45682 -+ if (cp_buffer_from_ref(tab->join->thd, table, &tab->ref))
45683 -+ error=HA_ERR_KEY_NOT_FOUND;
45684 -+ else
45685 -+ {
45686 -+ error=table->file->index_read_idx_map(table->record[0],tab->ref.key,
45687 -+ (uchar*) tab->ref.key_buff,
45688 -+ make_prev_keypart_map(tab->ref.key_parts),
45689 -+ HA_READ_KEY_EXACT);
45690 -+ }
45691 -+ if (error)
45692 -+ {
45693 -+ table->status= STATUS_NOT_FOUND;
45694 -+ mark_as_null_row(tab->table);
45695 -+ empty_record(table);
45696 -+ if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
45697 -+ return report_error(table, error);
45698 -+ return -1;
45699 -+ }
45700 -+ store_record(table,record[1]);
45701 -+ }
45702 -+ else if (!(table->status & ~STATUS_NULL_ROW)) // Only happens with left join
45703 -+ {
45704 -+ table->status=0;
45705 -+ restore_record(table,record[1]); // restore old record
45706 -+ }
45707 -+ table->null_row=0;
45708 -+ return table->status ? -1 : 0;
45709 -+}
45710 -+
45711 -+
45712 -+static int
45713 -+join_read_key(JOIN_TAB *tab)
45714 -+{
45715 -+ int error;
45716 -+ TABLE *table= tab->table;
45717 -+
45718 -+ if (!table->file->inited)
45719 -+ {
45720 -+ table->file->ha_index_init(tab->ref.key, tab->sorted);
45721 -+ }
45722 -+ if (cmp_buffer_with_ref(tab) ||
45723 -+ (table->status & (STATUS_GARBAGE | STATUS_NO_PARENT | STATUS_NULL_ROW)))
45724 -+ {
45725 -+ if (tab->ref.key_err)
45726 -+ {
45727 -+ table->status=STATUS_NOT_FOUND;
45728 -+ return -1;
45729 -+ }
45730 -+ /*
45731 -+ Moving away from the current record. Unlock the row
45732 -+ in the handler if it did not match the partial WHERE.
45733 -+ */
45734 -+ if (tab->ref.has_record && tab->ref.use_count == 0)
45735 -+ {
45736 -+ tab->read_record.file->unlock_row();
45737 -+ tab->ref.has_record= FALSE;
45738 -+ }
45739 -+ error=table->file->index_read_map(table->record[0],
45740 -+ tab->ref.key_buff,
45741 -+ make_prev_keypart_map(tab->ref.key_parts),
45742 -+ HA_READ_KEY_EXACT);
45743 -+ if (error && error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
45744 -+ return report_error(table, error);
45745 -+
45746 -+ if (! error)
45747 -+ {
45748 -+ tab->ref.has_record= TRUE;
45749 -+ tab->ref.use_count= 1;
45750 -+ }
45751 -+ }
45752 -+ else if (table->status == 0)
45753 -+ {
45754 -+ DBUG_ASSERT(tab->ref.has_record);
45755 -+ tab->ref.use_count++;
45756 -+ }
45757 -+ table->null_row=0;
45758 -+ return table->status ? -1 : 0;
45759 -+}
45760 -+
45761 -+
45762 -+/**
45763 -+ Since join_read_key may buffer a record, do not unlock
45764 -+ it if it was not used in this invocation of join_read_key().
45765 -+ Only count locks, thus remembering if the record was left unused,
45766 -+ and unlock already when pruning the current value of
45767 -+ TABLE_REF buffer.
45768 -+ @sa join_read_key()
45769 -+*/
45770 -+
45771 -+static void
45772 -+join_read_key_unlock_row(st_join_table *tab)
45773 -+{
45774 -+ DBUG_ASSERT(tab->ref.use_count);
45775 -+ if (tab->ref.use_count)
45776 -+ tab->ref.use_count--;
45777 -+}
45778 -+
45779 -+/*
45780 -+ ref access method implementation: "read_first" function
45781 -+
45782 -+ SYNOPSIS
45783 -+ join_read_always_key()
45784 -+ tab JOIN_TAB of the accessed table
45785 -+
45786 -+ DESCRIPTION
45787 -+ This is "read_fist" function for the "ref" access method.
45788 -+
45789 -+ The functon must leave the index initialized when it returns.
45790 -+ ref_or_null access implementation depends on that.
45791 -+
45792 -+ RETURN
45793 -+ 0 - Ok
45794 -+ -1 - Row not found
45795 -+ 1 - Error
45796 -+*/
45797 -+
45798 -+static int
45799 -+join_read_always_key(JOIN_TAB *tab)
45800 -+{
45801 -+ int error;
45802 -+ TABLE *table= tab->table;
45803 -+
45804 -+ /* Initialize the index first */
45805 -+ if (!table->file->inited)
45806 -+ table->file->ha_index_init(tab->ref.key, tab->sorted);
45807 -+
45808 -+ /* Perform "Late NULLs Filtering" (see internals manual for explanations) */
45809 -+ for (uint i= 0 ; i < tab->ref.key_parts ; i++)
45810 -+ {
45811 -+ if ((tab->ref.null_rejecting & 1 << i) && tab->ref.items[i]->is_null())
45812 -+ return -1;
45813 -+ }
45814 -+
45815 -+ if (cp_buffer_from_ref(tab->join->thd, table, &tab->ref))
45816 -+ return -1;
45817 -+ if ((error=table->file->index_read_map(table->record[0],
45818 -+ tab->ref.key_buff,
45819 -+ make_prev_keypart_map(tab->ref.key_parts),
45820 -+ HA_READ_KEY_EXACT)))
45821 -+ {
45822 -+ if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
45823 -+ return report_error(table, error);
45824 -+ return -1; /* purecov: inspected */
45825 -+ }
45826 -+ return 0;
45827 -+}
45828 -+
45829 -+
45830 -+/**
45831 -+ This function is used when optimizing away ORDER BY in
45832 -+ SELECT * FROM t1 WHERE a=1 ORDER BY a DESC,b DESC.
45833 -+*/
45834 -+
45835 -+static int
45836 -+join_read_last_key(JOIN_TAB *tab)
45837 -+{
45838 -+ int error;
45839 -+ TABLE *table= tab->table;
45840 -+
45841 -+ if (!table->file->inited)
45842 -+ table->file->ha_index_init(tab->ref.key, tab->sorted);
45843 -+ if (cp_buffer_from_ref(tab->join->thd, table, &tab->ref))
45844 -+ return -1;
45845 -+ if ((error=table->file->index_read_last_map(table->record[0],
45846 -+ tab->ref.key_buff,
45847 -+ make_prev_keypart_map(tab->ref.key_parts))))
45848 -+ {
45849 -+ if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
45850 -+ return report_error(table, error);
45851 -+ return -1; /* purecov: inspected */
45852 -+ }
45853 -+ return 0;
45854 -+}
45855 -+
45856 -+
45857 -+ /* ARGSUSED */
45858 -+static int
45859 -+join_no_more_records(READ_RECORD *info __attribute__((unused)))
45860 -+{
45861 -+ return -1;
45862 -+}
45863 -+
45864 -+
45865 -+static int
45866 -+join_read_next_same(READ_RECORD *info)
45867 -+{
45868 -+ int error;
45869 -+ TABLE *table= info->table;
45870 -+ JOIN_TAB *tab=table->reginfo.join_tab;
45871 -+
45872 -+ if ((error=table->file->index_next_same(table->record[0],
45873 -+ tab->ref.key_buff,
45874 -+ tab->ref.key_length)))
45875 -+ {
45876 -+ if (error != HA_ERR_END_OF_FILE)
45877 -+ return report_error(table, error);
45878 -+ table->status= STATUS_GARBAGE;
45879 -+ return -1;
45880 -+ }
45881 -+ return 0;
45882 -+}
45883 -+
45884 -+
45885 -+static int
45886 -+join_read_prev_same(READ_RECORD *info)
45887 -+{
45888 -+ int error;
45889 -+ TABLE *table= info->table;
45890 -+ JOIN_TAB *tab=table->reginfo.join_tab;
45891 -+
45892 -+ if ((error=table->file->index_prev(table->record[0])))
45893 -+ return report_error(table, error);
45894 -+ if (key_cmp_if_same(table, tab->ref.key_buff, tab->ref.key,
45895 -+ tab->ref.key_length))
45896 -+ {
45897 -+ table->status=STATUS_NOT_FOUND;
45898 -+ error= -1;
45899 -+ }
45900 -+ return error;
45901 -+}
45902 -+
45903 -+
45904 -+static int
45905 -+join_init_quick_read_record(JOIN_TAB *tab)
45906 -+{
45907 -+ if (test_if_quick_select(tab) == -1)
45908 -+ return -1; /* No possible records */
45909 -+ return join_init_read_record(tab);
45910 -+}
45911 -+
45912 -+
45913 -+int rr_sequential(READ_RECORD *info);
45914 -+int init_read_record_seq(JOIN_TAB *tab)
45915 -+{
45916 -+ tab->read_record.read_record= rr_sequential;
45917 -+ if (tab->read_record.file->ha_rnd_init(1))
45918 -+ return 1;
45919 -+ return (*tab->read_record.read_record)(&tab->read_record);
45920 -+}
45921 -+
45922 -+static int
45923 -+test_if_quick_select(JOIN_TAB *tab)
45924 -+{
45925 -+ delete tab->select->quick;
45926 -+ tab->select->quick=0;
45927 -+ return tab->select->test_quick_select(tab->join->thd, tab->keys,
45928 -+ (table_map) 0, HA_POS_ERROR, 0);
45929 -+}
45930 -+
45931 -+
45932 -+static int
45933 -+join_init_read_record(JOIN_TAB *tab)
45934 -+{
45935 -+ if (tab->select && tab->select->quick && tab->select->quick->reset())
45936 -+ return 1;
45937 -+ init_read_record(&tab->read_record, tab->join->thd, tab->table,
45938 -+ tab->select,1,1, FALSE);
45939 -+ return (*tab->read_record.read_record)(&tab->read_record);
45940 -+}
45941 -+
45942 -+
45943 -+static int
45944 -+join_read_first(JOIN_TAB *tab)
45945 -+{
45946 -+ int error;
45947 -+ TABLE *table=tab->table;
45948 -+ if (table->covering_keys.is_set(tab->index) && !table->no_keyread)
45949 -+ table->set_keyread(TRUE);
45950 -+ tab->table->status=0;
45951 -+ tab->read_record.read_record=join_read_next;
45952 -+ tab->read_record.table=table;
45953 -+ tab->read_record.file=table->file;
45954 -+ tab->read_record.index=tab->index;
45955 -+ tab->read_record.record=table->record[0];
45956 -+ if (!table->file->inited)
45957 -+ table->file->ha_index_init(tab->index, tab->sorted);
45958 -+ if ((error=tab->table->file->index_first(tab->table->record[0])))
45959 -+ {
45960 -+ if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
45961 -+ report_error(table, error);
45962 -+ return -1;
45963 -+ }
45964 -+ return 0;
45965 -+}
45966 -+
45967 -+
45968 -+static int
45969 -+join_read_next(READ_RECORD *info)
45970 -+{
45971 -+ int error;
45972 -+ if ((error=info->file->index_next(info->record)))
45973 -+ return report_error(info->table, error);
45974 -+ return 0;
45975 -+}
45976 -+
45977 -+
45978 -+static int
45979 -+join_read_last(JOIN_TAB *tab)
45980 -+{
45981 -+ TABLE *table=tab->table;
45982 -+ int error;
45983 -+ if (table->covering_keys.is_set(tab->index) && !table->no_keyread)
45984 -+ table->set_keyread(TRUE);
45985 -+ tab->table->status=0;
45986 -+ tab->read_record.read_record=join_read_prev;
45987 -+ tab->read_record.table=table;
45988 -+ tab->read_record.file=table->file;
45989 -+ tab->read_record.index=tab->index;
45990 -+ tab->read_record.record=table->record[0];
45991 -+ if (!table->file->inited)
45992 -+ table->file->ha_index_init(tab->index, 1);
45993 -+ if ((error= tab->table->file->index_last(tab->table->record[0])))
45994 -+ return report_error(table, error);
45995 -+ return 0;
45996 -+}
45997 -+
45998 -+
45999 -+static int
46000 -+join_read_prev(READ_RECORD *info)
46001 -+{
46002 -+ int error;
46003 -+ if ((error= info->file->index_prev(info->record)))
46004 -+ return report_error(info->table, error);
46005 -+ return 0;
46006 -+}
46007 -+
46008 -+
46009 -+static int
46010 -+join_ft_read_first(JOIN_TAB *tab)
46011 -+{
46012 -+ int error;
46013 -+ TABLE *table= tab->table;
46014 -+
46015 -+ if (!table->file->inited)
46016 -+ table->file->ha_index_init(tab->ref.key, 1);
46017 -+#if NOT_USED_YET
46018 -+ /* as ft-key doesn't use store_key's, see also FT_SELECT::init() */
46019 -+ if (cp_buffer_from_ref(tab->join->thd, table, &tab->ref))
46020 -+ return -1;
46021 -+#endif
46022 -+ table->file->ft_init();
46023 -+
46024 -+ if ((error= table->file->ft_read(table->record[0])))
46025 -+ return report_error(table, error);
46026 -+ return 0;
46027 -+}
46028 -+
46029 -+static int
46030 -+join_ft_read_next(READ_RECORD *info)
46031 -+{
46032 -+ int error;
46033 -+ if ((error= info->file->ft_read(info->table->record[0])))
46034 -+ return report_error(info->table, error);
46035 -+ return 0;
46036 -+}
46037 -+
46038 -+
46039 -+/**
46040 -+ Reading of key with key reference and one part that may be NULL.
46041 -+*/
46042 -+
46043 -+int
46044 -+join_read_always_key_or_null(JOIN_TAB *tab)
46045 -+{
46046 -+ int res;
46047 -+
46048 -+ /* First read according to key which is NOT NULL */
46049 -+ *tab->ref.null_ref_key= 0; // Clear null byte
46050 -+ if ((res= join_read_always_key(tab)) >= 0)
46051 -+ return res;
46052 -+
46053 -+ /* Then read key with null value */
46054 -+ *tab->ref.null_ref_key= 1; // Set null byte
46055 -+ return safe_index_read(tab);
46056 -+}
46057 -+
46058 -+
46059 -+int
46060 -+join_read_next_same_or_null(READ_RECORD *info)
46061 -+{
46062 -+ int error;
46063 -+ if ((error= join_read_next_same(info)) >= 0)
46064 -+ return error;
46065 -+ JOIN_TAB *tab= info->table->reginfo.join_tab;
46066 -+
46067 -+ /* Test if we have already done a read after null key */
46068 -+ if (*tab->ref.null_ref_key)
46069 -+ return -1; // All keys read
46070 -+ *tab->ref.null_ref_key= 1; // Set null byte
46071 -+ return safe_index_read(tab); // then read null keys
46072 -+}
46073 -+
46074 -+
46075 -+/*****************************************************************************
46076 -+ DESCRIPTION
46077 -+ Functions that end one nested loop iteration. Different functions
46078 -+ are used to support GROUP BY clause and to redirect records
46079 -+ to a table (e.g. in case of SELECT into a temporary table) or to the
46080 -+ network client.
46081 -+
46082 -+ RETURN VALUES
46083 -+ NESTED_LOOP_OK - the record has been successfully handled
46084 -+ NESTED_LOOP_ERROR - a fatal error (like table corruption)
46085 -+ was detected
46086 -+ NESTED_LOOP_KILLED - thread shutdown was requested while processing
46087 -+ the record
46088 -+ NESTED_LOOP_QUERY_LIMIT - the record has been successfully handled;
46089 -+ additionally, the nested loop produced the
46090 -+ number of rows specified in the LIMIT clause
46091 -+ for the query
46092 -+ NESTED_LOOP_CURSOR_LIMIT - the record has been successfully handled;
46093 -+ additionally, there is a cursor and the nested
46094 -+ loop algorithm produced the number of rows
46095 -+ that is specified for current cursor fetch
46096 -+ operation.
46097 -+ All return values except NESTED_LOOP_OK abort the nested loop.
46098 -+*****************************************************************************/
46099 -+
46100 -+/* ARGSUSED */
46101 -+static enum_nested_loop_state
46102 -+end_send(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
46103 -+ bool end_of_records)
46104 -+{
46105 -+ DBUG_ENTER("end_send");
46106 -+ if (!end_of_records)
46107 -+ {
46108 -+ int error;
46109 -+ if (join->having && join->having->val_int() == 0)
46110 -+ DBUG_RETURN(NESTED_LOOP_OK); // Didn't match having
46111 -+ error=0;
46112 -+ if (join->procedure)
46113 -+ error=join->procedure->send_row(join->procedure_fields_list);
46114 -+ else if (join->do_send_rows)
46115 -+ error=join->result->send_data(*join->fields);
46116 -+ if (error)
46117 -+ DBUG_RETURN(NESTED_LOOP_ERROR); /* purecov: inspected */
46118 -+ if (++join->send_records >= join->unit->select_limit_cnt &&
46119 -+ join->do_send_rows)
46120 -+ {
46121 -+ if (join->select_options & OPTION_FOUND_ROWS)
46122 -+ {
46123 -+ JOIN_TAB *jt=join->join_tab;
46124 -+ if ((join->tables == 1) && !join->tmp_table && !join->sort_and_group
46125 -+ && !join->send_group_parts && !join->having && !jt->select_cond &&
46126 -+ !(jt->select && jt->select->quick) &&
46127 -+ (jt->table->file->ha_table_flags() & HA_STATS_RECORDS_IS_EXACT) &&
46128 -+ (jt->ref.key < 0))
46129 -+ {
46130 -+ /* Join over all rows in table; Return number of found rows */
46131 -+ TABLE *table=jt->table;
46132 -+
46133 -+ join->select_options ^= OPTION_FOUND_ROWS;
46134 -+ if (table->sort.record_pointers ||
46135 -+ (table->sort.io_cache && my_b_inited(table->sort.io_cache)))
46136 -+ {
46137 -+ /* Using filesort */
46138 -+ join->send_records= table->sort.found_records;
46139 -+ }
46140 -+ else
46141 -+ {
46142 -+ table->file->info(HA_STATUS_VARIABLE);
46143 -+ join->send_records= table->file->stats.records;
46144 -+ }
46145 -+ }
46146 -+ else
46147 -+ {
46148 -+ join->do_send_rows= 0;
46149 -+ if (join->unit->fake_select_lex)
46150 -+ join->unit->fake_select_lex->select_limit= 0;
46151 -+ DBUG_RETURN(NESTED_LOOP_OK);
46152 -+ }
46153 -+ }
46154 -+ DBUG_RETURN(NESTED_LOOP_QUERY_LIMIT); // Abort nicely
46155 -+ }
46156 -+ else if (join->send_records >= join->fetch_limit)
46157 -+ {
46158 -+ /*
46159 -+ There is a server side cursor and all rows for
46160 -+ this fetch request are sent.
46161 -+ */
46162 -+ DBUG_RETURN(NESTED_LOOP_CURSOR_LIMIT);
46163 -+ }
46164 -+ }
46165 -+ else
46166 -+ {
46167 -+ if (join->procedure && join->procedure->end_of_records())
46168 -+ DBUG_RETURN(NESTED_LOOP_ERROR);
46169 -+ }
46170 -+ DBUG_RETURN(NESTED_LOOP_OK);
46171 -+}
46172 -+
46173 -+
46174 -+ /* ARGSUSED */
46175 -+static enum_nested_loop_state
46176 -+end_send_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
46177 -+ bool end_of_records)
46178 -+{
46179 -+ int idx= -1;
46180 -+ enum_nested_loop_state ok_code= NESTED_LOOP_OK;
46181 -+ DBUG_ENTER("end_send_group");
46182 -+
46183 -+ if (!join->first_record || end_of_records ||
46184 -+ (idx=test_if_group_changed(join->group_fields)) >= 0)
46185 -+ {
46186 -+ if (join->first_record ||
46187 -+ (end_of_records && !join->group && !join->group_optimized_away))
46188 -+ {
46189 -+ if (join->procedure)
46190 -+ join->procedure->end_group();
46191 -+ if (idx < (int) join->send_group_parts)
46192 -+ {
46193 -+ int error=0;
46194 -+ if (join->procedure)
46195 -+ {
46196 -+ if (join->having && join->having->val_int() == 0)
46197 -+ error= -1; // Didn't satisfy having
46198 -+ else
46199 -+ {
46200 -+ if (join->do_send_rows)
46201 -+ error=join->procedure->send_row(*join->fields) ? 1 : 0;
46202 -+ join->send_records++;
46203 -+ }
46204 -+ if (end_of_records && join->procedure->end_of_records())
46205 -+ error= 1; // Fatal error
46206 -+ }
46207 -+ else
46208 -+ {
46209 -+ if (!join->first_record)
46210 -+ {
46211 -+ List_iterator_fast<Item> it(*join->fields);
46212 -+ Item *item;
46213 -+ /* No matching rows for group function */
46214 -+ join->clear();
46215 -+
46216 -+ while ((item= it++))
46217 -+ item->no_rows_in_result();
46218 -+ }
46219 -+ if (join->having && join->having->val_int() == 0)
46220 -+ error= -1; // Didn't satisfy having
46221 -+ else
46222 -+ {
46223 -+ if (join->do_send_rows)
46224 -+ error=join->result->send_data(*join->fields) ? 1 : 0;
46225 -+ join->send_records++;
46226 -+ }
46227 -+ if (join->rollup.state != ROLLUP::STATE_NONE && error <= 0)
46228 -+ {
46229 -+ if (join->rollup_send_data((uint) (idx+1)))
46230 -+ error= 1;
46231 -+ }
46232 -+ }
46233 -+ if (error > 0)
46234 -+ DBUG_RETURN(NESTED_LOOP_ERROR); /* purecov: inspected */
46235 -+ if (end_of_records)
46236 -+ DBUG_RETURN(NESTED_LOOP_OK);
46237 -+ if (join->send_records >= join->unit->select_limit_cnt &&
46238 -+ join->do_send_rows)
46239 -+ {
46240 -+ if (!(join->select_options & OPTION_FOUND_ROWS))
46241 -+ DBUG_RETURN(NESTED_LOOP_QUERY_LIMIT); // Abort nicely
46242 -+ join->do_send_rows=0;
46243 -+ join->unit->select_limit_cnt = HA_POS_ERROR;
46244 -+ }
46245 -+ else if (join->send_records >= join->fetch_limit)
46246 -+ {
46247 -+ /*
46248 -+ There is a server side cursor and all rows
46249 -+ for this fetch request are sent.
46250 -+ */
46251 -+ /*
46252 -+ Preventing code duplication. When finished with the group reset
46253 -+ the group functions and copy_fields. We fall through. bug #11904
46254 -+ */
46255 -+ ok_code= NESTED_LOOP_CURSOR_LIMIT;
46256 -+ }
46257 -+ }
46258 -+ }
46259 -+ else
46260 -+ {
46261 -+ if (end_of_records)
46262 -+ DBUG_RETURN(NESTED_LOOP_OK);
46263 -+ join->first_record=1;
46264 -+ VOID(test_if_group_changed(join->group_fields));
46265 -+ }
46266 -+ if (idx < (int) join->send_group_parts)
46267 -+ {
46268 -+ /*
46269 -+ This branch is executed also for cursors which have finished their
46270 -+ fetch limit - the reason for ok_code.
46271 -+ */
46272 -+ copy_fields(&join->tmp_table_param);
46273 -+ if (init_sum_functions(join->sum_funcs, join->sum_funcs_end[idx+1]))
46274 -+ DBUG_RETURN(NESTED_LOOP_ERROR);
46275 -+ if (join->procedure)
46276 -+ join->procedure->add();
46277 -+ DBUG_RETURN(ok_code);
46278 -+ }
46279 -+ }
46280 -+ if (update_sum_func(join->sum_funcs))
46281 -+ DBUG_RETURN(NESTED_LOOP_ERROR);
46282 -+ if (join->procedure)
46283 -+ join->procedure->add();
46284 -+ DBUG_RETURN(NESTED_LOOP_OK);
46285 -+}
46286 -+
46287 -+
46288 -+ /* ARGSUSED */
46289 -+static enum_nested_loop_state
46290 -+end_write(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
46291 -+ bool end_of_records)
46292 -+{
46293 -+ TABLE *table=join->tmp_table;
46294 -+ DBUG_ENTER("end_write");
46295 -+
46296 -+ if (join->thd->killed) // Aborted by user
46297 -+ {
46298 -+ join->thd->send_kill_message();
46299 -+ DBUG_RETURN(NESTED_LOOP_KILLED); /* purecov: inspected */
46300 -+ }
46301 -+ if (!end_of_records)
46302 -+ {
46303 -+ copy_fields(&join->tmp_table_param);
46304 -+ if (copy_funcs(join->tmp_table_param.items_to_copy, join->thd))
46305 -+ DBUG_RETURN(NESTED_LOOP_ERROR); /* purecov: inspected */
46306 -+
46307 -+#ifdef TO_BE_DELETED
46308 -+ if (!table->uniques) // If not unique handling
46309 -+ {
46310 -+ /* Copy null values from group to row */
46311 -+ ORDER *group;
46312 -+ for (group=table->group ; group ; group=group->next)
46313 -+ {
46314 -+ Item *item= *group->item;
46315 -+ if (item->maybe_null)
46316 -+ {
46317 -+ Field *field=item->get_tmp_table_field();
46318 -+ field->ptr[-1]= (uchar) (field->is_null() ? 1 : 0);
46319 -+ }
46320 -+ }
46321 -+ }
46322 -+#endif
46323 -+ if (!join->having || join->having->val_int())
46324 -+ {
46325 -+ int error;
46326 -+ join->found_records++;
46327 -+ if ((error=table->file->ha_write_row(table->record[0])))
46328 -+ {
46329 -+ if (!table->file->is_fatal_error(error, HA_CHECK_DUP))
46330 -+ goto end;
46331 -+ if (create_myisam_from_heap(join->thd, table, &join->tmp_table_param,
46332 -+ error,1))
46333 -+ DBUG_RETURN(NESTED_LOOP_ERROR); // Not a table_is_full error
46334 -+ table->s->uniques=0; // To ensure rows are the same
46335 -+ }
46336 -+ if (++join->send_records >= join->tmp_table_param.end_write_records &&
46337 -+ join->do_send_rows)
46338 -+ {
46339 -+ if (!(join->select_options & OPTION_FOUND_ROWS))
46340 -+ DBUG_RETURN(NESTED_LOOP_QUERY_LIMIT);
46341 -+ join->do_send_rows=0;
46342 -+ join->unit->select_limit_cnt = HA_POS_ERROR;
46343 -+ DBUG_RETURN(NESTED_LOOP_OK);
46344 -+ }
46345 -+ }
46346 -+ }
46347 -+end:
46348 -+ DBUG_RETURN(NESTED_LOOP_OK);
46349 -+}
46350 -+
46351 -+/* ARGSUSED */
46352 -+/** Group by searching after group record and updating it if possible. */
46353 -+
46354 -+static enum_nested_loop_state
46355 -+end_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
46356 -+ bool end_of_records)
46357 -+{
46358 -+ TABLE *table=join->tmp_table;
46359 -+ ORDER *group;
46360 -+ int error;
46361 -+ DBUG_ENTER("end_update");
46362 -+
46363 -+ if (end_of_records)
46364 -+ DBUG_RETURN(NESTED_LOOP_OK);
46365 -+ if (join->thd->killed) // Aborted by user
46366 -+ {
46367 -+ join->thd->send_kill_message();
46368 -+ DBUG_RETURN(NESTED_LOOP_KILLED); /* purecov: inspected */
46369 -+ }
46370 -+
46371 -+ join->found_records++;
46372 -+ copy_fields(&join->tmp_table_param); // Groups are copied twice.
46373 -+ /* Make a key of group index */
46374 -+ for (group=table->group ; group ; group=group->next)
46375 -+ {
46376 -+ Item *item= *group->item;
46377 -+ item->save_org_in_field(group->field);
46378 -+ /* Store in the used key if the field was 0 */
46379 -+ if (item->maybe_null)
46380 -+ group->buff[-1]= (char) group->field->is_null();
46381 -+ }
46382 -+ if (!table->file->index_read_map(table->record[1],
46383 -+ join->tmp_table_param.group_buff,
46384 -+ HA_WHOLE_KEY,
46385 -+ HA_READ_KEY_EXACT))
46386 -+ { /* Update old record */
46387 -+ restore_record(table,record[1]);
46388 -+ update_tmptable_sum_func(join->sum_funcs,table);
46389 -+ if ((error=table->file->ha_update_row(table->record[1],
46390 -+ table->record[0])))
46391 -+ {
46392 -+ table->file->print_error(error,MYF(0)); /* purecov: inspected */
46393 -+ DBUG_RETURN(NESTED_LOOP_ERROR); /* purecov: inspected */
46394 -+ }
46395 -+ DBUG_RETURN(NESTED_LOOP_OK);
46396 -+ }
46397 -+
46398 -+ /*
46399 -+ Copy null bits from group key to table
46400 -+ We can't copy all data as the key may have different format
46401 -+ as the row data (for example as with VARCHAR keys)
46402 -+ */
46403 -+ KEY_PART_INFO *key_part;
46404 -+ for (group=table->group,key_part=table->key_info[0].key_part;
46405 -+ group ;
46406 -+ group=group->next,key_part++)
46407 -+ {
46408 -+ if (key_part->null_bit)
46409 -+ memcpy(table->record[0]+key_part->offset, group->buff, 1);
46410 -+ }
46411 -+ init_tmptable_sum_functions(join->sum_funcs);
46412 -+ if (copy_funcs(join->tmp_table_param.items_to_copy, join->thd))
46413 -+ DBUG_RETURN(NESTED_LOOP_ERROR); /* purecov: inspected */
46414 -+ if ((error=table->file->ha_write_row(table->record[0])))
46415 -+ {
46416 -+ if (create_myisam_from_heap(join->thd, table, &join->tmp_table_param,
46417 -+ error, 0))
46418 -+ DBUG_RETURN(NESTED_LOOP_ERROR); // Not a table_is_full error
46419 -+ /* Change method to update rows */
46420 -+ table->file->ha_index_init(0, 0);
46421 -+ join->join_tab[join->tables-1].next_select=end_unique_update;
46422 -+ }
46423 -+ join->send_records++;
46424 -+ DBUG_RETURN(NESTED_LOOP_OK);
46425 -+}
46426 -+
46427 -+
46428 -+/** Like end_update, but this is done with unique constraints instead of keys. */
46429 -+
46430 -+static enum_nested_loop_state
46431 -+end_unique_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
46432 -+ bool end_of_records)
46433 -+{
46434 -+ TABLE *table=join->tmp_table;
46435 -+ int error;
46436 -+ DBUG_ENTER("end_unique_update");
46437 -+
46438 -+ if (end_of_records)
46439 -+ DBUG_RETURN(NESTED_LOOP_OK);
46440 -+ if (join->thd->killed) // Aborted by user
46441 -+ {
46442 -+ join->thd->send_kill_message();
46443 -+ DBUG_RETURN(NESTED_LOOP_KILLED); /* purecov: inspected */
46444 -+ }
46445 -+
46446 -+ init_tmptable_sum_functions(join->sum_funcs);
46447 -+ copy_fields(&join->tmp_table_param); // Groups are copied twice.
46448 -+ if (copy_funcs(join->tmp_table_param.items_to_copy, join->thd))
46449 -+ DBUG_RETURN(NESTED_LOOP_ERROR); /* purecov: inspected */
46450 -+
46451 -+ if (!(error=table->file->ha_write_row(table->record[0])))
46452 -+ join->send_records++; // New group
46453 -+ else
46454 -+ {
46455 -+ if ((int) table->file->get_dup_key(error) < 0)
46456 -+ {
46457 -+ table->file->print_error(error,MYF(0)); /* purecov: inspected */
46458 -+ DBUG_RETURN(NESTED_LOOP_ERROR); /* purecov: inspected */
46459 -+ }
46460 -+ if (table->file->rnd_pos(table->record[1],table->file->dup_ref))
46461 -+ {
46462 -+ table->file->print_error(error,MYF(0)); /* purecov: inspected */
46463 -+ DBUG_RETURN(NESTED_LOOP_ERROR); /* purecov: inspected */
46464 -+ }
46465 -+ restore_record(table,record[1]);
46466 -+ update_tmptable_sum_func(join->sum_funcs,table);
46467 -+ if ((error=table->file->ha_update_row(table->record[1],
46468 -+ table->record[0])))
46469 -+ {
46470 -+ table->file->print_error(error,MYF(0)); /* purecov: inspected */
46471 -+ DBUG_RETURN(NESTED_LOOP_ERROR); /* purecov: inspected */
46472 -+ }
46473 -+ }
46474 -+ DBUG_RETURN(NESTED_LOOP_OK);
46475 -+}
46476 -+
46477 -+
46478 -+ /* ARGSUSED */
46479 -+static enum_nested_loop_state
46480 -+end_write_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
46481 -+ bool end_of_records)
46482 -+{
46483 -+ TABLE *table=join->tmp_table;
46484 -+ int idx= -1;
46485 -+ DBUG_ENTER("end_write_group");
46486 -+
46487 -+ if (join->thd->killed)
46488 -+ { // Aborted by user
46489 -+ join->thd->send_kill_message();
46490 -+ DBUG_RETURN(NESTED_LOOP_KILLED); /* purecov: inspected */
46491 -+ }
46492 -+ if (!join->first_record || end_of_records ||
46493 -+ (idx=test_if_group_changed(join->group_fields)) >= 0)
46494 -+ {
46495 -+ if (join->first_record || (end_of_records && !join->group))
46496 -+ {
46497 -+ if (join->procedure)
46498 -+ join->procedure->end_group();
46499 -+ int send_group_parts= join->send_group_parts;
46500 -+ if (idx < send_group_parts)
46501 -+ {
46502 -+ if (!join->first_record)
46503 -+ {
46504 -+ /* No matching rows for group function */
46505 -+ join->clear();
46506 -+ }
46507 -+ copy_sum_funcs(join->sum_funcs,
46508 -+ join->sum_funcs_end[send_group_parts]);
46509 -+ if (!join->having || join->having->val_int())
46510 -+ {
46511 -+ int error= table->file->ha_write_row(table->record[0]);
46512 -+ if (error && create_myisam_from_heap(join->thd, table,
46513 -+ &join->tmp_table_param,
46514 -+ error, 0))
46515 -+ DBUG_RETURN(NESTED_LOOP_ERROR);
46516 -+ }
46517 -+ if (join->rollup.state != ROLLUP::STATE_NONE)
46518 -+ {
46519 -+ if (join->rollup_write_data((uint) (idx+1), table))
46520 -+ DBUG_RETURN(NESTED_LOOP_ERROR);
46521 -+ }
46522 -+ if (end_of_records)
46523 -+ DBUG_RETURN(NESTED_LOOP_OK);
46524 -+ }
46525 -+ }
46526 -+ else
46527 -+ {
46528 -+ if (end_of_records)
46529 -+ DBUG_RETURN(NESTED_LOOP_OK);
46530 -+ join->first_record=1;
46531 -+ VOID(test_if_group_changed(join->group_fields));
46532 -+ }
46533 -+ if (idx < (int) join->send_group_parts)
46534 -+ {
46535 -+ copy_fields(&join->tmp_table_param);
46536 -+ if (copy_funcs(join->tmp_table_param.items_to_copy, join->thd))
46537 -+ DBUG_RETURN(NESTED_LOOP_ERROR);
46538 -+ if (init_sum_functions(join->sum_funcs, join->sum_funcs_end[idx+1]))
46539 -+ DBUG_RETURN(NESTED_LOOP_ERROR);
46540 -+ if (join->procedure)
46541 -+ join->procedure->add();
46542 -+ DBUG_RETURN(NESTED_LOOP_OK);
46543 -+ }
46544 -+ }
46545 -+ if (update_sum_func(join->sum_funcs))
46546 -+ DBUG_RETURN(NESTED_LOOP_ERROR);
46547 -+ if (join->procedure)
46548 -+ join->procedure->add();
46549 -+ DBUG_RETURN(NESTED_LOOP_OK);
46550 -+}
46551 -+
46552 -+
46553 -+/*****************************************************************************
46554 -+ Remove calculation with tables that aren't yet read. Remove also tests
46555 -+ against fields that are read through key where the table is not a
46556 -+ outer join table.
46557 -+ We can't remove tests that are made against columns which are stored
46558 -+ in sorted order.
46559 -+*****************************************************************************/
46560 -+
46561 -+/**
46562 -+ @return
46563 -+ 1 if right_item is used removable reference key on left_item
46564 -+*/
46565 -+
46566 -+static bool test_if_ref(Item_field *left_item,Item *right_item)
46567 -+{
46568 -+ Field *field=left_item->field;
46569 -+ // No need to change const test. We also have to keep tests on LEFT JOIN
46570 -+ if (!field->table->const_table && !field->table->maybe_null)
46571 -+ {
46572 -+ Item *ref_item=part_of_refkey(field->table,field);
46573 -+ if (ref_item && ref_item->eq(right_item,1))
46574 -+ {
46575 -+ right_item= right_item->real_item();
46576 -+ if (right_item->type() == Item::FIELD_ITEM)
46577 -+ return (field->eq_def(((Item_field *) right_item)->field));
46578 -+ /* remove equalities injected by IN->EXISTS transformation */
46579 -+ else if (right_item->type() == Item::CACHE_ITEM)
46580 -+ return ((Item_cache *)right_item)->eq_def (field);
46581 -+ if (right_item->const_item() && !(right_item->is_null()))
46582 -+ {
46583 -+ /*
46584 -+ We can remove binary fields and numerical fields except float,
46585 -+ as float comparison isn't 100 % secure
46586 -+ We have to keep normal strings to be able to check for end spaces
46587 -+ */
46588 -+ if (field->binary() &&
46589 -+ field->real_type() != MYSQL_TYPE_STRING &&
46590 -+ field->real_type() != MYSQL_TYPE_VARCHAR &&
46591 -+ (field->type() != MYSQL_TYPE_FLOAT || field->decimals() == 0))
46592 -+ {
46593 -+ return !store_val_in_field(field, right_item, CHECK_FIELD_WARN);
46594 -+ }
46595 -+ }
46596 -+ }
46597 -+ }
46598 -+ return 0; // keep test
46599 -+}
46600 -+
46601 -+
46602 -+static COND *
46603 -+make_cond_for_table(COND *cond, table_map tables, table_map used_table)
46604 -+{
46605 -+ if (used_table && !(cond->used_tables() & used_table))
46606 -+ return (COND*) 0; // Already checked
46607 -+ if (cond->type() == Item::COND_ITEM)
46608 -+ {
46609 -+ if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
46610 -+ {
46611 -+ /* Create new top level AND item */
46612 -+ Item_cond_and *new_cond=new Item_cond_and;
46613 -+ if (!new_cond)
46614 -+ return (COND*) 0; // OOM /* purecov: inspected */
46615 -+ List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
46616 -+ Item *item;
46617 -+ while ((item=li++))
46618 -+ {
46619 -+ Item *fix=make_cond_for_table(item,tables,used_table);
46620 -+ if (fix)
46621 -+ new_cond->argument_list()->push_back(fix);
46622 -+ }
46623 -+ switch (new_cond->argument_list()->elements) {
46624 -+ case 0:
46625 -+ return (COND*) 0; // Always true
46626 -+ case 1:
46627 -+ return new_cond->argument_list()->head();
46628 -+ default:
46629 -+ /*
46630 -+ Item_cond_and do not need fix_fields for execution, its parameters
46631 -+ are fixed or do not need fix_fields, too
46632 -+ */
46633 -+ new_cond->quick_fix_field();
46634 -+ new_cond->used_tables_cache=
46635 -+ ((Item_cond_and*) cond)->used_tables_cache &
46636 -+ tables;
46637 -+ return new_cond;
46638 -+ }
46639 -+ }
46640 -+ else
46641 -+ { // Or list
46642 -+ Item_cond_or *new_cond=new Item_cond_or;
46643 -+ if (!new_cond)
46644 -+ return (COND*) 0; // OOM /* purecov: inspected */
46645 -+ List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
46646 -+ Item *item;
46647 -+ while ((item=li++))
46648 -+ {
46649 -+ Item *fix=make_cond_for_table(item,tables,0L);
46650 -+ if (!fix)
46651 -+ return (COND*) 0; // Always true
46652 -+ new_cond->argument_list()->push_back(fix);
46653 -+ }
46654 -+ /*
46655 -+ Item_cond_and do not need fix_fields for execution, its parameters
46656 -+ are fixed or do not need fix_fields, too
46657 -+ */
46658 -+ new_cond->quick_fix_field();
46659 -+ new_cond->used_tables_cache= ((Item_cond_or*) cond)->used_tables_cache;
46660 -+ new_cond->top_level_item();
46661 -+ return new_cond;
46662 -+ }
46663 -+ }
46664 -+
46665 -+ /*
46666 -+ Because the following test takes a while and it can be done
46667 -+ table_count times, we mark each item that we have examined with the result
46668 -+ of the test
46669 -+ */
46670 -+
46671 -+ if (cond->marker == 3 || (cond->used_tables() & ~tables))
46672 -+ return (COND*) 0; // Can't check this yet
46673 -+ if (cond->marker == 2 || cond->eq_cmp_result() == Item::COND_OK)
46674 -+ return cond; // Not boolean op
46675 -+
46676 -+ if (((Item_func*) cond)->functype() == Item_func::EQ_FUNC)
46677 -+ {
46678 -+ Item *left_item= ((Item_func*) cond)->arguments()[0];
46679 -+ Item *right_item= ((Item_func*) cond)->arguments()[1];
46680 -+ if (left_item->type() == Item::FIELD_ITEM &&
46681 -+ test_if_ref((Item_field*) left_item,right_item))
46682 -+ {
46683 -+ cond->marker=3; // Checked when read
46684 -+ return (COND*) 0;
46685 -+ }
46686 -+ if (right_item->type() == Item::FIELD_ITEM &&
46687 -+ test_if_ref((Item_field*) right_item,left_item))
46688 -+ {
46689 -+ cond->marker=3; // Checked when read
46690 -+ return (COND*) 0;
46691 -+ }
46692 -+ }
46693 -+ cond->marker=2;
46694 -+ return cond;
46695 -+}
46696 -+
46697 -+static Item *
46698 -+part_of_refkey(TABLE *table,Field *field)
46699 -+{
46700 -+ if (!table->reginfo.join_tab)
46701 -+ return (Item*) 0; // field from outer non-select (UPDATE,...)
46702 -+
46703 -+ uint ref_parts=table->reginfo.join_tab->ref.key_parts;
46704 -+ if (ref_parts)
46705 -+ {
46706 -+ KEY_PART_INFO *key_part=
46707 -+ table->key_info[table->reginfo.join_tab->ref.key].key_part;
46708 -+
46709 -+ for (uint part=0 ; part < ref_parts ; part++,key_part++)
46710 -+ if (field->eq(key_part->field) &&
46711 -+ !(key_part->key_part_flag & (HA_PART_KEY_SEG | HA_NULL_PART)))
46712 -+ return table->reginfo.join_tab->ref.items[part];
46713 -+ }
46714 -+ return (Item*) 0;
46715 -+}
46716 -+
46717 -+
46718 -+/**
46719 -+ Test if one can use the key to resolve ORDER BY.
46720 -+
46721 -+ @param order Sort order
46722 -+ @param table Table to sort
46723 -+ @param idx Index to check
46724 -+ @param used_key_parts Return value for used key parts.
46725 -+
46726 -+
46727 -+ @note
46728 -+ used_key_parts is set to correct key parts used if return value != 0
46729 -+ (On other cases, used_key_part may be changed)
46730 -+ Note that the value may actually be greater than the number of index
46731 -+ key parts. This can happen for storage engines that have the primary
46732 -+ key parts as a suffix for every secondary key.
46733 -+
46734 -+ @retval
46735 -+ 1 key is ok.
46736 -+ @retval
46737 -+ 0 Key can't be used
46738 -+ @retval
46739 -+ -1 Reverse key can be used
46740 -+*/
46741 -+
46742 -+static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx,
46743 -+ uint *used_key_parts)
46744 -+{
46745 -+ KEY_PART_INFO *key_part,*key_part_end;
46746 -+ key_part=table->key_info[idx].key_part;
46747 -+ key_part_end=key_part+table->key_info[idx].key_parts;
46748 -+ key_part_map const_key_parts=table->const_key_parts[idx];
46749 -+ int reverse=0;
46750 -+ my_bool on_pk_suffix= FALSE;
46751 -+ DBUG_ENTER("test_if_order_by_key");
46752 -+
46753 -+ for (; order ; order=order->next, const_key_parts>>=1)
46754 -+ {
46755 -+ Field *field=((Item_field*) (*order->item)->real_item())->field;
46756 -+ int flag;
46757 -+
46758 -+ /*
46759 -+ Skip key parts that are constants in the WHERE clause.
46760 -+ These are already skipped in the ORDER BY by const_expression_in_where()
46761 -+ */
46762 -+ for (; const_key_parts & 1 ; const_key_parts>>= 1)
46763 -+ key_part++;
46764 -+
46765 -+ if (key_part == key_part_end)
46766 -+ {
46767 -+ /*
46768 -+ We are at the end of the key. Check if the engine has the primary
46769 -+ key as a suffix to the secondary keys. If it has continue to check
46770 -+ the primary key as a suffix.
46771 -+ */
46772 -+ if (!on_pk_suffix &&
46773 -+ (table->file->ha_table_flags() & HA_PRIMARY_KEY_IN_READ_INDEX) &&
46774 -+ table->s->primary_key != MAX_KEY &&
46775 -+ table->s->primary_key != idx)
46776 -+ {
46777 -+ on_pk_suffix= TRUE;
46778 -+ key_part= table->key_info[table->s->primary_key].key_part;
46779 -+ key_part_end=key_part+table->key_info[table->s->primary_key].key_parts;
46780 -+ const_key_parts=table->const_key_parts[table->s->primary_key];
46781 -+
46782 -+ for (; const_key_parts & 1 ; const_key_parts>>= 1)
46783 -+ key_part++;
46784 -+ /*
46785 -+ The primary and secondary key parts were all const (i.e. there's
46786 -+ one row). The sorting doesn't matter.
46787 -+ */
46788 -+ if (key_part == key_part_end && reverse == 0)
46789 -+ {
46790 -+ *used_key_parts= 0;
46791 -+ DBUG_RETURN(1);
46792 -+ }
46793 -+ }
46794 -+ else
46795 -+ DBUG_RETURN(0);
46796 -+ }
46797 -+
46798 -+ if (key_part->field != field)
46799 -+ DBUG_RETURN(0);
46800 -+
46801 -+ /* set flag to 1 if we can use read-next on key, else to -1 */
46802 -+ flag= ((order->asc == !(key_part->key_part_flag & HA_REVERSE_SORT)) ?
46803 -+ 1 : -1);
46804 -+ if (reverse && flag != reverse)
46805 -+ DBUG_RETURN(0);
46806 -+ reverse=flag; // Remember if reverse
46807 -+ key_part++;
46808 -+ }
46809 -+ if (on_pk_suffix)
46810 -+ {
46811 -+ uint used_key_parts_secondary= table->key_info[idx].key_parts;
46812 -+ uint used_key_parts_pk=
46813 -+ (uint) (key_part - table->key_info[table->s->primary_key].key_part);
46814 -+ *used_key_parts= used_key_parts_pk + used_key_parts_secondary;
46815 -+
46816 -+ if (reverse == -1 &&
46817 -+ (!(table->file->index_flags(idx, used_key_parts_secondary - 1, 1) &
46818 -+ HA_READ_PREV) ||
46819 -+ !(table->file->index_flags(table->s->primary_key,
46820 -+ used_key_parts_pk - 1, 1) & HA_READ_PREV)))
46821 -+ reverse= 0; // Index can't be used
46822 -+ }
46823 -+ else
46824 -+ {
46825 -+ *used_key_parts= (uint) (key_part - table->key_info[idx].key_part);
46826 -+ if (reverse == -1 &&
46827 -+ !(table->file->index_flags(idx, *used_key_parts-1, 1) & HA_READ_PREV))
46828 -+ reverse= 0; // Index can't be used
46829 -+ }
46830 -+ DBUG_RETURN(reverse);
46831 -+}
46832 -+
46833 -+
46834 -+/**
46835 -+ Find shortest key suitable for full table scan.
46836 -+
46837 -+ @param table Table to scan
46838 -+ @param usable_keys Allowed keys
46839 -+
46840 -+ @note
46841 -+ As far as
46842 -+ 1) clustered primary key entry data set is a set of all record
46843 -+ fields (key fields and not key fields) and
46844 -+ 2) secondary index entry data is a union of its key fields and
46845 -+ primary key fields (at least InnoDB and its derivatives don't
46846 -+ duplicate primary key fields there, even if the primary and
46847 -+ the secondary keys have a common subset of key fields),
46848 -+ then secondary index entry data is always a subset of primary key entry.
46849 -+ Unfortunately, key_info[nr].key_length doesn't show the length
46850 -+ of key/pointer pair but a sum of key field lengths only, thus
46851 -+ we can't estimate index IO volume comparing only this key_length
46852 -+ value of secondary keys and clustered PK.
46853 -+ So, try secondary keys first, and choose PK only if there are no
46854 -+ usable secondary covering keys or found best secondary key include
46855 -+ all table fields (i.e. same as PK):
46856 -+
46857 -+ @return
46858 -+ MAX_KEY no suitable key found
46859 -+ key index otherwise
46860 -+*/
46861 -+
46862 -+uint find_shortest_key(TABLE *table, const key_map *usable_keys)
46863 -+{
46864 -+ uint best= MAX_KEY;
46865 -+ uint usable_clustered_pk= (table->file->primary_key_is_clustered() &&
46866 -+ table->s->primary_key != MAX_KEY &&
46867 -+ usable_keys->is_set(table->s->primary_key)) ?
46868 -+ table->s->primary_key : MAX_KEY;
46869 -+ if (!usable_keys->is_clear_all())
46870 -+ {
46871 -+ uint min_length= (uint) ~0;
46872 -+ for (uint nr=0; nr < table->s->keys ; nr++)
46873 -+ {
46874 -+ if (nr == usable_clustered_pk)
46875 -+ continue;
46876 -+ if (usable_keys->is_set(nr))
46877 -+ {
46878 -+ if (table->key_info[nr].key_length < min_length)
46879 -+ {
46880 -+ min_length=table->key_info[nr].key_length;
46881 -+ best=nr;
46882 -+ }
46883 -+ }
46884 -+ }
46885 -+ }
46886 -+ if (usable_clustered_pk != MAX_KEY)
46887 -+ {
46888 -+ /*
46889 -+ If the primary key is clustered and found shorter key covers all table
46890 -+ fields then primary key scan normally would be faster because amount of
46891 -+ data to scan is the same but PK is clustered.
46892 -+ It's safe to compare key parts with table fields since duplicate key
46893 -+ parts aren't allowed.
46894 -+ */
46895 -+ if (best == MAX_KEY ||
46896 -+ table->key_info[best].key_parts >= table->s->fields)
46897 -+ best= usable_clustered_pk;
46898 -+ }
46899 -+ return best;
46900 -+}
46901 -+
46902 -+/**
46903 -+ Test if a second key is the subkey of the first one.
46904 -+
46905 -+ @param key_part First key parts
46906 -+ @param ref_key_part Second key parts
46907 -+ @param ref_key_part_end Last+1 part of the second key
46908 -+
46909 -+ @note
46910 -+ Second key MUST be shorter than the first one.
46911 -+
46912 -+ @retval
46913 -+ 1 is a subkey
46914 -+ @retval
46915 -+ 0 no sub key
46916 -+*/
46917 -+
46918 -+inline bool
46919 -+is_subkey(KEY_PART_INFO *key_part, KEY_PART_INFO *ref_key_part,
46920 -+ KEY_PART_INFO *ref_key_part_end)
46921 -+{
46922 -+ for (; ref_key_part < ref_key_part_end; key_part++, ref_key_part++)
46923 -+ if (!key_part->field->eq(ref_key_part->field))
46924 -+ return 0;
46925 -+ return 1;
46926 -+}
46927 -+
46928 -+/**
46929 -+ Test if we can use one of the 'usable_keys' instead of 'ref' key
46930 -+ for sorting.
46931 -+
46932 -+ @param ref Number of key, used for WHERE clause
46933 -+ @param usable_keys Keys for testing
46934 -+
46935 -+ @return
46936 -+ - MAX_KEY If we can't use other key
46937 -+ - the number of found key Otherwise
46938 -+*/
46939 -+
46940 -+static uint
46941 -+test_if_subkey(ORDER *order, TABLE *table, uint ref, uint ref_key_parts,
46942 -+ const key_map *usable_keys)
46943 -+{
46944 -+ uint nr;
46945 -+ uint min_length= (uint) ~0;
46946 -+ uint best= MAX_KEY;
46947 -+ uint not_used;
46948 -+ KEY_PART_INFO *ref_key_part= table->key_info[ref].key_part;
46949 -+ KEY_PART_INFO *ref_key_part_end= ref_key_part + ref_key_parts;
46950 -+
46951 -+ for (nr= 0 ; nr < table->s->keys ; nr++)
46952 -+ {
46953 -+ if (usable_keys->is_set(nr) &&
46954 -+ table->key_info[nr].key_length < min_length &&
46955 -+ table->key_info[nr].key_parts >= ref_key_parts &&
46956 -+ is_subkey(table->key_info[nr].key_part, ref_key_part,
46957 -+ ref_key_part_end) &&
46958 -+ test_if_order_by_key(order, table, nr, &not_used))
46959 -+ {
46960 -+ min_length= table->key_info[nr].key_length;
46961 -+ best= nr;
46962 -+ }
46963 -+ }
46964 -+ return best;
46965 -+}
46966 -+
46967 -+
46968 -+/**
46969 -+ Check if GROUP BY/DISTINCT can be optimized away because the set is
46970 -+ already known to be distinct.
46971 -+
46972 -+ Used in removing the GROUP BY/DISTINCT of the following types of
46973 -+ statements:
46974 -+ @code
46975 -+ SELECT [DISTINCT] <unique_key_cols>... FROM <single_table_ref>
46976 -+ [GROUP BY <unique_key_cols>,...]
46977 -+ @endcode
46978 -+
46979 -+ If (a,b,c is distinct)
46980 -+ then <any combination of a,b,c>,{whatever} is also distinct
46981 -+
46982 -+ This function checks if all the key parts of any of the unique keys
46983 -+ of the table are referenced by a list : either the select list
46984 -+ through find_field_in_item_list or GROUP BY list through
46985 -+ find_field_in_order_list.
46986 -+ If the above holds and the key parts cannot contain NULLs then we
46987 -+ can safely remove the GROUP BY/DISTINCT,
46988 -+ as no result set can be more distinct than an unique key.
46989 -+
46990 -+ @param table The table to operate on.
46991 -+ @param find_func function to iterate over the list and search
46992 -+ for a field
46993 -+
46994 -+ @retval
46995 -+ 1 found
46996 -+ @retval
46997 -+ 0 not found.
46998 -+*/
46999 -+
47000 -+static bool
47001 -+list_contains_unique_index(TABLE *table,
47002 -+ bool (*find_func) (Field *, void *), void *data)
47003 -+{
47004 -+ if (table->pos_in_table_list->outer_join)
47005 -+ return 0;
47006 -+ for (uint keynr= 0; keynr < table->s->keys; keynr++)
47007 -+ {
47008 -+ if (keynr == table->s->primary_key ||
47009 -+ (table->key_info[keynr].flags & HA_NOSAME))
47010 -+ {
47011 -+ KEY *keyinfo= table->key_info + keynr;
47012 -+ KEY_PART_INFO *key_part, *key_part_end;
47013 -+
47014 -+ for (key_part=keyinfo->key_part,
47015 -+ key_part_end=key_part+ keyinfo->key_parts;
47016 -+ key_part < key_part_end;
47017 -+ key_part++)
47018 -+ {
47019 -+ if (key_part->field->real_maybe_null() ||
47020 -+ !find_func(key_part->field, data))
47021 -+ break;
47022 -+ }
47023 -+ if (key_part == key_part_end)
47024 -+ return 1;
47025 -+ }
47026 -+ }
47027 -+ return 0;
47028 -+}
47029 -+
47030 -+
47031 -+/**
47032 -+ Helper function for list_contains_unique_index.
47033 -+ Find a field reference in a list of ORDER structures.
47034 -+ Finds a direct reference of the Field in the list.
47035 -+
47036 -+ @param field The field to search for.
47037 -+ @param data ORDER *.The list to search in
47038 -+
47039 -+ @retval
47040 -+ 1 found
47041 -+ @retval
47042 -+ 0 not found.
47043 -+*/
47044 -+
47045 -+static bool
47046 -+find_field_in_order_list (Field *field, void *data)
47047 -+{
47048 -+ ORDER *group= (ORDER *) data;
47049 -+ bool part_found= 0;
47050 -+ for (ORDER *tmp_group= group; tmp_group; tmp_group=tmp_group->next)
47051 -+ {
47052 -+ Item *item= (*tmp_group->item)->real_item();
47053 -+ if (item->type() == Item::FIELD_ITEM &&
47054 -+ ((Item_field*) item)->field->eq(field))
47055 -+ {
47056 -+ part_found= 1;
47057 -+ break;
47058 -+ }
47059 -+ }
47060 -+ return part_found;
47061 -+}
47062 -+
47063 -+
47064 -+/**
47065 -+ Helper function for list_contains_unique_index.
47066 -+ Find a field reference in a dynamic list of Items.
47067 -+ Finds a direct reference of the Field in the list.
47068 -+
47069 -+ @param[in] field The field to search for.
47070 -+ @param[in] data List<Item> *.The list to search in
47071 -+
47072 -+ @retval
47073 -+ 1 found
47074 -+ @retval
47075 -+ 0 not found.
47076 -+*/
47077 -+
47078 -+static bool
47079 -+find_field_in_item_list (Field *field, void *data)
47080 -+{
47081 -+ List<Item> *fields= (List<Item> *) data;
47082 -+ bool part_found= 0;
47083 -+ List_iterator<Item> li(*fields);
47084 -+ Item *item;
47085 -+
47086 -+ while ((item= li++))
47087 -+ {
47088 -+ if (item->type() == Item::FIELD_ITEM &&
47089 -+ ((Item_field*) item)->field->eq(field))
47090 -+ {
47091 -+ part_found= 1;
47092 -+ break;
47093 -+ }
47094 -+ }
47095 -+ return part_found;
47096 -+}
47097 -+
47098 -+
47099 -+/**
47100 -+ Test if we can skip the ORDER BY by using an index.
47101 -+
47102 -+ If we can use an index, the JOIN_TAB / tab->select struct
47103 -+ is changed to use the index.
47104 -+
47105 -+ The index must cover all fields in <order>, or it will not be considered.
47106 -+
47107 -+ @param no_changes No changes will be made to the query plan.
47108 -+
47109 -+ @todo
47110 -+ - sergeyp: Results of all index merge selects actually are ordered
47111 -+ by clustered PK values.
47112 -+
47113 -+ @retval
47114 -+ 0 We have to use filesort to do the sorting
47115 -+ @retval
47116 -+ 1 We can use an index.
47117 -+*/
47118 -+
47119 -+static bool
47120 -+test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
47121 -+ bool no_changes, key_map *map)
47122 -+{
47123 -+ int ref_key;
47124 -+ uint ref_key_parts;
47125 -+ int order_direction= 0;
47126 -+ uint used_key_parts;
47127 -+ TABLE *table=tab->table;
47128 -+ SQL_SELECT *select=tab->select;
47129 -+ key_map usable_keys;
47130 -+ QUICK_SELECT_I *save_quick= 0;
47131 -+ int best_key= -1;
47132 -+
47133 -+ DBUG_ENTER("test_if_skip_sort_order");
47134 -+ LINT_INIT(ref_key_parts);
47135 -+
47136 -+ /*
47137 -+ Keys disabled by ALTER TABLE ... DISABLE KEYS should have already
47138 -+ been taken into account.
47139 -+ */
47140 -+ usable_keys= *map;
47141 -+
47142 -+ for (ORDER *tmp_order=order; tmp_order ; tmp_order=tmp_order->next)
47143 -+ {
47144 -+ Item *item= (*tmp_order->item)->real_item();
47145 -+ if (item->type() != Item::FIELD_ITEM)
47146 -+ {
47147 -+ usable_keys.clear_all();
47148 -+ DBUG_RETURN(0);
47149 -+ }
47150 -+ usable_keys.intersect(((Item_field*) item)->field->part_of_sortkey);
47151 -+ if (usable_keys.is_clear_all())
47152 -+ DBUG_RETURN(0); // No usable keys
47153 -+ }
47154 -+
47155 -+ ref_key= -1;
47156 -+ /* Test if constant range in WHERE */
47157 -+ if (tab->ref.key >= 0 && tab->ref.key_parts)
47158 -+ {
47159 -+ ref_key= tab->ref.key;
47160 -+ ref_key_parts= tab->ref.key_parts;
47161 -+ if (tab->type == JT_REF_OR_NULL || tab->type == JT_FT)
47162 -+ DBUG_RETURN(0);
47163 -+ }
47164 -+ else if (select && select->quick) // Range found by opt_range
47165 -+ {
47166 -+ int quick_type= select->quick->get_type();
47167 -+ save_quick= select->quick;
47168 -+ /*
47169 -+ assume results are not ordered when index merge is used
47170 -+ TODO: sergeyp: Results of all index merge selects actually are ordered
47171 -+ by clustered PK values.
47172 -+ */
47173 -+
47174 -+ if (quick_type == QUICK_SELECT_I::QS_TYPE_INDEX_MERGE ||
47175 -+ quick_type == QUICK_SELECT_I::QS_TYPE_ROR_UNION ||
47176 -+ quick_type == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT)
47177 -+ DBUG_RETURN(0);
47178 -+ ref_key= select->quick->index;
47179 -+ ref_key_parts= select->quick->used_key_parts;
47180 -+ }
47181 -+
47182 -+ if (ref_key >= 0)
47183 -+ {
47184 -+ /*
47185 -+ We come here when there is a REF key.
47186 -+ */
47187 -+ if (!usable_keys.is_set(ref_key))
47188 -+ {
47189 -+ /*
47190 -+ We come here when ref_key is not among usable_keys
47191 -+ */
47192 -+ uint new_ref_key;
47193 -+ /*
47194 -+ If using index only read, only consider other possible index only
47195 -+ keys
47196 -+ */
47197 -+ if (table->covering_keys.is_set(ref_key))
47198 -+ usable_keys.intersect(table->covering_keys);
47199 -+ if ((new_ref_key= test_if_subkey(order, table, ref_key, ref_key_parts,
47200 -+ &usable_keys)) < MAX_KEY)
47201 -+ {
47202 -+ /* Found key that can be used to retrieve data in sorted order */
47203 -+ if (tab->ref.key >= 0)
47204 -+ {
47205 -+ /*
47206 -+ We'll use ref access method on key new_ref_key. In general case
47207 -+ the index search tuple for new_ref_key will be different (e.g.
47208 -+ when one index is defined as (part1, part2, ...) and another as
47209 -+ (part1, part2(N), ...) and the WHERE clause contains
47210 -+ "part1 = const1 AND part2=const2".
47211 -+ So we build tab->ref from scratch here.
47212 -+ */
47213 -+ KEYUSE *keyuse= tab->keyuse;
47214 -+ while (keyuse->key != new_ref_key && keyuse->table == tab->table)
47215 -+ keyuse++;
47216 -+ if (create_ref_for_key(tab->join, tab, keyuse,
47217 -+ tab->join->const_table_map))
47218 -+ DBUG_RETURN(0);
47219 -+
47220 -+ pick_table_access_method(tab);
47221 -+ }
47222 -+ else
47223 -+ {
47224 -+ /*
47225 -+ The range optimizer constructed QUICK_RANGE for ref_key, and
47226 -+ we want to use instead new_ref_key as the index. We can't
47227 -+ just change the index of the quick select, because this may
47228 -+ result in an incosistent QUICK_SELECT object. Below we
47229 -+ create a new QUICK_SELECT from scratch so that all its
47230 -+ parameres are set correctly by the range optimizer.
47231 -+ */
47232 -+ key_map new_ref_key_map;
47233 -+ new_ref_key_map.clear_all(); // Force the creation of quick select
47234 -+ new_ref_key_map.set_bit(new_ref_key); // only for new_ref_key.
47235 -+
47236 -+ select->quick= 0;
47237 -+ if (select->test_quick_select(tab->join->thd, new_ref_key_map, 0,
47238 -+ (tab->join->select_options &
47239 -+ OPTION_FOUND_ROWS) ?
47240 -+ HA_POS_ERROR :
47241 -+ tab->join->unit->select_limit_cnt,0) <=
47242 -+ 0)
47243 -+ goto use_filesort;
47244 -+ }
47245 -+ ref_key= new_ref_key;
47246 -+ }
47247 -+ }
47248 -+ /* Check if we get the rows in requested sorted order by using the key */
47249 -+ if (usable_keys.is_set(ref_key) &&
47250 -+ (order_direction= test_if_order_by_key(order,table,ref_key,
47251 -+ &used_key_parts)))
47252 -+ goto check_reverse_order;
47253 -+ }
47254 -+ {
47255 -+ /*
47256 -+ Check whether there is an index compatible with the given order
47257 -+ usage of which is cheaper than usage of the ref_key index (ref_key>=0)
47258 -+ or a table scan.
47259 -+ It may be the case if ORDER/GROUP BY is used with LIMIT.
47260 -+ */
47261 -+ uint nr;
47262 -+ key_map keys;
47263 -+ uint best_key_parts= 0;
47264 -+ uint saved_best_key_parts= 0;
47265 -+ int best_key_direction= 0;
47266 -+ ha_rows best_records= 0;
47267 -+ double read_time;
47268 -+ bool is_best_covering= FALSE;
47269 -+ double fanout= 1;
47270 -+ JOIN *join= tab->join;
47271 -+ uint tablenr= tab - join->join_tab;
47272 -+ ha_rows table_records= table->file->stats.records;
47273 -+ bool group= join->group && order == join->group_list;
47274 -+ ha_rows ref_key_quick_rows= HA_POS_ERROR;
47275 -+
47276 -+ /*
47277 -+ If not used with LIMIT, only use keys if the whole query can be
47278 -+ resolved with a key; This is because filesort() is usually faster than
47279 -+ retrieving all rows through an index.
47280 -+ */
47281 -+ if (select_limit >= table_records)
47282 -+ {
47283 -+ keys= *table->file->keys_to_use_for_scanning();
47284 -+ keys.merge(table->covering_keys);
47285 -+
47286 -+ /*
47287 -+ We are adding here also the index specified in FORCE INDEX clause,
47288 -+ if any.
47289 -+ This is to allow users to use index in ORDER BY.
47290 -+ */
47291 -+ if (table->force_index)
47292 -+ keys.merge(group ? table->keys_in_use_for_group_by :
47293 -+ table->keys_in_use_for_order_by);
47294 -+ keys.intersect(usable_keys);
47295 -+ }
47296 -+ else
47297 -+ keys= usable_keys;
47298 -+
47299 -+ if (ref_key >= 0 && table->covering_keys.is_set(ref_key))
47300 -+ ref_key_quick_rows= table->quick_rows[ref_key];
47301 -+
47302 -+ read_time= join->best_positions[tablenr].read_time;
47303 -+ for (uint i= tablenr+1; i < join->tables; i++)
47304 -+ fanout*= join->best_positions[i].records_read; // fanout is always >= 1
47305 -+
47306 -+ for (nr=0; nr < table->s->keys ; nr++)
47307 -+ {
47308 -+ int direction;
47309 -+
47310 -+ if (keys.is_set(nr) &&
47311 -+ (direction= test_if_order_by_key(order, table, nr, &used_key_parts)))
47312 -+ {
47313 -+ /*
47314 -+ At this point we are sure that ref_key is a non-ordering
47315 -+ key (where "ordering key" is a key that will return rows
47316 -+ in the order required by ORDER BY).
47317 -+ */
47318 -+ DBUG_ASSERT (ref_key != (int) nr);
47319 -+
47320 -+ bool is_covering= table->covering_keys.is_set(nr) ||
47321 -+ (nr == table->s->primary_key &&
47322 -+ table->file->primary_key_is_clustered());
47323 -+
47324 -+ /*
47325 -+ Don't use an index scan with ORDER BY without limit.
47326 -+ For GROUP BY without limit always use index scan
47327 -+ if there is a suitable index.
47328 -+ Why we hold to this asymmetry hardly can be explained
47329 -+ rationally. It's easy to demonstrate that using
47330 -+ temporary table + filesort could be cheaper for grouping
47331 -+ queries too.
47332 -+ */
47333 -+ if (is_covering ||
47334 -+ select_limit != HA_POS_ERROR ||
47335 -+ (ref_key < 0 && (group || table->force_index)))
47336 -+ {
47337 -+ double rec_per_key;
47338 -+ double index_scan_time;
47339 -+ KEY *keyinfo= tab->table->key_info+nr;
47340 -+ if (select_limit == HA_POS_ERROR)
47341 -+ select_limit= table_records;
47342 -+ if (group)
47343 -+ {
47344 -+ /*
47345 -+ Used_key_parts can be larger than keyinfo->key_parts
47346 -+ when using a secondary index clustered with a primary
47347 -+ key (e.g. as in Innodb).
47348 -+ See Bug #28591 for details.
47349 -+ */
47350 -+ rec_per_key= used_key_parts &&
47351 -+ used_key_parts <= keyinfo->key_parts ?
47352 -+ keyinfo->rec_per_key[used_key_parts-1] : 1;
47353 -+ set_if_bigger(rec_per_key, 1);
47354 -+ /*
47355 -+ With a grouping query each group containing on average
47356 -+ rec_per_key records produces only one row that will
47357 -+ be included into the result set.
47358 -+ */
47359 -+ if (select_limit > table_records/rec_per_key)
47360 -+ select_limit= table_records;
47361 -+ else
47362 -+ select_limit= (ha_rows) (select_limit*rec_per_key);
47363 -+ }
47364 -+ /*
47365 -+ If tab=tk is not the last joined table tn then to get first
47366 -+ L records from the result set we can expect to retrieve
47367 -+ only L/fanout(tk,tn) where fanout(tk,tn) says how many
47368 -+ rows in the record set on average will match each row tk.
47369 -+ Usually our estimates for fanouts are too pessimistic.
47370 -+ So the estimate for L/fanout(tk,tn) will be too optimistic
47371 -+ and as result we'll choose an index scan when using ref/range
47372 -+ access + filesort will be cheaper.
47373 -+ */
47374 -+ select_limit= (ha_rows) (select_limit < fanout ?
47375 -+ 1 : select_limit/fanout);
47376 -+ /*
47377 -+ We assume that each of the tested indexes is not correlated
47378 -+ with ref_key. Thus, to select first N records we have to scan
47379 -+ N/selectivity(ref_key) index entries.
47380 -+ selectivity(ref_key) = #scanned_records/#table_records =
47381 -+ table->quick_condition_rows/table_records.
47382 -+ In any case we can't select more than #table_records.
47383 -+ N/(table->quick_condition_rows/table_records) > table_records
47384 -+ <=> N > table->quick_condition_rows.
47385 -+ */
47386 -+ if (select_limit > table->quick_condition_rows)
47387 -+ select_limit= table_records;
47388 -+ else
47389 -+ select_limit= (ha_rows) (select_limit *
47390 -+ (double) table_records /
47391 -+ table->quick_condition_rows);
47392 -+ rec_per_key= keyinfo->rec_per_key[keyinfo->key_parts-1];
47393 -+ set_if_bigger(rec_per_key, 1);
47394 -+ /*
47395 -+ Here we take into account the fact that rows are
47396 -+ accessed in sequences rec_per_key records in each.
47397 -+ Rows in such a sequence are supposed to be ordered
47398 -+ by rowid/primary key. When reading the data
47399 -+ in a sequence we'll touch not more pages than the
47400 -+ table file contains.
47401 -+ TODO. Use the formula for a disk sweep sequential access
47402 -+ to calculate the cost of accessing data rows for one
47403 -+ index entry.
47404 -+ */
47405 -+ index_scan_time= select_limit/rec_per_key *
47406 -+ min(rec_per_key, table->file->scan_time());
47407 -+ if ((ref_key < 0 && is_covering) ||
47408 -+ (ref_key < 0 && (group || table->force_index)) ||
47409 -+ index_scan_time < read_time)
47410 -+ {
47411 -+ ha_rows quick_records= table_records;
47412 -+ if ((is_best_covering && !is_covering) ||
47413 -+ (is_covering && ref_key_quick_rows < select_limit))
47414 -+ continue;
47415 -+ if (table->quick_keys.is_set(nr))
47416 -+ quick_records= table->quick_rows[nr];
47417 -+ if (best_key < 0 ||
47418 -+ (select_limit <= min(quick_records,best_records) ?
47419 -+ keyinfo->key_parts < best_key_parts :
47420 -+ quick_records < best_records))
47421 -+ {
47422 -+ best_key= nr;
47423 -+ best_key_parts= keyinfo->key_parts;
47424 -+ saved_best_key_parts= used_key_parts;
47425 -+ best_records= quick_records;
47426 -+ is_best_covering= is_covering;
47427 -+ best_key_direction= direction;
47428 -+ }
47429 -+ }
47430 -+ }
47431 -+ }
47432 -+ }
47433 -+
47434 -+ /*
47435 -+ filesort() and join cache are usually faster than reading in
47436 -+ index order and not using join cache, except in case that chosen
47437 -+ index is clustered primary key.
47438 -+ */
47439 -+ if ((select_limit >= table_records) &&
47440 -+ (tab->type == JT_ALL &&
47441 -+ tab->join->tables > tab->join->const_tables + 1) &&
47442 -+ ((unsigned) best_key != table->s->primary_key ||
47443 -+ !table->file->primary_key_is_clustered()))
47444 -+ goto use_filesort;
47445 -+
47446 -+ if (best_key >= 0)
47447 -+ {
47448 -+ if (table->quick_keys.is_set(best_key) && best_key != ref_key)
47449 -+ {
47450 -+ key_map map;
47451 -+ map.clear_all(); // Force the creation of quick select
47452 -+ map.set_bit(best_key); // only best_key.
47453 -+ select->quick= 0;
47454 -+ select->test_quick_select(join->thd, map, 0,
47455 -+ join->select_options & OPTION_FOUND_ROWS ?
47456 -+ HA_POS_ERROR :
47457 -+ join->unit->select_limit_cnt,
47458 -+ 0);
47459 -+ }
47460 -+ order_direction= best_key_direction;
47461 -+ /*
47462 -+ saved_best_key_parts is actual number of used keyparts found by the
47463 -+ test_if_order_by_key function. It could differ from keyinfo->key_parts,
47464 -+ thus we have to restore it in case of desc order as it affects
47465 -+ QUICK_SELECT_DESC behaviour.
47466 -+ */
47467 -+ used_key_parts= (order_direction == -1) ?
47468 -+ saved_best_key_parts : best_key_parts;
47469 -+ }
47470 -+ else
47471 -+ goto use_filesort;
47472 -+ }
47473 -+
47474 -+check_reverse_order:
47475 -+ DBUG_ASSERT(order_direction != 0);
47476 -+
47477 -+ if (order_direction == -1) // If ORDER BY ... DESC
47478 -+ {
47479 -+ if (select && select->quick)
47480 -+ {
47481 -+ /*
47482 -+ Don't reverse the sort order, if it's already done.
47483 -+ (In some cases test_if_order_by_key() can be called multiple times
47484 -+ */
47485 -+ if (select->quick->reverse_sorted())
47486 -+ goto skipped_filesort;
47487 -+ else
47488 -+ {
47489 -+ int quick_type= select->quick->get_type();
47490 -+ if (quick_type == QUICK_SELECT_I::QS_TYPE_INDEX_MERGE ||
47491 -+ quick_type == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT ||
47492 -+ quick_type == QUICK_SELECT_I::QS_TYPE_ROR_UNION ||
47493 -+ quick_type == QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX)
47494 -+ {
47495 -+ tab->limit= 0;
47496 -+ goto use_filesort; // Use filesort
47497 -+ }
47498 -+ }
47499 -+ }
47500 -+ }
47501 -+
47502 -+ /*
47503 -+ Update query plan with access pattern for doing
47504 -+ ordered access according to what we have decided
47505 -+ above.
47506 -+ */
47507 -+ if (!no_changes) // We are allowed to update QEP
47508 -+ {
47509 -+ if (best_key >= 0)
47510 -+ {
47511 -+ bool quick_created=
47512 -+ (select && select->quick && select->quick!=save_quick);
47513 -+
47514 -+ /*
47515 -+ If ref_key used index tree reading only ('Using index' in EXPLAIN),
47516 -+ and best_key doesn't, then revert the decision.
47517 -+ */
47518 -+ if (!table->covering_keys.is_set(best_key))
47519 -+ table->set_keyread(FALSE);
47520 -+ if (!quick_created)
47521 -+ {
47522 -+ if (select) // Throw any existing quick select
47523 -+ select->quick= 0; // Cleanup either reset to save_quick,
47524 -+ // or 'delete save_quick'
47525 -+ tab->index= best_key;
47526 -+ tab->read_first_record= order_direction > 0 ?
47527 -+ join_read_first:join_read_last;
47528 -+ tab->type=JT_NEXT; // Read with index_first(), index_next()
47529 -+
47530 -+ if (table->covering_keys.is_set(best_key))
47531 -+ table->set_keyread(TRUE);
47532 -+ table->file->ha_index_or_rnd_end();
47533 -+ if (tab->join->select_options & SELECT_DESCRIBE)
47534 -+ {
47535 -+ tab->ref.key= -1;
47536 -+ tab->ref.key_parts= 0;
47537 -+ if (select_limit < table->file->stats.records)
47538 -+ tab->limit= select_limit;
47539 -+ }
47540 -+ }
47541 -+ else if (tab->type != JT_ALL)
47542 -+ {
47543 -+ /*
47544 -+ We're about to use a quick access to the table.
47545 -+ We need to change the access method so as the quick access
47546 -+ method is actually used.
47547 -+ */
47548 -+ DBUG_ASSERT(tab->select->quick);
47549 -+ tab->type=JT_ALL;
47550 -+ tab->use_quick=1;
47551 -+ tab->ref.key= -1;
47552 -+ tab->ref.key_parts=0; // Don't use ref key.
47553 -+ tab->read_first_record= join_init_read_record;
47554 -+ if (tab->is_using_loose_index_scan())
47555 -+ tab->join->tmp_table_param.precomputed_group_by= TRUE;
47556 -+ /*
47557 -+ TODO: update the number of records in join->best_positions[tablenr]
47558 -+ */
47559 -+ }
47560 -+ } // best_key >= 0
47561 -+
47562 -+ if (order_direction == -1) // If ORDER BY ... DESC
47563 -+ {
47564 -+ if (select && select->quick)
47565 -+ {
47566 -+ QUICK_SELECT_DESC *tmp;
47567 -+ /* ORDER BY range_key DESC */
47568 -+ tmp= new QUICK_SELECT_DESC((QUICK_RANGE_SELECT*)(select->quick),
47569 -+ used_key_parts);
47570 -+ if (tmp && select->quick == save_quick)
47571 -+ save_quick= 0; // ::QUICK_SELECT_DESC consumed it
47572 -+
47573 -+ if (!tmp || tmp->error)
47574 -+ {
47575 -+ delete tmp;
47576 -+ tab->limit= 0;
47577 -+ goto use_filesort; // Reverse sort failed -> filesort
47578 -+ }
47579 -+ select->quick= tmp;
47580 -+ }
47581 -+ else if (tab->type != JT_NEXT && tab->type != JT_REF_OR_NULL &&
47582 -+ tab->ref.key >= 0 && tab->ref.key_parts <= used_key_parts)
47583 -+ {
47584 -+ /*
47585 -+ SELECT * FROM t1 WHERE a=1 ORDER BY a DESC,b DESC
47586 -+
47587 -+ Use a traversal function that starts by reading the last row
47588 -+ with key part (A) and then traverse the index backwards.
47589 -+ */
47590 -+ tab->read_first_record= join_read_last_key;
47591 -+ tab->read_record.read_record= join_read_prev_same;
47592 -+ }
47593 -+ }
47594 -+ else if (select && select->quick)
47595 -+ select->quick->sorted= 1;
47596 -+
47597 -+ } // QEP has been modified
47598 -+
47599 -+ /*
47600 -+ Cleanup:
47601 -+ We may have both a 'select->quick' and 'save_quick' (original)
47602 -+ at this point. Delete the one that we wan't use.
47603 -+ */
47604 -+
47605 -+skipped_filesort:
47606 -+ // Keep current (ordered) select->quick
47607 -+ if (select && save_quick != select->quick)
47608 -+ {
47609 -+ delete save_quick;
47610 -+ save_quick= NULL;
47611 -+ }
47612 -+ DBUG_RETURN(1);
47613 -+
47614 -+use_filesort:
47615 -+ // Restore original save_quick
47616 -+ if (select && select->quick != save_quick)
47617 -+ {
47618 -+ delete select->quick;
47619 -+ select->quick= save_quick;
47620 -+ }
47621 -+ DBUG_RETURN(0);
47622 -+}
47623 -+
47624 -+
47625 -+/*
47626 -+ If not selecting by given key, create an index how records should be read
47627 -+
47628 -+ SYNOPSIS
47629 -+ create_sort_index()
47630 -+ thd Thread handler
47631 -+ tab Table to sort (in join structure)
47632 -+ order How table should be sorted
47633 -+ filesort_limit Max number of rows that needs to be sorted
47634 -+ select_limit Max number of rows in final output
47635 -+ Used to decide if we should use index or not
47636 -+ is_order_by true if we are sorting on ORDER BY, false if GROUP BY
47637 -+ Used to decide if we should use index or not
47638 -+
47639 -+
47640 -+ IMPLEMENTATION
47641 -+ - If there is an index that can be used, 'tab' is modified to use
47642 -+ this index.
47643 -+ - If no index, create with filesort() an index file that can be used to
47644 -+ retrieve rows in order (should be done with 'read_record').
47645 -+ The sorted data is stored in tab->table and will be freed when calling
47646 -+ free_io_cache(tab->table).
47647 -+
47648 -+ RETURN VALUES
47649 -+ 0 ok
47650 -+ -1 Some fatal error
47651 -+ 1 No records
47652 -+*/
47653 -+
47654 -+static int
47655 -+create_sort_index(THD *thd, JOIN *join, ORDER *order,
47656 -+ ha_rows filesort_limit, ha_rows select_limit,
47657 -+ bool is_order_by)
47658 -+{
47659 -+ uint length= 0;
47660 -+ ha_rows examined_rows;
47661 -+ TABLE *table;
47662 -+ SQL_SELECT *select;
47663 -+ JOIN_TAB *tab;
47664 -+ DBUG_ENTER("create_sort_index");
47665 -+
47666 -+ if (join->tables == join->const_tables)
47667 -+ DBUG_RETURN(0); // One row, no need to sort
47668 -+ tab= join->join_tab + join->const_tables;
47669 -+ table= tab->table;
47670 -+ select= tab->select;
47671 -+
47672 -+ /*
47673 -+ When there is SQL_BIG_RESULT do not sort using index for GROUP BY,
47674 -+ and thus force sorting on disk unless a group min-max optimization
47675 -+ is going to be used as it is applied now only for one table queries
47676 -+ with covering indexes.
47677 -+ */
47678 -+ if ((order != join->group_list ||
47679 -+ !(join->select_options & SELECT_BIG_RESULT) ||
47680 -+ (select && select->quick &&
47681 -+ select->quick->get_type() == QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX)) &&
47682 -+ test_if_skip_sort_order(tab,order,select_limit,0,
47683 -+ is_order_by ? &table->keys_in_use_for_order_by :
47684 -+ &table->keys_in_use_for_group_by))
47685 -+ DBUG_RETURN(0);
47686 -+ for (ORDER *ord= join->order; ord; ord= ord->next)
47687 -+ length++;
47688 -+ if (!(join->sortorder=
47689 -+ make_unireg_sortorder(order, &length, join->sortorder)))
47690 -+ goto err; /* purecov: inspected */
47691 -+
47692 -+ table->sort.io_cache=(IO_CACHE*) my_malloc(sizeof(IO_CACHE),
47693 -+ MYF(MY_WME | MY_ZEROFILL));
47694 -+ table->status=0; // May be wrong if quick_select
47695 -+
47696 -+ // If table has a range, move it to select
47697 -+ if (select && !select->quick && tab->ref.key >= 0)
47698 -+ {
47699 -+ if (tab->quick)
47700 -+ {
47701 -+ select->quick=tab->quick;
47702 -+ tab->quick=0;
47703 -+ /*
47704 -+ We can only use 'Only index' if quick key is same as ref_key
47705 -+ and in index_merge 'Only index' cannot be used
47706 -+ */
47707 -+ if (((uint) tab->ref.key != select->quick->index))
47708 -+ table->set_keyread(FALSE);
47709 -+ }
47710 -+ else
47711 -+ {
47712 -+ /*
47713 -+ We have a ref on a const; Change this to a range that filesort
47714 -+ can use.
47715 -+ For impossible ranges (like when doing a lookup on NULL on a NOT NULL
47716 -+ field, quick will contain an empty record set.
47717 -+ */
47718 -+ if (!(select->quick= (tab->type == JT_FT ?
47719 -+ new FT_SELECT(thd, table, tab->ref.key) :
47720 -+ get_quick_select_for_ref(thd, table, &tab->ref,
47721 -+ tab->found_records))))
47722 -+ goto err;
47723 -+ }
47724 -+ }
47725 -+
47726 -+ /* Fill schema tables with data before filesort if it's necessary */
47727 -+ if ((join->select_lex->options & OPTION_SCHEMA_TABLE) &&
47728 -+ get_schema_tables_result(join, PROCESSED_BY_CREATE_SORT_INDEX))
47729 -+ goto err;
47730 -+
47731 -+ if (table->s->tmp_table)
47732 -+ table->file->info(HA_STATUS_VARIABLE); // Get record count
47733 -+ table->sort.found_records=filesort(thd, table,join->sortorder, length,
47734 -+ select, filesort_limit, 0,
47735 -+ &examined_rows);
47736 -+ tab->records= table->sort.found_records; // For SQL_CALC_ROWS
47737 -+ if (select)
47738 -+ {
47739 -+ /*
47740 -+ We need to preserve tablesort's output resultset here, because
47741 -+ QUICK_INDEX_MERGE_SELECT::~QUICK_INDEX_MERGE_SELECT (called by
47742 -+ SQL_SELECT::cleanup()) may free it assuming it's the result of the quick
47743 -+ select operation that we no longer need. Note that all the other parts of
47744 -+ this data structure are cleaned up when
47745 -+ QUICK_INDEX_MERGE_SELECT::get_next encounters end of data, so the next
47746 -+ SQL_SELECT::cleanup() call changes sort.io_cache alone.
47747 -+ */
47748 -+ IO_CACHE *tablesort_result_cache;
47749 -+
47750 -+ tablesort_result_cache= table->sort.io_cache;
47751 -+ table->sort.io_cache= NULL;
47752 -+
47753 -+ select->cleanup(); // filesort did select
47754 -+ tab->select= 0;
47755 -+ table->quick_keys.clear_all(); // as far as we cleanup select->quick
47756 -+ table->sort.io_cache= tablesort_result_cache;
47757 -+ }
47758 -+ tab->select_cond=0;
47759 -+ tab->last_inner= 0;
47760 -+ tab->first_unmatched= 0;
47761 -+ tab->type=JT_ALL; // Read with normal read_record
47762 -+ tab->read_first_record= join_init_read_record;
47763 -+ tab->join->examined_rows+=examined_rows;
47764 -+ table->set_keyread(FALSE); // Restore if we used indexes
47765 -+ DBUG_RETURN(table->sort.found_records == HA_POS_ERROR);
47766 -+err:
47767 -+ DBUG_RETURN(-1);
47768 -+}
47769 -+
47770 -+#ifdef NOT_YET
47771 -+/**
47772 -+ Add the HAVING criteria to table->select.
47773 -+*/
47774 -+
47775 -+static bool fix_having(JOIN *join, Item **having)
47776 -+{
47777 -+ (*having)->update_used_tables(); // Some tables may have been const
47778 -+ JOIN_TAB *table=&join->join_tab[join->const_tables];
47779 -+ table_map used_tables= join->const_table_map | table->table->map;
47780 -+
47781 -+ DBUG_EXECUTE("where",print_where(*having,"having", QT_ORDINARY););
47782 -+ Item* sort_table_cond=make_cond_for_table(*having,used_tables,used_tables);
47783 -+ if (sort_table_cond)
47784 -+ {
47785 -+ if (!table->select)
47786 -+ if (!(table->select=new SQL_SELECT))
47787 -+ return 1;
47788 -+ if (!table->select->cond)
47789 -+ table->select->cond=sort_table_cond;
47790 -+ else // This should never happen
47791 -+ if (!(table->select->cond= new Item_cond_and(table->select->cond,
47792 -+ sort_table_cond)) ||
47793 -+ table->select->cond->fix_fields(join->thd, &table->select->cond))
47794 -+ return 1;
47795 -+ table->select_cond=table->select->cond;
47796 -+ table->select_cond->top_level_item();
47797 -+ DBUG_EXECUTE("where",print_where(table->select_cond,
47798 -+ "select and having",
47799 -+ QT_ORDINARY););
47800 -+ *having=make_cond_for_table(*having,~ (table_map) 0,~used_tables);
47801 -+ DBUG_EXECUTE("where",
47802 -+ print_where(*having,"having after make_cond", QT_ORDINARY););
47803 -+ }
47804 -+ return 0;
47805 -+}
47806 -+#endif
47807 -+
47808 -+
47809 -+/*****************************************************************************
47810 -+ Remove duplicates from tmp table
47811 -+ This should be recoded to add a unique index to the table and remove
47812 -+ duplicates
47813 -+ Table is a locked single thread table
47814 -+ fields is the number of fields to check (from the end)
47815 -+*****************************************************************************/
47816 -+
47817 -+static bool compare_record(TABLE *table, Field **ptr)
47818 -+{
47819 -+ for (; *ptr ; ptr++)
47820 -+ {
47821 -+ if ((*ptr)->cmp_offset(table->s->rec_buff_length))
47822 -+ return 1;
47823 -+ }
47824 -+ return 0;
47825 -+}
47826 -+
47827 -+static bool copy_blobs(Field **ptr)
47828 -+{
47829 -+ for (; *ptr ; ptr++)
47830 -+ {
47831 -+ if ((*ptr)->flags & BLOB_FLAG)
47832 -+ if (((Field_blob *) (*ptr))->copy())
47833 -+ return 1; // Error
47834 -+ }
47835 -+ return 0;
47836 -+}
47837 -+
47838 -+static void free_blobs(Field **ptr)
47839 -+{
47840 -+ for (; *ptr ; ptr++)
47841 -+ {
47842 -+ if ((*ptr)->flags & BLOB_FLAG)
47843 -+ ((Field_blob *) (*ptr))->free();
47844 -+ }
47845 -+}
47846 -+
47847 -+
47848 -+static int
47849 -+remove_duplicates(JOIN *join, TABLE *entry,List<Item> &fields, Item *having)
47850 -+{
47851 -+ int error;
47852 -+ ulong reclength,offset;
47853 -+ uint field_count;
47854 -+ THD *thd= join->thd;
47855 -+ DBUG_ENTER("remove_duplicates");
47856 -+
47857 -+ entry->reginfo.lock_type=TL_WRITE;
47858 -+
47859 -+ /* Calculate how many saved fields there is in list */
47860 -+ field_count=0;
47861 -+ List_iterator<Item> it(fields);
47862 -+ Item *item;
47863 -+ while ((item=it++))
47864 -+ {
47865 -+ if (item->get_tmp_table_field() && ! item->const_item())
47866 -+ field_count++;
47867 -+ }
47868 -+
47869 -+ if (!field_count && !(join->select_options & OPTION_FOUND_ROWS) && !having)
47870 -+ { // only const items with no OPTION_FOUND_ROWS
47871 -+ join->unit->select_limit_cnt= 1; // Only send first row
47872 -+ DBUG_RETURN(0);
47873 -+ }
47874 -+ Field **first_field=entry->field+entry->s->fields - field_count;
47875 -+ offset= (field_count ?
47876 -+ entry->field[entry->s->fields - field_count]->
47877 -+ offset(entry->record[0]) : 0);
47878 -+ reclength=entry->s->reclength-offset;
47879 -+
47880 -+ free_io_cache(entry); // Safety
47881 -+ entry->file->info(HA_STATUS_VARIABLE);
47882 -+ if (entry->s->db_type() == heap_hton ||
47883 -+ (!entry->s->blob_fields &&
47884 -+ ((ALIGN_SIZE(reclength) + HASH_OVERHEAD) * entry->file->stats.records <
47885 -+ thd->variables.sortbuff_size)))
47886 -+ error=remove_dup_with_hash_index(join->thd, entry,
47887 -+ field_count, first_field,
47888 -+ reclength, having);
47889 -+ else
47890 -+ error=remove_dup_with_compare(join->thd, entry, first_field, offset,
47891 -+ having);
47892 -+
47893 -+ free_blobs(first_field);
47894 -+ DBUG_RETURN(error);
47895 -+}
47896 -+
47897 -+
47898 -+static int remove_dup_with_compare(THD *thd, TABLE *table, Field **first_field,
47899 -+ ulong offset, Item *having)
47900 -+{
47901 -+ handler *file=table->file;
47902 -+ char *org_record,*new_record;
47903 -+ uchar *record;
47904 -+ int error;
47905 -+ ulong reclength= table->s->reclength-offset;
47906 -+ DBUG_ENTER("remove_dup_with_compare");
47907 -+
47908 -+ org_record=(char*) (record=table->record[0])+offset;
47909 -+ new_record=(char*) table->record[1]+offset;
47910 -+
47911 -+ file->ha_rnd_init(1);
47912 -+ error=file->rnd_next(record);
47913 -+ for (;;)
47914 -+ {
47915 -+ if (thd->killed)
47916 -+ {
47917 -+ thd->send_kill_message();
47918 -+ error=0;
47919 -+ goto err;
47920 -+ }
47921 -+ if (error)
47922 -+ {
47923 -+ if (error == HA_ERR_RECORD_DELETED)
47924 -+ {
47925 -+ error= file->rnd_next(record);
47926 -+ continue;
47927 -+ }
47928 -+ if (error == HA_ERR_END_OF_FILE)
47929 -+ break;
47930 -+ goto err;
47931 -+ }
47932 -+ if (having && !having->val_int())
47933 -+ {
47934 -+ if ((error=file->ha_delete_row(record)))
47935 -+ goto err;
47936 -+ error=file->rnd_next(record);
47937 -+ continue;
47938 -+ }
47939 -+ if (copy_blobs(first_field))
47940 -+ {
47941 -+ my_message(ER_OUTOFMEMORY, ER(ER_OUTOFMEMORY), MYF(0));
47942 -+ error=0;
47943 -+ goto err;
47944 -+ }
47945 -+ memcpy(new_record,org_record,reclength);
47946 -+
47947 -+ /* Read through rest of file and mark duplicated rows deleted */
47948 -+ bool found=0;
47949 -+ for (;;)
47950 -+ {
47951 -+ if ((error=file->rnd_next(record)))
47952 -+ {
47953 -+ if (error == HA_ERR_RECORD_DELETED)
47954 -+ continue;
47955 -+ if (error == HA_ERR_END_OF_FILE)
47956 -+ break;
47957 -+ goto err;
47958 -+ }
47959 -+ if (compare_record(table, first_field) == 0)
47960 -+ {
47961 -+ if ((error=file->ha_delete_row(record)))
47962 -+ goto err;
47963 -+ }
47964 -+ else if (!found)
47965 -+ {
47966 -+ found=1;
47967 -+ file->position(record); // Remember position
47968 -+ }
47969 -+ }
47970 -+ if (!found)
47971 -+ break; // End of file
47972 -+ /* Restart search on next row */
47973 -+ error=file->restart_rnd_next(record,file->ref);
47974 -+ }
47975 -+
47976 -+ file->extra(HA_EXTRA_NO_CACHE);
47977 -+ DBUG_RETURN(0);
47978 -+err:
47979 -+ file->extra(HA_EXTRA_NO_CACHE);
47980 -+ if (error)
47981 -+ file->print_error(error,MYF(0));
47982 -+ DBUG_RETURN(1);
47983 -+}
47984 -+
47985 -+
47986 -+/**
47987 -+ Generate a hash index for each row to quickly find duplicate rows.
47988 -+
47989 -+ @note
47990 -+ Note that this will not work on tables with blobs!
47991 -+*/
47992 -+
47993 -+static int remove_dup_with_hash_index(THD *thd, TABLE *table,
47994 -+ uint field_count,
47995 -+ Field **first_field,
47996 -+ ulong key_length,
47997 -+ Item *having)
47998 -+{
47999 -+ uchar *key_buffer, *key_pos, *record=table->record[0];
48000 -+ int error;
48001 -+ handler *file= table->file;
48002 -+ ulong extra_length= ALIGN_SIZE(key_length)-key_length;
48003 -+ uint *field_lengths,*field_length;
48004 -+ HASH hash;
48005 -+ DBUG_ENTER("remove_dup_with_hash_index");
48006 -+
48007 -+ if (!my_multi_malloc(MYF(MY_WME),
48008 -+ &key_buffer,
48009 -+ (uint) ((key_length + extra_length) *
48010 -+ (long) file->stats.records),
48011 -+ &field_lengths,
48012 -+ (uint) (field_count*sizeof(*field_lengths)),
48013 -+ NullS))
48014 -+ DBUG_RETURN(1);
48015 -+
48016 -+ {
48017 -+ Field **ptr;
48018 -+ ulong total_length= 0;
48019 -+ for (ptr= first_field, field_length=field_lengths ; *ptr ; ptr++)
48020 -+ {
48021 -+ uint length= (*ptr)->sort_length();
48022 -+ (*field_length++)= length;
48023 -+ total_length+= length;
48024 -+ }
48025 -+ DBUG_PRINT("info",("field_count: %u key_length: %lu total_length: %lu",
48026 -+ field_count, key_length, total_length));
48027 -+ DBUG_ASSERT(total_length <= key_length);
48028 -+ key_length= total_length;
48029 -+ extra_length= ALIGN_SIZE(key_length)-key_length;
48030 -+ }
48031 -+
48032 -+ if (hash_init(&hash, &my_charset_bin, (uint) file->stats.records, 0,
48033 -+ key_length, (hash_get_key) 0, 0, 0))
48034 -+ {
48035 -+ my_free((char*) key_buffer,MYF(0));
48036 -+ DBUG_RETURN(1);
48037 -+ }
48038 -+
48039 -+ file->ha_rnd_init(1);
48040 -+ key_pos=key_buffer;
48041 -+ for (;;)
48042 -+ {
48043 -+ uchar *org_key_pos;
48044 -+ if (thd->killed)
48045 -+ {
48046 -+ thd->send_kill_message();
48047 -+ error=0;
48048 -+ goto err;
48049 -+ }
48050 -+ if ((error=file->rnd_next(record)))
48051 -+ {
48052 -+ if (error == HA_ERR_RECORD_DELETED)
48053 -+ continue;
48054 -+ if (error == HA_ERR_END_OF_FILE)
48055 -+ break;
48056 -+ goto err;
48057 -+ }
48058 -+ if (having && !having->val_int())
48059 -+ {
48060 -+ if ((error=file->ha_delete_row(record)))
48061 -+ goto err;
48062 -+ continue;
48063 -+ }
48064 -+
48065 -+ /* copy fields to key buffer */
48066 -+ org_key_pos= key_pos;
48067 -+ field_length=field_lengths;
48068 -+ for (Field **ptr= first_field ; *ptr ; ptr++)
48069 -+ {
48070 -+ (*ptr)->sort_string(key_pos,*field_length);
48071 -+ key_pos+= *field_length++;
48072 -+ }
48073 -+ /* Check if it exists before */
48074 -+ if (hash_search(&hash, org_key_pos, key_length))
48075 -+ {
48076 -+ /* Duplicated found ; Remove the row */
48077 -+ if ((error=file->ha_delete_row(record)))
48078 -+ goto err;
48079 -+ }
48080 -+ else
48081 -+ {
48082 -+ if (my_hash_insert(&hash, org_key_pos))
48083 -+ goto err;
48084 -+ }
48085 -+ key_pos+=extra_length;
48086 -+ }
48087 -+ my_free((char*) key_buffer,MYF(0));
48088 -+ hash_free(&hash);
48089 -+ file->extra(HA_EXTRA_NO_CACHE);
48090 -+ (void) file->ha_rnd_end();
48091 -+ DBUG_RETURN(0);
48092 -+
48093 -+err:
48094 -+ my_free((char*) key_buffer,MYF(0));
48095 -+ hash_free(&hash);
48096 -+ file->extra(HA_EXTRA_NO_CACHE);
48097 -+ (void) file->ha_rnd_end();
48098 -+ if (error)
48099 -+ file->print_error(error,MYF(0));
48100 -+ DBUG_RETURN(1);
48101 -+}
48102 -+
48103 -+
48104 -+SORT_FIELD *make_unireg_sortorder(ORDER *order, uint *length,
48105 -+ SORT_FIELD *sortorder)
48106 -+{
48107 -+ uint count;
48108 -+ SORT_FIELD *sort,*pos;
48109 -+ DBUG_ENTER("make_unireg_sortorder");
48110 -+
48111 -+ count=0;
48112 -+ for (ORDER *tmp = order; tmp; tmp=tmp->next)
48113 -+ count++;
48114 -+ if (!sortorder)
48115 -+ sortorder= (SORT_FIELD*) sql_alloc(sizeof(SORT_FIELD) *
48116 -+ (max(count, *length) + 1));
48117 -+ pos= sort= sortorder;
48118 -+
48119 -+ if (!pos)
48120 -+ return 0;
48121 -+
48122 -+ for (;order;order=order->next,pos++)
48123 -+ {
48124 -+ Item *item= order->item[0]->real_item();
48125 -+ pos->field= 0; pos->item= 0;
48126 -+ if (item->type() == Item::FIELD_ITEM)
48127 -+ pos->field= ((Item_field*) item)->field;
48128 -+ else if (item->type() == Item::SUM_FUNC_ITEM && !item->const_item())
48129 -+ pos->field= ((Item_sum*) item)->get_tmp_table_field();
48130 -+ else if (item->type() == Item::COPY_STR_ITEM)
48131 -+ { // Blob patch
48132 -+ pos->item= ((Item_copy*) item)->get_item();
48133 -+ }
48134 -+ else
48135 -+ pos->item= *order->item;
48136 -+ pos->reverse=! order->asc;
48137 -+ }
48138 -+ *length=count;
48139 -+ DBUG_RETURN(sort);
48140 -+}
48141 -+
48142 -+
48143 -+/*****************************************************************************
48144 -+ Fill join cache with packed records
48145 -+ Records are stored in tab->cache.buffer and last record in
48146 -+ last record is stored with pointers to blobs to support very big
48147 -+ records
48148 -+******************************************************************************/
48149 -+
48150 -+static int
48151 -+join_init_cache(THD *thd,JOIN_TAB *tables,uint table_count)
48152 -+{
48153 -+ reg1 uint i;
48154 -+ uint length, blobs;
48155 -+ size_t size;
48156 -+ CACHE_FIELD *copy,**blob_ptr;
48157 -+ JOIN_CACHE *cache;
48158 -+ JOIN_TAB *join_tab;
48159 -+ DBUG_ENTER("join_init_cache");
48160 -+
48161 -+ cache= &tables[table_count].cache;
48162 -+ cache->fields=blobs=0;
48163 -+
48164 -+ join_tab=tables;
48165 -+ for (i=0 ; i < table_count ; i++,join_tab++)
48166 -+ {
48167 -+ if (!join_tab->used_fieldlength) /* Not calced yet */
48168 -+ calc_used_field_length(thd, join_tab);
48169 -+ cache->fields+=join_tab->used_fields;
48170 -+ blobs+=join_tab->used_blobs;
48171 -+ }
48172 -+ if (!(cache->field=(CACHE_FIELD*)
48173 -+ sql_alloc(sizeof(CACHE_FIELD)*(cache->fields+table_count*2)+(blobs+1)*
48174 -+
48175 -+ sizeof(CACHE_FIELD*))))
48176 -+ {
48177 -+ my_free((uchar*) cache->buff,MYF(0)); /* purecov: inspected */
48178 -+ cache->buff=0; /* purecov: inspected */
48179 -+ DBUG_RETURN(1); /* purecov: inspected */
48180 -+ }
48181 -+ copy=cache->field;
48182 -+ blob_ptr=cache->blob_ptr=(CACHE_FIELD**)
48183 -+ (cache->field+cache->fields+table_count*2);
48184 -+
48185 -+ length=0;
48186 -+ for (i=0 ; i < table_count ; i++)
48187 -+ {
48188 -+ bool have_bit_fields= FALSE;
48189 -+ uint null_fields=0,used_fields;
48190 -+ Field **f_ptr,*field;
48191 -+ MY_BITMAP *read_set= tables[i].table->read_set;
48192 -+ for (f_ptr=tables[i].table->field,used_fields=tables[i].used_fields ;
48193 -+ used_fields ;
48194 -+ f_ptr++)
48195 -+ {
48196 -+ field= *f_ptr;
48197 -+ if (bitmap_is_set(read_set, field->field_index))
48198 -+ {
48199 -+ used_fields--;
48200 -+ length+=field->fill_cache_field(copy);
48201 -+ if (copy->type == CACHE_BLOB)
48202 -+ (*blob_ptr++)=copy;
48203 -+ if (field->real_maybe_null())
48204 -+ null_fields++;
48205 -+ if (field->type() == MYSQL_TYPE_BIT &&
48206 -+ ((Field_bit*)field)->bit_len)
48207 -+ have_bit_fields= TRUE;
48208 -+ copy++;
48209 -+ }
48210 -+ }
48211 -+ /* Copy null bits from table */
48212 -+ if (null_fields || have_bit_fields)
48213 -+ { /* must copy null bits */
48214 -+ copy->str= tables[i].table->null_flags;
48215 -+ copy->length= tables[i].table->s->null_bytes;
48216 -+ copy->type=0;
48217 -+ copy->field=0;
48218 -+ length+=copy->length;
48219 -+ copy++;
48220 -+ cache->fields++;
48221 -+ }
48222 -+ /* If outer join table, copy null_row flag */
48223 -+ if (tables[i].table->maybe_null)
48224 -+ {
48225 -+ copy->str= (uchar*) &tables[i].table->null_row;
48226 -+ copy->length=sizeof(tables[i].table->null_row);
48227 -+ copy->type=0;
48228 -+ copy->field=0;
48229 -+ length+=copy->length;
48230 -+ copy++;
48231 -+ cache->fields++;
48232 -+ }
48233 -+ }
48234 -+
48235 -+ cache->length=length+blobs*sizeof(char*);
48236 -+ cache->blobs=blobs;
48237 -+ *blob_ptr=0; /* End sequentel */
48238 -+ size=max(thd->variables.join_buff_size, cache->length);
48239 -+ if (!(cache->buff=(uchar*) my_malloc(size,MYF(0))))
48240 -+ DBUG_RETURN(1); /* Don't use cache */ /* purecov: inspected */
48241 -+ cache->end=cache->buff+size;
48242 -+ reset_cache_write(cache);
48243 -+ DBUG_RETURN(0);
48244 -+}
48245 -+
48246 -+
48247 -+static ulong
48248 -+used_blob_length(CACHE_FIELD **ptr)
48249 -+{
48250 -+ uint length,blob_length;
48251 -+ for (length=0 ; *ptr ; ptr++)
48252 -+ {
48253 -+ Field_blob *field_blob= (Field_blob *) (*ptr)->field;
48254 -+ (*ptr)->blob_length=blob_length= field_blob->get_length();
48255 -+ length+=blob_length;
48256 -+ field_blob->get_ptr(&(*ptr)->str);
48257 -+ }
48258 -+ return length;
48259 -+}
48260 -+
48261 -+
48262 -+static bool
48263 -+store_record_in_cache(JOIN_CACHE *cache)
48264 -+{
48265 -+ uint length;
48266 -+ uchar *pos;
48267 -+ CACHE_FIELD *copy,*end_field;
48268 -+ bool last_record;
48269 -+
48270 -+ pos=cache->pos;
48271 -+ end_field=cache->field+cache->fields;
48272 -+
48273 -+ length=cache->length;
48274 -+ if (cache->blobs)
48275 -+ length+=used_blob_length(cache->blob_ptr);
48276 -+ if ((last_record= (length + cache->length > (size_t) (cache->end - pos))))
48277 -+ cache->ptr_record=cache->records;
48278 -+
48279 -+ /*
48280 -+ There is room in cache. Put record there
48281 -+ */
48282 -+ cache->records++;
48283 -+ for (copy=cache->field ; copy < end_field; copy++)
48284 -+ {
48285 -+ if (copy->type == CACHE_BLOB)
48286 -+ {
48287 -+ Field_blob *blob_field= (Field_blob *) copy->field;
48288 -+ if (last_record)
48289 -+ {
48290 -+ blob_field->get_image(pos, copy->length+sizeof(char*),
48291 -+ blob_field->charset());
48292 -+ pos+=copy->length+sizeof(char*);
48293 -+ }
48294 -+ else
48295 -+ {
48296 -+ blob_field->get_image(pos, copy->length, // blob length
48297 -+ blob_field->charset());
48298 -+ memcpy(pos+copy->length,copy->str,copy->blob_length); // Blob data
48299 -+ pos+=copy->length+copy->blob_length;
48300 -+ }
48301 -+ }
48302 -+ else
48303 -+ {
48304 -+ if (copy->type == CACHE_STRIPPED)
48305 -+ {
48306 -+ uchar *str,*end;
48307 -+ Field *field= copy->field;
48308 -+ if (field && field->maybe_null() && field->is_null())
48309 -+ end= str= copy->str;
48310 -+ else
48311 -+ for (str=copy->str,end= str+copy->length;
48312 -+ end > str && end[-1] == ' ' ;
48313 -+ end--) ;
48314 -+ length=(uint) (end-str);
48315 -+ memcpy(pos+2, str, length);
48316 -+ int2store(pos, length);
48317 -+ pos+= length+2;
48318 -+ }
48319 -+ else
48320 -+ {
48321 -+ memcpy(pos,copy->str,copy->length);
48322 -+ pos+=copy->length;
48323 -+ }
48324 -+ }
48325 -+ }
48326 -+ cache->pos=pos;
48327 -+ return last_record || (size_t) (cache->end - pos) < cache->length;
48328 -+}
48329 -+
48330 -+
48331 -+static void
48332 -+reset_cache_read(JOIN_CACHE *cache)
48333 -+{
48334 -+ cache->record_nr=0;
48335 -+ cache->pos=cache->buff;
48336 -+}
48337 -+
48338 -+
48339 -+static void reset_cache_write(JOIN_CACHE *cache)
48340 -+{
48341 -+ reset_cache_read(cache);
48342 -+ cache->records= 0;
48343 -+ cache->ptr_record= (uint) ~0;
48344 -+}
48345 -+
48346 -+
48347 -+static void
48348 -+read_cached_record(JOIN_TAB *tab)
48349 -+{
48350 -+ uchar *pos;
48351 -+ uint length;
48352 -+ bool last_record;
48353 -+ CACHE_FIELD *copy,*end_field;
48354 -+
48355 -+ last_record=tab->cache.record_nr++ == tab->cache.ptr_record;
48356 -+ pos=tab->cache.pos;
48357 -+
48358 -+ for (copy=tab->cache.field,end_field=copy+tab->cache.fields ;
48359 -+ copy < end_field;
48360 -+ copy++)
48361 -+ {
48362 -+ if (copy->type == CACHE_BLOB)
48363 -+ {
48364 -+ Field_blob *blob_field= (Field_blob *) copy->field;
48365 -+ if (last_record)
48366 -+ {
48367 -+ blob_field->set_image(pos, copy->length+sizeof(char*),
48368 -+ blob_field->charset());
48369 -+ pos+=copy->length+sizeof(char*);
48370 -+ }
48371 -+ else
48372 -+ {
48373 -+ blob_field->set_ptr(pos, pos+copy->length);
48374 -+ pos+=copy->length + blob_field->get_length();
48375 -+ }
48376 -+ }
48377 -+ else
48378 -+ {
48379 -+ if (copy->type == CACHE_STRIPPED)
48380 -+ {
48381 -+ length= uint2korr(pos);
48382 -+ memcpy(copy->str, pos+2, length);
48383 -+ memset(copy->str+length, ' ', copy->length-length);
48384 -+ pos+= 2 + length;
48385 -+ }
48386 -+ else
48387 -+ {
48388 -+ memcpy(copy->str,pos,copy->length);
48389 -+ pos+=copy->length;
48390 -+ }
48391 -+ }
48392 -+ }
48393 -+ tab->cache.pos=pos;
48394 -+ return;
48395 -+}
48396 -+
48397 -+
48398 -+static bool
48399 -+cmp_buffer_with_ref(JOIN_TAB *tab)
48400 -+{
48401 -+ bool diff;
48402 -+ if (!(diff=tab->ref.key_err))
48403 -+ {
48404 -+ memcpy(tab->ref.key_buff2, tab->ref.key_buff, tab->ref.key_length);
48405 -+ }
48406 -+ if ((tab->ref.key_err= cp_buffer_from_ref(tab->join->thd, tab->table,
48407 -+ &tab->ref)) ||
48408 -+ diff)
48409 -+ return 1;
48410 -+ return memcmp(tab->ref.key_buff2, tab->ref.key_buff, tab->ref.key_length)
48411 -+ != 0;
48412 -+}
48413 -+
48414 -+
48415 -+bool
48416 -+cp_buffer_from_ref(THD *thd, TABLE *table, TABLE_REF *ref)
48417 -+{
48418 -+ enum enum_check_fields save_count_cuted_fields= thd->count_cuted_fields;
48419 -+ thd->count_cuted_fields= CHECK_FIELD_IGNORE;
48420 -+ my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->write_set);
48421 -+ bool result= 0;
48422 -+
48423 -+ for (store_key **copy=ref->key_copy ; *copy ; copy++)
48424 -+ {
48425 -+ if ((*copy)->copy() & 1)
48426 -+ {
48427 -+ result= 1;
48428 -+ break;
48429 -+ }
48430 -+ }
48431 -+ thd->count_cuted_fields= save_count_cuted_fields;
48432 -+ dbug_tmp_restore_column_map(table->write_set, old_map);
48433 -+ return result;
48434 -+}
48435 -+
48436 -+
48437 -+/*****************************************************************************
48438 -+ Group and order functions
48439 -+*****************************************************************************/
48440 -+
48441 -+/**
48442 -+ Resolve an ORDER BY or GROUP BY column reference.
48443 -+
48444 -+ Given a column reference (represented by 'order') from a GROUP BY or ORDER
48445 -+ BY clause, find the actual column it represents. If the column being
48446 -+ resolved is from the GROUP BY clause, the procedure searches the SELECT
48447 -+ list 'fields' and the columns in the FROM list 'tables'. If 'order' is from
48448 -+ the ORDER BY clause, only the SELECT list is being searched.
48449 -+
48450 -+ If 'order' is resolved to an Item, then order->item is set to the found
48451 -+ Item. If there is no item for the found column (that is, it was resolved
48452 -+ into a table field), order->item is 'fixed' and is added to all_fields and
48453 -+ ref_pointer_array.
48454 -+
48455 -+ ref_pointer_array and all_fields are updated.
48456 -+
48457 -+ @param[in] thd Pointer to current thread structure
48458 -+ @param[in,out] ref_pointer_array All select, group and order by fields
48459 -+ @param[in] tables List of tables to search in (usually
48460 -+ FROM clause)
48461 -+ @param[in] order Column reference to be resolved
48462 -+ @param[in] fields List of fields to search in (usually
48463 -+ SELECT list)
48464 -+ @param[in,out] all_fields All select, group and order by fields
48465 -+ @param[in] is_group_field True if order is a GROUP field, false if
48466 -+ ORDER by field
48467 -+
48468 -+ @retval
48469 -+ FALSE if OK
48470 -+ @retval
48471 -+ TRUE if error occurred
48472 -+*/
48473 -+
48474 -+static bool
48475 -+find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
48476 -+ ORDER *order, List<Item> &fields, List<Item> &all_fields,
48477 -+ bool is_group_field)
48478 -+{
48479 -+ Item *order_item= *order->item; /* The item from the GROUP/ORDER caluse. */
48480 -+ Item::Type order_item_type;
48481 -+ Item **select_item; /* The corresponding item from the SELECT clause. */
48482 -+ Field *from_field; /* The corresponding field from the FROM clause. */
48483 -+ uint counter;
48484 -+ enum_resolution_type resolution;
48485 -+
48486 -+ /*
48487 -+ Local SP variables may be int but are expressions, not positions.
48488 -+ (And they can't be used before fix_fields is called for them).
48489 -+ */
48490 -+ if (order_item->type() == Item::INT_ITEM && order_item->basic_const_item())
48491 -+ { /* Order by position */
48492 -+ uint count= (uint) order_item->val_int();
48493 -+ if (!count || count > fields.elements)
48494 -+ {
48495 -+ my_error(ER_BAD_FIELD_ERROR, MYF(0),
48496 -+ order_item->full_name(), thd->where);
48497 -+ return TRUE;
48498 -+ }
48499 -+ order->item= ref_pointer_array + count - 1;
48500 -+ order->in_field_list= 1;
48501 -+ order->counter= count;
48502 -+ order->counter_used= 1;
48503 -+ return FALSE;
48504 -+ }
48505 -+ /* Lookup the current GROUP/ORDER field in the SELECT clause. */
48506 -+ select_item= find_item_in_list(order_item, fields, &counter,
48507 -+ REPORT_EXCEPT_NOT_FOUND, &resolution);
48508 -+ if (!select_item)
48509 -+ return TRUE; /* The item is not unique, or some other error occured. */
48510 -+
48511 -+
48512 -+ /* Check whether the resolved field is not ambiguos. */
48513 -+ if (select_item != not_found_item)
48514 -+ {
48515 -+ Item *view_ref= NULL;
48516 -+ /*
48517 -+ If we have found field not by its alias in select list but by its
48518 -+ original field name, we should additionaly check if we have conflict
48519 -+ for this name (in case if we would perform lookup in all tables).
48520 -+ */
48521 -+ if (resolution == RESOLVED_BEHIND_ALIAS && !order_item->fixed &&
48522 -+ order_item->fix_fields(thd, order->item))
48523 -+ return TRUE;
48524 -+
48525 -+ /* Lookup the current GROUP field in the FROM clause. */
48526 -+ order_item_type= order_item->type();
48527 -+ from_field= (Field*) not_found_field;
48528 -+ if ((is_group_field &&
48529 -+ order_item_type == Item::FIELD_ITEM) ||
48530 -+ order_item_type == Item::REF_ITEM)
48531 -+ {
48532 -+ from_field= find_field_in_tables(thd, (Item_ident*) order_item, tables,
48533 -+ NULL, &view_ref, IGNORE_ERRORS, TRUE,
48534 -+ FALSE);
48535 -+ if (!from_field)
48536 -+ from_field= (Field*) not_found_field;
48537 -+ }
48538 -+
48539 -+ if (from_field == not_found_field ||
48540 -+ (from_field != view_ref_found ?
48541 -+ /* it is field of base table => check that fields are same */
48542 -+ ((*select_item)->type() == Item::FIELD_ITEM &&
48543 -+ ((Item_field*) (*select_item))->field->eq(from_field)) :
48544 -+ /*
48545 -+ in is field of view table => check that references on translation
48546 -+ table are same
48547 -+ */
48548 -+ ((*select_item)->type() == Item::REF_ITEM &&
48549 -+ view_ref->type() == Item::REF_ITEM &&
48550 -+ ((Item_ref *) (*select_item))->ref ==
48551 -+ ((Item_ref *) view_ref)->ref)))
48552 -+ {
48553 -+ /*
48554 -+ If there is no such field in the FROM clause, or it is the same field
48555 -+ as the one found in the SELECT clause, then use the Item created for
48556 -+ the SELECT field. As a result if there was a derived field that
48557 -+ 'shadowed' a table field with the same name, the table field will be
48558 -+ chosen over the derived field.
48559 -+ */
48560 -+ order->item= ref_pointer_array + counter;
48561 -+ order->in_field_list=1;
48562 -+ return FALSE;
48563 -+ }
48564 -+ else
48565 -+ {
48566 -+ /*
48567 -+ There is a field with the same name in the FROM clause. This
48568 -+ is the field that will be chosen. In this case we issue a
48569 -+ warning so the user knows that the field from the FROM clause
48570 -+ overshadows the column reference from the SELECT list.
48571 -+ */
48572 -+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_NON_UNIQ_ERROR,
48573 -+ ER(ER_NON_UNIQ_ERROR),
48574 -+ ((Item_ident*) order_item)->field_name,
48575 -+ current_thd->where);
48576 -+ }
48577 -+ }
48578 -+
48579 -+ order->in_field_list=0;
48580 -+ /*
48581 -+ The call to order_item->fix_fields() means that here we resolve
48582 -+ 'order_item' to a column from a table in the list 'tables', or to
48583 -+ a column in some outer query. Exactly because of the second case
48584 -+ we come to this point even if (select_item == not_found_item),
48585 -+ inspite of that fix_fields() calls find_item_in_list() one more
48586 -+ time.
48587 -+
48588 -+ We check order_item->fixed because Item_func_group_concat can put
48589 -+ arguments for which fix_fields already was called.
48590 -+
48591 -+ group_fix_field= TRUE is to resolve aliases from the SELECT list
48592 -+ without creating of Item_ref-s: JOIN::exec() wraps aliased items
48593 -+ in SELECT list with Item_copy items. To re-evaluate such a tree
48594 -+ that includes Item_copy items we have to refresh Item_copy caches,
48595 -+ but:
48596 -+ - filesort() never refresh Item_copy items,
48597 -+ - end_send_group() checks every record for group boundary by the
48598 -+ test_if_group_changed function that obtain data from these
48599 -+ Item_copy items, but the copy_fields function that
48600 -+ refreshes Item copy items is called after group boundaries only -
48601 -+ that is a vicious circle.
48602 -+ So we prevent inclusion of Item_copy items.
48603 -+ */
48604 -+ bool save_group_fix_field= thd->lex->current_select->group_fix_field;
48605 -+ if (is_group_field)
48606 -+ thd->lex->current_select->group_fix_field= TRUE;
48607 -+ bool ret= (!order_item->fixed &&
48608 -+ (order_item->fix_fields(thd, order->item) ||
48609 -+ (order_item= *order->item)->check_cols(1) ||
48610 -+ thd->is_fatal_error));
48611 -+ thd->lex->current_select->group_fix_field= save_group_fix_field;
48612 -+ if (ret)
48613 -+ return TRUE; /* Wrong field. */
48614 -+
48615 -+ uint el= all_fields.elements;
48616 -+ all_fields.push_front(order_item); /* Add new field to field list. */
48617 -+ ref_pointer_array[el]= order_item;
48618 -+ order->item= ref_pointer_array + el;
48619 -+ return FALSE;
48620 -+}
48621 -+
48622 -+
48623 -+/**
48624 -+ Change order to point at item in select list.
48625 -+
48626 -+ If item isn't a number and doesn't exits in the select list, add it the
48627 -+ the field list.
48628 -+*/
48629 -+
48630 -+int setup_order(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
48631 -+ List<Item> &fields, List<Item> &all_fields, ORDER *order)
48632 -+{
48633 -+ thd->where="order clause";
48634 -+ for (; order; order=order->next)
48635 -+ {
48636 -+ if (find_order_in_list(thd, ref_pointer_array, tables, order, fields,
48637 -+ all_fields, FALSE))
48638 -+ return 1;
48639 -+ }
48640 -+ return 0;
48641 -+}
48642 -+
48643 -+
48644 -+/**
48645 -+ Intitialize the GROUP BY list.
48646 -+
48647 -+ @param thd Thread handler
48648 -+ @param ref_pointer_array We store references to all fields that was
48649 -+ not in 'fields' here.
48650 -+ @param fields All fields in the select part. Any item in
48651 -+ 'order' that is part of these list is replaced
48652 -+ by a pointer to this fields.
48653 -+ @param all_fields Total list of all unique fields used by the
48654 -+ select. All items in 'order' that was not part
48655 -+ of fields will be added first to this list.
48656 -+ @param order The fields we should do GROUP BY on.
48657 -+ @param hidden_group_fields Pointer to flag that is set to 1 if we added
48658 -+ any fields to all_fields.
48659 -+
48660 -+ @todo
48661 -+ change ER_WRONG_FIELD_WITH_GROUP to more detailed
48662 -+ ER_NON_GROUPING_FIELD_USED
48663 -+
48664 -+ @retval
48665 -+ 0 ok
48666 -+ @retval
48667 -+ 1 error (probably out of memory)
48668 -+*/
48669 -+
48670 -+int
48671 -+setup_group(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
48672 -+ List<Item> &fields, List<Item> &all_fields, ORDER *order,
48673 -+ bool *hidden_group_fields)
48674 -+{
48675 -+ *hidden_group_fields=0;
48676 -+ ORDER *ord;
48677 -+
48678 -+ if (!order)
48679 -+ return 0; /* Everything is ok */
48680 -+
48681 -+ uint org_fields=all_fields.elements;
48682 -+
48683 -+ thd->where="group statement";
48684 -+ for (ord= order; ord; ord= ord->next)
48685 -+ {
48686 -+ if (find_order_in_list(thd, ref_pointer_array, tables, ord, fields,
48687 -+ all_fields, TRUE))
48688 -+ return 1;
48689 -+ (*ord->item)->marker= UNDEF_POS; /* Mark found */
48690 -+ if ((*ord->item)->with_sum_func)
48691 -+ {
48692 -+ my_error(ER_WRONG_GROUP_FIELD, MYF(0), (*ord->item)->full_name());
48693 -+ return 1;
48694 -+ }
48695 -+ }
48696 -+ if (thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY)
48697 -+ {
48698 -+ /*
48699 -+ Don't allow one to use fields that is not used in GROUP BY
48700 -+ For each select a list of field references that aren't under an
48701 -+ aggregate function is created. Each field in this list keeps the
48702 -+ position of the select list expression which it belongs to.
48703 -+
48704 -+ First we check an expression from the select list against the GROUP BY
48705 -+ list. If it's found there then it's ok. It's also ok if this expression
48706 -+ is a constant or an aggregate function. Otherwise we scan the list
48707 -+ of non-aggregated fields and if we'll find at least one field reference
48708 -+ that belongs to this expression and doesn't occur in the GROUP BY list
48709 -+ we throw an error. If there are no fields in the created list for a
48710 -+ select list expression this means that all fields in it are used under
48711 -+ aggregate functions.
48712 -+ */
48713 -+ Item *item;
48714 -+ Item_field *field;
48715 -+ int cur_pos_in_select_list= 0;
48716 -+ List_iterator<Item> li(fields);
48717 -+ List_iterator<Item_field> naf_it(thd->lex->current_select->non_agg_fields);
48718 -+
48719 -+ field= naf_it++;
48720 -+ while (field && (item=li++))
48721 -+ {
48722 -+ if (item->type() != Item::SUM_FUNC_ITEM && item->marker >= 0 &&
48723 -+ !item->const_item() &&
48724 -+ !(item->real_item()->type() == Item::FIELD_ITEM &&
48725 -+ item->used_tables() & OUTER_REF_TABLE_BIT))
48726 -+ {
48727 -+ while (field)
48728 -+ {
48729 -+ /* Skip fields from previous expressions. */
48730 -+ if (field->marker < cur_pos_in_select_list)
48731 -+ goto next_field;
48732 -+ /* Found a field from the next expression. */
48733 -+ if (field->marker > cur_pos_in_select_list)
48734 -+ break;
48735 -+ /*
48736 -+ Check whether the field occur in the GROUP BY list.
48737 -+ Throw the error later if the field isn't found.
48738 -+ */
48739 -+ for (ord= order; ord; ord= ord->next)
48740 -+ if ((*ord->item)->eq((Item*)field, 0))
48741 -+ goto next_field;
48742 -+ /*
48743 -+ TODO: change ER_WRONG_FIELD_WITH_GROUP to more detailed
48744 -+ ER_NON_GROUPING_FIELD_USED
48745 -+ */
48746 -+ my_error(ER_WRONG_FIELD_WITH_GROUP, MYF(0), field->full_name());
48747 -+ return 1;
48748 -+next_field:
48749 -+ field= naf_it++;
48750 -+ }
48751 -+ }
48752 -+ cur_pos_in_select_list++;
48753 -+ }
48754 -+ }
48755 -+ if (org_fields != all_fields.elements)
48756 -+ *hidden_group_fields=1; // group fields is not used
48757 -+ return 0;
48758 -+}
48759 -+
48760 -+/**
48761 -+ Add fields with aren't used at start of field list.
48762 -+
48763 -+ @return
48764 -+ FALSE if ok
48765 -+*/
48766 -+
48767 -+static bool
48768 -+setup_new_fields(THD *thd, List<Item> &fields,
48769 -+ List<Item> &all_fields, ORDER *new_field)
48770 -+{
48771 -+ Item **item;
48772 -+ uint counter;
48773 -+ enum_resolution_type not_used;
48774 -+ DBUG_ENTER("setup_new_fields");
48775 -+
48776 -+ thd->mark_used_columns= MARK_COLUMNS_READ; // Not really needed, but...
48777 -+ for (; new_field ; new_field= new_field->next)
48778 -+ {
48779 -+ if ((item= find_item_in_list(*new_field->item, fields, &counter,
48780 -+ IGNORE_ERRORS, &not_used)))
48781 -+ new_field->item=item; /* Change to shared Item */
48782 -+ else
48783 -+ {
48784 -+ thd->where="procedure list";
48785 -+ if ((*new_field->item)->fix_fields(thd, new_field->item))
48786 -+ DBUG_RETURN(1); /* purecov: inspected */
48787 -+ all_fields.push_front(*new_field->item);
48788 -+ new_field->item=all_fields.head_ref();
48789 -+ }
48790 -+ }
48791 -+ DBUG_RETURN(0);
48792 -+}
48793 -+
48794 -+/**
48795 -+ Create a group by that consist of all non const fields.
48796 -+
48797 -+ Try to use the fields in the order given by 'order' to allow one to
48798 -+ optimize away 'order by'.
48799 -+*/
48800 -+
48801 -+static ORDER *
48802 -+create_distinct_group(THD *thd, Item **ref_pointer_array,
48803 -+ ORDER *order_list, List<Item> &fields,
48804 -+ List<Item> &all_fields,
48805 -+ bool *all_order_by_fields_used)
48806 -+{
48807 -+ List_iterator<Item> li(fields);
48808 -+ Item *item, **orig_ref_pointer_array= ref_pointer_array;
48809 -+ ORDER *order,*group,**prev;
48810 -+
48811 -+ *all_order_by_fields_used= 1;
48812 -+ while ((item=li++))
48813 -+ item->marker=0; /* Marker that field is not used */
48814 -+
48815 -+ prev= &group; group=0;
48816 -+ for (order=order_list ; order; order=order->next)
48817 -+ {
48818 -+ if (order->in_field_list)
48819 -+ {
48820 -+ ORDER *ord=(ORDER*) thd->memdup((char*) order,sizeof(ORDER));
48821 -+ if (!ord)
48822 -+ return 0;
48823 -+ *prev=ord;
48824 -+ prev= &ord->next;
48825 -+ (*ord->item)->marker=1;
48826 -+ }
48827 -+ else
48828 -+ *all_order_by_fields_used= 0;
48829 -+ }
48830 -+
48831 -+ li.rewind();
48832 -+ while ((item=li++))
48833 -+ {
48834 -+ if (!item->const_item() && !item->with_sum_func && !item->marker)
48835 -+ {
48836 -+ /*
48837 -+ Don't put duplicate columns from the SELECT list into the
48838 -+ GROUP BY list.
48839 -+ */
48840 -+ ORDER *ord_iter;
48841 -+ for (ord_iter= group; ord_iter; ord_iter= ord_iter->next)
48842 -+ if ((*ord_iter->item)->eq(item, 1))
48843 -+ goto next_item;
48844 -+
48845 -+ ORDER *ord=(ORDER*) thd->calloc(sizeof(ORDER));
48846 -+ if (!ord)
48847 -+ return 0;
48848 -+
48849 -+ if (item->type() == Item::FIELD_ITEM &&
48850 -+ item->field_type() == MYSQL_TYPE_BIT)
48851 -+ {
48852 -+ /*
48853 -+ Because HEAP tables can't index BIT fields we need to use an
48854 -+ additional hidden field for grouping because later it will be
48855 -+ converted to a LONG field. Original field will remain of the
48856 -+ BIT type and will be returned to a client.
48857 -+ */
48858 -+ Item_field *new_item= new Item_field(thd, (Item_field*)item);
48859 -+ int el= all_fields.elements;
48860 -+ orig_ref_pointer_array[el]= new_item;
48861 -+ all_fields.push_front(new_item);
48862 -+ ord->item= orig_ref_pointer_array + el;
48863 -+ }
48864 -+ else
48865 -+ {
48866 -+ /*
48867 -+ We have here only field_list (not all_field_list), so we can use
48868 -+ simple indexing of ref_pointer_array (order in the array and in the
48869 -+ list are same)
48870 -+ */
48871 -+ ord->item= ref_pointer_array;
48872 -+ }
48873 -+ ord->asc=1;
48874 -+ *prev=ord;
48875 -+ prev= &ord->next;
48876 -+ }
48877 -+next_item:
48878 -+ ref_pointer_array++;
48879 -+ }
48880 -+ *prev=0;
48881 -+ return group;
48882 -+}
48883 -+
48884 -+
48885 -+/**
48886 -+ Update join with count of the different type of fields.
48887 -+*/
48888 -+
48889 -+void
48890 -+count_field_types(SELECT_LEX *select_lex, TMP_TABLE_PARAM *param,
48891 -+ List<Item> &fields, bool reset_with_sum_func)
48892 -+{
48893 -+ List_iterator<Item> li(fields);
48894 -+ Item *field;
48895 -+
48896 -+ param->field_count=param->sum_func_count=param->func_count=
48897 -+ param->hidden_field_count=0;
48898 -+ param->quick_group=1;
48899 -+ while ((field=li++))
48900 -+ {
48901 -+ Item::Type real_type= field->real_item()->type();
48902 -+ if (real_type == Item::FIELD_ITEM)
48903 -+ param->field_count++;
48904 -+ else if (real_type == Item::SUM_FUNC_ITEM)
48905 -+ {
48906 -+ if (! field->const_item())
48907 -+ {
48908 -+ Item_sum *sum_item=(Item_sum*) field->real_item();
48909 -+ if (!sum_item->depended_from() ||
48910 -+ sum_item->depended_from() == select_lex)
48911 -+ {
48912 -+ if (!sum_item->quick_group)
48913 -+ param->quick_group=0; // UDF SUM function
48914 -+ param->sum_func_count++;
48915 -+
48916 -+ for (uint i=0 ; i < sum_item->get_arg_count() ; i++)
48917 -+ {
48918 -+ if (sum_item->get_arg(i)->real_item()->type() == Item::FIELD_ITEM)
48919 -+ param->field_count++;
48920 -+ else
48921 -+ param->func_count++;
48922 -+ }
48923 -+ }
48924 -+ param->func_count++;
48925 -+ }
48926 -+ }
48927 -+ else
48928 -+ {
48929 -+ param->func_count++;
48930 -+ if (reset_with_sum_func)
48931 -+ field->with_sum_func=0;
48932 -+ }
48933 -+ }
48934 -+}
48935 -+
48936 -+
48937 -+/**
48938 -+ Return 1 if second is a subpart of first argument.
48939 -+
48940 -+ If first parts has different direction, change it to second part
48941 -+ (group is sorted like order)
48942 -+*/
48943 -+
48944 -+static bool
48945 -+test_if_subpart(ORDER *a,ORDER *b)
48946 -+{
48947 -+ for (; a && b; a=a->next,b=b->next)
48948 -+ {
48949 -+ if ((*a->item)->eq(*b->item,1))
48950 -+ a->asc=b->asc;
48951 -+ else
48952 -+ return 0;
48953 -+ }
48954 -+ return test(!b);
48955 -+}
48956 -+
48957 -+/**
48958 -+ Return table number if there is only one table in sort order
48959 -+ and group and order is compatible, else return 0.
48960 -+*/
48961 -+
48962 -+static TABLE *
48963 -+get_sort_by_table(ORDER *a,ORDER *b,TABLE_LIST *tables)
48964 -+{
48965 -+ table_map map= (table_map) 0;
48966 -+ DBUG_ENTER("get_sort_by_table");
48967 -+
48968 -+ if (!a)
48969 -+ a=b; // Only one need to be given
48970 -+ else if (!b)
48971 -+ b=a;
48972 -+
48973 -+ for (; a && b; a=a->next,b=b->next)
48974 -+ {
48975 -+ if (!(*a->item)->eq(*b->item,1))
48976 -+ DBUG_RETURN(0);
48977 -+ map|=a->item[0]->used_tables();
48978 -+ }
48979 -+ if (!map || (map & (RAND_TABLE_BIT | OUTER_REF_TABLE_BIT)))
48980 -+ DBUG_RETURN(0);
48981 -+
48982 -+ for (; !(map & tables->table->map); tables= tables->next_leaf) ;
48983 -+ if (map != tables->table->map)
48984 -+ DBUG_RETURN(0); // More than one table
48985 -+ DBUG_PRINT("exit",("sort by table: %d",tables->table->tablenr));
48986 -+ DBUG_RETURN(tables->table);
48987 -+}
48988 -+
48989 -+
48990 -+/**
48991 -+ calc how big buffer we need for comparing group entries.
48992 -+*/
48993 -+
48994 -+static void
48995 -+calc_group_buffer(JOIN *join,ORDER *group)
48996 -+{
48997 -+ uint key_length=0, parts=0, null_parts=0;
48998 -+
48999 -+ if (group)
49000 -+ join->group= 1;
49001 -+ for (; group ; group=group->next)
49002 -+ {
49003 -+ Item *group_item= *group->item;
49004 -+ Field *field= group_item->get_tmp_table_field();
49005 -+ if (field)
49006 -+ {
49007 -+ enum_field_types type;
49008 -+ if ((type= field->type()) == MYSQL_TYPE_BLOB)
49009 -+ key_length+=MAX_BLOB_WIDTH; // Can't be used as a key
49010 -+ else if (type == MYSQL_TYPE_VARCHAR || type == MYSQL_TYPE_VAR_STRING)
49011 -+ key_length+= field->field_length + HA_KEY_BLOB_LENGTH;
49012 -+ else if (type == MYSQL_TYPE_BIT)
49013 -+ {
49014 -+ /* Bit is usually stored as a longlong key for group fields */
49015 -+ key_length+= 8; // Big enough
49016 -+ }
49017 -+ else
49018 -+ key_length+= field->pack_length();
49019 -+ }
49020 -+ else
49021 -+ {
49022 -+ switch (group_item->result_type()) {
49023 -+ case REAL_RESULT:
49024 -+ key_length+= sizeof(double);
49025 -+ break;
49026 -+ case INT_RESULT:
49027 -+ key_length+= sizeof(longlong);
49028 -+ break;
49029 -+ case DECIMAL_RESULT:
49030 -+ key_length+= my_decimal_get_binary_size(group_item->max_length -
49031 -+ (group_item->decimals ? 1 : 0),
49032 -+ group_item->decimals);
49033 -+ break;
49034 -+ case STRING_RESULT:
49035 -+ {
49036 -+ enum enum_field_types type= group_item->field_type();
49037 -+ /*
49038 -+ As items represented as DATE/TIME fields in the group buffer
49039 -+ have STRING_RESULT result type, we increase the length
49040 -+ by 8 as maximum pack length of such fields.
49041 -+ */
49042 -+ if (type == MYSQL_TYPE_TIME ||
49043 -+ type == MYSQL_TYPE_DATE ||
49044 -+ type == MYSQL_TYPE_DATETIME ||
49045 -+ type == MYSQL_TYPE_TIMESTAMP)
49046 -+ {
49047 -+ key_length+= 8;
49048 -+ }
49049 -+ else if (type == MYSQL_TYPE_BLOB)
49050 -+ key_length+= MAX_BLOB_WIDTH; // Can't be used as a key
49051 -+ else
49052 -+ {
49053 -+ /*
49054 -+ Group strings are taken as varstrings and require an length field.
49055 -+ A field is not yet created by create_tmp_field()
49056 -+ and the sizes should match up.
49057 -+ */
49058 -+ key_length+= group_item->max_length + HA_KEY_BLOB_LENGTH;
49059 -+ }
49060 -+ break;
49061 -+ }
49062 -+ default:
49063 -+ /* This case should never be choosen */
49064 -+ DBUG_ASSERT(0);
49065 -+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
49066 -+ join->thd->fatal_error();
49067 -+ }
49068 -+ }
49069 -+ parts++;
49070 -+ if (group_item->maybe_null)
49071 -+ null_parts++;
49072 -+ }
49073 -+ join->tmp_table_param.group_length=key_length+null_parts;
49074 -+ join->tmp_table_param.group_parts=parts;
49075 -+ join->tmp_table_param.group_null_parts=null_parts;
49076 -+}
49077 -+
49078 -+
49079 -+/**
49080 -+ allocate group fields or take prepared (cached).
49081 -+
49082 -+ @param main_join join of current select
49083 -+ @param curr_join current join (join of current select or temporary copy
49084 -+ of it)
49085 -+
49086 -+ @retval
49087 -+ 0 ok
49088 -+ @retval
49089 -+ 1 failed
49090 -+*/
49091 -+
49092 -+static bool
49093 -+make_group_fields(JOIN *main_join, JOIN *curr_join)
49094 -+{
49095 -+ if (main_join->group_fields_cache.elements)
49096 -+ {
49097 -+ curr_join->group_fields= main_join->group_fields_cache;
49098 -+ curr_join->sort_and_group= 1;
49099 -+ }
49100 -+ else
49101 -+ {
49102 -+ if (alloc_group_fields(curr_join, curr_join->group_list))
49103 -+ return (1);
49104 -+ main_join->group_fields_cache= curr_join->group_fields;
49105 -+ }
49106 -+ return (0);
49107 -+}
49108 -+
49109 -+
49110 -+/**
49111 -+ Get a list of buffers for saveing last group.
49112 -+
49113 -+ Groups are saved in reverse order for easyer check loop.
49114 -+*/
49115 -+
49116 -+static bool
49117 -+alloc_group_fields(JOIN *join,ORDER *group)
49118 -+{
49119 -+ if (group)
49120 -+ {
49121 -+ for (; group ; group=group->next)
49122 -+ {
49123 -+ Cached_item *tmp=new_Cached_item(join->thd, *group->item);
49124 -+ if (!tmp || join->group_fields.push_front(tmp))
49125 -+ return TRUE;
49126 -+ }
49127 -+ }
49128 -+ join->sort_and_group=1; /* Mark for do_select */
49129 -+ return FALSE;
49130 -+}
49131 -+
49132 -+
49133 -+static int
49134 -+test_if_group_changed(List<Cached_item> &list)
49135 -+{
49136 -+ DBUG_ENTER("test_if_group_changed");
49137 -+ List_iterator<Cached_item> li(list);
49138 -+ int idx= -1,i;
49139 -+ Cached_item *buff;
49140 -+
49141 -+ for (i=(int) list.elements-1 ; (buff=li++) ; i--)
49142 -+ {
49143 -+ if (buff->cmp())
49144 -+ idx=i;
49145 -+ }
49146 -+ DBUG_PRINT("info", ("idx: %d", idx));
49147 -+ DBUG_RETURN(idx);
49148 -+}
49149 -+
49150 -+
49151 -+/**
49152 -+ Setup copy_fields to save fields at start of new group.
49153 -+
49154 -+ Setup copy_fields to save fields at start of new group
49155 -+
49156 -+ Only FIELD_ITEM:s and FUNC_ITEM:s needs to be saved between groups.
49157 -+ Change old item_field to use a new field with points at saved fieldvalue
49158 -+ This function is only called before use of send_fields.
49159 -+
49160 -+ @param thd THD pointer
49161 -+ @param param temporary table parameters
49162 -+ @param ref_pointer_array array of pointers to top elements of filed list
49163 -+ @param res_selected_fields new list of items of select item list
49164 -+ @param res_all_fields new list of all items
49165 -+ @param elements number of elements in select item list
49166 -+ @param all_fields all fields list
49167 -+
49168 -+ @todo
49169 -+ In most cases this result will be sent to the user.
49170 -+ This should be changed to use copy_int or copy_real depending
49171 -+ on how the value is to be used: In some cases this may be an
49172 -+ argument in a group function, like: IF(ISNULL(col),0,COUNT(*))
49173 -+
49174 -+ @retval
49175 -+ 0 ok
49176 -+ @retval
49177 -+ !=0 error
49178 -+*/
49179 -+
49180 -+bool
49181 -+setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,
49182 -+ Item **ref_pointer_array,
49183 -+ List<Item> &res_selected_fields, List<Item> &res_all_fields,
49184 -+ uint elements, List<Item> &all_fields)
49185 -+{
49186 -+ Item *pos;
49187 -+ List_iterator_fast<Item> li(all_fields);
49188 -+ Copy_field *copy= NULL;
49189 -+ IF_DBUG(Copy_field *copy_start);
49190 -+ res_selected_fields.empty();
49191 -+ res_all_fields.empty();
49192 -+ List_iterator_fast<Item> itr(res_all_fields);
49193 -+ List<Item> extra_funcs;
49194 -+ uint i, border= all_fields.elements - elements;
49195 -+ DBUG_ENTER("setup_copy_fields");
49196 -+
49197 -+ if (param->field_count &&
49198 -+ !(copy=param->copy_field= new Copy_field[param->field_count]))
49199 -+ goto err2;
49200 -+
49201 -+ param->copy_funcs.empty();
49202 -+ IF_DBUG(copy_start= copy);
49203 -+ for (i= 0; (pos= li++); i++)
49204 -+ {
49205 -+ Field *field;
49206 -+ uchar *tmp;
49207 -+ Item *real_pos= pos->real_item();
49208 -+ /*
49209 -+ Aggregate functions can be substituted for fields (by e.g. temp tables).
49210 -+ We need to filter those substituted fields out.
49211 -+ */
49212 -+ if (real_pos->type() == Item::FIELD_ITEM &&
49213 -+ !(real_pos != pos &&
49214 -+ ((Item_ref *)pos)->ref_type() == Item_ref::AGGREGATE_REF))
49215 -+ {
49216 -+ Item_field *item;
49217 -+ if (!(item= new Item_field(thd, ((Item_field*) real_pos))))
49218 -+ goto err;
49219 -+ if (pos->type() == Item::REF_ITEM)
49220 -+ {
49221 -+ /* preserve the names of the ref when dereferncing */
49222 -+ Item_ref *ref= (Item_ref *) pos;
49223 -+ item->db_name= ref->db_name;
49224 -+ item->table_name= ref->table_name;
49225 -+ item->name= ref->name;
49226 -+ }
49227 -+ pos= item;
49228 -+ if (item->field->flags & BLOB_FLAG)
49229 -+ {
49230 -+ if (!(pos= Item_copy::create(pos)))
49231 -+ goto err;
49232 -+ /*
49233 -+ Item_copy_string::copy for function can call
49234 -+ Item_copy_string::val_int for blob via Item_ref.
49235 -+ But if Item_copy_string::copy for blob isn't called before,
49236 -+ it's value will be wrong
49237 -+ so let's insert Item_copy_string for blobs in the beginning of
49238 -+ copy_funcs
49239 -+ (to see full test case look at having.test, BUG #4358)
49240 -+ */
49241 -+ if (param->copy_funcs.push_front(pos))
49242 -+ goto err;
49243 -+ }
49244 -+ else
49245 -+ {
49246 -+ /*
49247 -+ set up save buffer and change result_field to point at
49248 -+ saved value
49249 -+ */
49250 -+ field= item->field;
49251 -+ item->result_field=field->new_field(thd->mem_root,field->table, 1);
49252 -+ /*
49253 -+ We need to allocate one extra byte for null handling and
49254 -+ another extra byte to not get warnings from purify in
49255 -+ Field_string::val_int
49256 -+ */
49257 -+ if (!(tmp= (uchar*) sql_alloc(field->pack_length()+2)))
49258 -+ goto err;
49259 -+ if (copy)
49260 -+ {
49261 -+ DBUG_ASSERT (param->field_count > (uint) (copy - copy_start));
49262 -+ copy->set(tmp, item->result_field);
49263 -+ item->result_field->move_field(copy->to_ptr,copy->to_null_ptr,1);
49264 -+#ifdef HAVE_purify
49265 -+ copy->to_ptr[copy->from_length]= 0;
49266 -+#endif
49267 -+ copy++;
49268 -+ }
49269 -+ }
49270 -+ }
49271 -+ else if ((real_pos->type() == Item::FUNC_ITEM ||
49272 -+ real_pos->type() == Item::SUBSELECT_ITEM ||
49273 -+ real_pos->type() == Item::CACHE_ITEM ||
49274 -+ real_pos->type() == Item::COND_ITEM) &&
49275 -+ !real_pos->with_sum_func)
49276 -+ { // Save for send fields
49277 -+ pos= real_pos;
49278 -+ /* TODO:
49279 -+ In most cases this result will be sent to the user.
49280 -+ This should be changed to use copy_int or copy_real depending
49281 -+ on how the value is to be used: In some cases this may be an
49282 -+ argument in a group function, like: IF(ISNULL(col),0,COUNT(*))
49283 -+ */
49284 -+ if (!(pos= Item_copy::create(pos)))
49285 -+ goto err;
49286 -+ if (i < border) // HAVING, ORDER and GROUP BY
49287 -+ {
49288 -+ if (extra_funcs.push_back(pos))
49289 -+ goto err;
49290 -+ }
49291 -+ else if (param->copy_funcs.push_back(pos))
49292 -+ goto err;
49293 -+ }
49294 -+ res_all_fields.push_back(pos);
49295 -+ ref_pointer_array[((i < border)? all_fields.elements-i-1 : i-border)]=
49296 -+ pos;
49297 -+ }
49298 -+ param->copy_field_end= copy;
49299 -+
49300 -+ for (i= 0; i < border; i++)
49301 -+ itr++;
49302 -+ itr.sublist(res_selected_fields, elements);
49303 -+ /*
49304 -+ Put elements from HAVING, ORDER BY and GROUP BY last to ensure that any
49305 -+ reference used in these will resolve to a item that is already calculated
49306 -+ */
49307 -+ param->copy_funcs.concat(&extra_funcs);
49308 -+
49309 -+ DBUG_RETURN(0);
49310 -+
49311 -+ err:
49312 -+ if (copy)
49313 -+ delete [] param->copy_field; // This is never 0
49314 -+ param->copy_field=0;
49315 -+err2:
49316 -+ DBUG_RETURN(TRUE);
49317 -+}
49318 -+
49319 -+
49320 -+/**
49321 -+ Make a copy of all simple SELECT'ed items.
49322 -+
49323 -+ This is done at the start of a new group so that we can retrieve
49324 -+ these later when the group changes.
49325 -+*/
49326 -+
49327 -+void
49328 -+copy_fields(TMP_TABLE_PARAM *param)
49329 -+{
49330 -+ Copy_field *ptr=param->copy_field;
49331 -+ Copy_field *end=param->copy_field_end;
49332 -+
49333 -+ for (; ptr != end; ptr++)
49334 -+ (*ptr->do_copy)(ptr);
49335 -+
49336 -+ List_iterator_fast<Item> it(param->copy_funcs);
49337 -+ Item_copy *item;
49338 -+ while ((item = (Item_copy*) it++))
49339 -+ item->copy();
49340 -+}
49341 -+
49342 -+
49343 -+/**
49344 -+ Make an array of pointers to sum_functions to speed up
49345 -+ sum_func calculation.
49346 -+
49347 -+ @retval
49348 -+ 0 ok
49349 -+ @retval
49350 -+ 1 Error
49351 -+*/
49352 -+
49353 -+bool JOIN::alloc_func_list()
49354 -+{
49355 -+ uint func_count, group_parts;
49356 -+ DBUG_ENTER("alloc_func_list");
49357 -+
49358 -+ func_count= tmp_table_param.sum_func_count;
49359 -+ /*
49360 -+ If we are using rollup, we need a copy of the summary functions for
49361 -+ each level
49362 -+ */
49363 -+ if (rollup.state != ROLLUP::STATE_NONE)
49364 -+ func_count*= (send_group_parts+1);
49365 -+
49366 -+ group_parts= send_group_parts;
49367 -+ /*
49368 -+ If distinct, reserve memory for possible
49369 -+ disctinct->group_by optimization
49370 -+ */
49371 -+ if (select_distinct)
49372 -+ {
49373 -+ group_parts+= fields_list.elements;
49374 -+ /*
49375 -+ If the ORDER clause is specified then it's possible that
49376 -+ it also will be optimized, so reserve space for it too
49377 -+ */
49378 -+ if (order)
49379 -+ {
49380 -+ ORDER *ord;
49381 -+ for (ord= order; ord; ord= ord->next)
49382 -+ group_parts++;
49383 -+ }
49384 -+ }
49385 -+
49386 -+ /* This must use calloc() as rollup_make_fields depends on this */
49387 -+ sum_funcs= (Item_sum**) thd->calloc(sizeof(Item_sum**) * (func_count+1) +
49388 -+ sizeof(Item_sum***) * (group_parts+1));
49389 -+ sum_funcs_end= (Item_sum***) (sum_funcs+func_count+1);
49390 -+ DBUG_RETURN(sum_funcs == 0);
49391 -+}
49392 -+
49393 -+
49394 -+/**
49395 -+ Initialize 'sum_funcs' array with all Item_sum objects.
49396 -+
49397 -+ @param field_list All items
49398 -+ @param send_fields Items in select list
49399 -+ @param before_group_by Set to 1 if this is called before GROUP BY handling
49400 -+ @param recompute Set to TRUE if sum_funcs must be recomputed
49401 -+
49402 -+ @retval
49403 -+ 0 ok
49404 -+ @retval
49405 -+ 1 error
49406 -+*/
49407 -+
49408 -+bool JOIN::make_sum_func_list(List<Item> &field_list, List<Item> &send_fields,
49409 -+ bool before_group_by, bool recompute)
49410 -+{
49411 -+ List_iterator_fast<Item> it(field_list);
49412 -+ Item_sum **func;
49413 -+ Item *item;
49414 -+ DBUG_ENTER("make_sum_func_list");
49415 -+
49416 -+ if (*sum_funcs && !recompute)
49417 -+ DBUG_RETURN(FALSE); /* We have already initialized sum_funcs. */
49418 -+
49419 -+ func= sum_funcs;
49420 -+ while ((item=it++))
49421 -+ {
49422 -+ if (item->type() == Item::SUM_FUNC_ITEM && !item->const_item() &&
49423 -+ (!((Item_sum*) item)->depended_from() ||
49424 -+ ((Item_sum *)item)->depended_from() == select_lex))
49425 -+ *func++= (Item_sum*) item;
49426 -+ }
49427 -+ if (before_group_by && rollup.state == ROLLUP::STATE_INITED)
49428 -+ {
49429 -+ rollup.state= ROLLUP::STATE_READY;
49430 -+ if (rollup_make_fields(field_list, send_fields, &func))
49431 -+ DBUG_RETURN(TRUE); // Should never happen
49432 -+ }
49433 -+ else if (rollup.state == ROLLUP::STATE_NONE)
49434 -+ {
49435 -+ for (uint i=0 ; i <= send_group_parts ;i++)
49436 -+ sum_funcs_end[i]= func;
49437 -+ }
49438 -+ else if (rollup.state == ROLLUP::STATE_READY)
49439 -+ DBUG_RETURN(FALSE); // Don't put end marker
49440 -+ *func=0; // End marker
49441 -+ DBUG_RETURN(FALSE);
49442 -+}
49443 -+
49444 -+
49445 -+/**
49446 -+ Change all funcs and sum_funcs to fields in tmp table, and create
49447 -+ new list of all items.
49448 -+
49449 -+ @param thd THD pointer
49450 -+ @param ref_pointer_array array of pointers to top elements of filed list
49451 -+ @param res_selected_fields new list of items of select item list
49452 -+ @param res_all_fields new list of all items
49453 -+ @param elements number of elements in select item list
49454 -+ @param all_fields all fields list
49455 -+
49456 -+ @retval
49457 -+ 0 ok
49458 -+ @retval
49459 -+ !=0 error
49460 -+*/
49461 -+
49462 -+static bool
49463 -+change_to_use_tmp_fields(THD *thd, Item **ref_pointer_array,
49464 -+ List<Item> &res_selected_fields,
49465 -+ List<Item> &res_all_fields,
49466 -+ uint elements, List<Item> &all_fields)
49467 -+{
49468 -+ List_iterator_fast<Item> it(all_fields);
49469 -+ Item *item_field,*item;
49470 -+ DBUG_ENTER("change_to_use_tmp_fields");
49471 -+
49472 -+ res_selected_fields.empty();
49473 -+ res_all_fields.empty();
49474 -+
49475 -+ uint i, border= all_fields.elements - elements;
49476 -+ for (i= 0; (item= it++); i++)
49477 -+ {
49478 -+ Field *field;
49479 -+
49480 -+ if ((item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM) ||
49481 -+ (item->type() == Item::FUNC_ITEM &&
49482 -+ ((Item_func*)item)->functype() == Item_func::SUSERVAR_FUNC))
49483 -+ item_field= item;
49484 -+ else
49485 -+ {
49486 -+ if (item->type() == Item::FIELD_ITEM)
49487 -+ {
49488 -+ item_field= item->get_tmp_table_item(thd);
49489 -+ }
49490 -+ else if ((field= item->get_tmp_table_field()))
49491 -+ {
49492 -+ if (item->type() == Item::SUM_FUNC_ITEM && field->table->group)
49493 -+ item_field= ((Item_sum*) item)->result_item(field);
49494 -+ else
49495 -+ item_field= (Item*) new Item_field(field);
49496 -+ if (!item_field)
49497 -+ DBUG_RETURN(TRUE); // Fatal error
49498 -+
49499 -+ if (item->real_item()->type() != Item::FIELD_ITEM)
49500 -+ field->orig_table= 0;
49501 -+ item_field->name= item->name;
49502 -+ if (item->type() == Item::REF_ITEM)
49503 -+ {
49504 -+ Item_field *ifield= (Item_field *) item_field;
49505 -+ Item_ref *iref= (Item_ref *) item;
49506 -+ ifield->table_name= iref->table_name;
49507 -+ ifield->db_name= iref->db_name;
49508 -+ }
49509 -+#ifndef DBUG_OFF
49510 -+ if (!item_field->name)
49511 -+ {
49512 -+ char buff[256];
49513 -+ String str(buff,sizeof(buff),&my_charset_bin);
49514 -+ str.length(0);
49515 -+ item->print(&str, QT_ORDINARY);
49516 -+ item_field->name= sql_strmake(str.ptr(),str.length());
49517 -+ }
49518 -+#endif
49519 -+ }
49520 -+ else
49521 -+ item_field= item;
49522 -+ }
49523 -+ res_all_fields.push_back(item_field);
49524 -+ ref_pointer_array[((i < border)? all_fields.elements-i-1 : i-border)]=
49525 -+ item_field;
49526 -+ }
49527 -+
49528 -+ List_iterator_fast<Item> itr(res_all_fields);
49529 -+ for (i= 0; i < border; i++)
49530 -+ itr++;
49531 -+ itr.sublist(res_selected_fields, elements);
49532 -+ DBUG_RETURN(FALSE);
49533 -+}
49534 -+
49535 -+
49536 -+/**
49537 -+ Change all sum_func refs to fields to point at fields in tmp table.
49538 -+ Change all funcs to be fields in tmp table.
49539 -+
49540 -+ @param thd THD pointer
49541 -+ @param ref_pointer_array array of pointers to top elements of filed list
49542 -+ @param res_selected_fields new list of items of select item list
49543 -+ @param res_all_fields new list of all items
49544 -+ @param elements number of elements in select item list
49545 -+ @param all_fields all fields list
49546 -+
49547 -+ @retval
49548 -+ 0 ok
49549 -+ @retval
49550 -+ 1 error
49551 -+*/
49552 -+
49553 -+static bool
49554 -+change_refs_to_tmp_fields(THD *thd, Item **ref_pointer_array,
49555 -+ List<Item> &res_selected_fields,
49556 -+ List<Item> &res_all_fields, uint elements,
49557 -+ List<Item> &all_fields)
49558 -+{
49559 -+ List_iterator_fast<Item> it(all_fields);
49560 -+ Item *item, *new_item;
49561 -+ res_selected_fields.empty();
49562 -+ res_all_fields.empty();
49563 -+
49564 -+ uint i, border= all_fields.elements - elements;
49565 -+ for (i= 0; (item= it++); i++)
49566 -+ {
49567 -+ res_all_fields.push_back(new_item= item->get_tmp_table_item(thd));
49568 -+ ref_pointer_array[((i < border)? all_fields.elements-i-1 : i-border)]=
49569 -+ new_item;
49570 -+ }
49571 -+
49572 -+ List_iterator_fast<Item> itr(res_all_fields);
49573 -+ for (i= 0; i < border; i++)
49574 -+ itr++;
49575 -+ itr.sublist(res_selected_fields, elements);
49576 -+
49577 -+ return thd->is_fatal_error;
49578 -+}
49579 -+
49580 -+
49581 -+
49582 -+/******************************************************************************
49583 -+ Code for calculating functions
49584 -+******************************************************************************/
49585 -+
49586 -+
49587 -+/**
49588 -+ Call ::setup for all sum functions.
49589 -+
49590 -+ @param thd thread handler
49591 -+ @param func_ptr sum function list
49592 -+
49593 -+ @retval
49594 -+ FALSE ok
49595 -+ @retval
49596 -+ TRUE error
49597 -+*/
49598 -+
49599 -+static bool setup_sum_funcs(THD *thd, Item_sum **func_ptr)
49600 -+{
49601 -+ Item_sum *func;
49602 -+ DBUG_ENTER("setup_sum_funcs");
49603 -+ while ((func= *(func_ptr++)))
49604 -+ {
49605 -+ if (func->setup(thd))
49606 -+ DBUG_RETURN(TRUE);
49607 -+ }
49608 -+ DBUG_RETURN(FALSE);
49609 -+}
49610 -+
49611 -+
49612 -+static void
49613 -+init_tmptable_sum_functions(Item_sum **func_ptr)
49614 -+{
49615 -+ Item_sum *func;
49616 -+ while ((func= *(func_ptr++)))
49617 -+ func->reset_field();
49618 -+}
49619 -+
49620 -+
49621 -+/** Update record 0 in tmp_table from record 1. */
49622 -+
49623 -+static void
49624 -+update_tmptable_sum_func(Item_sum **func_ptr,
49625 -+ TABLE *tmp_table __attribute__((unused)))
49626 -+{
49627 -+ Item_sum *func;
49628 -+ while ((func= *(func_ptr++)))
49629 -+ func->update_field();
49630 -+}
49631 -+
49632 -+
49633 -+/** Copy result of sum functions to record in tmp_table. */
49634 -+
49635 -+static void
49636 -+copy_sum_funcs(Item_sum **func_ptr, Item_sum **end_ptr)
49637 -+{
49638 -+ for (; func_ptr != end_ptr ; func_ptr++)
49639 -+ (void) (*func_ptr)->save_in_result_field(1);
49640 -+ return;
49641 -+}
49642 -+
49643 -+
49644 -+static bool
49645 -+init_sum_functions(Item_sum **func_ptr, Item_sum **end_ptr)
49646 -+{
49647 -+ for (; func_ptr != end_ptr ;func_ptr++)
49648 -+ {
49649 -+ if ((*func_ptr)->reset())
49650 -+ return 1;
49651 -+ }
49652 -+ /* If rollup, calculate the upper sum levels */
49653 -+ for ( ; *func_ptr ; func_ptr++)
49654 -+ {
49655 -+ if ((*func_ptr)->add())
49656 -+ return 1;
49657 -+ }
49658 -+ return 0;
49659 -+}
49660 -+
49661 -+
49662 -+static bool
49663 -+update_sum_func(Item_sum **func_ptr)
49664 -+{
49665 -+ Item_sum *func;
49666 -+ for (; (func= (Item_sum*) *func_ptr) ; func_ptr++)
49667 -+ if (func->add())
49668 -+ return 1;
49669 -+ return 0;
49670 -+}
49671 -+
49672 -+/**
49673 -+ Copy result of functions to record in tmp_table.
49674 -+
49675 -+ Uses the thread pointer to check for errors in
49676 -+ some of the val_xxx() methods called by the
49677 -+ save_in_result_field() function.
49678 -+ TODO: make the Item::val_xxx() return error code
49679 -+
49680 -+ @param func_ptr array of the function Items to copy to the tmp table
49681 -+ @param thd pointer to the current thread for error checking
49682 -+ @retval
49683 -+ FALSE if OK
49684 -+ @retval
49685 -+ TRUE on error
49686 -+*/
49687 -+
49688 -+bool
49689 -+copy_funcs(Item **func_ptr, const THD *thd)
49690 -+{
49691 -+ Item *func;
49692 -+ for (; (func = *func_ptr) ; func_ptr++)
49693 -+ {
49694 -+ func->save_in_result_field(1);
49695 -+ /*
49696 -+ Need to check the THD error state because Item::val_xxx() don't
49697 -+ return error code, but can generate errors
49698 -+ TODO: change it for a real status check when Item::val_xxx()
49699 -+ are extended to return status code.
49700 -+ */
49701 -+ if (thd->is_error())
49702 -+ return TRUE;
49703 -+ }
49704 -+ return FALSE;
49705 -+}
49706 -+
49707 -+
49708 -+/**
49709 -+ Create a condition for a const reference and add this to the
49710 -+ currenct select for the table.
49711 -+*/
49712 -+
49713 -+static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab)
49714 -+{
49715 -+ DBUG_ENTER("add_ref_to_table_cond");
49716 -+ if (!join_tab->ref.key_parts)
49717 -+ DBUG_RETURN(FALSE);
49718 -+
49719 -+ Item_cond_and *cond=new Item_cond_and();
49720 -+ TABLE *table=join_tab->table;
49721 -+ int error= 0;
49722 -+ if (!cond)
49723 -+ DBUG_RETURN(TRUE);
49724 -+
49725 -+ for (uint i=0 ; i < join_tab->ref.key_parts ; i++)
49726 -+ {
49727 -+ Field *field=table->field[table->key_info[join_tab->ref.key].key_part[i].
49728 -+ fieldnr-1];
49729 -+ Item *value=join_tab->ref.items[i];
49730 -+ cond->add(new Item_func_equal(new Item_field(field), value));
49731 -+ }
49732 -+ if (thd->is_fatal_error)
49733 -+ DBUG_RETURN(TRUE);
49734 -+
49735 -+ if (!cond->fixed)
49736 -+ cond->fix_fields(thd, (Item**)&cond);
49737 -+ if (join_tab->select)
49738 -+ {
49739 -+ if (join_tab->select->cond)
49740 -+ error=(int) cond->add(join_tab->select->cond);
49741 -+ join_tab->select_cond=join_tab->select->cond=cond;
49742 -+ }
49743 -+ else if ((join_tab->select= make_select(join_tab->table, 0, 0, cond, 0,
49744 -+ &error)))
49745 -+ join_tab->select_cond=cond;
49746 -+
49747 -+ DBUG_RETURN(error ? TRUE : FALSE);
49748 -+}
49749 -+
49750 -+
49751 -+/**
49752 -+ Free joins of subselect of this select.
49753 -+
49754 -+ @param thd THD pointer
49755 -+ @param select pointer to st_select_lex which subselects joins we will free
49756 -+*/
49757 -+
49758 -+void free_underlaid_joins(THD *thd, SELECT_LEX *select)
49759 -+{
49760 -+ for (SELECT_LEX_UNIT *unit= select->first_inner_unit();
49761 -+ unit;
49762 -+ unit= unit->next_unit())
49763 -+ unit->cleanup();
49764 -+}
49765 -+
49766 -+/****************************************************************************
49767 -+ ROLLUP handling
49768 -+****************************************************************************/
49769 -+
49770 -+/**
49771 -+ Replace occurences of group by fields in an expression by ref items.
49772 -+
49773 -+ The function replaces occurrences of group by fields in expr
49774 -+ by ref objects for these fields unless they are under aggregate
49775 -+ functions.
49776 -+ The function also corrects value of the the maybe_null attribute
49777 -+ for the items of all subexpressions containing group by fields.
49778 -+
49779 -+ @b EXAMPLES
49780 -+ @code
49781 -+ SELECT a+1 FROM t1 GROUP BY a WITH ROLLUP
49782 -+ SELECT SUM(a)+a FROM t1 GROUP BY a WITH ROLLUP
49783 -+ @endcode
49784 -+
49785 -+ @b IMPLEMENTATION
49786 -+
49787 -+ The function recursively traverses the tree of the expr expression,
49788 -+ looks for occurrences of the group by fields that are not under
49789 -+ aggregate functions and replaces them for the corresponding ref items.
49790 -+
49791 -+ @note
49792 -+ This substitution is needed GROUP BY queries with ROLLUP if
49793 -+ SELECT list contains expressions over group by attributes.
49794 -+
49795 -+ @param thd reference to the context
49796 -+ @param expr expression to make replacement
49797 -+ @param group_list list of references to group by items
49798 -+ @param changed out: returns 1 if item contains a replaced field item
49799 -+
49800 -+ @todo
49801 -+ - TODO: Some functions are not null-preserving. For those functions
49802 -+ updating of the maybe_null attribute is an overkill.
49803 -+
49804 -+ @retval
49805 -+ 0 if ok
49806 -+ @retval
49807 -+ 1 on error
49808 -+*/
49809 -+
49810 -+static bool change_group_ref(THD *thd, Item_func *expr, ORDER *group_list,
49811 -+ bool *changed)
49812 -+{
49813 -+ if (expr->arg_count)
49814 -+ {
49815 -+ Name_resolution_context *context= &thd->lex->current_select->context;
49816 -+ Item **arg,**arg_end;
49817 -+ bool arg_changed= FALSE;
49818 -+ for (arg= expr->arguments(),
49819 -+ arg_end= expr->arguments()+expr->arg_count;
49820 -+ arg != arg_end; arg++)
49821 -+ {
49822 -+ Item *item= *arg;
49823 -+ if (item->type() == Item::FIELD_ITEM || item->type() == Item::REF_ITEM)
49824 -+ {
49825 -+ ORDER *group_tmp;
49826 -+ for (group_tmp= group_list; group_tmp; group_tmp= group_tmp->next)
49827 -+ {
49828 -+ if (item->eq(*group_tmp->item,0))
49829 -+ {
49830 -+ Item *new_item;
49831 -+ if (!(new_item= new Item_ref(context, group_tmp->item, 0,
49832 -+ item->name)))
49833 -+ return 1; // fatal_error is set
49834 -+ thd->change_item_tree(arg, new_item);
49835 -+ arg_changed= TRUE;
49836 -+ }
49837 -+ }
49838 -+ }
49839 -+ else if (item->type() == Item::FUNC_ITEM)
49840 -+ {
49841 -+ if (change_group_ref(thd, (Item_func *) item, group_list, &arg_changed))
49842 -+ return 1;
49843 -+ }
49844 -+ }
49845 -+ if (arg_changed)
49846 -+ {
49847 -+ expr->maybe_null= 1;
49848 -+ *changed= TRUE;
49849 -+ }
49850 -+ }
49851 -+ return 0;
49852 -+}
49853 -+
49854 -+
49855 -+/** Allocate memory needed for other rollup functions. */
49856 -+
49857 -+bool JOIN::rollup_init()
49858 -+{
49859 -+ uint i,j;
49860 -+ Item **ref_array;
49861 -+
49862 -+ tmp_table_param.quick_group= 0; // Can't create groups in tmp table
49863 -+ rollup.state= ROLLUP::STATE_INITED;
49864 -+
49865 -+ /*
49866 -+ Create pointers to the different sum function groups
49867 -+ These are updated by rollup_make_fields()
49868 -+ */
49869 -+ tmp_table_param.group_parts= send_group_parts;
49870 -+
49871 -+ if (!(rollup.null_items= (Item_null_result**) thd->alloc((sizeof(Item*) +
49872 -+ sizeof(Item**) +
49873 -+ sizeof(List<Item>) +
49874 -+ ref_pointer_array_size)
49875 -+ * send_group_parts )))
49876 -+ return 1;
49877 -+
49878 -+ rollup.fields= (List<Item>*) (rollup.null_items + send_group_parts);
49879 -+ rollup.ref_pointer_arrays= (Item***) (rollup.fields + send_group_parts);
49880 -+ ref_array= (Item**) (rollup.ref_pointer_arrays+send_group_parts);
49881 -+
49882 -+ /*
49883 -+ Prepare space for field list for the different levels
49884 -+ These will be filled up in rollup_make_fields()
49885 -+ */
49886 -+ for (i= 0 ; i < send_group_parts ; i++)
49887 -+ {
49888 -+ rollup.null_items[i]= new (thd->mem_root) Item_null_result();
49889 -+ List<Item> *rollup_fields= &rollup.fields[i];
49890 -+ rollup_fields->empty();
49891 -+ rollup.ref_pointer_arrays[i]= ref_array;
49892 -+ ref_array+= all_fields.elements;
49893 -+ }
49894 -+ for (i= 0 ; i < send_group_parts; i++)
49895 -+ {
49896 -+ for (j=0 ; j < fields_list.elements ; j++)
49897 -+ rollup.fields[i].push_back(rollup.null_items[i]);
49898 -+ }
49899 -+ List_iterator<Item> it(all_fields);
49900 -+ Item *item;
49901 -+ while ((item= it++))
49902 -+ {
49903 -+ ORDER *group_tmp;
49904 -+ bool found_in_group= 0;
49905 -+
49906 -+ for (group_tmp= group_list; group_tmp; group_tmp= group_tmp->next)
49907 -+ {
49908 -+ if (*group_tmp->item == item)
49909 -+ {
49910 -+ item->maybe_null= 1;
49911 -+ found_in_group= 1;
49912 -+ break;
49913 -+ }
49914 -+ }
49915 -+ if (item->type() == Item::FUNC_ITEM && !found_in_group)
49916 -+ {
49917 -+ bool changed= FALSE;
49918 -+ if (change_group_ref(thd, (Item_func *) item, group_list, &changed))
49919 -+ return 1;
49920 -+ /*
49921 -+ We have to prevent creation of a field in a temporary table for
49922 -+ an expression that contains GROUP BY attributes.
49923 -+ Marking the expression item as 'with_sum_func' will ensure this.
49924 -+ */
49925 -+ if (changed)
49926 -+ item->with_sum_func= 1;
49927 -+ }
49928 -+ }
49929 -+ return 0;
49930 -+}
49931 -+
49932 -+/**
49933 -+ Wrap all constant Items in GROUP BY list.
49934 -+
49935 -+ For ROLLUP queries each constant item referenced in GROUP BY list
49936 -+ is wrapped up into an Item_func object yielding the same value
49937 -+ as the constant item. The objects of the wrapper class are never
49938 -+ considered as constant items and besides they inherit all
49939 -+ properties of the Item_result_field class.
49940 -+ This wrapping allows us to ensure writing constant items
49941 -+ into temporary tables whenever the result of the ROLLUP
49942 -+ operation has to be written into a temporary table, e.g. when
49943 -+ ROLLUP is used together with DISTINCT in the SELECT list.
49944 -+ Usually when creating temporary tables for a intermidiate
49945 -+ result we do not include fields for constant expressions.
49946 -+
49947 -+ @retval
49948 -+ 0 if ok
49949 -+ @retval
49950 -+ 1 on error
49951 -+*/
49952 -+
49953 -+bool JOIN::rollup_process_const_fields()
49954 -+{
49955 -+ ORDER *group_tmp;
49956 -+ Item *item;
49957 -+ List_iterator<Item> it(all_fields);
49958 -+
49959 -+ for (group_tmp= group_list; group_tmp; group_tmp= group_tmp->next)
49960 -+ {
49961 -+ if (!(*group_tmp->item)->const_item())
49962 -+ continue;
49963 -+ while ((item= it++))
49964 -+ {
49965 -+ if (*group_tmp->item == item)
49966 -+ {
49967 -+ Item* new_item= new Item_func_rollup_const(item);
49968 -+ if (!new_item)
49969 -+ return 1;
49970 -+ new_item->fix_fields(thd, (Item **) 0);
49971 -+ thd->change_item_tree(it.ref(), new_item);
49972 -+ for (ORDER *tmp= group_tmp; tmp; tmp= tmp->next)
49973 -+ {
49974 -+ if (*tmp->item == item)
49975 -+ thd->change_item_tree(tmp->item, new_item);
49976 -+ }
49977 -+ break;
49978 -+ }
49979 -+ }
49980 -+ it.rewind();
49981 -+ }
49982 -+ return 0;
49983 -+}
49984 -+
49985 -+
49986 -+/**
49987 -+ Fill up rollup structures with pointers to fields to use.
49988 -+
49989 -+ Creates copies of item_sum items for each sum level.
49990 -+
49991 -+ @param fields_arg List of all fields (hidden and real ones)
49992 -+ @param sel_fields Pointer to selected fields
49993 -+ @param func Store here a pointer to all fields
49994 -+
49995 -+ @retval
49996 -+ 0 if ok;
49997 -+ In this case func is pointing to next not used element.
49998 -+ @retval
49999 -+ 1 on error
50000 -+*/
50001 -+
50002 -+bool JOIN::rollup_make_fields(List<Item> &fields_arg, List<Item> &sel_fields,
50003 -+ Item_sum ***func)
50004 -+{
50005 -+ List_iterator_fast<Item> it(fields_arg);
50006 -+ Item *first_field= sel_fields.head();
50007 -+ uint level;
50008 -+
50009 -+ /*
50010 -+ Create field lists for the different levels
50011 -+
50012 -+ The idea here is to have a separate field list for each rollup level to
50013 -+ avoid all runtime checks of which columns should be NULL.
50014 -+
50015 -+ The list is stored in reverse order to get sum function in such an order
50016 -+ in func that it makes it easy to reset them with init_sum_functions()
50017 -+
50018 -+ Assuming: SELECT a, b, c SUM(b) FROM t1 GROUP BY a,b WITH ROLLUP
50019 -+
50020 -+ rollup.fields[0] will contain list where a,b,c is NULL
50021 -+ rollup.fields[1] will contain list where b,c is NULL
50022 -+ ...
50023 -+ rollup.ref_pointer_array[#] points to fields for rollup.fields[#]
50024 -+ ...
50025 -+ sum_funcs_end[0] points to all sum functions
50026 -+ sum_funcs_end[1] points to all sum functions, except grand totals
50027 -+ ...
50028 -+ */
50029 -+
50030 -+ for (level=0 ; level < send_group_parts ; level++)
50031 -+ {
50032 -+ uint i;
50033 -+ uint pos= send_group_parts - level -1;
50034 -+ bool real_fields= 0;
50035 -+ Item *item;
50036 -+ List_iterator<Item> new_it(rollup.fields[pos]);
50037 -+ Item **ref_array_start= rollup.ref_pointer_arrays[pos];
50038 -+ ORDER *start_group;
50039 -+
50040 -+ /* Point to first hidden field */
50041 -+ Item **ref_array= ref_array_start + fields_arg.elements-1;
50042 -+
50043 -+ /* Remember where the sum functions ends for the previous level */
50044 -+ sum_funcs_end[pos+1]= *func;
50045 -+
50046 -+ /* Find the start of the group for this level */
50047 -+ for (i= 0, start_group= group_list ;
50048 -+ i++ < pos ;
50049 -+ start_group= start_group->next)
50050 -+ ;
50051 -+
50052 -+ it.rewind();
50053 -+ while ((item= it++))
50054 -+ {
50055 -+ if (item == first_field)
50056 -+ {
50057 -+ real_fields= 1; // End of hidden fields
50058 -+ ref_array= ref_array_start;
50059 -+ }
50060 -+
50061 -+ if (item->type() == Item::SUM_FUNC_ITEM && !item->const_item() &&
50062 -+ (!((Item_sum*) item)->depended_from() ||
50063 -+ ((Item_sum *)item)->depended_from() == select_lex))
50064 -+
50065 -+ {
50066 -+ /*
50067 -+ This is a top level summary function that must be replaced with
50068 -+ a sum function that is reset for this level.
50069 -+
50070 -+ NOTE: This code creates an object which is not that nice in a
50071 -+ sub select. Fortunately it's not common to have rollup in
50072 -+ sub selects.
50073 -+ */
50074 -+ item= item->copy_or_same(thd);
50075 -+ ((Item_sum*) item)->make_unique();
50076 -+ *(*func)= (Item_sum*) item;
50077 -+ (*func)++;
50078 -+ }
50079 -+ else
50080 -+ {
50081 -+ /* Check if this is something that is part of this group by */
50082 -+ ORDER *group_tmp;
50083 -+ for (group_tmp= start_group, i= pos ;
50084 -+ group_tmp ; group_tmp= group_tmp->next, i++)
50085 -+ {
50086 -+ if (*group_tmp->item == item)
50087 -+ {
50088 -+ /*
50089 -+ This is an element that is used by the GROUP BY and should be
50090 -+ set to NULL in this level
50091 -+ */
50092 -+ Item_null_result *null_item= new (thd->mem_root) Item_null_result();
50093 -+ if (!null_item)
50094 -+ return 1;
50095 -+ item->maybe_null= 1; // Value will be null sometimes
50096 -+ null_item->result_field= item->get_tmp_table_field();
50097 -+ item= null_item;
50098 -+ break;
50099 -+ }
50100 -+ }
50101 -+ }
50102 -+ *ref_array= item;
50103 -+ if (real_fields)
50104 -+ {
50105 -+ (void) new_it++; // Point to next item
50106 -+ new_it.replace(item); // Replace previous
50107 -+ ref_array++;
50108 -+ }
50109 -+ else
50110 -+ ref_array--;
50111 -+ }
50112 -+ }
50113 -+ sum_funcs_end[0]= *func; // Point to last function
50114 -+ return 0;
50115 -+}
50116 -+
50117 -+/**
50118 -+ Send all rollup levels higher than the current one to the client.
50119 -+
50120 -+ @b SAMPLE
50121 -+ @code
50122 -+ SELECT a, b, c SUM(b) FROM t1 GROUP BY a,b WITH ROLLUP
50123 -+ @endcode
50124 -+
50125 -+ @param idx Level we are on:
50126 -+ - 0 = Total sum level
50127 -+ - 1 = First group changed (a)
50128 -+ - 2 = Second group changed (a,b)
50129 -+
50130 -+ @retval
50131 -+ 0 ok
50132 -+ @retval
50133 -+ 1 If send_data_failed()
50134 -+*/
50135 -+
50136 -+int JOIN::rollup_send_data(uint idx)
50137 -+{
50138 -+ uint i;
50139 -+ for (i= send_group_parts ; i-- > idx ; )
50140 -+ {
50141 -+ /* Get reference pointers to sum functions in place */
50142 -+ memcpy((char*) ref_pointer_array,
50143 -+ (char*) rollup.ref_pointer_arrays[i],
50144 -+ ref_pointer_array_size);
50145 -+ if ((!having || having->val_int()))
50146 -+ {
50147 -+ if (send_records < unit->select_limit_cnt && do_send_rows &&
50148 -+ result->send_data(rollup.fields[i]))
50149 -+ return 1;
50150 -+ send_records++;
50151 -+ }
50152 -+ }
50153 -+ /* Restore ref_pointer_array */
50154 -+ set_items_ref_array(current_ref_pointer_array);
50155 -+ return 0;
50156 -+}
50157 -+
50158 -+/**
50159 -+ Write all rollup levels higher than the current one to a temp table.
50160 -+
50161 -+ @b SAMPLE
50162 -+ @code
50163 -+ SELECT a, b, SUM(c) FROM t1 GROUP BY a,b WITH ROLLUP
50164 -+ @endcode
50165 -+
50166 -+ @param idx Level we are on:
50167 -+ - 0 = Total sum level
50168 -+ - 1 = First group changed (a)
50169 -+ - 2 = Second group changed (a,b)
50170 -+ @param table reference to temp table
50171 -+
50172 -+ @retval
50173 -+ 0 ok
50174 -+ @retval
50175 -+ 1 if write_data_failed()
50176 -+*/
50177 -+
50178 -+int JOIN::rollup_write_data(uint idx, TABLE *table_arg)
50179 -+{
50180 -+ uint i;
50181 -+ for (i= send_group_parts ; i-- > idx ; )
50182 -+ {
50183 -+ /* Get reference pointers to sum functions in place */
50184 -+ memcpy((char*) ref_pointer_array,
50185 -+ (char*) rollup.ref_pointer_arrays[i],
50186 -+ ref_pointer_array_size);
50187 -+ if ((!having || having->val_int()))
50188 -+ {
50189 -+ int write_error;
50190 -+ Item *item;
50191 -+ List_iterator_fast<Item> it(rollup.fields[i]);
50192 -+ while ((item= it++))
50193 -+ {
50194 -+ if (item->type() == Item::NULL_ITEM && item->is_result_field())
50195 -+ item->save_in_result_field(1);
50196 -+ }
50197 -+ copy_sum_funcs(sum_funcs_end[i+1], sum_funcs_end[i]);
50198 -+ if ((write_error= table_arg->file->ha_write_row(table_arg->record[0])))
50199 -+ {
50200 -+ if (create_myisam_from_heap(thd, table_arg, &tmp_table_param,
50201 -+ write_error, 0))
50202 -+ return 1;
50203 -+ }
50204 -+ }
50205 -+ }
50206 -+ /* Restore ref_pointer_array */
50207 -+ set_items_ref_array(current_ref_pointer_array);
50208 -+ return 0;
50209 -+}
50210 -+
50211 -+/**
50212 -+ clear results if there are not rows found for group
50213 -+ (end_send_group/end_write_group)
50214 -+*/
50215 -+
50216 -+void JOIN::clear()
50217 -+{
50218 -+ clear_tables(this);
50219 -+ copy_fields(&tmp_table_param);
50220 -+
50221 -+ if (sum_funcs)
50222 -+ {
50223 -+ Item_sum *func, **func_ptr= sum_funcs;
50224 -+ while ((func= *(func_ptr++)))
50225 -+ func->clear();
50226 -+ }
50227 -+}
50228 -+
50229 -+/**
50230 -+ EXPLAIN handling.
50231 -+
50232 -+ Send a description about what how the select will be done to stdout.
50233 -+*/
50234 -+
50235 -+static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
50236 -+ bool distinct,const char *message)
50237 -+{
50238 -+ List<Item> field_list;
50239 -+ List<Item> item_list;
50240 -+ THD *thd=join->thd;
50241 -+ select_result *result=join->result;
50242 -+ Item *item_null= new Item_null();
50243 -+ CHARSET_INFO *cs= system_charset_info;
50244 -+ int quick_type;
50245 -+ DBUG_ENTER("select_describe");
50246 -+ DBUG_PRINT("info", ("Select 0x%lx, type %s, message %s",
50247 -+ (ulong)join->select_lex, join->select_lex->type,
50248 -+ message ? message : "NULL"));
50249 -+ /* Don't log this into the slow query log */
50250 -+ thd->server_status&= ~(SERVER_QUERY_NO_INDEX_USED | SERVER_QUERY_NO_GOOD_INDEX_USED);
50251 -+ join->unit->offset_limit_cnt= 0;
50252 -+
50253 -+ /*
50254 -+ NOTE: the number/types of items pushed into item_list must be in sync with
50255 -+ EXPLAIN column types as they're "defined" in THD::send_explain_fields()
50256 -+ */
50257 -+ if (message)
50258 -+ {
50259 -+ item_list.push_back(new Item_int((int32)
50260 -+ join->select_lex->select_number));
50261 -+ item_list.push_back(new Item_string(join->select_lex->type,
50262 -+ strlen(join->select_lex->type), cs));
50263 -+ for (uint i=0 ; i < 7; i++)
50264 -+ item_list.push_back(item_null);
50265 -+ if (join->thd->lex->describe & DESCRIBE_PARTITIONS)
50266 -+ item_list.push_back(item_null);
50267 -+ if (join->thd->lex->describe & DESCRIBE_EXTENDED)
50268 -+ item_list.push_back(item_null);
50269 -+
50270 -+ item_list.push_back(new Item_string(message,strlen(message),cs));
50271 -+ if (result->send_data(item_list))
50272 -+ join->error= 1;
50273 -+ }
50274 -+ else if (join->select_lex == join->unit->fake_select_lex)
50275 -+ {
50276 -+ /*
50277 -+ here we assume that the query will return at least two rows, so we
50278 -+ show "filesort" in EXPLAIN. Of course, sometimes we'll be wrong
50279 -+ and no filesort will be actually done, but executing all selects in
50280 -+ the UNION to provide precise EXPLAIN information will hardly be
50281 -+ appreciated :)
50282 -+ */
50283 -+ char table_name_buffer[NAME_LEN];
50284 -+ item_list.empty();
50285 -+ /* id */
50286 -+ item_list.push_back(new Item_null);
50287 -+ /* select_type */
50288 -+ item_list.push_back(new Item_string(join->select_lex->type,
50289 -+ strlen(join->select_lex->type),
50290 -+ cs));
50291 -+ /* table */
50292 -+ {
50293 -+ SELECT_LEX *sl= join->unit->first_select();
50294 -+ uint len= 6, lastop= 0;
50295 -+ memcpy(table_name_buffer, STRING_WITH_LEN("<union"));
50296 -+ for (; sl && len + lastop + 5 < NAME_LEN; sl= sl->next_select())
50297 -+ {
50298 -+ len+= lastop;
50299 -+ lastop= my_snprintf(table_name_buffer + len, NAME_LEN - len,
50300 -+ "%u,", sl->select_number);
50301 -+ }
50302 -+ if (sl || len + lastop >= NAME_LEN)
50303 -+ {
50304 -+ memcpy(table_name_buffer + len, STRING_WITH_LEN("...>") + 1);
50305 -+ len+= 4;
50306 -+ }
50307 -+ else
50308 -+ {
50309 -+ len+= lastop;
50310 -+ table_name_buffer[len - 1]= '>'; // change ',' to '>'
50311 -+ }
50312 -+ item_list.push_back(new Item_string(table_name_buffer, len, cs));
50313 -+ }
50314 -+ /* partitions */
50315 -+ if (join->thd->lex->describe & DESCRIBE_PARTITIONS)
50316 -+ item_list.push_back(item_null);
50317 -+ /* type */
50318 -+ item_list.push_back(new Item_string(join_type_str[JT_ALL],
50319 -+ strlen(join_type_str[JT_ALL]),
50320 -+ cs));
50321 -+ /* possible_keys */
50322 -+ item_list.push_back(item_null);
50323 -+ /* key*/
50324 -+ item_list.push_back(item_null);
50325 -+ /* key_len */
50326 -+ item_list.push_back(item_null);
50327 -+ /* ref */
50328 -+ item_list.push_back(item_null);
50329 -+ /* in_rows */
50330 -+ if (join->thd->lex->describe & DESCRIBE_EXTENDED)
50331 -+ item_list.push_back(item_null);
50332 -+ /* rows */
50333 -+ item_list.push_back(item_null);
50334 -+ /* extra */
50335 -+ if (join->unit->global_parameters->order_list.first)
50336 -+ item_list.push_back(new Item_string("Using filesort",
50337 -+ 14, cs));
50338 -+ else
50339 -+ item_list.push_back(new Item_string("", 0, cs));
50340 -+
50341 -+ if (result->send_data(item_list))
50342 -+ join->error= 1;
50343 -+ }
50344 -+ else
50345 -+ {
50346 -+ table_map used_tables=0;
50347 -+ for (uint i=0 ; i < join->tables ; i++)
50348 -+ {
50349 -+ JOIN_TAB *tab=join->join_tab+i;
50350 -+ TABLE *table=tab->table;
50351 -+ TABLE_LIST *table_list= tab->table->pos_in_table_list;
50352 -+ char buff[512];
50353 -+ char buff1[512], buff2[512], buff3[512];
50354 -+ char keylen_str_buf[64];
50355 -+ String extra(buff, sizeof(buff),cs);
50356 -+ char table_name_buffer[NAME_LEN];
50357 -+ String tmp1(buff1,sizeof(buff1),cs);
50358 -+ String tmp2(buff2,sizeof(buff2),cs);
50359 -+ String tmp3(buff3,sizeof(buff3),cs);
50360 -+ extra.length(0);
50361 -+ tmp1.length(0);
50362 -+ tmp2.length(0);
50363 -+ tmp3.length(0);
50364 -+
50365 -+ quick_type= -1;
50366 -+ item_list.empty();
50367 -+ /* id */
50368 -+ item_list.push_back(new Item_uint((uint32)
50369 -+ join->select_lex->select_number));
50370 -+ /* select_type */
50371 -+ item_list.push_back(new Item_string(join->select_lex->type,
50372 -+ strlen(join->select_lex->type),
50373 -+ cs));
50374 -+ if (tab->type == JT_ALL && tab->select && tab->select->quick)
50375 -+ {
50376 -+ quick_type= tab->select->quick->get_type();
50377 -+ if ((quick_type == QUICK_SELECT_I::QS_TYPE_INDEX_MERGE) ||
50378 -+ (quick_type == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT) ||
50379 -+ (quick_type == QUICK_SELECT_I::QS_TYPE_ROR_UNION))
50380 -+ tab->type = JT_INDEX_MERGE;
50381 -+ else
50382 -+ tab->type = JT_RANGE;
50383 -+ }
50384 -+ /* table */
50385 -+ if (table->derived_select_number)
50386 -+ {
50387 -+ /* Derived table name generation */
50388 -+ int len= my_snprintf(table_name_buffer, sizeof(table_name_buffer)-1,
50389 -+ "<derived%u>",
50390 -+ table->derived_select_number);
50391 -+ item_list.push_back(new Item_string(table_name_buffer, len, cs));
50392 -+ }
50393 -+ else
50394 -+ {
50395 -+ TABLE_LIST *real_table= table->pos_in_table_list;
50396 -+ item_list.push_back(new Item_string(real_table->alias,
50397 -+ strlen(real_table->alias),
50398 -+ cs));
50399 -+ }
50400 -+ /* "partitions" column */
50401 -+ if (join->thd->lex->describe & DESCRIBE_PARTITIONS)
50402 -+ {
50403 -+#ifdef WITH_PARTITION_STORAGE_ENGINE
50404 -+ partition_info *part_info;
50405 -+ if (!table->derived_select_number &&
50406 -+ (part_info= table->part_info))
50407 -+ {
50408 -+ Item_string *item_str= new Item_string(cs);
50409 -+ make_used_partitions_str(part_info, &item_str->str_value);
50410 -+ item_list.push_back(item_str);
50411 -+ }
50412 -+ else
50413 -+ item_list.push_back(item_null);
50414 -+#else
50415 -+ /* just produce empty column if partitioning is not compiled in */
50416 -+ item_list.push_back(item_null);
50417 -+#endif
50418 -+ }
50419 -+ /* "type" column */
50420 -+ item_list.push_back(new Item_string(join_type_str[tab->type],
50421 -+ strlen(join_type_str[tab->type]),
50422 -+ cs));
50423 -+ /* Build "possible_keys" value and add it to item_list */
50424 -+ if (!tab->keys.is_clear_all())
50425 -+ {
50426 -+ uint j;
50427 -+ for (j=0 ; j < table->s->keys ; j++)
50428 -+ {
50429 -+ if (tab->keys.is_set(j))
50430 -+ {
50431 -+ if (tmp1.length())
50432 -+ tmp1.append(',');
50433 -+ tmp1.append(table->key_info[j].name,
50434 -+ strlen(table->key_info[j].name),
50435 -+ system_charset_info);
50436 -+ }
50437 -+ }
50438 -+ }
50439 -+ if (tmp1.length())
50440 -+ item_list.push_back(new Item_string(tmp1.ptr(),tmp1.length(),cs));
50441 -+ else
50442 -+ item_list.push_back(item_null);
50443 -+
50444 -+ /* Build "key", "key_len", and "ref" values and add them to item_list */
50445 -+ if (tab->ref.key_parts)
50446 -+ {
50447 -+ KEY *key_info=table->key_info+ tab->ref.key;
50448 -+ register uint length;
50449 -+ item_list.push_back(new Item_string(key_info->name,
50450 -+ strlen(key_info->name),
50451 -+ system_charset_info));
50452 -+ length= longlong2str(tab->ref.key_length, keylen_str_buf, 10) -
50453 -+ keylen_str_buf;
50454 -+ item_list.push_back(new Item_string(keylen_str_buf, length,
50455 -+ system_charset_info));
50456 -+ for (store_key **ref=tab->ref.key_copy ; *ref ; ref++)
50457 -+ {
50458 -+ if (tmp2.length())
50459 -+ tmp2.append(',');
50460 -+ tmp2.append((*ref)->name(), strlen((*ref)->name()),
50461 -+ system_charset_info);
50462 -+ }
50463 -+ item_list.push_back(new Item_string(tmp2.ptr(),tmp2.length(),cs));
50464 -+ }
50465 -+ else if (tab->type == JT_NEXT)
50466 -+ {
50467 -+ KEY *key_info=table->key_info+ tab->index;
50468 -+ register uint length;
50469 -+ item_list.push_back(new Item_string(key_info->name,
50470 -+ strlen(key_info->name),cs));
50471 -+ length= longlong2str(key_info->key_length, keylen_str_buf, 10) -
50472 -+ keylen_str_buf;
50473 -+ item_list.push_back(new Item_string(keylen_str_buf,
50474 -+ length,
50475 -+ system_charset_info));
50476 -+ item_list.push_back(item_null);
50477 -+ }
50478 -+ else if (tab->select && tab->select->quick)
50479 -+ {
50480 -+ tab->select->quick->add_keys_and_lengths(&tmp2, &tmp3);
50481 -+ item_list.push_back(new Item_string(tmp2.ptr(),tmp2.length(),cs));
50482 -+ item_list.push_back(new Item_string(tmp3.ptr(),tmp3.length(),cs));
50483 -+ item_list.push_back(item_null);
50484 -+ }
50485 -+ else
50486 -+ {
50487 -+ if (table_list->schema_table &&
50488 -+ table_list->schema_table->i_s_requested_object & OPTIMIZE_I_S_TABLE)
50489 -+ {
50490 -+ const char *tmp_buff;
50491 -+ int f_idx;
50492 -+ if (table_list->has_db_lookup_value)
50493 -+ {
50494 -+ f_idx= table_list->schema_table->idx_field1;
50495 -+ tmp_buff= table_list->schema_table->fields_info[f_idx].field_name;
50496 -+ tmp2.append(tmp_buff, strlen(tmp_buff), cs);
50497 -+ }
50498 -+ if (table_list->has_table_lookup_value)
50499 -+ {
50500 -+ if (table_list->has_db_lookup_value)
50501 -+ tmp2.append(',');
50502 -+ f_idx= table_list->schema_table->idx_field2;
50503 -+ tmp_buff= table_list->schema_table->fields_info[f_idx].field_name;
50504 -+ tmp2.append(tmp_buff, strlen(tmp_buff), cs);
50505 -+ }
50506 -+ if (tmp2.length())
50507 -+ item_list.push_back(new Item_string(tmp2.ptr(),tmp2.length(),cs));
50508 -+ else
50509 -+ item_list.push_back(item_null);
50510 -+ }
50511 -+ else
50512 -+ item_list.push_back(item_null);
50513 -+ item_list.push_back(item_null);
50514 -+ item_list.push_back(item_null);
50515 -+ }
50516 -+
50517 -+ /* Add "rows" field to item_list. */
50518 -+ if (table_list->schema_table)
50519 -+ {
50520 -+ /* in_rows */
50521 -+ if (join->thd->lex->describe & DESCRIBE_EXTENDED)
50522 -+ item_list.push_back(item_null);
50523 -+ /* rows */
50524 -+ item_list.push_back(item_null);
50525 -+ }
50526 -+ else
50527 -+ {
50528 -+ ha_rows examined_rows;
50529 -+ if (tab->select && tab->select->quick)
50530 -+ examined_rows= tab->select->quick->records;
50531 -+ else if (tab->type == JT_NEXT || tab->type == JT_ALL)
50532 -+ {
50533 -+ if (tab->limit)
50534 -+ examined_rows= tab->limit;
50535 -+ else
50536 -+ {
50537 -+ tab->table->file->info(HA_STATUS_VARIABLE);
50538 -+ examined_rows= tab->table->file->stats.records;
50539 -+ }
50540 -+ }
50541 -+ else
50542 -+ examined_rows=(ha_rows)join->best_positions[i].records_read;
50543 -+
50544 -+ item_list.push_back(new Item_int((longlong) (ulonglong) examined_rows,
50545 -+ MY_INT64_NUM_DECIMAL_DIGITS));
50546 -+
50547 -+ /* Add "filtered" field to item_list. */
50548 -+ if (join->thd->lex->describe & DESCRIBE_EXTENDED)
50549 -+ {
50550 -+ float f= 0.0;
50551 -+ if (examined_rows)
50552 -+ f= (float) (100.0 * join->best_positions[i].records_read /
50553 -+ examined_rows);
50554 -+ item_list.push_back(new Item_float(f, 2));
50555 -+ }
50556 -+ }
50557 -+
50558 -+ /* Build "Extra" field and add it to item_list. */
50559 -+ my_bool key_read=table->key_read;
50560 -+ if ((tab->type == JT_NEXT || tab->type == JT_CONST) &&
50561 -+ table->covering_keys.is_set(tab->index))
50562 -+ key_read=1;
50563 -+ if (quick_type == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT &&
50564 -+ !((QUICK_ROR_INTERSECT_SELECT*)tab->select->quick)->need_to_fetch_row)
50565 -+ key_read=1;
50566 -+
50567 -+ if (tab->info)
50568 -+ item_list.push_back(new Item_string(tab->info,strlen(tab->info),cs));
50569 -+ else if (tab->packed_info & TAB_INFO_HAVE_VALUE)
50570 -+ {
50571 -+ if (tab->packed_info & TAB_INFO_USING_INDEX)
50572 -+ extra.append(STRING_WITH_LEN("; Using index"));
50573 -+ if (tab->packed_info & TAB_INFO_USING_WHERE)
50574 -+ extra.append(STRING_WITH_LEN("; Using where"));
50575 -+ if (tab->packed_info & TAB_INFO_FULL_SCAN_ON_NULL)
50576 -+ extra.append(STRING_WITH_LEN("; Full scan on NULL key"));
50577 -+ /* Skip initial "; "*/
50578 -+ const char *str= extra.ptr();
50579 -+ uint32 len= extra.length();
50580 -+ if (len)
50581 -+ {
50582 -+ str += 2;
50583 -+ len -= 2;
50584 -+ }
50585 -+ item_list.push_back(new Item_string(str, len, cs));
50586 -+ }
50587 -+ else
50588 -+ {
50589 -+ if (quick_type == QUICK_SELECT_I::QS_TYPE_ROR_UNION ||
50590 -+ quick_type == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT ||
50591 -+ quick_type == QUICK_SELECT_I::QS_TYPE_INDEX_MERGE)
50592 -+ {
50593 -+ extra.append(STRING_WITH_LEN("; Using "));
50594 -+ tab->select->quick->add_info_string(&extra);
50595 -+ }
50596 -+ if (tab->select)
50597 -+ {
50598 -+ if (tab->use_quick == 2)
50599 -+ {
50600 -+ /* 4 bits per 1 hex digit + terminating '\0' */
50601 -+ char buf[MAX_KEY / 4 + 1];
50602 -+ extra.append(STRING_WITH_LEN("; Range checked for each "
50603 -+ "record (index map: 0x"));
50604 -+ extra.append(tab->keys.print(buf));
50605 -+ extra.append(')');
50606 -+ }
50607 -+ else if (tab->select->cond)
50608 -+ {
50609 -+ const COND *pushed_cond= tab->table->file->pushed_cond;
50610 -+
50611 -+ if (thd->variables.engine_condition_pushdown && pushed_cond)
50612 -+ {
50613 -+ extra.append(STRING_WITH_LEN("; Using where with pushed "
50614 -+ "condition"));
50615 -+ if (thd->lex->describe & DESCRIBE_EXTENDED)
50616 -+ {
50617 -+ extra.append(STRING_WITH_LEN(": "));
50618 -+ ((COND *)pushed_cond)->print(&extra, QT_ORDINARY);
50619 -+ }
50620 -+ }
50621 -+ else
50622 -+ extra.append(STRING_WITH_LEN("; Using where"));
50623 -+ }
50624 -+ }
50625 -+ if (table_list->schema_table &&
50626 -+ table_list->schema_table->i_s_requested_object & OPTIMIZE_I_S_TABLE)
50627 -+ {
50628 -+ if (!table_list->table_open_method)
50629 -+ extra.append(STRING_WITH_LEN("; Skip_open_table"));
50630 -+ else if (table_list->table_open_method == OPEN_FRM_ONLY)
50631 -+ extra.append(STRING_WITH_LEN("; Open_frm_only"));
50632 -+ else
50633 -+ extra.append(STRING_WITH_LEN("; Open_full_table"));
50634 -+ if (table_list->has_db_lookup_value &&
50635 -+ table_list->has_table_lookup_value)
50636 -+ extra.append(STRING_WITH_LEN("; Scanned 0 databases"));
50637 -+ else if (table_list->has_db_lookup_value ||
50638 -+ table_list->has_table_lookup_value)
50639 -+ extra.append(STRING_WITH_LEN("; Scanned 1 database"));
50640 -+ else
50641 -+ extra.append(STRING_WITH_LEN("; Scanned all databases"));
50642 -+ }
50643 -+ if (key_read)
50644 -+ {
50645 -+ if (quick_type == QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX)
50646 -+ extra.append(STRING_WITH_LEN("; Using index for group-by"));
50647 -+ else
50648 -+ extra.append(STRING_WITH_LEN("; Using index"));
50649 -+ }
50650 -+ if (table->reginfo.not_exists_optimize)
50651 -+ extra.append(STRING_WITH_LEN("; Not exists"));
50652 -+ if (need_tmp_table)
50653 -+ {
50654 -+ need_tmp_table=0;
50655 -+ extra.append(STRING_WITH_LEN("; Using temporary"));
50656 -+ }
50657 -+ if (need_order)
50658 -+ {
50659 -+ need_order=0;
50660 -+ extra.append(STRING_WITH_LEN("; Using filesort"));
50661 -+ }
50662 -+ if (distinct & test_all_bits(used_tables,thd->used_tables))
50663 -+ extra.append(STRING_WITH_LEN("; Distinct"));
50664 -+
50665 -+ for (uint part= 0; part < tab->ref.key_parts; part++)
50666 -+ {
50667 -+ if (tab->ref.cond_guards[part])
50668 -+ {
50669 -+ extra.append(STRING_WITH_LEN("; Full scan on NULL key"));
50670 -+ break;
50671 -+ }
50672 -+ }
50673 -+ if (i > 0 && tab[-1].next_select == sub_select_cache)
50674 -+ extra.append(STRING_WITH_LEN("; Using join buffer"));
50675 -+
50676 -+ /* Skip initial "; "*/
50677 -+ const char *str= extra.ptr();
50678 -+ uint32 len= extra.length();
50679 -+ if (len)
50680 -+ {
50681 -+ str += 2;
50682 -+ len -= 2;
50683 -+ }
50684 -+ item_list.push_back(new Item_string(str, len, cs));
50685 -+ }
50686 -+ // For next iteration
50687 -+ used_tables|=table->map;
50688 -+ if (result->send_data(item_list))
50689 -+ join->error= 1;
50690 -+ }
50691 -+ }
50692 -+ for (SELECT_LEX_UNIT *unit= join->select_lex->first_inner_unit();
50693 -+ unit;
50694 -+ unit= unit->next_unit())
50695 -+ {
50696 -+ if (mysql_explain_union(thd, unit, result))
50697 -+ DBUG_VOID_RETURN;
50698 -+ }
50699 -+ DBUG_VOID_RETURN;
50700 -+}
50701 -+
50702 -+
50703 -+bool mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result)
50704 -+{
50705 -+ DBUG_ENTER("mysql_explain_union");
50706 -+ bool res= 0;
50707 -+ SELECT_LEX *first= unit->first_select();
50708 -+
50709 -+ for (SELECT_LEX *sl= first;
50710 -+ sl;
50711 -+ sl= sl->next_select())
50712 -+ {
50713 -+ // drop UNCACHEABLE_EXPLAIN, because it is for internal usage only
50714 -+ uint8 uncacheable= (sl->uncacheable & ~UNCACHEABLE_EXPLAIN);
50715 -+ sl->type= (((&thd->lex->select_lex)==sl)?
50716 -+ (sl->first_inner_unit() || sl->next_select() ?
50717 -+ "PRIMARY" : "SIMPLE"):
50718 -+ ((sl == first)?
50719 -+ ((sl->linkage == DERIVED_TABLE_TYPE) ?
50720 -+ "DERIVED":
50721 -+ ((uncacheable & UNCACHEABLE_DEPENDENT) ?
50722 -+ "DEPENDENT SUBQUERY":
50723 -+ (uncacheable?"UNCACHEABLE SUBQUERY":
50724 -+ "SUBQUERY"))):
50725 -+ ((uncacheable & UNCACHEABLE_DEPENDENT) ?
50726 -+ "DEPENDENT UNION":
50727 -+ uncacheable?"UNCACHEABLE UNION":
50728 -+ "UNION")));
50729 -+ sl->options|= SELECT_DESCRIBE;
50730 -+ }
50731 -+ if (unit->is_union())
50732 -+ {
50733 -+ unit->fake_select_lex->select_number= UINT_MAX; // jost for initialization
50734 -+ unit->fake_select_lex->type= "UNION RESULT";
50735 -+ unit->fake_select_lex->options|= SELECT_DESCRIBE;
50736 -+ if (!(res= unit->prepare(thd, result, SELECT_NO_UNLOCK | SELECT_DESCRIBE)))
50737 -+ res= unit->exec();
50738 -+ res|= unit->cleanup();
50739 -+ }
50740 -+ else
50741 -+ {
50742 -+ thd->lex->current_select= first;
50743 -+ unit->set_limit(unit->global_parameters);
50744 -+ res= mysql_select(thd, &first->ref_pointer_array,
50745 -+ first->table_list.first,
50746 -+ first->with_wild, first->item_list,
50747 -+ first->where,
50748 -+ first->order_list.elements +
50749 -+ first->group_list.elements,
50750 -+ first->order_list.first,
50751 -+ first->group_list.first,
50752 -+ first->having,
50753 -+ thd->lex->proc_list.first,
50754 -+ first->options | thd->options | SELECT_DESCRIBE,
50755 -+ result, unit, first);
50756 -+ }
50757 -+ DBUG_RETURN(res || thd->is_error());
50758 -+}
50759 -+
50760 -+
50761 -+/**
50762 -+ Print joins from the FROM clause.
50763 -+
50764 -+ @param thd thread handler
50765 -+ @param str string where table should be printed
50766 -+ @param tables list of tables in join
50767 -+ @query_type type of the query is being generated
50768 -+*/
50769 -+
50770 -+static void print_join(THD *thd,
50771 -+ String *str,
50772 -+ List<TABLE_LIST> *tables,
50773 -+ enum_query_type query_type)
50774 -+{
50775 -+ /* List is reversed => we should reverse it before using */
50776 -+ List_iterator_fast<TABLE_LIST> ti(*tables);
50777 -+ TABLE_LIST **table= (TABLE_LIST **)thd->alloc(sizeof(TABLE_LIST*) *
50778 -+ tables->elements);
50779 -+ if (table == 0)
50780 -+ return; // out of memory
50781 -+
50782 -+ for (TABLE_LIST **t= table + (tables->elements - 1); t >= table; t--)
50783 -+ *t= ti++;
50784 -+
50785 -+ DBUG_ASSERT(tables->elements >= 1);
50786 -+ (*table)->print(thd, str, query_type);
50787 -+
50788 -+ TABLE_LIST **end= table + tables->elements;
50789 -+ for (TABLE_LIST **tbl= table + 1; tbl < end; tbl++)
50790 -+ {
50791 -+ TABLE_LIST *curr= *tbl;
50792 -+ if (curr->outer_join)
50793 -+ {
50794 -+ /* MySQL converts right to left joins */
50795 -+ str->append(STRING_WITH_LEN(" left join "));
50796 -+ }
50797 -+ else if (curr->straight)
50798 -+ str->append(STRING_WITH_LEN(" straight_join "));
50799 -+ else
50800 -+ str->append(STRING_WITH_LEN(" join "));
50801 -+ curr->print(thd, str, query_type);
50802 -+ if (curr->on_expr)
50803 -+ {
50804 -+ str->append(STRING_WITH_LEN(" on("));
50805 -+ curr->on_expr->print(str, query_type);
50806 -+ str->append(')');
50807 -+ }
50808 -+ }
50809 -+}
50810 -+
50811 -+
50812 -+/**
50813 -+ @brief Print an index hint
50814 -+
50815 -+ @details Prints out the USE|FORCE|IGNORE index hint.
50816 -+
50817 -+ @param thd the current thread
50818 -+ @param[out] str appends the index hint here
50819 -+ @param hint what the hint is (as string : "USE INDEX"|
50820 -+ "FORCE INDEX"|"IGNORE INDEX")
50821 -+ @param hint_length the length of the string in 'hint'
50822 -+ @param indexes a list of index names for the hint
50823 -+*/
50824 -+
50825 -+void
50826 -+Index_hint::print(THD *thd, String *str)
50827 -+{
50828 -+ switch (type)
50829 -+ {
50830 -+ case INDEX_HINT_IGNORE: str->append(STRING_WITH_LEN("IGNORE INDEX")); break;
50831 -+ case INDEX_HINT_USE: str->append(STRING_WITH_LEN("USE INDEX")); break;
50832 -+ case INDEX_HINT_FORCE: str->append(STRING_WITH_LEN("FORCE INDEX")); break;
50833 -+ }
50834 -+ str->append (STRING_WITH_LEN(" ("));
50835 -+ if (key_name.length)
50836 -+ {
50837 -+ if (thd && !my_strnncoll(system_charset_info,
50838 -+ (const uchar *)key_name.str, key_name.length,
50839 -+ (const uchar *)primary_key_name,
50840 -+ strlen(primary_key_name)))
50841 -+ str->append(primary_key_name);
50842 -+ else
50843 -+ append_identifier(thd, str, key_name.str, key_name.length);
50844 -+ }
50845 -+ str->append(')');
50846 -+}
50847 -+
50848 -+
50849 -+/**
50850 -+ Print table as it should be in join list.
50851 -+
50852 -+ @param str string where table should be printed
50853 -+*/
50854 -+
50855 -+void TABLE_LIST::print(THD *thd, String *str, enum_query_type query_type)
50856 -+{
50857 -+ if (nested_join)
50858 -+ {
50859 -+ str->append('(');
50860 -+ print_join(thd, str, &nested_join->join_list, query_type);
50861 -+ str->append(')');
50862 -+ }
50863 -+ else
50864 -+ {
50865 -+ const char *cmp_name; // Name to compare with alias
50866 -+ if (view_name.str)
50867 -+ {
50868 -+ // A view
50869 -+
50870 -+ if (!(belong_to_view &&
50871 -+ belong_to_view->compact_view_format))
50872 -+ {
50873 -+ append_identifier(thd, str, view_db.str, view_db.length);
50874 -+ str->append('.');
50875 -+ }
50876 -+ append_identifier(thd, str, view_name.str, view_name.length);
50877 -+ cmp_name= view_name.str;
50878 -+ }
50879 -+ else if (derived)
50880 -+ {
50881 -+ // A derived table
50882 -+ str->append('(');
50883 -+ derived->print(str, query_type);
50884 -+ str->append(')');
50885 -+ cmp_name= ""; // Force printing of alias
50886 -+ }
50887 -+ else
50888 -+ {
50889 -+ // A normal table
50890 -+
50891 -+ if (!(belong_to_view &&
50892 -+ belong_to_view->compact_view_format))
50893 -+ {
50894 -+ append_identifier(thd, str, db, db_length);
50895 -+ str->append('.');
50896 -+ }
50897 -+ if (schema_table)
50898 -+ {
50899 -+ append_identifier(thd, str, schema_table_name,
50900 -+ strlen(schema_table_name));
50901 -+ cmp_name= schema_table_name;
50902 -+ }
50903 -+ else
50904 -+ {
50905 -+ append_identifier(thd, str, table_name, table_name_length);
50906 -+ cmp_name= table_name;
50907 -+ }
50908 -+ }
50909 -+ if (my_strcasecmp(table_alias_charset, cmp_name, alias))
50910 -+ {
50911 -+ char t_alias_buff[MAX_ALIAS_NAME];
50912 -+ const char *t_alias= alias;
50913 -+
50914 -+ str->append(' ');
50915 -+ if (lower_case_table_names== 1)
50916 -+ {
50917 -+ if (alias && alias[0])
50918 -+ {
50919 -+ strmov(t_alias_buff, alias);
50920 -+ my_casedn_str(files_charset_info, t_alias_buff);
50921 -+ t_alias= t_alias_buff;
50922 -+ }
50923 -+ }
50924 -+
50925 -+ append_identifier(thd, str, t_alias, strlen(t_alias));
50926 -+ }
50927 -+
50928 -+ if (index_hints)
50929 -+ {
50930 -+ List_iterator<Index_hint> it(*index_hints);
50931 -+ Index_hint *hint;
50932 -+
50933 -+ while ((hint= it++))
50934 -+ {
50935 -+ str->append (STRING_WITH_LEN(" "));
50936 -+ hint->print (thd, str);
50937 -+ }
50938 -+ }
50939 -+ }
50940 -+}
50941 -+
50942 -+
50943 -+void st_select_lex::print(THD *thd, String *str, enum_query_type query_type)
50944 -+{
50945 -+ /* QQ: thd may not be set for sub queries, but this should be fixed */
50946 -+ if (!thd)
50947 -+ thd= current_thd;
50948 -+
50949 -+ str->append(STRING_WITH_LEN("select "));
50950 -+
50951 -+ /* First add options */
50952 -+ if (options & SELECT_STRAIGHT_JOIN)
50953 -+ str->append(STRING_WITH_LEN("straight_join "));
50954 -+ if ((thd->lex->lock_option == TL_READ_HIGH_PRIORITY) &&
50955 -+ (this == &thd->lex->select_lex))
50956 -+ str->append(STRING_WITH_LEN("high_priority "));
50957 -+ if (options & SELECT_DISTINCT)
50958 -+ str->append(STRING_WITH_LEN("distinct "));
50959 -+ if (options & SELECT_SMALL_RESULT)
50960 -+ str->append(STRING_WITH_LEN("sql_small_result "));
50961 -+ if (options & SELECT_BIG_RESULT)
50962 -+ str->append(STRING_WITH_LEN("sql_big_result "));
50963 -+ if (options & OPTION_BUFFER_RESULT)
50964 -+ str->append(STRING_WITH_LEN("sql_buffer_result "));
50965 -+ if (options & OPTION_FOUND_ROWS)
50966 -+ str->append(STRING_WITH_LEN("sql_calc_found_rows "));
50967 -+ switch (sql_cache)
50968 -+ {
50969 -+ case SQL_NO_CACHE:
50970 -+ str->append(STRING_WITH_LEN("sql_no_cache "));
50971 -+ break;
50972 -+ case SQL_CACHE:
50973 -+ str->append(STRING_WITH_LEN("sql_cache "));
50974 -+ break;
50975 -+ case SQL_CACHE_UNSPECIFIED:
50976 -+ break;
50977 -+ default:
50978 -+ DBUG_ASSERT(0);
50979 -+ }
50980 -+
50981 -+ //Item List
50982 -+ bool first= 1;
50983 -+ List_iterator_fast<Item> it(item_list);
50984 -+ Item *item;
50985 -+ while ((item= it++))
50986 -+ {
50987 -+ if (first)
50988 -+ first= 0;
50989 -+ else
50990 -+ str->append(',');
50991 -+
50992 -+ if (master_unit()->item && item->is_autogenerated_name)
50993 -+ {
50994 -+ /*
50995 -+ Do not print auto-generated aliases in subqueries. It has no purpose
50996 -+ in a view definition or other contexts where the query is printed.
50997 -+ */
50998 -+ item->print(str, query_type);
50999 -+ }
51000 -+ else
51001 -+ item->print_item_w_name(str, query_type);
51002 -+ }
51003 -+
51004 -+ /*
51005 -+ from clause
51006 -+ TODO: support USING/FORCE/IGNORE index
51007 -+ */
51008 -+ if (table_list.elements)
51009 -+ {
51010 -+ str->append(STRING_WITH_LEN(" from "));
51011 -+ /* go through join tree */
51012 -+ print_join(thd, str, &top_join_list, query_type);
51013 -+ }
51014 -+ else if (where)
51015 -+ {
51016 -+ /*
51017 -+ "SELECT 1 FROM DUAL WHERE 2" should not be printed as
51018 -+ "SELECT 1 WHERE 2": the 1st syntax is valid, but the 2nd is not.
51019 -+ */
51020 -+ str->append(STRING_WITH_LEN(" from DUAL "));
51021 -+ }
51022 -+
51023 -+ // Where
51024 -+ Item *cur_where= where;
51025 -+ if (join)
51026 -+ cur_where= join->conds;
51027 -+ if (cur_where || cond_value != Item::COND_UNDEF)
51028 -+ {
51029 -+ str->append(STRING_WITH_LEN(" where "));
51030 -+ if (cur_where)
51031 -+ cur_where->print(str, query_type);
51032 -+ else
51033 -+ str->append(cond_value != Item::COND_FALSE ? "1" : "0");
51034 -+ }
51035 -+
51036 -+ // group by & olap
51037 -+ if (group_list.elements)
51038 -+ {
51039 -+ str->append(STRING_WITH_LEN(" group by "));
51040 -+ print_order(str, group_list.first, query_type);
51041 -+ switch (olap)
51042 -+ {
51043 -+ case CUBE_TYPE:
51044 -+ str->append(STRING_WITH_LEN(" with cube"));
51045 -+ break;
51046 -+ case ROLLUP_TYPE:
51047 -+ str->append(STRING_WITH_LEN(" with rollup"));
51048 -+ break;
51049 -+ default:
51050 -+ ; //satisfy compiler
51051 -+ }
51052 -+ }
51053 -+
51054 -+ // having
51055 -+ Item *cur_having= having;
51056 -+ if (join)
51057 -+ cur_having= join->having;
51058 -+
51059 -+ if (cur_having || having_value != Item::COND_UNDEF)
51060 -+ {
51061 -+ str->append(STRING_WITH_LEN(" having "));
51062 -+ if (cur_having)
51063 -+ cur_having->print(str, query_type);
51064 -+ else
51065 -+ str->append(having_value != Item::COND_FALSE ? "1" : "0");
51066 -+ }
51067 -+
51068 -+ if (order_list.elements)
51069 -+ {
51070 -+ str->append(STRING_WITH_LEN(" order by "));
51071 -+ print_order(str, order_list.first, query_type);
51072 -+ }
51073 -+
51074 -+ // limit
51075 -+ print_limit(thd, str, query_type);
51076 -+
51077 -+ // PROCEDURE unsupported here
51078 -+}
51079 -+
51080 -+
51081 -+/**
51082 -+ change select_result object of JOIN.
51083 -+
51084 -+ @param res new select_result object
51085 -+
51086 -+ @retval
51087 -+ FALSE OK
51088 -+ @retval
51089 -+ TRUE error
51090 -+*/
51091 -+
51092 -+bool JOIN::change_result(select_result *res)
51093 -+{
51094 -+ DBUG_ENTER("JOIN::change_result");
51095 -+ result= res;
51096 -+ if (!procedure && (result->prepare(fields_list, select_lex->master_unit()) ||
51097 -+ result->prepare2()))
51098 -+ {
51099 -+ DBUG_RETURN(TRUE);
51100 -+ }
51101 -+ DBUG_RETURN(FALSE);
51102 -+}
51103 -+
51104 -+/**
51105 -+ @} (end of group Query_Optimizer)
51106 -+*/
51107 diff -urN mysql-old/sql/sql_show.cc mysql/sql/sql_show.cc
51108 --- mysql-old/sql/sql_show.cc 2011-05-10 17:45:45.626682377 +0000
51109 +++ mysql/sql/sql_show.cc 2011-05-10 17:56:01.596682375 +0000
51110 @@ -53517,7285 +2492,6 @@ diff -urN mysql-old/sql/sql_show.cc mysql/sql/sql_show.cc
51111
51112 stmt_fld->maybe_null= TRUE;
51113
51114 -diff -urN mysql-old/sql/sql_show.cc.orig mysql/sql/sql_show.cc.orig
51115 ---- mysql-old/sql/sql_show.cc.orig 1969-12-31 23:00:00.000000000 -0100
51116 -+++ mysql/sql/sql_show.cc.orig 2011-04-12 12:11:35.000000000 +0000
51117 -@@ -0,0 +1,7275 @@
51118 -+/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
51119 -+
51120 -+ This program is free software; you can redistribute it and/or modify
51121 -+ it under the terms of the GNU General Public License as published by
51122 -+ the Free Software Foundation; version 2 of the License.
51123 -+
51124 -+ This program is distributed in the hope that it will be useful,
51125 -+ but WITHOUT ANY WARRANTY; without even the implied warranty of
51126 -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
51127 -+ GNU General Public License for more details.
51128 -+
51129 -+ You should have received a copy of the GNU General Public License along
51130 -+ with this program; if not, write to the Free Software Foundation, Inc.,
51131 -+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
51132 -+
51133 -+
51134 -+/* Function with list databases, tables or fields */
51135 -+
51136 -+#include "mysql_priv.h"
51137 -+#include "sql_select.h" // For select_describe
51138 -+#include "sql_show.h"
51139 -+#include "repl_failsafe.h"
51140 -+#include "sp.h"
51141 -+#include "sp_head.h"
51142 -+#include "sql_trigger.h"
51143 -+#include "authors.h"
51144 -+#include "contributors.h"
51145 -+#ifdef HAVE_EVENT_SCHEDULER
51146 -+#include "events.h"
51147 -+#include "event_data_objects.h"
51148 -+#endif
51149 -+#include <my_dir.h>
51150 -+#include "debug_sync.h"
51151 -+
51152 -+#define STR_OR_NIL(S) ((S) ? (S) : "<nil>")
51153 -+
51154 -+#ifdef WITH_PARTITION_STORAGE_ENGINE
51155 -+#include "ha_partition.h"
51156 -+#endif
51157 -+enum enum_i_s_events_fields
51158 -+{
51159 -+ ISE_EVENT_CATALOG= 0,
51160 -+ ISE_EVENT_SCHEMA,
51161 -+ ISE_EVENT_NAME,
51162 -+ ISE_DEFINER,
51163 -+ ISE_TIME_ZONE,
51164 -+ ISE_EVENT_BODY,
51165 -+ ISE_EVENT_DEFINITION,
51166 -+ ISE_EVENT_TYPE,
51167 -+ ISE_EXECUTE_AT,
51168 -+ ISE_INTERVAL_VALUE,
51169 -+ ISE_INTERVAL_FIELD,
51170 -+ ISE_SQL_MODE,
51171 -+ ISE_STARTS,
51172 -+ ISE_ENDS,
51173 -+ ISE_STATUS,
51174 -+ ISE_ON_COMPLETION,
51175 -+ ISE_CREATED,
51176 -+ ISE_LAST_ALTERED,
51177 -+ ISE_LAST_EXECUTED,
51178 -+ ISE_EVENT_COMMENT,
51179 -+ ISE_ORIGINATOR,
51180 -+ ISE_CLIENT_CS,
51181 -+ ISE_CONNECTION_CL,
51182 -+ ISE_DB_CL
51183 -+};
51184 -+
51185 -+#ifndef NO_EMBEDDED_ACCESS_CHECKS
51186 -+static const char *grant_names[]={
51187 -+ "select","insert","update","delete","create","drop","reload","shutdown",
51188 -+ "process","file","grant","references","index","alter"};
51189 -+
51190 -+static TYPELIB grant_types = { sizeof(grant_names)/sizeof(char **),
51191 -+ "grant_types",
51192 -+ grant_names, NULL};
51193 -+#endif
51194 -+
51195 -+static void store_key_options(THD *thd, String *packet, TABLE *table,
51196 -+ KEY *key_info);
51197 -+
51198 -+static void
51199 -+append_algorithm(TABLE_LIST *table, String *buff);
51200 -+
51201 -+static COND * make_cond_for_info_schema(COND *cond, TABLE_LIST *table);
51202 -+
51203 -+/***************************************************************************
51204 -+** List all table types supported
51205 -+***************************************************************************/
51206 -+
51207 -+static int make_version_string(char *buf, int buf_length, uint version)
51208 -+{
51209 -+ return my_snprintf(buf, buf_length, "%d.%d", version>>8,version&0xff);
51210 -+}
51211 -+
51212 -+static my_bool show_plugins(THD *thd, plugin_ref plugin,
51213 -+ void *arg)
51214 -+{
51215 -+ TABLE *table= (TABLE*) arg;
51216 -+ struct st_mysql_plugin *plug= plugin_decl(plugin);
51217 -+ struct st_plugin_dl *plugin_dl= plugin_dlib(plugin);
51218 -+ CHARSET_INFO *cs= system_charset_info;
51219 -+ char version_buf[20];
51220 -+
51221 -+ restore_record(table, s->default_values);
51222 -+
51223 -+ table->field[0]->store(plugin_name(plugin)->str,
51224 -+ plugin_name(plugin)->length, cs);
51225 -+
51226 -+ table->field[1]->store(version_buf,
51227 -+ make_version_string(version_buf, sizeof(version_buf), plug->version),
51228 -+ cs);
51229 -+
51230 -+
51231 -+ switch (plugin_state(plugin)) {
51232 -+ /* case PLUGIN_IS_FREED: does not happen */
51233 -+ case PLUGIN_IS_DELETED:
51234 -+ table->field[2]->store(STRING_WITH_LEN("DELETED"), cs);
51235 -+ break;
51236 -+ case PLUGIN_IS_UNINITIALIZED:
51237 -+ table->field[2]->store(STRING_WITH_LEN("INACTIVE"), cs);
51238 -+ break;
51239 -+ case PLUGIN_IS_READY:
51240 -+ table->field[2]->store(STRING_WITH_LEN("ACTIVE"), cs);
51241 -+ break;
51242 -+ case PLUGIN_IS_DISABLED:
51243 -+ table->field[2]->store(STRING_WITH_LEN("DISABLED"), cs);
51244 -+ break;
51245 -+ default:
51246 -+ DBUG_ASSERT(0);
51247 -+ }
51248 -+
51249 -+ table->field[3]->store(plugin_type_names[plug->type].str,
51250 -+ plugin_type_names[plug->type].length,
51251 -+ cs);
51252 -+ table->field[4]->store(version_buf,
51253 -+ make_version_string(version_buf, sizeof(version_buf),
51254 -+ *(uint *)plug->info), cs);
51255 -+
51256 -+ if (plugin_dl)
51257 -+ {
51258 -+ table->field[5]->store(plugin_dl->dl.str, plugin_dl->dl.length, cs);
51259 -+ table->field[5]->set_notnull();
51260 -+ table->field[6]->store(version_buf,
51261 -+ make_version_string(version_buf, sizeof(version_buf),
51262 -+ plugin_dl->version),
51263 -+ cs);
51264 -+ table->field[6]->set_notnull();
51265 -+ }
51266 -+ else
51267 -+ {
51268 -+ table->field[5]->set_null();
51269 -+ table->field[6]->set_null();
51270 -+ }
51271 -+
51272 -+
51273 -+ if (plug->author)
51274 -+ {
51275 -+ table->field[7]->store(plug->author, strlen(plug->author), cs);
51276 -+ table->field[7]->set_notnull();
51277 -+ }
51278 -+ else
51279 -+ table->field[7]->set_null();
51280 -+
51281 -+ if (plug->descr)
51282 -+ {
51283 -+ table->field[8]->store(plug->descr, strlen(plug->descr), cs);
51284 -+ table->field[8]->set_notnull();
51285 -+ }
51286 -+ else
51287 -+ table->field[8]->set_null();
51288 -+
51289 -+ switch (plug->license) {
51290 -+ case PLUGIN_LICENSE_GPL:
51291 -+ table->field[9]->store(PLUGIN_LICENSE_GPL_STRING,
51292 -+ strlen(PLUGIN_LICENSE_GPL_STRING), cs);
51293 -+ break;
51294 -+ case PLUGIN_LICENSE_BSD:
51295 -+ table->field[9]->store(PLUGIN_LICENSE_BSD_STRING,
51296 -+ strlen(PLUGIN_LICENSE_BSD_STRING), cs);
51297 -+ break;
51298 -+ default:
51299 -+ table->field[9]->store(PLUGIN_LICENSE_PROPRIETARY_STRING,
51300 -+ strlen(PLUGIN_LICENSE_PROPRIETARY_STRING), cs);
51301 -+ break;
51302 -+ }
51303 -+ table->field[9]->set_notnull();
51304 -+
51305 -+ return schema_table_store_record(thd, table);
51306 -+}
51307 -+
51308 -+
51309 -+int fill_plugins(THD *thd, TABLE_LIST *tables, COND *cond)
51310 -+{
51311 -+ DBUG_ENTER("fill_plugins");
51312 -+ TABLE *table= tables->table;
51313 -+
51314 -+ if (plugin_foreach_with_mask(thd, show_plugins, MYSQL_ANY_PLUGIN,
51315 -+ ~PLUGIN_IS_FREED, table))
51316 -+ DBUG_RETURN(1);
51317 -+
51318 -+ DBUG_RETURN(0);
51319 -+}
51320 -+
51321 -+
51322 -+/***************************************************************************
51323 -+** List all Authors.
51324 -+** If you can update it, you get to be in it :)
51325 -+***************************************************************************/
51326 -+
51327 -+bool mysqld_show_authors(THD *thd)
51328 -+{
51329 -+ List<Item> field_list;
51330 -+ Protocol *protocol= thd->protocol;
51331 -+ DBUG_ENTER("mysqld_show_authors");
51332 -+
51333 -+ field_list.push_back(new Item_empty_string("Name",40));
51334 -+ field_list.push_back(new Item_empty_string("Location",40));
51335 -+ field_list.push_back(new Item_empty_string("Comment",80));
51336 -+
51337 -+ if (protocol->send_fields(&field_list,
51338 -+ Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
51339 -+ DBUG_RETURN(TRUE);
51340 -+
51341 -+ show_table_authors_st *authors;
51342 -+ for (authors= show_table_authors; authors->name; authors++)
51343 -+ {
51344 -+ protocol->prepare_for_resend();
51345 -+ protocol->store(authors->name, system_charset_info);
51346 -+ protocol->store(authors->location, system_charset_info);
51347 -+ protocol->store(authors->comment, system_charset_info);
51348 -+ if (protocol->write())
51349 -+ DBUG_RETURN(TRUE);
51350 -+ }
51351 -+ my_eof(thd);
51352 -+ DBUG_RETURN(FALSE);
51353 -+}
51354 -+
51355 -+
51356 -+/***************************************************************************
51357 -+** List all Contributors.
51358 -+** Please get permission before updating
51359 -+***************************************************************************/
51360 -+
51361 -+bool mysqld_show_contributors(THD *thd)
51362 -+{
51363 -+ List<Item> field_list;
51364 -+ Protocol *protocol= thd->protocol;
51365 -+ DBUG_ENTER("mysqld_show_contributors");
51366 -+
51367 -+ field_list.push_back(new Item_empty_string("Name",40));
51368 -+ field_list.push_back(new Item_empty_string("Location",40));
51369 -+ field_list.push_back(new Item_empty_string("Comment",80));
51370 -+
51371 -+ if (protocol->send_fields(&field_list,
51372 -+ Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
51373 -+ DBUG_RETURN(TRUE);
51374 -+
51375 -+ show_table_contributors_st *contributors;
51376 -+ for (contributors= show_table_contributors; contributors->name; contributors++)
51377 -+ {
51378 -+ protocol->prepare_for_resend();
51379 -+ protocol->store(contributors->name, system_charset_info);
51380 -+ protocol->store(contributors->location, system_charset_info);
51381 -+ protocol->store(contributors->comment, system_charset_info);
51382 -+ if (protocol->write())
51383 -+ DBUG_RETURN(TRUE);
51384 -+ }
51385 -+ my_eof(thd);
51386 -+ DBUG_RETURN(FALSE);
51387 -+}
51388 -+
51389 -+
51390 -+/***************************************************************************
51391 -+ List all privileges supported
51392 -+***************************************************************************/
51393 -+
51394 -+struct show_privileges_st {
51395 -+ const char *privilege;
51396 -+ const char *context;
51397 -+ const char *comment;
51398 -+};
51399 -+
51400 -+static struct show_privileges_st sys_privileges[]=
51401 -+{
51402 -+ {"Alter", "Tables", "To alter the table"},
51403 -+ {"Alter routine", "Functions,Procedures", "To alter or drop stored functions/procedures"},
51404 -+ {"Create", "Databases,Tables,Indexes", "To create new databases and tables"},
51405 -+ {"Create routine","Databases","To use CREATE FUNCTION/PROCEDURE"},
51406 -+ {"Create temporary tables","Databases","To use CREATE TEMPORARY TABLE"},
51407 -+ {"Create view", "Tables", "To create new views"},
51408 -+ {"Create user", "Server Admin", "To create new users"},
51409 -+ {"Delete", "Tables", "To delete existing rows"},
51410 -+ {"Drop", "Databases,Tables", "To drop databases, tables, and views"},
51411 -+#ifdef HAVE_EVENT_SCHEDULER
51412 -+ {"Event","Server Admin","To create, alter, drop and execute events"},
51413 -+#endif
51414 -+ {"Execute", "Functions,Procedures", "To execute stored routines"},
51415 -+ {"File", "File access on server", "To read and write files on the server"},
51416 -+ {"Grant option", "Databases,Tables,Functions,Procedures", "To give to other users those privileges you possess"},
51417 -+ {"Index", "Tables", "To create or drop indexes"},
51418 -+ {"Insert", "Tables", "To insert data into tables"},
51419 -+ {"Lock tables","Databases","To use LOCK TABLES (together with SELECT privilege)"},
51420 -+ {"Process", "Server Admin", "To view the plain text of currently executing queries"},
51421 -+ {"References", "Databases,Tables", "To have references on tables"},
51422 -+ {"Reload", "Server Admin", "To reload or refresh tables, logs and privileges"},
51423 -+ {"Replication client","Server Admin","To ask where the slave or master servers are"},
51424 -+ {"Replication slave","Server Admin","To read binary log events from the master"},
51425 -+ {"Select", "Tables", "To retrieve rows from table"},
51426 -+ {"Show databases","Server Admin","To see all databases with SHOW DATABASES"},
51427 -+ {"Show view","Tables","To see views with SHOW CREATE VIEW"},
51428 -+ {"Shutdown","Server Admin", "To shut down the server"},
51429 -+ {"Super","Server Admin","To use KILL thread, SET GLOBAL, CHANGE MASTER, etc."},
51430 -+ {"Trigger","Tables", "To use triggers"},
51431 -+ {"Update", "Tables", "To update existing rows"},
51432 -+ {"Usage","Server Admin","No privileges - allow connect only"},
51433 -+ {NullS, NullS, NullS}
51434 -+};
51435 -+
51436 -+bool mysqld_show_privileges(THD *thd)
51437 -+{
51438 -+ List<Item> field_list;
51439 -+ Protocol *protocol= thd->protocol;
51440 -+ DBUG_ENTER("mysqld_show_privileges");
51441 -+
51442 -+ field_list.push_back(new Item_empty_string("Privilege",10));
51443 -+ field_list.push_back(new Item_empty_string("Context",15));
51444 -+ field_list.push_back(new Item_empty_string("Comment",NAME_CHAR_LEN));
51445 -+
51446 -+ if (protocol->send_fields(&field_list,
51447 -+ Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
51448 -+ DBUG_RETURN(TRUE);
51449 -+
51450 -+ show_privileges_st *privilege= sys_privileges;
51451 -+ for (privilege= sys_privileges; privilege->privilege ; privilege++)
51452 -+ {
51453 -+ protocol->prepare_for_resend();
51454 -+ protocol->store(privilege->privilege, system_charset_info);
51455 -+ protocol->store(privilege->context, system_charset_info);
51456 -+ protocol->store(privilege->comment, system_charset_info);
51457 -+ if (protocol->write())
51458 -+ DBUG_RETURN(TRUE);
51459 -+ }
51460 -+ my_eof(thd);
51461 -+ DBUG_RETURN(FALSE);
51462 -+}
51463 -+
51464 -+
51465 -+/***************************************************************************
51466 -+ List all column types
51467 -+***************************************************************************/
51468 -+
51469 -+struct show_column_type_st
51470 -+{
51471 -+ const char *type;
51472 -+ uint size;
51473 -+ const char *min_value;
51474 -+ const char *max_value;
51475 -+ uint precision;
51476 -+ uint scale;
51477 -+ const char *nullable;
51478 -+ const char *auto_increment;
51479 -+ const char *unsigned_attr;
51480 -+ const char *zerofill;
51481 -+ const char *searchable;
51482 -+ const char *case_sensitivity;
51483 -+ const char *default_value;
51484 -+ const char *comment;
51485 -+};
51486 -+
51487 -+/* TODO: Add remaning types */
51488 -+
51489 -+static struct show_column_type_st sys_column_types[]=
51490 -+{
51491 -+ {"tinyint",
51492 -+ 1, "-128", "127", 0, 0, "YES", "YES",
51493 -+ "NO", "YES", "YES", "NO", "NULL,0",
51494 -+ "A very small integer"},
51495 -+ {"tinyint unsigned",
51496 -+ 1, "0" , "255", 0, 0, "YES", "YES",
51497 -+ "YES", "YES", "YES", "NO", "NULL,0",
51498 -+ "A very small integer"},
51499 -+};
51500 -+
51501 -+bool mysqld_show_column_types(THD *thd)
51502 -+{
51503 -+ List<Item> field_list;
51504 -+ Protocol *protocol= thd->protocol;
51505 -+ DBUG_ENTER("mysqld_show_column_types");
51506 -+
51507 -+ field_list.push_back(new Item_empty_string("Type",30));
51508 -+ field_list.push_back(new Item_int("Size",(longlong) 1,
51509 -+ MY_INT64_NUM_DECIMAL_DIGITS));
51510 -+ field_list.push_back(new Item_empty_string("Min_Value",20));
51511 -+ field_list.push_back(new Item_empty_string("Max_Value",20));
51512 -+ field_list.push_back(new Item_return_int("Prec", 4, MYSQL_TYPE_SHORT));
51513 -+ field_list.push_back(new Item_return_int("Scale", 4, MYSQL_TYPE_SHORT));
51514 -+ field_list.push_back(new Item_empty_string("Nullable",4));
51515 -+ field_list.push_back(new Item_empty_string("Auto_Increment",4));
51516 -+ field_list.push_back(new Item_empty_string("Unsigned",4));
51517 -+ field_list.push_back(new Item_empty_string("Zerofill",4));
51518 -+ field_list.push_back(new Item_empty_string("Searchable",4));
51519 -+ field_list.push_back(new Item_empty_string("Case_Sensitive",4));
51520 -+ field_list.push_back(new Item_empty_string("Default",NAME_CHAR_LEN));
51521 -+ field_list.push_back(new Item_empty_string("Comment",NAME_CHAR_LEN));
51522 -+
51523 -+ if (protocol->send_fields(&field_list,
51524 -+ Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
51525 -+ DBUG_RETURN(TRUE);
51526 -+
51527 -+ /* TODO: Change the loop to not use 'i' */
51528 -+ for (uint i=0; i < sizeof(sys_column_types)/sizeof(sys_column_types[0]); i++)
51529 -+ {
51530 -+ protocol->prepare_for_resend();
51531 -+ protocol->store(sys_column_types[i].type, system_charset_info);
51532 -+ protocol->store((ulonglong) sys_column_types[i].size);
51533 -+ protocol->store(sys_column_types[i].min_value, system_charset_info);
51534 -+ protocol->store(sys_column_types[i].max_value, system_charset_info);
51535 -+ protocol->store_short((longlong) sys_column_types[i].precision);
51536 -+ protocol->store_short((longlong) sys_column_types[i].scale);
51537 -+ protocol->store(sys_column_types[i].nullable, system_charset_info);
51538 -+ protocol->store(sys_column_types[i].auto_increment, system_charset_info);
51539 -+ protocol->store(sys_column_types[i].unsigned_attr, system_charset_info);
51540 -+ protocol->store(sys_column_types[i].zerofill, system_charset_info);
51541 -+ protocol->store(sys_column_types[i].searchable, system_charset_info);
51542 -+ protocol->store(sys_column_types[i].case_sensitivity, system_charset_info);
51543 -+ protocol->store(sys_column_types[i].default_value, system_charset_info);
51544 -+ protocol->store(sys_column_types[i].comment, system_charset_info);
51545 -+ if (protocol->write())
51546 -+ DBUG_RETURN(TRUE);
51547 -+ }
51548 -+ my_eof(thd);
51549 -+ DBUG_RETURN(FALSE);
51550 -+}
51551 -+
51552 -+
51553 -+/*
51554 -+ find_files() - find files in a given directory.
51555 -+
51556 -+ SYNOPSIS
51557 -+ find_files()
51558 -+ thd thread handler
51559 -+ files put found files in this list
51560 -+ db database name to set in TABLE_LIST structure
51561 -+ path path to database
51562 -+ wild filter for found files
51563 -+ dir read databases in path if TRUE, read .frm files in
51564 -+ database otherwise
51565 -+
51566 -+ RETURN
51567 -+ FIND_FILES_OK success
51568 -+ FIND_FILES_OOM out of memory error
51569 -+ FIND_FILES_DIR no such directory, or directory can't be read
51570 -+*/
51571 -+
51572 -+
51573 -+find_files_result
51574 -+find_files(THD *thd, List<LEX_STRING> *files, const char *db,
51575 -+ const char *path, const char *wild, bool dir)
51576 -+{
51577 -+ uint i;
51578 -+ char *ext;
51579 -+ MY_DIR *dirp;
51580 -+ FILEINFO *file;
51581 -+ LEX_STRING *file_name= 0;
51582 -+ uint file_name_len;
51583 -+#ifndef NO_EMBEDDED_ACCESS_CHECKS
51584 -+ uint col_access=thd->col_access;
51585 -+#endif
51586 -+ uint wild_length= 0;
51587 -+ TABLE_LIST table_list;
51588 -+ DBUG_ENTER("find_files");
51589 -+
51590 -+ if (wild)
51591 -+ {
51592 -+ if (!wild[0])
51593 -+ wild= 0;
51594 -+ else
51595 -+ wild_length= strlen(wild);
51596 -+ }
51597 -+
51598 -+
51599 -+
51600 -+ bzero((char*) &table_list,sizeof(table_list));
51601 -+
51602 -+ if (!(dirp = my_dir(path,MYF(dir ? MY_WANT_STAT : 0))))
51603 -+ {
51604 -+ if (my_errno == ENOENT)
51605 -+ my_error(ER_BAD_DB_ERROR, MYF(ME_BELL+ME_WAITTANG), db);
51606 -+ else
51607 -+ my_error(ER_CANT_READ_DIR, MYF(ME_BELL+ME_WAITTANG), path, my_errno);
51608 -+ DBUG_RETURN(FIND_FILES_DIR);
51609 -+ }
51610 -+
51611 -+ for (i=0 ; i < (uint) dirp->number_off_files ; i++)
51612 -+ {
51613 -+ char uname[NAME_LEN + 1]; /* Unencoded name */
51614 -+ file=dirp->dir_entry+i;
51615 -+ if (dir)
51616 -+ { /* Return databases */
51617 -+ if ((file->name[0] == '.' &&
51618 -+ ((file->name[1] == '.' && file->name[2] == '\0') ||
51619 -+ file->name[1] == '\0')))
51620 -+ continue; /* . or .. */
51621 -+#ifdef USE_SYMDIR
51622 -+ char *ext;
51623 -+ char buff[FN_REFLEN];
51624 -+ if (my_use_symdir && !strcmp(ext=fn_ext(file->name), ".sym"))
51625 -+ {
51626 -+ /* Only show the sym file if it points to a directory */
51627 -+ char *end;
51628 -+ *ext=0; /* Remove extension */
51629 -+ unpack_dirname(buff, file->name);
51630 -+ end= strend(buff);
51631 -+ if (end != buff && end[-1] == FN_LIBCHAR)
51632 -+ end[-1]= 0; // Remove end FN_LIBCHAR
51633 -+ if (!my_stat(buff, file->mystat, MYF(0)))
51634 -+ continue;
51635 -+ }
51636 -+#endif
51637 -+ if (!MY_S_ISDIR(file->mystat->st_mode))
51638 -+ continue;
51639 -+
51640 -+ file_name_len= filename_to_tablename(file->name, uname, sizeof(uname));
51641 -+ if (wild)
51642 -+ {
51643 -+ if (lower_case_table_names)
51644 -+ {
51645 -+ if (my_wildcmp(files_charset_info,
51646 -+ uname, uname + file_name_len,
51647 -+ wild, wild + wild_length,
51648 -+ wild_prefix, wild_one,wild_many))
51649 -+ continue;
51650 -+ }
51651 -+ else if (wild_compare(uname, wild, 0))
51652 -+ continue;
51653 -+ }
51654 -+ }
51655 -+ else
51656 -+ {
51657 -+ // Return only .frm files which aren't temp files.
51658 -+ if (my_strcasecmp(system_charset_info, ext=fn_rext(file->name),reg_ext) ||
51659 -+ is_prefix(file->name, tmp_file_prefix))
51660 -+ continue;
51661 -+ *ext=0;
51662 -+ file_name_len= filename_to_tablename(file->name, uname, sizeof(uname));
51663 -+ if (wild)
51664 -+ {
51665 -+ if (lower_case_table_names)
51666 -+ {
51667 -+ if (my_wildcmp(files_charset_info,
51668 -+ uname, uname + file_name_len,
51669 -+ wild, wild + wild_length,
51670 -+ wild_prefix, wild_one,wild_many))
51671 -+ continue;
51672 -+ }
51673 -+ else if (wild_compare(uname, wild, 0))
51674 -+ continue;
51675 -+ }
51676 -+ }
51677 -+#ifndef NO_EMBEDDED_ACCESS_CHECKS
51678 -+ /* Don't show tables where we don't have any privileges */
51679 -+ if (db && !(col_access & TABLE_ACLS))
51680 -+ {
51681 -+ table_list.db= (char*) db;
51682 -+ table_list.db_length= strlen(db);
51683 -+ table_list.table_name= uname;
51684 -+ table_list.table_name_length= file_name_len;
51685 -+ table_list.grant.privilege=col_access;
51686 -+ if (check_grant(thd, TABLE_ACLS, &table_list, 1, 1, 1))
51687 -+ continue;
51688 -+ }
51689 -+#endif
51690 -+ if (!(file_name=
51691 -+ thd->make_lex_string(file_name, uname, file_name_len, TRUE)) ||
51692 -+ files->push_back(file_name))
51693 -+ {
51694 -+ my_dirend(dirp);
51695 -+ DBUG_RETURN(FIND_FILES_OOM);
51696 -+ }
51697 -+ }
51698 -+ DBUG_PRINT("info",("found: %d files", files->elements));
51699 -+ my_dirend(dirp);
51700 -+
51701 -+ VOID(ha_find_files(thd, db, path, wild, dir, files));
51702 -+
51703 -+ DBUG_RETURN(FIND_FILES_OK);
51704 -+}
51705 -+
51706 -+
51707 -+/**
51708 -+ An Internal_error_handler that suppresses errors regarding views'
51709 -+ underlying tables that occur during privilege checking within SHOW CREATE
51710 -+ VIEW commands. This happens in the cases when
51711 -+
51712 -+ - A view's underlying table (e.g. referenced in its SELECT list) does not
51713 -+ exist. There should not be an error as no attempt was made to access it
51714 -+ per se.
51715 -+
51716 -+ - Access is denied for some table, column, function or stored procedure
51717 -+ such as mentioned above. This error gets raised automatically, since we
51718 -+ can't untangle its access checking from that of the view itself.
51719 -+ */
51720 -+class Show_create_error_handler : public Internal_error_handler {
51721 -+
51722 -+ TABLE_LIST *m_top_view;
51723 -+ bool m_handling;
51724 -+ Security_context *m_sctx;
51725 -+
51726 -+ char m_view_access_denied_message[MYSQL_ERRMSG_SIZE];
51727 -+ char *m_view_access_denied_message_ptr;
51728 -+
51729 -+public:
51730 -+
51731 -+ /**
51732 -+ Creates a new Show_create_error_handler for the particular security
51733 -+ context and view.
51734 -+
51735 -+ @thd Thread context, used for security context information if needed.
51736 -+ @top_view The view. We do not verify at this point that top_view is in
51737 -+ fact a view since, alas, these things do not stay constant.
51738 -+ */
51739 -+ explicit Show_create_error_handler(THD *thd, TABLE_LIST *top_view) :
51740 -+ m_top_view(top_view), m_handling(FALSE),
51741 -+ m_view_access_denied_message_ptr(NULL)
51742 -+ {
51743 -+
51744 -+ m_sctx = test(m_top_view->security_ctx) ?
51745 -+ m_top_view->security_ctx : thd->security_ctx;
51746 -+ }
51747 -+
51748 -+ /**
51749 -+ Lazy instantiation of 'view access denied' message. The purpose of the
51750 -+ Show_create_error_handler is to hide details of underlying tables for
51751 -+ which we have no privileges behind ER_VIEW_INVALID messages. But this
51752 -+ obviously does not apply if we lack privileges on the view itself.
51753 -+ Unfortunately the information about for which table privilege checking
51754 -+ failed is not available at this point. The only way for us to check is by
51755 -+ reconstructing the actual error message and see if it's the same.
51756 -+ */
51757 -+ char* get_view_access_denied_message()
51758 -+ {
51759 -+ if (!m_view_access_denied_message_ptr)
51760 -+ {
51761 -+ m_view_access_denied_message_ptr= m_view_access_denied_message;
51762 -+ my_snprintf(m_view_access_denied_message, MYSQL_ERRMSG_SIZE,
51763 -+ ER(ER_TABLEACCESS_DENIED_ERROR), "SHOW VIEW",
51764 -+ m_sctx->priv_user,
51765 -+ m_sctx->host_or_ip, m_top_view->get_table_name());
51766 -+ }
51767 -+ return m_view_access_denied_message_ptr;
51768 -+ }
51769 -+
51770 -+ bool handle_error(uint sql_errno, const char *message,
51771 -+ MYSQL_ERROR::enum_warning_level level, THD *thd) {
51772 -+ /*
51773 -+ The handler does not handle the errors raised by itself.
51774 -+ At this point we know if top_view is really a view.
51775 -+ */
51776 -+ if (m_handling || !m_top_view->view)
51777 -+ return FALSE;
51778 -+
51779 -+ m_handling= TRUE;
51780 -+
51781 -+ bool is_handled;
51782 -+
51783 -+ switch (sql_errno)
51784 -+ {
51785 -+ case ER_TABLEACCESS_DENIED_ERROR:
51786 -+ if (!strcmp(get_view_access_denied_message(), message))
51787 -+ {
51788 -+ /* Access to top view is not granted, don't interfere. */
51789 -+ is_handled= FALSE;
51790 -+ break;
51791 -+ }
51792 -+ case ER_COLUMNACCESS_DENIED_ERROR:
51793 -+ case ER_VIEW_NO_EXPLAIN: /* Error was anonymized, ignore all the same. */
51794 -+ case ER_PROCACCESS_DENIED_ERROR:
51795 -+ is_handled= TRUE;
51796 -+ break;
51797 -+
51798 -+ case ER_NO_SUCH_TABLE:
51799 -+ /* Established behavior: warn if underlying tables are missing. */
51800 -+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
51801 -+ ER_VIEW_INVALID,
51802 -+ ER(ER_VIEW_INVALID),
51803 -+ m_top_view->get_db_name(),
51804 -+ m_top_view->get_table_name());
51805 -+ is_handled= TRUE;
51806 -+ break;
51807 -+
51808 -+ case ER_SP_DOES_NOT_EXIST:
51809 -+ /* Established behavior: warn if underlying functions are missing. */
51810 -+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
51811 -+ ER_VIEW_INVALID,
51812 -+ ER(ER_VIEW_INVALID),
51813 -+ m_top_view->get_db_name(),
51814 -+ m_top_view->get_table_name());
51815 -+ is_handled= TRUE;
51816 -+ break;
51817 -+ default:
51818 -+ is_handled= FALSE;
51819 -+ }
51820 -+
51821 -+ m_handling= FALSE;
51822 -+ return is_handled;
51823 -+ }
51824 -+};
51825 -+
51826 -+
51827 -+bool
51828 -+mysqld_show_create(THD *thd, TABLE_LIST *table_list)
51829 -+{
51830 -+ Protocol *protocol= thd->protocol;
51831 -+ char buff[2048];
51832 -+ String buffer(buff, sizeof(buff), system_charset_info);
51833 -+ DBUG_ENTER("mysqld_show_create");
51834 -+ DBUG_PRINT("enter",("db: %s table: %s",table_list->db,
51835 -+ table_list->table_name));
51836 -+
51837 -+ /* We want to preserve the tree for views. */
51838 -+ thd->lex->context_analysis_only|= CONTEXT_ANALYSIS_ONLY_VIEW;
51839 -+
51840 -+ {
51841 -+ Show_create_error_handler view_error_suppressor(thd, table_list);
51842 -+ thd->push_internal_handler(&view_error_suppressor);
51843 -+ bool error= open_normal_and_derived_tables(thd, table_list, 0);
51844 -+ thd->pop_internal_handler();
51845 -+ if (error && (thd->killed || thd->main_da.is_error()))
51846 -+ DBUG_RETURN(TRUE);
51847 -+ }
51848 -+
51849 -+ /* TODO: add environment variables show when it become possible */
51850 -+ if (thd->lex->only_view && !table_list->view)
51851 -+ {
51852 -+ my_error(ER_WRONG_OBJECT, MYF(0),
51853 -+ table_list->db, table_list->table_name, "VIEW");
51854 -+ DBUG_RETURN(TRUE);
51855 -+ }
51856 -+
51857 -+ buffer.length(0);
51858 -+
51859 -+ if (table_list->view)
51860 -+ buffer.set_charset(table_list->view_creation_ctx->get_client_cs());
51861 -+
51862 -+ if ((table_list->view ?
51863 -+ view_store_create_info(thd, table_list, &buffer) :
51864 -+ store_create_info(thd, table_list, &buffer, NULL,
51865 -+ FALSE /* show_database */)))
51866 -+ DBUG_RETURN(TRUE);
51867 -+
51868 -+ List<Item> field_list;
51869 -+ if (table_list->view)
51870 -+ {
51871 -+ field_list.push_back(new Item_empty_string("View",NAME_CHAR_LEN));
51872 -+ field_list.push_back(new Item_empty_string("Create View",
51873 -+ max(buffer.length(),1024)));
51874 -+ field_list.push_back(new Item_empty_string("character_set_client",
51875 -+ MY_CS_NAME_SIZE));
51876 -+ field_list.push_back(new Item_empty_string("collation_connection",
51877 -+ MY_CS_NAME_SIZE));
51878 -+ }
51879 -+ else
51880 -+ {
51881 -+ field_list.push_back(new Item_empty_string("Table",NAME_CHAR_LEN));
51882 -+ // 1024 is for not to confuse old clients
51883 -+ field_list.push_back(new Item_empty_string("Create Table",
51884 -+ max(buffer.length(),1024)));
51885 -+ }
51886 -+
51887 -+ if (protocol->send_fields(&field_list,
51888 -+ Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
51889 -+ DBUG_RETURN(TRUE);
51890 -+ protocol->prepare_for_resend();
51891 -+ if (table_list->view)
51892 -+ protocol->store(table_list->view_name.str, system_charset_info);
51893 -+ else
51894 -+ {
51895 -+ if (table_list->schema_table)
51896 -+ protocol->store(table_list->schema_table->table_name,
51897 -+ system_charset_info);
51898 -+ else
51899 -+ protocol->store(table_list->table->alias, system_charset_info);
51900 -+ }
51901 -+
51902 -+ if (table_list->view)
51903 -+ {
51904 -+ protocol->store(buffer.ptr(), buffer.length(),
51905 -+ table_list->view_creation_ctx->get_client_cs());
51906 -+
51907 -+ protocol->store(table_list->view_creation_ctx->get_client_cs()->csname,
51908 -+ system_charset_info);
51909 -+
51910 -+ protocol->store(table_list->view_creation_ctx->get_connection_cl()->name,
51911 -+ system_charset_info);
51912 -+ }
51913 -+ else
51914 -+ protocol->store(buffer.ptr(), buffer.length(), buffer.charset());
51915 -+
51916 -+ if (protocol->write())
51917 -+ DBUG_RETURN(TRUE);
51918 -+
51919 -+ my_eof(thd);
51920 -+ DBUG_RETURN(FALSE);
51921 -+}
51922 -+
51923 -+bool mysqld_show_create_db(THD *thd, char *dbname,
51924 -+ HA_CREATE_INFO *create_info)
51925 -+{
51926 -+ char buff[2048];
51927 -+ String buffer(buff, sizeof(buff), system_charset_info);
51928 -+#ifndef NO_EMBEDDED_ACCESS_CHECKS
51929 -+ Security_context *sctx= thd->security_ctx;
51930 -+ uint db_access;
51931 -+#endif
51932 -+ HA_CREATE_INFO create;
51933 -+ uint create_options = create_info ? create_info->options : 0;
51934 -+ Protocol *protocol=thd->protocol;
51935 -+ DBUG_ENTER("mysql_show_create_db");
51936 -+
51937 -+#ifndef NO_EMBEDDED_ACCESS_CHECKS
51938 -+ if (test_all_bits(sctx->master_access, DB_ACLS))
51939 -+ db_access=DB_ACLS;
51940 -+ else
51941 -+ db_access= (acl_get(sctx->host, sctx->ip, sctx->priv_user, dbname, 0) |
51942 -+ sctx->master_access);
51943 -+ if (!(db_access & DB_ACLS) && check_grant_db(thd,dbname))
51944 -+ {
51945 -+ my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
51946 -+ sctx->priv_user, sctx->host_or_ip, dbname);
51947 -+ general_log_print(thd,COM_INIT_DB,ER(ER_DBACCESS_DENIED_ERROR),
51948 -+ sctx->priv_user, sctx->host_or_ip, dbname);
51949 -+ DBUG_RETURN(TRUE);
51950 -+ }
51951 -+#endif
51952 -+ if (is_schema_db(dbname))
51953 -+ {
51954 -+ dbname= INFORMATION_SCHEMA_NAME.str;
51955 -+ create.default_table_charset= system_charset_info;
51956 -+ }
51957 -+ else
51958 -+ {
51959 -+ if (check_db_dir_existence(dbname))
51960 -+ {
51961 -+ my_error(ER_BAD_DB_ERROR, MYF(0), dbname);
51962 -+ DBUG_RETURN(TRUE);
51963 -+ }
51964 -+
51965 -+ load_db_opt_by_name(thd, dbname, &create);
51966 -+ }
51967 -+ List<Item> field_list;
51968 -+ field_list.push_back(new Item_empty_string("Database",NAME_CHAR_LEN));
51969 -+ field_list.push_back(new Item_empty_string("Create Database",1024));
51970 -+
51971 -+ if (protocol->send_fields(&field_list,
51972 -+ Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
51973 -+ DBUG_RETURN(TRUE);
51974 -+
51975 -+ protocol->prepare_for_resend();
51976 -+ protocol->store(dbname, strlen(dbname), system_charset_info);
51977 -+ buffer.length(0);
51978 -+ buffer.append(STRING_WITH_LEN("CREATE DATABASE "));
51979 -+ if (create_options & HA_LEX_CREATE_IF_NOT_EXISTS)
51980 -+ buffer.append(STRING_WITH_LEN("/*!32312 IF NOT EXISTS*/ "));
51981 -+ append_identifier(thd, &buffer, dbname, strlen(dbname));
51982 -+
51983 -+ if (create.default_table_charset)
51984 -+ {
51985 -+ buffer.append(STRING_WITH_LEN(" /*!40100"));
51986 -+ buffer.append(STRING_WITH_LEN(" DEFAULT CHARACTER SET "));
51987 -+ buffer.append(create.default_table_charset->csname);
51988 -+ if (!(create.default_table_charset->state & MY_CS_PRIMARY))
51989 -+ {
51990 -+ buffer.append(STRING_WITH_LEN(" COLLATE "));
51991 -+ buffer.append(create.default_table_charset->name);
51992 -+ }
51993 -+ buffer.append(STRING_WITH_LEN(" */"));
51994 -+ }
51995 -+ protocol->store(buffer.ptr(), buffer.length(), buffer.charset());
51996 -+
51997 -+ if (protocol->write())
51998 -+ DBUG_RETURN(TRUE);
51999 -+ my_eof(thd);
52000 -+ DBUG_RETURN(FALSE);
52001 -+}
52002 -+
52003 -+
52004 -+
52005 -+/****************************************************************************
52006 -+ Return only fields for API mysql_list_fields
52007 -+ Use "show table wildcard" in mysql instead of this
52008 -+****************************************************************************/
52009 -+
52010 -+void
52011 -+mysqld_list_fields(THD *thd, TABLE_LIST *table_list, const char *wild)
52012 -+{
52013 -+ TABLE *table;
52014 -+ DBUG_ENTER("mysqld_list_fields");
52015 -+ DBUG_PRINT("enter",("table: %s",table_list->table_name));
52016 -+
52017 -+ if (open_normal_and_derived_tables(thd, table_list, 0))
52018 -+ DBUG_VOID_RETURN;
52019 -+ table= table_list->table;
52020 -+
52021 -+ List<Item> field_list;
52022 -+
52023 -+ Field **ptr,*field;
52024 -+ for (ptr=table->field ; (field= *ptr); ptr++)
52025 -+ {
52026 -+ if (!wild || !wild[0] ||
52027 -+ !wild_case_compare(system_charset_info, field->field_name,wild))
52028 -+ {
52029 -+ if (table_list->view)
52030 -+ field_list.push_back(new Item_ident_for_show(field,
52031 -+ table_list->view_db.str,
52032 -+ table_list->view_name.str));
52033 -+ else
52034 -+ field_list.push_back(new Item_field(field));
52035 -+ }
52036 -+ }
52037 -+ restore_record(table, s->default_values); // Get empty record
52038 -+ table->use_all_columns();
52039 -+ if (thd->protocol->send_fields(&field_list, Protocol::SEND_DEFAULTS))
52040 -+ DBUG_VOID_RETURN;
52041 -+ my_eof(thd);
52042 -+ DBUG_VOID_RETURN;
52043 -+}
52044 -+
52045 -+
52046 -+int
52047 -+mysqld_dump_create_info(THD *thd, TABLE_LIST *table_list, int fd)
52048 -+{
52049 -+ Protocol *protocol= thd->protocol;
52050 -+ String *packet= protocol->storage_packet();
52051 -+ DBUG_ENTER("mysqld_dump_create_info");
52052 -+ DBUG_PRINT("enter",("table: %s",table_list->table->s->table_name.str));
52053 -+
52054 -+ protocol->prepare_for_resend();
52055 -+ if (store_create_info(thd, table_list, packet, NULL,
52056 -+ FALSE /* show_database */))
52057 -+ DBUG_RETURN(-1);
52058 -+
52059 -+ if (fd < 0)
52060 -+ {
52061 -+ if (protocol->write())
52062 -+ DBUG_RETURN(-1);
52063 -+ protocol->flush();
52064 -+ }
52065 -+ else
52066 -+ {
52067 -+ if (my_write(fd, (const uchar*) packet->ptr(), packet->length(),
52068 -+ MYF(MY_WME)))
52069 -+ DBUG_RETURN(-1);
52070 -+ }
52071 -+ DBUG_RETURN(0);
52072 -+}
52073 -+
52074 -+/*
52075 -+ Go through all character combinations and ensure that sql_lex.cc can
52076 -+ parse it as an identifier.
52077 -+
52078 -+ SYNOPSIS
52079 -+ require_quotes()
52080 -+ name attribute name
52081 -+ name_length length of name
52082 -+
52083 -+ RETURN
52084 -+ # Pointer to conflicting character
52085 -+ 0 No conflicting character
52086 -+*/
52087 -+
52088 -+static const char *require_quotes(const char *name, uint name_length)
52089 -+{
52090 -+ uint length;
52091 -+ bool pure_digit= TRUE;
52092 -+ const char *end= name + name_length;
52093 -+
52094 -+ for (; name < end ; name++)
52095 -+ {
52096 -+ uchar chr= (uchar) *name;
52097 -+ length= my_mbcharlen(system_charset_info, chr);
52098 -+ if (length == 1 && !system_charset_info->ident_map[chr])
52099 -+ return name;
52100 -+ if (length == 1 && (chr < '0' || chr > '9'))
52101 -+ pure_digit= FALSE;
52102 -+ }
52103 -+ if (pure_digit)
52104 -+ return name;
52105 -+ return 0;
52106 -+}
52107 -+
52108 -+
52109 -+/*
52110 -+ Quote the given identifier if needed and append it to the target string.
52111 -+ If the given identifier is empty, it will be quoted.
52112 -+
52113 -+ SYNOPSIS
52114 -+ append_identifier()
52115 -+ thd thread handler
52116 -+ packet target string
52117 -+ name the identifier to be appended
52118 -+ name_length length of the appending identifier
52119 -+*/
52120 -+
52121 -+void
52122 -+append_identifier(THD *thd, String *packet, const char *name, uint length)
52123 -+{
52124 -+ const char *name_end;
52125 -+ char quote_char;
52126 -+ int q= get_quote_char_for_identifier(thd, name, length);
52127 -+
52128 -+ if (q == EOF)
52129 -+ {
52130 -+ packet->append(name, length, packet->charset());
52131 -+ return;
52132 -+ }
52133 -+
52134 -+ /*
52135 -+ The identifier must be quoted as it includes a quote character or
52136 -+ it's a keyword
52137 -+ */
52138 -+
52139 -+ VOID(packet->reserve(length*2 + 2));
52140 -+ quote_char= (char) q;
52141 -+ packet->append(&quote_char, 1, system_charset_info);
52142 -+
52143 -+ for (name_end= name+length ; name < name_end ; name+= length)
52144 -+ {
52145 -+ uchar chr= (uchar) *name;
52146 -+ length= my_mbcharlen(system_charset_info, chr);
52147 -+ /*
52148 -+ my_mbcharlen can return 0 on a wrong multibyte
52149 -+ sequence. It is possible when upgrading from 4.0,
52150 -+ and identifier contains some accented characters.
52151 -+ The manual says it does not work. So we'll just
52152 -+ change length to 1 not to hang in the endless loop.
52153 -+ */
52154 -+ if (!length)
52155 -+ length= 1;
52156 -+ if (length == 1 && chr == (uchar) quote_char)
52157 -+ packet->append(&quote_char, 1, system_charset_info);
52158 -+ packet->append(name, length, system_charset_info);
52159 -+ }
52160 -+ packet->append(&quote_char, 1, system_charset_info);
52161 -+}
52162 -+
52163 -+
52164 -+/*
52165 -+ Get the quote character for displaying an identifier.
52166 -+
52167 -+ SYNOPSIS
52168 -+ get_quote_char_for_identifier()
52169 -+ thd Thread handler
52170 -+ name name to quote
52171 -+ length length of name
52172 -+
52173 -+ IMPLEMENTATION
52174 -+ Force quoting in the following cases:
52175 -+ - name is empty (for one, it is possible when we use this function for
52176 -+ quoting user and host names for DEFINER clause);
52177 -+ - name is a keyword;
52178 -+ - name includes a special character;
52179 -+ Otherwise identifier is quoted only if the option OPTION_QUOTE_SHOW_CREATE
52180 -+ is set.
52181 -+
52182 -+ RETURN
52183 -+ EOF No quote character is needed
52184 -+ # Quote character
52185 -+*/
52186 -+
52187 -+int get_quote_char_for_identifier(THD *thd, const char *name, uint length)
52188 -+{
52189 -+ if (length &&
52190 -+ !is_keyword(name,length) &&
52191 -+ !require_quotes(name, length) &&
52192 -+ !(thd->options & OPTION_QUOTE_SHOW_CREATE))
52193 -+ return EOF;
52194 -+ if (thd->variables.sql_mode & MODE_ANSI_QUOTES)
52195 -+ return '"';
52196 -+ return '`';
52197 -+}
52198 -+
52199 -+
52200 -+/* Append directory name (if exists) to CREATE INFO */
52201 -+
52202 -+static void append_directory(THD *thd, String *packet, const char *dir_type,
52203 -+ const char *filename)
52204 -+{
52205 -+ if (filename && !(thd->variables.sql_mode & MODE_NO_DIR_IN_CREATE))
52206 -+ {
52207 -+ uint length= dirname_length(filename);
52208 -+ packet->append(' ');
52209 -+ packet->append(dir_type);
52210 -+ packet->append(STRING_WITH_LEN(" DIRECTORY='"));
52211 -+#ifdef __WIN__
52212 -+ /* Convert \ to / to be able to create table on unix */
52213 -+ char *winfilename= (char*) thd->memdup(filename, length);
52214 -+ char *pos, *end;
52215 -+ for (pos= winfilename, end= pos+length ; pos < end ; pos++)
52216 -+ {
52217 -+ if (*pos == '\\')
52218 -+ *pos = '/';
52219 -+ }
52220 -+ filename= winfilename;
52221 -+#endif
52222 -+ packet->append(filename, length);
52223 -+ packet->append('\'');
52224 -+ }
52225 -+}
52226 -+
52227 -+
52228 -+#define LIST_PROCESS_HOST_LEN 64
52229 -+
52230 -+static bool get_field_default_value(THD *thd, TABLE *table,
52231 -+ Field *field, String *def_value,
52232 -+ bool quoted)
52233 -+{
52234 -+ bool has_default;
52235 -+ bool has_now_default;
52236 -+ enum enum_field_types field_type= field->type();
52237 -+ /*
52238 -+ We are using CURRENT_TIMESTAMP instead of NOW because it is
52239 -+ more standard
52240 -+ */
52241 -+ has_now_default= table->timestamp_field == field &&
52242 -+ field->unireg_check != Field::TIMESTAMP_UN_FIELD;
52243 -+
52244 -+ has_default= (field_type != FIELD_TYPE_BLOB &&
52245 -+ !(field->flags & NO_DEFAULT_VALUE_FLAG) &&
52246 -+ field->unireg_check != Field::NEXT_NUMBER &&
52247 -+ !((thd->variables.sql_mode & (MODE_MYSQL323 | MODE_MYSQL40))
52248 -+ && has_now_default));
52249 -+
52250 -+ def_value->length(0);
52251 -+ if (has_default)
52252 -+ {
52253 -+ if (has_now_default)
52254 -+ def_value->append(STRING_WITH_LEN("CURRENT_TIMESTAMP"));
52255 -+ else if (!field->is_null())
52256 -+ { // Not null by default
52257 -+ char tmp[MAX_FIELD_WIDTH];
52258 -+ String type(tmp, sizeof(tmp), field->charset());
52259 -+ if (field_type == MYSQL_TYPE_BIT)
52260 -+ {
52261 -+ longlong dec= field->val_int();
52262 -+ char *ptr= longlong2str(dec, tmp + 2, 2);
52263 -+ uint32 length= (uint32) (ptr - tmp);
52264 -+ tmp[0]= 'b';
52265 -+ tmp[1]= '\'';
52266 -+ tmp[length]= '\'';
52267 -+ type.length(length + 1);
52268 -+ quoted= 0;
52269 -+ }
52270 -+ else
52271 -+ field->val_str(&type);
52272 -+ if (type.length())
52273 -+ {
52274 -+ String def_val;
52275 -+ uint dummy_errors;
52276 -+ /* convert to system_charset_info == utf8 */
52277 -+ def_val.copy(type.ptr(), type.length(), field->charset(),
52278 -+ system_charset_info, &dummy_errors);
52279 -+ if (quoted)
52280 -+ append_unescaped(def_value, def_val.ptr(), def_val.length());
52281 -+ else
52282 -+ def_value->append(def_val.ptr(), def_val.length());
52283 -+ }
52284 -+ else if (quoted)
52285 -+ def_value->append(STRING_WITH_LEN("''"));
52286 -+ }
52287 -+ else if (field->maybe_null() && quoted)
52288 -+ def_value->append(STRING_WITH_LEN("NULL")); // Null as default
52289 -+ else
52290 -+ return 0;
52291 -+
52292 -+ }
52293 -+ return has_default;
52294 -+}
52295 -+
52296 -+/*
52297 -+ Build a CREATE TABLE statement for a table.
52298 -+
52299 -+ SYNOPSIS
52300 -+ store_create_info()
52301 -+ thd The thread
52302 -+ table_list A list containing one table to write statement
52303 -+ for.
52304 -+ packet Pointer to a string where statement will be
52305 -+ written.
52306 -+ create_info_arg Pointer to create information that can be used
52307 -+ to tailor the format of the statement. Can be
52308 -+ NULL, in which case only SQL_MODE is considered
52309 -+ when building the statement.
52310 -+
52311 -+ NOTE
52312 -+ Currently always return 0, but might return error code in the
52313 -+ future.
52314 -+
52315 -+ RETURN
52316 -+ 0 OK
52317 -+ */
52318 -+
52319 -+int store_create_info(THD *thd, TABLE_LIST *table_list, String *packet,
52320 -+ HA_CREATE_INFO *create_info_arg, bool show_database)
52321 -+{
52322 -+ List<Item> field_list;
52323 -+ char tmp[MAX_FIELD_WIDTH], *for_str, buff[128], def_value_buf[MAX_FIELD_WIDTH];
52324 -+ const char *alias;
52325 -+ String type(tmp, sizeof(tmp), system_charset_info);
52326 -+ String def_value(def_value_buf, sizeof(def_value_buf), system_charset_info);
52327 -+ Field **ptr,*field;
52328 -+ uint primary_key;
52329 -+ KEY *key_info;
52330 -+ TABLE *table= table_list->table;
52331 -+ handler *file= table->file;
52332 -+ TABLE_SHARE *share= table->s;
52333 -+ HA_CREATE_INFO create_info;
52334 -+ bool show_table_options= FALSE;
52335 -+ bool foreign_db_mode= (thd->variables.sql_mode & (MODE_POSTGRESQL |
52336 -+ MODE_ORACLE |
52337 -+ MODE_MSSQL |
52338 -+ MODE_DB2 |
52339 -+ MODE_MAXDB |
52340 -+ MODE_ANSI)) != 0;
52341 -+ bool limited_mysql_mode= (thd->variables.sql_mode & (MODE_NO_FIELD_OPTIONS |
52342 -+ MODE_MYSQL323 |
52343 -+ MODE_MYSQL40)) != 0;
52344 -+ my_bitmap_map *old_map;
52345 -+ DBUG_ENTER("store_create_info");
52346 -+ DBUG_PRINT("enter",("table: %s", table->s->table_name.str));
52347 -+
52348 -+ restore_record(table, s->default_values); // Get empty record
52349 -+
52350 -+ if (share->tmp_table)
52351 -+ packet->append(STRING_WITH_LEN("CREATE TEMPORARY TABLE "));
52352 -+ else
52353 -+ packet->append(STRING_WITH_LEN("CREATE TABLE "));
52354 -+ if (create_info_arg &&
52355 -+ (create_info_arg->options & HA_LEX_CREATE_IF_NOT_EXISTS))
52356 -+ packet->append(STRING_WITH_LEN("IF NOT EXISTS "));
52357 -+ if (table_list->schema_table)
52358 -+ alias= table_list->schema_table->table_name;
52359 -+ else
52360 -+ {
52361 -+ if (lower_case_table_names == 2)
52362 -+ alias= table->alias;
52363 -+ else
52364 -+ {
52365 -+ alias= share->table_name.str;
52366 -+ }
52367 -+ }
52368 -+
52369 -+ /*
52370 -+ Print the database before the table name if told to do that. The
52371 -+ database name is only printed in the event that it is different
52372 -+ from the current database. The main reason for doing this is to
52373 -+ avoid having to update gazillions of tests and result files, but
52374 -+ it also saves a few bytes of the binary log.
52375 -+ */
52376 -+ if (show_database)
52377 -+ {
52378 -+ const LEX_STRING *const db=
52379 -+ table_list->schema_table ? &INFORMATION_SCHEMA_NAME : &table->s->db;
52380 -+ if (!thd->db || strcmp(db->str, thd->db))
52381 -+ {
52382 -+ append_identifier(thd, packet, db->str, db->length);
52383 -+ packet->append(STRING_WITH_LEN("."));
52384 -+ }
52385 -+ }
52386 -+
52387 -+ append_identifier(thd, packet, alias, strlen(alias));
52388 -+ packet->append(STRING_WITH_LEN(" (\n"));
52389 -+ /*
52390 -+ We need this to get default values from the table
52391 -+ We have to restore the read_set if we are called from insert in case
52392 -+ of row based replication.
52393 -+ */
52394 -+ old_map= tmp_use_all_columns(table, table->read_set);
52395 -+
52396 -+ for (ptr=table->field ; (field= *ptr); ptr++)
52397 -+ {
52398 -+ uint flags = field->flags;
52399 -+
52400 -+ if (ptr != table->field)
52401 -+ packet->append(STRING_WITH_LEN(",\n"));
52402 -+
52403 -+ packet->append(STRING_WITH_LEN(" "));
52404 -+ append_identifier(thd,packet,field->field_name, strlen(field->field_name));
52405 -+ packet->append(' ');
52406 -+ // check for surprises from the previous call to Field::sql_type()
52407 -+ if (type.ptr() != tmp)
52408 -+ type.set(tmp, sizeof(tmp), system_charset_info);
52409 -+ else
52410 -+ type.set_charset(system_charset_info);
52411 -+
52412 -+ field->sql_type(type);
52413 -+ packet->append(type.ptr(), type.length(), system_charset_info);
52414 -+
52415 -+ if (field->has_charset() &&
52416 -+ !(thd->variables.sql_mode & (MODE_MYSQL323 | MODE_MYSQL40)))
52417 -+ {
52418 -+ if (field->charset() != share->table_charset)
52419 -+ {
52420 -+ packet->append(STRING_WITH_LEN(" CHARACTER SET "));
52421 -+ packet->append(field->charset()->csname);
52422 -+ }
52423 -+ /*
52424 -+ For string types dump collation name only if
52425 -+ collation is not primary for the given charset
52426 -+ */
52427 -+ if (!(field->charset()->state & MY_CS_PRIMARY))
52428 -+ {
52429 -+ packet->append(STRING_WITH_LEN(" COLLATE "));
52430 -+ packet->append(field->charset()->name);
52431 -+ }
52432 -+ }
52433 -+
52434 -+ if (flags & NOT_NULL_FLAG)
52435 -+ packet->append(STRING_WITH_LEN(" NOT NULL"));
52436 -+ else if (field->type() == MYSQL_TYPE_TIMESTAMP)
52437 -+ {
52438 -+ /*
52439 -+ TIMESTAMP field require explicit NULL flag, because unlike
52440 -+ all other fields they are treated as NOT NULL by default.
52441 -+ */
52442 -+ packet->append(STRING_WITH_LEN(" NULL"));
52443 -+ }
52444 -+
52445 -+ if (get_field_default_value(thd, table, field, &def_value, 1))
52446 -+ {
52447 -+ packet->append(STRING_WITH_LEN(" DEFAULT "));
52448 -+ packet->append(def_value.ptr(), def_value.length(), system_charset_info);
52449 -+ }
52450 -+
52451 -+ if (!limited_mysql_mode && table->timestamp_field == field &&
52452 -+ field->unireg_check != Field::TIMESTAMP_DN_FIELD)
52453 -+ packet->append(STRING_WITH_LEN(" ON UPDATE CURRENT_TIMESTAMP"));
52454 -+
52455 -+ if (field->unireg_check == Field::NEXT_NUMBER &&
52456 -+ !(thd->variables.sql_mode & MODE_NO_FIELD_OPTIONS))
52457 -+ packet->append(STRING_WITH_LEN(" AUTO_INCREMENT"));
52458 -+
52459 -+ if (field->comment.length)
52460 -+ {
52461 -+ packet->append(STRING_WITH_LEN(" COMMENT "));
52462 -+ append_unescaped(packet, field->comment.str, field->comment.length);
52463 -+ }
52464 -+ }
52465 -+
52466 -+ key_info= table->key_info;
52467 -+ bzero((char*) &create_info, sizeof(create_info));
52468 -+ /* Allow update_create_info to update row type */
52469 -+ create_info.row_type= share->row_type;
52470 -+ file->update_create_info(&create_info);
52471 -+ primary_key= share->primary_key;
52472 -+
52473 -+ for (uint i=0 ; i < share->keys ; i++,key_info++)
52474 -+ {
52475 -+ KEY_PART_INFO *key_part= key_info->key_part;
52476 -+ bool found_primary=0;
52477 -+ packet->append(STRING_WITH_LEN(",\n "));
52478 -+
52479 -+ if (i == primary_key && !strcmp(key_info->name, primary_key_name))
52480 -+ {
52481 -+ found_primary=1;
52482 -+ /*
52483 -+ No space at end, because a space will be added after where the
52484 -+ identifier would go, but that is not added for primary key.
52485 -+ */
52486 -+ packet->append(STRING_WITH_LEN("PRIMARY KEY"));
52487 -+ }
52488 -+ else if (key_info->flags & HA_NOSAME)
52489 -+ packet->append(STRING_WITH_LEN("UNIQUE KEY "));
52490 -+ else if (key_info->flags & HA_FULLTEXT)
52491 -+ packet->append(STRING_WITH_LEN("FULLTEXT KEY "));
52492 -+ else if (key_info->flags & HA_SPATIAL)
52493 -+ packet->append(STRING_WITH_LEN("SPATIAL KEY "));
52494 -+ else
52495 -+ packet->append(STRING_WITH_LEN("KEY "));
52496 -+
52497 -+ if (!found_primary)
52498 -+ append_identifier(thd, packet, key_info->name, strlen(key_info->name));
52499 -+
52500 -+ packet->append(STRING_WITH_LEN(" ("));
52501 -+
52502 -+ for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
52503 -+ {
52504 -+ if (j)
52505 -+ packet->append(',');
52506 -+
52507 -+ if (key_part->field)
52508 -+ append_identifier(thd,packet,key_part->field->field_name,
52509 -+ strlen(key_part->field->field_name));
52510 -+ if (key_part->field &&
52511 -+ (key_part->length !=
52512 -+ table->field[key_part->fieldnr-1]->key_length() &&
52513 -+ !(key_info->flags & (HA_FULLTEXT | HA_SPATIAL))))
52514 -+ {
52515 -+ char *end;
52516 -+ buff[0] = '(';
52517 -+ end= int10_to_str((long) key_part->length /
52518 -+ key_part->field->charset()->mbmaxlen,
52519 -+ buff + 1,10);
52520 -+ *end++ = ')';
52521 -+ packet->append(buff,(uint) (end-buff));
52522 -+ }
52523 -+ }
52524 -+ packet->append(')');
52525 -+ store_key_options(thd, packet, table, key_info);
52526 -+ if (key_info->parser)
52527 -+ {
52528 -+ LEX_STRING *parser_name= plugin_name(key_info->parser);
52529 -+ packet->append(STRING_WITH_LEN(" /*!50100 WITH PARSER "));
52530 -+ append_identifier(thd, packet, parser_name->str, parser_name->length);
52531 -+ packet->append(STRING_WITH_LEN(" */ "));
52532 -+ }
52533 -+ }
52534 -+
52535 -+ /*
52536 -+ Get possible foreign key definitions stored in InnoDB and append them
52537 -+ to the CREATE TABLE statement
52538 -+ */
52539 -+
52540 -+ if ((for_str= file->get_foreign_key_create_info()))
52541 -+ {
52542 -+ packet->append(for_str, strlen(for_str));
52543 -+ file->free_foreign_key_create_info(for_str);
52544 -+ }
52545 -+
52546 -+ packet->append(STRING_WITH_LEN("\n)"));
52547 -+ if (!(thd->variables.sql_mode & MODE_NO_TABLE_OPTIONS) && !foreign_db_mode)
52548 -+ {
52549 -+ show_table_options= TRUE;
52550 -+ /*
52551 -+ Get possible table space definitions and append them
52552 -+ to the CREATE TABLE statement
52553 -+ */
52554 -+
52555 -+ if ((for_str= file->get_tablespace_name(thd,0,0)))
52556 -+ {
52557 -+ packet->append(STRING_WITH_LEN(" /*!50100 TABLESPACE "));
52558 -+ packet->append(for_str, strlen(for_str));
52559 -+ packet->append(STRING_WITH_LEN(" STORAGE DISK */"));
52560 -+ my_free(for_str, MYF(0));
52561 -+ }
52562 -+
52563 -+ /*
52564 -+ IF check_create_info
52565 -+ THEN add ENGINE only if it was used when creating the table
52566 -+ */
52567 -+ if (!create_info_arg ||
52568 -+ (create_info_arg->used_fields & HA_CREATE_USED_ENGINE))
52569 -+ {
52570 -+ if (thd->variables.sql_mode & (MODE_MYSQL323 | MODE_MYSQL40))
52571 -+ packet->append(STRING_WITH_LEN(" TYPE="));
52572 -+ else
52573 -+ packet->append(STRING_WITH_LEN(" ENGINE="));
52574 -+#ifdef WITH_PARTITION_STORAGE_ENGINE
52575 -+ if (table->part_info)
52576 -+ packet->append(ha_resolve_storage_engine_name(
52577 -+ table->part_info->default_engine_type));
52578 -+ else
52579 -+ packet->append(file->table_type());
52580 -+#else
52581 -+ packet->append(file->table_type());
52582 -+#endif
52583 -+ }
52584 -+
52585 -+ /*
52586 -+ Add AUTO_INCREMENT=... if there is an AUTO_INCREMENT column,
52587 -+ and NEXT_ID > 1 (the default). We must not print the clause
52588 -+ for engines that do not support this as it would break the
52589 -+ import of dumps, but as of this writing, the test for whether
52590 -+ AUTO_INCREMENT columns are allowed and wether AUTO_INCREMENT=...
52591 -+ is supported is identical, !(file->table_flags() & HA_NO_AUTO_INCREMENT))
52592 -+ Because of that, we do not explicitly test for the feature,
52593 -+ but may extrapolate its existence from that of an AUTO_INCREMENT column.
52594 -+ */
52595 -+
52596 -+ if (create_info.auto_increment_value > 1)
52597 -+ {
52598 -+ char *end;
52599 -+ packet->append(STRING_WITH_LEN(" AUTO_INCREMENT="));
52600 -+ end= longlong10_to_str(create_info.auto_increment_value, buff,10);
52601 -+ packet->append(buff, (uint) (end - buff));
52602 -+ }
52603 -+
52604 -+
52605 -+ if (share->table_charset &&
52606 -+ !(thd->variables.sql_mode & MODE_MYSQL323) &&
52607 -+ !(thd->variables.sql_mode & MODE_MYSQL40))
52608 -+ {
52609 -+ /*
52610 -+ IF check_create_info
52611 -+ THEN add DEFAULT CHARSET only if it was used when creating the table
52612 -+ */
52613 -+ if (!create_info_arg ||
52614 -+ (create_info_arg->used_fields & HA_CREATE_USED_DEFAULT_CHARSET))
52615 -+ {
52616 -+ packet->append(STRING_WITH_LEN(" DEFAULT CHARSET="));
52617 -+ packet->append(share->table_charset->csname);
52618 -+ if (!(share->table_charset->state & MY_CS_PRIMARY))
52619 -+ {
52620 -+ packet->append(STRING_WITH_LEN(" COLLATE="));
52621 -+ packet->append(table->s->table_charset->name);
52622 -+ }
52623 -+ }
52624 -+ }
52625 -+
52626 -+ if (share->min_rows)
52627 -+ {
52628 -+ char *end;
52629 -+ packet->append(STRING_WITH_LEN(" MIN_ROWS="));
52630 -+ end= longlong10_to_str(share->min_rows, buff, 10);
52631 -+ packet->append(buff, (uint) (end- buff));
52632 -+ }
52633 -+
52634 -+ if (share->max_rows && !table_list->schema_table)
52635 -+ {
52636 -+ char *end;
52637 -+ packet->append(STRING_WITH_LEN(" MAX_ROWS="));
52638 -+ end= longlong10_to_str(share->max_rows, buff, 10);
52639 -+ packet->append(buff, (uint) (end - buff));
52640 -+ }
52641 -+
52642 -+ if (share->avg_row_length)
52643 -+ {
52644 -+ char *end;
52645 -+ packet->append(STRING_WITH_LEN(" AVG_ROW_LENGTH="));
52646 -+ end= longlong10_to_str(share->avg_row_length, buff,10);
52647 -+ packet->append(buff, (uint) (end - buff));
52648 -+ }
52649 -+
52650 -+ if (share->db_create_options & HA_OPTION_PACK_KEYS)
52651 -+ packet->append(STRING_WITH_LEN(" PACK_KEYS=1"));
52652 -+ if (share->db_create_options & HA_OPTION_NO_PACK_KEYS)
52653 -+ packet->append(STRING_WITH_LEN(" PACK_KEYS=0"));
52654 -+ /* We use CHECKSUM, instead of TABLE_CHECKSUM, for backward compability */
52655 -+ if (share->db_create_options & HA_OPTION_CHECKSUM)
52656 -+ packet->append(STRING_WITH_LEN(" CHECKSUM=1"));
52657 -+ if (share->db_create_options & HA_OPTION_DELAY_KEY_WRITE)
52658 -+ packet->append(STRING_WITH_LEN(" DELAY_KEY_WRITE=1"));
52659 -+ if (create_info.row_type != ROW_TYPE_DEFAULT)
52660 -+ {
52661 -+ packet->append(STRING_WITH_LEN(" ROW_FORMAT="));
52662 -+ packet->append(ha_row_type[(uint) create_info.row_type]);
52663 -+ }
52664 -+ if (table->s->key_block_size)
52665 -+ {
52666 -+ char *end;
52667 -+ packet->append(STRING_WITH_LEN(" KEY_BLOCK_SIZE="));
52668 -+ end= longlong10_to_str(table->s->key_block_size, buff, 10);
52669 -+ packet->append(buff, (uint) (end - buff));
52670 -+ }
52671 -+ table->file->append_create_info(packet);
52672 -+ if (share->comment.length)
52673 -+ {
52674 -+ packet->append(STRING_WITH_LEN(" COMMENT="));
52675 -+ append_unescaped(packet, share->comment.str, share->comment.length);
52676 -+ }
52677 -+ if (share->connect_string.length)
52678 -+ {
52679 -+ packet->append(STRING_WITH_LEN(" CONNECTION="));
52680 -+ append_unescaped(packet, share->connect_string.str, share->connect_string.length);
52681 -+ }
52682 -+ append_directory(thd, packet, "DATA", create_info.data_file_name);
52683 -+ append_directory(thd, packet, "INDEX", create_info.index_file_name);
52684 -+ }
52685 -+#ifdef WITH_PARTITION_STORAGE_ENGINE
52686 -+ {
52687 -+ /*
52688 -+ Partition syntax for CREATE TABLE is at the end of the syntax.
52689 -+ */
52690 -+ uint part_syntax_len;
52691 -+ char *part_syntax;
52692 -+ if (table->part_info &&
52693 -+ (!table->part_info->is_auto_partitioned) &&
52694 -+ ((part_syntax= generate_partition_syntax(table->part_info,
52695 -+ &part_syntax_len,
52696 -+ FALSE,
52697 -+ show_table_options))))
52698 -+ {
52699 -+ packet->append(STRING_WITH_LEN("\n/*!50100"));
52700 -+ packet->append(part_syntax, part_syntax_len);
52701 -+ packet->append(STRING_WITH_LEN(" */"));
52702 -+ my_free(part_syntax, MYF(0));
52703 -+ }
52704 -+ }
52705 -+#endif
52706 -+ tmp_restore_column_map(table->read_set, old_map);
52707 -+ DBUG_RETURN(0);
52708 -+}
52709 -+
52710 -+
52711 -+static void store_key_options(THD *thd, String *packet, TABLE *table,
52712 -+ KEY *key_info)
52713 -+{
52714 -+ bool limited_mysql_mode= (thd->variables.sql_mode &
52715 -+ (MODE_NO_FIELD_OPTIONS | MODE_MYSQL323 |
52716 -+ MODE_MYSQL40)) != 0;
52717 -+ bool foreign_db_mode= (thd->variables.sql_mode & (MODE_POSTGRESQL |
52718 -+ MODE_ORACLE |
52719 -+ MODE_MSSQL |
52720 -+ MODE_DB2 |
52721 -+ MODE_MAXDB |
52722 -+ MODE_ANSI)) != 0;
52723 -+ char *end, buff[32];
52724 -+
52725 -+ if (!(thd->variables.sql_mode & MODE_NO_KEY_OPTIONS) &&
52726 -+ !limited_mysql_mode && !foreign_db_mode)
52727 -+ {
52728 -+
52729 -+ if (key_info->algorithm == HA_KEY_ALG_BTREE)
52730 -+ packet->append(STRING_WITH_LEN(" USING BTREE"));
52731 -+
52732 -+ if (key_info->algorithm == HA_KEY_ALG_HASH)
52733 -+ packet->append(STRING_WITH_LEN(" USING HASH"));
52734 -+
52735 -+ /* send USING only in non-default case: non-spatial rtree */
52736 -+ if ((key_info->algorithm == HA_KEY_ALG_RTREE) &&
52737 -+ !(key_info->flags & HA_SPATIAL))
52738 -+ packet->append(STRING_WITH_LEN(" USING RTREE"));
52739 -+
52740 -+ if ((key_info->flags & HA_USES_BLOCK_SIZE) &&
52741 -+ table->s->key_block_size != key_info->block_size)
52742 -+ {
52743 -+ packet->append(STRING_WITH_LEN(" KEY_BLOCK_SIZE="));
52744 -+ end= longlong10_to_str(key_info->block_size, buff, 10);
52745 -+ packet->append(buff, (uint) (end - buff));
52746 -+ }
52747 -+ }
52748 -+}
52749 -+
52750 -+
52751 -+void
52752 -+view_store_options(THD *thd, TABLE_LIST *table, String *buff)
52753 -+{
52754 -+ append_algorithm(table, buff);
52755 -+ append_definer(thd, buff, &table->definer.user, &table->definer.host);
52756 -+ if (table->view_suid)
52757 -+ buff->append(STRING_WITH_LEN("SQL SECURITY DEFINER "));
52758 -+ else
52759 -+ buff->append(STRING_WITH_LEN("SQL SECURITY INVOKER "));
52760 -+}
52761 -+
52762 -+
52763 -+/*
52764 -+ Append DEFINER clause to the given buffer.
52765 -+
52766 -+ SYNOPSIS
52767 -+ append_definer()
52768 -+ thd [in] thread handle
52769 -+ buffer [inout] buffer to hold DEFINER clause
52770 -+ definer_user [in] user name part of definer
52771 -+ definer_host [in] host name part of definer
52772 -+*/
52773 -+
52774 -+static void append_algorithm(TABLE_LIST *table, String *buff)
52775 -+{
52776 -+ buff->append(STRING_WITH_LEN("ALGORITHM="));
52777 -+ switch ((int8)table->algorithm) {
52778 -+ case VIEW_ALGORITHM_UNDEFINED:
52779 -+ buff->append(STRING_WITH_LEN("UNDEFINED "));
52780 -+ break;
52781 -+ case VIEW_ALGORITHM_TMPTABLE:
52782 -+ buff->append(STRING_WITH_LEN("TEMPTABLE "));
52783 -+ break;
52784 -+ case VIEW_ALGORITHM_MERGE:
52785 -+ buff->append(STRING_WITH_LEN("MERGE "));
52786 -+ break;
52787 -+ default:
52788 -+ DBUG_ASSERT(0); // never should happen
52789 -+ }
52790 -+}
52791 -+
52792 -+/*
52793 -+ Append DEFINER clause to the given buffer.
52794 -+
52795 -+ SYNOPSIS
52796 -+ append_definer()
52797 -+ thd [in] thread handle
52798 -+ buffer [inout] buffer to hold DEFINER clause
52799 -+ definer_user [in] user name part of definer
52800 -+ definer_host [in] host name part of definer
52801 -+*/
52802 -+
52803 -+void append_definer(THD *thd, String *buffer, const LEX_STRING *definer_user,
52804 -+ const LEX_STRING *definer_host)
52805 -+{
52806 -+ buffer->append(STRING_WITH_LEN("DEFINER="));
52807 -+ append_identifier(thd, buffer, definer_user->str, definer_user->length);
52808 -+ buffer->append('@');
52809 -+ append_identifier(thd, buffer, definer_host->str, definer_host->length);
52810 -+ buffer->append(' ');
52811 -+}
52812 -+
52813 -+
52814 -+int
52815 -+view_store_create_info(THD *thd, TABLE_LIST *table, String *buff)
52816 -+{
52817 -+ my_bool compact_view_name= TRUE;
52818 -+ my_bool foreign_db_mode= (thd->variables.sql_mode & (MODE_POSTGRESQL |
52819 -+ MODE_ORACLE |
52820 -+ MODE_MSSQL |
52821 -+ MODE_DB2 |
52822 -+ MODE_MAXDB |
52823 -+ MODE_ANSI)) != 0;
52824 -+
52825 -+ if (!thd->db || strcmp(thd->db, table->view_db.str))
52826 -+ /*
52827 -+ print compact view name if the view belongs to the current database
52828 -+ */
52829 -+ compact_view_name= table->compact_view_format= FALSE;
52830 -+ else
52831 -+ {
52832 -+ /*
52833 -+ Compact output format for view body can be used
52834 -+ if this view only references table inside it's own db
52835 -+ */
52836 -+ TABLE_LIST *tbl;
52837 -+ table->compact_view_format= TRUE;
52838 -+ for (tbl= thd->lex->query_tables;
52839 -+ tbl;
52840 -+ tbl= tbl->next_global)
52841 -+ {
52842 -+ if (strcmp(table->view_db.str, tbl->view ? tbl->view_db.str :tbl->db)!= 0)
52843 -+ {
52844 -+ table->compact_view_format= FALSE;
52845 -+ break;
52846 -+ }
52847 -+ }
52848 -+ }
52849 -+
52850 -+ buff->append(STRING_WITH_LEN("CREATE "));
52851 -+ if (!foreign_db_mode)
52852 -+ {
52853 -+ view_store_options(thd, table, buff);
52854 -+ }
52855 -+ buff->append(STRING_WITH_LEN("VIEW "));
52856 -+ if (!compact_view_name)
52857 -+ {
52858 -+ append_identifier(thd, buff, table->view_db.str, table->view_db.length);
52859 -+ buff->append('.');
52860 -+ }
52861 -+ append_identifier(thd, buff, table->view_name.str, table->view_name.length);
52862 -+ buff->append(STRING_WITH_LEN(" AS "));
52863 -+
52864 -+ /*
52865 -+ We can't just use table->query, because our SQL_MODE may trigger
52866 -+ a different syntax, like when ANSI_QUOTES is defined.
52867 -+ */
52868 -+ table->view->unit.print(buff, QT_ORDINARY);
52869 -+
52870 -+ if (table->with_check != VIEW_CHECK_NONE)
52871 -+ {
52872 -+ if (table->with_check == VIEW_CHECK_LOCAL)
52873 -+ buff->append(STRING_WITH_LEN(" WITH LOCAL CHECK OPTION"));
52874 -+ else
52875 -+ buff->append(STRING_WITH_LEN(" WITH CASCADED CHECK OPTION"));
52876 -+ }
52877 -+ return 0;
52878 -+}
52879 -+
52880 -+
52881 -+/****************************************************************************
52882 -+ Return info about all processes
52883 -+ returns for each thread: thread id, user, host, db, command, info
52884 -+****************************************************************************/
52885 -+
52886 -+class thread_info :public ilink {
52887 -+public:
52888 -+ static void *operator new(size_t size)
52889 -+ {
52890 -+ return (void*) sql_alloc((uint) size);
52891 -+ }
52892 -+ static void operator delete(void *ptr __attribute__((unused)),
52893 -+ size_t size __attribute__((unused)))
52894 -+ { TRASH(ptr, size); }
52895 -+
52896 -+ ulong thread_id;
52897 -+ time_t start_time;
52898 -+ uint command;
52899 -+ const char *user,*host,*db,*proc_info,*state_info;
52900 -+ char *query;
52901 -+};
52902 -+
52903 -+#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
52904 -+template class I_List<thread_info>;
52905 -+#endif
52906 -+
52907 -+void mysqld_list_processes(THD *thd,const char *user, bool verbose)
52908 -+{
52909 -+ Item *field;
52910 -+ List<Item> field_list;
52911 -+ I_List<thread_info> thread_infos;
52912 -+ ulong max_query_length= (verbose ? thd->variables.max_allowed_packet :
52913 -+ PROCESS_LIST_WIDTH);
52914 -+ Protocol *protocol= thd->protocol;
52915 -+ DBUG_ENTER("mysqld_list_processes");
52916 -+
52917 -+ field_list.push_back(new Item_int("Id", 0, MY_INT32_NUM_DECIMAL_DIGITS));
52918 -+ field_list.push_back(new Item_empty_string("User",16));
52919 -+ field_list.push_back(new Item_empty_string("Host",LIST_PROCESS_HOST_LEN));
52920 -+ field_list.push_back(field=new Item_empty_string("db",NAME_CHAR_LEN));
52921 -+ field->maybe_null=1;
52922 -+ field_list.push_back(new Item_empty_string("Command",16));
52923 -+ field_list.push_back(field= new Item_return_int("Time",7, MYSQL_TYPE_LONG));
52924 -+ field->unsigned_flag= 0;
52925 -+ field_list.push_back(field=new Item_empty_string("State",30));
52926 -+ field->maybe_null=1;
52927 -+ field_list.push_back(field=new Item_empty_string("Info",max_query_length));
52928 -+ field->maybe_null=1;
52929 -+ if (protocol->send_fields(&field_list,
52930 -+ Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
52931 -+ DBUG_VOID_RETURN;
52932 -+
52933 -+ VOID(pthread_mutex_lock(&LOCK_thread_count)); // For unlink from list
52934 -+ if (!thd->killed)
52935 -+ {
52936 -+ I_List_iterator<THD> it(threads);
52937 -+ THD *tmp;
52938 -+ while ((tmp=it++))
52939 -+ {
52940 -+ Security_context *tmp_sctx= tmp->security_ctx;
52941 -+ struct st_my_thread_var *mysys_var;
52942 -+ if ((tmp->vio_ok() || tmp->system_thread) &&
52943 -+ (!user || (tmp_sctx->user && !strcmp(tmp_sctx->user, user))))
52944 -+ {
52945 -+ thread_info *thd_info= new thread_info;
52946 -+
52947 -+ thd_info->thread_id=tmp->thread_id;
52948 -+ thd_info->user= thd->strdup(tmp_sctx->user ? tmp_sctx->user :
52949 -+ (tmp->system_thread ?
52950 -+ "system user" : "unauthenticated user"));
52951 -+ if (tmp->peer_port && (tmp_sctx->host || tmp_sctx->ip) &&
52952 -+ thd->security_ctx->host_or_ip[0])
52953 -+ {
52954 -+ if ((thd_info->host= (char*) thd->alloc(LIST_PROCESS_HOST_LEN+1)))
52955 -+ my_snprintf((char *) thd_info->host, LIST_PROCESS_HOST_LEN,
52956 -+ "%s:%u", tmp_sctx->host_or_ip, tmp->peer_port);
52957 -+ }
52958 -+ else
52959 -+ thd_info->host= thd->strdup(tmp_sctx->host_or_ip[0] ?
52960 -+ tmp_sctx->host_or_ip :
52961 -+ tmp_sctx->host ? tmp_sctx->host : "");
52962 -+ if ((thd_info->db=tmp->db)) // Safe test
52963 -+ thd_info->db=thd->strdup(thd_info->db);
52964 -+ thd_info->command=(int) tmp->command;
52965 -+ if ((mysys_var= tmp->mysys_var))
52966 -+ pthread_mutex_lock(&mysys_var->mutex);
52967 -+ thd_info->proc_info= (char*) (tmp->killed == THD::KILL_CONNECTION? "Killed" : 0);
52968 -+#ifndef EMBEDDED_LIBRARY
52969 -+ thd_info->state_info= (char*) (tmp->locked ? "Locked" :
52970 -+ tmp->net.reading_or_writing ?
52971 -+ (tmp->net.reading_or_writing == 2 ?
52972 -+ "Writing to net" :
52973 -+ thd_info->command == COM_SLEEP ? "" :
52974 -+ "Reading from net") :
52975 -+ tmp->proc_info ? tmp->proc_info :
52976 -+ tmp->mysys_var &&
52977 -+ tmp->mysys_var->current_cond ?
52978 -+ "Waiting on cond" : NullS);
52979 -+#else
52980 -+ thd_info->state_info= (char*)"Writing to net";
52981 -+#endif
52982 -+ if (mysys_var)
52983 -+ pthread_mutex_unlock(&mysys_var->mutex);
52984 -+
52985 -+ thd_info->start_time= tmp->start_time;
52986 -+ thd_info->query=0;
52987 -+ /* Lock THD mutex that protects its data when looking at it. */
52988 -+ pthread_mutex_lock(&tmp->LOCK_thd_data);
52989 -+ if (tmp->query())
52990 -+ {
52991 -+ uint length= min(max_query_length, tmp->query_length());
52992 -+ thd_info->query= (char*) thd->strmake(tmp->query(),length);
52993 -+ }
52994 -+ pthread_mutex_unlock(&tmp->LOCK_thd_data);
52995 -+ thread_infos.append(thd_info);
52996 -+ }
52997 -+ }
52998 -+ }
52999 -+ VOID(pthread_mutex_unlock(&LOCK_thread_count));
53000 -+
53001 -+ thread_info *thd_info;
53002 -+ time_t now= my_time(0);
53003 -+ while ((thd_info=thread_infos.get()))
53004 -+ {
53005 -+ protocol->prepare_for_resend();
53006 -+ protocol->store((ulonglong) thd_info->thread_id);
53007 -+ protocol->store(thd_info->user, system_charset_info);
53008 -+ protocol->store(thd_info->host, system_charset_info);
53009 -+ protocol->store(thd_info->db, system_charset_info);
53010 -+ if (thd_info->proc_info)
53011 -+ protocol->store(thd_info->proc_info, system_charset_info);
53012 -+ else
53013 -+ protocol->store(command_name[thd_info->command].str, system_charset_info);
53014 -+ if (thd_info->start_time)
53015 -+ protocol->store_long ((longlong) (now - thd_info->start_time));
53016 -+ else
53017 -+ protocol->store_null();
53018 -+ protocol->store(thd_info->state_info, system_charset_info);
53019 -+ protocol->store(thd_info->query, system_charset_info);
53020 -+ if (protocol->write())
53021 -+ break; /* purecov: inspected */
53022 -+ }
53023 -+ my_eof(thd);
53024 -+ DBUG_VOID_RETURN;
53025 -+}
53026 -+
53027 -+int fill_schema_processlist(THD* thd, TABLE_LIST* tables, COND* cond)
53028 -+{
53029 -+ TABLE *table= tables->table;
53030 -+ CHARSET_INFO *cs= system_charset_info;
53031 -+ char *user;
53032 -+ time_t now= my_time(0);
53033 -+ DBUG_ENTER("fill_process_list");
53034 -+
53035 -+ user= thd->security_ctx->master_access & PROCESS_ACL ?
53036 -+ NullS : thd->security_ctx->priv_user;
53037 -+
53038 -+ VOID(pthread_mutex_lock(&LOCK_thread_count));
53039 -+
53040 -+ if (!thd->killed)
53041 -+ {
53042 -+ I_List_iterator<THD> it(threads);
53043 -+ THD* tmp;
53044 -+
53045 -+ while ((tmp= it++))
53046 -+ {
53047 -+ Security_context *tmp_sctx= tmp->security_ctx;
53048 -+ struct st_my_thread_var *mysys_var;
53049 -+ const char *val;
53050 -+
53051 -+ if ((!tmp->vio_ok() && !tmp->system_thread) ||
53052 -+ (user && (!tmp_sctx->user || strcmp(tmp_sctx->user, user))))
53053 -+ continue;
53054 -+
53055 -+ restore_record(table, s->default_values);
53056 -+ /* ID */
53057 -+ table->field[0]->store((longlong) tmp->thread_id, TRUE);
53058 -+ /* USER */
53059 -+ val= tmp_sctx->user ? tmp_sctx->user :
53060 -+ (tmp->system_thread ? "system user" : "unauthenticated user");
53061 -+ table->field[1]->store(val, strlen(val), cs);
53062 -+ /* HOST */
53063 -+ if (tmp->peer_port && (tmp_sctx->host || tmp_sctx->ip) &&
53064 -+ thd->security_ctx->host_or_ip[0])
53065 -+ {
53066 -+ char host[LIST_PROCESS_HOST_LEN + 1];
53067 -+ my_snprintf(host, LIST_PROCESS_HOST_LEN, "%s:%u",
53068 -+ tmp_sctx->host_or_ip, tmp->peer_port);
53069 -+ table->field[2]->store(host, strlen(host), cs);
53070 -+ }
53071 -+ else
53072 -+ table->field[2]->store(tmp_sctx->host_or_ip,
53073 -+ strlen(tmp_sctx->host_or_ip), cs);
53074 -+ /* DB */
53075 -+ if (tmp->db)
53076 -+ {
53077 -+ table->field[3]->store(tmp->db, strlen(tmp->db), cs);
53078 -+ table->field[3]->set_notnull();
53079 -+ }
53080 -+
53081 -+ if ((mysys_var= tmp->mysys_var))
53082 -+ pthread_mutex_lock(&mysys_var->mutex);
53083 -+ /* COMMAND */
53084 -+ if ((val= (char *) (tmp->killed == THD::KILL_CONNECTION? "Killed" : 0)))
53085 -+ table->field[4]->store(val, strlen(val), cs);
53086 -+ else
53087 -+ table->field[4]->store(command_name[tmp->command].str,
53088 -+ command_name[tmp->command].length, cs);
53089 -+ /* MYSQL_TIME */
53090 -+ table->field[5]->store((longlong)(tmp->start_time ?
53091 -+ now - tmp->start_time : 0), FALSE);
53092 -+ /* STATE */
53093 -+#ifndef EMBEDDED_LIBRARY
53094 -+ val= (char*) (tmp->locked ? "Locked" :
53095 -+ tmp->net.reading_or_writing ?
53096 -+ (tmp->net.reading_or_writing == 2 ?
53097 -+ "Writing to net" :
53098 -+ tmp->command == COM_SLEEP ? "" :
53099 -+ "Reading from net") :
53100 -+ tmp->proc_info ? tmp->proc_info :
53101 -+ tmp->mysys_var &&
53102 -+ tmp->mysys_var->current_cond ?
53103 -+ "Waiting on cond" : NullS);
53104 -+#else
53105 -+ val= (char *) (tmp->proc_info ? tmp->proc_info : NullS);
53106 -+#endif
53107 -+ if (val)
53108 -+ {
53109 -+ table->field[6]->store(val, strlen(val), cs);
53110 -+ table->field[6]->set_notnull();
53111 -+ }
53112 -+
53113 -+ if (mysys_var)
53114 -+ pthread_mutex_unlock(&mysys_var->mutex);
53115 -+
53116 -+ /* INFO */
53117 -+ /* Lock THD mutex that protects its data when looking at it. */
53118 -+ pthread_mutex_lock(&tmp->LOCK_thd_data);
53119 -+ if (tmp->query())
53120 -+ {
53121 -+ table->field[7]->store(tmp->query(),
53122 -+ min(PROCESS_LIST_INFO_WIDTH,
53123 -+ tmp->query_length()), cs);
53124 -+ table->field[7]->set_notnull();
53125 -+ }
53126 -+ pthread_mutex_unlock(&tmp->LOCK_thd_data);
53127 -+
53128 -+ if (schema_table_store_record(thd, table))
53129 -+ {
53130 -+ VOID(pthread_mutex_unlock(&LOCK_thread_count));
53131 -+ DBUG_RETURN(1);
53132 -+ }
53133 -+ }
53134 -+ }
53135 -+
53136 -+ VOID(pthread_mutex_unlock(&LOCK_thread_count));
53137 -+ DBUG_RETURN(0);
53138 -+}
53139 -+
53140 -+/*****************************************************************************
53141 -+ Status functions
53142 -+*****************************************************************************/
53143 -+
53144 -+static DYNAMIC_ARRAY all_status_vars;
53145 -+static bool status_vars_inited= 0;
53146 -+static int show_var_cmp(const void *var1, const void *var2)
53147 -+{
53148 -+ return strcmp(((SHOW_VAR*)var1)->name, ((SHOW_VAR*)var2)->name);
53149 -+}
53150 -+
53151 -+/*
53152 -+ deletes all the SHOW_UNDEF elements from the array and calls
53153 -+ delete_dynamic() if it's completely empty.
53154 -+*/
53155 -+static void shrink_var_array(DYNAMIC_ARRAY *array)
53156 -+{
53157 -+ uint a,b;
53158 -+ SHOW_VAR *all= dynamic_element(array, 0, SHOW_VAR *);
53159 -+
53160 -+ for (a= b= 0; b < array->elements; b++)
53161 -+ if (all[b].type != SHOW_UNDEF)
53162 -+ all[a++]= all[b];
53163 -+ if (a)
53164 -+ {
53165 -+ bzero(all+a, sizeof(SHOW_VAR)); // writing NULL-element to the end
53166 -+ array->elements= a;
53167 -+ }
53168 -+ else // array is completely empty - delete it
53169 -+ delete_dynamic(array);
53170 -+}
53171 -+
53172 -+/*
53173 -+ Adds an array of SHOW_VAR entries to the output of SHOW STATUS
53174 -+
53175 -+ SYNOPSIS
53176 -+ add_status_vars(SHOW_VAR *list)
53177 -+ list - an array of SHOW_VAR entries to add to all_status_vars
53178 -+ the last entry must be {0,0,SHOW_UNDEF}
53179 -+
53180 -+ NOTE
53181 -+ The handling of all_status_vars[] is completely internal, it's allocated
53182 -+ automatically when something is added to it, and deleted completely when
53183 -+ the last entry is removed.
53184 -+
53185 -+ As a special optimization, if add_status_vars() is called before
53186 -+ init_status_vars(), it assumes "startup mode" - neither concurrent access
53187 -+ to the array nor SHOW STATUS are possible (thus it skips locks and qsort)
53188 -+
53189 -+ The last entry of the all_status_vars[] should always be {0,0,SHOW_UNDEF}
53190 -+*/
53191 -+int add_status_vars(SHOW_VAR *list)
53192 -+{
53193 -+ int res= 0;
53194 -+ if (status_vars_inited)
53195 -+ pthread_mutex_lock(&LOCK_status);
53196 -+ if (!all_status_vars.buffer && // array is not allocated yet - do it now
53197 -+ my_init_dynamic_array(&all_status_vars, sizeof(SHOW_VAR), 200, 20))
53198 -+ {
53199 -+ res= 1;
53200 -+ goto err;
53201 -+ }
53202 -+ while (list->name)
53203 -+ res|= insert_dynamic(&all_status_vars, (uchar*)list++);
53204 -+ res|= insert_dynamic(&all_status_vars, (uchar*)list); // appending NULL-element
53205 -+ all_status_vars.elements--; // but next insert_dynamic should overwite it
53206 -+ if (status_vars_inited)
53207 -+ sort_dynamic(&all_status_vars, show_var_cmp);
53208 -+err:
53209 -+ if (status_vars_inited)
53210 -+ pthread_mutex_unlock(&LOCK_status);
53211 -+ return res;
53212 -+}
53213 -+
53214 -+/*
53215 -+ Make all_status_vars[] usable for SHOW STATUS
53216 -+
53217 -+ NOTE
53218 -+ See add_status_vars(). Before init_status_vars() call, add_status_vars()
53219 -+ works in a special fast "startup" mode. Thus init_status_vars()
53220 -+ should be called as late as possible but before enabling multi-threading.
53221 -+*/
53222 -+void init_status_vars()
53223 -+{
53224 -+ status_vars_inited=1;
53225 -+ sort_dynamic(&all_status_vars, show_var_cmp);
53226 -+}
53227 -+
53228 -+void reset_status_vars()
53229 -+{
53230 -+ SHOW_VAR *ptr= (SHOW_VAR*) all_status_vars.buffer;
53231 -+ SHOW_VAR *last= ptr + all_status_vars.elements;
53232 -+ for (; ptr < last; ptr++)
53233 -+ {
53234 -+ /* Note that SHOW_LONG_NOFLUSH variables are not reset */
53235 -+ if (ptr->type == SHOW_LONG)
53236 -+ *(ulong*) ptr->value= 0;
53237 -+ }
53238 -+}
53239 -+
53240 -+/*
53241 -+ catch-all cleanup function, cleans up everything no matter what
53242 -+
53243 -+ DESCRIPTION
53244 -+ This function is not strictly required if all add_to_status/
53245 -+ remove_status_vars are properly paired, but it's a safety measure that
53246 -+ deletes everything from the all_status_vars[] even if some
53247 -+ remove_status_vars were forgotten
53248 -+*/
53249 -+void free_status_vars()
53250 -+{
53251 -+ delete_dynamic(&all_status_vars);
53252 -+}
53253 -+
53254 -+/*
53255 -+ Removes an array of SHOW_VAR entries from the output of SHOW STATUS
53256 -+
53257 -+ SYNOPSIS
53258 -+ remove_status_vars(SHOW_VAR *list)
53259 -+ list - an array of SHOW_VAR entries to remove to all_status_vars
53260 -+ the last entry must be {0,0,SHOW_UNDEF}
53261 -+
53262 -+ NOTE
53263 -+ there's lots of room for optimizing this, especially in non-sorted mode,
53264 -+ but nobody cares - it may be called only in case of failed plugin
53265 -+ initialization in the mysqld startup.
53266 -+*/
53267 -+
53268 -+void remove_status_vars(SHOW_VAR *list)
53269 -+{
53270 -+ if (status_vars_inited)
53271 -+ {
53272 -+ pthread_mutex_lock(&LOCK_status);
53273 -+ SHOW_VAR *all= dynamic_element(&all_status_vars, 0, SHOW_VAR *);
53274 -+ int a= 0, b= all_status_vars.elements, c= (a+b)/2;
53275 -+
53276 -+ for (; list->name; list++)
53277 -+ {
53278 -+ int res= 0;
53279 -+ for (a= 0, b= all_status_vars.elements; b-a > 1; c= (a+b)/2)
53280 -+ {
53281 -+ res= show_var_cmp(list, all+c);
53282 -+ if (res < 0)
53283 -+ b= c;
53284 -+ else if (res > 0)
53285 -+ a= c;
53286 -+ else
53287 -+ break;
53288 -+ }
53289 -+ if (res == 0)
53290 -+ all[c].type= SHOW_UNDEF;
53291 -+ }
53292 -+ shrink_var_array(&all_status_vars);
53293 -+ pthread_mutex_unlock(&LOCK_status);
53294 -+ }
53295 -+ else
53296 -+ {
53297 -+ SHOW_VAR *all= dynamic_element(&all_status_vars, 0, SHOW_VAR *);
53298 -+ uint i;
53299 -+ for (; list->name; list++)
53300 -+ {
53301 -+ for (i= 0; i < all_status_vars.elements; i++)
53302 -+ {
53303 -+ if (show_var_cmp(list, all+i))
53304 -+ continue;
53305 -+ all[i].type= SHOW_UNDEF;
53306 -+ break;
53307 -+ }
53308 -+ }
53309 -+ shrink_var_array(&all_status_vars);
53310 -+ }
53311 -+}
53312 -+
53313 -+inline void make_upper(char *buf)
53314 -+{
53315 -+ for (; *buf; buf++)
53316 -+ *buf= my_toupper(system_charset_info, *buf);
53317 -+}
53318 -+
53319 -+static bool show_status_array(THD *thd, const char *wild,
53320 -+ SHOW_VAR *variables,
53321 -+ enum enum_var_type value_type,
53322 -+ struct system_status_var *status_var,
53323 -+ const char *prefix, TABLE *table,
53324 -+ bool ucase_names,
53325 -+ COND *cond)
53326 -+{
53327 -+ my_aligned_storage<SHOW_VAR_FUNC_BUFF_SIZE, MY_ALIGNOF(long)> buffer;
53328 -+ char * const buff= buffer.data;
53329 -+ char *prefix_end;
53330 -+ /* the variable name should not be longer than 64 characters */
53331 -+ char name_buffer[64];
53332 -+ int len;
53333 -+ LEX_STRING null_lex_str;
53334 -+ SHOW_VAR tmp, *var;
53335 -+ COND *partial_cond= 0;
53336 -+ enum_check_fields save_count_cuted_fields= thd->count_cuted_fields;
53337 -+ bool res= FALSE;
53338 -+ CHARSET_INFO *charset= system_charset_info;
53339 -+ DBUG_ENTER("show_status_array");
53340 -+
53341 -+ thd->count_cuted_fields= CHECK_FIELD_WARN;
53342 -+ null_lex_str.str= 0; // For sys_var->value_ptr()
53343 -+ null_lex_str.length= 0;
53344 -+
53345 -+ prefix_end=strnmov(name_buffer, prefix, sizeof(name_buffer)-1);
53346 -+ if (*prefix)
53347 -+ *prefix_end++= '_';
53348 -+ len=name_buffer + sizeof(name_buffer) - prefix_end;
53349 -+ partial_cond= make_cond_for_info_schema(cond, table->pos_in_table_list);
53350 -+
53351 -+ for (; variables->name; variables++)
53352 -+ {
53353 -+ strnmov(prefix_end, variables->name, len);
53354 -+ name_buffer[sizeof(name_buffer)-1]=0; /* Safety */
53355 -+ if (ucase_names)
53356 -+ make_upper(name_buffer);
53357 -+
53358 -+ restore_record(table, s->default_values);
53359 -+ table->field[0]->store(name_buffer, strlen(name_buffer),
53360 -+ system_charset_info);
53361 -+ /*
53362 -+ if var->type is SHOW_FUNC, call the function.
53363 -+ Repeat as necessary, if new var is again SHOW_FUNC
53364 -+ */
53365 -+ for (var=variables; var->type == SHOW_FUNC; var= &tmp)
53366 -+ ((mysql_show_var_func)(var->value))(thd, &tmp, buff);
53367 -+
53368 -+ SHOW_TYPE show_type=var->type;
53369 -+ if (show_type == SHOW_ARRAY)
53370 -+ {
53371 -+ show_status_array(thd, wild, (SHOW_VAR *) var->value, value_type,
53372 -+ status_var, name_buffer, table, ucase_names, partial_cond);
53373 -+ }
53374 -+ else
53375 -+ {
53376 -+ if (!(wild && wild[0] && wild_case_compare(system_charset_info,
53377 -+ name_buffer, wild)) &&
53378 -+ (!partial_cond || partial_cond->val_int()))
53379 -+ {
53380 -+ char *value=var->value;
53381 -+ const char *pos, *end; // We assign a lot of const's
53382 -+
53383 -+ pthread_mutex_lock(&LOCK_global_system_variables);
53384 -+
53385 -+ if (show_type == SHOW_SYS)
53386 -+ {
53387 -+ sys_var *var= ((sys_var *) value);
53388 -+ show_type= var->show_type();
53389 -+ value= (char*) var->value_ptr(thd, value_type, &null_lex_str);
53390 -+ charset= var->charset(thd);
53391 -+ }
53392 -+
53393 -+ pos= end= buff;
53394 -+ /*
53395 -+ note that value may be == buff. All SHOW_xxx code below
53396 -+ should still work in this case
53397 -+ */
53398 -+ switch (show_type) {
53399 -+ case SHOW_DOUBLE_STATUS:
53400 -+ value= ((char *) status_var + (ulong) value);
53401 -+ /* fall through */
53402 -+ case SHOW_DOUBLE:
53403 -+ end= buff + sprintf(buff, "%f", *(double*) value);
53404 -+ break;
53405 -+ case SHOW_LONG_STATUS:
53406 -+ value= ((char *) status_var + (ulong) value);
53407 -+ /* fall through */
53408 -+ case SHOW_LONG:
53409 -+ case SHOW_LONG_NOFLUSH: // the difference lies in refresh_status()
53410 -+ end= int10_to_str(*(long*) value, buff, 10);
53411 -+ break;
53412 -+ case SHOW_LONGLONG_STATUS:
53413 -+ value= ((char *) status_var + (ulonglong) value);
53414 -+ /* fall through */
53415 -+ case SHOW_LONGLONG:
53416 -+ end= longlong10_to_str(*(longlong*) value, buff, 10);
53417 -+ break;
53418 -+ case SHOW_HA_ROWS:
53419 -+ end= longlong10_to_str((longlong) *(ha_rows*) value, buff, 10);
53420 -+ break;
53421 -+ case SHOW_BOOL:
53422 -+ end= strmov(buff, *(bool*) value ? "ON" : "OFF");
53423 -+ break;
53424 -+ case SHOW_MY_BOOL:
53425 -+ end= strmov(buff, *(my_bool*) value ? "ON" : "OFF");
53426 -+ break;
53427 -+ case SHOW_INT:
53428 -+ end= int10_to_str((long) *(uint32*) value, buff, 10);
53429 -+ break;
53430 -+ case SHOW_HAVE:
53431 -+ {
53432 -+ SHOW_COMP_OPTION tmp= *(SHOW_COMP_OPTION*) value;
53433 -+ pos= show_comp_option_name[(int) tmp];
53434 -+ end= strend(pos);
53435 -+ break;
53436 -+ }
53437 -+ case SHOW_CHAR:
53438 -+ {
53439 -+ if (!(pos= value))
53440 -+ pos= "";
53441 -+ end= strend(pos);
53442 -+ break;
53443 -+ }
53444 -+ case SHOW_CHAR_PTR:
53445 -+ {
53446 -+ if (!(pos= *(char**) value))
53447 -+ pos= "";
53448 -+ end= strend(pos);
53449 -+ break;
53450 -+ }
53451 -+ case SHOW_KEY_CACHE_LONG:
53452 -+ value= (char*) dflt_key_cache + (ulong)value;
53453 -+ end= int10_to_str(*(long*) value, buff, 10);
53454 -+ break;
53455 -+ case SHOW_KEY_CACHE_LONGLONG:
53456 -+ value= (char*) dflt_key_cache + (ulong)value;
53457 -+ end= longlong10_to_str(*(longlong*) value, buff, 10);
53458 -+ break;
53459 -+ case SHOW_UNDEF:
53460 -+ break; // Return empty string
53461 -+ case SHOW_SYS: // Cannot happen
53462 -+ default:
53463 -+ DBUG_ASSERT(0);
53464 -+ break;
53465 -+ }
53466 -+ table->field[1]->store(pos, (uint32) (end - pos), charset);
53467 -+ thd->count_cuted_fields= CHECK_FIELD_IGNORE;
53468 -+ table->field[1]->set_notnull();
53469 -+
53470 -+ pthread_mutex_unlock(&LOCK_global_system_variables);
53471 -+
53472 -+ if (schema_table_store_record(thd, table))
53473 -+ {
53474 -+ res= TRUE;
53475 -+ goto end;
53476 -+ }
53477 -+ }
53478 -+ }
53479 -+ }
53480 -+end:
53481 -+ thd->count_cuted_fields= save_count_cuted_fields;
53482 -+ DBUG_RETURN(res);
53483 -+}
53484 -+
53485 -+
53486 -+/* collect status for all running threads */
53487 -+
53488 -+void calc_sum_of_all_status(STATUS_VAR *to)
53489 -+{
53490 -+ DBUG_ENTER("calc_sum_of_all_status");
53491 -+
53492 -+ /* Ensure that thread id not killed during loop */
53493 -+ VOID(pthread_mutex_lock(&LOCK_thread_count)); // For unlink from list
53494 -+
53495 -+ I_List_iterator<THD> it(threads);
53496 -+ THD *tmp;
53497 -+
53498 -+ /* Get global values as base */
53499 -+ *to= global_status_var;
53500 -+
53501 -+ /* Add to this status from existing threads */
53502 -+ while ((tmp= it++))
53503 -+ add_to_status(to, &tmp->status_var);
53504 -+
53505 -+ VOID(pthread_mutex_unlock(&LOCK_thread_count));
53506 -+ DBUG_VOID_RETURN;
53507 -+}
53508 -+
53509 -+
53510 -+/* This is only used internally, but we need it here as a forward reference */
53511 -+extern ST_SCHEMA_TABLE schema_tables[];
53512 -+
53513 -+typedef struct st_lookup_field_values
53514 -+{
53515 -+ LEX_STRING db_value, table_value;
53516 -+ bool wild_db_value, wild_table_value;
53517 -+} LOOKUP_FIELD_VALUES;
53518 -+
53519 -+
53520 -+/*
53521 -+ Store record to I_S table, convert HEAP table
53522 -+ to MyISAM if necessary
53523 -+
53524 -+ SYNOPSIS
53525 -+ schema_table_store_record()
53526 -+ thd thread handler
53527 -+ table Information schema table to be updated
53528 -+
53529 -+ RETURN
53530 -+ 0 success
53531 -+ 1 error
53532 -+*/
53533 -+
53534 -+bool schema_table_store_record(THD *thd, TABLE *table)
53535 -+{
53536 -+ int error;
53537 -+ if ((error= table->file->ha_write_row(table->record[0])))
53538 -+ {
53539 -+ if (create_myisam_from_heap(thd, table,
53540 -+ table->pos_in_table_list->schema_table_param,
53541 -+ error, 0))
53542 -+ return 1;
53543 -+ }
53544 -+ return 0;
53545 -+}
53546 -+
53547 -+
53548 -+int make_table_list(THD *thd, SELECT_LEX *sel,
53549 -+ LEX_STRING *db_name, LEX_STRING *table_name)
53550 -+{
53551 -+ Table_ident *table_ident;
53552 -+ table_ident= new Table_ident(thd, *db_name, *table_name, 1);
53553 -+ sel->init_query();
53554 -+ if (!sel->add_table_to_list(thd, table_ident, 0, 0, TL_READ))
53555 -+ return 1;
53556 -+ return 0;
53557 -+}
53558 -+
53559 -+
53560 -+/**
53561 -+ @brief Get lookup value from the part of 'WHERE' condition
53562 -+
53563 -+ @details This function gets lookup value from
53564 -+ the part of 'WHERE' condition if it's possible and
53565 -+ fill appropriate lookup_field_vals struct field
53566 -+ with this value.
53567 -+
53568 -+ @param[in] thd thread handler
53569 -+ @param[in] item_func part of WHERE condition
53570 -+ @param[in] table I_S table
53571 -+ @param[in, out] lookup_field_vals Struct which holds lookup values
53572 -+
53573 -+ @return
53574 -+ 0 success
53575 -+ 1 error, there can be no matching records for the condition
53576 -+*/
53577 -+
53578 -+bool get_lookup_value(THD *thd, Item_func *item_func,
53579 -+ TABLE_LIST *table,
53580 -+ LOOKUP_FIELD_VALUES *lookup_field_vals)
53581 -+{
53582 -+ ST_SCHEMA_TABLE *schema_table= table->schema_table;
53583 -+ ST_FIELD_INFO *field_info= schema_table->fields_info;
53584 -+ const char *field_name1= schema_table->idx_field1 >= 0 ?
53585 -+ field_info[schema_table->idx_field1].field_name : "";
53586 -+ const char *field_name2= schema_table->idx_field2 >= 0 ?
53587 -+ field_info[schema_table->idx_field2].field_name : "";
53588 -+
53589 -+ if (item_func->functype() == Item_func::EQ_FUNC ||
53590 -+ item_func->functype() == Item_func::EQUAL_FUNC)
53591 -+ {
53592 -+ int idx_field, idx_val;
53593 -+ char tmp[MAX_FIELD_WIDTH];
53594 -+ String *tmp_str, str_buff(tmp, sizeof(tmp), system_charset_info);
53595 -+ Item_field *item_field;
53596 -+ CHARSET_INFO *cs= system_charset_info;
53597 -+
53598 -+ if (item_func->arguments()[0]->type() == Item::FIELD_ITEM &&
53599 -+ item_func->arguments()[1]->const_item())
53600 -+ {
53601 -+ idx_field= 0;
53602 -+ idx_val= 1;
53603 -+ }
53604 -+ else if (item_func->arguments()[1]->type() == Item::FIELD_ITEM &&
53605 -+ item_func->arguments()[0]->const_item())
53606 -+ {
53607 -+ idx_field= 1;
53608 -+ idx_val= 0;
53609 -+ }
53610 -+ else
53611 -+ return 0;
53612 -+
53613 -+ item_field= (Item_field*) item_func->arguments()[idx_field];
53614 -+ if (table->table != item_field->field->table)
53615 -+ return 0;
53616 -+ tmp_str= item_func->arguments()[idx_val]->val_str(&str_buff);
53617 -+
53618 -+ /* impossible value */
53619 -+ if (!tmp_str)
53620 -+ return 1;
53621 -+
53622 -+ /* Lookup value is database name */
53623 -+ if (!cs->coll->strnncollsp(cs, (uchar *) field_name1, strlen(field_name1),
53624 -+ (uchar *) item_field->field_name,
53625 -+ strlen(item_field->field_name), 0))
53626 -+ {
53627 -+ thd->make_lex_string(&lookup_field_vals->db_value, tmp_str->ptr(),
53628 -+ tmp_str->length(), FALSE);
53629 -+ }
53630 -+ /* Lookup value is table name */
53631 -+ else if (!cs->coll->strnncollsp(cs, (uchar *) field_name2,
53632 -+ strlen(field_name2),
53633 -+ (uchar *) item_field->field_name,
53634 -+ strlen(item_field->field_name), 0))
53635 -+ {
53636 -+ thd->make_lex_string(&lookup_field_vals->table_value, tmp_str->ptr(),
53637 -+ tmp_str->length(), FALSE);
53638 -+ }
53639 -+ }
53640 -+ return 0;
53641 -+}
53642 -+
53643 -+
53644 -+/**
53645 -+ @brief Calculates lookup values from 'WHERE' condition
53646 -+
53647 -+ @details This function calculates lookup value(database name, table name)
53648 -+ from 'WHERE' condition if it's possible and
53649 -+ fill lookup_field_vals struct fields with these values.
53650 -+
53651 -+ @param[in] thd thread handler
53652 -+ @param[in] cond WHERE condition
53653 -+ @param[in] table I_S table
53654 -+ @param[in, out] lookup_field_vals Struct which holds lookup values
53655 -+
53656 -+ @return
53657 -+ 0 success
53658 -+ 1 error, there can be no matching records for the condition
53659 -+*/
53660 -+
53661 -+bool calc_lookup_values_from_cond(THD *thd, COND *cond, TABLE_LIST *table,
53662 -+ LOOKUP_FIELD_VALUES *lookup_field_vals)
53663 -+{
53664 -+ if (!cond)
53665 -+ return 0;
53666 -+
53667 -+ if (cond->type() == Item::COND_ITEM)
53668 -+ {
53669 -+ if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
53670 -+ {
53671 -+ List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
53672 -+ Item *item;
53673 -+ while ((item= li++))
53674 -+ {
53675 -+ if (item->type() == Item::FUNC_ITEM)
53676 -+ {
53677 -+ if (get_lookup_value(thd, (Item_func*)item, table, lookup_field_vals))
53678 -+ return 1;
53679 -+ }
53680 -+ else
53681 -+ {
53682 -+ if (calc_lookup_values_from_cond(thd, item, table, lookup_field_vals))
53683 -+ return 1;
53684 -+ }
53685 -+ }
53686 -+ }
53687 -+ return 0;
53688 -+ }
53689 -+ else if (cond->type() == Item::FUNC_ITEM &&
53690 -+ get_lookup_value(thd, (Item_func*) cond, table, lookup_field_vals))
53691 -+ return 1;
53692 -+ return 0;
53693 -+}
53694 -+
53695 -+
53696 -+bool uses_only_table_name_fields(Item *item, TABLE_LIST *table)
53697 -+{
53698 -+ if (item->type() == Item::FUNC_ITEM)
53699 -+ {
53700 -+ Item_func *item_func= (Item_func*)item;
53701 -+ for (uint i=0; i<item_func->argument_count(); i++)
53702 -+ {
53703 -+ if (!uses_only_table_name_fields(item_func->arguments()[i], table))
53704 -+ return 0;
53705 -+ }
53706 -+ }
53707 -+ else if (item->type() == Item::FIELD_ITEM)
53708 -+ {
53709 -+ Item_field *item_field= (Item_field*)item;
53710 -+ CHARSET_INFO *cs= system_charset_info;
53711 -+ ST_SCHEMA_TABLE *schema_table= table->schema_table;
53712 -+ ST_FIELD_INFO *field_info= schema_table->fields_info;
53713 -+ const char *field_name1= schema_table->idx_field1 >= 0 ?
53714 -+ field_info[schema_table->idx_field1].field_name : "";
53715 -+ const char *field_name2= schema_table->idx_field2 >= 0 ?
53716 -+ field_info[schema_table->idx_field2].field_name : "";
53717 -+ if (table->table != item_field->field->table ||
53718 -+ (cs->coll->strnncollsp(cs, (uchar *) field_name1, strlen(field_name1),
53719 -+ (uchar *) item_field->field_name,
53720 -+ strlen(item_field->field_name), 0) &&
53721 -+ cs->coll->strnncollsp(cs, (uchar *) field_name2, strlen(field_name2),
53722 -+ (uchar *) item_field->field_name,
53723 -+ strlen(item_field->field_name), 0)))
53724 -+ return 0;
53725 -+ }
53726 -+ else if (item->type() == Item::REF_ITEM)
53727 -+ return uses_only_table_name_fields(item->real_item(), table);
53728 -+
53729 -+ if (item->type() == Item::SUBSELECT_ITEM && !item->const_item())
53730 -+ return 0;
53731 -+
53732 -+ return 1;
53733 -+}
53734 -+
53735 -+
53736 -+static COND * make_cond_for_info_schema(COND *cond, TABLE_LIST *table)
53737 -+{
53738 -+ if (!cond)
53739 -+ return (COND*) 0;
53740 -+ if (cond->type() == Item::COND_ITEM)
53741 -+ {
53742 -+ if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
53743 -+ {
53744 -+ /* Create new top level AND item */
53745 -+ Item_cond_and *new_cond=new Item_cond_and;
53746 -+ if (!new_cond)
53747 -+ return (COND*) 0;
53748 -+ List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
53749 -+ Item *item;
53750 -+ while ((item=li++))
53751 -+ {
53752 -+ Item *fix= make_cond_for_info_schema(item, table);
53753 -+ if (fix)
53754 -+ new_cond->argument_list()->push_back(fix);
53755 -+ }
53756 -+ switch (new_cond->argument_list()->elements) {
53757 -+ case 0:
53758 -+ return (COND*) 0;
53759 -+ case 1:
53760 -+ return new_cond->argument_list()->head();
53761 -+ default:
53762 -+ new_cond->quick_fix_field();
53763 -+ return new_cond;
53764 -+ }
53765 -+ }
53766 -+ else
53767 -+ { // Or list
53768 -+ Item_cond_or *new_cond=new Item_cond_or;
53769 -+ if (!new_cond)
53770 -+ return (COND*) 0;
53771 -+ List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
53772 -+ Item *item;
53773 -+ while ((item=li++))
53774 -+ {
53775 -+ Item *fix=make_cond_for_info_schema(item, table);
53776 -+ if (!fix)
53777 -+ return (COND*) 0;
53778 -+ new_cond->argument_list()->push_back(fix);
53779 -+ }
53780 -+ new_cond->quick_fix_field();
53781 -+ new_cond->top_level_item();
53782 -+ return new_cond;
53783 -+ }
53784 -+ }
53785 -+
53786 -+ if (!uses_only_table_name_fields(cond, table))
53787 -+ return (COND*) 0;
53788 -+ return cond;
53789 -+}
53790 -+
53791 -+
53792 -+/**
53793 -+ @brief Calculate lookup values(database name, table name)
53794 -+
53795 -+ @details This function calculates lookup values(database name, table name)
53796 -+ from 'WHERE' condition or wild values (for 'SHOW' commands only)
53797 -+ from LEX struct and fill lookup_field_vals struct field
53798 -+ with these values.
53799 -+
53800 -+ @param[in] thd thread handler
53801 -+ @param[in] cond WHERE condition
53802 -+ @param[in] tables I_S table
53803 -+ @param[in, out] lookup_field_values Struct which holds lookup values
53804 -+
53805 -+ @return
53806 -+ 0 success
53807 -+ 1 error, there can be no matching records for the condition
53808 -+*/
53809 -+
53810 -+bool get_lookup_field_values(THD *thd, COND *cond, TABLE_LIST *tables,
53811 -+ LOOKUP_FIELD_VALUES *lookup_field_values)
53812 -+{
53813 -+ LEX *lex= thd->lex;
53814 -+ const char *wild= lex->wild ? lex->wild->ptr() : NullS;
53815 -+ bool rc= 0;
53816 -+
53817 -+ bzero((char*) lookup_field_values, sizeof(LOOKUP_FIELD_VALUES));
53818 -+ switch (lex->sql_command) {
53819 -+ case SQLCOM_SHOW_DATABASES:
53820 -+ if (wild)
53821 -+ {
53822 -+ thd->make_lex_string(&lookup_field_values->db_value,
53823 -+ wild, strlen(wild), 0);
53824 -+ lookup_field_values->wild_db_value= 1;
53825 -+ }
53826 -+ break;
53827 -+ case SQLCOM_SHOW_TABLES:
53828 -+ case SQLCOM_SHOW_TABLE_STATUS:
53829 -+ case SQLCOM_SHOW_TRIGGERS:
53830 -+ case SQLCOM_SHOW_EVENTS:
53831 -+ thd->make_lex_string(&lookup_field_values->db_value,
53832 -+ lex->select_lex.db, strlen(lex->select_lex.db), 0);
53833 -+ if (wild)
53834 -+ {
53835 -+ thd->make_lex_string(&lookup_field_values->table_value,
53836 -+ wild, strlen(wild), 0);
53837 -+ lookup_field_values->wild_table_value= 1;
53838 -+ }
53839 -+ break;
53840 -+ default:
53841 -+ /*
53842 -+ The "default" is for queries over I_S.
53843 -+ All previous cases handle SHOW commands.
53844 -+ */
53845 -+ rc= calc_lookup_values_from_cond(thd, cond, tables, lookup_field_values);
53846 -+ break;
53847 -+ }
53848 -+
53849 -+ if (lower_case_table_names && !rc)
53850 -+ {
53851 -+ /*
53852 -+ We can safely do in-place upgrades here since all of the above cases
53853 -+ are allocating a new memory buffer for these strings.
53854 -+ */
53855 -+ if (lookup_field_values->db_value.str && lookup_field_values->db_value.str[0])
53856 -+ my_casedn_str(system_charset_info, lookup_field_values->db_value.str);
53857 -+ if (lookup_field_values->table_value.str &&
53858 -+ lookup_field_values->table_value.str[0])
53859 -+ my_casedn_str(system_charset_info, lookup_field_values->table_value.str);
53860 -+ }
53861 -+
53862 -+ return rc;
53863 -+}
53864 -+
53865 -+
53866 -+enum enum_schema_tables get_schema_table_idx(ST_SCHEMA_TABLE *schema_table)
53867 -+{
53868 -+ return (enum enum_schema_tables) (schema_table - &schema_tables[0]);
53869 -+}
53870 -+
53871 -+
53872 -+/*
53873 -+ Create db names list. Information schema name always is first in list
53874 -+
53875 -+ SYNOPSIS
53876 -+ make_db_list()
53877 -+ thd thread handler
53878 -+ files list of db names
53879 -+ wild wild string
53880 -+ idx_field_vals idx_field_vals->db_name contains db name or
53881 -+ wild string
53882 -+ with_i_schema returns 1 if we added 'IS' name to list
53883 -+ otherwise returns 0
53884 -+
53885 -+ RETURN
53886 -+ zero success
53887 -+ non-zero error
53888 -+*/
53889 -+
53890 -+int make_db_list(THD *thd, List<LEX_STRING> *files,
53891 -+ LOOKUP_FIELD_VALUES *lookup_field_vals,
53892 -+ bool *with_i_schema)
53893 -+{
53894 -+ LEX_STRING *i_s_name_copy= 0;
53895 -+ i_s_name_copy= thd->make_lex_string(i_s_name_copy,
53896 -+ INFORMATION_SCHEMA_NAME.str,
53897 -+ INFORMATION_SCHEMA_NAME.length, TRUE);
53898 -+ *with_i_schema= 0;
53899 -+ if (lookup_field_vals->wild_db_value)
53900 -+ {
53901 -+ /*
53902 -+ This part of code is only for SHOW DATABASES command.
53903 -+ idx_field_vals->db_value can be 0 when we don't use
53904 -+ LIKE clause (see also get_index_field_values() function)
53905 -+ */
53906 -+ if (!lookup_field_vals->db_value.str ||
53907 -+ !wild_case_compare(system_charset_info,
53908 -+ INFORMATION_SCHEMA_NAME.str,
53909 -+ lookup_field_vals->db_value.str))
53910 -+ {
53911 -+ *with_i_schema= 1;
53912 -+ if (files->push_back(i_s_name_copy))
53913 -+ return 1;
53914 -+ }
53915 -+ return (find_files(thd, files, NullS, mysql_data_home,
53916 -+ lookup_field_vals->db_value.str, 1) != FIND_FILES_OK);
53917 -+ }
53918 -+
53919 -+
53920 -+ /*
53921 -+ If we have db lookup vaule we just add it to list and
53922 -+ exit from the function
53923 -+ */
53924 -+ if (lookup_field_vals->db_value.str)
53925 -+ {
53926 -+ if (is_schema_db(lookup_field_vals->db_value.str,
53927 -+ lookup_field_vals->db_value.length))
53928 -+ {
53929 -+ *with_i_schema= 1;
53930 -+ if (files->push_back(i_s_name_copy))
53931 -+ return 1;
53932 -+ return 0;
53933 -+ }
53934 -+ if (files->push_back(&lookup_field_vals->db_value))
53935 -+ return 1;
53936 -+ return 0;
53937 -+ }
53938 -+
53939 -+ /*
53940 -+ Create list of existing databases. It is used in case
53941 -+ of select from information schema table
53942 -+ */
53943 -+ if (files->push_back(i_s_name_copy))
53944 -+ return 1;
53945 -+ *with_i_schema= 1;
53946 -+ return (find_files(thd, files, NullS,
53947 -+ mysql_data_home, NullS, 1) != FIND_FILES_OK);
53948 -+}
53949 -+
53950 -+
53951 -+struct st_add_schema_table
53952 -+{
53953 -+ List<LEX_STRING> *files;
53954 -+ const char *wild;
53955 -+};
53956 -+
53957 -+
53958 -+static my_bool add_schema_table(THD *thd, plugin_ref plugin,
53959 -+ void* p_data)
53960 -+{
53961 -+ LEX_STRING *file_name= 0;
53962 -+ st_add_schema_table *data= (st_add_schema_table *)p_data;
53963 -+ List<LEX_STRING> *file_list= data->files;
53964 -+ const char *wild= data->wild;
53965 -+ ST_SCHEMA_TABLE *schema_table= plugin_data(plugin, ST_SCHEMA_TABLE *);
53966 -+ DBUG_ENTER("add_schema_table");
53967 -+
53968 -+ if (schema_table->hidden)
53969 -+ DBUG_RETURN(0);
53970 -+ if (wild)
53971 -+ {
53972 -+ if (lower_case_table_names)
53973 -+ {
53974 -+ if (wild_case_compare(files_charset_info,
53975 -+ schema_table->table_name,
53976 -+ wild))
53977 -+ DBUG_RETURN(0);
53978 -+ }
53979 -+ else if (wild_compare(schema_table->table_name, wild, 0))
53980 -+ DBUG_RETURN(0);
53981 -+ }
53982 -+
53983 -+ if ((file_name= thd->make_lex_string(file_name, schema_table->table_name,
53984 -+ strlen(schema_table->table_name),
53985 -+ TRUE)) &&
53986 -+ !file_list->push_back(file_name))
53987 -+ DBUG_RETURN(0);
53988 -+ DBUG_RETURN(1);
53989 -+}
53990 -+
53991 -+
53992 -+int schema_tables_add(THD *thd, List<LEX_STRING> *files, const char *wild)
53993 -+{
53994 -+ LEX_STRING *file_name= 0;
53995 -+ ST_SCHEMA_TABLE *tmp_schema_table= schema_tables;
53996 -+ st_add_schema_table add_data;
53997 -+ DBUG_ENTER("schema_tables_add");
53998 -+
53999 -+ for (; tmp_schema_table->table_name; tmp_schema_table++)
54000 -+ {
54001 -+ if (tmp_schema_table->hidden)
54002 -+ continue;
54003 -+ if (wild)
54004 -+ {
54005 -+ if (lower_case_table_names)
54006 -+ {
54007 -+ if (wild_case_compare(files_charset_info,
54008 -+ tmp_schema_table->table_name,
54009 -+ wild))
54010 -+ continue;
54011 -+ }
54012 -+ else if (wild_compare(tmp_schema_table->table_name, wild, 0))
54013 -+ continue;
54014 -+ }
54015 -+ if ((file_name=
54016 -+ thd->make_lex_string(file_name, tmp_schema_table->table_name,
54017 -+ strlen(tmp_schema_table->table_name), TRUE)) &&
54018 -+ !files->push_back(file_name))
54019 -+ continue;
54020 -+ DBUG_RETURN(1);
54021 -+ }
54022 -+
54023 -+ add_data.files= files;
54024 -+ add_data.wild= wild;
54025 -+ if (plugin_foreach(thd, add_schema_table,
54026 -+ MYSQL_INFORMATION_SCHEMA_PLUGIN, &add_data))
54027 -+ DBUG_RETURN(1);
54028 -+
54029 -+ DBUG_RETURN(0);
54030 -+}
54031 -+
54032 -+
54033 -+/**
54034 -+ @brief Create table names list
54035 -+
54036 -+ @details The function creates the list of table names in
54037 -+ database
54038 -+
54039 -+ @param[in] thd thread handler
54040 -+ @param[in] table_names List of table names in database
54041 -+ @param[in] lex pointer to LEX struct
54042 -+ @param[in] lookup_field_vals pointer to LOOKUP_FIELD_VALUE struct
54043 -+ @param[in] with_i_schema TRUE means that we add I_S tables to list
54044 -+ @param[in] db_name database name
54045 -+
54046 -+ @return Operation status
54047 -+ @retval 0 ok
54048 -+ @retval 1 fatal error
54049 -+ @retval 2 Not fatal error; Safe to ignore this file list
54050 -+*/
54051 -+
54052 -+static int
54053 -+make_table_name_list(THD *thd, List<LEX_STRING> *table_names, LEX *lex,
54054 -+ LOOKUP_FIELD_VALUES *lookup_field_vals,
54055 -+ bool with_i_schema, LEX_STRING *db_name)
54056 -+{
54057 -+ char path[FN_REFLEN + 1];
54058 -+ build_table_filename(path, sizeof(path) - 1, db_name->str, "", "", 0);
54059 -+ if (!lookup_field_vals->wild_table_value &&
54060 -+ lookup_field_vals->table_value.str)
54061 -+ {
54062 -+ if (with_i_schema)
54063 -+ {
54064 -+ LEX_STRING *name;
54065 -+ ST_SCHEMA_TABLE *schema_table=
54066 -+ find_schema_table(thd, lookup_field_vals->table_value.str);
54067 -+ if (schema_table && !schema_table->hidden)
54068 -+ {
54069 -+ if (!(name=
54070 -+ thd->make_lex_string(NULL, schema_table->table_name,
54071 -+ strlen(schema_table->table_name), TRUE)) ||
54072 -+ table_names->push_back(name))
54073 -+ return 1;
54074 -+ }
54075 -+ }
54076 -+ else
54077 -+ {
54078 -+ if (table_names->push_back(&lookup_field_vals->table_value))
54079 -+ return 1;
54080 -+ /*
54081 -+ Check that table is relevant in current transaction.
54082 -+ (used for ndb engine, see ndbcluster_find_files(), ha_ndbcluster.cc)
54083 -+ */
54084 -+ VOID(ha_find_files(thd, db_name->str, path,
54085 -+ lookup_field_vals->table_value.str, 0,
54086 -+ table_names));
54087 -+ }
54088 -+ return 0;
54089 -+ }
54090 -+
54091 -+ /*
54092 -+ This call will add all matching the wildcards (if specified) IS tables
54093 -+ to the list
54094 -+ */
54095 -+ if (with_i_schema)
54096 -+ return (schema_tables_add(thd, table_names,
54097 -+ lookup_field_vals->table_value.str));
54098 -+
54099 -+ find_files_result res= find_files(thd, table_names, db_name->str, path,
54100 -+ lookup_field_vals->table_value.str, 0);
54101 -+ if (res != FIND_FILES_OK)
54102 -+ {
54103 -+ /*
54104 -+ Downgrade errors about problems with database directory to
54105 -+ warnings if this is not a 'SHOW' command. Another thread
54106 -+ may have dropped database, and we may still have a name
54107 -+ for that directory.
54108 -+ */
54109 -+ if (res == FIND_FILES_DIR)
54110 -+ {
54111 -+ if (sql_command_flags[lex->sql_command] & CF_STATUS_COMMAND)
54112 -+ return 1;
54113 -+ thd->clear_error();
54114 -+ return 2;
54115 -+ }
54116 -+ return 1;
54117 -+ }
54118 -+ return 0;
54119 -+}
54120 -+
54121 -+
54122 -+/**
54123 -+ @brief Fill I_S table for SHOW COLUMNS|INDEX commands
54124 -+
54125 -+ @param[in] thd thread handler
54126 -+ @param[in] tables TABLE_LIST for I_S table
54127 -+ @param[in] schema_table pointer to I_S structure
54128 -+ @param[in] open_tables_state_backup pointer to Open_tables_state object
54129 -+ which is used to save|restore original
54130 -+ status of variables related to
54131 -+ open tables state
54132 -+
54133 -+ @return Operation status
54134 -+ @retval 0 success
54135 -+ @retval 1 error
54136 -+*/
54137 -+
54138 -+static int
54139 -+fill_schema_show_cols_or_idxs(THD *thd, TABLE_LIST *tables,
54140 -+ ST_SCHEMA_TABLE *schema_table,
54141 -+ Open_tables_state *open_tables_state_backup)
54142 -+{
54143 -+ LEX *lex= thd->lex;
54144 -+ bool res;
54145 -+ LEX_STRING tmp_lex_string, tmp_lex_string1, *db_name, *table_name;
54146 -+ enum_sql_command save_sql_command= lex->sql_command;
54147 -+ TABLE_LIST *show_table_list= tables->schema_select_lex->table_list.first;
54148 -+ TABLE *table= tables->table;
54149 -+ int error= 1;
54150 -+ DBUG_ENTER("fill_schema_show");
54151 -+
54152 -+ lex->all_selects_list= tables->schema_select_lex;
54153 -+ /*
54154 -+ Restore thd->temporary_tables to be able to process
54155 -+ temporary tables(only for 'show index' & 'show columns').
54156 -+ This should be changed when processing of temporary tables for
54157 -+ I_S tables will be done.
54158 -+ */
54159 -+ thd->temporary_tables= open_tables_state_backup->temporary_tables;
54160 -+ /*
54161 -+ Let us set fake sql_command so views won't try to merge
54162 -+ themselves into main statement. If we don't do this,
54163 -+ SELECT * from information_schema.xxxx will cause problems.
54164 -+ SQLCOM_SHOW_FIELDS is used because it satisfies 'only_view_structure()'
54165 -+ */
54166 -+ lex->sql_command= SQLCOM_SHOW_FIELDS;
54167 -+ res= open_normal_and_derived_tables(thd, show_table_list,
54168 -+ MYSQL_LOCK_IGNORE_FLUSH);
54169 -+ lex->sql_command= save_sql_command;
54170 -+ /*
54171 -+ get_all_tables() returns 1 on failure and 0 on success thus
54172 -+ return only these and not the result code of ::process_table()
54173 -+
54174 -+ We should use show_table_list->alias instead of
54175 -+ show_table_list->table_name because table_name
54176 -+ could be changed during opening of I_S tables. It's safe
54177 -+ to use alias because alias contains original table name
54178 -+ in this case(this part of code is used only for
54179 -+ 'show columns' & 'show statistics' commands).
54180 -+ */
54181 -+ table_name= thd->make_lex_string(&tmp_lex_string1, show_table_list->alias,
54182 -+ strlen(show_table_list->alias), FALSE);
54183 -+ if (!show_table_list->view)
54184 -+ db_name= thd->make_lex_string(&tmp_lex_string, show_table_list->db,
54185 -+ show_table_list->db_length, FALSE);
54186 -+ else
54187 -+ db_name= &show_table_list->view_db;
54188 -+
54189 -+
54190 -+ error= test(schema_table->process_table(thd, show_table_list,
54191 -+ table, res, db_name,
54192 -+ table_name));
54193 -+ thd->temporary_tables= 0;
54194 -+ close_tables_for_reopen(thd, &show_table_list);
54195 -+ DBUG_RETURN(error);
54196 -+}
54197 -+
54198 -+
54199 -+/**
54200 -+ @brief Fill I_S table for SHOW TABLE NAMES commands
54201 -+
54202 -+ @param[in] thd thread handler
54203 -+ @param[in] table TABLE struct for I_S table
54204 -+ @param[in] db_name database name
54205 -+ @param[in] table_name table name
54206 -+ @param[in] with_i_schema I_S table if TRUE
54207 -+
54208 -+ @return Operation status
54209 -+ @retval 0 success
54210 -+ @retval 1 error
54211 -+*/
54212 -+
54213 -+static int fill_schema_table_names(THD *thd, TABLE *table,
54214 -+ LEX_STRING *db_name, LEX_STRING *table_name,
54215 -+ bool with_i_schema)
54216 -+{
54217 -+ if (with_i_schema)
54218 -+ {
54219 -+ table->field[3]->store(STRING_WITH_LEN("SYSTEM VIEW"),
54220 -+ system_charset_info);
54221 -+ }
54222 -+ else
54223 -+ {
54224 -+ enum legacy_db_type not_used;
54225 -+ char path[FN_REFLEN + 1];
54226 -+ (void) build_table_filename(path, sizeof(path) - 1, db_name->str,
54227 -+ table_name->str, reg_ext, 0);
54228 -+ switch (mysql_frm_type(thd, path, &not_used)) {
54229 -+ case FRMTYPE_ERROR:
54230 -+ table->field[3]->store(STRING_WITH_LEN("ERROR"),
54231 -+ system_charset_info);
54232 -+ break;
54233 -+ case FRMTYPE_TABLE:
54234 -+ table->field[3]->store(STRING_WITH_LEN("BASE TABLE"),
54235 -+ system_charset_info);
54236 -+ break;
54237 -+ case FRMTYPE_VIEW:
54238 -+ table->field[3]->store(STRING_WITH_LEN("VIEW"),
54239 -+ system_charset_info);
54240 -+ break;
54241 -+ default:
54242 -+ DBUG_ASSERT(0);
54243 -+ }
54244 -+ if (thd->is_error() && thd->main_da.sql_errno() == ER_NO_SUCH_TABLE)
54245 -+ {
54246 -+ thd->clear_error();
54247 -+ return 0;
54248 -+ }
54249 -+ }
54250 -+ if (schema_table_store_record(thd, table))
54251 -+ return 1;
54252 -+ return 0;
54253 -+}
54254 -+
54255 -+
54256 -+/**
54257 -+ @brief Get open table method
54258 -+
54259 -+ @details The function calculates the method which will be used
54260 -+ for table opening:
54261 -+ SKIP_OPEN_TABLE - do not open table
54262 -+ OPEN_FRM_ONLY - open FRM file only
54263 -+ OPEN_FULL_TABLE - open FRM, data, index files
54264 -+ @param[in] tables I_S table table_list
54265 -+ @param[in] schema_table I_S table struct
54266 -+ @param[in] schema_table_idx I_S table index
54267 -+
54268 -+ @return return a set of flags
54269 -+ @retval SKIP_OPEN_TABLE | OPEN_FRM_ONLY | OPEN_FULL_TABLE
54270 -+*/
54271 -+
54272 -+uint get_table_open_method(TABLE_LIST *tables,
54273 -+ ST_SCHEMA_TABLE *schema_table,
54274 -+ enum enum_schema_tables schema_table_idx)
54275 -+{
54276 -+ /*
54277 -+ determine which method will be used for table opening
54278 -+ */
54279 -+ if (schema_table->i_s_requested_object & OPTIMIZE_I_S_TABLE)
54280 -+ {
54281 -+ Field **ptr, *field;
54282 -+ int table_open_method= 0, field_indx= 0;
54283 -+ uint star_table_open_method= OPEN_FULL_TABLE;
54284 -+ bool used_star= true; // true if '*' is used in select
54285 -+ for (ptr=tables->table->field; (field= *ptr) ; ptr++)
54286 -+ {
54287 -+ star_table_open_method=
54288 -+ min(star_table_open_method,
54289 -+ schema_table->fields_info[field_indx].open_method);
54290 -+ if (bitmap_is_set(tables->table->read_set, field->field_index))
54291 -+ {
54292 -+ used_star= false;
54293 -+ table_open_method|= schema_table->fields_info[field_indx].open_method;
54294 -+ }
54295 -+ field_indx++;
54296 -+ }
54297 -+ if (used_star)
54298 -+ return star_table_open_method;
54299 -+ return table_open_method;
54300 -+ }
54301 -+ /* I_S tables which use get_all_tables but can not be optimized */
54302 -+ return (uint) OPEN_FULL_TABLE;
54303 -+}
54304 -+
54305 -+
54306 -+/**
54307 -+ @brief Fill I_S table with data from FRM file only
54308 -+
54309 -+ @param[in] thd thread handler
54310 -+ @param[in] table TABLE struct for I_S table
54311 -+ @param[in] schema_table I_S table struct
54312 -+ @param[in] db_name database name
54313 -+ @param[in] table_name table name
54314 -+ @param[in] schema_table_idx I_S table index
54315 -+
54316 -+ @return Operation status
54317 -+ @retval 0 Table is processed and we can continue
54318 -+ with new table
54319 -+ @retval 1 It's view and we have to use
54320 -+ open_tables function for this table
54321 -+*/
54322 -+
54323 -+static int fill_schema_table_from_frm(THD *thd,TABLE *table,
54324 -+ ST_SCHEMA_TABLE *schema_table,
54325 -+ LEX_STRING *db_name,
54326 -+ LEX_STRING *table_name,
54327 -+ enum enum_schema_tables schema_table_idx)
54328 -+{
54329 -+ TABLE_SHARE *share;
54330 -+ TABLE tbl;
54331 -+ TABLE_LIST table_list;
54332 -+ uint res= 0;
54333 -+ int error;
54334 -+ char key[MAX_DBKEY_LENGTH];
54335 -+ uint key_length;
54336 -+
54337 -+ bzero((char*) &table_list, sizeof(TABLE_LIST));
54338 -+ bzero((char*) &tbl, sizeof(TABLE));
54339 -+
54340 -+ table_list.table_name= table_name->str;
54341 -+ table_list.db= db_name->str;
54342 -+ key_length= create_table_def_key(thd, key, &table_list, 0);
54343 -+ pthread_mutex_lock(&LOCK_open);
54344 -+ share= get_table_share(thd, &table_list, key,
54345 -+ key_length, OPEN_VIEW, &error);
54346 -+ if (!share)
54347 -+ {
54348 -+ res= 0;
54349 -+ goto err;
54350 -+ }
54351 -+
54352 -+ if (share->is_view)
54353 -+ {
54354 -+ if (schema_table->i_s_requested_object & OPEN_TABLE_ONLY)
54355 -+ {
54356 -+ /* skip view processing */
54357 -+ res= 0;
54358 -+ goto err1;
54359 -+ }
54360 -+ else if (schema_table->i_s_requested_object & OPEN_VIEW_FULL)
54361 -+ {
54362 -+ /*
54363 -+ tell get_all_tables() to fall back to
54364 -+ open_normal_and_derived_tables()
54365 -+ */
54366 -+ res= 1;
54367 -+ goto err1;
54368 -+ }
54369 -+ }
54370 -+
54371 -+ if (share->is_view ||
54372 -+ !open_table_from_share(thd, share, table_name->str, 0,
54373 -+ (READ_KEYINFO | COMPUTE_TYPES |
54374 -+ EXTRA_RECORD | OPEN_FRM_FILE_ONLY),
54375 -+ thd->open_options, &tbl, FALSE))
54376 -+ {
54377 -+ tbl.s= share;
54378 -+ table_list.table= &tbl;
54379 -+ table_list.view= (st_lex*) share->is_view;
54380 -+ res= schema_table->process_table(thd, &table_list, table,
54381 -+ res, db_name, table_name);
54382 -+ closefrm(&tbl, true);
54383 -+ goto err;
54384 -+ }
54385 -+
54386 -+err1:
54387 -+ release_table_share(share, RELEASE_NORMAL);
54388 -+
54389 -+err:
54390 -+ pthread_mutex_unlock(&LOCK_open);
54391 -+ thd->clear_error();
54392 -+ return res;
54393 -+}
54394 -+
54395 -+
54396 -+
54397 -+/**
54398 -+ @brief Fill I_S tables whose data are retrieved
54399 -+ from frm files and storage engine
54400 -+
54401 -+ @details The information schema tables are internally represented as
54402 -+ temporary tables that are filled at query execution time.
54403 -+ Those I_S tables whose data are retrieved
54404 -+ from frm files and storage engine are filled by the function
54405 -+ get_all_tables().
54406 -+
54407 -+ @param[in] thd thread handler
54408 -+ @param[in] tables I_S table
54409 -+ @param[in] cond 'WHERE' condition
54410 -+
54411 -+ @return Operation status
54412 -+ @retval 0 success
54413 -+ @retval 1 error
54414 -+*/
54415 -+
54416 -+int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
54417 -+{
54418 -+ LEX *lex= thd->lex;
54419 -+ TABLE *table= tables->table;
54420 -+ SELECT_LEX *old_all_select_lex= lex->all_selects_list;
54421 -+ enum_sql_command save_sql_command= lex->sql_command;
54422 -+ SELECT_LEX *lsel= tables->schema_select_lex;
54423 -+ ST_SCHEMA_TABLE *schema_table= tables->schema_table;
54424 -+ SELECT_LEX sel;
54425 -+ LOOKUP_FIELD_VALUES lookup_field_vals;
54426 -+ LEX_STRING *db_name, *table_name;
54427 -+ bool with_i_schema;
54428 -+ enum enum_schema_tables schema_table_idx;
54429 -+ List<LEX_STRING> db_names;
54430 -+ List_iterator_fast<LEX_STRING> it(db_names);
54431 -+ COND *partial_cond= 0;
54432 -+ uint derived_tables= lex->derived_tables;
54433 -+ int error= 1;
54434 -+ Open_tables_state open_tables_state_backup;
54435 -+ uint8 save_context_analysis_only= lex->context_analysis_only;
54436 -+ Query_tables_list query_tables_list_backup;
54437 -+#ifndef NO_EMBEDDED_ACCESS_CHECKS
54438 -+ Security_context *sctx= thd->security_ctx;
54439 -+#endif
54440 -+ uint table_open_method;
54441 -+ DBUG_ENTER("get_all_tables");
54442 -+
54443 -+ lex->context_analysis_only|= CONTEXT_ANALYSIS_ONLY_VIEW;
54444 -+ lex->reset_n_backup_query_tables_list(&query_tables_list_backup);
54445 -+
54446 -+ /*
54447 -+ We should not introduce deadlocks even if we already have some
54448 -+ tables open and locked, since we won't lock tables which we will
54449 -+ open and will ignore possible name-locks for these tables.
54450 -+ */
54451 -+ thd->reset_n_backup_open_tables_state(&open_tables_state_backup);
54452 -+
54453 -+ /*
54454 -+ this branch processes SHOW FIELDS, SHOW INDEXES commands.
54455 -+ see sql_parse.cc, prepare_schema_table() function where
54456 -+ this values are initialized
54457 -+ */
54458 -+ if (lsel && lsel->table_list.first)
54459 -+ {
54460 -+ error= fill_schema_show_cols_or_idxs(thd, tables, schema_table,
54461 -+ &open_tables_state_backup);
54462 -+ goto err;
54463 -+ }
54464 -+
54465 -+ schema_table_idx= get_schema_table_idx(schema_table);
54466 -+ if (get_lookup_field_values(thd, cond, tables, &lookup_field_vals))
54467 -+ {
54468 -+ error= 0;
54469 -+ goto err;
54470 -+ }
54471 -+
54472 -+ DBUG_PRINT("INDEX VALUES",("db_name='%s', table_name='%s'",
54473 -+ STR_OR_NIL(lookup_field_vals.db_value.str),
54474 -+ STR_OR_NIL(lookup_field_vals.table_value.str)));
54475 -+
54476 -+ if (!lookup_field_vals.wild_db_value && !lookup_field_vals.wild_table_value)
54477 -+ {
54478 -+ /*
54479 -+ if lookup value is empty string then
54480 -+ it's impossible table name or db name
54481 -+ */
54482 -+ if ((lookup_field_vals.db_value.str &&
54483 -+ !lookup_field_vals.db_value.str[0]) ||
54484 -+ (lookup_field_vals.table_value.str &&
54485 -+ !lookup_field_vals.table_value.str[0]))
54486 -+ {
54487 -+ error= 0;
54488 -+ goto err;
54489 -+ }
54490 -+ }
54491 -+
54492 -+ if (lookup_field_vals.db_value.length &&
54493 -+ !lookup_field_vals.wild_db_value)
54494 -+ tables->has_db_lookup_value= TRUE;
54495 -+ if (lookup_field_vals.table_value.length &&
54496 -+ !lookup_field_vals.wild_table_value)
54497 -+ tables->has_table_lookup_value= TRUE;
54498 -+
54499 -+ if (tables->has_db_lookup_value && tables->has_table_lookup_value)
54500 -+ partial_cond= 0;
54501 -+ else
54502 -+ partial_cond= make_cond_for_info_schema(cond, tables);
54503 -+
54504 -+ tables->table_open_method= table_open_method=
54505 -+ get_table_open_method(tables, schema_table, schema_table_idx);
54506 -+
54507 -+ if (lex->describe)
54508 -+ {
54509 -+ /* EXPLAIN SELECT */
54510 -+ error= 0;
54511 -+ goto err;
54512 -+ }
54513 -+
54514 -+ if (make_db_list(thd, &db_names, &lookup_field_vals, &with_i_schema))
54515 -+ goto err;
54516 -+ it.rewind(); /* To get access to new elements in basis list */
54517 -+ while ((db_name= it++))
54518 -+ {
54519 -+ LEX_STRING orig_db_name;
54520 -+
54521 -+ /* db_name can be changed in make_table_list() func */
54522 -+ if (!thd->make_lex_string(&orig_db_name, db_name->str,
54523 -+ db_name->length, FALSE))
54524 -+ goto err;
54525 -+#ifndef NO_EMBEDDED_ACCESS_CHECKS
54526 -+ if (!(check_access(thd,SELECT_ACL, db_name->str,
54527 -+ &thd->col_access, 0, 1, with_i_schema) ||
54528 -+ (!thd->col_access && check_grant_db(thd, db_name->str))) ||
54529 -+ sctx->master_access & (DB_ACLS | SHOW_DB_ACL) ||
54530 -+ acl_get(sctx->host, sctx->ip, sctx->priv_user, db_name->str, 0))
54531 -+#endif
54532 -+ {
54533 -+ thd->no_warnings_for_error= 1;
54534 -+ List<LEX_STRING> table_names;
54535 -+ int res= make_table_name_list(thd, &table_names, lex,
54536 -+ &lookup_field_vals,
54537 -+ with_i_schema, db_name);
54538 -+ if (res == 2) /* Not fatal error, continue */
54539 -+ continue;
54540 -+ if (res)
54541 -+ goto err;
54542 -+
54543 -+ List_iterator_fast<LEX_STRING> it_files(table_names);
54544 -+ while ((table_name= it_files++))
54545 -+ {
54546 -+ restore_record(table, s->default_values);
54547 -+ table->field[schema_table->idx_field1]->
54548 -+ store(db_name->str, db_name->length, system_charset_info);
54549 -+ table->field[schema_table->idx_field2]->
54550 -+ store(table_name->str, table_name->length, system_charset_info);
54551 -+
54552 -+ if (!partial_cond || partial_cond->val_int())
54553 -+ {
54554 -+ /*
54555 -+ If table is I_S.tables and open_table_method is 0 (eg SKIP_OPEN)
54556 -+ we can skip table opening and we don't have lookup value for
54557 -+ table name or lookup value is wild string(table name list is
54558 -+ already created by make_table_name_list() function).
54559 -+ */
54560 -+ if (!table_open_method && schema_table_idx == SCH_TABLES &&
54561 -+ (!lookup_field_vals.table_value.length ||
54562 -+ lookup_field_vals.wild_table_value))
54563 -+ {
54564 -+ if (schema_table_store_record(thd, table))
54565 -+ goto err; /* Out of space in temporary table */
54566 -+ continue;
54567 -+ }
54568 -+
54569 -+ /* SHOW TABLE NAMES command */
54570 -+ if (schema_table_idx == SCH_TABLE_NAMES)
54571 -+ {
54572 -+ if (fill_schema_table_names(thd, tables->table, db_name,
54573 -+ table_name, with_i_schema))
54574 -+ continue;
54575 -+ }
54576 -+ else
54577 -+ {
54578 -+ if (!(table_open_method & ~OPEN_FRM_ONLY) &&
54579 -+ !with_i_schema)
54580 -+ {
54581 -+ if (!fill_schema_table_from_frm(thd, table, schema_table, db_name,
54582 -+ table_name, schema_table_idx))
54583 -+ continue;
54584 -+ }
54585 -+
54586 -+ int res;
54587 -+ LEX_STRING tmp_lex_string;
54588 -+ /*
54589 -+ Set the parent lex of 'sel' because it is needed by
54590 -+ sel.init_query() which is called inside make_table_list.
54591 -+ */
54592 -+ thd->no_warnings_for_error= 1;
54593 -+ sel.parent_lex= lex;
54594 -+ if (make_table_list(thd, &sel, db_name, table_name))
54595 -+ goto err;
54596 -+ TABLE_LIST *show_table_list= sel.table_list.first;
54597 -+ lex->all_selects_list= &sel;
54598 -+ lex->derived_tables= 0;
54599 -+ lex->sql_command= SQLCOM_SHOW_FIELDS;
54600 -+ show_table_list->i_s_requested_object=
54601 -+ schema_table->i_s_requested_object;
54602 -+ DEBUG_SYNC(thd, "before_open_in_get_all_tables");
54603 -+ res= open_normal_and_derived_tables(thd, show_table_list,
54604 -+ MYSQL_LOCK_IGNORE_FLUSH);
54605 -+ lex->sql_command= save_sql_command;
54606 -+ /*
54607 -+ XXX: show_table_list has a flag i_is_requested,
54608 -+ and when it's set, open_normal_and_derived_tables()
54609 -+ can return an error without setting an error message
54610 -+ in THD, which is a hack. This is why we have to
54611 -+ check for res, then for thd->is_error() only then
54612 -+ for thd->main_da.sql_errno().
54613 -+ */
54614 -+ if (res && thd->is_error() &&
54615 -+ thd->main_da.sql_errno() == ER_NO_SUCH_TABLE)
54616 -+ {
54617 -+ /*
54618 -+ Hide error for not existing table.
54619 -+ This error can occur for example when we use
54620 -+ where condition with db name and table name and this
54621 -+ table does not exist.
54622 -+ */
54623 -+ res= 0;
54624 -+ thd->clear_error();
54625 -+ }
54626 -+ else
54627 -+ {
54628 -+ /*
54629 -+ We should use show_table_list->alias instead of
54630 -+ show_table_list->table_name because table_name
54631 -+ could be changed during opening of I_S tables. It's safe
54632 -+ to use alias because alias contains original table name
54633 -+ in this case.
54634 -+ */
54635 -+ thd->make_lex_string(&tmp_lex_string, show_table_list->alias,
54636 -+ strlen(show_table_list->alias), FALSE);
54637 -+ res= schema_table->process_table(thd, show_table_list, table,
54638 -+ res, &orig_db_name,
54639 -+ &tmp_lex_string);
54640 -+ close_tables_for_reopen(thd, &show_table_list);
54641 -+ }
54642 -+ DBUG_ASSERT(!lex->query_tables_own_last);
54643 -+ if (res)
54644 -+ goto err;
54645 -+ }
54646 -+ }
54647 -+ }
54648 -+ /*
54649 -+ If we have information schema its always the first table and only
54650 -+ the first table. Reset for other tables.
54651 -+ */
54652 -+ with_i_schema= 0;
54653 -+ }
54654 -+ }
54655 -+
54656 -+ error= 0;
54657 -+err:
54658 -+ thd->restore_backup_open_tables_state(&open_tables_state_backup);
54659 -+ lex->restore_backup_query_tables_list(&query_tables_list_backup);
54660 -+ lex->derived_tables= derived_tables;
54661 -+ lex->all_selects_list= old_all_select_lex;
54662 -+ lex->context_analysis_only= save_context_analysis_only;
54663 -+ lex->sql_command= save_sql_command;
54664 -+ DBUG_RETURN(error);
54665 -+}
54666 -+
54667 -+
54668 -+bool store_schema_shemata(THD* thd, TABLE *table, LEX_STRING *db_name,
54669 -+ CHARSET_INFO *cs)
54670 -+{
54671 -+ restore_record(table, s->default_values);
54672 -+ table->field[1]->store(db_name->str, db_name->length, system_charset_info);
54673 -+ table->field[2]->store(cs->csname, strlen(cs->csname), system_charset_info);
54674 -+ table->field[3]->store(cs->name, strlen(cs->name), system_charset_info);
54675 -+ return schema_table_store_record(thd, table);
54676 -+}
54677 -+
54678 -+
54679 -+int fill_schema_schemata(THD *thd, TABLE_LIST *tables, COND *cond)
54680 -+{
54681 -+ /*
54682 -+ TODO: fill_schema_shemata() is called when new client is connected.
54683 -+ Returning error status in this case leads to client hangup.
54684 -+ */
54685 -+
54686 -+ LOOKUP_FIELD_VALUES lookup_field_vals;
54687 -+ List<LEX_STRING> db_names;
54688 -+ LEX_STRING *db_name;
54689 -+ bool with_i_schema;
54690 -+ HA_CREATE_INFO create;
54691 -+ TABLE *table= tables->table;
54692 -+#ifndef NO_EMBEDDED_ACCESS_CHECKS
54693 -+ Security_context *sctx= thd->security_ctx;
54694 -+#endif
54695 -+ DBUG_ENTER("fill_schema_shemata");
54696 -+
54697 -+ if (get_lookup_field_values(thd, cond, tables, &lookup_field_vals))
54698 -+ DBUG_RETURN(0);
54699 -+ DBUG_PRINT("INDEX VALUES",("db_name='%s', table_name='%s'",
54700 -+ lookup_field_vals.db_value.str,
54701 -+ lookup_field_vals.table_value.str));
54702 -+ if (make_db_list(thd, &db_names, &lookup_field_vals,
54703 -+ &with_i_schema))
54704 -+ DBUG_RETURN(1);
54705 -+
54706 -+ /*
54707 -+ If we have lookup db value we should check that the database exists
54708 -+ */
54709 -+ if(lookup_field_vals.db_value.str && !lookup_field_vals.wild_db_value &&
54710 -+ !with_i_schema)
54711 -+ {
54712 -+ char path[FN_REFLEN+16];
54713 -+ uint path_len;
54714 -+ MY_STAT stat_info;
54715 -+ if (!lookup_field_vals.db_value.str[0])
54716 -+ DBUG_RETURN(0);
54717 -+ path_len= build_table_filename(path, sizeof(path) - 1,
54718 -+ lookup_field_vals.db_value.str, "", "", 0);
54719 -+ path[path_len-1]= 0;
54720 -+ if (!my_stat(path,&stat_info,MYF(0)))
54721 -+ DBUG_RETURN(0);
54722 -+ }
54723 -+
54724 -+ List_iterator_fast<LEX_STRING> it(db_names);
54725 -+ while ((db_name=it++))
54726 -+ {
54727 -+ if (with_i_schema) // information schema name is always first in list
54728 -+ {
54729 -+ if (store_schema_shemata(thd, table, db_name,
54730 -+ system_charset_info))
54731 -+ DBUG_RETURN(1);
54732 -+ with_i_schema= 0;
54733 -+ continue;
54734 -+ }
54735 -+#ifndef NO_EMBEDDED_ACCESS_CHECKS
54736 -+ if (sctx->master_access & (DB_ACLS | SHOW_DB_ACL) ||
54737 -+ acl_get(sctx->host, sctx->ip, sctx->priv_user, db_name->str, 0) ||
54738 -+ !check_grant_db(thd, db_name->str))
54739 -+#endif
54740 -+ {
54741 -+ load_db_opt_by_name(thd, db_name->str, &create);
54742 -+ if (store_schema_shemata(thd, table, db_name,
54743 -+ create.default_table_charset))
54744 -+ DBUG_RETURN(1);
54745 -+ }
54746 -+ }
54747 -+ DBUG_RETURN(0);
54748 -+}
54749 -+
54750 -+
54751 -+static int get_schema_tables_record(THD *thd, TABLE_LIST *tables,
54752 -+ TABLE *table, bool res,
54753 -+ LEX_STRING *db_name,
54754 -+ LEX_STRING *table_name)
54755 -+{
54756 -+ const char *tmp_buff;
54757 -+ MYSQL_TIME time;
54758 -+ int info_error= 0;
54759 -+ CHARSET_INFO *cs= system_charset_info;
54760 -+ DBUG_ENTER("get_schema_tables_record");
54761 -+
54762 -+ restore_record(table, s->default_values);
54763 -+ table->field[1]->store(db_name->str, db_name->length, cs);
54764 -+ table->field[2]->store(table_name->str, table_name->length, cs);
54765 -+
54766 -+ if (res)
54767 -+ {
54768 -+ /* There was a table open error, so set the table type and return */
54769 -+ if (tables->view)
54770 -+ table->field[3]->store(STRING_WITH_LEN("VIEW"), cs);
54771 -+ else if (tables->schema_table)
54772 -+ table->field[3]->store(STRING_WITH_LEN("SYSTEM VIEW"), cs);
54773 -+ else
54774 -+ table->field[3]->store(STRING_WITH_LEN("BASE TABLE"), cs);
54775 -+
54776 -+ goto err;
54777 -+ }
54778 -+
54779 -+ if (tables->view)
54780 -+ {
54781 -+ table->field[3]->store(STRING_WITH_LEN("VIEW"), cs);
54782 -+ table->field[20]->store(STRING_WITH_LEN("VIEW"), cs);
54783 -+ }
54784 -+ else
54785 -+ {
54786 -+ char option_buff[350],*ptr;
54787 -+ TABLE *show_table= tables->table;
54788 -+ TABLE_SHARE *share= show_table->s;
54789 -+ handler *file= show_table->file;
54790 -+ handlerton *tmp_db_type= share->db_type();
54791 -+#ifdef WITH_PARTITION_STORAGE_ENGINE
54792 -+ bool is_partitioned= FALSE;
54793 -+#endif
54794 -+ if (share->tmp_table == SYSTEM_TMP_TABLE)
54795 -+ table->field[3]->store(STRING_WITH_LEN("SYSTEM VIEW"), cs);
54796 -+ else if (share->tmp_table)
54797 -+ table->field[3]->store(STRING_WITH_LEN("LOCAL TEMPORARY"), cs);
54798 -+ else
54799 -+ table->field[3]->store(STRING_WITH_LEN("BASE TABLE"), cs);
54800 -+
54801 -+ for (int i= 4; i < 20; i++)
54802 -+ {
54803 -+ if (i == 7 || (i > 12 && i < 17) || i == 18)
54804 -+ continue;
54805 -+ table->field[i]->set_notnull();
54806 -+ }
54807 -+#ifdef WITH_PARTITION_STORAGE_ENGINE
54808 -+ if (share->db_type() == partition_hton &&
54809 -+ share->partition_info_len)
54810 -+ {
54811 -+ tmp_db_type= share->default_part_db_type;
54812 -+ is_partitioned= TRUE;
54813 -+ }
54814 -+#endif
54815 -+ tmp_buff= (char *) ha_resolve_storage_engine_name(tmp_db_type);
54816 -+ table->field[4]->store(tmp_buff, strlen(tmp_buff), cs);
54817 -+ table->field[5]->store((longlong) share->frm_version, TRUE);
54818 -+
54819 -+ ptr=option_buff;
54820 -+ if (share->min_rows)
54821 -+ {
54822 -+ ptr=strmov(ptr," min_rows=");
54823 -+ ptr=longlong10_to_str(share->min_rows,ptr,10);
54824 -+ }
54825 -+ if (share->max_rows)
54826 -+ {
54827 -+ ptr=strmov(ptr," max_rows=");
54828 -+ ptr=longlong10_to_str(share->max_rows,ptr,10);
54829 -+ }
54830 -+ if (share->avg_row_length)
54831 -+ {
54832 -+ ptr=strmov(ptr," avg_row_length=");
54833 -+ ptr=longlong10_to_str(share->avg_row_length,ptr,10);
54834 -+ }
54835 -+ if (share->db_create_options & HA_OPTION_PACK_KEYS)
54836 -+ ptr=strmov(ptr," pack_keys=1");
54837 -+ if (share->db_create_options & HA_OPTION_NO_PACK_KEYS)
54838 -+ ptr=strmov(ptr," pack_keys=0");
54839 -+ /* We use CHECKSUM, instead of TABLE_CHECKSUM, for backward compability */
54840 -+ if (share->db_create_options & HA_OPTION_CHECKSUM)
54841 -+ ptr=strmov(ptr," checksum=1");
54842 -+ if (share->db_create_options & HA_OPTION_DELAY_KEY_WRITE)
54843 -+ ptr=strmov(ptr," delay_key_write=1");
54844 -+ if (share->row_type != ROW_TYPE_DEFAULT)
54845 -+ ptr=strxmov(ptr, " row_format=",
54846 -+ ha_row_type[(uint) share->row_type],
54847 -+ NullS);
54848 -+ if (share->key_block_size)
54849 -+ {
54850 -+ ptr= strmov(ptr, " KEY_BLOCK_SIZE=");
54851 -+ ptr= longlong10_to_str(share->key_block_size, ptr, 10);
54852 -+ }
54853 -+#ifdef WITH_PARTITION_STORAGE_ENGINE
54854 -+ if (is_partitioned)
54855 -+ ptr= strmov(ptr, " partitioned");
54856 -+#endif
54857 -+ table->field[19]->store(option_buff+1,
54858 -+ (ptr == option_buff ? 0 :
54859 -+ (uint) (ptr-option_buff)-1), cs);
54860 -+
54861 -+ tmp_buff= (share->table_charset ?
54862 -+ share->table_charset->name : "default");
54863 -+ table->field[17]->store(tmp_buff, strlen(tmp_buff), cs);
54864 -+
54865 -+ if (share->comment.str)
54866 -+ table->field[20]->store(share->comment.str, share->comment.length, cs);
54867 -+
54868 -+ if (file)
54869 -+ {
54870 -+ /* If info() fails, then there's nothing else to do */
54871 -+ if ((info_error= file->info(HA_STATUS_VARIABLE |
54872 -+ HA_STATUS_TIME |
54873 -+ HA_STATUS_AUTO)) != 0)
54874 -+ goto err;
54875 -+
54876 -+ enum row_type row_type = file->get_row_type();
54877 -+ switch (row_type) {
54878 -+ case ROW_TYPE_NOT_USED:
54879 -+ case ROW_TYPE_DEFAULT:
54880 -+ tmp_buff= ((share->db_options_in_use &
54881 -+ HA_OPTION_COMPRESS_RECORD) ? "Compressed" :
54882 -+ (share->db_options_in_use & HA_OPTION_PACK_RECORD) ?
54883 -+ "Dynamic" : "Fixed");
54884 -+ break;
54885 -+ case ROW_TYPE_FIXED:
54886 -+ tmp_buff= "Fixed";
54887 -+ break;
54888 -+ case ROW_TYPE_DYNAMIC:
54889 -+ tmp_buff= "Dynamic";
54890 -+ break;
54891 -+ case ROW_TYPE_COMPRESSED:
54892 -+ tmp_buff= "Compressed";
54893 -+ break;
54894 -+ case ROW_TYPE_REDUNDANT:
54895 -+ tmp_buff= "Redundant";
54896 -+ break;
54897 -+ case ROW_TYPE_COMPACT:
54898 -+ tmp_buff= "Compact";
54899 -+ break;
54900 -+ case ROW_TYPE_PAGE:
54901 -+ tmp_buff= "Paged";
54902 -+ break;
54903 -+ }
54904 -+ table->field[6]->store(tmp_buff, strlen(tmp_buff), cs);
54905 -+ if (!tables->schema_table)
54906 -+ {
54907 -+ table->field[7]->store((longlong) file->stats.records, TRUE);
54908 -+ table->field[7]->set_notnull();
54909 -+ }
54910 -+ table->field[8]->store((longlong) file->stats.mean_rec_length, TRUE);
54911 -+ table->field[9]->store((longlong) file->stats.data_file_length, TRUE);
54912 -+ if (file->stats.max_data_file_length)
54913 -+ {
54914 -+ table->field[10]->store((longlong) file->stats.max_data_file_length,
54915 -+ TRUE);
54916 -+ }
54917 -+ table->field[11]->store((longlong) file->stats.index_file_length, TRUE);
54918 -+ table->field[12]->store((longlong) file->stats.delete_length, TRUE);
54919 -+ if (show_table->found_next_number_field)
54920 -+ {
54921 -+ table->field[13]->store((longlong) file->stats.auto_increment_value,
54922 -+ TRUE);
54923 -+ table->field[13]->set_notnull();
54924 -+ }
54925 -+ if (file->stats.create_time)
54926 -+ {
54927 -+ thd->variables.time_zone->gmt_sec_to_TIME(&time,
54928 -+ (my_time_t) file->stats.create_time);
54929 -+ table->field[14]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
54930 -+ table->field[14]->set_notnull();
54931 -+ }
54932 -+ if (file->stats.update_time)
54933 -+ {
54934 -+ thd->variables.time_zone->gmt_sec_to_TIME(&time,
54935 -+ (my_time_t) file->stats.update_time);
54936 -+ table->field[15]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
54937 -+ table->field[15]->set_notnull();
54938 -+ }
54939 -+ if (file->stats.check_time)
54940 -+ {
54941 -+ thd->variables.time_zone->gmt_sec_to_TIME(&time,
54942 -+ (my_time_t) file->stats.check_time);
54943 -+ table->field[16]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
54944 -+ table->field[16]->set_notnull();
54945 -+ }
54946 -+ if (file->ha_table_flags() & (ulong) HA_HAS_CHECKSUM)
54947 -+ {
54948 -+ table->field[18]->store((longlong) file->checksum(), TRUE);
54949 -+ table->field[18]->set_notnull();
54950 -+ }
54951 -+ }
54952 -+ }
54953 -+
54954 -+err:
54955 -+ if (res || info_error)
54956 -+ {
54957 -+ /*
54958 -+ If an error was encountered, push a warning, set the TABLE COMMENT
54959 -+ column with the error text, and clear the error so that the operation
54960 -+ can continue.
54961 -+ */
54962 -+ const char *error= thd->is_error() ? thd->main_da.message() : "";
54963 -+ table->field[20]->store(error, strlen(error), cs);
54964 -+
54965 -+ if (thd->is_error())
54966 -+ {
54967 -+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
54968 -+ thd->main_da.sql_errno(), thd->main_da.message());
54969 -+ thd->clear_error();
54970 -+ }
54971 -+ }
54972 -+
54973 -+ DBUG_RETURN(schema_table_store_record(thd, table));
54974 -+}
54975 -+
54976 -+
54977 -+static int get_schema_column_record(THD *thd, TABLE_LIST *tables,
54978 -+ TABLE *table, bool res,
54979 -+ LEX_STRING *db_name,
54980 -+ LEX_STRING *table_name)
54981 -+{
54982 -+ LEX *lex= thd->lex;
54983 -+ const char *wild= lex->wild ? lex->wild->ptr() : NullS;
54984 -+ CHARSET_INFO *cs= system_charset_info;
54985 -+ TABLE *show_table;
54986 -+ Field **ptr,*field;
54987 -+ int count;
54988 -+ DBUG_ENTER("get_schema_column_record");
54989 -+
54990 -+ if (res)
54991 -+ {
54992 -+ if (lex->sql_command != SQLCOM_SHOW_FIELDS)
54993 -+ {
54994 -+ /*
54995 -+ I.e. we are in SELECT FROM INFORMATION_SCHEMA.COLUMS
54996 -+ rather than in SHOW COLUMNS
54997 -+ */
54998 -+ if (thd->is_error())
54999 -+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
55000 -+ thd->main_da.sql_errno(), thd->main_da.message());
55001 -+ thd->clear_error();
55002 -+ res= 0;
55003 -+ }
55004 -+ DBUG_RETURN(res);
55005 -+ }
55006 -+
55007 -+ show_table= tables->table;
55008 -+ count= 0;
55009 -+ restore_record(show_table, s->default_values);
55010 -+ show_table->use_all_columns(); // Required for default
55011 -+
55012 -+ for (ptr= show_table->field; (field= *ptr) ; ptr++)
55013 -+ {
55014 -+ const char *tmp_buff;
55015 -+ uchar *pos;
55016 -+ bool is_blob;
55017 -+ uint flags=field->flags;
55018 -+ char tmp[MAX_FIELD_WIDTH];
55019 -+ String type(tmp,sizeof(tmp), system_charset_info);
55020 -+ int decimals, field_length;
55021 -+
55022 -+ if (wild && wild[0] &&
55023 -+ wild_case_compare(system_charset_info, field->field_name,wild))
55024 -+ continue;
55025 -+
55026 -+ flags= field->flags;
55027 -+ count++;
55028 -+ /* Get default row, with all NULL fields set to NULL */
55029 -+ restore_record(table, s->default_values);
55030 -+
55031 -+#ifndef NO_EMBEDDED_ACCESS_CHECKS
55032 -+ uint col_access;
55033 -+ check_access(thd,SELECT_ACL | EXTRA_ACL, db_name->str,
55034 -+ &tables->grant.privilege, 0, 0, test(tables->schema_table));
55035 -+ col_access= get_column_grant(thd, &tables->grant,
55036 -+ db_name->str, table_name->str,
55037 -+ field->field_name) & COL_ACLS;
55038 -+ if (!tables->schema_table && !col_access)
55039 -+ continue;
55040 -+ char *end= tmp;
55041 -+ for (uint bitnr=0; col_access ; col_access>>=1,bitnr++)
55042 -+ {
55043 -+ if (col_access & 1)
55044 -+ {
55045 -+ *end++=',';
55046 -+ end=strmov(end,grant_types.type_names[bitnr]);
55047 -+ }
55048 -+ }
55049 -+ table->field[17]->store(tmp+1,end == tmp ? 0 : (uint) (end-tmp-1), cs);
55050 -+
55051 -+#endif
55052 -+ table->field[1]->store(db_name->str, db_name->length, cs);
55053 -+ table->field[2]->store(table_name->str, table_name->length, cs);
55054 -+ table->field[3]->store(field->field_name, strlen(field->field_name),
55055 -+ cs);
55056 -+ table->field[4]->store((longlong) count, TRUE);
55057 -+ field->sql_type(type);
55058 -+ table->field[14]->store(type.ptr(), type.length(), cs);
55059 -+ /*
55060 -+ MySQL column type has the following format:
55061 -+ base_type [(dimension)] [unsigned] [zerofill].
55062 -+ For DATA_TYPE column we extract only base type.
55063 -+ */
55064 -+ tmp_buff= strchr(type.ptr(), '(');
55065 -+ if (!tmp_buff)
55066 -+ /*
55067 -+ if there is no dimention part then check the presence of
55068 -+ [unsigned] [zerofill] attributes and cut them of if exist.
55069 -+ */
55070 -+ tmp_buff= strchr(type.ptr(), ' ');
55071 -+ table->field[7]->store(type.ptr(),
55072 -+ (tmp_buff ? tmp_buff - type.ptr() :
55073 -+ type.length()), cs);
55074 -+
55075 -+ if (get_field_default_value(thd, show_table, field, &type, 0))
55076 -+ {
55077 -+ table->field[5]->store(type.ptr(), type.length(), cs);
55078 -+ table->field[5]->set_notnull();
55079 -+ }
55080 -+ pos=(uchar*) ((flags & NOT_NULL_FLAG) ? "NO" : "YES");
55081 -+ table->field[6]->store((const char*) pos,
55082 -+ strlen((const char*) pos), cs);
55083 -+ is_blob= (field->type() == MYSQL_TYPE_BLOB);
55084 -+ if (field->has_charset() || is_blob ||
55085 -+ field->real_type() == MYSQL_TYPE_VARCHAR || // For varbinary type
55086 -+ field->real_type() == MYSQL_TYPE_STRING) // For binary type
55087 -+ {
55088 -+ uint32 octet_max_length= field->max_display_length();
55089 -+ if (is_blob && octet_max_length != (uint32) 4294967295U)
55090 -+ octet_max_length /= field->charset()->mbmaxlen;
55091 -+ longlong char_max_len= is_blob ?
55092 -+ (longlong) octet_max_length / field->charset()->mbminlen :
55093 -+ (longlong) octet_max_length / field->charset()->mbmaxlen;
55094 -+ table->field[8]->store(char_max_len, TRUE);
55095 -+ table->field[8]->set_notnull();
55096 -+ table->field[9]->store((longlong) octet_max_length, TRUE);
55097 -+ table->field[9]->set_notnull();
55098 -+ }
55099 -+
55100 -+ /*
55101 -+ Calculate field_length and decimals.
55102 -+ They are set to -1 if they should not be set (we should return NULL)
55103 -+ */
55104 -+
55105 -+ decimals= field->decimals();
55106 -+ switch (field->type()) {
55107 -+ case MYSQL_TYPE_NEWDECIMAL:
55108 -+ field_length= ((Field_new_decimal*) field)->precision;
55109 -+ break;
55110 -+ case MYSQL_TYPE_DECIMAL:
55111 -+ field_length= field->field_length - (decimals ? 2 : 1);
55112 -+ break;
55113 -+ case MYSQL_TYPE_TINY:
55114 -+ case MYSQL_TYPE_SHORT:
55115 -+ case MYSQL_TYPE_LONG:
55116 -+ case MYSQL_TYPE_INT24:
55117 -+ field_length= field->max_display_length() - 1;
55118 -+ break;
55119 -+ case MYSQL_TYPE_LONGLONG:
55120 -+ field_length= field->max_display_length() -
55121 -+ ((field->flags & UNSIGNED_FLAG) ? 0 : 1);
55122 -+ break;
55123 -+ case MYSQL_TYPE_BIT:
55124 -+ field_length= field->max_display_length();
55125 -+ decimals= -1; // return NULL
55126 -+ break;
55127 -+ case MYSQL_TYPE_FLOAT:
55128 -+ case MYSQL_TYPE_DOUBLE:
55129 -+ field_length= field->field_length;
55130 -+ if (decimals == NOT_FIXED_DEC)
55131 -+ decimals= -1; // return NULL
55132 -+ break;
55133 -+ default:
55134 -+ field_length= decimals= -1;
55135 -+ break;
55136 -+ }
55137 -+
55138 -+ if (field_length >= 0)
55139 -+ {
55140 -+ table->field[10]->store((longlong) field_length, TRUE);
55141 -+ table->field[10]->set_notnull();
55142 -+ }
55143 -+ if (decimals >= 0)
55144 -+ {
55145 -+ table->field[11]->store((longlong) decimals, TRUE);
55146 -+ table->field[11]->set_notnull();
55147 -+ }
55148 -+
55149 -+ if (field->has_charset())
55150 -+ {
55151 -+ pos=(uchar*) field->charset()->csname;
55152 -+ table->field[12]->store((const char*) pos,
55153 -+ strlen((const char*) pos), cs);
55154 -+ table->field[12]->set_notnull();
55155 -+ pos=(uchar*) field->charset()->name;
55156 -+ table->field[13]->store((const char*) pos,
55157 -+ strlen((const char*) pos), cs);
55158 -+ table->field[13]->set_notnull();
55159 -+ }
55160 -+ pos=(uchar*) ((field->flags & PRI_KEY_FLAG) ? "PRI" :
55161 -+ (field->flags & UNIQUE_KEY_FLAG) ? "UNI" :
55162 -+ (field->flags & MULTIPLE_KEY_FLAG) ? "MUL":"");
55163 -+ table->field[15]->store((const char*) pos,
55164 -+ strlen((const char*) pos), cs);
55165 -+
55166 -+ if (field->unireg_check == Field::NEXT_NUMBER)
55167 -+ table->field[16]->store(STRING_WITH_LEN("auto_increment"), cs);
55168 -+ if (show_table->timestamp_field == field &&
55169 -+ field->unireg_check != Field::TIMESTAMP_DN_FIELD)
55170 -+ table->field[16]->store(STRING_WITH_LEN("on update CURRENT_TIMESTAMP"),
55171 -+ cs);
55172 -+
55173 -+ table->field[18]->store(field->comment.str, field->comment.length, cs);
55174 -+ if (schema_table_store_record(thd, table))
55175 -+ DBUG_RETURN(1);
55176 -+ }
55177 -+ DBUG_RETURN(0);
55178 -+}
55179 -+
55180 -+
55181 -+
55182 -+int fill_schema_charsets(THD *thd, TABLE_LIST *tables, COND *cond)
55183 -+{
55184 -+ CHARSET_INFO **cs;
55185 -+ const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS;
55186 -+ TABLE *table= tables->table;
55187 -+ CHARSET_INFO *scs= system_charset_info;
55188 -+
55189 -+ for (cs= all_charsets ; cs < all_charsets+255 ; cs++)
55190 -+ {
55191 -+ CHARSET_INFO *tmp_cs= cs[0];
55192 -+ if (tmp_cs && (tmp_cs->state & MY_CS_PRIMARY) &&
55193 -+ (tmp_cs->state & MY_CS_AVAILABLE) &&
55194 -+ !(tmp_cs->state & MY_CS_HIDDEN) &&
55195 -+ !(wild && wild[0] &&
55196 -+ wild_case_compare(scs, tmp_cs->csname,wild)))
55197 -+ {
55198 -+ const char *comment;
55199 -+ restore_record(table, s->default_values);
55200 -+ table->field[0]->store(tmp_cs->csname, strlen(tmp_cs->csname), scs);
55201 -+ table->field[1]->store(tmp_cs->name, strlen(tmp_cs->name), scs);
55202 -+ comment= tmp_cs->comment ? tmp_cs->comment : "";
55203 -+ table->field[2]->store(comment, strlen(comment), scs);
55204 -+ table->field[3]->store((longlong) tmp_cs->mbmaxlen, TRUE);
55205 -+ if (schema_table_store_record(thd, table))
55206 -+ return 1;
55207 -+ }
55208 -+ }
55209 -+ return 0;
55210 -+}
55211 -+
55212 -+
55213 -+static my_bool iter_schema_engines(THD *thd, plugin_ref plugin,
55214 -+ void *ptable)
55215 -+{
55216 -+ TABLE *table= (TABLE *) ptable;
55217 -+ handlerton *hton= plugin_data(plugin, handlerton *);
55218 -+ const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS;
55219 -+ CHARSET_INFO *scs= system_charset_info;
55220 -+ handlerton *default_type= ha_default_handlerton(thd);
55221 -+ DBUG_ENTER("iter_schema_engines");
55222 -+
55223 -+
55224 -+ /* Disabled plugins */
55225 -+ if (plugin_state(plugin) != PLUGIN_IS_READY)
55226 -+ {
55227 -+
55228 -+ struct st_mysql_plugin *plug= plugin_decl(plugin);
55229 -+ if (!(wild && wild[0] &&
55230 -+ wild_case_compare(scs, plug->name,wild)))
55231 -+ {
55232 -+ restore_record(table, s->default_values);
55233 -+ table->field[0]->store(plug->name, strlen(plug->name), scs);
55234 -+ table->field[1]->store(C_STRING_WITH_LEN("NO"), scs);
55235 -+ table->field[2]->store(plug->descr, strlen(plug->descr), scs);
55236 -+ if (schema_table_store_record(thd, table))
55237 -+ DBUG_RETURN(1);
55238 -+ }
55239 -+ DBUG_RETURN(0);
55240 -+ }
55241 -+
55242 -+ if (!(hton->flags & HTON_HIDDEN))
55243 -+ {
55244 -+ LEX_STRING *name= plugin_name(plugin);
55245 -+ if (!(wild && wild[0] &&
55246 -+ wild_case_compare(scs, name->str,wild)))
55247 -+ {
55248 -+ LEX_STRING yesno[2]= {{ C_STRING_WITH_LEN("NO") },
55249 -+ { C_STRING_WITH_LEN("YES") }};
55250 -+ LEX_STRING *tmp;
55251 -+ const char *option_name= show_comp_option_name[(int) hton->state];
55252 -+ restore_record(table, s->default_values);
55253 -+
55254 -+ table->field[0]->store(name->str, name->length, scs);
55255 -+ if (hton->state == SHOW_OPTION_YES && default_type == hton)
55256 -+ option_name= "DEFAULT";
55257 -+ table->field[1]->store(option_name, strlen(option_name), scs);
55258 -+ table->field[2]->store(plugin_decl(plugin)->descr,
55259 -+ strlen(plugin_decl(plugin)->descr), scs);
55260 -+ tmp= &yesno[test(hton->commit)];
55261 -+ table->field[3]->store(tmp->str, tmp->length, scs);
55262 -+ table->field[3]->set_notnull();
55263 -+ tmp= &yesno[test(hton->prepare)];
55264 -+ table->field[4]->store(tmp->str, tmp->length, scs);
55265 -+ table->field[4]->set_notnull();
55266 -+ tmp= &yesno[test(hton->savepoint_set)];
55267 -+ table->field[5]->store(tmp->str, tmp->length, scs);
55268 -+ table->field[5]->set_notnull();
55269 -+
55270 -+ if (schema_table_store_record(thd, table))
55271 -+ DBUG_RETURN(1);
55272 -+ }
55273 -+ }
55274 -+ DBUG_RETURN(0);
55275 -+}
55276 -+
55277 -+int fill_schema_engines(THD *thd, TABLE_LIST *tables, COND *cond)
55278 -+{
55279 -+ DBUG_ENTER("fill_schema_engines");
55280 -+ if (plugin_foreach_with_mask(thd, iter_schema_engines,
55281 -+ MYSQL_STORAGE_ENGINE_PLUGIN,
55282 -+ ~PLUGIN_IS_FREED, tables->table))
55283 -+ DBUG_RETURN(1);
55284 -+ DBUG_RETURN(0);
55285 -+}
55286 -+
55287 -+
55288 -+int fill_schema_collation(THD *thd, TABLE_LIST *tables, COND *cond)
55289 -+{
55290 -+ CHARSET_INFO **cs;
55291 -+ const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS;
55292 -+ TABLE *table= tables->table;
55293 -+ CHARSET_INFO *scs= system_charset_info;
55294 -+ for (cs= all_charsets ; cs < all_charsets+255 ; cs++ )
55295 -+ {
55296 -+ CHARSET_INFO **cl;
55297 -+ CHARSET_INFO *tmp_cs= cs[0];
55298 -+ if (!tmp_cs || !(tmp_cs->state & MY_CS_AVAILABLE) ||
55299 -+ (tmp_cs->state & MY_CS_HIDDEN) ||
55300 -+ !(tmp_cs->state & MY_CS_PRIMARY))
55301 -+ continue;
55302 -+ for (cl= all_charsets; cl < all_charsets+255 ;cl ++)
55303 -+ {
55304 -+ CHARSET_INFO *tmp_cl= cl[0];
55305 -+ if (!tmp_cl || !(tmp_cl->state & MY_CS_AVAILABLE) ||
55306 -+ !my_charset_same(tmp_cs, tmp_cl))
55307 -+ continue;
55308 -+ if (!(wild && wild[0] &&
55309 -+ wild_case_compare(scs, tmp_cl->name,wild)))
55310 -+ {
55311 -+ const char *tmp_buff;
55312 -+ restore_record(table, s->default_values);
55313 -+ table->field[0]->store(tmp_cl->name, strlen(tmp_cl->name), scs);
55314 -+ table->field[1]->store(tmp_cl->csname , strlen(tmp_cl->csname), scs);
55315 -+ table->field[2]->store((longlong) tmp_cl->number, TRUE);
55316 -+ tmp_buff= (tmp_cl->state & MY_CS_PRIMARY) ? "Yes" : "";
55317 -+ table->field[3]->store(tmp_buff, strlen(tmp_buff), scs);
55318 -+ tmp_buff= (tmp_cl->state & MY_CS_COMPILED)? "Yes" : "";
55319 -+ table->field[4]->store(tmp_buff, strlen(tmp_buff), scs);
55320 -+ table->field[5]->store((longlong) tmp_cl->strxfrm_multiply, TRUE);
55321 -+ if (schema_table_store_record(thd, table))
55322 -+ return 1;
55323 -+ }
55324 -+ }
55325 -+ }
55326 -+ return 0;
55327 -+}
55328 -+
55329 -+
55330 -+int fill_schema_coll_charset_app(THD *thd, TABLE_LIST *tables, COND *cond)
55331 -+{
55332 -+ CHARSET_INFO **cs;
55333 -+ TABLE *table= tables->table;
55334 -+ CHARSET_INFO *scs= system_charset_info;
55335 -+ for (cs= all_charsets ; cs < all_charsets+255 ; cs++ )
55336 -+ {
55337 -+ CHARSET_INFO **cl;
55338 -+ CHARSET_INFO *tmp_cs= cs[0];
55339 -+ if (!tmp_cs || !(tmp_cs->state & MY_CS_AVAILABLE) ||
55340 -+ !(tmp_cs->state & MY_CS_PRIMARY))
55341 -+ continue;
55342 -+ for (cl= all_charsets; cl < all_charsets+255 ;cl ++)
55343 -+ {
55344 -+ CHARSET_INFO *tmp_cl= cl[0];
55345 -+ if (!tmp_cl || !(tmp_cl->state & MY_CS_AVAILABLE) ||
55346 -+ !my_charset_same(tmp_cs,tmp_cl))
55347 -+ continue;
55348 -+ restore_record(table, s->default_values);
55349 -+ table->field[0]->store(tmp_cl->name, strlen(tmp_cl->name), scs);
55350 -+ table->field[1]->store(tmp_cl->csname , strlen(tmp_cl->csname), scs);
55351 -+ if (schema_table_store_record(thd, table))
55352 -+ return 1;
55353 -+ }
55354 -+ }
55355 -+ return 0;
55356 -+}
55357 -+
55358 -+
55359 -+static inline void copy_field_as_string(Field *to_field, Field *from_field)
55360 -+{
55361 -+ char buff[MAX_FIELD_WIDTH];
55362 -+ String tmp_str(buff, sizeof(buff), system_charset_info);
55363 -+ from_field->val_str(&tmp_str);
55364 -+ to_field->store(tmp_str.ptr(), tmp_str.length(), system_charset_info);
55365 -+}
55366 -+
55367 -+
55368 -+bool store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table,
55369 -+ const char *wild, bool full_access, const char *sp_user)
55370 -+{
55371 -+ MYSQL_TIME time;
55372 -+ LEX *lex= thd->lex;
55373 -+ CHARSET_INFO *cs= system_charset_info;
55374 -+ char sp_db_buff[NAME_LEN + 1], sp_name_buff[NAME_LEN + 1],
55375 -+ definer_buff[USERNAME_LENGTH + HOSTNAME_LENGTH + 2];
55376 -+ String sp_db(sp_db_buff, sizeof(sp_db_buff), cs);
55377 -+ String sp_name(sp_name_buff, sizeof(sp_name_buff), cs);
55378 -+ String definer(definer_buff, sizeof(definer_buff), cs);
55379 -+
55380 -+ proc_table->field[0]->val_str(&sp_db);
55381 -+ proc_table->field[1]->val_str(&sp_name);
55382 -+ proc_table->field[11]->val_str(&definer);
55383 -+
55384 -+ if (!full_access)
55385 -+ full_access= !strcmp(sp_user, definer.c_ptr_safe());
55386 -+ if (!full_access &&
55387 -+ check_some_routine_access(thd, sp_db.c_ptr_safe(), sp_name.c_ptr_safe(),
55388 -+ proc_table->field[2]->val_int() ==
55389 -+ TYPE_ENUM_PROCEDURE))
55390 -+ return 0;
55391 -+
55392 -+ if ((lex->sql_command == SQLCOM_SHOW_STATUS_PROC &&
55393 -+ proc_table->field[2]->val_int() == TYPE_ENUM_PROCEDURE) ||
55394 -+ (lex->sql_command == SQLCOM_SHOW_STATUS_FUNC &&
55395 -+ proc_table->field[2]->val_int() == TYPE_ENUM_FUNCTION) ||
55396 -+ (sql_command_flags[lex->sql_command] & CF_STATUS_COMMAND) == 0)
55397 -+ {
55398 -+ restore_record(table, s->default_values);
55399 -+ if (!wild || !wild[0] || !wild_compare(sp_name.c_ptr_safe(), wild, 0))
55400 -+ {
55401 -+ int enum_idx= (int) proc_table->field[5]->val_int();
55402 -+ table->field[3]->store(sp_name.ptr(), sp_name.length(), cs);
55403 -+ copy_field_as_string(table->field[0], proc_table->field[3]);
55404 -+ table->field[2]->store(sp_db.ptr(), sp_db.length(), cs);
55405 -+ copy_field_as_string(table->field[4], proc_table->field[2]);
55406 -+ if (proc_table->field[2]->val_int() == TYPE_ENUM_FUNCTION)
55407 -+ {
55408 -+ copy_field_as_string(table->field[5], proc_table->field[9]);
55409 -+ table->field[5]->set_notnull();
55410 -+ }
55411 -+ if (full_access)
55412 -+ {
55413 -+ copy_field_as_string(table->field[7], proc_table->field[19]);
55414 -+ table->field[7]->set_notnull();
55415 -+ }
55416 -+ table->field[6]->store(STRING_WITH_LEN("SQL"), cs);
55417 -+ table->field[10]->store(STRING_WITH_LEN("SQL"), cs);
55418 -+ copy_field_as_string(table->field[11], proc_table->field[6]);
55419 -+ table->field[12]->store(sp_data_access_name[enum_idx].str,
55420 -+ sp_data_access_name[enum_idx].length , cs);
55421 -+ copy_field_as_string(table->field[14], proc_table->field[7]);
55422 -+
55423 -+ bzero((char *)&time, sizeof(time));
55424 -+ ((Field_timestamp *) proc_table->field[12])->get_time(&time);
55425 -+ table->field[15]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
55426 -+ bzero((char *)&time, sizeof(time));
55427 -+ ((Field_timestamp *) proc_table->field[13])->get_time(&time);
55428 -+ table->field[16]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
55429 -+ copy_field_as_string(table->field[17], proc_table->field[14]);
55430 -+ copy_field_as_string(table->field[18], proc_table->field[15]);
55431 -+ table->field[19]->store(definer.ptr(), definer.length(), cs);
55432 -+ copy_field_as_string(table->field[20], proc_table->field[16]);
55433 -+ copy_field_as_string(table->field[21], proc_table->field[17]);
55434 -+ copy_field_as_string(table->field[22], proc_table->field[18]);
55435 -+
55436 -+ return schema_table_store_record(thd, table);
55437 -+ }
55438 -+ }
55439 -+ return 0;
55440 -+}
55441 -+
55442 -+
55443 -+int fill_schema_proc(THD *thd, TABLE_LIST *tables, COND *cond)
55444 -+{
55445 -+ TABLE *proc_table;
55446 -+ TABLE_LIST proc_tables;
55447 -+ const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS;
55448 -+ int res= 0;
55449 -+ TABLE *table= tables->table;
55450 -+ bool full_access;
55451 -+ char definer[USER_HOST_BUFF_SIZE];
55452 -+ Open_tables_state open_tables_state_backup;
55453 -+ DBUG_ENTER("fill_schema_proc");
55454 -+
55455 -+ strxmov(definer, thd->security_ctx->priv_user, "@",
55456 -+ thd->security_ctx->priv_host, NullS);
55457 -+ /* We use this TABLE_LIST instance only for checking of privileges. */
55458 -+ bzero((char*) &proc_tables,sizeof(proc_tables));
55459 -+ proc_tables.db= (char*) "mysql";
55460 -+ proc_tables.db_length= 5;
55461 -+ proc_tables.table_name= proc_tables.alias= (char*) "proc";
55462 -+ proc_tables.table_name_length= 4;
55463 -+ proc_tables.lock_type= TL_READ;
55464 -+ full_access= !check_table_access(thd, SELECT_ACL, &proc_tables, 1, TRUE);
55465 -+ if (!(proc_table= open_proc_table_for_read(thd, &open_tables_state_backup)))
55466 -+ {
55467 -+ DBUG_RETURN(1);
55468 -+ }
55469 -+ proc_table->file->ha_index_init(0, 1);
55470 -+ if ((res= proc_table->file->index_first(proc_table->record[0])))
55471 -+ {
55472 -+ res= (res == HA_ERR_END_OF_FILE) ? 0 : 1;
55473 -+ goto err;
55474 -+ }
55475 -+ if (store_schema_proc(thd, table, proc_table, wild, full_access, definer))
55476 -+ {
55477 -+ res= 1;
55478 -+ goto err;
55479 -+ }
55480 -+ while (!proc_table->file->index_next(proc_table->record[0]))
55481 -+ {
55482 -+ if (store_schema_proc(thd, table, proc_table, wild, full_access, definer))
55483 -+ {
55484 -+ res= 1;
55485 -+ goto err;
55486 -+ }
55487 -+ }
55488 -+
55489 -+err:
55490 -+ proc_table->file->ha_index_end();
55491 -+ close_system_tables(thd, &open_tables_state_backup);
55492 -+ DBUG_RETURN(res);
55493 -+}
55494 -+
55495 -+
55496 -+static int get_schema_stat_record(THD *thd, TABLE_LIST *tables,
55497 -+ TABLE *table, bool res,
55498 -+ LEX_STRING *db_name,
55499 -+ LEX_STRING *table_name)
55500 -+{
55501 -+ CHARSET_INFO *cs= system_charset_info;
55502 -+ DBUG_ENTER("get_schema_stat_record");
55503 -+ if (res)
55504 -+ {
55505 -+ if (thd->lex->sql_command != SQLCOM_SHOW_KEYS)
55506 -+ {
55507 -+ /*
55508 -+ I.e. we are in SELECT FROM INFORMATION_SCHEMA.STATISTICS
55509 -+ rather than in SHOW KEYS
55510 -+ */
55511 -+ if (thd->is_error())
55512 -+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
55513 -+ thd->main_da.sql_errno(), thd->main_da.message());
55514 -+ thd->clear_error();
55515 -+ res= 0;
55516 -+ }
55517 -+ DBUG_RETURN(res);
55518 -+ }
55519 -+ else if (!tables->view)
55520 -+ {
55521 -+ TABLE *show_table= tables->table;
55522 -+ KEY *key_info=show_table->s->key_info;
55523 -+ if (show_table->file)
55524 -+ show_table->file->info(HA_STATUS_VARIABLE |
55525 -+ HA_STATUS_NO_LOCK |
55526 -+ HA_STATUS_TIME);
55527 -+ for (uint i=0 ; i < show_table->s->keys ; i++,key_info++)
55528 -+ {
55529 -+ KEY_PART_INFO *key_part= key_info->key_part;
55530 -+ const char *str;
55531 -+ for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
55532 -+ {
55533 -+ restore_record(table, s->default_values);
55534 -+ table->field[1]->store(db_name->str, db_name->length, cs);
55535 -+ table->field[2]->store(table_name->str, table_name->length, cs);
55536 -+ table->field[3]->store((longlong) ((key_info->flags &
55537 -+ HA_NOSAME) ? 0 : 1), TRUE);
55538 -+ table->field[4]->store(db_name->str, db_name->length, cs);
55539 -+ table->field[5]->store(key_info->name, strlen(key_info->name), cs);
55540 -+ table->field[6]->store((longlong) (j+1), TRUE);
55541 -+ str=(key_part->field ? key_part->field->field_name :
55542 -+ "?unknown field?");
55543 -+ table->field[7]->store(str, strlen(str), cs);
55544 -+ if (show_table->file)
55545 -+ {
55546 -+ if (show_table->file->index_flags(i, j, 0) & HA_READ_ORDER)
55547 -+ {
55548 -+ table->field[8]->store(((key_part->key_part_flag &
55549 -+ HA_REVERSE_SORT) ?
55550 -+ "D" : "A"), 1, cs);
55551 -+ table->field[8]->set_notnull();
55552 -+ }
55553 -+ KEY *key=show_table->key_info+i;
55554 -+ if (key->rec_per_key[j])
55555 -+ {
55556 -+ ha_rows records=(show_table->file->stats.records /
55557 -+ key->rec_per_key[j]);
55558 -+ table->field[9]->store((longlong) records, TRUE);
55559 -+ table->field[9]->set_notnull();
55560 -+ }
55561 -+ str= show_table->file->index_type(i);
55562 -+ table->field[13]->store(str, strlen(str), cs);
55563 -+ }
55564 -+ if (!(key_info->flags & HA_FULLTEXT) &&
55565 -+ (key_part->field &&
55566 -+ key_part->length !=
55567 -+ show_table->s->field[key_part->fieldnr-1]->key_length()))
55568 -+ {
55569 -+ table->field[10]->store((longlong) key_part->length /
55570 -+ key_part->field->charset()->mbmaxlen, TRUE);
55571 -+ table->field[10]->set_notnull();
55572 -+ }
55573 -+ uint flags= key_part->field ? key_part->field->flags : 0;
55574 -+ const char *pos=(char*) ((flags & NOT_NULL_FLAG) ? "" : "YES");
55575 -+ table->field[12]->store(pos, strlen(pos), cs);
55576 -+ if (!show_table->s->keys_in_use.is_set(i))
55577 -+ table->field[14]->store(STRING_WITH_LEN("disabled"), cs);
55578 -+ else
55579 -+ table->field[14]->store("", 0, cs);
55580 -+ table->field[14]->set_notnull();
55581 -+ if (schema_table_store_record(thd, table))
55582 -+ DBUG_RETURN(1);
55583 -+ }
55584 -+ }
55585 -+ }
55586 -+ DBUG_RETURN(res);
55587 -+}
55588 -+
55589 -+
55590 -+static int get_schema_views_record(THD *thd, TABLE_LIST *tables,
55591 -+ TABLE *table, bool res,
55592 -+ LEX_STRING *db_name,
55593 -+ LEX_STRING *table_name)
55594 -+{
55595 -+ CHARSET_INFO *cs= system_charset_info;
55596 -+ DBUG_ENTER("get_schema_views_record");
55597 -+ LEX_STRING *tmp_db_name, *tmp_table_name;
55598 -+ char definer[USER_HOST_BUFF_SIZE];
55599 -+ uint definer_len;
55600 -+ bool updatable_view;
55601 -+ /*
55602 -+ if SELECT FROM I_S.VIEWS uses only fields
55603 -+ which have OPEN_FRM_ONLY flag then 'tables'
55604 -+ structure is zeroed and only tables->view is set.
55605 -+ (see fill_schema_table_from_frm() function).
55606 -+ So we should disable other fields filling.
55607 -+ */
55608 -+ bool only_share= !tables->definer.user.str;
55609 -+
55610 -+ if (tables->view)
55611 -+ {
55612 -+ Security_context *sctx= thd->security_ctx;
55613 -+ if (!only_share && !tables->allowed_show)
55614 -+ {
55615 -+ if (!my_strcasecmp(system_charset_info, tables->definer.user.str,
55616 -+ sctx->priv_user) &&
55617 -+ !my_strcasecmp(system_charset_info, tables->definer.host.str,
55618 -+ sctx->priv_host))
55619 -+ tables->allowed_show= TRUE;
55620 -+#ifndef NO_EMBEDDED_ACCESS_CHECKS
55621 -+ else
55622 -+ {
55623 -+ if ((thd->col_access & (SHOW_VIEW_ACL|SELECT_ACL)) ==
55624 -+ (SHOW_VIEW_ACL|SELECT_ACL))
55625 -+ tables->allowed_show= TRUE;
55626 -+ else
55627 -+ {
55628 -+ TABLE_LIST table_list;
55629 -+ uint view_access;
55630 -+ memset(&table_list, 0, sizeof(table_list));
55631 -+ table_list.db= tables->view_db.str;
55632 -+ table_list.table_name= tables->view_name.str;
55633 -+ table_list.grant.privilege= thd->col_access;
55634 -+ view_access= get_table_grant(thd, &table_list);
55635 -+ if ((view_access & (SHOW_VIEW_ACL|SELECT_ACL)) ==
55636 -+ (SHOW_VIEW_ACL|SELECT_ACL))
55637 -+ tables->allowed_show= TRUE;
55638 -+ }
55639 -+ }
55640 -+#endif
55641 -+ }
55642 -+ restore_record(table, s->default_values);
55643 -+ tmp_db_name= &tables->view_db;
55644 -+ tmp_table_name= &tables->view_name;
55645 -+ if (only_share)
55646 -+ {
55647 -+ tmp_db_name= db_name;
55648 -+ tmp_table_name= table_name;
55649 -+ }
55650 -+ table->field[1]->store(tmp_db_name->str, tmp_db_name->length, cs);
55651 -+ table->field[2]->store(tmp_table_name->str, tmp_table_name->length, cs);
55652 -+ if (!only_share)
55653 -+ {
55654 -+ if (tables->allowed_show)
55655 -+ {
55656 -+ table->field[3]->store(tables->view_body_utf8.str,
55657 -+ tables->view_body_utf8.length,
55658 -+ cs);
55659 -+ }
55660 -+
55661 -+ if (tables->with_check != VIEW_CHECK_NONE)
55662 -+ {
55663 -+ if (tables->with_check == VIEW_CHECK_LOCAL)
55664 -+ table->field[4]->store(STRING_WITH_LEN("LOCAL"), cs);
55665 -+ else
55666 -+ table->field[4]->store(STRING_WITH_LEN("CASCADED"), cs);
55667 -+ }
55668 -+ else
55669 -+ table->field[4]->store(STRING_WITH_LEN("NONE"), cs);
55670 -+
55671 -+ updatable_view= 0;
55672 -+ if (tables->algorithm != VIEW_ALGORITHM_TMPTABLE)
55673 -+ {
55674 -+ /*
55675 -+ We should use tables->view->select_lex.item_list here and
55676 -+ can not use Field_iterator_view because the view always uses
55677 -+ temporary algorithm during opening for I_S and
55678 -+ TABLE_LIST fields 'field_translation' & 'field_translation_end'
55679 -+ are uninitialized is this case.
55680 -+ */
55681 -+ List<Item> *fields= &tables->view->select_lex.item_list;
55682 -+ List_iterator<Item> it(*fields);
55683 -+ Item *item;
55684 -+ Item_field *field;
55685 -+ /*
55686 -+ check that at least one column in view is updatable
55687 -+ */
55688 -+ while ((item= it++))
55689 -+ {
55690 -+ if ((field= item->filed_for_view_update()) && field->field &&
55691 -+ !field->field->table->pos_in_table_list->schema_table)
55692 -+ {
55693 -+ updatable_view= 1;
55694 -+ break;
55695 -+ }
55696 -+ }
55697 -+ if (updatable_view && !tables->view->can_be_merged())
55698 -+ updatable_view= 0;
55699 -+ }
55700 -+ if (updatable_view)
55701 -+ table->field[5]->store(STRING_WITH_LEN("YES"), cs);
55702 -+ else
55703 -+ table->field[5]->store(STRING_WITH_LEN("NO"), cs);
55704 -+ definer_len= (strxmov(definer, tables->definer.user.str, "@",
55705 -+ tables->definer.host.str, NullS) - definer);
55706 -+ table->field[6]->store(definer, definer_len, cs);
55707 -+ if (tables->view_suid)
55708 -+ table->field[7]->store(STRING_WITH_LEN("DEFINER"), cs);
55709 -+ else
55710 -+ table->field[7]->store(STRING_WITH_LEN("INVOKER"), cs);
55711 -+
55712 -+ table->field[8]->store(tables->view_creation_ctx->get_client_cs()->csname,
55713 -+ strlen(tables->view_creation_ctx->
55714 -+ get_client_cs()->csname), cs);
55715 -+
55716 -+ table->field[9]->store(tables->view_creation_ctx->
55717 -+ get_connection_cl()->name,
55718 -+ strlen(tables->view_creation_ctx->
55719 -+ get_connection_cl()->name), cs);
55720 -+ }
55721 -+
55722 -+ if (schema_table_store_record(thd, table))
55723 -+ DBUG_RETURN(1);
55724 -+ if (res && thd->is_error())
55725 -+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
55726 -+ thd->main_da.sql_errno(), thd->main_da.message());
55727 -+ }
55728 -+ if (res)
55729 -+ thd->clear_error();
55730 -+ DBUG_RETURN(0);
55731 -+}
55732 -+
55733 -+
55734 -+bool store_constraints(THD *thd, TABLE *table, LEX_STRING *db_name,
55735 -+ LEX_STRING *table_name, const char *key_name,
55736 -+ uint key_len, const char *con_type, uint con_len)
55737 -+{
55738 -+ CHARSET_INFO *cs= system_charset_info;
55739 -+ restore_record(table, s->default_values);
55740 -+ table->field[1]->store(db_name->str, db_name->length, cs);
55741 -+ table->field[2]->store(key_name, key_len, cs);
55742 -+ table->field[3]->store(db_name->str, db_name->length, cs);
55743 -+ table->field[4]->store(table_name->str, table_name->length, cs);
55744 -+ table->field[5]->store(con_type, con_len, cs);
55745 -+ return schema_table_store_record(thd, table);
55746 -+}
55747 -+
55748 -+
55749 -+static int get_schema_constraints_record(THD *thd, TABLE_LIST *tables,
55750 -+ TABLE *table, bool res,
55751 -+ LEX_STRING *db_name,
55752 -+ LEX_STRING *table_name)
55753 -+{
55754 -+ DBUG_ENTER("get_schema_constraints_record");
55755 -+ if (res)
55756 -+ {
55757 -+ if (thd->is_error())
55758 -+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
55759 -+ thd->main_da.sql_errno(), thd->main_da.message());
55760 -+ thd->clear_error();
55761 -+ DBUG_RETURN(0);
55762 -+ }
55763 -+ else if (!tables->view)
55764 -+ {
55765 -+ List<FOREIGN_KEY_INFO> f_key_list;
55766 -+ TABLE *show_table= tables->table;
55767 -+ KEY *key_info=show_table->key_info;
55768 -+ uint primary_key= show_table->s->primary_key;
55769 -+
55770 -+ // This is not needed since no statistics are displayed.
55771 -+ // show_table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK | HA_STATUS_TIME);
55772 -+
55773 -+ for (uint i=0 ; i < show_table->s->keys ; i++, key_info++)
55774 -+ {
55775 -+ if (i != primary_key && !(key_info->flags & HA_NOSAME))
55776 -+ continue;
55777 -+
55778 -+ if (i == primary_key && !strcmp(key_info->name, primary_key_name))
55779 -+ {
55780 -+ if (store_constraints(thd, table, db_name, table_name, key_info->name,
55781 -+ strlen(key_info->name),
55782 -+ STRING_WITH_LEN("PRIMARY KEY")))
55783 -+ DBUG_RETURN(1);
55784 -+ }
55785 -+ else if (key_info->flags & HA_NOSAME)
55786 -+ {
55787 -+ if (store_constraints(thd, table, db_name, table_name, key_info->name,
55788 -+ strlen(key_info->name),
55789 -+ STRING_WITH_LEN("UNIQUE")))
55790 -+ DBUG_RETURN(1);
55791 -+ }
55792 -+ }
55793 -+
55794 -+ show_table->file->get_foreign_key_list(thd, &f_key_list);
55795 -+ FOREIGN_KEY_INFO *f_key_info;
55796 -+ List_iterator_fast<FOREIGN_KEY_INFO> it(f_key_list);
55797 -+ while ((f_key_info=it++))
55798 -+ {
55799 -+ if (store_constraints(thd, table, db_name, table_name,
55800 -+ f_key_info->forein_id->str,
55801 -+ strlen(f_key_info->forein_id->str),
55802 -+ "FOREIGN KEY", 11))
55803 -+ DBUG_RETURN(1);
55804 -+ }
55805 -+ }
55806 -+ DBUG_RETURN(res);
55807 -+}
55808 -+
55809 -+
55810 -+static bool store_trigger(THD *thd, TABLE *table, LEX_STRING *db_name,
55811 -+ LEX_STRING *table_name, LEX_STRING *trigger_name,
55812 -+ enum trg_event_type event,
55813 -+ enum trg_action_time_type timing,
55814 -+ LEX_STRING *trigger_stmt,
55815 -+ ulong sql_mode,
55816 -+ LEX_STRING *definer_buffer,
55817 -+ LEX_STRING *client_cs_name,
55818 -+ LEX_STRING *connection_cl_name,
55819 -+ LEX_STRING *db_cl_name)
55820 -+{
55821 -+ CHARSET_INFO *cs= system_charset_info;
55822 -+ LEX_STRING sql_mode_rep;
55823 -+
55824 -+ restore_record(table, s->default_values);
55825 -+ table->field[1]->store(db_name->str, db_name->length, cs);
55826 -+ table->field[2]->store(trigger_name->str, trigger_name->length, cs);
55827 -+ table->field[3]->store(trg_event_type_names[event].str,
55828 -+ trg_event_type_names[event].length, cs);
55829 -+ table->field[5]->store(db_name->str, db_name->length, cs);
55830 -+ table->field[6]->store(table_name->str, table_name->length, cs);
55831 -+ table->field[9]->store(trigger_stmt->str, trigger_stmt->length, cs);
55832 -+ table->field[10]->store(STRING_WITH_LEN("ROW"), cs);
55833 -+ table->field[11]->store(trg_action_time_type_names[timing].str,
55834 -+ trg_action_time_type_names[timing].length, cs);
55835 -+ table->field[14]->store(STRING_WITH_LEN("OLD"), cs);
55836 -+ table->field[15]->store(STRING_WITH_LEN("NEW"), cs);
55837 -+
55838 -+ sys_var_thd_sql_mode::symbolic_mode_representation(thd, sql_mode,
55839 -+ &sql_mode_rep);
55840 -+ table->field[17]->store(sql_mode_rep.str, sql_mode_rep.length, cs);
55841 -+ table->field[18]->store(definer_buffer->str, definer_buffer->length, cs);
55842 -+ table->field[19]->store(client_cs_name->str, client_cs_name->length, cs);
55843 -+ table->field[20]->store(connection_cl_name->str,
55844 -+ connection_cl_name->length, cs);
55845 -+ table->field[21]->store(db_cl_name->str, db_cl_name->length, cs);
55846 -+
55847 -+ return schema_table_store_record(thd, table);
55848 -+}
55849 -+
55850 -+
55851 -+static int get_schema_triggers_record(THD *thd, TABLE_LIST *tables,
55852 -+ TABLE *table, bool res,
55853 -+ LEX_STRING *db_name,
55854 -+ LEX_STRING *table_name)
55855 -+{
55856 -+ DBUG_ENTER("get_schema_triggers_record");
55857 -+ /*
55858 -+ res can be non zero value when processed table is a view or
55859 -+ error happened during opening of processed table.
55860 -+ */
55861 -+ if (res)
55862 -+ {
55863 -+ if (thd->is_error())
55864 -+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
55865 -+ thd->main_da.sql_errno(), thd->main_da.message());
55866 -+ thd->clear_error();
55867 -+ DBUG_RETURN(0);
55868 -+ }
55869 -+ if (!tables->view && tables->table->triggers)
55870 -+ {
55871 -+ Table_triggers_list *triggers= tables->table->triggers;
55872 -+ int event, timing;
55873 -+
55874 -+ if (check_table_access(thd, TRIGGER_ACL, tables, 1, TRUE))
55875 -+ goto ret;
55876 -+
55877 -+ for (event= 0; event < (int)TRG_EVENT_MAX; event++)
55878 -+ {
55879 -+ for (timing= 0; timing < (int)TRG_ACTION_MAX; timing++)
55880 -+ {
55881 -+ LEX_STRING trigger_name;
55882 -+ LEX_STRING trigger_stmt;
55883 -+ ulong sql_mode;
55884 -+ char definer_holder[USER_HOST_BUFF_SIZE];
55885 -+ LEX_STRING definer_buffer;
55886 -+ LEX_STRING client_cs_name;
55887 -+ LEX_STRING connection_cl_name;
55888 -+ LEX_STRING db_cl_name;
55889 -+
55890 -+ definer_buffer.str= definer_holder;
55891 -+ if (triggers->get_trigger_info(thd, (enum trg_event_type) event,
55892 -+ (enum trg_action_time_type)timing,
55893 -+ &trigger_name, &trigger_stmt,
55894 -+ &sql_mode,
55895 -+ &definer_buffer,
55896 -+ &client_cs_name,
55897 -+ &connection_cl_name,
55898 -+ &db_cl_name))
55899 -+ continue;
55900 -+
55901 -+ if (store_trigger(thd, table, db_name, table_name, &trigger_name,
55902 -+ (enum trg_event_type) event,
55903 -+ (enum trg_action_time_type) timing, &trigger_stmt,
55904 -+ sql_mode,
55905 -+ &definer_buffer,
55906 -+ &client_cs_name,
55907 -+ &connection_cl_name,
55908 -+ &db_cl_name))
55909 -+ DBUG_RETURN(1);
55910 -+ }
55911 -+ }
55912 -+ }
55913 -+ret:
55914 -+ DBUG_RETURN(0);
55915 -+}
55916 -+
55917 -+
55918 -+void store_key_column_usage(TABLE *table, LEX_STRING *db_name,
55919 -+ LEX_STRING *table_name, const char *key_name,
55920 -+ uint key_len, const char *con_type, uint con_len,
55921 -+ longlong idx)
55922 -+{
55923 -+ CHARSET_INFO *cs= system_charset_info;
55924 -+ table->field[1]->store(db_name->str, db_name->length, cs);
55925 -+ table->field[2]->store(key_name, key_len, cs);
55926 -+ table->field[4]->store(db_name->str, db_name->length, cs);
55927 -+ table->field[5]->store(table_name->str, table_name->length, cs);
55928 -+ table->field[6]->store(con_type, con_len, cs);
55929 -+ table->field[7]->store((longlong) idx, TRUE);
55930 -+}
55931 -+
55932 -+
55933 -+static int get_schema_key_column_usage_record(THD *thd,
55934 -+ TABLE_LIST *tables,
55935 -+ TABLE *table, bool res,
55936 -+ LEX_STRING *db_name,
55937 -+ LEX_STRING *table_name)
55938 -+{
55939 -+ DBUG_ENTER("get_schema_key_column_usage_record");
55940 -+ if (res)
55941 -+ {
55942 -+ if (thd->is_error())
55943 -+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
55944 -+ thd->main_da.sql_errno(), thd->main_da.message());
55945 -+ thd->clear_error();
55946 -+ DBUG_RETURN(0);
55947 -+ }
55948 -+ else if (!tables->view)
55949 -+ {
55950 -+ List<FOREIGN_KEY_INFO> f_key_list;
55951 -+ TABLE *show_table= tables->table;
55952 -+ KEY *key_info=show_table->key_info;
55953 -+ uint primary_key= show_table->s->primary_key;
55954 -+
55955 -+ // This is not needed since no statistics are displayed.
55956 -+ // show_table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK | HA_STATUS_TIME);
55957 -+
55958 -+ for (uint i=0 ; i < show_table->s->keys ; i++, key_info++)
55959 -+ {
55960 -+ if (i != primary_key && !(key_info->flags & HA_NOSAME))
55961 -+ continue;
55962 -+ uint f_idx= 0;
55963 -+ KEY_PART_INFO *key_part= key_info->key_part;
55964 -+ for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
55965 -+ {
55966 -+ if (key_part->field)
55967 -+ {
55968 -+ f_idx++;
55969 -+ restore_record(table, s->default_values);
55970 -+ store_key_column_usage(table, db_name, table_name,
55971 -+ key_info->name,
55972 -+ strlen(key_info->name),
55973 -+ key_part->field->field_name,
55974 -+ strlen(key_part->field->field_name),
55975 -+ (longlong) f_idx);
55976 -+ if (schema_table_store_record(thd, table))
55977 -+ DBUG_RETURN(1);
55978 -+ }
55979 -+ }
55980 -+ }
55981 -+
55982 -+ show_table->file->get_foreign_key_list(thd, &f_key_list);
55983 -+ FOREIGN_KEY_INFO *f_key_info;
55984 -+ List_iterator_fast<FOREIGN_KEY_INFO> fkey_it(f_key_list);
55985 -+ while ((f_key_info= fkey_it++))
55986 -+ {
55987 -+ LEX_STRING *f_info;
55988 -+ LEX_STRING *r_info;
55989 -+ List_iterator_fast<LEX_STRING> it(f_key_info->foreign_fields),
55990 -+ it1(f_key_info->referenced_fields);
55991 -+ uint f_idx= 0;
55992 -+ while ((f_info= it++))
55993 -+ {
55994 -+ r_info= it1++;
55995 -+ f_idx++;
55996 -+ restore_record(table, s->default_values);
55997 -+ store_key_column_usage(table, db_name, table_name,
55998 -+ f_key_info->forein_id->str,
55999 -+ f_key_info->forein_id->length,
56000 -+ f_info->str, f_info->length,
56001 -+ (longlong) f_idx);
56002 -+ table->field[8]->store((longlong) f_idx, TRUE);
56003 -+ table->field[8]->set_notnull();
56004 -+ table->field[9]->store(f_key_info->referenced_db->str,
56005 -+ f_key_info->referenced_db->length,
56006 -+ system_charset_info);
56007 -+ table->field[9]->set_notnull();
56008 -+ table->field[10]->store(f_key_info->referenced_table->str,
56009 -+ f_key_info->referenced_table->length,
56010 -+ system_charset_info);
56011 -+ table->field[10]->set_notnull();
56012 -+ table->field[11]->store(r_info->str, r_info->length,
56013 -+ system_charset_info);
56014 -+ table->field[11]->set_notnull();
56015 -+ if (schema_table_store_record(thd, table))
56016 -+ DBUG_RETURN(1);
56017 -+ }
56018 -+ }
56019 -+ }
56020 -+ DBUG_RETURN(res);
56021 -+}
56022 -+
56023 -+
56024 -+#ifdef WITH_PARTITION_STORAGE_ENGINE
56025 -+static void collect_partition_expr(List<char> &field_list, String *str)
56026 -+{
56027 -+ List_iterator<char> part_it(field_list);
56028 -+ ulong no_fields= field_list.elements;
56029 -+ const char *field_str;
56030 -+ str->length(0);
56031 -+ while ((field_str= part_it++))
56032 -+ {
56033 -+ str->append(field_str);
56034 -+ if (--no_fields != 0)
56035 -+ str->append(",");
56036 -+ }
56037 -+ return;
56038 -+}
56039 -+#endif
56040 -+
56041 -+
56042 -+static void store_schema_partitions_record(THD *thd, TABLE *schema_table,
56043 -+ TABLE *showing_table,
56044 -+ partition_element *part_elem,
56045 -+ handler *file, uint part_id)
56046 -+{
56047 -+ TABLE* table= schema_table;
56048 -+ CHARSET_INFO *cs= system_charset_info;
56049 -+ PARTITION_INFO stat_info;
56050 -+ MYSQL_TIME time;
56051 -+ file->get_dynamic_partition_info(&stat_info, part_id);
56052 -+ table->field[12]->store((longlong) stat_info.records, TRUE);
56053 -+ table->field[13]->store((longlong) stat_info.mean_rec_length, TRUE);
56054 -+ table->field[14]->store((longlong) stat_info.data_file_length, TRUE);
56055 -+ if (stat_info.max_data_file_length)
56056 -+ {
56057 -+ table->field[15]->store((longlong) stat_info.max_data_file_length, TRUE);
56058 -+ table->field[15]->set_notnull();
56059 -+ }
56060 -+ table->field[16]->store((longlong) stat_info.index_file_length, TRUE);
56061 -+ table->field[17]->store((longlong) stat_info.delete_length, TRUE);
56062 -+ if (stat_info.create_time)
56063 -+ {
56064 -+ thd->variables.time_zone->gmt_sec_to_TIME(&time,
56065 -+ (my_time_t)stat_info.create_time);
56066 -+ table->field[18]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
56067 -+ table->field[18]->set_notnull();
56068 -+ }
56069 -+ if (stat_info.update_time)
56070 -+ {
56071 -+ thd->variables.time_zone->gmt_sec_to_TIME(&time,
56072 -+ (my_time_t)stat_info.update_time);
56073 -+ table->field[19]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
56074 -+ table->field[19]->set_notnull();
56075 -+ }
56076 -+ if (stat_info.check_time)
56077 -+ {
56078 -+ thd->variables.time_zone->gmt_sec_to_TIME(&time,
56079 -+ (my_time_t)stat_info.check_time);
56080 -+ table->field[20]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
56081 -+ table->field[20]->set_notnull();
56082 -+ }
56083 -+ if (file->ha_table_flags() & (ulong) HA_HAS_CHECKSUM)
56084 -+ {
56085 -+ table->field[21]->store((longlong) stat_info.check_sum, TRUE);
56086 -+ table->field[21]->set_notnull();
56087 -+ }
56088 -+ if (part_elem)
56089 -+ {
56090 -+ if (part_elem->part_comment)
56091 -+ table->field[22]->store(part_elem->part_comment,
56092 -+ strlen(part_elem->part_comment), cs);
56093 -+ else
56094 -+ table->field[22]->store(STRING_WITH_LEN(""), cs);
56095 -+ if (part_elem->nodegroup_id != UNDEF_NODEGROUP)
56096 -+ table->field[23]->store((longlong) part_elem->nodegroup_id, TRUE);
56097 -+ else
56098 -+ table->field[23]->store(STRING_WITH_LEN("default"), cs);
56099 -+
56100 -+ table->field[24]->set_notnull();
56101 -+ if (part_elem->tablespace_name)
56102 -+ table->field[24]->store(part_elem->tablespace_name,
56103 -+ strlen(part_elem->tablespace_name), cs);
56104 -+ else
56105 -+ {
56106 -+ char *ts= showing_table->file->get_tablespace_name(thd,0,0);
56107 -+ if(ts)
56108 -+ {
56109 -+ table->field[24]->store(ts, strlen(ts), cs);
56110 -+ my_free(ts, MYF(0));
56111 -+ }
56112 -+ else
56113 -+ table->field[24]->set_null();
56114 -+ }
56115 -+ }
56116 -+ return;
56117 -+}
56118 -+
56119 -+
56120 -+static int get_schema_partitions_record(THD *thd, TABLE_LIST *tables,
56121 -+ TABLE *table, bool res,
56122 -+ LEX_STRING *db_name,
56123 -+ LEX_STRING *table_name)
56124 -+{
56125 -+ CHARSET_INFO *cs= system_charset_info;
56126 -+ char buff[61];
56127 -+ String tmp_res(buff, sizeof(buff), cs);
56128 -+ String tmp_str;
56129 -+ TABLE *show_table= tables->table;
56130 -+ handler *file;
56131 -+#ifdef WITH_PARTITION_STORAGE_ENGINE
56132 -+ partition_info *part_info;
56133 -+#endif
56134 -+ DBUG_ENTER("get_schema_partitions_record");
56135 -+
56136 -+ if (res)
56137 -+ {
56138 -+ if (thd->is_error())
56139 -+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
56140 -+ thd->main_da.sql_errno(), thd->main_da.message());
56141 -+ thd->clear_error();
56142 -+ DBUG_RETURN(0);
56143 -+ }
56144 -+ file= show_table->file;
56145 -+#ifdef WITH_PARTITION_STORAGE_ENGINE
56146 -+ part_info= show_table->part_info;
56147 -+ if (part_info)
56148 -+ {
56149 -+ partition_element *part_elem;
56150 -+ List_iterator<partition_element> part_it(part_info->partitions);
56151 -+ uint part_pos= 0, part_id= 0;
56152 -+
56153 -+ restore_record(table, s->default_values);
56154 -+ table->field[1]->store(db_name->str, db_name->length, cs);
56155 -+ table->field[2]->store(table_name->str, table_name->length, cs);
56156 -+
56157 -+
56158 -+ /* Partition method*/
56159 -+ switch (part_info->part_type) {
56160 -+ case RANGE_PARTITION:
56161 -+ table->field[7]->store(partition_keywords[PKW_RANGE].str,
56162 -+ partition_keywords[PKW_RANGE].length, cs);
56163 -+ break;
56164 -+ case LIST_PARTITION:
56165 -+ table->field[7]->store(partition_keywords[PKW_LIST].str,
56166 -+ partition_keywords[PKW_LIST].length, cs);
56167 -+ break;
56168 -+ case HASH_PARTITION:
56169 -+ tmp_res.length(0);
56170 -+ if (part_info->linear_hash_ind)
56171 -+ tmp_res.append(partition_keywords[PKW_LINEAR].str,
56172 -+ partition_keywords[PKW_LINEAR].length);
56173 -+ if (part_info->list_of_part_fields)
56174 -+ tmp_res.append(partition_keywords[PKW_KEY].str,
56175 -+ partition_keywords[PKW_KEY].length);
56176 -+ else
56177 -+ tmp_res.append(partition_keywords[PKW_HASH].str,
56178 -+ partition_keywords[PKW_HASH].length);
56179 -+ table->field[7]->store(tmp_res.ptr(), tmp_res.length(), cs);
56180 -+ break;
56181 -+ default:
56182 -+ DBUG_ASSERT(0);
56183 -+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
56184 -+ current_thd->fatal_error();
56185 -+ DBUG_RETURN(1);
56186 -+ }
56187 -+ table->field[7]->set_notnull();
56188 -+
56189 -+ /* Partition expression */
56190 -+ if (part_info->part_expr)
56191 -+ {
56192 -+ table->field[9]->store(part_info->part_func_string,
56193 -+ part_info->part_func_len, cs);
56194 -+ }
56195 -+ else if (part_info->list_of_part_fields)
56196 -+ {
56197 -+ collect_partition_expr(part_info->part_field_list, &tmp_str);
56198 -+ table->field[9]->store(tmp_str.ptr(), tmp_str.length(), cs);
56199 -+ }
56200 -+ table->field[9]->set_notnull();
56201 -+
56202 -+ if (part_info->is_sub_partitioned())
56203 -+ {
56204 -+ /* Subpartition method */
56205 -+ tmp_res.length(0);
56206 -+ if (part_info->linear_hash_ind)
56207 -+ tmp_res.append(partition_keywords[PKW_LINEAR].str,
56208 -+ partition_keywords[PKW_LINEAR].length);
56209 -+ if (part_info->list_of_subpart_fields)
56210 -+ tmp_res.append(partition_keywords[PKW_KEY].str,
56211 -+ partition_keywords[PKW_KEY].length);
56212 -+ else
56213 -+ tmp_res.append(partition_keywords[PKW_HASH].str,
56214 -+ partition_keywords[PKW_HASH].length);
56215 -+ table->field[8]->store(tmp_res.ptr(), tmp_res.length(), cs);
56216 -+ table->field[8]->set_notnull();
56217 -+
56218 -+ /* Subpartition expression */
56219 -+ if (part_info->subpart_expr)
56220 -+ {
56221 -+ table->field[10]->store(part_info->subpart_func_string,
56222 -+ part_info->subpart_func_len, cs);
56223 -+ }
56224 -+ else if (part_info->list_of_subpart_fields)
56225 -+ {
56226 -+ collect_partition_expr(part_info->subpart_field_list, &tmp_str);
56227 -+ table->field[10]->store(tmp_str.ptr(), tmp_str.length(), cs);
56228 -+ }
56229 -+ table->field[10]->set_notnull();
56230 -+ }
56231 -+
56232 -+ while ((part_elem= part_it++))
56233 -+ {
56234 -+ table->field[3]->store(part_elem->partition_name,
56235 -+ strlen(part_elem->partition_name), cs);
56236 -+ table->field[3]->set_notnull();
56237 -+ /* PARTITION_ORDINAL_POSITION */
56238 -+ table->field[5]->store((longlong) ++part_pos, TRUE);
56239 -+ table->field[5]->set_notnull();
56240 -+
56241 -+ /* Partition description */
56242 -+ if (part_info->part_type == RANGE_PARTITION)
56243 -+ {
56244 -+ if (part_elem->range_value != LONGLONG_MAX)
56245 -+ table->field[11]->store((longlong) part_elem->range_value, FALSE);
56246 -+ else
56247 -+ table->field[11]->store(partition_keywords[PKW_MAXVALUE].str,
56248 -+ partition_keywords[PKW_MAXVALUE].length, cs);
56249 -+ table->field[11]->set_notnull();
56250 -+ }
56251 -+ else if (part_info->part_type == LIST_PARTITION)
56252 -+ {
56253 -+ List_iterator<part_elem_value> list_val_it(part_elem->list_val_list);
56254 -+ part_elem_value *list_value;
56255 -+ uint no_items= part_elem->list_val_list.elements;
56256 -+ tmp_str.length(0);
56257 -+ tmp_res.length(0);
56258 -+ if (part_elem->has_null_value)
56259 -+ {
56260 -+ tmp_str.append("NULL");
56261 -+ if (no_items > 0)
56262 -+ tmp_str.append(",");
56263 -+ }
56264 -+ while ((list_value= list_val_it++))
56265 -+ {
56266 -+ if (!list_value->unsigned_flag)
56267 -+ tmp_res.set(list_value->value, cs);
56268 -+ else
56269 -+ tmp_res.set((ulonglong)list_value->value, cs);
56270 -+ tmp_str.append(tmp_res);
56271 -+ if (--no_items != 0)
56272 -+ tmp_str.append(",");
56273 -+ };
56274 -+ table->field[11]->store(tmp_str.ptr(), tmp_str.length(), cs);
56275 -+ table->field[11]->set_notnull();
56276 -+ }
56277 -+
56278 -+ if (part_elem->subpartitions.elements)
56279 -+ {
56280 -+ List_iterator<partition_element> sub_it(part_elem->subpartitions);
56281 -+ partition_element *subpart_elem;
56282 -+ uint subpart_pos= 0;
56283 -+
56284 -+ while ((subpart_elem= sub_it++))
56285 -+ {
56286 -+ table->field[4]->store(subpart_elem->partition_name,
56287 -+ strlen(subpart_elem->partition_name), cs);
56288 -+ table->field[4]->set_notnull();
56289 -+ /* SUBPARTITION_ORDINAL_POSITION */
56290 -+ table->field[6]->store((longlong) ++subpart_pos, TRUE);
56291 -+ table->field[6]->set_notnull();
56292 -+
56293 -+ store_schema_partitions_record(thd, table, show_table, subpart_elem,
56294 -+ file, part_id);
56295 -+ part_id++;
56296 -+ if(schema_table_store_record(thd, table))
56297 -+ DBUG_RETURN(1);
56298 -+ }
56299 -+ }
56300 -+ else
56301 -+ {
56302 -+ store_schema_partitions_record(thd, table, show_table, part_elem,
56303 -+ file, part_id);
56304 -+ part_id++;
56305 -+ if(schema_table_store_record(thd, table))
56306 -+ DBUG_RETURN(1);
56307 -+ }
56308 -+ }
56309 -+ DBUG_RETURN(0);
56310 -+ }
56311 -+ else
56312 -+#endif
56313 -+ {
56314 -+ store_schema_partitions_record(thd, table, show_table, 0, file, 0);
56315 -+ if(schema_table_store_record(thd, table))
56316 -+ DBUG_RETURN(1);
56317 -+ }
56318 -+ DBUG_RETURN(0);
56319 -+}
56320 -+
56321 -+
56322 -+#ifdef NOT_USED
56323 -+static interval_type get_real_interval_type(interval_type i_type)
56324 -+{
56325 -+ switch (i_type) {
56326 -+ case INTERVAL_YEAR:
56327 -+ return INTERVAL_YEAR;
56328 -+
56329 -+ case INTERVAL_QUARTER:
56330 -+ case INTERVAL_YEAR_MONTH:
56331 -+ case INTERVAL_MONTH:
56332 -+ return INTERVAL_MONTH;
56333 -+
56334 -+ case INTERVAL_WEEK:
56335 -+ case INTERVAL_DAY:
56336 -+ return INTERVAL_DAY;
56337 -+
56338 -+ case INTERVAL_DAY_HOUR:
56339 -+ case INTERVAL_HOUR:
56340 -+ return INTERVAL_HOUR;
56341 -+
56342 -+ case INTERVAL_DAY_MINUTE:
56343 -+ case INTERVAL_HOUR_MINUTE:
56344 -+ case INTERVAL_MINUTE:
56345 -+ return INTERVAL_MINUTE;
56346 -+
56347 -+ case INTERVAL_DAY_SECOND:
56348 -+ case INTERVAL_HOUR_SECOND:
56349 -+ case INTERVAL_MINUTE_SECOND:
56350 -+ case INTERVAL_SECOND:
56351 -+ return INTERVAL_SECOND;
56352 -+
56353 -+ case INTERVAL_DAY_MICROSECOND:
56354 -+ case INTERVAL_HOUR_MICROSECOND:
56355 -+ case INTERVAL_MINUTE_MICROSECOND:
56356 -+ case INTERVAL_SECOND_MICROSECOND:
56357 -+ case INTERVAL_MICROSECOND:
56358 -+ return INTERVAL_MICROSECOND;
56359 -+ case INTERVAL_LAST:
56360 -+ DBUG_ASSERT(0);
56361 -+ }
56362 -+ DBUG_ASSERT(0);
56363 -+ return INTERVAL_SECOND;
56364 -+}
56365 -+
56366 -+#endif
56367 -+
56368 -+#ifdef HAVE_EVENT_SCHEDULER
56369 -+/*
56370 -+ Loads an event from mysql.event and copies it's data to a row of
56371 -+ I_S.EVENTS
56372 -+
56373 -+ Synopsis
56374 -+ copy_event_to_schema_table()
56375 -+ thd Thread
56376 -+ sch_table The schema table (information_schema.event)
56377 -+ event_table The event table to use for loading (mysql.event).
56378 -+
56379 -+ Returns
56380 -+ 0 OK
56381 -+ 1 Error
56382 -+*/
56383 -+
56384 -+int
56385 -+copy_event_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table)
56386 -+{
56387 -+ const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS;
56388 -+ CHARSET_INFO *scs= system_charset_info;
56389 -+ MYSQL_TIME time;
56390 -+ Event_timed et;
56391 -+ DBUG_ENTER("copy_event_to_schema_table");
56392 -+
56393 -+ restore_record(sch_table, s->default_values);
56394 -+
56395 -+ if (et.load_from_row(thd, event_table))
56396 -+ {
56397 -+ my_error(ER_CANNOT_LOAD_FROM_TABLE, MYF(0), event_table->alias);
56398 -+ DBUG_RETURN(1);
56399 -+ }
56400 -+
56401 -+ if (!(!wild || !wild[0] || !wild_compare(et.name.str, wild, 0)))
56402 -+ DBUG_RETURN(0);
56403 -+
56404 -+ /*
56405 -+ Skip events in schemas one does not have access to. The check is
56406 -+ optimized. It's guaranteed in case of SHOW EVENTS that the user
56407 -+ has access.
56408 -+ */
56409 -+ if (thd->lex->sql_command != SQLCOM_SHOW_EVENTS &&
56410 -+ check_access(thd, EVENT_ACL, et.dbname.str, 0, 0, 1,
56411 -+ is_schema_db(et.dbname.str, et.dbname.length)))
56412 -+ DBUG_RETURN(0);
56413 -+
56414 -+ /* ->field[0] is EVENT_CATALOG and is by default NULL */
56415 -+
56416 -+ sch_table->field[ISE_EVENT_SCHEMA]->
56417 -+ store(et.dbname.str, et.dbname.length,scs);
56418 -+ sch_table->field[ISE_EVENT_NAME]->
56419 -+ store(et.name.str, et.name.length, scs);
56420 -+ sch_table->field[ISE_DEFINER]->
56421 -+ store(et.definer.str, et.definer.length, scs);
56422 -+ const String *tz_name= et.time_zone->get_name();
56423 -+ sch_table->field[ISE_TIME_ZONE]->
56424 -+ store(tz_name->ptr(), tz_name->length(), scs);
56425 -+ sch_table->field[ISE_EVENT_BODY]->
56426 -+ store(STRING_WITH_LEN("SQL"), scs);
56427 -+ sch_table->field[ISE_EVENT_DEFINITION]->store(
56428 -+ et.body_utf8.str, et.body_utf8.length, scs);
56429 -+
56430 -+ /* SQL_MODE */
56431 -+ {
56432 -+ LEX_STRING sql_mode;
56433 -+ sys_var_thd_sql_mode::symbolic_mode_representation(thd, et.sql_mode,
56434 -+ &sql_mode);
56435 -+ sch_table->field[ISE_SQL_MODE]->
56436 -+ store(sql_mode.str, sql_mode.length, scs);
56437 -+ }
56438 -+
56439 -+ int not_used=0;
56440 -+
56441 -+ if (et.expression)
56442 -+ {
56443 -+ String show_str;
56444 -+ /* type */
56445 -+ sch_table->field[ISE_EVENT_TYPE]->store(STRING_WITH_LEN("RECURRING"), scs);
56446 -+
56447 -+ if (Events::reconstruct_interval_expression(&show_str, et.interval,
56448 -+ et.expression))
56449 -+ DBUG_RETURN(1);
56450 -+
56451 -+ sch_table->field[ISE_INTERVAL_VALUE]->set_notnull();
56452 -+ sch_table->field[ISE_INTERVAL_VALUE]->
56453 -+ store(show_str.ptr(), show_str.length(), scs);
56454 -+
56455 -+ LEX_STRING *ival= &interval_type_to_name[et.interval];
56456 -+ sch_table->field[ISE_INTERVAL_FIELD]->set_notnull();
56457 -+ sch_table->field[ISE_INTERVAL_FIELD]->store(ival->str, ival->length, scs);
56458 -+
56459 -+ /* starts & ends . STARTS is always set - see sql_yacc.yy */
56460 -+ et.time_zone->gmt_sec_to_TIME(&time, et.starts);
56461 -+ sch_table->field[ISE_STARTS]->set_notnull();
56462 -+ sch_table->field[ISE_STARTS]->
56463 -+ store_time(&time, MYSQL_TIMESTAMP_DATETIME);
56464 -+
56465 -+ if (!et.ends_null)
56466 -+ {
56467 -+ et.time_zone->gmt_sec_to_TIME(&time, et.ends);
56468 -+ sch_table->field[ISE_ENDS]->set_notnull();
56469 -+ sch_table->field[ISE_ENDS]->
56470 -+ store_time(&time, MYSQL_TIMESTAMP_DATETIME);
56471 -+ }
56472 -+ }
56473 -+ else
56474 -+ {
56475 -+ /* type */
56476 -+ sch_table->field[ISE_EVENT_TYPE]->store(STRING_WITH_LEN("ONE TIME"), scs);
56477 -+
56478 -+ et.time_zone->gmt_sec_to_TIME(&time, et.execute_at);
56479 -+ sch_table->field[ISE_EXECUTE_AT]->set_notnull();
56480 -+ sch_table->field[ISE_EXECUTE_AT]->
56481 -+ store_time(&time, MYSQL_TIMESTAMP_DATETIME);
56482 -+ }
56483 -+
56484 -+ /* status */
56485 -+
56486 -+ switch (et.status)
56487 -+ {
56488 -+ case Event_parse_data::ENABLED:
56489 -+ sch_table->field[ISE_STATUS]->store(STRING_WITH_LEN("ENABLED"), scs);
56490 -+ break;
56491 -+ case Event_parse_data::SLAVESIDE_DISABLED:
56492 -+ sch_table->field[ISE_STATUS]->store(STRING_WITH_LEN("SLAVESIDE_DISABLED"),
56493 -+ scs);
56494 -+ break;
56495 -+ case Event_parse_data::DISABLED:
56496 -+ sch_table->field[ISE_STATUS]->store(STRING_WITH_LEN("DISABLED"), scs);
56497 -+ break;
56498 -+ default:
56499 -+ DBUG_ASSERT(0);
56500 -+ }
56501 -+ sch_table->field[ISE_ORIGINATOR]->store(et.originator, TRUE);
56502 -+
56503 -+ /* on_completion */
56504 -+ if (et.on_completion == Event_parse_data::ON_COMPLETION_DROP)
56505 -+ sch_table->field[ISE_ON_COMPLETION]->
56506 -+ store(STRING_WITH_LEN("NOT PRESERVE"), scs);
56507 -+ else
56508 -+ sch_table->field[ISE_ON_COMPLETION]->
56509 -+ store(STRING_WITH_LEN("PRESERVE"), scs);
56510 -+
56511 -+ number_to_datetime(et.created, &time, 0, &not_used);
56512 -+ DBUG_ASSERT(not_used==0);
56513 -+ sch_table->field[ISE_CREATED]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
56514 -+
56515 -+ number_to_datetime(et.modified, &time, 0, &not_used);
56516 -+ DBUG_ASSERT(not_used==0);
56517 -+ sch_table->field[ISE_LAST_ALTERED]->
56518 -+ store_time(&time, MYSQL_TIMESTAMP_DATETIME);
56519 -+
56520 -+ if (et.last_executed)
56521 -+ {
56522 -+ et.time_zone->gmt_sec_to_TIME(&time, et.last_executed);
56523 -+ sch_table->field[ISE_LAST_EXECUTED]->set_notnull();
56524 -+ sch_table->field[ISE_LAST_EXECUTED]->
56525 -+ store_time(&time, MYSQL_TIMESTAMP_DATETIME);
56526 -+ }
56527 -+
56528 -+ sch_table->field[ISE_EVENT_COMMENT]->
56529 -+ store(et.comment.str, et.comment.length, scs);
56530 -+
56531 -+ sch_table->field[ISE_CLIENT_CS]->set_notnull();
56532 -+ sch_table->field[ISE_CLIENT_CS]->store(
56533 -+ et.creation_ctx->get_client_cs()->csname,
56534 -+ strlen(et.creation_ctx->get_client_cs()->csname),
56535 -+ scs);
56536 -+
56537 -+ sch_table->field[ISE_CONNECTION_CL]->set_notnull();
56538 -+ sch_table->field[ISE_CONNECTION_CL]->store(
56539 -+ et.creation_ctx->get_connection_cl()->name,
56540 -+ strlen(et.creation_ctx->get_connection_cl()->name),
56541 -+ scs);
56542 -+
56543 -+ sch_table->field[ISE_DB_CL]->set_notnull();
56544 -+ sch_table->field[ISE_DB_CL]->store(
56545 -+ et.creation_ctx->get_db_cl()->name,
56546 -+ strlen(et.creation_ctx->get_db_cl()->name),
56547 -+ scs);
56548 -+
56549 -+ if (schema_table_store_record(thd, sch_table))
56550 -+ DBUG_RETURN(1);
56551 -+
56552 -+ DBUG_RETURN(0);
56553 -+}
56554 -+#endif
56555 -+
56556 -+int fill_open_tables(THD *thd, TABLE_LIST *tables, COND *cond)
56557 -+{
56558 -+ DBUG_ENTER("fill_open_tables");
56559 -+ const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS;
56560 -+ TABLE *table= tables->table;
56561 -+ CHARSET_INFO *cs= system_charset_info;
56562 -+ OPEN_TABLE_LIST *open_list;
56563 -+ if (!(open_list=list_open_tables(thd,thd->lex->select_lex.db, wild))
56564 -+ && thd->is_fatal_error)
56565 -+ DBUG_RETURN(1);
56566 -+
56567 -+ for (; open_list ; open_list=open_list->next)
56568 -+ {
56569 -+ restore_record(table, s->default_values);
56570 -+ table->field[0]->store(open_list->db, strlen(open_list->db), cs);
56571 -+ table->field[1]->store(open_list->table, strlen(open_list->table), cs);
56572 -+ table->field[2]->store((longlong) open_list->in_use, TRUE);
56573 -+ table->field[3]->store((longlong) open_list->locked, TRUE);
56574 -+ if (schema_table_store_record(thd, table))
56575 -+ DBUG_RETURN(1);
56576 -+ }
56577 -+ DBUG_RETURN(0);
56578 -+}
56579 -+
56580 -+
56581 -+int fill_variables(THD *thd, TABLE_LIST *tables, COND *cond)
56582 -+{
56583 -+ DBUG_ENTER("fill_variables");
56584 -+ int res= 0;
56585 -+ LEX *lex= thd->lex;
56586 -+ const char *wild= lex->wild ? lex->wild->ptr() : NullS;
56587 -+ enum enum_schema_tables schema_table_idx=
56588 -+ get_schema_table_idx(tables->schema_table);
56589 -+ enum enum_var_type option_type= OPT_SESSION;
56590 -+ bool upper_case_names= (schema_table_idx != SCH_VARIABLES);
56591 -+ bool sorted_vars= (schema_table_idx == SCH_VARIABLES);
56592 -+
56593 -+ if (lex->option_type == OPT_GLOBAL ||
56594 -+ schema_table_idx == SCH_GLOBAL_VARIABLES)
56595 -+ option_type= OPT_GLOBAL;
56596 -+
56597 -+ rw_rdlock(&LOCK_system_variables_hash);
56598 -+ res= show_status_array(thd, wild, enumerate_sys_vars(thd, sorted_vars),
56599 -+ option_type, NULL, "", tables->table, upper_case_names, cond);
56600 -+ rw_unlock(&LOCK_system_variables_hash);
56601 -+ DBUG_RETURN(res);
56602 -+}
56603 -+
56604 -+
56605 -+int fill_status(THD *thd, TABLE_LIST *tables, COND *cond)
56606 -+{
56607 -+ DBUG_ENTER("fill_status");
56608 -+ LEX *lex= thd->lex;
56609 -+ const char *wild= lex->wild ? lex->wild->ptr() : NullS;
56610 -+ int res= 0;
56611 -+ STATUS_VAR *tmp1, tmp;
56612 -+ enum enum_schema_tables schema_table_idx=
56613 -+ get_schema_table_idx(tables->schema_table);
56614 -+ enum enum_var_type option_type;
56615 -+ bool upper_case_names= (schema_table_idx != SCH_STATUS);
56616 -+
56617 -+ if (schema_table_idx == SCH_STATUS)
56618 -+ {
56619 -+ option_type= lex->option_type;
56620 -+ if (option_type == OPT_GLOBAL)
56621 -+ tmp1= &tmp;
56622 -+ else
56623 -+ tmp1= thd->initial_status_var;
56624 -+ }
56625 -+ else if (schema_table_idx == SCH_GLOBAL_STATUS)
56626 -+ {
56627 -+ option_type= OPT_GLOBAL;
56628 -+ tmp1= &tmp;
56629 -+ }
56630 -+ else
56631 -+ {
56632 -+ option_type= OPT_SESSION;
56633 -+ tmp1= &thd->status_var;
56634 -+ }
56635 -+
56636 -+ pthread_mutex_lock(&LOCK_status);
56637 -+ if (option_type == OPT_GLOBAL)
56638 -+ calc_sum_of_all_status(&tmp);
56639 -+ res= show_status_array(thd, wild,
56640 -+ (SHOW_VAR *)all_status_vars.buffer,
56641 -+ option_type, tmp1, "", tables->table,
56642 -+ upper_case_names, cond);
56643 -+ pthread_mutex_unlock(&LOCK_status);
56644 -+ DBUG_RETURN(res);
56645 -+}
56646 -+
56647 -+
56648 -+/*
56649 -+ Fill and store records into I_S.referential_constraints table
56650 -+
56651 -+ SYNOPSIS
56652 -+ get_referential_constraints_record()
56653 -+ thd thread handle
56654 -+ tables table list struct(processed table)
56655 -+ table I_S table
56656 -+ res 1 means the error during opening of the processed table
56657 -+ 0 means processed table is opened without error
56658 -+ base_name db name
56659 -+ file_name table name
56660 -+
56661 -+ RETURN
56662 -+ 0 ok
56663 -+ # error
56664 -+*/
56665 -+
56666 -+static int
56667 -+get_referential_constraints_record(THD *thd, TABLE_LIST *tables,
56668 -+ TABLE *table, bool res,
56669 -+ LEX_STRING *db_name, LEX_STRING *table_name)
56670 -+{
56671 -+ CHARSET_INFO *cs= system_charset_info;
56672 -+ DBUG_ENTER("get_referential_constraints_record");
56673 -+
56674 -+ if (res)
56675 -+ {
56676 -+ if (thd->is_error())
56677 -+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
56678 -+ thd->main_da.sql_errno(), thd->main_da.message());
56679 -+ thd->clear_error();
56680 -+ DBUG_RETURN(0);
56681 -+ }
56682 -+ if (!tables->view)
56683 -+ {
56684 -+ List<FOREIGN_KEY_INFO> f_key_list;
56685 -+ TABLE *show_table= tables->table;
56686 -+
56687 -+ // This is not needed since no statistics are displayed.
56688 -+ // show_table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK | HA_STATUS_TIME);
56689 -+
56690 -+ show_table->file->get_foreign_key_list(thd, &f_key_list);
56691 -+ FOREIGN_KEY_INFO *f_key_info;
56692 -+ List_iterator_fast<FOREIGN_KEY_INFO> it(f_key_list);
56693 -+ while ((f_key_info= it++))
56694 -+ {
56695 -+ restore_record(table, s->default_values);
56696 -+ table->field[1]->store(db_name->str, db_name->length, cs);
56697 -+ table->field[9]->store(table_name->str, table_name->length, cs);
56698 -+ table->field[2]->store(f_key_info->forein_id->str,
56699 -+ f_key_info->forein_id->length, cs);
56700 -+ table->field[4]->store(f_key_info->referenced_db->str,
56701 -+ f_key_info->referenced_db->length, cs);
56702 -+ table->field[10]->store(f_key_info->referenced_table->str,
56703 -+ f_key_info->referenced_table->length, cs);
56704 -+ if (f_key_info->referenced_key_name)
56705 -+ {
56706 -+ table->field[5]->store(f_key_info->referenced_key_name->str,
56707 -+ f_key_info->referenced_key_name->length, cs);
56708 -+ table->field[5]->set_notnull();
56709 -+ }
56710 -+ else
56711 -+ table->field[5]->set_null();
56712 -+ table->field[6]->store(STRING_WITH_LEN("NONE"), cs);
56713 -+ table->field[7]->store(f_key_info->update_method->str,
56714 -+ f_key_info->update_method->length, cs);
56715 -+ table->field[8]->store(f_key_info->delete_method->str,
56716 -+ f_key_info->delete_method->length, cs);
56717 -+ if (schema_table_store_record(thd, table))
56718 -+ DBUG_RETURN(1);
56719 -+ }
56720 -+ }
56721 -+ DBUG_RETURN(0);
56722 -+}
56723 -+
56724 -+struct schema_table_ref
56725 -+{
56726 -+ const char *table_name;
56727 -+ ST_SCHEMA_TABLE *schema_table;
56728 -+};
56729 -+
56730 -+
56731 -+/*
56732 -+ Find schema_tables elment by name
56733 -+
56734 -+ SYNOPSIS
56735 -+ find_schema_table_in_plugin()
56736 -+ thd thread handler
56737 -+ plugin plugin
56738 -+ table_name table name
56739 -+
56740 -+ RETURN
56741 -+ 0 table not found
56742 -+ 1 found the schema table
56743 -+*/
56744 -+static my_bool find_schema_table_in_plugin(THD *thd, plugin_ref plugin,
56745 -+ void* p_table)
56746 -+{
56747 -+ schema_table_ref *p_schema_table= (schema_table_ref *)p_table;
56748 -+ const char* table_name= p_schema_table->table_name;
56749 -+ ST_SCHEMA_TABLE *schema_table= plugin_data(plugin, ST_SCHEMA_TABLE *);
56750 -+ DBUG_ENTER("find_schema_table_in_plugin");
56751 -+
56752 -+ if (!my_strcasecmp(system_charset_info,
56753 -+ schema_table->table_name,
56754 -+ table_name)) {
56755 -+ p_schema_table->schema_table= schema_table;
56756 -+ DBUG_RETURN(1);
56757 -+ }
56758 -+
56759 -+ DBUG_RETURN(0);
56760 -+}
56761 -+
56762 -+
56763 -+/*
56764 -+ Find schema_tables elment by name
56765 -+
56766 -+ SYNOPSIS
56767 -+ find_schema_table()
56768 -+ thd thread handler
56769 -+ table_name table name
56770 -+
56771 -+ RETURN
56772 -+ 0 table not found
56773 -+ # pointer to 'schema_tables' element
56774 -+*/
56775 -+
56776 -+ST_SCHEMA_TABLE *find_schema_table(THD *thd, const char* table_name)
56777 -+{
56778 -+ schema_table_ref schema_table_a;
56779 -+ ST_SCHEMA_TABLE *schema_table= schema_tables;
56780 -+ DBUG_ENTER("find_schema_table");
56781 -+
56782 -+ for (; schema_table->table_name; schema_table++)
56783 -+ {
56784 -+ if (!my_strcasecmp(system_charset_info,
56785 -+ schema_table->table_name,
56786 -+ table_name))
56787 -+ DBUG_RETURN(schema_table);
56788 -+ }
56789 -+
56790 -+ schema_table_a.table_name= table_name;
56791 -+ if (plugin_foreach(thd, find_schema_table_in_plugin,
56792 -+ MYSQL_INFORMATION_SCHEMA_PLUGIN, &schema_table_a))
56793 -+ DBUG_RETURN(schema_table_a.schema_table);
56794 -+
56795 -+ DBUG_RETURN(NULL);
56796 -+}
56797 -+
56798 -+
56799 -+ST_SCHEMA_TABLE *get_schema_table(enum enum_schema_tables schema_table_idx)
56800 -+{
56801 -+ return &schema_tables[schema_table_idx];
56802 -+}
56803 -+
56804 -+
56805 -+/**
56806 -+ Create information_schema table using schema_table data.
56807 -+
56808 -+ @note
56809 -+ For MYSQL_TYPE_DECIMAL fields only, the field_length member has encoded
56810 -+ into it two numbers, based on modulus of base-10 numbers. In the ones
56811 -+ position is the number of decimals. Tens position is unused. In the
56812 -+ hundreds and thousands position is a two-digit decimal number representing
56813 -+ length. Encode this value with (decimals*100)+length , where
56814 -+ 0<decimals<10 and 0<=length<100 .
56815 -+
56816 -+ @param
56817 -+ thd thread handler
56818 -+
56819 -+ @param table_list Used to pass I_S table information(fields info, tables
56820 -+ parameters etc) and table name.
56821 -+
56822 -+ @retval \# Pointer to created table
56823 -+ @retval NULL Can't create table
56824 -+*/
56825 -+
56826 -+TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list)
56827 -+{
56828 -+ int field_count= 0;
56829 -+ Item *item;
56830 -+ TABLE *table;
56831 -+ List<Item> field_list;
56832 -+ ST_SCHEMA_TABLE *schema_table= table_list->schema_table;
56833 -+ ST_FIELD_INFO *fields_info= schema_table->fields_info;
56834 -+ CHARSET_INFO *cs= system_charset_info;
56835 -+ DBUG_ENTER("create_schema_table");
56836 -+
56837 -+ for (; fields_info->field_name; fields_info++)
56838 -+ {
56839 -+ switch (fields_info->field_type) {
56840 -+ case MYSQL_TYPE_TINY:
56841 -+ case MYSQL_TYPE_LONG:
56842 -+ case MYSQL_TYPE_SHORT:
56843 -+ case MYSQL_TYPE_LONGLONG:
56844 -+ case MYSQL_TYPE_INT24:
56845 -+ if (!(item= new Item_return_int(fields_info->field_name,
56846 -+ fields_info->field_length,
56847 -+ fields_info->field_type,
56848 -+ fields_info->value)))
56849 -+ {
56850 -+ DBUG_RETURN(0);
56851 -+ }
56852 -+ item->unsigned_flag= (fields_info->field_flags & MY_I_S_UNSIGNED);
56853 -+ break;
56854 -+ case MYSQL_TYPE_DATE:
56855 -+ case MYSQL_TYPE_TIME:
56856 -+ case MYSQL_TYPE_TIMESTAMP:
56857 -+ case MYSQL_TYPE_DATETIME:
56858 -+ if (!(item=new Item_return_date_time(fields_info->field_name,
56859 -+ fields_info->field_type)))
56860 -+ {
56861 -+ DBUG_RETURN(0);
56862 -+ }
56863 -+ break;
56864 -+ case MYSQL_TYPE_FLOAT:
56865 -+ case MYSQL_TYPE_DOUBLE:
56866 -+ if ((item= new Item_float(fields_info->field_name, 0.0, NOT_FIXED_DEC,
56867 -+ fields_info->field_length)) == NULL)
56868 -+ DBUG_RETURN(NULL);
56869 -+ break;
56870 -+ case MYSQL_TYPE_DECIMAL:
56871 -+ case MYSQL_TYPE_NEWDECIMAL:
56872 -+ if (!(item= new Item_decimal((longlong) fields_info->value, false)))
56873 -+ {
56874 -+ DBUG_RETURN(0);
56875 -+ }
56876 -+ item->unsigned_flag= (fields_info->field_flags & MY_I_S_UNSIGNED);
56877 -+ item->decimals= fields_info->field_length%10;
56878 -+ item->max_length= (fields_info->field_length/100)%100;
56879 -+ if (item->unsigned_flag == 0)
56880 -+ item->max_length+= 1;
56881 -+ if (item->decimals > 0)
56882 -+ item->max_length+= 1;
56883 -+ item->set_name(fields_info->field_name,
56884 -+ strlen(fields_info->field_name), cs);
56885 -+ break;
56886 -+ case MYSQL_TYPE_TINY_BLOB:
56887 -+ case MYSQL_TYPE_MEDIUM_BLOB:
56888 -+ case MYSQL_TYPE_LONG_BLOB:
56889 -+ case MYSQL_TYPE_BLOB:
56890 -+ if (!(item= new Item_blob(fields_info->field_name,
56891 -+ fields_info->field_length)))
56892 -+ {
56893 -+ DBUG_RETURN(0);
56894 -+ }
56895 -+ break;
56896 -+ default:
56897 -+ /* Don't let unimplemented types pass through. Could be a grave error. */
56898 -+ DBUG_ASSERT(fields_info->field_type == MYSQL_TYPE_STRING);
56899 -+
56900 -+ if (!(item= new Item_empty_string("", fields_info->field_length, cs)))
56901 -+ {
56902 -+ DBUG_RETURN(0);
56903 -+ }
56904 -+ item->set_name(fields_info->field_name,
56905 -+ strlen(fields_info->field_name), cs);
56906 -+ break;
56907 -+ }
56908 -+ field_list.push_back(item);
56909 -+ item->maybe_null= (fields_info->field_flags & MY_I_S_MAYBE_NULL);
56910 -+ field_count++;
56911 -+ }
56912 -+ TMP_TABLE_PARAM *tmp_table_param =
56913 -+ (TMP_TABLE_PARAM*) (thd->alloc(sizeof(TMP_TABLE_PARAM)));
56914 -+ tmp_table_param->init();
56915 -+ tmp_table_param->table_charset= cs;
56916 -+ tmp_table_param->field_count= field_count;
56917 -+ tmp_table_param->schema_table= 1;
56918 -+ SELECT_LEX *select_lex= thd->lex->current_select;
56919 -+ if (!(table= create_tmp_table(thd, tmp_table_param,
56920 -+ field_list, (ORDER*) 0, 0, 0,
56921 -+ (select_lex->options | thd->options |
56922 -+ TMP_TABLE_ALL_COLUMNS),
56923 -+ HA_POS_ERROR, table_list->alias)))
56924 -+ DBUG_RETURN(0);
56925 -+ my_bitmap_map* bitmaps=
56926 -+ (my_bitmap_map*) thd->alloc(bitmap_buffer_size(field_count));
56927 -+ bitmap_init(&table->def_read_set, (my_bitmap_map*) bitmaps, field_count,
56928 -+ FALSE);
56929 -+ table->read_set= &table->def_read_set;
56930 -+ bitmap_clear_all(table->read_set);
56931 -+ table_list->schema_table_param= tmp_table_param;
56932 -+ DBUG_RETURN(table);
56933 -+}
56934 -+
56935 -+
56936 -+/*
56937 -+ For old SHOW compatibility. It is used when
56938 -+ old SHOW doesn't have generated column names
56939 -+ Make list of fields for SHOW
56940 -+
56941 -+ SYNOPSIS
56942 -+ make_old_format()
56943 -+ thd thread handler
56944 -+ schema_table pointer to 'schema_tables' element
56945 -+
56946 -+ RETURN
56947 -+ 1 error
56948 -+ 0 success
56949 -+*/
56950 -+
56951 -+int make_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
56952 -+{
56953 -+ ST_FIELD_INFO *field_info= schema_table->fields_info;
56954 -+ Name_resolution_context *context= &thd->lex->select_lex.context;
56955 -+ for (; field_info->field_name; field_info++)
56956 -+ {
56957 -+ if (field_info->old_name)
56958 -+ {
56959 -+ Item_field *field= new Item_field(context,
56960 -+ NullS, NullS, field_info->field_name);
56961 -+ if (field)
56962 -+ {
56963 -+ field->set_name(field_info->old_name,
56964 -+ strlen(field_info->old_name),
56965 -+ system_charset_info);
56966 -+ if (add_item_to_list(thd, field))
56967 -+ return 1;
56968 -+ }
56969 -+ }
56970 -+ }
56971 -+ return 0;
56972 -+}
56973 -+
56974 -+
56975 -+int make_schemata_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
56976 -+{
56977 -+ char tmp[128];
56978 -+ LEX *lex= thd->lex;
56979 -+ SELECT_LEX *sel= lex->current_select;
56980 -+ Name_resolution_context *context= &sel->context;
56981 -+
56982 -+ if (!sel->item_list.elements)
56983 -+ {
56984 -+ ST_FIELD_INFO *field_info= &schema_table->fields_info[1];
56985 -+ String buffer(tmp,sizeof(tmp), system_charset_info);
56986 -+ Item_field *field= new Item_field(context,
56987 -+ NullS, NullS, field_info->field_name);
56988 -+ if (!field || add_item_to_list(thd, field))
56989 -+ return 1;
56990 -+ buffer.length(0);
56991 -+ buffer.append(field_info->old_name);
56992 -+ if (lex->wild && lex->wild->ptr())
56993 -+ {
56994 -+ buffer.append(STRING_WITH_LEN(" ("));
56995 -+ buffer.append(lex->wild->ptr());
56996 -+ buffer.append(')');
56997 -+ }
56998 -+ field->set_name(buffer.ptr(), buffer.length(), system_charset_info);
56999 -+ }
57000 -+ return 0;
57001 -+}
57002 -+
57003 -+
57004 -+int make_table_names_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
57005 -+{
57006 -+ char tmp[128];
57007 -+ String buffer(tmp,sizeof(tmp), thd->charset());
57008 -+ LEX *lex= thd->lex;
57009 -+ Name_resolution_context *context= &lex->select_lex.context;
57010 -+
57011 -+ ST_FIELD_INFO *field_info= &schema_table->fields_info[2];
57012 -+ buffer.length(0);
57013 -+ buffer.append(field_info->old_name);
57014 -+ buffer.append(lex->select_lex.db);
57015 -+ if (lex->wild && lex->wild->ptr())
57016 -+ {
57017 -+ buffer.append(STRING_WITH_LEN(" ("));
57018 -+ buffer.append(lex->wild->ptr());
57019 -+ buffer.append(')');
57020 -+ }
57021 -+ Item_field *field= new Item_field(context,
57022 -+ NullS, NullS, field_info->field_name);
57023 -+ if (add_item_to_list(thd, field))
57024 -+ return 1;
57025 -+ field->set_name(buffer.ptr(), buffer.length(), system_charset_info);
57026 -+ if (thd->lex->verbose)
57027 -+ {
57028 -+ field->set_name(buffer.ptr(), buffer.length(), system_charset_info);
57029 -+ field_info= &schema_table->fields_info[3];
57030 -+ field= new Item_field(context, NullS, NullS, field_info->field_name);
57031 -+ if (add_item_to_list(thd, field))
57032 -+ return 1;
57033 -+ field->set_name(field_info->old_name, strlen(field_info->old_name),
57034 -+ system_charset_info);
57035 -+ }
57036 -+ return 0;
57037 -+}
57038 -+
57039 -+
57040 -+int make_columns_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
57041 -+{
57042 -+ int fields_arr[]= {3, 14, 13, 6, 15, 5, 16, 17, 18, -1};
57043 -+ int *field_num= fields_arr;
57044 -+ ST_FIELD_INFO *field_info;
57045 -+ Name_resolution_context *context= &thd->lex->select_lex.context;
57046 -+
57047 -+ for (; *field_num >= 0; field_num++)
57048 -+ {
57049 -+ field_info= &schema_table->fields_info[*field_num];
57050 -+ if (!thd->lex->verbose && (*field_num == 13 ||
57051 -+ *field_num == 17 ||
57052 -+ *field_num == 18))
57053 -+ continue;
57054 -+ Item_field *field= new Item_field(context,
57055 -+ NullS, NullS, field_info->field_name);
57056 -+ if (field)
57057 -+ {
57058 -+ field->set_name(field_info->old_name,
57059 -+ strlen(field_info->old_name),
57060 -+ system_charset_info);
57061 -+ if (add_item_to_list(thd, field))
57062 -+ return 1;
57063 -+ }
57064 -+ }
57065 -+ return 0;
57066 -+}
57067 -+
57068 -+
57069 -+int make_character_sets_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
57070 -+{
57071 -+ int fields_arr[]= {0, 2, 1, 3, -1};
57072 -+ int *field_num= fields_arr;
57073 -+ ST_FIELD_INFO *field_info;
57074 -+ Name_resolution_context *context= &thd->lex->select_lex.context;
57075 -+
57076 -+ for (; *field_num >= 0; field_num++)
57077 -+ {
57078 -+ field_info= &schema_table->fields_info[*field_num];
57079 -+ Item_field *field= new Item_field(context,
57080 -+ NullS, NullS, field_info->field_name);
57081 -+ if (field)
57082 -+ {
57083 -+ field->set_name(field_info->old_name,
57084 -+ strlen(field_info->old_name),
57085 -+ system_charset_info);
57086 -+ if (add_item_to_list(thd, field))
57087 -+ return 1;
57088 -+ }
57089 -+ }
57090 -+ return 0;
57091 -+}
57092 -+
57093 -+
57094 -+int make_proc_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
57095 -+{
57096 -+ int fields_arr[]= {2, 3, 4, 19, 16, 15, 14, 18, 20, 21, 22, -1};
57097 -+ int *field_num= fields_arr;
57098 -+ ST_FIELD_INFO *field_info;
57099 -+ Name_resolution_context *context= &thd->lex->select_lex.context;
57100 -+
57101 -+ for (; *field_num >= 0; field_num++)
57102 -+ {
57103 -+ field_info= &schema_table->fields_info[*field_num];
57104 -+ Item_field *field= new Item_field(context,
57105 -+ NullS, NullS, field_info->field_name);
57106 -+ if (field)
57107 -+ {
57108 -+ field->set_name(field_info->old_name,
57109 -+ strlen(field_info->old_name),
57110 -+ system_charset_info);
57111 -+ if (add_item_to_list(thd, field))
57112 -+ return 1;
57113 -+ }
57114 -+ }
57115 -+ return 0;
57116 -+}
57117 -+
57118 -+
57119 -+/*
57120 -+ Create information_schema table
57121 -+
57122 -+ SYNOPSIS
57123 -+ mysql_schema_table()
57124 -+ thd thread handler
57125 -+ lex pointer to LEX
57126 -+ table_list pointer to table_list
57127 -+
57128 -+ RETURN
57129 -+ 0 success
57130 -+ 1 error
57131 -+*/
57132 -+
57133 -+int mysql_schema_table(THD *thd, LEX *lex, TABLE_LIST *table_list)
57134 -+{
57135 -+ TABLE *table;
57136 -+ DBUG_ENTER("mysql_schema_table");
57137 -+ if (!(table= table_list->schema_table->create_table(thd, table_list)))
57138 -+ DBUG_RETURN(1);
57139 -+ table->s->tmp_table= SYSTEM_TMP_TABLE;
57140 -+ table->grant.privilege= SELECT_ACL;
57141 -+ /*
57142 -+ This test is necessary to make
57143 -+ case insensitive file systems +
57144 -+ upper case table names(information schema tables) +
57145 -+ views
57146 -+ working correctly
57147 -+ */
57148 -+ if (table_list->schema_table_name)
57149 -+ table->alias_name_used= my_strcasecmp(table_alias_charset,
57150 -+ table_list->schema_table_name,
57151 -+ table_list->alias);
57152 -+ table_list->table_name= table->s->table_name.str;
57153 -+ table_list->table_name_length= table->s->table_name.length;
57154 -+ table_list->table= table;
57155 -+ table->next= thd->derived_tables;
57156 -+ thd->derived_tables= table;
57157 -+ table_list->select_lex->options |= OPTION_SCHEMA_TABLE;
57158 -+ lex->safe_to_cache_query= 0;
57159 -+
57160 -+ if (table_list->schema_table_reformed) // show command
57161 -+ {
57162 -+ SELECT_LEX *sel= lex->current_select;
57163 -+ Item *item;
57164 -+ Field_translator *transl, *org_transl;
57165 -+
57166 -+ if (table_list->field_translation)
57167 -+ {
57168 -+ Field_translator *end= table_list->field_translation_end;
57169 -+ for (transl= table_list->field_translation; transl < end; transl++)
57170 -+ {
57171 -+ if (!transl->item->fixed &&
57172 -+ transl->item->fix_fields(thd, &transl->item))
57173 -+ DBUG_RETURN(1);
57174 -+ }
57175 -+ DBUG_RETURN(0);
57176 -+ }
57177 -+ List_iterator_fast<Item> it(sel->item_list);
57178 -+ if (!(transl=
57179 -+ (Field_translator*)(thd->stmt_arena->
57180 -+ alloc(sel->item_list.elements *
57181 -+ sizeof(Field_translator)))))
57182 -+ {
57183 -+ DBUG_RETURN(1);
57184 -+ }
57185 -+ for (org_transl= transl; (item= it++); transl++)
57186 -+ {
57187 -+ transl->item= item;
57188 -+ transl->name= item->name;
57189 -+ if (!item->fixed && item->fix_fields(thd, &transl->item))
57190 -+ {
57191 -+ DBUG_RETURN(1);
57192 -+ }
57193 -+ }
57194 -+ table_list->field_translation= org_transl;
57195 -+ table_list->field_translation_end= transl;
57196 -+ }
57197 -+
57198 -+ DBUG_RETURN(0);
57199 -+}
57200 -+
57201 -+
57202 -+/*
57203 -+ Generate select from information_schema table
57204 -+
57205 -+ SYNOPSIS
57206 -+ make_schema_select()
57207 -+ thd thread handler
57208 -+ sel pointer to SELECT_LEX
57209 -+ schema_table_idx index of 'schema_tables' element
57210 -+
57211 -+ RETURN
57212 -+ 0 success
57213 -+ 1 error
57214 -+*/
57215 -+
57216 -+int make_schema_select(THD *thd, SELECT_LEX *sel,
57217 -+ enum enum_schema_tables schema_table_idx)
57218 -+{
57219 -+ ST_SCHEMA_TABLE *schema_table= get_schema_table(schema_table_idx);
57220 -+ LEX_STRING db, table;
57221 -+ DBUG_ENTER("make_schema_select");
57222 -+ DBUG_PRINT("enter", ("mysql_schema_select: %s", schema_table->table_name));
57223 -+ /*
57224 -+ We have to make non const db_name & table_name
57225 -+ because of lower_case_table_names
57226 -+ */
57227 -+ thd->make_lex_string(&db, INFORMATION_SCHEMA_NAME.str,
57228 -+ INFORMATION_SCHEMA_NAME.length, 0);
57229 -+ thd->make_lex_string(&table, schema_table->table_name,
57230 -+ strlen(schema_table->table_name), 0);
57231 -+ if (schema_table->old_format(thd, schema_table) || /* Handle old syntax */
57232 -+ !sel->add_table_to_list(thd, new Table_ident(thd, db, table, 0),
57233 -+ 0, 0, TL_READ))
57234 -+ {
57235 -+ DBUG_RETURN(1);
57236 -+ }
57237 -+ DBUG_RETURN(0);
57238 -+}
57239 -+
57240 -+
57241 -+/*
57242 -+ Fill temporary schema tables before SELECT
57243 -+
57244 -+ SYNOPSIS
57245 -+ get_schema_tables_result()
57246 -+ join join which use schema tables
57247 -+ executed_place place where I_S table processed
57248 -+
57249 -+ RETURN
57250 -+ FALSE success
57251 -+ TRUE error
57252 -+*/
57253 -+
57254 -+bool get_schema_tables_result(JOIN *join,
57255 -+ enum enum_schema_table_state executed_place)
57256 -+{
57257 -+ JOIN_TAB *tmp_join_tab= join->join_tab+join->tables;
57258 -+ THD *thd= join->thd;
57259 -+ LEX *lex= thd->lex;
57260 -+ bool result= 0;
57261 -+ DBUG_ENTER("get_schema_tables_result");
57262 -+
57263 -+ thd->no_warnings_for_error= 1;
57264 -+ for (JOIN_TAB *tab= join->join_tab; tab < tmp_join_tab; tab++)
57265 -+ {
57266 -+ if (!tab->table || !tab->table->pos_in_table_list)
57267 -+ break;
57268 -+
57269 -+ TABLE_LIST *table_list= tab->table->pos_in_table_list;
57270 -+ if (table_list->schema_table && thd->fill_information_schema_tables())
57271 -+ {
57272 -+ bool is_subselect= (&lex->unit != lex->current_select->master_unit() &&
57273 -+ lex->current_select->master_unit()->item);
57274 -+
57275 -+ /* A value of 0 indicates a dummy implementation */
57276 -+ if (table_list->schema_table->fill_table == 0)
57277 -+ continue;
57278 -+
57279 -+ /* skip I_S optimizations specific to get_all_tables */
57280 -+ if (thd->lex->describe &&
57281 -+ (table_list->schema_table->fill_table != get_all_tables))
57282 -+ continue;
57283 -+
57284 -+ /*
57285 -+ If schema table is already processed and
57286 -+ the statement is not a subselect then
57287 -+ we don't need to fill this table again.
57288 -+ If schema table is already processed and
57289 -+ schema_table_state != executed_place then
57290 -+ table is already processed and
57291 -+ we should skip second data processing.
57292 -+ */
57293 -+ if (table_list->schema_table_state &&
57294 -+ (!is_subselect || table_list->schema_table_state != executed_place))
57295 -+ continue;
57296 -+
57297 -+ /*
57298 -+ if table is used in a subselect and
57299 -+ table has been processed earlier with the same
57300 -+ 'executed_place' value then we should refresh the table.
57301 -+ */
57302 -+ if (table_list->schema_table_state && is_subselect)
57303 -+ {
57304 -+ table_list->table->file->extra(HA_EXTRA_NO_CACHE);
57305 -+ table_list->table->file->extra(HA_EXTRA_RESET_STATE);
57306 -+ table_list->table->file->ha_delete_all_rows();
57307 -+ free_io_cache(table_list->table);
57308 -+ filesort_free_buffers(table_list->table,1);
57309 -+ table_list->table->null_row= 0;
57310 -+ }
57311 -+ else
57312 -+ table_list->table->file->stats.records= 0;
57313 -+
57314 -+ if (table_list->schema_table->fill_table(thd, table_list,
57315 -+ tab->select_cond))
57316 -+ {
57317 -+ result= 1;
57318 -+ join->error= 1;
57319 -+ tab->read_record.file= table_list->table->file;
57320 -+ table_list->schema_table_state= executed_place;
57321 -+ break;
57322 -+ }
57323 -+ tab->read_record.file= table_list->table->file;
57324 -+ table_list->schema_table_state= executed_place;
57325 -+ }
57326 -+ }
57327 -+ thd->no_warnings_for_error= 0;
57328 -+ DBUG_RETURN(result);
57329 -+}
57330 -+
57331 -+struct run_hton_fill_schema_files_args
57332 -+{
57333 -+ TABLE_LIST *tables;
57334 -+ COND *cond;
57335 -+};
57336 -+
57337 -+static my_bool run_hton_fill_schema_files(THD *thd, plugin_ref plugin,
57338 -+ void *arg)
57339 -+{
57340 -+ struct run_hton_fill_schema_files_args *args=
57341 -+ (run_hton_fill_schema_files_args *) arg;
57342 -+ handlerton *hton= plugin_data(plugin, handlerton *);
57343 -+ if(hton->fill_files_table && hton->state == SHOW_OPTION_YES)
57344 -+ hton->fill_files_table(hton, thd, args->tables, args->cond);
57345 -+ return false;
57346 -+}
57347 -+
57348 -+int fill_schema_files(THD *thd, TABLE_LIST *tables, COND *cond)
57349 -+{
57350 -+ DBUG_ENTER("fill_schema_files");
57351 -+
57352 -+ struct run_hton_fill_schema_files_args args;
57353 -+ args.tables= tables;
57354 -+ args.cond= cond;
57355 -+
57356 -+ plugin_foreach(thd, run_hton_fill_schema_files,
57357 -+ MYSQL_STORAGE_ENGINE_PLUGIN, &args);
57358 -+
57359 -+ DBUG_RETURN(0);
57360 -+}
57361 -+
57362 -+
57363 -+ST_FIELD_INFO schema_fields_info[]=
57364 -+{
57365 -+ {"CATALOG_NAME", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
57366 -+ {"SCHEMA_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Database",
57367 -+ SKIP_OPEN_TABLE},
57368 -+ {"DEFAULT_CHARACTER_SET_NAME", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0, 0,
57369 -+ SKIP_OPEN_TABLE},
57370 -+ {"DEFAULT_COLLATION_NAME", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0, 0,
57371 -+ SKIP_OPEN_TABLE},
57372 -+ {"SQL_PATH", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
57373 -+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
57374 -+};
57375 -+
57376 -+
57377 -+ST_FIELD_INFO tables_fields_info[]=
57378 -+{
57379 -+ {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
57380 -+ {"TABLE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
57381 -+ {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Name",
57382 -+ SKIP_OPEN_TABLE},
57383 -+ {"TABLE_TYPE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
57384 -+ {"ENGINE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, "Engine", OPEN_FRM_ONLY},
57385 -+ {"VERSION", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
57386 -+ (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Version", OPEN_FRM_ONLY},
57387 -+ {"ROW_FORMAT", 10, MYSQL_TYPE_STRING, 0, 1, "Row_format", OPEN_FULL_TABLE},
57388 -+ {"TABLE_ROWS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
57389 -+ (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Rows", OPEN_FULL_TABLE},
57390 -+ {"AVG_ROW_LENGTH", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
57391 -+ (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Avg_row_length", OPEN_FULL_TABLE},
57392 -+ {"DATA_LENGTH", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
57393 -+ (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Data_length", OPEN_FULL_TABLE},
57394 -+ {"MAX_DATA_LENGTH", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
57395 -+ (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Max_data_length", OPEN_FULL_TABLE},
57396 -+ {"INDEX_LENGTH", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
57397 -+ (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Index_length", OPEN_FULL_TABLE},
57398 -+ {"DATA_FREE", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
57399 -+ (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Data_free", OPEN_FULL_TABLE},
57400 -+ {"AUTO_INCREMENT", MY_INT64_NUM_DECIMAL_DIGITS , MYSQL_TYPE_LONGLONG, 0,
57401 -+ (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Auto_increment", OPEN_FULL_TABLE},
57402 -+ {"CREATE_TIME", 0, MYSQL_TYPE_DATETIME, 0, 1, "Create_time", OPEN_FULL_TABLE},
57403 -+ {"UPDATE_TIME", 0, MYSQL_TYPE_DATETIME, 0, 1, "Update_time", OPEN_FULL_TABLE},
57404 -+ {"CHECK_TIME", 0, MYSQL_TYPE_DATETIME, 0, 1, "Check_time", OPEN_FULL_TABLE},
57405 -+ {"TABLE_COLLATION", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 1, "Collation",
57406 -+ OPEN_FRM_ONLY},
57407 -+ {"CHECKSUM", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
57408 -+ (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Checksum", OPEN_FULL_TABLE},
57409 -+ {"CREATE_OPTIONS", 255, MYSQL_TYPE_STRING, 0, 1, "Create_options",
57410 -+ OPEN_FRM_ONLY},
57411 -+ {"TABLE_COMMENT", 80, MYSQL_TYPE_STRING, 0, 0, "Comment", OPEN_FRM_ONLY},
57412 -+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
57413 -+};
57414 -+
57415 -+
57416 -+ST_FIELD_INFO columns_fields_info[]=
57417 -+{
57418 -+ {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FRM_ONLY},
57419 -+ {"TABLE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
57420 -+ {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
57421 -+ {"COLUMN_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Field",
57422 -+ OPEN_FRM_ONLY},
57423 -+ {"ORDINAL_POSITION", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
57424 -+ MY_I_S_UNSIGNED, 0, OPEN_FRM_ONLY},
57425 -+ {"COLUMN_DEFAULT", MAX_FIELD_VARCHARLENGTH, MYSQL_TYPE_STRING, 0,
57426 -+ 1, "Default", OPEN_FRM_ONLY},
57427 -+ {"IS_NULLABLE", 3, MYSQL_TYPE_STRING, 0, 0, "Null", OPEN_FRM_ONLY},
57428 -+ {"DATA_TYPE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
57429 -+ {"CHARACTER_MAXIMUM_LENGTH", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG,
57430 -+ 0, (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), 0, OPEN_FRM_ONLY},
57431 -+ {"CHARACTER_OCTET_LENGTH", MY_INT64_NUM_DECIMAL_DIGITS , MYSQL_TYPE_LONGLONG,
57432 -+ 0, (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), 0, OPEN_FRM_ONLY},
57433 -+ {"NUMERIC_PRECISION", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG,
57434 -+ 0, (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), 0, OPEN_FRM_ONLY},
57435 -+ {"NUMERIC_SCALE", MY_INT64_NUM_DECIMAL_DIGITS , MYSQL_TYPE_LONGLONG,
57436 -+ 0, (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), 0, OPEN_FRM_ONLY},
57437 -+ {"CHARACTER_SET_NAME", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 1, 0,
57438 -+ OPEN_FRM_ONLY},
57439 -+ {"COLLATION_NAME", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 1, "Collation",
57440 -+ OPEN_FRM_ONLY},
57441 -+ {"COLUMN_TYPE", 65535, MYSQL_TYPE_STRING, 0, 0, "Type", OPEN_FRM_ONLY},
57442 -+ {"COLUMN_KEY", 3, MYSQL_TYPE_STRING, 0, 0, "Key", OPEN_FRM_ONLY},
57443 -+ {"EXTRA", 27, MYSQL_TYPE_STRING, 0, 0, "Extra", OPEN_FRM_ONLY},
57444 -+ {"PRIVILEGES", 80, MYSQL_TYPE_STRING, 0, 0, "Privileges", OPEN_FRM_ONLY},
57445 -+ {"COLUMN_COMMENT", 255, MYSQL_TYPE_STRING, 0, 0, "Comment", OPEN_FRM_ONLY},
57446 -+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
57447 -+};
57448 -+
57449 -+
57450 -+ST_FIELD_INFO charsets_fields_info[]=
57451 -+{
57452 -+ {"CHARACTER_SET_NAME", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0, "Charset",
57453 -+ SKIP_OPEN_TABLE},
57454 -+ {"DEFAULT_COLLATE_NAME", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0,
57455 -+ "Default collation", SKIP_OPEN_TABLE},
57456 -+ {"DESCRIPTION", 60, MYSQL_TYPE_STRING, 0, 0, "Description",
57457 -+ SKIP_OPEN_TABLE},
57458 -+ {"MAXLEN", 3, MYSQL_TYPE_LONGLONG, 0, 0, "Maxlen", SKIP_OPEN_TABLE},
57459 -+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
57460 -+};
57461 -+
57462 -+
57463 -+ST_FIELD_INFO collation_fields_info[]=
57464 -+{
57465 -+ {"COLLATION_NAME", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0, "Collation",
57466 -+ SKIP_OPEN_TABLE},
57467 -+ {"CHARACTER_SET_NAME", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0, "Charset",
57468 -+ SKIP_OPEN_TABLE},
57469 -+ {"ID", MY_INT32_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Id",
57470 -+ SKIP_OPEN_TABLE},
57471 -+ {"IS_DEFAULT", 3, MYSQL_TYPE_STRING, 0, 0, "Default", SKIP_OPEN_TABLE},
57472 -+ {"IS_COMPILED", 3, MYSQL_TYPE_STRING, 0, 0, "Compiled", SKIP_OPEN_TABLE},
57473 -+ {"SORTLEN", 3, MYSQL_TYPE_LONGLONG, 0, 0, "Sortlen", SKIP_OPEN_TABLE},
57474 -+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
57475 -+};
57476 -+
57477 -+
57478 -+ST_FIELD_INFO engines_fields_info[]=
57479 -+{
57480 -+ {"ENGINE", 64, MYSQL_TYPE_STRING, 0, 0, "Engine", SKIP_OPEN_TABLE},
57481 -+ {"SUPPORT", 8, MYSQL_TYPE_STRING, 0, 0, "Support", SKIP_OPEN_TABLE},
57482 -+ {"COMMENT", 80, MYSQL_TYPE_STRING, 0, 0, "Comment", SKIP_OPEN_TABLE},
57483 -+ {"TRANSACTIONS", 3, MYSQL_TYPE_STRING, 0, 1, "Transactions", SKIP_OPEN_TABLE},
57484 -+ {"XA", 3, MYSQL_TYPE_STRING, 0, 1, "XA", SKIP_OPEN_TABLE},
57485 -+ {"SAVEPOINTS", 3 ,MYSQL_TYPE_STRING, 0, 1, "Savepoints", SKIP_OPEN_TABLE},
57486 -+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
57487 -+};
57488 -+
57489 -+
57490 -+ST_FIELD_INFO events_fields_info[]=
57491 -+{
57492 -+ {"EVENT_CATALOG", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
57493 -+ {"EVENT_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Db",
57494 -+ SKIP_OPEN_TABLE},
57495 -+ {"EVENT_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Name",
57496 -+ SKIP_OPEN_TABLE},
57497 -+ {"DEFINER", 77, MYSQL_TYPE_STRING, 0, 0, "Definer", SKIP_OPEN_TABLE},
57498 -+ {"TIME_ZONE", 64, MYSQL_TYPE_STRING, 0, 0, "Time zone", SKIP_OPEN_TABLE},
57499 -+ {"EVENT_BODY", 8, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
57500 -+ {"EVENT_DEFINITION", 65535, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
57501 -+ {"EVENT_TYPE", 9, MYSQL_TYPE_STRING, 0, 0, "Type", SKIP_OPEN_TABLE},
57502 -+ {"EXECUTE_AT", 0, MYSQL_TYPE_DATETIME, 0, 1, "Execute at", SKIP_OPEN_TABLE},
57503 -+ {"INTERVAL_VALUE", 256, MYSQL_TYPE_STRING, 0, 1, "Interval value",
57504 -+ SKIP_OPEN_TABLE},
57505 -+ {"INTERVAL_FIELD", 18, MYSQL_TYPE_STRING, 0, 1, "Interval field",
57506 -+ SKIP_OPEN_TABLE},
57507 -+ {"SQL_MODE", 32*256, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
57508 -+ {"STARTS", 0, MYSQL_TYPE_DATETIME, 0, 1, "Starts", SKIP_OPEN_TABLE},
57509 -+ {"ENDS", 0, MYSQL_TYPE_DATETIME, 0, 1, "Ends", SKIP_OPEN_TABLE},
57510 -+ {"STATUS", 18, MYSQL_TYPE_STRING, 0, 0, "Status", SKIP_OPEN_TABLE},
57511 -+ {"ON_COMPLETION", 12, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
57512 -+ {"CREATED", 0, MYSQL_TYPE_DATETIME, 0, 0, 0, SKIP_OPEN_TABLE},
57513 -+ {"LAST_ALTERED", 0, MYSQL_TYPE_DATETIME, 0, 0, 0, SKIP_OPEN_TABLE},
57514 -+ {"LAST_EXECUTED", 0, MYSQL_TYPE_DATETIME, 0, 1, 0, SKIP_OPEN_TABLE},
57515 -+ {"EVENT_COMMENT", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
57516 -+ {"ORIGINATOR", 10, MYSQL_TYPE_LONGLONG, 0, 0, "Originator", SKIP_OPEN_TABLE},
57517 -+ {"CHARACTER_SET_CLIENT", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0,
57518 -+ "character_set_client", SKIP_OPEN_TABLE},
57519 -+ {"COLLATION_CONNECTION", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0,
57520 -+ "collation_connection", SKIP_OPEN_TABLE},
57521 -+ {"DATABASE_COLLATION", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0,
57522 -+ "Database Collation", SKIP_OPEN_TABLE},
57523 -+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
57524 -+};
57525 -+
57526 -+
57527 -+
57528 -+ST_FIELD_INFO coll_charset_app_fields_info[]=
57529 -+{
57530 -+ {"COLLATION_NAME", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0, 0,
57531 -+ SKIP_OPEN_TABLE},
57532 -+ {"CHARACTER_SET_NAME", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0, 0,
57533 -+ SKIP_OPEN_TABLE},
57534 -+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
57535 -+};
57536 -+
57537 -+
57538 -+ST_FIELD_INFO proc_fields_info[]=
57539 -+{
57540 -+ {"SPECIFIC_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
57541 -+ {"ROUTINE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
57542 -+ {"ROUTINE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Db",
57543 -+ SKIP_OPEN_TABLE},
57544 -+ {"ROUTINE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Name",
57545 -+ SKIP_OPEN_TABLE},
57546 -+ {"ROUTINE_TYPE", 9, MYSQL_TYPE_STRING, 0, 0, "Type", SKIP_OPEN_TABLE},
57547 -+ {"DTD_IDENTIFIER", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
57548 -+ {"ROUTINE_BODY", 8, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
57549 -+ {"ROUTINE_DEFINITION", 65535, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
57550 -+ {"EXTERNAL_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
57551 -+ {"EXTERNAL_LANGUAGE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0,
57552 -+ SKIP_OPEN_TABLE},
57553 -+ {"PARAMETER_STYLE", 8, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
57554 -+ {"IS_DETERMINISTIC", 3, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
57555 -+ {"SQL_DATA_ACCESS", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
57556 -+ SKIP_OPEN_TABLE},
57557 -+ {"SQL_PATH", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
57558 -+ {"SECURITY_TYPE", 7, MYSQL_TYPE_STRING, 0, 0, "Security_type",
57559 -+ SKIP_OPEN_TABLE},
57560 -+ {"CREATED", 0, MYSQL_TYPE_DATETIME, 0, 0, "Created", SKIP_OPEN_TABLE},
57561 -+ {"LAST_ALTERED", 0, MYSQL_TYPE_DATETIME, 0, 0, "Modified", SKIP_OPEN_TABLE},
57562 -+ {"SQL_MODE", 32*256, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
57563 -+ {"ROUTINE_COMMENT", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Comment",
57564 -+ SKIP_OPEN_TABLE},
57565 -+ {"DEFINER", 77, MYSQL_TYPE_STRING, 0, 0, "Definer", SKIP_OPEN_TABLE},
57566 -+ {"CHARACTER_SET_CLIENT", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0,
57567 -+ "character_set_client", SKIP_OPEN_TABLE},
57568 -+ {"COLLATION_CONNECTION", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0,
57569 -+ "collation_connection", SKIP_OPEN_TABLE},
57570 -+ {"DATABASE_COLLATION", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0,
57571 -+ "Database Collation", SKIP_OPEN_TABLE},
57572 -+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
57573 -+};
57574 -+
57575 -+
57576 -+ST_FIELD_INFO stat_fields_info[]=
57577 -+{
57578 -+ {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FRM_ONLY},
57579 -+ {"TABLE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
57580 -+ {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Table", OPEN_FRM_ONLY},
57581 -+ {"NON_UNIQUE", 1, MYSQL_TYPE_LONGLONG, 0, 0, "Non_unique", OPEN_FRM_ONLY},
57582 -+ {"INDEX_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
57583 -+ {"INDEX_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Key_name",
57584 -+ OPEN_FRM_ONLY},
57585 -+ {"SEQ_IN_INDEX", 2, MYSQL_TYPE_LONGLONG, 0, 0, "Seq_in_index", OPEN_FRM_ONLY},
57586 -+ {"COLUMN_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Column_name",
57587 -+ OPEN_FRM_ONLY},
57588 -+ {"COLLATION", 1, MYSQL_TYPE_STRING, 0, 1, "Collation", OPEN_FRM_ONLY},
57589 -+ {"CARDINALITY", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 1,
57590 -+ "Cardinality", OPEN_FULL_TABLE},
57591 -+ {"SUB_PART", 3, MYSQL_TYPE_LONGLONG, 0, 1, "Sub_part", OPEN_FRM_ONLY},
57592 -+ {"PACKED", 10, MYSQL_TYPE_STRING, 0, 1, "Packed", OPEN_FRM_ONLY},
57593 -+ {"NULLABLE", 3, MYSQL_TYPE_STRING, 0, 0, "Null", OPEN_FRM_ONLY},
57594 -+ {"INDEX_TYPE", 16, MYSQL_TYPE_STRING, 0, 0, "Index_type", OPEN_FULL_TABLE},
57595 -+ {"COMMENT", 16, MYSQL_TYPE_STRING, 0, 1, "Comment", OPEN_FRM_ONLY},
57596 -+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
57597 -+};
57598 -+
57599 -+
57600 -+ST_FIELD_INFO view_fields_info[]=
57601 -+{
57602 -+ {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FRM_ONLY},
57603 -+ {"TABLE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
57604 -+ {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
57605 -+ {"VIEW_DEFINITION", 65535, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
57606 -+ {"CHECK_OPTION", 8, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
57607 -+ {"IS_UPDATABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
57608 -+ {"DEFINER", 77, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
57609 -+ {"SECURITY_TYPE", 7, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
57610 -+ {"CHARACTER_SET_CLIENT", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0, 0,
57611 -+ OPEN_FULL_TABLE},
57612 -+ {"COLLATION_CONNECTION", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0, 0,
57613 -+ OPEN_FULL_TABLE},
57614 -+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
57615 -+};
57616 -+
57617 -+
57618 -+ST_FIELD_INFO user_privileges_fields_info[]=
57619 -+{
57620 -+ {"GRANTEE", 81, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
57621 -+ {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
57622 -+ {"PRIVILEGE_TYPE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
57623 -+ {"IS_GRANTABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
57624 -+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
57625 -+};
57626 -+
57627 -+
57628 -+ST_FIELD_INFO schema_privileges_fields_info[]=
57629 -+{
57630 -+ {"GRANTEE", 81, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
57631 -+ {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
57632 -+ {"TABLE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
57633 -+ {"PRIVILEGE_TYPE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
57634 -+ {"IS_GRANTABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
57635 -+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
57636 -+};
57637 -+
57638 -+
57639 -+ST_FIELD_INFO table_privileges_fields_info[]=
57640 -+{
57641 -+ {"GRANTEE", 81, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
57642 -+ {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
57643 -+ {"TABLE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
57644 -+ {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
57645 -+ {"PRIVILEGE_TYPE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
57646 -+ {"IS_GRANTABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
57647 -+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
57648 -+};
57649 -+
57650 -+
57651 -+ST_FIELD_INFO column_privileges_fields_info[]=
57652 -+{
57653 -+ {"GRANTEE", 81, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
57654 -+ {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
57655 -+ {"TABLE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
57656 -+ {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
57657 -+ {"COLUMN_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
57658 -+ {"PRIVILEGE_TYPE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
57659 -+ {"IS_GRANTABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
57660 -+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
57661 -+};
57662 -+
57663 -+
57664 -+ST_FIELD_INFO table_constraints_fields_info[]=
57665 -+{
57666 -+ {"CONSTRAINT_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
57667 -+ {"CONSTRAINT_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
57668 -+ OPEN_FULL_TABLE},
57669 -+ {"CONSTRAINT_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
57670 -+ OPEN_FULL_TABLE},
57671 -+ {"TABLE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
57672 -+ {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
57673 -+ {"CONSTRAINT_TYPE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
57674 -+ OPEN_FULL_TABLE},
57675 -+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
57676 -+};
57677 -+
57678 -+
57679 -+ST_FIELD_INFO key_column_usage_fields_info[]=
57680 -+{
57681 -+ {"CONSTRAINT_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
57682 -+ {"CONSTRAINT_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
57683 -+ OPEN_FULL_TABLE},
57684 -+ {"CONSTRAINT_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
57685 -+ OPEN_FULL_TABLE},
57686 -+ {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
57687 -+ {"TABLE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
57688 -+ {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
57689 -+ {"COLUMN_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
57690 -+ {"ORDINAL_POSITION", 10 ,MYSQL_TYPE_LONGLONG, 0, 0, 0, OPEN_FULL_TABLE},
57691 -+ {"POSITION_IN_UNIQUE_CONSTRAINT", 10 ,MYSQL_TYPE_LONGLONG, 0, 1, 0,
57692 -+ OPEN_FULL_TABLE},
57693 -+ {"REFERENCED_TABLE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0,
57694 -+ OPEN_FULL_TABLE},
57695 -+ {"REFERENCED_TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0,
57696 -+ OPEN_FULL_TABLE},
57697 -+ {"REFERENCED_COLUMN_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0,
57698 -+ OPEN_FULL_TABLE},
57699 -+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
57700 -+};
57701 -+
57702 -+
57703 -+ST_FIELD_INFO table_names_fields_info[]=
57704 -+{
57705 -+ {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
57706 -+ {"TABLE_SCHEMA",NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
57707 -+ {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Tables_in_",
57708 -+ SKIP_OPEN_TABLE},
57709 -+ {"TABLE_TYPE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Table_type",
57710 -+ OPEN_FRM_ONLY},
57711 -+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
57712 -+};
57713 -+
57714 -+
57715 -+ST_FIELD_INFO open_tables_fields_info[]=
57716 -+{
57717 -+ {"Database", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Database",
57718 -+ SKIP_OPEN_TABLE},
57719 -+ {"Table",NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Table", SKIP_OPEN_TABLE},
57720 -+ {"In_use", 1, MYSQL_TYPE_LONGLONG, 0, 0, "In_use", SKIP_OPEN_TABLE},
57721 -+ {"Name_locked", 4, MYSQL_TYPE_LONGLONG, 0, 0, "Name_locked", SKIP_OPEN_TABLE},
57722 -+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
57723 -+};
57724 -+
57725 -+
57726 -+ST_FIELD_INFO triggers_fields_info[]=
57727 -+{
57728 -+ {"TRIGGER_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
57729 -+ {"TRIGGER_SCHEMA",NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
57730 -+ {"TRIGGER_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Trigger",
57731 -+ OPEN_FULL_TABLE},
57732 -+ {"EVENT_MANIPULATION", 6, MYSQL_TYPE_STRING, 0, 0, "Event", OPEN_FULL_TABLE},
57733 -+ {"EVENT_OBJECT_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0,
57734 -+ OPEN_FULL_TABLE},
57735 -+ {"EVENT_OBJECT_SCHEMA",NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
57736 -+ OPEN_FULL_TABLE},
57737 -+ {"EVENT_OBJECT_TABLE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Table",
57738 -+ OPEN_FULL_TABLE},
57739 -+ {"ACTION_ORDER", 4, MYSQL_TYPE_LONGLONG, 0, 0, 0, OPEN_FULL_TABLE},
57740 -+ {"ACTION_CONDITION", 65535, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
57741 -+ {"ACTION_STATEMENT", 65535, MYSQL_TYPE_STRING, 0, 0, "Statement",
57742 -+ OPEN_FULL_TABLE},
57743 -+ {"ACTION_ORIENTATION", 9, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
57744 -+ {"ACTION_TIMING", 6, MYSQL_TYPE_STRING, 0, 0, "Timing", OPEN_FULL_TABLE},
57745 -+ {"ACTION_REFERENCE_OLD_TABLE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0,
57746 -+ OPEN_FULL_TABLE},
57747 -+ {"ACTION_REFERENCE_NEW_TABLE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0,
57748 -+ OPEN_FULL_TABLE},
57749 -+ {"ACTION_REFERENCE_OLD_ROW", 3, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
57750 -+ {"ACTION_REFERENCE_NEW_ROW", 3, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
57751 -+ {"CREATED", 0, MYSQL_TYPE_DATETIME, 0, 1, "Created", OPEN_FULL_TABLE},
57752 -+ {"SQL_MODE", 32*256, MYSQL_TYPE_STRING, 0, 0, "sql_mode", OPEN_FULL_TABLE},
57753 -+ {"DEFINER", 77, MYSQL_TYPE_STRING, 0, 0, "Definer", OPEN_FULL_TABLE},
57754 -+ {"CHARACTER_SET_CLIENT", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0,
57755 -+ "character_set_client", OPEN_FULL_TABLE},
57756 -+ {"COLLATION_CONNECTION", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0,
57757 -+ "collation_connection", OPEN_FULL_TABLE},
57758 -+ {"DATABASE_COLLATION", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0,
57759 -+ "Database Collation", OPEN_FULL_TABLE},
57760 -+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
57761 -+};
57762 -+
57763 -+
57764 -+ST_FIELD_INFO partitions_fields_info[]=
57765 -+{
57766 -+ {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
57767 -+ {"TABLE_SCHEMA",NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
57768 -+ {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
57769 -+ {"PARTITION_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
57770 -+ {"SUBPARTITION_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0,
57771 -+ OPEN_FULL_TABLE},
57772 -+ {"PARTITION_ORDINAL_POSITION", 21 , MYSQL_TYPE_LONGLONG, 0,
57773 -+ (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), 0, OPEN_FULL_TABLE},
57774 -+ {"SUBPARTITION_ORDINAL_POSITION", 21 , MYSQL_TYPE_LONGLONG, 0,
57775 -+ (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), 0, OPEN_FULL_TABLE},
57776 -+ {"PARTITION_METHOD", 12, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
57777 -+ {"SUBPARTITION_METHOD", 12, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
57778 -+ {"PARTITION_EXPRESSION", 65535, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
57779 -+ {"SUBPARTITION_EXPRESSION", 65535, MYSQL_TYPE_STRING, 0, 1, 0,
57780 -+ OPEN_FULL_TABLE},
57781 -+ {"PARTITION_DESCRIPTION", 65535, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
57782 -+ {"TABLE_ROWS", 21 , MYSQL_TYPE_LONGLONG, 0, MY_I_S_UNSIGNED, 0,
57783 -+ OPEN_FULL_TABLE},
57784 -+ {"AVG_ROW_LENGTH", 21 , MYSQL_TYPE_LONGLONG, 0, MY_I_S_UNSIGNED, 0,
57785 -+ OPEN_FULL_TABLE},
57786 -+ {"DATA_LENGTH", 21 , MYSQL_TYPE_LONGLONG, 0, MY_I_S_UNSIGNED, 0,
57787 -+ OPEN_FULL_TABLE},
57788 -+ {"MAX_DATA_LENGTH", 21 , MYSQL_TYPE_LONGLONG, 0,
57789 -+ (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), 0, OPEN_FULL_TABLE},
57790 -+ {"INDEX_LENGTH", 21 , MYSQL_TYPE_LONGLONG, 0, MY_I_S_UNSIGNED, 0,
57791 -+ OPEN_FULL_TABLE},
57792 -+ {"DATA_FREE", 21 , MYSQL_TYPE_LONGLONG, 0, MY_I_S_UNSIGNED, 0,
57793 -+ OPEN_FULL_TABLE},
57794 -+ {"CREATE_TIME", 0, MYSQL_TYPE_DATETIME, 0, 1, 0, OPEN_FULL_TABLE},
57795 -+ {"UPDATE_TIME", 0, MYSQL_TYPE_DATETIME, 0, 1, 0, OPEN_FULL_TABLE},
57796 -+ {"CHECK_TIME", 0, MYSQL_TYPE_DATETIME, 0, 1, 0, OPEN_FULL_TABLE},
57797 -+ {"CHECKSUM", 21 , MYSQL_TYPE_LONGLONG, 0,
57798 -+ (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), 0, OPEN_FULL_TABLE},
57799 -+ {"PARTITION_COMMENT", 80, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
57800 -+ {"NODEGROUP", 12 , MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
57801 -+ {"TABLESPACE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0,
57802 -+ OPEN_FULL_TABLE},
57803 -+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
57804 -+};
57805 -+
57806 -+
57807 -+ST_FIELD_INFO variables_fields_info[]=
57808 -+{
57809 -+ {"VARIABLE_NAME", 64, MYSQL_TYPE_STRING, 0, 0, "Variable_name",
57810 -+ SKIP_OPEN_TABLE},
57811 -+ {"VARIABLE_VALUE", 1024, MYSQL_TYPE_STRING, 0, 1, "Value", SKIP_OPEN_TABLE},
57812 -+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
57813 -+};
57814 -+
57815 -+
57816 -+ST_FIELD_INFO processlist_fields_info[]=
57817 -+{
57818 -+ {"ID", 4, MYSQL_TYPE_LONGLONG, 0, 0, "Id", SKIP_OPEN_TABLE},
57819 -+ {"USER", 16, MYSQL_TYPE_STRING, 0, 0, "User", SKIP_OPEN_TABLE},
57820 -+ {"HOST", LIST_PROCESS_HOST_LEN, MYSQL_TYPE_STRING, 0, 0, "Host",
57821 -+ SKIP_OPEN_TABLE},
57822 -+ {"DB", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, "Db", SKIP_OPEN_TABLE},
57823 -+ {"COMMAND", 16, MYSQL_TYPE_STRING, 0, 0, "Command", SKIP_OPEN_TABLE},
57824 -+ {"TIME", 7, MYSQL_TYPE_LONG, 0, 0, "Time", SKIP_OPEN_TABLE},
57825 -+ {"STATE", 64, MYSQL_TYPE_STRING, 0, 1, "State", SKIP_OPEN_TABLE},
57826 -+ {"INFO", PROCESS_LIST_INFO_WIDTH, MYSQL_TYPE_STRING, 0, 1, "Info",
57827 -+ SKIP_OPEN_TABLE},
57828 -+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
57829 -+};
57830 -+
57831 -+
57832 -+ST_FIELD_INFO plugin_fields_info[]=
57833 -+{
57834 -+ {"PLUGIN_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Name",
57835 -+ SKIP_OPEN_TABLE},
57836 -+ {"PLUGIN_VERSION", 20, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
57837 -+ {"PLUGIN_STATUS", 10, MYSQL_TYPE_STRING, 0, 0, "Status", SKIP_OPEN_TABLE},
57838 -+ {"PLUGIN_TYPE", 80, MYSQL_TYPE_STRING, 0, 0, "Type", SKIP_OPEN_TABLE},
57839 -+ {"PLUGIN_TYPE_VERSION", 20, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
57840 -+ {"PLUGIN_LIBRARY", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, "Library",
57841 -+ SKIP_OPEN_TABLE},
57842 -+ {"PLUGIN_LIBRARY_VERSION", 20, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
57843 -+ {"PLUGIN_AUTHOR", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
57844 -+ {"PLUGIN_DESCRIPTION", 65535, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
57845 -+ {"PLUGIN_LICENSE", 80, MYSQL_TYPE_STRING, 0, 1, "License", SKIP_OPEN_TABLE},
57846 -+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
57847 -+};
57848 -+
57849 -+ST_FIELD_INFO files_fields_info[]=
57850 -+{
57851 -+ {"FILE_ID", 4, MYSQL_TYPE_LONGLONG, 0, 0, 0, SKIP_OPEN_TABLE},
57852 -+ {"FILE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
57853 -+ {"FILE_TYPE", 20, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
57854 -+ {"TABLESPACE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0,
57855 -+ SKIP_OPEN_TABLE},
57856 -+ {"TABLE_CATALOG", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
57857 -+ {"TABLE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
57858 -+ {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
57859 -+ {"LOGFILE_GROUP_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0,
57860 -+ SKIP_OPEN_TABLE},
57861 -+ {"LOGFILE_GROUP_NUMBER", 4, MYSQL_TYPE_LONGLONG, 0, 1, 0, SKIP_OPEN_TABLE},
57862 -+ {"ENGINE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
57863 -+ {"FULLTEXT_KEYS", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
57864 -+ {"DELETED_ROWS", 4, MYSQL_TYPE_LONGLONG, 0, 1, 0, SKIP_OPEN_TABLE},
57865 -+ {"UPDATE_COUNT", 4, MYSQL_TYPE_LONGLONG, 0, 1, 0, SKIP_OPEN_TABLE},
57866 -+ {"FREE_EXTENTS", 4, MYSQL_TYPE_LONGLONG, 0, 1, 0, SKIP_OPEN_TABLE},
57867 -+ {"TOTAL_EXTENTS", 4, MYSQL_TYPE_LONGLONG, 0, 1, 0, SKIP_OPEN_TABLE},
57868 -+ {"EXTENT_SIZE", 4, MYSQL_TYPE_LONGLONG, 0, 0, 0, SKIP_OPEN_TABLE},
57869 -+ {"INITIAL_SIZE", 21, MYSQL_TYPE_LONGLONG, 0,
57870 -+ (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), 0, SKIP_OPEN_TABLE},
57871 -+ {"MAXIMUM_SIZE", 21, MYSQL_TYPE_LONGLONG, 0,
57872 -+ (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), 0, SKIP_OPEN_TABLE},
57873 -+ {"AUTOEXTEND_SIZE", 21, MYSQL_TYPE_LONGLONG, 0,
57874 -+ (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), 0, SKIP_OPEN_TABLE},
57875 -+ {"CREATION_TIME", 0, MYSQL_TYPE_DATETIME, 0, 1, 0, SKIP_OPEN_TABLE},
57876 -+ {"LAST_UPDATE_TIME", 0, MYSQL_TYPE_DATETIME, 0, 1, 0, SKIP_OPEN_TABLE},
57877 -+ {"LAST_ACCESS_TIME", 0, MYSQL_TYPE_DATETIME, 0, 1, 0, SKIP_OPEN_TABLE},
57878 -+ {"RECOVER_TIME", 4, MYSQL_TYPE_LONGLONG, 0, 1, 0, SKIP_OPEN_TABLE},
57879 -+ {"TRANSACTION_COUNTER", 4, MYSQL_TYPE_LONGLONG, 0, 1, 0, SKIP_OPEN_TABLE},
57880 -+ {"VERSION", 21 , MYSQL_TYPE_LONGLONG, 0,
57881 -+ (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Version", SKIP_OPEN_TABLE},
57882 -+ {"ROW_FORMAT", 10, MYSQL_TYPE_STRING, 0, 1, "Row_format", SKIP_OPEN_TABLE},
57883 -+ {"TABLE_ROWS", 21 , MYSQL_TYPE_LONGLONG, 0,
57884 -+ (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Rows", SKIP_OPEN_TABLE},
57885 -+ {"AVG_ROW_LENGTH", 21 , MYSQL_TYPE_LONGLONG, 0,
57886 -+ (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Avg_row_length", SKIP_OPEN_TABLE},
57887 -+ {"DATA_LENGTH", 21 , MYSQL_TYPE_LONGLONG, 0,
57888 -+ (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Data_length", SKIP_OPEN_TABLE},
57889 -+ {"MAX_DATA_LENGTH", 21 , MYSQL_TYPE_LONGLONG, 0,
57890 -+ (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Max_data_length", SKIP_OPEN_TABLE},
57891 -+ {"INDEX_LENGTH", 21 , MYSQL_TYPE_LONGLONG, 0,
57892 -+ (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Index_length", SKIP_OPEN_TABLE},
57893 -+ {"DATA_FREE", 21 , MYSQL_TYPE_LONGLONG, 0,
57894 -+ (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Data_free", SKIP_OPEN_TABLE},
57895 -+ {"CREATE_TIME", 0, MYSQL_TYPE_DATETIME, 0, 1, "Create_time", SKIP_OPEN_TABLE},
57896 -+ {"UPDATE_TIME", 0, MYSQL_TYPE_DATETIME, 0, 1, "Update_time", SKIP_OPEN_TABLE},
57897 -+ {"CHECK_TIME", 0, MYSQL_TYPE_DATETIME, 0, 1, "Check_time", SKIP_OPEN_TABLE},
57898 -+ {"CHECKSUM", 21 , MYSQL_TYPE_LONGLONG, 0,
57899 -+ (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Checksum", SKIP_OPEN_TABLE},
57900 -+ {"STATUS", 20, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
57901 -+ {"EXTRA", 255, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
57902 -+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
57903 -+};
57904 -+
57905 -+void init_fill_schema_files_row(TABLE* table)
57906 -+{
57907 -+ int i;
57908 -+ for(i=0; files_fields_info[i].field_name!=NULL; i++)
57909 -+ table->field[i]->set_null();
57910 -+
57911 -+ table->field[IS_FILES_STATUS]->set_notnull();
57912 -+ table->field[IS_FILES_STATUS]->store("NORMAL", 6, system_charset_info);
57913 -+}
57914 -+
57915 -+ST_FIELD_INFO referential_constraints_fields_info[]=
57916 -+{
57917 -+ {"CONSTRAINT_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
57918 -+ {"CONSTRAINT_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
57919 -+ OPEN_FULL_TABLE},
57920 -+ {"CONSTRAINT_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
57921 -+ OPEN_FULL_TABLE},
57922 -+ {"UNIQUE_CONSTRAINT_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0,
57923 -+ OPEN_FULL_TABLE},
57924 -+ {"UNIQUE_CONSTRAINT_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
57925 -+ OPEN_FULL_TABLE},
57926 -+ {"UNIQUE_CONSTRAINT_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0,
57927 -+ MY_I_S_MAYBE_NULL, 0, OPEN_FULL_TABLE},
57928 -+ {"MATCH_OPTION", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
57929 -+ {"UPDATE_RULE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
57930 -+ {"DELETE_RULE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
57931 -+ {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
57932 -+ {"REFERENCED_TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
57933 -+ OPEN_FULL_TABLE},
57934 -+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
57935 -+};
57936 -+
57937 -+
57938 -+/*
57939 -+ Description of ST_FIELD_INFO in table.h
57940 -+
57941 -+ Make sure that the order of schema_tables and enum_schema_tables are the same.
57942 -+
57943 -+*/
57944 -+
57945 -+ST_SCHEMA_TABLE schema_tables[]=
57946 -+{
57947 -+ {"CHARACTER_SETS", charsets_fields_info, create_schema_table,
57948 -+ fill_schema_charsets, make_character_sets_old_format, 0, -1, -1, 0, 0},
57949 -+ {"COLLATIONS", collation_fields_info, create_schema_table,
57950 -+ fill_schema_collation, make_old_format, 0, -1, -1, 0, 0},
57951 -+ {"COLLATION_CHARACTER_SET_APPLICABILITY", coll_charset_app_fields_info,
57952 -+ create_schema_table, fill_schema_coll_charset_app, 0, 0, -1, -1, 0, 0},
57953 -+ {"COLUMNS", columns_fields_info, create_schema_table,
57954 -+ get_all_tables, make_columns_old_format, get_schema_column_record, 1, 2, 0,
57955 -+ OPTIMIZE_I_S_TABLE|OPEN_VIEW_FULL},
57956 -+ {"COLUMN_PRIVILEGES", column_privileges_fields_info, create_schema_table,
57957 -+ fill_schema_column_privileges, 0, 0, -1, -1, 0, 0},
57958 -+ {"ENGINES", engines_fields_info, create_schema_table,
57959 -+ fill_schema_engines, make_old_format, 0, -1, -1, 0, 0},
57960 -+#ifdef HAVE_EVENT_SCHEDULER
57961 -+ {"EVENTS", events_fields_info, create_schema_table,
57962 -+ Events::fill_schema_events, make_old_format, 0, -1, -1, 0, 0},
57963 -+#else
57964 -+ {"EVENTS", events_fields_info, create_schema_table,
57965 -+ 0, make_old_format, 0, -1, -1, 0, 0},
57966 -+#endif
57967 -+ {"FILES", files_fields_info, create_schema_table,
57968 -+ fill_schema_files, 0, 0, -1, -1, 0, 0},
57969 -+ {"GLOBAL_STATUS", variables_fields_info, create_schema_table,
57970 -+ fill_status, make_old_format, 0, 0, -1, 0, 0},
57971 -+ {"GLOBAL_VARIABLES", variables_fields_info, create_schema_table,
57972 -+ fill_variables, make_old_format, 0, 0, -1, 0, 0},
57973 -+ {"KEY_COLUMN_USAGE", key_column_usage_fields_info, create_schema_table,
57974 -+ get_all_tables, 0, get_schema_key_column_usage_record, 4, 5, 0,
57975 -+ OPEN_TABLE_ONLY},
57976 -+ {"OPEN_TABLES", open_tables_fields_info, create_schema_table,
57977 -+ fill_open_tables, make_old_format, 0, -1, -1, 1, 0},
57978 -+ {"PARTITIONS", partitions_fields_info, create_schema_table,
57979 -+ get_all_tables, 0, get_schema_partitions_record, 1, 2, 0, OPEN_TABLE_ONLY},
57980 -+ {"PLUGINS", plugin_fields_info, create_schema_table,
57981 -+ fill_plugins, make_old_format, 0, -1, -1, 0, 0},
57982 -+ {"PROCESSLIST", processlist_fields_info, create_schema_table,
57983 -+ fill_schema_processlist, make_old_format, 0, -1, -1, 0, 0},
57984 -+ {"PROFILING", query_profile_statistics_info, create_schema_table,
57985 -+ fill_query_profile_statistics_info, make_profile_table_for_show,
57986 -+ NULL, -1, -1, false, 0},
57987 -+ {"REFERENTIAL_CONSTRAINTS", referential_constraints_fields_info,
57988 -+ create_schema_table, get_all_tables, 0, get_referential_constraints_record,
57989 -+ 1, 9, 0, OPEN_TABLE_ONLY},
57990 -+ {"ROUTINES", proc_fields_info, create_schema_table,
57991 -+ fill_schema_proc, make_proc_old_format, 0, -1, -1, 0, 0},
57992 -+ {"SCHEMATA", schema_fields_info, create_schema_table,
57993 -+ fill_schema_schemata, make_schemata_old_format, 0, 1, -1, 0, 0},
57994 -+ {"SCHEMA_PRIVILEGES", schema_privileges_fields_info, create_schema_table,
57995 -+ fill_schema_schema_privileges, 0, 0, -1, -1, 0, 0},
57996 -+ {"SESSION_STATUS", variables_fields_info, create_schema_table,
57997 -+ fill_status, make_old_format, 0, 0, -1, 0, 0},
57998 -+ {"SESSION_VARIABLES", variables_fields_info, create_schema_table,
57999 -+ fill_variables, make_old_format, 0, 0, -1, 0, 0},
58000 -+ {"STATISTICS", stat_fields_info, create_schema_table,
58001 -+ get_all_tables, make_old_format, get_schema_stat_record, 1, 2, 0,
58002 -+ OPEN_TABLE_ONLY|OPTIMIZE_I_S_TABLE},
58003 -+ {"STATUS", variables_fields_info, create_schema_table, fill_status,
58004 -+ make_old_format, 0, 0, -1, 1, 0},
58005 -+ {"TABLES", tables_fields_info, create_schema_table,
58006 -+ get_all_tables, make_old_format, get_schema_tables_record, 1, 2, 0,
58007 -+ OPTIMIZE_I_S_TABLE},
58008 -+ {"TABLE_CONSTRAINTS", table_constraints_fields_info, create_schema_table,
58009 -+ get_all_tables, 0, get_schema_constraints_record, 3, 4, 0, OPEN_TABLE_ONLY},
58010 -+ {"TABLE_NAMES", table_names_fields_info, create_schema_table,
58011 -+ get_all_tables, make_table_names_old_format, 0, 1, 2, 1, 0},
58012 -+ {"TABLE_PRIVILEGES", table_privileges_fields_info, create_schema_table,
58013 -+ fill_schema_table_privileges, 0, 0, -1, -1, 0, 0},
58014 -+ {"TRIGGERS", triggers_fields_info, create_schema_table,
58015 -+ get_all_tables, make_old_format, get_schema_triggers_record, 5, 6, 0,
58016 -+ OPEN_TABLE_ONLY},
58017 -+ {"USER_PRIVILEGES", user_privileges_fields_info, create_schema_table,
58018 -+ fill_schema_user_privileges, 0, 0, -1, -1, 0, 0},
58019 -+ {"VARIABLES", variables_fields_info, create_schema_table, fill_variables,
58020 -+ make_old_format, 0, 0, -1, 1, 0},
58021 -+ {"VIEWS", view_fields_info, create_schema_table,
58022 -+ get_all_tables, 0, get_schema_views_record, 1, 2, 0,
58023 -+ OPEN_VIEW_ONLY|OPTIMIZE_I_S_TABLE},
58024 -+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
58025 -+};
58026 -+
58027 -+
58028 -+#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
58029 -+template class List_iterator_fast<char>;
58030 -+template class List<char>;
58031 -+#endif
58032 -+
58033 -+int initialize_schema_table(st_plugin_int *plugin)
58034 -+{
58035 -+ ST_SCHEMA_TABLE *schema_table;
58036 -+ DBUG_ENTER("initialize_schema_table");
58037 -+
58038 -+ if (!(schema_table= (ST_SCHEMA_TABLE *)my_malloc(sizeof(ST_SCHEMA_TABLE),
58039 -+ MYF(MY_WME | MY_ZEROFILL))))
58040 -+ DBUG_RETURN(1);
58041 -+ /* Historical Requirement */
58042 -+ plugin->data= schema_table; // shortcut for the future
58043 -+ if (plugin->plugin->init)
58044 -+ {
58045 -+ schema_table->create_table= create_schema_table;
58046 -+ schema_table->old_format= make_old_format;
58047 -+ schema_table->idx_field1= -1,
58048 -+ schema_table->idx_field2= -1;
58049 -+
58050 -+ /* Make the name available to the init() function. */
58051 -+ schema_table->table_name= plugin->name.str;
58052 -+
58053 -+ if (plugin->plugin->init(schema_table))
58054 -+ {
58055 -+ sql_print_error("Plugin '%s' init function returned error.",
58056 -+ plugin->name.str);
58057 -+ plugin->data= NULL;
58058 -+ my_free(schema_table, MYF(0));
58059 -+ DBUG_RETURN(1);
58060 -+ }
58061 -+
58062 -+ /* Make sure the plugin name is not set inside the init() function. */
58063 -+ schema_table->table_name= plugin->name.str;
58064 -+ }
58065 -+ DBUG_RETURN(0);
58066 -+}
58067 -+
58068 -+int finalize_schema_table(st_plugin_int *plugin)
58069 -+{
58070 -+ ST_SCHEMA_TABLE *schema_table= (ST_SCHEMA_TABLE *)plugin->data;
58071 -+ DBUG_ENTER("finalize_schema_table");
58072 -+
58073 -+ if (schema_table)
58074 -+ {
58075 -+ if (plugin->plugin->deinit)
58076 -+ {
58077 -+ DBUG_PRINT("info", ("Deinitializing plugin: '%s'", plugin->name.str));
58078 -+ if (plugin->plugin->deinit(NULL))
58079 -+ {
58080 -+ DBUG_PRINT("warning", ("Plugin '%s' deinit function returned error.",
58081 -+ plugin->name.str));
58082 -+ }
58083 -+ }
58084 -+ my_free(schema_table, MYF(0));
58085 -+ }
58086 -+ DBUG_RETURN(0);
58087 -+}
58088 -+
58089 -+
58090 -+/**
58091 -+ Output trigger information (SHOW CREATE TRIGGER) to the client.
58092 -+
58093 -+ @param thd Thread context.
58094 -+ @param triggers List of triggers for the table.
58095 -+ @param trigger_idx Index of the trigger to dump.
58096 -+
58097 -+ @return Operation status
58098 -+ @retval TRUE Error.
58099 -+ @retval FALSE Success.
58100 -+*/
58101 -+
58102 -+static bool show_create_trigger_impl(THD *thd,
58103 -+ Table_triggers_list *triggers,
58104 -+ int trigger_idx)
58105 -+{
58106 -+ int ret_code;
58107 -+
58108 -+ Protocol *p= thd->protocol;
58109 -+ List<Item> fields;
58110 -+
58111 -+ LEX_STRING trg_name;
58112 -+ ulonglong trg_sql_mode;
58113 -+ LEX_STRING trg_sql_mode_str;
58114 -+ LEX_STRING trg_sql_original_stmt;
58115 -+ LEX_STRING trg_client_cs_name;
58116 -+ LEX_STRING trg_connection_cl_name;
58117 -+ LEX_STRING trg_db_cl_name;
58118 -+
58119 -+ CHARSET_INFO *trg_client_cs;
58120 -+
58121 -+ /*
58122 -+ TODO: Check privileges here. This functionality will be added by
58123 -+ implementation of the following WL items:
58124 -+ - WL#2227: New privileges for new objects
58125 -+ - WL#3482: Protect SHOW CREATE PROCEDURE | FUNCTION | VIEW | TRIGGER
58126 -+ properly
58127 -+
58128 -+ SHOW TRIGGERS and I_S.TRIGGERS will be affected too.
58129 -+ */
58130 -+
58131 -+ /* Prepare trigger "object". */
58132 -+
58133 -+ triggers->get_trigger_info(thd,
58134 -+ trigger_idx,
58135 -+ &trg_name,
58136 -+ &trg_sql_mode,
58137 -+ &trg_sql_original_stmt,
58138 -+ &trg_client_cs_name,
58139 -+ &trg_connection_cl_name,
58140 -+ &trg_db_cl_name);
58141 -+
58142 -+ sys_var_thd_sql_mode::symbolic_mode_representation(thd,
58143 -+ trg_sql_mode,
58144 -+ &trg_sql_mode_str);
58145 -+
58146 -+ /* Resolve trigger client character set. */
58147 -+
58148 -+ if (resolve_charset(trg_client_cs_name.str, NULL, &trg_client_cs))
58149 -+ return TRUE;
58150 -+
58151 -+ /* Send header. */
58152 -+
58153 -+ fields.push_back(new Item_empty_string("Trigger", NAME_LEN));
58154 -+ fields.push_back(new Item_empty_string("sql_mode", trg_sql_mode_str.length));
58155 -+
58156 -+ {
58157 -+ /*
58158 -+ NOTE: SQL statement field must be not less than 1024 in order not to
58159 -+ confuse old clients.
58160 -+ */
58161 -+
58162 -+ Item_empty_string *stmt_fld=
58163 -+ new Item_empty_string("SQL Original Statement",
58164 -+ max(trg_sql_original_stmt.length, 1024));
58165 -+
58166 -+ stmt_fld->maybe_null= TRUE;
58167 -+
58168 -+ fields.push_back(stmt_fld);
58169 -+ }
58170 -+
58171 -+ fields.push_back(new Item_empty_string("character_set_client",
58172 -+ MY_CS_NAME_SIZE));
58173 -+
58174 -+ fields.push_back(new Item_empty_string("collation_connection",
58175 -+ MY_CS_NAME_SIZE));
58176 -+
58177 -+ fields.push_back(new Item_empty_string("Database Collation",
58178 -+ MY_CS_NAME_SIZE));
58179 -+
58180 -+ if (p->send_fields(&fields, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
58181 -+ return TRUE;
58182 -+
58183 -+ /* Send data. */
58184 -+
58185 -+ p->prepare_for_resend();
58186 -+
58187 -+ p->store(trg_name.str,
58188 -+ trg_name.length,
58189 -+ system_charset_info);
58190 -+
58191 -+ p->store(trg_sql_mode_str.str,
58192 -+ trg_sql_mode_str.length,
58193 -+ system_charset_info);
58194 -+
58195 -+ p->store(trg_sql_original_stmt.str,
58196 -+ trg_sql_original_stmt.length,
58197 -+ trg_client_cs);
58198 -+
58199 -+ p->store(trg_client_cs_name.str,
58200 -+ trg_client_cs_name.length,
58201 -+ system_charset_info);
58202 -+
58203 -+ p->store(trg_connection_cl_name.str,
58204 -+ trg_connection_cl_name.length,
58205 -+ system_charset_info);
58206 -+
58207 -+ p->store(trg_db_cl_name.str,
58208 -+ trg_db_cl_name.length,
58209 -+ system_charset_info);
58210 -+
58211 -+ ret_code= p->write();
58212 -+
58213 -+ if (!ret_code)
58214 -+ my_eof(thd);
58215 -+
58216 -+ return ret_code != 0;
58217 -+}
58218 -+
58219 -+
58220 -+/**
58221 -+ Read TRN and TRG files to obtain base table name for the specified
58222 -+ trigger name and construct TABE_LIST object for the base table.
58223 -+
58224 -+ @param thd Thread context.
58225 -+ @param trg_name Trigger name.
58226 -+
58227 -+ @return TABLE_LIST object corresponding to the base table.
58228 -+
58229 -+ TODO: This function is a copy&paste from add_table_to_list() and
58230 -+ sp_add_to_query_tables(). The problem is that in order to be compatible
58231 -+ with Stored Programs (Prepared Statements), we should not touch thd->lex.
58232 -+ The "source" functions also add created TABLE_LIST object to the
58233 -+ thd->lex->query_tables.
58234 -+
58235 -+ The plan to eliminate this copy&paste is to:
58236 -+
58237 -+ - get rid of sp_add_to_query_tables() and use Lex::add_table_to_list().
58238 -+ Only add_table_to_list() must be used to add tables from the parser
58239 -+ into Lex::query_tables list.
58240 -+
58241 -+ - do not update Lex::query_tables in add_table_to_list().
58242 -+*/
58243 -+
58244 -+static TABLE_LIST *get_trigger_table_impl(
58245 -+ THD *thd,
58246 -+ const sp_name *trg_name)
58247 -+{
58248 -+ char trn_path_buff[FN_REFLEN];
58249 -+
58250 -+ LEX_STRING trn_path= { trn_path_buff, 0 };
58251 -+ LEX_STRING tbl_name;
58252 -+
58253 -+ build_trn_path(thd, trg_name, &trn_path);
58254 -+
58255 -+ if (check_trn_exists(&trn_path))
58256 -+ {
58257 -+ my_error(ER_TRG_DOES_NOT_EXIST, MYF(0));
58258 -+ return NULL;
58259 -+ }
58260 -+
58261 -+ if (load_table_name_for_trigger(thd, trg_name, &trn_path, &tbl_name))
58262 -+ return NULL;
58263 -+
58264 -+ /* We need to reset statement table list to be PS/SP friendly. */
58265 -+
58266 -+ TABLE_LIST *table;
58267 -+
58268 -+ if (!(table= (TABLE_LIST *)thd->calloc(sizeof(TABLE_LIST))))
58269 -+ {
58270 -+ my_error(ER_OUTOFMEMORY, MYF(0), sizeof(TABLE_LIST));
58271 -+ return NULL;
58272 -+ }
58273 -+
58274 -+ table->db_length= trg_name->m_db.length;
58275 -+ table->db= thd->strmake(trg_name->m_db.str, trg_name->m_db.length);
58276 -+
58277 -+ table->table_name_length= tbl_name.length;
58278 -+ table->table_name= thd->strmake(tbl_name.str, tbl_name.length);
58279 -+
58280 -+ table->alias= thd->strmake(tbl_name.str, tbl_name.length);
58281 -+
58282 -+ table->lock_type= TL_IGNORE;
58283 -+ table->cacheable_table= 0;
58284 -+
58285 -+ return table;
58286 -+}
58287 -+
58288 -+/**
58289 -+ Read TRN and TRG files to obtain base table name for the specified
58290 -+ trigger name and construct TABE_LIST object for the base table. Acquire
58291 -+ LOCK_open when doing this.
58292 -+
58293 -+ @param thd Thread context.
58294 -+ @param trg_name Trigger name.
58295 -+
58296 -+ @return TABLE_LIST object corresponding to the base table.
58297 -+*/
58298 -+
58299 -+static TABLE_LIST *get_trigger_table(THD *thd, const sp_name *trg_name)
58300 -+{
58301 -+ /* Acquire LOCK_open (stop the server). */
58302 -+
58303 -+ pthread_mutex_lock(&LOCK_open);
58304 -+
58305 -+ /*
58306 -+ Load base table name from the TRN-file and create TABLE_LIST object.
58307 -+ */
58308 -+
58309 -+ TABLE_LIST *lst= get_trigger_table_impl(thd, trg_name);
58310 -+
58311 -+ /* Release LOCK_open (continue the server). */
58312 -+
58313 -+ pthread_mutex_unlock(&LOCK_open);
58314 -+
58315 -+ /* That's it. */
58316 -+
58317 -+ return lst;
58318 -+}
58319 -+
58320 -+
58321 -+/**
58322 -+ SHOW CREATE TRIGGER high-level implementation.
58323 -+
58324 -+ @param thd Thread context.
58325 -+ @param trg_name Trigger name.
58326 -+
58327 -+ @return Operation status
58328 -+ @retval TRUE Error.
58329 -+ @retval FALSE Success.
58330 -+*/
58331 -+
58332 -+bool show_create_trigger(THD *thd, const sp_name *trg_name)
58333 -+{
58334 -+ TABLE_LIST *lst= get_trigger_table(thd, trg_name);
58335 -+
58336 -+ if (!lst)
58337 -+ return TRUE;
58338 -+
58339 -+ if (check_table_access(thd, TRIGGER_ACL, lst, 1, TRUE))
58340 -+ {
58341 -+ my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "TRIGGER");
58342 -+ return TRUE;
58343 -+ }
58344 -+
58345 -+ /*
58346 -+ Open the table by name in order to load Table_triggers_list object.
58347 -+
58348 -+ NOTE: there is race condition here -- the table can be dropped after
58349 -+ LOCK_open is released. It will be fixed later by introducing
58350 -+ acquire-shared-table-name-lock functionality.
58351 -+ */
58352 -+
58353 -+ uint num_tables; /* NOTE: unused, only to pass to open_tables(). */
58354 -+
58355 -+ if (open_tables(thd, &lst, &num_tables, 0))
58356 -+ {
58357 -+ my_error(ER_TRG_CANT_OPEN_TABLE, MYF(0),
58358 -+ (const char *) trg_name->m_db.str,
58359 -+ (const char *) lst->table_name);
58360 -+
58361 -+ return TRUE;
58362 -+
58363 -+ /* Perform closing actions and return error status. */
58364 -+ }
58365 -+
58366 -+ Table_triggers_list *triggers= lst->table->triggers;
58367 -+
58368 -+ if (!triggers)
58369 -+ {
58370 -+ my_error(ER_TRG_DOES_NOT_EXIST, MYF(0));
58371 -+ return TRUE;
58372 -+ }
58373 -+
58374 -+ int trigger_idx= triggers->find_trigger_by_name(&trg_name->m_name);
58375 -+
58376 -+ if (trigger_idx < 0)
58377 -+ {
58378 -+ my_error(ER_TRG_CORRUPTED_FILE, MYF(0),
58379 -+ (const char *) trg_name->m_db.str,
58380 -+ (const char *) lst->table_name);
58381 -+
58382 -+ return TRUE;
58383 -+ }
58384 -+
58385 -+ return show_create_trigger_impl(thd, triggers, trigger_idx);
58386 -+
58387 -+ /*
58388 -+ NOTE: if show_create_trigger_impl() failed, that means we could not
58389 -+ send data to the client. In this case we simply raise the error
58390 -+ status and client connection will be closed.
58391 -+ */
58392 -+}
58393 diff -urN mysql-old/sql/sql_string.cc mysql/sql/sql_string.cc
58394 --- mysql-old/sql/sql_string.cc 2011-05-10 17:45:45.633349043 +0000
58395 +++ mysql/sql/sql_string.cc 2011-05-10 17:56:01.616682376 +0000
58396 @@ -60856,8136 +2552,6 @@ diff -urN mysql-old/sql/sql_table.cc mysql/sql/sql_table.cc
58397 if (key->type == Key::MULTIPLE)
58398 {
58399 /* not a critical problem */
58400 -diff -urN mysql-old/sql/sql_table.cc.orig mysql/sql/sql_table.cc.orig
58401 ---- mysql-old/sql/sql_table.cc.orig 1969-12-31 23:00:00.000000000 -0100
58402 -+++ mysql/sql/sql_table.cc.orig 2011-04-12 12:11:35.000000000 +0000
58403 -@@ -0,0 +1,8126 @@
58404 -+/* Copyright 2000-2011, Oracle and/or its affiliates. All rights reserved.
58405 -+
58406 -+ This program is free software; you can redistribute it and/or modify
58407 -+ it under the terms of the GNU General Public License as published by
58408 -+ the Free Software Foundation; version 2 of the License.
58409 -+
58410 -+ This program is distributed in the hope that it will be useful,
58411 -+ but WITHOUT ANY WARRANTY; without even the implied warranty of
58412 -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
58413 -+ GNU General Public License for more details.
58414 -+
58415 -+ You should have received a copy of the GNU General Public License
58416 -+ along with this program; if not, write to the Free Software
58417 -+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
58418 -+ MA 02110-1301 USA */
58419 -+
58420 -+/* drop and alter of tables */
58421 -+
58422 -+#include "mysql_priv.h"
58423 -+#include <hash.h>
58424 -+#include <myisam.h>
58425 -+#include <my_dir.h>
58426 -+#include "sp_head.h"
58427 -+#include "sql_trigger.h"
58428 -+#include "sql_show.h"
58429 -+#include "debug_sync.h"
58430 -+
58431 -+#ifdef __WIN__
58432 -+#include <io.h>
58433 -+#endif
58434 -+
58435 -+int creating_table= 0; // How many mysql_create_table are running
58436 -+
58437 -+const char *primary_key_name="PRIMARY";
58438 -+
58439 -+static bool check_if_keyname_exists(const char *name,KEY *start, KEY *end);
58440 -+static char *make_unique_key_name(const char *field_name,KEY *start,KEY *end);
58441 -+static int copy_data_between_tables(TABLE *from,TABLE *to,
58442 -+ List<Create_field> &create, bool ignore,
58443 -+ uint order_num, ORDER *order,
58444 -+ ha_rows *copied,ha_rows *deleted,
58445 -+ enum enum_enable_or_disable keys_onoff,
58446 -+ bool error_if_not_empty);
58447 -+
58448 -+static bool prepare_blob_field(THD *thd, Create_field *sql_field);
58449 -+static bool check_engine(THD *, const char *, HA_CREATE_INFO *);
58450 -+static int
58451 -+mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
58452 -+ Alter_info *alter_info,
58453 -+ bool tmp_table,
58454 -+ uint *db_options,
58455 -+ handler *file, KEY **key_info_buffer,
58456 -+ uint *key_count, int select_field_count);
58457 -+static bool
58458 -+mysql_prepare_alter_table(THD *thd, TABLE *table,
58459 -+ HA_CREATE_INFO *create_info,
58460 -+ Alter_info *alter_info);
58461 -+
58462 -+#ifndef DBUG_OFF
58463 -+
58464 -+/* Wait until we get a 'mysql_kill' signal */
58465 -+
58466 -+static void wait_for_kill_signal(THD *thd)
58467 -+{
58468 -+ while (thd->killed == 0)
58469 -+ sleep(1);
58470 -+ // Reset signal and continue as if nothing happend
58471 -+ thd->killed= THD::NOT_KILLED;
58472 -+}
58473 -+#endif
58474 -+
58475 -+
58476 -+/**
58477 -+ @brief Helper function for explain_filename
58478 -+ @param thd Thread handle
58479 -+ @param to_p Explained name in system_charset_info
58480 -+ @param end_p End of the to_p buffer
58481 -+ @param name Name to be converted
58482 -+ @param name_len Length of the name, in bytes
58483 -+*/
58484 -+static char* add_identifier(THD* thd, char *to_p, const char * end_p,
58485 -+ const char* name, uint name_len)
58486 -+{
58487 -+ uint res;
58488 -+ uint errors;
58489 -+ const char *conv_name;
58490 -+ char tmp_name[FN_REFLEN];
58491 -+ char conv_string[FN_REFLEN];
58492 -+ int quote;
58493 -+
58494 -+ DBUG_ENTER("add_identifier");
58495 -+ if (!name[name_len])
58496 -+ conv_name= name;
58497 -+ else
58498 -+ {
58499 -+ strnmov(tmp_name, name, name_len);
58500 -+ tmp_name[name_len]= 0;
58501 -+ conv_name= tmp_name;
58502 -+ }
58503 -+ res= strconvert(&my_charset_filename, conv_name, system_charset_info,
58504 -+ conv_string, FN_REFLEN, &errors);
58505 -+ if (!res || errors)
58506 -+ {
58507 -+ DBUG_PRINT("error", ("strconvert of '%s' failed with %u (errors: %u)", conv_name, res, errors));
58508 -+ conv_name= name;
58509 -+ }
58510 -+ else
58511 -+ {
58512 -+ DBUG_PRINT("info", ("conv '%s' -> '%s'", conv_name, conv_string));
58513 -+ conv_name= conv_string;
58514 -+ }
58515 -+
58516 -+ quote = thd ? get_quote_char_for_identifier(thd, conv_name, res - 1) : '"';
58517 -+
58518 -+ if (quote != EOF && (end_p - to_p > 2))
58519 -+ {
58520 -+ *(to_p++)= (char) quote;
58521 -+ while (*conv_name && (end_p - to_p - 1) > 0)
58522 -+ {
58523 -+ uint length= my_mbcharlen(system_charset_info, *conv_name);
58524 -+ if (!length)
58525 -+ length= 1;
58526 -+ if (length == 1 && *conv_name == (char) quote)
58527 -+ {
58528 -+ if ((end_p - to_p) < 3)
58529 -+ break;
58530 -+ *(to_p++)= (char) quote;
58531 -+ *(to_p++)= *(conv_name++);
58532 -+ }
58533 -+ else if (((long) length) < (end_p - to_p))
58534 -+ {
58535 -+ to_p= strnmov(to_p, conv_name, length);
58536 -+ conv_name+= length;
58537 -+ }
58538 -+ else
58539 -+ break; /* string already filled */
58540 -+ }
58541 -+ if (end_p > to_p) {
58542 -+ *(to_p++)= (char) quote;
58543 -+ if (end_p > to_p)
58544 -+ *to_p= 0; /* terminate by NUL, but do not include it in the count */
58545 -+ }
58546 -+ }
58547 -+ else
58548 -+ to_p= strnmov(to_p, conv_name, end_p - to_p);
58549 -+ DBUG_RETURN(to_p);
58550 -+}
58551 -+
58552 -+
58553 -+/**
58554 -+ @brief Explain a path name by split it to database, table etc.
58555 -+
58556 -+ @details Break down the path name to its logic parts
58557 -+ (database, table, partition, subpartition).
58558 -+ filename_to_tablename cannot be used on partitions, due to the #P# part.
58559 -+ There can be up to 6 '#', #P# for partition, #SP# for subpartition
58560 -+ and #TMP# or #REN# for temporary or renamed partitions.
58561 -+ This should be used when something should be presented to a user in a
58562 -+ diagnostic, error etc. when it would be useful to know what a particular
58563 -+ file [and directory] means. Such as SHOW ENGINE STATUS, error messages etc.
58564 -+
58565 -+ @param thd Thread handle
58566 -+ @param from Path name in my_charset_filename
58567 -+ Null terminated in my_charset_filename, normalized
58568 -+ to use '/' as directory separation character.
58569 -+ @param to Explained name in system_charset_info
58570 -+ @param to_length Size of to buffer
58571 -+ @param explain_mode Requested output format.
58572 -+ EXPLAIN_ALL_VERBOSE ->
58573 -+ [Database `db`, ]Table `tbl`[,[ Temporary| Renamed]
58574 -+ Partition `p` [, Subpartition `sp`]]
58575 -+ EXPLAIN_PARTITIONS_VERBOSE -> `db`.`tbl`
58576 -+ [[ Temporary| Renamed] Partition `p`
58577 -+ [, Subpartition `sp`]]
58578 -+ EXPLAIN_PARTITIONS_AS_COMMENT -> `db`.`tbl` |*
58579 -+ [,[ Temporary| Renamed] Partition `p`
58580 -+ [, Subpartition `sp`]] *|
58581 -+ (| is really a /, and it is all in one line)
58582 -+
58583 -+ @retval Length of returned string
58584 -+*/
58585 -+
58586 -+uint explain_filename(THD* thd,
58587 -+ const char *from,
58588 -+ char *to,
58589 -+ uint to_length,
58590 -+ enum_explain_filename_mode explain_mode)
58591 -+{
58592 -+ uint res= 0;
58593 -+ char *to_p= to;
58594 -+ char *end_p= to_p + to_length;
58595 -+ const char *db_name= NULL;
58596 -+ int db_name_len= 0;
58597 -+ const char *table_name;
58598 -+ int table_name_len= 0;
58599 -+ const char *part_name= NULL;
58600 -+ int part_name_len= 0;
58601 -+ const char *subpart_name= NULL;
58602 -+ int subpart_name_len= 0;
58603 -+ enum enum_file_name_type {NORMAL, TEMP, RENAMED} name_type= NORMAL;
58604 -+ const char *tmp_p;
58605 -+ DBUG_ENTER("explain_filename");
58606 -+ DBUG_PRINT("enter", ("from '%s'", from));
58607 -+ tmp_p= from;
58608 -+ table_name= from;
58609 -+ /*
58610 -+ If '/' then take last directory part as database.
58611 -+ '/' is the directory separator, not FN_LIB_CHAR
58612 -+ */
58613 -+ while ((tmp_p= strchr(tmp_p, '/')))
58614 -+ {
58615 -+ db_name= table_name;
58616 -+ /* calculate the length */
58617 -+ db_name_len= tmp_p - db_name;
58618 -+ tmp_p++;
58619 -+ table_name= tmp_p;
58620 -+ }
58621 -+ tmp_p= table_name;
58622 -+ while (!res && (tmp_p= strchr(tmp_p, '#')))
58623 -+ {
58624 -+ tmp_p++;
58625 -+ switch (tmp_p[0]) {
58626 -+ case 'P':
58627 -+ case 'p':
58628 -+ if (tmp_p[1] == '#')
58629 -+ part_name= tmp_p + 2;
58630 -+ else
58631 -+ res= 1;
58632 -+ tmp_p+= 2;
58633 -+ break;
58634 -+ case 'S':
58635 -+ case 's':
58636 -+ if ((tmp_p[1] == 'P' || tmp_p[1] == 'p') && tmp_p[2] == '#')
58637 -+ {
58638 -+ part_name_len= tmp_p - part_name - 1;
58639 -+ subpart_name= tmp_p + 3;
58640 -+ }
58641 -+ else
58642 -+ res= 2;
58643 -+ tmp_p+= 3;
58644 -+ break;
58645 -+ case 'T':
58646 -+ case 't':
58647 -+ if ((tmp_p[1] == 'M' || tmp_p[1] == 'm') &&
58648 -+ (tmp_p[2] == 'P' || tmp_p[2] == 'p') &&
58649 -+ tmp_p[3] == '#' && !tmp_p[4])
58650 -+ name_type= TEMP;
58651 -+ else
58652 -+ res= 3;
58653 -+ tmp_p+= 4;
58654 -+ break;
58655 -+ case 'R':
58656 -+ case 'r':
58657 -+ if ((tmp_p[1] == 'E' || tmp_p[1] == 'e') &&
58658 -+ (tmp_p[2] == 'N' || tmp_p[2] == 'n') &&
58659 -+ tmp_p[3] == '#' && !tmp_p[4])
58660 -+ name_type= RENAMED;
58661 -+ else
58662 -+ res= 4;
58663 -+ tmp_p+= 4;
58664 -+ break;
58665 -+ default:
58666 -+ res= 5;
58667 -+ }
58668 -+ }
58669 -+ if (res)
58670 -+ {
58671 -+ /* Better to give something back if we fail parsing, than nothing at all */
58672 -+ DBUG_PRINT("info", ("Error in explain_filename: %u", res));
58673 -+ sql_print_warning("Invalid (old?) table or database name '%s'", from);
58674 -+ DBUG_RETURN(my_snprintf(to, to_length,
58675 -+ "<result %u when explaining filename '%s'>",
58676 -+ res, from));
58677 -+ }
58678 -+ if (part_name)
58679 -+ {
58680 -+ table_name_len= part_name - table_name - 3;
58681 -+ if (subpart_name)
58682 -+ subpart_name_len= strlen(subpart_name);
58683 -+ else
58684 -+ part_name_len= strlen(part_name);
58685 -+ if (name_type != NORMAL)
58686 -+ {
58687 -+ if (subpart_name)
58688 -+ subpart_name_len-= 5;
58689 -+ else
58690 -+ part_name_len-= 5;
58691 -+ }
58692 -+ }
58693 -+ else
58694 -+ table_name_len= strlen(table_name);
58695 -+ if (db_name)
58696 -+ {
58697 -+ if (explain_mode == EXPLAIN_ALL_VERBOSE)
58698 -+ {
58699 -+ to_p= strnmov(to_p, ER(ER_DATABASE_NAME), end_p - to_p);
58700 -+ *(to_p++)= ' ';
58701 -+ to_p= add_identifier(thd, to_p, end_p, db_name, db_name_len);
58702 -+ to_p= strnmov(to_p, ", ", end_p - to_p);
58703 -+ }
58704 -+ else
58705 -+ {
58706 -+ to_p= add_identifier(thd, to_p, end_p, db_name, db_name_len);
58707 -+ to_p= strnmov(to_p, ".", end_p - to_p);
58708 -+ }
58709 -+ }
58710 -+ if (explain_mode == EXPLAIN_ALL_VERBOSE)
58711 -+ {
58712 -+ to_p= strnmov(to_p, ER(ER_TABLE_NAME), end_p - to_p);
58713 -+ *(to_p++)= ' ';
58714 -+ to_p= add_identifier(thd, to_p, end_p, table_name, table_name_len);
58715 -+ }
58716 -+ else
58717 -+ to_p= add_identifier(thd, to_p, end_p, table_name, table_name_len);
58718 -+ if (part_name)
58719 -+ {
58720 -+ if (explain_mode == EXPLAIN_PARTITIONS_AS_COMMENT)
58721 -+ to_p= strnmov(to_p, " /* ", end_p - to_p);
58722 -+ else if (explain_mode == EXPLAIN_PARTITIONS_VERBOSE)
58723 -+ to_p= strnmov(to_p, " ", end_p - to_p);
58724 -+ else
58725 -+ to_p= strnmov(to_p, ", ", end_p - to_p);
58726 -+ if (name_type != NORMAL)
58727 -+ {
58728 -+ if (name_type == TEMP)
58729 -+ to_p= strnmov(to_p, ER(ER_TEMPORARY_NAME), end_p - to_p);
58730 -+ else
58731 -+ to_p= strnmov(to_p, ER(ER_RENAMED_NAME), end_p - to_p);
58732 -+ to_p= strnmov(to_p, " ", end_p - to_p);
58733 -+ }
58734 -+ to_p= strnmov(to_p, ER(ER_PARTITION_NAME), end_p - to_p);
58735 -+ *(to_p++)= ' ';
58736 -+ to_p= add_identifier(thd, to_p, end_p, part_name, part_name_len);
58737 -+ if (subpart_name)
58738 -+ {
58739 -+ to_p= strnmov(to_p, ", ", end_p - to_p);
58740 -+ to_p= strnmov(to_p, ER(ER_SUBPARTITION_NAME), end_p - to_p);
58741 -+ *(to_p++)= ' ';
58742 -+ to_p= add_identifier(thd, to_p, end_p, subpart_name, subpart_name_len);
58743 -+ }
58744 -+ if (explain_mode == EXPLAIN_PARTITIONS_AS_COMMENT)
58745 -+ to_p= strnmov(to_p, " */", end_p - to_p);
58746 -+ }
58747 -+ DBUG_PRINT("exit", ("to '%s'", to));
58748 -+ DBUG_RETURN(to_p - to);
58749 -+}
58750 -+
58751 -+
58752 -+/*
58753 -+ Translate a file name to a table name (WL #1324).
58754 -+
58755 -+ SYNOPSIS
58756 -+ filename_to_tablename()
58757 -+ from The file name in my_charset_filename.
58758 -+ to OUT The table name in system_charset_info.
58759 -+ to_length The size of the table name buffer.
58760 -+
58761 -+ RETURN
58762 -+ Table name length.
58763 -+*/
58764 -+
58765 -+uint filename_to_tablename(const char *from, char *to, uint to_length)
58766 -+{
58767 -+ uint errors;
58768 -+ size_t res;
58769 -+ DBUG_ENTER("filename_to_tablename");
58770 -+ DBUG_PRINT("enter", ("from '%s'", from));
58771 -+
58772 -+ if (!memcmp(from, tmp_file_prefix, tmp_file_prefix_length))
58773 -+ {
58774 -+ /* Temporary table name. */
58775 -+ res= (strnmov(to, from, to_length) - to);
58776 -+ }
58777 -+ else
58778 -+ {
58779 -+ res= strconvert(&my_charset_filename, from,
58780 -+ system_charset_info, to, to_length, &errors);
58781 -+ if (errors) // Old 5.0 name
58782 -+ {
58783 -+ res= (strxnmov(to, to_length, MYSQL50_TABLE_NAME_PREFIX, from, NullS) -
58784 -+ to);
58785 -+ sql_print_error("Invalid (old?) table or database name '%s'", from);
58786 -+ /*
58787 -+ TODO: add a stored procedure for fix table and database names,
58788 -+ and mention its name in error log.
58789 -+ */
58790 -+ }
58791 -+ }
58792 -+
58793 -+ DBUG_PRINT("exit", ("to '%s'", to));
58794 -+ DBUG_RETURN(res);
58795 -+}
58796 -+
58797 -+
58798 -+/**
58799 -+ Check if given string begins with "#mysql50#" prefix
58800 -+
58801 -+ @param name string to check cut
58802 -+
58803 -+ @retval
58804 -+ FALSE no prefix found
58805 -+ @retval
58806 -+ TRUE prefix found
58807 -+*/
58808 -+
58809 -+bool check_mysql50_prefix(const char *name)
58810 -+{
58811 -+ return (name[0] == '#' &&
58812 -+ !strncmp(name, MYSQL50_TABLE_NAME_PREFIX,
58813 -+ MYSQL50_TABLE_NAME_PREFIX_LENGTH));
58814 -+}
58815 -+
58816 -+
58817 -+/**
58818 -+ Check if given string begins with "#mysql50#" prefix, cut it if so.
58819 -+
58820 -+ @param from string to check and cut
58821 -+ @param to[out] buffer for result string
58822 -+ @param to_length its size
58823 -+
58824 -+ @retval
58825 -+ 0 no prefix found
58826 -+ @retval
58827 -+ non-0 result string length
58828 -+*/
58829 -+
58830 -+uint check_n_cut_mysql50_prefix(const char *from, char *to, uint to_length)
58831 -+{
58832 -+ if (check_mysql50_prefix(from))
58833 -+ return (uint) (strmake(to, from + MYSQL50_TABLE_NAME_PREFIX_LENGTH,
58834 -+ to_length - 1) - to);
58835 -+ return 0;
58836 -+}
58837 -+
58838 -+
58839 -+/*
58840 -+ Translate a table name to a file name (WL #1324).
58841 -+
58842 -+ SYNOPSIS
58843 -+ tablename_to_filename()
58844 -+ from The table name in system_charset_info.
58845 -+ to OUT The file name in my_charset_filename.
58846 -+ to_length The size of the file name buffer.
58847 -+
58848 -+ RETURN
58849 -+ File name length.
58850 -+*/
58851 -+
58852 -+uint tablename_to_filename(const char *from, char *to, uint to_length)
58853 -+{
58854 -+ uint errors, length;
58855 -+ DBUG_ENTER("tablename_to_filename");
58856 -+ DBUG_PRINT("enter", ("from '%s'", from));
58857 -+
58858 -+ if ((length= check_n_cut_mysql50_prefix(from, to, to_length)))
58859 -+ {
58860 -+ /*
58861 -+ Check if the name supplied is a valid mysql 5.0 name and
58862 -+ make the name a zero length string if it's not.
58863 -+ Note that just returning zero length is not enough :
58864 -+ a lot of places don't check the return value and expect
58865 -+ a zero terminated string.
58866 -+ */
58867 -+ if (check_table_name(to, length, TRUE))
58868 -+ {
58869 -+ to[0]= 0;
58870 -+ length= 0;
58871 -+ }
58872 -+ DBUG_RETURN(length);
58873 -+ }
58874 -+ length= strconvert(system_charset_info, from,
58875 -+ &my_charset_filename, to, to_length, &errors);
58876 -+ if (check_if_legal_tablename(to) &&
58877 -+ length + 4 < to_length)
58878 -+ {
58879 -+ memcpy(to + length, "@@@", 4);
58880 -+ length+= 3;
58881 -+ }
58882 -+ DBUG_PRINT("exit", ("to '%s'", to));
58883 -+ DBUG_RETURN(length);
58884 -+}
58885 -+
58886 -+
58887 -+/*
58888 -+ Creates path to a file: mysql_data_dir/db/table.ext
58889 -+
58890 -+ SYNOPSIS
58891 -+ build_table_filename()
58892 -+ buff Where to write result in my_charset_filename.
58893 -+ This may be the same as table_name.
58894 -+ bufflen buff size
58895 -+ db Database name in system_charset_info.
58896 -+ table_name Table name in system_charset_info.
58897 -+ ext File extension.
58898 -+ flags FN_FROM_IS_TMP or FN_TO_IS_TMP or FN_IS_TMP
58899 -+ table_name is temporary, do not change.
58900 -+
58901 -+ NOTES
58902 -+
58903 -+ Uses database and table name, and extension to create
58904 -+ a file name in mysql_data_dir. Database and table
58905 -+ names are converted from system_charset_info into "fscs".
58906 -+ Unless flags indicate a temporary table name.
58907 -+ 'db' is always converted.
58908 -+ 'ext' is not converted.
58909 -+
58910 -+ The conversion suppression is required for ALTER TABLE. This
58911 -+ statement creates intermediate tables. These are regular
58912 -+ (non-temporary) tables with a temporary name. Their path names must
58913 -+ be derivable from the table name. So we cannot use
58914 -+ build_tmptable_filename() for them.
58915 -+
58916 -+ RETURN
58917 -+ path length
58918 -+*/
58919 -+
58920 -+uint build_table_filename(char *buff, size_t bufflen, const char *db,
58921 -+ const char *table_name, const char *ext, uint flags)
58922 -+{
58923 -+ char dbbuff[FN_REFLEN];
58924 -+ char tbbuff[FN_REFLEN];
58925 -+ DBUG_ENTER("build_table_filename");
58926 -+ DBUG_PRINT("enter", ("db: '%s' table_name: '%s' ext: '%s' flags: %x",
58927 -+ db, table_name, ext, flags));
58928 -+
58929 -+ if (flags & FN_IS_TMP) // FN_FROM_IS_TMP | FN_TO_IS_TMP
58930 -+ strnmov(tbbuff, table_name, sizeof(tbbuff));
58931 -+ else
58932 -+ VOID(tablename_to_filename(table_name, tbbuff, sizeof(tbbuff)));
58933 -+
58934 -+ VOID(tablename_to_filename(db, dbbuff, sizeof(dbbuff)));
58935 -+
58936 -+ char *end = buff + bufflen;
58937 -+ /* Don't add FN_ROOTDIR if mysql_data_home already includes it */
58938 -+ char *pos = strnmov(buff, mysql_data_home, bufflen);
58939 -+ size_t rootdir_len= strlen(FN_ROOTDIR);
58940 -+ if (pos - rootdir_len >= buff &&
58941 -+ memcmp(pos - rootdir_len, FN_ROOTDIR, rootdir_len) != 0)
58942 -+ pos= strnmov(pos, FN_ROOTDIR, end - pos);
58943 -+ pos= strxnmov(pos, end - pos, dbbuff, FN_ROOTDIR, NullS);
58944 -+#ifdef USE_SYMDIR
58945 -+ unpack_dirname(buff, buff);
58946 -+ pos= strend(buff);
58947 -+#endif
58948 -+ pos= strxnmov(pos, end - pos, tbbuff, ext, NullS);
58949 -+
58950 -+ DBUG_PRINT("exit", ("buff: '%s'", buff));
58951 -+ DBUG_RETURN(pos - buff);
58952 -+}
58953 -+
58954 -+
58955 -+/*
58956 -+ Creates path to a file: mysql_tmpdir/#sql1234_12_1.ext
58957 -+
58958 -+ SYNOPSIS
58959 -+ build_tmptable_filename()
58960 -+ thd The thread handle.
58961 -+ buff Where to write result in my_charset_filename.
58962 -+ bufflen buff size
58963 -+
58964 -+ NOTES
58965 -+
58966 -+ Uses current_pid, thread_id, and tmp_table counter to create
58967 -+ a file name in mysql_tmpdir.
58968 -+
58969 -+ RETURN
58970 -+ path length
58971 -+*/
58972 -+
58973 -+uint build_tmptable_filename(THD* thd, char *buff, size_t bufflen)
58974 -+{
58975 -+ DBUG_ENTER("build_tmptable_filename");
58976 -+
58977 -+ char *p= strnmov(buff, mysql_tmpdir, bufflen);
58978 -+ my_snprintf(p, bufflen - (p - buff), "/%s%lx_%lx_%x%s",
58979 -+ tmp_file_prefix, current_pid,
58980 -+ thd->thread_id, thd->tmp_table++, reg_ext);
58981 -+
58982 -+ if (lower_case_table_names)
58983 -+ {
58984 -+ /* Convert all except tmpdir to lower case */
58985 -+ my_casedn_str(files_charset_info, p);
58986 -+ }
58987 -+
58988 -+ size_t length= unpack_filename(buff, buff);
58989 -+ DBUG_PRINT("exit", ("buff: '%s'", buff));
58990 -+ DBUG_RETURN(length);
58991 -+}
58992 -+
58993 -+/*
58994 -+--------------------------------------------------------------------------
58995 -+
58996 -+ MODULE: DDL log
58997 -+ -----------------
58998 -+
58999 -+ This module is used to ensure that we can recover from crashes that occur
59000 -+ in the middle of a meta-data operation in MySQL. E.g. DROP TABLE t1, t2;
59001 -+ We need to ensure that both t1 and t2 are dropped and not only t1 and
59002 -+ also that each table drop is entirely done and not "half-baked".
59003 -+
59004 -+ To support this we create log entries for each meta-data statement in the
59005 -+ ddl log while we are executing. These entries are dropped when the
59006 -+ operation is completed.
59007 -+
59008 -+ At recovery those entries that were not completed will be executed.
59009 -+
59010 -+ There is only one ddl log in the system and it is protected by a mutex
59011 -+ and there is a global struct that contains information about its current
59012 -+ state.
59013 -+
59014 -+ History:
59015 -+ First version written in 2006 by Mikael Ronstrom
59016 -+--------------------------------------------------------------------------
59017 -+*/
59018 -+
59019 -+
59020 -+struct st_global_ddl_log
59021 -+{
59022 -+ /*
59023 -+ We need to adjust buffer size to be able to handle downgrades/upgrades
59024 -+ where IO_SIZE has changed. We'll set the buffer size such that we can
59025 -+ handle that the buffer size was upto 4 times bigger in the version
59026 -+ that wrote the DDL log.
59027 -+ */
59028 -+ char file_entry_buf[4*IO_SIZE];
59029 -+ char file_name_str[FN_REFLEN];
59030 -+ char *file_name;
59031 -+ DDL_LOG_MEMORY_ENTRY *first_free;
59032 -+ DDL_LOG_MEMORY_ENTRY *first_used;
59033 -+ uint num_entries;
59034 -+ File file_id;
59035 -+ uint name_len;
59036 -+ uint io_size;
59037 -+ bool inited;
59038 -+ bool do_release;
59039 -+ bool recovery_phase;
59040 -+ st_global_ddl_log() : inited(false), do_release(false) {}
59041 -+};
59042 -+
59043 -+st_global_ddl_log global_ddl_log;
59044 -+
59045 -+pthread_mutex_t LOCK_gdl;
59046 -+
59047 -+#define DDL_LOG_ENTRY_TYPE_POS 0
59048 -+#define DDL_LOG_ACTION_TYPE_POS 1
59049 -+#define DDL_LOG_PHASE_POS 2
59050 -+#define DDL_LOG_NEXT_ENTRY_POS 4
59051 -+#define DDL_LOG_NAME_POS 8
59052 -+
59053 -+#define DDL_LOG_NUM_ENTRY_POS 0
59054 -+#define DDL_LOG_NAME_LEN_POS 4
59055 -+#define DDL_LOG_IO_SIZE_POS 8
59056 -+
59057 -+/*
59058 -+ Read one entry from ddl log file
59059 -+ SYNOPSIS
59060 -+ read_ddl_log_file_entry()
59061 -+ entry_no Entry number to read
59062 -+ RETURN VALUES
59063 -+ TRUE Error
59064 -+ FALSE Success
59065 -+*/
59066 -+
59067 -+static bool read_ddl_log_file_entry(uint entry_no)
59068 -+{
59069 -+ bool error= FALSE;
59070 -+ File file_id= global_ddl_log.file_id;
59071 -+ uchar *file_entry_buf= (uchar*)global_ddl_log.file_entry_buf;
59072 -+ uint io_size= global_ddl_log.io_size;
59073 -+ DBUG_ENTER("read_ddl_log_file_entry");
59074 -+
59075 -+ if (my_pread(file_id, file_entry_buf, io_size, io_size * entry_no,
59076 -+ MYF(MY_WME)) != io_size)
59077 -+ error= TRUE;
59078 -+ DBUG_RETURN(error);
59079 -+}
59080 -+
59081 -+
59082 -+/*
59083 -+ Write one entry from ddl log file
59084 -+ SYNOPSIS
59085 -+ write_ddl_log_file_entry()
59086 -+ entry_no Entry number to write
59087 -+ RETURN VALUES
59088 -+ TRUE Error
59089 -+ FALSE Success
59090 -+*/
59091 -+
59092 -+static bool write_ddl_log_file_entry(uint entry_no)
59093 -+{
59094 -+ bool error= FALSE;
59095 -+ File file_id= global_ddl_log.file_id;
59096 -+ char *file_entry_buf= (char*)global_ddl_log.file_entry_buf;
59097 -+ DBUG_ENTER("write_ddl_log_file_entry");
59098 -+
59099 -+ if (my_pwrite(file_id, (uchar*)file_entry_buf,
59100 -+ IO_SIZE, IO_SIZE * entry_no, MYF(MY_WME)) != IO_SIZE)
59101 -+ error= TRUE;
59102 -+ DBUG_RETURN(error);
59103 -+}
59104 -+
59105 -+
59106 -+/*
59107 -+ Write ddl log header
59108 -+ SYNOPSIS
59109 -+ write_ddl_log_header()
59110 -+ RETURN VALUES
59111 -+ TRUE Error
59112 -+ FALSE Success
59113 -+*/
59114 -+
59115 -+static bool write_ddl_log_header()
59116 -+{
59117 -+ uint16 const_var;
59118 -+ bool error= FALSE;
59119 -+ DBUG_ENTER("write_ddl_log_header");
59120 -+
59121 -+ int4store(&global_ddl_log.file_entry_buf[DDL_LOG_NUM_ENTRY_POS],
59122 -+ global_ddl_log.num_entries);
59123 -+ const_var= FN_LEN;
59124 -+ int4store(&global_ddl_log.file_entry_buf[DDL_LOG_NAME_LEN_POS],
59125 -+ (ulong) const_var);
59126 -+ const_var= IO_SIZE;
59127 -+ int4store(&global_ddl_log.file_entry_buf[DDL_LOG_IO_SIZE_POS],
59128 -+ (ulong) const_var);
59129 -+ if (write_ddl_log_file_entry(0UL))
59130 -+ {
59131 -+ sql_print_error("Error writing ddl log header");
59132 -+ DBUG_RETURN(TRUE);
59133 -+ }
59134 -+ VOID(sync_ddl_log());
59135 -+ DBUG_RETURN(error);
59136 -+}
59137 -+
59138 -+
59139 -+/*
59140 -+ Create ddl log file name
59141 -+ SYNOPSIS
59142 -+ create_ddl_log_file_name()
59143 -+ file_name Filename setup
59144 -+ RETURN VALUES
59145 -+ NONE
59146 -+*/
59147 -+
59148 -+static inline void create_ddl_log_file_name(char *file_name)
59149 -+{
59150 -+ strxmov(file_name, mysql_data_home, "/", "ddl_log.log", NullS);
59151 -+}
59152 -+
59153 -+
59154 -+/*
59155 -+ Read header of ddl log file
59156 -+ SYNOPSIS
59157 -+ read_ddl_log_header()
59158 -+ RETURN VALUES
59159 -+ > 0 Last entry in ddl log
59160 -+ 0 No entries in ddl log
59161 -+ DESCRIPTION
59162 -+ When we read the ddl log header we get information about maximum sizes
59163 -+ of names in the ddl log and we also get information about the number
59164 -+ of entries in the ddl log.
59165 -+*/
59166 -+
59167 -+static uint read_ddl_log_header()
59168 -+{
59169 -+ char *file_entry_buf= (char*)global_ddl_log.file_entry_buf;
59170 -+ char file_name[FN_REFLEN];
59171 -+ uint entry_no;
59172 -+ bool successful_open= FALSE;
59173 -+ DBUG_ENTER("read_ddl_log_header");
59174 -+
59175 -+ create_ddl_log_file_name(file_name);
59176 -+ if ((global_ddl_log.file_id= my_open(file_name,
59177 -+ O_RDWR | O_BINARY, MYF(0))) >= 0)
59178 -+ {
59179 -+ if (read_ddl_log_file_entry(0UL))
59180 -+ {
59181 -+ /* Write message into error log */
59182 -+ sql_print_error("Failed to read ddl log file in recovery");
59183 -+ }
59184 -+ else
59185 -+ successful_open= TRUE;
59186 -+ }
59187 -+ if (successful_open)
59188 -+ {
59189 -+ entry_no= uint4korr(&file_entry_buf[DDL_LOG_NUM_ENTRY_POS]);
59190 -+ global_ddl_log.name_len= uint4korr(&file_entry_buf[DDL_LOG_NAME_LEN_POS]);
59191 -+ global_ddl_log.io_size= uint4korr(&file_entry_buf[DDL_LOG_IO_SIZE_POS]);
59192 -+ DBUG_ASSERT(global_ddl_log.io_size <=
59193 -+ sizeof(global_ddl_log.file_entry_buf));
59194 -+ }
59195 -+ else
59196 -+ {
59197 -+ entry_no= 0;
59198 -+ }
59199 -+ global_ddl_log.first_free= NULL;
59200 -+ global_ddl_log.first_used= NULL;
59201 -+ global_ddl_log.num_entries= 0;
59202 -+ VOID(pthread_mutex_init(&LOCK_gdl, MY_MUTEX_INIT_FAST));
59203 -+ global_ddl_log.do_release= true;
59204 -+ DBUG_RETURN(entry_no);
59205 -+}
59206 -+
59207 -+
59208 -+/*
59209 -+ Read a ddl log entry
59210 -+ SYNOPSIS
59211 -+ read_ddl_log_entry()
59212 -+ read_entry Number of entry to read
59213 -+ out:entry_info Information from entry
59214 -+ RETURN VALUES
59215 -+ TRUE Error
59216 -+ FALSE Success
59217 -+ DESCRIPTION
59218 -+ Read a specified entry in the ddl log
59219 -+*/
59220 -+
59221 -+bool read_ddl_log_entry(uint read_entry, DDL_LOG_ENTRY *ddl_log_entry)
59222 -+{
59223 -+ char *file_entry_buf= (char*)&global_ddl_log.file_entry_buf;
59224 -+ uint inx;
59225 -+ uchar single_char;
59226 -+ DBUG_ENTER("read_ddl_log_entry");
59227 -+
59228 -+ if (read_ddl_log_file_entry(read_entry))
59229 -+ {
59230 -+ DBUG_RETURN(TRUE);
59231 -+ }
59232 -+ ddl_log_entry->entry_pos= read_entry;
59233 -+ single_char= file_entry_buf[DDL_LOG_ENTRY_TYPE_POS];
59234 -+ ddl_log_entry->entry_type= (enum ddl_log_entry_code)single_char;
59235 -+ single_char= file_entry_buf[DDL_LOG_ACTION_TYPE_POS];
59236 -+ ddl_log_entry->action_type= (enum ddl_log_action_code)single_char;
59237 -+ ddl_log_entry->phase= file_entry_buf[DDL_LOG_PHASE_POS];
59238 -+ ddl_log_entry->next_entry= uint4korr(&file_entry_buf[DDL_LOG_NEXT_ENTRY_POS]);
59239 -+ ddl_log_entry->name= &file_entry_buf[DDL_LOG_NAME_POS];
59240 -+ inx= DDL_LOG_NAME_POS + global_ddl_log.name_len;
59241 -+ ddl_log_entry->from_name= &file_entry_buf[inx];
59242 -+ inx+= global_ddl_log.name_len;
59243 -+ ddl_log_entry->handler_name= &file_entry_buf[inx];
59244 -+ DBUG_RETURN(FALSE);
59245 -+}
59246 -+
59247 -+
59248 -+/*
59249 -+ Initialise ddl log
59250 -+ SYNOPSIS
59251 -+ init_ddl_log()
59252 -+
59253 -+ DESCRIPTION
59254 -+ Write the header of the ddl log file and length of names. Also set
59255 -+ number of entries to zero.
59256 -+
59257 -+ RETURN VALUES
59258 -+ TRUE Error
59259 -+ FALSE Success
59260 -+*/
59261 -+
59262 -+static bool init_ddl_log()
59263 -+{
59264 -+ char file_name[FN_REFLEN];
59265 -+ DBUG_ENTER("init_ddl_log");
59266 -+
59267 -+ if (global_ddl_log.inited)
59268 -+ goto end;
59269 -+
59270 -+ global_ddl_log.io_size= IO_SIZE;
59271 -+ global_ddl_log.name_len= FN_LEN;
59272 -+ create_ddl_log_file_name(file_name);
59273 -+ if ((global_ddl_log.file_id= my_create(file_name,
59274 -+ CREATE_MODE,
59275 -+ O_RDWR | O_TRUNC | O_BINARY,
59276 -+ MYF(MY_WME))) < 0)
59277 -+ {
59278 -+ /* Couldn't create ddl log file, this is serious error */
59279 -+ sql_print_error("Failed to open ddl log file");
59280 -+ DBUG_RETURN(TRUE);
59281 -+ }
59282 -+ global_ddl_log.inited= TRUE;
59283 -+ if (write_ddl_log_header())
59284 -+ {
59285 -+ VOID(my_close(global_ddl_log.file_id, MYF(MY_WME)));
59286 -+ global_ddl_log.inited= FALSE;
59287 -+ DBUG_RETURN(TRUE);
59288 -+ }
59289 -+
59290 -+end:
59291 -+ DBUG_RETURN(FALSE);
59292 -+}
59293 -+
59294 -+
59295 -+/*
59296 -+ Execute one action in a ddl log entry
59297 -+ SYNOPSIS
59298 -+ execute_ddl_log_action()
59299 -+ ddl_log_entry Information in action entry to execute
59300 -+ RETURN VALUES
59301 -+ TRUE Error
59302 -+ FALSE Success
59303 -+*/
59304 -+
59305 -+static int execute_ddl_log_action(THD *thd, DDL_LOG_ENTRY *ddl_log_entry)
59306 -+{
59307 -+ bool frm_action= FALSE;
59308 -+ LEX_STRING handler_name;
59309 -+ handler *file= NULL;
59310 -+ MEM_ROOT mem_root;
59311 -+ int error= TRUE;
59312 -+ char to_path[FN_REFLEN];
59313 -+ char from_path[FN_REFLEN];
59314 -+#ifdef WITH_PARTITION_STORAGE_ENGINE
59315 -+ char *par_ext= (char*)".par";
59316 -+#endif
59317 -+ handlerton *hton;
59318 -+ DBUG_ENTER("execute_ddl_log_action");
59319 -+
59320 -+ if (ddl_log_entry->entry_type == DDL_IGNORE_LOG_ENTRY_CODE)
59321 -+ {
59322 -+ DBUG_RETURN(FALSE);
59323 -+ }
59324 -+ DBUG_PRINT("ddl_log",
59325 -+ ("execute type %c next %u name '%s' from_name '%s' handler '%s'",
59326 -+ ddl_log_entry->action_type,
59327 -+ ddl_log_entry->next_entry,
59328 -+ ddl_log_entry->name,
59329 -+ ddl_log_entry->from_name,
59330 -+ ddl_log_entry->handler_name));
59331 -+ handler_name.str= (char*)ddl_log_entry->handler_name;
59332 -+ handler_name.length= strlen(ddl_log_entry->handler_name);
59333 -+ init_sql_alloc(&mem_root, TABLE_ALLOC_BLOCK_SIZE, 0);
59334 -+ if (!strcmp(ddl_log_entry->handler_name, reg_ext))
59335 -+ frm_action= TRUE;
59336 -+ else
59337 -+ {
59338 -+ plugin_ref plugin= ha_resolve_by_name(thd, &handler_name);
59339 -+ if (!plugin)
59340 -+ {
59341 -+ my_error(ER_ILLEGAL_HA, MYF(0), ddl_log_entry->handler_name);
59342 -+ goto error;
59343 -+ }
59344 -+ hton= plugin_data(plugin, handlerton*);
59345 -+ file= get_new_handler((TABLE_SHARE*)0, &mem_root, hton);
59346 -+ if (!file)
59347 -+ {
59348 -+ mem_alloc_error(sizeof(handler));
59349 -+ goto error;
59350 -+ }
59351 -+ }
59352 -+ switch (ddl_log_entry->action_type)
59353 -+ {
59354 -+ case DDL_LOG_REPLACE_ACTION:
59355 -+ case DDL_LOG_DELETE_ACTION:
59356 -+ {
59357 -+ if (ddl_log_entry->phase == 0)
59358 -+ {
59359 -+ if (frm_action)
59360 -+ {
59361 -+ strxmov(to_path, ddl_log_entry->name, reg_ext, NullS);
59362 -+ if ((error= my_delete(to_path, MYF(MY_WME))))
59363 -+ {
59364 -+ if (my_errno != ENOENT)
59365 -+ break;
59366 -+ }
59367 -+#ifdef WITH_PARTITION_STORAGE_ENGINE
59368 -+ strxmov(to_path, ddl_log_entry->name, par_ext, NullS);
59369 -+ VOID(my_delete(to_path, MYF(MY_WME)));
59370 -+#endif
59371 -+ }
59372 -+ else
59373 -+ {
59374 -+ if ((error= file->ha_delete_table(ddl_log_entry->name)))
59375 -+ {
59376 -+ if (error != ENOENT && error != HA_ERR_NO_SUCH_TABLE)
59377 -+ break;
59378 -+ }
59379 -+ }
59380 -+ if ((deactivate_ddl_log_entry(ddl_log_entry->entry_pos)))
59381 -+ break;
59382 -+ VOID(sync_ddl_log());
59383 -+ error= FALSE;
59384 -+ if (ddl_log_entry->action_type == DDL_LOG_DELETE_ACTION)
59385 -+ break;
59386 -+ }
59387 -+ DBUG_ASSERT(ddl_log_entry->action_type == DDL_LOG_REPLACE_ACTION);
59388 -+ /*
59389 -+ Fall through and perform the rename action of the replace
59390 -+ action. We have already indicated the success of the delete
59391 -+ action in the log entry by stepping up the phase.
59392 -+ */
59393 -+ }
59394 -+ case DDL_LOG_RENAME_ACTION:
59395 -+ {
59396 -+ error= TRUE;
59397 -+ if (frm_action)
59398 -+ {
59399 -+ strxmov(to_path, ddl_log_entry->name, reg_ext, NullS);
59400 -+ strxmov(from_path, ddl_log_entry->from_name, reg_ext, NullS);
59401 -+ if (my_rename(from_path, to_path, MYF(MY_WME)))
59402 -+ break;
59403 -+#ifdef WITH_PARTITION_STORAGE_ENGINE
59404 -+ strxmov(to_path, ddl_log_entry->name, par_ext, NullS);
59405 -+ strxmov(from_path, ddl_log_entry->from_name, par_ext, NullS);
59406 -+ VOID(my_rename(from_path, to_path, MYF(MY_WME)));
59407 -+#endif
59408 -+ }
59409 -+ else
59410 -+ {
59411 -+ if (file->ha_rename_table(ddl_log_entry->from_name,
59412 -+ ddl_log_entry->name))
59413 -+ break;
59414 -+ }
59415 -+ if ((deactivate_ddl_log_entry(ddl_log_entry->entry_pos)))
59416 -+ break;
59417 -+ VOID(sync_ddl_log());
59418 -+ error= FALSE;
59419 -+ break;
59420 -+ }
59421 -+ default:
59422 -+ DBUG_ASSERT(0);
59423 -+ break;
59424 -+ }
59425 -+ delete file;
59426 -+error:
59427 -+ free_root(&mem_root, MYF(0));
59428 -+ DBUG_RETURN(error);
59429 -+}
59430 -+
59431 -+
59432 -+/*
59433 -+ Get a free entry in the ddl log
59434 -+ SYNOPSIS
59435 -+ get_free_ddl_log_entry()
59436 -+ out:active_entry A ddl log memory entry returned
59437 -+ RETURN VALUES
59438 -+ TRUE Error
59439 -+ FALSE Success
59440 -+*/
59441 -+
59442 -+static bool get_free_ddl_log_entry(DDL_LOG_MEMORY_ENTRY **active_entry,
59443 -+ bool *write_header)
59444 -+{
59445 -+ DDL_LOG_MEMORY_ENTRY *used_entry;
59446 -+ DDL_LOG_MEMORY_ENTRY *first_used= global_ddl_log.first_used;
59447 -+ DBUG_ENTER("get_free_ddl_log_entry");
59448 -+
59449 -+ if (global_ddl_log.first_free == NULL)
59450 -+ {
59451 -+ if (!(used_entry= (DDL_LOG_MEMORY_ENTRY*)my_malloc(
59452 -+ sizeof(DDL_LOG_MEMORY_ENTRY), MYF(MY_WME))))
59453 -+ {
59454 -+ sql_print_error("Failed to allocate memory for ddl log free list");
59455 -+ DBUG_RETURN(TRUE);
59456 -+ }
59457 -+ global_ddl_log.num_entries++;
59458 -+ used_entry->entry_pos= global_ddl_log.num_entries;
59459 -+ *write_header= TRUE;
59460 -+ }
59461 -+ else
59462 -+ {
59463 -+ used_entry= global_ddl_log.first_free;
59464 -+ global_ddl_log.first_free= used_entry->next_log_entry;
59465 -+ *write_header= FALSE;
59466 -+ }
59467 -+ /*
59468 -+ Move from free list to used list
59469 -+ */
59470 -+ used_entry->next_log_entry= first_used;
59471 -+ used_entry->prev_log_entry= NULL;
59472 -+ global_ddl_log.first_used= used_entry;
59473 -+ if (first_used)
59474 -+ first_used->prev_log_entry= used_entry;
59475 -+
59476 -+ *active_entry= used_entry;
59477 -+ DBUG_RETURN(FALSE);
59478 -+}
59479 -+
59480 -+
59481 -+/*
59482 -+ External interface methods for the DDL log Module
59483 -+ ---------------------------------------------------
59484 -+*/
59485 -+
59486 -+/*
59487 -+ SYNOPSIS
59488 -+ write_ddl_log_entry()
59489 -+ ddl_log_entry Information about log entry
59490 -+ out:entry_written Entry information written into
59491 -+
59492 -+ RETURN VALUES
59493 -+ TRUE Error
59494 -+ FALSE Success
59495 -+
59496 -+ DESCRIPTION
59497 -+ A careful write of the ddl log is performed to ensure that we can
59498 -+ handle crashes occurring during CREATE and ALTER TABLE processing.
59499 -+*/
59500 -+
59501 -+bool write_ddl_log_entry(DDL_LOG_ENTRY *ddl_log_entry,
59502 -+ DDL_LOG_MEMORY_ENTRY **active_entry)
59503 -+{
59504 -+ bool error, write_header;
59505 -+ DBUG_ENTER("write_ddl_log_entry");
59506 -+
59507 -+ if (init_ddl_log())
59508 -+ {
59509 -+ DBUG_RETURN(TRUE);
59510 -+ }
59511 -+ global_ddl_log.file_entry_buf[DDL_LOG_ENTRY_TYPE_POS]=
59512 -+ (char)DDL_LOG_ENTRY_CODE;
59513 -+ global_ddl_log.file_entry_buf[DDL_LOG_ACTION_TYPE_POS]=
59514 -+ (char)ddl_log_entry->action_type;
59515 -+ global_ddl_log.file_entry_buf[DDL_LOG_PHASE_POS]= 0;
59516 -+ int4store(&global_ddl_log.file_entry_buf[DDL_LOG_NEXT_ENTRY_POS],
59517 -+ ddl_log_entry->next_entry);
59518 -+ DBUG_ASSERT(strlen(ddl_log_entry->name) < FN_LEN);
59519 -+ strmake(&global_ddl_log.file_entry_buf[DDL_LOG_NAME_POS],
59520 -+ ddl_log_entry->name, FN_LEN - 1);
59521 -+ if (ddl_log_entry->action_type == DDL_LOG_RENAME_ACTION ||
59522 -+ ddl_log_entry->action_type == DDL_LOG_REPLACE_ACTION)
59523 -+ {
59524 -+ DBUG_ASSERT(strlen(ddl_log_entry->from_name) < FN_LEN);
59525 -+ strmake(&global_ddl_log.file_entry_buf[DDL_LOG_NAME_POS + FN_LEN],
59526 -+ ddl_log_entry->from_name, FN_LEN - 1);
59527 -+ }
59528 -+ else
59529 -+ global_ddl_log.file_entry_buf[DDL_LOG_NAME_POS + FN_LEN]= 0;
59530 -+ DBUG_ASSERT(strlen(ddl_log_entry->handler_name) < FN_LEN);
59531 -+ strmake(&global_ddl_log.file_entry_buf[DDL_LOG_NAME_POS + (2*FN_LEN)],
59532 -+ ddl_log_entry->handler_name, FN_LEN - 1);
59533 -+ if (get_free_ddl_log_entry(active_entry, &write_header))
59534 -+ {
59535 -+ DBUG_RETURN(TRUE);
59536 -+ }
59537 -+ error= FALSE;
59538 -+ DBUG_PRINT("ddl_log",
59539 -+ ("write type %c next %u name '%s' from_name '%s' handler '%s'",
59540 -+ (char) global_ddl_log.file_entry_buf[DDL_LOG_ACTION_TYPE_POS],
59541 -+ ddl_log_entry->next_entry,
59542 -+ (char*) &global_ddl_log.file_entry_buf[DDL_LOG_NAME_POS],
59543 -+ (char*) &global_ddl_log.file_entry_buf[DDL_LOG_NAME_POS
59544 -+ + FN_LEN],
59545 -+ (char*) &global_ddl_log.file_entry_buf[DDL_LOG_NAME_POS
59546 -+ + (2*FN_LEN)]));
59547 -+ if (write_ddl_log_file_entry((*active_entry)->entry_pos))
59548 -+ {
59549 -+ error= TRUE;
59550 -+ sql_print_error("Failed to write entry_no = %u",
59551 -+ (*active_entry)->entry_pos);
59552 -+ }
59553 -+ if (write_header && !error)
59554 -+ {
59555 -+ VOID(sync_ddl_log());
59556 -+ if (write_ddl_log_header())
59557 -+ error= TRUE;
59558 -+ }
59559 -+ if (error)
59560 -+ release_ddl_log_memory_entry(*active_entry);
59561 -+ DBUG_RETURN(error);
59562 -+}
59563 -+
59564 -+
59565 -+/*
59566 -+ Write final entry in the ddl log
59567 -+ SYNOPSIS
59568 -+ write_execute_ddl_log_entry()
59569 -+ first_entry First entry in linked list of entries
59570 -+ to execute, if 0 = NULL it means that
59571 -+ the entry is removed and the entries
59572 -+ are put into the free list.
59573 -+ complete Flag indicating we are simply writing
59574 -+ info about that entry has been completed
59575 -+ in:out:active_entry Entry to execute, 0 = NULL if the entry
59576 -+ is written first time and needs to be
59577 -+ returned. In this case the entry written
59578 -+ is returned in this parameter
59579 -+ RETURN VALUES
59580 -+ TRUE Error
59581 -+ FALSE Success
59582 -+
59583 -+ DESCRIPTION
59584 -+ This is the last write in the ddl log. The previous log entries have
59585 -+ already been written but not yet synched to disk.
59586 -+ We write a couple of log entries that describes action to perform.
59587 -+ This entries are set-up in a linked list, however only when a first
59588 -+ execute entry is put as the first entry these will be executed.
59589 -+ This routine writes this first
59590 -+*/
59591 -+
59592 -+bool write_execute_ddl_log_entry(uint first_entry,
59593 -+ bool complete,
59594 -+ DDL_LOG_MEMORY_ENTRY **active_entry)
59595 -+{
59596 -+ bool write_header= FALSE;
59597 -+ char *file_entry_buf= (char*)global_ddl_log.file_entry_buf;
59598 -+ DBUG_ENTER("write_execute_ddl_log_entry");
59599 -+
59600 -+ if (init_ddl_log())
59601 -+ {
59602 -+ DBUG_RETURN(TRUE);
59603 -+ }
59604 -+ if (!complete)
59605 -+ {
59606 -+ /*
59607 -+ We haven't synched the log entries yet, we synch them now before
59608 -+ writing the execute entry. If complete is true we haven't written
59609 -+ any log entries before, we are only here to write the execute
59610 -+ entry to indicate it is done.
59611 -+ */
59612 -+ VOID(sync_ddl_log());
59613 -+ file_entry_buf[DDL_LOG_ENTRY_TYPE_POS]= (char)DDL_LOG_EXECUTE_CODE;
59614 -+ }
59615 -+ else
59616 -+ file_entry_buf[DDL_LOG_ENTRY_TYPE_POS]= (char)DDL_IGNORE_LOG_ENTRY_CODE;
59617 -+ file_entry_buf[DDL_LOG_ACTION_TYPE_POS]= 0; /* Ignored for execute entries */
59618 -+ file_entry_buf[DDL_LOG_PHASE_POS]= 0;
59619 -+ int4store(&file_entry_buf[DDL_LOG_NEXT_ENTRY_POS], first_entry);
59620 -+ file_entry_buf[DDL_LOG_NAME_POS]= 0;
59621 -+ file_entry_buf[DDL_LOG_NAME_POS + FN_LEN]= 0;
59622 -+ file_entry_buf[DDL_LOG_NAME_POS + 2*FN_LEN]= 0;
59623 -+ if (!(*active_entry))
59624 -+ {
59625 -+ if (get_free_ddl_log_entry(active_entry, &write_header))
59626 -+ {
59627 -+ DBUG_RETURN(TRUE);
59628 -+ }
59629 -+ }
59630 -+ if (write_ddl_log_file_entry((*active_entry)->entry_pos))
59631 -+ {
59632 -+ sql_print_error("Error writing execute entry in ddl log");
59633 -+ release_ddl_log_memory_entry(*active_entry);
59634 -+ DBUG_RETURN(TRUE);
59635 -+ }
59636 -+ VOID(sync_ddl_log());
59637 -+ if (write_header)
59638 -+ {
59639 -+ if (write_ddl_log_header())
59640 -+ {
59641 -+ release_ddl_log_memory_entry(*active_entry);
59642 -+ DBUG_RETURN(TRUE);
59643 -+ }
59644 -+ }
59645 -+ DBUG_RETURN(FALSE);
59646 -+}
59647 -+
59648 -+
59649 -+/*
59650 -+ For complex rename operations we need to deactivate individual entries.
59651 -+ SYNOPSIS
59652 -+ deactivate_ddl_log_entry()
59653 -+ entry_no Entry position of record to change
59654 -+ RETURN VALUES
59655 -+ TRUE Error
59656 -+ FALSE Success
59657 -+ DESCRIPTION
59658 -+ During replace operations where we start with an existing table called
59659 -+ t1 and a replacement table called t1#temp or something else and where
59660 -+ we want to delete t1 and rename t1#temp to t1 this is not possible to
59661 -+ do in a safe manner unless the ddl log is informed of the phases in
59662 -+ the change.
59663 -+
59664 -+ Delete actions are 1-phase actions that can be ignored immediately after
59665 -+ being executed.
59666 -+ Rename actions from x to y is also a 1-phase action since there is no
59667 -+ interaction with any other handlers named x and y.
59668 -+ Replace action where drop y and x -> y happens needs to be a two-phase
59669 -+ action. Thus the first phase will drop y and the second phase will
59670 -+ rename x -> y.
59671 -+*/
59672 -+
59673 -+bool deactivate_ddl_log_entry(uint entry_no)
59674 -+{
59675 -+ char *file_entry_buf= (char*)global_ddl_log.file_entry_buf;
59676 -+ DBUG_ENTER("deactivate_ddl_log_entry");
59677 -+
59678 -+ if (!read_ddl_log_file_entry(entry_no))
59679 -+ {
59680 -+ if (file_entry_buf[DDL_LOG_ENTRY_TYPE_POS] == DDL_LOG_ENTRY_CODE)
59681 -+ {
59682 -+ if (file_entry_buf[DDL_LOG_ACTION_TYPE_POS] == DDL_LOG_DELETE_ACTION ||
59683 -+ file_entry_buf[DDL_LOG_ACTION_TYPE_POS] == DDL_LOG_RENAME_ACTION ||
59684 -+ (file_entry_buf[DDL_LOG_ACTION_TYPE_POS] == DDL_LOG_REPLACE_ACTION &&
59685 -+ file_entry_buf[DDL_LOG_PHASE_POS] == 1))
59686 -+ file_entry_buf[DDL_LOG_ENTRY_TYPE_POS]= DDL_IGNORE_LOG_ENTRY_CODE;
59687 -+ else if (file_entry_buf[DDL_LOG_ACTION_TYPE_POS] == DDL_LOG_REPLACE_ACTION)
59688 -+ {
59689 -+ DBUG_ASSERT(file_entry_buf[DDL_LOG_PHASE_POS] == 0);
59690 -+ file_entry_buf[DDL_LOG_PHASE_POS]= 1;
59691 -+ }
59692 -+ else
59693 -+ {
59694 -+ DBUG_ASSERT(0);
59695 -+ }
59696 -+ if (write_ddl_log_file_entry(entry_no))
59697 -+ {
59698 -+ sql_print_error("Error in deactivating log entry. Position = %u",
59699 -+ entry_no);
59700 -+ DBUG_RETURN(TRUE);
59701 -+ }
59702 -+ }
59703 -+ }
59704 -+ else
59705 -+ {
59706 -+ sql_print_error("Failed in reading entry before deactivating it");
59707 -+ DBUG_RETURN(TRUE);
59708 -+ }
59709 -+ DBUG_RETURN(FALSE);
59710 -+}
59711 -+
59712 -+
59713 -+/*
59714 -+ Sync ddl log file
59715 -+ SYNOPSIS
59716 -+ sync_ddl_log()
59717 -+ RETURN VALUES
59718 -+ TRUE Error
59719 -+ FALSE Success
59720 -+*/
59721 -+
59722 -+bool sync_ddl_log()
59723 -+{
59724 -+ bool error= FALSE;
59725 -+ DBUG_ENTER("sync_ddl_log");
59726 -+
59727 -+ if ((!global_ddl_log.recovery_phase) &&
59728 -+ init_ddl_log())
59729 -+ {
59730 -+ DBUG_RETURN(TRUE);
59731 -+ }
59732 -+ if (my_sync(global_ddl_log.file_id, MYF(0)))
59733 -+ {
59734 -+ /* Write to error log */
59735 -+ sql_print_error("Failed to sync ddl log");
59736 -+ error= TRUE;
59737 -+ }
59738 -+ DBUG_RETURN(error);
59739 -+}
59740 -+
59741 -+
59742 -+/*
59743 -+ Release a log memory entry
59744 -+ SYNOPSIS
59745 -+ release_ddl_log_memory_entry()
59746 -+ log_memory_entry Log memory entry to release
59747 -+ RETURN VALUES
59748 -+ NONE
59749 -+*/
59750 -+
59751 -+void release_ddl_log_memory_entry(DDL_LOG_MEMORY_ENTRY *log_entry)
59752 -+{
59753 -+ DDL_LOG_MEMORY_ENTRY *first_free= global_ddl_log.first_free;
59754 -+ DDL_LOG_MEMORY_ENTRY *next_log_entry= log_entry->next_log_entry;
59755 -+ DDL_LOG_MEMORY_ENTRY *prev_log_entry= log_entry->prev_log_entry;
59756 -+ DBUG_ENTER("release_ddl_log_memory_entry");
59757 -+
59758 -+ global_ddl_log.first_free= log_entry;
59759 -+ log_entry->next_log_entry= first_free;
59760 -+
59761 -+ if (prev_log_entry)
59762 -+ prev_log_entry->next_log_entry= next_log_entry;
59763 -+ else
59764 -+ global_ddl_log.first_used= next_log_entry;
59765 -+ if (next_log_entry)
59766 -+ next_log_entry->prev_log_entry= prev_log_entry;
59767 -+ DBUG_VOID_RETURN;
59768 -+}
59769 -+
59770 -+
59771 -+/*
59772 -+ Execute one entry in the ddl log. Executing an entry means executing
59773 -+ a linked list of actions.
59774 -+ SYNOPSIS
59775 -+ execute_ddl_log_entry()
59776 -+ first_entry Reference to first action in entry
59777 -+ RETURN VALUES
59778 -+ TRUE Error
59779 -+ FALSE Success
59780 -+*/
59781 -+
59782 -+bool execute_ddl_log_entry(THD *thd, uint first_entry)
59783 -+{
59784 -+ DDL_LOG_ENTRY ddl_log_entry;
59785 -+ uint read_entry= first_entry;
59786 -+ DBUG_ENTER("execute_ddl_log_entry");
59787 -+
59788 -+ pthread_mutex_lock(&LOCK_gdl);
59789 -+ do
59790 -+ {
59791 -+ if (read_ddl_log_entry(read_entry, &ddl_log_entry))
59792 -+ {
59793 -+ /* Write to error log and continue with next log entry */
59794 -+ sql_print_error("Failed to read entry = %u from ddl log",
59795 -+ read_entry);
59796 -+ break;
59797 -+ }
59798 -+ DBUG_ASSERT(ddl_log_entry.entry_type == DDL_LOG_ENTRY_CODE ||
59799 -+ ddl_log_entry.entry_type == DDL_IGNORE_LOG_ENTRY_CODE);
59800 -+
59801 -+ if (execute_ddl_log_action(thd, &ddl_log_entry))
59802 -+ {
59803 -+ /* Write to error log and continue with next log entry */
59804 -+ sql_print_error("Failed to execute action for entry = %u from ddl log",
59805 -+ read_entry);
59806 -+ break;
59807 -+ }
59808 -+ read_entry= ddl_log_entry.next_entry;
59809 -+ } while (read_entry);
59810 -+ pthread_mutex_unlock(&LOCK_gdl);
59811 -+ DBUG_RETURN(FALSE);
59812 -+}
59813 -+
59814 -+
59815 -+/*
59816 -+ Close the ddl log
59817 -+ SYNOPSIS
59818 -+ close_ddl_log()
59819 -+ RETURN VALUES
59820 -+ NONE
59821 -+*/
59822 -+
59823 -+static void close_ddl_log()
59824 -+{
59825 -+ DBUG_ENTER("close_ddl_log");
59826 -+ if (global_ddl_log.file_id >= 0)
59827 -+ {
59828 -+ VOID(my_close(global_ddl_log.file_id, MYF(MY_WME)));
59829 -+ global_ddl_log.file_id= (File) -1;
59830 -+ }
59831 -+ DBUG_VOID_RETURN;
59832 -+}
59833 -+
59834 -+
59835 -+/*
59836 -+ Execute the ddl log at recovery of MySQL Server
59837 -+ SYNOPSIS
59838 -+ execute_ddl_log_recovery()
59839 -+ RETURN VALUES
59840 -+ NONE
59841 -+*/
59842 -+
59843 -+void execute_ddl_log_recovery()
59844 -+{
59845 -+ uint num_entries, i;
59846 -+ THD *thd;
59847 -+ DDL_LOG_ENTRY ddl_log_entry;
59848 -+ char file_name[FN_REFLEN];
59849 -+ DBUG_ENTER("execute_ddl_log_recovery");
59850 -+
59851 -+ /*
59852 -+ Initialise global_ddl_log struct
59853 -+ */
59854 -+ bzero(global_ddl_log.file_entry_buf, sizeof(global_ddl_log.file_entry_buf));
59855 -+ global_ddl_log.inited= FALSE;
59856 -+ global_ddl_log.recovery_phase= TRUE;
59857 -+ global_ddl_log.io_size= IO_SIZE;
59858 -+ global_ddl_log.file_id= (File) -1;
59859 -+
59860 -+ /*
59861 -+ To be able to run this from boot, we allocate a temporary THD
59862 -+ */
59863 -+ if (!(thd=new THD))
59864 -+ DBUG_VOID_RETURN;
59865 -+ thd->thread_stack= (char*) &thd;
59866 -+ thd->store_globals();
59867 -+
59868 -+ num_entries= read_ddl_log_header();
59869 -+ for (i= 1; i < num_entries + 1; i++)
59870 -+ {
59871 -+ if (read_ddl_log_entry(i, &ddl_log_entry))
59872 -+ {
59873 -+ sql_print_error("Failed to read entry no = %u from ddl log",
59874 -+ i);
59875 -+ continue;
59876 -+ }
59877 -+ if (ddl_log_entry.entry_type == DDL_LOG_EXECUTE_CODE)
59878 -+ {
59879 -+ if (execute_ddl_log_entry(thd, ddl_log_entry.next_entry))
59880 -+ {
59881 -+ /* Real unpleasant scenario but we continue anyways. */
59882 -+ continue;
59883 -+ }
59884 -+ }
59885 -+ }
59886 -+ close_ddl_log();
59887 -+ create_ddl_log_file_name(file_name);
59888 -+ VOID(my_delete(file_name, MYF(0)));
59889 -+ global_ddl_log.recovery_phase= FALSE;
59890 -+ delete thd;
59891 -+ /* Remember that we don't have a THD */
59892 -+ my_pthread_setspecific_ptr(THR_THD, 0);
59893 -+ DBUG_VOID_RETURN;
59894 -+}
59895 -+
59896 -+
59897 -+/*
59898 -+ Release all memory allocated to the ddl log
59899 -+ SYNOPSIS
59900 -+ release_ddl_log()
59901 -+ RETURN VALUES
59902 -+ NONE
59903 -+*/
59904 -+
59905 -+void release_ddl_log()
59906 -+{
59907 -+ DDL_LOG_MEMORY_ENTRY *free_list= global_ddl_log.first_free;
59908 -+ DDL_LOG_MEMORY_ENTRY *used_list= global_ddl_log.first_used;
59909 -+ DBUG_ENTER("release_ddl_log");
59910 -+
59911 -+ if (!global_ddl_log.do_release)
59912 -+ DBUG_VOID_RETURN;
59913 -+
59914 -+ pthread_mutex_lock(&LOCK_gdl);
59915 -+ while (used_list)
59916 -+ {
59917 -+ DDL_LOG_MEMORY_ENTRY *tmp= used_list->next_log_entry;
59918 -+ my_free(used_list, MYF(0));
59919 -+ used_list= tmp;
59920 -+ }
59921 -+ while (free_list)
59922 -+ {
59923 -+ DDL_LOG_MEMORY_ENTRY *tmp= free_list->next_log_entry;
59924 -+ my_free(free_list, MYF(0));
59925 -+ free_list= tmp;
59926 -+ }
59927 -+ close_ddl_log();
59928 -+ global_ddl_log.inited= 0;
59929 -+ pthread_mutex_unlock(&LOCK_gdl);
59930 -+ VOID(pthread_mutex_destroy(&LOCK_gdl));
59931 -+ global_ddl_log.do_release= false;
59932 -+ DBUG_VOID_RETURN;
59933 -+}
59934 -+
59935 -+
59936 -+/*
59937 -+---------------------------------------------------------------------------
59938 -+
59939 -+ END MODULE DDL log
59940 -+ --------------------
59941 -+
59942 -+---------------------------------------------------------------------------
59943 -+*/
59944 -+
59945 -+
59946 -+/**
59947 -+ @brief construct a temporary shadow file name.
59948 -+
59949 -+ @details Make a shadow file name used by ALTER TABLE to construct the
59950 -+ modified table (with keeping the original). The modified table is then
59951 -+ moved back as original table. The name must start with the temp file
59952 -+ prefix so it gets filtered out by table files listing routines.
59953 -+
59954 -+ @param[out] buff buffer to receive the constructed name
59955 -+ @param bufflen size of buff
59956 -+ @param lpt alter table data structure
59957 -+
59958 -+ @retval path length
59959 -+*/
59960 -+
59961 -+uint build_table_shadow_filename(char *buff, size_t bufflen,
59962 -+ ALTER_PARTITION_PARAM_TYPE *lpt)
59963 -+{
59964 -+ char tmp_name[FN_REFLEN];
59965 -+ my_snprintf (tmp_name, sizeof (tmp_name), "%s-%s", tmp_file_prefix,
59966 -+ lpt->table_name);
59967 -+ return build_table_filename(buff, bufflen, lpt->db, tmp_name, "", FN_IS_TMP);
59968 -+}
59969 -+
59970 -+
59971 -+/*
59972 -+ SYNOPSIS
59973 -+ mysql_write_frm()
59974 -+ lpt Struct carrying many parameters needed for this
59975 -+ method
59976 -+ flags Flags as defined below
59977 -+ WFRM_INITIAL_WRITE If set we need to prepare table before
59978 -+ creating the frm file
59979 -+ WFRM_INSTALL_SHADOW If set we should install the new frm
59980 -+ WFRM_KEEP_SHARE If set we know that the share is to be
59981 -+ retained and thus we should ensure share
59982 -+ object is correct, if not set we don't
59983 -+ set the new partition syntax string since
59984 -+ we know the share object is destroyed.
59985 -+ WFRM_PACK_FRM If set we should pack the frm file and delete
59986 -+ the frm file
59987 -+
59988 -+ RETURN VALUES
59989 -+ TRUE Error
59990 -+ FALSE Success
59991 -+
59992 -+ DESCRIPTION
59993 -+ A support method that creates a new frm file and in this process it
59994 -+ regenerates the partition data. It works fine also for non-partitioned
59995 -+ tables since it only handles partitioned data if it exists.
59996 -+*/
59997 -+
59998 -+bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags)
59999 -+{
60000 -+ /*
60001 -+ Prepare table to prepare for writing a new frm file where the
60002 -+ partitions in add/drop state have temporarily changed their state
60003 -+ We set tmp_table to avoid get errors on naming of primary key index.
60004 -+ */
60005 -+ int error= 0;
60006 -+ char path[FN_REFLEN+1];
60007 -+ char shadow_path[FN_REFLEN+1];
60008 -+ char shadow_frm_name[FN_REFLEN+1];
60009 -+ char frm_name[FN_REFLEN+1];
60010 -+#ifdef WITH_PARTITION_STORAGE_ENGINE
60011 -+ char *part_syntax_buf;
60012 -+ uint syntax_len;
60013 -+#endif
60014 -+ DBUG_ENTER("mysql_write_frm");
60015 -+
60016 -+ /*
60017 -+ Build shadow frm file name
60018 -+ */
60019 -+ build_table_shadow_filename(shadow_path, sizeof(shadow_path) - 1, lpt);
60020 -+ strxmov(shadow_frm_name, shadow_path, reg_ext, NullS);
60021 -+ if (flags & WFRM_WRITE_SHADOW)
60022 -+ {
60023 -+ if (mysql_prepare_create_table(lpt->thd, lpt->create_info,
60024 -+ lpt->alter_info,
60025 -+ /*tmp_table*/ 1,
60026 -+ &lpt->db_options,
60027 -+ lpt->table->file,
60028 -+ &lpt->key_info_buffer,
60029 -+ &lpt->key_count,
60030 -+ /*select_field_count*/ 0))
60031 -+ {
60032 -+ DBUG_RETURN(TRUE);
60033 -+ }
60034 -+#ifdef WITH_PARTITION_STORAGE_ENGINE
60035 -+ {
60036 -+ partition_info *part_info= lpt->table->part_info;
60037 -+ if (part_info)
60038 -+ {
60039 -+ if (!(part_syntax_buf= generate_partition_syntax(part_info,
60040 -+ &syntax_len,
60041 -+ TRUE, TRUE)))
60042 -+ {
60043 -+ DBUG_RETURN(TRUE);
60044 -+ }
60045 -+ part_info->part_info_string= part_syntax_buf;
60046 -+ part_info->part_info_len= syntax_len;
60047 -+ }
60048 -+ }
60049 -+#endif
60050 -+ /* Write shadow frm file */
60051 -+ lpt->create_info->table_options= lpt->db_options;
60052 -+ if ((mysql_create_frm(lpt->thd, shadow_frm_name, lpt->db,
60053 -+ lpt->table_name, lpt->create_info,
60054 -+ lpt->alter_info->create_list, lpt->key_count,
60055 -+ lpt->key_info_buffer, lpt->table->file)) ||
60056 -+ lpt->table->file->ha_create_handler_files(shadow_path, NULL,
60057 -+ CHF_CREATE_FLAG,
60058 -+ lpt->create_info))
60059 -+ {
60060 -+ my_delete(shadow_frm_name, MYF(0));
60061 -+ error= 1;
60062 -+ goto end;
60063 -+ }
60064 -+ }
60065 -+ if (flags & WFRM_PACK_FRM)
60066 -+ {
60067 -+ /*
60068 -+ We need to pack the frm file and after packing it we delete the
60069 -+ frm file to ensure it doesn't get used. This is only used for
60070 -+ handlers that have the main version of the frm file stored in the
60071 -+ handler.
60072 -+ */
60073 -+ uchar *data;
60074 -+ size_t length;
60075 -+ if (readfrm(shadow_path, &data, &length) ||
60076 -+ packfrm(data, length, &lpt->pack_frm_data, &lpt->pack_frm_len))
60077 -+ {
60078 -+ my_free(data, MYF(MY_ALLOW_ZERO_PTR));
60079 -+ my_free(lpt->pack_frm_data, MYF(MY_ALLOW_ZERO_PTR));
60080 -+ mem_alloc_error(length);
60081 -+ error= 1;
60082 -+ goto end;
60083 -+ }
60084 -+ error= my_delete(shadow_frm_name, MYF(MY_WME));
60085 -+ }
60086 -+ if (flags & WFRM_INSTALL_SHADOW)
60087 -+ {
60088 -+#ifdef WITH_PARTITION_STORAGE_ENGINE
60089 -+ partition_info *part_info= lpt->part_info;
60090 -+#endif
60091 -+ /*
60092 -+ Build frm file name
60093 -+ */
60094 -+ build_table_filename(path, sizeof(path) - 1, lpt->db,
60095 -+ lpt->table_name, "", 0);
60096 -+ strxmov(frm_name, path, reg_ext, NullS);
60097 -+ /*
60098 -+ When we are changing to use new frm file we need to ensure that we
60099 -+ don't collide with another thread in process to open the frm file.
60100 -+ We start by deleting the .frm file and possible .par file. Then we
60101 -+ write to the DDL log that we have completed the delete phase by
60102 -+ increasing the phase of the log entry. Next step is to rename the
60103 -+ new .frm file and the new .par file to the real name. After
60104 -+ completing this we write a new phase to the log entry that will
60105 -+ deactivate it.
60106 -+ */
60107 -+ VOID(pthread_mutex_lock(&LOCK_open));
60108 -+ if (my_delete(frm_name, MYF(MY_WME)) ||
60109 -+#ifdef WITH_PARTITION_STORAGE_ENGINE
60110 -+ lpt->table->file->ha_create_handler_files(path, shadow_path,
60111 -+ CHF_DELETE_FLAG, NULL) ||
60112 -+ deactivate_ddl_log_entry(part_info->frm_log_entry->entry_pos) ||
60113 -+ (sync_ddl_log(), FALSE) ||
60114 -+#endif
60115 -+#ifdef WITH_PARTITION_STORAGE_ENGINE
60116 -+ my_rename(shadow_frm_name, frm_name, MYF(MY_WME)) ||
60117 -+ lpt->table->file->ha_create_handler_files(path, shadow_path,
60118 -+ CHF_RENAME_FLAG, NULL))
60119 -+#else
60120 -+ my_rename(shadow_frm_name, frm_name, MYF(MY_WME)))
60121 -+#endif
60122 -+ {
60123 -+ error= 1;
60124 -+ goto err;
60125 -+ }
60126 -+#ifdef WITH_PARTITION_STORAGE_ENGINE
60127 -+ if (part_info && (flags & WFRM_KEEP_SHARE))
60128 -+ {
60129 -+ TABLE_SHARE *share= lpt->table->s;
60130 -+ char *tmp_part_syntax_str;
60131 -+ if (!(part_syntax_buf= generate_partition_syntax(part_info,
60132 -+ &syntax_len,
60133 -+ TRUE, TRUE)))
60134 -+ {
60135 -+ error= 1;
60136 -+ goto err;
60137 -+ }
60138 -+ if (share->partition_info_buffer_size < syntax_len + 1)
60139 -+ {
60140 -+ share->partition_info_buffer_size= syntax_len+1;
60141 -+ if (!(tmp_part_syntax_str= (char*) strmake_root(&share->mem_root,
60142 -+ part_syntax_buf,
60143 -+ syntax_len)))
60144 -+ {
60145 -+ error= 1;
60146 -+ goto err;
60147 -+ }
60148 -+ share->partition_info= tmp_part_syntax_str;
60149 -+ }
60150 -+ else
60151 -+ memcpy((char*) share->partition_info, part_syntax_buf, syntax_len + 1);
60152 -+ share->partition_info_len= part_info->part_info_len= syntax_len;
60153 -+ part_info->part_info_string= part_syntax_buf;
60154 -+ }
60155 -+#endif
60156 -+
60157 -+err:
60158 -+ VOID(pthread_mutex_unlock(&LOCK_open));
60159 -+#ifdef WITH_PARTITION_STORAGE_ENGINE
60160 -+ deactivate_ddl_log_entry(part_info->frm_log_entry->entry_pos);
60161 -+ part_info->frm_log_entry= NULL;
60162 -+ VOID(sync_ddl_log());
60163 -+#endif
60164 -+ }
60165 -+
60166 -+end:
60167 -+ DBUG_RETURN(error);
60168 -+}
60169 -+
60170 -+
60171 -+/*
60172 -+ SYNOPSIS
60173 -+ write_bin_log()
60174 -+ thd Thread object
60175 -+ clear_error is clear_error to be called
60176 -+ query Query to log
60177 -+ query_length Length of query
60178 -+
60179 -+ RETURN VALUES
60180 -+ NONE
60181 -+
60182 -+ DESCRIPTION
60183 -+ Write the binlog if open, routine used in multiple places in this
60184 -+ file
60185 -+*/
60186 -+
60187 -+int write_bin_log(THD *thd, bool clear_error,
60188 -+ char const *query, ulong query_length)
60189 -+{
60190 -+ int error= 0;
60191 -+ if (mysql_bin_log.is_open())
60192 -+ {
60193 -+ int errcode= 0;
60194 -+ if (clear_error)
60195 -+ thd->clear_error();
60196 -+ else
60197 -+ errcode= query_error_code(thd, TRUE);
60198 -+ error= thd->binlog_query(THD::STMT_QUERY_TYPE,
60199 -+ query, query_length, FALSE, FALSE, errcode);
60200 -+ }
60201 -+ return error;
60202 -+}
60203 -+
60204 -+
60205 -+/*
60206 -+ delete (drop) tables.
60207 -+
60208 -+ SYNOPSIS
60209 -+ mysql_rm_table()
60210 -+ thd Thread handle
60211 -+ tables List of tables to delete
60212 -+ if_exists If 1, don't give error if one table doesn't exists
60213 -+
60214 -+ NOTES
60215 -+ Will delete all tables that can be deleted and give a compact error
60216 -+ messages for tables that could not be deleted.
60217 -+ If a table is in use, we will wait for all users to free the table
60218 -+ before dropping it
60219 -+
60220 -+ Wait if global_read_lock (FLUSH TABLES WITH READ LOCK) is set.
60221 -+
60222 -+ RETURN
60223 -+ FALSE OK. In this case ok packet is sent to user
60224 -+ TRUE Error
60225 -+
60226 -+*/
60227 -+
60228 -+bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists,
60229 -+ my_bool drop_temporary)
60230 -+{
60231 -+ bool error= FALSE, need_start_waiters= FALSE;
60232 -+ Drop_table_error_handler err_handler(thd->get_internal_handler());
60233 -+ DBUG_ENTER("mysql_rm_table");
60234 -+
60235 -+ /* mark for close and remove all cached entries */
60236 -+
60237 -+ if (!drop_temporary)
60238 -+ {
60239 -+ if ((error= wait_if_global_read_lock(thd, 0, 1)))
60240 -+ {
60241 -+ my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, MYF(0), tables->table_name);
60242 -+ DBUG_RETURN(TRUE);
60243 -+ }
60244 -+ else
60245 -+ need_start_waiters= TRUE;
60246 -+ }
60247 -+
60248 -+ /*
60249 -+ Acquire LOCK_open after wait_if_global_read_lock(). If we would hold
60250 -+ LOCK_open during wait_if_global_read_lock(), other threads could not
60251 -+ close their tables. This would make a pretty deadlock.
60252 -+ */
60253 -+ thd->push_internal_handler(&err_handler);
60254 -+ error= mysql_rm_table_part2(thd, tables, if_exists, drop_temporary, 0, 0);
60255 -+ thd->pop_internal_handler();
60256 -+
60257 -+
60258 -+ if (need_start_waiters)
60259 -+ start_waiting_global_read_lock(thd);
60260 -+
60261 -+ if (error)
60262 -+ DBUG_RETURN(TRUE);
60263 -+ my_ok(thd);
60264 -+ DBUG_RETURN(FALSE);
60265 -+}
60266 -+
60267 -+/*
60268 -+ Execute the drop of a normal or temporary table
60269 -+
60270 -+ SYNOPSIS
60271 -+ mysql_rm_table_part2()
60272 -+ thd Thread handler
60273 -+ tables Tables to drop
60274 -+ if_exists If set, don't give an error if table doesn't exists.
60275 -+ In this case we give an warning of level 'NOTE'
60276 -+ drop_temporary Only drop temporary tables
60277 -+ drop_view Allow to delete VIEW .frm
60278 -+ dont_log_query Don't write query to log files. This will also not
60279 -+ generate warnings if the handler files doesn't exists
60280 -+
60281 -+ TODO:
60282 -+ When logging to the binary log, we should log
60283 -+ tmp_tables and transactional tables as separate statements if we
60284 -+ are in a transaction; This is needed to get these tables into the
60285 -+ cached binary log that is only written on COMMIT.
60286 -+
60287 -+ The current code only writes DROP statements that only uses temporary
60288 -+ tables to the cache binary log. This should be ok on most cases, but
60289 -+ not all.
60290 -+
60291 -+ RETURN
60292 -+ 0 ok
60293 -+ 1 Error
60294 -+ -1 Thread was killed
60295 -+*/
60296 -+
60297 -+int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
60298 -+ bool drop_temporary, bool drop_view,
60299 -+ bool dont_log_query)
60300 -+{
60301 -+ TABLE_LIST *table;
60302 -+ char path[FN_REFLEN + 1], *alias;
60303 -+ uint path_length;
60304 -+ String wrong_tables;
60305 -+ int error= 0;
60306 -+ int non_temp_tables_count= 0;
60307 -+ bool some_tables_deleted=0, tmp_table_deleted=0, foreign_key_error=0;
60308 -+ String built_query;
60309 -+ String built_tmp_query;
60310 -+ DBUG_ENTER("mysql_rm_table_part2");
60311 -+
60312 -+ LINT_INIT(alias);
60313 -+ LINT_INIT(path_length);
60314 -+
60315 -+ if (thd->current_stmt_binlog_row_based && !dont_log_query)
60316 -+ {
60317 -+ built_query.set_charset(system_charset_info);
60318 -+ if (if_exists)
60319 -+ built_query.append("DROP TABLE IF EXISTS ");
60320 -+ else
60321 -+ built_query.append("DROP TABLE ");
60322 -+ }
60323 -+
60324 -+ mysql_ha_rm_tables(thd, tables, FALSE);
60325 -+
60326 -+ pthread_mutex_lock(&LOCK_open);
60327 -+
60328 -+ /* Disable drop of enabled log tables, must be done before name locking */
60329 -+ for (table= tables; table; table= table->next_local)
60330 -+ {
60331 -+ if (check_if_log_table(table->db_length, table->db,
60332 -+ table->table_name_length, table->table_name, 1))
60333 -+ {
60334 -+ my_error(ER_BAD_LOG_STATEMENT, MYF(0), "DROP");
60335 -+ pthread_mutex_unlock(&LOCK_open);
60336 -+ DBUG_RETURN(1);
60337 -+ }
60338 -+ }
60339 -+
60340 -+ if (!drop_temporary && lock_table_names_exclusively(thd, tables))
60341 -+ {
60342 -+ pthread_mutex_unlock(&LOCK_open);
60343 -+ DBUG_RETURN(1);
60344 -+ }
60345 -+
60346 -+ for (table= tables; table; table= table->next_local)
60347 -+ {
60348 -+ char *db=table->db;
60349 -+ handlerton *table_type;
60350 -+ enum legacy_db_type frm_db_type= DB_TYPE_UNKNOWN;
60351 -+
60352 -+ DBUG_PRINT("table", ("table_l: '%s'.'%s' table: 0x%lx s: 0x%lx",
60353 -+ table->db, table->table_name, (long) table->table,
60354 -+ table->table ? (long) table->table->s : (long) -1));
60355 -+
60356 -+ error= drop_temporary_table(thd, table);
60357 -+
60358 -+ switch (error) {
60359 -+ case 0:
60360 -+ // removed temporary table
60361 -+ tmp_table_deleted= 1;
60362 -+ if (thd->variables.binlog_format == BINLOG_FORMAT_MIXED &&
60363 -+ thd->current_stmt_binlog_row_based)
60364 -+ {
60365 -+ if (built_tmp_query.is_empty())
60366 -+ {
60367 -+ built_tmp_query.set_charset(system_charset_info);
60368 -+ built_tmp_query.append("DROP TEMPORARY TABLE IF EXISTS ");
60369 -+ }
60370 -+
60371 -+ built_tmp_query.append("`");
60372 -+ if (thd->db == NULL || strcmp(db,thd->db) != 0)
60373 -+ {
60374 -+ built_tmp_query.append(db);
60375 -+ built_tmp_query.append("`.`");
60376 -+ }
60377 -+ built_tmp_query.append(table->table_name);
60378 -+ built_tmp_query.append("`,");
60379 -+ }
60380 -+
60381 -+ continue;
60382 -+ case -1:
60383 -+ DBUG_ASSERT(thd->in_sub_stmt);
60384 -+ error= 1;
60385 -+ goto err_with_placeholders;
60386 -+ default:
60387 -+ // temporary table not found
60388 -+ error= 0;
60389 -+ }
60390 -+
60391 -+ /*
60392 -+ If row-based replication is used and the table is not a
60393 -+ temporary table, we add the table name to the drop statement
60394 -+ being built. The string always end in a comma and the comma
60395 -+ will be chopped off before being written to the binary log.
60396 -+ */
60397 -+ if (!drop_temporary && thd->current_stmt_binlog_row_based && !dont_log_query)
60398 -+ {
60399 -+ non_temp_tables_count++;
60400 -+ /*
60401 -+ Don't write the database name if it is the current one (or if
60402 -+ thd->db is NULL).
60403 -+ */
60404 -+ built_query.append("`");
60405 -+ if (thd->db == NULL || strcmp(db,thd->db) != 0)
60406 -+ {
60407 -+ built_query.append(db);
60408 -+ built_query.append("`.`");
60409 -+ }
60410 -+
60411 -+ built_query.append(table->table_name);
60412 -+ built_query.append("`,");
60413 -+ }
60414 -+
60415 -+ if (!drop_temporary)
60416 -+ {
60417 -+ TABLE *locked_table;
60418 -+ abort_locked_tables(thd, db, table->table_name);
60419 -+ remove_table_from_cache(thd, db, table->table_name,
60420 -+ RTFC_WAIT_OTHER_THREAD_FLAG |
60421 -+ RTFC_CHECK_KILLED_FLAG);
60422 -+ /*
60423 -+ If the table was used in lock tables, remember it so that
60424 -+ unlock_table_names can free it
60425 -+ */
60426 -+ if ((locked_table= drop_locked_tables(thd, db, table->table_name)))
60427 -+ table->table= locked_table;
60428 -+
60429 -+ if (thd->killed)
60430 -+ {
60431 -+ error= -1;
60432 -+ goto err_with_placeholders;
60433 -+ }
60434 -+ alias= (lower_case_table_names == 2) ? table->alias : table->table_name;
60435 -+ /* remove .frm file and engine files */
60436 -+ path_length= build_table_filename(path, sizeof(path) - 1, db, alias,
60437 -+ reg_ext,
60438 -+ table->internal_tmp_table ?
60439 -+ FN_IS_TMP : 0);
60440 -+ }
60441 -+ DEBUG_SYNC(thd, "rm_table_part2_before_delete_table");
60442 -+ if (drop_temporary ||
60443 -+ ((access(path, F_OK) &&
60444 -+ ha_create_table_from_engine(thd, db, alias)) ||
60445 -+ (!drop_view &&
60446 -+ mysql_frm_type(thd, path, &frm_db_type) != FRMTYPE_TABLE)))
60447 -+ {
60448 -+ // Table was not found on disk and table can't be created from engine
60449 -+ if (if_exists)
60450 -+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
60451 -+ ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
60452 -+ table->table_name);
60453 -+ else
60454 -+ error= 1;
60455 -+ }
60456 -+ else
60457 -+ {
60458 -+ char *end;
60459 -+ /*
60460 -+ Cannot use the db_type from the table, since that might have changed
60461 -+ while waiting for the exclusive name lock. We are under LOCK_open,
60462 -+ so reading from the frm-file is safe.
60463 -+ */
60464 -+ if (frm_db_type == DB_TYPE_UNKNOWN)
60465 -+ {
60466 -+ mysql_frm_type(thd, path, &frm_db_type);
60467 -+ DBUG_PRINT("info", ("frm_db_type %d from %s", frm_db_type, path));
60468 -+ }
60469 -+ table_type= ha_resolve_by_legacy_type(thd, frm_db_type);
60470 -+ // Remove extension for delete
60471 -+ *(end= path + path_length - reg_ext_length)= '\0';
60472 -+ DBUG_PRINT("info", ("deleting table of type %d",
60473 -+ (table_type ? table_type->db_type : 0)));
60474 -+ error= ha_delete_table(thd, table_type, path, db, table->table_name,
60475 -+ !dont_log_query);
60476 -+
60477 -+ /* No error if non existent table and 'IF EXIST' clause or view */
60478 -+ if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) &&
60479 -+ (if_exists || table_type == NULL))
60480 -+ {
60481 -+ error= 0;
60482 -+ thd->clear_error();
60483 -+ }
60484 -+ if (error == HA_ERR_ROW_IS_REFERENCED)
60485 -+ {
60486 -+ /* the table is referenced by a foreign key constraint */
60487 -+ foreign_key_error=1;
60488 -+ }
60489 -+ if (!error || error == ENOENT || error == HA_ERR_NO_SUCH_TABLE)
60490 -+ {
60491 -+ int new_error;
60492 -+ /* Delete the table definition file */
60493 -+ strmov(end,reg_ext);
60494 -+ if (!(new_error=my_delete(path,MYF(MY_WME))))
60495 -+ {
60496 -+ some_tables_deleted=1;
60497 -+ new_error= Table_triggers_list::drop_all_triggers(thd, db,
60498 -+ table->table_name);
60499 -+ }
60500 -+ error|= new_error;
60501 -+ }
60502 -+ }
60503 -+ if (error)
60504 -+ {
60505 -+ if (wrong_tables.length())
60506 -+ wrong_tables.append(',');
60507 -+ wrong_tables.append(String(table->table_name,system_charset_info));
60508 -+ }
60509 -+ DBUG_PRINT("table", ("table: 0x%lx s: 0x%lx", (long) table->table,
60510 -+ table->table ? (long) table->table->s : (long) -1));
60511 -+ }
60512 -+ /*
60513 -+ It's safe to unlock LOCK_open: we have an exclusive lock
60514 -+ on the table name.
60515 -+ */
60516 -+ pthread_mutex_unlock(&LOCK_open);
60517 -+ DEBUG_SYNC(thd, "rm_table_part2_before_binlog");
60518 -+ thd->thread_specific_used|= tmp_table_deleted;
60519 -+ error= 0;
60520 -+ if (wrong_tables.length())
60521 -+ {
60522 -+ if (!foreign_key_error)
60523 -+ my_printf_error(ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR), MYF(0),
60524 -+ wrong_tables.c_ptr());
60525 -+ else
60526 -+ my_message(ER_ROW_IS_REFERENCED, ER(ER_ROW_IS_REFERENCED), MYF(0));
60527 -+ error= 1;
60528 -+ }
60529 -+
60530 -+ if (some_tables_deleted || tmp_table_deleted || !error)
60531 -+ {
60532 -+ query_cache_invalidate3(thd, tables, 0);
60533 -+ if (!dont_log_query)
60534 -+ {
60535 -+ if (!thd->current_stmt_binlog_row_based ||
60536 -+ (non_temp_tables_count > 0 && !tmp_table_deleted))
60537 -+ {
60538 -+ /*
60539 -+ In this case, we are either using statement-based
60540 -+ replication or using row-based replication but have only
60541 -+ deleted one or more non-temporary tables (and no temporary
60542 -+ tables). In this case, we can write the original query into
60543 -+ the binary log.
60544 -+ */
60545 -+ error |= write_bin_log(thd, !error, thd->query(), thd->query_length());
60546 -+ }
60547 -+ else if (thd->current_stmt_binlog_row_based &&
60548 -+ tmp_table_deleted)
60549 -+ {
60550 -+ if (non_temp_tables_count > 0)
60551 -+ {
60552 -+ /*
60553 -+ In this case we have deleted both temporary and
60554 -+ non-temporary tables, so:
60555 -+ - since we have deleted a non-temporary table we have to
60556 -+ binlog the statement, but
60557 -+ - since we have deleted a temporary table we cannot binlog
60558 -+ the statement (since the table may have not been created on the
60559 -+ slave - check "if" branch below, this might cause the slave to
60560 -+ stop).
60561 -+
60562 -+ Instead, we write a built statement, only containing the
60563 -+ non-temporary tables, to the binary log
60564 -+ */
60565 -+ built_query.chop(); // Chop of the last comma
60566 -+ built_query.append(" /* generated by server */");
60567 -+ error|= write_bin_log(thd, !error, built_query.ptr(), built_query.length());
60568 -+ }
60569 -+
60570 -+ /*
60571 -+ One needs to always log any temporary table drop, if:
60572 -+ 1. thread logging format is mixed mode; AND
60573 -+ 2. current statement logging format is set to row.
60574 -+ */
60575 -+ if (thd->variables.binlog_format == BINLOG_FORMAT_MIXED)
60576 -+ {
60577 -+ /*
60578 -+ In this case we have deleted some temporary tables but we are using
60579 -+ row based logging for the statement. However, thread uses mixed mode
60580 -+ format, thence we need to log the dropping as we cannot tell for
60581 -+ sure whether the create was logged as statement previously or not, ie,
60582 -+ before switching to row mode.
60583 -+ */
60584 -+ built_tmp_query.chop(); // Chop of the last comma
60585 -+ built_tmp_query.append(" /* generated by server */");
60586 -+ error|= write_bin_log(thd, !error, built_tmp_query.ptr(), built_tmp_query.length());
60587 -+ }
60588 -+ }
60589 -+
60590 -+ /*
60591 -+ The remaining cases are:
60592 -+ - no tables were deleted and
60593 -+ - only temporary tables were deleted and row-based
60594 -+ replication is used.
60595 -+ In both these cases, nothing should be written to the binary
60596 -+ log.
60597 -+ */
60598 -+ }
60599 -+ }
60600 -+ pthread_mutex_lock(&LOCK_open);
60601 -+err_with_placeholders:
60602 -+ unlock_table_names(thd, tables, (TABLE_LIST*) 0);
60603 -+ pthread_mutex_unlock(&LOCK_open);
60604 -+ DBUG_RETURN(error);
60605 -+}
60606 -+
60607 -+
60608 -+/*
60609 -+ Quickly remove a table.
60610 -+
60611 -+ SYNOPSIS
60612 -+ quick_rm_table()
60613 -+ base The handlerton handle.
60614 -+ db The database name.
60615 -+ table_name The table name.
60616 -+ flags flags for build_table_filename().
60617 -+
60618 -+ RETURN
60619 -+ 0 OK
60620 -+ != 0 Error
60621 -+*/
60622 -+
60623 -+bool quick_rm_table(handlerton *base,const char *db,
60624 -+ const char *table_name, uint flags)
60625 -+{
60626 -+ char path[FN_REFLEN + 1];
60627 -+ bool error= 0;
60628 -+ DBUG_ENTER("quick_rm_table");
60629 -+
60630 -+ uint path_length= build_table_filename(path, sizeof(path) - 1,
60631 -+ db, table_name, reg_ext, flags);
60632 -+ if (my_delete(path,MYF(0)))
60633 -+ error= 1; /* purecov: inspected */
60634 -+ path[path_length - reg_ext_length]= '\0'; // Remove reg_ext
60635 -+ if (!(flags & FRM_ONLY))
60636 -+ error|= ha_delete_table(current_thd, base, path, db, table_name, 0);
60637 -+ DBUG_RETURN(error);
60638 -+}
60639 -+
60640 -+/*
60641 -+ Sort keys in the following order:
60642 -+ - PRIMARY KEY
60643 -+ - UNIQUE keys where all column are NOT NULL
60644 -+ - UNIQUE keys that don't contain partial segments
60645 -+ - Other UNIQUE keys
60646 -+ - Normal keys
60647 -+ - Fulltext keys
60648 -+
60649 -+ This will make checking for duplicated keys faster and ensure that
60650 -+ PRIMARY keys are prioritized.
60651 -+*/
60652 -+
60653 -+static int sort_keys(KEY *a, KEY *b)
60654 -+{
60655 -+ ulong a_flags= a->flags, b_flags= b->flags;
60656 -+
60657 -+ if (a_flags & HA_NOSAME)
60658 -+ {
60659 -+ if (!(b_flags & HA_NOSAME))
60660 -+ return -1;
60661 -+ if ((a_flags ^ b_flags) & (HA_NULL_PART_KEY | HA_END_SPACE_KEY))
60662 -+ {
60663 -+ /* Sort NOT NULL keys before other keys */
60664 -+ return (a_flags & (HA_NULL_PART_KEY | HA_END_SPACE_KEY)) ? 1 : -1;
60665 -+ }
60666 -+ if (a->name == primary_key_name)
60667 -+ return -1;
60668 -+ if (b->name == primary_key_name)
60669 -+ return 1;
60670 -+ /* Sort keys don't containing partial segments before others */
60671 -+ if ((a_flags ^ b_flags) & HA_KEY_HAS_PART_KEY_SEG)
60672 -+ return (a_flags & HA_KEY_HAS_PART_KEY_SEG) ? 1 : -1;
60673 -+ }
60674 -+ else if (b_flags & HA_NOSAME)
60675 -+ return 1; // Prefer b
60676 -+
60677 -+ if ((a_flags ^ b_flags) & HA_FULLTEXT)
60678 -+ {
60679 -+ return (a_flags & HA_FULLTEXT) ? 1 : -1;
60680 -+ }
60681 -+ /*
60682 -+ Prefer original key order. usable_key_parts contains here
60683 -+ the original key position.
60684 -+ */
60685 -+ return ((a->usable_key_parts < b->usable_key_parts) ? -1 :
60686 -+ (a->usable_key_parts > b->usable_key_parts) ? 1 :
60687 -+ 0);
60688 -+}
60689 -+
60690 -+/*
60691 -+ Check TYPELIB (set or enum) for duplicates
60692 -+
60693 -+ SYNOPSIS
60694 -+ check_duplicates_in_interval()
60695 -+ set_or_name "SET" or "ENUM" string for warning message
60696 -+ name name of the checked column
60697 -+ typelib list of values for the column
60698 -+ dup_val_count returns count of duplicate elements
60699 -+
60700 -+ DESCRIPTION
60701 -+ This function prints an warning for each value in list
60702 -+ which has some duplicates on its right
60703 -+
60704 -+ RETURN VALUES
60705 -+ 0 ok
60706 -+ 1 Error
60707 -+*/
60708 -+
60709 -+bool check_duplicates_in_interval(const char *set_or_name,
60710 -+ const char *name, TYPELIB *typelib,
60711 -+ CHARSET_INFO *cs, unsigned int *dup_val_count)
60712 -+{
60713 -+ TYPELIB tmp= *typelib;
60714 -+ const char **cur_value= typelib->type_names;
60715 -+ unsigned int *cur_length= typelib->type_lengths;
60716 -+ *dup_val_count= 0;
60717 -+
60718 -+ for ( ; tmp.count > 1; cur_value++, cur_length++)
60719 -+ {
60720 -+ tmp.type_names++;
60721 -+ tmp.type_lengths++;
60722 -+ tmp.count--;
60723 -+ if (find_type2(&tmp, (const char*)*cur_value, *cur_length, cs))
60724 -+ {
60725 -+ if ((current_thd->variables.sql_mode &
60726 -+ (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES)))
60727 -+ {
60728 -+ my_error(ER_DUPLICATED_VALUE_IN_TYPE, MYF(0),
60729 -+ name,*cur_value,set_or_name);
60730 -+ return 1;
60731 -+ }
60732 -+ push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_NOTE,
60733 -+ ER_DUPLICATED_VALUE_IN_TYPE,
60734 -+ ER(ER_DUPLICATED_VALUE_IN_TYPE),
60735 -+ name,*cur_value,set_or_name);
60736 -+ (*dup_val_count)++;
60737 -+ }
60738 -+ }
60739 -+ return 0;
60740 -+}
60741 -+
60742 -+
60743 -+/*
60744 -+ Check TYPELIB (set or enum) max and total lengths
60745 -+
60746 -+ SYNOPSIS
60747 -+ calculate_interval_lengths()
60748 -+ cs charset+collation pair of the interval
60749 -+ typelib list of values for the column
60750 -+ max_length length of the longest item
60751 -+ tot_length sum of the item lengths
60752 -+
60753 -+ DESCRIPTION
60754 -+ After this function call:
60755 -+ - ENUM uses max_length
60756 -+ - SET uses tot_length.
60757 -+
60758 -+ RETURN VALUES
60759 -+ void
60760 -+*/
60761 -+void calculate_interval_lengths(CHARSET_INFO *cs, TYPELIB *interval,
60762 -+ uint32 *max_length, uint32 *tot_length)
60763 -+{
60764 -+ const char **pos;
60765 -+ uint *len;
60766 -+ *max_length= *tot_length= 0;
60767 -+ for (pos= interval->type_names, len= interval->type_lengths;
60768 -+ *pos ; pos++, len++)
60769 -+ {
60770 -+ size_t length= cs->cset->numchars(cs, *pos, *pos + *len);
60771 -+ *tot_length+= length;
60772 -+ set_if_bigger(*max_length, (uint32)length);
60773 -+ }
60774 -+}
60775 -+
60776 -+
60777 -+/*
60778 -+ Prepare a create_table instance for packing
60779 -+
60780 -+ SYNOPSIS
60781 -+ prepare_create_field()
60782 -+ sql_field field to prepare for packing
60783 -+ blob_columns count for BLOBs
60784 -+ timestamps count for timestamps
60785 -+ table_flags table flags
60786 -+
60787 -+ DESCRIPTION
60788 -+ This function prepares a Create_field instance.
60789 -+ Fields such as pack_flag are valid after this call.
60790 -+
60791 -+ RETURN VALUES
60792 -+ 0 ok
60793 -+ 1 Error
60794 -+*/
60795 -+
60796 -+int prepare_create_field(Create_field *sql_field,
60797 -+ uint *blob_columns,
60798 -+ int *timestamps, int *timestamps_with_niladic,
60799 -+ longlong table_flags)
60800 -+{
60801 -+ unsigned int dup_val_count;
60802 -+ DBUG_ENTER("prepare_field");
60803 -+
60804 -+ /*
60805 -+ This code came from mysql_prepare_create_table.
60806 -+ Indent preserved to make patching easier
60807 -+ */
60808 -+ DBUG_ASSERT(sql_field->charset);
60809 -+
60810 -+ switch (sql_field->sql_type) {
60811 -+ case MYSQL_TYPE_BLOB:
60812 -+ case MYSQL_TYPE_MEDIUM_BLOB:
60813 -+ case MYSQL_TYPE_TINY_BLOB:
60814 -+ case MYSQL_TYPE_LONG_BLOB:
60815 -+ sql_field->pack_flag=FIELDFLAG_BLOB |
60816 -+ pack_length_to_packflag(sql_field->pack_length -
60817 -+ portable_sizeof_char_ptr);
60818 -+ if (sql_field->charset->state & MY_CS_BINSORT)
60819 -+ sql_field->pack_flag|=FIELDFLAG_BINARY;
60820 -+ sql_field->length=8; // Unireg field length
60821 -+ sql_field->unireg_check=Field::BLOB_FIELD;
60822 -+ (*blob_columns)++;
60823 -+ break;
60824 -+ case MYSQL_TYPE_GEOMETRY:
60825 -+#ifdef HAVE_SPATIAL
60826 -+ if (!(table_flags & HA_CAN_GEOMETRY))
60827 -+ {
60828 -+ my_printf_error(ER_CHECK_NOT_IMPLEMENTED, ER(ER_CHECK_NOT_IMPLEMENTED),
60829 -+ MYF(0), "GEOMETRY");
60830 -+ DBUG_RETURN(1);
60831 -+ }
60832 -+ sql_field->pack_flag=FIELDFLAG_GEOM |
60833 -+ pack_length_to_packflag(sql_field->pack_length -
60834 -+ portable_sizeof_char_ptr);
60835 -+ if (sql_field->charset->state & MY_CS_BINSORT)
60836 -+ sql_field->pack_flag|=FIELDFLAG_BINARY;
60837 -+ sql_field->length=8; // Unireg field length
60838 -+ sql_field->unireg_check=Field::BLOB_FIELD;
60839 -+ (*blob_columns)++;
60840 -+ break;
60841 -+#else
60842 -+ my_printf_error(ER_FEATURE_DISABLED,ER(ER_FEATURE_DISABLED), MYF(0),
60843 -+ sym_group_geom.name, sym_group_geom.needed_define);
60844 -+ DBUG_RETURN(1);
60845 -+#endif /*HAVE_SPATIAL*/
60846 -+ case MYSQL_TYPE_VARCHAR:
60847 -+#ifndef QQ_ALL_HANDLERS_SUPPORT_VARCHAR
60848 -+ if (table_flags & HA_NO_VARCHAR)
60849 -+ {
60850 -+ /* convert VARCHAR to CHAR because handler is not yet up to date */
60851 -+ sql_field->sql_type= MYSQL_TYPE_VAR_STRING;
60852 -+ sql_field->pack_length= calc_pack_length(sql_field->sql_type,
60853 -+ (uint) sql_field->length);
60854 -+ if ((sql_field->length / sql_field->charset->mbmaxlen) >
60855 -+ MAX_FIELD_CHARLENGTH)
60856 -+ {
60857 -+ my_printf_error(ER_TOO_BIG_FIELDLENGTH, ER(ER_TOO_BIG_FIELDLENGTH),
60858 -+ MYF(0), sql_field->field_name, MAX_FIELD_CHARLENGTH);
60859 -+ DBUG_RETURN(1);
60860 -+ }
60861 -+ }
60862 -+#endif
60863 -+ /* fall through */
60864 -+ case MYSQL_TYPE_STRING:
60865 -+ sql_field->pack_flag=0;
60866 -+ if (sql_field->charset->state & MY_CS_BINSORT)
60867 -+ sql_field->pack_flag|=FIELDFLAG_BINARY;
60868 -+ break;
60869 -+ case MYSQL_TYPE_ENUM:
60870 -+ sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) |
60871 -+ FIELDFLAG_INTERVAL;
60872 -+ if (sql_field->charset->state & MY_CS_BINSORT)
60873 -+ sql_field->pack_flag|=FIELDFLAG_BINARY;
60874 -+ sql_field->unireg_check=Field::INTERVAL_FIELD;
60875 -+ if (check_duplicates_in_interval("ENUM",sql_field->field_name,
60876 -+ sql_field->interval,
60877 -+ sql_field->charset, &dup_val_count))
60878 -+ DBUG_RETURN(1);
60879 -+ break;
60880 -+ case MYSQL_TYPE_SET:
60881 -+ sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) |
60882 -+ FIELDFLAG_BITFIELD;
60883 -+ if (sql_field->charset->state & MY_CS_BINSORT)
60884 -+ sql_field->pack_flag|=FIELDFLAG_BINARY;
60885 -+ sql_field->unireg_check=Field::BIT_FIELD;
60886 -+ if (check_duplicates_in_interval("SET",sql_field->field_name,
60887 -+ sql_field->interval,
60888 -+ sql_field->charset, &dup_val_count))
60889 -+ DBUG_RETURN(1);
60890 -+ /* Check that count of unique members is not more then 64 */
60891 -+ if (sql_field->interval->count - dup_val_count > sizeof(longlong)*8)
60892 -+ {
60893 -+ my_error(ER_TOO_BIG_SET, MYF(0), sql_field->field_name);
60894 -+ DBUG_RETURN(1);
60895 -+ }
60896 -+ break;
60897 -+ case MYSQL_TYPE_DATE: // Rest of string types
60898 -+ case MYSQL_TYPE_NEWDATE:
60899 -+ case MYSQL_TYPE_TIME:
60900 -+ case MYSQL_TYPE_DATETIME:
60901 -+ case MYSQL_TYPE_NULL:
60902 -+ sql_field->pack_flag=f_settype((uint) sql_field->sql_type);
60903 -+ break;
60904 -+ case MYSQL_TYPE_BIT:
60905 -+ /*
60906 -+ We have sql_field->pack_flag already set here, see
60907 -+ mysql_prepare_create_table().
60908 -+ */
60909 -+ break;
60910 -+ case MYSQL_TYPE_NEWDECIMAL:
60911 -+ sql_field->pack_flag=(FIELDFLAG_NUMBER |
60912 -+ (sql_field->flags & UNSIGNED_FLAG ? 0 :
60913 -+ FIELDFLAG_DECIMAL) |
60914 -+ (sql_field->flags & ZEROFILL_FLAG ?
60915 -+ FIELDFLAG_ZEROFILL : 0) |
60916 -+ (sql_field->decimals << FIELDFLAG_DEC_SHIFT));
60917 -+ break;
60918 -+ case MYSQL_TYPE_TIMESTAMP:
60919 -+ /* We should replace old TIMESTAMP fields with their newer analogs */
60920 -+ if (sql_field->unireg_check == Field::TIMESTAMP_OLD_FIELD)
60921 -+ {
60922 -+ if (!*timestamps)
60923 -+ {
60924 -+ sql_field->unireg_check= Field::TIMESTAMP_DNUN_FIELD;
60925 -+ (*timestamps_with_niladic)++;
60926 -+ }
60927 -+ else
60928 -+ sql_field->unireg_check= Field::NONE;
60929 -+ }
60930 -+ else if (sql_field->unireg_check != Field::NONE)
60931 -+ (*timestamps_with_niladic)++;
60932 -+
60933 -+ (*timestamps)++;
60934 -+ /* fall-through */
60935 -+ default:
60936 -+ sql_field->pack_flag=(FIELDFLAG_NUMBER |
60937 -+ (sql_field->flags & UNSIGNED_FLAG ? 0 :
60938 -+ FIELDFLAG_DECIMAL) |
60939 -+ (sql_field->flags & ZEROFILL_FLAG ?
60940 -+ FIELDFLAG_ZEROFILL : 0) |
60941 -+ f_settype((uint) sql_field->sql_type) |
60942 -+ (sql_field->decimals << FIELDFLAG_DEC_SHIFT));
60943 -+ break;
60944 -+ }
60945 -+ if (!(sql_field->flags & NOT_NULL_FLAG))
60946 -+ sql_field->pack_flag|= FIELDFLAG_MAYBE_NULL;
60947 -+ if (sql_field->flags & NO_DEFAULT_VALUE_FLAG)
60948 -+ sql_field->pack_flag|= FIELDFLAG_NO_DEFAULT;
60949 -+ DBUG_RETURN(0);
60950 -+}
60951 -+
60952 -+/*
60953 -+ Preparation for table creation
60954 -+
60955 -+ SYNOPSIS
60956 -+ mysql_prepare_create_table()
60957 -+ thd Thread object.
60958 -+ create_info Create information (like MAX_ROWS).
60959 -+ alter_info List of columns and indexes to create
60960 -+ tmp_table If a temporary table is to be created.
60961 -+ db_options INOUT Table options (like HA_OPTION_PACK_RECORD).
60962 -+ file The handler for the new table.
60963 -+ key_info_buffer OUT An array of KEY structs for the indexes.
60964 -+ key_count OUT The number of elements in the array.
60965 -+ select_field_count The number of fields coming from a select table.
60966 -+
60967 -+ DESCRIPTION
60968 -+ Prepares the table and key structures for table creation.
60969 -+
60970 -+ NOTES
60971 -+ sets create_info->varchar if the table has a varchar
60972 -+
60973 -+ RETURN VALUES
60974 -+ FALSE OK
60975 -+ TRUE error
60976 -+*/
60977 -+
60978 -+static int
60979 -+mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
60980 -+ Alter_info *alter_info,
60981 -+ bool tmp_table,
60982 -+ uint *db_options,
60983 -+ handler *file, KEY **key_info_buffer,
60984 -+ uint *key_count, int select_field_count)
60985 -+{
60986 -+ const char *key_name;
60987 -+ Create_field *sql_field,*dup_field;
60988 -+ uint field,null_fields,blob_columns,max_key_length;
60989 -+ ulong record_offset= 0;
60990 -+ KEY *key_info;
60991 -+ KEY_PART_INFO *key_part_info;
60992 -+ int timestamps= 0, timestamps_with_niladic= 0;
60993 -+ int field_no,dup_no;
60994 -+ int select_field_pos,auto_increment=0;
60995 -+ List_iterator<Create_field> it(alter_info->create_list);
60996 -+ List_iterator<Create_field> it2(alter_info->create_list);
60997 -+ uint total_uneven_bit_length= 0;
60998 -+ DBUG_ENTER("mysql_prepare_create_table");
60999 -+
61000 -+ select_field_pos= alter_info->create_list.elements - select_field_count;
61001 -+ null_fields=blob_columns=0;
61002 -+ create_info->varchar= 0;
61003 -+ max_key_length= file->max_key_length();
61004 -+
61005 -+ for (field_no=0; (sql_field=it++) ; field_no++)
61006 -+ {
61007 -+ CHARSET_INFO *save_cs;
61008 -+
61009 -+ /*
61010 -+ Initialize length from its original value (number of characters),
61011 -+ which was set in the parser. This is necessary if we're
61012 -+ executing a prepared statement for the second time.
61013 -+ */
61014 -+ sql_field->length= sql_field->char_length;
61015 -+ if (!sql_field->charset)
61016 -+ sql_field->charset= create_info->default_table_charset;
61017 -+ /*
61018 -+ table_charset is set in ALTER TABLE if we want change character set
61019 -+ for all varchar/char columns.
61020 -+ But the table charset must not affect the BLOB fields, so don't
61021 -+ allow to change my_charset_bin to somethig else.
61022 -+ */
61023 -+ if (create_info->table_charset && sql_field->charset != &my_charset_bin)
61024 -+ sql_field->charset= create_info->table_charset;
61025 -+
61026 -+ save_cs= sql_field->charset;
61027 -+ if ((sql_field->flags & BINCMP_FLAG) &&
61028 -+ !(sql_field->charset= get_charset_by_csname(sql_field->charset->csname,
61029 -+ MY_CS_BINSORT,MYF(0))))
61030 -+ {
61031 -+ char tmp[65];
61032 -+ strmake(strmake(tmp, save_cs->csname, sizeof(tmp)-4),
61033 -+ STRING_WITH_LEN("_bin"));
61034 -+ my_error(ER_UNKNOWN_COLLATION, MYF(0), tmp);
61035 -+ DBUG_RETURN(TRUE);
61036 -+ }
61037 -+
61038 -+ /*
61039 -+ Convert the default value from client character
61040 -+ set into the column character set if necessary.
61041 -+ */
61042 -+ if (sql_field->def &&
61043 -+ save_cs != sql_field->def->collation.collation &&
61044 -+ (sql_field->sql_type == MYSQL_TYPE_VAR_STRING ||
61045 -+ sql_field->sql_type == MYSQL_TYPE_STRING ||
61046 -+ sql_field->sql_type == MYSQL_TYPE_SET ||
61047 -+ sql_field->sql_type == MYSQL_TYPE_ENUM))
61048 -+ {
61049 -+ /*
61050 -+ Starting from 5.1 we work here with a copy of Create_field
61051 -+ created by the caller, not with the instance that was
61052 -+ originally created during parsing. It's OK to create
61053 -+ a temporary item and initialize with it a member of the
61054 -+ copy -- this item will be thrown away along with the copy
61055 -+ at the end of execution, and thus not introduce a dangling
61056 -+ pointer in the parsed tree of a prepared statement or a
61057 -+ stored procedure statement.
61058 -+ */
61059 -+ sql_field->def= sql_field->def->safe_charset_converter(save_cs);
61060 -+
61061 -+ if (sql_field->def == NULL)
61062 -+ {
61063 -+ /* Could not convert */
61064 -+ my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
61065 -+ DBUG_RETURN(TRUE);
61066 -+ }
61067 -+ }
61068 -+
61069 -+ if (sql_field->sql_type == MYSQL_TYPE_SET ||
61070 -+ sql_field->sql_type == MYSQL_TYPE_ENUM)
61071 -+ {
61072 -+ uint32 dummy;
61073 -+ CHARSET_INFO *cs= sql_field->charset;
61074 -+ TYPELIB *interval= sql_field->interval;
61075 -+
61076 -+ /*
61077 -+ Create typelib from interval_list, and if necessary
61078 -+ convert strings from client character set to the
61079 -+ column character set.
61080 -+ */
61081 -+ if (!interval)
61082 -+ {
61083 -+ /*
61084 -+ Create the typelib in runtime memory - we will free the
61085 -+ occupied memory at the same time when we free this
61086 -+ sql_field -- at the end of execution.
61087 -+ */
61088 -+ interval= sql_field->interval= typelib(thd->mem_root,
61089 -+ sql_field->interval_list);
61090 -+ List_iterator<String> int_it(sql_field->interval_list);
61091 -+ String conv, *tmp;
61092 -+ char comma_buf[2];
61093 -+ int comma_length= cs->cset->wc_mb(cs, ',', (uchar*) comma_buf,
61094 -+ (uchar*) comma_buf +
61095 -+ sizeof(comma_buf));
61096 -+ DBUG_ASSERT(comma_length > 0);
61097 -+ for (uint i= 0; (tmp= int_it++); i++)
61098 -+ {
61099 -+ size_t lengthsp;
61100 -+ if (String::needs_conversion(tmp->length(), tmp->charset(),
61101 -+ cs, &dummy))
61102 -+ {
61103 -+ uint cnv_errs;
61104 -+ conv.copy(tmp->ptr(), tmp->length(), tmp->charset(), cs, &cnv_errs);
61105 -+ interval->type_names[i]= strmake_root(thd->mem_root, conv.ptr(),
61106 -+ conv.length());
61107 -+ interval->type_lengths[i]= conv.length();
61108 -+ }
61109 -+
61110 -+ // Strip trailing spaces.
61111 -+ lengthsp= cs->cset->lengthsp(cs, interval->type_names[i],
61112 -+ interval->type_lengths[i]);
61113 -+ interval->type_lengths[i]= lengthsp;
61114 -+ ((uchar *)interval->type_names[i])[lengthsp]= '\0';
61115 -+ if (sql_field->sql_type == MYSQL_TYPE_SET)
61116 -+ {
61117 -+ if (cs->coll->instr(cs, interval->type_names[i],
61118 -+ interval->type_lengths[i],
61119 -+ comma_buf, comma_length, NULL, 0))
61120 -+ {
61121 -+ my_error(ER_ILLEGAL_VALUE_FOR_TYPE, MYF(0), "set", tmp->ptr());
61122 -+ DBUG_RETURN(TRUE);
61123 -+ }
61124 -+ }
61125 -+ }
61126 -+ sql_field->interval_list.empty(); // Don't need interval_list anymore
61127 -+ }
61128 -+
61129 -+ if (sql_field->sql_type == MYSQL_TYPE_SET)
61130 -+ {
61131 -+ uint32 field_length;
61132 -+ if (sql_field->def != NULL)
61133 -+ {
61134 -+ char *not_used;
61135 -+ uint not_used2;
61136 -+ bool not_found= 0;
61137 -+ String str, *def= sql_field->def->val_str(&str);
61138 -+ if (def == NULL) /* SQL "NULL" maps to NULL */
61139 -+ {
61140 -+ if ((sql_field->flags & NOT_NULL_FLAG) != 0)
61141 -+ {
61142 -+ my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
61143 -+ DBUG_RETURN(TRUE);
61144 -+ }
61145 -+
61146 -+ /* else, NULL is an allowed value */
61147 -+ (void) find_set(interval, NULL, 0,
61148 -+ cs, &not_used, &not_used2, &not_found);
61149 -+ }
61150 -+ else /* not NULL */
61151 -+ {
61152 -+ (void) find_set(interval, def->ptr(), def->length(),
61153 -+ cs, &not_used, &not_used2, &not_found);
61154 -+ }
61155 -+
61156 -+ if (not_found)
61157 -+ {
61158 -+ my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
61159 -+ DBUG_RETURN(TRUE);
61160 -+ }
61161 -+ }
61162 -+ calculate_interval_lengths(cs, interval, &dummy, &field_length);
61163 -+ sql_field->length= field_length + (interval->count - 1);
61164 -+ }
61165 -+ else /* MYSQL_TYPE_ENUM */
61166 -+ {
61167 -+ uint32 field_length;
61168 -+ DBUG_ASSERT(sql_field->sql_type == MYSQL_TYPE_ENUM);
61169 -+ if (sql_field->def != NULL)
61170 -+ {
61171 -+ String str, *def= sql_field->def->val_str(&str);
61172 -+ if (def == NULL) /* SQL "NULL" maps to NULL */
61173 -+ {
61174 -+ if ((sql_field->flags & NOT_NULL_FLAG) != 0)
61175 -+ {
61176 -+ my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
61177 -+ DBUG_RETURN(TRUE);
61178 -+ }
61179 -+
61180 -+ /* else, the defaults yield the correct length for NULLs. */
61181 -+ }
61182 -+ else /* not NULL */
61183 -+ {
61184 -+ def->length(cs->cset->lengthsp(cs, def->ptr(), def->length()));
61185 -+ if (find_type2(interval, def->ptr(), def->length(), cs) == 0) /* not found */
61186 -+ {
61187 -+ my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
61188 -+ DBUG_RETURN(TRUE);
61189 -+ }
61190 -+ }
61191 -+ }
61192 -+ calculate_interval_lengths(cs, interval, &field_length, &dummy);
61193 -+ sql_field->length= field_length;
61194 -+ }
61195 -+ set_if_smaller(sql_field->length, MAX_FIELD_WIDTH-1);
61196 -+ }
61197 -+
61198 -+ if (sql_field->sql_type == MYSQL_TYPE_BIT)
61199 -+ {
61200 -+ sql_field->pack_flag= FIELDFLAG_NUMBER;
61201 -+ if (file->ha_table_flags() & HA_CAN_BIT_FIELD)
61202 -+ total_uneven_bit_length+= sql_field->length & 7;
61203 -+ else
61204 -+ sql_field->pack_flag|= FIELDFLAG_TREAT_BIT_AS_CHAR;
61205 -+ }
61206 -+
61207 -+ sql_field->create_length_to_internal_length();
61208 -+ if (prepare_blob_field(thd, sql_field))
61209 -+ DBUG_RETURN(TRUE);
61210 -+
61211 -+ if (!(sql_field->flags & NOT_NULL_FLAG))
61212 -+ null_fields++;
61213 -+
61214 -+ if (check_column_name(sql_field->field_name))
61215 -+ {
61216 -+ my_error(ER_WRONG_COLUMN_NAME, MYF(0), sql_field->field_name);
61217 -+ DBUG_RETURN(TRUE);
61218 -+ }
61219 -+
61220 -+ /* Check if we have used the same field name before */
61221 -+ for (dup_no=0; (dup_field=it2++) != sql_field; dup_no++)
61222 -+ {
61223 -+ if (my_strcasecmp(system_charset_info,
61224 -+ sql_field->field_name,
61225 -+ dup_field->field_name) == 0)
61226 -+ {
61227 -+ /*
61228 -+ If this was a CREATE ... SELECT statement, accept a field
61229 -+ redefinition if we are changing a field in the SELECT part
61230 -+ */
61231 -+ if (field_no < select_field_pos || dup_no >= select_field_pos)
61232 -+ {
61233 -+ my_error(ER_DUP_FIELDNAME, MYF(0), sql_field->field_name);
61234 -+ DBUG_RETURN(TRUE);
61235 -+ }
61236 -+ else
61237 -+ {
61238 -+ /* Field redefined */
61239 -+ sql_field->def= dup_field->def;
61240 -+ sql_field->sql_type= dup_field->sql_type;
61241 -+ sql_field->charset= (dup_field->charset ?
61242 -+ dup_field->charset :
61243 -+ create_info->default_table_charset);
61244 -+ sql_field->length= dup_field->char_length;
61245 -+ sql_field->pack_length= dup_field->pack_length;
61246 -+ sql_field->key_length= dup_field->key_length;
61247 -+ sql_field->decimals= dup_field->decimals;
61248 -+ sql_field->create_length_to_internal_length();
61249 -+ sql_field->unireg_check= dup_field->unireg_check;
61250 -+ /*
61251 -+ We're making one field from two, the result field will have
61252 -+ dup_field->flags as flags. If we've incremented null_fields
61253 -+ because of sql_field->flags, decrement it back.
61254 -+ */
61255 -+ if (!(sql_field->flags & NOT_NULL_FLAG))
61256 -+ null_fields--;
61257 -+ sql_field->flags= dup_field->flags;
61258 -+ sql_field->interval= dup_field->interval;
61259 -+ it2.remove(); // Remove first (create) definition
61260 -+ select_field_pos--;
61261 -+ break;
61262 -+ }
61263 -+ }
61264 -+ }
61265 -+ /* Don't pack rows in old tables if the user has requested this */
61266 -+ if ((sql_field->flags & BLOB_FLAG) ||
61267 -+ (sql_field->sql_type == MYSQL_TYPE_VARCHAR &&
61268 -+ create_info->row_type != ROW_TYPE_FIXED))
61269 -+ (*db_options)|= HA_OPTION_PACK_RECORD;
61270 -+ it2.rewind();
61271 -+ }
61272 -+
61273 -+ /* record_offset will be increased with 'length-of-null-bits' later */
61274 -+ record_offset= 0;
61275 -+ null_fields+= total_uneven_bit_length;
61276 -+
61277 -+ it.rewind();
61278 -+ while ((sql_field=it++))
61279 -+ {
61280 -+ DBUG_ASSERT(sql_field->charset != 0);
61281 -+
61282 -+ if (prepare_create_field(sql_field, &blob_columns,
61283 -+ &timestamps, &timestamps_with_niladic,
61284 -+ file->ha_table_flags()))
61285 -+ DBUG_RETURN(TRUE);
61286 -+ if (sql_field->sql_type == MYSQL_TYPE_VARCHAR)
61287 -+ create_info->varchar= TRUE;
61288 -+ sql_field->offset= record_offset;
61289 -+ if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
61290 -+ auto_increment++;
61291 -+ record_offset+= sql_field->pack_length;
61292 -+ }
61293 -+ if (timestamps_with_niladic > 1)
61294 -+ {
61295 -+ my_message(ER_TOO_MUCH_AUTO_TIMESTAMP_COLS,
61296 -+ ER(ER_TOO_MUCH_AUTO_TIMESTAMP_COLS), MYF(0));
61297 -+ DBUG_RETURN(TRUE);
61298 -+ }
61299 -+ if (auto_increment > 1)
61300 -+ {
61301 -+ my_message(ER_WRONG_AUTO_KEY, ER(ER_WRONG_AUTO_KEY), MYF(0));
61302 -+ DBUG_RETURN(TRUE);
61303 -+ }
61304 -+ if (auto_increment &&
61305 -+ (file->ha_table_flags() & HA_NO_AUTO_INCREMENT))
61306 -+ {
61307 -+ my_message(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT,
61308 -+ ER(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT), MYF(0));
61309 -+ DBUG_RETURN(TRUE);
61310 -+ }
61311 -+
61312 -+ if (blob_columns && (file->ha_table_flags() & HA_NO_BLOBS))
61313 -+ {
61314 -+ my_message(ER_TABLE_CANT_HANDLE_BLOB, ER(ER_TABLE_CANT_HANDLE_BLOB),
61315 -+ MYF(0));
61316 -+ DBUG_RETURN(TRUE);
61317 -+ }
61318 -+
61319 -+ /* Create keys */
61320 -+
61321 -+ List_iterator<Key> key_iterator(alter_info->key_list);
61322 -+ List_iterator<Key> key_iterator2(alter_info->key_list);
61323 -+ uint key_parts=0, fk_key_count=0;
61324 -+ bool primary_key=0,unique_key=0;
61325 -+ Key *key, *key2;
61326 -+ uint tmp, key_number;
61327 -+ /* special marker for keys to be ignored */
61328 -+ static char ignore_key[1];
61329 -+
61330 -+ /* Calculate number of key segements */
61331 -+ *key_count= 0;
61332 -+
61333 -+ while ((key=key_iterator++))
61334 -+ {
61335 -+ DBUG_PRINT("info", ("key name: '%s' type: %d", key->name ? key->name :
61336 -+ "(none)" , key->type));
61337 -+ LEX_STRING key_name_str;
61338 -+ if (key->type == Key::FOREIGN_KEY)
61339 -+ {
61340 -+ fk_key_count++;
61341 -+ Foreign_key *fk_key= (Foreign_key*) key;
61342 -+ if (fk_key->ref_columns.elements &&
61343 -+ fk_key->ref_columns.elements != fk_key->columns.elements)
61344 -+ {
61345 -+ my_error(ER_WRONG_FK_DEF, MYF(0),
61346 -+ (fk_key->name ? fk_key->name : "foreign key without name"),
61347 -+ ER(ER_KEY_REF_DO_NOT_MATCH_TABLE_REF));
61348 -+ DBUG_RETURN(TRUE);
61349 -+ }
61350 -+ continue;
61351 -+ }
61352 -+ (*key_count)++;
61353 -+ tmp=file->max_key_parts();
61354 -+ if (key->columns.elements > tmp)
61355 -+ {
61356 -+ my_error(ER_TOO_MANY_KEY_PARTS,MYF(0),tmp);
61357 -+ DBUG_RETURN(TRUE);
61358 -+ }
61359 -+ key_name_str.str= (char*) key->name;
61360 -+ key_name_str.length= key->name ? strlen(key->name) : 0;
61361 -+ if (check_string_char_length(&key_name_str, "", NAME_CHAR_LEN,
61362 -+ system_charset_info, 1))
61363 -+ {
61364 -+ my_error(ER_TOO_LONG_IDENT, MYF(0), key->name);
61365 -+ DBUG_RETURN(TRUE);
61366 -+ }
61367 -+ key_iterator2.rewind ();
61368 -+ if (key->type != Key::FOREIGN_KEY)
61369 -+ {
61370 -+ while ((key2 = key_iterator2++) != key)
61371 -+ {
61372 -+ /*
61373 -+ foreign_key_prefix(key, key2) returns 0 if key or key2, or both, is
61374 -+ 'generated', and a generated key is a prefix of the other key.
61375 -+ Then we do not need the generated shorter key.
61376 -+ */
61377 -+ if ((key2->type != Key::FOREIGN_KEY &&
61378 -+ key2->name != ignore_key &&
61379 -+ !foreign_key_prefix(key, key2)))
61380 -+ {
61381 -+ /* TODO: issue warning message */
61382 -+ /* mark that the generated key should be ignored */
61383 -+ if (!key2->generated ||
61384 -+ (key->generated && key->columns.elements <
61385 -+ key2->columns.elements))
61386 -+ key->name= ignore_key;
61387 -+ else
61388 -+ {
61389 -+ key2->name= ignore_key;
61390 -+ key_parts-= key2->columns.elements;
61391 -+ (*key_count)--;
61392 -+ }
61393 -+ break;
61394 -+ }
61395 -+ }
61396 -+ }
61397 -+ if (key->name != ignore_key)
61398 -+ key_parts+=key->columns.elements;
61399 -+ else
61400 -+ (*key_count)--;
61401 -+ if (key->name && !tmp_table && (key->type != Key::PRIMARY) &&
61402 -+ !my_strcasecmp(system_charset_info,key->name,primary_key_name))
61403 -+ {
61404 -+ my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name);
61405 -+ DBUG_RETURN(TRUE);
61406 -+ }
61407 -+ }
61408 -+ tmp=file->max_keys();
61409 -+ if (*key_count > tmp)
61410 -+ {
61411 -+ my_error(ER_TOO_MANY_KEYS,MYF(0),tmp);
61412 -+ DBUG_RETURN(TRUE);
61413 -+ }
61414 -+
61415 -+ (*key_info_buffer)= key_info= (KEY*) sql_calloc(sizeof(KEY) * (*key_count));
61416 -+ key_part_info=(KEY_PART_INFO*) sql_calloc(sizeof(KEY_PART_INFO)*key_parts);
61417 -+ if (!*key_info_buffer || ! key_part_info)
61418 -+ DBUG_RETURN(TRUE); // Out of memory
61419 -+
61420 -+ key_iterator.rewind();
61421 -+ key_number=0;
61422 -+ for (; (key=key_iterator++) ; key_number++)
61423 -+ {
61424 -+ uint key_length=0;
61425 -+ Key_part_spec *column;
61426 -+
61427 -+ if (key->name == ignore_key)
61428 -+ {
61429 -+ /* ignore redundant keys */
61430 -+ do
61431 -+ key=key_iterator++;
61432 -+ while (key && key->name == ignore_key);
61433 -+ if (!key)
61434 -+ break;
61435 -+ }
61436 -+
61437 -+ switch (key->type) {
61438 -+ case Key::MULTIPLE:
61439 -+ key_info->flags= 0;
61440 -+ break;
61441 -+ case Key::FULLTEXT:
61442 -+ key_info->flags= HA_FULLTEXT;
61443 -+ if ((key_info->parser_name= &key->key_create_info.parser_name)->str)
61444 -+ key_info->flags|= HA_USES_PARSER;
61445 -+ else
61446 -+ key_info->parser_name= 0;
61447 -+ break;
61448 -+ case Key::SPATIAL:
61449 -+#ifdef HAVE_SPATIAL
61450 -+ key_info->flags= HA_SPATIAL;
61451 -+ break;
61452 -+#else
61453 -+ my_error(ER_FEATURE_DISABLED, MYF(0),
61454 -+ sym_group_geom.name, sym_group_geom.needed_define);
61455 -+ DBUG_RETURN(TRUE);
61456 -+#endif
61457 -+ case Key::FOREIGN_KEY:
61458 -+ key_number--; // Skip this key
61459 -+ continue;
61460 -+ default:
61461 -+ key_info->flags = HA_NOSAME;
61462 -+ break;
61463 -+ }
61464 -+ if (key->generated)
61465 -+ key_info->flags|= HA_GENERATED_KEY;
61466 -+
61467 -+ key_info->key_parts=(uint8) key->columns.elements;
61468 -+ key_info->key_part=key_part_info;
61469 -+ key_info->usable_key_parts= key_number;
61470 -+ key_info->algorithm= key->key_create_info.algorithm;
61471 -+
61472 -+ if (key->type == Key::FULLTEXT)
61473 -+ {
61474 -+ if (!(file->ha_table_flags() & HA_CAN_FULLTEXT))
61475 -+ {
61476 -+ my_message(ER_TABLE_CANT_HANDLE_FT, ER(ER_TABLE_CANT_HANDLE_FT),
61477 -+ MYF(0));
61478 -+ DBUG_RETURN(TRUE);
61479 -+ }
61480 -+ }
61481 -+ /*
61482 -+ Make SPATIAL to be RTREE by default
61483 -+ SPATIAL only on BLOB or at least BINARY, this
61484 -+ actually should be replaced by special GEOM type
61485 -+ in near future when new frm file is ready
61486 -+ checking for proper key parts number:
61487 -+ */
61488 -+
61489 -+ /* TODO: Add proper checks if handler supports key_type and algorithm */
61490 -+ if (key_info->flags & HA_SPATIAL)
61491 -+ {
61492 -+ if (!(file->ha_table_flags() & HA_CAN_RTREEKEYS))
61493 -+ {
61494 -+ my_message(ER_TABLE_CANT_HANDLE_SPKEYS, ER(ER_TABLE_CANT_HANDLE_SPKEYS),
61495 -+ MYF(0));
61496 -+ DBUG_RETURN(TRUE);
61497 -+ }
61498 -+ if (key_info->key_parts != 1)
61499 -+ {
61500 -+ my_error(ER_WRONG_ARGUMENTS, MYF(0), "SPATIAL INDEX");
61501 -+ DBUG_RETURN(TRUE);
61502 -+ }
61503 -+ }
61504 -+ else if (key_info->algorithm == HA_KEY_ALG_RTREE)
61505 -+ {
61506 -+#ifdef HAVE_RTREE_KEYS
61507 -+ if ((key_info->key_parts & 1) == 1)
61508 -+ {
61509 -+ my_error(ER_WRONG_ARGUMENTS, MYF(0), "RTREE INDEX");
61510 -+ DBUG_RETURN(TRUE);
61511 -+ }
61512 -+ /* TODO: To be deleted */
61513 -+ my_error(ER_NOT_SUPPORTED_YET, MYF(0), "RTREE INDEX");
61514 -+ DBUG_RETURN(TRUE);
61515 -+#else
61516 -+ my_error(ER_FEATURE_DISABLED, MYF(0),
61517 -+ sym_group_rtree.name, sym_group_rtree.needed_define);
61518 -+ DBUG_RETURN(TRUE);
61519 -+#endif
61520 -+ }
61521 -+
61522 -+ /* Take block size from key part or table part */
61523 -+ /*
61524 -+ TODO: Add warning if block size changes. We can't do it here, as
61525 -+ this may depend on the size of the key
61526 -+ */
61527 -+ key_info->block_size= (key->key_create_info.block_size ?
61528 -+ key->key_create_info.block_size :
61529 -+ create_info->key_block_size);
61530 -+
61531 -+ if (key_info->block_size)
61532 -+ key_info->flags|= HA_USES_BLOCK_SIZE;
61533 -+
61534 -+ List_iterator<Key_part_spec> cols(key->columns), cols2(key->columns);
61535 -+ CHARSET_INFO *ft_key_charset=0; // for FULLTEXT
61536 -+ for (uint column_nr=0 ; (column=cols++) ; column_nr++)
61537 -+ {
61538 -+ uint length;
61539 -+ Key_part_spec *dup_column;
61540 -+
61541 -+ it.rewind();
61542 -+ field=0;
61543 -+ while ((sql_field=it++) &&
61544 -+ my_strcasecmp(system_charset_info,
61545 -+ column->field_name,
61546 -+ sql_field->field_name))
61547 -+ field++;
61548 -+ if (!sql_field)
61549 -+ {
61550 -+ my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name);
61551 -+ DBUG_RETURN(TRUE);
61552 -+ }
61553 -+ while ((dup_column= cols2++) != column)
61554 -+ {
61555 -+ if (!my_strcasecmp(system_charset_info,
61556 -+ column->field_name, dup_column->field_name))
61557 -+ {
61558 -+ my_printf_error(ER_DUP_FIELDNAME,
61559 -+ ER(ER_DUP_FIELDNAME),MYF(0),
61560 -+ column->field_name);
61561 -+ DBUG_RETURN(TRUE);
61562 -+ }
61563 -+ }
61564 -+ cols2.rewind();
61565 -+ if (key->type == Key::FULLTEXT)
61566 -+ {
61567 -+ if ((sql_field->sql_type != MYSQL_TYPE_STRING &&
61568 -+ sql_field->sql_type != MYSQL_TYPE_VARCHAR &&
61569 -+ !f_is_blob(sql_field->pack_flag)) ||
61570 -+ sql_field->charset == &my_charset_bin ||
61571 -+ sql_field->charset->mbminlen > 1 || // ucs2 doesn't work yet
61572 -+ (ft_key_charset && sql_field->charset != ft_key_charset))
61573 -+ {
61574 -+ my_error(ER_BAD_FT_COLUMN, MYF(0), column->field_name);
61575 -+ DBUG_RETURN(-1);
61576 -+ }
61577 -+ ft_key_charset=sql_field->charset;
61578 -+ /*
61579 -+ for fulltext keys keyseg length is 1 for blobs (it's ignored in ft
61580 -+ code anyway, and 0 (set to column width later) for char's. it has
61581 -+ to be correct col width for char's, as char data are not prefixed
61582 -+ with length (unlike blobs, where ft code takes data length from a
61583 -+ data prefix, ignoring column->length).
61584 -+ */
61585 -+ column->length=test(f_is_blob(sql_field->pack_flag));
61586 -+ }
61587 -+ else
61588 -+ {
61589 -+ column->length*= sql_field->charset->mbmaxlen;
61590 -+
61591 -+ if (key->type == Key::SPATIAL)
61592 -+ {
61593 -+ if (column->length)
61594 -+ {
61595 -+ my_error(ER_WRONG_SUB_KEY, MYF(0));
61596 -+ DBUG_RETURN(TRUE);
61597 -+ }
61598 -+
61599 -+ if (!f_is_geom(sql_field->pack_flag))
61600 -+ {
61601 -+ my_error(ER_WRONG_ARGUMENTS, MYF(0), "SPATIAL INDEX");
61602 -+ DBUG_RETURN(TRUE);
61603 -+ }
61604 -+ }
61605 -+
61606 -+ if (f_is_blob(sql_field->pack_flag) ||
61607 -+ (f_is_geom(sql_field->pack_flag) && key->type != Key::SPATIAL))
61608 -+ {
61609 -+ if (!(file->ha_table_flags() & HA_CAN_INDEX_BLOBS))
61610 -+ {
61611 -+ my_error(ER_BLOB_USED_AS_KEY, MYF(0), column->field_name);
61612 -+ DBUG_RETURN(TRUE);
61613 -+ }
61614 -+ if (f_is_geom(sql_field->pack_flag) && sql_field->geom_type ==
61615 -+ Field::GEOM_POINT)
61616 -+ column->length= 25;
61617 -+ if (!column->length)
61618 -+ {
61619 -+ my_error(ER_BLOB_KEY_WITHOUT_LENGTH, MYF(0), column->field_name);
61620 -+ DBUG_RETURN(TRUE);
61621 -+ }
61622 -+ }
61623 -+#ifdef HAVE_SPATIAL
61624 -+ if (key->type == Key::SPATIAL)
61625 -+ {
61626 -+ if (!column->length)
61627 -+ {
61628 -+ /*
61629 -+ 4 is: (Xmin,Xmax,Ymin,Ymax), this is for 2D case
61630 -+ Lately we'll extend this code to support more dimensions
61631 -+ */
61632 -+ column->length= 4*sizeof(double);
61633 -+ }
61634 -+ }
61635 -+#endif
61636 -+ if (!(sql_field->flags & NOT_NULL_FLAG))
61637 -+ {
61638 -+ if (key->type == Key::PRIMARY)
61639 -+ {
61640 -+ /* Implicitly set primary key fields to NOT NULL for ISO conf. */
61641 -+ sql_field->flags|= NOT_NULL_FLAG;
61642 -+ sql_field->pack_flag&= ~FIELDFLAG_MAYBE_NULL;
61643 -+ null_fields--;
61644 -+ }
61645 -+ else
61646 -+ {
61647 -+ key_info->flags|= HA_NULL_PART_KEY;
61648 -+ if (!(file->ha_table_flags() & HA_NULL_IN_KEY))
61649 -+ {
61650 -+ my_error(ER_NULL_COLUMN_IN_INDEX, MYF(0), column->field_name);
61651 -+ DBUG_RETURN(TRUE);
61652 -+ }
61653 -+ if (key->type == Key::SPATIAL)
61654 -+ {
61655 -+ my_message(ER_SPATIAL_CANT_HAVE_NULL,
61656 -+ ER(ER_SPATIAL_CANT_HAVE_NULL), MYF(0));
61657 -+ DBUG_RETURN(TRUE);
61658 -+ }
61659 -+ }
61660 -+ }
61661 -+ if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
61662 -+ {
61663 -+ if (column_nr == 0 || (file->ha_table_flags() & HA_AUTO_PART_KEY))
61664 -+ auto_increment--; // Field is used
61665 -+ }
61666 -+ }
61667 -+
61668 -+ key_part_info->fieldnr= field;
61669 -+ key_part_info->offset= (uint16) sql_field->offset;
61670 -+ key_part_info->key_type=sql_field->pack_flag;
61671 -+ length= sql_field->key_length;
61672 -+
61673 -+ if (column->length)
61674 -+ {
61675 -+ if (f_is_blob(sql_field->pack_flag))
61676 -+ {
61677 -+ if ((length=column->length) > max_key_length ||
61678 -+ length > file->max_key_part_length())
61679 -+ {
61680 -+ length=min(max_key_length, file->max_key_part_length());
61681 -+ if (key->type == Key::MULTIPLE)
61682 -+ {
61683 -+ /* not a critical problem */
61684 -+ char warn_buff[MYSQL_ERRMSG_SIZE];
61685 -+ my_snprintf(warn_buff, sizeof(warn_buff), ER(ER_TOO_LONG_KEY),
61686 -+ length);
61687 -+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
61688 -+ ER_TOO_LONG_KEY, warn_buff);
61689 -+ /* Align key length to multibyte char boundary */
61690 -+ length-= length % sql_field->charset->mbmaxlen;
61691 -+ }
61692 -+ else
61693 -+ {
61694 -+ my_error(ER_TOO_LONG_KEY,MYF(0),length);
61695 -+ DBUG_RETURN(TRUE);
61696 -+ }
61697 -+ }
61698 -+ }
61699 -+ else if (!f_is_geom(sql_field->pack_flag) &&
61700 -+ (column->length > length ||
61701 -+ !Field::type_can_have_key_part (sql_field->sql_type) ||
61702 -+ ((f_is_packed(sql_field->pack_flag) ||
61703 -+ ((file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS) &&
61704 -+ (key_info->flags & HA_NOSAME))) &&
61705 -+ column->length != length)))
61706 -+ {
61707 -+ my_message(ER_WRONG_SUB_KEY, ER(ER_WRONG_SUB_KEY), MYF(0));
61708 -+ DBUG_RETURN(TRUE);
61709 -+ }
61710 -+ else if (!(file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS))
61711 -+ length=column->length;
61712 -+ }
61713 -+ else if (length == 0)
61714 -+ {
61715 -+ my_error(ER_WRONG_KEY_COLUMN, MYF(0), column->field_name);
61716 -+ DBUG_RETURN(TRUE);
61717 -+ }
61718 -+ if (length > file->max_key_part_length() && key->type != Key::FULLTEXT)
61719 -+ {
61720 -+ length= file->max_key_part_length();
61721 -+ if (key->type == Key::MULTIPLE)
61722 -+ {
61723 -+ /* not a critical problem */
61724 -+ char warn_buff[MYSQL_ERRMSG_SIZE];
61725 -+ my_snprintf(warn_buff, sizeof(warn_buff), ER(ER_TOO_LONG_KEY),
61726 -+ length);
61727 -+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
61728 -+ ER_TOO_LONG_KEY, warn_buff);
61729 -+ /* Align key length to multibyte char boundary */
61730 -+ length-= length % sql_field->charset->mbmaxlen;
61731 -+ }
61732 -+ else
61733 -+ {
61734 -+ my_error(ER_TOO_LONG_KEY,MYF(0),length);
61735 -+ DBUG_RETURN(TRUE);
61736 -+ }
61737 -+ }
61738 -+ key_part_info->length=(uint16) length;
61739 -+ /* Use packed keys for long strings on the first column */
61740 -+ if (!((*db_options) & HA_OPTION_NO_PACK_KEYS) &&
61741 -+ !((create_info->table_options & HA_OPTION_NO_PACK_KEYS)) &&
61742 -+ (length >= KEY_DEFAULT_PACK_LENGTH &&
61743 -+ (sql_field->sql_type == MYSQL_TYPE_STRING ||
61744 -+ sql_field->sql_type == MYSQL_TYPE_VARCHAR ||
61745 -+ sql_field->pack_flag & FIELDFLAG_BLOB)))
61746 -+ {
61747 -+ if ((column_nr == 0 && (sql_field->pack_flag & FIELDFLAG_BLOB)) ||
61748 -+ sql_field->sql_type == MYSQL_TYPE_VARCHAR)
61749 -+ key_info->flags|= HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY;
61750 -+ else
61751 -+ key_info->flags|= HA_PACK_KEY;
61752 -+ }
61753 -+ /* Check if the key segment is partial, set the key flag accordingly */
61754 -+ if (length != sql_field->key_length)
61755 -+ key_info->flags|= HA_KEY_HAS_PART_KEY_SEG;
61756 -+
61757 -+ key_length+=length;
61758 -+ key_part_info++;
61759 -+
61760 -+ /* Create the key name based on the first column (if not given) */
61761 -+ if (column_nr == 0)
61762 -+ {
61763 -+ if (key->type == Key::PRIMARY)
61764 -+ {
61765 -+ if (primary_key)
61766 -+ {
61767 -+ my_message(ER_MULTIPLE_PRI_KEY, ER(ER_MULTIPLE_PRI_KEY),
61768 -+ MYF(0));
61769 -+ DBUG_RETURN(TRUE);
61770 -+ }
61771 -+ key_name=primary_key_name;
61772 -+ primary_key=1;
61773 -+ }
61774 -+ else if (!(key_name = key->name))
61775 -+ key_name=make_unique_key_name(sql_field->field_name,
61776 -+ *key_info_buffer, key_info);
61777 -+ if (check_if_keyname_exists(key_name, *key_info_buffer, key_info))
61778 -+ {
61779 -+ my_error(ER_DUP_KEYNAME, MYF(0), key_name);
61780 -+ DBUG_RETURN(TRUE);
61781 -+ }
61782 -+ key_info->name=(char*) key_name;
61783 -+ }
61784 -+ }
61785 -+ if (!key_info->name || check_column_name(key_info->name))
61786 -+ {
61787 -+ my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key_info->name);
61788 -+ DBUG_RETURN(TRUE);
61789 -+ }
61790 -+ if (!(key_info->flags & HA_NULL_PART_KEY))
61791 -+ unique_key=1;
61792 -+ key_info->key_length=(uint16) key_length;
61793 -+ if (key_length > max_key_length && key->type != Key::FULLTEXT)
61794 -+ {
61795 -+ my_error(ER_TOO_LONG_KEY,MYF(0),max_key_length);
61796 -+ DBUG_RETURN(TRUE);
61797 -+ }
61798 -+ key_info++;
61799 -+ }
61800 -+ if (!unique_key && !primary_key &&
61801 -+ (file->ha_table_flags() & HA_REQUIRE_PRIMARY_KEY))
61802 -+ {
61803 -+ my_message(ER_REQUIRES_PRIMARY_KEY, ER(ER_REQUIRES_PRIMARY_KEY), MYF(0));
61804 -+ DBUG_RETURN(TRUE);
61805 -+ }
61806 -+ if (auto_increment > 0)
61807 -+ {
61808 -+ my_message(ER_WRONG_AUTO_KEY, ER(ER_WRONG_AUTO_KEY), MYF(0));
61809 -+ DBUG_RETURN(TRUE);
61810 -+ }
61811 -+ /* Sort keys in optimized order */
61812 -+ my_qsort((uchar*) *key_info_buffer, *key_count, sizeof(KEY),
61813 -+ (qsort_cmp) sort_keys);
61814 -+ create_info->null_bits= null_fields;
61815 -+
61816 -+ /* Check fields. */
61817 -+ it.rewind();
61818 -+ while ((sql_field=it++))
61819 -+ {
61820 -+ Field::utype type= (Field::utype) MTYP_TYPENR(sql_field->unireg_check);
61821 -+
61822 -+ if (thd->variables.sql_mode & MODE_NO_ZERO_DATE &&
61823 -+ !sql_field->def &&
61824 -+ sql_field->sql_type == MYSQL_TYPE_TIMESTAMP &&
61825 -+ (sql_field->flags & NOT_NULL_FLAG) &&
61826 -+ (type == Field::NONE || type == Field::TIMESTAMP_UN_FIELD))
61827 -+ {
61828 -+ /*
61829 -+ An error should be reported if:
61830 -+ - NO_ZERO_DATE SQL mode is active;
61831 -+ - there is no explicit DEFAULT clause (default column value);
61832 -+ - this is a TIMESTAMP column;
61833 -+ - the column is not NULL;
61834 -+ - this is not the DEFAULT CURRENT_TIMESTAMP column.
61835 -+
61836 -+ In other words, an error should be reported if
61837 -+ - NO_ZERO_DATE SQL mode is active;
61838 -+ - the column definition is equivalent to
61839 -+ 'column_name TIMESTAMP DEFAULT 0'.
61840 -+ */
61841 -+
61842 -+ my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
61843 -+ DBUG_RETURN(TRUE);
61844 -+ }
61845 -+ }
61846 -+
61847 -+ DBUG_RETURN(FALSE);
61848 -+}
61849 -+
61850 -+
61851 -+/*
61852 -+ Set table default charset, if not set
61853 -+
61854 -+ SYNOPSIS
61855 -+ set_table_default_charset()
61856 -+ create_info Table create information
61857 -+
61858 -+ DESCRIPTION
61859 -+ If the table character set was not given explicitely,
61860 -+ let's fetch the database default character set and
61861 -+ apply it to the table.
61862 -+*/
61863 -+
61864 -+static void set_table_default_charset(THD *thd,
61865 -+ HA_CREATE_INFO *create_info, char *db)
61866 -+{
61867 -+ /*
61868 -+ If the table character set was not given explicitly,
61869 -+ let's fetch the database default character set and
61870 -+ apply it to the table.
61871 -+ */
61872 -+ if (!create_info->default_table_charset)
61873 -+ {
61874 -+ HA_CREATE_INFO db_info;
61875 -+
61876 -+ load_db_opt_by_name(thd, db, &db_info);
61877 -+
61878 -+ create_info->default_table_charset= db_info.default_table_charset;
61879 -+ }
61880 -+}
61881 -+
61882 -+
61883 -+/*
61884 -+ Extend long VARCHAR fields to blob & prepare field if it's a blob
61885 -+
61886 -+ SYNOPSIS
61887 -+ prepare_blob_field()
61888 -+ sql_field Field to check
61889 -+
61890 -+ RETURN
61891 -+ 0 ok
61892 -+ 1 Error (sql_field can't be converted to blob)
61893 -+ In this case the error is given
61894 -+*/
61895 -+
61896 -+static bool prepare_blob_field(THD *thd, Create_field *sql_field)
61897 -+{
61898 -+ DBUG_ENTER("prepare_blob_field");
61899 -+
61900 -+ if (sql_field->length > MAX_FIELD_VARCHARLENGTH &&
61901 -+ !(sql_field->flags & BLOB_FLAG))
61902 -+ {
61903 -+ /* Convert long VARCHAR columns to TEXT or BLOB */
61904 -+ char warn_buff[MYSQL_ERRMSG_SIZE];
61905 -+
61906 -+ if (sql_field->def || (thd->variables.sql_mode & (MODE_STRICT_TRANS_TABLES |
61907 -+ MODE_STRICT_ALL_TABLES)))
61908 -+ {
61909 -+ my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0), sql_field->field_name,
61910 -+ MAX_FIELD_VARCHARLENGTH / sql_field->charset->mbmaxlen);
61911 -+ DBUG_RETURN(1);
61912 -+ }
61913 -+ sql_field->sql_type= MYSQL_TYPE_BLOB;
61914 -+ sql_field->flags|= BLOB_FLAG;
61915 -+ my_snprintf(warn_buff, sizeof(warn_buff), ER(ER_AUTO_CONVERT), sql_field->field_name,
61916 -+ (sql_field->charset == &my_charset_bin) ? "VARBINARY" : "VARCHAR",
61917 -+ (sql_field->charset == &my_charset_bin) ? "BLOB" : "TEXT");
61918 -+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_AUTO_CONVERT,
61919 -+ warn_buff);
61920 -+ }
61921 -+
61922 -+ if ((sql_field->flags & BLOB_FLAG) && sql_field->length)
61923 -+ {
61924 -+ if (sql_field->sql_type == FIELD_TYPE_BLOB ||
61925 -+ sql_field->sql_type == FIELD_TYPE_TINY_BLOB ||
61926 -+ sql_field->sql_type == FIELD_TYPE_MEDIUM_BLOB)
61927 -+ {
61928 -+ /* The user has given a length to the blob column */
61929 -+ sql_field->sql_type= get_blob_type_from_length(sql_field->length);
61930 -+ sql_field->pack_length= calc_pack_length(sql_field->sql_type, 0);
61931 -+ }
61932 -+ sql_field->length= 0;
61933 -+ }
61934 -+ DBUG_RETURN(0);
61935 -+}
61936 -+
61937 -+
61938 -+/*
61939 -+ Preparation of Create_field for SP function return values.
61940 -+ Based on code used in the inner loop of mysql_prepare_create_table()
61941 -+ above.
61942 -+
61943 -+ SYNOPSIS
61944 -+ sp_prepare_create_field()
61945 -+ thd Thread object
61946 -+ sql_field Field to prepare
61947 -+
61948 -+ DESCRIPTION
61949 -+ Prepares the field structures for field creation.
61950 -+
61951 -+*/
61952 -+
61953 -+void sp_prepare_create_field(THD *thd, Create_field *sql_field)
61954 -+{
61955 -+ if (sql_field->sql_type == MYSQL_TYPE_SET ||
61956 -+ sql_field->sql_type == MYSQL_TYPE_ENUM)
61957 -+ {
61958 -+ uint32 field_length, dummy;
61959 -+ if (sql_field->sql_type == MYSQL_TYPE_SET)
61960 -+ {
61961 -+ calculate_interval_lengths(sql_field->charset,
61962 -+ sql_field->interval, &dummy,
61963 -+ &field_length);
61964 -+ sql_field->length= field_length +
61965 -+ (sql_field->interval->count - 1);
61966 -+ }
61967 -+ else /* MYSQL_TYPE_ENUM */
61968 -+ {
61969 -+ calculate_interval_lengths(sql_field->charset,
61970 -+ sql_field->interval,
61971 -+ &field_length, &dummy);
61972 -+ sql_field->length= field_length;
61973 -+ }
61974 -+ set_if_smaller(sql_field->length, MAX_FIELD_WIDTH-1);
61975 -+ }
61976 -+
61977 -+ if (sql_field->sql_type == MYSQL_TYPE_BIT)
61978 -+ {
61979 -+ sql_field->pack_flag= FIELDFLAG_NUMBER |
61980 -+ FIELDFLAG_TREAT_BIT_AS_CHAR;
61981 -+ }
61982 -+ sql_field->create_length_to_internal_length();
61983 -+ DBUG_ASSERT(sql_field->def == 0);
61984 -+ /* Can't go wrong as sql_field->def is not defined */
61985 -+ (void) prepare_blob_field(thd, sql_field);
61986 -+}
61987 -+
61988 -+
61989 -+/*
61990 -+ Write CREATE TABLE binlog
61991 -+
61992 -+ SYNOPSIS
61993 -+ write_create_table_bin_log()
61994 -+ thd Thread object
61995 -+ create_info Create information
61996 -+ internal_tmp_table Set to 1 if this is an internal temporary table
61997 -+
61998 -+ DESCRIPTION
61999 -+ This function only is called in mysql_create_table_no_lock and
62000 -+ mysql_create_table
62001 -+
62002 -+ RETURN VALUES
62003 -+ NONE
62004 -+ */
62005 -+static inline int write_create_table_bin_log(THD *thd,
62006 -+ const HA_CREATE_INFO *create_info,
62007 -+ bool internal_tmp_table)
62008 -+{
62009 -+ /*
62010 -+ Don't write statement if:
62011 -+ - It is an internal temporary table,
62012 -+ - Row-based logging is used and it we are creating a temporary table, or
62013 -+ - The binary log is not open.
62014 -+ Otherwise, the statement shall be binlogged.
62015 -+ */
62016 -+ if (!internal_tmp_table &&
62017 -+ (!thd->current_stmt_binlog_row_based ||
62018 -+ (thd->current_stmt_binlog_row_based &&
62019 -+ !(create_info->options & HA_LEX_CREATE_TMP_TABLE))))
62020 -+ return write_bin_log(thd, TRUE, thd->query(), thd->query_length());
62021 -+ return 0;
62022 -+}
62023 -+
62024 -+
62025 -+/*
62026 -+ Create a table
62027 -+
62028 -+ SYNOPSIS
62029 -+ mysql_create_table_no_lock()
62030 -+ thd Thread object
62031 -+ db Database
62032 -+ table_name Table name
62033 -+ create_info Create information (like MAX_ROWS)
62034 -+ fields List of fields to create
62035 -+ keys List of keys to create
62036 -+ internal_tmp_table Set to 1 if this is an internal temporary table
62037 -+ (From ALTER TABLE)
62038 -+ select_field_count
62039 -+
62040 -+ DESCRIPTION
62041 -+ If one creates a temporary table, this is automatically opened
62042 -+
62043 -+ Note that this function assumes that caller already have taken
62044 -+ name-lock on table being created or used some other way to ensure
62045 -+ that concurrent operations won't intervene. mysql_create_table()
62046 -+ is a wrapper that can be used for this.
62047 -+
62048 -+ no_log is needed for the case of CREATE ... SELECT,
62049 -+ as the logging will be done later in sql_insert.cc
62050 -+ select_field_count is also used for CREATE ... SELECT,
62051 -+ and must be zero for standard create of table.
62052 -+
62053 -+ RETURN VALUES
62054 -+ FALSE OK
62055 -+ TRUE error
62056 -+*/
62057 -+
62058 -+bool mysql_create_table_no_lock(THD *thd,
62059 -+ const char *db, const char *table_name,
62060 -+ HA_CREATE_INFO *create_info,
62061 -+ Alter_info *alter_info,
62062 -+ bool internal_tmp_table,
62063 -+ uint select_field_count)
62064 -+{
62065 -+ char path[FN_REFLEN + 1];
62066 -+ uint path_length;
62067 -+ const char *alias;
62068 -+ uint db_options, key_count;
62069 -+ KEY *key_info_buffer;
62070 -+ handler *file;
62071 -+ bool error= TRUE;
62072 -+ DBUG_ENTER("mysql_create_table_no_lock");
62073 -+ DBUG_PRINT("enter", ("db: '%s' table: '%s' tmp: %d",
62074 -+ db, table_name, internal_tmp_table));
62075 -+
62076 -+
62077 -+ /* Check for duplicate fields and check type of table to create */
62078 -+ if (!alter_info->create_list.elements)
62079 -+ {
62080 -+ my_message(ER_TABLE_MUST_HAVE_COLUMNS, ER(ER_TABLE_MUST_HAVE_COLUMNS),
62081 -+ MYF(0));
62082 -+ DBUG_RETURN(TRUE);
62083 -+ }
62084 -+ if (check_engine(thd, table_name, create_info))
62085 -+ DBUG_RETURN(TRUE);
62086 -+ db_options= create_info->table_options;
62087 -+ if (create_info->row_type == ROW_TYPE_DYNAMIC)
62088 -+ db_options|=HA_OPTION_PACK_RECORD;
62089 -+ alias= table_case_name(create_info, table_name);
62090 -+ if (!(file= get_new_handler((TABLE_SHARE*) 0, thd->mem_root,
62091 -+ create_info->db_type)))
62092 -+ {
62093 -+ mem_alloc_error(sizeof(handler));
62094 -+ DBUG_RETURN(TRUE);
62095 -+ }
62096 -+#ifdef WITH_PARTITION_STORAGE_ENGINE
62097 -+ partition_info *part_info= thd->work_part_info;
62098 -+
62099 -+ if (!part_info && create_info->db_type->partition_flags &&
62100 -+ (create_info->db_type->partition_flags() & HA_USE_AUTO_PARTITION))
62101 -+ {
62102 -+ /*
62103 -+ Table is not defined as a partitioned table but the engine handles
62104 -+ all tables as partitioned. The handler will set up the partition info
62105 -+ object with the default settings.
62106 -+ */
62107 -+ thd->work_part_info= part_info= new partition_info();
62108 -+ if (!part_info)
62109 -+ {
62110 -+ mem_alloc_error(sizeof(partition_info));
62111 -+ DBUG_RETURN(TRUE);
62112 -+ }
62113 -+ file->set_auto_partitions(part_info);
62114 -+ part_info->default_engine_type= create_info->db_type;
62115 -+ part_info->is_auto_partitioned= TRUE;
62116 -+ }
62117 -+ if (part_info)
62118 -+ {
62119 -+ /*
62120 -+ The table has been specified as a partitioned table.
62121 -+ If this is part of an ALTER TABLE the handler will be the partition
62122 -+ handler but we need to specify the default handler to use for
62123 -+ partitions also in the call to check_partition_info. We transport
62124 -+ this information in the default_db_type variable, it is either
62125 -+ DB_TYPE_DEFAULT or the engine set in the ALTER TABLE command.
62126 -+
62127 -+ Check that we don't use foreign keys in the table since it won't
62128 -+ work even with InnoDB beneath it.
62129 -+ */
62130 -+ List_iterator<Key> key_iterator(alter_info->key_list);
62131 -+ Key *key;
62132 -+ handlerton *part_engine_type= create_info->db_type;
62133 -+ char *part_syntax_buf;
62134 -+ uint syntax_len;
62135 -+ handlerton *engine_type;
62136 -+ if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
62137 -+ {
62138 -+ my_error(ER_PARTITION_NO_TEMPORARY, MYF(0));
62139 -+ goto err;
62140 -+ }
62141 -+ while ((key= key_iterator++))
62142 -+ {
62143 -+ if (key->type == Key::FOREIGN_KEY &&
62144 -+ !part_info->is_auto_partitioned)
62145 -+ {
62146 -+ my_error(ER_FOREIGN_KEY_ON_PARTITIONED, MYF(0));
62147 -+ goto err;
62148 -+ }
62149 -+ }
62150 -+ if ((part_engine_type == partition_hton) &&
62151 -+ part_info->default_engine_type)
62152 -+ {
62153 -+ /*
62154 -+ This only happens at ALTER TABLE.
62155 -+ default_engine_type was assigned from the engine set in the ALTER
62156 -+ TABLE command.
62157 -+ */
62158 -+ ;
62159 -+ }
62160 -+ else
62161 -+ {
62162 -+ if (create_info->used_fields & HA_CREATE_USED_ENGINE)
62163 -+ {
62164 -+ part_info->default_engine_type= create_info->db_type;
62165 -+ }
62166 -+ else
62167 -+ {
62168 -+ if (part_info->default_engine_type == NULL)
62169 -+ {
62170 -+ part_info->default_engine_type= ha_checktype(thd,
62171 -+ DB_TYPE_DEFAULT, 0, 0);
62172 -+ }
62173 -+ }
62174 -+ }
62175 -+ DBUG_PRINT("info", ("db_type = %s create_info->db_type = %s",
62176 -+ ha_resolve_storage_engine_name(part_info->default_engine_type),
62177 -+ ha_resolve_storage_engine_name(create_info->db_type)));
62178 -+ if (part_info->check_partition_info(thd, &engine_type, file,
62179 -+ create_info, TRUE))
62180 -+ goto err;
62181 -+ part_info->default_engine_type= engine_type;
62182 -+
62183 -+ /*
62184 -+ We reverse the partitioning parser and generate a standard format
62185 -+ for syntax stored in frm file.
62186 -+ */
62187 -+ if (!(part_syntax_buf= generate_partition_syntax(part_info,
62188 -+ &syntax_len,
62189 -+ TRUE, TRUE)))
62190 -+ goto err;
62191 -+ part_info->part_info_string= part_syntax_buf;
62192 -+ part_info->part_info_len= syntax_len;
62193 -+ if ((!(engine_type->partition_flags &&
62194 -+ engine_type->partition_flags() & HA_CAN_PARTITION)) ||
62195 -+ create_info->db_type == partition_hton)
62196 -+ {
62197 -+ /*
62198 -+ The handler assigned to the table cannot handle partitioning.
62199 -+ Assign the partition handler as the handler of the table.
62200 -+ */
62201 -+ DBUG_PRINT("info", ("db_type: %s",
62202 -+ ha_resolve_storage_engine_name(create_info->db_type)));
62203 -+ delete file;
62204 -+ create_info->db_type= partition_hton;
62205 -+ if (!(file= get_ha_partition(part_info)))
62206 -+ {
62207 -+ DBUG_RETURN(TRUE);
62208 -+ }
62209 -+ /*
62210 -+ If we have default number of partitions or subpartitions we
62211 -+ might require to set-up the part_info object such that it
62212 -+ creates a proper .par file. The current part_info object is
62213 -+ only used to create the frm-file and .par-file.
62214 -+ */
62215 -+ if (part_info->use_default_no_partitions &&
62216 -+ part_info->no_parts &&
62217 -+ (int)part_info->no_parts !=
62218 -+ file->get_default_no_partitions(create_info))
62219 -+ {
62220 -+ uint i;
62221 -+ List_iterator<partition_element> part_it(part_info->partitions);
62222 -+ part_it++;
62223 -+ DBUG_ASSERT(thd->lex->sql_command != SQLCOM_CREATE_TABLE);
62224 -+ for (i= 1; i < part_info->partitions.elements; i++)
62225 -+ (part_it++)->part_state= PART_TO_BE_DROPPED;
62226 -+ }
62227 -+ else if (part_info->is_sub_partitioned() &&
62228 -+ part_info->use_default_no_subpartitions &&
62229 -+ part_info->no_subparts &&
62230 -+ (int)part_info->no_subparts !=
62231 -+ file->get_default_no_partitions(create_info))
62232 -+ {
62233 -+ DBUG_ASSERT(thd->lex->sql_command != SQLCOM_CREATE_TABLE);
62234 -+ part_info->no_subparts= file->get_default_no_partitions(create_info);
62235 -+ }
62236 -+ }
62237 -+ else if (create_info->db_type != engine_type)
62238 -+ {
62239 -+ /*
62240 -+ We come here when we don't use a partitioned handler.
62241 -+ Since we use a partitioned table it must be "native partitioned".
62242 -+ We have switched engine from defaults, most likely only specified
62243 -+ engines in partition clauses.
62244 -+ */
62245 -+ delete file;
62246 -+ if (!(file= get_new_handler((TABLE_SHARE*) 0, thd->mem_root,
62247 -+ engine_type)))
62248 -+ {
62249 -+ mem_alloc_error(sizeof(handler));
62250 -+ DBUG_RETURN(TRUE);
62251 -+ }
62252 -+ }
62253 -+ }
62254 -+#endif
62255 -+
62256 -+ set_table_default_charset(thd, create_info, (char*) db);
62257 -+
62258 -+ if (mysql_prepare_create_table(thd, create_info, alter_info,
62259 -+ internal_tmp_table,
62260 -+ &db_options, file,
62261 -+ &key_info_buffer, &key_count,
62262 -+ select_field_count))
62263 -+ goto err;
62264 -+
62265 -+ /* Check if table exists */
62266 -+ if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
62267 -+ {
62268 -+ path_length= build_tmptable_filename(thd, path, sizeof(path));
62269 -+ create_info->table_options|=HA_CREATE_DELAY_KEY_WRITE;
62270 -+ }
62271 -+ else
62272 -+ {
62273 -+ path_length= build_table_filename(path, sizeof(path) - 1, db, alias, reg_ext,
62274 -+ internal_tmp_table ? FN_IS_TMP : 0);
62275 -+ }
62276 -+
62277 -+ /* Check if table already exists */
62278 -+ if ((create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
62279 -+ find_temporary_table(thd, db, table_name))
62280 -+ {
62281 -+ if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
62282 -+ {
62283 -+ create_info->table_existed= 1; // Mark that table existed
62284 -+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
62285 -+ ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
62286 -+ alias);
62287 -+ error= write_create_table_bin_log(thd, create_info, internal_tmp_table);
62288 -+ goto err;
62289 -+ }
62290 -+ my_error(ER_TABLE_EXISTS_ERROR, MYF(0), alias);
62291 -+ goto err;
62292 -+ }
62293 -+
62294 -+ VOID(pthread_mutex_lock(&LOCK_open));
62295 -+ if (!internal_tmp_table && !(create_info->options & HA_LEX_CREATE_TMP_TABLE))
62296 -+ {
62297 -+ if (!access(path,F_OK))
62298 -+ {
62299 -+ if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
62300 -+ goto warn;
62301 -+ my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
62302 -+ goto unlock_and_end;
62303 -+ }
62304 -+ /*
62305 -+ We don't assert here, but check the result, because the table could be
62306 -+ in the table definition cache and in the same time the .frm could be
62307 -+ missing from the disk, in case of manual intervention which deletes
62308 -+ the .frm file. The user has to use FLUSH TABLES; to clear the cache.
62309 -+ Then she could create the table. This case is pretty obscure and
62310 -+ therefore we don't introduce a new error message only for it.
62311 -+ */
62312 -+ if (get_cached_table_share(db, table_name))
62313 -+ {
62314 -+ my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
62315 -+ goto unlock_and_end;
62316 -+ }
62317 -+ }
62318 -+
62319 -+ /*
62320 -+ Check that table with given name does not already
62321 -+ exist in any storage engine. In such a case it should
62322 -+ be discovered and the error ER_TABLE_EXISTS_ERROR be returned
62323 -+ unless user specified CREATE TABLE IF EXISTS
62324 -+ The LOCK_open mutex has been locked to make sure no
62325 -+ one else is attempting to discover the table. Since
62326 -+ it's not on disk as a frm file, no one could be using it!
62327 -+ */
62328 -+ if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
62329 -+ {
62330 -+ bool create_if_not_exists =
62331 -+ create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS;
62332 -+ int retcode = ha_table_exists_in_engine(thd, db, table_name);
62333 -+ DBUG_PRINT("info", ("exists_in_engine: %u",retcode));
62334 -+ switch (retcode)
62335 -+ {
62336 -+ case HA_ERR_NO_SUCH_TABLE:
62337 -+ /* Normal case, no table exists. we can go and create it */
62338 -+ break;
62339 -+ case HA_ERR_TABLE_EXIST:
62340 -+ DBUG_PRINT("info", ("Table existed in handler"));
62341 -+
62342 -+ if (create_if_not_exists)
62343 -+ goto warn;
62344 -+ my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
62345 -+ goto unlock_and_end;
62346 -+ break;
62347 -+ default:
62348 -+ DBUG_PRINT("info", ("error: %u from storage engine", retcode));
62349 -+ my_error(retcode, MYF(0),table_name);
62350 -+ goto unlock_and_end;
62351 -+ }
62352 -+ }
62353 -+
62354 -+ thd_proc_info(thd, "creating table");
62355 -+ create_info->table_existed= 0; // Mark that table is created
62356 -+
62357 -+#ifdef HAVE_READLINK
62358 -+ if (test_if_data_home_dir(create_info->data_file_name))
62359 -+ {
62360 -+ my_error(ER_WRONG_ARGUMENTS, MYF(0), "DATA DIRECTORY");
62361 -+ goto unlock_and_end;
62362 -+ }
62363 -+ if (test_if_data_home_dir(create_info->index_file_name))
62364 -+ {
62365 -+ my_error(ER_WRONG_ARGUMENTS, MYF(0), "INDEX DIRECTORY");
62366 -+ goto unlock_and_end;
62367 -+ }
62368 -+
62369 -+#ifdef WITH_PARTITION_STORAGE_ENGINE
62370 -+ if (check_partition_dirs(thd->lex->part_info))
62371 -+ {
62372 -+ goto unlock_and_end;
62373 -+ }
62374 -+#endif /* WITH_PARTITION_STORAGE_ENGINE */
62375 -+
62376 -+ if (!my_use_symdir || (thd->variables.sql_mode & MODE_NO_DIR_IN_CREATE))
62377 -+#endif /* HAVE_READLINK */
62378 -+ {
62379 -+ if (create_info->data_file_name)
62380 -+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
62381 -+ WARN_OPTION_IGNORED, ER(WARN_OPTION_IGNORED),
62382 -+ "DATA DIRECTORY");
62383 -+ if (create_info->index_file_name)
62384 -+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
62385 -+ WARN_OPTION_IGNORED, ER(WARN_OPTION_IGNORED),
62386 -+ "INDEX DIRECTORY");
62387 -+ create_info->data_file_name= create_info->index_file_name= 0;
62388 -+ }
62389 -+ create_info->table_options=db_options;
62390 -+
62391 -+ path[path_length - reg_ext_length]= '\0'; // Remove .frm extension
62392 -+ if (rea_create_table(thd, path, db, table_name,
62393 -+ create_info, alter_info->create_list,
62394 -+ key_count, key_info_buffer, file))
62395 -+ goto unlock_and_end;
62396 -+
62397 -+ if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
62398 -+ {
62399 -+ /* Open table and put in temporary table list */
62400 -+ if (!(open_temporary_table(thd, path, db, table_name, 1)))
62401 -+ {
62402 -+ (void) rm_temporary_table(create_info->db_type, path);
62403 -+ goto unlock_and_end;
62404 -+ }
62405 -+ thd->thread_specific_used= TRUE;
62406 -+ }
62407 -+
62408 -+ error= write_create_table_bin_log(thd, create_info, internal_tmp_table);
62409 -+unlock_and_end:
62410 -+ VOID(pthread_mutex_unlock(&LOCK_open));
62411 -+
62412 -+err:
62413 -+ thd_proc_info(thd, "After create");
62414 -+ delete file;
62415 -+ DBUG_RETURN(error);
62416 -+
62417 -+warn:
62418 -+ error= FALSE;
62419 -+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
62420 -+ ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
62421 -+ alias);
62422 -+ create_info->table_existed= 1; // Mark that table existed
62423 -+ error= write_create_table_bin_log(thd, create_info, internal_tmp_table);
62424 -+ goto unlock_and_end;
62425 -+}
62426 -+
62427 -+
62428 -+/*
62429 -+ Database and name-locking aware wrapper for mysql_create_table_no_lock(),
62430 -+*/
62431 -+
62432 -+bool mysql_create_table(THD *thd, const char *db, const char *table_name,
62433 -+ HA_CREATE_INFO *create_info,
62434 -+ Alter_info *alter_info,
62435 -+ bool internal_tmp_table,
62436 -+ uint select_field_count)
62437 -+{
62438 -+ TABLE *name_lock= 0;
62439 -+ bool result;
62440 -+ DBUG_ENTER("mysql_create_table");
62441 -+
62442 -+ /* Wait for any database locks */
62443 -+ pthread_mutex_lock(&LOCK_lock_db);
62444 -+ while (!thd->killed &&
62445 -+ hash_search(&lock_db_cache,(uchar*) db, strlen(db)))
62446 -+ {
62447 -+ wait_for_condition(thd, &LOCK_lock_db, &COND_refresh);
62448 -+ pthread_mutex_lock(&LOCK_lock_db);
62449 -+ }
62450 -+
62451 -+ if (thd->killed)
62452 -+ {
62453 -+ pthread_mutex_unlock(&LOCK_lock_db);
62454 -+ DBUG_RETURN(TRUE);
62455 -+ }
62456 -+ creating_table++;
62457 -+ pthread_mutex_unlock(&LOCK_lock_db);
62458 -+
62459 -+ if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
62460 -+ {
62461 -+ if (lock_table_name_if_not_cached(thd, db, table_name, &name_lock))
62462 -+ {
62463 -+ result= TRUE;
62464 -+ goto unlock;
62465 -+ }
62466 -+ if (!name_lock)
62467 -+ {
62468 -+ if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
62469 -+ {
62470 -+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
62471 -+ ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
62472 -+ table_name);
62473 -+ create_info->table_existed= 1;
62474 -+ result= FALSE;
62475 -+ write_create_table_bin_log(thd, create_info, internal_tmp_table);
62476 -+ }
62477 -+ else
62478 -+ {
62479 -+ my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
62480 -+ result= TRUE;
62481 -+ }
62482 -+ goto unlock;
62483 -+ }
62484 -+ }
62485 -+
62486 -+ result= mysql_create_table_no_lock(thd, db, table_name, create_info,
62487 -+ alter_info,
62488 -+ internal_tmp_table,
62489 -+ select_field_count);
62490 -+
62491 -+unlock:
62492 -+ if (name_lock)
62493 -+ {
62494 -+ pthread_mutex_lock(&LOCK_open);
62495 -+ unlink_open_table(thd, name_lock, FALSE);
62496 -+ pthread_mutex_unlock(&LOCK_open);
62497 -+ }
62498 -+ pthread_mutex_lock(&LOCK_lock_db);
62499 -+ if (!--creating_table && creating_database)
62500 -+ pthread_cond_signal(&COND_refresh);
62501 -+ pthread_mutex_unlock(&LOCK_lock_db);
62502 -+ DBUG_RETURN(result);
62503 -+}
62504 -+
62505 -+
62506 -+/*
62507 -+** Give the key name after the first field with an optional '_#' after
62508 -+**/
62509 -+
62510 -+static bool
62511 -+check_if_keyname_exists(const char *name, KEY *start, KEY *end)
62512 -+{
62513 -+ for (KEY *key=start ; key != end ; key++)
62514 -+ if (!my_strcasecmp(system_charset_info,name,key->name))
62515 -+ return 1;
62516 -+ return 0;
62517 -+}
62518 -+
62519 -+
62520 -+static char *
62521 -+make_unique_key_name(const char *field_name,KEY *start,KEY *end)
62522 -+{
62523 -+ char buff[MAX_FIELD_NAME],*buff_end;
62524 -+
62525 -+ if (!check_if_keyname_exists(field_name,start,end) &&
62526 -+ my_strcasecmp(system_charset_info,field_name,primary_key_name))
62527 -+ return (char*) field_name; // Use fieldname
62528 -+ buff_end=strmake(buff,field_name, sizeof(buff)-4);
62529 -+
62530 -+ /*
62531 -+ Only 3 chars + '\0' left, so need to limit to 2 digit
62532 -+ This is ok as we can't have more than 100 keys anyway
62533 -+ */
62534 -+ for (uint i=2 ; i< 100; i++)
62535 -+ {
62536 -+ *buff_end= '_';
62537 -+ int10_to_str(i, buff_end+1, 10);
62538 -+ if (!check_if_keyname_exists(buff,start,end))
62539 -+ return sql_strdup(buff);
62540 -+ }
62541 -+ return (char*) "not_specified"; // Should never happen
62542 -+}
62543 -+
62544 -+
62545 -+/****************************************************************************
62546 -+** Alter a table definition
62547 -+****************************************************************************/
62548 -+
62549 -+
62550 -+/*
62551 -+ Rename a table.
62552 -+
62553 -+ SYNOPSIS
62554 -+ mysql_rename_table()
62555 -+ base The handlerton handle.
62556 -+ old_db The old database name.
62557 -+ old_name The old table name.
62558 -+ new_db The new database name.
62559 -+ new_name The new table name.
62560 -+ flags flags for build_table_filename().
62561 -+ FN_FROM_IS_TMP old_name is temporary.
62562 -+ FN_TO_IS_TMP new_name is temporary.
62563 -+ NO_FRM_RENAME Don't rename the FRM file
62564 -+ but only the table in the storage engine.
62565 -+
62566 -+ RETURN
62567 -+ FALSE OK
62568 -+ TRUE Error
62569 -+*/
62570 -+
62571 -+bool
62572 -+mysql_rename_table(handlerton *base, const char *old_db,
62573 -+ const char *old_name, const char *new_db,
62574 -+ const char *new_name, uint flags)
62575 -+{
62576 -+ THD *thd= current_thd;
62577 -+ char from[FN_REFLEN + 1], to[FN_REFLEN + 1],
62578 -+ lc_from[FN_REFLEN + 1], lc_to[FN_REFLEN + 1];
62579 -+ char *from_base= from, *to_base= to;
62580 -+ char tmp_name[NAME_LEN+1];
62581 -+ handler *file;
62582 -+ int error=0;
62583 -+ DBUG_ENTER("mysql_rename_table");
62584 -+ DBUG_PRINT("enter", ("old: '%s'.'%s' new: '%s'.'%s'",
62585 -+ old_db, old_name, new_db, new_name));
62586 -+
62587 -+ file= (base == NULL ? 0 :
62588 -+ get_new_handler((TABLE_SHARE*) 0, thd->mem_root, base));
62589 -+
62590 -+ build_table_filename(from, sizeof(from) - 1, old_db, old_name, "",
62591 -+ flags & FN_FROM_IS_TMP);
62592 -+ build_table_filename(to, sizeof(to) - 1, new_db, new_name, "",
62593 -+ flags & FN_TO_IS_TMP);
62594 -+
62595 -+ /*
62596 -+ If lower_case_table_names == 2 (case-preserving but case-insensitive
62597 -+ file system) and the storage is not HA_FILE_BASED, we need to provide
62598 -+ a lowercase file name, but we leave the .frm in mixed case.
62599 -+ */
62600 -+ if (lower_case_table_names == 2 && file &&
62601 -+ !(file->ha_table_flags() & HA_FILE_BASED))
62602 -+ {
62603 -+ strmov(tmp_name, old_name);
62604 -+ my_casedn_str(files_charset_info, tmp_name);
62605 -+ build_table_filename(lc_from, sizeof(lc_from) - 1, old_db, tmp_name, "",
62606 -+ flags & FN_FROM_IS_TMP);
62607 -+ from_base= lc_from;
62608 -+
62609 -+ strmov(tmp_name, new_name);
62610 -+ my_casedn_str(files_charset_info, tmp_name);
62611 -+ build_table_filename(lc_to, sizeof(lc_to) - 1, new_db, tmp_name, "",
62612 -+ flags & FN_TO_IS_TMP);
62613 -+ to_base= lc_to;
62614 -+ }
62615 -+
62616 -+ if (!file || !(error=file->ha_rename_table(from_base, to_base)))
62617 -+ {
62618 -+ if (!(flags & NO_FRM_RENAME) && rename_file_ext(from,to,reg_ext))
62619 -+ {
62620 -+ error=my_errno;
62621 -+ /* Restore old file name */
62622 -+ if (file)
62623 -+ file->ha_rename_table(to_base, from_base);
62624 -+ }
62625 -+ }
62626 -+ delete file;
62627 -+ if (error == HA_ERR_WRONG_COMMAND)
62628 -+ my_error(ER_NOT_SUPPORTED_YET, MYF(0), "ALTER TABLE");
62629 -+ else if (error)
62630 -+ my_error(ER_ERROR_ON_RENAME, MYF(0), from, to, error);
62631 -+ DBUG_RETURN(error != 0);
62632 -+}
62633 -+
62634 -+
62635 -+/*
62636 -+ Force all other threads to stop using the table
62637 -+
62638 -+ SYNOPSIS
62639 -+ wait_while_table_is_used()
62640 -+ thd Thread handler
62641 -+ table Table to remove from cache
62642 -+ function HA_EXTRA_PREPARE_FOR_DROP if table is to be deleted
62643 -+ HA_EXTRA_FORCE_REOPEN if table is not be used
62644 -+ HA_EXTRA_PREPARE_FOR_RENAME if table is to be renamed
62645 -+ NOTES
62646 -+ When returning, the table will be unusable for other threads until
62647 -+ the table is closed.
62648 -+
62649 -+ PREREQUISITES
62650 -+ Lock on LOCK_open
62651 -+ Win32 clients must also have a WRITE LOCK on the table !
62652 -+*/
62653 -+
62654 -+void wait_while_table_is_used(THD *thd, TABLE *table,
62655 -+ enum ha_extra_function function)
62656 -+{
62657 -+ DBUG_ENTER("wait_while_table_is_used");
62658 -+ DBUG_PRINT("enter", ("table: '%s' share: 0x%lx db_stat: %u version: %lu",
62659 -+ table->s->table_name.str, (ulong) table->s,
62660 -+ table->db_stat, table->s->version));
62661 -+
62662 -+ safe_mutex_assert_owner(&LOCK_open);
62663 -+
62664 -+ VOID(table->file->extra(function));
62665 -+ /* Mark all tables that are in use as 'old' */
62666 -+ mysql_lock_abort(thd, table, TRUE); /* end threads waiting on lock */
62667 -+
62668 -+ /* Wait until all there are no other threads that has this table open */
62669 -+ remove_table_from_cache(thd, table->s->db.str,
62670 -+ table->s->table_name.str,
62671 -+ RTFC_WAIT_OTHER_THREAD_FLAG);
62672 -+ DBUG_VOID_RETURN;
62673 -+}
62674 -+
62675 -+/*
62676 -+ Close a cached table
62677 -+
62678 -+ SYNOPSIS
62679 -+ close_cached_table()
62680 -+ thd Thread handler
62681 -+ table Table to remove from cache
62682 -+
62683 -+ NOTES
62684 -+ Function ends by signaling threads waiting for the table to try to
62685 -+ reopen the table.
62686 -+
62687 -+ PREREQUISITES
62688 -+ Lock on LOCK_open
62689 -+ Win32 clients must also have a WRITE LOCK on the table !
62690 -+*/
62691 -+
62692 -+void close_cached_table(THD *thd, TABLE *table)
62693 -+{
62694 -+ DBUG_ENTER("close_cached_table");
62695 -+
62696 -+ wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
62697 -+ /* Close lock if this is not got with LOCK TABLES */
62698 -+ if (thd->lock)
62699 -+ {
62700 -+ mysql_unlock_tables(thd, thd->lock);
62701 -+ thd->lock=0; // Start locked threads
62702 -+ }
62703 -+ /* Close all copies of 'table'. This also frees all LOCK TABLES lock */
62704 -+ unlink_open_table(thd, table, TRUE);
62705 -+
62706 -+ /* When lock on LOCK_open is freed other threads can continue */
62707 -+ broadcast_refresh();
62708 -+ DBUG_VOID_RETURN;
62709 -+}
62710 -+
62711 -+static int send_check_errmsg(THD *thd, TABLE_LIST* table,
62712 -+ const char* operator_name, const char* errmsg)
62713 -+
62714 -+{
62715 -+ Protocol *protocol= thd->protocol;
62716 -+ protocol->prepare_for_resend();
62717 -+ protocol->store(table->alias, system_charset_info);
62718 -+ protocol->store((char*) operator_name, system_charset_info);
62719 -+ protocol->store(STRING_WITH_LEN("error"), system_charset_info);
62720 -+ protocol->store(errmsg, system_charset_info);
62721 -+ thd->clear_error();
62722 -+ if (protocol->write())
62723 -+ return -1;
62724 -+ return 1;
62725 -+}
62726 -+
62727 -+
62728 -+static int prepare_for_restore(THD* thd, TABLE_LIST* table,
62729 -+ HA_CHECK_OPT *check_opt)
62730 -+{
62731 -+ DBUG_ENTER("prepare_for_restore");
62732 -+
62733 -+ if (table->table) // do not overwrite existing tables on restore
62734 -+ {
62735 -+ DBUG_RETURN(send_check_errmsg(thd, table, "restore",
62736 -+ "table exists, will not overwrite on restore"
62737 -+ ));
62738 -+ }
62739 -+ else
62740 -+ {
62741 -+ char* backup_dir= thd->lex->backup_dir;
62742 -+ char src_path[FN_REFLEN], dst_path[FN_REFLEN + 1], uname[FN_REFLEN];
62743 -+ char* table_name= table->table_name;
62744 -+ char* db= table->db;
62745 -+
62746 -+ VOID(tablename_to_filename(table->table_name, uname, sizeof(uname) - 1));
62747 -+
62748 -+ if (fn_format_relative_to_data_home(src_path, uname, backup_dir, reg_ext))
62749 -+ DBUG_RETURN(-1); // protect buffer overflow
62750 -+
62751 -+ build_table_filename(dst_path, sizeof(dst_path) - 1,
62752 -+ db, table_name, reg_ext, 0);
62753 -+
62754 -+ if (lock_and_wait_for_table_name(thd,table))
62755 -+ DBUG_RETURN(-1);
62756 -+
62757 -+ if (my_copy(src_path, dst_path, MYF(MY_WME)))
62758 -+ {
62759 -+ pthread_mutex_lock(&LOCK_open);
62760 -+ unlock_table_name(thd, table);
62761 -+ pthread_mutex_unlock(&LOCK_open);
62762 -+ DBUG_RETURN(send_check_errmsg(thd, table, "restore",
62763 -+ "Failed copying .frm file"));
62764 -+ }
62765 -+ if (mysql_truncate(thd, table, 1))
62766 -+ {
62767 -+ pthread_mutex_lock(&LOCK_open);
62768 -+ unlock_table_name(thd, table);
62769 -+ pthread_mutex_unlock(&LOCK_open);
62770 -+ DBUG_RETURN(send_check_errmsg(thd, table, "restore",
62771 -+ "Failed generating table from .frm file"));
62772 -+ }
62773 -+ }
62774 -+
62775 -+ /*
62776 -+ Now we should be able to open the partially restored table
62777 -+ to finish the restore in the handler later on
62778 -+ */
62779 -+ pthread_mutex_lock(&LOCK_open);
62780 -+ if (reopen_name_locked_table(thd, table, TRUE))
62781 -+ {
62782 -+ unlock_table_name(thd, table);
62783 -+ pthread_mutex_unlock(&LOCK_open);
62784 -+ DBUG_RETURN(send_check_errmsg(thd, table, "restore",
62785 -+ "Failed to open partially restored table"));
62786 -+ }
62787 -+ /* A MERGE table must not come here. */
62788 -+ DBUG_ASSERT(!table->table || !table->table->child_l);
62789 -+ pthread_mutex_unlock(&LOCK_open);
62790 -+ DBUG_RETURN(0);
62791 -+}
62792 -+
62793 -+
62794 -+static int prepare_for_repair(THD *thd, TABLE_LIST *table_list,
62795 -+ HA_CHECK_OPT *check_opt)
62796 -+{
62797 -+ int error= 0;
62798 -+ TABLE tmp_table, *table;
62799 -+ TABLE_SHARE *share;
62800 -+ char from[FN_REFLEN],tmp[FN_REFLEN+32];
62801 -+ const char **ext;
62802 -+ MY_STAT stat_info;
62803 -+ DBUG_ENTER("prepare_for_repair");
62804 -+
62805 -+ if (!(check_opt->sql_flags & TT_USEFRM))
62806 -+ DBUG_RETURN(0);
62807 -+
62808 -+ if (!(table= table_list->table)) /* if open_ltable failed */
62809 -+ {
62810 -+ char key[MAX_DBKEY_LENGTH];
62811 -+ uint key_length;
62812 -+
62813 -+ key_length= create_table_def_key(thd, key, table_list, 0);
62814 -+ pthread_mutex_lock(&LOCK_open);
62815 -+ if (!(share= (get_table_share(thd, table_list, key, key_length, 0,
62816 -+ &error))))
62817 -+ {
62818 -+ pthread_mutex_unlock(&LOCK_open);
62819 -+ DBUG_RETURN(0); // Can't open frm file
62820 -+ }
62821 -+
62822 -+ if (open_table_from_share(thd, share, "", 0, 0, 0, &tmp_table, FALSE))
62823 -+ {
62824 -+ release_table_share(share, RELEASE_NORMAL);
62825 -+ pthread_mutex_unlock(&LOCK_open);
62826 -+ DBUG_RETURN(0); // Out of memory
62827 -+ }
62828 -+ table= &tmp_table;
62829 -+ pthread_mutex_unlock(&LOCK_open);
62830 -+ }
62831 -+
62832 -+ /*
62833 -+ REPAIR TABLE ... USE_FRM for temporary tables makes little sense.
62834 -+ */
62835 -+ if (table->s->tmp_table)
62836 -+ {
62837 -+ error= send_check_errmsg(thd, table_list, "repair",
62838 -+ "Cannot repair temporary table from .frm file");
62839 -+ goto end;
62840 -+ }
62841 -+
62842 -+ /*
62843 -+ User gave us USE_FRM which means that the header in the index file is
62844 -+ trashed.
62845 -+ In this case we will try to fix the table the following way:
62846 -+ - Rename the data file to a temporary name
62847 -+ - Truncate the table
62848 -+ - Replace the new data file with the old one
62849 -+ - Run a normal repair using the new index file and the old data file
62850 -+ */
62851 -+
62852 -+ if (table->s->frm_version != FRM_VER_TRUE_VARCHAR)
62853 -+ {
62854 -+ error= send_check_errmsg(thd, table_list, "repair",
62855 -+ "Failed repairing incompatible .frm file");
62856 -+ goto end;
62857 -+ }
62858 -+
62859 -+ /*
62860 -+ Check if this is a table type that stores index and data separately,
62861 -+ like ISAM or MyISAM. We assume fixed order of engine file name
62862 -+ extentions array. First element of engine file name extentions array
62863 -+ is meta/index file extention. Second element - data file extention.
62864 -+ */
62865 -+ ext= table->file->bas_ext();
62866 -+ if (!ext[0] || !ext[1])
62867 -+ goto end; // No data file
62868 -+
62869 -+ // Name of data file
62870 -+ strxmov(from, table->s->normalized_path.str, ext[1], NullS);
62871 -+ if (!my_stat(from, &stat_info, MYF(0)))
62872 -+ goto end; // Can't use USE_FRM flag
62873 -+
62874 -+ my_snprintf(tmp, sizeof(tmp), "%s-%lx_%lx",
62875 -+ from, current_pid, thd->thread_id);
62876 -+
62877 -+ /* If we could open the table, close it */
62878 -+ if (table_list->table)
62879 -+ {
62880 -+ pthread_mutex_lock(&LOCK_open);
62881 -+ close_cached_table(thd, table);
62882 -+ pthread_mutex_unlock(&LOCK_open);
62883 -+ }
62884 -+ if (lock_and_wait_for_table_name(thd,table_list))
62885 -+ {
62886 -+ error= -1;
62887 -+ goto end;
62888 -+ }
62889 -+ if (my_rename(from, tmp, MYF(MY_WME)))
62890 -+ {
62891 -+ pthread_mutex_lock(&LOCK_open);
62892 -+ unlock_table_name(thd, table_list);
62893 -+ pthread_mutex_unlock(&LOCK_open);
62894 -+ error= send_check_errmsg(thd, table_list, "repair",
62895 -+ "Failed renaming data file");
62896 -+ goto end;
62897 -+ }
62898 -+ if (mysql_truncate(thd, table_list, 1))
62899 -+ {
62900 -+ pthread_mutex_lock(&LOCK_open);
62901 -+ unlock_table_name(thd, table_list);
62902 -+ pthread_mutex_unlock(&LOCK_open);
62903 -+ error= send_check_errmsg(thd, table_list, "repair",
62904 -+ "Failed generating table from .frm file");
62905 -+ goto end;
62906 -+ }
62907 -+ if (my_rename(tmp, from, MYF(MY_WME)))
62908 -+ {
62909 -+ pthread_mutex_lock(&LOCK_open);
62910 -+ unlock_table_name(thd, table_list);
62911 -+ pthread_mutex_unlock(&LOCK_open);
62912 -+ error= send_check_errmsg(thd, table_list, "repair",
62913 -+ "Failed restoring .MYD file");
62914 -+ goto end;
62915 -+ }
62916 -+
62917 -+ /*
62918 -+ Now we should be able to open the partially repaired table
62919 -+ to finish the repair in the handler later on.
62920 -+ */
62921 -+ pthread_mutex_lock(&LOCK_open);
62922 -+ if (reopen_name_locked_table(thd, table_list, TRUE))
62923 -+ {
62924 -+ unlock_table_name(thd, table_list);
62925 -+ pthread_mutex_unlock(&LOCK_open);
62926 -+ error= send_check_errmsg(thd, table_list, "repair",
62927 -+ "Failed to open partially repaired table");
62928 -+ goto end;
62929 -+ }
62930 -+ pthread_mutex_unlock(&LOCK_open);
62931 -+
62932 -+end:
62933 -+ if (table == &tmp_table)
62934 -+ {
62935 -+ pthread_mutex_lock(&LOCK_open);
62936 -+ closefrm(table, 1); // Free allocated memory
62937 -+ pthread_mutex_unlock(&LOCK_open);
62938 -+ }
62939 -+ DBUG_RETURN(error);
62940 -+}
62941 -+
62942 -+
62943 -+
62944 -+/*
62945 -+ RETURN VALUES
62946 -+ FALSE Message sent to net (admin operation went ok)
62947 -+ TRUE Message should be sent by caller
62948 -+ (admin operation or network communication failed)
62949 -+*/
62950 -+static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
62951 -+ HA_CHECK_OPT* check_opt,
62952 -+ const char *operator_name,
62953 -+ thr_lock_type lock_type,
62954 -+ bool open_for_modify,
62955 -+ bool no_warnings_for_error,
62956 -+ uint extra_open_options,
62957 -+ int (*prepare_func)(THD *, TABLE_LIST *,
62958 -+ HA_CHECK_OPT *),
62959 -+ int (handler::*operator_func)(THD *,
62960 -+ HA_CHECK_OPT *),
62961 -+ int (view_operator_func)(THD *, TABLE_LIST*))
62962 -+{
62963 -+ TABLE_LIST *table;
62964 -+ SELECT_LEX *select= &thd->lex->select_lex;
62965 -+ List<Item> field_list;
62966 -+ Item *item;
62967 -+ Protocol *protocol= thd->protocol;
62968 -+ LEX *lex= thd->lex;
62969 -+ int result_code;
62970 -+ DBUG_ENTER("mysql_admin_table");
62971 -+
62972 -+ if (end_active_trans(thd))
62973 -+ DBUG_RETURN(1);
62974 -+ field_list.push_back(item = new Item_empty_string("Table", NAME_CHAR_LEN*2));
62975 -+ item->maybe_null = 1;
62976 -+ field_list.push_back(item = new Item_empty_string("Op", 10));
62977 -+ item->maybe_null = 1;
62978 -+ field_list.push_back(item = new Item_empty_string("Msg_type", 10));
62979 -+ item->maybe_null = 1;
62980 -+ field_list.push_back(item = new Item_empty_string("Msg_text", 255));
62981 -+ item->maybe_null = 1;
62982 -+ if (protocol->send_fields(&field_list,
62983 -+ Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
62984 -+ DBUG_RETURN(TRUE);
62985 -+
62986 -+ mysql_ha_rm_tables(thd, tables, FALSE);
62987 -+
62988 -+ for (table= tables; table; table= table->next_local)
62989 -+ {
62990 -+ char table_name[NAME_LEN*2+2];
62991 -+ char* db = table->db;
62992 -+ bool fatal_error=0;
62993 -+
62994 -+ DBUG_PRINT("admin", ("table: '%s'.'%s'", table->db, table->table_name));
62995 -+ DBUG_PRINT("admin", ("extra_open_options: %u", extra_open_options));
62996 -+ strxmov(table_name, db, ".", table->table_name, NullS);
62997 -+ thd->open_options|= extra_open_options;
62998 -+ table->lock_type= lock_type;
62999 -+ /* open only one table from local list of command */
63000 -+ {
63001 -+ TABLE_LIST *save_next_global, *save_next_local;
63002 -+ save_next_global= table->next_global;
63003 -+ table->next_global= 0;
63004 -+ save_next_local= table->next_local;
63005 -+ table->next_local= 0;
63006 -+ select->table_list.first= table;
63007 -+ /*
63008 -+ Time zone tables and SP tables can be add to lex->query_tables list,
63009 -+ so it have to be prepared.
63010 -+ TODO: Investigate if we can put extra tables into argument instead of
63011 -+ using lex->query_tables
63012 -+ */
63013 -+ lex->query_tables= table;
63014 -+ lex->query_tables_last= &table->next_global;
63015 -+ lex->query_tables_own_last= 0;
63016 -+ thd->no_warnings_for_error= no_warnings_for_error;
63017 -+ if (view_operator_func == NULL)
63018 -+ table->required_type=FRMTYPE_TABLE;
63019 -+
63020 -+ open_and_lock_tables(thd, table);
63021 -+ thd->no_warnings_for_error= 0;
63022 -+ table->next_global= save_next_global;
63023 -+ table->next_local= save_next_local;
63024 -+ thd->open_options&= ~extra_open_options;
63025 -+#ifdef WITH_PARTITION_STORAGE_ENGINE
63026 -+ if (table->table)
63027 -+ {
63028 -+ /*
63029 -+ Set up which partitions that should be processed
63030 -+ if ALTER TABLE t ANALYZE/CHECK/OPTIMIZE/REPAIR PARTITION ..
63031 -+ */
63032 -+ Alter_info *alter_info= &lex->alter_info;
63033 -+
63034 -+ if (alter_info->flags & ALTER_ADMIN_PARTITION)
63035 -+ {
63036 -+ if (!table->table->part_info)
63037 -+ {
63038 -+ my_error(ER_PARTITION_MGMT_ON_NONPARTITIONED, MYF(0));
63039 -+ DBUG_RETURN(TRUE);
63040 -+ }
63041 -+ uint no_parts_found;
63042 -+ uint no_parts_opt= alter_info->partition_names.elements;
63043 -+ no_parts_found= set_part_state(alter_info, table->table->part_info,
63044 -+ PART_CHANGED);
63045 -+ if (no_parts_found != no_parts_opt &&
63046 -+ (!(alter_info->flags & ALTER_ALL_PARTITION)))
63047 -+ {
63048 -+ char buff[FN_REFLEN + MYSQL_ERRMSG_SIZE];
63049 -+ size_t length;
63050 -+ DBUG_PRINT("admin", ("sending non existent partition error"));
63051 -+ protocol->prepare_for_resend();
63052 -+ protocol->store(table_name, system_charset_info);
63053 -+ protocol->store(operator_name, system_charset_info);
63054 -+ protocol->store(STRING_WITH_LEN("error"), system_charset_info);
63055 -+ length= my_snprintf(buff, sizeof(buff),
63056 -+ ER(ER_DROP_PARTITION_NON_EXISTENT),
63057 -+ table_name);
63058 -+ protocol->store(buff, length, system_charset_info);
63059 -+ if(protocol->write())
63060 -+ goto err;
63061 -+ my_eof(thd);
63062 -+ goto err;
63063 -+ }
63064 -+ }
63065 -+ }
63066 -+#endif
63067 -+ }
63068 -+ DBUG_PRINT("admin", ("table: 0x%lx", (long) table->table));
63069 -+
63070 -+ if (prepare_func)
63071 -+ {
63072 -+ DBUG_PRINT("admin", ("calling prepare_func"));
63073 -+ switch ((*prepare_func)(thd, table, check_opt)) {
63074 -+ case 1: // error, message written to net
63075 -+ ha_autocommit_or_rollback(thd, 1);
63076 -+ end_trans(thd, ROLLBACK);
63077 -+ close_thread_tables(thd);
63078 -+ DBUG_PRINT("admin", ("simple error, admin next table"));
63079 -+ continue;
63080 -+ case -1: // error, message could be written to net
63081 -+ /* purecov: begin inspected */
63082 -+ DBUG_PRINT("admin", ("severe error, stop"));
63083 -+ goto err;
63084 -+ /* purecov: end */
63085 -+ default: // should be 0 otherwise
63086 -+ DBUG_PRINT("admin", ("prepare_func succeeded"));
63087 -+ ;
63088 -+ }
63089 -+ }
63090 -+
63091 -+ /*
63092 -+ CHECK TABLE command is only command where VIEW allowed here and this
63093 -+ command use only temporary teble method for VIEWs resolving => there
63094 -+ can't be VIEW tree substitition of join view => if opening table
63095 -+ succeed then table->table will have real TABLE pointer as value (in
63096 -+ case of join view substitution table->table can be 0, but here it is
63097 -+ impossible)
63098 -+ */
63099 -+ if (!table->table)
63100 -+ {
63101 -+ DBUG_PRINT("admin", ("open table failed"));
63102 -+ if (!thd->warn_list.elements)
63103 -+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
63104 -+ ER_CHECK_NO_SUCH_TABLE, ER(ER_CHECK_NO_SUCH_TABLE));
63105 -+ /* if it was a view will check md5 sum */
63106 -+ if (table->view &&
63107 -+ view_checksum(thd, table) == HA_ADMIN_WRONG_CHECKSUM)
63108 -+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
63109 -+ ER_VIEW_CHECKSUM, ER(ER_VIEW_CHECKSUM));
63110 -+ if (thd->main_da.is_error() &&
63111 -+ (thd->main_da.sql_errno() == ER_NO_SUCH_TABLE ||
63112 -+ thd->main_da.sql_errno() == ER_FILE_NOT_FOUND))
63113 -+ /* A missing table is just issued as a failed command */
63114 -+ result_code= HA_ADMIN_FAILED;
63115 -+ else
63116 -+ /* Default failure code is corrupt table */
63117 -+ result_code= HA_ADMIN_CORRUPT;
63118 -+ goto send_result;
63119 -+ }
63120 -+
63121 -+ if (table->view)
63122 -+ {
63123 -+ DBUG_PRINT("admin", ("calling view_operator_func"));
63124 -+ result_code= (*view_operator_func)(thd, table);
63125 -+ goto send_result;
63126 -+ }
63127 -+
63128 -+ if (table->schema_table)
63129 -+ {
63130 -+ result_code= HA_ADMIN_NOT_IMPLEMENTED;
63131 -+ goto send_result;
63132 -+ }
63133 -+
63134 -+ if ((table->table->db_stat & HA_READ_ONLY) && open_for_modify)
63135 -+ {
63136 -+ /* purecov: begin inspected */
63137 -+ char buff[FN_REFLEN + MYSQL_ERRMSG_SIZE];
63138 -+ size_t length;
63139 -+ DBUG_PRINT("admin", ("sending error message"));
63140 -+ protocol->prepare_for_resend();
63141 -+ protocol->store(table_name, system_charset_info);
63142 -+ protocol->store(operator_name, system_charset_info);
63143 -+ protocol->store(STRING_WITH_LEN("error"), system_charset_info);
63144 -+ length= my_snprintf(buff, sizeof(buff), ER(ER_OPEN_AS_READONLY),
63145 -+ table_name);
63146 -+ protocol->store(buff, length, system_charset_info);
63147 -+ ha_autocommit_or_rollback(thd, 0);
63148 -+ end_trans(thd, COMMIT);
63149 -+ close_thread_tables(thd);
63150 -+ lex->reset_query_tables_list(FALSE);
63151 -+ table->table=0; // For query cache
63152 -+ if (protocol->write())
63153 -+ goto err;
63154 -+ thd->main_da.reset_diagnostics_area();
63155 -+ continue;
63156 -+ /* purecov: end */
63157 -+ }
63158 -+
63159 -+ /* Close all instances of the table to allow repair to rename files */
63160 -+ if (lock_type == TL_WRITE && table->table->s->version)
63161 -+ {
63162 -+ DBUG_PRINT("admin", ("removing table from cache"));
63163 -+ pthread_mutex_lock(&LOCK_open);
63164 -+ const char *old_message=thd->enter_cond(&COND_refresh, &LOCK_open,
63165 -+ "Waiting to get writelock");
63166 -+ mysql_lock_abort(thd,table->table, TRUE);
63167 -+ remove_table_from_cache(thd, table->table->s->db.str,
63168 -+ table->table->s->table_name.str,
63169 -+ RTFC_WAIT_OTHER_THREAD_FLAG |
63170 -+ RTFC_CHECK_KILLED_FLAG);
63171 -+ thd->exit_cond(old_message);
63172 -+ DBUG_EXECUTE_IF("wait_in_mysql_admin_table", wait_for_kill_signal(thd););
63173 -+ if (thd->killed)
63174 -+ goto err;
63175 -+ /* Flush entries in the query cache involving this table. */
63176 -+ query_cache_invalidate3(thd, table->table, 0);
63177 -+ open_for_modify= 0;
63178 -+ }
63179 -+
63180 -+ if (table->table->s->crashed && operator_func == &handler::ha_check)
63181 -+ {
63182 -+ /* purecov: begin inspected */
63183 -+ DBUG_PRINT("admin", ("sending crashed warning"));
63184 -+ protocol->prepare_for_resend();
63185 -+ protocol->store(table_name, system_charset_info);
63186 -+ protocol->store(operator_name, system_charset_info);
63187 -+ protocol->store(STRING_WITH_LEN("warning"), system_charset_info);
63188 -+ protocol->store(STRING_WITH_LEN("Table is marked as crashed"),
63189 -+ system_charset_info);
63190 -+ if (protocol->write())
63191 -+ goto err;
63192 -+ /* purecov: end */
63193 -+ }
63194 -+
63195 -+ if (operator_func == &handler::ha_repair &&
63196 -+ !(check_opt->sql_flags & TT_USEFRM))
63197 -+ {
63198 -+ if ((table->table->file->check_old_types() == HA_ADMIN_NEEDS_ALTER) ||
63199 -+ (table->table->file->ha_check_for_upgrade(check_opt) ==
63200 -+ HA_ADMIN_NEEDS_ALTER))
63201 -+ {
63202 -+ DBUG_PRINT("admin", ("recreating table"));
63203 -+ ha_autocommit_or_rollback(thd, 1);
63204 -+ close_thread_tables(thd);
63205 -+ tmp_disable_binlog(thd); // binlogging is done by caller if wanted
63206 -+ result_code= mysql_recreate_table(thd, table);
63207 -+ reenable_binlog(thd);
63208 -+ /*
63209 -+ mysql_recreate_table() can push OK or ERROR.
63210 -+ Clear 'OK' status. If there is an error, keep it:
63211 -+ we will store the error message in a result set row
63212 -+ and then clear.
63213 -+ */
63214 -+ if (thd->main_da.is_ok())
63215 -+ thd->main_da.reset_diagnostics_area();
63216 -+ goto send_result;
63217 -+ }
63218 -+ }
63219 -+
63220 -+ DBUG_PRINT("admin", ("calling operator_func '%s'", operator_name));
63221 -+ result_code = (table->table->file->*operator_func)(thd, check_opt);
63222 -+ DBUG_PRINT("admin", ("operator_func returned: %d", result_code));
63223 -+
63224 -+send_result:
63225 -+
63226 -+ lex->cleanup_after_one_table_open();
63227 -+ thd->clear_error(); // these errors shouldn't get client
63228 -+ {
63229 -+ List_iterator_fast<MYSQL_ERROR> it(thd->warn_list);
63230 -+ MYSQL_ERROR *err;
63231 -+ while ((err= it++))
63232 -+ {
63233 -+ protocol->prepare_for_resend();
63234 -+ protocol->store(table_name, system_charset_info);
63235 -+ protocol->store((char*) operator_name, system_charset_info);
63236 -+ protocol->store(warning_level_names[err->level].str,
63237 -+ warning_level_names[err->level].length,
63238 -+ system_charset_info);
63239 -+ protocol->store(err->msg, system_charset_info);
63240 -+ if (protocol->write())
63241 -+ goto err;
63242 -+ }
63243 -+ mysql_reset_errors(thd, true);
63244 -+ }
63245 -+ protocol->prepare_for_resend();
63246 -+ protocol->store(table_name, system_charset_info);
63247 -+ protocol->store(operator_name, system_charset_info);
63248 -+
63249 -+send_result_message:
63250 -+
63251 -+ DBUG_PRINT("info", ("result_code: %d", result_code));
63252 -+ switch (result_code) {
63253 -+ case HA_ADMIN_NOT_IMPLEMENTED:
63254 -+ {
63255 -+ char buf[MYSQL_ERRMSG_SIZE];
63256 -+ size_t length=my_snprintf(buf, sizeof(buf),
63257 -+ ER(ER_CHECK_NOT_IMPLEMENTED), operator_name);
63258 -+ protocol->store(STRING_WITH_LEN("note"), system_charset_info);
63259 -+ protocol->store(buf, length, system_charset_info);
63260 -+ }
63261 -+ break;
63262 -+
63263 -+ case HA_ADMIN_NOT_BASE_TABLE:
63264 -+ {
63265 -+ char buf[MYSQL_ERRMSG_SIZE];
63266 -+ size_t length= my_snprintf(buf, sizeof(buf),
63267 -+ ER(ER_BAD_TABLE_ERROR), table_name);
63268 -+ protocol->store(STRING_WITH_LEN("note"), system_charset_info);
63269 -+ protocol->store(buf, length, system_charset_info);
63270 -+ }
63271 -+ break;
63272 -+
63273 -+ case HA_ADMIN_OK:
63274 -+ protocol->store(STRING_WITH_LEN("status"), system_charset_info);
63275 -+ protocol->store(STRING_WITH_LEN("OK"), system_charset_info);
63276 -+ break;
63277 -+
63278 -+ case HA_ADMIN_FAILED:
63279 -+ protocol->store(STRING_WITH_LEN("status"), system_charset_info);
63280 -+ protocol->store(STRING_WITH_LEN("Operation failed"),
63281 -+ system_charset_info);
63282 -+ break;
63283 -+
63284 -+ case HA_ADMIN_REJECT:
63285 -+ protocol->store(STRING_WITH_LEN("status"), system_charset_info);
63286 -+ protocol->store(STRING_WITH_LEN("Operation need committed state"),
63287 -+ system_charset_info);
63288 -+ open_for_modify= FALSE;
63289 -+ break;
63290 -+
63291 -+ case HA_ADMIN_ALREADY_DONE:
63292 -+ protocol->store(STRING_WITH_LEN("status"), system_charset_info);
63293 -+ protocol->store(STRING_WITH_LEN("Table is already up to date"),
63294 -+ system_charset_info);
63295 -+ break;
63296 -+
63297 -+ case HA_ADMIN_CORRUPT:
63298 -+ protocol->store(STRING_WITH_LEN("error"), system_charset_info);
63299 -+ protocol->store(STRING_WITH_LEN("Corrupt"), system_charset_info);
63300 -+ fatal_error=1;
63301 -+ break;
63302 -+
63303 -+ case HA_ADMIN_INVALID:
63304 -+ protocol->store(STRING_WITH_LEN("error"), system_charset_info);
63305 -+ protocol->store(STRING_WITH_LEN("Invalid argument"),
63306 -+ system_charset_info);
63307 -+ break;
63308 -+
63309 -+ case HA_ADMIN_TRY_ALTER:
63310 -+ {
63311 -+ /*
63312 -+ This is currently used only by InnoDB. ha_innobase::optimize() answers
63313 -+ "try with alter", so here we close the table, do an ALTER TABLE,
63314 -+ reopen the table and do ha_innobase::analyze() on it.
63315 -+ We have to end the row, so analyze could return more rows.
63316 -+ */
63317 -+ protocol->store(STRING_WITH_LEN("note"), system_charset_info);
63318 -+ protocol->store(STRING_WITH_LEN(
63319 -+ "Table does not support optimize, doing recreate + analyze instead"),
63320 -+ system_charset_info);
63321 -+ if (protocol->write())
63322 -+ goto err;
63323 -+ ha_autocommit_or_rollback(thd, 0);
63324 -+ close_thread_tables(thd);
63325 -+ DBUG_PRINT("info", ("HA_ADMIN_TRY_ALTER, trying analyze..."));
63326 -+ TABLE_LIST *save_next_local= table->next_local,
63327 -+ *save_next_global= table->next_global;
63328 -+ table->next_local= table->next_global= 0;
63329 -+ tmp_disable_binlog(thd); // binlogging is done by caller if wanted
63330 -+ result_code= mysql_recreate_table(thd, table);
63331 -+ reenable_binlog(thd);
63332 -+ /*
63333 -+ mysql_recreate_table() can push OK or ERROR.
63334 -+ Clear 'OK' status. If there is an error, keep it:
63335 -+ we will store the error message in a result set row
63336 -+ and then clear.
63337 -+ */
63338 -+ if (thd->main_da.is_ok())
63339 -+ thd->main_da.reset_diagnostics_area();
63340 -+ ha_autocommit_or_rollback(thd, 0);
63341 -+ close_thread_tables(thd);
63342 -+ if (!result_code) // recreation went ok
63343 -+ {
63344 -+ if ((table->table= open_ltable(thd, table, lock_type, 0)) &&
63345 -+ ((result_code= table->table->file->ha_analyze(thd, check_opt)) > 0))
63346 -+ result_code= 0; // analyze went ok
63347 -+ }
63348 -+ /* Start a new row for the final status row */
63349 -+ protocol->prepare_for_resend();
63350 -+ protocol->store(table_name, system_charset_info);
63351 -+ protocol->store(operator_name, system_charset_info);
63352 -+ if (result_code) // either mysql_recreate_table or analyze failed
63353 -+ {
63354 -+ DBUG_ASSERT(thd->is_error());
63355 -+ if (thd->is_error())
63356 -+ {
63357 -+ const char *err_msg= thd->main_da.message();
63358 -+ if (!thd->vio_ok())
63359 -+ {
63360 -+ sql_print_error("%s", err_msg);
63361 -+ }
63362 -+ else
63363 -+ {
63364 -+ /* Hijack the row already in-progress. */
63365 -+ protocol->store(STRING_WITH_LEN("error"), system_charset_info);
63366 -+ protocol->store(err_msg, system_charset_info);
63367 -+ if (protocol->write())
63368 -+ goto err;
63369 -+ /* Start off another row for HA_ADMIN_FAILED */
63370 -+ protocol->prepare_for_resend();
63371 -+ protocol->store(table_name, system_charset_info);
63372 -+ protocol->store(operator_name, system_charset_info);
63373 -+ }
63374 -+ thd->clear_error();
63375 -+ }
63376 -+ }
63377 -+ result_code= result_code ? HA_ADMIN_FAILED : HA_ADMIN_OK;
63378 -+ table->next_local= save_next_local;
63379 -+ table->next_global= save_next_global;
63380 -+ goto send_result_message;
63381 -+ }
63382 -+ case HA_ADMIN_WRONG_CHECKSUM:
63383 -+ {
63384 -+ protocol->store(STRING_WITH_LEN("note"), system_charset_info);
63385 -+ protocol->store(ER(ER_VIEW_CHECKSUM), strlen(ER(ER_VIEW_CHECKSUM)),
63386 -+ system_charset_info);
63387 -+ break;
63388 -+ }
63389 -+
63390 -+ case HA_ADMIN_NEEDS_UPGRADE:
63391 -+ case HA_ADMIN_NEEDS_ALTER:
63392 -+ {
63393 -+ char buf[MYSQL_ERRMSG_SIZE];
63394 -+ size_t length;
63395 -+
63396 -+ protocol->store(STRING_WITH_LEN("error"), system_charset_info);
63397 -+ length=my_snprintf(buf, sizeof(buf), ER(ER_TABLE_NEEDS_UPGRADE),
63398 -+ table->table_name);
63399 -+ protocol->store(buf, length, system_charset_info);
63400 -+ fatal_error=1;
63401 -+ break;
63402 -+ }
63403 -+
63404 -+ default: // Probably HA_ADMIN_INTERNAL_ERROR
63405 -+ {
63406 -+ char buf[MYSQL_ERRMSG_SIZE];
63407 -+ size_t length=my_snprintf(buf, sizeof(buf),
63408 -+ "Unknown - internal error %d during operation",
63409 -+ result_code);
63410 -+ protocol->store(STRING_WITH_LEN("error"), system_charset_info);
63411 -+ protocol->store(buf, length, system_charset_info);
63412 -+ fatal_error=1;
63413 -+ break;
63414 -+ }
63415 -+ }
63416 -+ if (table->table)
63417 -+ {
63418 -+ if (fatal_error)
63419 -+ table->table->s->version=0; // Force close of table
63420 -+ else if (open_for_modify)
63421 -+ {
63422 -+ if (table->table->s->tmp_table)
63423 -+ table->table->file->info(HA_STATUS_CONST);
63424 -+ else
63425 -+ {
63426 -+ pthread_mutex_lock(&LOCK_open);
63427 -+ remove_table_from_cache(thd, table->table->s->db.str,
63428 -+ table->table->s->table_name.str, RTFC_NO_FLAG);
63429 -+ pthread_mutex_unlock(&LOCK_open);
63430 -+ }
63431 -+ /* May be something modified consequently we have to invalidate cache */
63432 -+ query_cache_invalidate3(thd, table->table, 0);
63433 -+ }
63434 -+ }
63435 -+ ha_autocommit_or_rollback(thd, 0);
63436 -+ end_trans(thd, COMMIT);
63437 -+ close_thread_tables(thd);
63438 -+ table->table=0; // For query cache
63439 -+ if (protocol->write())
63440 -+ goto err;
63441 -+ }
63442 -+
63443 -+ my_eof(thd);
63444 -+ DBUG_RETURN(FALSE);
63445 -+
63446 -+err:
63447 -+ ha_autocommit_or_rollback(thd, 1);
63448 -+ end_trans(thd, ROLLBACK);
63449 -+ close_thread_tables(thd); // Shouldn't be needed
63450 -+ if (table)
63451 -+ table->table=0;
63452 -+ DBUG_RETURN(TRUE);
63453 -+}
63454 -+
63455 -+
63456 -+bool mysql_backup_table(THD* thd, TABLE_LIST* table_list)
63457 -+{
63458 -+ DBUG_ENTER("mysql_backup_table");
63459 -+ WARN_DEPRECATED(thd, "6.0", "BACKUP TABLE",
63460 -+ "MySQL Administrator (mysqldump, mysql)");
63461 -+ DBUG_RETURN(mysql_admin_table(thd, table_list, 0,
63462 -+ "backup", TL_READ, 0, 0, 0, 0,
63463 -+ &handler::ha_backup, 0));
63464 -+}
63465 -+
63466 -+
63467 -+bool mysql_restore_table(THD* thd, TABLE_LIST* table_list)
63468 -+{
63469 -+ DBUG_ENTER("mysql_restore_table");
63470 -+ WARN_DEPRECATED(thd, "6.0", "RESTORE TABLE",
63471 -+ "MySQL Administrator (mysqldump, mysql)");
63472 -+ DBUG_RETURN(mysql_admin_table(thd, table_list, 0,
63473 -+ "restore", TL_WRITE, 1, 1, 0,
63474 -+ &prepare_for_restore,
63475 -+ &handler::ha_restore, 0));
63476 -+}
63477 -+
63478 -+
63479 -+bool mysql_repair_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
63480 -+{
63481 -+ DBUG_ENTER("mysql_repair_table");
63482 -+ DBUG_RETURN(mysql_admin_table(thd, tables, check_opt,
63483 -+ "repair", TL_WRITE, 1,
63484 -+ test(check_opt->sql_flags & TT_USEFRM),
63485 -+ HA_OPEN_FOR_REPAIR,
63486 -+ &prepare_for_repair,
63487 -+ &handler::ha_repair, 0));
63488 -+}
63489 -+
63490 -+
63491 -+bool mysql_optimize_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
63492 -+{
63493 -+ DBUG_ENTER("mysql_optimize_table");
63494 -+ DBUG_RETURN(mysql_admin_table(thd, tables, check_opt,
63495 -+ "optimize", TL_WRITE, 1,0,0,0,
63496 -+ &handler::ha_optimize, 0));
63497 -+}
63498 -+
63499 -+
63500 -+/*
63501 -+ Assigned specified indexes for a table into key cache
63502 -+
63503 -+ SYNOPSIS
63504 -+ mysql_assign_to_keycache()
63505 -+ thd Thread object
63506 -+ tables Table list (one table only)
63507 -+
63508 -+ RETURN VALUES
63509 -+ FALSE ok
63510 -+ TRUE error
63511 -+*/
63512 -+
63513 -+bool mysql_assign_to_keycache(THD* thd, TABLE_LIST* tables,
63514 -+ LEX_STRING *key_cache_name)
63515 -+{
63516 -+ HA_CHECK_OPT check_opt;
63517 -+ KEY_CACHE *key_cache;
63518 -+ DBUG_ENTER("mysql_assign_to_keycache");
63519 -+
63520 -+ check_opt.init();
63521 -+ pthread_mutex_lock(&LOCK_global_system_variables);
63522 -+ if (!(key_cache= get_key_cache(key_cache_name)))
63523 -+ {
63524 -+ pthread_mutex_unlock(&LOCK_global_system_variables);
63525 -+ my_error(ER_UNKNOWN_KEY_CACHE, MYF(0), key_cache_name->str);
63526 -+ DBUG_RETURN(TRUE);
63527 -+ }
63528 -+ pthread_mutex_unlock(&LOCK_global_system_variables);
63529 -+ check_opt.key_cache= key_cache;
63530 -+ DBUG_RETURN(mysql_admin_table(thd, tables, &check_opt,
63531 -+ "assign_to_keycache", TL_READ_NO_INSERT, 0, 0,
63532 -+ 0, 0, &handler::assign_to_keycache, 0));
63533 -+}
63534 -+
63535 -+
63536 -+/*
63537 -+ Reassign all tables assigned to a key cache to another key cache
63538 -+
63539 -+ SYNOPSIS
63540 -+ reassign_keycache_tables()
63541 -+ thd Thread object
63542 -+ src_cache Reference to the key cache to clean up
63543 -+ dest_cache New key cache
63544 -+
63545 -+ NOTES
63546 -+ This is called when one sets a key cache size to zero, in which
63547 -+ case we have to move the tables associated to this key cache to
63548 -+ the "default" one.
63549 -+
63550 -+ One has to ensure that one never calls this function while
63551 -+ some other thread is changing the key cache. This is assured by
63552 -+ the caller setting src_cache->in_init before calling this function.
63553 -+
63554 -+ We don't delete the old key cache as there may still be pointers pointing
63555 -+ to it for a while after this function returns.
63556 -+
63557 -+ RETURN VALUES
63558 -+ 0 ok
63559 -+*/
63560 -+
63561 -+int reassign_keycache_tables(THD *thd, KEY_CACHE *src_cache,
63562 -+ KEY_CACHE *dst_cache)
63563 -+{
63564 -+ DBUG_ENTER("reassign_keycache_tables");
63565 -+
63566 -+ DBUG_ASSERT(src_cache != dst_cache);
63567 -+ DBUG_ASSERT(src_cache->in_init);
63568 -+ src_cache->param_buff_size= 0; // Free key cache
63569 -+ ha_resize_key_cache(src_cache);
63570 -+ ha_change_key_cache(src_cache, dst_cache);
63571 -+ DBUG_RETURN(0);
63572 -+}
63573 -+
63574 -+
63575 -+/*
63576 -+ Preload specified indexes for a table into key cache
63577 -+
63578 -+ SYNOPSIS
63579 -+ mysql_preload_keys()
63580 -+ thd Thread object
63581 -+ tables Table list (one table only)
63582 -+
63583 -+ RETURN VALUES
63584 -+ FALSE ok
63585 -+ TRUE error
63586 -+*/
63587 -+
63588 -+bool mysql_preload_keys(THD* thd, TABLE_LIST* tables)
63589 -+{
63590 -+ DBUG_ENTER("mysql_preload_keys");
63591 -+ /*
63592 -+ We cannot allow concurrent inserts. The storage engine reads
63593 -+ directly from the index file, bypassing the cache. It could read
63594 -+ outdated information if parallel inserts into cache blocks happen.
63595 -+ */
63596 -+ DBUG_RETURN(mysql_admin_table(thd, tables, 0,
63597 -+ "preload_keys", TL_READ_NO_INSERT, 0, 0, 0, 0,
63598 -+ &handler::preload_keys, 0));
63599 -+}
63600 -+
63601 -+
63602 -+
63603 -+/**
63604 -+ @brief Create frm file based on I_S table
63605 -+
63606 -+ @param[in] thd thread handler
63607 -+ @param[in] schema_table I_S table
63608 -+ @param[in] dst_path path where frm should be created
63609 -+ @param[in] create_info Create info
63610 -+
63611 -+ @return Operation status
63612 -+ @retval 0 success
63613 -+ @retval 1 error
63614 -+*/
63615 -+
63616 -+
63617 -+bool mysql_create_like_schema_frm(THD* thd, TABLE_LIST* schema_table,
63618 -+ char *dst_path, HA_CREATE_INFO *create_info)
63619 -+{
63620 -+ HA_CREATE_INFO local_create_info;
63621 -+ Alter_info alter_info;
63622 -+ bool tmp_table= (create_info->options & HA_LEX_CREATE_TMP_TABLE);
63623 -+ uint keys= schema_table->table->s->keys;
63624 -+ uint db_options= 0;
63625 -+ DBUG_ENTER("mysql_create_like_schema_frm");
63626 -+
63627 -+ bzero((char*) &local_create_info, sizeof(local_create_info));
63628 -+ local_create_info.db_type= schema_table->table->s->db_type();
63629 -+ local_create_info.row_type= schema_table->table->s->row_type;
63630 -+ local_create_info.default_table_charset=default_charset_info;
63631 -+ alter_info.flags= (ALTER_CHANGE_COLUMN | ALTER_RECREATE);
63632 -+ schema_table->table->use_all_columns();
63633 -+ if (mysql_prepare_alter_table(thd, schema_table->table,
63634 -+ &local_create_info, &alter_info))
63635 -+ DBUG_RETURN(1);
63636 -+ if (mysql_prepare_create_table(thd, &local_create_info, &alter_info,
63637 -+ tmp_table, &db_options,
63638 -+ schema_table->table->file,
63639 -+ &schema_table->table->s->key_info, &keys, 0))
63640 -+ DBUG_RETURN(1);
63641 -+ local_create_info.max_rows= 0;
63642 -+ if (mysql_create_frm(thd, dst_path, NullS, NullS,
63643 -+ &local_create_info, alter_info.create_list,
63644 -+ keys, schema_table->table->s->key_info,
63645 -+ schema_table->table->file))
63646 -+ DBUG_RETURN(1);
63647 -+ DBUG_RETURN(0);
63648 -+}
63649 -+
63650 -+
63651 -+/*
63652 -+ Create a table identical to the specified table
63653 -+
63654 -+ SYNOPSIS
63655 -+ mysql_create_like_table()
63656 -+ thd Thread object
63657 -+ table Table list element for target table
63658 -+ src_table Table list element for source table
63659 -+ create_info Create info
63660 -+
63661 -+ RETURN VALUES
63662 -+ FALSE OK
63663 -+ TRUE error
63664 -+*/
63665 -+
63666 -+bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table,
63667 -+ HA_CREATE_INFO *create_info)
63668 -+{
63669 -+ TABLE *name_lock= 0;
63670 -+ char src_path[FN_REFLEN], dst_path[FN_REFLEN + 1];
63671 -+ uint dst_path_length;
63672 -+ char *db= table->db;
63673 -+ char *table_name= table->table_name;
63674 -+ int err;
63675 -+ bool res= TRUE;
63676 -+ uint not_used;
63677 -+#ifdef WITH_PARTITION_STORAGE_ENGINE
63678 -+ char tmp_path[FN_REFLEN];
63679 -+#endif
63680 -+ char ts_name[FN_LEN + 1];
63681 -+ myf flags= MY_DONT_OVERWRITE_FILE;
63682 -+ DBUG_ENTER("mysql_create_like_table");
63683 -+
63684 -+
63685 -+ /*
63686 -+ By opening source table we guarantee that it exists and no concurrent
63687 -+ DDL operation will mess with it. Later we also take an exclusive
63688 -+ name-lock on target table name, which makes copying of .frm file,
63689 -+ call to ha_create_table() and binlogging atomic against concurrent DML
63690 -+ and DDL operations on target table. Thus by holding both these "locks"
63691 -+ we ensure that our statement is properly isolated from all concurrent
63692 -+ operations which matter.
63693 -+ */
63694 -+ if (open_tables(thd, &src_table, &not_used, 0))
63695 -+ DBUG_RETURN(TRUE);
63696 -+
63697 -+ /*
63698 -+ For bug#25875, Newly created table through CREATE TABLE .. LIKE
63699 -+ has no ndb_dd attributes;
63700 -+ Add something to get possible tablespace info from src table,
63701 -+ it can get valid tablespace name only for disk-base ndb table
63702 -+ */
63703 -+ if ((src_table->table->file->get_tablespace_name(thd, ts_name, FN_LEN)))
63704 -+ {
63705 -+ create_info->tablespace= ts_name;
63706 -+ create_info->storage_media= HA_SM_DISK;
63707 -+ }
63708 -+
63709 -+ strxmov(src_path, src_table->table->s->path.str, reg_ext, NullS);
63710 -+
63711 -+ DBUG_EXECUTE_IF("sleep_create_like_before_check_if_exists", my_sleep(6000000););
63712 -+
63713 -+ /*
63714 -+ Check that destination tables does not exist. Note that its name
63715 -+ was already checked when it was added to the table list.
63716 -+ */
63717 -+ if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
63718 -+ {
63719 -+ if (src_table->table->file->ht == partition_hton)
63720 -+ {
63721 -+ my_error(ER_PARTITION_NO_TEMPORARY, MYF(0));
63722 -+ goto err;
63723 -+ }
63724 -+ if (find_temporary_table(thd, db, table_name))
63725 -+ goto table_exists;
63726 -+ dst_path_length= build_tmptable_filename(thd, dst_path, sizeof(dst_path));
63727 -+ create_info->table_options|= HA_CREATE_DELAY_KEY_WRITE;
63728 -+ }
63729 -+ else
63730 -+ {
63731 -+ if (lock_table_name_if_not_cached(thd, db, table_name, &name_lock))
63732 -+ goto err;
63733 -+ if (!name_lock)
63734 -+ goto table_exists;
63735 -+ dst_path_length= build_table_filename(dst_path, sizeof(dst_path) - 1,
63736 -+ db, table_name, reg_ext, 0);
63737 -+ if (!access(dst_path, F_OK))
63738 -+ goto table_exists;
63739 -+ }
63740 -+
63741 -+ DBUG_EXECUTE_IF("sleep_create_like_before_copy", my_sleep(6000000););
63742 -+
63743 -+ if (opt_sync_frm && !(create_info->options & HA_LEX_CREATE_TMP_TABLE))
63744 -+ flags|= MY_SYNC;
63745 -+
63746 -+ /*
63747 -+ Create a new table by copying from source table
63748 -+ and sync the new table if the flag MY_SYNC is set
63749 -+
63750 -+ Altough exclusive name-lock on target table protects us from concurrent
63751 -+ DML and DDL operations on it we still want to wrap .FRM creation and call
63752 -+ to ha_create_table() in critical section protected by LOCK_open in order
63753 -+ to provide minimal atomicity against operations which disregard name-locks,
63754 -+ like I_S implementation, for example. This is a temporary and should not
63755 -+ be copied. Instead we should fix our code to always honor name-locks.
63756 -+
63757 -+ Also some engines (e.g. NDB cluster) require that LOCK_open should be held
63758 -+ during the call to ha_create_table(). See bug #28614 for more info.
63759 -+ */
63760 -+ VOID(pthread_mutex_lock(&LOCK_open));
63761 -+ if (src_table->schema_table)
63762 -+ {
63763 -+ if (mysql_create_like_schema_frm(thd, src_table, dst_path, create_info))
63764 -+ {
63765 -+ VOID(pthread_mutex_unlock(&LOCK_open));
63766 -+ goto err;
63767 -+ }
63768 -+ }
63769 -+ else if (my_copy(src_path, dst_path, flags))
63770 -+ {
63771 -+ if (my_errno == ENOENT)
63772 -+ my_error(ER_BAD_DB_ERROR,MYF(0),db);
63773 -+ else
63774 -+ my_error(ER_CANT_CREATE_FILE,MYF(0),dst_path,my_errno);
63775 -+ VOID(pthread_mutex_unlock(&LOCK_open));
63776 -+ goto err;
63777 -+ }
63778 -+
63779 -+ /*
63780 -+ As mysql_truncate don't work on a new table at this stage of
63781 -+ creation, instead create the table directly (for both normal
63782 -+ and temporary tables).
63783 -+ */
63784 -+#ifdef WITH_PARTITION_STORAGE_ENGINE
63785 -+ /*
63786 -+ For partitioned tables we need to copy the .par file as well since
63787 -+ it is used in open_table_def to even be able to create a new handler.
63788 -+ */
63789 -+ if (src_table->table->file->ht == partition_hton)
63790 -+ {
63791 -+ fn_format(tmp_path, dst_path, reg_ext, ".par", MYF(MY_REPLACE_EXT));
63792 -+ strmov(dst_path, tmp_path);
63793 -+ fn_format(tmp_path, src_path, reg_ext, ".par", MYF(MY_REPLACE_EXT));
63794 -+ strmov(src_path, tmp_path);
63795 -+ my_copy(src_path, dst_path, MYF(MY_DONT_OVERWRITE_FILE));
63796 -+ }
63797 -+#endif
63798 -+
63799 -+ DBUG_EXECUTE_IF("sleep_create_like_before_ha_create", my_sleep(6000000););
63800 -+
63801 -+ dst_path[dst_path_length - reg_ext_length]= '\0'; // Remove .frm
63802 -+ if (thd->variables.keep_files_on_create)
63803 -+ create_info->options|= HA_CREATE_KEEP_FILES;
63804 -+ err= ha_create_table(thd, dst_path, db, table_name, create_info, 1);
63805 -+ VOID(pthread_mutex_unlock(&LOCK_open));
63806 -+
63807 -+ if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
63808 -+ {
63809 -+ if (err || !open_temporary_table(thd, dst_path, db, table_name, 1))
63810 -+ {
63811 -+ (void) rm_temporary_table(create_info->db_type,
63812 -+ dst_path); /* purecov: inspected */
63813 -+ goto err; /* purecov: inspected */
63814 -+ }
63815 -+ thd->thread_specific_used= TRUE;
63816 -+ }
63817 -+ else if (err)
63818 -+ {
63819 -+ (void) quick_rm_table(create_info->db_type, db,
63820 -+ table_name, 0); /* purecov: inspected */
63821 -+ goto err; /* purecov: inspected */
63822 -+ }
63823 -+
63824 -+goto binlog;
63825 -+
63826 -+table_exists:
63827 -+ if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
63828 -+ {
63829 -+ char warn_buff[MYSQL_ERRMSG_SIZE];
63830 -+ my_snprintf(warn_buff, sizeof(warn_buff),
63831 -+ ER(ER_TABLE_EXISTS_ERROR), table_name);
63832 -+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
63833 -+ ER_TABLE_EXISTS_ERROR,warn_buff);
63834 -+ }
63835 -+ else
63836 -+ {
63837 -+ my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
63838 -+ goto err;
63839 -+ }
63840 -+
63841 -+binlog:
63842 -+ DBUG_EXECUTE_IF("sleep_create_like_before_binlogging", my_sleep(6000000););
63843 -+
63844 -+ /*
63845 -+ We have to write the query before we unlock the tables.
63846 -+ */
63847 -+ if (thd->current_stmt_binlog_row_based)
63848 -+ {
63849 -+ /*
63850 -+ Since temporary tables are not replicated under row-based
63851 -+ replication, CREATE TABLE ... LIKE ... needs special
63852 -+ treatement. We have four cases to consider, according to the
63853 -+ following decision table:
63854 -+
63855 -+ ==== ========= ========= ==============================
63856 -+ Case Target Source Write to binary log
63857 -+ ==== ========= ========= ==============================
63858 -+ 1 normal normal Original statement
63859 -+ 2 normal temporary Generated statement
63860 -+ 3 temporary normal Nothing
63861 -+ 4 temporary temporary Nothing
63862 -+ ==== ========= ========= ==============================
63863 -+ */
63864 -+ if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
63865 -+ {
63866 -+ if (src_table->table->s->tmp_table) // Case 2
63867 -+ {
63868 -+ char buf[2048];
63869 -+ String query(buf, sizeof(buf), system_charset_info);
63870 -+ query.length(0); // Have to zero it since constructor doesn't
63871 -+
63872 -+ /*
63873 -+ Here we open the destination table, on which we already have
63874 -+ name-lock. This is needed for store_create_info() to work.
63875 -+ The table will be closed by unlink_open_table() at the end
63876 -+ of this function.
63877 -+ */
63878 -+ table->table= name_lock;
63879 -+ VOID(pthread_mutex_lock(&LOCK_open));
63880 -+ if (reopen_name_locked_table(thd, table, FALSE))
63881 -+ {
63882 -+ VOID(pthread_mutex_unlock(&LOCK_open));
63883 -+ goto err;
63884 -+ }
63885 -+ VOID(pthread_mutex_unlock(&LOCK_open));
63886 -+
63887 -+ /*
63888 -+ The condition avoids a crash as described in BUG#48506. Other
63889 -+ binlogging problems related to CREATE TABLE IF NOT EXISTS LIKE
63890 -+ when the existing object is a view will be solved by BUG 47442.
63891 -+ */
63892 -+ if (!table->view)
63893 -+ {
63894 -+ IF_DBUG(int result=)
63895 -+ store_create_info(thd, table, &query,
63896 -+ create_info, FALSE /* show_database */);
63897 -+
63898 -+ DBUG_ASSERT(result == 0); // store_create_info() always return 0
63899 -+ if (write_bin_log(thd, TRUE, query.ptr(), query.length()))
63900 -+ goto err;
63901 -+ }
63902 -+ }
63903 -+ else // Case 1
63904 -+ if (write_bin_log(thd, TRUE, thd->query(), thd->query_length()))
63905 -+ goto err;
63906 -+ }
63907 -+ /*
63908 -+ Case 3 and 4 does nothing under RBR
63909 -+ */
63910 -+ }
63911 -+ else if (write_bin_log(thd, TRUE, thd->query(), thd->query_length()))
63912 -+ goto err;
63913 -+
63914 -+ res= FALSE;
63915 -+
63916 -+err:
63917 -+ if (name_lock)
63918 -+ {
63919 -+ pthread_mutex_lock(&LOCK_open);
63920 -+ unlink_open_table(thd, name_lock, FALSE);
63921 -+ pthread_mutex_unlock(&LOCK_open);
63922 -+ }
63923 -+ DBUG_RETURN(res);
63924 -+}
63925 -+
63926 -+
63927 -+bool mysql_analyze_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
63928 -+{
63929 -+ thr_lock_type lock_type = TL_READ_NO_INSERT;
63930 -+
63931 -+ DBUG_ENTER("mysql_analyze_table");
63932 -+ DBUG_RETURN(mysql_admin_table(thd, tables, check_opt,
63933 -+ "analyze", lock_type, 1, 0, 0, 0,
63934 -+ &handler::ha_analyze, 0));
63935 -+}
63936 -+
63937 -+
63938 -+bool mysql_check_table(THD* thd, TABLE_LIST* tables,HA_CHECK_OPT* check_opt)
63939 -+{
63940 -+ thr_lock_type lock_type = TL_READ_NO_INSERT;
63941 -+
63942 -+ DBUG_ENTER("mysql_check_table");
63943 -+ DBUG_RETURN(mysql_admin_table(thd, tables, check_opt,
63944 -+ "check", lock_type,
63945 -+ 0, 0, HA_OPEN_FOR_REPAIR, 0,
63946 -+ &handler::ha_check, &view_checksum));
63947 -+}
63948 -+
63949 -+
63950 -+/* table_list should contain just one table */
63951 -+static int
63952 -+mysql_discard_or_import_tablespace(THD *thd,
63953 -+ TABLE_LIST *table_list,
63954 -+ enum tablespace_op_type tablespace_op)
63955 -+{
63956 -+ TABLE *table;
63957 -+ my_bool discard;
63958 -+ int error;
63959 -+ DBUG_ENTER("mysql_discard_or_import_tablespace");
63960 -+
63961 -+ /*
63962 -+ Note that DISCARD/IMPORT TABLESPACE always is the only operation in an
63963 -+ ALTER TABLE
63964 -+ */
63965 -+
63966 -+ thd_proc_info(thd, "discard_or_import_tablespace");
63967 -+
63968 -+ discard= test(tablespace_op == DISCARD_TABLESPACE);
63969 -+
63970 -+ /*
63971 -+ We set this flag so that ha_innobase::open and ::external_lock() do
63972 -+ not complain when we lock the table
63973 -+ */
63974 -+ thd->tablespace_op= TRUE;
63975 -+ if (!(table=open_ltable(thd, table_list, TL_WRITE, 0)))
63976 -+ {
63977 -+ thd->tablespace_op=FALSE;
63978 -+ DBUG_RETURN(-1);
63979 -+ }
63980 -+
63981 -+ error= table->file->ha_discard_or_import_tablespace(discard);
63982 -+
63983 -+ thd_proc_info(thd, "end");
63984 -+
63985 -+ if (error)
63986 -+ goto err;
63987 -+
63988 -+ /*
63989 -+ The 0 in the call below means 'not in a transaction', which means
63990 -+ immediate invalidation; that is probably what we wish here
63991 -+ */
63992 -+ query_cache_invalidate3(thd, table_list, 0);
63993 -+
63994 -+ /* The ALTER TABLE is always in its own transaction */
63995 -+ error = ha_autocommit_or_rollback(thd, 0);
63996 -+ if (end_active_trans(thd))
63997 -+ error=1;
63998 -+ if (error)
63999 -+ goto err;
64000 -+ error= write_bin_log(thd, FALSE, thd->query(), thd->query_length());
64001 -+
64002 -+err:
64003 -+ ha_autocommit_or_rollback(thd, error);
64004 -+ thd->tablespace_op=FALSE;
64005 -+
64006 -+ if (error == 0)
64007 -+ {
64008 -+ my_ok(thd);
64009 -+ DBUG_RETURN(0);
64010 -+ }
64011 -+
64012 -+ table->file->print_error(error, MYF(0));
64013 -+
64014 -+ DBUG_RETURN(-1);
64015 -+}
64016 -+
64017 -+/**
64018 -+ @brief Check if both DROP and CREATE are present for an index in ALTER TABLE
64019 -+
64020 -+ @details Checks if any index is being modified (present as both DROP INDEX
64021 -+ and ADD INDEX) in the current ALTER TABLE statement. Needed for disabling
64022 -+ online ALTER TABLE.
64023 -+
64024 -+ @param table The table being altered
64025 -+ @param alter_info The ALTER TABLE structure
64026 -+ @return presence of index being altered
64027 -+ @retval FALSE No such index
64028 -+ @retval TRUE Have at least 1 index modified
64029 -+*/
64030 -+
64031 -+static bool
64032 -+is_index_maintenance_unique (TABLE *table, Alter_info *alter_info)
64033 -+{
64034 -+ List_iterator<Key> key_it(alter_info->key_list);
64035 -+ List_iterator<Alter_drop> drop_it(alter_info->drop_list);
64036 -+ Key *key;
64037 -+
64038 -+ while ((key= key_it++))
64039 -+ {
64040 -+ if (key->name)
64041 -+ {
64042 -+ Alter_drop *drop;
64043 -+
64044 -+ drop_it.rewind();
64045 -+ while ((drop= drop_it++))
64046 -+ {
64047 -+ if (drop->type == Alter_drop::KEY &&
64048 -+ !my_strcasecmp(system_charset_info, key->name, drop->name))
64049 -+ return TRUE;
64050 -+ }
64051 -+ }
64052 -+ }
64053 -+ return FALSE;
64054 -+}
64055 -+
64056 -+
64057 -+/*
64058 -+ SYNOPSIS
64059 -+ compare_tables()
64060 -+ table The original table.
64061 -+ alter_info Alter options, fields and keys for the new
64062 -+ table.
64063 -+ create_info Create options for the new table.
64064 -+ order_num Number of order list elements.
64065 -+ need_copy_table OUT Result of the comparison. Undefined if error.
64066 -+ Otherwise is one of:
64067 -+ ALTER_TABLE_METADATA_ONLY No copy needed
64068 -+ ALTER_TABLE_DATA_CHANGED Data changes,
64069 -+ copy needed
64070 -+ ALTER_TABLE_INDEX_CHANGED Index changes,
64071 -+ copy might be needed
64072 -+ key_info_buffer OUT An array of KEY structs for new indexes
64073 -+ index_drop_buffer OUT An array of offsets into table->key_info.
64074 -+ index_drop_count OUT The number of elements in the array.
64075 -+ index_add_buffer OUT An array of offsets into key_info_buffer.
64076 -+ index_add_count OUT The number of elements in the array.
64077 -+ candidate_key_count OUT The number of candidate keys in original table.
64078 -+
64079 -+ DESCRIPTION
64080 -+ 'table' (first argument) contains information of the original
64081 -+ table, which includes all corresponding parts that the new
64082 -+ table has in arguments create_list, key_list and create_info.
64083 -+
64084 -+ By comparing the changes between the original and new table
64085 -+ we can determine how much it has changed after ALTER TABLE
64086 -+ and whether we need to make a copy of the table, or just change
64087 -+ the .frm file.
64088 -+
64089 -+ If there are no data changes, but index changes, 'index_drop_buffer'
64090 -+ and/or 'index_add_buffer' are populated with offsets into
64091 -+ table->key_info or key_info_buffer respectively for the indexes
64092 -+ that need to be dropped and/or (re-)created.
64093 -+
64094 -+ RETURN VALUES
64095 -+ TRUE error
64096 -+ FALSE success
64097 -+*/
64098 -+
64099 -+static
64100 -+bool
64101 -+compare_tables(TABLE *table,
64102 -+ Alter_info *alter_info,
64103 -+ HA_CREATE_INFO *create_info,
64104 -+ uint order_num,
64105 -+ enum_alter_table_change_level *need_copy_table,
64106 -+ KEY **key_info_buffer,
64107 -+ uint **index_drop_buffer, uint *index_drop_count,
64108 -+ uint **index_add_buffer, uint *index_add_count,
64109 -+ uint *candidate_key_count)
64110 -+{
64111 -+ Field **f_ptr, *field;
64112 -+ uint changes= 0, tmp;
64113 -+ uint key_count;
64114 -+ List_iterator_fast<Create_field> new_field_it, tmp_new_field_it;
64115 -+ Create_field *new_field, *tmp_new_field;
64116 -+ KEY_PART_INFO *key_part;
64117 -+ KEY_PART_INFO *end;
64118 -+ THD *thd= table->in_use;
64119 -+ /*
64120 -+ Remember if the new definition has new VARCHAR column;
64121 -+ create_info->varchar will be reset in mysql_prepare_create_table.
64122 -+ */
64123 -+ bool varchar= create_info->varchar;
64124 -+ bool not_nullable= true;
64125 -+ DBUG_ENTER("compare_tables");
64126 -+
64127 -+ /*
64128 -+ Create a copy of alter_info.
64129 -+ To compare the new and old table definitions, we need to "prepare"
64130 -+ the new definition - transform it from parser output to a format
64131 -+ that describes the final table layout (all column defaults are
64132 -+ initialized, duplicate columns are removed). This is done by
64133 -+ mysql_prepare_create_table. Unfortunately,
64134 -+ mysql_prepare_create_table performs its transformations
64135 -+ "in-place", that is, modifies the argument. Since we would
64136 -+ like to keep compare_tables() idempotent (not altering any
64137 -+ of the arguments) we create a copy of alter_info here and
64138 -+ pass it to mysql_prepare_create_table, then use the result
64139 -+ to evaluate possibility of fast ALTER TABLE, and then
64140 -+ destroy the copy.
64141 -+ */
64142 -+ Alter_info tmp_alter_info(*alter_info, thd->mem_root);
64143 -+ uint db_options= 0; /* not used */
64144 -+
64145 -+ /* Create the prepared information. */
64146 -+ if (mysql_prepare_create_table(thd, create_info,
64147 -+ &tmp_alter_info,
64148 -+ (table->s->tmp_table != NO_TMP_TABLE),
64149 -+ &db_options,
64150 -+ table->file, key_info_buffer,
64151 -+ &key_count, 0))
64152 -+ DBUG_RETURN(1);
64153 -+ /* Allocate result buffers. */
64154 -+ if (! (*index_drop_buffer=
64155 -+ (uint*) thd->alloc(sizeof(uint) * table->s->keys)) ||
64156 -+ ! (*index_add_buffer=
64157 -+ (uint*) thd->alloc(sizeof(uint) * tmp_alter_info.key_list.elements)))
64158 -+ DBUG_RETURN(1);
64159 -+
64160 -+ /*
64161 -+ Some very basic checks. If number of fields changes, or the
64162 -+ handler, we need to run full ALTER TABLE. In the future
64163 -+ new fields can be added and old dropped without copy, but
64164 -+ not yet.
64165 -+
64166 -+ Test also that engine was not given during ALTER TABLE, or
64167 -+ we are force to run regular alter table (copy).
64168 -+ E.g. ALTER TABLE tbl_name ENGINE=MyISAM.
64169 -+
64170 -+ For the following ones we also want to run regular alter table:
64171 -+ ALTER TABLE tbl_name ORDER BY ..
64172 -+ ALTER TABLE tbl_name CONVERT TO CHARACTER SET ..
64173 -+
64174 -+ At the moment we can't handle altering temporary tables without a copy.
64175 -+ We also test if OPTIMIZE TABLE was given and was mapped to alter table.
64176 -+ In that case we always do full copy.
64177 -+
64178 -+ There was a bug prior to mysql-4.0.25. Number of null fields was
64179 -+ calculated incorrectly. As a result frm and data files gets out of
64180 -+ sync after fast alter table. There is no way to determine by which
64181 -+ mysql version (in 4.0 and 4.1 branches) table was created, thus we
64182 -+ disable fast alter table for all tables created by mysql versions
64183 -+ prior to 5.0 branch.
64184 -+ See BUG#6236.
64185 -+ */
64186 -+ if (table->s->fields != alter_info->create_list.elements ||
64187 -+ table->s->db_type() != create_info->db_type ||
64188 -+ table->s->tmp_table ||
64189 -+ create_info->used_fields & HA_CREATE_USED_ENGINE ||
64190 -+ create_info->used_fields & HA_CREATE_USED_CHARSET ||
64191 -+ create_info->used_fields & HA_CREATE_USED_DEFAULT_CHARSET ||
64192 -+ (table->s->row_type != create_info->row_type) ||
64193 -+ create_info->used_fields & HA_CREATE_USED_PACK_KEYS ||
64194 -+ create_info->used_fields & HA_CREATE_USED_MAX_ROWS ||
64195 -+ (alter_info->flags & (ALTER_RECREATE | ALTER_FOREIGN_KEY)) ||
64196 -+ order_num ||
64197 -+ !table->s->mysql_version ||
64198 -+ (table->s->frm_version < FRM_VER_TRUE_VARCHAR && varchar))
64199 -+ {
64200 -+ *need_copy_table= ALTER_TABLE_DATA_CHANGED;
64201 -+ DBUG_RETURN(0);
64202 -+ }
64203 -+
64204 -+ /*
64205 -+ Use transformed info to evaluate possibility of fast ALTER TABLE
64206 -+ but use the preserved field to persist modifications.
64207 -+ */
64208 -+ new_field_it.init(alter_info->create_list);
64209 -+ tmp_new_field_it.init(tmp_alter_info.create_list);
64210 -+
64211 -+ /*
64212 -+ Go through fields and check if the original ones are compatible
64213 -+ with new table.
64214 -+ */
64215 -+ for (f_ptr= table->field, new_field= new_field_it++,
64216 -+ tmp_new_field= tmp_new_field_it++;
64217 -+ (field= *f_ptr);
64218 -+ f_ptr++, new_field= new_field_it++,
64219 -+ tmp_new_field= tmp_new_field_it++)
64220 -+ {
64221 -+ /* Make sure we have at least the default charset in use. */
64222 -+ if (!new_field->charset)
64223 -+ new_field->charset= create_info->default_table_charset;
64224 -+
64225 -+ /* Check that NULL behavior is same for old and new fields */
64226 -+ if ((tmp_new_field->flags & NOT_NULL_FLAG) !=
64227 -+ (uint) (field->flags & NOT_NULL_FLAG))
64228 -+ {
64229 -+ *need_copy_table= ALTER_TABLE_DATA_CHANGED;
64230 -+ DBUG_RETURN(0);
64231 -+ }
64232 -+
64233 -+ /* Don't pack rows in old tables if the user has requested this. */
64234 -+ if (create_info->row_type == ROW_TYPE_DYNAMIC ||
64235 -+ (tmp_new_field->flags & BLOB_FLAG) ||
64236 -+ (tmp_new_field->sql_type == MYSQL_TYPE_VARCHAR &&
64237 -+ create_info->row_type != ROW_TYPE_FIXED))
64238 -+ create_info->table_options|= HA_OPTION_PACK_RECORD;
64239 -+
64240 -+ /* Check if field was renamed */
64241 -+ field->flags&= ~FIELD_IS_RENAMED;
64242 -+ if (my_strcasecmp(system_charset_info,
64243 -+ field->field_name,
64244 -+ tmp_new_field->field_name))
64245 -+ field->flags|= FIELD_IS_RENAMED;
64246 -+
64247 -+ /* Evaluate changes bitmap and send to check_if_incompatible_data() */
64248 -+ if (!(tmp= field->is_equal(tmp_new_field)))
64249 -+ {
64250 -+ *need_copy_table= ALTER_TABLE_DATA_CHANGED;
64251 -+ DBUG_RETURN(0);
64252 -+ }
64253 -+ // Clear indexed marker
64254 -+ field->flags&= ~FIELD_IN_ADD_INDEX;
64255 -+ changes|= tmp;
64256 -+ }
64257 -+
64258 -+ /*
64259 -+ Go through keys and check if the original ones are compatible
64260 -+ with new table.
64261 -+ */
64262 -+ KEY *table_key;
64263 -+ KEY *table_key_end= table->key_info + table->s->keys;
64264 -+ KEY *new_key;
64265 -+ KEY *new_key_end= *key_info_buffer + key_count;
64266 -+
64267 -+ DBUG_PRINT("info", ("index count old: %d new: %d",
64268 -+ table->s->keys, key_count));
64269 -+ /*
64270 -+ Step through all keys of the old table and search matching new keys.
64271 -+ */
64272 -+ *index_drop_count= 0;
64273 -+ *index_add_count= 0;
64274 -+ *candidate_key_count= 0;
64275 -+ for (table_key= table->key_info; table_key < table_key_end; table_key++)
64276 -+ {
64277 -+ KEY_PART_INFO *table_part;
64278 -+ KEY_PART_INFO *table_part_end= table_key->key_part + table_key->key_parts;
64279 -+ KEY_PART_INFO *new_part;
64280 -+
64281 -+ /*
64282 -+ Check if key is a candidate key, i.e. a unique index with no index
64283 -+ fields nullable, then key is either already primary key or could
64284 -+ be promoted to primary key if the original primary key is dropped.
64285 -+ Count all candidate keys.
64286 -+ */
64287 -+ not_nullable= true;
64288 -+ for (table_part= table_key->key_part;
64289 -+ table_part < table_part_end;
64290 -+ table_part++)
64291 -+ {
64292 -+ not_nullable= not_nullable && (! table_part->field->maybe_null());
64293 -+ }
64294 -+ if ((table_key->flags & HA_NOSAME) && not_nullable)
64295 -+ (*candidate_key_count)++;
64296 -+
64297 -+ /* Search a new key with the same name. */
64298 -+ for (new_key= *key_info_buffer; new_key < new_key_end; new_key++)
64299 -+ {
64300 -+ if (! strcmp(table_key->name, new_key->name))
64301 -+ break;
64302 -+ }
64303 -+ if (new_key >= new_key_end)
64304 -+ {
64305 -+ /* Key not found. Add the offset of the key to the drop buffer. */
64306 -+ (*index_drop_buffer)[(*index_drop_count)++]= table_key - table->key_info;
64307 -+ DBUG_PRINT("info", ("index dropped: '%s'", table_key->name));
64308 -+ continue;
64309 -+ }
64310 -+
64311 -+ /* Check that the key types are compatible between old and new tables. */
64312 -+ if ((table_key->algorithm != new_key->algorithm) ||
64313 -+ ((table_key->flags & HA_KEYFLAG_MASK) !=
64314 -+ (new_key->flags & HA_KEYFLAG_MASK)) ||
64315 -+ (table_key->key_parts != new_key->key_parts))
64316 -+ goto index_changed;
64317 -+
64318 -+ /*
64319 -+ Check that the key parts remain compatible between the old and
64320 -+ new tables.
64321 -+ */
64322 -+ for (table_part= table_key->key_part, new_part= new_key->key_part;
64323 -+ table_part < table_part_end;
64324 -+ table_part++, new_part++)
64325 -+ {
64326 -+ /*
64327 -+ Key definition has changed if we are using a different field or
64328 -+ if the used key part length is different. We know that the fields
64329 -+ did not change. Comparing field numbers is sufficient.
64330 -+ */
64331 -+ if ((table_part->length != new_part->length) ||
64332 -+ (table_part->fieldnr - 1 != new_part->fieldnr))
64333 -+ goto index_changed;
64334 -+ }
64335 -+ continue;
64336 -+
64337 -+ index_changed:
64338 -+ /* Key modified. Add the offset of the key to both buffers. */
64339 -+ (*index_drop_buffer)[(*index_drop_count)++]= table_key - table->key_info;
64340 -+ (*index_add_buffer)[(*index_add_count)++]= new_key - *key_info_buffer;
64341 -+ key_part= new_key->key_part;
64342 -+ end= key_part + new_key->key_parts;
64343 -+ for(; key_part != end; key_part++)
64344 -+ {
64345 -+ // Mark field to be part of new key
64346 -+ field= table->field[key_part->fieldnr];
64347 -+ field->flags|= FIELD_IN_ADD_INDEX;
64348 -+ }
64349 -+ DBUG_PRINT("info", ("index changed: '%s'", table_key->name));
64350 -+ }
64351 -+ /*end of for (; table_key < table_key_end;) */
64352 -+
64353 -+ /*
64354 -+ Step through all keys of the new table and find matching old keys.
64355 -+ */
64356 -+ for (new_key= *key_info_buffer; new_key < new_key_end; new_key++)
64357 -+ {
64358 -+ /* Search an old key with the same name. */
64359 -+ for (table_key= table->key_info; table_key < table_key_end; table_key++)
64360 -+ {
64361 -+ if (! strcmp(table_key->name, new_key->name))
64362 -+ break;
64363 -+ }
64364 -+ if (table_key >= table_key_end)
64365 -+ {
64366 -+ /* Key not found. Add the offset of the key to the add buffer. */
64367 -+ (*index_add_buffer)[(*index_add_count)++]= new_key - *key_info_buffer;
64368 -+ key_part= new_key->key_part;
64369 -+ end= key_part + new_key->key_parts;
64370 -+ for(; key_part != end; key_part++)
64371 -+ {
64372 -+ // Mark field to be part of new key
64373 -+ field= table->field[key_part->fieldnr];
64374 -+ field->flags|= FIELD_IN_ADD_INDEX;
64375 -+ }
64376 -+ DBUG_PRINT("info", ("index added: '%s'", new_key->name));
64377 -+ }
64378 -+ }
64379 -+
64380 -+ /* Check if changes are compatible with current handler without a copy */
64381 -+ if (table->file->check_if_incompatible_data(create_info, changes))
64382 -+ {
64383 -+ *need_copy_table= ALTER_TABLE_DATA_CHANGED;
64384 -+ DBUG_RETURN(0);
64385 -+ }
64386 -+
64387 -+ if (*index_drop_count || *index_add_count)
64388 -+ {
64389 -+ *need_copy_table= ALTER_TABLE_INDEX_CHANGED;
64390 -+ DBUG_RETURN(0);
64391 -+ }
64392 -+
64393 -+ *need_copy_table= ALTER_TABLE_METADATA_ONLY; // Tables are compatible
64394 -+ DBUG_RETURN(0);
64395 -+}
64396 -+
64397 -+
64398 -+/*
64399 -+ Manages enabling/disabling of indexes for ALTER TABLE
64400 -+
64401 -+ SYNOPSIS
64402 -+ alter_table_manage_keys()
64403 -+ table Target table
64404 -+ indexes_were_disabled Whether the indexes of the from table
64405 -+ were disabled
64406 -+ keys_onoff ENABLE | DISABLE | LEAVE_AS_IS
64407 -+
64408 -+ RETURN VALUES
64409 -+ FALSE OK
64410 -+ TRUE Error
64411 -+*/
64412 -+
64413 -+static
64414 -+bool alter_table_manage_keys(TABLE *table, int indexes_were_disabled,
64415 -+ enum enum_enable_or_disable keys_onoff)
64416 -+{
64417 -+ int error= 0;
64418 -+ DBUG_ENTER("alter_table_manage_keys");
64419 -+ DBUG_PRINT("enter", ("table=%p were_disabled=%d on_off=%d",
64420 -+ table, indexes_were_disabled, keys_onoff));
64421 -+
64422 -+ switch (keys_onoff) {
64423 -+ case ENABLE:
64424 -+ error= table->file->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
64425 -+ break;
64426 -+ case LEAVE_AS_IS:
64427 -+ if (!indexes_were_disabled)
64428 -+ break;
64429 -+ /* fall-through: disabled indexes */
64430 -+ case DISABLE:
64431 -+ error= table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
64432 -+ }
64433 -+
64434 -+ if (error == HA_ERR_WRONG_COMMAND)
64435 -+ {
64436 -+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
64437 -+ ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
64438 -+ table->s->table_name.str);
64439 -+ error= 0;
64440 -+ } else if (error)
64441 -+ table->file->print_error(error, MYF(0));
64442 -+
64443 -+ DBUG_RETURN(error);
64444 -+}
64445 -+
64446 -+
64447 -+/**
64448 -+ Prepare column and key definitions for CREATE TABLE in ALTER TABLE.
64449 -+
64450 -+ This function transforms parse output of ALTER TABLE - lists of
64451 -+ columns and keys to add, drop or modify into, essentially,
64452 -+ CREATE TABLE definition - a list of columns and keys of the new
64453 -+ table. While doing so, it also performs some (bug not all)
64454 -+ semantic checks.
64455 -+
64456 -+ This function is invoked when we know that we're going to
64457 -+ perform ALTER TABLE via a temporary table -- i.e. fast ALTER TABLE
64458 -+ is not possible, perhaps because the ALTER statement contains
64459 -+ instructions that require change in table data, not only in
64460 -+ table definition or indexes.
64461 -+
64462 -+ @param[in,out] thd thread handle. Used as a memory pool
64463 -+ and source of environment information.
64464 -+ @param[in] table the source table, open and locked
64465 -+ Used as an interface to the storage engine
64466 -+ to acquire additional information about
64467 -+ the original table.
64468 -+ @param[in,out] create_info A blob with CREATE/ALTER TABLE
64469 -+ parameters
64470 -+ @param[in,out] alter_info Another blob with ALTER/CREATE parameters.
64471 -+ Originally create_info was used only in
64472 -+ CREATE TABLE and alter_info only in ALTER TABLE.
64473 -+ But since ALTER might end-up doing CREATE,
64474 -+ this distinction is gone and we just carry
64475 -+ around two structures.
64476 -+
64477 -+ @return
64478 -+ Fills various create_info members based on information retrieved
64479 -+ from the storage engine.
64480 -+ Sets create_info->varchar if the table has a VARCHAR column.
64481 -+ Prepares alter_info->create_list and alter_info->key_list with
64482 -+ columns and keys of the new table.
64483 -+ @retval TRUE error, out of memory or a semantical error in ALTER
64484 -+ TABLE instructions
64485 -+ @retval FALSE success
64486 -+*/
64487 -+
64488 -+static bool
64489 -+mysql_prepare_alter_table(THD *thd, TABLE *table,
64490 -+ HA_CREATE_INFO *create_info,
64491 -+ Alter_info *alter_info)
64492 -+{
64493 -+ /* New column definitions are added here */
64494 -+ List<Create_field> new_create_list;
64495 -+ /* New key definitions are added here */
64496 -+ List<Key> new_key_list;
64497 -+ List_iterator<Alter_drop> drop_it(alter_info->drop_list);
64498 -+ List_iterator<Create_field> def_it(alter_info->create_list);
64499 -+ List_iterator<Alter_column> alter_it(alter_info->alter_list);
64500 -+ List_iterator<Key> key_it(alter_info->key_list);
64501 -+ List_iterator<Create_field> find_it(new_create_list);
64502 -+ List_iterator<Create_field> field_it(new_create_list);
64503 -+ List<Key_part_spec> key_parts;
64504 -+ uint db_create_options= (table->s->db_create_options
64505 -+ & ~(HA_OPTION_PACK_RECORD));
64506 -+ uint used_fields= create_info->used_fields;
64507 -+ KEY *key_info=table->key_info;
64508 -+ bool rc= TRUE;
64509 -+
64510 -+ DBUG_ENTER("mysql_prepare_alter_table");
64511 -+
64512 -+ create_info->varchar= FALSE;
64513 -+ /* Let new create options override the old ones */
64514 -+ if (!(used_fields & HA_CREATE_USED_MIN_ROWS))
64515 -+ create_info->min_rows= table->s->min_rows;
64516 -+ if (!(used_fields & HA_CREATE_USED_MAX_ROWS))
64517 -+ create_info->max_rows= table->s->max_rows;
64518 -+ if (!(used_fields & HA_CREATE_USED_AVG_ROW_LENGTH))
64519 -+ create_info->avg_row_length= table->s->avg_row_length;
64520 -+ if (!(used_fields & HA_CREATE_USED_DEFAULT_CHARSET))
64521 -+ create_info->default_table_charset= table->s->table_charset;
64522 -+ if (!(used_fields & HA_CREATE_USED_AUTO) && table->found_next_number_field)
64523 -+ {
64524 -+ /* Table has an autoincrement, copy value to new table */
64525 -+ table->file->info(HA_STATUS_AUTO);
64526 -+ create_info->auto_increment_value= table->file->stats.auto_increment_value;
64527 -+ }
64528 -+ if (!(used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE))
64529 -+ create_info->key_block_size= table->s->key_block_size;
64530 -+
64531 -+ if (!create_info->tablespace && create_info->storage_media != HA_SM_MEMORY)
64532 -+ {
64533 -+ char *tablespace= static_cast<char *>(thd->alloc(FN_LEN + 1));
64534 -+ /*
64535 -+ Regular alter table of disk stored table (no tablespace/storage change)
64536 -+ Copy tablespace name
64537 -+ */
64538 -+ if (tablespace &&
64539 -+ (table->file->get_tablespace_name(thd, tablespace, FN_LEN)))
64540 -+ create_info->tablespace= tablespace;
64541 -+ }
64542 -+ restore_record(table, s->default_values); // Empty record for DEFAULT
64543 -+ Create_field *def;
64544 -+
64545 -+ /*
64546 -+ First collect all fields from table which isn't in drop_list
64547 -+ */
64548 -+ Field **f_ptr,*field;
64549 -+ for (f_ptr=table->field ; (field= *f_ptr) ; f_ptr++)
64550 -+ {
64551 -+ if (field->type() == MYSQL_TYPE_STRING)
64552 -+ create_info->varchar= TRUE;
64553 -+ /* Check if field should be dropped */
64554 -+ Alter_drop *drop;
64555 -+ drop_it.rewind();
64556 -+ while ((drop=drop_it++))
64557 -+ {
64558 -+ if (drop->type == Alter_drop::COLUMN &&
64559 -+ !my_strcasecmp(system_charset_info,field->field_name, drop->name))
64560 -+ {
64561 -+ /* Reset auto_increment value if it was dropped */
64562 -+ if (MTYP_TYPENR(field->unireg_check) == Field::NEXT_NUMBER &&
64563 -+ !(used_fields & HA_CREATE_USED_AUTO))
64564 -+ {
64565 -+ create_info->auto_increment_value=0;
64566 -+ create_info->used_fields|=HA_CREATE_USED_AUTO;
64567 -+ }
64568 -+ break;
64569 -+ }
64570 -+ }
64571 -+ if (drop)
64572 -+ {
64573 -+ drop_it.remove();
64574 -+ continue;
64575 -+ }
64576 -+ /* Check if field is changed */
64577 -+ def_it.rewind();
64578 -+ while ((def=def_it++))
64579 -+ {
64580 -+ if (def->change &&
64581 -+ !my_strcasecmp(system_charset_info,field->field_name, def->change))
64582 -+ break;
64583 -+ }
64584 -+ if (def)
64585 -+ { // Field is changed
64586 -+ def->field=field;
64587 -+ if (!def->after)
64588 -+ {
64589 -+ new_create_list.push_back(def);
64590 -+ def_it.remove();
64591 -+ }
64592 -+ }
64593 -+ else
64594 -+ {
64595 -+ /*
64596 -+ This field was not dropped and not changed, add it to the list
64597 -+ for the new table.
64598 -+ */
64599 -+ def= new Create_field(field, field);
64600 -+ new_create_list.push_back(def);
64601 -+ alter_it.rewind(); // Change default if ALTER
64602 -+ Alter_column *alter;
64603 -+ while ((alter=alter_it++))
64604 -+ {
64605 -+ if (!my_strcasecmp(system_charset_info,field->field_name, alter->name))
64606 -+ break;
64607 -+ }
64608 -+ if (alter)
64609 -+ {
64610 -+ if (def->sql_type == MYSQL_TYPE_BLOB)
64611 -+ {
64612 -+ my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), def->change);
64613 -+ goto err;
64614 -+ }
64615 -+ if ((def->def=alter->def)) // Use new default
64616 -+ def->flags&= ~NO_DEFAULT_VALUE_FLAG;
64617 -+ else
64618 -+ def->flags|= NO_DEFAULT_VALUE_FLAG;
64619 -+ alter_it.remove();
64620 -+ }
64621 -+ }
64622 -+ }
64623 -+ def_it.rewind();
64624 -+ while ((def=def_it++)) // Add new columns
64625 -+ {
64626 -+ if (def->change && ! def->field)
64627 -+ {
64628 -+ my_error(ER_BAD_FIELD_ERROR, MYF(0), def->change, table->s->table_name.str);
64629 -+ goto err;
64630 -+ }
64631 -+ /*
64632 -+ Check that the DATE/DATETIME not null field we are going to add is
64633 -+ either has a default value or the '0000-00-00' is allowed by the
64634 -+ set sql mode.
64635 -+ If the '0000-00-00' value isn't allowed then raise the error_if_not_empty
64636 -+ flag to allow ALTER TABLE only if the table to be altered is empty.
64637 -+ */
64638 -+ if ((def->sql_type == MYSQL_TYPE_DATE ||
64639 -+ def->sql_type == MYSQL_TYPE_NEWDATE ||
64640 -+ def->sql_type == MYSQL_TYPE_DATETIME) &&
64641 -+ !alter_info->datetime_field &&
64642 -+ !(~def->flags & (NO_DEFAULT_VALUE_FLAG | NOT_NULL_FLAG)) &&
64643 -+ thd->variables.sql_mode & MODE_NO_ZERO_DATE)
64644 -+ {
64645 -+ alter_info->datetime_field= def;
64646 -+ alter_info->error_if_not_empty= TRUE;
64647 -+ }
64648 -+ if (!def->after)
64649 -+ new_create_list.push_back(def);
64650 -+ else if (def->after == first_keyword)
64651 -+ new_create_list.push_front(def);
64652 -+ else
64653 -+ {
64654 -+ Create_field *find;
64655 -+ find_it.rewind();
64656 -+ while ((find=find_it++)) // Add new columns
64657 -+ {
64658 -+ if (!my_strcasecmp(system_charset_info,def->after, find->field_name))
64659 -+ break;
64660 -+ }
64661 -+ if (!find)
64662 -+ {
64663 -+ my_error(ER_BAD_FIELD_ERROR, MYF(0), def->after, table->s->table_name.str);
64664 -+ goto err;
64665 -+ }
64666 -+ find_it.after(def); // Put element after this
64667 -+ alter_info->change_level= ALTER_TABLE_DATA_CHANGED;
64668 -+ }
64669 -+ }
64670 -+ if (alter_info->alter_list.elements)
64671 -+ {
64672 -+ my_error(ER_BAD_FIELD_ERROR, MYF(0),
64673 -+ alter_info->alter_list.head()->name, table->s->table_name.str);
64674 -+ goto err;
64675 -+ }
64676 -+ if (!new_create_list.elements)
64677 -+ {
64678 -+ my_message(ER_CANT_REMOVE_ALL_FIELDS, ER(ER_CANT_REMOVE_ALL_FIELDS),
64679 -+ MYF(0));
64680 -+ goto err;
64681 -+ }
64682 -+
64683 -+ /*
64684 -+ Collect all keys which isn't in drop list. Add only those
64685 -+ for which some fields exists.
64686 -+ */
64687 -+
64688 -+ for (uint i=0 ; i < table->s->keys ; i++,key_info++)
64689 -+ {
64690 -+ char *key_name= key_info->name;
64691 -+ Alter_drop *drop;
64692 -+ drop_it.rewind();
64693 -+ while ((drop=drop_it++))
64694 -+ {
64695 -+ if (drop->type == Alter_drop::KEY &&
64696 -+ !my_strcasecmp(system_charset_info,key_name, drop->name))
64697 -+ break;
64698 -+ }
64699 -+ if (drop)
64700 -+ {
64701 -+ drop_it.remove();
64702 -+ continue;
64703 -+ }
64704 -+
64705 -+ KEY_PART_INFO *key_part= key_info->key_part;
64706 -+ key_parts.empty();
64707 -+ for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
64708 -+ {
64709 -+ if (!key_part->field)
64710 -+ continue; // Wrong field (from UNIREG)
64711 -+ const char *key_part_name=key_part->field->field_name;
64712 -+ Create_field *cfield;
64713 -+ field_it.rewind();
64714 -+ while ((cfield=field_it++))
64715 -+ {
64716 -+ if (cfield->change)
64717 -+ {
64718 -+ if (!my_strcasecmp(system_charset_info, key_part_name,
64719 -+ cfield->change))
64720 -+ break;
64721 -+ }
64722 -+ else if (!my_strcasecmp(system_charset_info,
64723 -+ key_part_name, cfield->field_name))
64724 -+ break;
64725 -+ }
64726 -+ if (!cfield)
64727 -+ continue; // Field is removed
64728 -+ uint key_part_length=key_part->length;
64729 -+ if (cfield->field) // Not new field
64730 -+ {
64731 -+ /*
64732 -+ If the field can't have only a part used in a key according to its
64733 -+ new type, or should not be used partially according to its
64734 -+ previous type, or the field length is less than the key part
64735 -+ length, unset the key part length.
64736 -+
64737 -+ We also unset the key part length if it is the same as the
64738 -+ old field's length, so the whole new field will be used.
64739 -+
64740 -+ BLOBs may have cfield->length == 0, which is why we test it before
64741 -+ checking whether cfield->length < key_part_length (in chars).
64742 -+ */
64743 -+ if (!Field::type_can_have_key_part(cfield->field->type()) ||
64744 -+ !Field::type_can_have_key_part(cfield->sql_type) ||
64745 -+ /* spatial keys can't have sub-key length */
64746 -+ (key_info->flags & HA_SPATIAL) ||
64747 -+ (cfield->field->field_length == key_part_length &&
64748 -+ !f_is_blob(key_part->key_type)) ||
64749 -+ (cfield->length && (cfield->length < key_part_length /
64750 -+ key_part->field->charset()->mbmaxlen)))
64751 -+ key_part_length= 0; // Use whole field
64752 -+ }
64753 -+ key_part_length /= key_part->field->charset()->mbmaxlen;
64754 -+ key_parts.push_back(new Key_part_spec(cfield->field_name,
64755 -+ key_part_length));
64756 -+ }
64757 -+ if (key_parts.elements)
64758 -+ {
64759 -+ KEY_CREATE_INFO key_create_info;
64760 -+ Key *key;
64761 -+ enum Key::Keytype key_type;
64762 -+ bzero((char*) &key_create_info, sizeof(key_create_info));
64763 -+
64764 -+ key_create_info.algorithm= key_info->algorithm;
64765 -+ if (key_info->flags & HA_USES_BLOCK_SIZE)
64766 -+ key_create_info.block_size= key_info->block_size;
64767 -+ if (key_info->flags & HA_USES_PARSER)
64768 -+ key_create_info.parser_name= *plugin_name(key_info->parser);
64769 -+
64770 -+ if (key_info->flags & HA_SPATIAL)
64771 -+ key_type= Key::SPATIAL;
64772 -+ else if (key_info->flags & HA_NOSAME)
64773 -+ {
64774 -+ if (! my_strcasecmp(system_charset_info, key_name, primary_key_name))
64775 -+ key_type= Key::PRIMARY;
64776 -+ else
64777 -+ key_type= Key::UNIQUE;
64778 -+ }
64779 -+ else if (key_info->flags & HA_FULLTEXT)
64780 -+ key_type= Key::FULLTEXT;
64781 -+ else
64782 -+ key_type= Key::MULTIPLE;
64783 -+
64784 -+ key= new Key(key_type, key_name,
64785 -+ &key_create_info,
64786 -+ test(key_info->flags & HA_GENERATED_KEY),
64787 -+ key_parts);
64788 -+ new_key_list.push_back(key);
64789 -+ }
64790 -+ }
64791 -+ {
64792 -+ Key *key;
64793 -+ while ((key=key_it++)) // Add new keys
64794 -+ {
64795 -+ if (key->type != Key::FOREIGN_KEY)
64796 -+ new_key_list.push_back(key);
64797 -+ if (key->name &&
64798 -+ !my_strcasecmp(system_charset_info,key->name,primary_key_name))
64799 -+ {
64800 -+ my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name);
64801 -+ goto err;
64802 -+ }
64803 -+ }
64804 -+ }
64805 -+
64806 -+ if (alter_info->drop_list.elements)
64807 -+ {
64808 -+ my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0),
64809 -+ alter_info->drop_list.head()->name);
64810 -+ goto err;
64811 -+ }
64812 -+ if (alter_info->alter_list.elements)
64813 -+ {
64814 -+ my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0),
64815 -+ alter_info->alter_list.head()->name);
64816 -+ goto err;
64817 -+ }
64818 -+
64819 -+ if (!create_info->comment.str)
64820 -+ {
64821 -+ create_info->comment.str= table->s->comment.str;
64822 -+ create_info->comment.length= table->s->comment.length;
64823 -+ }
64824 -+
64825 -+ table->file->update_create_info(create_info);
64826 -+ if ((create_info->table_options &
64827 -+ (HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS)) ||
64828 -+ (used_fields & HA_CREATE_USED_PACK_KEYS))
64829 -+ db_create_options&= ~(HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS);
64830 -+ if (create_info->table_options &
64831 -+ (HA_OPTION_CHECKSUM | HA_OPTION_NO_CHECKSUM))
64832 -+ db_create_options&= ~(HA_OPTION_CHECKSUM | HA_OPTION_NO_CHECKSUM);
64833 -+ if (create_info->table_options &
64834 -+ (HA_OPTION_DELAY_KEY_WRITE | HA_OPTION_NO_DELAY_KEY_WRITE))
64835 -+ db_create_options&= ~(HA_OPTION_DELAY_KEY_WRITE |
64836 -+ HA_OPTION_NO_DELAY_KEY_WRITE);
64837 -+ create_info->table_options|= db_create_options;
64838 -+
64839 -+ if (table->s->tmp_table)
64840 -+ create_info->options|=HA_LEX_CREATE_TMP_TABLE;
64841 -+
64842 -+ rc= FALSE;
64843 -+ alter_info->create_list.swap(new_create_list);
64844 -+ alter_info->key_list.swap(new_key_list);
64845 -+err:
64846 -+ DBUG_RETURN(rc);
64847 -+}
64848 -+
64849 -+
64850 -+/*
64851 -+ Alter table
64852 -+
64853 -+ SYNOPSIS
64854 -+ mysql_alter_table()
64855 -+ thd Thread handle
64856 -+ new_db If there is a RENAME clause
64857 -+ new_name If there is a RENAME clause
64858 -+ create_info Information from the parsing phase about new
64859 -+ table properties.
64860 -+ table_list The table to change.
64861 -+ alter_info Lists of fields, keys to be changed, added
64862 -+ or dropped.
64863 -+ order_num How many ORDER BY fields has been specified.
64864 -+ order List of fields to ORDER BY.
64865 -+ ignore Whether we have ALTER IGNORE TABLE
64866 -+
64867 -+ DESCRIPTION
64868 -+ This is a veery long function and is everything but the kitchen sink :)
64869 -+ It is used to alter a table and not only by ALTER TABLE but also
64870 -+ CREATE|DROP INDEX are mapped on this function.
64871 -+
64872 -+ When the ALTER TABLE statement just does a RENAME or ENABLE|DISABLE KEYS,
64873 -+ or both, then this function short cuts its operation by renaming
64874 -+ the table and/or enabling/disabling the keys. In this case, the FRM is
64875 -+ not changed, directly by mysql_alter_table. However, if there is a
64876 -+ RENAME + change of a field, or an index, the short cut is not used.
64877 -+ See how `create_list` is used to generate the new FRM regarding the
64878 -+ structure of the fields. The same is done for the indices of the table.
64879 -+
64880 -+ Important is the fact, that this function tries to do as little work as
64881 -+ possible, by finding out whether a intermediate table is needed to copy
64882 -+ data into and when finishing the altering to use it as the original table.
64883 -+ For this reason the function compare_tables() is called, which decides
64884 -+ based on all kind of data how similar are the new and the original
64885 -+ tables.
64886 -+
64887 -+ RETURN VALUES
64888 -+ FALSE OK
64889 -+ TRUE Error
64890 -+*/
64891 -+
64892 -+bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
64893 -+ HA_CREATE_INFO *create_info,
64894 -+ TABLE_LIST *table_list,
64895 -+ Alter_info *alter_info,
64896 -+ uint order_num, ORDER *order, bool ignore)
64897 -+{
64898 -+ TABLE *table, *new_table= 0, *name_lock= 0;
64899 -+ int error= 0;
64900 -+ char tmp_name[80],old_name[32],new_name_buff[FN_REFLEN + 1];
64901 -+ char new_alias_buff[FN_REFLEN], *table_name, *db, *new_alias, *alias;
64902 -+ char index_file[FN_REFLEN], data_file[FN_REFLEN];
64903 -+ char path[FN_REFLEN + 1];
64904 -+ char reg_path[FN_REFLEN+1];
64905 -+ ha_rows copied,deleted;
64906 -+ handlerton *old_db_type, *new_db_type, *save_old_db_type;
64907 -+ legacy_db_type table_type;
64908 -+ frm_type_enum frm_type;
64909 -+ enum_alter_table_change_level need_copy_table= ALTER_TABLE_METADATA_ONLY;
64910 -+#ifdef WITH_PARTITION_STORAGE_ENGINE
64911 -+ uint fast_alter_partition= 0;
64912 -+ bool partition_changed= FALSE;
64913 -+#endif
64914 -+ bool need_lock_for_indexes= TRUE;
64915 -+ KEY *key_info_buffer;
64916 -+ uint index_drop_count= 0;
64917 -+ uint *index_drop_buffer= NULL;
64918 -+ uint index_add_count= 0;
64919 -+ uint *index_add_buffer= NULL;
64920 -+ uint candidate_key_count= 0;
64921 -+ bool no_pk;
64922 -+ DBUG_ENTER("mysql_alter_table");
64923 -+
64924 -+ /*
64925 -+ Check if we attempt to alter mysql.slow_log or
64926 -+ mysql.general_log table and return an error if
64927 -+ it is the case.
64928 -+ TODO: this design is obsolete and will be removed.
64929 -+ */
64930 -+ if (table_list && table_list->db && table_list->table_name)
64931 -+ {
64932 -+ int table_kind= 0;
64933 -+
64934 -+ table_kind= check_if_log_table(table_list->db_length, table_list->db,
64935 -+ table_list->table_name_length,
64936 -+ table_list->table_name, 0);
64937 -+
64938 -+ if (table_kind)
64939 -+ {
64940 -+ /* Disable alter of enabled log tables */
64941 -+ if (logger.is_log_table_enabled(table_kind))
64942 -+ {
64943 -+ my_error(ER_BAD_LOG_STATEMENT, MYF(0), "ALTER");
64944 -+ DBUG_RETURN(TRUE);
64945 -+ }
64946 -+
64947 -+ /* Disable alter of log tables to unsupported engine */
64948 -+ if ((create_info->used_fields & HA_CREATE_USED_ENGINE) &&
64949 -+ (!create_info->db_type || /* unknown engine */
64950 -+ !(create_info->db_type->flags & HTON_SUPPORT_LOG_TABLES)))
64951 -+ {
64952 -+ my_error(ER_UNSUPORTED_LOG_ENGINE, MYF(0));
64953 -+ DBUG_RETURN(TRUE);
64954 -+ }
64955 -+
64956 -+#ifdef WITH_PARTITION_STORAGE_ENGINE
64957 -+ if (alter_info->flags & ALTER_PARTITION)
64958 -+ {
64959 -+ my_error(ER_WRONG_USAGE, MYF(0), "PARTITION", "log table");
64960 -+ DBUG_RETURN(TRUE);
64961 -+ }
64962 -+#endif
64963 -+ }
64964 -+ }
64965 -+
64966 -+ /*
64967 -+ Assign variables table_name, new_name, db, new_db, path, reg_path
64968 -+ to simplify further comparisions: we want to see if it's a RENAME
64969 -+ later just by comparing the pointers, avoiding the need for strcmp.
64970 -+ */
64971 -+ thd_proc_info(thd, "init");
64972 -+ table_name=table_list->table_name;
64973 -+ alias= (lower_case_table_names == 2) ? table_list->alias : table_name;
64974 -+ db=table_list->db;
64975 -+ if (!new_db || !my_strcasecmp(table_alias_charset, new_db, db))
64976 -+ new_db= db;
64977 -+ build_table_filename(reg_path, sizeof(reg_path) - 1, db, table_name, reg_ext, 0);
64978 -+ build_table_filename(path, sizeof(path) - 1, db, table_name, "", 0);
64979 -+
64980 -+ mysql_ha_rm_tables(thd, table_list, FALSE);
64981 -+
64982 -+ /* DISCARD/IMPORT TABLESPACE is always alone in an ALTER TABLE */
64983 -+ if (alter_info->tablespace_op != NO_TABLESPACE_OP)
64984 -+ /* Conditionally writes to binlog. */
64985 -+ DBUG_RETURN(mysql_discard_or_import_tablespace(thd,table_list,
64986 -+ alter_info->tablespace_op));
64987 -+ strxnmov(new_name_buff, sizeof (new_name_buff) - 1, mysql_data_home, "/", db,
64988 -+ "/", table_name, reg_ext, NullS);
64989 -+ (void) unpack_filename(new_name_buff, new_name_buff);
64990 -+ /*
64991 -+ If this is just a rename of a view, short cut to the
64992 -+ following scenario: 1) lock LOCK_open 2) do a RENAME
64993 -+ 2) unlock LOCK_open.
64994 -+ This is a copy-paste added to make sure
64995 -+ ALTER (sic:) TABLE .. RENAME works for views. ALTER VIEW is handled
64996 -+ as an independent branch in mysql_execute_command. The need
64997 -+ for a copy-paste arose because the main code flow of ALTER TABLE
64998 -+ ... RENAME tries to use open_ltable, which does not work for views
64999 -+ (open_ltable was never modified to merge table lists of child tables
65000 -+ into the main table list, like open_tables does).
65001 -+ This code is wrong and will be removed, please do not copy.
65002 -+ */
65003 -+ frm_type= mysql_frm_type(thd, new_name_buff, &table_type);
65004 -+ /* Rename a view */
65005 -+ /* Sic: there is a race here */
65006 -+ if (frm_type == FRMTYPE_VIEW && !(alter_info->flags & ~ALTER_RENAME))
65007 -+ {
65008 -+ /*
65009 -+ The following branch handles "ALTER VIEW v1 /no arguments/;"
65010 -+ This feature is not documented one.
65011 -+ However, before "OPTIMIZE TABLE t1;" was implemented,
65012 -+ ALTER TABLE with no alter_specifications was used to force-rebuild
65013 -+ the table. That's why this grammar is allowed. That's why we ignore
65014 -+ it for views. So just do nothing in such a case.
65015 -+ */
65016 -+ if (!new_name)
65017 -+ {
65018 -+ my_ok(thd);
65019 -+ DBUG_RETURN(FALSE);
65020 -+ }
65021 -+
65022 -+ /*
65023 -+ Avoid problems with a rename on a table that we have locked or
65024 -+ if the user is trying to to do this in a transcation context
65025 -+ */
65026 -+
65027 -+ if (thd->locked_tables || thd->active_transaction())
65028 -+ {
65029 -+ my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
65030 -+ ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
65031 -+ DBUG_RETURN(TRUE);
65032 -+ }
65033 -+
65034 -+ if (wait_if_global_read_lock(thd,0,1))
65035 -+ DBUG_RETURN(TRUE);
65036 -+ VOID(pthread_mutex_lock(&LOCK_open));
65037 -+ if (lock_table_names(thd, table_list))
65038 -+ {
65039 -+ error= 1;
65040 -+ goto view_err;
65041 -+ }
65042 -+
65043 -+ if (!do_rename(thd, table_list, new_db, new_name, new_name, 1))
65044 -+ {
65045 -+ if (mysql_bin_log.is_open())
65046 -+ {
65047 -+ thd->clear_error();
65048 -+ Query_log_event qinfo(thd, thd->query(), thd->query_length(),
65049 -+ 0, FALSE, 0);
65050 -+ if ((error= mysql_bin_log.write(&qinfo)))
65051 -+ goto view_err_unlock;
65052 -+ }
65053 -+ my_ok(thd);
65054 -+ }
65055 -+
65056 -+view_err_unlock:
65057 -+ unlock_table_names(thd, table_list, (TABLE_LIST*) 0);
65058 -+
65059 -+view_err:
65060 -+ pthread_mutex_unlock(&LOCK_open);
65061 -+ start_waiting_global_read_lock(thd);
65062 -+ DBUG_RETURN(error);
65063 -+ }
65064 -+
65065 -+ if (!(table= open_n_lock_single_table(thd, table_list, TL_WRITE_ALLOW_READ)))
65066 -+ DBUG_RETURN(TRUE);
65067 -+ table->use_all_columns();
65068 -+
65069 -+ /*
65070 -+ Prohibit changing of the UNION list of a non-temporary MERGE table
65071 -+ under LOCK tables. It would be quite difficult to reuse a shrinked
65072 -+ set of tables from the old table or to open a new TABLE object for
65073 -+ an extended list and verify that they belong to locked tables.
65074 -+ */
65075 -+ if (thd->locked_tables &&
65076 -+ (create_info->used_fields & HA_CREATE_USED_UNION) &&
65077 -+ (table->s->tmp_table == NO_TMP_TABLE))
65078 -+ {
65079 -+ my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0));
65080 -+ DBUG_RETURN(TRUE);
65081 -+ }
65082 -+
65083 -+ /* Check that we are not trying to rename to an existing table */
65084 -+ if (new_name)
65085 -+ {
65086 -+ DBUG_PRINT("info", ("new_db.new_name: '%s'.'%s'", new_db, new_name));
65087 -+ strmov(new_name_buff,new_name);
65088 -+ strmov(new_alias= new_alias_buff, new_name);
65089 -+ if (lower_case_table_names)
65090 -+ {
65091 -+ if (lower_case_table_names != 2)
65092 -+ {
65093 -+ my_casedn_str(files_charset_info, new_name_buff);
65094 -+ new_alias= new_name; // Create lower case table name
65095 -+ }
65096 -+ my_casedn_str(files_charset_info, new_name);
65097 -+ }
65098 -+ if (new_db == db &&
65099 -+ !my_strcasecmp(table_alias_charset, new_name_buff, table_name))
65100 -+ {
65101 -+ /*
65102 -+ Source and destination table names are equal: make later check
65103 -+ easier.
65104 -+ */
65105 -+ new_alias= new_name= table_name;
65106 -+ }
65107 -+ else
65108 -+ {
65109 -+ if (table->s->tmp_table != NO_TMP_TABLE)
65110 -+ {
65111 -+ if (find_temporary_table(thd,new_db,new_name_buff))
65112 -+ {
65113 -+ my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name_buff);
65114 -+ DBUG_RETURN(TRUE);
65115 -+ }
65116 -+ }
65117 -+ else
65118 -+ {
65119 -+ if (lock_table_name_if_not_cached(thd, new_db, new_name, &name_lock))
65120 -+ DBUG_RETURN(TRUE);
65121 -+ if (!name_lock)
65122 -+ {
65123 -+ my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
65124 -+ DBUG_RETURN(TRUE);
65125 -+ }
65126 -+
65127 -+ build_table_filename(new_name_buff, sizeof(new_name_buff) - 1,
65128 -+ new_db, new_name_buff, reg_ext, 0);
65129 -+ if (!access(new_name_buff, F_OK))
65130 -+ {
65131 -+ /* Table will be closed in do_command() */
65132 -+ my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
65133 -+ goto err;
65134 -+ }
65135 -+ }
65136 -+ }
65137 -+ }
65138 -+ else
65139 -+ {
65140 -+ new_alias= (lower_case_table_names == 2) ? alias : table_name;
65141 -+ new_name= table_name;
65142 -+ }
65143 -+
65144 -+ old_db_type= table->s->db_type();
65145 -+ if (!create_info->db_type)
65146 -+ {
65147 -+#ifdef WITH_PARTITION_STORAGE_ENGINE
65148 -+ if (table->part_info &&
65149 -+ create_info->used_fields & HA_CREATE_USED_ENGINE)
65150 -+ {
65151 -+ /*
65152 -+ This case happens when the user specified
65153 -+ ENGINE = x where x is a non-existing storage engine
65154 -+ We set create_info->db_type to default_engine_type
65155 -+ to ensure we don't change underlying engine type
65156 -+ due to a erroneously given engine name.
65157 -+ */
65158 -+ create_info->db_type= table->part_info->default_engine_type;
65159 -+ }
65160 -+ else
65161 -+#endif
65162 -+ create_info->db_type= old_db_type;
65163 -+ }
65164 -+
65165 -+ if (check_engine(thd, new_name, create_info))
65166 -+ goto err;
65167 -+ new_db_type= create_info->db_type;
65168 -+
65169 -+ if ((new_db_type != old_db_type ||
65170 -+ alter_info->flags & ALTER_PARTITION) &&
65171 -+ !table->file->can_switch_engines())
65172 -+ {
65173 -+ my_error(ER_ROW_IS_REFERENCED, MYF(0));
65174 -+ goto err;
65175 -+ }
65176 -+
65177 -+ /*
65178 -+ If this is an ALTER TABLE and no explicit row type specified reuse
65179 -+ the table's row type.
65180 -+ Note : this is the same as if the row type was specified explicitly.
65181 -+ */
65182 -+ if (create_info->row_type == ROW_TYPE_NOT_USED)
65183 -+ {
65184 -+ /* ALTER TABLE without explicit row type */
65185 -+ create_info->row_type= table->s->row_type;
65186 -+ }
65187 -+ else
65188 -+ {
65189 -+ /* ALTER TABLE with specific row type */
65190 -+ create_info->used_fields |= HA_CREATE_USED_ROW_FORMAT;
65191 -+ }
65192 -+
65193 -+ DBUG_PRINT("info", ("old type: %s new type: %s",
65194 -+ ha_resolve_storage_engine_name(old_db_type),
65195 -+ ha_resolve_storage_engine_name(new_db_type)));
65196 -+ if (ha_check_storage_engine_flag(old_db_type, HTON_ALTER_NOT_SUPPORTED) ||
65197 -+ ha_check_storage_engine_flag(new_db_type, HTON_ALTER_NOT_SUPPORTED))
65198 -+ {
65199 -+ DBUG_PRINT("info", ("doesn't support alter"));
65200 -+ my_error(ER_ILLEGAL_HA, MYF(0), table_name);
65201 -+ goto err;
65202 -+ }
65203 -+
65204 -+ thd_proc_info(thd, "setup");
65205 -+ if (!(alter_info->flags & ~(ALTER_RENAME | ALTER_KEYS_ONOFF)) &&
65206 -+ !table->s->tmp_table) // no need to touch frm
65207 -+ {
65208 -+ switch (alter_info->keys_onoff) {
65209 -+ case LEAVE_AS_IS:
65210 -+ break;
65211 -+ case ENABLE:
65212 -+ /*
65213 -+ wait_while_table_is_used() ensures that table being altered is
65214 -+ opened only by this thread and that TABLE::TABLE_SHARE::version
65215 -+ of TABLE object corresponding to this table is 0.
65216 -+ The latter guarantees that no DML statement will open this table
65217 -+ until ALTER TABLE finishes (i.e. until close_thread_tables())
65218 -+ while the fact that the table is still open gives us protection
65219 -+ from concurrent DDL statements.
65220 -+ */
65221 -+ VOID(pthread_mutex_lock(&LOCK_open));
65222 -+ wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
65223 -+ VOID(pthread_mutex_unlock(&LOCK_open));
65224 -+ DBUG_EXECUTE_IF("sleep_alter_enable_indexes", my_sleep(6000000););
65225 -+ error= table->file->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
65226 -+ /* COND_refresh will be signaled in close_thread_tables() */
65227 -+ break;
65228 -+ case DISABLE:
65229 -+ VOID(pthread_mutex_lock(&LOCK_open));
65230 -+ wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
65231 -+ VOID(pthread_mutex_unlock(&LOCK_open));
65232 -+ error=table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
65233 -+ /* COND_refresh will be signaled in close_thread_tables() */
65234 -+ break;
65235 -+ default:
65236 -+ DBUG_ASSERT(FALSE);
65237 -+ error= 0;
65238 -+ break;
65239 -+ }
65240 -+ if (error == HA_ERR_WRONG_COMMAND)
65241 -+ {
65242 -+ error= 0;
65243 -+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
65244 -+ ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
65245 -+ table->alias);
65246 -+ }
65247 -+
65248 -+ /*
65249 -+ Unlike to the above case close_cached_table() below will remove ALL
65250 -+ instances of TABLE from table cache (it will also remove table lock
65251 -+ held by this thread). So to make actual table renaming and writing
65252 -+ to binlog atomic we have to put them into the same critical section
65253 -+ protected by LOCK_open mutex. This also removes gap for races between
65254 -+ access() and mysql_rename_table() calls.
65255 -+ */
65256 -+
65257 -+ if (!error && (new_name != table_name || new_db != db))
65258 -+ {
65259 -+ thd_proc_info(thd, "rename");
65260 -+
65261 -+ /*
65262 -+ Workaround InnoDB ending the transaction when the table instance
65263 -+ is unlocked/closed (close_cached_table below), otherwise the trx
65264 -+ state will differ between the server and storage engine layers.
65265 -+ */
65266 -+ ha_autocommit_or_rollback(thd, 0);
65267 -+
65268 -+ VOID(pthread_mutex_lock(&LOCK_open));
65269 -+ /*
65270 -+ Then do a 'simple' rename of the table. First we need to close all
65271 -+ instances of 'source' table.
65272 -+ */
65273 -+ close_cached_table(thd, table);
65274 -+ /*
65275 -+ Then, we want check once again that target table does not exist.
65276 -+ Actually the order of these two steps does not matter since
65277 -+ earlier we took name-lock on the target table, so we do them
65278 -+ in this particular order only to be consistent with 5.0, in which
65279 -+ we don't take this name-lock and where this order really matters.
65280 -+ TODO: Investigate if we need this access() check at all.
65281 -+ */
65282 -+ if (!access(new_name_buff,F_OK))
65283 -+ {
65284 -+ my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name);
65285 -+ error= -1;
65286 -+ }
65287 -+ else
65288 -+ {
65289 -+ *fn_ext(new_name)=0;
65290 -+ if (mysql_rename_table(old_db_type,db,table_name,new_db,new_alias, 0))
65291 -+ error= -1;
65292 -+ else if (Table_triggers_list::change_table_name(thd, db, table_name,
65293 -+ new_db, new_alias))
65294 -+ {
65295 -+ VOID(mysql_rename_table(old_db_type, new_db, new_alias, db,
65296 -+ table_name, 0));
65297 -+ error= -1;
65298 -+ }
65299 -+ }
65300 -+ }
65301 -+ else
65302 -+ VOID(pthread_mutex_lock(&LOCK_open));
65303 -+
65304 -+ if (error == HA_ERR_WRONG_COMMAND)
65305 -+ {
65306 -+ error= 0;
65307 -+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
65308 -+ ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
65309 -+ table->alias);
65310 -+ }
65311 -+
65312 -+ if (!error)
65313 -+ {
65314 -+ error= write_bin_log(thd, TRUE, thd->query(), thd->query_length());
65315 -+ if (!error)
65316 -+ my_ok(thd);
65317 -+ }
65318 -+ else if (error > 0)
65319 -+ {
65320 -+ table->file->print_error(error, MYF(0));
65321 -+ error= -1;
65322 -+ }
65323 -+ if (name_lock)
65324 -+ unlink_open_table(thd, name_lock, FALSE);
65325 -+ VOID(pthread_mutex_unlock(&LOCK_open));
65326 -+ table_list->table= NULL; // For query cache
65327 -+ query_cache_invalidate3(thd, table_list, 0);
65328 -+ DBUG_RETURN(error);
65329 -+ }
65330 -+
65331 -+ /* We have to do full alter table. */
65332 -+
65333 -+#ifdef WITH_PARTITION_STORAGE_ENGINE
65334 -+ if (prep_alter_part_table(thd, table, alter_info, create_info, old_db_type,
65335 -+ &partition_changed, &fast_alter_partition))
65336 -+ goto err;
65337 -+#endif
65338 -+ /*
65339 -+ If the old table had partitions and we are doing ALTER TABLE ...
65340 -+ engine= <new_engine>, the new table must preserve the original
65341 -+ partitioning. That means that the new engine is still the
65342 -+ partitioning engine, not the engine specified in the parser.
65343 -+ This is discovered in prep_alter_part_table, which in such case
65344 -+ updates create_info->db_type.
65345 -+ Now we need to update the stack copy of create_info->db_type,
65346 -+ as otherwise we won't be able to correctly move the files of the
65347 -+ temporary table to the result table files.
65348 -+ */
65349 -+ new_db_type= create_info->db_type;
65350 -+
65351 -+ if (is_index_maintenance_unique (table, alter_info))
65352 -+ need_copy_table= ALTER_TABLE_DATA_CHANGED;
65353 -+
65354 -+ if (mysql_prepare_alter_table(thd, table, create_info, alter_info))
65355 -+ goto err;
65356 -+
65357 -+ if (need_copy_table == ALTER_TABLE_METADATA_ONLY)
65358 -+ need_copy_table= alter_info->change_level;
65359 -+
65360 -+ set_table_default_charset(thd, create_info, db);
65361 -+
65362 -+ if (thd->variables.old_alter_table
65363 -+ || (table->s->db_type() != create_info->db_type)
65364 -+#ifdef WITH_PARTITION_STORAGE_ENGINE
65365 -+ || partition_changed
65366 -+#endif
65367 -+ )
65368 -+ need_copy_table= ALTER_TABLE_DATA_CHANGED;
65369 -+ else
65370 -+ {
65371 -+ enum_alter_table_change_level need_copy_table_res;
65372 -+ /* Check how much the tables differ. */
65373 -+ if (compare_tables(table, alter_info,
65374 -+ create_info, order_num,
65375 -+ &need_copy_table_res,
65376 -+ &key_info_buffer,
65377 -+ &index_drop_buffer, &index_drop_count,
65378 -+ &index_add_buffer, &index_add_count,
65379 -+ &candidate_key_count))
65380 -+ goto err;
65381 -+
65382 -+ DBUG_EXECUTE_IF("alter_table_only_metadata_change", {
65383 -+ if (need_copy_table_res != ALTER_TABLE_METADATA_ONLY)
65384 -+ goto err; });
65385 -+ DBUG_EXECUTE_IF("alter_table_only_index_change", {
65386 -+ if (need_copy_table_res != ALTER_TABLE_INDEX_CHANGED)
65387 -+ goto err; });
65388 -+
65389 -+ if (need_copy_table == ALTER_TABLE_METADATA_ONLY)
65390 -+ need_copy_table= need_copy_table_res;
65391 -+ }
65392 -+
65393 -+ /*
65394 -+ If there are index changes only, try to do them online. "Index
65395 -+ changes only" means also that the handler for the table does not
65396 -+ change. The table is open and locked. The handler can be accessed.
65397 -+ */
65398 -+ if (need_copy_table == ALTER_TABLE_INDEX_CHANGED)
65399 -+ {
65400 -+ int pk_changed= 0;
65401 -+ ulong alter_flags= 0;
65402 -+ ulong needed_online_flags= 0;
65403 -+ ulong needed_fast_flags= 0;
65404 -+ KEY *key;
65405 -+ uint *idx_p;
65406 -+ uint *idx_end_p;
65407 -+
65408 -+ alter_flags= table->file->alter_table_flags(alter_info->flags);
65409 -+ DBUG_PRINT("info", ("alter_flags: %lu", alter_flags));
65410 -+ /* Check dropped indexes. */
65411 -+ for (idx_p= index_drop_buffer, idx_end_p= idx_p + index_drop_count;
65412 -+ idx_p < idx_end_p;
65413 -+ idx_p++)
65414 -+ {
65415 -+ key= table->key_info + *idx_p;
65416 -+ DBUG_PRINT("info", ("index dropped: '%s'", key->name));
65417 -+ if (key->flags & HA_NOSAME)
65418 -+ {
65419 -+ /*
65420 -+ Unique key. Check for "PRIMARY".
65421 -+ or if dropping last unique key
65422 -+ */
65423 -+ if ((uint) (key - table->key_info) == table->s->primary_key)
65424 -+ {
65425 -+ DBUG_PRINT("info", ("Dropping primary key"));
65426 -+ /* Primary key. */
65427 -+ needed_online_flags|= HA_ONLINE_DROP_PK_INDEX;
65428 -+ needed_fast_flags|= HA_ONLINE_DROP_PK_INDEX_NO_WRITES;
65429 -+ pk_changed++;
65430 -+ candidate_key_count--;
65431 -+ }
65432 -+ else
65433 -+ {
65434 -+ KEY_PART_INFO *part_end= key->key_part + key->key_parts;
65435 -+ bool is_candidate_key= true;
65436 -+
65437 -+ /* Non-primary unique key. */
65438 -+ needed_online_flags|= HA_ONLINE_DROP_UNIQUE_INDEX;
65439 -+ needed_fast_flags|= HA_ONLINE_DROP_UNIQUE_INDEX_NO_WRITES;
65440 -+
65441 -+ /*
65442 -+ Check if all fields in key are declared
65443 -+ NOT NULL and adjust candidate_key_count
65444 -+ */
65445 -+ for (KEY_PART_INFO *key_part= key->key_part;
65446 -+ key_part < part_end;
65447 -+ key_part++)
65448 -+ is_candidate_key=
65449 -+ (is_candidate_key &&
65450 -+ (! table->field[key_part->fieldnr-1]->maybe_null()));
65451 -+ if (is_candidate_key)
65452 -+ candidate_key_count--;
65453 -+ }
65454 -+ }
65455 -+ else
65456 -+ {
65457 -+ /* Non-unique key. */
65458 -+ needed_online_flags|= HA_ONLINE_DROP_INDEX;
65459 -+ needed_fast_flags|= HA_ONLINE_DROP_INDEX_NO_WRITES;
65460 -+ }
65461 -+ }
65462 -+ no_pk= ((table->s->primary_key == MAX_KEY) ||
65463 -+ (needed_online_flags & HA_ONLINE_DROP_PK_INDEX));
65464 -+ /* Check added indexes. */
65465 -+ for (idx_p= index_add_buffer, idx_end_p= idx_p + index_add_count;
65466 -+ idx_p < idx_end_p;
65467 -+ idx_p++)
65468 -+ {
65469 -+ key= key_info_buffer + *idx_p;
65470 -+ DBUG_PRINT("info", ("index added: '%s'", key->name));
65471 -+ if (key->flags & HA_NOSAME)
65472 -+ {
65473 -+ /* Unique key */
65474 -+
65475 -+ KEY_PART_INFO *part_end= key->key_part + key->key_parts;
65476 -+ bool is_candidate_key= true;
65477 -+
65478 -+ /*
65479 -+ Check if all fields in key are declared
65480 -+ NOT NULL
65481 -+ */
65482 -+ for (KEY_PART_INFO *key_part= key->key_part;
65483 -+ key_part < part_end;
65484 -+ key_part++)
65485 -+ is_candidate_key=
65486 -+ (is_candidate_key &&
65487 -+ (! table->field[key_part->fieldnr]->maybe_null()));
65488 -+
65489 -+ /*
65490 -+ Check for "PRIMARY"
65491 -+ or if adding first unique key
65492 -+ defined on non-nullable fields
65493 -+ */
65494 -+
65495 -+ if ((!my_strcasecmp(system_charset_info,
65496 -+ key->name, primary_key_name)) ||
65497 -+ (no_pk && candidate_key_count == 0 && is_candidate_key))
65498 -+ {
65499 -+ DBUG_PRINT("info", ("Adding primary key"));
65500 -+ /* Primary key. */
65501 -+ needed_online_flags|= HA_ONLINE_ADD_PK_INDEX;
65502 -+ needed_fast_flags|= HA_ONLINE_ADD_PK_INDEX_NO_WRITES;
65503 -+ pk_changed++;
65504 -+ no_pk= false;
65505 -+ }
65506 -+ else
65507 -+ {
65508 -+ /* Non-primary unique key. */
65509 -+ needed_online_flags|= HA_ONLINE_ADD_UNIQUE_INDEX;
65510 -+ needed_fast_flags|= HA_ONLINE_ADD_UNIQUE_INDEX_NO_WRITES;
65511 -+ }
65512 -+ }
65513 -+ else
65514 -+ {
65515 -+ /* Non-unique key. */
65516 -+ needed_online_flags|= HA_ONLINE_ADD_INDEX;
65517 -+ needed_fast_flags|= HA_ONLINE_ADD_INDEX_NO_WRITES;
65518 -+ }
65519 -+ }
65520 -+
65521 -+ if ((candidate_key_count > 0) &&
65522 -+ (needed_online_flags & HA_ONLINE_DROP_PK_INDEX))
65523 -+ {
65524 -+ /*
65525 -+ Dropped primary key when there is some other unique
65526 -+ not null key that should be converted to primary key
65527 -+ */
65528 -+ needed_online_flags|= HA_ONLINE_ADD_PK_INDEX;
65529 -+ needed_fast_flags|= HA_ONLINE_ADD_PK_INDEX_NO_WRITES;
65530 -+ pk_changed= 2;
65531 -+ }
65532 -+
65533 -+ DBUG_PRINT("info", ("needed_online_flags: 0x%lx, needed_fast_flags: 0x%lx",
65534 -+ needed_online_flags, needed_fast_flags));
65535 -+ /*
65536 -+ Online or fast add/drop index is possible only if
65537 -+ the primary key is not added and dropped in the same statement.
65538 -+ Otherwise we have to recreate the table.
65539 -+ need_copy_table is no-zero at this place.
65540 -+ */
65541 -+ if ( pk_changed < 2 )
65542 -+ {
65543 -+ if ((alter_flags & needed_online_flags) == needed_online_flags)
65544 -+ {
65545 -+ /* All required online flags are present. */
65546 -+ need_copy_table= ALTER_TABLE_METADATA_ONLY;
65547 -+ need_lock_for_indexes= FALSE;
65548 -+ }
65549 -+ else if ((alter_flags & needed_fast_flags) == needed_fast_flags)
65550 -+ {
65551 -+ /* All required fast flags are present. */
65552 -+ need_copy_table= ALTER_TABLE_METADATA_ONLY;
65553 -+ }
65554 -+ }
65555 -+ DBUG_PRINT("info", ("need_copy_table: %u need_lock: %d",
65556 -+ need_copy_table, need_lock_for_indexes));
65557 -+ }
65558 -+
65559 -+ /*
65560 -+ better have a negative test here, instead of positive, like
65561 -+ alter_info->flags & ALTER_ADD_COLUMN|ALTER_ADD_INDEX|...
65562 -+ so that ALTER TABLE won't break when somebody will add new flag
65563 -+ */
65564 -+ if (need_copy_table == ALTER_TABLE_METADATA_ONLY)
65565 -+ create_info->frm_only= 1;
65566 -+
65567 -+#ifdef WITH_PARTITION_STORAGE_ENGINE
65568 -+ if (fast_alter_partition)
65569 -+ {
65570 -+ DBUG_ASSERT(!name_lock);
65571 -+ DBUG_RETURN(fast_alter_partition_table(thd, table, alter_info,
65572 -+ create_info, table_list,
65573 -+ db, table_name,
65574 -+ fast_alter_partition));
65575 -+ }
65576 -+#endif
65577 -+
65578 -+ my_snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%lx", tmp_file_prefix,
65579 -+ current_pid, thd->thread_id);
65580 -+ /* Safety fix for innodb */
65581 -+ if (lower_case_table_names)
65582 -+ my_casedn_str(files_charset_info, tmp_name);
65583 -+
65584 -+ /*
65585 -+ Handling of symlinked tables:
65586 -+ If no rename:
65587 -+ Create new data file and index file on the same disk as the
65588 -+ old data and index files.
65589 -+ Copy data.
65590 -+ Rename new data file over old data file and new index file over
65591 -+ old index file.
65592 -+ Symlinks are not changed.
65593 -+
65594 -+ If rename:
65595 -+ Create new data file and index file on the same disk as the
65596 -+ old data and index files. Create also symlinks to point at
65597 -+ the new tables.
65598 -+ Copy data.
65599 -+ At end, rename intermediate tables, and symlinks to intermediate
65600 -+ table, to final table name.
65601 -+ Remove old table and old symlinks
65602 -+
65603 -+ If rename is made to another database:
65604 -+ Create new tables in new database.
65605 -+ Copy data.
65606 -+ Remove old table and symlinks.
65607 -+ */
65608 -+ if (!strcmp(db, new_db)) // Ignore symlink if db changed
65609 -+ {
65610 -+ if (create_info->index_file_name)
65611 -+ {
65612 -+ /* Fix index_file_name to have 'tmp_name' as basename */
65613 -+ strmov(index_file, tmp_name);
65614 -+ create_info->index_file_name=fn_same(index_file,
65615 -+ create_info->index_file_name,
65616 -+ 1);
65617 -+ }
65618 -+ if (create_info->data_file_name)
65619 -+ {
65620 -+ /* Fix data_file_name to have 'tmp_name' as basename */
65621 -+ strmov(data_file, tmp_name);
65622 -+ create_info->data_file_name=fn_same(data_file,
65623 -+ create_info->data_file_name,
65624 -+ 1);
65625 -+ }
65626 -+ }
65627 -+ else
65628 -+ create_info->data_file_name=create_info->index_file_name=0;
65629 -+
65630 -+ DEBUG_SYNC(thd, "alter_table_before_create_table_no_lock");
65631 -+ /*
65632 -+ Create a table with a temporary name.
65633 -+ With create_info->frm_only == 1 this creates a .frm file only.
65634 -+ We don't log the statement, it will be logged later.
65635 -+ */
65636 -+ tmp_disable_binlog(thd);
65637 -+ error= mysql_create_table_no_lock(thd, new_db, tmp_name,
65638 -+ create_info,
65639 -+ alter_info,
65640 -+ 1, 0);
65641 -+ reenable_binlog(thd);
65642 -+ if (error)
65643 -+ goto err;
65644 -+
65645 -+ /* Open the table if we need to copy the data. */
65646 -+ DBUG_PRINT("info", ("need_copy_table: %u", need_copy_table));
65647 -+ if (need_copy_table != ALTER_TABLE_METADATA_ONLY)
65648 -+ {
65649 -+ if (table->s->tmp_table)
65650 -+ {
65651 -+ TABLE_LIST tbl;
65652 -+ bzero((void*) &tbl, sizeof(tbl));
65653 -+ tbl.db= new_db;
65654 -+ tbl.table_name= tbl.alias= tmp_name;
65655 -+ /* Table is in thd->temporary_tables */
65656 -+ new_table= open_table(thd, &tbl, thd->mem_root, (bool*) 0,
65657 -+ MYSQL_LOCK_IGNORE_FLUSH);
65658 -+ }
65659 -+ else
65660 -+ {
65661 -+ char path[FN_REFLEN + 1];
65662 -+ /* table is a normal table: Create temporary table in same directory */
65663 -+ build_table_filename(path, sizeof(path) - 1, new_db, tmp_name, "",
65664 -+ FN_IS_TMP);
65665 -+ /* Open our intermediate table */
65666 -+ new_table=open_temporary_table(thd, path, new_db, tmp_name,0);
65667 -+ }
65668 -+ if (!new_table)
65669 -+ goto err1;
65670 -+ /*
65671 -+ Note: In case of MERGE table, we do not attach children. We do not
65672 -+ copy data for MERGE tables. Only the children have data.
65673 -+ */
65674 -+ }
65675 -+
65676 -+ /* Copy the data if necessary. */
65677 -+ thd->count_cuted_fields= CHECK_FIELD_WARN; // calc cuted fields
65678 -+ thd->cuted_fields=0L;
65679 -+ copied=deleted=0;
65680 -+ /*
65681 -+ We do not copy data for MERGE tables. Only the children have data.
65682 -+ MERGE tables have HA_NO_COPY_ON_ALTER set.
65683 -+ */
65684 -+ if (new_table && !(new_table->file->ha_table_flags() & HA_NO_COPY_ON_ALTER))
65685 -+ {
65686 -+ /* We don't want update TIMESTAMP fields during ALTER TABLE. */
65687 -+ new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
65688 -+ new_table->next_number_field=new_table->found_next_number_field;
65689 -+ thd_proc_info(thd, "copy to tmp table");
65690 -+ error= copy_data_between_tables(table, new_table,
65691 -+ alter_info->create_list, ignore,
65692 -+ order_num, order, &copied, &deleted,
65693 -+ alter_info->keys_onoff,
65694 -+ alter_info->error_if_not_empty);
65695 -+ }
65696 -+ else
65697 -+ {
65698 -+ VOID(pthread_mutex_lock(&LOCK_open));
65699 -+ wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
65700 -+ VOID(pthread_mutex_unlock(&LOCK_open));
65701 -+ thd_proc_info(thd, "manage keys");
65702 -+ alter_table_manage_keys(table, table->file->indexes_are_disabled(),
65703 -+ alter_info->keys_onoff);
65704 -+ error= ha_autocommit_or_rollback(thd, 0);
65705 -+ if (end_active_trans(thd))
65706 -+ error= 1;
65707 -+ }
65708 -+ thd->count_cuted_fields= CHECK_FIELD_IGNORE;
65709 -+
65710 -+ /* If we did not need to copy, we might still need to add/drop indexes. */
65711 -+ if (! new_table)
65712 -+ {
65713 -+ uint *key_numbers;
65714 -+ uint *keyno_p;
65715 -+ KEY *key_info;
65716 -+ KEY *key;
65717 -+ uint *idx_p;
65718 -+ uint *idx_end_p;
65719 -+ KEY_PART_INFO *key_part;
65720 -+ KEY_PART_INFO *part_end;
65721 -+ DBUG_PRINT("info", ("No new_table, checking add/drop index"));
65722 -+
65723 -+ table->file->ha_prepare_for_alter();
65724 -+ if (index_add_count)
65725 -+ {
65726 -+ /* The add_index() method takes an array of KEY structs. */
65727 -+ key_info= (KEY*) thd->alloc(sizeof(KEY) * index_add_count);
65728 -+ key= key_info;
65729 -+ for (idx_p= index_add_buffer, idx_end_p= idx_p + index_add_count;
65730 -+ idx_p < idx_end_p;
65731 -+ idx_p++, key++)
65732 -+ {
65733 -+ /* Copy the KEY struct. */
65734 -+ *key= key_info_buffer[*idx_p];
65735 -+ /* Fix the key parts. */
65736 -+ part_end= key->key_part + key->key_parts;
65737 -+ for (key_part= key->key_part; key_part < part_end; key_part++)
65738 -+ key_part->field= table->field[key_part->fieldnr];
65739 -+ }
65740 -+ /* Add the indexes. */
65741 -+ if ((error= table->file->add_index(table, key_info, index_add_count)))
65742 -+ {
65743 -+ /*
65744 -+ Exchange the key_info for the error message. If we exchange
65745 -+ key number by key name in the message later, we need correct info.
65746 -+ */
65747 -+ KEY *save_key_info= table->key_info;
65748 -+ table->key_info= key_info;
65749 -+ table->file->print_error(error, MYF(0));
65750 -+ table->key_info= save_key_info;
65751 -+ goto err1;
65752 -+ }
65753 -+ }
65754 -+ /*end of if (index_add_count)*/
65755 -+
65756 -+ if (index_drop_count)
65757 -+ {
65758 -+ /* The prepare_drop_index() method takes an array of key numbers. */
65759 -+ key_numbers= (uint*) thd->alloc(sizeof(uint) * index_drop_count);
65760 -+ keyno_p= key_numbers;
65761 -+ /* Get the number of each key. */
65762 -+ for (idx_p= index_drop_buffer, idx_end_p= idx_p + index_drop_count;
65763 -+ idx_p < idx_end_p;
65764 -+ idx_p++, keyno_p++)
65765 -+ *keyno_p= *idx_p;
65766 -+ /*
65767 -+ Tell the handler to prepare for drop indexes.
65768 -+ This re-numbers the indexes to get rid of gaps.
65769 -+ */
65770 -+ if ((error= table->file->prepare_drop_index(table, key_numbers,
65771 -+ index_drop_count)))
65772 -+ {
65773 -+ table->file->print_error(error, MYF(0));
65774 -+ goto err1;
65775 -+ }
65776 -+
65777 -+ /* Tell the handler to finally drop the indexes. */
65778 -+ if ((error= table->file->final_drop_index(table)))
65779 -+ {
65780 -+ table->file->print_error(error, MYF(0));
65781 -+ goto err1;
65782 -+ }
65783 -+ }
65784 -+ /*end of if (index_drop_count)*/
65785 -+
65786 -+ /*
65787 -+ The final .frm file is already created as a temporary file
65788 -+ and will be renamed to the original table name later.
65789 -+ */
65790 -+
65791 -+ /* Need to commit before a table is unlocked (NDB requirement). */
65792 -+ DBUG_PRINT("info", ("Committing before unlocking table"));
65793 -+ if (ha_autocommit_or_rollback(thd, 0) || end_active_trans(thd))
65794 -+ goto err1;
65795 -+ }
65796 -+ /*end of if (! new_table) for add/drop index*/
65797 -+
65798 -+ if (table->s->tmp_table != NO_TMP_TABLE)
65799 -+ {
65800 -+ /* We changed a temporary table */
65801 -+ if (error)
65802 -+ goto err1;
65803 -+ /* Close lock if this is a transactional table */
65804 -+ if (thd->lock)
65805 -+ {
65806 -+ mysql_unlock_tables(thd, thd->lock);
65807 -+ thd->lock=0;
65808 -+ }
65809 -+ /*
65810 -+ If LOCK TABLES list is not empty and contains this table,
65811 -+ unlock the table and remove the table from this list.
65812 -+ */
65813 -+ mysql_lock_remove(thd, thd->locked_tables, table, FALSE);
65814 -+ /* Remove link to old table and rename the new one */
65815 -+ close_temporary_table(thd, table, 1, 1);
65816 -+ /* Should pass the 'new_name' as we store table name in the cache */
65817 -+ if (rename_temporary_table(thd, new_table, new_db, new_name))
65818 -+ goto err1;
65819 -+ /* We don't replicate alter table statement on temporary tables */
65820 -+ if (!thd->current_stmt_binlog_row_based &&
65821 -+ write_bin_log(thd, TRUE, thd->query(), thd->query_length()))
65822 -+ DBUG_RETURN(TRUE);
65823 -+ goto end_temporary;
65824 -+ }
65825 -+
65826 -+ if (new_table)
65827 -+ {
65828 -+ /*
65829 -+ Close the intermediate table that will be the new table.
65830 -+ Note that MERGE tables do not have their children attached here.
65831 -+ */
65832 -+ intern_close_table(new_table);
65833 -+ my_free(new_table,MYF(0));
65834 -+ }
65835 -+ DEBUG_SYNC(thd, "alter_table_before_rename_result_table");
65836 -+ VOID(pthread_mutex_lock(&LOCK_open));
65837 -+ if (error)
65838 -+ {
65839 -+ VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP));
65840 -+ VOID(pthread_mutex_unlock(&LOCK_open));
65841 -+ goto err;
65842 -+ }
65843 -+
65844 -+ /*
65845 -+ Data is copied. Now we:
65846 -+ 1) Wait until all other threads close old version of table.
65847 -+ 2) Close instances of table open by this thread and replace them
65848 -+ with exclusive name-locks.
65849 -+ 3) Rename the old table to a temp name, rename the new one to the
65850 -+ old name.
65851 -+ 4) If we are under LOCK TABLES and don't do ALTER TABLE ... RENAME
65852 -+ we reopen new version of table.
65853 -+ 5) Write statement to the binary log.
65854 -+ 6) If we are under LOCK TABLES and do ALTER TABLE ... RENAME we
65855 -+ remove name-locks from list of open tables and table cache.
65856 -+ 7) If we are not not under LOCK TABLES we rely on close_thread_tables()
65857 -+ call to remove name-locks from table cache and list of open table.
65858 -+ */
65859 -+
65860 -+ thd_proc_info(thd, "rename result table");
65861 -+ my_snprintf(old_name, sizeof(old_name), "%s2-%lx-%lx", tmp_file_prefix,
65862 -+ current_pid, thd->thread_id);
65863 -+ if (lower_case_table_names)
65864 -+ my_casedn_str(files_charset_info, old_name);
65865 -+
65866 -+ wait_while_table_is_used(thd, table, HA_EXTRA_PREPARE_FOR_RENAME);
65867 -+ close_data_files_and_morph_locks(thd, db, table_name);
65868 -+
65869 -+ error=0;
65870 -+ save_old_db_type= old_db_type;
65871 -+
65872 -+ /*
65873 -+ This leads to the storage engine (SE) not being notified for renames in
65874 -+ mysql_rename_table(), because we just juggle with the FRM and nothing
65875 -+ more. If we have an intermediate table, then we notify the SE that
65876 -+ it should become the actual table. Later, we will recycle the old table.
65877 -+ However, in case of ALTER TABLE RENAME there might be no intermediate
65878 -+ table. This is when the old and new tables are compatible, according to
65879 -+ compare_table(). Then, we need one additional call to
65880 -+ mysql_rename_table() with flag NO_FRM_RENAME, which does nothing else but
65881 -+ actual rename in the SE and the FRM is not touched. Note that, if the
65882 -+ table is renamed and the SE is also changed, then an intermediate table
65883 -+ is created and the additional call will not take place.
65884 -+ */
65885 -+ if (need_copy_table == ALTER_TABLE_METADATA_ONLY)
65886 -+ {
65887 -+ DBUG_ASSERT(new_db_type == old_db_type);
65888 -+ /* This type cannot happen in regular ALTER. */
65889 -+ new_db_type= old_db_type= NULL;
65890 -+ }
65891 -+ if (mysql_rename_table(old_db_type, db, table_name, db, old_name,
65892 -+ FN_TO_IS_TMP))
65893 -+ {
65894 -+ error=1;
65895 -+ VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP));
65896 -+ }
65897 -+ else if (mysql_rename_table(new_db_type, new_db, tmp_name, new_db,
65898 -+ new_alias, FN_FROM_IS_TMP) ||
65899 -+ ((new_name != table_name || new_db != db) && // we also do rename
65900 -+ (need_copy_table != ALTER_TABLE_METADATA_ONLY ||
65901 -+ mysql_rename_table(save_old_db_type, db, table_name, new_db,
65902 -+ new_alias, NO_FRM_RENAME)) &&
65903 -+ Table_triggers_list::change_table_name(thd, db, table_name,
65904 -+ new_db, new_alias)))
65905 -+ {
65906 -+ /* Try to get everything back. */
65907 -+ error=1;
65908 -+ VOID(quick_rm_table(new_db_type,new_db,new_alias, 0));
65909 -+ VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP));
65910 -+ VOID(mysql_rename_table(old_db_type, db, old_name, db, alias,
65911 -+ FN_FROM_IS_TMP));
65912 -+ }
65913 -+
65914 -+ if (error)
65915 -+ {
65916 -+ /* This shouldn't happen. But let us play it safe. */
65917 -+ goto err_with_placeholders;
65918 -+ }
65919 -+
65920 -+ if (need_copy_table == ALTER_TABLE_METADATA_ONLY)
65921 -+ {
65922 -+ /*
65923 -+ Now we have to inform handler that new .FRM file is in place.
65924 -+ To do this we need to obtain a handler object for it.
65925 -+ NO need to tamper with MERGE tables. The real open is done later.
65926 -+ */
65927 -+ TABLE *t_table;
65928 -+ if (new_name != table_name || new_db != db)
65929 -+ {
65930 -+ table_list->alias= new_name;
65931 -+ table_list->table_name= new_name;
65932 -+ table_list->table_name_length= strlen(new_name);
65933 -+ table_list->db= new_db;
65934 -+ table_list->db_length= strlen(new_db);
65935 -+ table_list->table= name_lock;
65936 -+ if (reopen_name_locked_table(thd, table_list, FALSE))
65937 -+ goto err_with_placeholders;
65938 -+ t_table= table_list->table;
65939 -+ }
65940 -+ else
65941 -+ {
65942 -+ if (reopen_table(table))
65943 -+ goto err_with_placeholders;
65944 -+ t_table= table;
65945 -+ }
65946 -+ /* Tell the handler that a new frm file is in place. */
65947 -+ if (t_table->file->ha_create_handler_files(path, NULL, CHF_INDEX_FLAG,
65948 -+ create_info))
65949 -+ goto err_with_placeholders;
65950 -+ if (thd->locked_tables && new_name == table_name && new_db == db)
65951 -+ {
65952 -+ /*
65953 -+ We are going to reopen table down on the road, so we have to restore
65954 -+ state of the TABLE object which we used for obtaining of handler
65955 -+ object to make it suitable for reopening.
65956 -+ */
65957 -+ DBUG_ASSERT(t_table == table);
65958 -+ table->open_placeholder= 1;
65959 -+ close_handle_and_leave_table_as_lock(table);
65960 -+ }
65961 -+ }
65962 -+
65963 -+ VOID(quick_rm_table(old_db_type, db, old_name, FN_IS_TMP));
65964 -+
65965 -+ if (thd->locked_tables && new_name == table_name && new_db == db)
65966 -+ {
65967 -+ thd->in_lock_tables= 1;
65968 -+ error= reopen_tables(thd, 1, 1);
65969 -+ thd->in_lock_tables= 0;
65970 -+ if (error)
65971 -+ goto err_with_placeholders;
65972 -+ }
65973 -+ VOID(pthread_mutex_unlock(&LOCK_open));
65974 -+
65975 -+ thd_proc_info(thd, "end");
65976 -+
65977 -+ DBUG_EXECUTE_IF("sleep_alter_before_main_binlog", my_sleep(6000000););
65978 -+ DEBUG_SYNC(thd, "alter_table_before_main_binlog");
65979 -+
65980 -+ ha_binlog_log_query(thd, create_info->db_type, LOGCOM_ALTER_TABLE,
65981 -+ thd->query(), thd->query_length(),
65982 -+ db, table_name);
65983 -+
65984 -+ DBUG_ASSERT(!(mysql_bin_log.is_open() &&
65985 -+ thd->current_stmt_binlog_row_based &&
65986 -+ (create_info->options & HA_LEX_CREATE_TMP_TABLE)));
65987 -+ if (write_bin_log(thd, TRUE, thd->query(), thd->query_length()))
65988 -+ DBUG_RETURN(TRUE);
65989 -+
65990 -+ if (ha_check_storage_engine_flag(old_db_type, HTON_FLUSH_AFTER_RENAME))
65991 -+ {
65992 -+ /*
65993 -+ For the alter table to be properly flushed to the logs, we
65994 -+ have to open the new table. If not, we get a problem on server
65995 -+ shutdown. But we do not need to attach MERGE children.
65996 -+ */
65997 -+ char path[FN_REFLEN];
65998 -+ TABLE *t_table;
65999 -+ build_table_filename(path + 1, sizeof(path) - 1, new_db, table_name, "", 0);
66000 -+ t_table= open_temporary_table(thd, path, new_db, tmp_name, 0);
66001 -+ if (t_table)
66002 -+ {
66003 -+ intern_close_table(t_table);
66004 -+ my_free(t_table, MYF(0));
66005 -+ }
66006 -+ else
66007 -+ sql_print_warning("Could not open table %s.%s after rename\n",
66008 -+ new_db,table_name);
66009 -+ ha_flush_logs(old_db_type);
66010 -+ }
66011 -+ table_list->table=0; // For query cache
66012 -+ query_cache_invalidate3(thd, table_list, 0);
66013 -+
66014 -+ if (thd->locked_tables && (new_name != table_name || new_db != db))
66015 -+ {
66016 -+ /*
66017 -+ If are we under LOCK TABLES and did ALTER TABLE with RENAME we need
66018 -+ to remove placeholders for the old table and for the target table
66019 -+ from the list of open tables and table cache. If we are not under
66020 -+ LOCK TABLES we can rely on close_thread_tables() doing this job.
66021 -+ */
66022 -+ pthread_mutex_lock(&LOCK_open);
66023 -+ unlink_open_table(thd, table, FALSE);
66024 -+ unlink_open_table(thd, name_lock, FALSE);
66025 -+ pthread_mutex_unlock(&LOCK_open);
66026 -+ }
66027 -+
66028 -+end_temporary:
66029 -+ my_snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO),
66030 -+ (ulong) (copied + deleted), (ulong) deleted,
66031 -+ (ulong) thd->cuted_fields);
66032 -+ my_ok(thd, copied + deleted, 0L, tmp_name);
66033 -+ thd->some_tables_deleted=0;
66034 -+ DBUG_RETURN(FALSE);
66035 -+
66036 -+err1:
66037 -+ if (new_table)
66038 -+ {
66039 -+ /* close_temporary_table() frees the new_table pointer. */
66040 -+ close_temporary_table(thd, new_table, 1, 1);
66041 -+ }
66042 -+ else
66043 -+ VOID(quick_rm_table(new_db_type, new_db, tmp_name,
66044 -+ create_info->frm_only
66045 -+ ? FN_IS_TMP | FRM_ONLY
66046 -+ : FN_IS_TMP));
66047 -+
66048 -+err:
66049 -+ /*
66050 -+ No default value was provided for a DATE/DATETIME field, the
66051 -+ current sql_mode doesn't allow the '0000-00-00' value and
66052 -+ the table to be altered isn't empty.
66053 -+ Report error here.
66054 -+ */
66055 -+ if (alter_info->error_if_not_empty && thd->row_count)
66056 -+ {
66057 -+ const char *f_val= 0;
66058 -+ enum enum_mysql_timestamp_type t_type= MYSQL_TIMESTAMP_DATE;
66059 -+ switch (alter_info->datetime_field->sql_type)
66060 -+ {
66061 -+ case MYSQL_TYPE_DATE:
66062 -+ case MYSQL_TYPE_NEWDATE:
66063 -+ f_val= "0000-00-00";
66064 -+ t_type= MYSQL_TIMESTAMP_DATE;
66065 -+ break;
66066 -+ case MYSQL_TYPE_DATETIME:
66067 -+ f_val= "0000-00-00 00:00:00";
66068 -+ t_type= MYSQL_TIMESTAMP_DATETIME;
66069 -+ break;
66070 -+ default:
66071 -+ /* Shouldn't get here. */
66072 -+ DBUG_ASSERT(0);
66073 -+ }
66074 -+ bool save_abort_on_warning= thd->abort_on_warning;
66075 -+ thd->abort_on_warning= TRUE;
66076 -+ make_truncated_value_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
66077 -+ f_val, strlength(f_val), t_type,
66078 -+ alter_info->datetime_field->field_name);
66079 -+ thd->abort_on_warning= save_abort_on_warning;
66080 -+ }
66081 -+ if (name_lock)
66082 -+ {
66083 -+ pthread_mutex_lock(&LOCK_open);
66084 -+ unlink_open_table(thd, name_lock, FALSE);
66085 -+ pthread_mutex_unlock(&LOCK_open);
66086 -+ }
66087 -+ DBUG_RETURN(TRUE);
66088 -+
66089 -+err_with_placeholders:
66090 -+ /*
66091 -+ An error happened while we were holding exclusive name-lock on table
66092 -+ being altered. To be safe under LOCK TABLES we should remove placeholders
66093 -+ from list of open tables list and table cache.
66094 -+ */
66095 -+ unlink_open_table(thd, table, FALSE);
66096 -+ if (name_lock)
66097 -+ unlink_open_table(thd, name_lock, FALSE);
66098 -+ VOID(pthread_mutex_unlock(&LOCK_open));
66099 -+ DBUG_RETURN(TRUE);
66100 -+}
66101 -+/* mysql_alter_table */
66102 -+
66103 -+static int
66104 -+copy_data_between_tables(TABLE *from,TABLE *to,
66105 -+ List<Create_field> &create,
66106 -+ bool ignore,
66107 -+ uint order_num, ORDER *order,
66108 -+ ha_rows *copied,
66109 -+ ha_rows *deleted,
66110 -+ enum enum_enable_or_disable keys_onoff,
66111 -+ bool error_if_not_empty)
66112 -+{
66113 -+ int error;
66114 -+ Copy_field *copy,*copy_end;
66115 -+ ulong found_count,delete_count;
66116 -+ THD *thd= current_thd;
66117 -+ uint length= 0;
66118 -+ SORT_FIELD *sortorder;
66119 -+ READ_RECORD info;
66120 -+ TABLE_LIST tables;
66121 -+ List<Item> fields;
66122 -+ List<Item> all_fields;
66123 -+ ha_rows examined_rows;
66124 -+ bool auto_increment_field_copied= 0;
66125 -+ ulong save_sql_mode;
66126 -+ ulonglong prev_insert_id;
66127 -+ DBUG_ENTER("copy_data_between_tables");
66128 -+
66129 -+ /*
66130 -+ Turn off recovery logging since rollback of an alter table is to
66131 -+ delete the new table so there is no need to log the changes to it.
66132 -+
66133 -+ This needs to be done before external_lock
66134 -+ */
66135 -+ error= ha_enable_transaction(thd, FALSE);
66136 -+ if (error)
66137 -+ DBUG_RETURN(-1);
66138 -+
66139 -+ if (!(copy= new Copy_field[to->s->fields]))
66140 -+ DBUG_RETURN(-1); /* purecov: inspected */
66141 -+
66142 -+ if (to->file->ha_external_lock(thd, F_WRLCK))
66143 -+ DBUG_RETURN(-1);
66144 -+
66145 -+ /* We need external lock before we can disable/enable keys */
66146 -+ alter_table_manage_keys(to, from->file->indexes_are_disabled(), keys_onoff);
66147 -+
66148 -+ /* We can abort alter table for any table type */
66149 -+ thd->abort_on_warning= !ignore && test(thd->variables.sql_mode &
66150 -+ (MODE_STRICT_TRANS_TABLES |
66151 -+ MODE_STRICT_ALL_TABLES));
66152 -+
66153 -+ from->file->info(HA_STATUS_VARIABLE);
66154 -+ to->file->ha_start_bulk_insert(from->file->stats.records);
66155 -+
66156 -+ save_sql_mode= thd->variables.sql_mode;
66157 -+
66158 -+ List_iterator<Create_field> it(create);
66159 -+ Create_field *def;
66160 -+ copy_end=copy;
66161 -+ for (Field **ptr=to->field ; *ptr ; ptr++)
66162 -+ {
66163 -+ def=it++;
66164 -+ if (def->field)
66165 -+ {
66166 -+ if (*ptr == to->next_number_field)
66167 -+ {
66168 -+ auto_increment_field_copied= TRUE;
66169 -+ /*
66170 -+ If we are going to copy contents of one auto_increment column to
66171 -+ another auto_increment column it is sensible to preserve zeroes.
66172 -+ This condition also covers case when we are don't actually alter
66173 -+ auto_increment column.
66174 -+ */
66175 -+ if (def->field == from->found_next_number_field)
66176 -+ thd->variables.sql_mode|= MODE_NO_AUTO_VALUE_ON_ZERO;
66177 -+ }
66178 -+ (copy_end++)->set(*ptr,def->field,0);
66179 -+ }
66180 -+
66181 -+ }
66182 -+
66183 -+ found_count=delete_count=0;
66184 -+
66185 -+ if (order)
66186 -+ {
66187 -+ if (to->s->primary_key != MAX_KEY && to->file->primary_key_is_clustered())
66188 -+ {
66189 -+ char warn_buff[MYSQL_ERRMSG_SIZE];
66190 -+ my_snprintf(warn_buff, sizeof(warn_buff),
66191 -+ "ORDER BY ignored as there is a user-defined clustered index"
66192 -+ " in the table '%-.192s'", from->s->table_name.str);
66193 -+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
66194 -+ warn_buff);
66195 -+ }
66196 -+ else
66197 -+ {
66198 -+ from->sort.io_cache=(IO_CACHE*) my_malloc(sizeof(IO_CACHE),
66199 -+ MYF(MY_FAE | MY_ZEROFILL));
66200 -+ bzero((char *) &tables, sizeof(tables));
66201 -+ tables.table= from;
66202 -+ tables.alias= tables.table_name= from->s->table_name.str;
66203 -+ tables.db= from->s->db.str;
66204 -+ error= 1;
66205 -+
66206 -+ if (thd->lex->select_lex.setup_ref_array(thd, order_num) ||
66207 -+ setup_order(thd, thd->lex->select_lex.ref_pointer_array,
66208 -+ &tables, fields, all_fields, order) ||
66209 -+ !(sortorder= make_unireg_sortorder(order, &length, NULL)) ||
66210 -+ (from->sort.found_records= filesort(thd, from, sortorder, length,
66211 -+ (SQL_SELECT *) 0, HA_POS_ERROR,
66212 -+ 1, &examined_rows)) ==
66213 -+ HA_POS_ERROR)
66214 -+ goto err;
66215 -+ }
66216 -+ };
66217 -+
66218 -+ /* Tell handler that we have values for all columns in the to table */
66219 -+ to->use_all_columns();
66220 -+ init_read_record(&info, thd, from, (SQL_SELECT *) 0, 1, 1, FALSE);
66221 -+ if (ignore)
66222 -+ to->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
66223 -+ thd->row_count= 0;
66224 -+ restore_record(to, s->default_values); // Create empty record
66225 -+ while (!(error=info.read_record(&info)))
66226 -+ {
66227 -+ if (thd->killed)
66228 -+ {
66229 -+ thd->send_kill_message();
66230 -+ error= 1;
66231 -+ break;
66232 -+ }
66233 -+ thd->row_count++;
66234 -+ /* Return error if source table isn't empty. */
66235 -+ if (error_if_not_empty)
66236 -+ {
66237 -+ error= 1;
66238 -+ break;
66239 -+ }
66240 -+ if (to->next_number_field)
66241 -+ {
66242 -+ if (auto_increment_field_copied)
66243 -+ to->auto_increment_field_not_null= TRUE;
66244 -+ else
66245 -+ to->next_number_field->reset();
66246 -+ }
66247 -+
66248 -+ for (Copy_field *copy_ptr=copy ; copy_ptr != copy_end ; copy_ptr++)
66249 -+ {
66250 -+ copy_ptr->do_copy(copy_ptr);
66251 -+ }
66252 -+ prev_insert_id= to->file->next_insert_id;
66253 -+ error=to->file->ha_write_row(to->record[0]);
66254 -+ to->auto_increment_field_not_null= FALSE;
66255 -+ if (error)
66256 -+ {
66257 -+ if (!ignore ||
66258 -+ to->file->is_fatal_error(error, HA_CHECK_DUP))
66259 -+ {
66260 -+ if (!to->file->is_fatal_error(error, HA_CHECK_DUP))
66261 -+ {
66262 -+ uint key_nr= to->file->get_dup_key(error);
66263 -+ if ((int) key_nr >= 0)
66264 -+ {
66265 -+ const char *err_msg= ER(ER_DUP_ENTRY_WITH_KEY_NAME);
66266 -+ if (key_nr == 0 &&
66267 -+ (to->key_info[0].key_part[0].field->flags &
66268 -+ AUTO_INCREMENT_FLAG))
66269 -+ err_msg= ER(ER_DUP_ENTRY_AUTOINCREMENT_CASE);
66270 -+ to->file->print_keydup_error(key_nr, err_msg);
66271 -+ break;
66272 -+ }
66273 -+ }
66274 -+
66275 -+ to->file->print_error(error,MYF(0));
66276 -+ break;
66277 -+ }
66278 -+ to->file->restore_auto_increment(prev_insert_id);
66279 -+ delete_count++;
66280 -+ }
66281 -+ else
66282 -+ found_count++;
66283 -+ }
66284 -+ end_read_record(&info);
66285 -+ free_io_cache(from);
66286 -+ delete [] copy; // This is never 0
66287 -+
66288 -+ if (to->file->ha_end_bulk_insert() && error <= 0)
66289 -+ {
66290 -+ to->file->print_error(my_errno,MYF(0));
66291 -+ error=1;
66292 -+ }
66293 -+ to->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
66294 -+
66295 -+ if (ha_enable_transaction(thd, TRUE))
66296 -+ {
66297 -+ error= 1;
66298 -+ goto err;
66299 -+ }
66300 -+
66301 -+ /*
66302 -+ Ensure that the new table is saved properly to disk so that we
66303 -+ can do a rename
66304 -+ */
66305 -+ if (ha_autocommit_or_rollback(thd, 0))
66306 -+ error=1;
66307 -+ if (end_active_trans(thd))
66308 -+ error=1;
66309 -+
66310 -+ err:
66311 -+ thd->variables.sql_mode= save_sql_mode;
66312 -+ thd->abort_on_warning= 0;
66313 -+ free_io_cache(from);
66314 -+ *copied= found_count;
66315 -+ *deleted=delete_count;
66316 -+ to->file->ha_release_auto_increment();
66317 -+ if (to->file->ha_external_lock(thd,F_UNLCK))
66318 -+ error=1;
66319 -+ DBUG_RETURN(error > 0 ? -1 : 0);
66320 -+}
66321 -+
66322 -+
66323 -+/*
66324 -+ Recreates tables by calling mysql_alter_table().
66325 -+
66326 -+ SYNOPSIS
66327 -+ mysql_recreate_table()
66328 -+ thd Thread handler
66329 -+ tables Tables to recreate
66330 -+
66331 -+ RETURN
66332 -+ Like mysql_alter_table().
66333 -+*/
66334 -+bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list)
66335 -+{
66336 -+ HA_CREATE_INFO create_info;
66337 -+ Alter_info alter_info;
66338 -+
66339 -+ DBUG_ENTER("mysql_recreate_table");
66340 -+ DBUG_ASSERT(!table_list->next_global);
66341 -+ /*
66342 -+ table_list->table has been closed and freed. Do not reference
66343 -+ uninitialized data. open_tables() could fail.
66344 -+ */
66345 -+ table_list->table= NULL;
66346 -+
66347 -+ bzero((char*) &create_info, sizeof(create_info));
66348 -+ create_info.row_type=ROW_TYPE_NOT_USED;
66349 -+ create_info.default_table_charset=default_charset_info;
66350 -+ /* Force alter table to recreate table */
66351 -+ alter_info.flags= (ALTER_CHANGE_COLUMN | ALTER_RECREATE);
66352 -+ DBUG_RETURN(mysql_alter_table(thd, NullS, NullS, &create_info,
66353 -+ table_list, &alter_info, 0,
66354 -+ (ORDER *) 0, 0));
66355 -+}
66356 -+
66357 -+
66358 -+bool mysql_checksum_table(THD *thd, TABLE_LIST *tables,
66359 -+ HA_CHECK_OPT *check_opt)
66360 -+{
66361 -+ TABLE_LIST *table;
66362 -+ List<Item> field_list;
66363 -+ Item *item;
66364 -+ Protocol *protocol= thd->protocol;
66365 -+ DBUG_ENTER("mysql_checksum_table");
66366 -+
66367 -+ field_list.push_back(item = new Item_empty_string("Table", NAME_LEN*2));
66368 -+ item->maybe_null= 1;
66369 -+ field_list.push_back(item= new Item_int("Checksum", (longlong) 1,
66370 -+ MY_INT64_NUM_DECIMAL_DIGITS));
66371 -+ item->maybe_null= 1;
66372 -+ if (protocol->send_fields(&field_list,
66373 -+ Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
66374 -+ DBUG_RETURN(TRUE);
66375 -+
66376 -+ /* Open one table after the other to keep lock time as short as possible. */
66377 -+ for (table= tables; table; table= table->next_local)
66378 -+ {
66379 -+ char table_name[NAME_LEN*2+2];
66380 -+ TABLE *t;
66381 -+
66382 -+ strxmov(table_name, table->db ,".", table->table_name, NullS);
66383 -+
66384 -+ t= table->table= open_n_lock_single_table(thd, table, TL_READ);
66385 -+ thd->clear_error(); // these errors shouldn't get client
66386 -+
66387 -+ protocol->prepare_for_resend();
66388 -+ protocol->store(table_name, system_charset_info);
66389 -+
66390 -+ if (!t)
66391 -+ {
66392 -+ /* Table didn't exist */
66393 -+ protocol->store_null();
66394 -+ thd->clear_error();
66395 -+ }
66396 -+ else
66397 -+ {
66398 -+ if (t->file->ha_table_flags() & HA_HAS_CHECKSUM &&
66399 -+ !(check_opt->flags & T_EXTEND))
66400 -+ protocol->store((ulonglong)t->file->checksum());
66401 -+ else if (!(t->file->ha_table_flags() & HA_HAS_CHECKSUM) &&
66402 -+ (check_opt->flags & T_QUICK))
66403 -+ protocol->store_null();
66404 -+ else
66405 -+ {
66406 -+ /* calculating table's checksum */
66407 -+ ha_checksum crc= 0;
66408 -+ uchar null_mask=256 - (1 << t->s->last_null_bit_pos);
66409 -+
66410 -+ t->use_all_columns();
66411 -+
66412 -+ if (t->file->ha_rnd_init(1))
66413 -+ protocol->store_null();
66414 -+ else
66415 -+ {
66416 -+ for (;;)
66417 -+ {
66418 -+ if (thd->killed)
66419 -+ {
66420 -+ /*
66421 -+ we've been killed; let handler clean up, and remove the
66422 -+ partial current row from the recordset (embedded lib)
66423 -+ */
66424 -+ t->file->ha_rnd_end();
66425 -+ thd->protocol->remove_last_row();
66426 -+ goto err;
66427 -+ }
66428 -+ ha_checksum row_crc= 0;
66429 -+ int error= t->file->rnd_next(t->record[0]);
66430 -+ if (unlikely(error))
66431 -+ {
66432 -+ if (error == HA_ERR_RECORD_DELETED)
66433 -+ continue;
66434 -+ break;
66435 -+ }
66436 -+ if (t->s->null_bytes)
66437 -+ {
66438 -+ /* fix undefined null bits */
66439 -+ t->record[0][t->s->null_bytes-1] |= null_mask;
66440 -+ if (!(t->s->db_create_options & HA_OPTION_PACK_RECORD))
66441 -+ t->record[0][0] |= 1;
66442 -+
66443 -+ row_crc= my_checksum(row_crc, t->record[0], t->s->null_bytes);
66444 -+ }
66445 -+
66446 -+ for (uint i= 0; i < t->s->fields; i++ )
66447 -+ {
66448 -+ Field *f= t->field[i];
66449 -+
66450 -+ /*
66451 -+ BLOB and VARCHAR have pointers in their field, we must convert
66452 -+ to string; GEOMETRY is implemented on top of BLOB.
66453 -+ BIT may store its data among NULL bits, convert as well.
66454 -+ */
66455 -+ switch (f->type()) {
66456 -+ case MYSQL_TYPE_BLOB:
66457 -+ case MYSQL_TYPE_VARCHAR:
66458 -+ case MYSQL_TYPE_GEOMETRY:
66459 -+ case MYSQL_TYPE_BIT:
66460 -+ {
66461 -+ String tmp;
66462 -+ f->val_str(&tmp);
66463 -+ row_crc= my_checksum(row_crc, (uchar*) tmp.ptr(),
66464 -+ tmp.length());
66465 -+ break;
66466 -+ }
66467 -+ default:
66468 -+ row_crc= my_checksum(row_crc, f->ptr, f->pack_length());
66469 -+ break;
66470 -+ }
66471 -+ }
66472 -+
66473 -+ crc+= row_crc;
66474 -+ }
66475 -+ protocol->store((ulonglong)crc);
66476 -+ t->file->ha_rnd_end();
66477 -+ }
66478 -+ }
66479 -+ thd->clear_error();
66480 -+ close_thread_tables(thd);
66481 -+ table->table=0; // For query cache
66482 -+ }
66483 -+ if (protocol->write())
66484 -+ goto err;
66485 -+ }
66486 -+
66487 -+ my_eof(thd);
66488 -+ DBUG_RETURN(FALSE);
66489 -+
66490 -+ err:
66491 -+ close_thread_tables(thd); // Shouldn't be needed
66492 -+ if (table)
66493 -+ table->table=0;
66494 -+ DBUG_RETURN(TRUE);
66495 -+}
66496 -+
66497 -+static bool check_engine(THD *thd, const char *table_name,
66498 -+ HA_CREATE_INFO *create_info)
66499 -+{
66500 -+ handlerton **new_engine= &create_info->db_type;
66501 -+ handlerton *req_engine= *new_engine;
66502 -+ bool no_substitution=
66503 -+ test(thd->variables.sql_mode & MODE_NO_ENGINE_SUBSTITUTION);
66504 -+ if (!(*new_engine= ha_checktype(thd, ha_legacy_type(req_engine),
66505 -+ no_substitution, 1)))
66506 -+ return TRUE;
66507 -+
66508 -+ if (req_engine && req_engine != *new_engine)
66509 -+ {
66510 -+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
66511 -+ ER_WARN_USING_OTHER_HANDLER,
66512 -+ ER(ER_WARN_USING_OTHER_HANDLER),
66513 -+ ha_resolve_storage_engine_name(*new_engine),
66514 -+ table_name);
66515 -+ }
66516 -+ if (create_info->options & HA_LEX_CREATE_TMP_TABLE &&
66517 -+ ha_check_storage_engine_flag(*new_engine, HTON_TEMPORARY_NOT_SUPPORTED))
66518 -+ {
66519 -+ if (create_info->used_fields & HA_CREATE_USED_ENGINE)
66520 -+ {
66521 -+ my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
66522 -+ ha_resolve_storage_engine_name(*new_engine), "TEMPORARY");
66523 -+ *new_engine= 0;
66524 -+ return TRUE;
66525 -+ }
66526 -+ *new_engine= myisam_hton;
66527 -+ }
66528 -+ return FALSE;
66529 -+}
66530 diff -urN mysql-old/sql/sql_yacc.cc mysql/sql/sql_yacc.cc
66531 --- mysql-old/sql/sql_yacc.cc 2011-05-10 17:45:45.636682376 +0000
66532 +++ mysql/sql/sql_yacc.cc 2011-05-10 17:56:01.630015710 +0000