diff options
author | unknown <pem@mysql.com> | 2004-02-10 18:44:02 +0100 |
---|---|---|
committer | unknown <pem@mysql.com> | 2004-02-10 18:44:02 +0100 |
commit | 6efd76f317be8fc5fd0a2d144a7c57506723c2ad (patch) | |
tree | f04786f8a211a4c03eab547b7332792201289ac1 /sql | |
parent | 5390589c3c5845f48d3cf251d8b3dad359e0c9b1 (diff) | |
parent | 23103e44b4cc8abfdb1da47214ff2bd7cc2f3fca (diff) | |
download | mariadb-git-6efd76f317be8fc5fd0a2d144a7c57506723c2ad.tar.gz |
Merge 4.1 into 5.0.
BitKeeper/etc/logging_ok:
auto-union
configure.in:
Auto merged
BitKeeper/deleted/.del-opt_ft.cc~2048ffa561f9c59:
Auto merged
BitKeeper/deleted/.del-opt_ft.h~24aac1d29304599a:
Auto merged
client/mysql.cc:
Auto merged
include/my_global.h:
Auto merged
libmysql/libmysql.c:
Auto merged
libmysqld/Makefile.am:
Auto merged
libmysqld/lib_sql.cc:
Auto merged
myisam/mi_check.c:
Auto merged
mysql-test/install_test_db.sh:
Auto merged
mysql-test/r/multi_update.result:
Auto merged
mysql-test/r/mysqldump.result:
Auto merged
mysql-test/r/null.result:
Auto merged
mysql-test/r/show_check.result:
Auto merged
mysql-test/r/subselect.result:
Auto merged
mysql-test/r/symlink.result:
Auto merged
mysql-test/t/multi_update.test:
Auto merged
mysql-test/t/null.test:
Auto merged
mysql-test/t/rpl_until.test:
Auto merged
mysql-test/t/subselect.test:
Auto merged
sql/Makefile.am:
Auto merged
sql/filesort.cc:
Auto merged
sql/item.cc:
Auto merged
sql/item_cmpfunc.cc:
Auto merged
sql/item_cmpfunc.h:
Auto merged
sql/item_create.cc:
Auto merged
sql/item_create.h:
Auto merged
sql/item_func.h:
Auto merged
sql/item_subselect.cc:
Auto merged
sql/item_sum.cc:
Auto merged
sql/item_sum.h:
Auto merged
sql/item_timefunc.cc:
Auto merged
sql/mysqld.cc:
Auto merged
sql/protocol.cc:
Auto merged
sql/repl_failsafe.cc:
Auto merged
sql/set_var.cc:
Auto merged
sql/slave.cc:
Auto merged
sql/slave.h:
Auto merged
sql/sql_acl.cc:
Auto merged
sql/sql_base.cc:
Auto merged
sql/sql_cache.cc:
Auto merged
sql/sql_class.h:
Auto merged
sql/sql_db.cc:
Auto merged
sql/sql_delete.cc:
Auto merged
sql/sql_derived.cc:
Auto merged
sql/sql_insert.cc:
Auto merged
sql/sql_lex.cc:
Auto merged
sql/sql_lex.h:
Auto merged
sql/sql_list.h:
Auto merged
sql/sql_load.cc:
Auto merged
sql/sql_prepare.cc:
Auto merged
sql/sql_select.cc:
Auto merged
sql/sql_select.h:
Auto merged
sql/sql_show.cc:
Auto merged
sql/sql_table.cc:
Auto merged
sql/sql_union.cc:
Auto merged
sql/sql_update.cc:
Auto merged
sql-common/client.c:
Auto merged
Diffstat (limited to 'sql')
96 files changed, 2951 insertions, 1998 deletions
diff --git a/sql/Makefile.am b/sql/Makefile.am index 7353b58df07..045b3e64698 100644 --- a/sql/Makefile.am +++ b/sql/Makefile.am @@ -52,7 +52,7 @@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \ field.h handler.h \ ha_isammrg.h ha_isam.h ha_myisammrg.h\ ha_heap.h ha_myisam.h ha_berkeley.h ha_innodb.h \ - opt_range.h opt_ft.h protocol.h \ + opt_range.h protocol.h \ sql_select.h structs.h table.h sql_udf.h hash_filo.h\ lex.h lex_symbol.h sql_acl.h sql_crypt.h \ log_event.h sql_repl.h slave.h \ @@ -76,7 +76,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc \ procedure.cc item_uniq.cc sql_test.cc \ log.cc log_event.cc init.cc derror.cc sql_acl.cc \ unireg.cc des_key_file.cc \ - time.cc opt_range.cc opt_sum.cc opt_ft.cc \ + time.cc opt_range.cc opt_sum.cc \ records.cc filesort.cc handler.cc \ ha_heap.cc ha_myisam.cc ha_myisammrg.cc \ ha_berkeley.cc ha_innodb.cc \ diff --git a/sql/field.cc b/sql/field.cc index a9029b893e3..d26534b5ac7 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -4055,44 +4055,45 @@ void Field_datetime::sql_type(String &res) const /* Copy a string and fill with space */ -static bool use_conversion(CHARSET_INFO *cs1, CHARSET_INFO *cs2) -{ - return (cs1 != &my_charset_bin) && (cs2 != &my_charset_bin) && (cs1!=cs2); -} - int Field_string::store(const char *from,uint length,CHARSET_INFO *cs) { int error= 0; + uint32 not_used; char buff[80]; String tmpstr(buff,sizeof(buff), &my_charset_bin); + uint copy_length; + /* Convert character set if nesessary */ - if (use_conversion(cs, field_charset)) + if (String::needs_conversion(length, cs, field_charset, ¬_used)) { tmpstr.copy(from, length, cs, field_charset); from= tmpstr.ptr(); length= tmpstr.length(); } - if (length <= field_length) - { - memcpy(ptr,from,length); - if (length < field_length) - field_charset->cset->fill(field_charset,ptr+length,field_length-length, - ' '); - } - else - { - memcpy(ptr,from,field_length); - if (current_thd->count_cuted_fields) - { // Check if we loosed some info - const char *end=from+length; - from+= field_length; - from+= field_charset->cset->scan(field_charset, from, end, - MY_SEQ_SPACES); - if (from != end) - { - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED); - error=1; - } + + /* + Make sure we don't break a multibyte sequence + as well as don't copy a malformed data. + */ + copy_length= field_charset->cset->wellformedlen(field_charset, + from,from+length, + field_length/ + field_charset->mbmaxlen); + memcpy(ptr,from,copy_length); + if (copy_length < field_length) // Append spaces if shorter + field_charset->cset->fill(field_charset,ptr+copy_length, + field_length-copy_length,' '); + + if ((copy_length < length) && current_thd->count_cuted_fields) + { // Check if we loosed some info + const char *end=from+length; + from+= copy_length; + from+= field_charset->cset->scan(field_charset, from, end, + MY_SEQ_SPACES); + if (from != end) + { + set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED); + error=1; } } return error; @@ -4251,10 +4252,12 @@ uint Field_string::max_packed_col_length(uint max_length) int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs) { int error= 0; + uint32 not_used; char buff[80]; String tmpstr(buff,sizeof(buff), &my_charset_bin); + /* Convert character set if nesessary */ - if (use_conversion(cs, field_charset)) + if (String::needs_conversion(length, cs, field_charset, ¬_used)) { tmpstr.copy(from, length, cs, field_charset); from= tmpstr.ptr(); @@ -4470,7 +4473,7 @@ Field_blob::Field_blob(char *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, :Field_str(ptr_arg, (1L << min(blob_pack_length,3)*8)-1L, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, table_arg, cs), - geom_flag(true), packlength(blob_pack_length) + packlength(blob_pack_length) { flags|= BLOB_FLAG; if (table) @@ -4482,19 +4485,9 @@ void Field_blob::store_length(uint32 number) { switch (packlength) { case 1: - if (number > 255) - { - number=255; - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED); - } ptr[0]= (uchar) number; break; case 2: - if (number > (uint16) ~0) - { - number= (uint16) ~0; - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED); - } #ifdef WORDS_BIGENDIAN if (table->db_low_byte_first) { @@ -4505,11 +4498,6 @@ void Field_blob::store_length(uint32 number) shortstore(ptr,(unsigned short) number); break; case 3: - if (number > (uint32) (1L << 24)) - { - number= (uint32) (1L << 24)-1L; - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED); - } int3store(ptr,number); break; case 4: @@ -4567,21 +4555,36 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs) } else { + bool was_conversion; char buff[80]; String tmpstr(buff,sizeof(buff), &my_charset_bin); + uint copy_length; + uint32 not_used; + /* Convert character set if nesessary */ - if (use_conversion(cs, field_charset)) + if ((was_conversion= String::needs_conversion(length, cs, field_charset, + ¬_used))) { tmpstr.copy(from, length, cs, field_charset); from= tmpstr.ptr(); length= tmpstr.length(); } - Field_blob::store_length(length); - if (table->copy_blobs || length <= MAX_FIELD_WIDTH) + + copy_length= max_data_length(); + if (copy_length > length) + copy_length= length; + copy_length= field_charset->cset->wellformedlen(field_charset, + from,from+copy_length, + field_length); + if (copy_length < length) + set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED); + + Field_blob::store_length(copy_length); + if (was_conversion || table->copy_blobs || copy_length <= MAX_FIELD_WIDTH) { // Must make a copy if (from != value.ptr()) // For valgrind { - value.copy(from,length,charset()); + value.copy(from,copy_length,charset()); from=value.ptr(); } } @@ -4705,6 +4708,7 @@ void Field_blob::get_key_image(char *buff,uint length, uint32 blob_length= get_length(ptr); char *blob; +#ifdef HAVE_SPATIAL if (type == itMBR) { if (!blob_length) @@ -4721,6 +4725,7 @@ void Field_blob::get_key_image(char *buff,uint length, float8store(buff+24, mbr.ymax); return; } +#endif /*HAVE_SPATIAL*/ if ((uint32) length > blob_length) { @@ -4930,6 +4935,7 @@ uint Field_blob::max_packed_col_length(uint max_length) return (max_length > 255 ? 2 : 1)+max_length; } +#ifdef HAVE_SPATIAL void Field_geom::get_key_image(char *buff, uint length, CHARSET_INFO *cs, imagetype type) @@ -5013,6 +5019,7 @@ int Field_geom::store(const char *from, uint length, CHARSET_INFO *cs) return 0; } +#endif /*HAVE_SPATIAL*/ /**************************************************************************** ** enum type. @@ -5077,10 +5084,12 @@ void Field_enum::store_type(ulonglong value) int Field_enum::store(const char *from,uint length,CHARSET_INFO *cs) { int err= 0; + uint32 not_used; char buff[80]; String tmpstr(buff,sizeof(buff), &my_charset_bin); + /* Convert character set if nesessary */ - if (use_conversion(cs, field_charset)) + if (String::needs_conversion(length, cs, field_charset, ¬_used)) { tmpstr.copy(from, length, cs, field_charset); from= tmpstr.ptr(); @@ -5257,11 +5266,12 @@ int Field_set::store(const char *from,uint length,CHARSET_INFO *cs) int err= 0; char *not_used; uint not_used2; + uint32 not_used_offset; char buff[80]; String tmpstr(buff,sizeof(buff), &my_charset_bin); /* Convert character set if nesessary */ - if (use_conversion(cs, field_charset)) + if (String::needs_conversion(length, cs, field_charset, ¬_used_offset)) { tmpstr.copy(from, length, cs, field_charset); from= tmpstr.ptr(); @@ -5488,10 +5498,12 @@ Field *make_field(char *ptr, uint32 field_length, f_packtype(pack_flag), field_length); +#ifdef HAVE_SPATIAL if (f_is_geom(pack_flag)) return new Field_geom(ptr,null_pos,null_bit, unireg_check, field_name, table, pack_length, geom_type); +#endif if (f_is_blob(pack_flag)) return new Field_blob(ptr,null_pos,null_bit, unireg_check, field_name, table, @@ -5609,16 +5621,16 @@ create_field::create_field(Field *old_field,Field *orig_field) case 3: sql_type= FIELD_TYPE_MEDIUM_BLOB; break; default: sql_type= FIELD_TYPE_LONG_BLOB; break; } - length /= charset->mbmaxlen; // QQ: Probably not needed + length=(length+charset->mbmaxlen-1)/charset->mbmaxlen; // QQ: Probably not needed break; case FIELD_TYPE_STRING: case FIELD_TYPE_VAR_STRING: - length /= charset->mbmaxlen; + length=(length+charset->mbmaxlen-1)/charset->mbmaxlen; break; default: break; } - + decimals= old_field->decimals(); if (sql_type == FIELD_TYPE_STRING) { @@ -5651,10 +5663,12 @@ create_field::create_field(Field *old_field,Field *orig_field) def=new Item_string(pos,tmp.length(), charset); } } +#ifdef HAVE_SPATIAL if (sql_type == FIELD_TYPE_GEOMETRY) { geom_type= ((Field_geom*)old_field)->geom_type; } +#endif } diff --git a/sql/field.h b/sql/field.h index e3b4bf29fb8..b62b7a7859e 100644 --- a/sql/field.h +++ b/sql/field.h @@ -913,7 +913,6 @@ public: class Field_blob :public Field_str { - bool geom_flag; protected: uint packlength; String value; // For temporaries @@ -926,7 +925,7 @@ public: struct st_table *table_arg, CHARSET_INFO *cs) :Field_str((char*) 0,len_arg, maybe_null_arg ? (uchar*) "": 0,0, NONE, field_name_arg, table_arg, cs), - geom_flag(true), packlength(4) + packlength(4) { flags|= BLOB_FLAG; } @@ -950,6 +949,15 @@ public: void sort_string(char *buff,uint length); uint32 pack_length() const { return (uint32) (packlength+table->blob_ptr_size); } + uint32 max_data_length() const + { + switch (packlength) { + case 1: return 255; + case 2: return (uint32) 0xFFFFL; + case 3: return (uint32) 0xFFFFFF; + default: return (uint32) 0xFFFFFFFF; + } + } void reset(void) { bzero(ptr, packlength+sizeof(char*)); } void reset_fields() { bzero((char*) &value,sizeof(value)); } void store_length(uint32 number); @@ -1001,7 +1009,7 @@ public: field_cast_enum field_cast_type() { return FIELD_CAST_BLOB; } }; - +#ifdef HAVE_SPATIAL class Field_geom :public Field_blob { public: enum geometry_type geom_type; @@ -1029,7 +1037,7 @@ public: void set_key_image(char *buff,uint length, CHARSET_INFO *cs); field_cast_enum field_cast_type() { return FIELD_CAST_GEOM; } }; - +#endif /*HAVE_SPATIAL*/ class Field_enum :public Field_str { protected: diff --git a/sql/filesort.cc b/sql/filesort.cc index 1d06846e8b0..d09b8936d42 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -423,7 +423,7 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select, } if (error == 0) param->examined_rows++; - if (error == 0 && (!select || select->skipp_record() == 0)) + if (error == 0 && (!select || select->skip_record() == 0)) { if (idx == param->keys) { diff --git a/sql/gen_lex_hash.cc b/sql/gen_lex_hash.cc index 7126b7ee577..6df7d867a4d 100644 --- a/sql/gen_lex_hash.cc +++ b/sql/gen_lex_hash.cc @@ -81,9 +81,10 @@ TODO: #endif #include <my_getopt.h> #include "mysql_version.h" +#include "mysql_priv.h" #include "lex.h" -static struct my_option my_long_options[] = +struct my_option my_long_options[] = { {"help", '?', "Display help and exit", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc index ae0267b98f3..c1228cbd319 100644 --- a/sql/ha_heap.cc +++ b/sql/ha_heap.cc @@ -40,6 +40,7 @@ int ha_heap::open(const char *name, int mode, uint test_if_locked) if (!create(name, table, &create_info)) file= heap_open(name, mode); } + ref_length= sizeof(HEAP_PTR); return (file ? 0 : 1); } @@ -335,7 +336,6 @@ int ha_heap::create(const char *name, TABLE *table_arg, my_free((gptr) keydef, MYF(0)); if (file) info(HA_STATUS_NO_LOCK | HA_STATUS_CONST | HA_STATUS_VARIABLE); - ref_length= sizeof(HEAP_PTR); return (error); } diff --git a/sql/item.cc b/sql/item.cc index acb2fdbb40a..78d4224cac8 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -72,18 +72,18 @@ Item::Item(): Used for duplicating lists in processing queries with temporary tables */ -Item::Item(THD *thd, Item &item): - str_value(item.str_value), - name(item.name), - max_length(item.max_length), - marker(item.marker), - decimals(item.decimals), - maybe_null(item.maybe_null), - null_value(item.null_value), - unsigned_flag(item.unsigned_flag), - with_sum_func(item.with_sum_func), - fixed(item.fixed), - collation(item.collation) +Item::Item(THD *thd, Item *item): + str_value(item->str_value), + name(item->name), + max_length(item->max_length), + marker(item->marker), + decimals(item->decimals), + maybe_null(item->maybe_null), + null_value(item->null_value), + unsigned_flag(item->unsigned_flag), + with_sum_func(item->with_sum_func), + fixed(item->fixed), + collation(item->collation) { next= thd->free_list; // Put in free list thd->free_list= this; @@ -111,12 +111,12 @@ Item_ident::Item_ident(const char *db_name_par,const char *table_name_par, } // Constructor used by Item_field & Item_ref (see Item comment) -Item_ident::Item_ident(THD *thd, Item_ident &item): +Item_ident::Item_ident(THD *thd, Item_ident *item): Item(thd, item), - db_name(item.db_name), - table_name(item.table_name), - field_name(item.field_name), - depended_from(item.depended_from) + db_name(item->db_name), + table_name(item->table_name), + field_name(item->field_name), + depended_from(item->depended_from) {} bool Item_ident::remove_dependence_processor(byte * arg) @@ -326,10 +326,10 @@ Item_field::Item_field(Field *f) :Item_ident(NullS,f->table_name,f->field_name) } // Constructor need to process subselect with temporary tables (see Item) -Item_field::Item_field(THD *thd, Item_field &item) +Item_field::Item_field(THD *thd, Item_field *item) :Item_ident(thd, item), - field(item.field), - result_field(item.result_field) + field(item->field), + result_field(item->result_field) { collation.set(DERIVATION_IMPLICIT); } @@ -485,7 +485,7 @@ table_map Item_field::used_tables() const Item *Item_field::get_tmp_table_item(THD *thd) { - Item_field *new_item= new Item_field(thd, *this); + Item_field *new_item= new Item_field(thd, this); if (new_item) new_item->field= new_item->result_field; return new_item; @@ -950,6 +950,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) Item_ref *rf; *ref= rf= new Item_ref(last->ref_pointer_array + counter, + ref, (char *)table_name, (char *)field_name); if (!rf) @@ -966,7 +967,8 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) if (last->having_fix_field) { Item_ref *rf; - *ref= rf= new Item_ref((where->db[0]?where->db:0), + *ref= rf= new Item_ref(ref, *ref, + (where->db[0]?where->db:0), (char *)where->alias, (char *)field_name); if (!rf) @@ -992,6 +994,11 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) return 0; } +void Item_field::cleanup() +{ + Item_ident::cleanup(); + field= result_field= 0; +} void Item::init_make_field(Send_field *tmp_field, enum enum_field_types field_type) @@ -1631,6 +1638,14 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) } +void Item_ref::cleanup() +{ + Item_ident::cleanup(); + if (hook_ptr) + *hook_ptr= orig_item; +} + + void Item_ref::print(String *str) { if (ref && *ref) @@ -1794,17 +1809,9 @@ Item *resolve_const_item(Item *item,Item *comp_item) String tmp(buff,sizeof(buff),&my_charset_bin),*result; result=item->val_str(&tmp); if (item->null_value) - { -#ifdef DELETE_ITEMS - delete item; -#endif return new Item_null(name); - } uint length=result->length(); char *tmp_str=sql_strmake(result->ptr(),length); -#ifdef DELETE_ITEMS - delete item; -#endif return new Item_string(name,tmp_str,length,result->charset()); } if (res_type == INT_RESULT) @@ -1812,9 +1819,6 @@ Item *resolve_const_item(Item *item,Item *comp_item) longlong result=item->val_int(); uint length=item->max_length; bool null_value=item->null_value; -#ifdef DELETE_ITEMS - delete item; -#endif return (null_value ? (Item*) new Item_null(name) : (Item*) new Item_int(name,result,length)); } @@ -1823,9 +1827,6 @@ Item *resolve_const_item(Item *item,Item *comp_item) double result=item->val(); uint length=item->max_length,decimals=item->decimals; bool null_value=item->null_value; -#ifdef DELETE_ITEMS - delete item; -#endif return (null_value ? (Item*) new Item_null(name) : (Item*) new Item_real(name,result,decimals,length)); } @@ -1897,7 +1898,6 @@ void Item_cache_int::store(Item *item) { value= item->val_int_result(); null_value= item->null_value; - collation.set(item->collation); } @@ -1905,7 +1905,6 @@ void Item_cache_real::store(Item *item) { value= item->val_result(); null_value= item->null_value; - collation.set(item->collation); } @@ -1928,7 +1927,6 @@ void Item_cache_str::store(Item *item) value_buff.copy(*value); value= &value_buff; } - collation.set(item->collation); } @@ -2042,7 +2040,8 @@ void Item_cache_row::bring_value() Item_type_holder::Item_type_holder(THD *thd, Item *item) - :Item(thd, *item), item_type(item->result_type()) + :Item(thd, item), item_type(item->result_type()), + orig_type(item_type) { DBUG_ASSERT(item->fixed); diff --git a/sql/item.h b/sql/item.h index 584fad9eede..35e5d4a3666 100644 --- a/sql/item.h +++ b/sql/item.h @@ -125,8 +125,8 @@ public: top AND/OR ctructure of WHERE clause to protect it of optimisation changes in prepared statements */ - Item(THD *thd, Item &item); - virtual ~Item() { name=0; cleanup(); } /*lint -e1509 */ + Item(THD *thd, Item *item); + virtual ~Item() { name=0; } /*lint -e1509 */ void set_name(const char *str,uint length, CHARSET_INFO *cs); void init_make_field(Send_field *tmp_field,enum enum_field_types type); virtual void cleanup() { fixed=0; } @@ -205,6 +205,7 @@ public: virtual Item *get_tmp_table_item(THD *thd) { return copy_or_same(thd); } CHARSET_INFO *default_charset() const; + virtual CHARSET_INFO *compare_collation() { return NULL; } virtual bool walk(Item_processor processor, byte *arg) { @@ -231,6 +232,10 @@ public: /* Used in sql_select.cc:eliminate_not_funcs() */ virtual Item *neg_transformer() { return NULL; } + void delete_self() + { + cleanup(); + delete this; }; @@ -339,7 +344,7 @@ public: st_select_lex *depended_from; Item_ident(const char *db_name_par,const char *table_name_par, const char *field_name_par); - Item_ident(THD *thd, Item_ident &item); + Item_ident(THD *thd, Item_ident *item); const char *full_name() const; bool remove_dependence_processor(byte * arg); @@ -358,7 +363,7 @@ public: :Item_ident(db_par,table_name_par,field_name_par),field(0),result_field(0) { collation.set(DERIVATION_IMPLICIT); } // Constructor need to process subselect with temporary tables (see Item) - Item_field(THD *thd, Item_field &item); + Item_field(THD *thd, Item_field *item); Item_field(Field *field); enum Type type() const { return FIELD_ITEM; } bool eq(const Item *item, bool binary_cmp) const; @@ -389,6 +394,7 @@ public: bool get_time(TIME *ltime); bool is_null() { return field->is_null(); } Item *get_tmp_table_item(THD *thd); + void cleanup(); friend class Item_default_value; friend class Item_insert_value; }; @@ -576,7 +582,7 @@ public: CHARSET_INFO *cs, Derivation dv= DERIVATION_COERCIBLE) { collation.set(cs, dv); - str_value.set(str,length,cs); + str_value.set_or_copy_aligned(str,length,cs); /* We have to have a different max_length than 'length' here to ensure that we get the right length if we do use the item @@ -592,12 +598,11 @@ public: CHARSET_INFO *cs, Derivation dv= DERIVATION_COERCIBLE) { collation.set(cs, dv); - str_value.set(str,length,cs); + str_value.set_or_copy_aligned(str,length,cs); max_length= str_value.numchars()*cs->mbmaxlen; set_name(name_par,0,cs); decimals=NOT_FIXED_DEC; } - ~Item_string() {} enum Type type() const { return STRING_ITEM; } double val() { @@ -664,7 +669,6 @@ class Item_varbinary :public Item { public: Item_varbinary(const char *str,uint str_length); - ~Item_varbinary() {} enum Type type() const { return VARBIN_ITEM; } double val() { return (double) Item_varbinary::val_int(); } longlong val_int(); @@ -681,8 +685,8 @@ public: Field *result_field; /* Save result here */ Item_result_field() :result_field(0) {} // Constructor used for Item_sum/Item_cond_and/or (see Item comment) - Item_result_field(THD *thd, Item_result_field &item): - Item(thd, item), result_field(item.result_field) + Item_result_field(THD *thd, Item_result_field *item): + Item(thd, item), result_field(item->result_field) {} ~Item_result_field() {} /* Required with gcc 2.95 */ Field *get_tmp_table_field() { return result_field; } @@ -701,20 +705,25 @@ public: class Item_ref :public Item_ident { public: - Field *result_field; /* Save result here */ + Field *result_field; /* Save result here */ Item **ref; - Item_ref(const char *db_par, const char *table_name_par, - const char *field_name_par) - :Item_ident(db_par,table_name_par,field_name_par),ref(0) {} - Item_ref(Item **item, const char *table_name_par, const char *field_name_par) - :Item_ident(NullS,table_name_par,field_name_par),ref(item) {} + Item **hook_ptr; /* These two to restore */ + Item *orig_item; /* things in 'cleanup()' */ + Item_ref(Item **hook, Item *original,const char *db_par, + const char *table_name_par, const char *field_name_par) + :Item_ident(db_par,table_name_par,field_name_par),ref(0), hook_ptr(hook), + orig_item(original) {} + Item_ref(Item **item, Item **hook, + const char *table_name_par, const char *field_name_par) + :Item_ident(NullS,table_name_par,field_name_par), + ref(item), hook_ptr(hook), orig_item(hook ? *hook:0) {} // Constructor need to process subselect with temporary tables (see Item) - Item_ref(THD *thd, Item_ref &item) - :Item_ident(thd, item), ref(item.ref) {} + Item_ref(THD *thd, Item_ref *item, Item **hook) + :Item_ident(thd, item), ref(item->ref), + hook_ptr(hook), orig_item(hook ? *hook : 0) {} enum Type type() const { return REF_ITEM; } bool eq(const Item *item, bool binary_cmp) const { return ref && (*ref)->eq(item, binary_cmp); } - ~Item_ref() { if (ref && (*ref) && (*ref) != this) delete *ref; } double val() { double tmp=(*ref)->val_result(); @@ -759,6 +768,7 @@ public: } Item *real_item() { return *ref; } void print(String *str); + void cleanup(); }; class Item_in_subselect; @@ -769,7 +779,7 @@ protected: public: Item_ref_null_helper(Item_in_subselect* master, Item **item, const char *table_name_par, const char *field_name_par): - Item_ref(item, table_name_par, field_name_par), owner(master) {} + Item_ref(item, NULL, table_name_par, field_name_par), owner(master) {} double val(); longlong val_int(); String* val_str(String* s); @@ -833,7 +843,6 @@ public: name=item->name; cached_field_type= item->field_type(); } - ~Item_copy_string() { delete item; } enum Type type() const { return COPY_STR_ITEM; } enum Item_result result_type () const { return STRING_RESULT; } enum_field_types field_type() const { return cached_field_type; } @@ -977,13 +986,15 @@ public: void set_used_tables(table_map map) { used_table_map= map; } virtual bool allocate(uint i) { return 0; }; - virtual bool setup(Item *item) { example= item; return 0; }; - virtual void store(Item *)= 0; - void set_len_n_dec(uint32 max_len, uint8 dec) + virtual bool setup(Item *item) { - max_length= max_len; - decimals= dec; - } + example= item; + max_length= item->max_length; + decimals= item->decimals; + collation.set(item->collation); + return 0; + }; + virtual void store(Item *)= 0; enum Type type() const { return CACHE_ITEM; } static Item_cache* get_cache(Item_result type); table_map used_tables() const { return used_table_map; } @@ -1008,7 +1019,7 @@ class Item_cache_real: public Item_cache double value; public: Item_cache_real(): Item_cache() {} - + void store(Item *item); double val() { return value; } longlong val_int() { return (longlong) (value+(value > 0 ? 0.5 : -0.5)); } @@ -1081,6 +1092,11 @@ public: bool check_cols(uint c); bool null_inside(); void bring_value(); + void cleanup() + { + Item_cache::cleanup(); + values= 0; + } }; @@ -1091,6 +1107,7 @@ class Item_type_holder: public Item { protected: Item_result item_type; + Item_result orig_type; Field *field_example; public: Item_type_holder(THD*, Item*); @@ -1102,6 +1119,11 @@ public: String *val_str(String*); bool join_types(THD *thd, Item *); Field *example() { return field_example; } + void cleanup() + { + Item::cleanup(); + item_type= orig_type; + } }; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index a79ef21e97a..4046a4d6414 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -496,7 +496,6 @@ longlong Item_func_eq::val_int() return value == 0 ? 1 : 0; } - /* Same as Item_func_eq, but NULL = NULL */ void Item_func_equal::fix_length_and_dec() @@ -1652,32 +1651,25 @@ longlong Item_func_bit_and::val_int() return (longlong) (arg1 & arg2); } -Item_cond::Item_cond(THD *thd, Item_cond &item) +Item_cond::Item_cond(THD *thd, Item_cond *item) :Item_bool_func(thd, item), - abort_on_null(item.abort_on_null), - and_tables_cache(item.and_tables_cache) + abort_on_null(item->abort_on_null), + and_tables_cache(item->and_tables_cache) { /* - here should be following text: - - List_iterator_fast<Item*> li(item.list); - while(Item *it= li++) - list.push_back(it); - - but it do not need, - because this constructor used only for AND/OR and - argument list will be copied by copy_andor_arguments call + item->list will be copied by copy_andor_arguments() call */ - } + void Item_cond::copy_andor_arguments(THD *thd, Item_cond *item) { List_iterator_fast<Item> li(item->list); - while(Item *it= li++) + while (Item *it= li++) list.push_back(it->copy_andor_structure(thd)); } + bool Item_cond::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) { @@ -1704,9 +1696,6 @@ Item_cond::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) { // Identical function li.replace(((Item_cond*) item)->list); ((Item_cond*) item)->list.empty(); -#ifdef DELETE_ITEMS - delete (Item_cond*) item; -#endif item= *li.ref(); // new current item } if (abort_on_null) @@ -1754,7 +1743,7 @@ void Item_cond::split_sum_func(Item **ref_pointer_array, List<Item> &fields) uint el= fields.elements; fields.push_front(item); ref_pointer_array[el]= item; - li.replace(new Item_ref(ref_pointer_array + el, 0, item->name)); + li.replace(new Item_ref(ref_pointer_array + el, li.ref(), 0, item->name)); } item->update_used_tables(); used_tables_cache|=item->used_tables(); @@ -2198,11 +2187,11 @@ void Item_func_like::turboBM_compute_suffixes(int *suff) int f = 0; int g = plm1; int *const splm1 = suff + plm1; - CHARSET_INFO *cs=system_charset_info; // QQ Needs to be fixed + CHARSET_INFO *cs= cmp.cmp_collation.collation; *splm1 = pattern_len; - if (cmp.cmp_collation.collation == &my_charset_bin) + if (cs == &my_charset_bin) { int i; for (i = pattern_len - 2; i >= 0; i--) @@ -2300,12 +2289,12 @@ void Item_func_like::turboBM_compute_bad_character_shifts() int *end = bmBc + alphabet_size; int j; const int plm1 = pattern_len - 1; - CHARSET_INFO *cs=system_charset_info; // QQ Needs to be fixed + CHARSET_INFO *cs= cmp.cmp_collation.collation; for (i = bmBc; i < end; i++) *i = pattern_len; - if (cmp.cmp_collation.collation == &my_charset_bin) + if (cs == &my_charset_bin) { for (j = 0; j < plm1; j++) bmBc[(uint) (uchar) pattern[j]] = plm1 - j; @@ -2330,13 +2319,13 @@ bool Item_func_like::turboBM_matches(const char* text, int text_len) const int shift = pattern_len; int j = 0; int u = 0; - CHARSET_INFO *cs= cmp.cmp_collation.collation; // QQ Needs to be fixed + CHARSET_INFO *cs= cmp.cmp_collation.collation; const int plm1= pattern_len - 1; const int tlmpl= text_len - pattern_len; /* Searching */ - if (cmp.cmp_collation.collation == &my_charset_bin) + if (cs == &my_charset_bin) { while (j <= tlmpl) { diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 541bc47557d..7e1749ef7a0 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -82,7 +82,7 @@ public: Item_bool_func() :Item_int_func() {} Item_bool_func(Item *a) :Item_int_func(a) {} Item_bool_func(Item *a,Item *b) :Item_int_func(a,b) {} - Item_bool_func(THD *thd, Item_bool_func &item) :Item_int_func(thd, item) {} + Item_bool_func(THD *thd, Item_bool_func *item) :Item_int_func(thd, item) {} void fix_length_and_dec() { decimals=0; max_length=1; } }; @@ -191,17 +191,26 @@ public: bool have_rev_func() const { return rev_functype() != UNKNOWN_FUNC; } void print(String *str) { Item_func::print_op(str); } bool is_null() { return test(args[0]->is_null() || args[1]->is_null()); } + CHARSET_INFO *compare_collation() { return cmp.cmp_collation.collation; } friend class Arg_comparator; }; class Item_bool_rowready_func2 :public Item_bool_func2 { + Item *orig_a, *orig_b; /* propagate_const can change parameters */ public: - Item_bool_rowready_func2(Item *a,Item *b) :Item_bool_func2(a,b) + Item_bool_rowready_func2(Item *a,Item *b) :Item_bool_func2(a,b), + orig_a(a), orig_b(b) { allowed_arg_cols= a->cols(); } + void cleanup() + { + Item_bool_func2::cleanup(); + tmp_arg[0]= orig_a; + tmp_arg[1]= orig_b; + } }; class Item_func_not :public Item_bool_func @@ -332,6 +341,7 @@ public: const char *func_name() const { return "between"; } void fix_length_and_dec(); void print(String *str); + CHARSET_INFO *compare_collation() { return cmp_collation.collation; } }; @@ -471,6 +481,7 @@ public: const char *func_name() const { return "case"; } void print(String *str); Item *find_item(String *str); + CHARSET_INFO *compare_collation() { return cmp_collation.collation; } }; @@ -705,10 +716,6 @@ class Item_func_in :public Item_int_func } longlong val_int(); void fix_length_and_dec(); - ~Item_func_in() - { - cleanup(); /* This is not called by Item::~Item() */ - } void cleanup() { delete array; @@ -722,6 +729,7 @@ class Item_func_in :public Item_int_func enum Functype functype() const { return IN_FUNC; } const char *func_name() const { return " IN "; } bool nulls_in_row(); + CHARSET_INFO *compare_collation() { return cmp_collation.collation; } }; /* Functions used by where clause */ @@ -762,6 +770,7 @@ public: table_map not_null_tables() const { return 0; } optimize_type select_optimize() const { return OPTIMIZE_NULL; } Item *neg_transformer(); + CHARSET_INFO *compare_collation() { return args[0]->collation.collation; } }; /* Functions used by HAVING for rewriting IN subquery */ @@ -796,6 +805,7 @@ public: table_map not_null_tables() const { return 0; } Item *neg_transformer(); void print(String *str); + CHARSET_INFO *compare_collation() { return args[0]->collation.collation; } }; @@ -850,6 +860,7 @@ public: bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref); const char *func_name() const { return "regexp"; } void print(String *str) { print_op(str); } + CHARSET_INFO *compare_collation() { return cmp_collation.collation; } }; #else @@ -885,10 +896,9 @@ public: list.push_back(i1); list.push_back(i2); } - Item_cond(THD *thd, Item_cond &item); + Item_cond(THD *thd, Item_cond *item); Item_cond(List<Item> &nlist) :Item_bool_func(), list(nlist), abort_on_null(0) {} - ~Item_cond() { list.delete_elements(); } bool add(Item *item) { return list.push_back(item); } bool fix_fields(THD *, struct st_table_list *, Item **ref); @@ -911,7 +921,7 @@ class Item_cond_and :public Item_cond public: Item_cond_and() :Item_cond() {} Item_cond_and(Item *i1,Item *i2) :Item_cond(i1,i2) {} - Item_cond_and(THD *thd, Item_cond_and &item) :Item_cond(thd, item) {} + Item_cond_and(THD *thd, Item_cond_and *item) :Item_cond(thd, item) {} Item_cond_and(List<Item> &list): Item_cond(list) {} enum Functype functype() const { return COND_AND_FUNC; } longlong val_int(); @@ -919,7 +929,7 @@ public: Item* copy_andor_structure(THD *thd) { Item_cond_and *item; - if((item= new Item_cond_and(thd, *this))) + if ((item= new Item_cond_and(thd, this))) item->copy_andor_arguments(thd, this); return item; } @@ -931,7 +941,7 @@ class Item_cond_or :public Item_cond public: Item_cond_or() :Item_cond() {} Item_cond_or(Item *i1,Item *i2) :Item_cond(i1,i2) {} - Item_cond_or(THD *thd, Item_cond_or &item) :Item_cond(thd, item) {} + Item_cond_or(THD *thd, Item_cond_or *item) :Item_cond(thd, item) {} Item_cond_or(List<Item> &list): Item_cond(list) {} enum Functype functype() const { return COND_OR_FUNC; } longlong val_int(); @@ -940,7 +950,7 @@ public: Item* copy_andor_structure(THD *thd) { Item_cond_or *item; - if((item= new Item_cond_or(thd, *this))) + if ((item= new Item_cond_or(thd, this))) item->copy_andor_arguments(thd, this); return item; } diff --git a/sql/item_create.cc b/sql/item_create.cc index cccbf6e4226..6519e242465 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -478,6 +478,7 @@ Item *create_func_quote(Item* a) return new Item_func_quote(a); } +#ifdef HAVE_SPATIAL Item *create_func_as_wkt(Item *a) { return new Item_func_as_wkt(a); @@ -637,6 +638,7 @@ Item *create_func_point(Item *a, Item *b) { return new Item_func_point(a, b); } +#endif /*HAVE_SPATIAL*/ Item *create_func_crc32(Item* a) { diff --git a/sql/item_create.h b/sql/item_create.h index b445eab3bac..5dc53fb04b8 100644 --- a/sql/item_create.h +++ b/sql/item_create.h @@ -98,6 +98,8 @@ Item *create_func_is_free_lock(Item* a); Item *create_func_is_used_lock(Item* a); Item *create_func_quote(Item* a); +#ifdef HAVE_SPATIAL + Item *create_func_geometry_from_text(Item *a); Item *create_func_as_wkt(Item *a); Item *create_func_as_wkb(Item *a); @@ -137,6 +139,8 @@ Item *create_func_numgeometries(Item *a); Item *create_func_point(Item *a, Item *b); +#endif /*HAVE_SPATIAL*/ + Item *create_func_compress(Item *a); Item *create_func_uncompress(Item *a); Item *create_func_uncompressed_length(Item *a); diff --git a/sql/item_func.cc b/sql/item_func.cc index 41da8e35419..d1d03b21eed 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -133,13 +133,13 @@ Item_func::Item_func(List<Item> &list) set_arguments(list); } -Item_func::Item_func(THD *thd, Item_func &item) +Item_func::Item_func(THD *thd, Item_func *item) :Item_result_field(thd, item), - allowed_arg_cols(item.allowed_arg_cols), - arg_count(item.arg_count), - used_tables_cache(item.used_tables_cache), - not_null_tables_cache(item.not_null_tables_cache), - const_item_cache(item.const_item_cache) + allowed_arg_cols(item->allowed_arg_cols), + arg_count(item->arg_count), + used_tables_cache(item->used_tables_cache), + not_null_tables_cache(item->not_null_tables_cache), + const_item_cache(item->const_item_cache) { if (arg_count) { @@ -150,7 +150,7 @@ Item_func::Item_func(THD *thd, Item_func &item) if (!(args=(Item**) thd->alloc(sizeof(Item*)*arg_count))) return; } - memcpy((char*) args, (char*) item.args, sizeof(Item*)*arg_count); + memcpy((char*) args, (char*) item->args, sizeof(Item*)*arg_count); } } @@ -255,7 +255,7 @@ void Item_func::split_sum_func(Item **ref_pointer_array, List<Item> &fields) uint el= fields.elements; fields.push_front(item); ref_pointer_array[el]= item; - *arg= new Item_ref(ref_pointer_array + el, 0, item->name); + *arg= new Item_ref(ref_pointer_array + el, arg, 0, item->name); } } } @@ -1071,7 +1071,8 @@ String *Item_func_min_max::val_str(String *str) } } } - res->set_charset(collation.collation); + if (res) // If !NULL + res->set_charset(collation.collation); return res; } case ROW_RESULT: @@ -1561,7 +1562,7 @@ udf_handler::fix_fields(THD *thd, TABLE_LIST *tables, Item_result_field *func, if ((error=(uchar) init(&initid, &f_args, thd->net.last_error))) { my_printf_error(ER_CANT_INITIALIZE_UDF,ER(ER_CANT_INITIALIZE_UDF),MYF(0), - u_d->name,thd->net.last_error); + u_d->name.str, thd->net.last_error); free_udf(u_d); DBUG_RETURN(1); } @@ -1574,7 +1575,7 @@ udf_handler::fix_fields(THD *thd, TABLE_LIST *tables, Item_result_field *func, if (error) { my_printf_error(ER_CANT_INITIALIZE_UDF,ER(ER_CANT_INITIALIZE_UDF),MYF(0), - u_d->name, ER(ER_UNKNOWN_ERROR)); + u_d->name.str, ER(ER_UNKNOWN_ERROR)); DBUG_RETURN(1); } DBUG_RETURN(0); @@ -2173,6 +2174,7 @@ bool Item_func_set_user_var::fix_fields(THD *thd, TABLE_LIST *tables, is different from query_id). */ entry->update_query_id= thd->query_id; + entry->collation.set(args[0]->collation); cached_result_type= args[0]->result_type(); return 0; } @@ -2184,6 +2186,7 @@ Item_func_set_user_var::fix_length_and_dec() maybe_null=args[0]->maybe_null; max_length=args[0]->max_length; decimals=args[0]->decimals; + collation.set(args[0]->collation); } @@ -2498,6 +2501,9 @@ void Item_func_get_user_var::fix_length_and_dec() if (!(var_entry= get_variable(&thd->user_vars, name, 0))) null_value= 1; + else + collation.set(var_entry->collation); + if (!(opt_bin_log && is_update_query(thd->lex->sql_command))) return; @@ -2623,6 +2629,7 @@ longlong Item_func_inet_aton::val_int() const char *p,* end; char c = '.'; // we mark c to indicate invalid IP in case length is 0 char buff[36]; + int dot_count= 0; String *s,tmp(buff,sizeof(buff),&my_charset_bin); if (!(s = args[0]->val_str(&tmp))) // If null value @@ -2641,6 +2648,7 @@ longlong Item_func_inet_aton::val_int() } else if (c == '.') { + dot_count++; result= (result << 8) + (ulonglong) byte_result; byte_result = 0; } @@ -2648,7 +2656,19 @@ longlong Item_func_inet_aton::val_int() goto err; // Invalid character } if (c != '.') // IP number can't end on '.' + { + /* + Handle short-forms addresses according to standard. Examples: + 127 -> 0.0.0.127 + 127.1 -> 127.0.0.1 + 127.2.1 -> 127.2.0.1 + */ + switch (dot_count) { + case 1: result<<= 8; /* Fall through */ + case 2: result<<= 8; /* Fall through */ + } return (result << 8) + (ulonglong) byte_result; + } err: null_value=1; diff --git a/sql/item_func.h b/sql/item_func.h index c2aa62ec2d7..75c8b348347 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -107,8 +107,7 @@ public: } Item_func(List<Item> &list); // Constructor used for Item_cond_and/or (see Item comment) - Item_func(THD *thd, Item_func &item); - ~Item_func() {} /* Nothing to do; Items are freed automaticly */ + Item_func(THD *thd, Item_func *item); bool fix_fields(THD *,struct st_table_list *, Item **ref); table_map used_tables() const; table_map not_null_tables() const; @@ -201,7 +200,7 @@ public: Item_int_func(Item *a,Item *b) :Item_func(a,b) { max_length=21; } Item_int_func(Item *a,Item *b,Item *c) :Item_func(a,b,c) { max_length=21; } Item_int_func(List<Item> &list) :Item_func(list) { max_length=21; } - Item_int_func(THD *thd, Item_int_func &item) :Item_func(thd, item) {} + Item_int_func(THD *thd, Item_int_func *item) :Item_func(thd, item) {} double val() { return (double) val_int(); } String *val_str(String*str); enum Item_result result_type () const { return INT_RESULT; } @@ -213,20 +212,28 @@ class Item_func_signed :public Item_int_func { public: Item_func_signed(Item *a) :Item_int_func(a) {} - double val() { return args[0]->val(); } - longlong val_int() { return args[0]->val_int(); } + double val() + { + double tmp= args[0]->val(); + null_value= args[0]->null_value; + return tmp; + } + longlong val_int() + { + longlong tmp= args[0]->val_int(); + null_value= args[0]->null_value; + return tmp; + } void fix_length_and_dec() { max_length=args[0]->max_length; unsigned_flag=0; } void print(String *str); }; -class Item_func_unsigned :public Item_int_func +class Item_func_unsigned :public Item_func_signed { public: - Item_func_unsigned(Item *a) :Item_int_func(a) {} - double val() { return args[0]->val(); } - longlong val_int() { return args[0]->val_int(); } + Item_func_unsigned(Item *a) :Item_func_signed(a) {} void fix_length_and_dec() { max_length=args[0]->max_length; unsigned_flag=1; } void print(String *str); @@ -756,7 +763,6 @@ public: Item_udf_func(udf_func *udf_arg) :Item_func(), udf(udf_arg) {} Item_udf_func(udf_func *udf_arg, List<Item> &list) :Item_func(list), udf(udf_arg) {} - ~Item_udf_func() {} const char *func_name() const { return udf.name(); } bool fix_fields(THD *thd, struct st_table_list *tables, Item **ref) { @@ -777,7 +783,6 @@ class Item_func_udf_float :public Item_udf_func Item_func_udf_float(udf_func *udf_arg) :Item_udf_func(udf_arg) {} Item_func_udf_float(udf_func *udf_arg, List<Item> &list) :Item_udf_func(udf_arg,list) {} - ~Item_func_udf_float() {} longlong val_int() { return (longlong) Item_func_udf_float::val(); } double val(); String *val_str(String *str); @@ -791,7 +796,6 @@ public: Item_func_udf_int(udf_func *udf_arg) :Item_udf_func(udf_arg) {} Item_func_udf_int(udf_func *udf_arg, List<Item> &list) :Item_udf_func(udf_arg,list) {} - ~Item_func_udf_int() {} longlong val_int(); double val() { return (double) Item_func_udf_int::val_int(); } String *val_str(String *str); @@ -806,7 +810,6 @@ public: Item_func_udf_str(udf_func *udf_arg) :Item_udf_func(udf_arg) {} Item_func_udf_str(udf_func *udf_arg, List<Item> &list) :Item_udf_func(udf_arg,list) {} - ~Item_func_udf_str() {} String *val_str(String *); double val() { @@ -831,7 +834,6 @@ class Item_func_udf_float :public Item_real_func public: Item_func_udf_float(udf_func *udf_arg) :Item_real_func() {} Item_func_udf_float(udf_func *udf_arg, List<Item> &list) :Item_real_func(list) {} - ~Item_func_udf_float() {} double val() { return 0.0; } }; @@ -841,7 +843,6 @@ class Item_func_udf_int :public Item_int_func public: Item_func_udf_int(udf_func *udf_arg) :Item_int_func() {} Item_func_udf_int(udf_func *udf_arg, List<Item> &list) :Item_int_func(list) {} - ~Item_func_udf_int() {} longlong val_int() { return 0; } }; @@ -851,7 +852,6 @@ class Item_func_udf_str :public Item_func public: Item_func_udf_str(udf_func *udf_arg) :Item_func() {} Item_func_udf_str(udf_func *udf_arg, List<Item> &list) :Item_func(list) {} - ~Item_func_udf_str() {} String *val_str(String *) { null_value=1; return 0; } double val() { null_value=1; return 0.0; } longlong val_int() { null_value=1; return 0; } @@ -1000,7 +1000,7 @@ public: Item_func_match(List<Item> &a, uint b): Item_real_func(a), key(0), flags(b), join_key(0), ft_handler(0), table(0), master(0), concat(0) { } - ~Item_func_match() + void cleanup() { if (!master && ft_handler) { diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc index 5ac87a25e67..6934ad9d3b0 100644 --- a/sql/item_geofunc.cc +++ b/sql/item_geofunc.cc @@ -22,6 +22,8 @@ #endif #include "mysql_priv.h" + +#ifdef HAVE_SPATIAL #include "sql_acl.h" #include <m_ctype.h> @@ -651,3 +653,5 @@ longlong Item_func_srid::val_int() uint32 res= uint4korr(swkb->ptr()); return (longlong) res; } + +#endif /*HAVE_SPATIAL*/ diff --git a/sql/item_geofunc.h b/sql/item_geofunc.h index f6f00ed2bab..545052807ec 100644 --- a/sql/item_geofunc.h +++ b/sql/item_geofunc.h @@ -17,6 +17,8 @@ /* This file defines all spatial functions */ +#ifdef HAVE_SPATIAL + #ifdef __GNUC__ #pragma interface /* gcc class implementation */ #endif @@ -338,3 +340,12 @@ public: const char *func_name() const { return "srid"; } void fix_length_and_dec() { max_length= 10; } }; + +#define GEOM_NEW(obj_constructor) new obj_constructor + +#else /*HAVE_SPATIAL*/ + +#define GEOM_NEW(obj_constructor) NULL + +#endif + diff --git a/sql/item_row.cc b/sql/item_row.cc index 89b38c8a753..7f847bd1d4e 100644 --- a/sql/item_row.cc +++ b/sql/item_row.cc @@ -91,7 +91,7 @@ void Item_row::split_sum_func(Item **ref_pointer_array, List<Item> &fields) uint el= fields.elements; fields.push_front(*arg); ref_pointer_array[el]= *arg; - *arg= new Item_ref(ref_pointer_array + el, 0, (*arg)->name); + *arg= new Item_ref(ref_pointer_array + el, arg, 0, (*arg)->name); } } } diff --git a/sql/item_row.h b/sql/item_row.h index a09bd1a2c31..f87b4f66e80 100644 --- a/sql/item_row.h +++ b/sql/item_row.h @@ -34,12 +34,6 @@ public: with_null(0) {} - ~Item_row() - { - if (array_holder && items) - sql_element_free(items); - } - enum Type type() const { return ROW_ITEM; }; void illegal_method_call(const char *); bool is_null() { return null_value; } diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 3cb03d7ea49..fd1222d5f1a 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -616,7 +616,8 @@ void Item_func_concat_ws::split_sum_func(Item **ref_pointer_array, uint el= fields.elements; fields.push_front(separator); ref_pointer_array[el]= separator; - separator= new Item_ref(ref_pointer_array + el, 0, separator->name); + separator= new Item_ref(ref_pointer_array + el, + &separator, 0, separator->name); } Item_str_func::split_sum_func(ref_pointer_array, fields); } @@ -779,7 +780,7 @@ redo: register char *i,*j; i=(char*) ptr+1; j=(char*) search+1; while (j != search_end) - if (*i++ != *j++) goto skipp; + if (*i++ != *j++) goto skip; offset= (int) (ptr-res->ptr()); if (res->length()-from_length + to_length > current_thd->variables.max_allowed_packet) @@ -793,7 +794,7 @@ redo: offset+=(int) to_length; goto redo; } -skipp: +skip: if ((l=my_ismbchar(res->charset(), ptr,strend))) ptr+=l; else ++ptr; } @@ -975,9 +976,10 @@ String *Item_func_right::val_str(String *str) if (res->length() <= (uint) length) return res; /* purecov: inspected */ - uint start=res->numchars()-(uint) length; - if (start<=0) return res; - start=res->charpos(start); + uint start=res->numchars(); + if (start <= (uint) length) + return res; + start=res->charpos(start - (uint) length); tmp_value.set(*res,start,res->length()-start); return &tmp_value; } @@ -1087,13 +1089,13 @@ String *Item_func_substr_index::val_str(String *str) register char *i,*j; i=(char*) ptr+1; j=(char*) search+1; while (j != search_end) - if (*i++ != *j++) goto skipp; + if (*i++ != *j++) goto skip; if (pass==0) ++n; else if (!--c) break; ptr+=delimeter_length; continue; } - skipp: + skip: if ((l=my_ismbchar(res->charset(), ptr,strend))) ptr+=l; else ++ptr; } /* either not found or got total number when count<0 */ @@ -1646,11 +1648,11 @@ void Item_func_elt::fix_length_and_dec() { max_length=0; decimals=0; - + if (agg_arg_collations(collation, args+1, arg_count-1)) return; - for (uint i=1 ; i < arg_count ; i++) + for (uint i= 1 ; i < arg_count ; i++) { set_if_bigger(max_length,args[i]->max_length); set_if_bigger(decimals,args[i]->decimals); @@ -1709,7 +1711,7 @@ void Item_func_make_set::split_sum_func(Item **ref_pointer_array, uint el= fields.elements; fields.push_front(item); ref_pointer_array[el]= item; - item= new Item_ref(ref_pointer_array + el, 0, item->name); + item= new Item_ref(ref_pointer_array + el, &item, 0, item->name); } Item_str_func::split_sum_func(ref_pointer_array, fields); } @@ -2022,9 +2024,8 @@ String *Item_func_lpad::val_str(String *str) { uint32 res_char_length,pad_char_length; ulong count= (long) args[1]->val_int(), byte_count; - String a1,a3; - String *res= args[0]->val_str(&a1); - String *pad= args[2]->val_str(&a3); + String *res= args[0]->val_str(&tmp_value); + String *pad= args[2]->val_str(&lpad_str); if (!res || args[1]->null_value || !pad) goto err; @@ -2104,8 +2105,8 @@ String *Item_func_conv_charset::val_str(String *str) null_value=1; return 0; } - null_value= str->copy(arg->ptr(),arg->length(),arg->charset(),conv_charset); - return null_value ? 0 : str; + null_value= str_value.copy(arg->ptr(),arg->length(),arg->charset(),conv_charset); + return null_value ? 0 : &str_value; } void Item_func_conv_charset::fix_length_and_dec() @@ -2125,14 +2126,12 @@ void Item_func_conv_charset::print(String *str) String *Item_func_conv_charset3::val_str(String *str) { - my_wc_t wc; - int cnvres; - const uchar *s, *se; - uchar *d, *d0, *de; - uint32 dmaxlen; + char cs1[30], cs2[30]; + String to_cs_buff(cs1, sizeof(cs1), default_charset_info); + String from_cs_buff(cs2, sizeof(cs2), default_charset_info); String *arg= args[0]->val_str(str); - String *to_cs= args[1]->val_str(str); - String *from_cs= args[2]->val_str(str); + String *to_cs= args[1]->val_str(&to_cs_buff); + String *from_cs= args[2]->val_str(&from_cs_buff); CHARSET_INFO *from_charset; CHARSET_INFO *to_charset; @@ -2142,51 +2141,17 @@ String *Item_func_conv_charset3::val_str(String *str) !(from_charset=get_charset_by_name(from_cs->ptr(), MYF(MY_WME))) || !(to_charset=get_charset_by_name(to_cs->ptr(), MYF(MY_WME)))) { - null_value=1; + null_value= 1; return 0; } - s=(const uchar*)arg->ptr(); - se=s+arg->length(); - - dmaxlen=arg->length()*to_charset->mbmaxlen+1; - str->alloc(dmaxlen); - d0=d=(unsigned char*)str->ptr(); - de=d+dmaxlen; - - while (1) + if (str_value.copy(arg->ptr(), arg->length(), from_charset, to_charset)) { - cnvres=from_charset->cset->mb_wc(from_charset,&wc,s,se); - if (cnvres>0) - { - s+=cnvres; - } - else if (cnvres==MY_CS_ILSEQ) - { - s++; - wc='?'; - } - else - break; - -outp: - cnvres=to_charset->cset->wc_mb(to_charset,wc,d,de); - if (cnvres>0) - { - d+=cnvres; - } - else if (cnvres==MY_CS_ILUNI && wc!='?') - { - wc='?'; - goto outp; - } - else - break; - }; - - str->length((uint32) (d-d0)); - str->set_charset(to_charset); - return str; + null_value= 1; + return 0; + } + null_value= 0; + return &str_value; } diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 40b00cdd488..465300e721e 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -95,7 +95,6 @@ class Item_func_concat_ws :public Item_str_func public: Item_func_concat_ws(Item *a,List<Item> &list) :Item_str_func(list),separator(a) {} - ~Item_func_concat_ws() { delete separator; } String *val_str(String *); void fix_length_and_dec(); void update_used_tables(); @@ -409,7 +408,6 @@ class Item_func_make_set :public Item_str_func public: Item_func_make_set(Item *a,List<Item> &list) :Item_str_func(list),item(a) {} - ~Item_func_make_set() { delete item; } String *val_str(String *str); bool fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref) { @@ -520,7 +518,8 @@ public: void fix_length_and_dec() { collation.set(default_charset()); - decimals=0; max_length=args[0]->max_length*2; + decimals=0; + max_length=args[0]->max_length*2*collation.collation->mbmaxlen; } }; diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 43775e1c96c..5b3cc326679 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -63,6 +63,11 @@ void Item_subselect::init(st_select_lex *select_lex, DBUG_VOID_RETURN; } +void Item_subselect::cleanup() +{ + Item_result_field::cleanup(); + engine->cleanup(); +} Item_subselect::~Item_subselect() { @@ -301,8 +306,6 @@ void Item_singlerow_subselect::fix_length_and_dec() if ((max_columns= engine->cols()) == 1) { engine->fix_length_and_dec(row= &value); - if (!(value= Item_cache::get_cache(engine->type()))) - return; } else { @@ -641,7 +644,8 @@ Item_in_subselect::single_value_transformer(JOIN *join, As far as Item_ref_in_optimizer do not substitude itself on fix_fields we can use same item for all selects. */ - expr= new Item_ref((Item**)optimizer->get_cache(), + expr= new Item_ref((Item**)optimizer->get_cache(), + NULL, (char *)"<no matter>", (char *)in_left_expr_name); @@ -791,7 +795,8 @@ Item_in_subselect::row_value_transformer(JOIN *join) (char *) "<list ref>"); func= eq_creator.create(new Item_ref((*optimizer->get_cache())-> - addr(i), + addr(i), + NULL, (char *)"<no matter>", (char *)in_left_expr_name), func); @@ -889,6 +894,12 @@ subselect_single_select_engine(st_select_lex *select, this->select_lex= select_lex; } +void subselect_single_select_engine::cleanup() +{ + prepared= 0; + optimized= 0; + executed= 0; +} subselect_union_engine::subselect_union_engine(st_select_lex_unit *u, select_subselect *result_arg, @@ -906,7 +917,8 @@ int subselect_single_select_engine::prepare() { if (prepared) return 0; - join= new JOIN(thd, select_lex->item_list, select_lex->options, result); + join= new JOIN(thd, select_lex->item_list, + select_lex->options | SELECT_NO_UNLOCK, result); if (!join || !result) { thd->fatal_error(); //out of memory @@ -933,7 +945,7 @@ int subselect_single_select_engine::prepare() int subselect_union_engine::prepare() { - return unit->prepare(thd, result); + return unit->prepare(thd, result, SELECT_NO_UNLOCK); } int subselect_uniquesubquery_engine::prepare() @@ -955,13 +967,9 @@ static Item_result set_row(List<Item> &item_list, Item *item, res_type= sel_item->result_type(); item->decimals= sel_item->decimals; *maybe_null= sel_item->maybe_null; - if (row) - { - if (!(row[i]= Item_cache::get_cache(res_type))) - return STRING_RESULT; // we should return something - row[i]->set_len_n_dec(sel_item->max_length, sel_item->decimals); - row[i]->collation.set(sel_item->collation); - } + if (!(row[i]= Item_cache::get_cache(res_type))) + return STRING_RESULT; // we should return something + row[i]->setup(sel_item); } if (item_list.elements > 1) res_type= ROW_RESULT; @@ -982,7 +990,10 @@ void subselect_union_engine::fix_length_and_dec(Item_cache **row) DBUG_ASSERT(row || unit->first_select()->item_list.elements==1); if (unit->first_select()->item_list.elements == 1) + { res_type= set_row(unit->types, item, row, &maybe_null); + item->collation.set(row[0]->collation); + } else { bool fake= 0; @@ -1099,7 +1110,7 @@ int subselect_indexsubquery_engine::exec() if (check_null) { /* We need to check for NULL if there wasn't a matching value */ - *tab->null_ref_key= 0; // Search first for not null + *tab->ref.null_ref_key= 0; // Search first for not null ((Item_in_subselect *) item)->was_null= 0; } @@ -1144,7 +1155,7 @@ int subselect_indexsubquery_engine::exec() { if (!check_null || null_finding) break; /* We don't need to check nulls */ - *tab->null_ref_key= 1; + *tab->ref.null_ref_key= 1; null_finding= 1; /* Check if there exists a row with a null value in the index */ if ((error= (safe_index_read(tab) == 1))) diff --git a/sql/item_subselect.h b/sql/item_subselect.h index 8444dc7bf66..dc3d07540da 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -69,6 +69,7 @@ public: select_subselect *result); ~Item_subselect(); + void cleanup(); virtual void reset() { null_value= 1; @@ -199,6 +200,13 @@ public: {} + void cleanup() + { + Item_exists_subselect::cleanup(); + abort_on_null= 0; + transformed= 0; + upper_not= 0; + } subs_type substype() { return IN_SUBS; } void reset() { @@ -261,6 +269,7 @@ public: maybe_null= 0; } virtual ~subselect_engine() {}; // to satisfy compiler + virtual void cleanup() {} // set_thd should be called before prepare() void set_thd(THD *thd_arg) { thd= thd_arg; } @@ -290,6 +299,7 @@ public: subselect_single_select_engine(st_select_lex *select, select_subselect *result, Item_subselect *item); + void cleanup(); int prepare(); void fix_length_and_dec(Item_cache** row); int exec(); diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 3bc52159a96..2753c2a5d53 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -42,17 +42,17 @@ Item_sum::Item_sum(List<Item> &list) } // Constructor used in processing select with temporary tebles -Item_sum::Item_sum(THD *thd, Item_sum &item): - Item_result_field(thd, item), quick_group(item.quick_group) +Item_sum::Item_sum(THD *thd, Item_sum *item): + Item_result_field(thd, item), quick_group(item->quick_group) { - arg_count= item.arg_count; + arg_count= item->arg_count; if (arg_count <= 2) args=tmp_args; else if (!(args=(Item**) sql_alloc(sizeof(Item*)*arg_count))) return; for (uint i= 0; i < arg_count; i++) - args[i]= item.args[i]; + args[i]= item->args[i]; } void Item_sum::mark_as_sum_func() @@ -240,7 +240,7 @@ Item_sum_hybrid::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) Item *Item_sum_sum::copy_or_same(THD* thd) { - return new (&thd->mem_root) Item_sum_sum(thd, *this); + return new (&thd->mem_root) Item_sum_sum(thd, this); } @@ -383,7 +383,7 @@ double Item_sum_sum_distinct::val() Item *Item_sum_count::copy_or_same(THD* thd) { - return new (&thd->mem_root) Item_sum_count(thd, *this); + return new (&thd->mem_root) Item_sum_count(thd, this); } @@ -417,7 +417,7 @@ longlong Item_sum_count::val_int() Item *Item_sum_avg::copy_or_same(THD* thd) { - return new (&thd->mem_root) Item_sum_avg(thd, *this); + return new (&thd->mem_root) Item_sum_avg(thd, this); } @@ -462,7 +462,7 @@ double Item_sum_std::val() Item *Item_sum_std::copy_or_same(THD* thd) { - return new (&thd->mem_root) Item_sum_std(thd, *this); + return new (&thd->mem_root) Item_sum_std(thd, this); } @@ -472,7 +472,7 @@ Item *Item_sum_std::copy_or_same(THD* thd) Item *Item_sum_variance::copy_or_same(THD* thd) { - return new (&thd->mem_root) Item_sum_variance(thd, *this); + return new (&thd->mem_root) Item_sum_variance(thd, this); } @@ -613,7 +613,7 @@ Item_sum_hybrid::val_str(String *str) Item *Item_sum_min::copy_or_same(THD* thd) { - return new (&thd->mem_root) Item_sum_min(thd, *this); + return new (&thd->mem_root) Item_sum_min(thd, this); } @@ -666,7 +666,7 @@ bool Item_sum_min::add() Item *Item_sum_max::copy_or_same(THD* thd) { - return new (&thd->mem_root) Item_sum_max(thd, *this); + return new (&thd->mem_root) Item_sum_max(thd, this); } @@ -732,7 +732,7 @@ void Item_sum_bit::clear() Item *Item_sum_or::copy_or_same(THD* thd) { - return new (&thd->mem_root) Item_sum_or(thd, *this); + return new (&thd->mem_root) Item_sum_or(thd, this); } @@ -746,7 +746,7 @@ bool Item_sum_or::add() Item *Item_sum_xor::copy_or_same(THD* thd) { - return new (&thd->mem_root) Item_sum_xor(thd, *this); + return new (&thd->mem_root) Item_sum_xor(thd, this); } @@ -760,7 +760,7 @@ bool Item_sum_xor::add() Item *Item_sum_and::copy_or_same(THD* thd) { - return new (&thd->mem_root) Item_sum_and(thd, *this); + return new (&thd->mem_root) Item_sum_and(thd, this); } @@ -1193,8 +1193,9 @@ int dump_leaf(byte* key, uint32 count __attribute__((unused)), } -Item_sum_count_distinct::~Item_sum_count_distinct() +void Item_sum_count_distinct::cleanup() { + Item_sum_int::cleanup(); /* Free table and tree if they belong to this item (if item have not pointer to original item from which was made copy => it own its objects ) @@ -1202,13 +1203,21 @@ Item_sum_count_distinct::~Item_sum_count_distinct() if (!original) { if (table) + { free_tmp_table(current_thd, table); + table= 0; + } delete tmp_table_param; + tmp_table_param= 0; if (use_tree) + { delete_tree(tree); + use_tree= 0; + } } } + bool Item_sum_count_distinct::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) { @@ -1390,7 +1399,7 @@ int Item_sum_count_distinct::tree_to_myisam() Item *Item_sum_count_distinct::copy_or_same(THD* thd) { - return new (&thd->mem_root) Item_sum_count_distinct(thd, *this); + return new (&thd->mem_root) Item_sum_count_distinct(thd, this); } @@ -1490,7 +1499,7 @@ bool Item_udf_sum::add() Item *Item_sum_udf_float::copy_or_same(THD* thd) { - return new (&thd->mem_root) Item_sum_udf_float(thd, *this); + return new (&thd->mem_root) Item_sum_udf_float(thd, this); } double Item_sum_udf_float::val() @@ -1513,7 +1522,7 @@ String *Item_sum_udf_float::val_str(String *str) Item *Item_sum_udf_int::copy_or_same(THD* thd) { - return new (&thd->mem_root) Item_sum_udf_int(thd, *this); + return new (&thd->mem_root) Item_sum_udf_int(thd, this); } @@ -1549,7 +1558,7 @@ void Item_sum_udf_str::fix_length_and_dec() Item *Item_sum_udf_str::copy_or_same(THD* thd) { - return new (&thd->mem_root) Item_sum_udf_str(thd, *this); + return new (&thd->mem_root) Item_sum_udf_str(thd, this); } @@ -1772,6 +1781,31 @@ Item_func_group_concat::Item_func_group_concat(bool is_distinct, } +void Item_func_group_concat::cleanup() +{ + /* + Free table and tree if they belong to this item (if item have not pointer + to original item from which was made copy => it own its objects ) + */ + if (!original) + { + THD *thd= current_thd; + if (table) + { + free_tmp_table(thd, table); + table= 0; + } + delete tmp_table_param; + tmp_table_param= 0; + if (tree_mode) + { + tree_mode= 0; + delete_tree(tree); + } + } +} + + Item_func_group_concat::~Item_func_group_concat() { /* @@ -1787,18 +1821,13 @@ Item_func_group_concat::~Item_func_group_concat() sprintf(warn_buff, ER(ER_CUT_VALUE_GROUP_CONCAT), count_cut_values); warning->set_msg(thd, warn_buff); } - if (table) - free_tmp_table(thd, table); - delete tmp_table_param; - if (tree_mode) - delete_tree(tree); } } Item *Item_func_group_concat::copy_or_same(THD* thd) { - return new (&thd->mem_root) Item_func_group_concat(thd, *this); + return new (&thd->mem_root) Item_func_group_concat(thd, this); } diff --git a/sql/item_sum.h b/sql/item_sum.h index afed152bb0e..3d6a9c776b8 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -57,8 +57,12 @@ public: } Item_sum(List<Item> &list); //Copy constructor, need to perform subselects with temporary tables - Item_sum(THD *thd, Item_sum &item); - ~Item_sum() { result_field=0; } + Item_sum(THD *thd, Item_sum *item); + void cleanup() + { + Item_result_field::cleanup(); + result_field=0; + } enum Type type() const { return SUM_FUNC_ITEM; } virtual enum Sumfunctype sum_func () const=0; @@ -106,7 +110,7 @@ public: Item_sum_num(Item *item_par) :Item_sum(item_par) {} Item_sum_num(Item *a, Item* b) :Item_sum(a,b) {} Item_sum_num(List<Item> &list) :Item_sum(list) {} - Item_sum_num(THD *thd, Item_sum_num &item) :Item_sum(thd, item) {} + Item_sum_num(THD *thd, Item_sum_num *item) :Item_sum(thd, item) {} bool fix_fields(THD *, TABLE_LIST *, Item **); longlong val_int() { return (longlong) val(); } /* Real as default */ String *val_str(String*str); @@ -119,7 +123,7 @@ class Item_sum_int :public Item_sum_num public: Item_sum_int(Item *item_par) :Item_sum_num(item_par) {} Item_sum_int(List<Item> &list) :Item_sum_num(list) {} - Item_sum_int(THD *thd, Item_sum_int &item) :Item_sum_num(thd, item) {} + Item_sum_int(THD *thd, Item_sum_int *item) :Item_sum_num(thd, item) {} double val() { return (double) val_int(); } String *val_str(String*str); enum Item_result result_type () const { return INT_RESULT; } @@ -135,8 +139,8 @@ class Item_sum_sum :public Item_sum_num public: Item_sum_sum(Item *item_par) :Item_sum_num(item_par),sum(0.0) {} - Item_sum_sum(THD *thd, Item_sum_sum &item) - :Item_sum_num(thd, item), sum(item.sum) {} + Item_sum_sum(THD *thd, Item_sum_sum *item) + :Item_sum_num(thd, item), sum(item->sum) {} enum Sumfunctype sum_func () const {return SUM_FUNC;} void clear(); bool add(); @@ -191,9 +195,9 @@ class Item_sum_count :public Item_sum_int Item_sum_count(Item *item_par) :Item_sum_int(item_par),count(0),used_table_cache(~(table_map) 0) {} - Item_sum_count(THD *thd, Item_sum_count &item) - :Item_sum_int(thd, item), count(item.count), - used_table_cache(item.used_table_cache) + Item_sum_count(THD *thd, Item_sum_count *item) + :Item_sum_int(thd, item), count(item->count), + used_table_cache(item->used_table_cache) {} table_map used_tables() const { return used_table_cache; } bool const_item() const { return !used_table_cache; } @@ -259,16 +263,16 @@ class Item_sum_count_distinct :public Item_sum_int tmp_table_param(0), tree(&tree_base), original(0), use_tree(0), always_null(0) { quick_group= 0; } - Item_sum_count_distinct(THD *thd, Item_sum_count_distinct &item) - :Item_sum_int(thd, item), table(item.table), - used_table_cache(item.used_table_cache), - field_lengths(item.field_lengths), tmp_table_param(item.tmp_table_param), - tree(item.tree), original(&item), key_length(item.key_length), - max_elements_in_tree(item.max_elements_in_tree), - rec_offset(item.rec_offset), use_tree(item.use_tree), - always_null(item.always_null) + Item_sum_count_distinct(THD *thd, Item_sum_count_distinct *item) + :Item_sum_int(thd, item), table(item->table), + used_table_cache(item->used_table_cache), + field_lengths(item->field_lengths), tmp_table_param(item->tmp_table_param), + tree(item->tree), original(item), key_length(item->key_length), + max_elements_in_tree(item->max_elements_in_tree), + rec_offset(item->rec_offset), use_tree(item->use_tree), + always_null(item->always_null) {} - ~Item_sum_count_distinct(); + void cleanup(); table_map used_tables() const { return used_table_cache; } enum Sumfunctype sum_func () const { return COUNT_DISTINCT_FUNC; } @@ -314,8 +318,8 @@ class Item_sum_avg :public Item_sum_num public: Item_sum_avg(Item *item_par) :Item_sum_num(item_par),count(0) {} - Item_sum_avg(THD *thd, Item_sum_avg &item) - :Item_sum_num(thd, item), sum(item.sum), count(item.count) {} + Item_sum_avg(THD *thd, Item_sum_avg *item) + :Item_sum_num(thd, item), sum(item->sum), count(item->count) {} enum Sumfunctype sum_func () const {return AVG_FUNC;} void clear(); bool add(); @@ -366,9 +370,9 @@ class Item_sum_variance : public Item_sum_num public: Item_sum_variance(Item *item_par) :Item_sum_num(item_par),count(0) {} - Item_sum_variance(THD *thd, Item_sum_variance &item): - Item_sum_num(thd, item), sum(item.sum), sum_sqr(item.sum_sqr), - count(item.count) {} + Item_sum_variance(THD *thd, Item_sum_variance *item): + Item_sum_num(thd, item), sum(item->sum), sum_sqr(item->sum_sqr), + count(item->count) {} enum Sumfunctype sum_func () const { return VARIANCE_FUNC; } void clear(); bool add(); @@ -399,7 +403,7 @@ class Item_sum_std :public Item_sum_variance { public: Item_sum_std(Item *item_par) :Item_sum_variance(item_par) {} - Item_sum_std(THD *thd, Item_sum_std &item) + Item_sum_std(THD *thd, Item_sum_std *item) :Item_sum_variance(thd, item) {} enum Sumfunctype sum_func () const { return STD_FUNC; } @@ -426,15 +430,16 @@ class Item_sum_hybrid :public Item_sum public: Item_sum_hybrid(Item *item_par,int sign) - :Item_sum(item_par), hybrid_type(INT_RESULT), cmp_sign(sign), - used_table_cache(~(table_map) 0), + :Item_sum(item_par), sum(0.0), sum_int(0), + hybrid_type(INT_RESULT), hybrid_field_type(FIELD_TYPE_LONGLONG), + cmp_sign(sign), used_table_cache(~(table_map) 0), cmp_charset(&my_charset_bin) {} - Item_sum_hybrid(THD *thd, Item_sum_hybrid &item): - Item_sum(thd, item), value(item.value), tmp_value(item.tmp_value), - sum(item.sum), sum_int(item.sum_int), hybrid_type(item.hybrid_type), - hybrid_field_type(item.hybrid_field_type),cmp_sign(item.cmp_sign), - used_table_cache(item.used_table_cache), cmp_charset(item.cmp_charset) {} + Item_sum_hybrid(THD *thd, Item_sum_hybrid *item): + Item_sum(thd, item), value(item->value), + sum(item->sum), sum_int(item->sum_int), hybrid_type(item->hybrid_type), + hybrid_field_type(item->hybrid_field_type),cmp_sign(item->cmp_sign), + used_table_cache(item->used_table_cache), cmp_charset(item->cmp_charset) {} bool fix_fields(THD *, TABLE_LIST *, Item **); table_map used_tables() const { return used_table_cache; } bool const_item() const { return !used_table_cache; } @@ -465,7 +470,7 @@ class Item_sum_min :public Item_sum_hybrid { public: Item_sum_min(Item *item_par) :Item_sum_hybrid(item_par,1) {} - Item_sum_min(THD *thd, Item_sum_min &item) :Item_sum_hybrid(thd, item) {} + Item_sum_min(THD *thd, Item_sum_min *item) :Item_sum_hybrid(thd, item) {} enum Sumfunctype sum_func () const {return MIN_FUNC;} bool add(); @@ -478,7 +483,7 @@ class Item_sum_max :public Item_sum_hybrid { public: Item_sum_max(Item *item_par) :Item_sum_hybrid(item_par,-1) {} - Item_sum_max(THD *thd, Item_sum_max &item) :Item_sum_hybrid(thd, item) {} + Item_sum_max(THD *thd, Item_sum_max *item) :Item_sum_hybrid(thd, item) {} enum Sumfunctype sum_func () const {return MAX_FUNC;} bool add(); @@ -495,8 +500,8 @@ protected: public: Item_sum_bit(Item *item_par,ulonglong reset_arg) :Item_sum_int(item_par),reset_bits(reset_arg),bits(reset_arg) {} - Item_sum_bit(THD *thd, Item_sum_bit &item): - Item_sum_int(thd, item), reset_bits(item.reset_bits), bits(item.bits) {} + Item_sum_bit(THD *thd, Item_sum_bit *item): + Item_sum_int(thd, item), reset_bits(item->reset_bits), bits(item->bits) {} enum Sumfunctype sum_func () const {return SUM_BIT_FUNC;} void clear(); longlong val_int(); @@ -511,7 +516,7 @@ class Item_sum_or :public Item_sum_bit { public: Item_sum_or(Item *item_par) :Item_sum_bit(item_par,LL(0)) {} - Item_sum_or(THD *thd, Item_sum_or &item) :Item_sum_bit(thd, item) {} + Item_sum_or(THD *thd, Item_sum_or *item) :Item_sum_bit(thd, item) {} bool add(); const char *func_name() const { return "bit_or"; } Item *copy_or_same(THD* thd); @@ -522,7 +527,7 @@ class Item_sum_and :public Item_sum_bit { public: Item_sum_and(Item *item_par) :Item_sum_bit(item_par, ULONGLONG_MAX) {} - Item_sum_and(THD *thd, Item_sum_and &item) :Item_sum_bit(thd, item) {} + Item_sum_and(THD *thd, Item_sum_and *item) :Item_sum_bit(thd, item) {} bool add(); const char *func_name() const { return "bit_and"; } Item *copy_or_same(THD* thd); @@ -532,7 +537,7 @@ class Item_sum_xor :public Item_sum_bit { public: Item_sum_xor(Item *item_par) :Item_sum_bit(item_par,LL(0)) {} - Item_sum_xor(THD *thd, Item_sum_xor &item) :Item_sum_bit(thd, item) {} + Item_sum_xor(THD *thd, Item_sum_xor *item) :Item_sum_bit(thd, item) {} bool add(); const char *func_name() const { return "bit_xor"; } Item *copy_or_same(THD* thd); @@ -554,9 +559,8 @@ public: Item_udf_sum( udf_func *udf_arg, List<Item> &list ) :Item_sum( list ), udf(udf_arg) { quick_group=0;} - Item_udf_sum(THD *thd, Item_udf_sum &item) - :Item_sum(thd, item), udf(item.udf) {} - ~Item_udf_sum() {} + Item_udf_sum(THD *thd, Item_udf_sum *item) + :Item_sum(thd, item), udf(item->udf) {} const char *func_name() const { return udf.name(); } bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) { @@ -579,9 +583,8 @@ class Item_sum_udf_float :public Item_udf_sum Item_sum_udf_float(udf_func *udf_arg) :Item_udf_sum(udf_arg) {} Item_sum_udf_float(udf_func *udf_arg, List<Item> &list) :Item_udf_sum(udf_arg,list) {} - Item_sum_udf_float(THD *thd, Item_sum_udf_float &item) + Item_sum_udf_float(THD *thd, Item_sum_udf_float *item) :Item_udf_sum(thd, item) {} - ~Item_sum_udf_float() {} longlong val_int() { return (longlong) Item_sum_udf_float::val(); } double val(); String *val_str(String*str); @@ -596,9 +599,8 @@ public: Item_sum_udf_int(udf_func *udf_arg) :Item_udf_sum(udf_arg) {} Item_sum_udf_int(udf_func *udf_arg, List<Item> &list) :Item_udf_sum(udf_arg,list) {} - Item_sum_udf_int(THD *thd, Item_sum_udf_int &item) + Item_sum_udf_int(THD *thd, Item_sum_udf_int *item) :Item_udf_sum(thd, item) {} - ~Item_sum_udf_int() {} longlong val_int(); double val() { return (double) Item_sum_udf_int::val_int(); } String *val_str(String*str); @@ -614,9 +616,8 @@ public: Item_sum_udf_str(udf_func *udf_arg) :Item_udf_sum(udf_arg) {} Item_sum_udf_str(udf_func *udf_arg, List<Item> &list) :Item_udf_sum(udf_arg,list) {} - Item_sum_udf_str(THD *thd, Item_sum_udf_str &item) + Item_sum_udf_str(THD *thd, Item_sum_udf_str *item) :Item_udf_sum(thd, item) {} - ~Item_sum_udf_str() {} String *val_str(String *); double val() { @@ -643,9 +644,8 @@ class Item_sum_udf_float :public Item_sum_num public: Item_sum_udf_float(udf_func *udf_arg) :Item_sum_num() {} Item_sum_udf_float(udf_func *udf_arg, List<Item> &list) :Item_sum_num() {} - Item_sum_udf_float(THD *thd, Item_sum_udf_float &item) + Item_sum_udf_float(THD *thd, Item_sum_udf_float *item) :Item_sum_num(thd, item) {} - ~Item_sum_udf_float() {} enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; } double val() { return 0.0; } void clear() {} @@ -659,9 +659,8 @@ class Item_sum_udf_int :public Item_sum_num public: Item_sum_udf_int(udf_func *udf_arg) :Item_sum_num() {} Item_sum_udf_int(udf_func *udf_arg, List<Item> &list) :Item_sum_num() {} - Item_sum_udf_int(THD *thd, Item_sum_udf_int &item) + Item_sum_udf_int(THD *thd, Item_sum_udf_int *item) :Item_sum_num(thd, item) {} - ~Item_sum_udf_int() {} enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; } longlong val_int() { return 0; } double val() { return 0; } @@ -676,9 +675,8 @@ class Item_sum_udf_str :public Item_sum_num public: Item_sum_udf_str(udf_func *udf_arg) :Item_sum_num() {} Item_sum_udf_str(udf_func *udf_arg, List<Item> &list) :Item_sum_num() {} - Item_sum_udf_str(THD *thd, Item_sum_udf_str &item) + Item_sum_udf_str(THD *thd, Item_sum_udf_str *item) :Item_sum_num(thd, item) {} - ~Item_sum_udf_str() {} String *val_str(String *) { null_value=1; return 0; } double val() { null_value=1; return 0.0; } longlong val_int() { null_value=1; return 0; } @@ -740,33 +738,35 @@ class Item_func_group_concat : public Item_sum Item_func_group_concat(bool is_distinct,List<Item> *is_select, SQL_LIST *is_order,String *is_separator); - Item_func_group_concat(THD *thd, Item_func_group_concat &item) + Item_func_group_concat(THD *thd, Item_func_group_concat *item) :Item_sum(thd, item),item_thd(thd), - tmp_table_param(item.tmp_table_param), - max_elements_in_tree(item.max_elements_in_tree), - warning(item.warning), - warning_available(item.warning_available), - key_length(item.key_length), - rec_offset(item.rec_offset), - tree_mode(item.tree_mode), - distinct(item.distinct), - warning_for_row(item.warning_for_row), - separator(item.separator), - tree(item.tree), - table(item.table), - order(item.order), - tables_list(item.tables_list), - group_concat_max_len(item.group_concat_max_len), - show_elements(item.show_elements), - arg_count_order(item.arg_count_order), - arg_count_field(item.arg_count_field), - arg_show_fields(item.arg_show_fields), - count_cut_values(item.count_cut_values), - original(&item) + tmp_table_param(item->tmp_table_param), + max_elements_in_tree(item->max_elements_in_tree), + warning(item->warning), + warning_available(item->warning_available), + key_length(item->key_length), + rec_offset(item->rec_offset), + tree_mode(item->tree_mode), + distinct(item->distinct), + warning_for_row(item->warning_for_row), + separator(item->separator), + tree(item->tree), + table(item->table), + order(item->order), + tables_list(item->tables_list), + group_concat_max_len(item->group_concat_max_len), + show_elements(item->show_elements), + arg_count_order(item->arg_count_order), + arg_count_field(item->arg_count_field), + arg_show_fields(item->arg_show_fields), + count_cut_values(item->count_cut_values), + original(item) { - quick_group= item.quick_group; + quick_group= item->quick_group; }; ~Item_func_group_concat(); + void cleanup(); + enum Sumfunctype sum_func () const {return GROUP_CONCAT_FUNC;} const char *func_name() const { return "group_concat"; } enum Type type() const { return SUM_FUNC_ITEM; } diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index cccea6bcdb5..e49f2287f4b 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -1289,14 +1289,20 @@ longlong Item_func_sec_to_time::val_int() void Item_func_date_format::fix_length_and_dec() { decimals=0; + collation.set(&my_charset_bin); if (args[1]->type() == STRING_ITEM) { // Optimize the normal case fixed_length=1; - max_length=format_length(((Item_string*) args[1])->const_string()); + /* + The result is a binary string (no reason to use collation->mbmaxlen + This is becasue make_date_time() only returns binary strings + */ + max_length= format_length(((Item_string*) args[1])->const_string()); } else { fixed_length=0; + /* The result is a binary string (no reason to use collation->mbmaxlen */ max_length=args[1]->max_length*10; set_if_smaller(max_length,MAX_BLOB_WIDTH); } @@ -1867,6 +1873,8 @@ String *Item_char_typecast::val_str(String *str) } res= str; } + + res->set_charset(cast_cs); /* Cut the tail if cast with length diff --git a/sql/item_uniq.h b/sql/item_uniq.h index 5c6f6eefb6b..47f967b52c6 100644 --- a/sql/item_uniq.h +++ b/sql/item_uniq.h @@ -38,7 +38,7 @@ class Item_sum_unique_users :public Item_sum_num public: Item_sum_unique_users(Item *name_arg,int start,int end,Item *item_arg) :Item_sum_num(item_arg) {} - Item_sum_unique_users(THD *thd, Item_sum_unique_users &item) + Item_sum_unique_users(THD *thd, Item_sum_unique_users *item) :Item_sum_num(thd, item) {} double val() { return 0.0; } enum Sumfunctype sum_func () const {return UNIQUE_USERS_FUNC;} @@ -53,7 +53,7 @@ public: } Item *copy_or_same(THD* thd) { - return new Item_sum_unique_users(thd, *this); + return new Item_sum_unique_users(thd, this); } void print(String *str) { str->append("0.0", 3); } }; diff --git a/sql/lex.h b/sql/lex.h index 114e1a6b960..8bf8985a3ab 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -20,13 +20,25 @@ #include "lex_symbol.h" /* We don't want to include sql_yacc.h into gen_lex_hash */ +SYM_GROUP sym_group_common= {"", ""}; +SYM_GROUP sym_group_geom= {"Spatial extentions", "HAVE_SPATIAL"}; +SYM_GROUP sym_group_rtree= {"RTree keys", "HAVE_RTREE_KEYS"}; #ifdef NO_YACC_SYMBOLS -#define SYM(A) 0 -#define CREATE_FUNC(A) 0 +#define SYM_OR_NULL(A) 0 #else -#define SYM(A) A -#define CREATE_FUNC(A) (void*) (A) +#define SYM_OR_NULL(A) A +#endif + +#define SYM(A) SYM_OR_NULL(A),0,0,&sym_group_common +#define F_SYM(A) SYM_OR_NULL(A) + +#define CREATE_FUNC(A) (void *)(SYM_OR_NULL(A)), &sym_group_common + +#ifdef HAVE_SPATIAL +#define CREATE_FUNC_GEOM(A) (void *)(SYM_OR_NULL(A)), &sym_group_geom +#else +#define CREATE_FUNC_GEOM(A) 0, &sym_group_geom #endif /* @@ -36,683 +48,684 @@ */ static SYMBOL symbols[] = { - { "&&", SYM(AND),0,0}, - { "<", SYM(LT),0,0}, - { "<=", SYM(LE),0,0}, - { "<>", SYM(NE),0,0}, - { "!=", SYM(NE),0,0}, - { "=", SYM(EQ),0,0}, - { ">", SYM(GT_SYM),0,0}, - { ">=", SYM(GE),0,0}, - { "<<", SYM(SHIFT_LEFT),0,0}, - { ">>", SYM(SHIFT_RIGHT),0,0}, - { "<=>", SYM(EQUAL_SYM),0,0}, - { "ACTION", SYM(ACTION),0,0}, - { "ADD", SYM(ADD),0,0}, - { "AFTER", SYM(AFTER_SYM),0,0}, - { "AGAINST", SYM(AGAINST),0,0}, - { "AGGREGATE", SYM(AGGREGATE_SYM),0,0}, - { "ALL", SYM(ALL),0,0}, - { "ALTER", SYM(ALTER),0,0}, - { "ANALYZE", SYM(ANALYZE_SYM),0,0}, - { "AND", SYM(AND),0,0}, - { "ANY", SYM(ANY_SYM),0,0}, - { "AS", SYM(AS),0,0}, - { "ASC", SYM(ASC),0,0}, - { "ASCII", SYM(ASCII_SYM),0,0}, - { "ASENSITIVE", SYM(ASENSITIVE_SYM),0,0}, - { "AUTO_INCREMENT", SYM(AUTO_INC),0,0}, - { "AVG", SYM(AVG_SYM),0,0}, - { "AVG_ROW_LENGTH", SYM(AVG_ROW_LENGTH),0,0}, - { "BACKUP", SYM(BACKUP_SYM),0,0}, - { "BDB", SYM(BERKELEY_DB_SYM),0,0}, - { "BEFORE", SYM(BEFORE_SYM),0,0}, - { "BEGIN", SYM(BEGIN_SYM),0,0}, - { "BERKELEYDB", SYM(BERKELEY_DB_SYM),0,0}, - { "BETWEEN", SYM(BETWEEN_SYM),0,0}, - { "BIGINT", SYM(BIGINT),0,0}, - { "BINARY", SYM(BINARY),0,0}, - { "BINLOG", SYM(BINLOG_SYM),0,0}, - { "BIT", SYM(BIT_SYM),0,0}, - { "BLOB", SYM(BLOB_SYM),0,0}, - { "BOOL", SYM(BOOL_SYM),0,0}, - { "BOOLEAN", SYM(BOOLEAN_SYM),0,0}, - { "BOTH", SYM(BOTH),0,0}, - { "BTREE", SYM(BTREE_SYM),0,0}, - { "BY", SYM(BY),0,0}, - { "BYTE", SYM(BYTE_SYM), 0, 0}, - { "CACHE", SYM(CACHE_SYM),0,0}, - { "CALL", SYM(CALL_SYM),0,0}, - { "CASCADE", SYM(CASCADE),0,0}, - { "CASE", SYM(CASE_SYM),0,0}, - { "CHANGE", SYM(CHANGE),0,0}, - { "CHANGED", SYM(CHANGED),0,0}, - { "CHAR", SYM(CHAR_SYM),0,0}, - { "CHARACTER", SYM(CHAR_SYM),0,0}, - { "CHARSET", SYM(CHARSET),0,0}, - { "CHECK", SYM(CHECK_SYM),0,0}, - { "CHECKSUM", SYM(CHECKSUM_SYM),0,0}, - { "CIPHER", SYM(CIPHER_SYM),0,0}, - { "CLIENT", SYM(CLIENT_SYM),0,0}, - { "CLOSE", SYM(CLOSE_SYM),0,0}, - { "COLLATE", SYM(COLLATE_SYM),0,0}, - { "COLLATION", SYM(COLLATION_SYM),0,0}, - { "COLUMN", SYM(COLUMN_SYM),0,0}, - { "COLUMNS", SYM(COLUMNS),0,0}, - { "COMMENT", SYM(COMMENT_SYM),0,0}, - { "COMMIT", SYM(COMMIT_SYM),0,0}, - { "COMMITTED", SYM(COMMITTED_SYM),0,0}, - { "COMPRESSED", SYM(COMPRESSED_SYM),0,0}, - { "CONCURRENT", SYM(CONCURRENT),0,0}, - { "CONDITION", SYM(CONDITION_SYM),0,0}, - { "CONNECTION", SYM(CONNECTION_SYM),0,0}, - { "CONSTRAINT", SYM(CONSTRAINT),0,0}, - { "CONTINUE", SYM(CONTINUE_SYM),0,0}, - { "CREATE", SYM(CREATE),0,0}, - { "CROSS", SYM(CROSS),0,0}, - { "CUBE", SYM(CUBE_SYM),0,0}, - { "CURRENT_DATE", SYM(CURDATE),0,0}, - { "CURRENT_TIME", SYM(CURTIME),0,0}, - { "CURRENT_TIMESTAMP", SYM(NOW_SYM),0,0}, - { "CURSOR", SYM(CURSOR_SYM),0,0}, - { "DATA", SYM(DATA_SYM),0,0}, - { "DATABASE", SYM(DATABASE),0,0}, - { "DATABASES", SYM(DATABASES),0,0}, - { "DATE", SYM(DATE_SYM),0,0}, - { "DATETIME", SYM(DATETIME),0,0}, - { "DAY", SYM(DAY_SYM),0,0}, - { "DAY_HOUR", SYM(DAY_HOUR_SYM),0,0}, - { "DAY_MICROSECOND", SYM(DAY_MICROSECOND_SYM),0,0}, - { "DAY_MINUTE", SYM(DAY_MINUTE_SYM),0,0}, - { "DAY_SECOND", SYM(DAY_SECOND_SYM),0,0}, - { "DEC", SYM(DECIMAL_SYM),0,0}, - { "DECIMAL", SYM(DECIMAL_SYM),0,0}, - { "DECLARE", SYM(DECLARE_SYM),0,0}, - { "DEFAULT", SYM(DEFAULT),0,0}, - { "DEFINER", SYM(DEFINER_SYM),0,0}, - { "DELAYED", SYM(DELAYED_SYM),0,0}, - { "DELAY_KEY_WRITE", SYM(DELAY_KEY_WRITE_SYM),0,0}, - { "DELETE", SYM(DELETE_SYM),0,0}, - { "DESC", SYM(DESC),0,0}, - { "DESCRIBE", SYM(DESCRIBE),0,0}, - { "DES_KEY_FILE", SYM(DES_KEY_FILE),0,0}, - { "DETERMINISTIC", SYM(DETERMINISTIC_SYM),0,0}, - { "DIRECTORY", SYM(DIRECTORY_SYM),0,0}, - { "DISABLE", SYM(DISABLE_SYM),0,0}, - { "DISCARD", SYM(DISCARD),0,0}, - { "DISTINCT", SYM(DISTINCT),0,0}, - { "DISTINCTROW", SYM(DISTINCT),0,0}, /* Access likes this */ - { "DIV", SYM(DIV_SYM),0,0}, - { "DO", SYM(DO_SYM),0,0}, - { "DOUBLE", SYM(DOUBLE_SYM),0,0}, - { "DROP", SYM(DROP),0,0}, - { "DUAL", SYM(DUAL_SYM),0,0}, - { "DUMPFILE", SYM(DUMPFILE),0,0}, - { "DUPLICATE", SYM(DUPLICATE_SYM),0,0}, - { "DYNAMIC", SYM(DYNAMIC_SYM),0,0}, - { "ELSE", SYM(ELSE),0,0}, - { "ELSEIF", SYM(ELSEIF_SYM),0,0}, - { "ENABLE", SYM(ENABLE_SYM),0,0}, - { "ENCLOSED", SYM(ENCLOSED),0,0}, - { "END", SYM(END),0,0}, - { "ENGINE", SYM(ENGINE_SYM),0,0}, - { "ENGINES", SYM(ENGINES_SYM),0,0}, - { "ENUM", SYM(ENUM),0,0}, - { "ERRORS", SYM(ERRORS),0,0}, - { "ESCAPE", SYM(ESCAPE_SYM),0,0}, - { "ESCAPED", SYM(ESCAPED),0,0}, - { "EVENTS", SYM(EVENTS_SYM),0,0}, - { "EXECUTE", SYM(EXECUTE_SYM),0,0}, - { "EXISTS", SYM(EXISTS),0,0}, - { "EXIT", SYM(EXIT_SYM),0,0}, - { "EXPANSION", SYM(EXPANSION_SYM),0,0}, - { "EXPLAIN", SYM(DESCRIBE),0,0}, - { "EXTENDED", SYM(EXTENDED_SYM),0,0}, - { "FALSE", SYM(FALSE_SYM),0,0}, - { "FAST", SYM(FAST_SYM),0,0}, - { "FETCH", SYM(FETCH_SYM),0,0}, - { "FIELDS", SYM(COLUMNS),0,0}, - { "FILE", SYM(FILE_SYM),0,0}, - { "FIRST", SYM(FIRST_SYM),0,0}, - { "FIXED", SYM(FIXED_SYM),0,0}, - { "FLOAT", SYM(FLOAT_SYM),0,0}, - { "FLOAT4", SYM(FLOAT_SYM),0,0}, - { "FLOAT8", SYM(DOUBLE_SYM),0,0}, - { "FLUSH", SYM(FLUSH_SYM),0,0}, - { "FOR", SYM(FOR_SYM),0,0}, - { "FORCE", SYM(FORCE_SYM),0,0}, - { "FOREIGN", SYM(FOREIGN),0,0}, - { "FOUND", SYM(FOUND_SYM),0,0}, - { "FRAC_SECOND", SYM(FRAC_SECOND_SYM),0,0}, - { "FROM", SYM(FROM),0,0}, - { "FULL", SYM(FULL),0,0}, - { "FULLTEXT", SYM(FULLTEXT_SYM),0,0}, - { "FUNCTION", SYM(FUNCTION_SYM),0,0}, - { "GEOMETRY", SYM(GEOMETRY_SYM),0,0}, - { "GEOMETRYCOLLECTION",SYM(GEOMETRYCOLLECTION),0,0}, - { "GET_FORMAT", SYM(GET_FORMAT),0,0}, - { "GLOBAL", SYM(GLOBAL_SYM),0,0}, - { "GRANT", SYM(GRANT),0,0}, - { "GRANTS", SYM(GRANTS),0,0}, - { "GROUP", SYM(GROUP),0,0}, - { "HANDLER", SYM(HANDLER_SYM),0,0}, - { "HASH", SYM(HASH_SYM),0,0}, - { "HAVING", SYM(HAVING),0,0}, - { "HELP", SYM(HELP_SYM),0,0}, - { "HIGH_PRIORITY", SYM(HIGH_PRIORITY),0,0}, - { "HOSTS", SYM(HOSTS_SYM),0,0}, - { "HOUR", SYM(HOUR_SYM),0,0}, - { "HOUR_MICROSECOND", SYM(HOUR_MICROSECOND_SYM),0,0}, - { "HOUR_MINUTE", SYM(HOUR_MINUTE_SYM),0,0}, - { "HOUR_SECOND", SYM(HOUR_SECOND_SYM),0,0}, - { "IDENTIFIED", SYM(IDENTIFIED_SYM),0,0}, - { "IF", SYM(IF),0,0}, - { "IGNORE", SYM(IGNORE_SYM),0,0}, - { "IMPORT", SYM(IMPORT),0,0}, - { "IN", SYM(IN_SYM),0,0}, - { "INDEX", SYM(INDEX),0,0}, - { "INDEXES", SYM(INDEXES),0,0}, - { "INFILE", SYM(INFILE),0,0}, - { "INNER", SYM(INNER_SYM),0,0}, - { "INNOBASE", SYM(INNOBASE_SYM),0,0}, - { "INNODB", SYM(INNOBASE_SYM),0,0}, - { "INOUT", SYM(INOUT_SYM),0,0}, - { "INSENSITIVE", SYM(INSENSITIVE_SYM),0,0}, - { "INSERT", SYM(INSERT),0,0}, - { "INSERT_METHOD", SYM(INSERT_METHOD),0,0}, - { "INT", SYM(INT_SYM),0,0}, - { "INT1", SYM(TINYINT),0,0}, - { "INT2", SYM(SMALLINT),0,0}, - { "INT3", SYM(MEDIUMINT),0,0}, - { "INT4", SYM(INT_SYM),0,0}, - { "INT8", SYM(BIGINT),0,0}, - { "INTEGER", SYM(INT_SYM),0,0}, - { "INTERVAL", SYM(INTERVAL_SYM),0,0}, - { "INTO", SYM(INTO),0,0}, - { "IO_THREAD", SYM(RELAY_THREAD),0,0}, - { "IS", SYM(IS),0,0}, - { "ISOLATION", SYM(ISOLATION),0,0}, - { "ISSUER", SYM(ISSUER_SYM),0,0}, - { "ITERATE", SYM(ITERATE_SYM),0,0}, - { "INVOKER", SYM(INVOKER_SYM),0,0}, - { "JOIN", SYM(JOIN_SYM),0,0}, - { "KEY", SYM(KEY_SYM),0,0}, - { "KEYS", SYM(KEYS),0,0}, - { "KILL", SYM(KILL_SYM),0,0}, - { "LANGUAGE", SYM(LANGUAGE_SYM),0,0}, - { "LAST", SYM(LAST_SYM),0,0}, - { "LEADING", SYM(LEADING),0,0}, - { "LEAVE", SYM(LEAVE_SYM),0,0}, - { "LEAVES", SYM(LEAVES),0,0}, - { "LEFT", SYM(LEFT),0,0}, - { "LEVEL", SYM(LEVEL_SYM),0,0}, - { "LIKE", SYM(LIKE),0,0}, - { "LIMIT", SYM(LIMIT),0,0}, - { "LINES", SYM(LINES),0,0}, - { "LINESTRING", SYM(LINESTRING),0,0}, - { "LOAD", SYM(LOAD),0,0}, - { "LOCAL", SYM(LOCAL_SYM),0,0}, - { "LOCALTIME", SYM(NOW_SYM),0,0}, - { "LOCALTIMESTAMP", SYM(NOW_SYM),0,0}, - { "LOCK", SYM(LOCK_SYM),0,0}, - { "LOCKS", SYM(LOCKS_SYM),0,0}, - { "LOGS", SYM(LOGS_SYM),0,0}, - { "LONG", SYM(LONG_SYM),0,0}, - { "LONGBLOB", SYM(LONGBLOB),0,0}, - { "LONGTEXT", SYM(LONGTEXT),0,0}, - { "LOOP", SYM(LOOP_SYM),0,0}, - { "LOW_PRIORITY", SYM(LOW_PRIORITY),0,0}, - { "MASTER", SYM(MASTER_SYM),0,0}, - { "MASTER_CONNECT_RETRY", SYM(MASTER_CONNECT_RETRY_SYM),0,0}, - { "MASTER_HOST", SYM(MASTER_HOST_SYM),0,0}, - { "MASTER_LOG_FILE", SYM(MASTER_LOG_FILE_SYM),0,0}, - { "MASTER_LOG_POS", SYM(MASTER_LOG_POS_SYM),0,0}, - { "MASTER_PASSWORD", SYM(MASTER_PASSWORD_SYM),0,0}, - { "MASTER_PORT", SYM(MASTER_PORT_SYM),0,0}, - { "MASTER_SERVER_ID", SYM(MASTER_SERVER_ID_SYM),0,0}, - { "MASTER_SSL", SYM(MASTER_SSL_SYM),0,0}, - { "MASTER_SSL_CA", SYM(MASTER_SSL_CA_SYM),0,0}, - { "MASTER_SSL_CAPATH",SYM(MASTER_SSL_CAPATH_SYM),0,0}, - { "MASTER_SSL_CERT", SYM(MASTER_SSL_CERT_SYM),0,0}, - { "MASTER_SSL_CIPHER",SYM(MASTER_SSL_CIPHER_SYM),0,0}, - { "MASTER_SSL_KEY", SYM(MASTER_SSL_KEY_SYM),0,0}, - { "MASTER_USER", SYM(MASTER_USER_SYM),0,0}, - { "MATCH", SYM(MATCH),0,0}, - { "MAX_CONNECTIONS_PER_HOUR", SYM(MAX_CONNECTIONS_PER_HOUR), 0,0}, - { "MAX_QUERIES_PER_HOUR", SYM(MAX_QUERIES_PER_HOUR), 0,0}, - { "MAX_ROWS", SYM(MAX_ROWS),0,0}, - { "MAX_UPDATES_PER_HOUR", SYM(MAX_UPDATES_PER_HOUR), 0,0}, - { "MEDIUM", SYM(MEDIUM_SYM),0,0}, - { "MEDIUMBLOB", SYM(MEDIUMBLOB),0,0}, - { "MEDIUMINT", SYM(MEDIUMINT),0,0}, - { "MEDIUMTEXT", SYM(MEDIUMTEXT),0,0}, - { "MICROSECOND", SYM(MICROSECOND_SYM),0,0}, - { "MIDDLEINT", SYM(MEDIUMINT),0,0}, /* For powerbuilder */ - { "MINUTE", SYM(MINUTE_SYM),0,0}, - { "MINUTE_MICROSECOND", SYM(MINUTE_MICROSECOND_SYM),0,0}, - { "MINUTE_SECOND", SYM(MINUTE_SECOND_SYM),0,0}, - { "MIN_ROWS", SYM(MIN_ROWS),0,0}, - { "MOD", SYM(MOD_SYM),0,0}, - { "MODE", SYM(MODE_SYM),0,0}, - { "MODIFY", SYM(MODIFY_SYM),0,0}, - { "MONTH", SYM(MONTH_SYM),0,0}, - { "MULTILINESTRING", SYM(MULTILINESTRING),0,0}, - { "MULTIPOINT", SYM(MULTIPOINT),0,0}, - { "MULTIPOLYGON", SYM(MULTIPOLYGON),0,0}, - { "NAME", SYM(NAME_SYM),0,0}, - { "NAMES", SYM(NAMES_SYM),0,0}, - { "NATIONAL", SYM(NATIONAL_SYM),0,0}, - { "NATURAL", SYM(NATURAL),0,0}, - { "NCHAR", SYM(NCHAR_SYM),0,0}, - { "NEW", SYM(NEW_SYM),0,0}, - { "NEXT", SYM(NEXT_SYM),0,0}, - { "NO", SYM(NO_SYM),0,0}, - { "NONE", SYM(NONE_SYM),0,0}, - { "NOT", SYM(NOT),0,0}, - { "NO_WRITE_TO_BINLOG", SYM(NO_WRITE_TO_BINLOG),0,0}, - { "NULL", SYM(NULL_SYM),0,0}, - { "NUMERIC", SYM(NUMERIC_SYM),0,0}, - { "NVARCHAR", SYM(NVARCHAR_SYM),0,0}, - { "OFFSET", SYM(OFFSET_SYM),0,0}, - { "OLD_PASSWORD", SYM(OLD_PASSWORD),0,0}, - { "ON", SYM(ON),0,0}, - { "OPEN", SYM(OPEN_SYM),0,0}, - { "OPTIMIZE", SYM(OPTIMIZE),0,0}, - { "OPTION", SYM(OPTION),0,0}, - { "OPTIONALLY", SYM(OPTIONALLY),0,0}, - { "OR", SYM(OR),0,0}, - { "ORDER", SYM(ORDER_SYM),0,0}, - { "OUT", SYM(OUT_SYM),0,0}, - { "OUTER", SYM(OUTER),0,0}, - { "OUTFILE", SYM(OUTFILE),0,0}, - { "PACK_KEYS", SYM(PACK_KEYS_SYM),0,0}, - { "PARTIAL", SYM(PARTIAL),0,0}, - { "PASSWORD", SYM(PASSWORD),0,0}, - { "POINT", SYM(POINT_SYM),0,0}, - { "POLYGON", SYM(POLYGON),0,0}, - { "PRECISION", SYM(PRECISION),0,0}, - { "PREV", SYM(PREV_SYM),0,0}, - { "PRIMARY", SYM(PRIMARY_SYM),0,0}, - { "PRIVILEGES", SYM(PRIVILEGES),0,0}, - { "PROCEDURE", SYM(PROCEDURE),0,0}, - { "PROCESS" , SYM(PROCESS),0,0}, - { "PROCESSLIST", SYM(PROCESSLIST_SYM),0,0}, - { "PURGE", SYM(PURGE),0,0}, - { "QUARTER", SYM(QUARTER_SYM),0,0}, - { "QUERY", SYM(QUERY_SYM),0,0}, - { "QUICK", SYM(QUICK),0,0}, - { "RAID0", SYM(RAID_0_SYM),0,0}, - { "RAID_CHUNKS", SYM(RAID_CHUNKS),0,0}, - { "RAID_CHUNKSIZE", SYM(RAID_CHUNKSIZE),0,0}, - { "RAID_TYPE", SYM(RAID_TYPE),0,0}, - { "READ", SYM(READ_SYM),0,0}, - { "REAL", SYM(REAL),0,0}, - { "REFERENCES", SYM(REFERENCES),0,0}, - { "REGEXP", SYM(REGEXP),0,0}, - { "RELAY_LOG_FILE", SYM(RELAY_LOG_FILE_SYM),0,0}, - { "RELAY_LOG_POS", SYM(RELAY_LOG_POS_SYM),0,0}, - { "RELAY_THREAD", SYM(RELAY_THREAD),0,0}, - { "RELOAD", SYM(RELOAD),0,0}, - { "RENAME", SYM(RENAME),0,0}, - { "REPAIR", SYM(REPAIR),0,0}, - { "REPEATABLE", SYM(REPEATABLE_SYM),0,0}, - { "REPLACE", SYM(REPLACE),0,0}, - { "REPLICATION", SYM(REPLICATION),0,0}, - { "REPEAT", SYM(REPEAT_SYM),0,0}, - { "REQUIRE", SYM(REQUIRE_SYM),0,0}, - { "RESET", SYM(RESET_SYM),0,0}, - { "RESTORE", SYM(RESTORE_SYM),0,0}, - { "RESTRICT", SYM(RESTRICT),0,0}, - { "RETURN", SYM(RETURN_SYM),0,0}, - { "RETURNS", SYM(RETURNS_SYM),0,0}, - { "REVOKE", SYM(REVOKE),0,0}, - { "RIGHT", SYM(RIGHT),0,0}, - { "RLIKE", SYM(REGEXP),0,0}, /* Like in mSQL2 */ - { "ROLLBACK", SYM(ROLLBACK_SYM),0,0}, - { "ROLLUP", SYM(ROLLUP_SYM),0,0}, - { "ROW", SYM(ROW_SYM),0,0}, - { "ROWS", SYM(ROWS_SYM),0,0}, - { "ROW_FORMAT", SYM(ROW_FORMAT_SYM),0,0}, - { "RTREE", SYM(RTREE_SYM),0,0}, - { "SAVEPOINT", SYM(SAVEPOINT_SYM),0,0}, - { "SECOND", SYM(SECOND_SYM),0,0}, - { "SECOND_MICROSECOND", SYM(SECOND_MICROSECOND_SYM),0,0}, - { "SECURITY", SYM(SECURITY_SYM),0,0}, - { "SELECT", SYM(SELECT_SYM),0,0}, - { "SENSITIVE", SYM(SENSITIVE_SYM),0,0}, - { "SEPARATOR", SYM(SEPARATOR_SYM),0,0}, - { "SERIAL", SYM(SERIAL_SYM),0,0}, - { "SERIALIZABLE", SYM(SERIALIZABLE_SYM),0,0}, - { "SESSION", SYM(SESSION_SYM),0,0}, - { "SET", SYM(SET),0,0}, - { "SHARE", SYM(SHARE_SYM),0,0}, - { "SHOW", SYM(SHOW),0,0}, - { "SHUTDOWN", SYM(SHUTDOWN),0,0}, - { "SIGNED", SYM(SIGNED_SYM),0,0}, - { "SIMPLE", SYM(SIMPLE_SYM),0,0}, - { "SLAVE", SYM(SLAVE),0,0}, - { "SMALLINT", SYM(SMALLINT),0,0}, - { "SOME", SYM(ANY_SYM),0,0}, - { "SONAME", SYM(UDF_SONAME_SYM),0,0}, - { "SOUNDS", SYM(SOUNDS_SYM),0,0}, - { "SPATIAL", SYM(SPATIAL_SYM),0,0}, - { "SPECIFIC", SYM(SPECIFIC_SYM),0,0}, - { "SQL", SYM(SQL_SYM),0,0}, - { "SQLEXCEPTION", SYM(SQLEXCEPTION_SYM),0,0}, - { "SQLSTATE", SYM(SQLSTATE_SYM),0,0}, - { "SQLWARNING", SYM(SQLWARNING_SYM),0,0}, - { "SQL_BIG_RESULT", SYM(SQL_BIG_RESULT),0,0}, - { "SQL_BUFFER_RESULT", SYM(SQL_BUFFER_RESULT),0,0}, - { "SQL_CACHE", SYM(SQL_CACHE_SYM), 0, 0}, - { "SQL_CALC_FOUND_ROWS", SYM(SQL_CALC_FOUND_ROWS),0,0}, - { "SQL_NO_CACHE", SYM(SQL_NO_CACHE_SYM), 0, 0}, - { "SQL_SMALL_RESULT", SYM(SQL_SMALL_RESULT),0,0}, - { "SQL_THREAD", SYM(SQL_THREAD),0,0}, - { "SQL_TSI_FRAC_SECOND", SYM(FRAC_SECOND_SYM),0,0}, - { "SQL_TSI_SECOND", SYM(SECOND_SYM),0,0}, - { "SQL_TSI_MINUTE", SYM(MINUTE_SYM),0,0}, - { "SQL_TSI_HOUR", SYM(HOUR_SYM),0,0}, - { "SQL_TSI_DAY", SYM(DAY_SYM),0,0}, - { "SQL_TSI_WEEK", SYM(WEEK_SYM),0,0}, - { "SQL_TSI_MONTH", SYM(MONTH_SYM),0,0}, - { "SQL_TSI_QUARTER", SYM(QUARTER_SYM),0,0}, - { "SQL_TSI_YEAR", SYM(YEAR_SYM),0,0}, - { "SSL", SYM(SSL_SYM),0,0}, - { "START", SYM(START_SYM),0,0}, - { "STARTING", SYM(STARTING),0,0}, - { "STATUS", SYM(STATUS_SYM),0,0}, - { "STOP", SYM(STOP_SYM),0,0}, - { "STORAGE", SYM(STORAGE_SYM),0,0}, - { "STRAIGHT_JOIN", SYM(STRAIGHT_JOIN),0,0}, - { "STRING", SYM(STRING_SYM),0,0}, - { "STRIPED", SYM(RAID_STRIPED_SYM),0,0}, - { "SUBJECT", SYM(SUBJECT_SYM),0,0}, - { "SUPER", SYM(SUPER_SYM),0,0}, - { "TABLE", SYM(TABLE_SYM),0,0}, - { "TABLES", SYM(TABLES),0,0}, - { "TABLESPACE", SYM(TABLESPACE),0,0}, - { "TEMPORARY", SYM(TEMPORARY),0,0}, - { "TERMINATED", SYM(TERMINATED),0,0}, - { "TEXT", SYM(TEXT_SYM),0,0}, - { "THEN", SYM(THEN_SYM),0,0}, - { "TIME", SYM(TIME_SYM),0,0}, - { "TIMESTAMP", SYM(TIMESTAMP),0,0}, - { "TIMESTAMPADD", SYM(TIMESTAMP_ADD),0,0}, - { "TIMESTAMPDIFF", SYM(TIMESTAMP_DIFF),0,0}, - { "TINYBLOB", SYM(TINYBLOB),0,0}, - { "TINYINT", SYM(TINYINT),0,0}, - { "TINYTEXT", SYM(TINYTEXT),0,0}, - { "TO", SYM(TO_SYM),0,0}, - { "TRAILING", SYM(TRAILING),0,0}, - { "TRANSACTION", SYM(TRANSACTION_SYM),0,0}, - { "TRUE", SYM(TRUE_SYM),0,0}, - { "TRUNCATE", SYM(TRUNCATE_SYM),0,0}, - { "TYPE", SYM(TYPE_SYM),0,0}, - { "TYPES", SYM(TYPES_SYM),0,0}, - { "UNCOMMITTED", SYM(UNCOMMITTED_SYM),0,0}, - { "UNDO", SYM(UNDO_SYM),0,0}, - { "UNICODE", SYM(UNICODE_SYM),0,0}, - { "UNION", SYM(UNION_SYM),0,0}, - { "UNIQUE", SYM(UNIQUE_SYM),0,0}, - { "UNLOCK", SYM(UNLOCK_SYM),0,0}, - { "UNSIGNED", SYM(UNSIGNED),0,0}, - { "UNTIL", SYM(UNTIL_SYM),0,0}, - { "UPDATE", SYM(UPDATE_SYM),0,0}, - { "USAGE", SYM(USAGE),0,0}, - { "USE", SYM(USE_SYM),0,0}, - { "USER", SYM(USER),0,0}, - { "USER_RESOURCES", SYM(RESOURCES),0,0}, - { "USE_FRM", SYM(USE_FRM),0,0}, - { "USING", SYM(USING),0,0}, - { "UTC_DATE", SYM(UTC_DATE_SYM),0,0}, - { "UTC_TIME", SYM(UTC_TIME_SYM),0,0}, - { "UTC_TIMESTAMP", SYM(UTC_TIMESTAMP_SYM),0,0}, - { "VALUE", SYM(VALUE_SYM),0,0}, - { "VALUES", SYM(VALUES),0,0}, - { "VARBINARY", SYM(VARBINARY),0,0}, - { "VARCHAR", SYM(VARCHAR),0,0}, - { "VARCHARACTER", SYM(VARCHAR),0,0}, - { "VARIABLES", SYM(VARIABLES),0,0}, - { "VARYING", SYM(VARYING),0,0}, - { "WARNINGS", SYM(WARNINGS),0,0}, - { "WEEK", SYM(WEEK_SYM),0,0}, - { "WHEN", SYM(WHEN_SYM),0,0}, - { "WHERE", SYM(WHERE),0,0}, - { "WITH", SYM(WITH),0,0}, - { "WORK", SYM(WORK_SYM),0,0}, - { "WRITE", SYM(WRITE_SYM),0,0}, - { "WHILE", SYM(WHILE_SYM),0,0}, - { "X509", SYM(X509_SYM),0,0}, - { "XOR", SYM(XOR),0,0}, - { "YEAR", SYM(YEAR_SYM),0,0}, - { "YEAR_MONTH", SYM(YEAR_MONTH_SYM),0,0}, - { "ZEROFILL", SYM(ZEROFILL),0,0}, - { "||", SYM(OR_OR_CONCAT),0,0} + { "&&", SYM(AND)}, + { "<", SYM(LT)}, + { "<=", SYM(LE)}, + { "<>", SYM(NE)}, + { "!=", SYM(NE)}, + { "=", SYM(EQ)}, + { ">", SYM(GT_SYM)}, + { ">=", SYM(GE)}, + { "<<", SYM(SHIFT_LEFT)}, + { ">>", SYM(SHIFT_RIGHT)}, + { "<=>", SYM(EQUAL_SYM)}, + { "ACTION", SYM(ACTION)}, + { "ADD", SYM(ADD)}, + { "AFTER", SYM(AFTER_SYM)}, + { "AGAINST", SYM(AGAINST)}, + { "AGGREGATE", SYM(AGGREGATE_SYM)}, + { "ALL", SYM(ALL)}, + { "ALTER", SYM(ALTER)}, + { "ANALYZE", SYM(ANALYZE_SYM)}, + { "AND", SYM(AND)}, + { "ANY", SYM(ANY_SYM)}, + { "AS", SYM(AS)}, + { "ASC", SYM(ASC)}, + { "ASCII", SYM(ASCII_SYM)}, + { "ASENSITIVE", SYM(ASENSITIVE_SYM)}, + { "AUTO_INCREMENT", SYM(AUTO_INC)}, + { "AVG", SYM(AVG_SYM)}, + { "AVG_ROW_LENGTH", SYM(AVG_ROW_LENGTH)}, + { "BACKUP", SYM(BACKUP_SYM)}, + { "BDB", SYM(BERKELEY_DB_SYM)}, + { "BEFORE", SYM(BEFORE_SYM)}, + { "BEGIN", SYM(BEGIN_SYM)}, + { "BERKELEYDB", SYM(BERKELEY_DB_SYM)}, + { "BETWEEN", SYM(BETWEEN_SYM)}, + { "BIGINT", SYM(BIGINT)}, + { "BINARY", SYM(BINARY)}, + { "BINLOG", SYM(BINLOG_SYM)}, + { "BIT", SYM(BIT_SYM)}, + { "BLOB", SYM(BLOB_SYM)}, + { "BOOL", SYM(BOOL_SYM)}, + { "BOOLEAN", SYM(BOOLEAN_SYM)}, + { "BOTH", SYM(BOTH)}, + { "BTREE", SYM(BTREE_SYM)}, + { "BY", SYM(BY)}, + { "BYTE", SYM(BYTE_SYM)}, + { "CACHE", SYM(CACHE_SYM)}, + { "CALL", SYM(CALL_SYM)}, + { "CASCADE", SYM(CASCADE)}, + { "CASE", SYM(CASE_SYM)}, + { "CHANGE", SYM(CHANGE)}, + { "CHANGED", SYM(CHANGED)}, + { "CHAR", SYM(CHAR_SYM)}, + { "CHARACTER", SYM(CHAR_SYM)}, + { "CHARSET", SYM(CHARSET)}, + { "CHECK", SYM(CHECK_SYM)}, + { "CHECKSUM", SYM(CHECKSUM_SYM)}, + { "CIPHER", SYM(CIPHER_SYM)}, + { "CLIENT", SYM(CLIENT_SYM)}, + { "CLOSE", SYM(CLOSE_SYM)}, + { "COLLATE", SYM(COLLATE_SYM)}, + { "COLLATION", SYM(COLLATION_SYM)}, + { "COLUMN", SYM(COLUMN_SYM)}, + { "COLUMNS", SYM(COLUMNS)}, + { "COMMENT", SYM(COMMENT_SYM)}, + { "COMMIT", SYM(COMMIT_SYM)}, + { "COMMITTED", SYM(COMMITTED_SYM)}, + { "COMPRESSED", SYM(COMPRESSED_SYM)}, + { "CONCURRENT", SYM(CONCURRENT)}, + { "CONDITION", SYM(CONDITION_SYM)}, + { "CONNECTION", SYM(CONNECTION_SYM)}, + { "CONSTRAINT", SYM(CONSTRAINT)}, + { "CONTINUE", SYM(CONTINUE_SYM)}, + { "CREATE", SYM(CREATE)}, + { "CROSS", SYM(CROSS)}, + { "CUBE", SYM(CUBE_SYM)}, + { "CURRENT_DATE", SYM(CURDATE)}, + { "CURRENT_TIME", SYM(CURTIME)}, + { "CURRENT_TIMESTAMP", SYM(NOW_SYM)}, + { "CURSOR", SYM(CURSOR_SYM)}, + { "DATA", SYM(DATA_SYM)}, + { "DATABASE", SYM(DATABASE)}, + { "DATABASES", SYM(DATABASES)}, + { "DATE", SYM(DATE_SYM)}, + { "DATETIME", SYM(DATETIME)}, + { "DAY", SYM(DAY_SYM)}, + { "DAY_HOUR", SYM(DAY_HOUR_SYM)}, + { "DAY_MICROSECOND", SYM(DAY_MICROSECOND_SYM)}, + { "DAY_MINUTE", SYM(DAY_MINUTE_SYM)}, + { "DAY_SECOND", SYM(DAY_SECOND_SYM)}, + { "DEC", SYM(DECIMAL_SYM)}, + { "DECIMAL", SYM(DECIMAL_SYM)}, + { "DECLARE", SYM(DECLARE_SYM)}, + { "DEFAULT", SYM(DEFAULT)}, + { "DEFINER", SYM(DEFINER_SYM)}, + { "DELAYED", SYM(DELAYED_SYM)}, + { "DELAY_KEY_WRITE", SYM(DELAY_KEY_WRITE_SYM)}, + { "DELETE", SYM(DELETE_SYM)}, + { "DESC", SYM(DESC)}, + { "DESCRIBE", SYM(DESCRIBE)}, + { "DES_KEY_FILE", SYM(DES_KEY_FILE)}, + { "DETERMINISTIC", SYM(DETERMINISTIC_SYM)}, + { "DIRECTORY", SYM(DIRECTORY_SYM)}, + { "DISABLE", SYM(DISABLE_SYM)}, + { "DISCARD", SYM(DISCARD)}, + { "DISTINCT", SYM(DISTINCT)}, + { "DISTINCTROW", SYM(DISTINCT)}, /* Access likes this */ + { "DIV", SYM(DIV_SYM)}, + { "DO", SYM(DO_SYM)}, + { "DOUBLE", SYM(DOUBLE_SYM)}, + { "DROP", SYM(DROP)}, + { "DUAL", SYM(DUAL_SYM)}, + { "DUMPFILE", SYM(DUMPFILE)}, + { "DUPLICATE", SYM(DUPLICATE_SYM)}, + { "DYNAMIC", SYM(DYNAMIC_SYM)}, + { "ELSE", SYM(ELSE)}, + { "ELSEIF", SYM(ELSEIF_SYM)}, + { "ENABLE", SYM(ENABLE_SYM)}, + { "ENCLOSED", SYM(ENCLOSED)}, + { "END", SYM(END)}, + { "ENGINE", SYM(ENGINE_SYM)}, + { "ENGINES", SYM(ENGINES_SYM)}, + { "ENUM", SYM(ENUM)}, + { "ERRORS", SYM(ERRORS)}, + { "ESCAPE", SYM(ESCAPE_SYM)}, + { "ESCAPED", SYM(ESCAPED)}, + { "EVENTS", SYM(EVENTS_SYM)}, + { "EXECUTE", SYM(EXECUTE_SYM)}, + { "EXISTS", SYM(EXISTS)}, + { "EXIT", SYM(EXIT_SYM)}, + { "EXPANSION", SYM(EXPANSION_SYM)}, + { "EXPLAIN", SYM(DESCRIBE)}, + { "EXTENDED", SYM(EXTENDED_SYM)}, + { "FALSE", SYM(FALSE_SYM)}, + { "FAST", SYM(FAST_SYM)}, + { "FETCH", SYM(FETCH_SYM)}, + { "FIELDS", SYM(COLUMNS)}, + { "FILE", SYM(FILE_SYM)}, + { "FIRST", SYM(FIRST_SYM)}, + { "FIXED", SYM(FIXED_SYM)}, + { "FLOAT", SYM(FLOAT_SYM)}, + { "FLOAT4", SYM(FLOAT_SYM)}, + { "FLOAT8", SYM(DOUBLE_SYM)}, + { "FLUSH", SYM(FLUSH_SYM)}, + { "FOR", SYM(FOR_SYM)}, + { "FORCE", SYM(FORCE_SYM)}, + { "FOREIGN", SYM(FOREIGN)}, + { "FOUND", SYM(FOUND_SYM)}, + { "FRAC_SECOND", SYM(FRAC_SECOND_SYM)}, + { "FROM", SYM(FROM)}, + { "FULL", SYM(FULL)}, + { "FULLTEXT", SYM(FULLTEXT_SYM)}, + { "FUNCTION", SYM(FUNCTION_SYM)}, + { "GEOMETRY", SYM(GEOMETRY_SYM)}, + { "GEOMETRYCOLLECTION",SYM(GEOMETRYCOLLECTION)}, + { "GET_FORMAT", SYM(GET_FORMAT)}, + { "GLOBAL", SYM(GLOBAL_SYM)}, + { "GRANT", SYM(GRANT)}, + { "GRANTS", SYM(GRANTS)}, + { "GROUP", SYM(GROUP)}, + { "HANDLER", SYM(HANDLER_SYM)}, + { "HASH", SYM(HASH_SYM)}, + { "HAVING", SYM(HAVING)}, + { "HELP", SYM(HELP_SYM)}, + { "HIGH_PRIORITY", SYM(HIGH_PRIORITY)}, + { "HOSTS", SYM(HOSTS_SYM)}, + { "HOUR", SYM(HOUR_SYM)}, + { "HOUR_MICROSECOND", SYM(HOUR_MICROSECOND_SYM)}, + { "HOUR_MINUTE", SYM(HOUR_MINUTE_SYM)}, + { "HOUR_SECOND", SYM(HOUR_SECOND_SYM)}, + { "IDENTIFIED", SYM(IDENTIFIED_SYM)}, + { "IF", SYM(IF)}, + { "IGNORE", SYM(IGNORE_SYM)}, + { "IMPORT", SYM(IMPORT)}, + { "IN", SYM(IN_SYM)}, + { "INDEX", SYM(INDEX)}, + { "INDEXES", SYM(INDEXES)}, + { "INFILE", SYM(INFILE)}, + { "INNER", SYM(INNER_SYM)}, + { "INNOBASE", SYM(INNOBASE_SYM)}, + { "INNODB", SYM(INNOBASE_SYM)}, + { "INOUT", SYM(INOUT_SYM)}, + { "INSENSITIVE", SYM(INSENSITIVE_SYM)}, + { "INSERT", SYM(INSERT)}, + { "INSERT_METHOD", SYM(INSERT_METHOD)}, + { "INT", SYM(INT_SYM)}, + { "INT1", SYM(TINYINT)}, + { "INT2", SYM(SMALLINT)}, + { "INT3", SYM(MEDIUMINT)}, + { "INT4", SYM(INT_SYM)}, + { "INT8", SYM(BIGINT)}, + { "INTEGER", SYM(INT_SYM)}, + { "INTERVAL", SYM(INTERVAL_SYM)}, + { "INTO", SYM(INTO)}, + { "IO_THREAD", SYM(RELAY_THREAD)}, + { "IS", SYM(IS)}, + { "ISOLATION", SYM(ISOLATION)}, + { "ISSUER", SYM(ISSUER_SYM)}, + { "ITERATE", SYM(ITERATE_SYM)}, + { "INVOKER", SYM(INVOKER_SYM)}, + { "JOIN", SYM(JOIN_SYM)}, + { "KEY", SYM(KEY_SYM)}, + { "KEYS", SYM(KEYS)}, + { "KILL", SYM(KILL_SYM)}, + { "LANGUAGE", SYM(LANGAUGE_SYM)}, + { "LAST", SYM(LAST_SYM)}, + { "LEADING", SYM(LEADING)}, + { "LEAVE", SYM(LEAVE_SYM)}, + { "LEAVES", SYM(LEAVES)}, + { "LEFT", SYM(LEFT)}, + { "LEVEL", SYM(LEVEL_SYM)}, + { "LIKE", SYM(LIKE)}, + { "LIMIT", SYM(LIMIT)}, + { "LINES", SYM(LINES)}, + { "LINESTRING", SYM(LINESTRING)}, + { "LOAD", SYM(LOAD)}, + { "LOCAL", SYM(LOCAL_SYM)}, + { "LOCALTIME", SYM(NOW_SYM)}, + { "LOCALTIMESTAMP", SYM(NOW_SYM)}, + { "LOCK", SYM(LOCK_SYM)}, + { "LOCKS", SYM(LOCKS_SYM)}, + { "LOGS", SYM(LOGS_SYM)}, + { "LONG", SYM(LONG_SYM)}, + { "LONGBLOB", SYM(LONGBLOB)}, + { "LONGTEXT", SYM(LONGTEXT)}, + { "LOOP", SYM(LOOP_SYM)}, + { "LOW_PRIORITY", SYM(LOW_PRIORITY)}, + { "MASTER", SYM(MASTER_SYM)}, + { "MASTER_CONNECT_RETRY", SYM(MASTER_CONNECT_RETRY_SYM)}, + { "MASTER_HOST", SYM(MASTER_HOST_SYM)}, + { "MASTER_LOG_FILE", SYM(MASTER_LOG_FILE_SYM)}, + { "MASTER_LOG_POS", SYM(MASTER_LOG_POS_SYM)}, + { "MASTER_PASSWORD", SYM(MASTER_PASSWORD_SYM)}, + { "MASTER_PORT", SYM(MASTER_PORT_SYM)}, + { "MASTER_SERVER_ID", SYM(MASTER_SERVER_ID_SYM)}, + { "MASTER_SSL", SYM(MASTER_SSL_SYM)}, + { "MASTER_SSL_CA", SYM(MASTER_SSL_CA_SYM)}, + { "MASTER_SSL_CAPATH",SYM(MASTER_SSL_CAPATH_SYM)}, + { "MASTER_SSL_CERT", SYM(MASTER_SSL_CERT_SYM)}, + { "MASTER_SSL_CIPHER",SYM(MASTER_SSL_CIPHER_SYM)}, + { "MASTER_SSL_KEY", SYM(MASTER_SSL_KEY_SYM)}, + { "MASTER_USER", SYM(MASTER_USER_SYM)}, + { "MATCH", SYM(MATCH)}, + { "MAX_CONNECTIONS_PER_HOUR", SYM(MAX_CONNECTIONS_PER_HOUR)}, + { "MAX_QUERIES_PER_HOUR", SYM(MAX_QUERIES_PER_HOUR)}, + { "MAX_ROWS", SYM(MAX_ROWS)}, + { "MAX_UPDATES_PER_HOUR", SYM(MAX_UPDATES_PER_HOUR)}, + { "MEDIUM", SYM(MEDIUM_SYM)}, + { "MEDIUMBLOB", SYM(MEDIUMBLOB)}, + { "MEDIUMINT", SYM(MEDIUMINT)}, + { "MEDIUMTEXT", SYM(MEDIUMTEXT)}, + { "MICROSECOND", SYM(MICROSECOND_SYM)}, + { "MIDDLEINT", SYM(MEDIUMINT)}, /* For powerbuilder */ + { "MINUTE", SYM(MINUTE_SYM)}, + { "MINUTE_MICROSECOND", SYM(MINUTE_MICROSECOND_SYM)}, + { "MINUTE_SECOND", SYM(MINUTE_SECOND_SYM)}, + { "MIN_ROWS", SYM(MIN_ROWS)}, + { "MOD", SYM(MOD_SYM)}, + { "MODE", SYM(MODE_SYM)}, + { "MODIFY", SYM(MODIFY_SYM)}, + { "MONTH", SYM(MONTH_SYM)}, + { "MULTILINESTRING", SYM(MULTILINESTRING)}, + { "MULTIPOINT", SYM(MULTIPOINT)}, + { "MULTIPOLYGON", SYM(MULTIPOLYGON)}, + { "NAME", SYM(NAME_SYM)}, + { "NAMES", SYM(NAMES_SYM)}, + { "NATIONAL", SYM(NATIONAL_SYM)}, + { "NATURAL", SYM(NATURAL)}, + { "NCHAR", SYM(NCHAR_SYM)}, + { "NEW", SYM(NEW_SYM)}, + { "NEXT", SYM(NEXT_SYM)}, + { "NO", SYM(NO_SYM)}, + { "NONE", SYM(NONE_SYM)}, + { "NOT", SYM(NOT)}, + { "NO_WRITE_TO_BINLOG", SYM(NO_WRITE_TO_BINLOG)}, + { "NULL", SYM(NULL_SYM)}, + { "NUMERIC", SYM(NUMERIC_SYM)}, + { "NVARCHAR", SYM(NVARCHAR_SYM)}, + { "OFFSET", SYM(OFFSET_SYM)}, + { "OLD_PASSWORD", SYM(OLD_PASSWORD)}, + { "ON", SYM(ON)}, + { "OPEN", SYM(OPEN_SYM)}, + { "OPTIMIZE", SYM(OPTIMIZE)}, + { "OPTION", SYM(OPTION)}, + { "OPTIONALLY", SYM(OPTIONALLY)}, + { "OR", SYM(OR)}, + { "ORDER", SYM(ORDER_SYM)}, + { "OUT", SYM(OUT_SYM)}, + { "OUTER", SYM(OUTER)}, + { "OUTFILE", SYM(OUTFILE)}, + { "PACK_KEYS", SYM(PACK_KEYS_SYM)}, + { "PARTIAL", SYM(PARTIAL)}, + { "PASSWORD", SYM(PASSWORD)}, + { "POINT", SYM(POINT_SYM)}, + { "POLYGON", SYM(POLYGON)}, + { "PRECISION", SYM(PRECISION)}, + { "PREV", SYM(PREV_SYM)}, + { "PRIMARY", SYM(PRIMARY_SYM)}, + { "PRIVILEGES", SYM(PRIVILEGES)}, + { "PROCEDURE", SYM(PROCEDURE)}, + { "PROCESS" , SYM(PROCESS)}, + { "PROCESSLIST", SYM(PROCESSLIST_SYM)}, + { "PURGE", SYM(PURGE)}, + { "QUARTER", SYM(QUARTER_SYM)}, + { "QUERY", SYM(QUERY_SYM)}, + { "QUICK", SYM(QUICK)}, + { "RAID0", SYM(RAID_0_SYM)}, + { "RAID_CHUNKS", SYM(RAID_CHUNKS)}, + { "RAID_CHUNKSIZE", SYM(RAID_CHUNKSIZE)}, + { "RAID_TYPE", SYM(RAID_TYPE)}, + { "READ", SYM(READ_SYM)}, + { "REAL", SYM(REAL)}, + { "REFERENCES", SYM(REFERENCES)}, + { "REGEXP", SYM(REGEXP)}, + { "RELAY_LOG_FILE", SYM(RELAY_LOG_FILE_SYM)}, + { "RELAY_LOG_POS", SYM(RELAY_LOG_POS_SYM)}, + { "RELAY_THREAD", SYM(RELAY_THREAD)}, + { "RELOAD", SYM(RELOAD)}, + { "RENAME", SYM(RENAME)}, + { "REPAIR", SYM(REPAIR)}, + { "REPEATABLE", SYM(REPEATABLE_SYM)}, + { "REPLACE", SYM(REPLACE)}, + { "REPLICATION", SYM(REPLICATION)}, + { "REPEAT", SYM(REPEAT_SYM)}, + { "REQUIRE", SYM(REQUIRE_SYM)}, + { "RESET", SYM(RESET_SYM)}, + { "RESTORE", SYM(RESTORE_SYM)}, + { "RESTRICT", SYM(RESTRICT)}, + { "RETURN", SYM(RETURN_SYM)}, + { "RETURNS", SYM(RETURNS_SYM)}, + { "REVOKE", SYM(REVOKE)}, + { "RIGHT", SYM(RIGHT)}, + { "RLIKE", SYM(REGEXP)}, /* Like in mSQL2 */ + { "ROLLBACK", SYM(ROLLBACK_SYM)}, + { "ROLLUP", SYM(ROLLUP_SYM)}, + { "ROW", SYM(ROW_SYM)}, + { "ROWS", SYM(ROWS_SYM)}, + { "ROW_FORMAT", SYM(ROW_FORMAT_SYM)}, + { "RTREE", SYM(RTREE_SYM)}, + { "SAVEPOINT", SYM(SAVEPOINT_SYM)}, + { "SECOND", SYM(SECOND_SYM)}, + { "SECOND_MICROSECOND", SYM(SECOND_MICROSECOND_SYM)}, + { "SECURITY", SYM(SECURITY_SYM)}, + { "SELECT", SYM(SELECT_SYM)}, + { "SENSITIVE", SYM(SENSITIVE_SYM)}, + { "SEPARATOR", SYM(SEPARATOR_SYM)}, + { "SERIAL", SYM(SERIAL_SYM)}, + { "SERIALIZABLE", SYM(SERIALIZABLE_SYM)}, + { "SESSION", SYM(SESSION_SYM)}, + { "SET", SYM(SET)}, + { "SHARE", SYM(SHARE_SYM)}, + { "SHOW", SYM(SHOW)}, + { "SHUTDOWN", SYM(SHUTDOWN)}, + { "SIGNED", SYM(SIGNED_SYM)}, + { "SIMPLE", SYM(SIMPLE_SYM)}, + { "SLAVE", SYM(SLAVE)}, + { "SMALLINT", SYM(SMALLINT)}, + { "SOME", SYM(ANY_SYM)}, + { "SONAME", SYM(UDF_SONAME_SYM)}, + { "SOUNDS", SYM(SOUNDS_SYM)}, + { "SPATIAL", SYM(SPATIAL_SYM)}, + { "SPECIFIC", SYM(SPECIFIC_SYM)}, + { "SQL", SYM(SQL_SYM)}, + { "SQLEXCEPTION", SYM(SQLEXCEPTION_SYM)}, + { "SQLSTATE", SYM(SQLSTATE_SYM)}, + { "SQLWARNING", SYM(SQLWARNING_SYM)}, + { "SQL_BIG_RESULT", SYM(SQL_BIG_RESULT)}, + { "SQL_BUFFER_RESULT", SYM(SQL_BUFFER_RESULT)}, + { "SQL_CACHE", SYM(SQL_CACHE_SYM)}, + { "SQL_CALC_FOUND_ROWS", SYM(SQL_CALC_FOUND_ROWS)}, + { "SQL_NO_CACHE", SYM(SQL_NO_CACHE_SYM)}, + { "SQL_SMALL_RESULT", SYM(SQL_SMALL_RESULT)}, + { "SQL_THREAD", SYM(SQL_THREAD)}, + { "SQL_TSI_FRAC_SECOND", SYM(FRAC_SECOND_SYM)}, + { "SQL_TSI_SECOND", SYM(SECOND_SYM)}, + { "SQL_TSI_MINUTE", SYM(MINUTE_SYM)}, + { "SQL_TSI_HOUR", SYM(HOUR_SYM)}, + { "SQL_TSI_DAY", SYM(DAY_SYM)}, + { "SQL_TSI_WEEK", SYM(WEEK_SYM)}, + { "SQL_TSI_MONTH", SYM(MONTH_SYM)}, + { "SQL_TSI_QUARTER", SYM(QUARTER_SYM)}, + { "SQL_TSI_YEAR", SYM(YEAR_SYM)}, + { "SSL", SYM(SSL_SYM)}, + { "START", SYM(START_SYM)}, + { "STARTING", SYM(STARTING)}, + { "STATUS", SYM(STATUS_SYM)}, + { "STOP", SYM(STOP_SYM)}, + { "STORAGE", SYM(STORAGE_SYM)}, + { "STRAIGHT_JOIN", SYM(STRAIGHT_JOIN)}, + { "STRING", SYM(STRING_SYM)}, + { "STRIPED", SYM(RAID_STRIPED_SYM)}, + { "SUBJECT", SYM(SUBJECT_SYM)}, + { "SUPER", SYM(SUPER_SYM)}, + { "TABLE", SYM(TABLE_SYM)}, + { "TABLES", SYM(TABLES)}, + { "TABLESPACE", SYM(TABLESPACE)}, + { "TEMPORARY", SYM(TEMPORARY)}, + { "TERMINATED", SYM(TERMINATED)}, + { "TEXT", SYM(TEXT_SYM)}, + { "THEN", SYM(THEN_SYM)}, + { "TIME", SYM(TIME_SYM)}, + { "TIMESTAMP", SYM(TIMESTAMP)}, + { "TIMESTAMPADD", SYM(TIMESTAMP_ADD)}, + { "TIMESTAMPDIFF", SYM(TIMESTAMP_DIFF)}, + { "TINYBLOB", SYM(TINYBLOB)}, + { "TINYINT", SYM(TINYINT)}, + { "TINYTEXT", SYM(TINYTEXT)}, + { "TO", SYM(TO_SYM)}, + { "TRAILING", SYM(TRAILING)}, + { "TRANSACTION", SYM(TRANSACTION_SYM)}, + { "TRUE", SYM(TRUE_SYM)}, + { "TRUNCATE", SYM(TRUNCATE_SYM)}, + { "TYPE", SYM(TYPE_SYM)}, + { "TYPES", SYM(TYPES_SYM)}, + { "UNCOMMITTED", SYM(UNCOMMITTED_SYM)}, + { "UNDO", SYM(UNDO_SYM)}, + { "UNICODE", SYM(UNICODE_SYM)}, + { "UNION", SYM(UNION_SYM)}, + { "UNIQUE", SYM(UNIQUE_SYM)}, + { "UNLOCK", SYM(UNLOCK_SYM)}, + { "UNSIGNED", SYM(UNSIGNED)}, + { "UNTIL", SYM(UNTIL_SYM)}, + { "UPDATE", SYM(UPDATE_SYM)}, + { "USAGE", SYM(USAGE)}, + { "USE", SYM(USE_SYM)}, + { "USER", SYM(USER)}, + { "USER_RESOURCES", SYM(RESOURCES)}, + { "USE_FRM", SYM(USE_FRM)}, + { "USING", SYM(USING)}, + { "UTC_DATE", SYM(UTC_DATE_SYM)}, + { "UTC_TIME", SYM(UTC_TIME_SYM)}, + { "UTC_TIMESTAMP", SYM(UTC_TIMESTAMP_SYM)}, + { "VALUE", SYM(VALUE_SYM)}, + { "VALUES", SYM(VALUES)}, + { "VARBINARY", SYM(VARBINARY)}, + { "VARCHAR", SYM(VARCHAR)}, + { "VARCHARACTER", SYM(VARCHAR)}, + { "VARIABLES", SYM(VARIABLES)}, + { "VARYING", SYM(VARYING)}, + { "WARNINGS", SYM(WARNINGS)}, + { "WEEK", SYM(WEEK_SYM)}, + { "WHEN", SYM(WHEN_SYM)}, + { "WHERE", SYM(WHERE)}, + { "WHILE", SYM(WHILE_SYM)}, + { "WITH", SYM(WITH)}, + { "WORK", SYM(WORK_SYM)}, + { "WRITE", SYM(WRITE_SYM)}, + { "X509", SYM(X509_SYM)}, + { "XOR", SYM(XOR)}, + { "YEAR", SYM(YEAR_SYM)}, + { "YEAR_MONTH", SYM(YEAR_MONTH_SYM)}, + { "ZEROFILL", SYM(ZEROFILL)}, + { "||", SYM(OR_OR_CONCAT)} }; static SYMBOL sql_functions[] = { - { "ABS", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_abs)}, - { "ACOS", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_acos)}, - { "ADDDATE", SYM(ADDDATE_SYM),0,0}, - { "ADDTIME", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_addtime)}, - { "AES_ENCRYPT", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_aes_encrypt)}, - { "AES_DECRYPT", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_aes_decrypt)}, - { "AREA", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_area)}, - { "ASIN", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_asin)}, - { "ASBINARY", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_as_wkb)}, - { "ASTEXT", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_as_wkt)}, - { "ASWKB", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_as_wkb)}, - { "ASWKT", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_as_wkt)}, - { "ATAN", SYM(ATAN),0,0}, - { "ATAN2", SYM(ATAN),0,0}, - { "BENCHMARK", SYM(BENCHMARK_SYM),0,0}, - { "BIN", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_bin)}, - { "BIT_COUNT", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_bit_count)}, - { "BIT_OR", SYM(BIT_OR),0,0}, - { "BIT_AND", SYM(BIT_AND),0,0}, - { "BIT_XOR", SYM(BIT_XOR),0,0}, - { "CAST", SYM(CAST_SYM),0,0}, - { "CEIL", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ceiling)}, - { "CEILING", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ceiling)}, - { "CURRENT_USER", SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_current_user)}, - { "BIT_LENGTH", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_bit_length)}, - { "CENTROID", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_centroid)}, - { "CHAR_LENGTH", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_char_length)}, - { "CHARACTER_LENGTH", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_char_length)}, - { "COALESCE", SYM(COALESCE),0,0}, - { "COERCIBILITY", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_coercibility)}, - { "COMPRESS", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_compress)}, - { "CONCAT", SYM(CONCAT),0,0}, - { "CONCAT_WS", SYM(CONCAT_WS),0,0}, - { "CONNECTION_ID", SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_connection_id)}, - { "CONTAINS", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_contains)}, - { "CONV", SYM(FUNC_ARG3),0,CREATE_FUNC(create_func_conv)}, - { "CONVERT", SYM(CONVERT_SYM),0,0}, - { "COUNT", SYM(COUNT_SYM),0,0}, - { "COS", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_cos)}, - { "COT", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_cot)}, - { "CRC32", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_crc32)}, - { "CROSSES", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_crosses)}, - { "CURDATE", SYM(CURDATE),0,0}, - { "CURTIME", SYM(CURTIME),0,0}, - { "DATE_ADD", SYM(DATE_ADD_INTERVAL),0,0}, - { "DATEDIFF", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_datediff)}, - { "DATE_FORMAT", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_date_format)}, - { "DATE_SUB", SYM(DATE_SUB_INTERVAL),0,0}, - { "DAYNAME", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_dayname)}, - { "DAYOFMONTH", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_dayofmonth)}, - { "DAYOFWEEK", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_dayofweek)}, - { "DAYOFYEAR", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_dayofyear)}, - { "DECODE", SYM(DECODE_SYM),0,0}, - { "DEGREES", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_degrees)}, - { "DES_ENCRYPT", SYM(DES_ENCRYPT_SYM),0,0}, - { "DES_DECRYPT", SYM(DES_DECRYPT_SYM),0,0}, - { "DIMENSION", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_dimension)}, - { "DISJOINT", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_disjoint)}, - { "ELT", SYM(ELT_FUNC),0,0}, - { "ENCODE", SYM(ENCODE_SYM),0,0}, - { "ENCRYPT", SYM(ENCRYPT),0,0}, - { "ENDPOINT", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_endpoint)}, - { "ENVELOPE", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_envelope)}, - { "EQUALS", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_equals)}, - { "EXTERIORRING", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_exteriorring)}, - { "EXTRACT", SYM(EXTRACT_SYM),0,0}, - { "EXP", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_exp)}, - { "EXPORT_SET", SYM(EXPORT_SET),0,0}, - { "FIELD", SYM(FIELD_FUNC),0,0}, /* For compability */ - { "FIND_IN_SET", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_find_in_set)}, - { "FLOOR", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_floor)}, - { "FORMAT", SYM(FORMAT_SYM),0,0}, - { "FOUND_ROWS", SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_found_rows)}, - { "FROM_DAYS", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_from_days)}, - { "FROM_UNIXTIME", SYM(FROM_UNIXTIME),0,0}, - { "GET_LOCK", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_get_lock)}, - { "GEOMETRYN", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_geometryn)}, - { "GEOMETRYTYPE", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_geometry_type)}, - { "GEOMCOLLFROMTEXT", SYM(GEOMCOLLFROMTEXT),0,0}, - { "GEOMCOLLFROMWKB", SYM(GEOMFROMWKB),0,0}, - { "GEOMETRYCOLLECTIONFROMTEXT",SYM(GEOMCOLLFROMTEXT),0,0}, - { "GEOMETRYCOLLECTIONFROMWKB",SYM(GEOMFROMWKB),0,0}, - { "GEOMETRYFROMTEXT", SYM(GEOMFROMTEXT),0,0}, - { "GEOMETRYFROMWKB", SYM(GEOMFROMWKB),0,0}, - { "GEOMFROMTEXT", SYM(GEOMFROMTEXT),0,0}, - { "GEOMFROMWKB", SYM(GEOMFROMWKB),0,0}, - { "GLENGTH", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_glength)}, - { "GREATEST", SYM(GREATEST_SYM),0,0}, - { "GROUP_CONCAT", SYM(GROUP_CONCAT_SYM),0,0}, - { "GROUP_UNIQUE_USERS", SYM(GROUP_UNIQUE_USERS),0,0}, - { "HEX", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_hex)}, - { "IFNULL", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_ifnull)}, - { "INET_ATON", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_inet_aton)}, - { "INET_NTOA", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_inet_ntoa)}, - { "INSTR", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_instr)}, - { "INTERIORRINGN", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_interiorringn)}, - { "INTERSECTS", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_intersects)}, - { "ISCLOSED", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_isclosed)}, - { "ISEMPTY", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_isempty)}, - { "ISNULL", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_isnull)}, - { "IS_FREE_LOCK", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_is_free_lock)}, - { "IS_USED_LOCK", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_is_used_lock)}, - { "LAST_INSERT_ID", SYM(LAST_INSERT_ID),0,0}, - { "ISSIMPLE", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_issimple)}, - { "LAST_DAY", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_last_day)}, - { "LCASE", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_lcase)}, - { "LEAST", SYM(LEAST_SYM),0,0}, - { "LENGTH", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_length)}, - { "LN", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ln)}, - { "LINEFROMTEXT", SYM(LINEFROMTEXT),0,0}, - { "LINEFROMWKB", SYM(GEOMFROMWKB),0,0}, - { "LINESTRINGFROMTEXT",SYM(LINEFROMTEXT),0,0}, - { "LINESTRINGFROMWKB",SYM(GEOMFROMWKB),0,0}, - { "LOAD_FILE", SYM(FUNC_ARG1),0,CREATE_FUNC(create_load_file)}, - { "LOCATE", SYM(LOCATE),0,0}, - { "LOG", SYM(LOG_SYM),0,0}, - { "LOG2", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_log2)}, - { "LOG10", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_log10)}, - { "LOWER", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_lcase)}, - { "LPAD", SYM(FUNC_ARG3),0,CREATE_FUNC(create_func_lpad)}, - { "LTRIM", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ltrim)}, - { "MAKE_SET", SYM(MAKE_SET_SYM),0,0}, - { "MAKEDATE", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_makedate)}, - { "MAKETIME", SYM(FUNC_ARG3),0,CREATE_FUNC(create_func_maketime)}, - { "MASTER_POS_WAIT", SYM(MASTER_POS_WAIT),0,0}, - { "MAX", SYM(MAX_SYM),0,0}, - { "MBRCONTAINS", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_contains)}, - { "MBRDISJOINT", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_disjoint)}, - { "MBREQUAL", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_equals)}, - { "MBRINTERSECTS", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_intersects)}, - { "MBROVERLAPS", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_overlaps)}, - { "MBRTOUCHES", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_touches)}, - { "MBRWITHIN", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_within)}, - { "MD5", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_md5)}, - { "MID", SYM(SUBSTRING),0,0}, /* unireg function */ - { "MIN", SYM(MIN_SYM),0,0}, - { "MLINEFROMTEXT", SYM(MLINEFROMTEXT),0,0}, - { "MLINEFROMWKB", SYM(GEOMFROMWKB),0,0}, - { "MPOINTFROMTEXT", SYM(MPOINTFROMTEXT),0,0}, - { "MPOINTFROMWKB", SYM(GEOMFROMWKB),0,0}, - { "MPOLYFROMTEXT", SYM(MPOLYFROMTEXT),0,0}, - { "MPOLYFROMWKB", SYM(GEOMFROMWKB),0,0}, - { "MONTHNAME", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_monthname)}, - { "MULTILINESTRINGFROMTEXT",SYM(MLINEFROMTEXT),0,0}, - { "MULTILINESTRINGFROMWKB",SYM(GEOMFROMWKB),0,0}, - { "MULTIPOINTFROMTEXT",SYM(MPOINTFROMTEXT),0,0}, - { "MULTIPOINTFROMWKB",SYM(GEOMFROMWKB),0,0}, - { "MULTIPOLYGONFROMTEXT",SYM(MPOLYFROMTEXT),0,0}, - { "MULTIPOLYGONFROMWKB",SYM(GEOMFROMWKB),0,0}, - { "NOW", SYM(NOW_SYM),0,0}, - { "NULLIF", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_nullif)}, - { "NUMGEOMETRIES", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_numgeometries)}, - { "NUMINTERIORRINGS", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_numinteriorring)}, - { "NUMPOINTS", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_numpoints)}, - { "OCTET_LENGTH", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_length)}, - { "OCT", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_oct)}, - { "ORD", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ord)}, - { "OVERLAPS", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_overlaps)}, - { "PERIOD_ADD", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_period_add)}, - { "PERIOD_DIFF", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_period_diff)}, - { "PI", SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_pi)}, - { "POINTFROMTEXT", SYM(POINTFROMTEXT),0,0}, - { "POINTFROMWKB", SYM(GEOMFROMWKB),0,0}, - { "POINTN", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_pointn)}, - { "POLYFROMTEXT", SYM(POLYFROMTEXT),0,0}, - { "POLYFROMWKB", SYM(GEOMFROMWKB),0,0}, - { "POLYGONFROMTEXT", SYM(POLYFROMTEXT),0,0}, - { "POLYGONFROMWKB", SYM(GEOMFROMWKB),0,0}, - { "POSITION", SYM(POSITION_SYM),0,0}, - { "POW", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_pow)}, - { "POWER", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_pow)}, - { "QUOTE", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_quote)}, - { "RADIANS", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_radians)}, - { "RAND", SYM(RAND),0,0}, - { "RELEASE_LOCK", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_release_lock)}, - { "REVERSE", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_reverse)}, - { "ROUND", SYM(ROUND),0,0}, - { "RPAD", SYM(FUNC_ARG3),0,CREATE_FUNC(create_func_rpad)}, - { "RTRIM", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_rtrim)}, - { "SEC_TO_TIME", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sec_to_time)}, - { "SESSION_USER", SYM(USER),0,0}, - { "SUBDATE", SYM(SUBDATE_SYM),0,0}, - { "SIGN", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sign)}, - { "SIN", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sin)}, - { "SHA", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sha)}, - { "SHA1", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sha)}, - { "SOUNDEX", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_soundex)}, - { "SPACE", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_space)}, - { "SQRT", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sqrt)}, - { "SRID", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_srid)}, - { "STARTPOINT", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_startpoint)}, - { "STD", SYM(STD_SYM),0,0}, - { "STDDEV", SYM(STD_SYM),0,0}, - { "STR_TO_DATE", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_str_to_date)}, - { "STRCMP", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_strcmp)}, - { "SUBSTR", SYM(SUBSTRING),0,0}, - { "SUBSTRING", SYM(SUBSTRING),0,0}, - { "SUBSTRING_INDEX", SYM(SUBSTRING_INDEX),0,0}, - { "SUBTIME", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_subtime)}, - { "SUM", SYM(SUM_SYM),0,0}, - { "SYSDATE", SYM(NOW_SYM),0,0}, - { "SYSTEM_USER", SYM(USER),0,0}, - { "TAN", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_tan)}, - { "TIME_FORMAT", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_time_format)}, - { "TIME_TO_SEC", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_time_to_sec)}, - { "TIMEDIFF", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_timediff)}, - { "TO_DAYS", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_to_days)}, - { "TOUCHES", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_touches)}, - { "TRIM", SYM(TRIM),0,0}, - { "UCASE", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ucase)}, - { "UNCOMPRESS", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_uncompress)}, - { "UNCOMPRESSED_LENGTH", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_uncompressed_length)}, - { "UNIQUE_USERS", SYM(UNIQUE_USERS),0,0}, - { "UNIX_TIMESTAMP", SYM(UNIX_TIMESTAMP),0,0}, - { "UPPER", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ucase)}, - { "VARIANCE", SYM(VARIANCE_SYM),0,0}, - { "VERSION", SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_version)}, - { "WEEKDAY", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_weekday)}, - { "WEEKOFYEAR", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_weekofyear)}, - { "WITHIN", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_within)}, - { "X", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_x)}, - { "Y", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_y)}, - { "YEARWEEK", SYM(YEARWEEK),0,0} + { "ABS", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_abs)}, + { "ACOS", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_acos)}, + { "ADDDATE", SYM(ADDDATE_SYM)}, + { "ADDTIME", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_addtime)}, + { "AES_ENCRYPT", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_aes_encrypt)}, + { "AES_DECRYPT", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_aes_decrypt)}, + { "AREA", F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_area)}, + { "ASIN", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_asin)}, + { "ASBINARY", F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_as_wkb)}, + { "ASTEXT", F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_as_wkt)}, + { "ASWKB", F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_as_wkb)}, + { "ASWKT", F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_as_wkt)}, + { "ATAN", SYM(ATAN)}, + { "ATAN2", SYM(ATAN)}, + { "BENCHMARK", SYM(BENCHMARK_SYM)}, + { "BIN", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_bin)}, + { "BIT_COUNT", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_bit_count)}, + { "BIT_OR", SYM(BIT_OR)}, + { "BIT_AND", SYM(BIT_AND)}, + { "BIT_XOR", SYM(BIT_XOR)}, + { "CAST", SYM(CAST_SYM)}, + { "CEIL", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ceiling)}, + { "CEILING", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ceiling)}, + { "CURRENT_USER", F_SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_current_user)}, + { "BIT_LENGTH", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_bit_length)}, + { "CENTROID", F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_centroid)}, + { "CHAR_LENGTH", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_char_length)}, + { "CHARACTER_LENGTH", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_char_length)}, + { "COALESCE", SYM(COALESCE)}, + { "COERCIBILITY", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_coercibility)}, + { "COMPRESS", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_compress)}, + { "CONCAT", SYM(CONCAT)}, + { "CONCAT_WS", SYM(CONCAT_WS)}, + { "CONNECTION_ID", F_SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_connection_id)}, + { "CONTAINS", F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_contains)}, + { "CONV", F_SYM(FUNC_ARG3),0,CREATE_FUNC(create_func_conv)}, + { "CONVERT", SYM(CONVERT_SYM)}, + { "COUNT", SYM(COUNT_SYM)}, + { "COS", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_cos)}, + { "COT", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_cot)}, + { "CRC32", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_crc32)}, + { "CROSSES", F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_crosses)}, + { "CURDATE", SYM(CURDATE)}, + { "CURTIME", SYM(CURTIME)}, + { "DATE_ADD", SYM(DATE_ADD_INTERVAL)}, + { "DATEDIFF", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_datediff)}, + { "DATE_FORMAT", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_date_format)}, + { "DATE_SUB", SYM(DATE_SUB_INTERVAL)}, + { "DAYNAME", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_dayname)}, + { "DAYOFMONTH", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_dayofmonth)}, + { "DAYOFWEEK", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_dayofweek)}, + { "DAYOFYEAR", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_dayofyear)}, + { "DECODE", SYM(DECODE_SYM)}, + { "DEGREES", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_degrees)}, + { "DES_ENCRYPT", SYM(DES_ENCRYPT_SYM)}, + { "DES_DECRYPT", SYM(DES_DECRYPT_SYM)}, + { "DIMENSION", F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_dimension)}, + { "DISJOINT", F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_disjoint)}, + { "ELT", SYM(ELT_FUNC)}, + { "ENCODE", SYM(ENCODE_SYM)}, + { "ENCRYPT", SYM(ENCRYPT)}, + { "ENDPOINT", F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_endpoint)}, + { "ENVELOPE", F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_envelope)}, + { "EQUALS", F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_equals)}, + { "EXTERIORRING", F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_exteriorring)}, + { "EXTRACT", SYM(EXTRACT_SYM)}, + { "EXP", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_exp)}, + { "EXPORT_SET", SYM(EXPORT_SET)}, + { "FIELD", SYM(FIELD_FUNC)}, /* For compability */ + { "FIND_IN_SET", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_find_in_set)}, + { "FLOOR", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_floor)}, + { "FORMAT", SYM(FORMAT_SYM)}, + { "FOUND_ROWS", F_SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_found_rows)}, + { "FROM_DAYS", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_from_days)}, + { "FROM_UNIXTIME", SYM(FROM_UNIXTIME)}, + { "GET_LOCK", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_get_lock)}, + { "GEOMETRYN", F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_geometryn)}, + { "GEOMETRYTYPE", F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_geometry_type)}, + { "GEOMCOLLFROMTEXT", SYM(GEOMCOLLFROMTEXT)}, + { "GEOMCOLLFROMWKB", SYM(GEOMFROMWKB)}, + { "GEOMETRYCOLLECTIONFROMTEXT",SYM(GEOMCOLLFROMTEXT)}, + { "GEOMETRYCOLLECTIONFROMWKB",SYM(GEOMFROMWKB)}, + { "GEOMETRYFROMTEXT", SYM(GEOMFROMTEXT)}, + { "GEOMETRYFROMWKB", SYM(GEOMFROMWKB)}, + { "GEOMFROMTEXT", SYM(GEOMFROMTEXT)}, + { "GEOMFROMWKB", SYM(GEOMFROMWKB)}, + { "GLENGTH", F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_glength)}, + { "GREATEST", SYM(GREATEST_SYM)}, + { "GROUP_CONCAT", SYM(GROUP_CONCAT_SYM)}, + { "GROUP_UNIQUE_USERS", SYM(GROUP_UNIQUE_USERS)}, + { "HEX", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_hex)}, + { "IFNULL", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_ifnull)}, + { "INET_ATON", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_inet_aton)}, + { "INET_NTOA", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_inet_ntoa)}, + { "INSTR", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_instr)}, + { "INTERIORRINGN", F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_interiorringn)}, + { "INTERSECTS", F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_intersects)}, + { "ISCLOSED", F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_isclosed)}, + { "ISEMPTY", F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_isempty)}, + { "ISNULL", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_isnull)}, + { "IS_FREE_LOCK", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_is_free_lock)}, + { "IS_USED_LOCK", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_is_used_lock)}, + { "LAST_INSERT_ID", SYM(LAST_INSERT_ID)}, + { "ISSIMPLE", F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_issimple)}, + { "LAST_DAY", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_last_day)}, + { "LCASE", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_lcase)}, + { "LEAST", SYM(LEAST_SYM)}, + { "LENGTH", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_length)}, + { "LN", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ln)}, + { "LINEFROMTEXT", SYM(LINEFROMTEXT)}, + { "LINEFROMWKB", SYM(GEOMFROMWKB)}, + { "LINESTRINGFROMTEXT",SYM(LINEFROMTEXT)}, + { "LINESTRINGFROMWKB",SYM(GEOMFROMWKB)}, + { "LOAD_FILE", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_load_file)}, + { "LOCATE", SYM(LOCATE)}, + { "LOG", SYM(LOG_SYM)}, + { "LOG2", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_log2)}, + { "LOG10", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_log10)}, + { "LOWER", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_lcase)}, + { "LPAD", F_SYM(FUNC_ARG3),0,CREATE_FUNC(create_func_lpad)}, + { "LTRIM", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ltrim)}, + { "MAKE_SET", SYM(MAKE_SET_SYM)}, + { "MAKEDATE", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_makedate)}, + { "MAKETIME", F_SYM(FUNC_ARG3),0,CREATE_FUNC(create_func_maketime)}, + { "MASTER_POS_WAIT", SYM(MASTER_POS_WAIT)}, + { "MAX", SYM(MAX_SYM)}, + { "MBRCONTAINS", F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_contains)}, + { "MBRDISJOINT", F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_disjoint)}, + { "MBREQUAL", F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_equals)}, + { "MBRINTERSECTS", F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_intersects)}, + { "MBROVERLAPS", F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_overlaps)}, + { "MBRTOUCHES", F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_touches)}, + { "MBRWITHIN", F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_within)}, + { "MD5", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_md5)}, + { "MID", SYM(SUBSTRING)}, /* unireg function */ + { "MIN", SYM(MIN_SYM)}, + { "MLINEFROMTEXT", SYM(MLINEFROMTEXT)}, + { "MLINEFROMWKB", SYM(GEOMFROMWKB)}, + { "MPOINTFROMTEXT", SYM(MPOINTFROMTEXT)}, + { "MPOINTFROMWKB", SYM(GEOMFROMWKB)}, + { "MPOLYFROMTEXT", SYM(MPOLYFROMTEXT)}, + { "MPOLYFROMWKB", SYM(GEOMFROMWKB)}, + { "MONTHNAME", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_monthname)}, + { "MULTILINESTRINGFROMTEXT",SYM(MLINEFROMTEXT)}, + { "MULTILINESTRINGFROMWKB",SYM(GEOMFROMWKB)}, + { "MULTIPOINTFROMTEXT",SYM(MPOINTFROMTEXT)}, + { "MULTIPOINTFROMWKB",SYM(GEOMFROMWKB)}, + { "MULTIPOLYGONFROMTEXT",SYM(MPOLYFROMTEXT)}, + { "MULTIPOLYGONFROMWKB",SYM(GEOMFROMWKB)}, + { "NOW", SYM(NOW_SYM)}, + { "NULLIF", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_nullif)}, + { "NUMGEOMETRIES", F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_numgeometries)}, + { "NUMINTERIORRINGS", F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_numinteriorring)}, + { "NUMPOINTS", F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_numpoints)}, + { "OCTET_LENGTH", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_length)}, + { "OCT", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_oct)}, + { "ORD", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ord)}, + { "OVERLAPS", F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_overlaps)}, + { "PERIOD_ADD", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_period_add)}, + { "PERIOD_DIFF", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_period_diff)}, + { "PI", F_SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_pi)}, + { "POINTFROMTEXT", SYM(POINTFROMTEXT)}, + { "POINTFROMWKB", SYM(GEOMFROMWKB)}, + { "POINTN", F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_pointn)}, + { "POLYFROMTEXT", SYM(POLYFROMTEXT)}, + { "POLYFROMWKB", SYM(GEOMFROMWKB)}, + { "POLYGONFROMTEXT", SYM(POLYFROMTEXT)}, + { "POLYGONFROMWKB", SYM(GEOMFROMWKB)}, + { "POSITION", SYM(POSITION_SYM)}, + { "POW", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_pow)}, + { "POWER", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_pow)}, + { "QUOTE", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_quote)}, + { "RADIANS", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_radians)}, + { "RAND", SYM(RAND)}, + { "RELEASE_LOCK", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_release_lock)}, + { "REVERSE", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_reverse)}, + { "ROUND", SYM(ROUND)}, + { "RPAD", F_SYM(FUNC_ARG3),0,CREATE_FUNC(create_func_rpad)}, + { "RTRIM", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_rtrim)}, + { "SEC_TO_TIME", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sec_to_time)}, + { "SESSION_USER", SYM(USER)}, + { "SUBDATE", SYM(SUBDATE_SYM)}, + { "SIGN", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sign)}, + { "SIN", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sin)}, + { "SHA", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sha)}, + { "SHA1", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sha)}, + { "SOUNDEX", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_soundex)}, + { "SPACE", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_space)}, + { "SQRT", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sqrt)}, + { "SRID", F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_srid)}, + { "STARTPOINT", F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_startpoint)}, + { "STD", SYM(STD_SYM)}, + { "STDDEV", SYM(STD_SYM)}, + { "STR_TO_DATE", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_str_to_date)}, + { "STRCMP", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_strcmp)}, + { "SUBSTR", SYM(SUBSTRING)}, + { "SUBSTRING", SYM(SUBSTRING)}, + { "SUBSTRING_INDEX", SYM(SUBSTRING_INDEX)}, + { "SUBTIME", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_subtime)}, + { "SUM", SYM(SUM_SYM)}, + { "SYSDATE", SYM(NOW_SYM)}, + { "SYSTEM_USER", SYM(USER)}, + { "TAN", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_tan)}, + { "TIME_FORMAT", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_time_format)}, + { "TIME_TO_SEC", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_time_to_sec)}, + { "TIMEDIFF", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_timediff)}, + { "TO_DAYS", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_to_days)}, + { "TOUCHES", F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_touches)}, + { "TRIM", SYM(TRIM)}, + { "UCASE", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ucase)}, + { "UNCOMPRESS", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_uncompress)}, + { "UNCOMPRESSED_LENGTH", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_uncompressed_length)}, + { "UNIQUE_USERS", SYM(UNIQUE_USERS)}, + { "UNIX_TIMESTAMP", SYM(UNIX_TIMESTAMP)}, + { "UPPER", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ucase)}, + { "VARIANCE", SYM(VARIANCE_SYM)}, + { "VERSION", F_SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_version)}, + { "WEEK", SYM(WEEK_SYM)}, + { "WEEKDAY", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_weekday)}, + { "WEEKOFYEAR", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_weekofyear)}, + { "WITHIN", F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_within)}, + { "X", F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_x)}, + { "Y", F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_y)}, + { "YEARWEEK", SYM(YEARWEEK)} }; diff --git a/sql/lex_symbol.h b/sql/lex_symbol.h index 9fff1751b1b..d1d30a73669 100644 --- a/sql/lex_symbol.h +++ b/sql/lex_symbol.h @@ -20,11 +20,14 @@ #ifndef _lex_symbol_h #define _lex_symbol_h +struct st_sym_group; + typedef struct st_symbol { const char *name; uint tok; uint length; void *create_func; + struct st_sym_group *group; } SYMBOL; typedef struct st_lex_symbol diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 225be6e7ffd..39851838cb2 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -47,6 +47,7 @@ typedef ulong key_part_map; /* Used for finding key parts */ /* useful constants */ extern const key_map key_map_empty; extern const key_map key_map_full; +extern const char *primary_key_name; #include "mysql_com.h" #include <violite.h> @@ -286,7 +287,9 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset; // uncachable cause #define UNCACHEABLE_DEPENDENT 1 #define UNCACHEABLE_RAND 2 -#define UNCACHEABLE_SIDEEFFECT 4 +#define UNCACHEABLE_SIDEEFFECT 4 +// forcing to save JOIN for explain +#define UNCACHEABLE_EXPLAIN 8 #ifdef EXTRA_DEBUG /* @@ -520,14 +523,13 @@ int mysql_select(THD *thd, Item ***rref_pointer_array, SELECT_LEX *select_lex); void free_underlaid_joins(THD *thd, SELECT_LEX *select); void fix_tables_pointers(SELECT_LEX *select_lex); -void fix_tables_pointers(SELECT_LEX_UNIT *select_lex); int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result); int mysql_explain_select(THD *thd, SELECT_LEX *sl, char const *type, select_result *result); int mysql_union(THD *thd, LEX *lex, select_result *result, SELECT_LEX_UNIT *unit); -int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *s, TABLE_LIST *t); +int mysql_handle_derived(LEX *lex); Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, Item ***copy_func, Field **from_field, bool group,bool modify_item); @@ -548,7 +550,6 @@ int mysql_alter_table(THD *thd, char *new_db, char *new_name, List<Key> &keys,List<Alter_drop> &drop_list, List<Alter_column> &alter_list, uint order_num, ORDER *order, - bool drop_primary, enum enum_duplicates handle_duplicates, enum enum_enable_or_disable keys_onoff=LEAVE_AS_IS, enum tablespace_op_type tablespace_op=NO_TABLESPACE_OP, @@ -704,7 +705,7 @@ bool get_key_map_from_key_list(key_map *map, TABLE *table, bool insert_fields(THD *thd,TABLE_LIST *tables, const char *db_name, const char *table_name, List_iterator<Item> *it); -bool setup_tables(TABLE_LIST *tables); +bool setup_tables(TABLE_LIST *tables, my_bool reinit); int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields, List<Item> *sum_func_list, uint wild_num); int setup_fields(THD *thd, Item** ref_pointer_array, TABLE_LIST *tables, @@ -714,9 +715,10 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds); int setup_ftfuncs(SELECT_LEX* select); int init_ftfuncs(THD *thd, SELECT_LEX* select, bool no_order); void wait_for_refresh(THD *thd); -int open_tables(THD *thd,TABLE_LIST *tables); +int open_tables(THD *thd, TABLE_LIST *tables, uint *counter); +int simple_open_n_lock_tables(THD *thd,TABLE_LIST *tables); int open_and_lock_tables(THD *thd,TABLE_LIST *tables); -int lock_tables(THD *thd,TABLE_LIST *tables); +int lock_tables(THD *thd, TABLE_LIST *tables, uint counter); TABLE *open_temporary_table(THD *thd, const char *path, const char *db, const char *table_name, bool link_in_list); bool rm_temporary_table(enum db_type base, char *path); @@ -799,6 +801,13 @@ uint find_type(TYPELIB *lib, const char *find, uint length, bool part_match); uint check_word(TYPELIB *lib, const char *val, const char *end, const char **end_of_word); +/* sql_parse.cc */ +void free_items(Item *item); +void cleanup_items(Item *item); + +#define MY_DB_OPT_FILE "db.opt" +bool load_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create); + /* External variables */ @@ -1140,4 +1149,13 @@ inline void setup_table_map(TABLE *table, TABLE_LIST *table_list, uint tablenr) table->force_index= table_list->force_index; } +typedef struct st_sym_group { + const char *name; + const char *needed_define; +} SYM_GROUP; + +extern SYM_GROUP sym_group_common; +extern SYM_GROUP sym_group_geom; +extern SYM_GROUP sym_group_rtree; + #endif /* MYSQL_CLIENT */ diff --git a/sql/mysqld.cc b/sql/mysqld.cc index e465d310259..0a05da7491b 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -2154,8 +2154,12 @@ static int init_common_variables(const char *conf_file_name, int argc, { CHARSET_INFO *default_collation; default_collation= get_charset_by_name(default_collation_name, MYF(0)); - if (!default_collation || !my_charset_same(default_charset_info, - default_collation)) + if (!default_collation) + { + sql_print_error(ER(ER_UNKNOWN_COLLATION), default_collation_name); + return 1; + } + if (!my_charset_same(default_charset_info, default_collation)) { sql_print_error(ER(ER_COLLATION_CHARSET_MISMATCH), default_collation_name, @@ -4386,7 +4390,7 @@ log and this option does nothing anymore.", (gptr*) 0, 0, (enum get_opt_var_type) (GET_ULONG | GET_ASK_ADDR) , REQUIRED_ARG, 100, 1, 100, 0, 1, 0}, - {"key_cache_division_age_threshold", OPT_KEY_CACHE_AGE_THRESHOLD, + {"key_cache_age_threshold", OPT_KEY_CACHE_AGE_THRESHOLD, "This characterizes the number of hits a hot block has to be untouched until it is considered aged enough to be downgraded to a warm block. This specifies the percentage ratio of that number of hits to the total number of blocks in key cache", (gptr*) &dflt_key_cache_var.param_age_threshold, (gptr*) 0, @@ -4606,7 +4610,7 @@ The minimum value for this variable is 4096.", "Use compression on master/slave protocol.", (gptr*) &opt_slave_compressed_protocol, (gptr*) &opt_slave_compressed_protocol, - 0, GET_BOOL, REQUIRED_ARG, 0, 0, 1, 0, 1, 0}, + 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 1, 0}, {"slave_net_timeout", OPT_SLAVE_NET_TIMEOUT, "Number of seconds to wait for more data from a master/slave connection before aborting the read.", (gptr*) &slave_net_timeout, (gptr*) &slave_net_timeout, 0, @@ -4669,7 +4673,7 @@ The minimum value for this variable is 4096.", (gptr*) &max_system_variables.net_wait_timeout, 0, GET_ULONG, REQUIRED_ARG, NET_WAIT_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0}, {"expire_logs_days", OPT_EXPIRE_LOGS_DAYS, - "Logs will be rotated after expire-log-days days ", + "Binary logs will be rotated after expire-log-days days ", (gptr*) &expire_logs_days, (gptr*) &expire_logs_days, 0, GET_ULONG, REQUIRED_ARG, 0, 0, 99, 0, 1, 0}, @@ -5816,8 +5820,9 @@ static void fix_paths(void) { strxnmov(mysql_charsets_dir, sizeof(mysql_charsets_dir)-1, buff, CHARSET_DIR, NullS); - charsets_dir=mysql_charsets_dir; } + (void) my_load_path(mysql_charsets_dir, mysql_charsets_dir, buff); + charsets_dir=mysql_charsets_dir; if (init_tmpdir(&mysql_tmpdir_list, opt_mysql_tmpdir)) exit(1); @@ -5968,7 +5973,7 @@ static ulong find_bit_type(const char *x, TYPELIB *bit_lib) { if (my_toupper(mysqld_charset,*i++) != my_toupper(mysqld_charset,*j++)) - goto skipp; + goto skip; } found_int=bit; if (! *i) @@ -5980,7 +5985,7 @@ static ulong find_bit_type(const char *x, TYPELIB *bit_lib) { found_count++; // Could be one of two values } -skipp: ; +skip: ; } if (found_count != 1) DBUG_RETURN(~(ulong) 0); // No unique value diff --git a/sql/opt_ft.cc b/sql/opt_ft.cc deleted file mode 100644 index 9d1fc55c777..00000000000 --- a/sql/opt_ft.cc +++ /dev/null @@ -1,36 +0,0 @@ -/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult 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 - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -#ifdef __GNUC__ -#pragma implementation // gcc: Class implementation -#endif - -#include "mysql_priv.h" -#include "sql_select.h" -#include "opt_ft.h" - -/**************************************************************************** -** Create a FT or QUICK RANGE based on a key -****************************************************************************/ - -QUICK_RANGE_SELECT *get_ft_or_quick_select_for_ref(THD *thd, TABLE *table, - JOIN_TAB *tab) -{ - if (tab->type == JT_FT) - return new FT_SELECT(thd, table, &tab->ref); - return get_quick_select_for_ref(thd, table, &tab->ref); -} - diff --git a/sql/opt_ft.h b/sql/opt_ft.h deleted file mode 100644 index 954c25b6caa..00000000000 --- a/sql/opt_ft.h +++ /dev/null @@ -1,42 +0,0 @@ -/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult 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 - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - - -/* classes to use when handling where clause */ - -#ifndef _opt_ft_h -#define _opt_ft_h - -#ifdef __GNUC__ -#pragma interface /* gcc class implementation */ -#endif - -class FT_SELECT: public QUICK_RANGE_SELECT { -public: - TABLE_REF *ref; - - FT_SELECT(THD *thd, TABLE *table, TABLE_REF *tref) : - QUICK_RANGE_SELECT (thd, table, tref->key, 1), ref(tref) { init(); } - - int init() { return error=file->ft_init(); } - int get_next() { return error=file->ft_read(record); } - int get_type() { return QS_TYPE_FULLTEXT; } -}; - -QUICK_RANGE_SELECT *get_ft_or_quick_select_for_ref(THD *thd, TABLE *table, - JOIN_TAB *tab); - -#endif diff --git a/sql/opt_range.cc b/sql/opt_range.cc index fa1b80f007e..be1e764ddba 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -301,10 +301,11 @@ typedef struct st_qsel_param { uint imerge_cost_buff_size; /* size of the buffer */ } PARAM; -static SEL_TREE * get_mm_parts(PARAM *param,Field *field, +static SEL_TREE * get_mm_parts(PARAM *param,COND *cond_func,Field *field, Item_func::Functype type,Item *value, Item_result cmp_type); -static SEL_ARG *get_mm_leaf(PARAM *param,Field *field,KEY_PART *key_part, +static SEL_ARG *get_mm_leaf(PARAM *param,COND *cond_func,Field *field, + KEY_PART *key_part, Item_func::Functype type,Item *value); static SEL_TREE *get_mm_tree(PARAM *param,COND *cond); static ha_rows check_quick_select(PARAM *param,uint index,SEL_ARG *key_tree); @@ -612,14 +613,25 @@ SQL_SELECT::SQL_SELECT() :quick(0),cond(0),free_cond(0) } -SQL_SELECT::~SQL_SELECT() +void SQL_SELECT::cleanup() { delete quick; + quick= 0; if (free_cond) + { + free_cond=0; delete cond; + cond= 0; + } close_cached_file(&file); } + +SQL_SELECT::~SQL_SELECT() +{ + cleanup(); +} + #undef index // Fix for Unixware 7 QUICK_SELECT_I::QUICK_SELECT_I() @@ -1565,10 +1577,10 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond) Field *field=((Item_field*) (cond_func->arguments()[0]))->field; Item_result cmp_type=field->cmp_type(); DBUG_RETURN(tree_and(param, - get_mm_parts(param, field, + get_mm_parts(param, cond_func, field, Item_func::GE_FUNC, cond_func->arguments()[1], cmp_type), - get_mm_parts(param, field, + get_mm_parts(param, cond_func, field, Item_func::LE_FUNC, cond_func->arguments()[2], cmp_type))); } @@ -1581,13 +1593,14 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond) { Field *field=((Item_field*) (func->key_item()))->field; Item_result cmp_type=field->cmp_type(); - tree= get_mm_parts(param,field,Item_func::EQ_FUNC, + tree= get_mm_parts(param,cond_func,field,Item_func::EQ_FUNC, func->arguments()[1],cmp_type); if (!tree) DBUG_RETURN(tree); // Not key field for (uint i=2 ; i < func->argument_count(); i++) { - SEL_TREE *new_tree=get_mm_parts(param,field,Item_func::EQ_FUNC, + SEL_TREE *new_tree=get_mm_parts(param,cond_func,field, + Item_func::EQ_FUNC, func->arguments()[i],cmp_type); tree=tree_or(param,tree,new_tree); } @@ -1606,7 +1619,7 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond) /* btw, ft_func's arguments()[0] isn't FIELD_ITEM. SerG*/ if (cond_func->arguments()[0]->type() == Item::FIELD_ITEM) { - tree= get_mm_parts(param, + tree= get_mm_parts(param, cond_func, ((Item_field*) (cond_func->arguments()[0]))->field, cond_func->functype(), cond_func->arg_count > 1 ? cond_func->arguments()[1] : @@ -1619,7 +1632,7 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond) cond_func->have_rev_func() && cond_func->arguments()[1]->type() == Item::FIELD_ITEM) { - DBUG_RETURN(get_mm_parts(param, + DBUG_RETURN(get_mm_parts(param, cond_func, ((Item_field*) (cond_func->arguments()[1]))->field, ((Item_bool_func2*) cond_func)->rev_functype(), @@ -1633,7 +1646,8 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond) static SEL_TREE * -get_mm_parts(PARAM *param, Field *field, Item_func::Functype type, +get_mm_parts(PARAM *param, COND *cond_func, Field *field, + Item_func::Functype type, Item *value, Item_result cmp_type) { bool ne_func= FALSE; @@ -1662,7 +1676,8 @@ get_mm_parts(PARAM *param, Field *field, Item_func::Functype type, DBUG_RETURN(0); // OOM if (!value || !(value->used_tables() & ~param->read_tables)) { - sel_arg=get_mm_leaf(param,key_part->field,key_part,type,value); + sel_arg=get_mm_leaf(param,cond_func, + key_part->field,key_part,type,value); if (!sel_arg) continue; if (sel_arg->type == SEL_ARG::IMPOSSIBLE) @@ -1685,7 +1700,8 @@ get_mm_parts(PARAM *param, Field *field, Item_func::Functype type, if (ne_func) { - SEL_TREE *tree2= get_mm_parts(param, field, Item_func::GT_FUNC, + SEL_TREE *tree2= get_mm_parts(param, cond_func, + field, Item_func::GT_FUNC, value, cmp_type); if (tree2) tree= tree_or(param,tree,tree2); @@ -1696,7 +1712,7 @@ get_mm_parts(PARAM *param, Field *field, Item_func::Functype type, static SEL_ARG * -get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part, +get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part, Item_func::Functype type,Item *value) { uint maybe_null=(uint) field->real_maybe_null(), copies; @@ -1705,6 +1721,32 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part, char *str, *str2; DBUG_ENTER("get_mm_leaf"); + if (!value) // IS NULL or IS NOT NULL + { + if (field->table->outer_join) // Can't use a key on this + DBUG_RETURN(0); + if (!maybe_null) // Not null field + DBUG_RETURN(type == Item_func::ISNULL_FUNC ? &null_element : 0); + if (!(tree=new SEL_ARG(field,is_null_string,is_null_string))) + DBUG_RETURN(0); // out of memory + if (type == Item_func::ISNOTNULL_FUNC) + { + tree->min_flag=NEAR_MIN; /* IS NOT NULL -> X > NULL */ + tree->max_flag=NO_MAX_RANGE; + } + DBUG_RETURN(tree); + } + + /* + We can't use an index when comparing strings of + different collations + */ + if (field->result_type() == STRING_RESULT && + value->result_type() == STRING_RESULT && + key_part->image_type == Field::itRAW && + ((Field_str*)field)->charset() != conf_func->compare_collation()) + DBUG_RETURN(0); + if (type == Item_func::LIKE_FUNC) { bool like_error; @@ -1768,22 +1810,6 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part, DBUG_RETURN(new SEL_ARG(field,min_str,max_str)); } - if (!value) // IS NULL or IS NOT NULL - { - if (field->table->outer_join) // Can't use a key on this - DBUG_RETURN(0); - if (!maybe_null) // Not null field - DBUG_RETURN(type == Item_func::ISNULL_FUNC ? &null_element : 0); - if (!(tree=new SEL_ARG(field,is_null_string,is_null_string))) - DBUG_RETURN(0); // out of memory - if (type == Item_func::ISNOTNULL_FUNC) - { - tree->min_flag=NEAR_MIN; /* IS NOT NULL -> X > NULL */ - tree->max_flag=NO_MAX_RANGE; - } - DBUG_RETURN(tree); - } - if (!field->optimize_range(param->real_keynr[key_part->key]) && type != Item_func::EQ_FUNC && type != Item_func::EQUAL_FUNC) @@ -1797,7 +1823,7 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part, value->result_type() != STRING_RESULT && field->cmp_type() != value->result_type()) DBUG_RETURN(0); - + if (value->save_in_field(field, 1) > 0) { /* This happens when we try to insert a NULL field in a not null column */ @@ -2999,6 +3025,7 @@ check_quick_select(PARAM *param,uint idx,SEL_ARG *tree) param->table->quick_rows[key]=records; param->table->quick_key_parts[key]=param->max_key_part+1; } + DBUG_PRINT("exit", ("Records: %lu", (ulong) records)); DBUG_RETURN(records); } @@ -3342,8 +3369,30 @@ QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table, key_part->part_length+=HA_KEY_BLOB_LENGTH; key_part->null_bit= key_info->key_part[part].null_bit; } - if (!insert_dynamic(&quick->ranges,(gptr)&range)) - return quick; + if (insert_dynamic(&quick->ranges,(gptr)&range)) + goto err; + + /* + Add a NULL range if REF_OR_NULL optimization is used. + For example: + if we have "WHERE A=2 OR A IS NULL" we created the (A=2) range above + and have ref->null_ref_key set. Will create a new NULL range here. + */ + if (ref->null_ref_key) + { + QUICK_RANGE *null_range; + + *ref->null_ref_key= 1; // Set null byte then create a range + if (!(null_range= new QUICK_RANGE(ref->key_buff, ref->key_length, + ref->key_buff, ref->key_length, + EQ_RANGE))) + goto err; + *ref->null_ref_key= 0; // Clear null byte + if (insert_dynamic(&quick->ranges,(gptr)&null_range)) + goto err; + } + + return quick; err: delete quick; @@ -3486,12 +3535,7 @@ int QUICK_RANGE_SELECT::get_next() int result; if (range) { // Already read through key -/* result=((range->flag & EQ_RANGE) ? - file->index_next_same(record, (byte*) range->min_key, - range->min_length) : - file->index_next(record)); -*/ - result=((range->flag & (EQ_RANGE | GEOM_FLAG) ) ? + result=((range->flag & (EQ_RANGE | GEOM_FLAG)) ? file->index_next_same(record, (byte*) range->min_key, range->min_length) : file->index_next(record)); diff --git a/sql/opt_range.h b/sql/opt_range.h index 7c2981795a2..40a0e259ddd 100644 --- a/sql/opt_range.h +++ b/sql/opt_range.h @@ -295,13 +295,25 @@ class SQL_SELECT :public Sql_alloc { SQL_SELECT(); ~SQL_SELECT(); + void cleanup(); bool check_quick(THD *thd, bool force_quick_range, ha_rows limit) { return test_quick_select(thd, key_map(~0), 0, limit, force_quick_range) < 0; } - inline bool skipp_record() { return cond ? cond->val_int() == 0 : 0; } + inline bool skip_record() { return cond ? cond->val_int() == 0 : 0; } int test_quick_select(THD *thd, key_map keys, table_map prev_tables, ha_rows limit, bool force_quick_range=0); }; + +class FT_SELECT: public QUICK_SELECT { +public: + FT_SELECT(THD *thd, TABLE *table, uint key): + QUICK_SELECT (thd, table, key, 1) { init(); } + + int init() { return error= file->ft_init(); } + int get_next() { return error= file->ft_read(record); } +}; + + QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table, struct st_table_ref *ref); diff --git a/sql/protocol.cc b/sql/protocol.cc index 89aa7203e17..4be74c74134 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -128,7 +128,7 @@ void send_error(THD *thd, uint sql_errno, const char *err) /* Abort multi-result sets */ thd->lex->found_colon= 0; - thd->server_status= ~SERVER_MORE_RESULTS_EXISTS; + thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS; DBUG_VOID_RETURN; } @@ -326,6 +326,7 @@ send_ok(THD *thd, ha_rows affected_rows, ulonglong id, const char *message) DBUG_VOID_RETURN; } +static char eof_buff[1]= { (char) 254 }; /* Marker for end of fields */ /* Send eof (= end of result set) to the client @@ -352,12 +353,11 @@ send_ok(THD *thd, ha_rows affected_rows, ulonglong id, const char *message) void send_eof(THD *thd, bool no_flush) { - static char eof_buff[1]= { (char) 254 }; /* Marker for end of fields */ NET *net= &thd->net; DBUG_ENTER("send_eof"); if (net->vio != 0 && !net->no_send_eof) { - if (!no_flush && (thd->client_capabilities & CLIENT_PROTOCOL_41)) + if (thd->client_capabilities & CLIENT_PROTOCOL_41) { uchar buff[5]; uint tmp= min(thd->total_warn_count, 65535); @@ -369,7 +369,7 @@ send_eof(THD *thd, bool no_flush) other queries (see the if test in dispatch_command / COM_QUERY) */ if (thd->is_fatal_error) - thd->server_status= ~SERVER_MORE_RESULTS_EXISTS; + thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS; int2store(buff+3, thd->server_status); VOID(my_net_write(net,(char*) buff,5)); VOID(net_flush(net)); @@ -397,9 +397,8 @@ send_eof(THD *thd, bool no_flush) bool send_old_password_request(THD *thd) { - static char buff[1]= { (char) 254 }; NET *net= &thd->net; - return my_net_write(net, buff, 1) || net_flush(net); + return my_net_write(net, eof_buff, 1) || net_flush(net); } #endif /* EMBEDDED_LIBRARY */ @@ -598,7 +597,7 @@ bool Protocol::send_fields(List<Item> *list, uint flag) #endif } - send_eof(thd, 1); + my_net_write(&thd->net, eof_buff, 1); DBUG_RETURN(prepare_for_send(list)); err: diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc index 81ea9d9e2ac..d125c95e839 100644 --- a/sql/repl_failsafe.cc +++ b/sql/repl_failsafe.cc @@ -732,7 +732,7 @@ static int fetch_db_tables(THD *thd, MYSQL *mysql, const char *db, int error; if (table_rules_on) { - table.next= 0; + bzero((char*) &table, sizeof(table)); //just for safe table.db= (char*) db; table.real_name= (char*) table_name; table.updating= 1; diff --git a/sql/set_var.cc b/sql/set_var.cc index 4cf9f07b4ba..b74bf3e5f7b 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -696,7 +696,6 @@ struct show_var_st init_vars[]= { {"port", (char*) &mysqld_port, SHOW_INT}, {"protocol_version", (char*) &protocol_version, SHOW_INT}, {sys_preload_buff_size.name, (char*) &sys_preload_buff_size, SHOW_SYS}, - {sys_pseudo_thread_id.name, (char*) &sys_pseudo_thread_id, SHOW_SYS}, {sys_query_alloc_block_size.name, (char*) &sys_query_alloc_block_size, SHOW_SYS}, #ifdef HAVE_QUERY_CACHE @@ -2655,11 +2654,6 @@ ulong fix_sql_mode(ulong sql_mode) MODE_IGNORE_SPACE | MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS | MODE_NO_FIELD_OPTIONS); - if (sql_mode & MODE_MSSQL) - sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES | - MODE_IGNORE_SPACE | - MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS | - MODE_NO_FIELD_OPTIONS); if (sql_mode & MODE_POSTGRESQL) sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES | MODE_IGNORE_SPACE | @@ -2670,11 +2664,6 @@ ulong fix_sql_mode(ulong sql_mode) MODE_IGNORE_SPACE | MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS | MODE_NO_FIELD_OPTIONS); - if (sql_mode & MODE_DB2) - sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES | - MODE_IGNORE_SPACE | - MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS | - MODE_NO_FIELD_OPTIONS); if (sql_mode & MODE_MAXDB) sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES | MODE_IGNORE_SPACE | diff --git a/sql/share/charsets/Index.xml b/sql/share/charsets/Index.xml index 3661784325c..f21e03de8b2 100644 --- a/sql/share/charsets/Index.xml +++ b/sql/share/charsets/Index.xml @@ -1,6 +1,6 @@ <?xml version='1.0' encoding="utf-8"?> -<charsets max-id="93"> +<charsets max-id="94"> <description> This file lists all of the available character sets. @@ -100,6 +100,7 @@ To make maintaining easier please: <collation name="latin1_swedish_ci" id="8" order="Finnish, Swedish" flag="primary"/> <collation name="latin1_danish_ci" id="15" order="Danish"/> <collation name="latin1_german2_ci" id="31" order="German Phonebook" flag="compiled"/> + <collation name="latin1_spanish_ci" id="94" order="Spanish"/> <collation name="latin1_bin" id="47" order="Binary"> <flag>binary</flag> <flag>compiled</flag> diff --git a/sql/share/charsets/languages.html b/sql/share/charsets/languages.html new file mode 100644 index 00000000000..6d1a8aafc5c --- /dev/null +++ b/sql/share/charsets/languages.html @@ -0,0 +1,257 @@ +#!/bin/sh +#<pre> +( +echo "DROP TABLE lang;" +echo "CREATE TABLE lang (lang varchar(128), letters text character set utf8);" +( +grep -v "^#" << END +# +Greenlandic ÁÂÃÊÍÎÔÚÛáâãêíîôúûĨĩĸŨũ +#Use of these letters was abolished in a spelling reform in 1973: +#Greenlandic ÅÆØåæø +#Characters not found in the UCS: +# K LATIN CAPITAL LETTER KRA +############################################################# +#Basque ÑÜñüŔŕ +#Characters not found in the UCS: +# D LATIN CAPITAL LETTER D WITH MACRON +# d LATIN SMALL LETTER D WITH MACRON +# L LATIN CAPITAL LETTER L WITH MACRON +# l LATIN SMALL LETTER L WITH MACRON +# T LATIN CAPITAL LETTER T WITH MACRON +# t LATIN SMALL LETTER T WITH MACRON +############################################################# +#Maltese #ÀÁÂÈÉÊÌÍÎÒÓÔÙÚÛ#àáâèéêìíîòÓôùúû#ĊċĠġĦħŻżʼ +#BosnianCyr ЂЈЉЊЋЏАБВГДЕЖЗИКЛМНОПРСТУФХЦЧШабвгдежзиклмнопрстуфхцчшђјљњћџ +#Scots A +#Scots1 ƷȜȝʒ +########################################### +#### Hiragana 3040-309F +Hiragana ぁあぃいぅうぇえぉおかがきぎくぐけげこごさざしじすずせぜそぞただちぢっつづてでとどなにぬねのはばぱひびぴふぶぷへべぺほぼぽまみむめもゃやゅゆょよらりるれろゎわゐゑをん +Hiragana1 ゔ゙゚ +Hiragana2 ゛゜ゝゞ +#### Katakana 30A0-30FF +Katakana ァアィイゥウェエォオカガキギクグケゲコゴサザシジスズセゼソゾタダチヂッツヅテデトドナニヌネノハバパヒビピフブプヘベペホボポマミムメモャヤュユョヨラリルレロヮワヰヱヲンヴヵヶ +Katakana1 ヷヸヹヺ +Katakana2 ・ーヽヾ +############################################ +Albanian ÂÇËâçë +Bosnian ĆćČčĐ𩹮ž +Breton ÂÊÑÙÜâêñùü +Catalan ÀÇÈÉÍÏÒÓÚÜàçèéíïòóúü +#Catalan1 ·Ŀŀ +Croatian ĆćČčĐ𩹮ž +CroatianLig DZDzdzDŽDždžLJLjljNJNjnj +Czech ÁÉÍÓÚÝáéíóúýČčĎďĚěŇňŘřŠšŤťŮůŽž +Danish ÁÄÅÆÉÓÖØÜáäåæéóöøü +Dutch ÀÂÄÆÇÈÉÊËÎÏÑÒÓÔÖÙÚÛÜàâäæçèéêëîïñòóôöùúûü +Esperanto ĈĉĜĝĤĥĴĵŜŝŬŭ +Estonian ÄÕÖÜäõöüŠšŽž +Faroese ÅÆÐÓÖØÚÝåæðóöøúý +Finnish ÄÅÖÜäåöü +#Finnish1 ŠšŽž +French(limited) ÀÂÆÇÈÉÊËÎÏÑÔÙÛàâæçèéêëîïñôùûÿ +French ŒœŸ +German ÄÖÜßäöü +Hungarian ÁÉÍÓÖÚÜáéíóöúüŐőŰű +Icelandic ÁÆÉÍÐÓÖÚÝÞáæéíðóöúýþ +Italian ÀÈÉÌÍÏÒÓÙÚàèéìíïòóùú +#Latin A +Latvian ĀāČčĒēĢģĪīĶķĻļŅņŠšŪūŽž +Lithuanian ĄąČčĖėĘęĮįŠšŪūŲųŽž +Norwegian ÅÆØåæø +Polish ÓóĄąĆćĘꣳŃńŚśŹźŻż +Portuguese ÀÁÂÃÇÉÊÍÓÔÕÚÜàáâãçéêíóôõúü +#http://en.wikipedia.org/wiki/Special_Romanian_Unicode_characters +Romanian ÂÎâîĂăȘșȚț +Romanian(ErrorST) ÂÎâîĂ㪺Ţţ +Slovak ÁÄÉÍÓÔÚÝáäéíóôúýČčĎďĹ弾ŇňŔ੹ŤťŽž +Slovene Č芚Žž +Sorbian-Lower ĆćČčĚ죳ŃńŘřŚśŠšŹźŽž +Sorbian-Upper ÓóĆćČčĚ죳ŃńŘřŠšŽž +Spanish ÁÉÍÑÓÚÜáéíñóúü +Swedish ÄÅÖäåö +Turkish ÂÇÖÛÜâçöûüĞğİı +Welsh ÀÁÂÄÈÉÊËÌÍÎÏÒÓÔÖÙÚÛÜÝàáâäèéêëìíîïòóôöùúûüýÿŴŵŶŷŸẀẁẂẃẄẅỲỳ +################################## +Belarusian ЁІЎАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюяёіў +Bulgarian АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЬЮЯабвгдежзийклмнопрстуфхцчшщъьюя +Bulgarian1 ЀҭѐѝѢѣѪѫ +Macedonian ЃЅЈЉЊЌЏАБВГДЕЖЗИКЛМНОПРСТУФХЦЧШабвгдежзиклмнопрстуфхцчшѓѕјљњќџ +Russian ЁАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюяё +RussianOLD ІіѢѣѲѳѴѵ +Serbian ЂЈЉЊЋЏАБВГДЕЖЗИКЛМНОПРСТУФХЦЧШабвгдежзиклмнопрстуфхцчшђјљњћџ +Ukrainian ЄІЇАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЬЭЮЯабвгдежзийклмнопрстуфхцчшщьэюяєіїҐґ +################################## +Armenian ԱԲԳԴԵԶԷԸԹԺԻԼԽԾԿՁՂՃՄՅՆՇՈՉՊՋՌՍՎՏՑՒՓՔՕՖ՛՜՝՞՟աբգդեֆ։ +#Armenian1 ՚֊ +#Characters not found in the UCS: +# ARMENIAN ETERNITY SIGN +# +GeorgianOld ႠႡႢႣႤႥႦႧႨႩႪႫႬႭႮႯႰႱႲႳႴႵႶႷႸႹႺႻႼႽႾႿჀჁჂჃჄჅ +Georgian აბგდევზთიკლმნოპჟრსტუფქღყშჩცძწჭხჯჰ +GeorgianArc ჱჲჳჴჵჶ +GeorgianPunc ჻ +# +GreekExt1 ΄΅Ά·ΈΉΊ»Ό½ΎΏΐ +Greek ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩαβγδεζηθικλμνξοπρστυφχψω +GreekExt2 ΪΫάέήίΰϊϋόύώ +GreekExt4 ς +# +Hebrew אבגדהוזחטיךכלםמןנסעףפץצקרשת +################################## +#Abaza +#Abkhaz +#Adyghe +#Agul * +#(Aisor) +#Akhvakh * +#(?lvdalska) +#(Andi) * +#(Aragonese) +#Archi * +#Arumanian +#(Arvanite) +#Asturian +#Avar +#Azerbaijani +#(Bagulal) * +#Balkar +#Bashkir +#Basque ! +#Bats * +#Bezhta * +#(Botlikh) * +#Budukh * +#(Chamalal) +#Chechen +#Chuvash +#Cornish ! +#(Corsican) +#Dargwa +#Erzya +#(Franco-Proven?al) +#(Frisian, East) +#(Frisian, North) +#Frisian, West +#Friulian +#Gagauz +#Gaelic, Irish ! +#Gaelic, Manx ! +#Gaelic, Scottish ! +#Galician ! +#(German, Low) ! +#(German, Swiss) ! +#Godoberi * +#(Hinukh) * +#(Hunzib) * +#Ingrian +#Ingush +#Istro-Romanian +#(Judeo-Georgian) +#(Judeo-Kurdish) +#(Judeo-Tati) +#Kabardian +#Kalmyk +#Karachay +#(Karaim) +#(Karata) * +#Karelian +#Kashubian +#Kazakh +#Khinalug +#(Khvarshi) * +#(Kirmanji) +#Komi +#Komi-Permyak +#(Kryts) +#Kumyk +#(Kurdish) +#(Ladin) +#(Ladino) +#Lak +#Laz +#Lezgian +#Livonian +#(Ludian) +#Luxemburgish ! +#Mari, Hill +#Mari, Meadow +#Megleno-Romanian +#(Mingrelian) +#Moksha +#Moldavian +#Nenets, Tundra +#Nogai +#Occitan +#Old Church Slavonic +#(Olonets) +#Ossetian +#(Romani) +#Romansch +#(Rusyn) +#Rutul +#Sami, Inari +#Sami, Kildin +#Sami, Lule +#Sami, Northern +#Sami, Skolt +#Sami, Southern +#(Sami, Ter) * +#(Sami, Ume) * +#(Sardinian) * +#Scots ! +#Svan +#Tabasaran +#(Talysh) +#Tatar, Crimean +#Tatar, Kazan +#Tati +#(Tindi) * +#(Tsakonian) * +#Tsakhur * +#(Tsez) * +#(Turkish, Crimean) +#Ubykh * +#Udi +#Udmurt +#(V?mhusm?l) +#Vepsian +#Votic +#(Walloon) +#(Yiddish) +################################ +# 4 Gaelic-new-orthography +# 4 Frisian +# 3 Rhaeto-Romanic +# 2 S&AACUTEmi-with-restrictions +# 1 Rhjaeto-Romanic +# 1 Gaelic-old-and-new-orthographies +END +) | + +while read a b +do + c=`echo $b | replace "&#x" "" ";" ""` + printf "INSERT INTO lang VALUES ('$a',_ucs2 X'$c');\n" +done +) | mysql -f test + +#mysql test << END +#SELECT * FROM lang WHERE CONVERT(letters USING latin1) NOT LIKE _binary'%?%'; +#SELECT * FROM lang WHERE CONVERT(letters USING latin2) NOT LIKE _binary'%?%'; +#END + + + +list="big5 dec8 cp850 hp8 koi8r latin1 latin2 swe7 ascii ujis sjis hebrew euckr koi8u gb2312 greek cp1250 gbk latin5 armscii8 cp866 keybcs2 macce macroman cp852 latin7 cp1251 cp1256 cp1257 geostd8" + +for p in $list +do +echo "-----------------" +echo $p: +mysql -sss test << END +SELECT lang FROM lang WHERE CONVERT(letters USING $p) NOT LIKE _binary'%?%' ORDER BY lang; +END +done + diff --git a/sql/share/charsets/latin1.xml b/sql/share/charsets/latin1.xml index 9e11be39ad6..178fd07e7f6 100644 --- a/sql/share/charsets/latin1.xml +++ b/sql/share/charsets/latin1.xml @@ -209,6 +209,27 @@ </collation> +<collation name="latin1_spanish_ci"> +<map> + 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F + 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F + 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F + 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F + 40 41 51 53 57 5B 65 67 69 6B 75 77 79 7B 7D 81 + 8F 91 93 95 98 9A A4 A6 A8 AA AF B3 B4 B5 B6 B7 + B8 41 51 53 57 5B 65 67 69 6B 75 77 79 7B 7D 81 + 8F 91 93 95 98 9A A4 A6 A8 AA AF B9 BA BB BC BF + C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF + D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF + E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF + F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF + 41 41 41 41 41 41 41 53 5B 5B 5B 5B 6B 6B 6B 6B + 57 7F 81 81 81 81 81 BD 81 9A 9A 9A 9A AA B1 97 + 41 41 41 41 41 41 41 53 5B 5B 5B 5B 6B 6B 6B 6B + 57 7F 81 81 81 81 81 BE 81 9A 9A 9A 9A AA B1 AA +</map> +</collation> + </charset> </charsets> diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt index ae040fd92ac..117bf4b37d4 100644 --- a/sql/share/czech/errmsg.txt +++ b/sql/share/czech/errmsg.txt @@ -299,6 +299,9 @@ character-set=latin2 "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Unknown table engine '%s'", "'%s' is deprecated. Use '%s' instead.", +"The target table %-.100s of the %s is not updatable.", +"The '%s' feature was disabled. You need MySQL built with '%s' define to have it working" +"MySQL is started in --skip-grant-tables mode. You can't use this command" "Can't create a %s from within another stored routine" "%s %s already exists" "%s %s does not exist" diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt index b7f947d346e..ba012e0eea3 100644 --- a/sql/share/danish/errmsg.txt +++ b/sql/share/danish/errmsg.txt @@ -293,6 +293,9 @@ character-set=latin1 "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Unknown table engine '%s'", "'%s' is deprecated. Use '%s' instead.", +"The target table %-.100s of the %s is not updatable.", +"The '%s' feature was disabled. You need MySQL built with '%s' define to have it working" +"MySQL is started in --skip-grant-tables mode. You can't use this command" "Can't create a %s from within another stored routine" "%s %s already exists" "%s %s does not exist" diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt index 9e2bb859a45..0349929f0d3 100644 --- a/sql/share/dutch/errmsg.txt +++ b/sql/share/dutch/errmsg.txt @@ -301,6 +301,9 @@ character-set=latin1 "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Unknown table engine '%s'", "'%s' is deprecated. Use '%s' instead.", +"The target table %-.100s of the %s is not updatable.", +"The '%s' feature was disabled. You need MySQL built with '%s' define to have it working" +"MySQL is started in --skip-grant-tables mode. You can't use this command" "Can't create a %s from within another stored routine" "%s %s already exists" "%s %s does not exist" diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt index cffbdeeeca2..6bf4bde9b22 100644 --- a/sql/share/english/errmsg.txt +++ b/sql/share/english/errmsg.txt @@ -290,6 +290,9 @@ character-set=latin1 "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Unknown table engine '%s'", "'%s' is deprecated. Use '%s' instead.", +"The target table %-.100s of the %s is not updatable.", +"The '%s' feature was disabled. You need MySQL built with '%s' define to have it working", +"MySQL is started in --skip-grant-tables mode. You can't use this command" "Can't create a %s from within another stored routine" "%s %s already exists" "%s %s does not exist" diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt index 34158b491b2..03e2d4d6c90 100644 --- a/sql/share/estonian/errmsg.txt +++ b/sql/share/estonian/errmsg.txt @@ -295,6 +295,9 @@ character-set=latin7 "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Unknown table engine '%s'", "'%s' is deprecated. Use '%s' instead.", +"The target table %-.100s of the %s is not updatable.", +"The '%s' feature was disabled. You need MySQL built with '%s' define to have it working" +"MySQL is started in --skip-grant-tables mode. You can't use this command" "Can't create a %s from within another stored routine" "%s %s already exists" "%s %s does not exist" diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt index 9a2b3a5ec6a..dab2ab9f51d 100644 --- a/sql/share/french/errmsg.txt +++ b/sql/share/french/errmsg.txt @@ -290,6 +290,9 @@ character-set=latin1 "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Unknown table engine '%s'", "'%s' is deprecated. Use '%s' instead.", +"The target table %-.100s of the %s is not updatable.", +"The '%s' feature was disabled. You need MySQL built with '%s' define to have it working" +"MySQL is started in --skip-grant-tables mode. You can't use this command" "Can't create a %s from within another stored routine" "%s %s already exists" "%s %s does not exist" diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt index 36b8d4b98d6..5b2378dde22 100644 --- a/sql/share/german/errmsg.txt +++ b/sql/share/german/errmsg.txt @@ -302,6 +302,9 @@ character-set=latin1 "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Unknown table engine '%s'", "'%s' is deprecated. Use '%s' instead.", +"The target table %-.100s of the %s is not updatable.", +"The '%s' feature was disabled. You need MySQL built with '%s' define to have it working" +"MySQL is started in --skip-grant-tables mode. You can't use this command" "Can't create a %s from within another stored routine" "%s %s already exists" "%s %s does not exist" diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt index 95c00ec2dd9..a840e95de97 100644 --- a/sql/share/greek/errmsg.txt +++ b/sql/share/greek/errmsg.txt @@ -290,6 +290,9 @@ character-set=greek "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Unknown table engine '%s'", "'%s' is deprecated. Use '%s' instead.", +"The target table %-.100s of the %s is not updatable.", +"The '%s' feature was disabled. You need MySQL built with '%s' define to have it working" +"MySQL is started in --skip-grant-tables mode. You can't use this command" "Can't create a %s from within another stored routine" "%s %s already exists" "%s %s does not exist" diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt index 4a10797e1d1..0b24ca6afb8 100644 --- a/sql/share/hungarian/errmsg.txt +++ b/sql/share/hungarian/errmsg.txt @@ -292,6 +292,9 @@ character-set=latin2 "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Unknown table engine '%s'", "'%s' is deprecated. Use '%s' instead.", +"The target table %-.100s of the %s is not updatable.", +"The '%s' feature was disabled. You need MySQL built with '%s' define to have it working" +"MySQL is started in --skip-grant-tables mode. You can't use this command" "Can't create a %s from within another stored routine" "%s %s already exists" "%s %s does not exist" diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt index 2b8a7ea5632..a298baa7682 100644 --- a/sql/share/italian/errmsg.txt +++ b/sql/share/italian/errmsg.txt @@ -290,6 +290,9 @@ character-set=latin1 "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Unknown table engine '%s'", "'%s' is deprecated. Use '%s' instead.", +"The target table %-.100s of the %s is not updatable.", +"The '%s' feature was disabled. You need MySQL built with '%s' define to have it working" +"MySQL is started in --skip-grant-tables mode. You can't use this command" "Can't create a %s from within another stored routine" "%s %s already exists" "%s %s does not exist" diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt index 752ed402190..a25357ae079 100644 --- a/sql/share/japanese/errmsg.txt +++ b/sql/share/japanese/errmsg.txt @@ -292,6 +292,9 @@ character-set=ujis "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Unknown table engine '%s'", "'%s' is deprecated. Use '%s' instead.", +"The target table %-.100s of the %s is not updatable.", +"The '%s' feature was disabled. You need MySQL built with '%s' define to have it working" +"MySQL is started in --skip-grant-tables mode. You can't use this command" "Can't create a %s from within another stored routine" "%s %s already exists" "%s %s does not exist" diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt index 8d98d5cb610..d3799d881ed 100644 --- a/sql/share/korean/errmsg.txt +++ b/sql/share/korean/errmsg.txt @@ -290,6 +290,9 @@ character-set=euckr "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Unknown table engine '%s'", "'%s' is deprecated. Use '%s' instead.", +"The target table %-.100s of the %s is not updatable.", +"The '%s' feature was disabled. You need MySQL built with '%s' define to have it working" +"MySQL is started in --skip-grant-tables mode. You can't use this command" "Can't create a %s from within another stored routine" "%s %s already exists" "%s %s does not exist" diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt index f1dd2cb8371..d69d52408ff 100644 --- a/sql/share/norwegian-ny/errmsg.txt +++ b/sql/share/norwegian-ny/errmsg.txt @@ -292,6 +292,9 @@ character-set=latin1 "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Unknown table engine '%s'", "'%s' is deprecated. Use '%s' instead.", +"The target table %-.100s of the %s is not updatable.", +"The '%s' feature was disabled. You need MySQL built with '%s' define to have it working" +"MySQL is started in --skip-grant-tables mode. You can't use this command" "Can't create a %s from within another stored routine" "%s %s already exists" "%s %s does not exist" diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt index 44705db0af5..5fbbaf19480 100644 --- a/sql/share/norwegian/errmsg.txt +++ b/sql/share/norwegian/errmsg.txt @@ -292,6 +292,9 @@ character-set=latin1 "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Unknown table engine '%s'", "'%s' is deprecated. Use '%s' instead.", +"The target table %-.100s of the %s is not updatable.", +"The '%s' feature was disabled. You need MySQL built with '%s' define to have it working" +"MySQL is started in --skip-grant-tables mode. You can't use this command" "Can't create a %s from within another stored routine" "%s %s already exists" "%s %s does not exist" diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt index 622e127dc5e..92572db5fdc 100644 --- a/sql/share/polish/errmsg.txt +++ b/sql/share/polish/errmsg.txt @@ -294,6 +294,9 @@ character-set=latin2 "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Unknown table engine '%s'", "'%s' is deprecated. Use '%s' instead.", +"The target table %-.100s of the %s is not updatable.", +"The '%s' feature was disabled. You need MySQL built with '%s' define to have it working" +"MySQL is started in --skip-grant-tables mode. You can't use this command" "Can't create a %s from within another stored routine" "%s %s already exists" "%s %s does not exist" diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt index cb9c0e745f9..580fec472b6 100644 --- a/sql/share/portuguese/errmsg.txt +++ b/sql/share/portuguese/errmsg.txt @@ -291,6 +291,9 @@ character-set=latin1 "MySQL foi inicializado em modo --skip-name-resolve. Você necesita reincializá-lo sem esta opção para este grant funcionar", "Motor de tabela desconhecido '%s'", "'%s' é desatualizado. Use '%s' em seu lugar.", +"The target table %-.100s of the %s is not updatable.", +"The '%s' feature was disabled. You need MySQL built with '%s' define to have it working" +"MySQL is started in --skip-grant-tables mode. You can't use this command" "Can't create a %s from within another stored routine" "%s %s already exists" "%s %s does not exist" diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt index a37f29b8a33..3e6bff75591 100644 --- a/sql/share/romanian/errmsg.txt +++ b/sql/share/romanian/errmsg.txt @@ -294,6 +294,9 @@ character-set=latin2 "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Unknown table engine '%s'", "'%s' is deprecated. Use '%s' instead.", +"The target table %-.100s of the %s is not updatable.", +"The '%s' feature was disabled. You need MySQL built with '%s' define to have it working" +"MySQL is started in --skip-grant-tables mode. You can't use this command" "Can't create a %s from within another stored routine" "%s %s already exists" "%s %s does not exist" diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt index 2dbe6b9184c..b04cda84efd 100644 --- a/sql/share/russian/errmsg.txt +++ b/sql/share/russian/errmsg.txt @@ -292,6 +292,9 @@ character-set=koi8r "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Unknown table engine '%s'", "'%s' is deprecated. Use '%s' instead.", +"ôÁÂÌÉÃÁ %-.100s × %s ÎÅ ÍÏÖÅÔ ÉÚÍÅÎÑÔÓÑ.", +"The '%s' feature was disabled. You need MySQL built with '%s' define to have it working" +"MySQL is started in --skip-grant-tables mode. You can't use this command" "Can't create a %s from within another stored routine" "%s %s already exists" "%s %s does not exist" diff --git a/sql/share/serbian/errmsg.txt b/sql/share/serbian/errmsg.txt index 97bef4e1714..2737ce26873 100644 --- a/sql/share/serbian/errmsg.txt +++ b/sql/share/serbian/errmsg.txt @@ -285,6 +285,9 @@ character-set=cp1250 "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Unknown table engine '%s'", "'%s' is deprecated. Use '%s' instead.", +"The target table %-.100s of the %s is not updatable.", +"The '%s' feature was disabled. You need MySQL built with '%s' define to have it working" +"MySQL is started in --skip-grant-tables mode. You can't use this command" "Can't create a %s from within another stored routine" "%s %s already exists" "%s %s does not exist" diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt index e841214ba1c..bf9fe6d3519 100644 --- a/sql/share/slovak/errmsg.txt +++ b/sql/share/slovak/errmsg.txt @@ -298,6 +298,9 @@ character-set=latin2 "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Unknown table engine '%s'", "'%s' is deprecated. Use '%s' instead.", +"The target table %-.100s of the %s is not updatable.", +"The '%s' feature was disabled. You need MySQL built with '%s' define to have it working" +"MySQL is started in --skip-grant-tables mode. You can't use this command" "Can't create a %s from within another stored routine" "%s %s already exists" "%s %s does not exist" diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt index cdabd339e1e..fec6bbb4342 100644 --- a/sql/share/spanish/errmsg.txt +++ b/sql/share/spanish/errmsg.txt @@ -292,6 +292,9 @@ character-set=latin1 "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Unknown table engine '%s'", "'%s' is deprecated. Use '%s' instead.", +"The target table %-.100s of the %s is not updatable.", +"The '%s' feature was disabled. You need MySQL built with '%s' define to have it working" +"MySQL is started in --skip-grant-tables mode. You can't use this command" "Can't create a %s from within another stored routine" "%s %s already exists" "%s %s does not exist" diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt index aab70294ec8..8b2892172ba 100644 --- a/sql/share/swedish/errmsg.txt +++ b/sql/share/swedish/errmsg.txt @@ -290,6 +290,9 @@ character-set=latin1 "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Unknown table engine '%s'", "'%s' is deprecated. Use '%s' instead.", +"The target table %-.100s of the %s is not updatable.", +"The '%s' feature was disabled. You need MySQL built with '%s' define to have it working" +"MySQL is started in --skip-grant-tables mode. You can't use this command" "Can't create a %s from within another stored routine" "%s %s already exists" "%s %s does not exist" diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt index 828c0a46cad..393c765a8ca 100644 --- a/sql/share/ukrainian/errmsg.txt +++ b/sql/share/ukrainian/errmsg.txt @@ -295,6 +295,9 @@ character-set=koi8u "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Unknown table engine '%s'", "'%s' is deprecated. Use '%s' instead.", +"ôÁÂÌÉÃÑ %-.100s Õ %s ÎÅ ÍÏÖÅ ÏÎÏ×ÌÀ×ÁÔÉÓØ.", +"The '%s' feature was disabled. You need MySQL built with '%s' define to have it working" +"MySQL is started in --skip-grant-tables mode. You can't use this command" "Can't create a %s from within another stored routine" "%s %s already exists" "%s %s does not exist" diff --git a/sql/slave.cc b/sql/slave.cc index 99f7eb8d019..e3d9e0dab58 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -2866,7 +2866,7 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli) rli->is_until_satisfied()) { sql_print_error("Slave SQL thread stopped because it reached its" - " UNTIL position"); + " UNTIL position %ld", (long) rli->until_pos()); /* Setting abort_slave flag because we do not want additional message about error in query execution to be printed. @@ -3342,6 +3342,7 @@ slave_begin: sql_print_error("Failed during slave thread initialization"); goto err; } + thd->init_for_queries(); rli->sql_thd= thd; thd->temporary_tables = rli->save_temporary_tables; // restore temp tables pthread_mutex_lock(&LOCK_thread_count); diff --git a/sql/slave.h b/sql/slave.h index 3313f587b3d..016944534f7 100644 --- a/sql/slave.h +++ b/sql/slave.h @@ -347,6 +347,11 @@ typedef struct st_relay_log_info /* Check if UNTIL condition is satisfied. See slave.cc for more. */ bool is_until_satisfied(); + inline ulonglong until_pos() + { + return ((until_condition == UNTIL_MASTER_POS) ? group_master_log_pos : + group_relay_log_pos); + } } RELAY_LOG_INFO; diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 2feb9594715..5febb49e110 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -52,7 +52,7 @@ static byte* acl_entry_get_key(acl_entry *entry,uint *length, return (byte*) entry->key; } -#define IP_ADDR_STRLEN +#define IP_ADDR_STRLEN (3+1+3+1+3+1+3) #define ACL_KEY_LENGTH (IP_ADDR_STRLEN+1+NAME_LEN+1+USERNAME_LENGTH+1) static DYNAMIC_ARRAY acl_hosts,acl_users,acl_dbs; @@ -173,7 +173,8 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables) tables[0].lock_type=tables[1].lock_type=tables[2].lock_type=TL_READ; tables[0].db=tables[1].db=tables[2].db=thd->db; - if (open_tables(thd,tables)) + uint counter; + if (open_tables(thd, tables, &counter)) { sql_print_error("Fatal error: Can't open privilege tables: %s", thd->net.last_error); @@ -1174,8 +1175,8 @@ bool check_change_password(THD *thd, const char *host, const char *user) { if (!initialized) { - send_error(thd, ER_PASSWORD_NOT_ALLOWED); /* purecov: inspected */ - return(1); /* purecov: inspected */ + send_error(thd, ER_SKIP_GRANT_TABLES); /* purecov: inspected */ + return(1); /* purecov: inspected */ } if (!thd->slave_thread && (strcmp(thd->user,user) || @@ -1649,8 +1650,14 @@ static int replace_db_table(TABLE *table, const char *db, char what= (revoke_grant) ? 'N' : 'Y'; DBUG_ENTER("replace_db_table"); + if (!initialized) + { + my_error(ER_SKIP_GRANT_TABLES, MYF(0)); + DBUG_RETURN(-1); + } + /* Check if there is such a user in user table in memory? */ - if (!initialized || !find_acl_user(combo.host.str,combo.user.str)) + if (!find_acl_user(combo.host.str,combo.user.str)) { my_error(ER_PASSWORD_NO_MATCH,MYF(0)); DBUG_RETURN(-1); @@ -2226,7 +2233,7 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, if (!initialized) { - send_error(thd, ER_UNKNOWN_COM_ERROR); /* purecov: inspected */ + send_error(thd, ER_SKIP_GRANT_TABLES); /* purecov: inspected */ DBUG_RETURN(1); /* purecov: inspected */ } if (rights & ~TABLE_ACLS) @@ -2300,7 +2307,7 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, } #endif - if (open_and_lock_tables(thd,tables)) + if (simple_open_n_lock_tables(thd,tables)) { // Should never happen close_thread_tables(thd); /* purecov: deadcode */ DBUG_RETURN(-1); /* purecov: deadcode */ @@ -2436,8 +2443,8 @@ int mysql_grant(THD *thd, const char *db, List <LEX_USER> &list, DBUG_ENTER("mysql_grant"); if (!initialized) { - my_error(ER_UNKNOWN_COM_ERROR, MYF(0)); /* purecov: tested */ - return -1; /* purecov: tested */ + my_error(ER_SKIP_GRANT_TABLES, MYF(0)); /* purecov: tested */ + DBUG_RETURN(-1); /* purecov: tested */ } if (lower_case_table_names && db) @@ -2448,7 +2455,7 @@ int mysql_grant(THD *thd, const char *db, List <LEX_USER> &list, } /* open the mysql.user and mysql.db tables */ - + bzero((char*) &tables,sizeof(tables)); tables[0].alias=tables[0].real_name=(char*) "user"; tables[1].alias=tables[1].real_name=(char*) "db"; tables[0].next=tables+1; @@ -2474,7 +2481,7 @@ int mysql_grant(THD *thd, const char *db, List <LEX_USER> &list, } #endif - if (open_and_lock_tables(thd,tables)) + if (simple_open_n_lock_tables(thd,tables)) { // This should never happen close_thread_tables(thd); /* purecov: deadcode */ DBUG_RETURN(-1); /* purecov: deadcode */ @@ -2570,14 +2577,15 @@ my_bool grant_init(THD *org_thd) thd->store_globals(); thd->db= my_strdup("mysql",MYF(0)); thd->db_length=5; // Safety - bzero((char*) &tables,sizeof(tables)); + bzero((char*) &tables, sizeof(tables)); tables[0].alias=tables[0].real_name= (char*) "tables_priv"; tables[1].alias=tables[1].real_name= (char*) "columns_priv"; tables[0].next=tables+1; tables[0].lock_type=tables[1].lock_type=TL_READ; tables[0].db=tables[1].db=thd->db; - if (open_tables(thd,tables)) + uint counter; + if (open_tables(thd, tables, &counter)) goto end; TABLE *ptr[2]; // Lock tables for quick update @@ -2602,7 +2610,7 @@ my_bool grant_init(THD *org_thd) do { GRANT_TABLE *mem_check; - if (!(mem_check=new GRANT_TABLE(t_table,c_table)) || mem_check->ok()) + if (!(mem_check=new GRANT_TABLE(t_table,c_table)) || !mem_check->ok()) { /* This could only happen if we are out memory */ grant_option= FALSE; /* purecov: deadcode */ @@ -3041,8 +3049,8 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user) LINT_INIT(acl_user); if (!initialized) { - send_error(thd, ER_UNKNOWN_COM_ERROR); - DBUG_RETURN(-1); + send_error(thd, ER_SKIP_GRANT_TABLES); + DBUG_RETURN(1); } if (lex_user->host.length > HOSTNAME_LENGTH || lex_user->user.length > USERNAME_LENGTH) @@ -3394,7 +3402,7 @@ int open_grant_tables(THD *thd, TABLE_LIST *tables) if (!initialized) { - send_error(thd, ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES)); + send_error(thd, ER_SKIP_GRANT_TABLES); DBUG_RETURN(-1); } @@ -3429,7 +3437,7 @@ int open_grant_tables(THD *thd, TABLE_LIST *tables) } #endif - if (open_and_lock_tables(thd, tables)) + if (simple_open_n_lock_tables(thd, tables)) { // This should never happen close_thread_tables(thd); DBUG_RETURN(-1); @@ -3475,7 +3483,7 @@ int mysql_drop_user(THD *thd, List <LEX_USER> &list) DBUG_ENTER("mysql_drop_user"); if ((result= open_grant_tables(thd, tables))) - DBUG_RETURN(result == 1 ? 0 : -1); + DBUG_RETURN(result == 1 ? 0 : 1); rw_wrlock(&LOCK_grant); VOID(pthread_mutex_lock(&acl_cache->lock)); @@ -3588,7 +3596,7 @@ int mysql_revoke_all(THD *thd, List <LEX_USER> &list) DBUG_ENTER("mysql_revoke_all"); if ((result= open_grant_tables(thd, tables))) - DBUG_RETURN(result == 1 ? 0 : -1); + DBUG_RETURN(result == 1 ? 0 : 1); rw_wrlock(&LOCK_grant); VOID(pthread_mutex_lock(&acl_cache->lock)); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 02ecb158ebe..8f319ee645d 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1305,9 +1305,9 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db, goto err; // Can't repair the table TABLE_LIST table_list; + bzero((char*) &table_list, sizeof(table_list)); // just for safe table_list.db=(char*) db; table_list.real_name=(char*) name; - table_list.next=0; safe_mutex_assert_owner(&LOCK_open); if ((error=lock_table_name(thd,&table_list))) @@ -1356,27 +1356,45 @@ err: DBUG_RETURN(1); } -/***************************************************************************** -** open all tables in list -*****************************************************************************/ +/* + Open all tables in list -int open_tables(THD *thd,TABLE_LIST *start) + SYNOPSIS + open_tables() + thd - thread handler + start - list of tables + counter - number of opened tables will be return using this parameter + + RETURN + 0 - OK + -1 - error +*/ + +int open_tables(THD *thd, TABLE_LIST *start, uint *counter) { TABLE_LIST *tables; bool refresh; int result=0; DBUG_ENTER("open_tables"); + *counter= 0; thd->current_tablenr= 0; restart: thd->proc_info="Opening tables"; for (tables=start ; tables ; tables=tables->next) { + /* + Ignore placeholders for derived tables. After derived tables + processing, link to created temporary table will be put here. + */ + if (tables->derived) + continue; + (*counter)++; if (!tables->table && - !(tables->table=open_table(thd, - tables->db, - tables->real_name, - tables->alias, &refresh))) + !(tables->table= open_table(thd, + tables->db, + tables->real_name, + tables->alias, &refresh))) { if (refresh) // Refresh in progress { @@ -1522,15 +1540,57 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type) /* - Open all tables in list and locks them for read. - The lock will automaticly be freed by close_thread_tables() + Open all tables in list and locks them for read without derived + tables processing. + + SYNOPSIS + simple_open_n_lock_tables() + thd - thread handler + tables - list of tables for open&locking + + RETURN + 0 - ok + -1 - error + + NOTE + The lock will automaticly be freed by close_thread_tables() */ -int open_and_lock_tables(THD *thd,TABLE_LIST *tables) +int simple_open_n_lock_tables(THD *thd, TABLE_LIST *tables) { - if (open_tables(thd,tables) || lock_tables(thd,tables)) - return -1; /* purecov: inspected */ - return 0; + DBUG_ENTER("simple_open_n_lock_tables"); + uint counter; + if (open_tables(thd, tables, &counter) || lock_tables(thd, tables, counter)) + DBUG_RETURN(-1); /* purecov: inspected */ + DBUG_RETURN(0); +} + + +/* + Open all tables in list, locks them and process derived tables + tables processing. + + SYNOPSIS + open_and_lock_tables() + thd - thread handler + tables - list of tables for open&locking + + RETURN + 0 - ok + -1 - error + + NOTE + The lock will automaticly be freed by close_thread_tables() +*/ + +int open_and_lock_tables(THD *thd, TABLE_LIST *tables) +{ + DBUG_ENTER("open_and_lock_tables"); + uint counter; + if (open_tables(thd, tables, &counter) || lock_tables(thd, tables, counter)) + DBUG_RETURN(-1); /* purecov: inspected */ + fix_tables_pointers(thd->lex->all_selects_list); + DBUG_RETURN(mysql_handle_derived(thd->lex)); } @@ -1541,6 +1601,7 @@ int open_and_lock_tables(THD *thd,TABLE_LIST *tables) lock_tables() thd Thread handler tables Tables to lock + count umber of opened tables NOTES You can't call lock_tables twice, as this would break the dead-lock-free @@ -1552,7 +1613,7 @@ int open_and_lock_tables(THD *thd,TABLE_LIST *tables) -1 Error */ -int lock_tables(THD *thd,TABLE_LIST *tables) +int lock_tables(THD *thd, TABLE_LIST *tables, uint count) { TABLE_LIST *table; if (!tables) @@ -1561,14 +1622,14 @@ int lock_tables(THD *thd,TABLE_LIST *tables) if (!thd->locked_tables) { DBUG_ASSERT(thd->lock == 0); // You must lock everything at once - uint count=0; - for (table = tables ; table ; table=table->next) - count++; TABLE **start,**ptr; if (!(ptr=start=(TABLE**) sql_alloc(sizeof(TABLE*)*count))) return -1; for (table = tables ; table ; table=table->next) - *(ptr++)= table->table; + { + if (!table->derived) + *(ptr++)= table->table; + } if (!(thd->lock=mysql_lock_tables(thd,start,count))) return -1; /* purecov: inspected */ } @@ -1576,7 +1637,8 @@ int lock_tables(THD *thd,TABLE_LIST *tables) { for (table = tables ; table ; table=table->next) { - if (check_lock_and_start_stmt(thd, table->table, table->lock_type)) + if (!table->derived && + check_lock_and_start_stmt(thd, table->table, table->lock_type)) { ha_rollback_stmt(thd); return -1; @@ -2039,15 +2101,28 @@ int setup_fields(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, /* - Remap table numbers if INSERT ... SELECT - Check also that the 'used keys' and 'ignored keys' exists and set up the - table structure accordingly + prepare tables + + SYNOPSIS + setup_tables() + tables - tables list + reinit - true if called for table reinitialization before + subquery reexecuting + + RETURN + 0 ok; In this case *map will includes the choosed index + 1 error + + NOTE + Remap table numbers if INSERT ... SELECT + Check also that the 'used keys' and 'ignored keys' exists and set up the + table structure accordingly - This has to be called for all tables that are used by items, as otherwise - table->map is not set and all Item_field will be regarded as const items. + This has to be called for all tables that are used by items, as otherwise + table->map is not set and all Item_field will be regarded as const items. */ -bool setup_tables(TABLE_LIST *tables) +bool setup_tables(TABLE_LIST *tables, my_bool reinit) { DBUG_ENTER("setup_tables"); uint tablenr=0; @@ -2074,7 +2149,7 @@ bool setup_tables(TABLE_LIST *tables) table->keys_in_use_for_query.subtract(map); } table->used_keys.intersect(table->keys_in_use_for_query); - if (table_list->shared || table->clear_query_id) + if ((table_list->shared || table->clear_query_id) && !reinit) { table->clear_query_id= 0; /* Clear query_id that may have been set by previous select */ @@ -2382,7 +2457,7 @@ int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys) create_info.default_table_charset= thd->variables.collation_database; DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->real_name, &create_info, table_list, - fields, keys, drop, alter, 0, (ORDER*)0, FALSE, + fields, keys, drop, alter, 0, (ORDER*)0, DUP_ERROR)); } @@ -2399,7 +2474,7 @@ int mysql_drop_index(THD *thd, TABLE_LIST *table_list, List<Alter_drop> &drop) create_info.default_table_charset= thd->variables.collation_database; DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->real_name, &create_info, table_list, - fields, keys, drop, alter, 0, (ORDER*)0, FALSE, + fields, keys, drop, alter, 0, (ORDER*)0, DUP_ERROR)); } diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index 02df644f3b4..fd5c339a6ff 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -308,6 +308,10 @@ TODO list: #include "../myisammrg/myrg_def.h" #endif +#ifdef EMBEDDED_LIBRARY +#include "emb_qcache.h" +#endif + #if defined(EXTRA_DEBUG) && !defined(DBUG_OFF) #define MUTEX_LOCK(M) { DBUG_PRINT("lock", ("mutex lock 0x%lx", (ulong)(M))); \ pthread_mutex_lock(M);} @@ -646,7 +650,7 @@ void query_cache_abort(NET *net) } -void query_cache_end_of_result(NET *net) +void query_cache_end_of_result(THD *thd) { DBUG_ENTER("query_cache_end_of_result"); @@ -655,11 +659,15 @@ void query_cache_end_of_result(NET *net) if (query_cache.query_cache_size == 0) DBUG_VOID_RETURN; #endif - if (net->query_cache_query != 0) // Quick check on unlocked structure + if (thd->net.query_cache_query != 0) // Quick check on unlocked structure { +#ifdef EMBEDDED_LIBRARY + query_cache_insert(&thd->net, (byte*)thd, + emb_count_querycache_size(thd)); +#endif STRUCT_LOCK(&query_cache.structure_guard_mutex); Query_cache_block *query_block = ((Query_cache_block*) - net->query_cache_query); + thd->net.query_cache_query); if (query_block) { DUMP(&query_cache); @@ -691,7 +699,7 @@ void query_cache_end_of_result(NET *net) // Cache was flushed or resized and query was deleted => do nothing STRUCT_UNLOCK(&query_cache.structure_guard_mutex); } - net->query_cache_query=0; + thd->net.query_cache_query=0; DBUG_EXECUTE("check_querycache",query_cache.check_integrity(0);); } DBUG_VOID_RETURN; @@ -1057,23 +1065,29 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length) /* Send cached result to client */ +#ifndef EMBEDDED_LIBRARY do { DBUG_PRINT("qcache", ("Results (len %lu, used %lu, headers %lu)", - result_block->length, result_block->used, - result_block->headers_len()+ - ALIGN_SIZE(sizeof(Query_cache_result)))); - + result_block->length, result_block->used, + result_block->headers_len()+ + ALIGN_SIZE(sizeof(Query_cache_result)))); + Query_cache_result *result = result_block->result(); -#ifndef EMBEDDED_LIBRARY /* TODO query cache in embedded library*/ if (net_real_write(&thd->net, result->data(), result_block->used - result_block->headers_len() - ALIGN_SIZE(sizeof(Query_cache_result)))) break; // Client aborted -#endif result_block = result_block->next; } while (result_block != first_result_block); +#else + { + Querycache_stream qs(result_block, result_block->headers_len() + + ALIGN_SIZE(sizeof(Query_cache_result))); + emb_load_querycache_result(thd, &qs); + } +#endif /*!EMBEDDED_LIBRARY*/ thd->limit_found_rows = query->found_rows(); @@ -1809,18 +1823,23 @@ my_bool Query_cache::write_result_data(Query_cache_block **result_block, Query_cache_block *block = *result_block; uint headers_len = (ALIGN_SIZE(sizeof(Query_cache_block)) + ALIGN_SIZE(sizeof(Query_cache_result))); +#ifndef EMBEDDED_LIBRARY // Now fill list of blocks that created by allocate_data_chain do { block->type = type; ulong length = block->used - headers_len; DBUG_PRINT("qcache", ("write %lu byte in block 0x%lx",length, - (ulong)block)); + (ulong)block)); memcpy((void*)(((byte*) block)+headers_len), (void*) rest, length); rest += length; block = block->next; type = Query_cache_block::RES_CONT; } while (block != *result_block); +#else + Querycache_stream qs(*result_block, headers_len); + emb_store_querycache_result(&qs, (THD*)data); +#endif /*!EMBEDDED_LIBRARY*/ } else { diff --git a/sql/sql_cache.h b/sql/sql_cache.h index 68e69ab523f..ac4f465bf79 100644 --- a/sql/sql_cache.h +++ b/sql/sql_cache.h @@ -392,7 +392,7 @@ protected: void destroy(); friend void query_cache_insert(NET *net, const char *packet, ulong length); - friend void query_cache_end_of_result(NET *net); + friend void query_cache_end_of_result(THD *thd); friend void query_cache_abort(NET *net); /* @@ -416,7 +416,7 @@ protected: extern Query_cache query_cache; extern TYPELIB query_cache_type_typelib; -void query_cache_end_of_result(NET *net); +void query_cache_end_of_result(THD *thd); void query_cache_abort(NET *net); #endif diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 93a2db50876..635e6807516 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -149,9 +149,6 @@ THD::THD():user_time(0), is_fatal_error(0), *scramble= '\0'; init(); - init_sql_alloc(&mem_root, // must be after init() - variables.query_alloc_block_size, - variables.query_prealloc_size); /* Initialize sub structures */ init_alloc_root(&warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE); user_connect=(USER_CONN *)0; @@ -188,9 +185,6 @@ THD::THD():user_time(0), is_fatal_error(0), transaction.trans_log.end_of_file= max_binlog_cache_size; } #endif - init_sql_alloc(&transaction.mem_root, - variables.trans_alloc_block_size, - variables.trans_prealloc_size); /* We need good random number initialization for new thread Just coping global one will not work @@ -234,6 +228,23 @@ void THD::init(void) /* + Init THD for query processing. + This has to be called once before we call mysql_parse. + See also comments in sql_class.h. +*/ + +void THD::init_for_queries() +{ + init_sql_alloc(&mem_root, + variables.query_alloc_block_size, + variables.query_prealloc_size); + init_sql_alloc(&transaction.mem_root, + variables.trans_alloc_block_size, + variables.trans_prealloc_size); +} + + +/* Do what's needed when one invokes change user SYNOPSIS @@ -330,8 +341,8 @@ THD::~THD() safeFree(host); if (user != delayed_user) safeFree(user); - safeFree(db); safeFree(ip); + safeFree(db); free_root(&warn_root,MYF(0)); free_root(&transaction.mem_root,MYF(0)); mysys_var=0; // Safety (shouldn't be needed) @@ -339,6 +350,8 @@ THD::~THD() #ifndef DBUG_OFF dbug_sentry= THD_SENTRY_GONE; #endif + /* Reset stmt_backup.mem_root to not double-free memory from thd.mem_root */ + init_alloc_root(&stmt_backup.mem_root, 0, 0); DBUG_VOID_RETURN; } @@ -678,12 +691,24 @@ bool select_send::send_eof() } -/*************************************************************************** -** Export of select to textfile -***************************************************************************/ +/************************************************************************ + Handling writing to file +************************************************************************/ +void select_to_file::send_error(uint errcode,const char *err) +{ + ::send_error(thd,errcode,err); + if (file > 0) + { + (void) end_io_cache(&cache); + (void) my_close(file,MYF(0)); + (void) my_delete(path,MYF(0)); // Delete file on error + file= -1; + } +} -select_export::~select_export() + +select_to_file::~select_to_file() { if (file >= 0) { // This only happens in case of error @@ -691,42 +716,78 @@ select_export::~select_export() (void) my_close(file,MYF(0)); file= -1; } +} + +/*************************************************************************** +** Export of select to textfile +***************************************************************************/ + +select_export::~select_export() +{ thd->sent_row_count=row_count; } -int -select_export::prepare(List<Item> &list, SELECT_LEX_UNIT *u) + +/* + Create file with IO cache + + SYNOPSIS + create_file() + thd Thread handle + path File name + exchange Excange class + cache IO cache + + RETURN + >= 0 File handle + -1 Error +*/ + + +static File create_file(THD *thd, char *path, sql_exchange *exchange, + IO_CACHE *cache) { - char path[FN_REFLEN]; - uint option=4; - bool blob_flag=0; - unit= u; + File file; + uint option= MY_UNPACK_FILENAME; + #ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS - option|=1; // Force use of db directory + option|= MY_REPLACE_DIR; // Force use of db directory #endif - if ((uint) strlen(exchange->file_name) + NAME_LEN >= FN_REFLEN) - strmake(path,exchange->file_name,FN_REFLEN-1); - (void) fn_format(path,exchange->file_name, thd->db ? thd->db : "", "", + (void) fn_format(path, exchange->file_name, thd->db ? thd->db : "", "", option); - if (!access(path,F_OK)) + if (!access(path, F_OK)) { my_error(ER_FILE_EXISTS_ERROR, MYF(0), exchange->file_name); - return 1; + return -1; } /* Create the file world readable */ - if ((file=my_create(path, 0666, O_WRONLY, MYF(MY_WME))) < 0) - return 1; + if ((file= my_create(path, 0666, O_WRONLY, MYF(MY_WME))) < 0) + return file; #ifdef HAVE_FCHMOD - (void) fchmod(file,0666); // Because of umask() + (void) fchmod(file, 0666); // Because of umask() #else - (void) chmod(path,0666); + (void) chmod(path, 0666); #endif - if (init_io_cache(&cache,file,0L,WRITE_CACHE,0L,1,MYF(MY_WME))) + if (init_io_cache(cache, file, 0L, WRITE_CACHE, 0L, 1, MYF(MY_WME))) { - my_close(file,MYF(0)); - file= -1; - return 1; + my_close(file, MYF(0)); + my_delete(path, MYF(0)); // Delete file on error, it was just created + return -1; } + return file; +} + + +int +select_export::prepare(List<Item> &list, SELECT_LEX_UNIT *u) +{ + bool blob_flag=0; + unit= u; + if ((uint) strlen(exchange->file_name) + NAME_LEN >= FN_REFLEN) + strmake(path,exchange->file_name,FN_REFLEN-1); + + if ((file= create_file(thd, path, exchange, &cache)) < 0) + return 1; /* Check if there is any blobs in data */ { List_iterator_fast<Item> li(list); @@ -897,15 +958,6 @@ err: } -void select_export::send_error(uint errcode, const char *err) -{ - ::send_error(thd,errcode,err); - (void) end_io_cache(&cache); - (void) my_close(file,MYF(0)); - file= -1; -} - - bool select_export::send_eof() { int error=test(end_io_cache(&cache)); @@ -923,48 +975,12 @@ bool select_export::send_eof() ***************************************************************************/ -select_dump::~select_dump() -{ - if (file >= 0) - { // This only happens in case of error - (void) end_io_cache(&cache); - (void) my_close(file,MYF(0)); - file= -1; - } -} - int select_dump::prepare(List<Item> &list __attribute__((unused)), SELECT_LEX_UNIT *u) { - uint option=4; unit= u; -#ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS - option|=1; // Force use of db directory -#endif - (void) fn_format(path,exchange->file_name, thd->db ? thd->db : "", "", - option); - if (!access(path,F_OK)) - { - my_error(ER_FILE_EXISTS_ERROR,MYF(0),exchange->file_name); - return 1; - } - /* Create the file world readable */ - if ((file=my_create(path, 0666, O_WRONLY, MYF(MY_WME))) < 0) - return 1; -#ifdef HAVE_FCHMOD - (void) fchmod(file,0666); // Because of umask() -#else - (void) chmod(path,0666); -#endif - if (init_io_cache(&cache,file,0L,WRITE_CACHE,0L,1,MYF(MY_WME))) - { - my_close(file,MYF(0)); - my_delete(path,MYF(0)); - file= -1; - return 1; - } - return 0; + return (int) ((file= create_file(thd, path, exchange, &cache)) < 0); } @@ -1007,15 +1023,6 @@ err: } -void select_dump::send_error(uint errcode,const char *err) -{ - ::send_error(thd,errcode,err); - (void) end_io_cache(&cache); - (void) my_close(file,MYF(0)); - (void) my_delete(path,MYF(0)); // Delete file on error - file= -1; -} - bool select_dump::send_eof() { int error=test(end_io_cache(&cache)); @@ -1027,18 +1034,20 @@ bool select_dump::send_eof() return error; } + select_subselect::select_subselect(Item_subselect *item_arg) { item= item_arg; } + bool select_singlerow_subselect::send_data(List<Item> &items) { DBUG_ENTER("select_singlerow_subselect::send_data"); Item_singlerow_subselect *it= (Item_singlerow_subselect *)item; if (it->assigned()) { - my_message(ER_SUBQUERY_NO_1_ROW, ER(ER_SUBQUERY_NO_1_ROW), MYF(0)); + my_message(ER_SUBQUERY_NO_1_ROW, ER(ER_SUBQUERY_NO_1_ROW), MYF(0)); DBUG_RETURN(1); } if (unit->offset_limit_cnt) @@ -1054,6 +1063,7 @@ bool select_singlerow_subselect::send_data(List<Item> &items) DBUG_RETURN(0); } + bool select_max_min_finder_subselect::send_data(List<Item> &items) { DBUG_ENTER("select_max_min_finder_subselect::send_data"); @@ -1159,8 +1169,9 @@ bool select_exists_subselect::send_data(List<Item> &items) /*************************************************************************** -** Dump of select to variables + Dump of select to variables ***************************************************************************/ + int select_dumpvar::prepare(List<Item> &list, SELECT_LEX_UNIT *u) { List_iterator_fast<Item> li(list); diff --git a/sql/sql_class.h b/sql/sql_class.h index 91ffb9bb7d9..2638d633e8f 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -428,7 +428,6 @@ struct system_variables void free_tmp_table(THD *thd, TABLE *entry); -class Prepared_statement; /* State of a single command executed against this connection. @@ -606,8 +605,7 @@ public: Statement_map stmt_map; /* keeps THD state while it is used for active statement - Note, that double free_root() is safe, so we don't need to do any - special cleanup for it in THD destructor. + Note: we perform special cleanup for it in THD destructor. */ Statement stmt_backup; /* @@ -657,6 +655,19 @@ public: and are still in use by this thread */ TABLE *open_tables,*temporary_tables, *handler_tables, *derived_tables; + /* + During a MySQL session, one can lock tables in two modes: automatic + or manual. In automatic mode all necessary tables are locked just before + statement execution, and all acquired locks are stored in 'lock' + member. Unlocking takes place automatically as well, when the + statement ends. + Manual mode comes into play when a user issues a 'LOCK TABLES' + statement. In this mode the user can only use the locked tables. + Trying to use any other tables will give an error. The locked tables are + stored in 'locked_tables' member. Manual locking is described in + the 'LOCK_TABLES' chapter of the MySQL manual. + See also lock_tables() for details. + */ MYSQL_LOCK *lock; /* Current locks */ MYSQL_LOCK *locked_tables; /* Tables locked with LOCK */ /* @@ -806,6 +817,16 @@ public: ~THD(); void init(void); + /* + Initialize memory roots necessary for query processing and (!) + pre-allocate memory for it. We can't do that in THD constructor because + there are use cases (acl_init, delayed inserts, watcher threads, + killing mysqld) where it's vital to not allocate excessive and not used + memory. Note, that we still don't return error from init_for_queries(): + if preallocation fails, we should notice that at the first call to + alloc_root. + */ + void init_for_queries(); void change_user(void); void cleanup(void); bool store_globals(); @@ -987,41 +1008,41 @@ public: }; -class select_export :public select_result { +class select_to_file :public select_result { +protected: sql_exchange *exchange; File file; IO_CACHE cache; ha_rows row_count; + char path[FN_REFLEN]; + +public: + select_to_file(sql_exchange *ex) :exchange(ex), file(-1),row_count(0L) + { path[0]=0; } + ~select_to_file(); + bool send_fields(List<Item> &list, uint flag) { return 0; } + void send_error(uint errcode,const char *err); +}; + + +class select_export :public select_to_file { uint field_term_length; int field_sep_char,escape_char,line_sep_char; bool fixed_row_size; public: - select_export(sql_exchange *ex) :exchange(ex),file(-1),row_count(0L) {} + select_export(sql_exchange *ex) :select_to_file(ex) {} ~select_export(); int prepare(List<Item> &list, SELECT_LEX_UNIT *u); - bool send_fields(List<Item> &list, - uint flag) { return 0; } bool send_data(List<Item> &items); - void send_error(uint errcode,const char *err); bool send_eof(); }; -class select_dump :public select_result { - sql_exchange *exchange; - File file; - IO_CACHE cache; - ha_rows row_count; - char path[FN_REFLEN]; +class select_dump :public select_to_file { public: - select_dump(sql_exchange *ex) :exchange(ex),file(-1),row_count(0L) - { path[0]=0; } - ~select_dump(); + select_dump(sql_exchange *ex) :select_to_file(ex) {} int prepare(List<Item> &list, SELECT_LEX_UNIT *u); - bool send_fields(List<Item> &list, - uint flag) { return 0; } bool send_data(List<Item> &items); - void send_error(uint errcode,const char *err); bool send_eof(); }; diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 2d636c51dd4..bc6b30040d6 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -25,8 +25,6 @@ #include <direct.h> #endif -#define MY_DB_OPT_FILE "db.opt" - const char *del_exts[]= {".frm", ".BAK", ".TMD",".opt", NullS}; static TYPELIB deletable_extentions= {array_elements(del_exts)-1,"del_exts", del_exts}; @@ -92,7 +90,7 @@ static bool write_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create) */ -static bool load_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create) +bool load_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create) { File file; char buf[256]; @@ -269,11 +267,8 @@ int mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info) VOID(pthread_mutex_lock(&LOCK_mysql_create_db)); // do not alter database if another thread is holding read lock - if (wait_if_global_read_lock(thd,0)) - { - error= -1; + if ((error=wait_if_global_read_lock(thd,0))) goto exit2; - } /* Check directory */ (void)sprintf(path,"%s/%s/%s", mysql_data_home, db, MY_DB_OPT_FILE); @@ -305,7 +300,7 @@ exit: start_waiting_global_read_lock(thd); exit2: VOID(pthread_mutex_unlock(&LOCK_mysql_create_db)); - DBUG_RETURN(error); + DBUG_RETURN(error ? -1 : 0); /* -1 to delegate send_error() */ } @@ -408,7 +403,7 @@ exit: when the slave is replicating a DROP DATABASE: - garbage characters in the error message: "Error 'Can't drop database 'test2'; database doesn't exist' on query - 'h4zI¿'" + 'h4zI©'" - segfault - hang in "free(vio)" (yes!) in the I/O or SQL slave threads (so slave server hangs at shutdown etc). @@ -417,7 +412,8 @@ exit: { if (!(thd->slave_thread)) /* a slave thread will free it itself */ x_free(thd->db); - thd->db= 0; + thd->db= 0; + thd->db_length= 0; } exit2: VOID(pthread_mutex_unlock(&LOCK_mysql_create_db)); @@ -667,90 +663,3 @@ bool mysql_change_db(THD *thd, const char *name) DBUG_RETURN(0); } - -int mysqld_show_create_db(THD *thd, char *dbname, - HA_CREATE_INFO *create_info) -{ - int length; - char path[FN_REFLEN], *to; - uint db_access; - bool found_libchar; - HA_CREATE_INFO create; - uint create_options = create_info ? create_info->options : 0; - Protocol *protocol=thd->protocol; - DBUG_ENTER("mysql_show_create_db"); - - if (check_db_name(dbname)) - { - net_printf(thd,ER_WRONG_DB_NAME, dbname); - DBUG_RETURN(1); - } - -#ifndef NO_EMBEDDED_ACCESS_CHECKS - if (test_all_bits(thd->master_access,DB_ACLS)) - db_access=DB_ACLS; - else - db_access= (acl_get(thd->host,thd->ip, thd->priv_user,dbname,0) | - thd->master_access); - if (!(db_access & DB_ACLS) && (!grant_option || check_grant_db(thd,dbname))) - { - net_printf(thd,ER_DBACCESS_DENIED_ERROR, - thd->priv_user, - thd->host_or_ip, - dbname); - mysql_log.write(thd,COM_INIT_DB,ER(ER_DBACCESS_DENIED_ERROR), - thd->priv_user, - thd->host_or_ip, - dbname); - DBUG_RETURN(1); - } -#endif - - (void) sprintf(path,"%s/%s",mysql_data_home, dbname); - length=unpack_dirname(path,path); // Convert if not unix - found_libchar= 0; - if (length && path[length-1] == FN_LIBCHAR) - { - found_libchar= 1; - path[length-1]=0; // remove ending '\' - } - if (access(path,F_OK)) - { - net_printf(thd,ER_BAD_DB_ERROR,dbname); - DBUG_RETURN(1); - } - if (found_libchar) - path[length-1]= FN_LIBCHAR; - strmov(path+length, MY_DB_OPT_FILE); - load_db_opt(thd, path, &create); - - List<Item> field_list; - field_list.push_back(new Item_empty_string("Database",NAME_LEN)); - field_list.push_back(new Item_empty_string("Create Database",1024)); - - if (protocol->send_fields(&field_list,1)) - DBUG_RETURN(1); - - protocol->prepare_for_resend(); - protocol->store(dbname, strlen(dbname), system_charset_info); - to= strxmov(path, "CREATE DATABASE ", NullS); - if (create_options & HA_LEX_CREATE_IF_NOT_EXISTS) - to= strxmov(to,"/*!32312 IF NOT EXISTS*/ ", NullS); - to=strxmov(to,"`",dbname,"`", NullS); - - if (create.default_table_charset) - { - int cl= (create.default_table_charset->state & MY_CS_PRIMARY) ? 0 : 1; - to= strxmov(to," /*!40100" - " DEFAULT CHARACTER SET ",create.default_table_charset->csname, - cl ? " COLLATE " : "", - cl ? create.default_table_charset->name : "", - " */",NullS); - } - protocol->store(path, (uint) (to-path), system_charset_info); - - if (protocol->write()) - DBUG_RETURN(1); - send_eof(thd); - DBUG_RETURN(0); -} diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 22cb11eed41..1fa216fdb58 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -43,7 +43,6 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, SQL_LIST *order, if ((open_and_lock_tables(thd, table_list))) DBUG_RETURN(-1); - fix_tables_pointers(thd->lex->all_selects_list); table= table_list->table; table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK); thd->proc_info="init"; @@ -159,7 +158,7 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, SQL_LIST *order, !thd->net.report_error) { // thd->net.report_error is tested to disallow delete row on error - if (!(select && select->skipp_record())&& !thd->net.report_error ) + if (!(select && select->skip_record())&& !thd->net.report_error ) { if (!(error=table->file->delete_row(table->record[0]))) { diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index e8f1c5d87de..0e04316a2e7 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -25,6 +25,58 @@ #include "sql_select.h" #include "sql_acl.h" +static int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *s, + TABLE_LIST *t); + +/* + Resolve derived tables in all queries + + SYNOPSIS + mysql_handle_derived() + lex LEX for this thread + + RETURN + 0 ok + -1 Error + 1 Error and error message given +*/ + +int +mysql_handle_derived(LEX *lex) +{ + if (lex->derived_tables) + { + for (SELECT_LEX *sl= lex->all_selects_list; + sl; + sl= sl->next_select_in_list()) + { + for (TABLE_LIST *cursor= sl->get_table_list(); + cursor; + cursor= cursor->next) + { + int res; + if (cursor->derived && (res=mysql_derived(lex->thd, lex, + cursor->derived, + cursor))) + { + return res; + } + } + if (lex->describe) + { + /* + Force join->join_tmp creation, because we will use this JOIN + twice for EXPLAIN and we have to have unchanged join for EXPLAINing + */ + sl->uncacheable|= UNCACHEABLE_EXPLAIN; + sl->master_unit()->uncacheable|= UNCACHEABLE_EXPLAIN; + } + } + } + return 0; +} + + /* Resolve derived tables in all queries @@ -49,9 +101,6 @@ Derived tables is stored in thd->derived_tables and freed in close_thread_tables() - TODO - Move creation of derived tables in open_and_lock_tables() - RETURN 0 ok 1 Error @@ -59,8 +108,8 @@ */ -int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, - TABLE_LIST *org_table_list) +static int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, + TABLE_LIST *org_table_list) { SELECT_LEX *first_select= unit->first_select(); TABLE *table; @@ -72,80 +121,39 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, bool is_subsel= first_select->first_inner_unit() ? 1: 0; SELECT_LEX *save_current_select= lex->current_select; DBUG_ENTER("mysql_derived"); - - /* - In create_total_list, derived tables have to be treated in case of - EXPLAIN, This is because unit/node is not deleted in that - case. Current code in this function has to be improved to - recognize better when this function is called from derived tables - and when from other functions. - */ - if ((is_union || is_subsel) && unit->create_total_list(thd, lex, &tables, 1)) - DBUG_RETURN(-1); + if (!(derived_result= new select_union(0))) + DBUG_RETURN(1); // out of memory + + // st_select_lex_unit::prepare correctly work for single select + if ((res= unit->prepare(thd, derived_result, 0))) + goto exit; + + + derived_result->tmp_table_param.init(); + derived_result->tmp_table_param.field_count= unit->types.elements; /* - We have to do access checks here as this code is executed before any - sql command is started to execute. + Temp table is created so that it hounours if UNION without ALL is to be + processed */ -#ifndef NO_EMBEDDED_ACCESS_CHECKS - if (tables) - res= check_table_access(thd,SELECT_ACL, tables,0); - else - res= check_access(thd, SELECT_ACL, any_db,0,0,0); - if (res) - DBUG_RETURN(1); -#endif - - if (!(res=open_and_lock_tables(thd,tables))) + if (!(table= create_tmp_table(thd, &derived_result->tmp_table_param, + unit->types, (ORDER*) 0, + is_union && !unit->union_option, 1, + (first_select->options | thd->options | + TMP_TABLE_ALL_COLUMNS), + HA_POS_ERROR, + org_table_list->alias))) { - if (is_union || is_subsel) - { - /* - The following code is a re-do of fix_tables_pointers() found - in sql_select.cc for UNION's within derived tables. The only - difference is in navigation, as in derived tables we care for - this level only. - - */ - fix_tables_pointers(unit); - } - - if (!(derived_result= new select_union(0))) - DBUG_RETURN(1); // out of memory + res= -1; + goto exit; + } + derived_result->set_table(table); - // st_select_lex_unit::prepare correctly work for single select - if ((res= unit->prepare(thd, derived_result))) - goto exit; - - /* - This is done in order to redo all field optimisations when any of the - involved tables is used in the outer query - */ - if (tables) - { - for (TABLE_LIST *cursor= tables; cursor; cursor= cursor->next) - cursor->table->clear_query_id= 1; - } - - derived_result->tmp_table_param.init(); - derived_result->tmp_table_param.field_count= unit->types.elements; - /* - Temp table is created so that it hounours if UNION without ALL is to be - processed - */ - if (!(table= create_tmp_table(thd, &derived_result->tmp_table_param, - unit->types, (ORDER*) 0, - is_union && !unit->union_option, 1, - (first_select->options | thd->options | - TMP_TABLE_ALL_COLUMNS), - HA_POS_ERROR, - org_table_list->alias))) - { - res= -1; - goto exit; - } - derived_result->set_table(table); + if (is_union) + res= mysql_union(thd, lex, derived_result, unit); + else + { unit->offset_limit_cnt= first_select->offset_limit; unit->select_limit_cnt= first_select->select_limit+ first_select->offset_limit; @@ -154,57 +162,50 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, if (unit->select_limit_cnt == HA_POS_ERROR) first_select->options&= ~OPTION_FOUND_ROWS; - if (is_union) - res= mysql_union(thd, lex, derived_result, unit); + lex->current_select= first_select; + res= mysql_select(thd, &first_select->ref_pointer_array, + (TABLE_LIST*) first_select->table_list.first, + first_select->with_wild, + first_select->item_list, first_select->where, + (first_select->order_list.elements+ + first_select->group_list.elements), + (ORDER *) first_select->order_list.first, + (ORDER *) first_select->group_list.first, + first_select->having, (ORDER*) NULL, + (first_select->options | thd->options | + SELECT_NO_UNLOCK), + derived_result, unit, first_select); + } + + if (!res) + { + /* + Here we entirely fix both TABLE_LIST and list of SELECT's as + there were no derived tables + */ + if (derived_result->flush()) + res= 1; else - res= mysql_select(thd, &first_select->ref_pointer_array, - (TABLE_LIST*) first_select->table_list.first, - first_select->with_wild, - first_select->item_list, first_select->where, - (first_select->order_list.elements+ - first_select->group_list.elements), - (ORDER *) first_select->order_list.first, - (ORDER *) first_select->group_list.first, - first_select->having, (ORDER*) NULL, - (first_select->options | thd->options | - SELECT_NO_UNLOCK), - derived_result, unit, first_select); - - if (!res) { - /* - Here we entirely fix both TABLE_LIST and list of SELECT's as - there were no derived tables - */ - if (derived_result->flush()) - res= 1; - else + org_table_list->real_name= table->real_name; + org_table_list->table= table; + if (org_table_list->table_list) { - org_table_list->real_name=table->real_name; - org_table_list->table=table; - table->derived_select_number= first_select->select_number; - table->tmp_table= TMP_TABLE; + org_table_list->table_list->real_name= table->real_name; + org_table_list->table_list->table= table; + } + table->derived_select_number= first_select->select_number; + table->tmp_table= TMP_TABLE; #ifndef NO_EMBEDDED_ACCESS_CHECKS - org_table_list->grant.privilege= SELECT_ACL; + table->grant.privilege= SELECT_ACL; #endif - if (lex->describe) - { - // to fix a problem in EXPLAIN - if (tables) - { - for (TABLE_LIST *cursor= tables; cursor; cursor= cursor->next) - if (cursor->table_list) - cursor->table_list->table=cursor->table; - } - } - else - unit->exclude_tree(); - org_table_list->db= (char *)""; - // Force read of table stats in the optimizer - table->file->info(HA_STATUS_VARIABLE); - } + org_table_list->db= (char *)""; + // Force read of table stats in the optimizer + table->file->info(HA_STATUS_VARIABLE); } + if (!lex->describe) + unit->cleanup(); if (res) free_tmp_table(thd, table); else @@ -217,7 +218,6 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, exit: delete derived_result; lex->current_select= save_current_select; - close_thread_tables(thd, 0, 1); } DBUG_RETURN(res); } diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index 405cfdb5bdc..897aa37ba11 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -48,7 +48,8 @@ static TABLE **find_table_ptr_by_name(THD *thd,const char *db, int mysql_ha_open(THD *thd, TABLE_LIST *tables) { HANDLER_TABLES_HACK(thd); - int err=open_tables(thd,tables); + uint counter; + int err=open_tables(thd, tables, &counter); HANDLER_TABLES_HACK(thd); if (err) return -1; diff --git a/sql/sql_help.cc b/sql/sql_help.cc index c40133c04a8..3c98b7b0bb4 100644 --- a/sql/sql_help.cc +++ b/sql/sql_help.cc @@ -274,9 +274,9 @@ int get_topics_for_keyword(THD *thd, TABLE *topics, TABLE *relations, DBUG_ENTER("get_topics_for_keyword"); - if ((iindex_topic= find_type((char*) "PRIMARY", + if ((iindex_topic= find_type((char*) primary_key_name, &topics->keynames, 1+2)-1)<0 || - (iindex_relations= find_type((char*) "PRIMARY", + (iindex_relations= find_type((char*) primary_key_name, &relations->keynames, 1+2)-1)<0) { send_error(thd,ER_CORRUPT_HELP_DB); @@ -686,7 +686,7 @@ int mysqld_help(THD *thd, const char *mask) goto end; } /* Init tables and fields to be usable from items */ - setup_tables(tables); + setup_tables(tables, 0); memcpy((char*) used_fields, (char*) init_used_fields, sizeof(used_fields)); if (init_fields(thd, tables, used_fields, array_elements(used_fields))) { diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 010ebc3b798..3a7e2a8d285 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -81,7 +81,7 @@ check_insert_fields(THD *thd,TABLE *table,List<Item> &fields, table_list.grant=table->grant; thd->dupp_field=0; - if (setup_tables(&table_list) || + if (setup_tables(&table_list, 0) || setup_fields(thd, 0, &table_list,fields,1,0,0)) return -1; if (thd->dupp_field) @@ -175,7 +175,6 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, res= open_and_lock_tables(thd, table_list); if (res) DBUG_RETURN(-1); - fix_tables_pointers(thd->lex->all_selects_list); table= table_list->table; thd->proc_info="init"; @@ -185,13 +184,14 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, if (duplic == DUP_UPDATE && !table->insert_values) { /* it should be allocated before Item::fix_fields() */ - table->insert_values=(byte *)alloc_root(&table->mem_root, table->rec_buff_length); + table->insert_values= + (byte *)alloc_root(&thd->mem_root, table->rec_buff_length); if (!table->insert_values) goto abort; } if (check_insert_fields(thd,table,fields,*values,1) || - setup_tables(insert_table_list) || + setup_tables(insert_table_list, 0) || setup_fields(thd, 0, insert_table_list, *values, 0, 0, 0) || (duplic == DUP_UPDATE && (setup_fields(thd, 0, insert_table_list, update_fields, 0, 0, 0) || @@ -633,7 +633,8 @@ public: thd.command=COM_DELAYED_INSERT; thd.lex->current_select= 0; /* for my_message_sql */ - bzero((char*) &thd.net,sizeof(thd.net)); // Safety + bzero((char*) &thd.net, sizeof(thd.net)); // Safety + bzero((char*) &table_list, sizeof(table_list)); // Safety thd.system_thread= SYSTEM_THREAD_DELAYED_INSERT; thd.host_or_ip= ""; bzero((char*) &info,sizeof(info)); diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index b0381ae1d30..58dc334b86e 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -130,6 +130,8 @@ LEX *lex_start(THD *thd, uchar *buf,uint length) lex->select_lex.expr_list.empty(); lex->select_lex.ftfunc_list_alloc.empty(); lex->select_lex.ftfunc_list= &lex->select_lex.ftfunc_list_alloc; + lex->select_lex.group_list.empty(); + lex->select_lex.order_list.empty(); lex->current_select= &lex->select_lex; lex->yacc_yyss=lex->yacc_yyvs=0; lex->ignore_space=test(thd->variables.sql_mode & MODE_IGNORE_SPACE); @@ -687,13 +689,24 @@ int yylex(void *arg, void *yythd) case MY_LEX_USER_VARIABLE_DELIMITER: { - char delim= c; // Used char + uint double_quotes= 0; + char quote_char= c; // Used char lex->tok_start=lex->ptr; // Skip first ` #ifdef USE_MB if (use_mb(cs)) { - while ((c=yyGet()) && c != delim && c != (uchar) NAMES_SEP_CHAR) + while ((c= yyGet())) { + if (c == quote_char) + { + if (yyPeek() != quote_char) + break; + c= yyGet(); + double_quotes++; + continue; + } + if (c == (uchar) NAMES_SEP_CHAR) + break; if (my_mbcharlen(cs, c) > 1) { int l; @@ -704,13 +717,10 @@ int yylex(void *arg, void *yythd) lex->ptr += l-1; } } - yylval->lex_str=get_token(lex,yyLength()); } else #endif { - uint double_quotes= 0; - char quote_char= c; while ((c=yyGet())) { if (c == quote_char) @@ -724,13 +734,13 @@ int yylex(void *arg, void *yythd) if (c == (uchar) NAMES_SEP_CHAR) break; } - if (double_quotes) - yylval->lex_str=get_quoted_token(lex,yyLength() - double_quotes, - quote_char); - else - yylval->lex_str=get_token(lex,yyLength()); } - if (c == delim) + if (double_quotes) + yylval->lex_str=get_quoted_token(lex,yyLength() - double_quotes, + quote_char); + else + yylval->lex_str=get_token(lex,yyLength()); + if (c == quote_char) yySkip(); // Skip end ` lex->next_state= MY_LEX_START; return(IDENT_QUOTED); @@ -1008,6 +1018,7 @@ void st_select_lex_unit::init_query() union_result= 0; table= 0; fake_select_lex= 0; + cleaned= 0; } void st_select_lex::init_query() @@ -1197,7 +1208,6 @@ void st_select_lex_unit::exclude_level() */ void st_select_lex_unit::exclude_tree() { - SELECT_LEX_UNIT *units= 0; for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select()) { // unlink current level from global SELECTs list @@ -1244,11 +1254,6 @@ void st_select_lex::mark_as_dependent(SELECT_LEX *last) s->uncacheable|= UNCACHEABLE_DEPENDENT; SELECT_LEX_UNIT *munit= s->master_unit(); munit->uncacheable|= UNCACHEABLE_DEPENDENT; - //Tables will be reopened many times - for (TABLE_LIST *tbl= s->get_table_list(); - tbl; - tbl= tbl->next) - tbl->shared= 1; } } @@ -1312,12 +1317,10 @@ bool st_select_lex::test_limit() !0 - error */ bool st_select_lex_unit::create_total_list(THD *thd_arg, st_lex *lex, - TABLE_LIST **result_arg, - bool check_derived) + TABLE_LIST **result_arg) { *result_arg= 0; - res= create_total_list_n_last_return(thd_arg, lex, &result_arg, - check_derived); + res= create_total_list_n_last_return(thd_arg, lex, &result_arg); return res; } @@ -1329,8 +1332,7 @@ bool st_select_lex_unit::create_total_list(THD *thd_arg, st_lex *lex, thd THD pointer lex pointer on LEX stricture result pointer on pointer on result list of tables pointer - check_derived force derived table chacking (used for creating - table list for derived query) + DESCRIPTION This is used for UNION & subselect to create a new table list of all used tables. @@ -1344,8 +1346,7 @@ bool st_select_lex_unit::create_total_list(THD *thd_arg, st_lex *lex, bool st_select_lex_unit:: create_total_list_n_last_return(THD *thd_arg, st_lex *lex, - TABLE_LIST ***result_arg, - bool check_derived) + TABLE_LIST ***result_arg) { TABLE_LIST *slave_list_first=0, **slave_list_last= &slave_list_first; TABLE_LIST **new_table_list= *result_arg, *aux; @@ -1371,15 +1372,12 @@ create_total_list_n_last_return(THD *thd_arg, return 1; } - if (sl->linkage == DERIVED_TABLE_TYPE && !check_derived) - goto end; - for (SELECT_LEX_UNIT *inner= sl->first_inner_unit(); inner; inner= inner->next_unit()) { if (inner->create_total_list_n_last_return(thd, lex, - &slave_list_last, 0)) + &slave_list_last)) return 1; } @@ -1426,63 +1424,75 @@ end: return 0; } + st_select_lex_unit* st_select_lex_unit::master_unit() { return this; } + st_select_lex* st_select_lex_unit::outer_select() { return (st_select_lex*) master; } + bool st_select_lex::add_order_to_list(THD *thd, Item *item, bool asc) { return add_to_list(thd, order_list, item, asc); } + bool st_select_lex::add_item_to_list(THD *thd, Item *item) { return item_list.push_back(item); } + bool st_select_lex::add_group_to_list(THD *thd, Item *item, bool asc) { return add_to_list(thd, group_list, item, asc); } + bool st_select_lex::add_ftfunc_to_list(Item_func_match *func) { return !func || ftfunc_list->push_back(func); // end of memory? } + st_select_lex_unit* st_select_lex::master_unit() { return (st_select_lex_unit*) master; } + st_select_lex* st_select_lex::outer_select() { return (st_select_lex*) master->get_master(); } + bool st_select_lex::set_braces(bool value) { braces= value; return 0; } + bool st_select_lex::inc_in_sum_expr() { in_sum_expr++; return 0; } + uint st_select_lex::get_in_sum_expr() { return in_sum_expr; } + TABLE_LIST* st_select_lex::get_table_list() { return (TABLE_LIST*) table_list.first; @@ -1493,21 +1503,25 @@ List<Item>* st_select_lex::get_item_list() return &item_list; } + List<String>* st_select_lex::get_use_index() { return use_index_ptr; } + List<String>* st_select_lex::get_ignore_index() { return ignore_index_ptr; } + ulong st_select_lex::get_table_join_options() { return table_join_options; } + bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num) { if (ref_pointer_array) @@ -1519,6 +1533,58 @@ bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num) order_group_num)* 5)) == 0; } + +/* + Find db.table which will be updated in this unit + + SYNOPSIS + st_select_lex_unit::check_updateable() + db - data base name + table - real table name + + RETURN + 1 - found + 0 - OK (table did not found) +*/ +bool st_select_lex_unit::check_updateable(char *db, char *table) +{ + for(SELECT_LEX *sl= first_select(); sl; sl= sl->next_select()) + if (sl->check_updateable(db, table)) + return 1; + return 0; +} + + +/* + Find db.table which will be updated in this select and + underlayed ones (except derived tables) + + SYNOPSIS + st_select_lex::check_updateable() + db - data base name + table - real table name + + RETURN + 1 - found + 0 - OK (table did not found) +*/ +bool st_select_lex::check_updateable(char *db, char *table) +{ + if (find_real_table_in_list(get_table_list(), db, table)) + return 1; + + for (SELECT_LEX_UNIT *un= first_inner_unit(); + un; + un= un->next_unit()) + { + if (un->first_select()->linkage != DERIVED_TABLE_TYPE && + un->check_updateable(db, table)) + return 1; + } + return 0; +} + + void st_select_lex_unit::print(String *str) { for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select()) @@ -1561,6 +1627,7 @@ void st_select_lex::print_order(String *str, ORDER *order) } } + void st_select_lex::print_limit(THD *thd, String *str) { if (!thd) diff --git a/sql/sql_lex.h b/sql/sql_lex.h index fb7d8415e91..50b8f322731 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -243,6 +243,7 @@ public: UNCACHEABLE_DEPENDENT UNCACHEABLE_RAND UNCACHEABLE_SIDEEFFECT + UNCACHEABLE_EXPLAIN */ uint8 uncacheable; enum sub_select_type linkage; @@ -315,7 +316,8 @@ protected: ulong found_rows_for_union; bool prepared, // prepare phase already performed for UNION (unit) optimized, // optimize phase already performed for UNION (unit) - executed; // already executed + executed, // already executed + cleaned; public: // list of fields which points to temporary table for union @@ -347,8 +349,7 @@ public: uint union_option; void init_query(); - bool create_total_list(THD *thd, st_lex *lex, TABLE_LIST **result, - bool check_current_derived); + bool create_total_list(THD *thd, st_lex *lex, TABLE_LIST **result); st_select_lex_unit* master_unit(); st_select_lex* outer_select(); st_select_lex* first_select() { return (st_select_lex*) slave; } @@ -362,18 +363,19 @@ public: void exclude_tree(); /* UNION methods */ - int prepare(THD *thd, select_result *result); + int prepare(THD *thd, select_result *result, ulong additional_options); int exec(); int cleanup(); + bool check_updateable(char *db, char *table); void print(String *str); + friend void mysql_init_query(THD *thd, bool lexonly); friend int subselect_union_engine::exec(); private: bool create_total_list_n_last_return(THD *thd, st_lex *lex, - TABLE_LIST ***result, - bool check_current_derived); + TABLE_LIST ***result); }; typedef class st_select_lex_unit SELECT_LEX_UNIT; @@ -510,6 +512,7 @@ public: init_select(); } bool setup_ref_array(THD *thd, uint order_group_num); + bool check_updateable(char *db, char *table); void print(THD *thd, String *str); static void print_order(String *str, ORDER *order); void print_limit(THD *thd, String *str); @@ -596,7 +599,7 @@ typedef struct st_lex uint param_count; uint slave_thd_opt; uint8 describe; - bool drop_primary, drop_if_exists, drop_temporary, local_file; + bool drop_if_exists, drop_temporary, local_file; bool in_comment, ignore_space, verbose, simple_alter, no_write_to_binlog; bool derived_tables; bool safe_to_cache_query; diff --git a/sql/sql_list.h b/sql/sql_list.h index 592173c36da..8faa7109174 100644 --- a/sql/sql_list.h +++ b/sql/sql_list.h @@ -21,6 +21,12 @@ /* mysql standard class memoryallocator */ +#ifdef PEDANTIC_SAFEMALLOC +#define TRASH(XX,YY) bfill((XX), (YY), 0x8F) +#else +#define TRASH(XX,YY) /* no-op */ +#endif + class Sql_alloc { public: @@ -34,8 +40,8 @@ public: } static void *operator new(size_t size, MEM_ROOT *mem_root) { return (void*) alloc_root(mem_root, (uint) size); } - static void operator delete(void *ptr, size_t size) {} /*lint -e715 */ - static void operator delete[](void *ptr, size_t size) {} + static void operator delete(void *ptr, size_t size) { TRASH(ptr, size); } + static void operator delete[](void *ptr, size_t size) { TRASH(ptr, size); } #ifdef HAVE_purify bool dummy; inline Sql_alloc() :dummy(0) {} diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 2f8a979b5ee..f128601d281 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -123,7 +123,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, else { // Part field list thd->dupp_field=0; - if (setup_tables(table_list) || + if (setup_tables(table_list, 0) || setup_fields(thd, 0, table_list, fields, 1, 0, 0)) DBUG_RETURN(-1); if (thd->dupp_field) diff --git a/sql/sql_olap.cc b/sql/sql_olap.cc index ef7bf013be8..efc4cf0921d 100644 --- a/sql/sql_olap.cc +++ b/sql/sql_olap.cc @@ -143,18 +143,6 @@ int handle_olaps(LEX *lex, SELECT_LEX *select_lex) int count=select_lex->group_list.elements; int sl_return=0; -// a fix for UNION's - for (TABLE_LIST *cursor= (TABLE_LIST *)select_lex->table_list.first; - cursor; - cursor=cursor->next) - { - if (cursor->do_redirect) - { - //Sinisa TODO: there are function for this purpose: fix_tables_pointers - cursor->table= cursor->table_list->table; - cursor->do_redirect= 0; - } - } lex->last_selects=select_lex; @@ -164,7 +152,7 @@ int handle_olaps(LEX *lex, SELECT_LEX *select_lex) List<Item> all_fields(select_lex->item_list); - if (setup_tables((TABLE_LIST *)select_lex->table_list.first) || + if (setup_tables((TABLE_LIST *)select_lex->table_list.first, 0) || setup_fields(lex->thd, 0, (TABLE_LIST *)select_lex->table_list.first, select_lex->item_list, 1, &all_fields,1) || setup_fields(lex->thd, 0, (TABLE_LIST *)select_lex->table_list.first, diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 5a06e835d88..7a0ddc3c5c8 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -846,6 +846,7 @@ static int check_connection(THD *thd) char *passwd= strend(user)+1; char *db= passwd; char db_buff[NAME_LEN+1]; // buffer to store db in utf8 + char user_buff[USERNAME_LENGTH+1]; // buffer to store user in utf8 /* Old clients send null-terminated string as password; new clients send the size (1 byte) + string (not null-terminated). Hence in case of empty @@ -866,6 +867,14 @@ static int check_connection(THD *thd) db= db_buff; } + if (user) + { + user_buff[copy_and_convert(user_buff, sizeof(user_buff)-1, + system_charset_info, user, strlen(user), + thd->charset())]= '\0'; + user= user_buff; + } + if (thd->user) x_free(thd->user); if (!(thd->user= my_strdup(user, MYF(0)))) @@ -986,6 +995,7 @@ pthread_handler_decl(handle_one_connection,arg) thd->proc_info=0; thd->set_time(); + thd->init_for_queries(); while (!net->error && net->vio != 0 && !(thd->killed == THD::KILL_CONNECTION)) { if (do_command(thd)) @@ -1065,6 +1075,7 @@ extern "C" pthread_handler_decl(handle_bootstrap,arg) thd->priv_user=thd->user=(char*) my_strdup("boot", MYF(MY_WME)); buff= (char*) thd->net.buff; + thd->init_for_queries(); while (fgets(buff, thd->net.max_packet, file)) { uint length=(uint) strlen(buff); @@ -1109,7 +1120,7 @@ end: void free_items(Item *item) { for (; item ; item=item->next) - delete item; + item->delete_self(); } /* This works because items are allocated with sql_alloc() */ @@ -1625,9 +1636,11 @@ bool dispatch_command(enum enum_server_command command, THD *thd, switch (command) { case MYSQL_OPTION_MULTI_STATEMENTS_ON: thd->client_capabilities|= CLIENT_MULTI_STATEMENTS; + send_eof(thd); break; case MYSQL_OPTION_MULTI_STATEMENTS_OFF: thd->client_capabilities&= ~CLIENT_MULTI_STATEMENTS; + send_eof(thd); break; default: send_error(thd, ER_UNKNOWN_COM_ERROR); @@ -1796,34 +1809,9 @@ mysql_execute_command(THD *thd) #endif } #endif /* !HAVE_REPLICATION */ - /* - TODO: make derived tables processing 'inside' SELECT processing. - TODO: solve problem with depended derived tables in subselects - */ - if (lex->derived_tables) - { - for (SELECT_LEX *sl= lex->all_selects_list; - sl; - sl= sl->next_select_in_list()) - { - for (TABLE_LIST *cursor= sl->get_table_list(); - cursor; - cursor= cursor->next) - { - if (cursor->derived && (res=mysql_derived(thd, lex, - cursor->derived, - cursor))) - { - if (res < 0 || thd->net.report_error) - send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN : 0); - DBUG_RETURN(res); - } - } - } - } if (&lex->select_lex != lex->all_selects_list && lex->sql_command != SQLCOM_CREATE_TABLE && - lex->unit.create_total_list(thd, lex, &tables, 0)) + lex->unit.create_total_list(thd, lex, &tables)) DBUG_RETURN(0); /* @@ -1882,7 +1870,6 @@ mysql_execute_command(THD *thd) } else thd->send_explain_fields(result); - fix_tables_pointers(lex->all_selects_list); res= mysql_explain_union(thd, &thd->lex->unit, result); MYSQL_LOCK *save_lock= thd->lock; thd->lock= (MYSQL_LOCK *)0; @@ -1906,10 +1893,6 @@ mysql_execute_command(THD *thd) if (!(result=new select_send())) { res= -1; -#ifdef DELETE_ITEMS - delete select_lex->having; - delete select_lex->where; -#endif break; } } @@ -1925,7 +1908,6 @@ mysql_execute_command(THD *thd) (res= open_and_lock_tables(thd,tables)))) break; - fix_tables_pointers(lex->all_selects_list); res= mysql_do(thd, *lex->insert_list); if (thd->net.report_error) res= -1; @@ -2134,7 +2116,7 @@ mysql_execute_command(THD *thd) lex->select_lex.table_list.first= (byte*) (tables); create_table->next= 0; if (&lex->select_lex != lex->all_selects_list && - lex->unit.create_total_list(thd, lex, &tables, 0)) + lex->unit.create_total_list(thd, lex, &tables)) DBUG_RETURN(-1); ulong want_priv= ((lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) ? @@ -2326,7 +2308,7 @@ mysql_execute_command(THD *thd) lex->key_list, lex->drop_list, lex->alter_list, select_lex->order_list.elements, (ORDER *) select_lex->order_list.first, - lex->drop_primary, lex->duplicates, + lex->duplicates, lex->alter_keys_onoff, lex->tablespace_op, lex->simple_alter); @@ -2349,6 +2331,8 @@ mysql_execute_command(THD *thd) if (grant_option) { TABLE_LIST old_list,new_list; + bzero((char*) &old_list, sizeof(old_list)); + bzero((char*) &new_list, sizeof(new_list)); // Safety old_list=table[0]; new_list=table->next[0]; old_list.next=new_list.next=0; @@ -2471,7 +2455,7 @@ mysql_execute_command(THD *thd) tables, lex->create_list, lex->key_list, lex->drop_list, lex->alter_list, 0, (ORDER *) 0, - 0, DUP_ERROR); + DUP_ERROR); } else res = mysql_optimize_table(thd, tables, &lex->check_opt); @@ -2669,15 +2653,21 @@ mysql_execute_command(THD *thd) table_count++; /* All tables in aux_tables must be found in FROM PART */ TABLE_LIST *walk; - for (walk=(TABLE_LIST*) tables ; walk ; walk=walk->next) + for (walk= (TABLE_LIST*) tables; walk; walk= walk->next) { - if (!strcmp(auxi->real_name,walk->real_name) && - !strcmp(walk->db,auxi->db)) + if (!strcmp(auxi->real_name, walk->alias) && + !strcmp(walk->db, auxi->db)) break; } if (!walk) { - net_printf(thd,ER_NONUNIQ_TABLE,auxi->real_name); + net_printf(thd, ER_NONUNIQ_TABLE, auxi->real_name); + goto error; + } + if (walk->derived) + { + net_printf(thd, ER_NON_UPDATABLE_TABLE, + auxi->real_name, "DELETE"); goto error; } walk->lock_type= auxi->lock_type; @@ -2693,21 +2683,27 @@ mysql_execute_command(THD *thd) break; /* Fix tables-to-be-deleted-from list to point at opened tables */ for (auxi=(TABLE_LIST*) aux_tables ; auxi ; auxi=auxi->next) - auxi->table= auxi->table_list->table; - if (&lex->select_lex != lex->all_selects_list) { - for (TABLE_LIST *t= select_lex->get_table_list(); - t; t= t->next) + auxi->table= auxi->table_list->table; + /* + Multi-delete can't be constructed over-union => we always have + single SELECT on top and have to check underlaying SELECTs of it + */ + for (SELECT_LEX_UNIT *un= lex->select_lex.first_inner_unit(); + un; + un= un->next_unit()) { - if (find_real_table_in_list(t->table_list->next, t->db, t->real_name)) + if (un->first_select()->linkage != DERIVED_TABLE_TYPE && + un->check_updateable(auxi->table_list->db, + auxi->table_list->real_name)) { - my_error(ER_UPDATE_TABLE_USED, MYF(0), t->real_name); + my_error(ER_UPDATE_TABLE_USED, MYF(0), auxi->table_list->real_name); res= -1; break; } } } - fix_tables_pointers(lex->all_selects_list); + if (!thd->is_fatal_error && (result= new multi_delete(thd,aux_tables, table_count))) { @@ -2952,7 +2948,6 @@ mysql_execute_command(THD *thd) if (tables && ((res= check_table_access(thd, SELECT_ACL, tables,0)) || (res= open_and_lock_tables(thd,tables)))) break; - fix_tables_pointers(lex->all_selects_list); if (!(res= sql_set_variables(thd, &lex->var_list))) send_ok(thd); if (thd->net.report_error) @@ -4147,7 +4142,7 @@ mysql_parse(THD *thd, char *inBuf, uint length) else { mysql_execute_command(thd); - query_cache_end_of_result(&thd->net); + query_cache_end_of_result(thd); } } } diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 165e1bf28c9..43bf3e3651c 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -680,7 +680,7 @@ static bool mysql_test_upd_fields(Prepared_statement *stmt, #endif if (open_and_lock_tables(thd, table_list)) DBUG_RETURN(1); - if (setup_tables(table_list) || + if (setup_tables(table_list, 0) || setup_fields(thd, 0, table_list, fields, 1, 0, 0) || setup_conds(thd, table_list, &conds) || thd->net.report_error) DBUG_RETURN(1); @@ -734,7 +734,7 @@ static bool mysql_test_select_fields(Prepared_statement *stmt, DBUG_RETURN(1); #endif if ((&lex->select_lex != lex->all_selects_list && - lex->unit.create_total_list(thd, lex, &tables, 0))) + lex->unit.create_total_list(thd, lex, &tables))) DBUG_RETURN(1); if (open_and_lock_tables(thd, tables)) @@ -747,7 +747,6 @@ static bool mysql_test_select_fields(Prepared_statement *stmt, } else { - fix_tables_pointers(lex->all_selects_list); if (!result && !(result= new select_send())) { send_error(thd, ER_OUT_OF_RESOURCES); @@ -757,7 +756,8 @@ static bool mysql_test_select_fields(Prepared_statement *stmt, JOIN *join= new JOIN(thd, fields, select_options, result); thd->used_tables= 0; // Updated by setup_fields - if (join->prepare(&select_lex->ref_pointer_array, tables, + if (join->prepare(&select_lex->ref_pointer_array, + (TABLE_LIST*)select_lex->get_table_list(), wild_num, conds, og_num, order, group, having, proc, select_lex, unit)) DBUG_RETURN(1); @@ -926,6 +926,7 @@ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length) sl->prep_where= sl->where; } + cleanup_items(thd->free_list); stmt->set_statement(thd); thd->set_statement(&thd->stmt_backup); @@ -983,14 +984,10 @@ void mysql_stmt_execute(THD *thd, char *packet) DBUG_VOID_RETURN; } - /* - XXX: while thd->query_id is incremented for each command, stmt->query_id - holds query_id of prepare stage. Keeping old query_id seems to be more - natural, but differs from the way prepared statements work in 4.1: - */ - /* stmt->query_id= thd->query_id; */ + stmt->query_id= thd->query_id; thd->stmt_backup.set_statement(thd); thd->set_statement(stmt); + thd->free_list= 0; /* To make sure that all runtime data is stored in its own memory root and @@ -1014,6 +1011,13 @@ void mysql_stmt_execute(THD *thd, char *packet) if (sl->prep_where) sl->where= sl->prep_where->copy_andor_structure(thd); DBUG_ASSERT(sl->join == 0); + ORDER *order; + /* Fix GROUP list */ + for (order=(ORDER *)sl->group_list.first ; order ; order=order->next) + order->item= (Item **)(order+1); + /* Fix ORDER list */ + for (order=(ORDER *)sl->order_list.first ; order ; order=order->next) + order->item= (Item **)(order+1); } /* @@ -1050,6 +1054,8 @@ void mysql_stmt_execute(THD *thd, char *packet) if (!(specialflag & SPECIAL_NO_PRIOR)) my_pthread_setprio(pthread_self(), WAIT_PRIOR); + free_items(thd->free_list); + cleanup_items(stmt->free_list); free_root(&thd->mem_root, MYF(0)); thd->set_statement(&thd->stmt_backup); DBUG_VOID_RETURN; @@ -1201,7 +1207,7 @@ Prepared_statement::Prepared_statement(THD *thd_arg) #ifndef EMBEDDED_LIBRARY setup_params= insert_params; // not fully qualified query #else - setup_params_data= setup_params_data; + setup_params_data= ::setup_params_data; #endif } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 9f26d7458d0..6df2917a959 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -24,8 +24,6 @@ #include "mysql_priv.h" #include "sql_select.h" -#include "opt_ft.h" - #include <m_ctype.h> #include <hash.h> #include <ft_global.h> @@ -83,7 +81,7 @@ static int do_select(JOIN *join,List<Item> *fields,TABLE *tmp_table, Procedure *proc); static int sub_select_cache(JOIN *join,JOIN_TAB *join_tab,bool end_of_records); static int sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records); -static int flush_cached_records(JOIN *join,JOIN_TAB *join_tab,bool skipp_last); +static int flush_cached_records(JOIN *join,JOIN_TAB *join_tab,bool skip_last); static int end_send(JOIN *join, JOIN_TAB *join_tab, bool end_of_records); static int end_send_group(JOIN *join, JOIN_TAB *join_tab,bool end_of_records); static int end_write(JOIN *join, JOIN_TAB *join_tab, bool end_of_records); @@ -176,7 +174,6 @@ int handle_select(THD *thd, LEX *lex, select_result *result) register SELECT_LEX *select_lex = &lex->select_lex; DBUG_ENTER("handle_select"); - fix_tables_pointers(lex->all_selects_list); if (select_lex->next_select()) res=mysql_union(thd, lex, result, &lex->unit); else @@ -303,7 +300,7 @@ JOIN::prepare(Item ***rref_pointer_array, /* Check that all tables, fields, conds and order are ok */ - if (setup_tables(tables_list) || + if (setup_tables(tables_list, 0) || setup_wild(thd, tables_list, fields_list, &all_fields, wild_num) || select_lex->setup_ref_array(thd, og_num) || setup_fields(thd, (*rref_pointer_array), tables_list, fields_list, 1, @@ -862,8 +859,10 @@ JOIN::optimize() as in other cases the join is done before the sort. */ if (const_tables != tables && - (order || group_list) && join_tab[const_tables].type != JT_ALL && + (order || group_list) && + join_tab[const_tables].type != JT_ALL && join_tab[const_tables].type != JT_FT && + join_tab[const_tables].type != JT_REF_OR_NULL && (order && simple_order || group_list && simple_group)) { if (add_ref_to_table_cond(thd,&join_tab[const_tables])) @@ -1017,7 +1016,7 @@ JOIN::reinit() if (unit->select_limit_cnt == HA_POS_ERROR) select_lex->options&= ~OPTION_FOUND_ROWS; - if (setup_tables(tables_list)) + if (setup_tables(tables_list, 1)) DBUG_RETURN(1); /* Reset of sum functions */ @@ -1513,12 +1512,7 @@ JOIN::cleanup() JOIN_TAB *tab, *end; for (tab= join_tab, end= tab+tables ; tab != end ; tab++) { - delete tab->select; - delete tab->quick; - tab->select=0; - tab->quick=0; - x_free(tab->cache.buff); - tab->cache.buff= 0; + tab->cleanup(); } } tmp_join->tmp_join= 0; @@ -1582,13 +1576,14 @@ mysql_select(THD *thd, Item ***rref_pointer_array, goto err; } } - free_join= 0; } + free_join= 0; join->select_options= select_options; } else { - join= new JOIN(thd, fields, select_options, result); + if (!(join= new JOIN(thd, fields, select_options, result))) + DBUG_RETURN(-1); thd->proc_info="init"; thd->used_tables=0; // Updated by setup_fields if (join->prepare(rref_pointer_array, tables, wild_num, @@ -1649,8 +1644,8 @@ static ha_rows get_quick_record_count(THD *thd, SQL_SELECT *select, { select->head=table; table->reginfo.impossible_range=0; - if ((error=select->test_quick_select(thd, *(key_map *)keys,(table_map) 0,limit)) - == 1) + if ((error=select->test_quick_select(thd, *(key_map *)keys,(table_map) 0, + limit)) == 1) DBUG_RETURN(select->quick->records); if (error == -1) { @@ -2132,7 +2127,7 @@ merge_key_fields(KEY_FIELD *start,KEY_FIELD *new_fields,KEY_FIELD *end, */ static void -add_key_field(KEY_FIELD **key_fields,uint and_level, +add_key_field(KEY_FIELD **key_fields,uint and_level, COND *cond, Field *field,bool eq_func,Item **value, uint num_values, table_map usable_tables) { @@ -2199,6 +2194,17 @@ add_key_field(KEY_FIELD **key_fields,uint and_level, (*value)->result_type() != STRING_RESULT && field->cmp_type() != (*value)->result_type()) return; + + /* + We can't use indexes if the effective collation + of the operation differ from the field collation. + */ + if (field->result_type() == STRING_RESULT && + (*value)->result_type() == STRING_RESULT && + field->cmp_type() == STRING_RESULT && + ((Field_str*)field)->charset() != cond->compare_collation()) + return; + } } DBUG_ASSERT(num_values == 1); @@ -2262,7 +2268,7 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level, // BETWEEN or IN if (cond_func->key_item()->real_item()->type() == Item::FIELD_ITEM && !(cond_func->used_tables() & OUTER_REF_TABLE_BIT)) - add_key_field(key_fields,*and_level, + add_key_field(key_fields,*and_level,cond_func, ((Item_field*) (cond_func->key_item()->real_item()))-> field, 0, cond_func->arguments()+1, cond_func->argument_count()-1, @@ -2276,7 +2282,7 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level, if (cond_func->arguments()[0]->real_item()->type() == Item::FIELD_ITEM && !(cond_func->arguments()[0]->used_tables() & OUTER_REF_TABLE_BIT)) { - add_key_field(key_fields,*and_level, + add_key_field(key_fields,*and_level,cond_func, ((Item_field*) (cond_func->arguments()[0])->real_item()) ->field, equal_func, @@ -2286,7 +2292,7 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level, cond_func->functype() != Item_func::LIKE_FUNC && !(cond_func->arguments()[1]->used_tables() & OUTER_REF_TABLE_BIT)) { - add_key_field(key_fields,*and_level, + add_key_field(key_fields,*and_level,cond_func, ((Item_field*) (cond_func->arguments()[1])->real_item()) ->field, equal_func, @@ -2302,7 +2308,7 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level, Item *tmp=new Item_null; if (!tmp) // Should never be true return; - add_key_field(key_fields,*and_level, + add_key_field(key_fields,*and_level,cond_func, ((Item_field*) (cond_func->arguments()[0])->real_item()) ->field, cond_func->functype() == Item_func::ISNULL_FUNC, @@ -2690,22 +2696,35 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count, do { uint keypart=keyuse->keypart; - uint found_part_ref_or_null= KEY_OPTIMIZE_REF_OR_NULL; + table_map best_part_found_ref= 0; + double best_prev_record_reads= DBL_MAX; do { if (!(rest_tables & keyuse->used_tables) && !(found_ref_or_null & keyuse->optimize)) { found_part|=keyuse->keypart_map; - found_ref|= keyuse->used_tables; + double tmp= prev_record_reads(join, + (found_ref | + keyuse->used_tables)); + if (tmp < best_prev_record_reads) + { + best_part_found_ref= keyuse->used_tables; + best_prev_record_reads= tmp; + } if (rec > keyuse->ref_table_rows) rec= keyuse->ref_table_rows; - found_part_ref_or_null&= keyuse->optimize; + /* + If there is one 'key_column IS NULL' expression, we can + use this ref_or_null optimsation of this field + */ + found_ref_or_null|= (keyuse->optimize & + KEY_OPTIMIZE_REF_OR_NULL); } keyuse++; - found_ref_or_null|= found_part_ref_or_null; } while (keyuse->table == table && keyuse->key == key && keyuse->keypart == keypart); + found_ref|= best_part_found_ref; } while (keyuse->table == table && keyuse->key == key); /* @@ -3258,7 +3277,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse, { /* Must read with repeat */ j->type= null_ref_key ? JT_REF_OR_NULL : JT_REF; - j->null_ref_key= null_ref_key; + j->ref.null_ref_key= null_ref_key; } else if (ref_key == j->ref.key_copy) { @@ -3738,6 +3757,41 @@ bool error_if_full_join(JOIN *join) /* + cleanup JOIN_TAB + + SYNOPSIS + JOIN_TAB::cleanup() +*/ + +void JOIN_TAB::cleanup() +{ + delete select; + select= 0; + delete quick; + quick= 0; + x_free(cache.buff); + cache.buff= 0; + if (table) + { + if (table->key_read) + { + table->key_read= 0; + table->file->extra(HA_EXTRA_NO_KEYREAD); + } + /* Don't free index if we are using read_record */ + if (!read_record.table) + table->file->index_end(); + /* + We need to reset this for next select + (Tested in part_of_refkey) + */ + table->reginfo.join_tab= 0; + } + end_read_record(&read_record); +} + + +/* Free resources of given join SYNOPSIS @@ -3771,11 +3825,6 @@ JOIN::join_free(bool full) { if (tab->table) { - if (tab->table->key_read) - { - tab->table->key_read= 0; - tab->table->file->extra(HA_EXTRA_NO_KEYREAD); - } /* Don't free index if we are using read_record */ if (!tab->read_record.table) tab->table->file->index_end(); @@ -3786,29 +3835,7 @@ JOIN::join_free(bool full) { for (tab= join_tab, end= tab+tables; tab != end; tab++) { - delete tab->select; - delete tab->quick; - tab->select=0; - tab->quick=0; - x_free(tab->cache.buff); - tab->cache.buff= 0; - if (tab->table) - { - if (tab->table->key_read) - { - tab->table->key_read= 0; - tab->table->file->extra(HA_EXTRA_NO_KEYREAD); - } - /* Don't free index if we are using read_record */ - if (!tab->read_record.table) - tab->table->file->index_end(); - /* - We need to reset this for next select - (Tested in part_of_refkey) - */ - tab->table->reginfo.join_tab= 0; - } - end_read_record(&tab->read_record); + tab->cleanup(); } table= 0; } @@ -4385,17 +4412,9 @@ remove_eq_conds(COND *cond,Item::cond_result *cond_value) { Item *new_item=remove_eq_conds(item,&tmp_cond_value); if (!new_item) - { -#ifdef DELETE_ITEMS - delete item; // This may be shared -#endif li.remove(); - } else if (item != new_item) { -#ifdef DELETE_ITEMS - delete item; // This may be shared -#endif VOID(li.replace(new_item)); should_fix_fields=1; } @@ -5747,14 +5766,14 @@ sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records) static int -flush_cached_records(JOIN *join,JOIN_TAB *join_tab,bool skipp_last) +flush_cached_records(JOIN *join,JOIN_TAB *join_tab,bool skip_last) { int error; READ_RECORD *info; if (!join_tab->cache.records) return 0; /* Nothing to do */ - if (skipp_last) + if (skip_last) (void) store_record_in_cache(&join_tab->cache); // Must save this for later if (join_tab->use_quick == 2) { @@ -5788,21 +5807,21 @@ flush_cached_records(JOIN *join,JOIN_TAB *join_tab,bool skipp_last) } SQL_SELECT *select=join_tab->select; if (!error && (!join_tab->cache.select || - !join_tab->cache.select->skipp_record())) + !join_tab->cache.select->skip_record())) { uint i; reset_cache(&join_tab->cache); - for (i=(join_tab->cache.records- (skipp_last ? 1 : 0)) ; i-- > 0 ;) + for (i=(join_tab->cache.records- (skip_last ? 1 : 0)) ; i-- > 0 ;) { read_cached_record(join_tab); - if (!select || !select->skipp_record()) + if (!select || !select->skip_record()) if ((error=(join_tab->next_select)(join,join_tab+1,0)) < 0) return error; /* purecov: inspected */ } } } while (!(error=info->read_record(info))); - if (skipp_last) + if (skip_last) read_cached_record(join_tab); // Restore current record reset_cache(&join_tab->cache); join_tab->cache.records=0; join_tab->cache.ptr_record= (uint) ~0; @@ -6209,12 +6228,12 @@ join_read_always_key_or_null(JOIN_TAB *tab) int res; /* First read according to key which is NOT NULL */ - *tab->null_ref_key=0; + *tab->ref.null_ref_key= 0; // Clear null byte if ((res= join_read_always_key(tab)) >= 0) return res; /* Then read key with null value */ - *tab->null_ref_key= 1; + *tab->ref.null_ref_key= 1; // Set null byte return safe_index_read(tab); } @@ -6228,10 +6247,10 @@ join_read_next_same_or_null(READ_RECORD *info) JOIN_TAB *tab= info->table->reginfo.join_tab; /* Test if we have already done a read after null key */ - if (*tab->null_ref_key) + if (*tab->ref.null_ref_key) return -1; // All keys read - *tab->null_ref_key= 1; // Read null key - return safe_index_read(tab); + *tab->ref.null_ref_key= 1; // Set null byte + return safe_index_read(tab); // then read null keys } @@ -7204,8 +7223,9 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order, For impossible ranges (like when doing a lookup on NULL on a NOT NULL field, quick will contain an empty record set. */ - if (!(select->quick=get_ft_or_quick_select_for_ref(tab->join->thd, - table, tab))) + if (!(select->quick= tab->type == JT_FT ? + new FT_SELECT(thd, table, tab->ref.key) : + get_quick_select_for_ref(thd, table, &tab->ref))) goto err; } } @@ -7213,9 +7233,12 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order, table->file->info(HA_STATUS_VARIABLE); // Get record count table->sort.found_records=filesort(thd, table,sortorder, length, select, filesort_limit, &examined_rows); - tab->records=table->sort.found_records; // For SQL_CALC_ROWS - delete select; // filesort did select - tab->select=0; + tab->records= table->sort.found_records; // For SQL_CALC_ROWS + if (select) + { + select->cleanup(); // filesort did select + tab->select= 0; + } tab->select_cond=0; tab->type=JT_ALL; // Read with normal read_record tab->read_first_record= join_init_read_record; @@ -8297,7 +8320,7 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param, if (pos->type() == Item::FIELD_ITEM) { Item_field *item; - if (!(item= new Item_field(thd, *((Item_field*) pos)))) + if (!(item= new Item_field(thd, ((Item_field*) pos)))) goto err; pos= item; if (item->field->flags & BLOB_FLAG) @@ -9198,20 +9221,23 @@ int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result) sl; sl= sl->next_select()) { + // drop UNCACHEABLE_EXPLAIN, because it is for internal usage only + uint8 uncacheable= (sl->uncacheable & ~UNCACHEABLE_EXPLAIN); + res= mysql_explain_select(thd, sl, (((&thd->lex->select_lex)==sl)? - ((thd->lex->all_selects_list != sl)?"PRIMARY": - "SIMPLE"): + ((thd->lex->all_selects_list != sl) ? + primary_key_name : "SIMPLE"): ((sl == first)? ((sl->linkage == DERIVED_TABLE_TYPE) ? "DERIVED": - ((sl->uncacheable & UNCACHEABLE_DEPENDENT)? + ((uncacheable & UNCACHEABLE_DEPENDENT) ? "DEPENDENT SUBQUERY": - (sl->uncacheable?"UNCACHEABLE SUBQUERY": + (uncacheable?"UNCACHEABLE SUBQUERY": "SUBQUERY"))): - ((sl->uncacheable & UNCACHEABLE_DEPENDENT)? + ((uncacheable & UNCACHEABLE_DEPENDENT) ? "DEPENDENT UNION": - sl->uncacheable?"UNCACHEABLE UNION": + uncacheable?"UNCACHEABLE UNION": "UNION"))), result); if (res) diff --git a/sql/sql_select.h b/sql/sql_select.h index 9bba4e9318e..e1fc5d1c1fe 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -46,6 +46,8 @@ typedef struct st_table_ref store_key **key_copy; // Item **items; // val()'s for each keypart table_map depend_map; // Table depends on these tables. + byte *null_ref_key; // null byte position in the key_buf. + // used for REF_OR_NULL optimization. } TABLE_REF; /* @@ -88,7 +90,6 @@ typedef struct st_join_table { QUICK_SELECT_I *quick; Item *on_expr; const char *info; - byte *null_ref_key; int (*read_first_record)(struct st_join_table *tab); int (*next_select)(JOIN *,struct st_join_table *,bool); READ_RECORD read_record; @@ -107,6 +108,8 @@ typedef struct st_join_table { TABLE_REF ref; JOIN_CACHE cache; JOIN *join; + + void cleanup(); } JOIN_TAB; @@ -431,7 +434,6 @@ public: bool cp_buffer_from_ref(TABLE_REF *ref); bool error_if_full_join(JOIN *join); -void relink_tables(SELECT_LEX *select_lex); int report_error(TABLE *table, int error); int safe_index_read(JOIN_TAB *tab); COND *eliminate_not_funcs(COND *cond); diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 3dfef4b7189..3a5f260bf0f 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -519,7 +519,7 @@ int mysqld_extend_show_tables(THD *thd,const char *db,const char *wild) protocol->store_null(); // Send error to Comment field protocol->store(thd->net.last_error, system_charset_info); - thd->net.last_error[0]=0; + thd->clear_error(); } else { @@ -812,6 +812,94 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list) DBUG_RETURN(0); } +int mysqld_show_create_db(THD *thd, char *dbname, + HA_CREATE_INFO *create_info) +{ + int length; + char path[FN_REFLEN]; + char buff[2048]; + String buffer(buff, sizeof(buff), system_charset_info); + uint db_access; + bool found_libchar; + HA_CREATE_INFO create; + uint create_options = create_info ? create_info->options : 0; + Protocol *protocol=thd->protocol; + DBUG_ENTER("mysql_show_create_db"); + + if (check_db_name(dbname)) + { + net_printf(thd,ER_WRONG_DB_NAME, dbname); + DBUG_RETURN(1); + } + +#ifndef NO_EMBEDDED_ACCESS_CHECKS + if (test_all_bits(thd->master_access,DB_ACLS)) + db_access=DB_ACLS; + else + db_access= (acl_get(thd->host,thd->ip, thd->priv_user,dbname,0) | + thd->master_access); + if (!(db_access & DB_ACLS) && (!grant_option || check_grant_db(thd,dbname))) + { + net_printf(thd,ER_DBACCESS_DENIED_ERROR, + thd->priv_user, thd->host_or_ip, dbname); + mysql_log.write(thd,COM_INIT_DB,ER(ER_DBACCESS_DENIED_ERROR), + thd->priv_user, thd->host_or_ip, dbname); + DBUG_RETURN(1); + } +#endif + + (void) sprintf(path,"%s/%s",mysql_data_home, dbname); + length=unpack_dirname(path,path); // Convert if not unix + found_libchar= 0; + if (length && path[length-1] == FN_LIBCHAR) + { + found_libchar= 1; + path[length-1]=0; // remove ending '\' + } + if (access(path,F_OK)) + { + net_printf(thd,ER_BAD_DB_ERROR,dbname); + DBUG_RETURN(1); + } + if (found_libchar) + path[length-1]= FN_LIBCHAR; + strmov(path+length, MY_DB_OPT_FILE); + load_db_opt(thd, path, &create); + + List<Item> field_list; + field_list.push_back(new Item_empty_string("Database",NAME_LEN)); + field_list.push_back(new Item_empty_string("Create Database",1024)); + + if (protocol->send_fields(&field_list,1)) + DBUG_RETURN(1); + + protocol->prepare_for_resend(); + protocol->store(dbname, strlen(dbname), system_charset_info); + buffer.length(0); + buffer.append("CREATE DATABASE ", 16); + if (create_options & HA_LEX_CREATE_IF_NOT_EXISTS) + buffer.append("/*!32312 IF NOT EXISTS*/ ", 25); + append_identifier(thd, &buffer, dbname, strlen(dbname)); + + if (create.default_table_charset) + { + buffer.append(" /*!40100", 9); + buffer.append(" DEFAULT CHARACTER SET ", 23); + buffer.append(create.default_table_charset->csname); + if (!(create.default_table_charset->state & MY_CS_PRIMARY)) + { + buffer.append(" COLLATE ", 9); + buffer.append(create.default_table_charset->name); + } + buffer.append(" */", 3); + } + protocol->store(buffer.ptr(), buffer.length(), buffer.charset()); + + if (protocol->write()) + DBUG_RETURN(1); + send_eof(thd); + DBUG_RETURN(0); +} int mysqld_show_logs(THD *thd) @@ -997,6 +1085,19 @@ mysqld_dump_create_info(THD *thd, TABLE *table, int fd) DBUG_RETURN(0); } +/* possible TODO: call find_keyword() from sql_lex.cc here */ +static bool require_quotes(const char *name, uint length) +{ + uint i, d, c; + for (i=0; i<length; i+=d) + { + c=((uchar *)name)[i]; + d=my_mbcharlen(system_charset_info, c); + if (d==1 && !system_charset_info->ident_map[c]) + return 1; + } + return 0; +} void append_identifier(THD *thd, String *packet, const char *name, uint length) @@ -1007,7 +1108,8 @@ append_identifier(THD *thd, String *packet, const char *name, uint length) else qtype= '`'; - if (thd->options & OPTION_QUOTE_SHOW_CREATE) + if ((thd->options & OPTION_QUOTE_SHOW_CREATE) || + require_quotes(name, length)) { packet->append(&qtype, 1); packet->append(name, length, system_charset_info); @@ -1167,7 +1269,7 @@ store_create_info(THD *thd, TABLE *table, String *packet) bool found_primary=0; packet->append(",\n ", 4); - if (i == primary_key && !strcmp(key_info->name,"PRIMARY")) + if (i == primary_key && !strcmp(key_info->name, primary_key_name)) { found_primary=1; packet->append("PRIMARY ", 8); @@ -1235,7 +1337,10 @@ store_create_info(THD *thd, TABLE *table, String *packet) packet->append("\n)", 2); if (!(thd->variables.sql_mode & MODE_NO_TABLE_OPTIONS) && !foreign_db_mode) { - packet->append(" ENGINE=", 8); + if (thd->variables.sql_mode & (MODE_MYSQL323 | MODE_MYSQL40)) + packet->append(" TYPE=", 6); + else + packet->append(" ENGINE=", 8); packet->append(file->table_type()); if (table->table_charset && diff --git a/sql/sql_string.cc b/sql/sql_string.cc index 61070f07266..093b85b46b7 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -24,6 +24,7 @@ #include <my_sys.h> #include <m_string.h> #include <m_ctype.h> +#include <assert.h> #ifdef HAVE_FCONVERT #include <floatingpoint.h> #endif @@ -228,15 +229,117 @@ bool String::copy(const char *str,uint32 arg_length, CHARSET_INFO *cs) return FALSE; } + +/* + Checks that the source string can be just copied to the destination string + without conversion. + + SYNPOSIS + + needs_conversion() + arg_length Length of string to copy. + from_cs Character set to copy from + to_cs Character set to copy to + uint32 *offset Returns number of unaligned characters. + + RETURN + 0 No conversion needed + 1 Either character set conversion or adding leading zeros + (e.g. for UCS-2) must be done +*/ + +bool String::needs_conversion(uint32 arg_length, + CHARSET_INFO *from_cs, + CHARSET_INFO *to_cs, + uint32 *offset) +{ + *offset= 0; + if ((to_cs == &my_charset_bin) || + (to_cs == from_cs) || + my_charset_same(from_cs, to_cs) || + ((from_cs == &my_charset_bin) && + (!(*offset=(arg_length % to_cs->mbminlen))))) + return FALSE; + return TRUE; +} + + +/* + Copy a multi-byte character sets with adding leading zeros. + + SYNOPSIS + + copy_aligned() + str String to copy + arg_length Length of string. This should NOT be dividable with + cs->mbminlen. + offset arg_length % cs->mb_minlength + cs Character set for 'str' + + NOTES + For real multi-byte, ascii incompatible charactser sets, + like UCS-2, add leading zeros if we have an incomplete character. + Thus, + SELECT _ucs2 0xAA + will automatically be converted into + SELECT _ucs2 0x00AA + + RETURN + 0 ok + 1 error +*/ + +bool String::copy_aligned(const char *str,uint32 arg_length, uint32 offset, + CHARSET_INFO *cs) +{ + /* How many bytes are in incomplete character */ + offset= cs->mbmaxlen - offset; /* How many zeros we should prepend */ + DBUG_ASSERT(offset && offset != cs->mbmaxlen); + + uint32 aligned_length= arg_length + offset; + if (alloc(aligned_length)) + return TRUE; + + /* + Note, this is only safe for little-endian UCS-2. + If we add big-endian UCS-2 sometimes, this code + will be more complicated. But it's OK for now. + */ + bzero((char*) Ptr, offset); + memcpy(Ptr + offset, str, arg_length); + Ptr[aligned_length]=0; + /* str_length is always >= 0 as arg_length is != 0 */ + str_length= aligned_length; + str_charset= cs; + return FALSE; +} + + +bool String::set_or_copy_aligned(const char *str,uint32 arg_length, + CHARSET_INFO *cs) +{ + /* How many bytes are in incomplete character */ + uint32 offset= (arg_length % cs->mbminlen); + + if (!offset) /* All characters are complete, just copy */ + { + set(str, arg_length, cs); + return FALSE; + } + return copy_aligned(str, arg_length, offset, cs); +} + /* Copy with charset convertion */ bool String::copy(const char *str, uint32 arg_length, CHARSET_INFO *from_cs, CHARSET_INFO *to_cs) { - if ((from_cs == &my_charset_bin) || (to_cs == &my_charset_bin)) - { - return copy(str, arg_length, &my_charset_bin); - } + uint32 offset; + if (!needs_conversion(arg_length, from_cs, to_cs, &offset)) + return copy(str, arg_length, to_cs); + if ((from_cs == &my_charset_bin) && offset) + return copy_aligned(str, arg_length, offset, to_cs); + uint32 new_length= to_cs->mbmaxlen*arg_length; if (alloc(new_length)) return TRUE; @@ -434,7 +537,7 @@ int String::strstr(const String &s,uint32 offset) register const char *search=s.ptr(); const char *end=Ptr+str_length-s.length()+1; const char *search_end=s.ptr()+s.length(); -skipp: +skip: while (str != end) { if (*str++ == *search) @@ -442,7 +545,7 @@ skipp: register char *i,*j; i=(char*) str; j=(char*) search+1; while (j != search_end) - if (*i++ != *j++) goto skipp; + if (*i++ != *j++) goto skip; return (int) (str-Ptr) -1; } } @@ -466,7 +569,7 @@ int String::strstr_case(const String &s,uint32 offset) register const char *search=s.ptr(); const char *end=Ptr+str_length-s.length()+1; const char *search_end=s.ptr()+s.length(); -skipp: +skip: while (str != end) { if (str_charset->sort_order[*str++] == str_charset->sort_order[*search]) @@ -476,7 +579,7 @@ skipp: while (j != search_end) if (str_charset->sort_order[*i++] != str_charset->sort_order[*j++]) - goto skipp; + goto skip; return (int) (str-Ptr) -1; } } @@ -499,7 +602,7 @@ int String::strrstr(const String &s,uint32 offset) const char *end=Ptr+s.length()-2; const char *search_end=s.ptr()-1; -skipp: +skip: while (str != end) { if (*str-- == *search) @@ -507,7 +610,7 @@ skipp: register char *i,*j; i=(char*) str; j=(char*) search-1; while (j != search_end) - if (*i-- != *j--) goto skipp; + if (*i-- != *j--) goto skip; return (int) (i-Ptr) +1; } } @@ -657,7 +760,8 @@ copy_and_convert(char *to, uint32 to_length, CHARSET_INFO *to_cs, while (1) { - if ((cnvres=from_cs->cset->mb_wc(from_cs, &wc, (uchar*) from, from_end)) > 0) + if ((cnvres= from_cs->cset->mb_wc(from_cs, &wc, (uchar*) from, + from_end)) > 0) from+= cnvres; else if (cnvres == MY_CS_ILSEQ) { diff --git a/sql/sql_string.h b/sql/sql_string.h index 325611737ca..163156fdfe2 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -183,6 +183,12 @@ public: bool copy(); // Alloc string if not alloced bool copy(const String &s); // Allocate new string bool copy(const char *s,uint32 arg_length, CHARSET_INFO *cs); // Allocate new string + static bool needs_conversion(uint32 arg_length, + CHARSET_INFO *cs_from, CHARSET_INFO *cs_to, + uint32 *offset); + bool copy_aligned(const char *s, uint32 arg_length, uint32 offset, + CHARSET_INFO *cs); + bool set_or_copy_aligned(const char *s, uint32 arg_length, CHARSET_INFO *cs); bool copy(const char*s,uint32 arg_length, CHARSET_INFO *csfrom, CHARSET_INFO *csto); bool append(const String &s); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index fe2cfcf2b41..c2f46c9999e 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -29,7 +29,7 @@ #include <io.h> #endif -static const char *primary_key_name="PRIMARY"; +const char *primary_key_name= "PRIMARY"; static bool check_if_keyname_exists(const char *name,KEY *start, KEY *end); static char *make_unique_key_name(const char *field_name,KEY *start,KEY *end); @@ -506,6 +506,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, blob_columns++; break; case FIELD_TYPE_GEOMETRY: +#ifdef HAVE_SPATIAL if (!(file->table_flags() & HA_HAS_GEOMETRY)) { my_printf_error(ER_CHECK_NOT_IMPLEMENTED, ER(ER_CHECK_NOT_IMPLEMENTED), @@ -521,6 +522,11 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, sql_field->unireg_check=Field::BLOB_FIELD; blob_columns++; break; +#else + my_printf_error(ER_FEATURE_DISABLED,ER(ER_FEATURE_DISABLED), MYF(0), + sym_group_geom.name, sym_group_geom.needed_define); + DBUG_RETURN(-1); +#endif /*HAVE_SPATIAL*/ case FIELD_TYPE_VAR_STRING: case FIELD_TYPE_STRING: sql_field->pack_flag=0; @@ -654,8 +660,14 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, key_info->flags = HA_FULLTEXT; break; case Key::SPATIAL: +#ifdef HAVE_SPATIAL key_info->flags = HA_SPATIAL; break; +#else + my_printf_error(ER_FEATURE_DISABLED,ER(ER_FEATURE_DISABLED),MYF(0), + sym_group_geom.name, sym_group_geom.needed_define); + DBUG_RETURN(-1); +#endif case Key::FOREIGN_KEY: key_number--; // Skip this key continue; @@ -694,8 +706,10 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, DBUG_RETURN(-1); } } - else if (key_info->algorithm == HA_KEY_ALG_RTREE) + else + if (key_info->algorithm == HA_KEY_ALG_RTREE) { +#ifdef HAVE_RTREE_KEYS if ((key_info->key_parts & 1) == 1) { my_printf_error(ER_WRONG_ARGUMENTS, @@ -706,6 +720,11 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, my_printf_error(ER_NOT_SUPPORTED_YET, ER(ER_NOT_SUPPORTED_YET), MYF(0), "RTREE INDEX"); DBUG_RETURN(-1); +#else + my_printf_error(ER_FEATURE_DISABLED,ER(ER_FEATURE_DISABLED),MYF(0), + sym_group_rtree.name, sym_group_rtree.needed_define); + DBUG_RETURN(-1); +#endif } List_iterator<key_part_spec> cols(key->columns); @@ -775,6 +794,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, DBUG_RETURN(-1); } } +#ifdef HAVE_SPATIAL if (key->type == Key::SPATIAL) { if (!column->length ) @@ -786,6 +806,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, column->length=4*sizeof(double); } } +#endif if (!(sql_field->flags & NOT_NULL_FLAG)) { if (key->type == Key::PRIMARY) @@ -830,6 +851,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, DBUG_RETURN(-1); } } + /* TODO HF What's this for??? */ else if (f_is_geom(sql_field->pack_flag)) { } @@ -1930,7 +1952,6 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, List<Key> &keys,List<Alter_drop> &drop_list, List<Alter_column> &alter_list, uint order_num, ORDER *order, - bool drop_primary, enum enum_duplicates handle_duplicates, enum enum_enable_or_disable keys_onoff, enum tablespace_op_type tablespace_op, @@ -2138,7 +2159,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, def_it.rewind(); while ((def=def_it++)) { - if (def->change && + if (def->change && !my_strcasecmp(system_charset_info,field->field_name, def->change)) break; } @@ -2231,13 +2252,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, KEY *key_info=table->key_info; for (uint i=0 ; i < table->keys ; i++,key_info++) { - if (drop_primary && (key_info->flags & HA_NOSAME)) - { - drop_primary=0; - continue; - } - - char *key_name=key_info->name; + char *key_name= key_info->name; Alter_drop *drop; drop_it.rewind(); while ((drop=drop_it++)) @@ -2280,7 +2295,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, { // Check if sub key if (cfield->field->type() != FIELD_TYPE_BLOB && (cfield->field->pack_length() == key_part_length || - cfield->length <= key_part_length / + cfield->length <= key_part_length / key_part->field->charset()->mbmaxlen)) key_part_length=0; // Use whole field } @@ -2292,7 +2307,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, key_list.push_back(new Key(key_info->flags & HA_SPATIAL ? Key::SPATIAL : (key_info->flags & HA_NOSAME ? (!my_strcasecmp(system_charset_info, - key_name, "PRIMARY") ? + key_name, primary_key_name) ? Key::PRIMARY : Key::UNIQUE) : (key_info->flags & HA_FULLTEXT ? Key::FULLTEXT : Key::MULTIPLE)), diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc index 337f2540a39..6e8aae54b23 100644 --- a/sql/sql_udf.cc +++ b/sql/sql_udf.cc @@ -149,7 +149,7 @@ void udf_init() tables.lock_type = TL_READ; tables.db=new_thd->db; - if (open_and_lock_tables(new_thd, &tables)) + if (simple_open_n_lock_tables(new_thd, &tables)) { DBUG_PRINT("error",("Can't open udf table")); sql_print_error("Can't open mysql/func table"); diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 25620229844..75fd9be88bd 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -29,7 +29,7 @@ int mysql_union(THD *thd, LEX *lex, select_result *result, { DBUG_ENTER("mysql_union"); int res= 0; - if (!(res= unit->prepare(thd, result))) + if (!(res= unit->prepare(thd, result, SELECT_NO_UNLOCK))) res= unit->exec(); res|= unit->cleanup(); DBUG_RETURN(res); @@ -106,7 +106,8 @@ bool select_union::flush() } -int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result) +int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, + ulong additional_options) { SELECT_LEX *lex_select_save= thd_arg->lex->current_select; SELECT_LEX *sl, *first_select; @@ -145,8 +146,9 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result) for (;sl; sl= sl->next_select()) { + sl->options|= SELECT_NO_UNLOCK; JOIN *join= new JOIN(thd_arg, sl->item_list, - sl->options | thd_arg->options | SELECT_NO_UNLOCK, + sl->options | thd_arg->options | additional_options, tmp_result); thd_arg->lex->current_select= sl; offset_limit_cnt= sl->offset_limit; @@ -440,9 +442,16 @@ int st_select_lex_unit::cleanup() int error= 0; DBUG_ENTER("st_select_lex_unit::cleanup"); + if (cleaned) + { + DBUG_RETURN(0); + } + cleaned= 0; + if (union_result) { delete union_result; + union_result=0; // Safety if (table) free_tmp_table(thd, table); table= 0; // Safety diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 6b4d2f9b659..03ab3d01c1a 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -79,7 +79,6 @@ int mysql_update(THD *thd, if ((open_and_lock_tables(thd, table_list))) DBUG_RETURN(-1); thd->proc_info="init"; - fix_tables_pointers(thd->lex->all_selects_list); table= table_list->table; table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK); @@ -95,7 +94,7 @@ int mysql_update(THD *thd, tables.table= table; tables.alias= table_list->alias; - if (setup_tables(update_table_list) || + if (setup_tables(update_table_list, 0) || setup_conds(thd,update_table_list,&conds) || thd->lex->select_lex.setup_ref_array(thd, order_num) || setup_order(thd, thd->lex->select_lex.ref_pointer_array, @@ -253,7 +252,7 @@ int mysql_update(THD *thd, while (!(error=info.read_record(&info)) && !thd->killed) { - if (!(select && select->skipp_record())) + if (!(select && select->skip_record())) { table->file->position(table->record[0]); if (my_b_write(&tempfile,table->file->ref, @@ -310,7 +309,7 @@ int mysql_update(THD *thd, while (!(error=info.read_record(&info)) && !thd->killed) { - if (!(select && select->skipp_record())) + if (!(select && select->skip_record())) { store_record(table,record[1]); if (fill_record(fields,values, 0) || thd->net.report_error) @@ -440,16 +439,38 @@ int mysql_multi_update(THD *thd, #endif if ((res=open_and_lock_tables(thd,table_list))) DBUG_RETURN(res); - fix_tables_pointers(thd->lex->all_selects_list); select_lex->select_limit= HA_POS_ERROR; + + table_map item_tables= 0, derived_tables= 0; + if (thd->lex->derived_tables) + { + // Assign table map values to check updatability of derived tables + uint tablenr=0; + for (TABLE_LIST *table_list= (TABLE_LIST*) select_lex->table_list.first; + table_list; + table_list= table_list->next, tablenr++) + { + table_list->table->map= (table_map) 1 << tablenr; + } + } if (setup_fields(thd, 0, table_list, *fields, 1, 0, 0)) DBUG_RETURN(-1); + if (thd->lex->derived_tables) + { + // Find tables used in items + List_iterator_fast<Item> it(*fields); + Item *item; + while ((item= it++)) + { + item_tables|= item->used_tables(); + } + } /* Count tables and setup timestamp handling */ - for (tl= select_lex->get_table_list() ; tl ; tl=tl->next) + for (tl= select_lex->get_table_list() ; tl ; tl= tl->next) { TABLE *table= tl->table; if (table->timestamp_field) @@ -459,6 +480,21 @@ int mysql_multi_update(THD *thd, if (table->timestamp_field->query_id != thd->query_id) table->time_stamp= table->timestamp_field->offset() +1; } + if (tl->derived) + derived_tables|= table->map; + } + if (thd->lex->derived_tables && (item_tables & derived_tables)) + { + // find derived table which cause error + for (tl= select_lex->get_table_list() ; tl ; tl= tl->next) + { + if (tl->derived && (item_tables & tl->table->map)) + { + my_printf_error(ER_NON_UPDATABLE_TABLE, ER(ER_NON_UPDATABLE_TABLE), + MYF(0), tl->alias, "UPDATE"); + DBUG_RETURN(-1); + } + } } if (!(result=new multi_update(thd, table_list, fields, values, diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index f35b7f12fd1..7b8aa13e214 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -660,7 +660,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); udf_type if_exists opt_local opt_table_options table_options table_option opt_if_not_exists opt_no_write_to_binlog opt_var_type opt_var_ident_type delete_option opt_temporary all_or_any opt_distinct - opt_ignore_leaves fulltext_options + opt_ignore_leaves fulltext_options spatial_type %type <ulong_num> ULONG_NUM raid_types merge_insert_types @@ -677,8 +677,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); table_wild no_in_expr expr_expr simple_expr no_and_expr udf_expr using_list expr_or_default set_expr_or_default interval_expr param_marker singlerow_subselect singlerow_subselect_init + exists_subselect exists_subselect_init geometry_function signed_literal NUM_literal - exists_subselect exists_subselect_init sp_opt_default + sp_opt_default simple_ident_nospvar simple_ident_q %type <item_list> @@ -717,7 +718,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %type <ha_rkey_mode> handler_rkey_mode -%type <cast_type> cast_type cast_type_finalize +%type <cast_type> cast_type %type <udf_type> udf_func_type @@ -985,7 +986,7 @@ create: &tmp_table_alias : (LEX_STRING*) 0), TL_OPTION_UPDATING, - ((using_update_log)? + (using_update_log ? TL_READ_NO_INSERT: TL_READ))) YYABORT; @@ -2108,7 +2109,7 @@ create_table_options: create_table_option: ENGINE_SYM opt_equal storage_engines { Lex->create_info.db_type= $3; } - | TYPE_SYM opt_equal storage_engines { Lex->create_info.db_type= $3; WARN_DEPRECATED("TYPE=database_engine","ENGINE=database_engine"); } + | TYPE_SYM opt_equal storage_engines { Lex->create_info.db_type= $3; WARN_DEPRECATED("TYPE=storage_engine","ENGINE=storage_engine"); } | MAX_ROWS opt_equal ulonglong_num { Lex->create_info.max_rows= $3; Lex->create_info.used_fields|= HA_CREATE_USED_MAX_ROWS;} | MIN_ROWS opt_equal ulonglong_num { Lex->create_info.min_rows= $3; Lex->create_info.used_fields|= HA_CREATE_USED_MIN_ROWS;} | AVG_ROW_LENGTH opt_equal ULONG_NUM { Lex->create_info.avg_row_length=$3; Lex->create_info.used_fields|= HA_CREATE_USED_AVG_ROW_LENGTH;} @@ -2328,30 +2329,19 @@ type: $$=FIELD_TYPE_TINY_BLOB; } | BLOB_SYM opt_len { Lex->charset=&my_charset_bin; $$=FIELD_TYPE_BLOB; } - | GEOMETRY_SYM { Lex->charset=&my_charset_bin; - Lex->uint_geom_type= (uint) Field::GEOM_GEOMETRY; - $$=FIELD_TYPE_GEOMETRY; } - | GEOMETRYCOLLECTION { Lex->charset=&my_charset_bin; - Lex->uint_geom_type= (uint) Field::GEOM_GEOMETRYCOLLECTION; - $$=FIELD_TYPE_GEOMETRY; } - | POINT_SYM { Lex->charset=&my_charset_bin; - Lex->uint_geom_type= (uint) Field::GEOM_POINT; - $$=FIELD_TYPE_GEOMETRY; } - | MULTIPOINT { Lex->charset=&my_charset_bin; - Lex->uint_geom_type= (uint) Field::GEOM_MULTIPOINT; - $$=FIELD_TYPE_GEOMETRY; } - | LINESTRING { Lex->charset=&my_charset_bin; - Lex->uint_geom_type= (uint) Field::GEOM_LINESTRING; - $$=FIELD_TYPE_GEOMETRY; } - | MULTILINESTRING { Lex->charset=&my_charset_bin; - Lex->uint_geom_type= (uint) Field::GEOM_MULTILINESTRING; - $$=FIELD_TYPE_GEOMETRY; } - | POLYGON { Lex->charset=&my_charset_bin; - Lex->uint_geom_type= (uint) Field::GEOM_POLYGON; - $$=FIELD_TYPE_GEOMETRY; } - | MULTIPOLYGON { Lex->charset=&my_charset_bin; - Lex->uint_geom_type= (uint) Field::GEOM_MULTIPOLYGON; - $$=FIELD_TYPE_GEOMETRY; } + | spatial_type { +#ifdef HAVE_SPATIAL + Lex->charset=&my_charset_bin; + Lex->uint_geom_type= (uint)$1; + $$=FIELD_TYPE_GEOMETRY; +#else + net_printf(Lex->thd, ER_FEATURE_DISABLED, + ER(ER_FEATURE_DISABLED), + sym_group_geom.name, + sym_group_geom.needed_define); + YYABORT; +#endif + } | MEDIUMBLOB { Lex->charset=&my_charset_bin; $$=FIELD_TYPE_MEDIUM_BLOB; } | LONGBLOB { Lex->charset=&my_charset_bin; @@ -2390,6 +2380,17 @@ type: } ; +spatial_type: + GEOMETRY_SYM { $$= Field::GEOM_GEOMETRY; } + | GEOMETRYCOLLECTION { $$= Field::GEOM_GEOMETRYCOLLECTION; } + | POINT_SYM { $$= Field::GEOM_POINT; } + | MULTIPOINT { $$= Field::GEOM_MULTIPOINT; } + | LINESTRING { $$= Field::GEOM_LINESTRING; } + | MULTILINESTRING { $$= Field::GEOM_MULTILINESTRING; } + | POLYGON { $$= Field::GEOM_POLYGON; } + | MULTIPOLYGON { $$= Field::GEOM_MULTIPOLYGON; } + ; + char: CHAR_SYM {} ; @@ -2620,23 +2621,30 @@ delete_option: key_type: key_or_index { $$= Key::MULTIPLE; } - | FULLTEXT_SYM { $$= Key::FULLTEXT; } - | FULLTEXT_SYM key_or_index { $$= Key::FULLTEXT; } - | SPATIAL_SYM { $$= Key::SPATIAL; } - | SPATIAL_SYM key_or_index { $$= Key::SPATIAL; }; + | FULLTEXT_SYM opt_key_or_index { $$= Key::FULLTEXT; } + | SPATIAL_SYM opt_key_or_index + { +#ifdef HAVE_SPATIAL + $$= Key::SPATIAL; +#else + net_printf(Lex->thd, ER_FEATURE_DISABLED, + ER(ER_FEATURE_DISABLED), + sym_group_geom.name, sym_group_geom.needed_define); + YYABORT; +#endif + }; constraint_key_type: PRIMARY_SYM KEY_SYM { $$= Key::PRIMARY; } - | UNIQUE_SYM { $$= Key::UNIQUE; } - | UNIQUE_SYM key_or_index { $$= Key::UNIQUE; }; + | UNIQUE_SYM opt_key_or_index { $$= Key::UNIQUE; }; key_or_index: KEY_SYM {} | INDEX {}; -opt_keys_or_index: +opt_key_or_index: /* empty */ {} - | keys_or_index + | key_or_index ; keys_or_index: @@ -2648,7 +2656,17 @@ opt_unique_or_fulltext: /* empty */ { $$= Key::MULTIPLE; } | UNIQUE_SYM { $$= Key::UNIQUE; } | FULLTEXT_SYM { $$= Key::FULLTEXT;} - | SPATIAL_SYM { $$= Key::SPATIAL; } + | SPATIAL_SYM + { +#ifdef HAVE_SPATIAL + $$= Key::SPATIAL; +#else + net_printf(Lex->thd, ER_FEATURE_DISABLED, + ER(ER_FEATURE_DISABLED), + sym_group_geom.name, sym_group_geom.needed_define); + YYABORT; +#endif + } ; key_alg: @@ -2658,7 +2676,10 @@ key_alg: opt_btree_or_rtree: BTREE_SYM { $$= HA_KEY_ALG_BTREE; } - | RTREE_SYM { $$= HA_KEY_ALG_RTREE; } + | RTREE_SYM + { + $$= HA_KEY_ALG_RTREE; + } | HASH_SYM { $$= HA_KEY_ALG_HASH; }; key_list: @@ -2695,7 +2716,6 @@ alter: if (!lex->select_lex.add_table_to_list(thd, $4, NULL, TL_OPTION_UPDATING)) YYABORT; - lex->drop_primary=0; lex->create_list.empty(); lex->key_list.empty(); lex->col_list.empty(); @@ -2797,12 +2817,14 @@ alter_list_item: lex->drop_list.push_back(new Alter_drop(Alter_drop::COLUMN, $3.str)); lex->simple_alter=0; } + | DROP FOREIGN KEY_SYM opt_ident { Lex->simple_alter=0; } | DROP PRIMARY_SYM KEY_SYM { LEX *lex=Lex; - lex->drop_primary=1; lex->simple_alter=0; + lex->drop_list.push_back(new Alter_drop(Alter_drop::KEY, + primary_key_name)); + lex->simple_alter=0; } - | DROP FOREIGN KEY_SYM opt_ident { Lex->simple_alter=0; } | DROP key_or_index field_ident { LEX *lex=Lex; @@ -2859,7 +2881,6 @@ opt_to: /* SLAVE START and SLAVE STOP are deprecated. We keep them for compatibility. - To use UNTIL, one must use START SLAVE, not SLAVE START. */ slave: @@ -2870,6 +2891,7 @@ slave: lex->type = 0; /* We'll use mi structure for UNTIL options */ bzero((char*) &lex->mi, sizeof(lex->mi)); + /* If you change this code don't forget to update SLAVE START too */ } slave_until {} @@ -2878,13 +2900,18 @@ slave: LEX *lex=Lex; lex->sql_command = SQLCOM_SLAVE_STOP; lex->type = 0; + /* If you change this code don't forget to update SLAVE STOP too */ } | SLAVE START_SYM slave_thread_opts { LEX *lex=Lex; lex->sql_command = SQLCOM_SLAVE_START; lex->type = 0; - } + /* We'll use mi structure for UNTIL options */ + bzero((char*) &lex->mi, sizeof(lex->mi)); + } + slave_until + {} | SLAVE STOP_SYM slave_thread_opts { LEX *lex=Lex; @@ -3150,7 +3177,7 @@ cache_keys_spec: cache_key_list_or_empty: /* empty */ { Lex->select_lex.use_index_ptr= 0; } - | opt_keys_or_index '(' key_usage_list2 ')' + | opt_key_or_index '(' key_usage_list2 ')' { SELECT_LEX *sel= &Lex->select_lex; sel->use_index_ptr= &sel->use_index; @@ -3224,10 +3251,9 @@ select_init2: select_part2: { - LEX *lex=Lex; - SELECT_LEX * sel= lex->current_select; - if (lex->current_select == &lex->select_lex) - lex->lock_option= TL_READ; /* Only for global SELECT */ + LEX *lex= Lex; + SELECT_LEX *sel= lex->current_select; + lex->lock_option= TL_READ; if (sel->linkage != UNION_TYPE) mysql_init_select(lex); lex->current_select->parsing_place= SELECT_LEX_NODE::SELECT_LIST; @@ -3617,13 +3643,53 @@ simple_expr: | VALUES '(' simple_ident ')' { $$= new Item_insert_value($3); } | FUNC_ARG0 '(' ')' - { $$= ((Item*(*)(void))($1.symbol->create_func))();} + { + if (!$1.symbol->create_func) + { + net_printf(Lex->thd, ER_FEATURE_DISABLED, + ER(ER_FEATURE_DISABLED), + $1.symbol->group->name, + $1.symbol->group->needed_define); + YYABORT; + } + $$= ((Item*(*)(void))($1.symbol->create_func))(); + } | FUNC_ARG1 '(' expr ')' - { $$= ((Item*(*)(Item*))($1.symbol->create_func))($3);} + { + if (!$1.symbol->create_func) + { + net_printf(Lex->thd, ER_FEATURE_DISABLED, + ER(ER_FEATURE_DISABLED), + $1.symbol->group->name, + $1.symbol->group->needed_define); + YYABORT; + } + $$= ((Item*(*)(Item*))($1.symbol->create_func))($3); + } | FUNC_ARG2 '(' expr ',' expr ')' - { $$= ((Item*(*)(Item*,Item*))($1.symbol->create_func))($3,$5);} + { + if (!$1.symbol->create_func) + { + net_printf(Lex->thd, ER_FEATURE_DISABLED, + ER(ER_FEATURE_DISABLED), + $1.symbol->group->name, + $1.symbol->group->needed_define); + YYABORT; + } + $$= ((Item*(*)(Item*,Item*))($1.symbol->create_func))($3,$5); + } | FUNC_ARG3 '(' expr ',' expr ',' expr ')' - { $$= ((Item*(*)(Item*,Item*,Item*))($1.symbol->create_func))($3,$5,$7);} + { + if (!$1.symbol->create_func) + { + net_printf(Lex->thd, ER_FEATURE_DISABLED, + ER(ER_FEATURE_DISABLED), + $1.symbol->group->name, + $1.symbol->group->needed_define); + YYABORT; + } + $$= ((Item*(*)(Item*,Item*,Item*))($1.symbol->create_func))($3,$5,$7); + } | ADDDATE_SYM '(' expr ',' expr ')' { $$= new Item_date_add_interval($3, $5, INTERVAL_DAY, 0);} | ADDDATE_SYM '(' expr ',' INTERVAL_SYM expr interval ')' @@ -3708,18 +3774,17 @@ simple_expr: } | FIELD_FUNC '(' expr ',' expr_list ')' { $5->push_front($3); $$= new Item_func_field(*$5); } - | GEOMFROMTEXT '(' expr ')' - { $$= new Item_func_geometry_from_text($3); } - | GEOMFROMTEXT '(' expr ',' expr ')' - { $$= new Item_func_geometry_from_text($3, $5); } - | GEOMFROMWKB '(' expr ')' - { $$= new Item_func_geometry_from_wkb($3); } - | GEOMFROMWKB '(' expr ',' expr ')' - { $$= new Item_func_geometry_from_wkb($3, $5); } - | GEOMETRYCOLLECTION '(' expr_list ')' - { $$= new Item_func_spatial_collection(* $3, - Geometry::wkbGeometryCollection, - Geometry::wkbPoint); } + | geometry_function + { +#ifdef HAVE_SPATIAL + $$= $1; +#else + net_printf(Lex->thd, ER_FEATURE_DISABLED, + ER(ER_FEATURE_DISABLED), + sym_group_geom.name, sym_group_geom.needed_define); + YYABORT; +#endif + } | GET_FORMAT '(' date_time_type ',' expr ')' { $$= new Item_func_get_format($3, $5); } | HOUR_SYM '(' expr ')' @@ -3753,17 +3818,10 @@ simple_expr: } | LEFT '(' expr ',' expr ')' { $$= new Item_func_left($3,$5); } - | LINESTRING '(' expr_list ')' - { $$= new Item_func_spatial_collection(* $3, - Geometry::wkbLineString, Geometry::wkbPoint); } | LOCATE '(' expr ',' expr ')' { $$= new Item_func_locate($5,$3); } | LOCATE '(' expr ',' expr ',' expr ')' { $$= new Item_func_locate($5,$3,$7); } - | GEOMCOLLFROMTEXT '(' expr ')' - { $$= new Item_func_geometry_from_text($3); } - | GEOMCOLLFROMTEXT '(' expr ',' expr ')' - { $$= new Item_func_geometry_from_text($3, $5); } | GREATEST_SYM '(' expr ',' expr_list ')' { $5->push_front($3); $$= new Item_func_max(*$5); } | LEAST_SYM '(' expr ',' expr_list ')' @@ -3772,10 +3830,6 @@ simple_expr: { $$= new Item_func_log($3); } | LOG_SYM '(' expr ',' expr ')' { $$= new Item_func_log($3, $5); } - | LINEFROMTEXT '(' expr ')' - { $$= new Item_func_geometry_from_text($3); } - | LINEFROMTEXT '(' expr ',' expr ')' - { $$= new Item_func_geometry_from_text($3, $5); } | MASTER_POS_WAIT '(' expr ',' expr ')' { $$= new Item_master_pos_wait($3, $5); @@ -3794,27 +3848,6 @@ simple_expr: { $$ = new Item_func_mod( $3, $5); } | MONTH_SYM '(' expr ')' { $$= new Item_func_month($3); } - | MULTILINESTRING '(' expr_list ')' - { $$= new Item_func_spatial_collection(* $3, - Geometry::wkbMultiLineString, Geometry::wkbLineString); } - | MLINEFROMTEXT '(' expr ')' - { $$= new Item_func_geometry_from_text($3); } - | MLINEFROMTEXT '(' expr ',' expr ')' - { $$= new Item_func_geometry_from_text($3, $5); } - | MPOINTFROMTEXT '(' expr ')' - { $$= new Item_func_geometry_from_text($3); } - | MPOINTFROMTEXT '(' expr ',' expr ')' - { $$= new Item_func_geometry_from_text($3, $5); } - | MPOLYFROMTEXT '(' expr ')' - { $$= new Item_func_geometry_from_text($3); } - | MPOLYFROMTEXT '(' expr ',' expr ')' - { $$= new Item_func_geometry_from_text($3, $5); } - | MULTIPOINT '(' expr_list ')' - { $$= new Item_func_spatial_collection(* $3, - Geometry::wkbMultiPoint, Geometry::wkbPoint); } - | MULTIPOLYGON '(' expr_list ')' - { $$= new Item_func_spatial_collection(* $3, - Geometry::wkbMultiPolygon, Geometry::wkbPolygon ); } | NOW_SYM optional_braces { $$= new Item_func_now_local(); Lex->safe_to_cache_query=0;} | NOW_SYM '(' expr ')' @@ -3827,19 +3860,6 @@ simple_expr: } | OLD_PASSWORD '(' expr ')' { $$= new Item_func_old_password($3); } - | POINT_SYM '(' expr ',' expr ')' - { $$= new Item_func_point($3,$5); } - | POINTFROMTEXT '(' expr ')' - { $$= new Item_func_geometry_from_text($3); } - | POINTFROMTEXT '(' expr ',' expr ')' - { $$= new Item_func_geometry_from_text($3, $5); } - | POLYFROMTEXT '(' expr ')' - { $$= new Item_func_geometry_from_text($3); } - | POLYFROMTEXT '(' expr ',' expr ')' - { $$= new Item_func_geometry_from_text($3, $5); } - | POLYGON '(' expr_list ')' - { $$= new Item_func_spatial_collection(* $3, - Geometry::wkbPolygon, Geometry::wkbLineString); } | POSITION_SYM '(' no_in_expr IN_SYM expr ')' { $$ = new Item_func_locate($5,$3); } | QUARTER_SYM '(' expr ')' @@ -3991,6 +4011,66 @@ simple_expr: | EXTRACT_SYM '(' interval FROM expr ')' { $$=new Item_extract( $3, $5); }; +geometry_function: + GEOMFROMTEXT '(' expr ')' + { $$= GEOM_NEW(Item_func_geometry_from_text($3)); } + | GEOMFROMTEXT '(' expr ',' expr ')' + { $$= GEOM_NEW(Item_func_geometry_from_text($3, $5)); } + | GEOMFROMWKB '(' expr ')' + { $$= GEOM_NEW(Item_func_geometry_from_wkb($3)); } + | GEOMFROMWKB '(' expr ',' expr ')' + { $$= GEOM_NEW(Item_func_geometry_from_wkb($3, $5)); } + | GEOMETRYCOLLECTION '(' expr_list ')' + { $$= GEOM_NEW(Item_func_spatial_collection(* $3, + Geometry::wkbGeometryCollection, + Geometry::wkbPoint)); } + | LINESTRING '(' expr_list ')' + { $$= GEOM_NEW(Item_func_spatial_collection(* $3, + Geometry::wkbLineString, Geometry::wkbPoint)); } + | MULTILINESTRING '(' expr_list ')' + { $$= GEOM_NEW( Item_func_spatial_collection(* $3, + Geometry::wkbMultiLineString, Geometry::wkbLineString)); } + | MLINEFROMTEXT '(' expr ')' + { $$= GEOM_NEW(Item_func_geometry_from_text($3)); } + | MLINEFROMTEXT '(' expr ',' expr ')' + { $$= GEOM_NEW(Item_func_geometry_from_text($3, $5)); } + | MPOINTFROMTEXT '(' expr ')' + { $$= GEOM_NEW(Item_func_geometry_from_text($3)); } + | MPOINTFROMTEXT '(' expr ',' expr ')' + { $$= GEOM_NEW(Item_func_geometry_from_text($3, $5)); } + | MPOLYFROMTEXT '(' expr ')' + { $$= GEOM_NEW(Item_func_geometry_from_text($3)); } + | MPOLYFROMTEXT '(' expr ',' expr ')' + { $$= GEOM_NEW(Item_func_geometry_from_text($3, $5)); } + | MULTIPOINT '(' expr_list ')' + { $$= GEOM_NEW(Item_func_spatial_collection(* $3, + Geometry::wkbMultiPoint, Geometry::wkbPoint)); } + | MULTIPOLYGON '(' expr_list ')' + { $$= GEOM_NEW(Item_func_spatial_collection(* $3, + Geometry::wkbMultiPolygon, Geometry::wkbPolygon)); } + | POINT_SYM '(' expr ',' expr ')' + { $$= GEOM_NEW(Item_func_point($3,$5)); } + | POINTFROMTEXT '(' expr ')' + { $$= GEOM_NEW(Item_func_geometry_from_text($3)); } + | POINTFROMTEXT '(' expr ',' expr ')' + { $$= GEOM_NEW(Item_func_geometry_from_text($3, $5)); } + | POLYFROMTEXT '(' expr ')' + { $$= GEOM_NEW(Item_func_geometry_from_text($3)); } + | POLYFROMTEXT '(' expr ',' expr ')' + { $$= GEOM_NEW(Item_func_geometry_from_text($3, $5)); } + | POLYGON '(' expr_list ')' + { $$= GEOM_NEW(Item_func_spatial_collection(* $3, + Geometry::wkbPolygon, Geometry::wkbLineString)); } + | GEOMCOLLFROMTEXT '(' expr ')' + { $$= GEOM_NEW(Item_func_geometry_from_text($3)); } + | GEOMCOLLFROMTEXT '(' expr ',' expr ')' + { $$= GEOM_NEW(Item_func_geometry_from_text($3, $5)); } + | LINEFROMTEXT '(' expr ')' + { $$= GEOM_NEW(Item_func_geometry_from_text($3)); } + | LINEFROMTEXT '(' expr ',' expr ')' + { $$= GEOM_NEW(Item_func_geometry_from_text($3, $5)); } + ; + fulltext_options: /* nothing */ { $$= FT_NL; } | WITH QUERY_SYM EXPANSION_SYM { $$= FT_NL | FT_EXPAND; } @@ -4101,7 +4181,7 @@ opt_gorder_clause: | order_clause { LEX *lex=Lex; - lex->gorder_list= + lex->gorder_list= (SQL_LIST*) sql_memdup((char*) &lex->current_select->order_list, sizeof(st_sql_list)); lex->current_select->order_list.empty(); @@ -4124,25 +4204,17 @@ in_sum_expr: $$= $3; }; -cast_type_init: - { Lex->charset= NULL; Lex->length= (char*)0; } - ; - -cast_type_finalize: - BINARY { $$=ITEM_CAST_BINARY; } +cast_type: + BINARY { $$=ITEM_CAST_BINARY; Lex->charset= NULL; Lex->length= (char*)0; } | CHAR_SYM opt_len opt_binary { $$=ITEM_CAST_CHAR; } | NCHAR_SYM opt_len { $$=ITEM_CAST_CHAR; Lex->charset= national_charset_info; } - | SIGNED_SYM { $$=ITEM_CAST_SIGNED_INT; } - | SIGNED_SYM INT_SYM { $$=ITEM_CAST_SIGNED_INT; } - | UNSIGNED { $$=ITEM_CAST_UNSIGNED_INT; } - | UNSIGNED INT_SYM { $$=ITEM_CAST_UNSIGNED_INT; } - | DATE_SYM { $$=ITEM_CAST_DATE; } - | TIME_SYM { $$=ITEM_CAST_TIME; } - | DATETIME { $$=ITEM_CAST_DATETIME; } - ; - -cast_type: - cast_type_init cast_type_finalize { $$= $2; } + | SIGNED_SYM { $$=ITEM_CAST_SIGNED_INT; Lex->charset= NULL; Lex->length= (char*)0; } + | SIGNED_SYM INT_SYM { $$=ITEM_CAST_SIGNED_INT; Lex->charset= NULL; Lex->length= (char*)0; } + | UNSIGNED { $$=ITEM_CAST_UNSIGNED_INT; Lex->charset= NULL; Lex->length= (char*)0; } + | UNSIGNED INT_SYM { $$=ITEM_CAST_UNSIGNED_INT; Lex->charset= NULL; Lex->length= (char*)0; } + | DATE_SYM { $$=ITEM_CAST_DATE; Lex->charset= NULL; Lex->length= (char*)0; } + | TIME_SYM { $$=ITEM_CAST_TIME; Lex->charset= NULL; Lex->length= (char*)0; } + | DATETIME { $$=ITEM_CAST_DATETIME; Lex->charset= NULL; Lex->length= (char*)0; } ; expr_list: @@ -4276,13 +4348,6 @@ join_table: | '(' SELECT_SYM select_derived ')' opt_table_alias { LEX *lex=Lex; - if (lex->sql_command == SQLCOM_UPDATE && - &lex->select_lex == lex->current_select->outer_select()) - { - send_error(lex->thd, ER_SYNTAX_ERROR); - YYABORT; - } - SELECT_LEX_UNIT *unit= lex->current_select->master_unit(); lex->current_select= unit->outer_select(); if (!($$= lex->current_select-> @@ -4984,6 +5049,7 @@ update: LEX *lex= Lex; mysql_init_select(lex); lex->sql_command= SQLCOM_UPDATE; + lex->lock_option= TL_UNLOCK; /* Will be set later */ } opt_low_priority opt_ignore join_table_list SET update_list where_clause opt_order_clause delete_limit_clause @@ -4992,6 +5058,13 @@ update: Select->set_lock_for_tables($3); if (lex->select_lex.table_list.elements > 1) lex->sql_command= SQLCOM_UPDATE_MULTI; + else if (lex->select_lex.get_table_list()->derived) + { + /* it is single table update and it is update of derived table */ + net_printf(lex->thd, ER_NON_UPDATABLE_TABLE, + lex->select_lex.get_table_list()->alias, "UPDATE"); + YYABORT; + } } ; @@ -5679,9 +5752,8 @@ simple_ident: $$= (sel->parsing_place != SELECT_LEX_NODE::IN_HAVING || sel->get_in_sum_expr() > 0) ? (Item*) new Item_field(NullS,NullS,$1.str) : - (Item*) new Item_ref(NullS,NullS,$1.str); + (Item*) new Item_ref(0,0, NullS,NullS,$1.str); } - } | simple_ident_q { $$= $1; } ; @@ -5712,7 +5784,7 @@ simple_ident_q: $$= (sel->parsing_place != SELECT_LEX_NODE::IN_HAVING || sel->get_in_sum_expr() > 0) ? (Item*) new Item_field(NullS,$1.str,$3.str) : - (Item*) new Item_ref(NullS,$1.str,$3.str); + (Item*) new Item_ref(0,0,NullS,$1.str,$3.str); } | '.' ident '.' ident { @@ -5728,7 +5800,7 @@ simple_ident_q: $$= (sel->parsing_place != SELECT_LEX_NODE::IN_HAVING || sel->get_in_sum_expr() > 0) ? (Item*) new Item_field(NullS,$2.str,$4.str) : - (Item*) new Item_ref(NullS,$2.str,$4.str); + (Item*) new Item_ref(0,0,NullS,$2.str,$4.str); } | ident '.' ident '.' ident { @@ -5746,8 +5818,8 @@ simple_ident_q: (Item*) new Item_field((YYTHD->client_capabilities & CLIENT_NO_SCHEMA ? NullS : $1.str), $3.str, $5.str) : - (Item*) new Item_ref((YYTHD->client_capabilities & - CLIENT_NO_SCHEMA ? NullS : $1.str), + (Item*) new Item_ref(0,0,(YYTHD->client_capabilities & + CLIENT_NO_SCHEMA ? NullS : $1.str), $3.str, $5.str); }; diff --git a/sql/table.cc b/sql/table.cc index 912c133e571..8fe061af530 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -405,8 +405,13 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, // charset and geometry_type share the same byte in frm if (field_type == FIELD_TYPE_GEOMETRY) { +#ifdef HAVE_SPATIAL geom_type= (Field::geometry_type) strpos[14]; charset= &my_charset_bin; +#else + error= 4; // unsupported field type + goto err_not_open; +#endif } else { @@ -481,8 +486,8 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, /* Fix key->name and key_part->field */ if (key_parts) { - uint primary_key=(uint) (find_type((char*) "PRIMARY",&outparam->keynames, - 3)-1); + uint primary_key=(uint) (find_type((char*) primary_key_name, + &outparam->keynames, 3) - 1); uint ha_option=outparam->file->table_flags(); keyinfo=outparam->key_info; key_part=keyinfo->key_part; diff --git a/sql/unireg.cc b/sql/unireg.cc index fc948ddd5a6..6ebba313442 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -471,7 +471,12 @@ static bool pack_fields(File file,List<create_field> &create_fields) buff[12]= (uchar) field->interval_id; buff[13]= (uchar) field->sql_type; if (field->sql_type == FIELD_TYPE_GEOMETRY) + { buff[14]= (uchar) field->geom_type; +#ifndef HAVE_SPATIAL + DBUG_ASSERT(0); // Should newer happen +#endif + } else if (field->charset) buff[14]= (uchar) field->charset->number; else |