Commit 39eb21ed authored by unknown's avatar unknown

Merge rkalimullin@work.mysql.com:/home/bk/mysql-4.1

into ram.(none):/home/ram/work/mysql-4.1.spatial


BitKeeper/etc/logging_ok:
  Logging to logging@openlogging.org accepted
parents e2e2e7c9 fd053b2e
......@@ -478,3 +478,4 @@ vio/test-ssl
vio/test-sslclient
vio/test-sslserver
vio/viotest-ssl
tests/client_test
......@@ -67,3 +67,6 @@ venu@work.mysql.com
worm@altair.is.lan
zak@balfor.local
zak@linux.local
venu@myvenu.com
walrus@mysql.com
ram@ram.(none)
......@@ -94,6 +94,7 @@
#undef HAVE_CHARSET_sjis
#undef HAVE_CHARSET_swe7
#undef HAVE_CHARSET_tis620
#undef HAVE_CHARSET_ucs2
#undef HAVE_CHARSET_ujis
#undef HAVE_CHARSET_usa7
#undef HAVE_CHARSET_utf8
......
......@@ -1942,10 +1942,10 @@ AC_DIVERT_PUSH(0)
CHARSETS_AVAILABLE="armscii8 big5 cp1251 cp1257
croat czech danish dec8 dos estonia euc_kr gb2312 gbk
german1 greek hebrew hp8 hungarian koi8_ru koi8_ukr
latin1 latin1_de latin2 latin5 sjis swe7 tis620 ujis
latin1 latin1_de latin2 latin5 sjis swe7 tis620 ucs2 ujis
usa7 utf8 win1250 win1250ch win1251ukr"
CHARSETS_DEPRECATED="win1251"
CHARSETS_COMPLEX="big5 czech euc_kr gb2312 gbk latin1_de sjis tis620 ujis utf8 win1250ch"
CHARSETS_COMPLEX="big5 czech euc_kr gb2312 gbk latin1_de sjis tis620 ucs2 ujis utf8 win1250ch"
DEFAULT_CHARSET=latin1
AC_DIVERT_POP
......@@ -2067,6 +2067,10 @@ do
tis620)
AC_DEFINE(HAVE_CHARSET_tis620)
;;
ucs2)
AC_DEFINE(HAVE_CHARSET_ucs2)
use_mb="yes"
;;
ujis)
AC_DEFINE(HAVE_CHARSET_ujis)
use_mb="yes"
......
......@@ -61,3 +61,17 @@ extern const char *client_errors[]; /* Error messages */
#define CR_PROBE_SLAVE_HOSTS 2023
#define CR_PROBE_SLAVE_CONNECT 2024
#define CR_PROBE_MASTER_CONNECT 2025
/* new 4.1 error codes */
#define CR_INVALID_CONN_HANDLE 2026
#define CR_NULL_POINTER 2027
#define CR_MEMORY_ERROR 2028
#define CR_NO_PREPARE_STMT 2029
#define CR_NOT_ALL_PARAMS_BOUND 2030
#define CR_DATA_TRUNCATED 2031
#define CR_NOT_ALL_BUFFERS_BOUND 2032
#define CR_FAILED_TO_SET_PARAM_DATA 2033
#define CR_NO_PARAMETERS_EXISTS 2033
#define CR_INVALID_PARAMETER_NO 2035
#define CR_INVALID_BUFFER_USE 2036
......@@ -287,6 +287,40 @@ void my_hash_sort_utf8(struct charset_info_st *cs, const uchar *key, uint len, u
#endif
#ifdef HAVE_CHARSET_ucs2
extern uchar ctype_ucs2[];
extern uchar to_lower_ucs2[];
extern uchar to_upper_ucs2[];
int my_strnncoll_ucs2(CHARSET_INFO *cs,
const uchar *s, uint s_len, const uchar *t, uint t_len);
int my_strnxfrm_ucs2(CHARSET_INFO *cs,
uchar *dest, uint destlen, const uchar *src, uint srclen);
int my_ismbchar_ucs2(CHARSET_INFO *cs, const char *b, const char *e);
my_bool my_ismbhead_ucs2(CHARSET_INFO * cs, uint ch);
int my_mbcharlen_ucs2(CHARSET_INFO *cs, uint c);
void my_caseup_str_ucs2(CHARSET_INFO * cs, char * s);
void my_casedn_str_ucs2(CHARSET_INFO *cs, char * s);
void my_caseup_ucs2(CHARSET_INFO *cs, char *s, uint len);
void my_casedn_ucs2(CHARSET_INFO *cs, char *s, uint len);
int my_strcasecmp_ucs2(CHARSET_INFO *cs, const char *s, const char *t);
int my_strncasecmp_ucs2(CHARSET_INFO *cs, const char *s,const char *t,uint l);
int my_ucs2_uni (CHARSET_INFO *cs, my_wc_t *p, const uchar *s, const uchar *e);
int my_uni_ucs2 (CHARSET_INFO *cs, my_wc_t wc, uchar *b, uchar *e);
uint my_hash_caseup_ucs2(struct charset_info_st *cs, const byte *key, uint len);
void my_hash_sort_ucs2(struct charset_info_st *cs, const uchar *key, uint len, ulong *nr1, ulong *nr2);
#endif
#define _U 01 /* Upper case */
#define _L 02 /* Lower case */
#define _NMR 04 /* Numeral (digit) */
......
......@@ -68,16 +68,17 @@ extern char *mysql_unix_port;
#define INTERNAL_NUM_FIELD(f) (((f)->type <= FIELD_TYPE_INT24 && ((f)->type != FIELD_TYPE_TIMESTAMP || (f)->length == 14 || (f)->length == 8)) || (f)->type == FIELD_TYPE_YEAR)
typedef struct st_mysql_field {
char *name; /* Name of column */
char *table; /* Table of column if column was a field */
char *org_table; /* Org table name if table was an alias */
char *db; /* Database for table */
char *def; /* Default value (set by mysql_list_fields) */
unsigned long length; /* Width of column */
unsigned long max_length; /* Max width of selected set */
unsigned int flags; /* Div flags */
unsigned int decimals; /* Number of decimals in field */
enum enum_field_types type; /* Type of field. Se mysql_com.h for types */
char *name; /* Name of column */
char *org_name; /* Original column name, if column was an alias */
char *table; /* Table of column if column was a field */
char *org_table; /* Org table name, if table was an alias */
char *db; /* Database for table */
char *def; /* Default value (set by mysql_list_fields) */
unsigned long length; /* Width of column */
unsigned long max_length; /* Max width of selected set */
unsigned int flags; /* Div flags */
unsigned int decimals; /* Number of decimals in field */
enum enum_field_types type; /* Type of field. Se mysql_com.h for types */
} MYSQL_FIELD;
typedef char **MYSQL_ROW; /* return data as array of strings */
......@@ -101,6 +102,23 @@ typedef struct st_mysql_rows {
typedef MYSQL_ROWS *MYSQL_ROW_OFFSET; /* offset to current row */
#include <my_alloc.h>
#ifndef ST_USED_MEM_DEFINED
#define ST_USED_MEM_DEFINED
typedef struct st_used_mem { /* struct for once_alloc */
struct st_used_mem *next; /* Next block in use */
unsigned int left; /* memory left in block */
unsigned int size; /* size of block */
} USED_MEM;
typedef struct st_mem_root {
USED_MEM *free;
USED_MEM *used;
USED_MEM *pre_alloc;
unsigned int min_malloc;
unsigned int block_size;
void (*error_handler)(void);
} MEM_ROOT;
#endif
typedef struct st_mysql_data {
my_ulonglong rows;
......@@ -391,6 +409,83 @@ int STDCALL mysql_manager_command(MYSQL_MANAGER* con,
int STDCALL mysql_manager_fetch_line(MYSQL_MANAGER* con,
char* res_buf,
int res_buf_size);
/*
The following definations are added for the enhanced
client-server protocol
*/
/* statement state */
enum MY_STMT_STATE { MY_ST_UNKNOWN, MY_ST_PREPARE, MY_ST_EXECUTE };
/* bind structure */
typedef struct st_mysql_bind {
enum enum_field_types buffer_type; /* buffer type */
enum enum_field_types field_type; /* field type */
gptr buffer; /* buffer */
long *length; /* output length pointer */
unsigned long buffer_length; /* buffer length */
unsigned long bind_length; /* internal use */
my_bool is_null; /* NULL indicator */
my_bool is_long_data; /* long data indicator */
my_bool long_ended; /* internal use */
} MYSQL_BIND;
/* statement handler */
typedef struct st_mysql_stmt {
MYSQL *mysql; /* connection handle */
MYSQL_BIND *params; /* input parameters */
MYSQL_RES *result; /* resultset */
MYSQL_BIND *bind; /* row binding */
MYSQL_FIELD *fields; /* prepare meta info */
MEM_ROOT mem_root; /* root allocations */
unsigned long param_count; /* parameters count */
unsigned long field_count; /* fields count */
unsigned long long_length; /* long buffer alloced length */
uint err_no; /* error code */
char error[MYSQL_ERRMSG_SIZE]; /* error message */
char *query; /* query buffer */
char *long_data; /* long buffer */
enum MY_STMT_STATE state; /* statement state */
my_bool long_alloced; /* flag to indicate long alloced */
my_bool types_supplied; /* to indicate types supply */
} MYSQL_STMT;
MYSQL_STMT * STDCALL mysql_prepare(MYSQL * mysql, const char *query);
int STDCALL mysql_execute(MYSQL_STMT * stmt);
unsigned long STDCALL mysql_param_count(MYSQL_STMT * stmt);
int STDCALL mysql_bind_param(MYSQL_STMT * stmt, MYSQL_BIND * bind);
int STDCALL mysql_bind_result(MYSQL_STMT * stmt, MYSQL_BIND * bind);
int STDCALL mysql_stmt_close(MYSQL_STMT * stmt);
uint STDCALL mysql_stmt_errno(MYSQL_STMT * stmt);
const char *STDCALL mysql_stmt_error(MYSQL_STMT * stmt);
int STDCALL mysql_commit(MYSQL * mysql);
int STDCALL mysql_rollback(MYSQL * mysql);
int STDCALL mysql_autocommit(MYSQL * mysql, my_bool auto_mode);
int STDCALL mysql_fetch(MYSQL_STMT *stmt);
my_bool STDCALL mysql_send_long_data(MYSQL_STMT *stmt,
uint param_number,gptr data,
unsigned long length);
int STDCALL mysql_multi_query(MYSQL *mysql,const char *query,unsigned long len);
MYSQL_RES *STDCALL mysql_next_result(MYSQL *mysql);
MYSQL_RES * STDCALL mysql_prepare_result(MYSQL_STMT *stmt);
/* new status messages */
#define MYSQL_SUCCESS 0
#define MYSQL_WARNING 1
#define MYSQL_ERROR -1
#define MYSQL_NO_DATA 100
#define MYSQL_NEED_DATA 99
#define MYSQL_LONG_DATA_END 0xFF
#define mysql_reload(mysql) mysql_refresh((mysql),REFRESH_GRANT)
#ifdef USE_OLD_FUNCTIONS
......
......@@ -42,7 +42,8 @@ enum enum_server_command {COM_SLEEP,COM_QUIT,COM_INIT_DB,COM_QUERY,
COM_DEBUG,COM_PING,COM_TIME,COM_DELAYED_INSERT,
COM_CHANGE_USER, COM_BINLOG_DUMP,
COM_TABLE_DUMP, COM_CONNECT_OUT,
COM_REGISTER_SLAVE};
COM_REGISTER_SLAVE,
COM_PREPARE,COM_EXECUTE,COM_LONG_DATA };
#define NOT_NULL_FLAG 1 /* Field can't be NULL */
#define PRI_KEY_FLAG 2 /* Field is part of a primary key */
......@@ -96,6 +97,7 @@ enum enum_server_command {COM_SLEEP,COM_QUIT,COM_INIT_DB,COM_QUERY,
#define CLIENT_SSL 2048 /* Switch to SSL after handshake */
#define CLIENT_IGNORE_SIGPIPE 4096 /* IGNORE sigpipes */
#define CLIENT_TRANSACTIONS 8192 /* Client knows about transactions */
#define CLIENT_PROTOCOL_41 16384 /* New 4.1 protocol */
#define SERVER_STATUS_IN_TRANS 1 /* Transaction has started */
#define SERVER_STATUS_AUTOCOMMIT 2 /* Server in auto_commit mode */
......@@ -136,27 +138,64 @@ typedef struct st_net {
#define packet_error (~(unsigned long) 0)
enum enum_field_types { FIELD_TYPE_DECIMAL, FIELD_TYPE_TINY,
FIELD_TYPE_SHORT, FIELD_TYPE_LONG,
FIELD_TYPE_FLOAT, FIELD_TYPE_DOUBLE,
FIELD_TYPE_NULL, FIELD_TYPE_TIMESTAMP,
FIELD_TYPE_LONGLONG,FIELD_TYPE_INT24,
FIELD_TYPE_DATE, FIELD_TYPE_TIME,
FIELD_TYPE_DATETIME, FIELD_TYPE_YEAR,
FIELD_TYPE_NEWDATE,
FIELD_TYPE_ENUM=247,
FIELD_TYPE_SET=248,
FIELD_TYPE_TINY_BLOB=249,
FIELD_TYPE_MEDIUM_BLOB=250,
FIELD_TYPE_LONG_BLOB=251,
FIELD_TYPE_BLOB=252,
FIELD_TYPE_VAR_STRING=253,
FIELD_TYPE_STRING=254,
FIELD_TYPE_GEOMETRY=255
enum enum_field_types { MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY,
MYSQL_TYPE_SHORT, MYSQL_TYPE_LONG,
MYSQL_TYPE_FLOAT, MYSQL_TYPE_DOUBLE,
MYSQL_TYPE_NULL, MYSQL_TYPE_TIMESTAMP,
MYSQL_TYPE_LONGLONG,MYSQL_TYPE_INT24,
MYSQL_TYPE_DATE, MYSQL_TYPE_TIME,
MYSQL_TYPE_DATETIME, MYSQL_TYPE_YEAR,
MYSQL_TYPE_NEWDATE,
MYSQL_TYPE_ENUM=247,
MYSQL_TYPE_SET=248,
MYSQL_TYPE_TINY_BLOB=249,
MYSQL_TYPE_MEDIUM_BLOB=250,
MYSQL_TYPE_LONG_BLOB=251,
MYSQL_TYPE_BLOB=252,
MYSQL_TYPE_VAR_STRING=253,
MYSQL_TYPE_STRING=254,
MYSQL_TYPE_GEOMETRY=255
};
#define FIELD_TYPE_CHAR FIELD_TYPE_TINY /* For compability */
#define FIELD_TYPE_INTERVAL FIELD_TYPE_ENUM /* For compability */
/* For backward compatibility */
#define FIELD_TYPE_DECIMAL MYSQL_TYPE_DECIMAL
#define FIELD_TYPE_TINY MYSQL_TYPE_TINY
#define FIELD_TYPE_SHORT MYSQL_TYPE_SHORT
#define FIELD_TYPE_LONG MYSQL_TYPE_LONG
#define FIELD_TYPE_FLOAT MYSQL_TYPE_FLOAT
#define FIELD_TYPE_DOUBLE MYSQL_TYPE_DOUBLE
#define FIELD_TYPE_NULL MYSQL_TYPE_NULL
#define FIELD_TYPE_TIMESTAMP MYSQL_TYPE_TIMESTAMP
#define FIELD_TYPE_LONGLONG MYSQL_TYPE_LONGLONG
#define FIELD_TYPE_INT24 MYSQL_TYPE_INT24
#define FIELD_TYPE_DATE MYSQL_TYPE_DATE
#define FIELD_TYPE_TIME MYSQL_TYPE_TIME
#define FIELD_TYPE_DATETIME MYSQL_TYPE_DATETIME
#define FIELD_TYPE_YEAR MYSQL_TYPE_YEAR
#define FIELD_TYPE_NEWDATE MYSQL_TYPE_NEWDATE
#define FIELD_TYPE_ENUM MYSQL_TYPE_ENUM
#define FIELD_TYPE_SET MYSQL_TYPE_SET
#define FIELD_TYPE_TINY_BLOB MYSQL_TYPE_TINY_BLOB
#define FIELD_TYPE_MEDIUM_BLOB MYSQL_TYPE_MEDIUM_BLOB
#define FIELD_TYPE_LONG_BLOB MYSQL_TYPE_LONG_BLOB
#define FIELD_TYPE_BLOB MYSQL_TYPE_BLOB
#define FIELD_TYPE_VAR_STRING MYSQL_TYPE_VAR_STRING
#define FIELD_TYPE_STRING MYSQL_TYPE_STRING
#define FIELD_TYPE_CHAR MYSQL_TYPE_TINY
#define FIELD_TYPE_INTERVAL MYSQL_TYPE_ENUM
#define FIELD_TYPE_GEOMETRY MYSQL_TYPE_GEOMETRY
#if TO_BE_INCLUDED_LATER
/* For bind applications, to indicate unsigned buffers */
#define MYSQL_TYPE_UTINY -10
#define MYSQL_TYPE_USHORT -9
#define MYSQL_TYPE_ULONG -8
#define MYSQL_TYPE_UFLOAT -7
#define MYSQL_TYPE_UDOUBLE -6
#define MYSQL_TYPE_ULONGLONG -5
#define MYSQL_TYPE_UINT24 -4
#endif
#define net_new_transaction(net) ((net)->pkt_nr=0)
......@@ -251,5 +290,6 @@ void my_thread_end(void);
#endif
#define NULL_LENGTH ((unsigned long) ~0) /* For net_store_length */
#define MYSQL_LONG_DATA_END 0xFF /* For indication of long data ending */
#endif
......@@ -49,7 +49,18 @@ const char *client_errors[]=
"Error on SHOW SLAVE STATUS:",
"Error on SHOW SLAVE HOSTS:",
"Error connecting to slave:",
"Error connecting to master:"
"Error connecting to master:",
"Invalid connection handle",
"Invalid use of null pointer",
"Memory allocation error",
"Statement not prepared",
"Not all parameters data supplied",
"Data truncated",
"Not all parameters bound for the row fetch",
"Failed to send the parameter data",
"No parameters exists in the statement",
"Invalid parameter number",
"Can't send long data for non string or binary data types"
};
/* Start of code added by Roberto M. Serqueira - martinsc@uol.com.br - 05.24.2001 */
......@@ -82,7 +93,18 @@ const char *client_errors[]=
"Error on SHOW SLAVE STATUS:",
"Error on SHOW SLAVE HOSTS:",
"Error connecting to slave:",
"Error connecting to master:"
"Error connecting to master:",
"Invalid connection handle",
"Invalid use of null pointer",
"Memory allocation error",
"Statement not prepared",
"Not all parameters data supplied",
"Data truncated",
"Not all parameters bound for the row fetch",
"Failed to send the parameter data",
"No parameters exists in the statement",
"Invalid parameter number",
"Can't send long data for non string or binary data types"
};
#else /* ENGLISH */
......@@ -113,7 +135,18 @@ const char *client_errors[]=
"Error on SHOW SLAVE STATUS:",
"Error on SHOW SLAVE HOSTS:",
"Error connecting to slave:",
"Error connecting to master:"
"Error connecting to master:",
"Invalid connection handle",
"Invalid use of null pointer",
"Memory allocation error",
"Statement not prepared",
"Not all parameters data supplied",
"Data truncated",
"Not all parameters bound for the row fetch",
"Failed to send the parameter data",
"No parameters exists in the statement",
"Invalid parameter number",
"Can't send long data for non string or binary data types"
};
#endif
......
This diff is collapsed.
......@@ -49,9 +49,10 @@ sqlsources = convert.cc derror.cc field.cc field_conv.cc filesort.cc \
opt_sum.cc procedure.cc records.cc sql_acl.cc \
repl_failsafe.cc slave.cc \
sql_analyse.cc sql_base.cc sql_cache.cc sql_class.cc \
sql_crypt.cc sql_db.cc sql_delete.cc sql_insert.cc sql_lex.cc \
sql_list.cc sql_manager.cc sql_map.cc sql_parse.cc sql_derived.cc \
sql_rename.cc sql_repl.cc sql_select.cc sql_do.cc sql_show.cc \
sql_crypt.cc sql_db.cc sql_delete.cc sql_error.cc sql_insert.cc \
sql_lex.cc sql_list.cc sql_manager.cc sql_map.cc sql_parse.cc \
sql_prepare.cc sql_derived.cc sql_rename.cc sql_repl.cc \
sql_select.cc sql_do.cc sql_show.cc \
sql_string.cc sql_table.cc sql_test.cc sql_udf.cc \
sql_update.cc sql_yacc.cc table.cc thr_malloc.cc time.cc \
unireg.cc uniques.cc stacktrace.c sql_union.cc hash_filo.cc \
......
......@@ -99,11 +99,20 @@ ha_checksum mi_unique_hash(MI_UNIQUEDEF *def, const byte *record)
end= pos+length;
if (type == HA_KEYTYPE_TEXT || type == HA_KEYTYPE_VARTEXT)
{
uchar *sort_order=keyseg->charset->sort_order;
while (pos != end)
crc=((crc << 8) +
(((uchar) sort_order[*(uchar*) pos++]))) +
(crc >> (8*sizeof(ha_checksum)-8));
if (keyseg->charset->hash_sort)
{
ulong nr=1, nr2=4;
keyseg->charset->hash_sort(keyseg->charset,(const uchar*)pos,length,&nr, &nr2);
crc=nr;
}
else
{
uchar *sort_order=keyseg->charset->sort_order;
while (pos != end)
crc=((crc << 8) +
(((uchar) sort_order[*(uchar*) pos++]))) +
(crc >> (8*sizeof(ha_checksum)-8));
}
}
else
while (pos != end)
......@@ -173,11 +182,19 @@ int mi_unique_comp(MI_UNIQUEDEF *def, const byte *a, const byte *b,
end= pos_a+length;
if (type == HA_KEYTYPE_TEXT || type == HA_KEYTYPE_VARTEXT)
{
uchar *sort_order=keyseg->charset->sort_order;
while (pos_a != end)
if (sort_order[*(uchar*) pos_a++] !=
sort_order[*(uchar*) pos_b++])
if (use_strcoll(keyseg->charset))
{
if (my_strnncoll(keyseg->charset,pos_a,length,pos_b,length))
return 1;
}
else
{
uchar *sort_order=keyseg->charset->sort_order;
while (pos_a != end)
if (sort_order[*(uchar*) pos_a++] !=
sort_order[*(uchar*) pos_b++])
return 1;
}
}
else
while (pos_a != end)
......
......@@ -32,7 +32,7 @@ result_file=$RESULT_DIR/$test_name.result
touch $result_file
echo "Running the test case against empty file, will fail, but don't worry"
./mysql-test-run --do-test=$test_name
./mysql-test-run --local $test_name
reject_file=$result_file.reject
......
This diff is collapsed.
......@@ -65,6 +65,21 @@ a
select b,(select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2) from t4;
b (select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2)
8 7.5000
8 6.0000
9 5.5000
8 4.5000
9 7.5000
select * from t3 where exists (select * from t2 where t2.b=t3.a);
a
7
select * from t3 where not exists (select * from t2 where t2.b=t3.a);
a
6
3
insert into t4 values (12,7),(1,7),(10,9),(9,6),(7,6),(3,9);
select b,max(a) as ma from t4 group by b having b < (select max(t2.a)
from t2 where t2.b=t4.b);
b ma
select b,max(a) as ma from t4 group by b having b >= (select max(t2.a)
from t2 where t2.b=t4.b);
b ma
7 12
drop table t1,t2,t3,t4;
This diff is collapsed.
......@@ -26,4 +26,11 @@ select * from t1 where t1.a=(select t2.a from t2 where t2.b=(select max(a) from
select * from t1 where t1.a=(select t2.a from t2 where t2.b=(select max(a) from t3 where t3.a > t1.a) order by 1 desc limit 1);
select * from t1 where t1.a=(select t2.a from t2 where t2.b=(select max(a) from t3 where t3.a < t1.a) order by 1 desc limit 1);
select b,(select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2) from t4;
select * from t3 where exists (select * from t2 where t2.b=t3.a);
select * from t3 where not exists (select * from t2 where t2.b=t3.a);
insert into t4 values (12,7),(1,7),(10,9),(9,6),(7,6),(3,9);
select b,max(a) as ma from t4 group by b having b < (select max(t2.a)
from t2 where t2.b=t4.b);
select b,max(a) as ma from t4 group by b having b >= (select max(t2.a)
from t2 where t2.b=t4.b);
drop table t1,t2,t3,t4;
......@@ -48,11 +48,11 @@ int main(int argc, char **argv) {
cs_list = list_charsets(MYF(MY_COMPILED_SETS | MY_CONFIG_SETS));
printf("LIST OF CHARSETS (compiled + *.conf):\n%s\n", cs_list);
free(cs_list);
my_free(cs_list,MYF(0));
cs_list = list_charsets(MYF(MY_INDEX_SETS | MY_LOADED_SETS));
printf("LIST OF CHARSETS (index + loaded):\n%s\n", cs_list);
free(cs_list);
my_free(cs_list,MYF(0));
return 0;
}
This diff is collapsed.
......@@ -67,6 +67,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc \
mysqld.cc password.c hash_filo.cc hostname.cc \
convert.cc sql_parse.cc sql_yacc.yy \
sql_base.cc table.cc sql_select.cc sql_insert.cc \
sql_prepare.cc sql_error.cc \
sql_update.cc sql_delete.cc uniques.cc sql_do.cc \
procedure.cc item_uniq.cc sql_test.cc \
log.cc log_event.cc init.cc derror.cc sql_acl.cc \
......
......@@ -279,8 +279,10 @@ void Field_num::add_zerofill_and_unsigned(String &res) const
void Field_num::make_field(Send_field *field)
{
field->db_name=table->table_cache_key ? table->table_cache_key : "";
field->org_table_name=table->real_name;
field->table_name=table_name;
field->col_name=field_name;
field->col_name=field->org_col_name=field_name;
field->length=field_length;
field->type=type();
field->flags=table->maybe_null ? (flags & ~NOT_NULL_FLAG) : flags;
......@@ -290,8 +292,10 @@ void Field_num::make_field(Send_field *field)
void Field_str::make_field(Send_field *field)
{
field->db_name=table->table_cache_key ? table->table_cache_key : "";
field->org_table_name=table->real_name;
field->table_name=table_name;
field->col_name=field_name;
field->col_name=field->org_col_name=field_name;
field->length=field_length;
field->type=type();
field->flags=table->maybe_null ? (flags & ~NOT_NULL_FLAG) : flags;
......@@ -3778,10 +3782,10 @@ uint Field_varstring::max_packed_col_length(uint max_length)
Field_blob::Field_blob(char *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,uint blob_pack_length,
bool binary_arg)
bool binary_arg, CHARSET_INFO *cs)
: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, default_charset_info),
table_arg, cs),
packlength(blob_pack_length),binary_flag(binary_arg), geom_flag(true)
{
flags|= BLOB_FLAG;
......@@ -3963,9 +3967,9 @@ String *Field_blob::val_str(String *val_buffer __attribute__((unused)),
char *blob;
memcpy_fixed(&blob,ptr+packlength,sizeof(char*));
if (!blob)
val_ptr->set("",0,default_charset_info); // A bit safer than ->length(0)
val_ptr->set("",0,field_charset); // A bit safer than ->length(0)
else
val_ptr->set((const char*) blob,get_length(ptr),default_charset_info);
val_ptr->set((const char*) blob,get_length(ptr),field_charset);
return val_ptr;
}
......@@ -4778,7 +4782,8 @@ Field *make_field(char *ptr, uint32 field_length,
if (f_is_blob(pack_flag))
return new Field_blob(ptr,null_pos,null_bit,
unireg_check, field_name, table,
pack_length,f_is_binary(pack_flag) != 0);
pack_length,f_is_binary(pack_flag) != 0,
default_charset_info);
if (f_is_geom(pack_flag))
return new Field_geom(ptr,null_pos,null_bit,
unireg_check, field_name, table,
......
......@@ -842,11 +842,11 @@ class Field_blob :public Field_str {
Field_blob(char *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,uint blob_pack_length,
bool binary_arg);
bool binary_arg, CHARSET_INFO *cs);
Field_blob(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg,
struct st_table *table_arg, bool binary_arg)
struct st_table *table_arg, bool binary_arg, CHARSET_INFO *cs)
:Field_str((char*) 0,len_arg, maybe_null_arg ? (uchar*) "": 0,0,
NONE, field_name_arg, table_arg, default_charset_info),
NONE, field_name_arg, table_arg, cs),
packlength(3),binary_flag(binary_arg), geom_flag(true)
{
flags|= BLOB_FLAG;
......@@ -930,11 +930,12 @@ class Field_geom :public Field_blob {
struct st_table *table_arg,uint blob_pack_length,
bool binary_arg)
:Field_blob(ptr_arg, null_ptr_arg, null_bit_arg, unireg_check_arg,
field_name_arg, table_arg, blob_pack_length,binary_arg) {}
field_name_arg, table_arg, blob_pack_length,binary_arg,
default_charset_info) {}
Field_geom(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg,
struct st_table *table_arg, bool binary_arg)
:Field_blob(len_arg, maybe_null_arg, field_name_arg,
table_arg, binary_arg) {}
table_arg, binary_arg, default_charset_info) {}
enum ha_base_keytype key_type() const { return HA_KEYTYPE_VARBINARY; }
void get_key_image(char *buff,uint length, imagetype type);
......@@ -1038,7 +1039,9 @@ class create_field :public Sql_alloc {
class Send_field {
public:
const char *table_name,*col_name;
const char *db_name;
const char *table_name,*org_table_name;
const char *col_name,*org_col_name;
uint length,flags,decimals;
enum_field_types type;
Send_field() {}
......
......@@ -508,7 +508,8 @@ void field_conv(Field *to,Field *from)
if (!blob->value.is_alloced() &&
from->real_type() != FIELD_TYPE_STRING)
blob->value.copy();
blob->store(blob->value.ptr(),blob->value.length(),default_charset_info);
blob->store(blob->value.ptr(),blob->value.length(),
to->binary()?default_charset_info:((Field_str*)to)->charset());
return;
}
if ((from->result_type() == STRING_RESULT &&
......@@ -520,7 +521,9 @@ void field_conv(Field *to,Field *from)
char buff[MAX_FIELD_WIDTH];
String result(buff,sizeof(buff),default_charset_info);
from->val_str(&result,&result);
to->store(result.c_ptr_quick(),result.length(),default_charset_info);
to->store(result.c_ptr_quick(),result.length(),
to->binary()?default_charset_info:((Field_str*)to)->charset());
// QQ: what to do if "from" and "to" are of dirrent charsets?
}
else if (from->result_type() == REAL_RESULT)
to->store(from->val_real());
......
......@@ -137,6 +137,7 @@ enum row_type { ROW_TYPE_NOT_USED=-1, ROW_TYPE_DEFAULT, ROW_TYPE_FIXED,
#define HA_CREATE_USED_MAX_ROWS 32
#define HA_CREATE_USED_AVG_ROW_LENGTH 64
#define HA_CREATE_USED_PACK_KEYS 128
#define HA_CREATE_USED_CHARSET 256
typedef struct st_thd_trans {
void *bdb_tid;
......
......@@ -133,6 +133,9 @@ void Item_field::set_field(Field *field_par)
field_name=field_par->field_name;
binary=field_par->binary();
unsigned_flag=test(field_par->flags & UNSIGNED_FLAG);
/* For string fields copy character set from original field */
if (!field_par->binary())
str_value.set_charset(((Field_str*)field_par)->charset());
}
const char *Item_ident::full_name() const
......@@ -287,6 +290,140 @@ String *Item_null::val_str(String *str)
{ null_value=1; return 0;}
/* Item_param related */
void Item_param::set_null()
{
maybe_null=null_value=1;
}
void Item_param::set_int(longlong i)
{
int_value=(longlong)i;
item_result_type = INT_RESULT;
item_type = INT_ITEM;
}
void Item_param::set_double(double i)
{
double value = (double)i;
real_value=value;
item_result_type = REAL_RESULT;
item_type = REAL_ITEM;
}
void Item_param::set_double(float i)
{
float value = (float)i;
real_value=(double)value;
item_result_type = REAL_RESULT;
item_type = REAL_ITEM;
}
void Item_param::set_value(const char *str, uint length)
{
str_value.set(str,length,default_charset_info);
item_result_type = STRING_RESULT;
item_type = STRING_ITEM;
}
void Item_param::set_longdata(const char *str, ulong length)
{
/* TODO: Fix this for binary handling by making use of
buffer_type..
*/
str_value.append(str,length);
}
void Item_param::set_long_end()
{
long_data_supplied = true;
item_result_type = STRING_RESULT;
};
bool Item_param::save_in_field(Field *field)
{
if (null_value)
return set_field_to_null(field);
field->set_notnull();
if (item_result_type == INT_RESULT)
{
longlong nr=val_int();
field->store(nr);
return 0;
}
if (item_result_type == REAL_RESULT)
{
double nr=val();
field->store(nr);
return 0;
}
String *result;
CHARSET_INFO *cs=default_charset_info;//fix this
result=val_str(&str_value);
field->store(result->ptr(),result->length(),cs);
return 0;
}
void Item_param::make_field(Send_field *tmp_field)
{
init_make_field(tmp_field,FIELD_TYPE_STRING);
}
double Item_param::val()
{
/* Cross check whether we need need this conversions ? or direct
return(real_value) is enough ?
*/
switch(item_result_type) {
case STRING_RESULT:
return (double)atof(str_value.ptr());
case INT_RESULT:
return (double)int_value;
default:
return real_value;
}
}
longlong Item_param::val_int()
{
/* Cross check whether we need need this conversions ? or direct
return(int_value) is enough ?
*/
switch(item_result_type) {
case STRING_RESULT:
return (longlong)strtoll(str_value.ptr(),(char**) 0,10);
case REAL_RESULT:
return (longlong) (real_value+(real_value > 0 ? 0.5 : -0.5));
default:
return int_value;
}
}
String *Item_param::val_str(String* str)
{
/* Cross check whether we need need this conversions ? or direct
return(&str_value) is enough ?
*/
switch(item_result_type) {
case INT_RESULT:
str->set(int_value);
return str;
case REAL_RESULT:
str->set(real_value);
return str;
default:
return (String*) &str_value;
}
}
/* End of Item_param related */
void Item_copy_string::copy()
{
String *res=item->val_str(&str_value);
......@@ -309,12 +446,13 @@ String *Item_copy_string::val_str(String *str)
/* ARGSUSED */
bool Item::fix_fields(THD *thd,
struct st_table_list *list)
struct st_table_list *list,
Item ** ref)
{
return 0;
}
bool Item_field::fix_fields(THD *thd,TABLE_LIST *tables)
bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{
if (!field) // If field is not checked
{
......@@ -330,7 +468,7 @@ bool Item_field::fix_fields(THD *thd,TABLE_LIST *tables)
mention of table name, but if we join tables in one list it will
cause error ER_NON_UNIQ_ERROR in find_field_in_tables.
*/
SELECT_LEX *last;
SELECT_LEX *last= 0;
for (SELECT_LEX *sl= thd->lex.select->outer_select();
sl && !tmp;
sl= sl->outer_select())
......@@ -339,6 +477,8 @@ bool Item_field::fix_fields(THD *thd,TABLE_LIST *tables)
if (!tmp)
return 1;
else
{
depended_from= last;
/*
Mark all selects from resolved to 1 before select where was
found table as depended (of select where was found table)
......@@ -356,6 +496,7 @@ bool Item_field::fix_fields(THD *thd,TABLE_LIST *tables)
tbl= tbl->next)
tbl->shared= 1;
}
}
}
set_field(tmp);
}
......@@ -367,13 +508,24 @@ bool Item_field::fix_fields(THD *thd,TABLE_LIST *tables)
table->used_fields++;
table->used_keys&=field->part_of_key;
}
if (depended_from != 0 && depended_from->having_fix_field)
{
*ref= new Item_ref((char *)db_name, (char *)table_name,
(char *)field_name);
if (!*ref)
return 1;
return (*ref)->fix_fields(thd, tables, ref);
}
return 0;
}
void Item::init_make_field(Send_field *tmp_field,
enum enum_field_types field_type)
{
{
tmp_field->db_name=(char*) "";
tmp_field->org_table_name=(char*) "";
tmp_field->org_col_name=(char*) "";
tmp_field->table_name=(char*) "";
tmp_field->col_name=name;
tmp_field->flags=maybe_null ? 0 : NOT_NULL_FLAG;
......@@ -647,12 +799,50 @@ bool Item_null::send(THD *thd, String *packet)
Find field in select list having the same name
*/
bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables)
bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
{
if (!ref)
{
if (!(ref=find_item_in_list(this,thd->lex.select->item_list)))
return 1;
if (!(ref= find_item_in_list(this,thd->lex.select->item_list)))
{
/*
We can't find table field in table list of current select,
consequently we have to find it in outer subselect(s).
We can't join lists of outer & current select, because of scope
of view rules. For example if both tables (outer & current) have
field 'field' it is not mistake to refer to this field without
mention of table name, but if we join tables in one list it will
cause error ER_NON_UNIQ_ERROR in find_field_in_tables.
*/
SELECT_LEX *last=0;
for (SELECT_LEX *sl= thd->lex.select->outer_select();
sl && !ref;
sl= sl->outer_select())
ref= find_item_in_list(this, (last= sl)->item_list);
if (!ref)
return 1;
else
{
depended_from= last;
/*
Mark all selects from resolved to 1 before select where was
found table as depended (of select where was found table)
*/
for (SELECT_LEX *s= thd->lex.select;
s &&s != last;
s= s->outer_select())
if( !s->depended )
{
s->depended= 1; //Select is depended of outer select
//Tables will be reopened many times
for (TABLE_LIST *tbl=
(TABLE_LIST*)s->table_list.first;
tbl;
tbl= tbl->next)
tbl->shared= 1;
}
}
}
max_length= (*ref)->max_length;
maybe_null= (*ref)->maybe_null;
decimals= (*ref)->decimals;
......
......@@ -52,7 +52,7 @@ class Item {
virtual ~Item() { name=0; } /*lint -e1509 */
void set_name(char* str,uint length=0);
void init_make_field(Send_field *tmp_field,enum enum_field_types type);
virtual bool fix_fields(THD *,struct st_table_list *);
virtual bool fix_fields(THD *, struct st_table_list *, Item **);
virtual bool save_in_field(Field *field);
virtual void save_org_in_field(Field *field)
{ (void) save_in_field(field); }
......@@ -85,15 +85,18 @@ class Item {
};
class st_select_lex;
class Item_ident :public Item
{
public:
const char *db_name;
const char *table_name;
const char *field_name;
st_select_lex *depended_from;
Item_ident(const char *db_name_par,const char *table_name_par,
const char *field_name_par)
:db_name(db_name_par),table_name(table_name_par),field_name(field_name_par)
:db_name(db_name_par),table_name(table_name_par),
field_name(field_name_par), depended_from(0)
{ name = (char*) field_name_par; }
const char *full_name() const;
};
......@@ -120,7 +123,7 @@ class Item_field :public Item_ident
String *str_result(String* tmp);
bool send(THD *thd, String *str_arg) { return result_field->send(thd,str_arg); }
void make_field(Send_field *field);
bool fix_fields(THD *,struct st_table_list *);
bool fix_fields(THD *, struct st_table_list *, Item **);
bool save_in_field(Field *field);
void save_org_in_field(Field *field);
table_map used_tables() const;
......@@ -155,6 +158,40 @@ class Item_null :public Item
bool is_null() { return 1; }
};
class Item_param :public Item
{
public:
longlong int_value;
double real_value;
enum Item_result item_result_type;
enum Type item_type;
enum enum_field_types buffer_type;
my_bool long_data_supplied;
Item_param(char *name_par=0){
name= name_par ? name_par : (char*) "?";
long_data_supplied = false;
item_type = STRING_ITEM; item_result_type = STRING_RESULT;
}
enum Type type() const { return item_type; }
double val();
longlong val_int();
String *val_str(String*);
void make_field(Send_field *field);
bool save_in_field(Field *field);
void set_null();
void set_int(longlong i);
void set_double(float i);
void set_double(double i);
void set_value(const char *str, uint length);
void set_long_str(const char *str, ulong length);
void set_long_binary(const char *str, ulong length);
void set_longdata(const char *str, ulong length);
void set_long_end();
enum Item_result result_type () const
{ return item_result_type; }
Item *new_item() { return new Item_param(name); }
};
class Item_int :public Item
{
......@@ -356,7 +393,7 @@ class Item_ref :public Item_ident
}
bool send(THD *thd, String *tmp) { return (*ref)->send(thd, tmp); }
void make_field(Send_field *field) { (*ref)->make_field(field); }
bool fix_fields(THD *,struct st_table_list *);
bool fix_fields(THD *, struct st_table_list *, Item **);
bool save_in_field(Field *field) { return (*ref)->save_in_field(field); }
void save_org_in_field(Field *field) { (*ref)->save_org_in_field(field); }
enum Item_result result_type () const { return (*ref)->result_type(); }
......
......@@ -727,12 +727,12 @@ double Item_func_case::val()
bool
Item_func_case::fix_fields(THD *thd,TABLE_LIST *tables)
Item_func_case::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{
if (first_expr && first_expr->fix_fields(thd,tables) ||
else_expr && else_expr->fix_fields(thd,tables))
if (first_expr && first_expr->fix_fields(thd, tables, &first_expr) ||
else_expr && else_expr->fix_fields(thd, tables, &else_expr))
return 1;
if (Item_func::fix_fields(thd,tables))
if (Item_func::fix_fields(thd, tables, ref))
return 1;
if (first_expr)
{
......@@ -1074,7 +1074,7 @@ longlong Item_func_bit_and::val_int()
bool
Item_cond::fix_fields(THD *thd,TABLE_LIST *tables)
Item_cond::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{
List_iterator<Item> li(list);
Item *item;
......@@ -1096,7 +1096,7 @@ Item_cond::fix_fields(THD *thd,TABLE_LIST *tables)
#endif
item= *li.ref(); // new current item
}
if (item->fix_fields(thd,tables))
if (item->fix_fields(thd, tables, li.ref()))
return 1; /* purecov: inspected */
used_tables_cache|=item->used_tables();
with_sum_func= with_sum_func || item->with_sum_func;
......@@ -1272,9 +1272,9 @@ Item_func::optimize_type Item_func_like::select_optimize() const
return OPTIMIZE_NONE;
}
bool Item_func_like::fix_fields(THD *thd,struct st_table_list *tlist)
bool Item_func_like::fix_fields(THD *thd, TABLE_LIST *tlist, Item ** ref)
{
if (Item_bool_func2::fix_fields(thd, tlist))
if (Item_bool_func2::fix_fields(thd, tlist, ref))
return 1;
/*
......@@ -1324,9 +1324,10 @@ bool Item_func_like::fix_fields(THD *thd,struct st_table_list *tlist)
#ifdef USE_REGEX
bool
Item_func_regex::fix_fields(THD *thd,TABLE_LIST *tables)
Item_func_regex::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{
if (args[0]->fix_fields(thd,tables) || args[1]->fix_fields(thd,tables))
if (args[0]->fix_fields(thd, tables, args) ||
args[1]->fix_fields(thd,tables, args + 1))
return 1; /* purecov: inspected */
with_sum_func=args[0]->with_sum_func || args[1]->with_sum_func;
max_length=1; decimals=0;
......
......@@ -177,9 +177,10 @@ class Item_func_interval :public Item_int_func
Item_func_interval(Item *a,List<Item> &list)
:Item_int_func(list),item(a),intervals(0) {}
longlong val_int();
bool fix_fields(THD *thd,struct st_table_list *tlist)
bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref)
{
return (item->fix_fields(thd,tlist) || Item_func::fix_fields(thd,tlist));
return (item->fix_fields(thd, tlist, &item) ||
Item_func::fix_fields(thd, tlist, ref));
}
void fix_length_and_dec();
~Item_func_interval() { delete item; }
......@@ -259,7 +260,7 @@ class Item_func_case :public Item_func
enum Item_result result_type () const { return cached_result_type; }
const char *func_name() const { return "case"; }
void print(String *str);
bool fix_fields(THD *thd,struct st_table_list *tlist);
bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref);
Item *find_item(String *str);
};
......@@ -409,9 +410,10 @@ class Item_func_in :public Item_int_func
Item_func_in(Item *a,List<Item> &list)
:Item_int_func(list),item(a),array(0),in_item(0) {}
longlong val_int();
bool fix_fields(THD *thd,struct st_table_list *tlist)
bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref)
{
return (item->fix_fields(thd,tlist) || Item_func::fix_fields(thd,tlist));
return (item->fix_fields(thd, tlist, &item) ||
Item_func::fix_fields(thd, tlist, ref));
}
void fix_length_and_dec();
~Item_func_in() { delete item; delete array; delete in_item; }
......@@ -505,7 +507,7 @@ class Item_func_like :public Item_bool_func2
cond_result eq_cmp_result() const { return COND_TRUE; }
const char *func_name() const { return "like"; }
void fix_length_and_dec();
bool fix_fields(THD *thd,struct st_table_list *tlist);
bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref);
};
#ifdef USE_REGEX
......@@ -523,7 +525,7 @@ class Item_func_regex :public Item_bool_func
regex_compiled(0),regex_is_const(0) {}
~Item_func_regex();
longlong val_int();
bool fix_fields(THD *thd,struct st_table_list *tlist);
bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref);
const char *func_name() const { return "regex"; }
};
......@@ -552,7 +554,7 @@ class Item_cond :public Item_bool_func
{ list.push_back(i1); list.push_back(i2); }
~Item_cond() { list.delete_elements(); }
bool add(Item *item) { return list.push_back(item); }
bool fix_fields(THD *,struct st_table_list *);
bool fix_fields(THD *, struct st_table_list *, Item **ref);
enum Type type() const { return COND_ITEM; }
List<Item>* argument_list() { return &list; }
......
......@@ -58,7 +58,7 @@ Item_func::Item_func(List<Item> &list)
}
bool
Item_func::fix_fields(THD *thd,TABLE_LIST *tables)
Item_func::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{
Item **arg,**arg_end;
char buff[STACK_BUFF_ALLOC]; // Max argument in function
......@@ -72,12 +72,23 @@ Item_func::fix_fields(THD *thd,TABLE_LIST *tables)
{ // Print purify happy
for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++)
{
if ((*arg)->fix_fields(thd,tables))
if ((*arg)->fix_fields(thd, tables, arg))
return 1; /* purecov: inspected */
if ((*arg)->maybe_null)
maybe_null=1;
if ((*arg)->binary)
binary=1;
/*
Change charset to arg charset if it is not equal to
default_charset_info. This will work for many cases,
but generally this should be done more carefull. Each string
function should have it's own fix_fields() method to correctly
setup it's result's character set taking in account arguments.
For example: left(a,b) should take in account only first argument,
but ignore the second one.
*/
if ((*arg)->str_value.charset() != default_charset_info)
str_value.set_charset((*arg)->str_value.charset());
with_sum_func= with_sum_func || (*arg)->with_sum_func;
used_tables_cache|=(*arg)->used_tables();
const_item_cache&= (*arg)->const_item();
......@@ -1091,7 +1102,7 @@ udf_handler::~udf_handler()
bool
udf_handler::fix_fields(THD *thd,TABLE_LIST *tables,Item_result_field *func,
udf_handler::fix_fields(THD *thd, TABLE_LIST *tables, Item_result_field *func,
uint arg_count, Item **arguments)
{
char buff[STACK_BUFF_ALLOC]; // Max argument in function
......@@ -1135,7 +1146,7 @@ udf_handler::fix_fields(THD *thd,TABLE_LIST *tables,Item_result_field *func,
arg != arg_end ;
arg++,i++)
{
if ((*arg)->fix_fields(thd,tables))
if ((*arg)->fix_fields(thd, tables, arg))
return 1;
if ((*arg)->binary)
func->binary=1;
......@@ -1754,11 +1765,12 @@ static user_var_entry *get_variable(HASH *hash, LEX_STRING &name,
}
bool Item_func_set_user_var::fix_fields(THD *thd,TABLE_LIST *tables)
bool Item_func_set_user_var::fix_fields(THD *thd, TABLE_LIST *tables,
Item **ref)
{
if (!thd)
thd=current_thd;
if (Item_func::fix_fields(thd,tables) ||
if (Item_func::fix_fields(thd, tables, ref) ||
!(entry= get_variable(&thd->user_vars, name, 1)))
return 1;
entry->update_query_id=thd->query_id;
......@@ -2084,7 +2096,7 @@ void Item_func_match::init_search(bool no_order)
}
}
bool Item_func_match::fix_fields(THD *thd,struct st_table_list *tlist)
bool Item_func_match::fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
{
List_iterator<Item> li(fields);
Item *item;
......@@ -2097,7 +2109,7 @@ bool Item_func_match::fix_fields(THD *thd,struct st_table_list *tlist)
modifications to find_best and auto_close as complement to auto_init code
above.
*/
if (Item_func::fix_fields(thd,tlist) || !const_item())
if (Item_func::fix_fields(thd, tlist, ref) || !const_item())
{
my_error(ER_WRONG_ARGUMENTS,MYF(0),"AGAINST");
return 1;
......@@ -2105,7 +2117,7 @@ bool Item_func_match::fix_fields(THD *thd,struct st_table_list *tlist)
while ((item=li++))
{
if (item->fix_fields(thd,tlist))
if (item->fix_fields(thd, tlist, li.ref()))
return 1;
if (item->type() == Item::REF_ITEM)
li.replace(item= *((Item_ref *)item)->ref);
......
......@@ -99,7 +99,7 @@ class Item_func :public Item_result_field
}
Item_func(List<Item> &list);
~Item_func() {} /* Nothing to do; Items are freed automaticly */
bool fix_fields(THD *,struct st_table_list *);
bool fix_fields(THD *,struct st_table_list *, Item **ref);
void make_field(Send_field *field);
table_map used_tables() const;
void update_used_tables();
......@@ -567,9 +567,10 @@ class Item_func_field :public Item_int_func
Item_func_field(Item *a,List<Item> &list) :Item_int_func(list),item(a) {}
~Item_func_field() { delete item; }
longlong val_int();
bool fix_fields(THD *thd,struct st_table_list *tlist)
bool fix_fields(THD *thd,struct st_table_list *tlist, Item **ref)
{
return (item->fix_fields(thd,tlist) || Item_func::fix_fields(thd,tlist));
return (item->fix_fields(thd, tlist, &item) ||
Item_func::fix_fields(thd, tlist, ref));
}
void update_used_tables()
{
......@@ -708,11 +709,11 @@ class Item_udf_func :public Item_func
: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)
bool fix_fields(THD *thd, struct st_table_list *tables, Item **ref)
{
bool res=udf.fix_fields(thd,tables,this,arg_count,args);
used_tables_cache=udf.used_tables_cache;
const_item_cache=udf.const_item_cache;
bool res= udf.fix_fields(thd, tables, this, arg_count, args);
used_tables_cache= udf.used_tables_cache;
const_item_cache= udf.const_item_cache;
return res;
}
Item_result result_type () const { return udf.result_type(); }
......@@ -867,7 +868,7 @@ class Item_func_set_user_var :public Item_func
void update_hash(void *ptr, uint length, enum Item_result type);
bool update();
enum Item_result result_type () const { return cached_result_type; }
bool fix_fields(THD *thd,struct st_table_list *tables);
bool fix_fields(THD *thd, struct st_table_list *tables, Item **ref);
void fix_length_and_dec();
void print(String *str);
const char *func_name() const { return "set_user_var"; }
......@@ -941,7 +942,7 @@ class Item_func_match :public Item_real_func
}
enum Functype functype() const { return FT_FUNC; }
void update_used_tables() {}
bool fix_fields(THD *thd,struct st_table_list *tlist);
bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref);
bool eq(const Item *, bool binary_cmp) const;
longlong val_int() { return val()!=0.0; }
double val();
......
......@@ -759,6 +759,7 @@ String *Item_func_left::val_str(String *str)
if (!res->alloced_length())
{ // Don't change const str
str_value= *res; // Not malloced string
str_value.set_charset(res->charset());
res= &str_value;
}
res->length((uint) length);
......@@ -1791,6 +1792,7 @@ String *Item_func_conv_charset::val_str(String *str)
null_value=1;
return 0;
}
null_value=0;
from=arg->charset();
to=conv_charset;
......@@ -1798,7 +1800,7 @@ String *Item_func_conv_charset::val_str(String *str)
s=(const uchar*)arg->ptr();
se=s+arg->length();
dmaxlen=arg->length()*(conv_charset->mbmaxlen?conv_charset->mbmaxlen:1)+1;
dmaxlen=arg->length()*(to->mbmaxlen?to->mbmaxlen:1)+1;
str->alloc(dmaxlen);
d0=d=(unsigned char*)str->ptr();
de=d+dmaxlen;
......@@ -1840,7 +1842,7 @@ String *Item_func_conv_charset::val_str(String *str)
void Item_func_conv_charset::fix_length_and_dec()
{
/* BAR TODO: What to do here??? */
max_length = args[0]->max_length*(conv_charset->mbmaxlen?conv_charset->mbmaxlen:1);
}
......@@ -1910,9 +1912,41 @@ String *Item_func_conv_charset3::val_str(String *str)
return str;
}
bool Item_func_conv_charset::fix_fields(THD *thd,struct st_table_list *tables)
{
char buff[STACK_BUFF_ALLOC]; // Max argument in function
binary=0;
used_tables_cache=0;
const_item_cache=1;
if (thd && check_stack_overrun(thd,buff))
return 0; // Fatal error if flag is set!
if (args[0]->fix_fields(thd, tables, args))
return 1;
maybe_null=args[0]->maybe_null;
binary=args[0]->binary;
const_item_cache=args[0]->const_item();
str_value.set_charset(conv_charset);
fix_length_and_dec();
return 0;
}
void Item_func_conv_charset3::fix_length_and_dec()
{
/* BAR TODO: What to do here??? */
max_length = args[0]->max_length;
}
String *Item_func_charset::val_str(String *str)
{
String *res = args[0]->val_str(str);
if ((null_value=(args[0]->null_value || !res->charset())))
return 0;
str->copy(res->charset()->name,strlen(res->charset()->name));
return str;
}
......
......@@ -40,9 +40,10 @@ class Item_str_func :public Item_func
if (!t_arg)
return result_field;
return (max_length > 255) ?
(Field *)new Field_blob(max_length,maybe_null, name,t_arg, binary) :
(Field *)new Field_blob(max_length,maybe_null, name,t_arg, binary,
str_value.charset()) :
(Field *) new Field_string(max_length,maybe_null, name,t_arg, binary,
default_charset_info);
str_value.charset());
}
};
......@@ -79,10 +80,10 @@ class Item_func_concat_ws :public Item_str_func
String *val_str(String *);
void fix_length_and_dec();
void update_used_tables();
bool fix_fields(THD *thd,struct st_table_list *tlist)
bool fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
{
return (separator->fix_fields(thd,tlist)
|| Item_func::fix_fields(thd,tlist));
return (separator->fix_fields(thd, tlist, &separator)
|| Item_func::fix_fields(thd, tlist, ref));
}
const char *func_name() const { return "concat_ws"; }
};
......@@ -325,9 +326,10 @@ class Item_func_elt :public Item_str_func
double val();
longlong val_int();
String *val_str(String *str);
bool fix_fields(THD *thd,struct st_table_list *tlist)
bool fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
{
return (item->fix_fields(thd,tlist) || Item_func::fix_fields(thd,tlist));
return (item->fix_fields(thd, tlist, &item) ||
Item_func::fix_fields(thd, tlist, ref));
}
void fix_length_and_dec();
void update_used_tables();
......@@ -344,9 +346,10 @@ class Item_func_make_set :public Item_str_func
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,struct st_table_list *tlist)
bool fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
{
return (item->fix_fields(thd,tlist) || Item_func::fix_fields(thd,tlist));
return (item->fix_fields(thd, tlist, &item) ||
Item_func::fix_fields(thd, tlist, ref));
}
void fix_length_and_dec();
void update_used_tables();
......@@ -488,6 +491,7 @@ class Item_func_conv_charset :public Item_str_func
{
conv_charset=cs;
}
bool fix_fields(THD *thd,struct st_table_list *tables);
String *val_str(String *);
void fix_length_and_dec();
const char *func_name() const { return "conv_charset"; }
......@@ -503,6 +507,18 @@ class Item_func_conv_charset3 :public Item_str_func
const char *func_name() const { return "conv_charset3"; }
};
class Item_func_charset :public Item_str_func
{
public:
Item_func_charset(Item *a) :Item_str_func(a) {}
String *val_str(String *);
const char *func_name() const { return "charset"; }
void fix_length_and_dec()
{
max_length=20; // should be enough
};
};
/*******************************************************
Spatial functions
......
......@@ -35,12 +35,13 @@ SUBSELECT TODO:
#include "mysql_priv.h"
#include "sql_select.h"
Item_subselect::Item_subselect(THD *thd, st_select_lex *select_lex):
Item_subselect::Item_subselect(THD *thd, st_select_lex *select_lex,
select_subselect *result):
assigned(0), executed(0), optimized(0), error(0)
{
DBUG_ENTER("Item_subselect::Item_subselect");
DBUG_PRINT("subs", ("select_lex 0x%xl", (long) select_lex));
result= new select_subselect(this);
this->result= result;
SELECT_LEX_UNIT *unit= select_lex->master_unit();
unit->offset_limit_cnt= unit->global_parameters->offset_limit;
unit->select_limit_cnt= unit->global_parameters->select_limit+
......@@ -51,41 +52,15 @@ Item_subselect::Item_subselect(THD *thd, st_select_lex *select_lex):
select_lex->options&= ~OPTION_FOUND_ROWS;
join= new JOIN(thd, select_lex->item_list, select_lex->options, result);
this->select_lex= select_lex;
maybe_null= 1;
assign_null();
/*
item value is NULL if select_subselect not changed this value
(i.e. some rows will be found returned)
*/
assign_null();
null_value= 1;
DBUG_VOID_RETURN;
}
Item::Type Item_subselect::type() const
{
return SUBSELECT_ITEM;
}
double Item_subselect::val ()
{
if (exec())
return 0;
return real_value;
}
longlong Item_subselect::val_int ()
{
if (exec())
return 0;
return int_value;
}
String *Item_subselect::val_str (String *str)
{
if (exec() || null_value)
return 0;
return &str_value;
}
void Item_subselect::make_field (Send_field *tmp_field)
{
if (null_value)
......@@ -100,17 +75,10 @@ void Item_subselect::make_field (Send_field *tmp_field)
}
}
bool Item_subselect::fix_fields(THD *thd,TABLE_LIST *tables)
bool Item_subselect::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{
if (thd->having_fix_field)
{
//TODO: subselects in having do not suported now
my_printf_error(ER_SYNTAX_ERROR, ER(ER_SYNTAX_ERROR), MYF(0));
return 1;
}
// Is it one field subselect?
if (select_lex->item_list.elements != 1)
if (select_lex->item_list.elements > max_columns)
{
my_printf_error(ER_SUBSELECT_NO_1_COL, ER(ER_SUBSELECT_NO_1_COL), MYF(0));
return 1;
......@@ -131,13 +99,14 @@ bool Item_subselect::fix_fields(THD *thd,TABLE_LIST *tables)
int Item_subselect::exec()
{
DBUG_ENTER("Item_subselect::exec");
if (!optimized)
{
optimized=1;
if (join->optimize())
{
executed= 1;
return (join->error?join->error:1);
DBUG_RETURN(join->error?join->error:1);
}
}
if (join->select_lex->depended && executed)
......@@ -145,7 +114,7 @@ int Item_subselect::exec()
if (join->reinit())
{
error= 1;
return 1;
DBUG_RETURN(1);
}
assign_null();
executed= assigned= 0;
......@@ -157,7 +126,80 @@ int Item_subselect::exec()
join->exec();
join->thd->lex.select= save_select;
executed= 1;
return join->error;
DBUG_RETURN(join->error);
}
return 0;
DBUG_RETURN(0);
}
inline table_map Item_subselect::used_tables() const
{
return (table_map) select_lex->depended ? 1L : 0L;
}
Item_singleval_subselect::Item_singleval_subselect(THD *thd,
st_select_lex *select_lex):
Item_subselect(thd, select_lex, new select_singleval_subselect(this))
{
max_columns= 1;
maybe_null= 1;
}
Item::Type Item_subselect::type() const
{
return SUBSELECT_ITEM;
}
double Item_singleval_subselect::val ()
{
if (exec())
return 0;
return real_value;
}
longlong Item_singleval_subselect::val_int ()
{
if (exec())
return 0;
return int_value;
}
String *Item_singleval_subselect::val_str (String *str)
{
if (exec() || null_value)
return 0;
return &str_value;
}
Item_exists_subselect::Item_exists_subselect(THD *thd,
st_select_lex *select_lex):
Item_subselect(thd, select_lex, new select_singleval_subselect(this))
{
max_columns= UINT_MAX;
null_value= 0; //can't be NULL
maybe_null= 0; //can't be NULL
value= 0;
select_lex->select_limit= 1; // we need only 1 row to determinate existence
}
double Item_exists_subselect::val ()
{
if (exec())
return 0;
return (double) value;
}
longlong Item_exists_subselect::val_int ()
{
if (exec())
return 0;
return value;
}
String *Item_exists_subselect::val_str(String *str)
{
if (exec())
return 0;
str->set(value);
return str;
}
......@@ -20,46 +20,38 @@
#pragma interface /* gcc class implementation */
#endif
struct st_select_lex;
class st_select_lex;
class JOIN;
class select_subselect;
/* simple (not depended of covered select ) subselect */
/* base class for subselects */
class Item_subselect :public Item
{
protected:
longlong int_value;
double real_value;
uint max_columns;
my_bool assigned; /* value already assigned to subselect */
my_bool executed; /* simple subselect is executed */
my_bool optimized; /* simple subselect is optimized */
my_bool error; /* error in query */
enum Item_result res_type;
int exec();
void assign_null()
virtual void assign_null()
{
null_value= 1;
int_value= 0;
real_value= 0;
max_length= 4;
res_type= STRING_RESULT;
}
public:
st_select_lex *select_lex;
JOIN *join;
select_subselect *result;
Item_subselect(THD *thd, st_select_lex *select_lex);
Item_subselect(THD *thd, st_select_lex *select_lex,
select_subselect* result);
Item_subselect(Item_subselect *item)
{
null_value= item->null_value;
int_value= item->int_value;
real_value= item->real_value;
max_length= item->max_length;
decimals= item->decimals;
res_type= item->res_type;
max_columns= item->max_columns;
assigned= item->assigned;
executed= item->executed;
select_lex= item->select_lex;
......@@ -69,16 +61,75 @@ class Item_subselect :public Item
error= item->error;
}
enum Type type() const;
bool is_null() { return null_value; }
void make_field (Send_field *);
bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref);
table_map used_tables() const;
friend class select_subselect;
};
/* single value subselect */
class Item_singleval_subselect :public Item_subselect
{
protected:
longlong int_value;
double real_value;
enum Item_result res_type;
virtual void assign_null()
{
null_value= 1;
int_value= 0;
real_value= 0;
max_length= 4;
res_type= STRING_RESULT;
}
public:
Item_singleval_subselect(THD *thd, st_select_lex *select_lex);
Item_singleval_subselect(Item_singleval_subselect *item):
Item_subselect(item)
{
int_value= item->int_value;
real_value= item->real_value;
max_length= item->max_length;
decimals= item->decimals;
res_type= item->res_type;
}
double val ();
longlong val_int ();
String *val_str (String *);
bool is_null() { return null_value; }
void make_field (Send_field *);
bool fix_fields(THD *thd, TABLE_LIST *tables);
Item *new_item() { return new Item_subselect(this); }
Item *new_item() { return new Item_singleval_subselect(this); }
enum Item_result result_type() const { return res_type; }
friend class select_subselect;
friend class select_singleval_subselect;
};
/* exists subselect */
class Item_exists_subselect :public Item_subselect
{
protected:
longlong value;
virtual void assign_null()
{
value= 0;
}
public:
Item_exists_subselect(THD *thd, st_select_lex *select_lex);
Item_exists_subselect(Item_exists_subselect *item):
Item_subselect(item)
{
value= item->value;
}
Item *new_item() { return new Item_exists_subselect(this); }
enum Item_result result_type() const { return INT_RESULT;}
longlong val_int();
double val();
String *val_str(String*);
friend class select_exists_subselect;
};
......@@ -60,8 +60,9 @@ void Item_sum::make_field(Send_field *tmp_field)
result_type() == REAL_RESULT ? FIELD_TYPE_DOUBLE :
FIELD_TYPE_VAR_STRING);
}
tmp_field->table_name=(char*)"";
tmp_field->col_name=name;
tmp_field->db_name=(char*)"";
tmp_field->org_table_name=tmp_field->table_name=(char*)"";
tmp_field->org_col_name=tmp_field->col_name=name;
}
void Item_sum::print(String *str)
......@@ -111,7 +112,7 @@ Item_sum_int::val_str(String *str)
bool
Item_sum_num::fix_fields(THD *thd,TABLE_LIST *tables)
Item_sum_num::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{
if (!thd->allow_sum_func)
{
......@@ -123,7 +124,7 @@ Item_sum_num::fix_fields(THD *thd,TABLE_LIST *tables)
maybe_null=0;
for (uint i=0 ; i < arg_count ; i++)
{
if (args[i]->fix_fields(thd,tables))
if (args[i]->fix_fields(thd, tables, args + i))
return 1;
if (decimals < args[i]->decimals)
decimals=args[i]->decimals;
......@@ -139,7 +140,7 @@ Item_sum_num::fix_fields(THD *thd,TABLE_LIST *tables)
bool
Item_sum_hybrid::fix_fields(THD *thd,TABLE_LIST *tables)
Item_sum_hybrid::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{
Item *item=args[0];
if (!thd->allow_sum_func)
......@@ -148,7 +149,7 @@ Item_sum_hybrid::fix_fields(THD *thd,TABLE_LIST *tables)
return 1;
}
thd->allow_sum_func=0; // No included group funcs
if (item->fix_fields(thd,tables))
if (item->fix_fields(thd, tables, args))
return 1;
hybrid_type=item->result_type();
if (hybrid_type == INT_RESULT)
......@@ -929,9 +930,10 @@ Item_sum_count_distinct::~Item_sum_count_distinct()
}
bool Item_sum_count_distinct::fix_fields(THD *thd,TABLE_LIST *tables)
bool Item_sum_count_distinct::fix_fields(THD *thd, TABLE_LIST *tables,
Item **ref)
{
if (Item_sum_num::fix_fields(thd,tables) ||
if (Item_sum_num::fix_fields(thd, tables, ref) ||
!(tmp_table_param= new TMP_TABLE_PARAM))
return 1;
return 0;
......
......@@ -80,7 +80,7 @@ class Item_sum_num :public Item_sum
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) {}
bool fix_fields(THD *,struct st_table_list *);
bool fix_fields(THD *, TABLE_LIST *, Item **);
longlong val_int() { return (longlong) val(); } /* Real as default */
String *val_str(String*str);
void reset_field();
......@@ -146,7 +146,7 @@ class Item_sum_count_distinct :public Item_sum_int
{
TABLE *table;
table_map used_table_cache;
bool fix_fields(THD *thd,TABLE_LIST *tables);
bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref);
uint32 *field_lengths;
TMP_TABLE_PARAM *tmp_table_param;
TREE tree;
......@@ -283,7 +283,7 @@ class Item_sum_hybrid :public Item_sum
Item_sum_hybrid(Item *item_par,int sign) :Item_sum(item_par),cmp_sign(sign),
used_table_cache(~(table_map) 0)
{}
bool fix_fields(THD *,struct st_table_list *);
bool fix_fields(THD *, TABLE_LIST *, Item **);
table_map used_tables() const { return used_table_cache; }
bool const_item() const { return !used_table_cache; }
......@@ -382,7 +382,7 @@ class Item_udf_sum : public Item_sum
{ quick_group=0;}
~Item_udf_sum() {}
const char *func_name() const { return udf.name(); }
bool fix_fields(THD *thd,struct st_table_list *tables)
bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{
return udf.fix_fields(thd,tables,this,this->arg_count,this->args);
}
......
......@@ -42,5 +42,5 @@ class Item_sum_unique_users :public Item_sum_num
bool add() { return 0; }
void reset_field() {}
void update_field(int offset) {}
bool fix_fields(THD *thd,struct st_table_list *tlist) { return 0;}
bool fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref) { return 0;}
};
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -39,3 +39,4 @@ latin1_de 31
armscii8 32
utf8 33
win1250ch 34
ucs2 35
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -106,7 +106,7 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
}
tables->table=table;
if (cond && cond->fix_fields(thd,tables))
if (cond && cond->fix_fields(thd, tables, &cond))
return -1;
if (keyname)
......
......@@ -44,7 +44,7 @@ static void unlink_blobs(register TABLE *table);
Resets form->time_stamp if a timestamp value is set
*/
static int
int
check_insert_fields(THD *thd,TABLE *table,List<Item> &fields,
List<Item> &values, ulong counter)
{
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment