summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <pem@mysql.com>2004-02-10 18:44:02 +0100
committerunknown <pem@mysql.com>2004-02-10 18:44:02 +0100
commit6efd76f317be8fc5fd0a2d144a7c57506723c2ad (patch)
treef04786f8a211a4c03eab547b7332792201289ac1 /sql
parent5390589c3c5845f48d3cf251d8b3dad359e0c9b1 (diff)
parent23103e44b4cc8abfdb1da47214ff2bd7cc2f3fca (diff)
downloadmariadb-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')
-rw-r--r--sql/Makefile.am4
-rw-r--r--sql/field.cc120
-rw-r--r--sql/field.h16
-rw-r--r--sql/filesort.cc2
-rw-r--r--sql/gen_lex_hash.cc3
-rw-r--r--sql/ha_heap.cc2
-rw-r--r--sql/item.cc79
-rw-r--r--sql/item.h78
-rw-r--r--sql/item_cmpfunc.cc39
-rw-r--r--sql/item_cmpfunc.h34
-rw-r--r--sql/item_create.cc2
-rw-r--r--sql/item_create.h4
-rw-r--r--sql/item_func.cc42
-rw-r--r--sql/item_func.h34
-rw-r--r--sql/item_geofunc.cc4
-rw-r--r--sql/item_geofunc.h11
-rw-r--r--sql/item_row.cc2
-rw-r--r--sql/item_row.h6
-rw-r--r--sql/item_strfunc.cc93
-rw-r--r--sql/item_strfunc.h5
-rw-r--r--sql/item_subselect.cc41
-rw-r--r--sql/item_subselect.h10
-rw-r--r--sql/item_sum.cc79
-rw-r--r--sql/item_sum.h152
-rw-r--r--sql/item_timefunc.cc10
-rw-r--r--sql/item_uniq.h4
-rw-r--r--sql/lex.h1371
-rw-r--r--sql/lex_symbol.h3
-rw-r--r--sql/mysql_priv.h32
-rw-r--r--sql/mysqld.cc21
-rw-r--r--sql/opt_ft.cc36
-rw-r--r--sql/opt_ft.h42
-rw-r--r--sql/opt_range.cc120
-rw-r--r--sql/opt_range.h14
-rw-r--r--sql/protocol.cc13
-rw-r--r--sql/repl_failsafe.cc2
-rw-r--r--sql/set_var.cc11
-rw-r--r--sql/share/charsets/Index.xml3
-rw-r--r--sql/share/charsets/languages.html257
-rw-r--r--sql/share/charsets/latin1.xml21
-rw-r--r--sql/share/czech/errmsg.txt3
-rw-r--r--sql/share/danish/errmsg.txt3
-rw-r--r--sql/share/dutch/errmsg.txt3
-rw-r--r--sql/share/english/errmsg.txt3
-rw-r--r--sql/share/estonian/errmsg.txt3
-rw-r--r--sql/share/french/errmsg.txt3
-rw-r--r--sql/share/german/errmsg.txt3
-rw-r--r--sql/share/greek/errmsg.txt3
-rw-r--r--sql/share/hungarian/errmsg.txt3
-rw-r--r--sql/share/italian/errmsg.txt3
-rw-r--r--sql/share/japanese/errmsg.txt3
-rw-r--r--sql/share/korean/errmsg.txt3
-rw-r--r--sql/share/norwegian-ny/errmsg.txt3
-rw-r--r--sql/share/norwegian/errmsg.txt3
-rw-r--r--sql/share/polish/errmsg.txt3
-rw-r--r--sql/share/portuguese/errmsg.txt3
-rw-r--r--sql/share/romanian/errmsg.txt3
-rw-r--r--sql/share/russian/errmsg.txt3
-rw-r--r--sql/share/serbian/errmsg.txt3
-rw-r--r--sql/share/slovak/errmsg.txt3
-rw-r--r--sql/share/spanish/errmsg.txt3
-rw-r--r--sql/share/swedish/errmsg.txt3
-rw-r--r--sql/share/ukrainian/errmsg.txt3
-rw-r--r--sql/slave.cc3
-rw-r--r--sql/slave.h5
-rw-r--r--sql/sql_acl.cc48
-rw-r--r--sql/sql_base.cc135
-rw-r--r--sql/sql_cache.cc41
-rw-r--r--sql/sql_cache.h4
-rw-r--r--sql/sql_class.cc187
-rw-r--r--sql/sql_class.h61
-rw-r--r--sql/sql_db.cc103
-rw-r--r--sql/sql_delete.cc3
-rw-r--r--sql/sql_derived.cc236
-rw-r--r--sql/sql_handler.cc3
-rw-r--r--sql/sql_help.cc6
-rw-r--r--sql/sql_insert.cc11
-rw-r--r--sql/sql_lex.cc125
-rw-r--r--sql/sql_lex.h17
-rw-r--r--sql/sql_list.h10
-rw-r--r--sql/sql_load.cc2
-rw-r--r--sql/sql_olap.cc14
-rw-r--r--sql/sql_parse.cc93
-rw-r--r--sql/sql_prepare.cc28
-rw-r--r--sql/sql_select.cc198
-rw-r--r--sql/sql_select.h6
-rw-r--r--sql/sql_show.cc113
-rw-r--r--sql/sql_string.cc126
-rw-r--r--sql/sql_string.h6
-rw-r--r--sql/sql_table.cc41
-rw-r--r--sql/sql_udf.cc2
-rw-r--r--sql/sql_union.cc15
-rw-r--r--sql/sql_update.cc48
-rw-r--r--sql/sql_yacc.yy354
-rw-r--r--sql/table.cc9
-rw-r--r--sql/unireg.cc5
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, &not_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, &not_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,
+ &not_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, &not_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, &not_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 &#x00C1;&#x00C2;&#x00C3;&#x00CA;&#x00CD;&#x00CE;&#x00D4;&#x00DA;&#x00DB;&#x00E1;&#x00E2;&#x00E3;&#x00EA;&#x00ED;&#x00EE;&#x00F4;&#x00FA;&#x00FB;&#x0128;&#x0129;&#x0138;&#x0168;&#x0169;
+#Use of these letters was abolished in a spelling reform in 1973:
+#Greenlandic &#x00C5;&#x00C6;&#x00D8;&#x00E5;&#x00E6;&#x00F8;
+#Characters not found in the UCS:
+# K LATIN CAPITAL LETTER KRA
+#############################################################
+#Basque &#x00D1;&#x00DC;&#x00F1;&#x00FC;&#x0154;&#x0155;
+#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 #&#x00C0;&#x00C1;&#x00C2;&#x00C8;&#x00C9;&#x00CA;&#x00CC;&#x00CD;&#x00CE;&#x00D2;&#x00D3;&#x00D4;&#x00D9;&#x00DA;&#x00DB;#&#x00E0;&#x00E1;&#x00E2;&#x00E8;&#x00E9;&#x00EA;&#x00EC;&#x00ED;&#x00EE;&#x00F2;&#x00D3;&#x00F4;&#x00F9;&#x00FA;&#x00FB;#&#x010A;&#x010B;&#x0120;&#x0121;&#x0126;&#x0127;&#x017B;&#x017C;&#x02BC;
+#BosnianCyr &#x0402;&#x0408;&#x0409;&#x040A;&#x040B;&#x040F;&#x0410;&#x0411;&#x0412;&#x0413;&#x0414;&#x0415;&#x0416;&#x0417;&#x0418;&#x041A;&#x041B;&#x041C;&#x041D;&#x041E;&#x041F;&#x0420;&#x0421;&#x0422;&#x0423;&#x0424;&#x0425;&#x0426;&#x0427;&#x0428;&#x0430;&#x0431;&#x0432;&#x0433;&#x0434;&#x0435;&#x0436;&#x0437;&#x0438;&#x043A;&#x043B;&#x043C;&#x043D;&#x043E;&#x043F;&#x0440;&#x0441;&#x0442;&#x0443;&#x0444;&#x0445;&#x0446;&#x0447;&#x0448;&#x0452;&#x0458;&#x0459;&#x045A;&#x045B;&#x045F;
+#Scots &#x0041;
+#Scots1 &#x01B7;&#x021C;&#x021D;&#x0292;
+###########################################
+#### Hiragana 3040-309F
+Hiragana &#x3041;&#x3042;&#x3043;&#x3044;&#x3045;&#x3046;&#x3047;&#x3048;&#x3049;&#x304A;&#x304B;&#x304C;&#x304D;&#x304E;&#x304F;&#x3050;&#x3051;&#x3052;&#x3053;&#x3054;&#x3055;&#x3056;&#x3057;&#x3058;&#x3059;&#x305A;&#x305B;&#x305C;&#x305D;&#x305E;&#x305F;&#x3060;&#x3061;&#x3062;&#x3063;&#x3064;&#x3065;&#x3066;&#x3067;&#x3068;&#x3069;&#x306A;&#x306B;&#x306C;&#x306D;&#x306E;&#x306F;&#x3070;&#x3071;&#x3072;&#x3073;&#x3074;&#x3075;&#x3076;&#x3077;&#x3078;&#x3079;&#x307A;&#x307B;&#x307C;&#x307D;&#x307E;&#x307F;&#x3080;&#x3081;&#x3082;&#x3083;&#x3084;&#x3085;&#x3086;&#x3087;&#x3088;&#x3089;&#x308A;&#x308B;&#x308C;&#x308D;&#x308E;&#x308F;&#x3090;&#x3091;&#x3092;&#x3093;
+Hiragana1 &#x3094;&#x3099;&#x309A;
+Hiragana2 &#x309B;&#x309C;&#x309D;&#x309E;
+#### Katakana 30A0-30FF
+Katakana &#x30A1;&#x30A2;&#x30A3;&#x30A4;&#x30A5;&#x30A6;&#x30A7;&#x30A8;&#x30A9;&#x30AA;&#x30AB;&#x30AC;&#x30AD;&#x30AE;&#x30AF;&#x30B0;&#x30B1;&#x30B2;&#x30B3;&#x30B4;&#x30B5;&#x30B6;&#x30B7;&#x30B8;&#x30B9;&#x30BA;&#x30BB;&#x30BC;&#x30BD;&#x30BE;&#x30BF;&#x30C0;&#x30C1;&#x30C2;&#x30C3;&#x30C4;&#x30C5;&#x30C6;&#x30C7;&#x30C8;&#x30C9;&#x30CA;&#x30CB;&#x30CC;&#x30CD;&#x30CE;&#x30CF;&#x30D0;&#x30D1;&#x30D2;&#x30D3;&#x30D4;&#x30D5;&#x30D6;&#x30D7;&#x30D8;&#x30D9;&#x30DA;&#x30DB;&#x30DC;&#x30DD;&#x30DE;&#x30DF;&#x30E0;&#x30E1;&#x30E2;&#x30E3;&#x30E4;&#x30E5;&#x30E6;&#x30E7;&#x30E8;&#x30E9;&#x30EA;&#x30EB;&#x30EC;&#x30ED;&#x30EE;&#x30EF;&#x30F0;&#x30F1;&#x30F2;&#x30F3;&#x30F4;&#x30F5;&#x30F6;
+Katakana1 &#x30F7;&#x30F8;&#x30F9;&#x30FA;
+Katakana2 &#x30FB;&#x30FC;&#x30FD;&#x30FE;
+############################################
+Albanian &#x00C2;&#x00C7;&#x00CB;&#x00E2;&#x00E7;&#x00EB;
+Bosnian &#x0106;&#x0107;&#x010C;&#x010D;&#x0110;&#x0111;&#x0160;&#x0161;&#x017D;&#x017E;
+Breton &#x00C2;&#x00CA;&#x00D1;&#x00D9;&#x00DC;&#x00E2;&#x00EA;&#x00F1;&#x00F9;&#x00FC;
+Catalan &#x00C0;&#x00C7;&#x00C8;&#x00C9;&#x00CD;&#x00CF;&#x00D2;&#x00D3;&#x00DA;&#x00DC;&#x00E0;&#x00E7;&#x00E8;&#x00E9;&#x00ED;&#x00EF;&#x00F2;&#x00F3;&#x00FA;&#x00FC;
+#Catalan1 &#x00B7;&#x013F;&#x0140;
+Croatian &#x0106;&#x0107;&#x010C;&#x010D;&#x0110;&#x0111;&#x0160;&#x0161;&#x017D;&#x017E;
+CroatianLig &#x01F1;&#x01F2;&#x01F3;&#x01C4;&#x01C5;&#x01C6;&#x01C7;&#x01C8;&#x01C9;&#x01CA;&#x01CB;&#x01CC;
+Czech &#x00C1;&#x00C9;&#x00CD;&#x00D3;&#x00DA;&#x00DD;&#x00E1;&#x00E9;&#x00ED;&#x00F3;&#x00FA;&#x00FD;&#x010C;&#x010D;&#x010E;&#x010F;&#x011A;&#x011B;&#x0147;&#x0148;&#x0158;&#x0159;&#x0160;&#x0161;&#x0164;&#x0165;&#x016E;&#x016F;&#x017D;&#x017E;
+Danish &#x00C1;&#x00C4;&#x00C5;&#x00C6;&#x00C9;&#x00D3;&#x00D6;&#x00D8;&#x00DC;&#x00E1;&#x00E4;&#x00E5;&#x00E6;&#x00E9;&#x00F3;&#x00F6;&#x00F8;&#x00FC;
+Dutch &#x00C0;&#x00C2;&#x00C4;&#x00C6;&#x00C7;&#x00C8;&#x00C9;&#x00CA;&#x00CB;&#x00CE;&#x00CF;&#x00D1;&#x00D2;&#x00D3;&#x00D4;&#x00D6;&#x00D9;&#x00DA;&#x00DB;&#x00DC;&#x00E0;&#x00E2;&#x00E4;&#x00E6;&#x00E7;&#x00E8;&#x00E9;&#x00EA;&#x00EB;&#x00EE;&#x00EF;&#x00F1;&#x00F2;&#x00F3;&#x00F4;&#x00F6;&#x00F9;&#x00FA;&#x00FB;&#x00FC;
+Esperanto &#x0108;&#x0109;&#x011C;&#x011D;&#x0124;&#x0125;&#x0134;&#x0135;&#x015C;&#x015D;&#x016C;&#x016D;
+Estonian &#x00C4;&#x00D5;&#x00D6;&#x00DC;&#x00E4;&#x00F5;&#x00F6;&#x00FC;&#x0160;&#x0161;&#x017D;&#x017E;
+Faroese &#x00C5;&#x00C6;&#x00D0;&#x00D3;&#x00D6;&#x00D8;&#x00DA;&#x00DD;&#x00E5;&#x00E6;&#x00F0;&#x00F3;&#x00F6;&#x00F8;&#x00FA;&#x00FD;
+Finnish &#x00C4;&#x00C5;&#x00D6;&#x00DC;&#x00E4;&#x00E5;&#x00F6;&#x00FC;
+#Finnish1 &#x0160;&#x0161;&#x017D;&#x017E;
+French(limited) &#x00C0;&#x00C2;&#x00C6;&#x00C7;&#x00C8;&#x00C9;&#x00CA;&#x00CB;&#x00CE;&#x00CF;&#x00D1;&#x00D4;&#x00D9;&#x00DB;&#x00E0;&#x00E2;&#x00E6;&#x00E7;&#x00E8;&#x00E9;&#x00EA;&#x00EB;&#x00EE;&#x00EF;&#x00F1;&#x00F4;&#x00F9;&#x00FB;&#x00FF;
+French &#x0152;&#x0153;&#x0178;
+German &#x00C4;&#x00D6;&#x00DC;&#x00DF;&#x00E4;&#x00F6;&#x00FC;
+Hungarian &#x00C1;&#x00C9;&#x00CD;&#x00D3;&#x00D6;&#x00DA;&#x00DC;&#x00E1;&#x00E9;&#x00ED;&#x00F3;&#x00F6;&#x00FA;&#x00FC;&#x0150;&#x0151;&#x0170;&#x0171;
+Icelandic &#x00C1;&#x00C6;&#x00C9;&#x00CD;&#x00D0;&#x00D3;&#x00D6;&#x00DA;&#x00DD;&#x00DE;&#x00E1;&#x00E6;&#x00E9;&#x00ED;&#x00F0;&#x00F3;&#x00F6;&#x00FA;&#x00FD;&#x00FE;
+Italian &#x00C0;&#x00C8;&#x00C9;&#x00CC;&#x00CD;&#x00CF;&#x00D2;&#x00D3;&#x00D9;&#x00DA;&#x00E0;&#x00E8;&#x00E9;&#x00EC;&#x00ED;&#x00EF;&#x00F2;&#x00F3;&#x00F9;&#x00FA;
+#Latin &#x0041;
+Latvian &#x0100;&#x0101;&#x010C;&#x010D;&#x0112;&#x0113;&#x0122;&#x0123;&#x012A;&#x012B;&#x0136;&#x0137;&#x013B;&#x013C;&#x0145;&#x0146;&#x0160;&#x0161;&#x016A;&#x016B;&#x017D;&#x017E;
+Lithuanian &#x0104;&#x0105;&#x010C;&#x010D;&#x0116;&#x0117;&#x0118;&#x0119;&#x012E;&#x012F;&#x0160;&#x0161;&#x016A;&#x016B;&#x0172;&#x0173;&#x017D;&#x017E;
+Norwegian &#x00C5;&#x00C6;&#x00D8;&#x00E5;&#x00E6;&#x00F8;
+Polish &#x00D3;&#x00F3;&#x0104;&#x0105;&#x0106;&#x0107;&#x0118;&#x0119;&#x0141;&#x0142;&#x0143;&#x0144;&#x015A;&#x015B;&#x0179;&#x017A;&#x017B;&#x017C;
+Portuguese &#x00C0;&#x00C1;&#x00C2;&#x00C3;&#x00C7;&#x00C9;&#x00CA;&#x00CD;&#x00D3;&#x00D4;&#x00D5;&#x00DA;&#x00DC;&#x00E0;&#x00E1;&#x00E2;&#x00E3;&#x00E7;&#x00E9;&#x00EA;&#x00ED;&#x00F3;&#x00F4;&#x00F5;&#x00FA;&#x00FC;
+#http://en.wikipedia.org/wiki/Special_Romanian_Unicode_characters
+Romanian &#x00C2;&#x00CE;&#x00E2;&#x00EE;&#x0102;&#x0103;&#x0218;&#x0219;&#x021A;&#x021B;
+Romanian(ErrorST) &#x00C2;&#x00CE;&#x00E2;&#x00EE;&#x0102;&#x0103;&#x015E;&#x015F;&#x0162;&#x0163;
+Slovak &#x00C1;&#x00C4;&#x00C9;&#x00CD;&#x00D3;&#x00D4;&#x00DA;&#x00DD;&#x00E1;&#x00E4;&#x00E9;&#x00ED;&#x00F3;&#x00F4;&#x00FA;&#x00FD;&#x010C;&#x010D;&#x010E;&#x010F;&#x0139;&#x013A;&#x013D;&#x013E;&#x0147;&#x0148;&#x0154;&#x0155;&#x0160;&#x0161;&#x0164;&#x0165;&#x017D;&#x017E;
+Slovene &#x010C;&#x010D;&#x0160;&#x0161;&#x017D;&#x017E
+Sorbian-Lower &#x0106;&#x0107;&#x010C;&#x010D;&#x011A;&#x011B;&#x0141;&#x0142;&#x0143;&#x0144;&#x0158;&#x0159;&#x015A;&#x015B;&#x0160;&#x0161;&#x0179;&#x017A;&#x017D;&#x017E;
+Sorbian-Upper &#x00D3;&#x00F3;&#x0106;&#x0107;&#x010C;&#x010D;&#x011A;&#x011B;&#x0141;&#x0142;&#x0143;&#x0144;&#x0158;&#x0159;&#x0160;&#x0161;&#x017D;&#x017E;
+Spanish &#x00C1;&#x00C9;&#x00CD;&#x00D1;&#x00D3;&#x00DA;&#x00DC;&#x00E1;&#x00E9;&#x00ED;&#x00F1;&#x00F3;&#x00FA;&#x00FC;
+Swedish &#x00C4;&#x00C5;&#x00D6;&#x00E4;&#x00E5;&#x00F6;
+Turkish &#x00C2;&#x00C7;&#x00D6;&#x00DB;&#x00DC;&#x00E2;&#x00E7;&#x00F6;&#x00FB;&#x00FC;&#x011E;&#x011F;&#x0130;&#x0131;
+Welsh &#x00C0;&#x00C1;&#x00C2;&#x00C4;&#x00C8;&#x00C9;&#x00CA;&#x00CB;&#x00CC;&#x00CD;&#x00CE;&#x00CF;&#x00D2;&#x00D3;&#x00D4;&#x00D6;&#x00D9;&#x00DA;&#x00DB;&#x00DC;&#x00DD;&#x00E0;&#x00E1;&#x00E2;&#x00E4;&#x00E8;&#x00E9;&#x00EA;&#x00EB;&#x00EC;&#x00ED;&#x00EE;&#x00EF;&#x00F2;&#x00F3;&#x00F4;&#x00F6;&#x00F9;&#x00FA;&#x00FB;&#x00FC;&#x00FD;&#x00FF;&#x0174;&#x0175;&#x0176;&#x0177;&#x0178;&#x1E80;&#x1E81;&#x1E82;&#x1E83;&#x1E84;&#x1E85;&#x1EF2;&#x1EF3;
+##################################
+Belarusian &#x0401;&#x0406;&#x040E;&#x0410;&#x0411;&#x0412;&#x0413;&#x0414;&#x0415;&#x0416;&#x0417;&#x0418;&#x0419;&#x041A;&#x041B;&#x041C;&#x041D;&#x041E;&#x041F;&#x0420;&#x0421;&#x0422;&#x0423;&#x0424;&#x0425;&#x0426;&#x0427;&#x0428;&#x0429;&#x042A;&#x042B;&#x042C;&#x042D;&#x042E;&#x042F;&#x0430;&#x0431;&#x0432;&#x0433;&#x0434;&#x0435;&#x0436;&#x0437;&#x0438;&#x0439;&#x043A;&#x043B;&#x043C;&#x043D;&#x043E;&#x043F;&#x0440;&#x0441;&#x0442;&#x0443;&#x0444;&#x0445;&#x0446;&#x0447;&#x0448;&#x0449;&#x044A;&#x044B;&#x044C;&#x044D;&#x044E;&#x044F;&#x0451;&#x0456;&#x045E;
+Bulgarian &#x0410;&#x0411;&#x0412;&#x0413;&#x0414;&#x0415;&#x0416;&#x0417;&#x0418;&#x0419;&#x041A;&#x041B;&#x041C;&#x041D;&#x041E;&#x041F;&#x0420;&#x0421;&#x0422;&#x0423;&#x0424;&#x0425;&#x0426;&#x0427;&#x0428;&#x0429;&#x042A;&#x042C;&#x042E;&#x042F;&#x0430;&#x0431;&#x0432;&#x0433;&#x0434;&#x0435;&#x0436;&#x0437;&#x0438;&#x0439;&#x043A;&#x043B;&#x043C;&#x043D;&#x043E;&#x043F;&#x0440;&#x0441;&#x0442;&#x0443;&#x0444;&#x0445;&#x0446;&#x0447;&#x0448;&#x0449;&#x044A;&#x044C;&#x044E;&#x044F;
+Bulgarian1 &#x0400;&#x04AD;&#x0450;&#x045D;&#x0462;&#x0463;&#x046A;&#x046B;
+Macedonian &#x0403;&#x0405;&#x0408;&#x0409;&#x040A;&#x040C;&#x040F;&#x0410;&#x0411;&#x0412;&#x0413;&#x0414;&#x0415;&#x0416;&#x0417;&#x0418;&#x041A;&#x041B;&#x041C;&#x041D;&#x041E;&#x041F;&#x0420;&#x0421;&#x0422;&#x0423;&#x0424;&#x0425;&#x0426;&#x0427;&#x0428;&#x0430;&#x0431;&#x0432;&#x0433;&#x0434;&#x0435;&#x0436;&#x0437;&#x0438;&#x043A;&#x043B;&#x043C;&#x043D;&#x043E;&#x043F;&#x0440;&#x0441;&#x0442;&#x0443;&#x0444;&#x0445;&#x0446;&#x0447;&#x0448;&#x0453;&#x0455;&#x0458;&#x0459;&#x045A;&#x045C;&#x045F;
+Russian &#x0401;&#x0410;&#x0411;&#x0412;&#x0413;&#x0414;&#x0415;&#x0416;&#x0417;&#x0418;&#x0419;&#x041A;&#x041B;&#x041C;&#x041D;&#x041E;&#x041F;&#x0420;&#x0421;&#x0422;&#x0423;&#x0424;&#x0425;&#x0426;&#x0427;&#x0428;&#x0429;&#x042A;&#x042B;&#x042C;&#x042D;&#x042E;&#x042F;&#x0430;&#x0431;&#x0432;&#x0433;&#x0434;&#x0435;&#x0436;&#x0437;&#x0438;&#x0439;&#x043A;&#x043B;&#x043C;&#x043D;&#x043E;&#x043F;&#x0440;&#x0441;&#x0442;&#x0443;&#x0444;&#x0445;&#x0446;&#x0447;&#x0448;&#x0449;&#x044A;&#x044B;&#x044C;&#x044D;&#x044E;&#x044F;&#x0451;
+RussianOLD &#x0406;&#x0456;&#x0462;&#x0463;&#x0472;&#x0473;&#x0474;&#x0475;
+Serbian &#x0402;&#x0408;&#x0409;&#x040A;&#x040B;&#x040F;&#x0410;&#x0411;&#x0412;&#x0413;&#x0414;&#x0415;&#x0416;&#x0417;&#x0418;&#x041A;&#x041B;&#x041C;&#x041D;&#x041E;&#x041F;&#x0420;&#x0421;&#x0422;&#x0423;&#x0424;&#x0425;&#x0426;&#x0427;&#x0428;&#x0430;&#x0431;&#x0432;&#x0433;&#x0434;&#x0435;&#x0436;&#x0437;&#x0438;&#x043A;&#x043B;&#x043C;&#x043D;&#x043E;&#x043F;&#x0440;&#x0441;&#x0442;&#x0443;&#x0444;&#x0445;&#x0446;&#x0447;&#x0448;&#x0452;&#x0458;&#x0459;&#x045A;&#x045B;&#x045F;
+Ukrainian &#x0404;&#x0406;&#x0407;&#x0410;&#x0411;&#x0412;&#x0413;&#x0414;&#x0415;&#x0416;&#x0417;&#x0418;&#x0419;&#x041A;&#x041B;&#x041C;&#x041D;&#x041E;&#x041F;&#x0420;&#x0421;&#x0422;&#x0423;&#x0424;&#x0425;&#x0426;&#x0427;&#x0428;&#x0429;&#x042C;&#x042D;&#x042E;&#x042F;&#x0430;&#x0431;&#x0432;&#x0433;&#x0434;&#x0435;&#x0436;&#x0437;&#x0438;&#x0439;&#x043A;&#x043B;&#x043C;&#x043D;&#x043E;&#x043F;&#x0440;&#x0441;&#x0442;&#x0443;&#x0444;&#x0445;&#x0446;&#x0447;&#x0448;&#x0449;&#x044C;&#x044D;&#x044E;&#x044F;&#x0454;&#x0456;&#x0457;&#x0490;&#x0491;
+##################################
+Armenian &#x0531;&#x0532;&#x0533;&#x0534;&#x0535;&#x0536;&#x0537;&#x0538;&#x0539;&#x053A;&#x053B;&#x053C;&#x053D;&#x053E;&#x053F;&#x0541;&#x0542;&#x0543;&#x0544;&#x0545;&#x0546;&#x0547;&#x0548;&#x0549;&#x054A;&#x054B;&#x054C;&#x054D;&#x054E;&#x054F;&#x0551;&#x0552;&#x0553;&#x0554;&#x0555;&#x0556;&#x055B;&#x055C;&#x055D;&#x055E;&#x055F;&#x0561;&#x0562;&#x0563;&#x0564;&#x0565;&#x0586;&#x0589;
+#Armenian1 &#x055A;&#x058A;
+#Characters not found in the UCS:
+# ARMENIAN ETERNITY SIGN
+#
+GeorgianOld &#x10A0;&#x10A1;&#x10A2;&#x10A3;&#x10A4;&#x10A5;&#x10A6;&#x10A7;&#x10A8;&#x10A9;&#x10AA;&#x10AB;&#x10AC;&#x10AD;&#x10AE;&#x10AF;&#x10B0;&#x10B1;&#x10B2;&#x10B3;&#x10B4;&#x10B5;&#x10B6;&#x10B7;&#x10B8;&#x10B9;&#x10BA;&#x10BB;&#x10BC;&#x10BD;&#x10BE;&#x10BF;&#x10C0;&#x10C1;&#x10C2;&#x10C3;&#x10C4;&#x10C5;
+Georgian &#x10D0;&#x10D1;&#x10D2;&#x10D3;&#x10D4;&#x10D5;&#x10D6;&#x10D7;&#x10D8;&#x10D9;&#x10DA;&#x10DB;&#x10DC;&#x10DD;&#x10DE;&#x10DF;&#x10E0;&#x10E1;&#x10E2;&#x10E3;&#x10E4;&#x10E5;&#x10E6;&#x10E7;&#x10E8;&#x10E9;&#x10EA;&#x10EB;&#x10EC;&#x10ED;&#x10EE;&#x10EF;&#x10F0;
+GeorgianArc &#x10F1;&#x10F2;&#x10F3;&#x10F4;&#x10F5;&#x10F6;
+GeorgianPunc &#x10FB;
+#
+GreekExt1 &#x0384;&#x0385;&#x0386;&#x00B7;&#x0388;&#x0389;&#x038A;&#x00BB;&#x038C;&#x00BD;&#x038E;&#x038F;&#x0390;
+Greek &#x0391;&#x0392;&#x0393;&#x0394;&#x0395;&#x0396;&#x0397;&#x0398;&#x0399;&#x039A;&#x039B;&#x039C;&#x039D;&#x039E;&#x039F;&#x03A0;&#x03A1;&#x03A3;&#x03A4;&#x03A5;&#x03A6;&#x03A7;&#x03A8;&#x03A9;&#x03B1;&#x03B2;&#x03B3;&#x03B4;&#x03B5;&#x03B6;&#x03B7;&#x03B8;&#x03B9;&#x03BA;&#x03BB;&#x03BC;&#x03BD;&#x03BE;&#x03BF;&#x03C0;&#x03C1;&#x03C3;&#x03C4;&#x03C5;&#x03C6;&#x03C7;&#x03C8;&#x03C9;
+GreekExt2 &#x03AA;&#x03AB;&#x03AC;&#x03AD;&#x03AE;&#x03AF;&#x03B0;&#x03CA;&#x03CB;&#x03CC;&#x03CD;&#x03CE;
+GreekExt4 &#x03C2;
+#
+Hebrew &#x05D0;&#x05D1;&#x05D2;&#x05D3;&#x05D4;&#x05D5;&#x05D6;&#x05D7;&#x05D8;&#x05D9;&#x05DA;&#x05DB;&#x05DC;&#x05DD;&#x05DE;&#x05DF;&#x05E0;&#x05E1;&#x05E2;&#x05E3;&#x05E4;&#x05E5;&#x05E6;&#x05E7;&#x05E8;&#x05E9;&#x05EA;
+##################################
+#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