Commit 5d62bde7 authored by ram@ram.(none)'s avatar ram@ram.(none)

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

into ram.(none):/home/ram/work/mysql-4.1.spatial
parents 57ef43d5 984c84c2
...@@ -478,3 +478,4 @@ vio/test-ssl ...@@ -478,3 +478,4 @@ vio/test-ssl
vio/test-sslclient vio/test-sslclient
vio/test-sslserver vio/test-sslserver
vio/viotest-ssl vio/viotest-ssl
tests/client_test
...@@ -67,3 +67,6 @@ venu@work.mysql.com ...@@ -67,3 +67,6 @@ venu@work.mysql.com
worm@altair.is.lan worm@altair.is.lan
zak@balfor.local zak@balfor.local
zak@linux.local zak@linux.local
venu@myvenu.com
walrus@mysql.com
ram@ram.(none)
...@@ -94,6 +94,7 @@ ...@@ -94,6 +94,7 @@
#undef HAVE_CHARSET_sjis #undef HAVE_CHARSET_sjis
#undef HAVE_CHARSET_swe7 #undef HAVE_CHARSET_swe7
#undef HAVE_CHARSET_tis620 #undef HAVE_CHARSET_tis620
#undef HAVE_CHARSET_ucs2
#undef HAVE_CHARSET_ujis #undef HAVE_CHARSET_ujis
#undef HAVE_CHARSET_usa7 #undef HAVE_CHARSET_usa7
#undef HAVE_CHARSET_utf8 #undef HAVE_CHARSET_utf8
......
...@@ -1942,10 +1942,10 @@ AC_DIVERT_PUSH(0) ...@@ -1942,10 +1942,10 @@ AC_DIVERT_PUSH(0)
CHARSETS_AVAILABLE="armscii8 big5 cp1251 cp1257 CHARSETS_AVAILABLE="armscii8 big5 cp1251 cp1257
croat czech danish dec8 dos estonia euc_kr gb2312 gbk croat czech danish dec8 dos estonia euc_kr gb2312 gbk
german1 greek hebrew hp8 hungarian koi8_ru koi8_ukr 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" usa7 utf8 win1250 win1250ch win1251ukr"
CHARSETS_DEPRECATED="win1251" 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 DEFAULT_CHARSET=latin1
AC_DIVERT_POP AC_DIVERT_POP
...@@ -2067,6 +2067,10 @@ do ...@@ -2067,6 +2067,10 @@ do
tis620) tis620)
AC_DEFINE(HAVE_CHARSET_tis620) AC_DEFINE(HAVE_CHARSET_tis620)
;; ;;
ucs2)
AC_DEFINE(HAVE_CHARSET_ucs2)
use_mb="yes"
;;
ujis) ujis)
AC_DEFINE(HAVE_CHARSET_ujis) AC_DEFINE(HAVE_CHARSET_ujis)
use_mb="yes" use_mb="yes"
......
...@@ -61,3 +61,17 @@ extern const char *client_errors[]; /* Error messages */ ...@@ -61,3 +61,17 @@ extern const char *client_errors[]; /* Error messages */
#define CR_PROBE_SLAVE_HOSTS 2023 #define CR_PROBE_SLAVE_HOSTS 2023
#define CR_PROBE_SLAVE_CONNECT 2024 #define CR_PROBE_SLAVE_CONNECT 2024
#define CR_PROBE_MASTER_CONNECT 2025 #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 ...@@ -287,6 +287,40 @@ void my_hash_sort_utf8(struct charset_info_st *cs, const uchar *key, uint len, u
#endif #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 _U 01 /* Upper case */
#define _L 02 /* Lower case */ #define _L 02 /* Lower case */
#define _NMR 04 /* Numeral (digit) */ #define _NMR 04 /* Numeral (digit) */
......
...@@ -68,16 +68,17 @@ extern char *mysql_unix_port; ...@@ -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) #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 { typedef struct st_mysql_field {
char *name; /* Name of column */ char *name; /* Name of column */
char *table; /* Table of column if column was a field */ char *org_name; /* Original column name, if column was an alias */
char *org_table; /* Org table name if table was an alias */ char *table; /* Table of column if column was a field */
char *db; /* Database for table */ char *org_table; /* Org table name, if table was an alias */
char *def; /* Default value (set by mysql_list_fields) */ char *db; /* Database for table */
unsigned long length; /* Width of column */ char *def; /* Default value (set by mysql_list_fields) */
unsigned long max_length; /* Max width of selected set */ unsigned long length; /* Width of column */
unsigned int flags; /* Div flags */ unsigned long max_length; /* Max width of selected set */
unsigned int decimals; /* Number of decimals in field */ unsigned int flags; /* Div flags */
enum enum_field_types type; /* Type of field. Se mysql_com.h for types */ unsigned int decimals; /* Number of decimals in field */
enum enum_field_types type; /* Type of field. Se mysql_com.h for types */
} MYSQL_FIELD; } MYSQL_FIELD;
typedef char **MYSQL_ROW; /* return data as array of strings */ typedef char **MYSQL_ROW; /* return data as array of strings */
...@@ -101,6 +102,23 @@ typedef struct st_mysql_rows { ...@@ -101,6 +102,23 @@ typedef struct st_mysql_rows {
typedef MYSQL_ROWS *MYSQL_ROW_OFFSET; /* offset to current row */ typedef MYSQL_ROWS *MYSQL_ROW_OFFSET; /* offset to current row */
#include <my_alloc.h> #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 { typedef struct st_mysql_data {
my_ulonglong rows; my_ulonglong rows;
...@@ -391,6 +409,83 @@ int STDCALL mysql_manager_command(MYSQL_MANAGER* con, ...@@ -391,6 +409,83 @@ int STDCALL mysql_manager_command(MYSQL_MANAGER* con,
int STDCALL mysql_manager_fetch_line(MYSQL_MANAGER* con, int STDCALL mysql_manager_fetch_line(MYSQL_MANAGER* con,
char* res_buf, char* res_buf,
int res_buf_size); 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) #define mysql_reload(mysql) mysql_refresh((mysql),REFRESH_GRANT)
#ifdef USE_OLD_FUNCTIONS #ifdef USE_OLD_FUNCTIONS
......
...@@ -42,7 +42,8 @@ enum enum_server_command {COM_SLEEP,COM_QUIT,COM_INIT_DB,COM_QUERY, ...@@ -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_DEBUG,COM_PING,COM_TIME,COM_DELAYED_INSERT,
COM_CHANGE_USER, COM_BINLOG_DUMP, COM_CHANGE_USER, COM_BINLOG_DUMP,
COM_TABLE_DUMP, COM_CONNECT_OUT, 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 NOT_NULL_FLAG 1 /* Field can't be NULL */
#define PRI_KEY_FLAG 2 /* Field is part of a primary key */ #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, ...@@ -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_SSL 2048 /* Switch to SSL after handshake */
#define CLIENT_IGNORE_SIGPIPE 4096 /* IGNORE sigpipes */ #define CLIENT_IGNORE_SIGPIPE 4096 /* IGNORE sigpipes */
#define CLIENT_TRANSACTIONS 8192 /* Client knows about transactions */ #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_IN_TRANS 1 /* Transaction has started */
#define SERVER_STATUS_AUTOCOMMIT 2 /* Server in auto_commit mode */ #define SERVER_STATUS_AUTOCOMMIT 2 /* Server in auto_commit mode */
...@@ -136,27 +138,64 @@ typedef struct st_net { ...@@ -136,27 +138,64 @@ typedef struct st_net {
#define packet_error (~(unsigned long) 0) #define packet_error (~(unsigned long) 0)
enum enum_field_types { FIELD_TYPE_DECIMAL, FIELD_TYPE_TINY, enum enum_field_types { MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY,
FIELD_TYPE_SHORT, FIELD_TYPE_LONG, MYSQL_TYPE_SHORT, MYSQL_TYPE_LONG,
FIELD_TYPE_FLOAT, FIELD_TYPE_DOUBLE, MYSQL_TYPE_FLOAT, MYSQL_TYPE_DOUBLE,
FIELD_TYPE_NULL, FIELD_TYPE_TIMESTAMP, MYSQL_TYPE_NULL, MYSQL_TYPE_TIMESTAMP,
FIELD_TYPE_LONGLONG,FIELD_TYPE_INT24, MYSQL_TYPE_LONGLONG,MYSQL_TYPE_INT24,
FIELD_TYPE_DATE, FIELD_TYPE_TIME, MYSQL_TYPE_DATE, MYSQL_TYPE_TIME,
FIELD_TYPE_DATETIME, FIELD_TYPE_YEAR, MYSQL_TYPE_DATETIME, MYSQL_TYPE_YEAR,
FIELD_TYPE_NEWDATE, MYSQL_TYPE_NEWDATE,
FIELD_TYPE_ENUM=247, MYSQL_TYPE_ENUM=247,
FIELD_TYPE_SET=248, MYSQL_TYPE_SET=248,
FIELD_TYPE_TINY_BLOB=249, MYSQL_TYPE_TINY_BLOB=249,
FIELD_TYPE_MEDIUM_BLOB=250, MYSQL_TYPE_MEDIUM_BLOB=250,
FIELD_TYPE_LONG_BLOB=251, MYSQL_TYPE_LONG_BLOB=251,
FIELD_TYPE_BLOB=252, MYSQL_TYPE_BLOB=252,
FIELD_TYPE_VAR_STRING=253, MYSQL_TYPE_VAR_STRING=253,
FIELD_TYPE_STRING=254, MYSQL_TYPE_STRING=254,
FIELD_TYPE_GEOMETRY=255 MYSQL_TYPE_GEOMETRY=255
}; };
#define FIELD_TYPE_CHAR FIELD_TYPE_TINY /* For compability */ /* For backward compatibility */
#define FIELD_TYPE_INTERVAL FIELD_TYPE_ENUM /* For compability */ #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) #define net_new_transaction(net) ((net)->pkt_nr=0)
...@@ -251,5 +290,6 @@ void my_thread_end(void); ...@@ -251,5 +290,6 @@ void my_thread_end(void);
#endif #endif
#define NULL_LENGTH ((unsigned long) ~0) /* For net_store_length */ #define NULL_LENGTH ((unsigned long) ~0) /* For net_store_length */
#define MYSQL_LONG_DATA_END 0xFF /* For indication of long data ending */
#endif #endif
...@@ -49,7 +49,18 @@ const char *client_errors[]= ...@@ -49,7 +49,18 @@ const char *client_errors[]=
"Error on SHOW SLAVE STATUS:", "Error on SHOW SLAVE STATUS:",
"Error on SHOW SLAVE HOSTS:", "Error on SHOW SLAVE HOSTS:",
"Error connecting to slave:", "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 */ /* Start of code added by Roberto M. Serqueira - martinsc@uol.com.br - 05.24.2001 */
...@@ -82,7 +93,18 @@ const char *client_errors[]= ...@@ -82,7 +93,18 @@ const char *client_errors[]=
"Error on SHOW SLAVE STATUS:", "Error on SHOW SLAVE STATUS:",
"Error on SHOW SLAVE HOSTS:", "Error on SHOW SLAVE HOSTS:",
"Error connecting to slave:", "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 */ #else /* ENGLISH */
...@@ -113,7 +135,18 @@ const char *client_errors[]= ...@@ -113,7 +135,18 @@ const char *client_errors[]=
"Error on SHOW SLAVE STATUS:", "Error on SHOW SLAVE STATUS:",
"Error on SHOW SLAVE HOSTS:", "Error on SHOW SLAVE HOSTS:",
"Error connecting to slave:", "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 #endif
......
This diff is collapsed.
...@@ -49,9 +49,10 @@ sqlsources = convert.cc derror.cc field.cc field_conv.cc filesort.cc \ ...@@ -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 \ opt_sum.cc procedure.cc records.cc sql_acl.cc \
repl_failsafe.cc slave.cc \ repl_failsafe.cc slave.cc \
sql_analyse.cc sql_base.cc sql_cache.cc sql_class.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_crypt.cc sql_db.cc sql_delete.cc sql_error.cc sql_insert.cc \
sql_list.cc sql_manager.cc sql_map.cc sql_parse.cc sql_derived.cc \ sql_lex.cc sql_list.cc sql_manager.cc sql_map.cc sql_parse.cc \
sql_rename.cc sql_repl.cc sql_select.cc sql_do.cc sql_show.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_string.cc sql_table.cc sql_test.cc sql_udf.cc \
sql_update.cc sql_yacc.cc table.cc thr_malloc.cc time.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 \ 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) ...@@ -99,11 +99,20 @@ ha_checksum mi_unique_hash(MI_UNIQUEDEF *def, const byte *record)
end= pos+length; end= pos+length;
if (type == HA_KEYTYPE_TEXT || type == HA_KEYTYPE_VARTEXT) if (type == HA_KEYTYPE_TEXT || type == HA_KEYTYPE_VARTEXT)
{ {
uchar *sort_order=keyseg->charset->sort_order; if (keyseg->charset->hash_sort)
while (pos != end) {
crc=((crc << 8) + ulong nr=1, nr2=4;
(((uchar) sort_order[*(uchar*) pos++]))) + keyseg->charset->hash_sort(keyseg->charset,(const uchar*)pos,length,&nr, &nr2);
(crc >> (8*sizeof(ha_checksum)-8)); 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 else
while (pos != end) while (pos != end)
...@@ -173,11 +182,19 @@ int mi_unique_comp(MI_UNIQUEDEF *def, const byte *a, const byte *b, ...@@ -173,11 +182,19 @@ int mi_unique_comp(MI_UNIQUEDEF *def, const byte *a, const byte *b,
end= pos_a+length; end= pos_a+length;
if (type == HA_KEYTYPE_TEXT || type == HA_KEYTYPE_VARTEXT) if (type == HA_KEYTYPE_TEXT || type == HA_KEYTYPE_VARTEXT)
{ {
uchar *sort_order=keyseg->charset->sort_order; if (use_strcoll(keyseg->charset))
while (pos_a != end) {
if (sort_order[*(uchar*) pos_a++] != if (my_strnncoll(keyseg->charset,pos_a,length,pos_b,length))
sort_order[*(uchar*) pos_b++])
return 1; 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 else
while (pos_a != end) while (pos_a != end)
......
...@@ -32,7 +32,7 @@ result_file=$RESULT_DIR/$test_name.result ...@@ -32,7 +32,7 @@ result_file=$RESULT_DIR/$test_name.result
touch $result_file touch $result_file
echo "Running the test case against empty file, will fail, but don't worry" 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 reject_file=$result_file.reject
......
This diff is collapsed.
...@@ -65,6 +65,21 @@ a ...@@ -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; 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) b (select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2)
8 7.5000 8 7.5000
8 6.0000 8 4.5000
9 5.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; 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 ...@@ -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 * 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 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; drop table t1,t2,t3,t4;
...@@ -48,11 +48,11 @@ int main(int argc, char **argv) { ...@@ -48,11 +48,11 @@ int main(int argc, char **argv) {
cs_list = list_charsets(MYF(MY_COMPILED_SETS | MY_CONFIG_SETS)); cs_list = list_charsets(MYF(MY_COMPILED_SETS | MY_CONFIG_SETS));
printf("LIST OF CHARSETS (compiled + *.conf):\n%s\n", cs_list); 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)); cs_list = list_charsets(MYF(MY_INDEX_SETS | MY_LOADED_SETS));
printf("LIST OF CHARSETS (index + loaded):\n%s\n", cs_list); printf("LIST OF CHARSETS (index + loaded):\n%s\n", cs_list);
free(cs_list); my_free(cs_list,MYF(0));
return 0; return 0;
} }
This diff is collapsed.
...@@ -67,6 +67,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc \ ...@@ -67,6 +67,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc \
mysqld.cc password.c hash_filo.cc hostname.cc \ mysqld.cc password.c hash_filo.cc hostname.cc \
convert.cc sql_parse.cc sql_yacc.yy \ convert.cc sql_parse.cc sql_yacc.yy \
sql_base.cc table.cc sql_select.cc sql_insert.cc \ 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 \ sql_update.cc sql_delete.cc uniques.cc sql_do.cc \
procedure.cc item_uniq.cc sql_test.cc \ procedure.cc item_uniq.cc sql_test.cc \
log.cc log_event.cc init.cc derror.cc sql_acl.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 ...@@ -279,8 +279,10 @@ void Field_num::add_zerofill_and_unsigned(String &res) const
void Field_num::make_field(Send_field *field) 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->table_name=table_name;
field->col_name=field_name; field->col_name=field->org_col_name=field_name;
field->length=field_length; field->length=field_length;
field->type=type(); field->type=type();
field->flags=table->maybe_null ? (flags & ~NOT_NULL_FLAG) : flags; field->flags=table->maybe_null ? (flags & ~NOT_NULL_FLAG) : flags;
...@@ -290,8 +292,10 @@ void Field_num::make_field(Send_field *field) ...@@ -290,8 +292,10 @@ void Field_num::make_field(Send_field *field)
void Field_str::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->table_name=table_name;
field->col_name=field_name; field->col_name=field->org_col_name=field_name;
field->length=field_length; field->length=field_length;
field->type=type(); field->type=type();
field->flags=table->maybe_null ? (flags & ~NOT_NULL_FLAG) : flags; field->flags=table->maybe_null ? (flags & ~NOT_NULL_FLAG) : flags;
...@@ -3778,10 +3782,10 @@ uint Field_varstring::max_packed_col_length(uint max_length) ...@@ -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, 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, enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,uint blob_pack_length, 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, :Field_str(ptr_arg, (1L << min(blob_pack_length,3)*8)-1L,
null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, 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) packlength(blob_pack_length),binary_flag(binary_arg), geom_flag(true)
{ {
flags|= BLOB_FLAG; flags|= BLOB_FLAG;
...@@ -3963,9 +3967,9 @@ String *Field_blob::val_str(String *val_buffer __attribute__((unused)), ...@@ -3963,9 +3967,9 @@ String *Field_blob::val_str(String *val_buffer __attribute__((unused)),
char *blob; char *blob;
memcpy_fixed(&blob,ptr+packlength,sizeof(char*)); memcpy_fixed(&blob,ptr+packlength,sizeof(char*));
if (!blob) 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 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; return val_ptr;
} }
...@@ -4778,7 +4782,8 @@ Field *make_field(char *ptr, uint32 field_length, ...@@ -4778,7 +4782,8 @@ Field *make_field(char *ptr, uint32 field_length,
if (f_is_blob(pack_flag)) if (f_is_blob(pack_flag))
return new Field_blob(ptr,null_pos,null_bit, return new Field_blob(ptr,null_pos,null_bit,
unireg_check, field_name, table, 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)) if (f_is_geom(pack_flag))
return new Field_geom(ptr,null_pos,null_bit, return new Field_geom(ptr,null_pos,null_bit,
unireg_check, field_name, table, unireg_check, field_name, table,
......
...@@ -842,11 +842,11 @@ public: ...@@ -842,11 +842,11 @@ public:
Field_blob(char *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, Field_blob(char *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg, enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,uint blob_pack_length, 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, 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, :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) packlength(3),binary_flag(binary_arg), geom_flag(true)
{ {
flags|= BLOB_FLAG; flags|= BLOB_FLAG;
...@@ -930,11 +930,12 @@ public: ...@@ -930,11 +930,12 @@ public:
struct st_table *table_arg,uint blob_pack_length, struct st_table *table_arg,uint blob_pack_length,
bool binary_arg) bool binary_arg)
:Field_blob(ptr_arg, null_ptr_arg, null_bit_arg, unireg_check_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, Field_geom(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)
:Field_blob(len_arg, maybe_null_arg, field_name_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; } enum ha_base_keytype key_type() const { return HA_KEYTYPE_VARBINARY; }
void get_key_image(char *buff,uint length, imagetype type); void get_key_image(char *buff,uint length, imagetype type);
...@@ -1038,7 +1039,9 @@ public: ...@@ -1038,7 +1039,9 @@ public:
class Send_field { class Send_field {
public: 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; uint length,flags,decimals;
enum_field_types type; enum_field_types type;
Send_field() {} Send_field() {}
......
...@@ -508,7 +508,8 @@ void field_conv(Field *to,Field *from) ...@@ -508,7 +508,8 @@ void field_conv(Field *to,Field *from)
if (!blob->value.is_alloced() && if (!blob->value.is_alloced() &&
from->real_type() != FIELD_TYPE_STRING) from->real_type() != FIELD_TYPE_STRING)
blob->value.copy(); 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; return;
} }
if ((from->result_type() == STRING_RESULT && if ((from->result_type() == STRING_RESULT &&
...@@ -520,7 +521,9 @@ void field_conv(Field *to,Field *from) ...@@ -520,7 +521,9 @@ void field_conv(Field *to,Field *from)
char buff[MAX_FIELD_WIDTH]; char buff[MAX_FIELD_WIDTH];
String result(buff,sizeof(buff),default_charset_info); String result(buff,sizeof(buff),default_charset_info);
from->val_str(&result,&result); 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) else if (from->result_type() == REAL_RESULT)
to->store(from->val_real()); to->store(from->val_real());
......
...@@ -137,6 +137,7 @@ enum row_type { ROW_TYPE_NOT_USED=-1, ROW_TYPE_DEFAULT, ROW_TYPE_FIXED, ...@@ -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_MAX_ROWS 32
#define HA_CREATE_USED_AVG_ROW_LENGTH 64 #define HA_CREATE_USED_AVG_ROW_LENGTH 64
#define HA_CREATE_USED_PACK_KEYS 128 #define HA_CREATE_USED_PACK_KEYS 128
#define HA_CREATE_USED_CHARSET 256
typedef struct st_thd_trans { typedef struct st_thd_trans {
void *bdb_tid; void *bdb_tid;
......
...@@ -133,6 +133,9 @@ void Item_field::set_field(Field *field_par) ...@@ -133,6 +133,9 @@ void Item_field::set_field(Field *field_par)
field_name=field_par->field_name; field_name=field_par->field_name;
binary=field_par->binary(); binary=field_par->binary();
unsigned_flag=test(field_par->flags & UNSIGNED_FLAG); 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 const char *Item_ident::full_name() const
...@@ -287,6 +290,140 @@ String *Item_null::val_str(String *str) ...@@ -287,6 +290,140 @@ String *Item_null::val_str(String *str)
{ null_value=1; return 0;} { 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() void Item_copy_string::copy()
{ {
String *res=item->val_str(&str_value); String *res=item->val_str(&str_value);
...@@ -309,12 +446,13 @@ String *Item_copy_string::val_str(String *str) ...@@ -309,12 +446,13 @@ String *Item_copy_string::val_str(String *str)
/* ARGSUSED */ /* ARGSUSED */
bool Item::fix_fields(THD *thd, bool Item::fix_fields(THD *thd,
struct st_table_list *list) struct st_table_list *list,
Item ** ref)
{ {
return 0; 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 if (!field) // If field is not checked
{ {
...@@ -330,7 +468,7 @@ bool Item_field::fix_fields(THD *thd,TABLE_LIST *tables) ...@@ -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 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. 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(); for (SELECT_LEX *sl= thd->lex.select->outer_select();
sl && !tmp; sl && !tmp;
sl= sl->outer_select()) sl= sl->outer_select())
...@@ -339,6 +477,8 @@ bool Item_field::fix_fields(THD *thd,TABLE_LIST *tables) ...@@ -339,6 +477,8 @@ bool Item_field::fix_fields(THD *thd,TABLE_LIST *tables)
if (!tmp) if (!tmp)
return 1; return 1;
else else
{
depended_from= last;
/* /*
Mark all selects from resolved to 1 before select where was Mark all selects from resolved to 1 before select where was
found table as depended (of select where was found table) found table as depended (of select where was found table)
...@@ -356,6 +496,7 @@ bool Item_field::fix_fields(THD *thd,TABLE_LIST *tables) ...@@ -356,6 +496,7 @@ bool Item_field::fix_fields(THD *thd,TABLE_LIST *tables)
tbl= tbl->next) tbl= tbl->next)
tbl->shared= 1; tbl->shared= 1;
} }
}
} }
set_field(tmp); set_field(tmp);
} }
...@@ -367,13 +508,24 @@ bool Item_field::fix_fields(THD *thd,TABLE_LIST *tables) ...@@ -367,13 +508,24 @@ bool Item_field::fix_fields(THD *thd,TABLE_LIST *tables)
table->used_fields++; table->used_fields++;
table->used_keys&=field->part_of_key; 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; return 0;
} }
void Item::init_make_field(Send_field *tmp_field, void Item::init_make_field(Send_field *tmp_field,
enum enum_field_types field_type) 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->table_name=(char*) "";
tmp_field->col_name=name; tmp_field->col_name=name;
tmp_field->flags=maybe_null ? 0 : NOT_NULL_FLAG; tmp_field->flags=maybe_null ? 0 : NOT_NULL_FLAG;
...@@ -647,12 +799,50 @@ bool Item_null::send(THD *thd, String *packet) ...@@ -647,12 +799,50 @@ bool Item_null::send(THD *thd, String *packet)
Find field in select list having the same name 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)
{ {
if (!(ref=find_item_in_list(this,thd->lex.select->item_list))) if (!(ref= find_item_in_list(this,thd->lex.select->item_list)))
return 1; {
/*
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; max_length= (*ref)->max_length;
maybe_null= (*ref)->maybe_null; maybe_null= (*ref)->maybe_null;
decimals= (*ref)->decimals; decimals= (*ref)->decimals;
......
...@@ -52,7 +52,7 @@ public: ...@@ -52,7 +52,7 @@ public:
virtual ~Item() { name=0; } /*lint -e1509 */ virtual ~Item() { name=0; } /*lint -e1509 */
void set_name(char* str,uint length=0); void set_name(char* str,uint length=0);
void init_make_field(Send_field *tmp_field,enum enum_field_types type); 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 bool save_in_field(Field *field);
virtual void save_org_in_field(Field *field) virtual void save_org_in_field(Field *field)
{ (void) save_in_field(field); } { (void) save_in_field(field); }
...@@ -85,15 +85,18 @@ public: ...@@ -85,15 +85,18 @@ public:
}; };
class st_select_lex;
class Item_ident :public Item class Item_ident :public Item
{ {
public: public:
const char *db_name; const char *db_name;
const char *table_name; const char *table_name;
const char *field_name; const char *field_name;
st_select_lex *depended_from;
Item_ident(const char *db_name_par,const char *table_name_par, Item_ident(const char *db_name_par,const char *table_name_par,
const char *field_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; } { name = (char*) field_name_par; }
const char *full_name() const; const char *full_name() const;
}; };
...@@ -120,7 +123,7 @@ public: ...@@ -120,7 +123,7 @@ public:
String *str_result(String* tmp); String *str_result(String* tmp);
bool send(THD *thd, String *str_arg) { return result_field->send(thd,str_arg); } bool send(THD *thd, String *str_arg) { return result_field->send(thd,str_arg); }
void make_field(Send_field *field); 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); bool save_in_field(Field *field);
void save_org_in_field(Field *field); void save_org_in_field(Field *field);
table_map used_tables() const; table_map used_tables() const;
...@@ -155,6 +158,40 @@ public: ...@@ -155,6 +158,40 @@ public:
bool is_null() { return 1; } 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 class Item_int :public Item
{ {
...@@ -356,7 +393,7 @@ public: ...@@ -356,7 +393,7 @@ public:
} }
bool send(THD *thd, String *tmp) { return (*ref)->send(thd, tmp); } bool send(THD *thd, String *tmp) { return (*ref)->send(thd, tmp); }
void make_field(Send_field *field) { (*ref)->make_field(field); } 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); } 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); } void save_org_in_field(Field *field) { (*ref)->save_org_in_field(field); }
enum Item_result result_type () const { return (*ref)->result_type(); } enum Item_result result_type () const { return (*ref)->result_type(); }
......
...@@ -727,12 +727,12 @@ double Item_func_case::val() ...@@ -727,12 +727,12 @@ double Item_func_case::val()
bool 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) || if (first_expr && first_expr->fix_fields(thd, tables, &first_expr) ||
else_expr && else_expr->fix_fields(thd,tables)) else_expr && else_expr->fix_fields(thd, tables, &else_expr))
return 1; return 1;
if (Item_func::fix_fields(thd,tables)) if (Item_func::fix_fields(thd, tables, ref))
return 1; return 1;
if (first_expr) if (first_expr)
{ {
...@@ -1074,7 +1074,7 @@ longlong Item_func_bit_and::val_int() ...@@ -1074,7 +1074,7 @@ longlong Item_func_bit_and::val_int()
bool 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); List_iterator<Item> li(list);
Item *item; Item *item;
...@@ -1096,7 +1096,7 @@ Item_cond::fix_fields(THD *thd,TABLE_LIST *tables) ...@@ -1096,7 +1096,7 @@ Item_cond::fix_fields(THD *thd,TABLE_LIST *tables)
#endif #endif
item= *li.ref(); // new current item item= *li.ref(); // new current item
} }
if (item->fix_fields(thd,tables)) if (item->fix_fields(thd, tables, li.ref()))
return 1; /* purecov: inspected */ return 1; /* purecov: inspected */
used_tables_cache|=item->used_tables(); used_tables_cache|=item->used_tables();
with_sum_func= with_sum_func || item->with_sum_func; with_sum_func= with_sum_func || item->with_sum_func;
...@@ -1272,9 +1272,9 @@ Item_func::optimize_type Item_func_like::select_optimize() const ...@@ -1272,9 +1272,9 @@ Item_func::optimize_type Item_func_like::select_optimize() const
return OPTIMIZE_NONE; 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; return 1;
/* /*
...@@ -1324,9 +1324,10 @@ bool Item_func_like::fix_fields(THD *thd,struct st_table_list *tlist) ...@@ -1324,9 +1324,10 @@ bool Item_func_like::fix_fields(THD *thd,struct st_table_list *tlist)
#ifdef USE_REGEX #ifdef USE_REGEX
bool 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 */ return 1; /* purecov: inspected */
with_sum_func=args[0]->with_sum_func || args[1]->with_sum_func; with_sum_func=args[0]->with_sum_func || args[1]->with_sum_func;
max_length=1; decimals=0; max_length=1; decimals=0;
......
...@@ -177,9 +177,10 @@ public: ...@@ -177,9 +177,10 @@ public:
Item_func_interval(Item *a,List<Item> &list) Item_func_interval(Item *a,List<Item> &list)
:Item_int_func(list),item(a),intervals(0) {} :Item_int_func(list),item(a),intervals(0) {}
longlong val_int(); 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(); void fix_length_and_dec();
~Item_func_interval() { delete item; } ~Item_func_interval() { delete item; }
...@@ -259,7 +260,7 @@ public: ...@@ -259,7 +260,7 @@ public:
enum Item_result result_type () const { return cached_result_type; } enum Item_result result_type () const { return cached_result_type; }
const char *func_name() const { return "case"; } const char *func_name() const { return "case"; }
void print(String *str); 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); Item *find_item(String *str);
}; };
...@@ -409,9 +410,10 @@ class Item_func_in :public Item_int_func ...@@ -409,9 +410,10 @@ class Item_func_in :public Item_int_func
Item_func_in(Item *a,List<Item> &list) Item_func_in(Item *a,List<Item> &list)
:Item_int_func(list),item(a),array(0),in_item(0) {} :Item_int_func(list),item(a),array(0),in_item(0) {}
longlong val_int(); 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(); void fix_length_and_dec();
~Item_func_in() { delete item; delete array; delete in_item; } ~Item_func_in() { delete item; delete array; delete in_item; }
...@@ -505,7 +507,7 @@ public: ...@@ -505,7 +507,7 @@ public:
cond_result eq_cmp_result() const { return COND_TRUE; } cond_result eq_cmp_result() const { return COND_TRUE; }
const char *func_name() const { return "like"; } const char *func_name() const { return "like"; }
void fix_length_and_dec(); 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 #ifdef USE_REGEX
...@@ -523,7 +525,7 @@ public: ...@@ -523,7 +525,7 @@ public:
regex_compiled(0),regex_is_const(0) {} regex_compiled(0),regex_is_const(0) {}
~Item_func_regex(); ~Item_func_regex();
longlong val_int(); 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"; } const char *func_name() const { return "regex"; }
}; };
...@@ -552,7 +554,7 @@ public: ...@@ -552,7 +554,7 @@ public:
{ list.push_back(i1); list.push_back(i2); } { list.push_back(i1); list.push_back(i2); }
~Item_cond() { list.delete_elements(); } ~Item_cond() { list.delete_elements(); }
bool add(Item *item) { return list.push_back(item); } 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; } enum Type type() const { return COND_ITEM; }
List<Item>* argument_list() { return &list; } List<Item>* argument_list() { return &list; }
......
...@@ -58,7 +58,7 @@ Item_func::Item_func(List<Item> &list) ...@@ -58,7 +58,7 @@ Item_func::Item_func(List<Item> &list)
} }
bool 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; Item **arg,**arg_end;
char buff[STACK_BUFF_ALLOC]; // Max argument in function char buff[STACK_BUFF_ALLOC]; // Max argument in function
...@@ -72,12 +72,23 @@ Item_func::fix_fields(THD *thd,TABLE_LIST *tables) ...@@ -72,12 +72,23 @@ Item_func::fix_fields(THD *thd,TABLE_LIST *tables)
{ // Print purify happy { // Print purify happy
for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++) 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 */ return 1; /* purecov: inspected */
if ((*arg)->maybe_null) if ((*arg)->maybe_null)
maybe_null=1; maybe_null=1;
if ((*arg)->binary) if ((*arg)->binary)
binary=1; 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; with_sum_func= with_sum_func || (*arg)->with_sum_func;
used_tables_cache|=(*arg)->used_tables(); used_tables_cache|=(*arg)->used_tables();
const_item_cache&= (*arg)->const_item(); const_item_cache&= (*arg)->const_item();
...@@ -1091,7 +1102,7 @@ udf_handler::~udf_handler() ...@@ -1091,7 +1102,7 @@ udf_handler::~udf_handler()
bool 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) uint arg_count, Item **arguments)
{ {
char buff[STACK_BUFF_ALLOC]; // Max argument in function 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, ...@@ -1135,7 +1146,7 @@ udf_handler::fix_fields(THD *thd,TABLE_LIST *tables,Item_result_field *func,
arg != arg_end ; arg != arg_end ;
arg++,i++) arg++,i++)
{ {
if ((*arg)->fix_fields(thd,tables)) if ((*arg)->fix_fields(thd, tables, arg))
return 1; return 1;
if ((*arg)->binary) if ((*arg)->binary)
func->binary=1; func->binary=1;
...@@ -1754,11 +1765,12 @@ static user_var_entry *get_variable(HASH *hash, LEX_STRING &name, ...@@ -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) if (!thd)
thd=current_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))) !(entry= get_variable(&thd->user_vars, name, 1)))
return 1; return 1;
entry->update_query_id=thd->query_id; entry->update_query_id=thd->query_id;
...@@ -2084,7 +2096,7 @@ void Item_func_match::init_search(bool no_order) ...@@ -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); List_iterator<Item> li(fields);
Item *item; Item *item;
...@@ -2097,7 +2109,7 @@ bool Item_func_match::fix_fields(THD *thd,struct st_table_list *tlist) ...@@ -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 modifications to find_best and auto_close as complement to auto_init code
above. 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"); my_error(ER_WRONG_ARGUMENTS,MYF(0),"AGAINST");
return 1; return 1;
...@@ -2105,7 +2117,7 @@ bool Item_func_match::fix_fields(THD *thd,struct st_table_list *tlist) ...@@ -2105,7 +2117,7 @@ bool Item_func_match::fix_fields(THD *thd,struct st_table_list *tlist)
while ((item=li++)) while ((item=li++))
{ {
if (item->fix_fields(thd,tlist)) if (item->fix_fields(thd, tlist, li.ref()))
return 1; return 1;
if (item->type() == Item::REF_ITEM) if (item->type() == Item::REF_ITEM)
li.replace(item= *((Item_ref *)item)->ref); li.replace(item= *((Item_ref *)item)->ref);
......
...@@ -99,7 +99,7 @@ public: ...@@ -99,7 +99,7 @@ public:
} }
Item_func(List<Item> &list); Item_func(List<Item> &list);
~Item_func() {} /* Nothing to do; Items are freed automaticly */ ~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); void make_field(Send_field *field);
table_map used_tables() const; table_map used_tables() const;
void update_used_tables(); void update_used_tables();
...@@ -567,9 +567,10 @@ public: ...@@ -567,9 +567,10 @@ public:
Item_func_field(Item *a,List<Item> &list) :Item_int_func(list),item(a) {} Item_func_field(Item *a,List<Item> &list) :Item_int_func(list),item(a) {}
~Item_func_field() { delete item; } ~Item_func_field() { delete item; }
longlong val_int(); 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() void update_used_tables()
{ {
...@@ -708,11 +709,11 @@ public: ...@@ -708,11 +709,11 @@ public:
:Item_func(list), udf(udf_arg) {} :Item_func(list), udf(udf_arg) {}
~Item_udf_func() {} ~Item_udf_func() {}
const char *func_name() const { return udf.name(); } 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); bool res= udf.fix_fields(thd, tables, this, arg_count, args);
used_tables_cache=udf.used_tables_cache; used_tables_cache= udf.used_tables_cache;
const_item_cache=udf.const_item_cache; const_item_cache= udf.const_item_cache;
return res; return res;
} }
Item_result result_type () const { return udf.result_type(); } Item_result result_type () const { return udf.result_type(); }
...@@ -867,7 +868,7 @@ public: ...@@ -867,7 +868,7 @@ public:
void update_hash(void *ptr, uint length, enum Item_result type); void update_hash(void *ptr, uint length, enum Item_result type);
bool update(); bool update();
enum Item_result result_type () const { return cached_result_type; } 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 fix_length_and_dec();
void print(String *str); void print(String *str);
const char *func_name() const { return "set_user_var"; } const char *func_name() const { return "set_user_var"; }
...@@ -941,7 +942,7 @@ public: ...@@ -941,7 +942,7 @@ public:
} }
enum Functype functype() const { return FT_FUNC; } enum Functype functype() const { return FT_FUNC; }
void update_used_tables() {} 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; bool eq(const Item *, bool binary_cmp) const;
longlong val_int() { return val()!=0.0; } longlong val_int() { return val()!=0.0; }
double val(); double val();
......
...@@ -759,6 +759,7 @@ String *Item_func_left::val_str(String *str) ...@@ -759,6 +759,7 @@ String *Item_func_left::val_str(String *str)
if (!res->alloced_length()) if (!res->alloced_length())
{ // Don't change const str { // Don't change const str
str_value= *res; // Not malloced string str_value= *res; // Not malloced string
str_value.set_charset(res->charset());
res= &str_value; res= &str_value;
} }
res->length((uint) length); res->length((uint) length);
...@@ -1791,6 +1792,7 @@ String *Item_func_conv_charset::val_str(String *str) ...@@ -1791,6 +1792,7 @@ String *Item_func_conv_charset::val_str(String *str)
null_value=1; null_value=1;
return 0; return 0;
} }
null_value=0;
from=arg->charset(); from=arg->charset();
to=conv_charset; to=conv_charset;
...@@ -1798,7 +1800,7 @@ String *Item_func_conv_charset::val_str(String *str) ...@@ -1798,7 +1800,7 @@ String *Item_func_conv_charset::val_str(String *str)
s=(const uchar*)arg->ptr(); s=(const uchar*)arg->ptr();
se=s+arg->length(); 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); str->alloc(dmaxlen);
d0=d=(unsigned char*)str->ptr(); d0=d=(unsigned char*)str->ptr();
de=d+dmaxlen; de=d+dmaxlen;
...@@ -1840,7 +1842,7 @@ outp: ...@@ -1840,7 +1842,7 @@ outp:
void Item_func_conv_charset::fix_length_and_dec() 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 @@ outp: ...@@ -1910,9 +1912,41 @@ outp:
return 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() 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 @@ public: ...@@ -40,9 +40,10 @@ public:
if (!t_arg) if (!t_arg)
return result_field; return result_field;
return (max_length > 255) ? 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, (Field *) new Field_string(max_length,maybe_null, name,t_arg, binary,
default_charset_info); str_value.charset());
} }
}; };
...@@ -79,10 +80,10 @@ public: ...@@ -79,10 +80,10 @@ public:
String *val_str(String *); String *val_str(String *);
void fix_length_and_dec(); void fix_length_and_dec();
void update_used_tables(); 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) return (separator->fix_fields(thd, tlist, &separator)
|| Item_func::fix_fields(thd,tlist)); || Item_func::fix_fields(thd, tlist, ref));
} }
const char *func_name() const { return "concat_ws"; } const char *func_name() const { return "concat_ws"; }
}; };
...@@ -325,9 +326,10 @@ public: ...@@ -325,9 +326,10 @@ public:
double val(); double val();
longlong val_int(); longlong val_int();
String *val_str(String *str); 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 fix_length_and_dec();
void update_used_tables(); void update_used_tables();
...@@ -344,9 +346,10 @@ public: ...@@ -344,9 +346,10 @@ public:
Item_func_make_set(Item *a,List<Item> &list) :Item_str_func(list),item(a) {} Item_func_make_set(Item *a,List<Item> &list) :Item_str_func(list),item(a) {}
~Item_func_make_set() { delete item; } ~Item_func_make_set() { delete item; }
String *val_str(String *str); 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 fix_length_and_dec();
void update_used_tables(); void update_used_tables();
...@@ -488,6 +491,7 @@ public: ...@@ -488,6 +491,7 @@ public:
{ {
conv_charset=cs; conv_charset=cs;
} }
bool fix_fields(THD *thd,struct st_table_list *tables);
String *val_str(String *); String *val_str(String *);
void fix_length_and_dec(); void fix_length_and_dec();
const char *func_name() const { return "conv_charset"; } const char *func_name() const { return "conv_charset"; }
...@@ -503,6 +507,18 @@ public: ...@@ -503,6 +507,18 @@ public:
const char *func_name() const { return "conv_charset3"; } 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 Spatial functions
......
...@@ -35,12 +35,13 @@ SUBSELECT TODO: ...@@ -35,12 +35,13 @@ SUBSELECT TODO:
#include "mysql_priv.h" #include "mysql_priv.h"
#include "sql_select.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) assigned(0), executed(0), optimized(0), error(0)
{ {
DBUG_ENTER("Item_subselect::Item_subselect"); DBUG_ENTER("Item_subselect::Item_subselect");
DBUG_PRINT("subs", ("select_lex 0x%xl", (long) select_lex)); 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(); SELECT_LEX_UNIT *unit= select_lex->master_unit();
unit->offset_limit_cnt= unit->global_parameters->offset_limit; unit->offset_limit_cnt= unit->global_parameters->offset_limit;
unit->select_limit_cnt= unit->global_parameters->select_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): ...@@ -51,41 +52,15 @@ Item_subselect::Item_subselect(THD *thd, st_select_lex *select_lex):
select_lex->options&= ~OPTION_FOUND_ROWS; select_lex->options&= ~OPTION_FOUND_ROWS;
join= new JOIN(thd, select_lex->item_list, select_lex->options, result); join= new JOIN(thd, select_lex->item_list, select_lex->options, result);
this->select_lex= select_lex; this->select_lex= select_lex;
maybe_null= 1; assign_null();
/* /*
item value is NULL if select_subselect not changed this value item value is NULL if select_subselect not changed this value
(i.e. some rows will be found returned) (i.e. some rows will be found returned)
*/ */
assign_null(); null_value= 1;
DBUG_VOID_RETURN; 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) void Item_subselect::make_field (Send_field *tmp_field)
{ {
if (null_value) if (null_value)
...@@ -100,17 +75,10 @@ void Item_subselect::make_field (Send_field *tmp_field) ...@@ -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? // 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)); my_printf_error(ER_SUBSELECT_NO_1_COL, ER(ER_SUBSELECT_NO_1_COL), MYF(0));
return 1; return 1;
...@@ -131,13 +99,14 @@ bool Item_subselect::fix_fields(THD *thd,TABLE_LIST *tables) ...@@ -131,13 +99,14 @@ bool Item_subselect::fix_fields(THD *thd,TABLE_LIST *tables)
int Item_subselect::exec() int Item_subselect::exec()
{ {
DBUG_ENTER("Item_subselect::exec");
if (!optimized) if (!optimized)
{ {
optimized=1; optimized=1;
if (join->optimize()) if (join->optimize())
{ {
executed= 1; executed= 1;
return (join->error?join->error:1); DBUG_RETURN(join->error?join->error:1);
} }
} }
if (join->select_lex->depended && executed) if (join->select_lex->depended && executed)
...@@ -145,7 +114,7 @@ int Item_subselect::exec() ...@@ -145,7 +114,7 @@ int Item_subselect::exec()
if (join->reinit()) if (join->reinit())
{ {
error= 1; error= 1;
return 1; DBUG_RETURN(1);
} }
assign_null(); assign_null();
executed= assigned= 0; executed= assigned= 0;
...@@ -157,7 +126,80 @@ int Item_subselect::exec() ...@@ -157,7 +126,80 @@ int Item_subselect::exec()
join->exec(); join->exec();
join->thd->lex.select= save_select; join->thd->lex.select= save_select;
executed= 1; 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 @@ ...@@ -20,46 +20,38 @@
#pragma interface /* gcc class implementation */ #pragma interface /* gcc class implementation */
#endif #endif
struct st_select_lex; class st_select_lex;
class JOIN; class JOIN;
class select_subselect; class select_subselect;
/* simple (not depended of covered select ) subselect */ /* base class for subselects */
class Item_subselect :public Item class Item_subselect :public Item
{ {
protected: protected:
longlong int_value; uint max_columns;
double real_value;
my_bool assigned; /* value already assigned to subselect */ my_bool assigned; /* value already assigned to subselect */
my_bool executed; /* simple subselect is executed */ my_bool executed; /* simple subselect is executed */
my_bool optimized; /* simple subselect is optimized */ my_bool optimized; /* simple subselect is optimized */
my_bool error; /* error in query */ my_bool error; /* error in query */
enum Item_result res_type;
int exec(); int exec();
void assign_null() virtual void assign_null()
{ {
null_value= 1; null_value= 1;
int_value= 0;
real_value= 0;
max_length= 4;
res_type= STRING_RESULT;
} }
public: public:
st_select_lex *select_lex; st_select_lex *select_lex;
JOIN *join; JOIN *join;
select_subselect *result; 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) Item_subselect(Item_subselect *item)
{ {
null_value= item->null_value; null_value= item->null_value;
int_value= item->int_value;
real_value= item->real_value;
max_length= item->max_length;
decimals= item->decimals; decimals= item->decimals;
res_type= item->res_type; max_columns= item->max_columns;
assigned= item->assigned; assigned= item->assigned;
executed= item->executed; executed= item->executed;
select_lex= item->select_lex; select_lex= item->select_lex;
...@@ -69,16 +61,75 @@ public: ...@@ -69,16 +61,75 @@ public:
error= item->error; error= item->error;
} }
enum Type type() const; 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 (); double val ();
longlong val_int (); longlong val_int ();
String *val_str (String *); String *val_str (String *);
bool is_null() { return null_value; } Item *new_item() { return new Item_singleval_subselect(this); }
void make_field (Send_field *);
bool fix_fields(THD *thd, TABLE_LIST *tables);
Item *new_item() { return new Item_subselect(this); }
enum Item_result result_type() const { return res_type; } 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) ...@@ -60,8 +60,9 @@ void Item_sum::make_field(Send_field *tmp_field)
result_type() == REAL_RESULT ? FIELD_TYPE_DOUBLE : result_type() == REAL_RESULT ? FIELD_TYPE_DOUBLE :
FIELD_TYPE_VAR_STRING); FIELD_TYPE_VAR_STRING);
} }
tmp_field->table_name=(char*)""; tmp_field->db_name=(char*)"";
tmp_field->col_name=name; 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) void Item_sum::print(String *str)
...@@ -111,7 +112,7 @@ Item_sum_int::val_str(String *str) ...@@ -111,7 +112,7 @@ Item_sum_int::val_str(String *str)
bool 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) if (!thd->allow_sum_func)
{ {
...@@ -123,7 +124,7 @@ Item_sum_num::fix_fields(THD *thd,TABLE_LIST *tables) ...@@ -123,7 +124,7 @@ Item_sum_num::fix_fields(THD *thd,TABLE_LIST *tables)
maybe_null=0; maybe_null=0;
for (uint i=0 ; i < arg_count ; i++) 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; return 1;
if (decimals < args[i]->decimals) if (decimals < args[i]->decimals)
decimals=args[i]->decimals; decimals=args[i]->decimals;
...@@ -139,7 +140,7 @@ Item_sum_num::fix_fields(THD *thd,TABLE_LIST *tables) ...@@ -139,7 +140,7 @@ Item_sum_num::fix_fields(THD *thd,TABLE_LIST *tables)
bool 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]; Item *item=args[0];
if (!thd->allow_sum_func) if (!thd->allow_sum_func)
...@@ -148,7 +149,7 @@ Item_sum_hybrid::fix_fields(THD *thd,TABLE_LIST *tables) ...@@ -148,7 +149,7 @@ Item_sum_hybrid::fix_fields(THD *thd,TABLE_LIST *tables)
return 1; return 1;
} }
thd->allow_sum_func=0; // No included group funcs thd->allow_sum_func=0; // No included group funcs
if (item->fix_fields(thd,tables)) if (item->fix_fields(thd, tables, args))
return 1; return 1;
hybrid_type=item->result_type(); hybrid_type=item->result_type();
if (hybrid_type == INT_RESULT) if (hybrid_type == INT_RESULT)
...@@ -929,9 +930,10 @@ Item_sum_count_distinct::~Item_sum_count_distinct() ...@@ -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)) !(tmp_table_param= new TMP_TABLE_PARAM))
return 1; return 1;
return 0; return 0;
......
...@@ -80,7 +80,7 @@ public: ...@@ -80,7 +80,7 @@ public:
Item_sum_num(Item *item_par) :Item_sum(item_par) {} Item_sum_num(Item *item_par) :Item_sum(item_par) {}
Item_sum_num(Item *a, Item* b) :Item_sum(a,b) {} Item_sum_num(Item *a, Item* b) :Item_sum(a,b) {}
Item_sum_num(List<Item> &list) :Item_sum(list) {} 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 */ longlong val_int() { return (longlong) val(); } /* Real as default */
String *val_str(String*str); String *val_str(String*str);
void reset_field(); void reset_field();
...@@ -146,7 +146,7 @@ class Item_sum_count_distinct :public Item_sum_int ...@@ -146,7 +146,7 @@ class Item_sum_count_distinct :public Item_sum_int
{ {
TABLE *table; TABLE *table;
table_map used_table_cache; 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; uint32 *field_lengths;
TMP_TABLE_PARAM *tmp_table_param; TMP_TABLE_PARAM *tmp_table_param;
TREE tree; TREE tree;
...@@ -283,7 +283,7 @@ class Item_sum_hybrid :public Item_sum ...@@ -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), Item_sum_hybrid(Item *item_par,int sign) :Item_sum(item_par),cmp_sign(sign),
used_table_cache(~(table_map) 0) 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; } table_map used_tables() const { return used_table_cache; }
bool const_item() const { return !used_table_cache; } bool const_item() const { return !used_table_cache; }
...@@ -382,7 +382,7 @@ public: ...@@ -382,7 +382,7 @@ public:
{ quick_group=0;} { quick_group=0;}
~Item_udf_sum() {} ~Item_udf_sum() {}
const char *func_name() const { return udf.name(); } 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); return udf.fix_fields(thd,tables,this,this->arg_count,this->args);
} }
......
...@@ -42,5 +42,5 @@ public: ...@@ -42,5 +42,5 @@ public:
bool add() { return 0; } bool add() { return 0; }
void reset_field() {} void reset_field() {}
void update_field(int offset) {} 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 ...@@ -39,3 +39,4 @@ latin1_de 31
armscii8 32 armscii8 32
utf8 33 utf8 33
win1250ch 34 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, ...@@ -106,7 +106,7 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
} }
tables->table=table; tables->table=table;
if (cond && cond->fix_fields(thd,tables)) if (cond && cond->fix_fields(thd, tables, &cond))
return -1; return -1;
if (keyname) if (keyname)
......
...@@ -44,7 +44,7 @@ static void unlink_blobs(register TABLE *table); ...@@ -44,7 +44,7 @@ static void unlink_blobs(register TABLE *table);
Resets form->time_stamp if a timestamp value is set Resets form->time_stamp if a timestamp value is set
*/ */
static int int
check_insert_fields(THD *thd,TABLE *table,List<Item> &fields, check_insert_fields(THD *thd,TABLE *table,List<Item> &fields,
List<Item> &values, ulong counter) 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