diff options
Diffstat (limited to 'sql/item_cmpfunc.cc')
-rw-r--r-- | sql/item_cmpfunc.cc | 96 |
1 files changed, 82 insertions, 14 deletions
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index d950c0c1443..3b09da68927 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2012, Oracle and/or its affiliates. - Copyright (c) 2009, 2012 Monty Program Ab + Copyright (c) 2009, 2013, Monty Program Ab. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -914,7 +914,7 @@ get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg, if (save_arena) thd->set_query_arena(save_arena); - cache->store_packed(value); + cache->store_packed(value, item); *cache_arg= cache; *item_arg= cache_arg; } @@ -1353,7 +1353,7 @@ int Arg_comparator::compare_e_row() void Item_func_truth::fix_length_and_dec() { - maybe_null= 0; + set_persist_maybe_null(0); null_value= 0; decimals= 0; max_length= 1; @@ -1865,7 +1865,8 @@ longlong Item_func_eq::val_int() void Item_func_equal::fix_length_and_dec() { Item_bool_func2::fix_length_and_dec(); - maybe_null=null_value=0; + set_persist_maybe_null(0); + null_value= 0; } longlong Item_func_equal::val_int() @@ -2004,7 +2005,7 @@ void Item_func_interval::fix_length_and_dec() } } } - maybe_null= 0; + set_persist_maybe_null(0); max_length= 2; used_tables_cache|= row->used_tables(); not_null_tables_cache= row->not_null_tables(); @@ -2685,7 +2686,7 @@ void Item_func_nullif::fix_length_and_dec() { Item_bool_func2::fix_length_and_dec(); - maybe_null=1; + set_persist_maybe_null(1); if (args[0]) // Only false if EOM { max_length=args[0]->max_length; @@ -4546,6 +4547,8 @@ void Item_cond::update_used_tables() item->update_used_tables(); used_tables_cache|= item->used_tables(); const_item_cache&= item->const_item(); + if (!persistent_maybe_null && item->maybe_null) + maybe_null= 1; } } @@ -4720,10 +4723,9 @@ longlong Item_is_not_null_test::val_int() */ void Item_is_not_null_test::update_used_tables() { + args[0]->update_used_tables(); if (!args[0]->maybe_null) used_tables_cache= 0; /* is always true */ - else - args[0]->update_used_tables(); } @@ -5004,7 +5006,7 @@ Item_func_regex::fix_fields(THD *thd, Item **ref) int comp_res= regcomp(TRUE); if (comp_res == -1) { // Will always return NULL - maybe_null=1; + set_persist_maybe_null(1); fixed= 1; return FALSE; } @@ -5014,7 +5016,7 @@ Item_func_regex::fix_fields(THD *thd, Item **ref) maybe_null= args[0]->maybe_null; } else - maybe_null=1; + set_persist_maybe_null(1); fixed= 1; return FALSE; } @@ -5828,6 +5830,8 @@ void Item_equal::update_used_tables() used_tables_cache|= item->used_tables(); /* see commentary at Item_equal::update_const() */ const_item_cache&= item->const_item() && !item->is_outer_field(); + if (!persistent_maybe_null && item->maybe_null) + maybe_null= 1; } } @@ -6068,23 +6072,87 @@ Item* Item_equal::get_first(JOIN_TAB *context, Item *field_item) } -longlong Item_func_dyncol_exists::val_int() +longlong Item_func_dyncol_check::val_int() { char buff[STRING_BUFFER_USUAL_SIZE]; String tmp(buff, sizeof(buff), &my_charset_bin); DYNAMIC_COLUMN col; String *str; - ulonglong num; enum enum_dyncol_func_result rc; - num= args[1]->val_int(); + str= args[0]->val_str(&tmp); + if (args[0]->null_value) + goto null; + col.length= str->length(); + /* We do not change the string, so could do this trick */ + col.str= (char *)str->ptr(); + rc= mariadb_dyncol_check(&col); + if (rc < 0 && rc != ER_DYNCOL_FORMAT) + { + dynamic_column_error_message(rc); + goto null; + } + null_value= FALSE; + return rc == ER_DYNCOL_OK; + +null: + null_value= TRUE; + return 0; +} + +longlong Item_func_dyncol_exists::val_int() +{ + char buff[STRING_BUFFER_USUAL_SIZE], nmstrbuf[11]; + String tmp(buff, sizeof(buff), &my_charset_bin), + nmbuf(nmstrbuf, sizeof(nmstrbuf), system_charset_info); + DYNAMIC_COLUMN col; + String *str; + LEX_STRING buf, *name= NULL; + ulonglong num= 0; + enum enum_dyncol_func_result rc; + + if (args[1]->result_type() == INT_RESULT) + num= args[1]->val_int(); + else + { + String *nm= args[1]->val_str(&nmbuf); + if (!nm || args[1]->null_value) + { + null_value= 1; + return 1; + } + if (my_charset_same(nm->charset(), &my_charset_utf8_general_ci)) + { + buf.str= (char *) nm->ptr(); + buf.length= nm->length(); + } + else + { + uint strlen; + uint dummy_errors; + buf.str= (char *)sql_alloc((strlen= nm->length() * + my_charset_utf8_general_ci.mbmaxlen + 1)); + if (buf.str) + { + buf.length= + copy_and_convert(buf.str, strlen, &my_charset_utf8_general_ci, + nm->ptr(), nm->length(), nm->charset(), + &dummy_errors); + } + else + buf.length= 0; + } + name= &buf; + } str= args[0]->val_str(&tmp); if (args[0]->null_value || args[1]->null_value || num > UINT_MAX16) goto null; col.length= str->length(); /* We do not change the string, so could do this trick */ col.str= (char *)str->ptr(); - rc= dynamic_column_exists(&col, (uint) num); + rc= ((name == NULL) ? + mariadb_dyncol_exists(&col, (uint) num) : + mariadb_dyncol_exists_named(&col, name)); if (rc < 0) { dynamic_column_error_message(rc); |