Merge sanja.is.com.ua:/home/bell/mysql/mysql-4.1
into sanja.is.com.ua:/home/bell/mysql/work-select-4.1
This commit is contained in:
commit
291f8a225a
@ -18,6 +18,7 @@
|
||||
#undef MYSQL_SERVER
|
||||
#include "client_priv.h"
|
||||
#include <time.h>
|
||||
#include <assert.h>
|
||||
#include "log_event.h"
|
||||
|
||||
#define BIN_LOG_HEADER_SIZE 4
|
||||
|
@ -16,6 +16,12 @@
|
||||
|
||||
/* Defines for Win32 to make it compatible for MySQL */
|
||||
|
||||
#ifdef __WIN2000__
|
||||
/* We have to do this define before including windows.h to get the AWE API
|
||||
functions */
|
||||
#define _WIN32_WINNT 0x0500
|
||||
#endif
|
||||
|
||||
#include <sys/locking.h>
|
||||
#include <windows.h>
|
||||
#include <math.h> /* Because of rint() */
|
||||
|
@ -92,6 +92,8 @@ typedef struct charset_info_st
|
||||
uint strxfrm_multiply;
|
||||
int (*strnncoll)(struct charset_info_st *,
|
||||
const uchar *, uint, const uchar *, uint);
|
||||
int (*strnncollsp)(struct charset_info_st *,
|
||||
const uchar *, uint, const uchar *, uint);
|
||||
int (*strnxfrm)(struct charset_info_st *,
|
||||
uchar *, uint, const uchar *, uint);
|
||||
my_bool (*like_range)(struct charset_info_st *,
|
||||
@ -110,6 +112,8 @@ typedef struct charset_info_st
|
||||
int (*ismbchar)(struct charset_info_st *, const char *, const char *);
|
||||
my_bool (*ismbhead)(struct charset_info_st *, uint);
|
||||
int (*mbcharlen)(struct charset_info_st *, uint);
|
||||
uint (*numchars)(struct charset_info_st *, const char *b, const char *e);
|
||||
uint (*charpos)(struct charset_info_st *, const char *b, const char *e, uint pos);
|
||||
|
||||
/* Unicode convertion */
|
||||
int (*mb_wc)(struct charset_info_st *cs,my_wc_t *wc,
|
||||
@ -189,6 +193,9 @@ extern int my_strnxfrm_simple(CHARSET_INFO *, uchar *, uint, const uchar *,
|
||||
extern int my_strnncoll_simple(CHARSET_INFO *, const uchar *, uint,
|
||||
const uchar *, uint);
|
||||
|
||||
extern int my_strnncollsp_simple(CHARSET_INFO *, const uchar *, uint,
|
||||
const uchar *, uint);
|
||||
|
||||
extern uint my_hash_caseup_simple(CHARSET_INFO *cs,
|
||||
const byte *key, uint len);
|
||||
|
||||
@ -247,6 +254,9 @@ int my_wildcmp_8bit(CHARSET_INFO *,
|
||||
const char *wildstr,const char *wildend,
|
||||
int escape, int w_one, int w_many);
|
||||
|
||||
uint my_numchars_8bit(CHARSET_INFO *, const char *b, const char *e);
|
||||
uint my_charpos_8bit(CHARSET_INFO *, const char *b, const char *e, uint pos);
|
||||
|
||||
|
||||
#ifdef USE_MB
|
||||
/* Functions for multibyte charsets */
|
||||
@ -261,6 +271,9 @@ int my_wildcmp_mb(CHARSET_INFO *,
|
||||
const char *str,const char *str_end,
|
||||
const char *wildstr,const char *wildend,
|
||||
int escape, int w_one, int w_many);
|
||||
uint my_numchars_mb(CHARSET_INFO *, const char *b, const char *e);
|
||||
uint my_charpos_mb(CHARSET_INFO *, const char *b, const char *e, uint pos);
|
||||
|
||||
#endif
|
||||
|
||||
#define _U 01 /* Upper case */
|
||||
|
@ -706,6 +706,7 @@ extern void freeze_size(DYNAMIC_ARRAY *array);
|
||||
#define dynamic_array_ptr(array,array_index) ((array)->buffer+(array_index)*(array)->size_of_element)
|
||||
#define dynamic_element(array,array_index,type) ((type)((array)->buffer) +(array_index))
|
||||
#define push_dynamic(A,B) insert_dynamic(A,B)
|
||||
#define reset_dynamic(array) ((array)->elements= 0)
|
||||
|
||||
extern my_bool init_dynamic_string(DYNAMIC_STRING *str, const char *init_str,
|
||||
uint init_alloc,uint alloc_increment);
|
||||
|
@ -16,7 +16,7 @@ typedef void* os_process_t;
|
||||
typedef unsigned long int os_process_id_t;
|
||||
|
||||
/* The cell type in os_awe_allocate_mem page info */
|
||||
#if defined(__NT__) && defined(ULONG_PTR)
|
||||
#if defined(__WIN2000__) && defined(ULONG_PTR)
|
||||
typedef ULONG_PTR os_awe_t;
|
||||
#else
|
||||
typedef ulint os_awe_t;
|
||||
|
@ -20,14 +20,14 @@ Created 9/30/1995 Heikki Tuuri
|
||||
How to get AWE to compile on Windows?
|
||||
-------------------------------------
|
||||
|
||||
the Visual C++ has to be relatively recent and _WIN32_WINNT has to be
|
||||
defined to a value >= 0x0500 when windows.h is included. An easy way
|
||||
to accomplish that is to put
|
||||
In the project settings of the innobase project the Visual C++ source,
|
||||
__WIN2000__ has to be defined.
|
||||
|
||||
The Visual C++ has to be relatively recent and _WIN32_WINNT has to be
|
||||
defined to a value >= 0x0500 when windows.h is included.
|
||||
|
||||
#define _WIN32_WINNT 0x0500
|
||||
|
||||
to the start of file \mysql\include\config-win.h
|
||||
|
||||
Where does AWE work?
|
||||
-------------------
|
||||
|
||||
@ -62,7 +62,7 @@ to a mapped 'physical page' for each 4 kB page in the AWE window */
|
||||
byte** os_awe_simulate_map;
|
||||
#endif
|
||||
|
||||
#ifdef __NT__
|
||||
#ifdef __WIN2000__
|
||||
os_awe_t* os_awe_page_info;
|
||||
ulint os_awe_n_pages;
|
||||
byte* os_awe_window;
|
||||
@ -84,7 +84,7 @@ os_awe_enable_lock_pages_in_mem(void)
|
||||
|
||||
return(TRUE);
|
||||
|
||||
#elif defined(__NT__)
|
||||
#elif defined(__WIN2000__)
|
||||
struct {
|
||||
DWORD Count;
|
||||
LUID_AND_ATTRIBUTES Privilege[1];
|
||||
@ -187,7 +187,7 @@ os_awe_allocate_physical_mem(
|
||||
|
||||
return(TRUE);
|
||||
|
||||
#elif defined(__NT__)
|
||||
#elif defined(__WIN2000__)
|
||||
BOOL bResult;
|
||||
os_awe_t NumberOfPages; /* Question: why does Windows
|
||||
use the name ULONG_PTR for
|
||||
@ -318,7 +318,7 @@ os_awe_allocate_virtual_mem_window(
|
||||
|
||||
return(os_awe_simulate_window);
|
||||
|
||||
#elif defined(__NT__)
|
||||
#elif defined(__WIN2000__)
|
||||
byte* ptr;
|
||||
|
||||
if (size > 0x7FFFFFFFFF) {
|
||||
@ -424,7 +424,7 @@ os_awe_map_physical_mem_to_window(
|
||||
|
||||
return(TRUE);
|
||||
|
||||
#elif defined(__NT__)
|
||||
#elif defined(__WIN2000__)
|
||||
BOOL bResult;
|
||||
os_awe_t n_pages;
|
||||
|
||||
|
@ -1008,7 +1008,7 @@ innobase_start_or_create_for_mysql(void)
|
||||
srv_startup_is_before_trx_rollback_phase = TRUE;
|
||||
os_aio_use_native_aio = FALSE;
|
||||
|
||||
#if !defined(__NT__) && !defined(UNIV_SIMULATE_AWE)
|
||||
#if !defined(__WIN2000__) && !defined(UNIV_SIMULATE_AWE)
|
||||
if (srv_use_awe) {
|
||||
|
||||
fprintf(stderr,
|
||||
|
@ -59,7 +59,7 @@ const char *client_errors[]=
|
||||
"No parameters exists in the statement",
|
||||
"Invalid parameter number",
|
||||
"Can't send long data for non string or binary data types (parameter: %d)",
|
||||
"Using un supported buffer type: %d (parameter: %d)",
|
||||
"Using unsupported buffer type: %d (parameter: %d)",
|
||||
"Shared memory (%lu)",
|
||||
"Can't open shared memory. Request event don't create (%lu)",
|
||||
"Can't open shared memory. Answer event don't create (%lu)",
|
||||
@ -114,7 +114,7 @@ const char *client_errors[]=
|
||||
"No parameters exists in the statement",
|
||||
"Invalid parameter number",
|
||||
"Can't send long data for non string or binary data types (parameter: %d)",
|
||||
"Using un supported buffer type: %d (parameter: %d)",
|
||||
"Using unsupported buffer type: %d (parameter: %d)",
|
||||
"Shared memory (%lu)",
|
||||
"Can't open shared memory. Request event don't create (%lu)",
|
||||
"Can't open shared memory. Answer event don't create (%lu)",
|
||||
@ -167,7 +167,7 @@ const char *client_errors[]=
|
||||
"No parameters exists in the statement",
|
||||
"Invalid parameter number",
|
||||
"Can't send long data for non string or binary data types (parameter: %d)",
|
||||
"Using un supported buffer type: %d (parameter: %d)",
|
||||
"Using unsupported buffer type: %d (parameter: %d)",
|
||||
"Shared memory (%lu)",
|
||||
"Can't open shared memory. Request event don't create (%lu)",
|
||||
"Can't open shared memory. Answer event don't create (%lu)",
|
||||
|
@ -3932,19 +3932,40 @@ mysql_prepare(MYSQL *mysql, const char *query, ulong length)
|
||||
|
||||
unsigned int alloc_stmt_fields(MYSQL_STMT *stmt)
|
||||
{
|
||||
MYSQL_FIELD *fields;
|
||||
MYSQL_FIELD *fields, *field, *end;
|
||||
MEM_ROOT *alloc= &stmt->mem_root;
|
||||
|
||||
if (!stmt->mysql->field_count)
|
||||
return 0;
|
||||
stmt->field_count= stmt->mysql->field_count;
|
||||
fields= stmt->mysql->fields;
|
||||
|
||||
if (!(stmt->fields= (MYSQL_FIELD *) alloc_root(&stmt->mem_root,
|
||||
sizeof(fields))) ||
|
||||
!(stmt->bind= (MYSQL_BIND *) alloc_root(&stmt->mem_root,
|
||||
stmt->field_count= stmt->mysql->field_count;
|
||||
|
||||
/*
|
||||
Get the field information for non-select statements
|
||||
like SHOW and DESCRIBE commands
|
||||
*/
|
||||
if (!(stmt->fields= (MYSQL_FIELD *) alloc_root(alloc,
|
||||
sizeof(MYSQL_FIELD) * stmt->field_count)) ||
|
||||
!(stmt->bind= (MYSQL_BIND *) alloc_root(alloc,
|
||||
sizeof(MYSQL_BIND ) * stmt->field_count)))
|
||||
return 0;
|
||||
memcpy((char *)stmt->fields, (char *)fields, sizeof(fields));
|
||||
|
||||
for (fields= stmt->mysql->fields, end= fields+stmt->field_count,
|
||||
field= stmt->fields;
|
||||
field && fields < end; fields++, field++)
|
||||
{
|
||||
field->db = strdup_root(alloc,fields->db);
|
||||
field->table = strdup_root(alloc,fields->table);
|
||||
field->org_table= strdup_root(alloc,fields->org_table);
|
||||
field->name = strdup_root(alloc,fields->name);
|
||||
field->org_name = strdup_root(alloc,fields->org_name);
|
||||
field->length = fields->length;
|
||||
field->type = fields->type;
|
||||
field->flags = fields->flags;
|
||||
field->decimals = fields->decimals;
|
||||
field->def = fields->def ? strdup_root(alloc,fields->def): 0;
|
||||
field->max_length= 0;
|
||||
}
|
||||
return stmt->field_count;
|
||||
}
|
||||
|
||||
@ -4356,6 +4377,7 @@ my_ulonglong STDCALL mysql_stmt_affected_rows(MYSQL_STMT *stmt)
|
||||
static my_bool int_is_null_true= 1; /* Used for MYSQL_TYPE_NULL */
|
||||
static my_bool int_is_null_false= 0;
|
||||
static my_bool int_is_null_dummy;
|
||||
static unsigned long param_length_is_dummy;
|
||||
|
||||
/*
|
||||
Setup the parameter data buffers from application
|
||||
@ -5041,7 +5063,7 @@ my_bool STDCALL mysql_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind)
|
||||
param->is_null= &int_is_null_dummy;
|
||||
|
||||
if (!param->length)
|
||||
param->length= ¶m->buffer_length;
|
||||
param->length= ¶m_length_is_dummy;
|
||||
|
||||
param->param_number= param_count++;
|
||||
/* Setup data copy functions for the different supported types */
|
||||
@ -5318,22 +5340,42 @@ int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt)
|
||||
*/
|
||||
static my_bool stmt_close(MYSQL_STMT *stmt, my_bool skip_list)
|
||||
{
|
||||
MYSQL *mysql;
|
||||
my_bool error= 0;
|
||||
DBUG_ENTER("mysql_stmt_close");
|
||||
|
||||
DBUG_ASSERT(stmt != 0);
|
||||
|
||||
mysql= stmt->mysql;
|
||||
if (mysql->status != MYSQL_STATUS_READY)
|
||||
{
|
||||
/* Clear the current execution status */
|
||||
DBUG_PRINT("warning",("Not all packets read, clearing them"));
|
||||
for (;;)
|
||||
{
|
||||
ulong pkt_len;
|
||||
if ((pkt_len= net_safe_read(mysql)) == packet_error)
|
||||
break;
|
||||
if (pkt_len <= 8 && mysql->net.read_pos[0] == 254)
|
||||
break;
|
||||
}
|
||||
mysql->status= MYSQL_STATUS_READY;
|
||||
}
|
||||
if (stmt->state == MY_ST_PREPARE || stmt->state == MY_ST_EXECUTE)
|
||||
{
|
||||
char buff[4];
|
||||
int4store(buff, stmt->stmt_id);
|
||||
error= simple_command(stmt->mysql, COM_CLOSE_STMT, buff, 4, 1);
|
||||
error= simple_command(mysql, COM_CLOSE_STMT, buff, 4, 1);
|
||||
}
|
||||
if (!error)
|
||||
{
|
||||
mysql_free_result(stmt->result);
|
||||
free_root(&stmt->mem_root, MYF(0));
|
||||
if (!skip_list)
|
||||
mysql->stmts= list_delete(mysql->stmts, &stmt->list);
|
||||
mysql->status= MYSQL_STATUS_READY;
|
||||
my_free((gptr) stmt, MYF(MY_WME));
|
||||
}
|
||||
mysql_free_result(stmt->result);
|
||||
free_root(&stmt->mem_root, MYF(0));
|
||||
if (!skip_list)
|
||||
stmt->mysql->stmts= list_delete(stmt->mysql->stmts, &stmt->list);
|
||||
stmt->mysql->status= MYSQL_STATUS_READY;
|
||||
my_free((gptr) stmt, MYF(MY_WME));
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
|
78
mysql-test/r/rpl_user_variables.result
Normal file
78
mysql-test/r/rpl_user_variables.result
Normal file
@ -0,0 +1,78 @@
|
||||
stop slave;
|
||||
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
|
||||
reset master;
|
||||
reset slave;
|
||||
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
|
||||
start slave;
|
||||
stop slave;
|
||||
reset master;
|
||||
drop table if exists t1;
|
||||
create table t1(n char(30));
|
||||
set @i1:=12345678901234, @i2:=-12345678901234, @i3:=0, @i4:=-1;
|
||||
set @s1:='This is a test', @r1:=12.5, @r2:=-12.5;
|
||||
set @n1:=null;
|
||||
set @s2:='', @s3:='abc\'def', @s4:= 'abc\\def', @s5:= 'abc''def';
|
||||
insert into t1 values (@i1), (@i2), (@i3), (@i4);
|
||||
insert into t1 values (@r1), (@r2);
|
||||
insert into t1 values (@s1), (@s2), (@s3), (@s4), (@s5);
|
||||
insert into t1 values (@n1);
|
||||
insert into t1 values (@n2);
|
||||
insert into t1 values (@a:=0), (@a:=@a+1), (@a:=@a+1);
|
||||
insert into t1 values (@a+(@b:=@a+1));
|
||||
set @q:='abc';
|
||||
insert t1 values (@q), (@q:=concat(@q, 'n1')), (@q:=concat(@q, 'n2'));
|
||||
set @a:=5;
|
||||
insert into t1 values (@a),(@a);
|
||||
start slave;
|
||||
select * from t1;
|
||||
n
|
||||
12345678901234
|
||||
-12345678901234
|
||||
0
|
||||
-1
|
||||
12.5
|
||||
-12.5
|
||||
This is a test
|
||||
|
||||
abc'def
|
||||
abc\def
|
||||
abc'def
|
||||
NULL
|
||||
NULL
|
||||
0
|
||||
1
|
||||
2
|
||||
5
|
||||
abc
|
||||
abcn1
|
||||
abcn1n2
|
||||
5
|
||||
5
|
||||
show binlog events from 141;
|
||||
Log_name Pos Event_type Server_id Orig_log_pos Info
|
||||
slave-bin.000001 141 User var 2 141 @i1=12345678901234
|
||||
slave-bin.000001 184 User var 2 184 @i2=-12345678901234
|
||||
slave-bin.000001 227 User var 2 227 @i3=0
|
||||
slave-bin.000001 270 User var 2 270 @i4=-1
|
||||
slave-bin.000001 313 Query 1 313 use `test`; insert into t1 values (@i1), (@i2), (@i3), (@i4)
|
||||
slave-bin.000001 396 User var 2 396 @r1=12.5
|
||||
slave-bin.000001 439 User var 2 439 @r2=-12.5
|
||||
slave-bin.000001 482 Query 1 482 use `test`; insert into t1 values (@r1), (@r2)
|
||||
slave-bin.000001 551 User var 2 551 @s1='This is a test'
|
||||
slave-bin.000001 601 User var 2 601 @s2=''
|
||||
slave-bin.000001 637 User var 2 637 @s3='abc'def'
|
||||
slave-bin.000001 680 User var 2 680 @s4='abc\def'
|
||||
slave-bin.000001 723 User var 2 723 @s5='abc'def'
|
||||
slave-bin.000001 766 Query 1 766 use `test`; insert into t1 values (@s1), (@s2), (@s3), (@s4), (@s5)
|
||||
slave-bin.000001 856 User var 2 856 @n1=NULL
|
||||
slave-bin.000001 882 Query 1 882 use `test`; insert into t1 values (@n1)
|
||||
slave-bin.000001 944 Query 1 944 use `test`; insert into t1 values (@n2)
|
||||
slave-bin.000001 1006 Query 1 1006 use `test`; insert into t1 values (@a:=0), (@a:=@a+1), (@a:=@a+1)
|
||||
slave-bin.000001 1094 User var 2 1094 @a='2'
|
||||
slave-bin.000001 1130 Query 1 1130 use `test`; insert into t1 values (@a+(@b:=@a+1))
|
||||
slave-bin.000001 1202 User var 2 1202 @q='abc'
|
||||
slave-bin.000001 1240 Query 1 1240 use `test`; insert t1 values (@q), (@q:=concat(@q, 'n1')), (@q:=concat(@q, 'n2'))
|
||||
slave-bin.000001 1344 User var 2 1344 @a=5
|
||||
slave-bin.000001 1386 Query 1 1386 use `test`; insert into t1 values (@a),(@a)
|
||||
drop table t1;
|
||||
stop slave;
|
39
mysql-test/t/rpl_user_variables.test
Normal file
39
mysql-test/t/rpl_user_variables.test
Normal file
@ -0,0 +1,39 @@
|
||||
source include/master-slave.inc;
|
||||
connection master;
|
||||
save_master_pos;
|
||||
connection slave;
|
||||
sync_with_master;
|
||||
stop slave;
|
||||
reset master;
|
||||
connection master;
|
||||
--disable_warnings
|
||||
drop table if exists t1;
|
||||
--enable_warnings
|
||||
create table t1(n char(30));
|
||||
set @i1:=12345678901234, @i2:=-12345678901234, @i3:=0, @i4:=-1;
|
||||
set @s1:='This is a test', @r1:=12.5, @r2:=-12.5;
|
||||
set @n1:=null;
|
||||
set @s2:='', @s3:='abc\'def', @s4:= 'abc\\def', @s5:= 'abc''def';
|
||||
insert into t1 values (@i1), (@i2), (@i3), (@i4);
|
||||
insert into t1 values (@r1), (@r2);
|
||||
insert into t1 values (@s1), (@s2), (@s3), (@s4), (@s5);
|
||||
insert into t1 values (@n1);
|
||||
insert into t1 values (@n2);
|
||||
insert into t1 values (@a:=0), (@a:=@a+1), (@a:=@a+1);
|
||||
insert into t1 values (@a+(@b:=@a+1));
|
||||
set @q:='abc';
|
||||
insert t1 values (@q), (@q:=concat(@q, 'n1')), (@q:=concat(@q, 'n2'));
|
||||
set @a:=5;
|
||||
insert into t1 values (@a),(@a);
|
||||
save_master_pos;
|
||||
connection slave;
|
||||
start slave;
|
||||
sync_with_master;
|
||||
select * from t1;
|
||||
show binlog events from 141;
|
||||
connection master;
|
||||
drop table t1;
|
||||
save_master_pos;
|
||||
connection slave;
|
||||
sync_with_master;
|
||||
stop slave;
|
@ -59,6 +59,7 @@ static void simple_cs_init_functions(CHARSET_INFO *cs)
|
||||
|
||||
cs->strnxfrm = my_strnxfrm_simple;
|
||||
cs->strnncoll = my_strnncoll_simple;
|
||||
cs->strnncollsp = my_strnncollsp_simple;
|
||||
cs->like_range = my_like_range_simple;
|
||||
cs->wildcmp = my_wildcmp_8bit;
|
||||
cs->mb_wc = my_mb_wc_8bit;
|
||||
@ -83,6 +84,8 @@ static void simple_cs_init_functions(CHARSET_INFO *cs)
|
||||
cs->strntod = my_strntod_8bit;
|
||||
cs->scan = my_scan_8bit;
|
||||
cs->mbmaxlen = 1;
|
||||
cs->numchars = my_numchars_8bit;
|
||||
cs->charpos = my_charpos_8bit;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1280,11 +1280,11 @@ udf_handler::fix_fields(THD *thd, TABLE_LIST *tables, Item_result_field *func,
|
||||
}
|
||||
else
|
||||
thd=current_thd; // In WHERE / const clause
|
||||
udf_func *tmp_udf=find_udf(u_d->name,(uint) strlen(u_d->name),1);
|
||||
udf_func *tmp_udf=find_udf(u_d->name.str,(uint) u_d->name.length,1);
|
||||
|
||||
if (!tmp_udf)
|
||||
{
|
||||
my_printf_error(ER_CANT_FIND_UDF,ER(ER_CANT_FIND_UDF),MYF(0),u_d->name,
|
||||
my_printf_error(ER_CANT_FIND_UDF,ER(ER_CANT_FIND_UDF),MYF(0),u_d->name.str,
|
||||
errno);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
@ -1930,6 +1930,7 @@ static user_var_entry *get_variable(HASH *hash, LEX_STRING &name,
|
||||
entry->value=0;
|
||||
entry->length=0;
|
||||
entry->update_query_id=0;
|
||||
entry->used_query_id=current_thd->query_id;
|
||||
entry->type=STRING_RESULT;
|
||||
memcpy(entry->name.str, name.str, name.length+1);
|
||||
if (hash_insert(hash,(byte*) entry))
|
||||
@ -2063,7 +2064,7 @@ Item_func_set_user_var::val_str(String *str)
|
||||
{
|
||||
String *res=args[0]->val_str(str);
|
||||
if (!res) // Null value
|
||||
update_hash((void*) 0,0,STRING_RESULT, default_charset_info);
|
||||
update_hash((void*) 0, 0, STRING_RESULT, default_charset_info);
|
||||
else
|
||||
update_hash(res->c_ptr(),res->length()+1,STRING_RESULT,res->charset());
|
||||
return res;
|
||||
@ -2162,14 +2163,58 @@ longlong Item_func_get_user_var::val_int()
|
||||
return LL(0); // Impossible
|
||||
}
|
||||
|
||||
/* From sql_parse.cc */
|
||||
extern bool is_update_query(enum enum_sql_command command);
|
||||
|
||||
void Item_func_get_user_var::fix_length_and_dec()
|
||||
{
|
||||
BINLOG_USER_VAR_EVENT *user_var_event;
|
||||
THD *thd=current_thd;
|
||||
maybe_null=1;
|
||||
decimals=NOT_FIXED_DEC;
|
||||
max_length=MAX_BLOB_WIDTH;
|
||||
var_entry= get_variable(&thd->user_vars, name, 0);
|
||||
|
||||
if ((var_entry= get_variable(&thd->user_vars, name, 0)))
|
||||
{
|
||||
if (opt_bin_log && is_update_query(thd->lex.sql_command) &&
|
||||
var_entry->used_query_id != thd->query_id)
|
||||
{
|
||||
/*
|
||||
First we need to store value of var_entry, when the next situation appers:
|
||||
> set @a:=1;
|
||||
> insert into t1 values (@a), (@a:=@a+1), (@a:=@a+1);
|
||||
We have to write to binlog value @a= 1;
|
||||
*/
|
||||
uint size= ALIGN_SIZE(sizeof(BINLOG_USER_VAR_EVENT)) + var_entry->length;
|
||||
if (!(user_var_event= (BINLOG_USER_VAR_EVENT *) thd->alloc(size)))
|
||||
goto err;
|
||||
|
||||
user_var_event->value= (char*) user_var_event +
|
||||
ALIGN_SIZE(sizeof(BINLOG_USER_VAR_EVENT));
|
||||
user_var_event->user_var_event= var_entry;
|
||||
user_var_event->type= var_entry->type;
|
||||
user_var_event->charset_number= var_entry->var_charset->number;
|
||||
if (!var_entry->value)
|
||||
{
|
||||
/* NULL value*/
|
||||
user_var_event->length= 0;
|
||||
user_var_event->value= 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
user_var_event->length= var_entry->length;
|
||||
memcpy(user_var_event->value, var_entry->value,
|
||||
var_entry->length);
|
||||
}
|
||||
var_entry->used_query_id= thd->query_id;
|
||||
if (insert_dynamic(&thd->user_var_events, (gptr) &user_var_event))
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
return;
|
||||
err:
|
||||
thd->fatal_error= 1;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
@ -805,13 +805,8 @@ String *Item_func_insert::val_str(String *str)
|
||||
if (args[0]->null_value || args[1]->null_value || args[2]->null_value ||
|
||||
args[3]->null_value)
|
||||
goto null; /* purecov: inspected */
|
||||
#ifdef USE_MB
|
||||
if (use_mb(res->charset()) && !args[0]->binary())
|
||||
{
|
||||
start=res->charpos(start);
|
||||
length=res->charpos(length,start);
|
||||
}
|
||||
#endif
|
||||
start=res->charpos(start);
|
||||
length=res->charpos(length,start);
|
||||
if (start > res->length()+1)
|
||||
return res; // Wrong param; skip insert
|
||||
if (length > res->length()-start)
|
||||
@ -878,10 +873,7 @@ String *Item_func_left::val_str(String *str)
|
||||
return 0;
|
||||
if (length <= 0)
|
||||
return &empty_string;
|
||||
#ifdef USE_MB
|
||||
if (use_mb(res->charset()) && !binary())
|
||||
length = res->charpos(length);
|
||||
#endif
|
||||
length= res->charpos(length);
|
||||
if (res->length() > (ulong) length)
|
||||
{ // Safe even if const arg
|
||||
if (!res->alloced_length())
|
||||
@ -927,19 +919,11 @@ String *Item_func_right::val_str(String *str)
|
||||
return &empty_string; /* purecov: inspected */
|
||||
if (res->length() <= (uint) length)
|
||||
return res; /* purecov: inspected */
|
||||
#ifdef USE_MB
|
||||
if (use_mb(res->charset()) && !binary())
|
||||
{
|
||||
uint start=res->numchars()-(uint) length;
|
||||
if (start<=0) return res;
|
||||
start=res->charpos(start);
|
||||
tmp_value.set(*res,start,res->length()-start);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
tmp_value.set(*res,(res->length()- (uint) length),(uint) length);
|
||||
}
|
||||
|
||||
uint start=res->numchars()-(uint) length;
|
||||
if (start<=0) return res;
|
||||
start=res->charpos(start);
|
||||
tmp_value.set(*res,start,res->length()-start);
|
||||
return &tmp_value;
|
||||
}
|
||||
|
||||
@ -960,13 +944,8 @@ String *Item_func_substr::val_str(String *str)
|
||||
if ((null_value=(args[0]->null_value || args[1]->null_value ||
|
||||
(arg_count == 3 && args[2]->null_value))))
|
||||
return 0; /* purecov: inspected */
|
||||
#ifdef USE_MB
|
||||
if (use_mb(res->charset()) && !binary())
|
||||
{
|
||||
start=res->charpos(start);
|
||||
length=res->charpos(length,start);
|
||||
}
|
||||
#endif
|
||||
start=res->charpos(start);
|
||||
length=res->charpos(length,start);
|
||||
if (start < 0 || (uint) start+1 > res->length() || length <= 0)
|
||||
return &empty_string;
|
||||
|
||||
|
17
sql/log.cc
17
sql/log.cc
@ -1104,6 +1104,23 @@ bool MYSQL_LOG::write(Log_event* event_info)
|
||||
if (e.write(file))
|
||||
goto err;
|
||||
}
|
||||
if (thd->user_var_events.elements)
|
||||
{
|
||||
for (uint i= 0; i < thd->user_var_events.elements; i++)
|
||||
{
|
||||
BINLOG_USER_VAR_EVENT *user_var_event;
|
||||
get_dynamic(&thd->user_var_events,(gptr) &user_var_event, i);
|
||||
User_var_log_event e(thd, user_var_event->user_var_event->name.str,
|
||||
user_var_event->user_var_event->name.length,
|
||||
user_var_event->value,
|
||||
user_var_event->length,
|
||||
user_var_event->type,
|
||||
user_var_event->charset_number);
|
||||
e.set_log_pos(this);
|
||||
if (e.write(file))
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
if (thd->variables.convert_set)
|
||||
{
|
||||
char buf[256], *p;
|
||||
|
242
sql/log_event.cc
242
sql/log_event.cc
@ -227,6 +227,7 @@ const char* Log_event::get_type_str()
|
||||
case DELETE_FILE_EVENT: return "Delete_file";
|
||||
case EXEC_LOAD_EVENT: return "Exec_load";
|
||||
case RAND_EVENT: return "RAND";
|
||||
case USER_VAR_EVENT: return "User var";
|
||||
default: /* impossible */ return "Unknown";
|
||||
}
|
||||
}
|
||||
@ -614,6 +615,9 @@ Log_event* Log_event::read_log_event(const char* buf, int event_len,
|
||||
case RAND_EVENT:
|
||||
ev = new Rand_log_event(buf, old_format);
|
||||
break;
|
||||
case USER_VAR_EVENT:
|
||||
ev = new User_var_log_event(buf, old_format);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -1979,8 +1983,246 @@ int Rand_log_event::exec_event(struct st_relay_log_info* rli)
|
||||
rli->inc_pending(get_event_len());
|
||||
return 0;
|
||||
}
|
||||
#endif // !MYSQL_CLIENT
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*****************************************************************************
|
||||
|
||||
User_var_log_event methods
|
||||
|
||||
*****************************************************************************
|
||||
****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
|
||||
User_var_log_event::pack_info()
|
||||
|
||||
****************************************************************************/
|
||||
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
|
||||
void User_var_log_event::pack_info(Protocol* protocol)
|
||||
{
|
||||
char *buf= 0;
|
||||
uint val_offset= 2 + name_len;
|
||||
uint event_len= val_offset;
|
||||
|
||||
if (is_null)
|
||||
{
|
||||
buf= my_malloc(val_offset + 5, MYF(MY_WME));
|
||||
strmov(buf + val_offset, "NULL");
|
||||
event_len= val_offset + 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (type) {
|
||||
case REAL_RESULT:
|
||||
double real_val;
|
||||
float8get(real_val, val);
|
||||
buf= my_malloc(val_offset + FLOATING_POINT_BUFFER, MYF(MY_WME));
|
||||
event_len += my_sprintf(buf + val_offset,
|
||||
(buf + val_offset, "%.14g", real_val));
|
||||
break;
|
||||
case INT_RESULT:
|
||||
buf= my_malloc(val_offset + 22, MYF(MY_WME));
|
||||
event_len= longlong10_to_str(uint8korr(val), buf + val_offset,-10)-buf;
|
||||
break;
|
||||
case STRING_RESULT:
|
||||
/*
|
||||
This is correct as pack_info is used for SHOW BINLOG command
|
||||
only. But be carefull this is may be incorrect in other cases as
|
||||
string may contain \ and '.
|
||||
*/
|
||||
buf= my_malloc(val_offset + 2 + val_len, MYF(MY_WME));
|
||||
buf[val_offset]= '\'';
|
||||
memcpy(buf + val_offset + 1, val, val_len);
|
||||
buf[val_offset + val_len]= '\'';
|
||||
event_len= val_offset + 1 + val_len;
|
||||
break;
|
||||
case ROW_RESULT:
|
||||
DBUG_ASSERT(1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
buf[0]= '@';
|
||||
buf[1+name_len]= '=';
|
||||
memcpy(buf+1, name, name_len);
|
||||
protocol->store(buf, event_len);
|
||||
my_free(buf, MYF(MY_ALLOW_ZERO_PTR));
|
||||
}
|
||||
#endif // !MYSQL_CLIENT
|
||||
/*****************************************************************************
|
||||
|
||||
User_var_log_event::User_var_log_event()
|
||||
|
||||
****************************************************************************/
|
||||
User_var_log_event::User_var_log_event(const char* buf, bool old_format)
|
||||
:Log_event(buf, old_format)
|
||||
{
|
||||
buf+= (old_format) ? OLD_HEADER_LEN : LOG_EVENT_HEADER_LEN;
|
||||
name_len= uint4korr(buf);
|
||||
name= (char *) buf + UV_NAME_LEN_SIZE;
|
||||
is_null= buf[UV_NAME_LEN_SIZE + name_len];
|
||||
if (is_null)
|
||||
{
|
||||
type= STRING_RESULT;
|
||||
val_len= 0;
|
||||
val= 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
type= (Item_result) buf[UV_VAL_IS_NULL + UV_NAME_LEN_SIZE + name_len];
|
||||
charset_number= uint4korr(buf + UV_NAME_LEN_SIZE + name_len +
|
||||
UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE);
|
||||
val_len= uint4korr(buf + UV_NAME_LEN_SIZE + name_len +
|
||||
UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE +
|
||||
UV_CHARSET_NUMBER_SIZE);
|
||||
val= (char *) buf + UV_NAME_LEN_SIZE + name_len + UV_VAL_IS_NULL +
|
||||
UV_VAL_TYPE_SIZE + UV_CHARSET_NUMBER_SIZE + UV_VAL_LEN_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
|
||||
User_var_log_event::write_data()
|
||||
|
||||
****************************************************************************/
|
||||
int User_var_log_event::write_data(IO_CACHE* file)
|
||||
{
|
||||
char buf[UV_NAME_LEN_SIZE];
|
||||
char buf1[UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE +
|
||||
UV_CHARSET_NUMBER_SIZE + UV_VAL_LEN_SIZE];
|
||||
char buf2[8];
|
||||
char *pos= buf2;
|
||||
int4store(buf, name_len);
|
||||
buf1[0]= is_null;
|
||||
if (!is_null)
|
||||
{
|
||||
buf1[1]= type;
|
||||
int4store(buf1 + 2, charset_number);
|
||||
int4store(buf1 + 2 + UV_CHARSET_NUMBER_SIZE, val_len);
|
||||
|
||||
switch (type) {
|
||||
case REAL_RESULT:
|
||||
float8store(buf2, *(double*) val);
|
||||
break;
|
||||
case INT_RESULT:
|
||||
int8store(buf2, *(longlong*) val);
|
||||
break;
|
||||
case STRING_RESULT:
|
||||
pos= val;
|
||||
break;
|
||||
case ROW_RESULT:
|
||||
DBUG_ASSERT(1);
|
||||
return 0;
|
||||
}
|
||||
return (my_b_safe_write(file, (byte*) buf, sizeof(buf)) ||
|
||||
my_b_safe_write(file, (byte*) name, name_len) ||
|
||||
my_b_safe_write(file, (byte*) buf1, sizeof(buf1)) ||
|
||||
my_b_safe_write(file, (byte*) pos, val_len));
|
||||
}
|
||||
|
||||
return (my_b_safe_write(file, (byte*) buf, sizeof(buf)) ||
|
||||
my_b_safe_write(file, (byte*) name, name_len) ||
|
||||
my_b_safe_write(file, (byte*) buf1, 1));
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
|
||||
User_var_log_event::print()
|
||||
|
||||
****************************************************************************/
|
||||
#ifdef MYSQL_CLIENT
|
||||
void User_var_log_event::print(FILE* file, bool short_form, char* last_db)
|
||||
{
|
||||
if (!short_form)
|
||||
{
|
||||
print_header(file);
|
||||
fprintf(file, "\tUser_var\n");
|
||||
}
|
||||
|
||||
fprintf(file, "SET @");
|
||||
my_fwrite(file, (byte*) name, (uint) (name_len), MYF(MY_NABP | MY_WME));
|
||||
|
||||
if (is_null)
|
||||
{
|
||||
fprintf(file, ":=NULL;\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (type) {
|
||||
case REAL_RESULT:
|
||||
double real_val;
|
||||
float8get(real_val, val);
|
||||
fprintf(file, ":=%.14g;\n", real_val);
|
||||
break;
|
||||
case INT_RESULT:
|
||||
char int_buf[22];
|
||||
longlong10_to_str(uint8korr(val), int_buf, -10);
|
||||
fprintf(file, ":=%s;\n", int_buf);
|
||||
break;
|
||||
case STRING_RESULT:
|
||||
fprintf(file, ":='%s';\n", val);
|
||||
break;
|
||||
case ROW_RESULT:
|
||||
DBUG_ASSERT(1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
fflush(file);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*****************************************************************************
|
||||
|
||||
User_var_log_event::exec_event()
|
||||
|
||||
****************************************************************************/
|
||||
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
|
||||
int User_var_log_event::exec_event(struct st_relay_log_info* rli)
|
||||
{
|
||||
Item *it= 0;
|
||||
CHARSET_INFO *charset= log_cs;
|
||||
LEX_STRING user_var_name;
|
||||
user_var_name.str= name;
|
||||
user_var_name.length= name_len;
|
||||
|
||||
if (type != ROW_RESULT)
|
||||
init_sql_alloc(&thd->mem_root, 8192,0);
|
||||
|
||||
if (is_null)
|
||||
{
|
||||
it= new Item_null();
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (type) {
|
||||
case REAL_RESULT:
|
||||
double real_val;
|
||||
float8get(real_val, val);
|
||||
it= new Item_real(real_val);
|
||||
break;
|
||||
case INT_RESULT:
|
||||
it= new Item_int((longlong) uint8korr(val));
|
||||
break;
|
||||
case STRING_RESULT:
|
||||
it= new Item_string(val, val_len, charset);
|
||||
break;
|
||||
case ROW_RESULT:
|
||||
DBUG_ASSERT(1);
|
||||
return 0;
|
||||
}
|
||||
charset= get_charset(charset_number, MYF(0));
|
||||
}
|
||||
Item_func_set_user_var e(user_var_name, it);
|
||||
e.fix_fields(thd, 0, 0);
|
||||
e.update_hash(val, val_len, type, charset);
|
||||
free_root(&thd->mem_root,0);
|
||||
|
||||
rli->inc_pending(get_event_len());
|
||||
return 0;
|
||||
}
|
||||
#endif // !MYSQL_CLIENT
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*****************************************************************************
|
||||
|
@ -173,6 +173,14 @@ struct sql_ex_info
|
||||
#define RAND_SEED1_OFFSET 0
|
||||
#define RAND_SEED2_OFFSET 8
|
||||
|
||||
/* User_var event post-header */
|
||||
|
||||
#define UV_VAL_LEN_SIZE 4
|
||||
#define UV_VAL_IS_NULL 1
|
||||
#define UV_VAL_TYPE_SIZE 1
|
||||
#define UV_NAME_LEN_SIZE 4
|
||||
#define UV_CHARSET_NUMBER_SIZE 4
|
||||
|
||||
/* Load event post-header */
|
||||
|
||||
#define L_THREAD_ID_OFFSET 0
|
||||
@ -222,7 +230,7 @@ enum Log_event_type
|
||||
START_EVENT = 1, QUERY_EVENT =2, STOP_EVENT=3, ROTATE_EVENT = 4,
|
||||
INTVAR_EVENT=5, LOAD_EVENT=6, SLAVE_EVENT=7, CREATE_FILE_EVENT=8,
|
||||
APPEND_BLOCK_EVENT=9, EXEC_LOAD_EVENT=10, DELETE_FILE_EVENT=11,
|
||||
NEW_LOAD_EVENT=12, RAND_EVENT=13
|
||||
NEW_LOAD_EVENT=12, RAND_EVENT=13, USER_VAR_EVENT=14
|
||||
};
|
||||
|
||||
enum Int_event_type
|
||||
@ -613,6 +621,46 @@ class Rand_log_event: public Log_event
|
||||
bool is_valid() { return 1; }
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
|
||||
User var Log Event class
|
||||
|
||||
****************************************************************************/
|
||||
class User_var_log_event: public Log_event
|
||||
{
|
||||
public:
|
||||
char *name;
|
||||
uint name_len;
|
||||
char *val;
|
||||
ulong val_len;
|
||||
Item_result type;
|
||||
uint charset_number;
|
||||
byte is_null;
|
||||
#ifndef MYSQL_CLIENT
|
||||
User_var_log_event(THD* thd_arg, char *name_arg, uint name_len_arg,
|
||||
char *val_arg, ulong val_len_arg, Item_result type_arg,
|
||||
uint charset_number_arg)
|
||||
:Log_event(), name(name_arg), name_len(name_len_arg), val(val_arg),
|
||||
val_len(val_len_arg), type(type_arg), charset_number(charset_number_arg)
|
||||
{ is_null= !val; }
|
||||
void pack_info(Protocol* protocol);
|
||||
int exec_event(struct st_relay_log_info* rli);
|
||||
#else
|
||||
void print(FILE* file, bool short_form = 0, char* last_db = 0);
|
||||
#endif
|
||||
|
||||
User_var_log_event(const char* buf, bool old_format);
|
||||
~User_var_log_event() {}
|
||||
Log_event_type get_type_code() { return USER_VAR_EVENT;}
|
||||
int get_data_size()
|
||||
{
|
||||
return (is_null ? UV_NAME_LEN_SIZE + name_len + UV_VAL_IS_NULL :
|
||||
UV_NAME_LEN_SIZE + name_len + UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE +
|
||||
UV_CHARSET_NUMBER_SIZE + UV_VAL_LEN_SIZE + val_len);
|
||||
}
|
||||
int write_data(IO_CACHE* file);
|
||||
bool is_valid() { return 1; }
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
|
||||
|
@ -146,6 +146,17 @@ THD::THD():user_time(0), is_fatal_error(0),
|
||||
(hash_get_key) get_var_key,
|
||||
(hash_free_key) free_user_var,0);
|
||||
|
||||
/* For user vars replication*/
|
||||
if (opt_bin_log)
|
||||
my_init_dynamic_array(&user_var_events,
|
||||
sizeof(BINLOG_USER_VAR_EVENT *),
|
||||
16,
|
||||
16);
|
||||
else
|
||||
bzero((char*) &user_var_events, sizeof(user_var_events));
|
||||
|
||||
|
||||
|
||||
/* Prepared statements */
|
||||
last_prepared_stmt= 0;
|
||||
init_tree(&prepared_statements, 0, 0, sizeof(PREP_STMT),
|
||||
@ -244,6 +255,7 @@ void THD::cleanup(void)
|
||||
close_thread_tables(this);
|
||||
}
|
||||
close_temporary_tables(this);
|
||||
delete_dynamic(&user_var_events);
|
||||
hash_free(&user_vars);
|
||||
if (global_read_lock)
|
||||
unlock_global_read_lock(this);
|
||||
|
@ -57,6 +57,15 @@ typedef struct st_log_info
|
||||
~st_log_info() { pthread_mutex_destroy(&lock);}
|
||||
} LOG_INFO;
|
||||
|
||||
typedef struct st_user_var_events
|
||||
{
|
||||
user_var_entry *user_var_event;
|
||||
char *value;
|
||||
ulong length;
|
||||
Item_result type;
|
||||
uint charset_number;
|
||||
} BINLOG_USER_VAR_EVENT;
|
||||
|
||||
class Log_event;
|
||||
|
||||
class MYSQL_LOG {
|
||||
@ -523,6 +532,8 @@ public:
|
||||
uint select_number; //number of select (used for EXPLAIN)
|
||||
/* variables.transaction_isolation is reset to this after each commit */
|
||||
enum_tx_isolation session_tx_isolation;
|
||||
/* for user variables replication*/
|
||||
DYNAMIC_ARRAY user_var_events;
|
||||
// extend scramble to handle new auth
|
||||
char scramble[SCRAMBLE41_LENGTH+1];
|
||||
// old scramble is needed to handle old clients
|
||||
@ -917,7 +928,7 @@ class user_var_entry
|
||||
public:
|
||||
LEX_STRING name;
|
||||
char *value;
|
||||
ulong length, update_query_id;
|
||||
ulong length, update_query_id, used_query_id;
|
||||
Item_result type;
|
||||
CHARSET_INFO *var_charset;
|
||||
};
|
||||
|
@ -396,6 +396,10 @@ void init_update_queries(void)
|
||||
uc_update_queries[SQLCOM_UPDATE_MULTI]=1;
|
||||
}
|
||||
|
||||
bool is_update_query(enum enum_sql_command command)
|
||||
{
|
||||
return uc_update_queries[command];
|
||||
}
|
||||
|
||||
/*
|
||||
Check if maximum queries per hour limit has been reached
|
||||
@ -1225,6 +1229,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
|
||||
}
|
||||
thd->query_length= length;
|
||||
thd->query= packet;
|
||||
thd->net.last_error[0]= '\0';
|
||||
VOID(pthread_mutex_lock(&LOCK_thread_count));
|
||||
thd->query_id= query_id++;
|
||||
VOID(pthread_mutex_unlock(&LOCK_thread_count));
|
||||
@ -2709,7 +2714,7 @@ mysql_execute_command(THD *thd)
|
||||
if (check_access(thd,DELETE_ACL,"mysql",0,1))
|
||||
break;
|
||||
#ifdef HAVE_DLOPEN
|
||||
if (!(res = mysql_drop_function(thd,lex->udf.name)))
|
||||
if (!(res = mysql_drop_function(thd,&lex->udf.name)))
|
||||
send_ok(thd);
|
||||
#else
|
||||
res= -1;
|
||||
@ -3157,6 +3162,9 @@ mysql_init_query(THD *thd)
|
||||
thd->sent_row_count= thd->examined_row_count= 0;
|
||||
thd->is_fatal_error= thd->rand_used= 0;
|
||||
thd->server_status &= ~SERVER_MORE_RESULTS_EXISTS;
|
||||
if (opt_bin_log)
|
||||
reset_dynamic(&thd->user_var_events);
|
||||
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
@ -363,46 +363,13 @@ bool String::append(IO_CACHE* file, uint32 arg_length)
|
||||
|
||||
uint32 String::numchars()
|
||||
{
|
||||
#ifdef USE_MB
|
||||
register uint32 n=0,mblen;
|
||||
register const char *mbstr=Ptr;
|
||||
register const char *end=mbstr+str_length;
|
||||
if (use_mb(str_charset))
|
||||
{
|
||||
while (mbstr < end) {
|
||||
if ((mblen=my_ismbchar(str_charset, mbstr,end))) mbstr+=mblen;
|
||||
else ++mbstr;
|
||||
++n;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
return str_length;
|
||||
return str_charset->numchars(str_charset, Ptr, Ptr+str_length);
|
||||
}
|
||||
|
||||
int String::charpos(int i,uint32 offset)
|
||||
{
|
||||
#ifdef USE_MB
|
||||
register uint32 mblen;
|
||||
register const char *mbstr=Ptr+offset;
|
||||
register const char *end=Ptr+str_length;
|
||||
if (use_mb(str_charset))
|
||||
{
|
||||
if (i<=0) return i;
|
||||
while (i && mbstr < end) {
|
||||
if ((mblen=my_ismbchar(str_charset, mbstr,end))) mbstr+=mblen;
|
||||
else ++mbstr;
|
||||
--i;
|
||||
}
|
||||
if ( INT_MAX32-i <= (int) (mbstr-Ptr-offset))
|
||||
return INT_MAX32;
|
||||
else
|
||||
return (int) ((mbstr-Ptr-offset)+i);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
return i;
|
||||
if (i<0) return i;
|
||||
return str_charset->charpos(str_charset,Ptr+offset,Ptr+str_length,i);
|
||||
}
|
||||
|
||||
int String::strstr(const String &s,uint32 offset)
|
||||
@ -573,66 +540,10 @@ void String::qs_append(const char &c)
|
||||
|
||||
int sortcmp(const String *x,const String *y)
|
||||
{
|
||||
const char *s= x->ptr();
|
||||
const char *t= y->ptr();
|
||||
uint32 x_len=x->length(),y_len=y->length(),len=min(x_len,y_len);
|
||||
|
||||
if (use_strnxfrm(x->str_charset))
|
||||
{
|
||||
#ifndef CMP_ENDSPACE
|
||||
while (x_len && my_isspace(x->str_charset,s[x_len-1]))
|
||||
x_len--;
|
||||
while (y_len && my_isspace(x->str_charset,t[y_len-1]))
|
||||
y_len--;
|
||||
#endif
|
||||
return my_strnncoll(x->str_charset,
|
||||
(unsigned char *)s,x_len,(unsigned char *)t,y_len);
|
||||
}
|
||||
else
|
||||
{
|
||||
x_len-=len; // For easy end space test
|
||||
y_len-=len;
|
||||
if (x->str_charset->sort_order)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
if (x->str_charset->sort_order[(uchar) *s++] !=
|
||||
x->str_charset->sort_order[(uchar) *t++])
|
||||
return ((int) x->str_charset->sort_order[(uchar) s[-1]] -
|
||||
(int) x->str_charset->sort_order[(uchar) t[-1]]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
if (*s++ != *t++)
|
||||
return ((int) s[-1] - (int) t[-1]);
|
||||
}
|
||||
}
|
||||
#ifndef CMP_ENDSPACE
|
||||
/* Don't compare end space in strings */
|
||||
{
|
||||
if (y_len)
|
||||
{
|
||||
const char *end=t+y_len;
|
||||
for (; t != end ; t++)
|
||||
if (!my_isspace(x->str_charset,*t))
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *end=s+x_len;
|
||||
for (; s != end ; s++)
|
||||
if (!my_isspace(x->str_charset,*s))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
return (int) (x_len-y_len);
|
||||
#endif /* CMP_ENDSPACE */
|
||||
}
|
||||
CHARSET_INFO *cs= x->str_charset;
|
||||
return cs->strnncollsp(cs,
|
||||
(unsigned char *) x->ptr(),x->length(),
|
||||
(unsigned char *) y->ptr(),y->length());
|
||||
}
|
||||
|
||||
|
||||
|
@ -74,7 +74,7 @@ static HASH udf_hash;
|
||||
static rw_lock_t THR_LOCK_udf;
|
||||
|
||||
|
||||
static udf_func *add_udf(char *name, Item_result ret, char *dl,
|
||||
static udf_func *add_udf(LEX_STRING *name, Item_result ret, char *dl,
|
||||
Item_udftype typ);
|
||||
static void del_udf(udf_func *udf);
|
||||
static void *find_udf_dl(const char *dl);
|
||||
@ -84,8 +84,8 @@ static void init_syms(udf_func *tmp)
|
||||
{
|
||||
char nm[MAX_FIELD_NAME+16],*end;
|
||||
|
||||
tmp->func = dlsym(tmp->dlhandle, tmp->name);
|
||||
end=strmov(nm,tmp->name);
|
||||
tmp->func = dlsym(tmp->dlhandle, tmp->name.str);
|
||||
end=strmov(nm,tmp->name.str);
|
||||
(void) strmov(end,"_init");
|
||||
tmp->func_init = dlsym(tmp->dlhandle, nm);
|
||||
(void) strmov(end,"_deinit");
|
||||
@ -103,8 +103,8 @@ extern "C" byte* get_hash_key(const byte *buff,uint *length,
|
||||
my_bool not_used __attribute__((unused)))
|
||||
{
|
||||
udf_func *udf=(udf_func*) buff;
|
||||
*length=(uint) udf->name_length;
|
||||
return (byte*) udf->name;
|
||||
*length=(uint) udf->name.length;
|
||||
return (byte*) udf->name.str;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -161,14 +161,16 @@ void udf_init()
|
||||
while (!(error = read_record_info.read_record(&read_record_info)))
|
||||
{
|
||||
DBUG_PRINT("info",("init udf record"));
|
||||
char *name=get_field(&mem, table, 0);
|
||||
LEX_STRING name;
|
||||
name.str=get_field(&mem, table, 0);
|
||||
name.length = strlen(name.str);
|
||||
char *dl_name= get_field(&mem, table, 2);
|
||||
bool new_dl=0;
|
||||
Item_udftype udftype=UDFTYPE_FUNCTION;
|
||||
if (table->fields >= 4) // New func table
|
||||
udftype=(Item_udftype) table->field[3]->val_int();
|
||||
|
||||
if (!(tmp = add_udf(name,(Item_result) table->field[1]->val_int(),
|
||||
if (!(tmp = add_udf(&name,(Item_result) table->field[1]->val_int(),
|
||||
dl_name, udftype)))
|
||||
{
|
||||
sql_print_error("Can't alloc memory for udf function: name");
|
||||
@ -250,10 +252,10 @@ static void del_udf(udf_func *udf)
|
||||
The functions will be automaticly removed when the least threads
|
||||
doesn't use it anymore
|
||||
*/
|
||||
char *name= udf->name;
|
||||
uint name_length=udf->name_length;
|
||||
udf->name=(char*) "*";
|
||||
udf->name_length=1;
|
||||
char *name= udf->name.str;
|
||||
uint name_length=udf->name.length;
|
||||
udf->name.str=(char*) "*";
|
||||
udf->name.length=1;
|
||||
hash_update(&udf_hash,(byte*) udf,(byte*) name,name_length);
|
||||
}
|
||||
DBUG_VOID_RETURN;
|
||||
@ -322,7 +324,7 @@ static void *find_udf_dl(const char *dl)
|
||||
|
||||
/* Assume that name && dl is already allocated */
|
||||
|
||||
static udf_func *add_udf(char *name, Item_result ret, char *dl,
|
||||
static udf_func *add_udf(LEX_STRING *name, Item_result ret, char *dl,
|
||||
Item_udftype type)
|
||||
{
|
||||
if (!name || !dl || !(uint) type || (uint) type > (uint) UDFTYPE_AGGREGATE)
|
||||
@ -331,8 +333,7 @@ static udf_func *add_udf(char *name, Item_result ret, char *dl,
|
||||
if (!tmp)
|
||||
return 0;
|
||||
bzero((char*) tmp,sizeof(*tmp));
|
||||
tmp->name = name;
|
||||
tmp->name_length=(uint) strlen(tmp->name);
|
||||
tmp->name = *name; //dup !!
|
||||
tmp->dl = dl;
|
||||
tmp->returns = ret;
|
||||
tmp->type = type;
|
||||
@ -370,14 +371,14 @@ int mysql_create_function(THD *thd,udf_func *udf)
|
||||
send_error(thd, ER_UDF_NO_PATHS,ER(ER_UDF_NO_PATHS));
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
if (udf->name_length > NAME_LEN)
|
||||
if (udf->name.length > NAME_LEN)
|
||||
{
|
||||
net_printf(thd, ER_TOO_LONG_IDENT,udf->name);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
rw_wrlock(&THR_LOCK_udf);
|
||||
if ((hash_search(&udf_hash,(byte*) udf->name, udf->name_length)))
|
||||
if ((hash_search(&udf_hash,(byte*) udf->name.str, udf->name.length)))
|
||||
{
|
||||
net_printf(thd, ER_UDF_EXISTS, udf->name);
|
||||
goto err;
|
||||
@ -401,9 +402,9 @@ int mysql_create_function(THD *thd,udf_func *udf)
|
||||
net_printf(thd, ER_CANT_FIND_DL_ENTRY, udf->name);
|
||||
goto err;
|
||||
}
|
||||
udf->name=strdup_root(&mem,udf->name);
|
||||
udf->name.str=strdup_root(&mem,udf->name.str);
|
||||
udf->dl=strdup_root(&mem,udf->dl);
|
||||
if (!(u_d=add_udf(udf->name,udf->returns,udf->dl,udf->type)))
|
||||
if (!(u_d=add_udf(&udf->name,udf->returns,udf->dl,udf->type)))
|
||||
{
|
||||
send_error(thd,0); // End of memory
|
||||
goto err;
|
||||
@ -425,7 +426,7 @@ int mysql_create_function(THD *thd,udf_func *udf)
|
||||
goto err;
|
||||
|
||||
restore_record(table,2); // Get default values for fields
|
||||
table->field[0]->store(u_d->name, u_d->name_length, default_charset_info);
|
||||
table->field[0]->store(u_d->name.str, u_d->name.length, default_charset_info);
|
||||
table->field[1]->store((longlong) u_d->returns);
|
||||
table->field[2]->store(u_d->dl,(uint) strlen(u_d->dl), default_charset_info);
|
||||
if (table->fields >= 4) // If not old func format
|
||||
@ -450,7 +451,7 @@ int mysql_create_function(THD *thd,udf_func *udf)
|
||||
}
|
||||
|
||||
|
||||
int mysql_drop_function(THD *thd,const char *udf_name)
|
||||
int mysql_drop_function(THD *thd,const LEX_STRING *udf_name)
|
||||
{
|
||||
TABLE *table;
|
||||
TABLE_LIST tables;
|
||||
@ -462,8 +463,8 @@ int mysql_drop_function(THD *thd,const char *udf_name)
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
rw_wrlock(&THR_LOCK_udf);
|
||||
if (!(udf=(udf_func*) hash_search(&udf_hash,(byte*) udf_name,
|
||||
(uint) strlen(udf_name))))
|
||||
if (!(udf=(udf_func*) hash_search(&udf_hash,(byte*) udf_name->str,
|
||||
(uint) udf_name->length)))
|
||||
{
|
||||
net_printf(thd, ER_FUNCTION_NOT_DEFINED, udf_name);
|
||||
goto err;
|
||||
@ -481,8 +482,8 @@ int mysql_drop_function(THD *thd,const char *udf_name)
|
||||
tables.real_name= tables.alias= (char*) "func";
|
||||
if (!(table = open_ltable(thd,&tables,TL_WRITE)))
|
||||
goto err;
|
||||
if (!table->file->index_read_idx(table->record[0],0,(byte*) udf_name,
|
||||
(uint) strlen(udf_name),
|
||||
if (!table->file->index_read_idx(table->record[0],0,(byte*) udf_name->str,
|
||||
(uint) udf_name->length,
|
||||
HA_READ_KEY_EXACT))
|
||||
{
|
||||
int error;
|
||||
|
@ -25,8 +25,7 @@ enum Item_udftype {UDFTYPE_FUNCTION=1,UDFTYPE_AGGREGATE};
|
||||
|
||||
typedef struct st_udf_func
|
||||
{
|
||||
char *name;
|
||||
int name_length;
|
||||
LEX_STRING name;
|
||||
Item_result returns;
|
||||
Item_udftype type;
|
||||
char *dl;
|
||||
@ -61,7 +60,7 @@ class udf_handler :public Sql_alloc
|
||||
initialized(0)
|
||||
{}
|
||||
~udf_handler();
|
||||
const char *name() const { return u_d ? u_d->name : "?"; }
|
||||
const char *name() const { return u_d ? u_d->name.str : "?"; }
|
||||
Item_result result_type () const
|
||||
{ return u_d ? u_d->returns : STRING_RESULT;}
|
||||
bool get_arguments();
|
||||
@ -140,5 +139,5 @@ void udf_init(void),udf_free(void);
|
||||
udf_func *find_udf(const char *name, uint len=0,bool mark_used=0);
|
||||
void free_udf(udf_func *udf);
|
||||
int mysql_create_function(THD *thd,udf_func *udf);
|
||||
int mysql_drop_function(THD *thd,const char *name);
|
||||
int mysql_drop_function(THD *thd,const LEX_STRING *name);
|
||||
#endif
|
||||
|
@ -870,12 +870,11 @@ create:
|
||||
lex->name=$4.str;
|
||||
lex->create_info.options=$3;
|
||||
}
|
||||
| CREATE udf_func_type UDF_SYM ident
|
||||
| CREATE udf_func_type UDF_SYM IDENT
|
||||
{
|
||||
LEX *lex=Lex;
|
||||
lex->sql_command = SQLCOM_CREATE_FUNCTION;
|
||||
lex->udf.name=$4.str;
|
||||
lex->udf.name_length=$4.length;
|
||||
lex->udf.name = $4;
|
||||
lex->udf.type= $2;
|
||||
}
|
||||
UDF_RETURNS_SYM udf_type UDF_SONAME_SYM TEXT_STRING
|
||||
@ -3016,11 +3015,11 @@ drop:
|
||||
lex->drop_if_exists=$3;
|
||||
lex->name=$4.str;
|
||||
}
|
||||
| DROP UDF_SYM ident
|
||||
| DROP UDF_SYM IDENT
|
||||
{
|
||||
LEX *lex=Lex;
|
||||
lex->sql_command = SQLCOM_DROP_FUNCTION;
|
||||
lex->udf.name=$3.str;
|
||||
lex->udf.name = $3;
|
||||
};
|
||||
|
||||
|
||||
|
@ -136,6 +136,8 @@ bfill((A)->null_flags,(A)->null_bytes,255);\
|
||||
|
||||
#define BIN_LOG_HEADER_SIZE 4
|
||||
|
||||
#define FLOATING_POINT_BUFFER 331
|
||||
|
||||
/* Include prototypes for unireg */
|
||||
|
||||
#include "mysqld_error.h"
|
||||
|
@ -242,6 +242,16 @@ static int my_strnncoll_big5(CHARSET_INFO *cs __attribute__((unused)),
|
||||
return (int) (len1-len2);
|
||||
}
|
||||
|
||||
static
|
||||
int my_strnncollsp_big5(CHARSET_INFO * cs,
|
||||
const uchar *s, uint slen,
|
||||
const uchar *t, uint tlen)
|
||||
{
|
||||
for ( ; slen && my_isspace(cs, s[slen-1]) ; slen--);
|
||||
for ( ; tlen && my_isspace(cs, t[tlen-1]) ; tlen--);
|
||||
return my_strnncoll_big5(cs,s,slen,t,tlen);
|
||||
}
|
||||
|
||||
static int my_strnxfrm_big5(CHARSET_INFO *cs __attribute__((unused)),
|
||||
uchar * dest, uint len,
|
||||
const uchar * src, uint srclen)
|
||||
@ -6236,6 +6246,7 @@ CHARSET_INFO my_charset_big5 =
|
||||
NULL, /* tab_from_uni */
|
||||
1, /* strxfrm_multiply */
|
||||
my_strnncoll_big5,
|
||||
my_strnncollsp_big5,
|
||||
my_strnxfrm_big5,
|
||||
my_like_range_big5,
|
||||
my_wildcmp_mb,
|
||||
@ -6243,6 +6254,8 @@ CHARSET_INFO my_charset_big5 =
|
||||
ismbchar_big5,
|
||||
ismbhead_big5,
|
||||
mbcharlen_big5,
|
||||
my_numchars_mb,
|
||||
my_charpos_mb,
|
||||
my_mb_wc_big5, /* mb_wc */
|
||||
my_wc_mb_big5, /* wc_mb */
|
||||
my_caseup_str_mb,
|
||||
|
@ -284,6 +284,7 @@ CHARSET_INFO my_charset_bin =
|
||||
NULL, /* tab_from_uni */
|
||||
0, /* strxfrm_multiply */
|
||||
my_strnncoll_binary, /* strnncoll */
|
||||
my_strnncoll_binary,
|
||||
my_strnxfrm_bin, /* strxnfrm */
|
||||
my_like_range_simple, /* like_range */
|
||||
my_wildcmp_bin, /* wildcmp */
|
||||
@ -291,6 +292,8 @@ CHARSET_INFO my_charset_bin =
|
||||
NULL, /* ismbchar */
|
||||
NULL, /* ismbhead */
|
||||
NULL, /* mbcharlen */
|
||||
my_numchars_8bit,
|
||||
my_charpos_8bit,
|
||||
my_mb_wc_bin, /* mb_wc */
|
||||
my_wc_mb_bin, /* wc_mb */
|
||||
my_caseup_str_bin, /* caseup_str */
|
||||
|
@ -593,6 +593,18 @@ static MY_UNI_IDX idx_uni_8859_2[]={
|
||||
{0,0,NULL}
|
||||
};
|
||||
|
||||
|
||||
static
|
||||
int my_strnncollsp_czech(CHARSET_INFO * cs,
|
||||
const uchar *s, uint slen,
|
||||
const uchar *t, uint tlen)
|
||||
{
|
||||
for ( ; slen && my_isspace(cs, s[slen-1]) ; slen--);
|
||||
for ( ; tlen && my_isspace(cs, t[tlen-1]) ; tlen--);
|
||||
return my_strnncoll_czech(cs,s,slen,t,tlen);
|
||||
}
|
||||
|
||||
|
||||
CHARSET_INFO my_charset_czech =
|
||||
{
|
||||
2, /* number */
|
||||
@ -608,6 +620,7 @@ CHARSET_INFO my_charset_czech =
|
||||
idx_uni_8859_2, /* tab_from_uni */
|
||||
4, /* strxfrm_multiply */
|
||||
my_strnncoll_czech,
|
||||
my_strnncollsp_czech,
|
||||
my_strnxfrm_czech,
|
||||
my_like_range_czech,
|
||||
my_wildcmp_8bit,
|
||||
@ -615,6 +628,8 @@ CHARSET_INFO my_charset_czech =
|
||||
NULL, /* ismbchar */
|
||||
NULL, /* ismbhead */
|
||||
NULL, /* mbcharlen */
|
||||
my_numchars_8bit,
|
||||
my_charpos_8bit,
|
||||
my_mb_wc_8bit, /* mb_wc */
|
||||
my_wc_mb_8bit, /* wc_mb */
|
||||
my_caseup_str_8bit,
|
||||
|
@ -8654,6 +8654,7 @@ CHARSET_INFO my_charset_euc_kr =
|
||||
NULL, /* tab_from_uni */
|
||||
0, /* strxfrm_multiply */
|
||||
my_strnncoll_simple,/* strnncoll */
|
||||
my_strnncollsp_simple,
|
||||
my_strnxfrm_simple, /* strnxfrm */
|
||||
my_like_range_simple,/* like_range */
|
||||
my_wildcmp_mb, /* wildcmp */
|
||||
@ -8661,6 +8662,8 @@ CHARSET_INFO my_charset_euc_kr =
|
||||
ismbchar_euc_kr,
|
||||
ismbhead_euc_kr,
|
||||
mbcharlen_euc_kr,
|
||||
my_numchars_mb,
|
||||
my_charpos_mb,
|
||||
my_mb_wc_euc_kr, /* mb_wc */
|
||||
my_wc_mb_euc_kr, /* wc_mb */
|
||||
my_caseup_str_mb,
|
||||
|
@ -2820,6 +2820,7 @@ CHARSET_INFO compiled_charsets[] = {
|
||||
idx_uni_8859_1, /* tab_from_uni */
|
||||
0, /* strxfrm_multiply */
|
||||
my_strnncoll_simple,/* strnncoll */
|
||||
my_strnncollsp_simple,/* strnncollsp */
|
||||
my_strnxfrm_simple, /* strnxfrm */
|
||||
my_like_range_simple,/* like_range */
|
||||
my_wildcmp_8bit, /* wildcmp */
|
||||
@ -2827,6 +2828,8 @@ CHARSET_INFO compiled_charsets[] = {
|
||||
NULL, /* ismbchar */
|
||||
NULL, /* ismbhead */
|
||||
NULL, /* mbcharlen */
|
||||
my_numchars_8bit,
|
||||
my_charpos_8bit,
|
||||
my_mb_wc_8bit, /* mb_wc */
|
||||
my_wc_mb_8bit, /* wc_mb */
|
||||
my_caseup_str_8bit,
|
||||
@ -2868,6 +2871,7 @@ CHARSET_INFO compiled_charsets[] = {
|
||||
idx_uni_cp1251, /* tab_from_uni */
|
||||
0, /* strxfrm_multiply */
|
||||
my_strnncoll_simple,/* strnncoll */
|
||||
my_strnncollsp_simple,/* strnncollsp */
|
||||
my_strnxfrm_simple, /* strnxfrm */
|
||||
my_like_range_simple,/* like_range */
|
||||
my_wildcmp_8bit, /* wildcmp */
|
||||
@ -2875,6 +2879,8 @@ CHARSET_INFO compiled_charsets[] = {
|
||||
NULL, /* ismbchar */
|
||||
NULL, /* ismbhead */
|
||||
NULL, /* mbcharlen */
|
||||
my_numchars_8bit,
|
||||
my_charpos_8bit,
|
||||
my_mb_wc_8bit, /* mb_wc */
|
||||
my_wc_mb_8bit, /* wc_mb */
|
||||
my_caseup_str_8bit,
|
||||
@ -2915,6 +2921,7 @@ CHARSET_INFO compiled_charsets[] = {
|
||||
idx_uni_cp1257, /* tab_from_uni */
|
||||
0, /* strxfrm_multiply */
|
||||
my_strnncoll_simple,/* strnncoll */
|
||||
my_strnncollsp_simple,/* strnncollsp */
|
||||
my_strnxfrm_simple, /* strnxfrm */
|
||||
my_like_range_simple,/* like_range */
|
||||
my_wildcmp_8bit, /* wildcmp */
|
||||
@ -2922,6 +2929,8 @@ CHARSET_INFO compiled_charsets[] = {
|
||||
NULL, /* ismbchar */
|
||||
NULL, /* ismbhead */
|
||||
NULL, /* mbcharlen */
|
||||
my_numchars_8bit,
|
||||
my_charpos_8bit,
|
||||
my_mb_wc_8bit, /* mb_wc */
|
||||
my_wc_mb_8bit, /* wc_mb */
|
||||
my_caseup_str_8bit,
|
||||
@ -2962,6 +2971,7 @@ CHARSET_INFO compiled_charsets[] = {
|
||||
idx_uni_8859_2, /* tab_from_uni */
|
||||
0, /* strxfrm_multiply */
|
||||
my_strnncoll_simple,/* strnncoll */
|
||||
my_strnncollsp_simple,/* strnncollsp */
|
||||
my_strnxfrm_simple, /* strnxfrm */
|
||||
my_like_range_simple,/* like_range */
|
||||
my_wildcmp_8bit, /* wildcmp */
|
||||
@ -3010,6 +3020,7 @@ CHARSET_INFO compiled_charsets[] = {
|
||||
idx_uni_8859_1, /* tab_from_uni */
|
||||
0, /* strxfrm_multiply */
|
||||
my_strnncoll_simple,/* strnncoll */
|
||||
my_strnncollsp_simple,/* strnncollsp */
|
||||
my_strnxfrm_simple, /* strnxfrm */
|
||||
my_like_range_simple,/* like_range */
|
||||
my_wildcmp_8bit, /* wildcmp */
|
||||
@ -3057,6 +3068,7 @@ CHARSET_INFO compiled_charsets[] = {
|
||||
NULL, /* tab_from_uni */
|
||||
0, /* strxfrm_multiply */
|
||||
my_strnncoll_simple,/* strnncoll */
|
||||
my_strnncollsp_simple,/* strnncollsp */
|
||||
my_strnxfrm_simple, /* strnxfrm */
|
||||
my_like_range_simple,/* like_range */
|
||||
my_wildcmp_8bit, /* wildcmp */
|
||||
@ -3104,6 +3116,7 @@ CHARSET_INFO compiled_charsets[] = {
|
||||
NULL, /* tab_from_uni */
|
||||
0, /* strxfrm_multiply */
|
||||
my_strnncoll_simple,/* strnncoll */
|
||||
my_strnncollsp_simple,/* strnncollsp */
|
||||
my_strnxfrm_simple, /* strnxfrm */
|
||||
my_like_range_simple,/* like_range */
|
||||
my_wildcmp_8bit, /* wildcmp */
|
||||
@ -3151,6 +3164,7 @@ CHARSET_INFO compiled_charsets[] = {
|
||||
NULL, /* tab_from_uni */
|
||||
0, /* strxfrm_multiply */
|
||||
my_strnncoll_simple,/* strnncoll */
|
||||
my_strnncollsp_simple,/* strnncollsp */
|
||||
my_strnxfrm_simple, /* strnxfrm */
|
||||
my_like_range_simple,/* like_range */
|
||||
my_wildcmp_8bit, /* wildcmp */
|
||||
@ -3199,6 +3213,7 @@ CHARSET_INFO compiled_charsets[] = {
|
||||
idx_uni_8859_1, /* tab_from_uni */
|
||||
0, /* strxfrm_multiply */
|
||||
my_strnncoll_simple,/* strnncoll */
|
||||
my_strnncollsp_simple,/* strnncollsp */
|
||||
my_strnxfrm_simple, /* strnxfrm */
|
||||
my_like_range_simple,/* like_range */
|
||||
my_wildcmp_8bit, /* wildcmp */
|
||||
@ -3246,6 +3261,7 @@ CHARSET_INFO compiled_charsets[] = {
|
||||
NULL, /* tab_from_uni */
|
||||
0, /* strxfrm_multiply */
|
||||
my_strnncoll_simple,/* strnncoll */
|
||||
my_strnncollsp_simple,/* strnncollsp */
|
||||
my_strnxfrm_simple, /* strnxfrm */
|
||||
my_like_range_simple,/* like_range */
|
||||
my_wildcmp_8bit, /* wildcmp */
|
||||
@ -3293,6 +3309,7 @@ CHARSET_INFO compiled_charsets[] = {
|
||||
NULL, /* tab_from_uni */
|
||||
0, /* strxfrm_multiply */
|
||||
my_strnncoll_simple,/* strnncoll */
|
||||
my_strnncollsp_simple,/* strnncollsp */
|
||||
my_strnxfrm_simple, /* strnxfrm */
|
||||
my_like_range_simple,/* like_range */
|
||||
my_wildcmp_8bit, /* wildcmp */
|
||||
@ -3340,6 +3357,7 @@ CHARSET_INFO compiled_charsets[] = {
|
||||
NULL, /* tab_from_uni */
|
||||
0, /* strxfrm_multiply */
|
||||
my_strnncoll_simple,/* strnncoll */
|
||||
my_strnncollsp_simple,/* strnncollsp */
|
||||
my_strnxfrm_simple, /* strnxfrm */
|
||||
my_like_range_simple,/* like_range */
|
||||
my_wildcmp_8bit, /* wildcmp */
|
||||
@ -3387,6 +3405,7 @@ CHARSET_INFO compiled_charsets[] = {
|
||||
idx_uni_8859_2, /* tab_from_uni */
|
||||
0, /* strxfrm_multiply */
|
||||
my_strnncoll_simple,/* strnncoll */
|
||||
my_strnncollsp_simple,/* strnncollsp */
|
||||
my_strnxfrm_simple, /* strnxfrm */
|
||||
my_like_range_simple,/* like_range */
|
||||
my_wildcmp_8bit, /* wildcmp */
|
||||
@ -3434,6 +3453,7 @@ CHARSET_INFO compiled_charsets[] = {
|
||||
idx_uni_koi8_r, /* tab_from_uni */
|
||||
0, /* strxfrm_multiply */
|
||||
my_strnncoll_simple,/* strnncoll */
|
||||
my_strnncollsp_simple,/* strnncollsp */
|
||||
my_strnxfrm_simple, /* strnxfrm */
|
||||
my_like_range_simple,/* like_range */
|
||||
my_wildcmp_8bit, /* wildcmp */
|
||||
@ -3481,6 +3501,7 @@ CHARSET_INFO compiled_charsets[] = {
|
||||
idx_uni_koi8_u, /* tab_from_uni */
|
||||
0, /* strxfrm_multiply */
|
||||
my_strnncoll_simple,/* strnncoll */
|
||||
my_strnncollsp_simple,/* strnncollsp */
|
||||
my_strnxfrm_simple, /* strnxfrm */
|
||||
my_like_range_simple,/* like_range */
|
||||
my_wildcmp_8bit, /* wildcmp */
|
||||
@ -3529,6 +3550,7 @@ CHARSET_INFO compiled_charsets[] = {
|
||||
idx_uni_8859_2, /* tab_from_uni */
|
||||
0, /* strxfrm_multiply */
|
||||
my_strnncoll_simple,/* strnncoll */
|
||||
my_strnncollsp_simple,/* strnncollsp */
|
||||
my_strnxfrm_simple, /* strnxfrm */
|
||||
my_like_range_simple,/* like_range */
|
||||
my_wildcmp_8bit, /* wildcmp */
|
||||
@ -3576,6 +3598,7 @@ CHARSET_INFO compiled_charsets[] = {
|
||||
idx_uni_8859_9, /* tab_from_uni */
|
||||
0, /* strxfrm_multiply */
|
||||
my_strnncoll_simple,/* strnncoll */
|
||||
my_strnncollsp_simple,/* strnncollsp */
|
||||
my_strnxfrm_simple, /* strnxfrm */
|
||||
my_like_range_simple,/* like_range */
|
||||
my_wildcmp_8bit, /* wildcmp */
|
||||
@ -3624,6 +3647,7 @@ CHARSET_INFO compiled_charsets[] = {
|
||||
NULL, /* tab_from_uni */
|
||||
0, /* strxfrm_multiply */
|
||||
my_strnncoll_simple,/* strnncoll */
|
||||
my_strnncollsp_simple,/* strnncollsp */
|
||||
my_strnxfrm_simple, /* strnxfrm */
|
||||
my_like_range_simple,/* like_range */
|
||||
my_wildcmp_8bit, /* wildcmp */
|
||||
@ -3672,6 +3696,7 @@ CHARSET_INFO compiled_charsets[] = {
|
||||
idx_uni_us_ascii, /* tab_from_uni */
|
||||
0, /* strxfrm_multiply */
|
||||
my_strnncoll_simple,/* strnncoll */
|
||||
my_strnncollsp_simple,/* strnncollsp */
|
||||
my_strnxfrm_simple, /* strnxfrm */
|
||||
my_like_range_simple,/* like_range */
|
||||
my_wildcmp_8bit, /* wildcmp */
|
||||
@ -3719,6 +3744,7 @@ CHARSET_INFO compiled_charsets[] = {
|
||||
idx_uni_cp1250, /* tab_from_uni */
|
||||
0, /* strxfrm_multiply */
|
||||
my_strnncoll_simple,/* strnncoll */
|
||||
my_strnncollsp_simple,/* strnncollsp */
|
||||
my_strnxfrm_simple, /* strnxfrm */
|
||||
my_like_range_simple,/* like_range */
|
||||
my_wildcmp_8bit, /* wildcmp */
|
||||
@ -3766,6 +3792,7 @@ CHARSET_INFO compiled_charsets[] = {
|
||||
idx_uni_cp1251, /* tab_from_uni */
|
||||
0, /* strxfrm_multiply */
|
||||
my_strnncoll_simple,/* strnncoll */
|
||||
my_strnncollsp_simple,/* strnncollsp */
|
||||
my_strnxfrm_simple, /* strnxfrm */
|
||||
my_like_range_simple,/* like_range */
|
||||
my_wildcmp_8bit, /* wildcmp */
|
||||
@ -3813,6 +3840,7 @@ CHARSET_INFO compiled_charsets[] = {
|
||||
idx_uni_armscii_8, /* tab_from_uni */
|
||||
0, /* strxfrm_multiply */
|
||||
my_strnncoll_simple,/* strnncoll */
|
||||
my_strnncollsp_simple,/* strnncollsp */
|
||||
my_strnxfrm_simple, /* strnxfrm */
|
||||
my_like_range_simple,/* like_range */
|
||||
my_wildcmp_8bit, /* wildcmp */
|
||||
@ -3860,6 +3888,7 @@ CHARSET_INFO compiled_charsets[] = {
|
||||
idx_uni_cp1251, /* tab_from_uni */
|
||||
0, /* strxfrm_multiply */
|
||||
my_strnncoll_simple,/* strnncoll */
|
||||
my_strnncollsp_simple,/* strnncollsp */
|
||||
my_strnxfrm_simple, /* strnxfrm */
|
||||
my_like_range_simple,/* like_range */
|
||||
my_wildcmp_8bit, /* wildcmp */
|
||||
@ -3906,6 +3935,7 @@ CHARSET_INFO compiled_charsets[] = {
|
||||
NULL, /* tab_from_uni */
|
||||
0,
|
||||
NULL, /* strnncoll */
|
||||
NULL, /* strnncollsp */
|
||||
NULL, /* strnxfrm */
|
||||
NULL, /* like_range */
|
||||
NULL, /* wildcmp */
|
||||
@ -3913,7 +3943,8 @@ CHARSET_INFO compiled_charsets[] = {
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
|
||||
NULL,
|
||||
NULL,
|
||||
NULL, /* mb_wc */
|
||||
NULL, /* wc_mb */
|
||||
|
||||
|
@ -5704,6 +5704,7 @@ CHARSET_INFO my_charset_gb2312 =
|
||||
NULL, /* tab_from_uni */
|
||||
0, /* strxfrm_multiply */
|
||||
my_strnncoll_simple,/* strnncoll */
|
||||
my_strnncollsp_simple,
|
||||
my_strnxfrm_simple, /* strnxfrm */
|
||||
my_like_range_simple,/* like_range */
|
||||
my_wildcmp_mb, /* wildcmp */
|
||||
@ -5711,6 +5712,8 @@ CHARSET_INFO my_charset_gb2312 =
|
||||
ismbchar_gb2312,
|
||||
ismbhead_gb2312,
|
||||
mbcharlen_gb2312,
|
||||
my_numchars_mb,
|
||||
my_charpos_mb,
|
||||
my_mb_wc_gb2312, /* mb_wc */
|
||||
my_wc_mb_gb2312, /* wc_mb */
|
||||
my_caseup_str_mb,
|
||||
|
@ -2608,6 +2608,16 @@ int my_strnncoll_gbk(CHARSET_INFO *cs __attribute__((unused)),
|
||||
return (int) (len1-len2);
|
||||
}
|
||||
|
||||
static
|
||||
int my_strnncollsp_gbk(CHARSET_INFO * cs,
|
||||
const uchar *s, uint slen,
|
||||
const uchar *t, uint tlen)
|
||||
{
|
||||
for ( ; slen && my_isspace(cs, s[slen-1]) ; slen--);
|
||||
for ( ; tlen && my_isspace(cs, t[tlen-1]) ; tlen--);
|
||||
return my_strnncoll_gbk(cs,s,slen,t,tlen);
|
||||
}
|
||||
|
||||
|
||||
int my_strnxfrm_gbk(CHARSET_INFO *cs __attribute__((unused)),
|
||||
uchar * dest, uint len,
|
||||
@ -9891,6 +9901,7 @@ CHARSET_INFO my_charset_gbk =
|
||||
NULL, /* tab_from_uni */
|
||||
1, /* strxfrm_multiply */
|
||||
my_strnncoll_gbk,
|
||||
my_strnncollsp_gbk,
|
||||
my_strnxfrm_gbk,
|
||||
my_like_range_gbk,
|
||||
my_wildcmp_mb, /* wildcmp */
|
||||
@ -9898,6 +9909,8 @@ CHARSET_INFO my_charset_gbk =
|
||||
ismbchar_gbk,
|
||||
ismbhead_gbk,
|
||||
mbcharlen_gbk,
|
||||
my_numchars_mb,
|
||||
my_charpos_mb,
|
||||
my_mb_wc_gbk, /* mb_wc */
|
||||
my_wc_mb_gbk, /* wc_mb */
|
||||
my_caseup_str_mb,
|
||||
|
@ -190,6 +190,7 @@ CHARSET_INFO my_charset_latin1 =
|
||||
NULL, /* tab_from_uni */
|
||||
2, /* strxfrm_multiply */
|
||||
my_strnncoll_simple,
|
||||
my_strnncollsp_simple,
|
||||
my_strnxfrm_simple,
|
||||
my_like_range_simple,
|
||||
my_wildcmp_8bit, /* wildcmp */
|
||||
@ -197,6 +198,8 @@ CHARSET_INFO my_charset_latin1 =
|
||||
NULL, /* ismbchar */
|
||||
NULL, /* ismbhead */
|
||||
NULL, /* mbcharlen */
|
||||
my_numchars_8bit,
|
||||
my_charpos_8bit,
|
||||
my_mb_wc_latin1, /* mb_wc */
|
||||
my_wc_mb_latin1, /* wc_mb */
|
||||
my_caseup_str_8bit,
|
||||
|
@ -295,6 +295,16 @@ static int my_strnncoll_latin1_de(CHARSET_INFO *cs __attribute__((unused)),
|
||||
return s1 < e1 ? 1 : s2 < e2 ? -1 : 0;
|
||||
}
|
||||
|
||||
static
|
||||
int my_strnncollsp_latin1_de(CHARSET_INFO * cs,
|
||||
const uchar *s, uint slen,
|
||||
const uchar *t, uint tlen)
|
||||
{
|
||||
for ( ; slen && my_isspace(cs, s[slen-1]) ; slen--);
|
||||
for ( ; tlen && my_isspace(cs, t[tlen-1]) ; tlen--);
|
||||
return my_strnncoll_latin1_de(cs,s,slen,t,tlen);
|
||||
}
|
||||
|
||||
|
||||
static int my_strnxfrm_latin1_de(CHARSET_INFO *cs __attribute__((unused)),
|
||||
uchar * dest, uint len,
|
||||
@ -336,81 +346,6 @@ static int my_strnxfrm_latin1_de(CHARSET_INFO *cs __attribute__((unused)),
|
||||
return dest - dest_orig;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Calculate min_str and max_str that ranges a LIKE string.
|
||||
* Arguments:
|
||||
* ptr IN: Pointer to LIKE string.
|
||||
* ptr_length IN: Length of LIKE string.
|
||||
* escape IN: Escape character in LIKE. (Normally '\').
|
||||
* No escape characters should appear in min_str or max_str
|
||||
* res_length IN: Length of min_str and max_str.
|
||||
* min_str IN/OUT: Smallest case sensitive string that ranges LIKE.
|
||||
* Should be space padded to res_length.
|
||||
* max_str IN/OUT: Largest case sensitive string that ranges LIKE.
|
||||
* Normally padded with the biggest character sort value.
|
||||
* min_length OUT: Length of min_str without space padding.
|
||||
* max_length OUT: Length of max_str without space padding.
|
||||
*
|
||||
* The function should return 0 if ok and 1 if the LIKE string can't be
|
||||
* optimized !
|
||||
*/
|
||||
|
||||
#define min_sort_char ((char) 0)
|
||||
#define max_sort_char ((char) 255)
|
||||
|
||||
static my_bool my_like_range_latin1_de(CHARSET_INFO *cs __attribute__((unused)),
|
||||
const char *ptr, uint ptr_length,
|
||||
int escape, int w_one, int w_many,
|
||||
uint res_length,
|
||||
char *min_str, char *max_str,
|
||||
uint *min_length, uint *max_length)
|
||||
{
|
||||
const char *end = ptr + ptr_length;
|
||||
char *min_org = min_str;
|
||||
char *min_end = min_str + res_length;
|
||||
|
||||
for (; ptr != end && min_str != min_end; ptr++)
|
||||
{
|
||||
if (*ptr == escape && ptr + 1 != end)
|
||||
{
|
||||
ptr++; /* Skip escape */
|
||||
*min_str++ = *max_str++ = *ptr;
|
||||
continue;
|
||||
}
|
||||
if (*ptr == w_one) /* '_' in SQL */
|
||||
{
|
||||
*min_str++ = min_sort_char;
|
||||
*max_str++ = max_sort_char;
|
||||
continue;
|
||||
}
|
||||
if (*ptr == w_many) /* '%' in SQL */
|
||||
{
|
||||
*min_length = (uint)(min_str - min_org);
|
||||
*max_length = res_length;
|
||||
do {
|
||||
*min_str++ = ' '; /* Because if key compression */
|
||||
*max_str++ = max_sort_char;
|
||||
} while (min_str != min_end);
|
||||
return 0;
|
||||
}
|
||||
*min_str++ = *max_str++ = *ptr;
|
||||
}
|
||||
*min_length = *max_length = (uint) (min_str - min_org);
|
||||
|
||||
/* Temporary fix for handling w_one at end of string (key compression) */
|
||||
{
|
||||
char *tmp;
|
||||
for (tmp= min_str ; tmp > min_org && tmp[-1] == '\0';)
|
||||
*--tmp=' ';
|
||||
}
|
||||
|
||||
while (min_str != min_end)
|
||||
*min_str++ = *max_str++ = ' '; /* Because if key compression */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
CHARSET_INFO my_charset_latin1_de =
|
||||
{
|
||||
31, /* number */
|
||||
@ -426,13 +361,16 @@ CHARSET_INFO my_charset_latin1_de =
|
||||
idx_uni_8859_1, /* tab_from_uni */
|
||||
2, /* strxfrm_multiply */
|
||||
my_strnncoll_latin1_de,
|
||||
my_strnncollsp_latin1_de,
|
||||
my_strnxfrm_latin1_de,
|
||||
my_like_range_latin1_de,
|
||||
my_like_range_simple,
|
||||
my_wildcmp_8bit, /* wildcmp */
|
||||
1, /* mbmaxlen */
|
||||
NULL, /* ismbchar */
|
||||
NULL, /* ismbhead */
|
||||
NULL, /* mbcharlen */
|
||||
my_numchars_8bit,
|
||||
my_charpos_8bit,
|
||||
my_mb_wc_8bit, /* mb_wc */
|
||||
my_wc_mb_8bit, /* wc_mb */
|
||||
my_caseup_str_8bit,
|
||||
|
@ -276,5 +276,31 @@ int my_wildcmp_mb(CHARSET_INFO *cs,
|
||||
return (str != str_end ? 1 : 0);
|
||||
}
|
||||
|
||||
uint my_numchars_mb(CHARSET_INFO *cs __attribute__((unused)),
|
||||
const char *b, const char *e)
|
||||
{
|
||||
register uint32 n=0,mblen;
|
||||
while (b < e)
|
||||
{
|
||||
b+= (mblen= my_ismbchar(cs,b,e)) ? mblen : 1;
|
||||
++n;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
uint my_charpos_mb(CHARSET_INFO *cs __attribute__((unused)),
|
||||
const char *b, const char *e, uint pos)
|
||||
{
|
||||
uint mblen;
|
||||
const char *b0=b;
|
||||
|
||||
while (pos && b<e)
|
||||
{
|
||||
b+= (mblen= my_ismbchar(cs,b,e)) ? mblen : 1;
|
||||
pos--;
|
||||
}
|
||||
return b-b0;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -50,6 +50,26 @@ int my_strnncoll_simple(CHARSET_INFO * cs, const uchar *s, uint slen,
|
||||
return (int) (slen-tlen);
|
||||
}
|
||||
|
||||
|
||||
int my_strnncollsp_simple(CHARSET_INFO * cs, const uchar *s, uint slen,
|
||||
const uchar *t, uint tlen)
|
||||
{
|
||||
uchar *map= cs->sort_order;
|
||||
int len;
|
||||
|
||||
for ( ; slen && my_isspace(cs, s[slen-1]) ; slen--);
|
||||
for ( ; tlen && my_isspace(cs, t[tlen-1]) ; tlen--);
|
||||
|
||||
len = ( slen > tlen ) ? tlen : slen;
|
||||
|
||||
while (len--)
|
||||
{
|
||||
if (map[*s++] != map[*t++])
|
||||
return ((int) map[s[-1]] - (int) map[t[-1]]);
|
||||
}
|
||||
return (int) (slen-tlen);
|
||||
}
|
||||
|
||||
void my_caseup_str_8bit(CHARSET_INFO * cs,char *str)
|
||||
{
|
||||
register uchar *map=cs->to_upper;
|
||||
@ -844,7 +864,7 @@ int my_wildcmp_8bit(CHARSET_INFO *cs,
|
||||
const char *wildstr,const char *wildend,
|
||||
int escape, int w_one, int w_many)
|
||||
{
|
||||
int result= -1; // Not found, using wildcards
|
||||
int result= -1; /* Not found, using wildcards */
|
||||
|
||||
while (wildstr != wildend)
|
||||
{
|
||||
@ -854,16 +874,16 @@ int my_wildcmp_8bit(CHARSET_INFO *cs,
|
||||
wildstr++;
|
||||
|
||||
if (str == str_end || likeconv(cs,*wildstr++) != likeconv(cs,*str++))
|
||||
return(1); // No match
|
||||
return(1); /* No match */
|
||||
if (wildstr == wildend)
|
||||
return (str != str_end); // Match if both are at end
|
||||
result=1; // Found an anchor char
|
||||
return (str != str_end); /* Match if both are at end */
|
||||
result=1; /* Found an anchor char */
|
||||
}
|
||||
if (*wildstr == w_one)
|
||||
{
|
||||
do
|
||||
{
|
||||
if (str == str_end) // Skip one char if possible
|
||||
if (str == str_end) /* Skip one char if possible */
|
||||
return (result);
|
||||
INC_PTR(cs,str,str_end);
|
||||
} while (++wildstr < wildend && *wildstr == w_one);
|
||||
@ -871,7 +891,7 @@ int my_wildcmp_8bit(CHARSET_INFO *cs,
|
||||
break;
|
||||
}
|
||||
if (*wildstr == w_many)
|
||||
{ // Found w_many
|
||||
{ /* Found w_many */
|
||||
uchar cmp;
|
||||
|
||||
wildstr++;
|
||||
@ -887,17 +907,17 @@ int my_wildcmp_8bit(CHARSET_INFO *cs,
|
||||
INC_PTR(cs,str,str_end);
|
||||
continue;
|
||||
}
|
||||
break; // Not a wild character
|
||||
break; /* Not a wild character */
|
||||
}
|
||||
if (wildstr == wildend)
|
||||
return(0); // Ok if w_many is last
|
||||
return(0); /* Ok if w_many is last */
|
||||
if (str == str_end)
|
||||
return -1;
|
||||
|
||||
if ((cmp= *wildstr) == escape && wildstr+1 != wildend)
|
||||
cmp= *++wildstr;
|
||||
|
||||
INC_PTR(cs,wildstr,wildend); // This is compared trough cmp
|
||||
INC_PTR(cs,wildstr,wildend); /* This is compared trough cmp */
|
||||
cmp=likeconv(cs,cmp);
|
||||
do
|
||||
{
|
||||
@ -949,22 +969,22 @@ my_bool my_like_range_simple(CHARSET_INFO *cs,
|
||||
{
|
||||
if (*ptr == escape && ptr+1 != end)
|
||||
{
|
||||
ptr++; // Skip escape
|
||||
ptr++; /* Skip escape */
|
||||
*min_str++= *max_str++ = *ptr;
|
||||
continue;
|
||||
}
|
||||
if (*ptr == w_one) // '_' in SQL
|
||||
if (*ptr == w_one) /* '_' in SQL */
|
||||
{
|
||||
*min_str++='\0'; // This should be min char
|
||||
*min_str++='\0'; /* This should be min char */
|
||||
*max_str++=cs->max_sort_char;
|
||||
continue;
|
||||
}
|
||||
if (*ptr == w_many) // '%' in SQL
|
||||
if (*ptr == w_many) /* '%' in SQL */
|
||||
{
|
||||
*min_length= (uint) (min_str - min_org);
|
||||
*max_length=res_length;
|
||||
do {
|
||||
*min_str++ = ' '; // Because if key compression
|
||||
*min_str++ = ' '; /* Because if key compression */
|
||||
*max_str++ = cs->max_sort_char;
|
||||
} while (min_str != min_end);
|
||||
return 0;
|
||||
@ -981,7 +1001,7 @@ my_bool my_like_range_simple(CHARSET_INFO *cs,
|
||||
}
|
||||
|
||||
while (min_str != min_end)
|
||||
*min_str++ = *max_str++ = ' '; // Because if key compression
|
||||
*min_str++ = *max_str++ = ' '; /* Because if key compression */
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1015,4 +1035,18 @@ void my_fill_8bit(CHARSET_INFO *cs __attribute__((unused)),
|
||||
char *s, uint l, int fill)
|
||||
{
|
||||
bfill(s,l,fill);
|
||||
}
|
||||
}
|
||||
|
||||
uint my_numchars_8bit(CHARSET_INFO *cs __attribute__((unused)),
|
||||
const char *b, const char *e)
|
||||
{
|
||||
return e-b;
|
||||
}
|
||||
|
||||
uint my_charpos_8bit(CHARSET_INFO *cs __attribute__((unused)),
|
||||
const char *b __attribute__((unused)),
|
||||
const char *e __attribute__((unused)),
|
||||
uint pos)
|
||||
{
|
||||
return pos;
|
||||
}
|
||||
|
@ -227,6 +227,16 @@ static int my_strnncoll_sjis(CHARSET_INFO *cs __attribute__((unused)),
|
||||
return len1 - len2;
|
||||
}
|
||||
|
||||
static
|
||||
int my_strnncollsp_sjis(CHARSET_INFO * cs,
|
||||
const uchar *s, uint slen,
|
||||
const uchar *t, uint tlen)
|
||||
{
|
||||
for ( ; slen && my_isspace(cs, s[slen-1]) ; slen--);
|
||||
for ( ; tlen && my_isspace(cs, t[tlen-1]) ; tlen--);
|
||||
return my_strnncoll_sjis(cs,s,slen,t,tlen);
|
||||
}
|
||||
|
||||
static int my_strnxfrm_sjis(CHARSET_INFO *cs __attribute__((unused)),
|
||||
uchar *dest, uint len,
|
||||
const uchar *src, uint srclen)
|
||||
@ -4478,6 +4488,7 @@ CHARSET_INFO my_charset_sjis =
|
||||
NULL, /* tab_from_uni */
|
||||
1, /* strxfrm_multiply */
|
||||
my_strnncoll_sjis,
|
||||
my_strnncollsp_sjis,
|
||||
my_strnxfrm_sjis,
|
||||
my_like_range_sjis,
|
||||
my_wildcmp_mb, /* wildcmp */
|
||||
@ -4485,6 +4496,8 @@ CHARSET_INFO my_charset_sjis =
|
||||
ismbchar_sjis,
|
||||
ismbhead_sjis,
|
||||
mbcharlen_sjis,
|
||||
my_numchars_mb,
|
||||
my_charpos_mb,
|
||||
my_mb_wc_sjis, /* mb_wc */
|
||||
my_wc_mb_sjis, /* wc_mb */
|
||||
my_caseup_str_8bit,
|
||||
|
@ -551,6 +551,17 @@ int my_strnncoll_tis620(CHARSET_INFO *cs __attribute__((unused)),
|
||||
return(i);
|
||||
}
|
||||
|
||||
static
|
||||
int my_strnncollsp_tis620(CHARSET_INFO * cs,
|
||||
const uchar *s, uint slen,
|
||||
const uchar *t, uint tlen)
|
||||
{
|
||||
for ( ; slen && my_isspace(cs, s[slen-1]) ; slen--);
|
||||
for ( ; tlen && my_isspace(cs, t[tlen-1]) ; tlen--);
|
||||
return my_strnncoll_tis620(cs,s,slen,t,tlen);
|
||||
}
|
||||
|
||||
|
||||
/* strnxfrm replacment, convert Thai string to sortable string
|
||||
Arg: Destination buffer, source string, dest length and source length
|
||||
Ret: Conveted string size
|
||||
@ -700,6 +711,7 @@ CHARSET_INFO my_charset_tis620 =
|
||||
NULL, /* tab_from_uni */
|
||||
4, /* strxfrm_multiply */
|
||||
my_strnncoll_tis620,
|
||||
my_strnncollsp_tis620,
|
||||
my_strnxfrm_tis620,
|
||||
my_like_range_tis620,
|
||||
my_wildcmp_8bit, /* wildcmp */
|
||||
@ -707,6 +719,8 @@ CHARSET_INFO my_charset_tis620 =
|
||||
NULL, /* ismbchar */
|
||||
NULL, /* ismbhead */
|
||||
NULL, /* mbcharlen */
|
||||
my_numchars_8bit,
|
||||
my_charpos_8bit,
|
||||
my_mb_wc_8bit, /* mb_wc */
|
||||
my_wc_mb_8bit, /* wc_mb */
|
||||
my_caseup_str_8bit,
|
||||
|
@ -8444,7 +8444,8 @@ CHARSET_INFO my_charset_ujis =
|
||||
NULL, /* tab_to_uni */
|
||||
NULL, /* tab_from_uni */
|
||||
0, /* strxfrm_multiply */
|
||||
NULL, /* strnncoll */
|
||||
my_strnncoll_simple,/* strnncoll */
|
||||
my_strnncollsp_simple,
|
||||
my_strnxfrm_simple, /* strnxfrm */
|
||||
my_like_range_simple,/* like_range */
|
||||
my_wildcmp_mb, /* wildcmp */
|
||||
@ -8452,6 +8453,8 @@ CHARSET_INFO my_charset_ujis =
|
||||
ismbchar_ujis,
|
||||
ismbhead_ujis,
|
||||
mbcharlen_ujis,
|
||||
my_numchars_mb,
|
||||
my_charpos_mb,
|
||||
my_mb_wc_euc_jp, /* mb_wc */
|
||||
my_wc_mb_euc_jp, /* wc_mb */
|
||||
my_caseup_str_mb,
|
||||
|
@ -1855,6 +1855,17 @@ static int my_strnncoll_utf8(CHARSET_INFO *cs,
|
||||
return ( (se-s) - (te-t) );
|
||||
}
|
||||
|
||||
static
|
||||
int my_strnncollsp_utf8(CHARSET_INFO * cs,
|
||||
const uchar *s, uint slen,
|
||||
const uchar *t, uint tlen)
|
||||
{
|
||||
for ( ; slen && my_isspace(cs, s[slen-1]) ; slen--);
|
||||
for ( ; tlen && my_isspace(cs, t[tlen-1]) ; tlen--);
|
||||
return my_strnncoll_utf8(cs,s,slen,t,tlen);
|
||||
}
|
||||
|
||||
|
||||
static int my_strncasecmp_utf8(CHARSET_INFO *cs,
|
||||
const char *s, const char *t, uint len)
|
||||
{
|
||||
@ -1979,6 +1990,7 @@ CHARSET_INFO my_charset_utf8 =
|
||||
NULL, /* tab_from_uni */
|
||||
1, /* strxfrm_multiply */
|
||||
my_strnncoll_utf8, /* strnncoll */
|
||||
my_strnncollsp_utf8,
|
||||
my_strnxfrm_utf8, /* strnxfrm */
|
||||
my_like_range_simple,/* like_range */
|
||||
my_wildcmp_mb, /* wildcmp */
|
||||
@ -1986,6 +1998,8 @@ CHARSET_INFO my_charset_utf8 =
|
||||
my_ismbchar_utf8, /* ismbchar */
|
||||
my_ismbhead_utf8, /* ismbhead */
|
||||
my_mbcharlen_utf8, /* mbcharlen */
|
||||
my_numchars_mb,
|
||||
my_charpos_mb,
|
||||
my_utf8_uni, /* mb_wc */
|
||||
my_uni_utf8, /* wc_mb */
|
||||
my_caseup_str_utf8,
|
||||
@ -3052,6 +3066,21 @@ cnv:
|
||||
return (int) (dst-db);
|
||||
}
|
||||
|
||||
static
|
||||
uint my_numchars_ucs2(CHARSET_INFO *cs __attribute__((unused)),
|
||||
const char *b, const char *e)
|
||||
{
|
||||
return (e-b)/2;
|
||||
}
|
||||
|
||||
static
|
||||
uint my_charpos_ucs2(CHARSET_INFO *cs __attribute__((unused)),
|
||||
const char *b __attribute__((unused)),
|
||||
const char *e __attribute__((unused)),
|
||||
uint pos)
|
||||
{
|
||||
return pos*2;
|
||||
}
|
||||
|
||||
CHARSET_INFO my_charset_ucs2 =
|
||||
{
|
||||
@ -3068,6 +3097,7 @@ CHARSET_INFO my_charset_ucs2 =
|
||||
NULL, /* tab_from_uni */
|
||||
1, /* strxfrm_multiply */
|
||||
my_strnncoll_ucs2, /* strnncoll */
|
||||
my_strnncoll_ucs2,
|
||||
my_strnxfrm_ucs2, /* strnxfrm */
|
||||
my_like_range_simple,/* like_range */
|
||||
my_wildcmp_mb, /* wildcmp */
|
||||
@ -3075,6 +3105,8 @@ CHARSET_INFO my_charset_ucs2 =
|
||||
my_ismbchar_ucs2, /* ismbchar */
|
||||
my_ismbhead_ucs2, /* ismbhead */
|
||||
my_mbcharlen_ucs2, /* mbcharlen */
|
||||
my_numchars_ucs2,
|
||||
my_charpos_ucs2,
|
||||
my_ucs2_uni, /* mb_wc */
|
||||
my_uni_ucs2, /* wc_mb */
|
||||
my_caseup_str_ucs2,
|
||||
|
@ -503,6 +503,17 @@ static int my_strnncoll_win1250ch(CHARSET_INFO *cs __attribute__((unused)),
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int my_strnncollsp_win1250ch(CHARSET_INFO * cs,
|
||||
const uchar *s, uint slen,
|
||||
const uchar *t, uint tlen)
|
||||
{
|
||||
for ( ; slen && my_isspace(cs, s[slen-1]) ; slen--);
|
||||
for ( ; tlen && my_isspace(cs, t[tlen-1]) ; tlen--);
|
||||
return my_strnncoll_win1250ch(cs,s,slen,t,tlen);
|
||||
}
|
||||
|
||||
|
||||
static int my_strnxfrm_win1250ch(CHARSET_INFO * cs __attribute__((unused)),
|
||||
uchar * dest, uint len,
|
||||
const uchar * src, uint srclen) {
|
||||
@ -644,6 +655,7 @@ CHARSET_INFO my_charset_win1250ch =
|
||||
idx_uni_cp1250, /* tab_from_uni */
|
||||
2, /* strxfrm_multiply */
|
||||
my_strnncoll_win1250ch,
|
||||
my_strnncollsp_win1250ch,
|
||||
my_strnxfrm_win1250ch,
|
||||
my_like_range_win1250ch,
|
||||
my_wildcmp_8bit, /* wildcmp */
|
||||
@ -651,6 +663,8 @@ CHARSET_INFO my_charset_win1250ch =
|
||||
NULL, /* ismbchar */
|
||||
NULL, /* ismbhead */
|
||||
NULL, /* mbcharlen */
|
||||
my_numchars_8bit,
|
||||
my_charpos_8bit,
|
||||
my_mb_wc_8bit, /* mb_wc */
|
||||
my_wc_mb_8bit, /* wc_mb */
|
||||
my_caseup_str_8bit,
|
||||
|
@ -50,6 +50,9 @@ static unsigned int test_count= 0;
|
||||
static unsigned int opt_count= 0;
|
||||
static unsigned int iter_count= 0;
|
||||
|
||||
static time_t start_time, end_time;
|
||||
static double total_time;
|
||||
|
||||
#define myheader(str) \
|
||||
{ \
|
||||
fprintf(stdout,"\n\n#####################################\n"); \
|
||||
@ -77,10 +80,10 @@ static void print_error(const char *msg)
|
||||
if (mysql)
|
||||
{
|
||||
if (mysql->server_version)
|
||||
fprintf(stderr,"\n [MySQL-%s]",mysql->server_version);
|
||||
fprintf(stdout,"\n [MySQL-%s]",mysql->server_version);
|
||||
else
|
||||
fprintf(stderr,"\n [MySQL]");
|
||||
fprintf(stderr,"[%d] %s\n",mysql_errno(mysql),mysql_error(mysql));
|
||||
fprintf(stdout,"\n [MySQL]");
|
||||
fprintf(stdout,"[%d] %s\n",mysql_errno(mysql),mysql_error(mysql));
|
||||
}
|
||||
else if (msg) fprintf(stderr, " [MySQL] %s\n", msg);
|
||||
}
|
||||
@ -90,11 +93,11 @@ static void print_st_error(MYSQL_STMT *stmt, const char *msg)
|
||||
if (stmt)
|
||||
{
|
||||
if (stmt->mysql && stmt->mysql->server_version)
|
||||
fprintf(stderr,"\n [MySQL-%s]",stmt->mysql->server_version);
|
||||
fprintf(stdout,"\n [MySQL-%s]",stmt->mysql->server_version);
|
||||
else
|
||||
fprintf(stderr,"\n [MySQL]");
|
||||
fprintf(stdout,"\n [MySQL]");
|
||||
|
||||
fprintf(stderr,"[%d] %s\n",mysql_stmt_errno(stmt),
|
||||
fprintf(stdout,"[%d] %s\n",mysql_stmt_errno(stmt),
|
||||
mysql_stmt_error(stmt));
|
||||
}
|
||||
else if (msg) fprintf(stderr, " [MySQL] %s\n", msg);
|
||||
@ -173,6 +176,7 @@ static void client_connect()
|
||||
{
|
||||
myerror("connection failed");
|
||||
mysql_close(mysql);
|
||||
fprintf(stdout,"\n Check the connection options using --help or -?\n");
|
||||
exit(0);
|
||||
}
|
||||
fprintf(stdout," OK");
|
||||
@ -438,7 +442,7 @@ uint my_stmt_result(const char *query, unsigned long length)
|
||||
uint row_count;
|
||||
int rc;
|
||||
|
||||
fprintf(stdout,"\n\n %s \n", query);
|
||||
fprintf(stdout,"\n\n %s", query);
|
||||
stmt= mysql_prepare(mysql,query,length);
|
||||
mystmt_init(stmt);
|
||||
|
||||
@ -1072,7 +1076,7 @@ static void test_prepare()
|
||||
myquery(rc);
|
||||
|
||||
/* test the results now, only one row should exists */
|
||||
myassert(tiny_data == (int) my_stmt_result("SELECT * FROM my_prepare",50));
|
||||
myassert(tiny_data == (char) my_stmt_result("SELECT * FROM my_prepare",50));
|
||||
|
||||
stmt = mysql_prepare(mysql,"SELECT * FROM my_prepare",50);
|
||||
mystmt_init(stmt);
|
||||
@ -1238,8 +1242,7 @@ static void test_null()
|
||||
{
|
||||
MYSQL_STMT *stmt;
|
||||
int rc;
|
||||
int nData=1;
|
||||
MYSQL_RES *result;
|
||||
uint nData;
|
||||
MYSQL_BIND bind[2];
|
||||
my_bool is_null[2];
|
||||
|
||||
@ -1268,33 +1271,69 @@ static void test_null()
|
||||
bind[0].buffer_type=MYSQL_TYPE_LONG;
|
||||
bind[0].is_null= &is_null[0];
|
||||
is_null[0]= 1;
|
||||
bind[1]=bind[0]; /* string data */
|
||||
bind[1]=bind[0];
|
||||
|
||||
rc = mysql_bind_param(stmt,bind);
|
||||
mystmt(stmt, rc);
|
||||
|
||||
/* now, execute the prepared statement to insert 10 records.. */
|
||||
for (nData=0; nData<9; nData++)
|
||||
for (nData=0; nData<10; nData++)
|
||||
{
|
||||
rc = mysql_execute(stmt);
|
||||
mystmt(stmt, rc);
|
||||
}
|
||||
|
||||
/* Re-bind with MYSQL_TYPE_NULL */
|
||||
bind[0].buffer_type= MYSQL_TYPE_NULL;
|
||||
is_null[0]= 0; /* reset */
|
||||
bind[1]= bind[0];
|
||||
|
||||
rc = mysql_bind_param(stmt,bind);
|
||||
mystmt(stmt,rc);
|
||||
|
||||
for (nData=0; nData<10; nData++)
|
||||
{
|
||||
rc = mysql_execute(stmt);
|
||||
mystmt(stmt, rc);
|
||||
}
|
||||
|
||||
mysql_stmt_close(stmt);
|
||||
|
||||
/* now fetch the results ..*/
|
||||
rc = mysql_commit(mysql);
|
||||
myquery(rc);
|
||||
|
||||
/* test the results now, only one row should exists */
|
||||
rc = mysql_query(mysql,"SELECT * FROM test_null");
|
||||
myquery(rc);
|
||||
nData*= 2;
|
||||
myassert(nData == my_stmt_result("SELECT * FROM test_null", 30));
|
||||
|
||||
/* get the result */
|
||||
result = mysql_store_result(mysql);
|
||||
mytest(result);
|
||||
/* Fetch results */
|
||||
bind[0].buffer_type= MYSQL_TYPE_LONG;
|
||||
bind[0].buffer= (char *)&nData; /* this buffer won't be altered */
|
||||
bind[0].length= 0;
|
||||
bind[1]= bind[0];
|
||||
bind[0].is_null= &is_null[0];
|
||||
bind[1].is_null= &is_null[1];
|
||||
|
||||
myassert(nData == my_process_result_set(result));
|
||||
mysql_free_result(result);
|
||||
stmt = mysql_prepare(mysql,"SELECT * FROM test_null",30);
|
||||
mystmt_init(stmt);
|
||||
|
||||
rc = mysql_execute(stmt);
|
||||
mystmt(stmt,rc);
|
||||
|
||||
rc = mysql_bind_result(stmt,bind);
|
||||
mystmt(stmt,rc);
|
||||
|
||||
rc= 0;
|
||||
is_null[0]= is_null[1]= 0;
|
||||
while (mysql_fetch(stmt) != MYSQL_NO_DATA)
|
||||
{
|
||||
myassert(is_null[0]);
|
||||
myassert(is_null[1]);
|
||||
rc++;
|
||||
is_null[0]= is_null[1]= 0;
|
||||
}
|
||||
myassert(rc == (int)nData);
|
||||
mysql_stmt_close(stmt);
|
||||
}
|
||||
|
||||
|
||||
@ -1636,8 +1675,13 @@ static void test_select_show()
|
||||
|
||||
mysql_autocommit(mysql,TRUE);
|
||||
|
||||
strmov(query,"SELECT * FROM mysql.host");
|
||||
stmt = mysql_prepare(mysql, query, strlen(query));
|
||||
rc = mysql_query(mysql, "DROP TABLE IF EXISTS test_show");
|
||||
myquery(rc);
|
||||
|
||||
rc = mysql_query(mysql, "CREATE TABLE test_show(id int(4) NOT NULL, name char(2))");
|
||||
myquery(rc);
|
||||
|
||||
stmt = mysql_prepare(mysql, "show columns from test_show", 30);
|
||||
mystmt_init(stmt);
|
||||
|
||||
verify_param_count(stmt,0);
|
||||
@ -1646,7 +1690,28 @@ static void test_select_show()
|
||||
mystmt(stmt, rc);
|
||||
|
||||
my_process_stmt_result(stmt);
|
||||
mysql_stmt_close(stmt);
|
||||
|
||||
stmt = mysql_prepare(mysql, "show tables from mysql like ?", 50);
|
||||
mystmt_init_r(stmt);
|
||||
|
||||
strxmov(query,"show tables from ", current_db, " like \'test_show\'", NullS);
|
||||
stmt = mysql_prepare(mysql, query, strlen(query));
|
||||
mystmt_init(stmt);
|
||||
|
||||
rc = mysql_execute(stmt);
|
||||
mystmt(stmt, rc);
|
||||
|
||||
my_process_stmt_result(stmt);
|
||||
mysql_stmt_close(stmt);
|
||||
|
||||
stmt = mysql_prepare(mysql, "describe test_show", 30);
|
||||
mystmt_init(stmt);
|
||||
|
||||
rc = mysql_execute(stmt);
|
||||
mystmt(stmt, rc);
|
||||
|
||||
my_process_stmt_result(stmt);
|
||||
mysql_stmt_close(stmt);
|
||||
}
|
||||
|
||||
@ -4361,6 +4426,9 @@ static void test_multi_query()
|
||||
int rc;
|
||||
|
||||
const char *query= "DROP TABLE IF EXISTS test_multi_tab;\
|
||||
CREATE TABLE test_multi_tab(id int,name char(20));\
|
||||
INSERT INTO test_multi_tab(xxxx) VALUES(10);\
|
||||
UPDATE test_multi_tab SET id=10 WHERE unkown_col=10;\
|
||||
CREATE TABLE test_multi_tab(id int,name char(20));\
|
||||
INSERT INTO test_multi_tab(id) VALUES(10),(20);\
|
||||
INSERT INTO test_multi_tab VALUES(20,'insert;comma');\
|
||||
@ -4370,14 +4438,20 @@ static void test_multi_query()
|
||||
DELETE FROM test_multi_tab WHERE name='new;name';\
|
||||
SELECT * FROM test_multi_tab;\
|
||||
DELETE FROM test_multi_tab WHERE id=10;\
|
||||
SELECT * FROM test_multi_tab";
|
||||
uint count, rows[10]={0,2,1,3,0,2,2,1,1,0};
|
||||
|
||||
SELECT * FROM test_multi_tab;\
|
||||
DROP TABLE test_multi_tab;\
|
||||
DROP TABLE test_multi_tab;\
|
||||
DROP TABLE IF EXISTS test_multi_tab";
|
||||
uint count, rows[16]={0,1054,1054,1050,2,1,3,1054,2,2,1,1,0,0,1051,0}, exp_value;
|
||||
|
||||
myheader("test_multi_query");
|
||||
|
||||
rc = mysql_query(mysql, query); /* syntax error */
|
||||
myquery_r(rc);
|
||||
|
||||
myassert(0 == mysql_next_result(mysql));
|
||||
myassert(0 == mysql_more_results(mysql));
|
||||
|
||||
if (!(l_mysql = mysql_init(NULL)))
|
||||
{
|
||||
fprintf(stdout,"\n mysql_init() failed");
|
||||
@ -4396,19 +4470,25 @@ static void test_multi_query()
|
||||
rc = mysql_query(mysql, query);
|
||||
myquery(rc);
|
||||
|
||||
count= 0;
|
||||
while (mysql_more_results(mysql) && count < sizeof(rows)/sizeof(uint))
|
||||
count= exp_value= 0;
|
||||
while (mysql_more_results(mysql) && count < array_elements(rows))
|
||||
{
|
||||
fprintf(stdout,"\n query %d", count);
|
||||
fprintf(stdout,"\n Query %d: ", count);
|
||||
if ((rc= mysql_next_result(mysql)))
|
||||
fprintf(stdout, "\n\t failed(%s)", mysql_error(mysql));
|
||||
{
|
||||
exp_value= mysql_errno(mysql);
|
||||
fprintf(stdout, "ERROR %d: %s", exp_value, mysql_error(mysql));
|
||||
}
|
||||
else
|
||||
fprintf(stdout,"\n\t affected rows: %lld", mysql_affected_rows(mysql));
|
||||
if ((result= mysql_store_result(mysql)))
|
||||
my_process_result_set(result);
|
||||
if (!rc)
|
||||
myassert(rows[count] == (uint)mysql_affected_rows(mysql));
|
||||
count++;
|
||||
{
|
||||
if ((result= mysql_store_result(mysql)))
|
||||
my_process_result_set(result);
|
||||
else
|
||||
fprintf(stdout,"OK, %d row(s) affected, %d warning(s)", exp_value,
|
||||
mysql_warning_count(mysql));
|
||||
exp_value= (uint) mysql_affected_rows(mysql);
|
||||
}
|
||||
myassert(rows[count++] == exp_value);
|
||||
}
|
||||
mysql= org_mysql;
|
||||
}
|
||||
@ -4865,7 +4945,7 @@ static void test_bind_date_conv(uint row_count)
|
||||
for (i= 0; i < array_elements(bind); i++)
|
||||
{
|
||||
fprintf(stdout, "\n");
|
||||
fprintf(stdout,"time[%d]: %02d-%02d-%02d %02d:%02d:%02d.%02lu",
|
||||
fprintf(stdout," time[%d]: %02d-%02d-%02d %02d:%02d:%02d.%02lu",
|
||||
i, tm[i].year, tm[i].month, tm[i].day,
|
||||
tm[i].hour, tm[i].minute, tm[i].second,
|
||||
tm[i].second_part);
|
||||
@ -5196,6 +5276,157 @@ static void test_buffers()
|
||||
mysql_stmt_close(stmt);
|
||||
}
|
||||
|
||||
/*
|
||||
Test the direct query execution in the middle of open stmts
|
||||
*/
|
||||
static void test_open_direct()
|
||||
{
|
||||
MYSQL_STMT *stmt;
|
||||
MYSQL_RES *result;
|
||||
int rc;
|
||||
|
||||
myheader("test_open_direct");
|
||||
|
||||
rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_open_direct");
|
||||
myquery(rc);
|
||||
|
||||
rc = mysql_query(mysql,"CREATE TABLE test_open_direct(id int, name char(6))");
|
||||
myquery(rc);
|
||||
|
||||
stmt = mysql_prepare(mysql,"INSERT INTO test_open_direct values(10,'mysql')", 100);
|
||||
mystmt_init(stmt);
|
||||
|
||||
rc = mysql_query(mysql, "SELECT * FROM test_open_direct");
|
||||
myquery(rc);
|
||||
|
||||
result = mysql_store_result(mysql);
|
||||
mytest(result);
|
||||
|
||||
myassert(0 == my_process_result_set(result));
|
||||
|
||||
rc = mysql_execute(stmt);
|
||||
mystmt(stmt, rc);
|
||||
|
||||
fprintf(stdout, "\n total affected rows: %lld", mysql_stmt_affected_rows(stmt));
|
||||
myassert(1 == mysql_stmt_affected_rows(stmt));
|
||||
|
||||
rc = mysql_query(mysql, "SELECT * FROM test_open_direct");
|
||||
myquery(rc);
|
||||
|
||||
result = mysql_store_result(mysql);
|
||||
mytest(result);
|
||||
|
||||
myassert(1 == my_process_result_set(result));
|
||||
|
||||
rc = mysql_execute(stmt);
|
||||
mystmt(stmt, rc);
|
||||
|
||||
fprintf(stdout, "\n total affected rows: %lld", mysql_stmt_affected_rows(stmt));
|
||||
myassert(1 == mysql_stmt_affected_rows(stmt));
|
||||
|
||||
rc = mysql_query(mysql, "SELECT * FROM test_open_direct");
|
||||
myquery(rc);
|
||||
|
||||
result = mysql_store_result(mysql);
|
||||
mytest(result);
|
||||
|
||||
myassert(2 == my_process_result_set(result));
|
||||
mysql_stmt_close(stmt);
|
||||
|
||||
/* run a direct query in the middle of a fetch */
|
||||
stmt= mysql_prepare(mysql,"SELECT * FROM test_open_direct",100);
|
||||
mystmt_init(stmt);
|
||||
|
||||
rc = mysql_execute(stmt);
|
||||
mystmt(stmt, rc);
|
||||
|
||||
rc = mysql_fetch(stmt);
|
||||
mystmt(stmt, rc);
|
||||
|
||||
rc = mysql_query(mysql,"INSERT INTO test_open_direct(id) VALUES(20)");
|
||||
myquery_r(rc);
|
||||
|
||||
rc = mysql_stmt_close(stmt);
|
||||
mystmt(stmt, rc);
|
||||
|
||||
rc = mysql_query(mysql,"INSERT INTO test_open_direct(id) VALUES(20)");
|
||||
myquery(rc);
|
||||
|
||||
/* run a direct query with store result */
|
||||
stmt= mysql_prepare(mysql,"SELECT * FROM test_open_direct",100);
|
||||
mystmt_init(stmt);
|
||||
|
||||
rc = mysql_execute(stmt);
|
||||
mystmt(stmt, rc);
|
||||
|
||||
rc = mysql_stmt_store_result(stmt);
|
||||
mystmt(stmt, rc);
|
||||
|
||||
rc = mysql_fetch(stmt);
|
||||
mystmt(stmt, rc);
|
||||
|
||||
rc = mysql_query(mysql,"drop table test_open_direct");
|
||||
myquery(rc);
|
||||
|
||||
rc = mysql_stmt_close(stmt);
|
||||
mystmt(stmt, rc);
|
||||
}
|
||||
|
||||
/*
|
||||
To test fetch without prior bound buffers
|
||||
*/
|
||||
static void test_fetch_nobuffs()
|
||||
{
|
||||
MYSQL_STMT *stmt;
|
||||
MYSQL_BIND bind[4];
|
||||
char str[4][50];
|
||||
int rc;
|
||||
|
||||
myheader("test_fetch_nobuffs");
|
||||
|
||||
stmt = mysql_prepare(mysql,"SELECT DATABASE(), CURRENT_USER(), CURRENT_DATE(), CURRENT_TIME()",100);
|
||||
mystmt_init(stmt);
|
||||
|
||||
rc = mysql_execute(stmt);
|
||||
mystmt(stmt, rc);
|
||||
|
||||
rc = 0;
|
||||
while (mysql_fetch(stmt) != MYSQL_NO_DATA)
|
||||
rc++;
|
||||
fprintf(stdout, "\n total rows: %d", rc);
|
||||
myassert(rc == 1);
|
||||
|
||||
bind[0].buffer_type= MYSQL_TYPE_STRING;
|
||||
bind[0].buffer= (char *)str[0];
|
||||
bind[0].is_null= 0;
|
||||
bind[0].length= 0;
|
||||
bind[0].buffer_length= sizeof(str[0]);
|
||||
bind[1]= bind[2]= bind[3]= bind[0];
|
||||
bind[1].buffer= (char *)str[1];
|
||||
bind[2].buffer= (char *)str[2];
|
||||
bind[3].buffer= (char *)str[3];
|
||||
|
||||
rc = mysql_bind_result(stmt, bind);
|
||||
mystmt(stmt, rc);
|
||||
|
||||
rc = mysql_execute(stmt);
|
||||
mystmt(stmt, rc);
|
||||
|
||||
rc = 0;
|
||||
while (mysql_fetch(stmt) != MYSQL_NO_DATA)
|
||||
{
|
||||
rc++;
|
||||
fprintf(stdout, "\n CURRENT_DATABASE(): %s", str[0]);
|
||||
fprintf(stdout, "\n CURRENT_USER() : %s", str[1]);
|
||||
fprintf(stdout, "\n CURRENT_DATE() : %s", str[2]);
|
||||
fprintf(stdout, "\n CURRENT_TIME() : %s", str[3]);
|
||||
}
|
||||
fprintf(stdout, "\n total rows: %d", rc);
|
||||
myassert(rc == 1);
|
||||
|
||||
mysql_stmt_close(stmt);
|
||||
}
|
||||
|
||||
static struct my_option myctest_long_options[] =
|
||||
{
|
||||
{"help", '?', "Display this help and exit", 0, 0, 0, GET_NO_ARG, NO_ARG, 0,
|
||||
@ -5225,6 +5456,7 @@ static void usage(void)
|
||||
/*
|
||||
* show the usage string when the user asks for this
|
||||
*/
|
||||
putc('\n',stdout);
|
||||
puts("***********************************************************************\n");
|
||||
puts(" Test for client-server protocol 4.1");
|
||||
puts(" By Monty & Venu \n");
|
||||
@ -5251,7 +5483,7 @@ static void usage(void)
|
||||
#endif
|
||||
fprintf(stdout,"\
|
||||
-t, --count=... Execute the test count times.\n");
|
||||
fprintf(stdout,"*********************************************************************\n");
|
||||
puts("***********************************************************************\n");
|
||||
}
|
||||
|
||||
static my_bool
|
||||
@ -5300,26 +5532,42 @@ static void get_options(int argc, char **argv)
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
Print the test output on successful execution before exiting
|
||||
*/
|
||||
|
||||
static void print_test_output()
|
||||
{
|
||||
fprintf(stdout,"\n\n");
|
||||
fprintf(stdout,"All '%d' tests were successful (in '%d' iterations)",
|
||||
test_count-1, opt_count);
|
||||
fprintf(stdout,"\n Total execution time: %g SECS", total_time);
|
||||
if (opt_count > 1)
|
||||
fprintf(stdout," (Avg: %g SECS)", total_time/opt_count);
|
||||
|
||||
fprintf(stdout,"\n\n!!! SUCCESS !!!\n");
|
||||
}
|
||||
|
||||
/********************************************************
|
||||
* main routine *
|
||||
*********************************************************/
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
time_t start_time, end_time;
|
||||
double total_time= 0;
|
||||
|
||||
MY_INIT(argv[0]);
|
||||
get_options(argc,argv);
|
||||
|
||||
client_connect(); /* connect to server */
|
||||
|
||||
total_time= 0;
|
||||
for (iter_count=1; iter_count <= opt_count; iter_count++)
|
||||
{
|
||||
/* Start of tests */
|
||||
test_count= 1;
|
||||
|
||||
start_time= time((time_t *)0);
|
||||
|
||||
|
||||
test_fetch_nobuffs(); /* to fecth without prior bound buffers */
|
||||
test_open_direct(); /* direct execution in the middle of open stmts */
|
||||
test_fetch_null(); /* to fetch null data */
|
||||
test_fetch_date(); /* to fetch date,time and timestamp */
|
||||
test_fetch_str(); /* to fetch string to all types */
|
||||
@ -5399,13 +5647,8 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
client_disconnect(); /* disconnect from server */
|
||||
fprintf(stdout,"\n\nAll '%d' tests were successful (in '%d' iterations)",
|
||||
test_count-1, opt_count);
|
||||
fprintf(stdout,"\n Total execution time: %g SECS", total_time);
|
||||
if (opt_count > 1)
|
||||
fprintf(stdout," (Avg: %g SECS)", total_time/opt_count);
|
||||
print_test_output();
|
||||
|
||||
fprintf(stdout,"\n\nSUCCESS !!!\n");
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user