Merge bk-internal.mysql.com:/home/bk/mysql-4.1
into mysql.com:/home/my/mysql-4.1
This commit is contained in:
commit
a6f89625fc
@ -619,10 +619,10 @@ static struct my_option my_long_options[] =
|
||||
(gptr*) ¤t_user, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||
#endif
|
||||
{"safe-updates", 'U', "Only allow UPDATE and DELETE that uses keys.",
|
||||
(gptr*) &safe_updates, (gptr*) &safe_updates, 0, GET_BOOL, OPT_ARG, 0, 0,
|
||||
(gptr*) &safe_updates, (gptr*) &safe_updates, 0, GET_BOOL, NO_ARG, 0, 0,
|
||||
0, 0, 0, 0},
|
||||
{"i-am-a-dummy", 'U', "Synonym for option --safe-updates, -U.",
|
||||
(gptr*) &safe_updates, (gptr*) &safe_updates, 0, GET_BOOL, OPT_ARG, 0, 0,
|
||||
(gptr*) &safe_updates, (gptr*) &safe_updates, 0, GET_BOOL, NO_ARG, 0, 0,
|
||||
0, 0, 0, 0},
|
||||
{"verbose", 'v', "Write more. (-v -v -v gives the table output format).", 0,
|
||||
0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||
|
@ -95,6 +95,7 @@ functions */
|
||||
#define LONGLONG_MAX ((__int64) 0x7FFFFFFFFFFFFFFF)
|
||||
#define ULONGLONG_MAX ((unsigned __int64) 0xFFFFFFFFFFFFFFFF)
|
||||
#define LL(A) ((__int64) A)
|
||||
#define ULL(A) ((unsigned __int64) A)
|
||||
|
||||
/* Type information */
|
||||
|
||||
|
@ -67,7 +67,7 @@ extern const char *client_errors[]; /* Error messages */
|
||||
/* new 4.1 error codes */
|
||||
#define CR_NULL_POINTER 2028
|
||||
#define CR_NO_PREPARE_STMT 2029
|
||||
#define CR_NOT_ALL_PARAMS_BOUND 2030
|
||||
#define CR_PARAMS_NOT_BOUND 2030
|
||||
#define CR_DATA_TRUNCATED 2031
|
||||
#define CR_NO_PARAMETERS_EXISTS 2032
|
||||
#define CR_INVALID_PARAMETER_NO 2033
|
||||
@ -87,3 +87,5 @@ extern const char *client_errors[]; /* Error messages */
|
||||
#define CR_CONN_UNKNOW_PROTOCOL 2046
|
||||
#define CR_INVALID_CONN_HANDLE 2047
|
||||
#define CR_SECURE_AUTH 2048
|
||||
#define CR_FETCH_CANCELLED 2049
|
||||
#define CR_NO_DATA 2050
|
||||
|
@ -842,6 +842,14 @@ typedef char bool; /* Ordinary boolean values 0 1 */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef ULL
|
||||
#ifdef HAVE_LONG_LONG
|
||||
#define ULL(A) A ## ULL
|
||||
#else
|
||||
#define ULL(A) A ## UL
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
Defines to make it possible to prioritize register assignments. No
|
||||
longer that important with modern compilers.
|
||||
|
@ -256,6 +256,11 @@ typedef struct st_mysql
|
||||
LIST *stmts; /* list of all statements */
|
||||
const struct st_mysql_methods *methods;
|
||||
void *thd;
|
||||
/*
|
||||
Points to boolean flag in MYSQL_RES or MYSQL_STMT. We set this flag
|
||||
from mysql_stmt_close if close had to cancel result set of this object.
|
||||
*/
|
||||
my_bool *unbuffered_fetch_owner;
|
||||
} MYSQL;
|
||||
|
||||
typedef struct st_mysql_res {
|
||||
@ -270,6 +275,8 @@ typedef struct st_mysql_res {
|
||||
MYSQL_ROW row; /* If unbuffered read */
|
||||
MYSQL_ROW current_row; /* buffer to current row */
|
||||
my_bool eof; /* Used by mysql_fetch_row */
|
||||
/* mysql_stmt_close() had to cancel this result */
|
||||
my_bool unbuffered_fetch_cancelled;
|
||||
const struct st_mysql_methods *methods;
|
||||
} MYSQL_RES;
|
||||
|
||||
@ -479,7 +486,11 @@ my_bool STDCALL mysql_read_query_result(MYSQL *mysql);
|
||||
*/
|
||||
|
||||
/* statement state */
|
||||
enum PREP_STMT_STATE { MY_ST_UNKNOWN, MY_ST_PREPARE, MY_ST_EXECUTE };
|
||||
enum enum_mysql_stmt_state
|
||||
{
|
||||
MYSQL_STMT_INIT_DONE= 1, MYSQL_STMT_PREPARE_DONE, MYSQL_STMT_EXECUTE_DONE,
|
||||
MYSQL_STMT_FETCH_DONE
|
||||
};
|
||||
|
||||
/*
|
||||
client TIME structure to handle TIME, DATE and TIMESTAMP directly in
|
||||
@ -525,31 +536,34 @@ typedef struct st_mysql_bind
|
||||
/* statement handler */
|
||||
typedef struct st_mysql_stmt
|
||||
{
|
||||
MYSQL *mysql; /* connection handle */
|
||||
MYSQL_BIND *params; /* input parameters */
|
||||
MYSQL_RES *result; /* resultset */
|
||||
MYSQL_BIND *bind; /* row binding */
|
||||
MYSQL_FIELD *fields; /* prepare meta info */
|
||||
MEM_ROOT mem_root; /* root allocations */
|
||||
LIST list; /* list to keep track of all stmts */
|
||||
unsigned char *current_row; /* unbuffered row */
|
||||
unsigned char *last_fetched_buffer; /* last fetched column buffer */
|
||||
char *query; /* query buffer */
|
||||
MEM_ROOT mem_root; /* root allocations */
|
||||
my_ulonglong last_fetched_column; /* last fetched column */
|
||||
MYSQL *mysql; /* connection handle */
|
||||
MYSQL_BIND *params; /* input parameters */
|
||||
MYSQL_BIND *bind; /* output parameters */
|
||||
MYSQL_FIELD *fields; /* result set metadata */
|
||||
MYSQL_RES *result; /* cached result set */
|
||||
/* copy of mysql->affected_rows after statement execution */
|
||||
my_ulonglong affected_rows;
|
||||
/*
|
||||
mysql_stmt_fetch() calls this function to fetch one row (it's different
|
||||
for buffered, unbuffered and cursor fetch).
|
||||
*/
|
||||
int (*read_row_func)(struct st_mysql_stmt *stmt,
|
||||
unsigned char **row);
|
||||
unsigned long stmt_id; /* Id for prepared statement */
|
||||
unsigned int last_errno; /* error code */
|
||||
unsigned int param_count; /* parameters count */
|
||||
unsigned int field_count; /* fields count */
|
||||
enum PREP_STMT_STATE state; /* statement state */
|
||||
unsigned int param_count; /* inpute parameters count */
|
||||
unsigned int field_count; /* number of columns in result set */
|
||||
enum enum_mysql_stmt_state state; /* statement state */
|
||||
char last_error[MYSQL_ERRMSG_SIZE]; /* error message */
|
||||
char sqlstate[SQLSTATE_LENGTH+1];
|
||||
my_bool long_alloced; /* flag to indicate long alloced */
|
||||
my_bool send_types_to_server; /* Types sent to server */
|
||||
my_bool param_buffers; /* param bound buffers */
|
||||
my_bool res_buffers; /* output bound buffers */
|
||||
my_bool result_buffered; /* Results buffered */
|
||||
/* Types of input parameters should be sent to server */
|
||||
my_bool send_types_to_server;
|
||||
my_bool bind_param_done; /* input buffers were supplied */
|
||||
my_bool bind_result_done; /* output buffers were supplied */
|
||||
/* mysql_stmt_close() had to cancel this result */
|
||||
my_bool unbuffered_fetch_cancelled;
|
||||
} MYSQL_STMT;
|
||||
|
||||
|
||||
|
@ -308,4 +308,5 @@
|
||||
#define ER_FEATURE_DISABLED 1289
|
||||
#define ER_OPTION_PREVENTS_STATEMENT 1290
|
||||
#define ER_DUPLICATED_VALUE_IN_TYPE 1291
|
||||
#define ER_ERROR_MESSAGES 292
|
||||
#define ER_TRUNCATED_WRONG_VALUE 1292
|
||||
#define ER_ERROR_MESSAGES 293
|
||||
|
@ -25,6 +25,7 @@ extern "C" {
|
||||
MYSQL_FIELD *unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields,
|
||||
my_bool default_value, uint server_capabilities);
|
||||
void free_rows(MYSQL_DATA *cur);
|
||||
void flush_use_result(MYSQL *mysql);
|
||||
my_bool mysql_autenticate(MYSQL *mysql, const char *passwd);
|
||||
void free_old_query(MYSQL *mysql);
|
||||
void end_server(MYSQL *mysql);
|
||||
|
@ -22,7 +22,6 @@ extern my_string mysql_unix_port;
|
||||
CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION)
|
||||
|
||||
sig_handler pipe_sig_handler(int sig __attribute__((unused)));
|
||||
my_bool stmt_close(MYSQL_STMT *stmt, my_bool skip_free);
|
||||
void read_user_name(char *name);
|
||||
my_bool send_file_to_server(MYSQL *mysql, const char *filename);
|
||||
|
||||
|
@ -54,7 +54,7 @@ const char *client_errors[]=
|
||||
"Malformed packet",
|
||||
"Invalid use of null pointer",
|
||||
"Statement not prepared",
|
||||
"Not all parameters data supplied",
|
||||
"Parameters data was not supplied",
|
||||
"Data truncated",
|
||||
"No parameters exists in the statement",
|
||||
"Invalid parameter number",
|
||||
@ -72,7 +72,9 @@ const char *client_errors[]=
|
||||
"Can't open shared memory. Can't send the request event to server (%lu)",
|
||||
"Wrong or unknown protocol",
|
||||
"Invalid connection handle",
|
||||
"Connection using old (pre 4.1.1) authentication protocol refused (client option 'secure_auth' enabled)"
|
||||
"Connection using old (pre 4.1.1) authentication protocol refused (client option 'secure_auth' enabled)",
|
||||
"Row retrieval was cancelled by mysql_stmt_close() call",
|
||||
"Attempt to read column without prior row fetch"
|
||||
};
|
||||
|
||||
/* Start of code added by Roberto M. Serqueira - martinsc@uol.com.br - 05.24.2001 */
|
||||
@ -110,7 +112,7 @@ const char *client_errors[]=
|
||||
"Malformed packet",
|
||||
"Invalid use of null pointer",
|
||||
"Statement not prepared",
|
||||
"Not all parameters data supplied",
|
||||
"Parameters data was not supplied",
|
||||
"Data truncated",
|
||||
"No parameters exists in the statement",
|
||||
"Invalid parameter number",
|
||||
@ -128,7 +130,9 @@ const char *client_errors[]=
|
||||
"Can't open shared memory. Can't send the request event to server (%lu)",
|
||||
"Wrong or unknown protocol",
|
||||
"Invalid connection handle",
|
||||
"Connection using old (pre 4.1.1) authentication protocol refused (client option 'secure_auth' enabled)"
|
||||
"Connection using old (pre 4.1.1) authentication protocol refused (client option 'secure_auth' enabled)",
|
||||
"Row retrieval was cancelled by mysql_stmt_close() call",
|
||||
"Attempt to read column without prior row fetch"
|
||||
};
|
||||
|
||||
#else /* ENGLISH */
|
||||
@ -182,7 +186,9 @@ const char *client_errors[]=
|
||||
"Can't open shared memory. Can't send the request event to server (%lu)",
|
||||
"Wrong or unknown protocol",
|
||||
"Invalid connection handle",
|
||||
"Connection using old (pre 4.1.1) authentication protocol refused (client option 'secure_auth' enabled)"
|
||||
"Connection using old (pre 4.1.1) authentication protocol refused (client option 'secure_auth' enabled)",
|
||||
"Row retrieval was cancelled by mysql_stmt_close() call",
|
||||
"Attempt to read column without prior row fetch"
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -638,6 +638,7 @@ int cli_read_change_user_result(MYSQL *mysql, char *buff, const char *passwd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user,
|
||||
const char *passwd, const char *db)
|
||||
{
|
||||
@ -866,6 +867,7 @@ STDCALL mysql_set_master(MYSQL* mysql, const char* host,
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
STDCALL mysql_add_slave(MYSQL* mysql, const char* host,
|
||||
unsigned int port,
|
||||
@ -987,6 +989,7 @@ mysql_list_tables(MYSQL *mysql, const char *wild)
|
||||
DBUG_RETURN (mysql_store_result(mysql));
|
||||
}
|
||||
|
||||
|
||||
MYSQL_FIELD *cli_list_fields(MYSQL *mysql)
|
||||
{
|
||||
MYSQL_DATA *query;
|
||||
@ -1062,6 +1065,7 @@ mysql_list_processes(MYSQL *mysql)
|
||||
DBUG_RETURN(mysql_store_result(mysql));
|
||||
}
|
||||
|
||||
|
||||
#ifdef USE_OLD_FUNCTIONS
|
||||
int STDCALL
|
||||
mysql_create_db(MYSQL *mysql, const char *db)
|
||||
@ -1099,6 +1103,7 @@ mysql_refresh(MYSQL *mysql,uint options)
|
||||
DBUG_RETURN(simple_command(mysql,COM_REFRESH,(char*) bits,1,0));
|
||||
}
|
||||
|
||||
|
||||
int STDCALL
|
||||
mysql_kill(MYSQL *mysql,ulong pid)
|
||||
{
|
||||
@ -1126,6 +1131,7 @@ mysql_dump_debug_info(MYSQL *mysql)
|
||||
DBUG_RETURN(simple_command(mysql,COM_DEBUG,0,0,0));
|
||||
}
|
||||
|
||||
|
||||
const char *cli_read_statistics(MYSQL *mysql)
|
||||
{
|
||||
mysql->net.read_pos[mysql->packet_length]=0; /* End of stat string */
|
||||
@ -1139,6 +1145,7 @@ const char *cli_read_statistics(MYSQL *mysql)
|
||||
return (char*) mysql->net.read_pos;
|
||||
}
|
||||
|
||||
|
||||
const char * STDCALL
|
||||
mysql_stat(MYSQL *mysql)
|
||||
{
|
||||
@ -1576,6 +1583,10 @@ static my_bool my_realloc_str(NET *net, ulong length)
|
||||
Prepare related implementations
|
||||
********************************************************************/
|
||||
|
||||
static int stmt_read_row_unbuffered(MYSQL_STMT *stmt, unsigned char **row);
|
||||
static int stmt_read_row_buffered(MYSQL_STMT *stmt, unsigned char **row);
|
||||
static int stmt_read_row_no_data(MYSQL_STMT *stmt, unsigned char **row);
|
||||
|
||||
/*
|
||||
Read the prepared statement results ..
|
||||
|
||||
@ -1591,13 +1602,12 @@ static my_bool my_realloc_str(NET *net, ulong length)
|
||||
my_bool cli_read_prepare_result(MYSQL *mysql, MYSQL_STMT *stmt)
|
||||
{
|
||||
uchar *pos;
|
||||
uint field_count;
|
||||
ulong length, param_count;
|
||||
uint field_count, param_count;
|
||||
MYSQL_DATA *fields_data;
|
||||
DBUG_ENTER("read_prepare_result");
|
||||
|
||||
mysql= mysql->last_used_con;
|
||||
if ((length= net_safe_read(mysql)) == packet_error)
|
||||
if (net_safe_read(mysql) == packet_error)
|
||||
DBUG_RETURN(1);
|
||||
|
||||
pos= (uchar*) mysql->net.read_pos;
|
||||
@ -1634,7 +1644,7 @@ MYSQL_STMT * STDCALL mysql_prepare(MYSQL *mysql, const char *query,
|
||||
stmt= mysql_stmt_init(mysql);
|
||||
if (stmt && mysql_stmt_prepare(stmt, query, query_length))
|
||||
{
|
||||
stmt_close(stmt, 0);
|
||||
mysql_stmt_close(stmt);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
DBUG_RETURN(stmt);
|
||||
@ -1646,6 +1656,7 @@ MYSQL_STMT * STDCALL mysql_prepare(MYSQL *mysql, const char *query,
|
||||
SYNOPSIS
|
||||
mysql_stmt_init()
|
||||
mysql connection handle
|
||||
|
||||
RETURN VALUE
|
||||
statement structure upon success and NULL if out of
|
||||
memory
|
||||
@ -1664,20 +1675,35 @@ mysql_stmt_init(MYSQL *mysql)
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
init_alloc_root(&stmt->mem_root,8192,0);
|
||||
init_alloc_root(&stmt->mem_root, 2048, 2048);
|
||||
mysql->stmts= list_add(mysql->stmts, &stmt->list);
|
||||
stmt->list.data= stmt;
|
||||
stmt->state= MY_ST_UNKNOWN;
|
||||
stmt->state= MYSQL_STMT_INIT_DONE;
|
||||
stmt->mysql= mysql;
|
||||
stmt->read_row_func= stmt_read_row_no_data;
|
||||
/* The rest of statement members was bzeroed inside malloc */
|
||||
|
||||
DBUG_RETURN(stmt);
|
||||
}
|
||||
|
||||
/*
|
||||
Prepare server side statement with query.
|
||||
Prepare server side statement with query:
|
||||
SYNOPSIS
|
||||
mysql_stmt_prepare()
|
||||
query statement to prepare
|
||||
length statement length
|
||||
|
||||
Also update the total parameter count along with resultset
|
||||
metadata information by reading from server
|
||||
DESCRIPTION
|
||||
- if this is a re-prepare of the statement, first close previous data
|
||||
structure on the server and free old statement data
|
||||
- send the query to server and get back number of placeholders,
|
||||
number of columns in result set (if any), and result set metadata.
|
||||
At the same time allocate memory for input and output parameters
|
||||
to have less checks in mysql_stmt_bind_{param, result}.
|
||||
|
||||
RETURN VALUES
|
||||
0 success
|
||||
!0 error
|
||||
*/
|
||||
|
||||
|
||||
@ -1687,17 +1713,44 @@ mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, ulong length)
|
||||
MYSQL *mysql= stmt->mysql;
|
||||
DBUG_ENTER("mysql_stmt_prepare");
|
||||
|
||||
DBUG_ASSERT(mysql != 0);
|
||||
|
||||
/* In case we reprepare this handle with another statement */
|
||||
free_root(&stmt->mem_root, MYF(0));
|
||||
|
||||
/* stmt->query is never used yet */
|
||||
if (!(stmt->query= strmake_root(&stmt->mem_root, query, length)))
|
||||
if (!mysql)
|
||||
{
|
||||
set_stmt_error(stmt, CR_OUT_OF_MEMORY, unknown_sqlstate);
|
||||
/* mysql can be reset in mysql_close called from mysql_reconnect */
|
||||
set_stmt_error(stmt, CR_SERVER_LOST, unknown_sqlstate);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
if ((int) stmt->state > (int) MYSQL_STMT_INIT_DONE)
|
||||
{
|
||||
/* This is second prepare with another statement */
|
||||
char buff[4];
|
||||
|
||||
mysql_stmt_free_result(stmt);
|
||||
/*
|
||||
These members must be reset for API to
|
||||
function in case of error or misuse.
|
||||
*/
|
||||
stmt->bind_param_done= stmt->bind_result_done= FALSE;
|
||||
stmt->param_count= stmt->field_count= 0;
|
||||
stmt->last_errno= 0;
|
||||
stmt->last_error[0]= '\0';
|
||||
free_root(&stmt->mem_root, MYF(MY_KEEP_PREALLOC));
|
||||
|
||||
int4store(buff, stmt->stmt_id);
|
||||
/*
|
||||
If there was a 'use' result from another statement, or from
|
||||
mysql_use_result it won't be freed in mysql_stmt_free_result and
|
||||
we should get 'Commands out of sync' here.
|
||||
*/
|
||||
if (simple_command(mysql, COM_CLOSE_STMT, buff, 4, 1))
|
||||
{
|
||||
set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno,
|
||||
mysql->net.sqlstate);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
stmt->state= MYSQL_STMT_INIT_DONE;
|
||||
}
|
||||
|
||||
if (simple_command(mysql, COM_PREPARE, query, length, 1))
|
||||
{
|
||||
set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno,
|
||||
@ -1706,8 +1759,18 @@ mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, ulong length)
|
||||
}
|
||||
|
||||
if ((*mysql->methods->read_prepare_result)(mysql, stmt))
|
||||
{
|
||||
set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno,
|
||||
mysql->net.sqlstate);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
/*
|
||||
alloc_root will return valid address even in case param_count
|
||||
and field_count are zero. Thus we should never rely on stmt->bind
|
||||
or stmt->params when checking for existence of placeholders or
|
||||
result set.
|
||||
*/
|
||||
if (!(stmt->params= (MYSQL_BIND *) alloc_root(&stmt->mem_root,
|
||||
sizeof(MYSQL_BIND)*
|
||||
(stmt->param_count +
|
||||
@ -1717,26 +1780,22 @@ mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, ulong length)
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
stmt->bind= stmt->params + stmt->param_count;
|
||||
stmt->state= MY_ST_PREPARE;
|
||||
mysql->status= MYSQL_STATUS_READY;
|
||||
stmt->state= MYSQL_STMT_PREPARE_DONE;
|
||||
DBUG_PRINT("info", ("Parameter count: %ld", stmt->param_count));
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
/*
|
||||
Get the execute query meta information for non-select
|
||||
statements (on demand).
|
||||
statements.
|
||||
*/
|
||||
|
||||
unsigned int alloc_stmt_fields(MYSQL_STMT *stmt)
|
||||
static unsigned int alloc_stmt_fields(MYSQL_STMT *stmt)
|
||||
{
|
||||
MYSQL_FIELD *fields, *field, *end;
|
||||
MEM_ROOT *alloc= &stmt->mem_root;
|
||||
MYSQL *mysql= stmt->mysql->last_used_con;
|
||||
|
||||
if (stmt->state != MY_ST_EXECUTE || !mysql->field_count)
|
||||
return 0;
|
||||
|
||||
stmt->field_count= mysql->field_count;
|
||||
|
||||
/*
|
||||
@ -1782,20 +1841,25 @@ mysql_stmt_result_metadata(MYSQL_STMT *stmt)
|
||||
MYSQL_RES *result;
|
||||
DBUG_ENTER("mysql_stmt_result_metadata");
|
||||
|
||||
if (!stmt->field_count || !stmt->fields)
|
||||
{
|
||||
if (!alloc_stmt_fields(stmt))
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
if (!(result=(MYSQL_RES*) my_malloc(sizeof(*result)+
|
||||
sizeof(ulong)*stmt->field_count,
|
||||
MYF(MY_WME | MY_ZEROFILL))))
|
||||
return 0;
|
||||
/*
|
||||
stmt->fields is only defined if stmt->field_count is not null;
|
||||
stmt->field_count is initialized in prepare.
|
||||
*/
|
||||
if (!stmt->field_count)
|
||||
DBUG_RETURN(0);
|
||||
|
||||
result->methods= stmt->mysql->methods;
|
||||
result->eof=1; /* Marker for buffered */
|
||||
if (!(result=(MYSQL_RES*) my_malloc(sizeof(*result),
|
||||
MYF(MY_WME | MY_ZEROFILL))))
|
||||
{
|
||||
set_stmt_error(stmt, CR_OUT_OF_MEMORY, unknown_sqlstate);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
result->methods= stmt->mysql->methods;
|
||||
result->eof= 1; /* Marker for buffered */
|
||||
result->fields= stmt->fields;
|
||||
result->field_count= stmt->field_count;
|
||||
/* The rest of members of 'result' was bzeroed inside malloc */
|
||||
DBUG_RETURN(result);
|
||||
}
|
||||
|
||||
@ -1989,11 +2053,9 @@ static void store_param_null(NET *net, MYSQL_BIND *param)
|
||||
client application
|
||||
*/
|
||||
|
||||
|
||||
static my_bool store_param(MYSQL_STMT *stmt, MYSQL_BIND *param)
|
||||
{
|
||||
MYSQL *mysql= stmt->mysql;
|
||||
NET *net = &mysql->net;
|
||||
NET *net= &stmt->mysql->net;
|
||||
DBUG_ENTER("store_param");
|
||||
DBUG_PRINT("enter",("type: %d, buffer:%lx, length: %lu is_null: %d",
|
||||
param->buffer_type,
|
||||
@ -2059,6 +2121,12 @@ int cli_stmt_execute(MYSQL_STMT *stmt)
|
||||
uint null_count;
|
||||
my_bool result;
|
||||
|
||||
if (!stmt->bind_param_done)
|
||||
{
|
||||
set_stmt_error(stmt, CR_PARAMS_NOT_BOUND, unknown_sqlstate);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
net_clear(net); /* Sets net->write_pos */
|
||||
/* Reserve place for null-marker bytes */
|
||||
null_count= (stmt->param_count+7) /8;
|
||||
@ -2093,7 +2161,6 @@ int cli_stmt_execute(MYSQL_STMT *stmt)
|
||||
set_stmt_error(stmt, CR_OUT_OF_MEMORY, unknown_sqlstate);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
net->write_pos= net->buff; /* Reset for net_write() */
|
||||
result= execute(stmt, param_data, length);
|
||||
stmt->send_types_to_server=0;
|
||||
my_free(param_data, MYF(MY_WME));
|
||||
@ -2102,22 +2169,146 @@ int cli_stmt_execute(MYSQL_STMT *stmt)
|
||||
DBUG_RETURN((int) execute(stmt,0,0));
|
||||
}
|
||||
|
||||
/*
|
||||
Read one row from buffered result set. Result set is created by prior
|
||||
call to mysql_stmt_store_result().
|
||||
SYNOPSIS
|
||||
stmt_read_row_buffered()
|
||||
|
||||
RETURN VALUE
|
||||
0 - success; *row is set to valid row pointer (row data
|
||||
is stored in result set buffer)
|
||||
MYSQL_NO_DATA - end of result set. *row is set to NULL
|
||||
*/
|
||||
|
||||
static int stmt_read_row_buffered(MYSQL_STMT *stmt, unsigned char **row)
|
||||
{
|
||||
MYSQL_RES *result= stmt->result;
|
||||
|
||||
if (result && result->data_cursor)
|
||||
{
|
||||
*row= (uchar *) result->data_cursor->data;
|
||||
result->data_cursor= result->data_cursor->next;
|
||||
return 0;
|
||||
}
|
||||
*row= 0;
|
||||
return MYSQL_NO_DATA;
|
||||
}
|
||||
|
||||
/*
|
||||
Read one row from network: unbuffered non-cursor fetch.
|
||||
If last row was read, or error occured, erase this statement
|
||||
from record pointing to object unbuffered fetch is performed from.
|
||||
|
||||
SYNOPSIS
|
||||
stmt_read_row_unbuffered()
|
||||
stmt statement handle
|
||||
row pointer to write pointer to row data;
|
||||
|
||||
RETURN VALUE
|
||||
0 - success; *row contains valid address of a row;
|
||||
row data is stored in network buffer
|
||||
1 - error; error code is written to
|
||||
stmt->last_{errno,error}; *row is not changed
|
||||
MYSQL_NO_DATA - end of file was read from network;
|
||||
*row is to NULL
|
||||
*/
|
||||
|
||||
static int stmt_read_row_unbuffered(MYSQL_STMT *stmt, unsigned char **row)
|
||||
{
|
||||
int rc= 1;
|
||||
MYSQL *mysql= stmt->mysql;
|
||||
/*
|
||||
This function won't be called if stmt->field_count is zero
|
||||
or execution wasn't done: this is ensured by mysql_stmt_execute.
|
||||
*/
|
||||
if (!mysql)
|
||||
{
|
||||
set_stmt_error(stmt, CR_SERVER_LOST, unknown_sqlstate);
|
||||
return 1;
|
||||
}
|
||||
if (mysql->status != MYSQL_STATUS_GET_RESULT)
|
||||
{
|
||||
set_stmt_error(stmt, stmt->unbuffered_fetch_cancelled ?
|
||||
CR_FETCH_CANCELLED : CR_COMMANDS_OUT_OF_SYNC,
|
||||
unknown_sqlstate);
|
||||
goto error;
|
||||
}
|
||||
if ((*mysql->methods->unbuffered_fetch)(mysql, (char**) row))
|
||||
{
|
||||
set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno,
|
||||
mysql->net.sqlstate);
|
||||
goto error;
|
||||
}
|
||||
if (!*row)
|
||||
{
|
||||
mysql->status= MYSQL_STATUS_READY;
|
||||
rc= MYSQL_NO_DATA;
|
||||
goto error;
|
||||
}
|
||||
return 0;
|
||||
error:
|
||||
if (mysql->unbuffered_fetch_owner == &stmt->unbuffered_fetch_cancelled)
|
||||
mysql->unbuffered_fetch_owner= 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
Default read row function to not SIGSEGV in client in
|
||||
case of wrong sequence of API calls.
|
||||
*/
|
||||
|
||||
static int
|
||||
stmt_read_row_no_data(MYSQL_STMT *stmt __attribute__((unused)),
|
||||
unsigned char **row __attribute__((unused)))
|
||||
{
|
||||
if ((int) stmt->state < (int) MYSQL_STMT_PREPARE_DONE)
|
||||
{
|
||||
set_stmt_error(stmt, CR_NO_PREPARE_STMT, unknown_sqlstate);
|
||||
return 1;
|
||||
}
|
||||
return MYSQL_NO_DATA;
|
||||
}
|
||||
|
||||
/*
|
||||
Execute the prepared query
|
||||
*/
|
||||
|
||||
int STDCALL mysql_stmt_execute(MYSQL_STMT *stmt)
|
||||
{
|
||||
MYSQL *mysql= stmt->mysql;
|
||||
DBUG_ENTER("mysql_stmt_execute");
|
||||
|
||||
if ((*stmt->mysql->methods->stmt_execute)(stmt))
|
||||
if (!mysql)
|
||||
{
|
||||
set_stmt_error(stmt, CR_SERVER_LOST, unknown_sqlstate);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
mysql_stmt_free_result(stmt);
|
||||
/*
|
||||
No need to check for stmt->state: if the statement wasn't
|
||||
prepared we'll get 'unknown statemenet handler' error from server.
|
||||
*/
|
||||
if (mysql->methods->stmt_execute(stmt))
|
||||
DBUG_RETURN(1);
|
||||
if (!stmt->field_count && mysql->field_count)
|
||||
{
|
||||
/*
|
||||
This is 'SHOW'/'EXPLAIN'-like query. Current implementation of
|
||||
prepared statements can't send result set metadata for this queries
|
||||
on prepare stage. Read it now.
|
||||
*/
|
||||
alloc_stmt_fields(stmt);
|
||||
}
|
||||
|
||||
stmt->state= MY_ST_EXECUTE;
|
||||
mysql_free_result(stmt->result);
|
||||
stmt->result= (MYSQL_RES *)0;
|
||||
stmt->result_buffered= 0;
|
||||
stmt->current_row= 0;
|
||||
stmt->state= MYSQL_STMT_EXECUTE_DONE;
|
||||
if (stmt->field_count)
|
||||
{
|
||||
stmt->mysql->unbuffered_fetch_owner= &stmt->unbuffered_fetch_cancelled;
|
||||
stmt->unbuffered_fetch_cancelled= FALSE;
|
||||
stmt->read_row_func= stmt_read_row_unbuffered;
|
||||
}
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
@ -2155,6 +2346,16 @@ my_bool STDCALL mysql_stmt_bind_param(MYSQL_STMT *stmt, MYSQL_BIND * bind)
|
||||
MYSQL_BIND *param, *end;
|
||||
DBUG_ENTER("mysql_stmt_bind_param");
|
||||
|
||||
if (!stmt->param_count)
|
||||
{
|
||||
if ((int) stmt->state < (int) MYSQL_STMT_PREPARE_DONE)
|
||||
{
|
||||
set_stmt_error(stmt, CR_NO_PREPARE_STMT, unknown_sqlstate);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
/* Allocated on prepare */
|
||||
memcpy((char*) stmt->params, (char*) bind,
|
||||
sizeof(MYSQL_BIND) * stmt->param_count);
|
||||
@ -2166,13 +2367,6 @@ my_bool STDCALL mysql_stmt_bind_param(MYSQL_STMT *stmt, MYSQL_BIND * bind)
|
||||
param->param_number= count++;
|
||||
param->long_data_used= 0;
|
||||
|
||||
/*
|
||||
If param->length is not given, change it to point to buffer_length.
|
||||
This way we can always use *param->length to get the length of data
|
||||
*/
|
||||
if (!param->length)
|
||||
param->length= ¶m->buffer_length;
|
||||
|
||||
/* If param->is_null is not set, then the value can never be NULL */
|
||||
if (!param->is_null)
|
||||
param->is_null= &int_is_null_false;
|
||||
@ -2239,10 +2433,16 @@ my_bool STDCALL mysql_stmt_bind_param(MYSQL_STMT *stmt, MYSQL_BIND * bind)
|
||||
param->buffer_type, count);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
/*
|
||||
If param->length is not given, change it to point to buffer_length.
|
||||
This way we can always use *param->length to get the length of data
|
||||
*/
|
||||
if (!param->length)
|
||||
param->length= ¶m->buffer_length;
|
||||
}
|
||||
/* We have to send/resendtype information to MySQL */
|
||||
stmt->send_types_to_server= 1;
|
||||
stmt->param_buffers= 1;
|
||||
stmt->send_types_to_server= TRUE;
|
||||
stmt->bind_param_done= TRUE;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
@ -2276,6 +2476,16 @@ mysql_stmt_send_long_data(MYSQL_STMT *stmt, uint param_number,
|
||||
DBUG_ASSERT(stmt != 0);
|
||||
DBUG_PRINT("enter",("param no : %d, data : %lx, length : %ld",
|
||||
param_number, data, length));
|
||||
|
||||
/*
|
||||
We only need to check for stmt->param_count, if it's not null
|
||||
prepare was done.
|
||||
*/
|
||||
if (param_number >= stmt->param_count)
|
||||
{
|
||||
set_stmt_error(stmt, CR_INVALID_PARAMETER_NO, unknown_sqlstate);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
param= stmt->params+param_number;
|
||||
if (param->buffer_type < MYSQL_TYPE_TINY_BLOB ||
|
||||
@ -2846,9 +3056,20 @@ my_bool STDCALL mysql_stmt_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind)
|
||||
DBUG_ENTER("mysql_stmt_bind_result");
|
||||
DBUG_ASSERT(stmt != 0);
|
||||
|
||||
if (!(bind_count= stmt->field_count) &&
|
||||
!(bind_count= alloc_stmt_fields(stmt)))
|
||||
if (!stmt->field_count)
|
||||
{
|
||||
if ((int) stmt->state < (int) MYSQL_STMT_PREPARE_DONE)
|
||||
{
|
||||
set_stmt_error(stmt, CR_NO_PREPARE_STMT, unknown_sqlstate);
|
||||
}
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
bind_count= stmt->field_count;
|
||||
|
||||
/*
|
||||
We only need to check that stmt->field_count - if it is not null
|
||||
stmt->bind was initialized in mysql_stmt_prepare
|
||||
*/
|
||||
|
||||
memcpy((char*) stmt->bind, (char*) bind,
|
||||
sizeof(MYSQL_BIND)*bind_count);
|
||||
@ -2929,7 +3150,7 @@ my_bool STDCALL mysql_stmt_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind)
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
}
|
||||
stmt->res_buffers= 1;
|
||||
stmt->bind_result_done= TRUE;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
@ -2943,9 +3164,18 @@ static int stmt_fetch_row(MYSQL_STMT *stmt, uchar *row)
|
||||
MYSQL_BIND *bind, *end;
|
||||
MYSQL_FIELD *field, *field_end;
|
||||
uchar *null_ptr, bit;
|
||||
/*
|
||||
Precondition: if stmt->field_count is zero or row is NULL, read_row_*
|
||||
function must return no data.
|
||||
*/
|
||||
DBUG_ASSERT(stmt->field_count);
|
||||
DBUG_ASSERT(row);
|
||||
|
||||
if (!row || !stmt->res_buffers)
|
||||
if (!stmt->bind_result_done)
|
||||
{
|
||||
/* If output parameters were not bound we should just return success */
|
||||
return 0;
|
||||
}
|
||||
|
||||
null_ptr= row;
|
||||
row+= (stmt->field_count+9)/8; /* skip null bits */
|
||||
@ -2994,57 +3224,22 @@ int cli_unbuffered_fetch(MYSQL *mysql, char **row)
|
||||
|
||||
int STDCALL mysql_stmt_fetch(MYSQL_STMT *stmt)
|
||||
{
|
||||
MYSQL *mysql= stmt->mysql;
|
||||
int rc;
|
||||
uchar *row;
|
||||
DBUG_ENTER("mysql_stmt_fetch");
|
||||
|
||||
stmt->last_fetched_column= 0; /* reset */
|
||||
if (stmt->result_buffered) /* buffered */
|
||||
if ((rc= (*stmt->read_row_func)(stmt, &row)) ||
|
||||
(rc= stmt_fetch_row(stmt, row)))
|
||||
{
|
||||
MYSQL_RES *res;
|
||||
|
||||
if (!(res= stmt->result))
|
||||
goto no_data;
|
||||
|
||||
if (!res->data_cursor)
|
||||
{
|
||||
stmt->current_row= 0;
|
||||
goto no_data;
|
||||
}
|
||||
row= (uchar *)res->data_cursor->data;
|
||||
res->data_cursor= res->data_cursor->next;
|
||||
stmt->state= MYSQL_STMT_PREPARE_DONE; /* XXX: this is buggy */
|
||||
stmt->read_row_func= stmt_read_row_no_data;
|
||||
}
|
||||
else /* un-buffered */
|
||||
else
|
||||
{
|
||||
if (mysql->status != MYSQL_STATUS_GET_RESULT)
|
||||
{
|
||||
if (!stmt->field_count)
|
||||
goto no_data;
|
||||
|
||||
set_stmt_error(stmt, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
if ((*mysql->methods->unbuffered_fetch)(mysql, (char**) &row))
|
||||
{
|
||||
set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno,
|
||||
mysql->net.sqlstate);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
if (!row)
|
||||
{
|
||||
mysql->status= MYSQL_STATUS_READY;
|
||||
stmt->current_row= 0;
|
||||
goto no_data;
|
||||
}
|
||||
/* This is to know in mysql_stmt_fetch_column that data was fetched */
|
||||
stmt->state= MYSQL_STMT_FETCH_DONE;
|
||||
}
|
||||
|
||||
stmt->current_row= row;
|
||||
DBUG_RETURN(stmt_fetch_row(stmt, row));
|
||||
|
||||
no_data:
|
||||
DBUG_PRINT("info", ("end of data"));
|
||||
DBUG_RETURN(MYSQL_NO_DATA); /* no more data */
|
||||
DBUG_RETURN(rc);
|
||||
}
|
||||
|
||||
|
||||
@ -3065,13 +3260,22 @@ no_data:
|
||||
*/
|
||||
|
||||
int STDCALL mysql_stmt_fetch_column(MYSQL_STMT *stmt, MYSQL_BIND *bind,
|
||||
uint column, ulong offset)
|
||||
uint column, ulong offset)
|
||||
{
|
||||
MYSQL_BIND *param= stmt->bind+column;
|
||||
DBUG_ENTER("mysql_stmt_fetch_column");
|
||||
|
||||
if (!stmt->current_row)
|
||||
goto no_data;
|
||||
if ((int) stmt->state < (int) MYSQL_STMT_FETCH_DONE)
|
||||
{
|
||||
set_stmt_error(stmt, CR_NO_DATA, unknown_sqlstate);
|
||||
return 1;
|
||||
}
|
||||
if (column >= stmt->field_count)
|
||||
{
|
||||
set_stmt_error(stmt, CR_INVALID_PARAMETER_NO, unknown_sqlstate);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
|
||||
if (param->null_field)
|
||||
{
|
||||
@ -3092,10 +3296,6 @@ int STDCALL mysql_stmt_fetch_column(MYSQL_STMT *stmt, MYSQL_BIND *bind,
|
||||
fetch_results(bind, field, &row);
|
||||
}
|
||||
DBUG_RETURN(0);
|
||||
|
||||
no_data:
|
||||
DBUG_PRINT("info", ("end of data"));
|
||||
DBUG_RETURN(MYSQL_NO_DATA); /* no more data */
|
||||
}
|
||||
|
||||
|
||||
@ -3111,7 +3311,7 @@ MYSQL_DATA *cli_read_binary_rows(MYSQL_STMT *stmt)
|
||||
MYSQL_DATA *result;
|
||||
MYSQL_ROWS *cur, **prev_ptr;
|
||||
NET *net = &mysql->net;
|
||||
DBUG_ENTER("read_binary_rows");
|
||||
DBUG_ENTER("cli_read_binary_rows");
|
||||
|
||||
mysql= mysql->last_used_con;
|
||||
if ((pkt_len= net_safe_read(mysql)) == packet_error)
|
||||
@ -3181,33 +3381,37 @@ int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt)
|
||||
|
||||
if (!stmt->field_count)
|
||||
DBUG_RETURN(0);
|
||||
if (mysql->status != MYSQL_STATUS_GET_RESULT)
|
||||
if ((int) stmt->state < (int) MYSQL_STMT_EXECUTE_DONE ||
|
||||
mysql->status != MYSQL_STATUS_GET_RESULT)
|
||||
{
|
||||
set_stmt_error(stmt, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
mysql->status= MYSQL_STATUS_READY; /* server is ready */
|
||||
if (!(result= (MYSQL_RES*) my_malloc((uint) (sizeof(MYSQL_RES)+
|
||||
sizeof(ulong) *
|
||||
stmt->field_count),
|
||||
if (!(result= (MYSQL_RES*) my_malloc(sizeof(MYSQL_RES),
|
||||
MYF(MY_WME | MY_ZEROFILL))))
|
||||
{
|
||||
set_stmt_error(stmt, CR_OUT_OF_MEMORY, unknown_sqlstate);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
result->methods= mysql->methods;
|
||||
stmt->result_buffered= 1;
|
||||
if (!(result->data= (*stmt->mysql->methods->read_binary_rows)(stmt)))
|
||||
if ((result->data= (*mysql->methods->read_binary_rows)(stmt)))
|
||||
{
|
||||
result->row_count= result->data->rows;
|
||||
result->data_cursor= result->data->data;
|
||||
}
|
||||
else if (stmt->last_errno)
|
||||
{
|
||||
my_free((gptr) result,MYF(0));
|
||||
DBUG_RETURN(0);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
mysql->affected_rows= result->row_count= result->data->rows;
|
||||
stmt->affected_rows= result->row_count;
|
||||
result->data_cursor= result->data->data;
|
||||
mysql->affected_rows= stmt->affected_rows= result->row_count;
|
||||
result->fields= stmt->fields;
|
||||
result->field_count= stmt->field_count;
|
||||
/* The rest of MYSQL_RES members were bzeroed inside my_malloc */
|
||||
stmt->result= result;
|
||||
stmt->read_row_func= stmt_read_row_buffered;
|
||||
mysql->unbuffered_fetch_owner= 0; /* set in stmt_execute */
|
||||
mysql->status= MYSQL_STATUS_READY; /* server is ready */
|
||||
DBUG_RETURN(0); /* Data buffered, must be fetched with mysql_stmt_fetch() */
|
||||
}
|
||||
|
||||
@ -3292,6 +3496,40 @@ my_ulonglong STDCALL mysql_stmt_num_rows(MYSQL_STMT *stmt)
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
my_bool STDCALL mysql_stmt_free_result(MYSQL_STMT *stmt)
|
||||
{
|
||||
DBUG_ENTER("mysql_stmt_free_result");
|
||||
|
||||
DBUG_ASSERT(stmt != 0);
|
||||
|
||||
if ((int) stmt->state > (int) MYSQL_STMT_INIT_DONE)
|
||||
{
|
||||
MYSQL *mysql= stmt->mysql;
|
||||
|
||||
if (stmt->result)
|
||||
{
|
||||
/* Result buffered */
|
||||
mysql_free_result(stmt->result);
|
||||
stmt->result= 0;
|
||||
}
|
||||
else if (mysql && stmt->field_count
|
||||
&& (int) stmt->state > (int) MYSQL_STMT_PREPARE_DONE)
|
||||
{
|
||||
if (mysql->unbuffered_fetch_owner == &stmt->unbuffered_fetch_cancelled)
|
||||
mysql->unbuffered_fetch_owner= 0;
|
||||
if (mysql->status != MYSQL_STATUS_READY)
|
||||
{
|
||||
/* There is a result set and it belongs to this statement */
|
||||
flush_use_result(mysql);
|
||||
mysql->status= MYSQL_STATUS_READY;
|
||||
}
|
||||
}
|
||||
stmt->state= MYSQL_STMT_PREPARE_DONE;
|
||||
stmt->read_row_func= stmt_read_row_no_data;
|
||||
}
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
statement error handling and close
|
||||
*********************************************************************/
|
||||
@ -3300,82 +3538,55 @@ my_ulonglong STDCALL mysql_stmt_num_rows(MYSQL_STMT *stmt)
|
||||
Close the statement handle by freeing all alloced resources
|
||||
|
||||
SYNOPSIS
|
||||
mysql_stmt_free_result()
|
||||
mysql_stmt_close()
|
||||
stmt Statement handle
|
||||
skip_list Flag to indicate delete from list or not
|
||||
|
||||
RETURN VALUES
|
||||
0 ok
|
||||
1 error
|
||||
*/
|
||||
|
||||
my_bool STDCALL mysql_stmt_free_result(MYSQL_STMT *stmt)
|
||||
{
|
||||
MYSQL *mysql;
|
||||
DBUG_ENTER("mysql_stmt_free_result");
|
||||
|
||||
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;
|
||||
}
|
||||
mysql_free_result(stmt->result);
|
||||
stmt->result= 0;
|
||||
stmt->result_buffered= 0;
|
||||
stmt->current_row= 0;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
||||
my_bool stmt_close(MYSQL_STMT *stmt, my_bool skip_free)
|
||||
{
|
||||
MYSQL *mysql;
|
||||
DBUG_ENTER("stmt_close");
|
||||
|
||||
DBUG_ASSERT(stmt != 0);
|
||||
|
||||
if (!(mysql= stmt->mysql))
|
||||
{
|
||||
if (!skip_free)
|
||||
my_free((gptr) stmt, MYF(MY_WME));
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
mysql_stmt_free_result(stmt);
|
||||
if (stmt->state == MY_ST_PREPARE || stmt->state == MY_ST_EXECUTE)
|
||||
{
|
||||
char buff[4];
|
||||
int4store(buff, stmt->stmt_id);
|
||||
if (skip_free || simple_command(mysql, COM_CLOSE_STMT, buff, 4, 1))
|
||||
{
|
||||
set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno,
|
||||
mysql->net.sqlstate);
|
||||
stmt->mysql= NULL; /* connection isn't valid anymore */
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
}
|
||||
stmt->field_count= 0;
|
||||
free_root(&stmt->mem_root, MYF(0));
|
||||
mysql->stmts= list_delete(mysql->stmts, &stmt->list);
|
||||
mysql->status= MYSQL_STATUS_READY;
|
||||
my_free((gptr) stmt, MYF(MY_WME));
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
||||
my_bool STDCALL mysql_stmt_close(MYSQL_STMT *stmt)
|
||||
{
|
||||
return stmt_close(stmt, 0);
|
||||
MYSQL *mysql= stmt->mysql;
|
||||
int rc= 0;
|
||||
DBUG_ENTER("mysql_stmt_close");
|
||||
|
||||
mysql_free_result(stmt->result); /* if result is buffered */
|
||||
free_root(&stmt->mem_root, MYF(0));
|
||||
|
||||
if (mysql)
|
||||
{
|
||||
mysql->stmts= list_delete(mysql->stmts, &stmt->list);
|
||||
if ((int) stmt->state > (int) MYSQL_STMT_INIT_DONE)
|
||||
{
|
||||
char buff[4];
|
||||
|
||||
if (mysql->unbuffered_fetch_owner == &stmt->unbuffered_fetch_cancelled)
|
||||
mysql->unbuffered_fetch_owner= 0;
|
||||
if (mysql->status != MYSQL_STATUS_READY)
|
||||
{
|
||||
/*
|
||||
Flush result set of the connection. If it does not belong
|
||||
to this statement, set a warning.
|
||||
*/
|
||||
flush_use_result(mysql);
|
||||
if (mysql->unbuffered_fetch_owner)
|
||||
*mysql->unbuffered_fetch_owner= TRUE;
|
||||
mysql->status= MYSQL_STATUS_READY;
|
||||
}
|
||||
int4store(buff, stmt->stmt_id);
|
||||
if ((rc= simple_command(mysql, COM_CLOSE_STMT, buff, 4, 1)))
|
||||
{
|
||||
set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno,
|
||||
mysql->net.sqlstate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
my_free((gptr) stmt, MYF(MY_WME));
|
||||
|
||||
DBUG_RETURN(test(rc));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -3388,6 +3599,10 @@ my_bool STDCALL mysql_stmt_reset(MYSQL_STMT *stmt)
|
||||
MYSQL *mysql;
|
||||
DBUG_ENTER("mysql_stmt_reset");
|
||||
DBUG_ASSERT(stmt != 0);
|
||||
|
||||
/* If statement hasnt been prepared there is nothing to reset */
|
||||
if ((int) stmt->state < (int) MYSQL_STMT_PREPARE_DONE)
|
||||
DBUG_RETURN(0);
|
||||
|
||||
mysql= stmt->mysql->last_used_con;
|
||||
int4store(buff, stmt->stmt_id); /* Send stmt id to server */
|
||||
|
@ -78,11 +78,11 @@ select str_to_date(concat('15-01-2001',' 2:59:58.999'),
|
||||
concat('%d-%m-%Y',' ','%H:%i:%s.%f'));
|
||||
str_to_date(concat('15-01-2001',' 2:59:58.999'),
|
||||
concat('%d-%m-%Y',' ','%H:%i:%s.%f'))
|
||||
2001-01-15 02:59:58.000999
|
||||
2001-01-15 02:59:58.999000
|
||||
create table t1 (date char(30), format char(30) not null);
|
||||
insert into t1 values
|
||||
('2003-01-02 10:11:12', '%Y-%m-%d %H:%i:%S'),
|
||||
('03-01-02 8:11:2.123456', '%y-%m-%d %H:%i:%S'),
|
||||
('03-01-02 8:11:2.123456', '%y-%m-%d %H:%i:%S.%#'),
|
||||
('2003-01-02 10:11:12 PM', '%Y-%m-%d %h:%i:%S %p'),
|
||||
('2003-01-02 01:11:12.12345AM', '%Y-%m-%d %h:%i:%S.%f%p'),
|
||||
('2003-01-02 02:11:12.12345AM', '%Y-%m-%d %h:%i:%S.%f %p'),
|
||||
@ -106,16 +106,16 @@ insert into t1 values
|
||||
select date,format,str_to_date(date, format) as str_to_date from t1;
|
||||
date format str_to_date
|
||||
2003-01-02 10:11:12 %Y-%m-%d %H:%i:%S 2003-01-02 10:11:12
|
||||
03-01-02 8:11:2.123456 %y-%m-%d %H:%i:%S 2003-01-02 08:11:02
|
||||
03-01-02 8:11:2.123456 %y-%m-%d %H:%i:%S.%# 2003-01-02 08:11:02
|
||||
2003-01-02 10:11:12 PM %Y-%m-%d %h:%i:%S %p 2003-01-02 22:11:12
|
||||
2003-01-02 01:11:12.12345AM %Y-%m-%d %h:%i:%S.%f%p 2003-01-02 01:11:12.012345
|
||||
2003-01-02 02:11:12.12345AM %Y-%m-%d %h:%i:%S.%f %p 2003-01-02 02:11:12.012345
|
||||
2003-01-02 12:11:12.12345 am %Y-%m-%d %h:%i:%S.%f%p 2003-01-02 00:11:12.012345
|
||||
2003-01-02 01:11:12.12345AM %Y-%m-%d %h:%i:%S.%f%p 2003-01-02 01:11:12.123450
|
||||
2003-01-02 02:11:12.12345AM %Y-%m-%d %h:%i:%S.%f %p 2003-01-02 02:11:12.123450
|
||||
2003-01-02 12:11:12.12345 am %Y-%m-%d %h:%i:%S.%f%p 2003-01-02 00:11:12.123450
|
||||
2003-01-02 11:11:12Pm %Y-%m-%d %h:%i:%S%p 2003-01-02 23:11:12
|
||||
10:20:10 %H:%i:%s 0000-00-00 10:20:10
|
||||
10:20:10 %h:%i:%s.%f 0000-00-00 10:20:10
|
||||
10:20:10AM %h:%i:%s%p 0000-00-00 10:20:10
|
||||
10:20:10.44AM %h:%i:%s.%f%p 0000-00-00 10:20:10.000044
|
||||
10:20:10.44AM %h:%i:%s.%f%p 0000-00-00 10:20:10.440000
|
||||
15-01-2001 12:59:58 %d-%m-%Y %H:%i:%S 2001-01-15 12:59:58
|
||||
15 September 2001 %d %M %Y 2001-09-15 00:00:00
|
||||
15 SEPTEMB 2001 %d %M %Y 2001-09-15 00:00:00
|
||||
@ -130,16 +130,16 @@ Thursday 53 1998 %W %u %Y 1998-12-31 00:00:00
|
||||
select date,format,concat('',str_to_date(date, format)) as con from t1;
|
||||
date format con
|
||||
2003-01-02 10:11:12 %Y-%m-%d %H:%i:%S 2003-01-02 10:11:12
|
||||
03-01-02 8:11:2.123456 %y-%m-%d %H:%i:%S 2003-01-02 08:11:02
|
||||
03-01-02 8:11:2.123456 %y-%m-%d %H:%i:%S.%# 2003-01-02 08:11:02
|
||||
2003-01-02 10:11:12 PM %Y-%m-%d %h:%i:%S %p 2003-01-02 22:11:12
|
||||
2003-01-02 01:11:12.12345AM %Y-%m-%d %h:%i:%S.%f%p 2003-01-02 01:11:12.012345
|
||||
2003-01-02 02:11:12.12345AM %Y-%m-%d %h:%i:%S.%f %p 2003-01-02 02:11:12.012345
|
||||
2003-01-02 12:11:12.12345 am %Y-%m-%d %h:%i:%S.%f%p 2003-01-02 00:11:12.012345
|
||||
2003-01-02 01:11:12.12345AM %Y-%m-%d %h:%i:%S.%f%p 2003-01-02 01:11:12.123450
|
||||
2003-01-02 02:11:12.12345AM %Y-%m-%d %h:%i:%S.%f %p 2003-01-02 02:11:12.123450
|
||||
2003-01-02 12:11:12.12345 am %Y-%m-%d %h:%i:%S.%f%p 2003-01-02 00:11:12.123450
|
||||
2003-01-02 11:11:12Pm %Y-%m-%d %h:%i:%S%p 2003-01-02 23:11:12
|
||||
10:20:10 %H:%i:%s 0000-00-00 10:20:10
|
||||
10:20:10 %h:%i:%s.%f 0000-00-00 10:20:10
|
||||
10:20:10AM %h:%i:%s%p 0000-00-00 10:20:10
|
||||
10:20:10.44AM %h:%i:%s.%f%p 0000-00-00 10:20:10.000044
|
||||
10:20:10.44AM %h:%i:%s.%f%p 0000-00-00 10:20:10.440000
|
||||
15-01-2001 12:59:58 %d-%m-%Y %H:%i:%S 2001-01-15 12:59:58
|
||||
15 September 2001 %d %M %Y 2001-09-15 00:00:00
|
||||
15 SEPTEMB 2001 %d %M %Y 2001-09-15 00:00:00
|
||||
@ -154,16 +154,16 @@ Thursday 53 1998 %W %u %Y 1998-12-31 00:00:00
|
||||
select date,format,cast(str_to_date(date, format) as datetime) as datetime from t1;
|
||||
date format datetime
|
||||
2003-01-02 10:11:12 %Y-%m-%d %H:%i:%S 2003-01-02 10:11:12
|
||||
03-01-02 8:11:2.123456 %y-%m-%d %H:%i:%S 2003-01-02 08:11:02
|
||||
03-01-02 8:11:2.123456 %y-%m-%d %H:%i:%S.%# 2003-01-02 08:11:02
|
||||
2003-01-02 10:11:12 PM %Y-%m-%d %h:%i:%S %p 2003-01-02 22:11:12
|
||||
2003-01-02 01:11:12.12345AM %Y-%m-%d %h:%i:%S.%f%p 2003-01-02 01:11:12.012345
|
||||
2003-01-02 02:11:12.12345AM %Y-%m-%d %h:%i:%S.%f %p 2003-01-02 02:11:12.012345
|
||||
2003-01-02 12:11:12.12345 am %Y-%m-%d %h:%i:%S.%f%p 2003-01-02 00:11:12.012345
|
||||
2003-01-02 01:11:12.12345AM %Y-%m-%d %h:%i:%S.%f%p 2003-01-02 01:11:12.123450
|
||||
2003-01-02 02:11:12.12345AM %Y-%m-%d %h:%i:%S.%f %p 2003-01-02 02:11:12.123450
|
||||
2003-01-02 12:11:12.12345 am %Y-%m-%d %h:%i:%S.%f%p 2003-01-02 00:11:12.123450
|
||||
2003-01-02 11:11:12Pm %Y-%m-%d %h:%i:%S%p 2003-01-02 23:11:12
|
||||
10:20:10 %H:%i:%s 0000-00-00 10:20:10
|
||||
10:20:10 %h:%i:%s.%f 0000-00-00 10:20:10
|
||||
10:20:10AM %h:%i:%s%p 0000-00-00 10:20:10
|
||||
10:20:10.44AM %h:%i:%s.%f%p 0000-00-00 10:20:10.000044
|
||||
10:20:10.44AM %h:%i:%s.%f%p 0000-00-00 10:20:10.440000
|
||||
15-01-2001 12:59:58 %d-%m-%Y %H:%i:%S 2001-01-15 12:59:58
|
||||
15 September 2001 %d %M %Y 2001-09-15 00:00:00
|
||||
15 SEPTEMB 2001 %d %M %Y 2001-09-15 00:00:00
|
||||
@ -178,7 +178,7 @@ Thursday 53 1998 %W %u %Y 1998-12-31 00:00:00
|
||||
select date,format,DATE(str_to_date(date, format)) as date2 from t1;
|
||||
date format date2
|
||||
2003-01-02 10:11:12 %Y-%m-%d %H:%i:%S 2003-01-02
|
||||
03-01-02 8:11:2.123456 %y-%m-%d %H:%i:%S 2003-01-02
|
||||
03-01-02 8:11:2.123456 %y-%m-%d %H:%i:%S.%# 2003-01-02
|
||||
2003-01-02 10:11:12 PM %Y-%m-%d %h:%i:%S %p 2003-01-02
|
||||
2003-01-02 01:11:12.12345AM %Y-%m-%d %h:%i:%S.%f%p 2003-01-02
|
||||
2003-01-02 02:11:12.12345AM %Y-%m-%d %h:%i:%S.%f %p 2003-01-02
|
||||
@ -202,16 +202,16 @@ Thursday 53 1998 %W %u %Y 1998-12-31
|
||||
select date,format,TIME(str_to_date(date, format)) as time from t1;
|
||||
date format time
|
||||
2003-01-02 10:11:12 %Y-%m-%d %H:%i:%S 10:11:12
|
||||
03-01-02 8:11:2.123456 %y-%m-%d %H:%i:%S 08:11:02
|
||||
03-01-02 8:11:2.123456 %y-%m-%d %H:%i:%S.%# 08:11:02
|
||||
2003-01-02 10:11:12 PM %Y-%m-%d %h:%i:%S %p 22:11:12
|
||||
2003-01-02 01:11:12.12345AM %Y-%m-%d %h:%i:%S.%f%p 01:11:12.012345
|
||||
2003-01-02 02:11:12.12345AM %Y-%m-%d %h:%i:%S.%f %p 02:11:12.012345
|
||||
2003-01-02 12:11:12.12345 am %Y-%m-%d %h:%i:%S.%f%p 00:11:12.012345
|
||||
2003-01-02 01:11:12.12345AM %Y-%m-%d %h:%i:%S.%f%p 01:11:12.123450
|
||||
2003-01-02 02:11:12.12345AM %Y-%m-%d %h:%i:%S.%f %p 02:11:12.123450
|
||||
2003-01-02 12:11:12.12345 am %Y-%m-%d %h:%i:%S.%f%p 00:11:12.123450
|
||||
2003-01-02 11:11:12Pm %Y-%m-%d %h:%i:%S%p 23:11:12
|
||||
10:20:10 %H:%i:%s 10:20:10
|
||||
10:20:10 %h:%i:%s.%f 10:20:10
|
||||
10:20:10AM %h:%i:%s%p 10:20:10
|
||||
10:20:10.44AM %h:%i:%s.%f%p 10:20:10.000044
|
||||
10:20:10.44AM %h:%i:%s.%f%p 10:20:10.440000
|
||||
15-01-2001 12:59:58 %d-%m-%Y %H:%i:%S 12:59:58
|
||||
15 September 2001 %d %M %Y 00:00:00
|
||||
15 SEPTEMB 2001 %d %M %Y 00:00:00
|
||||
@ -226,16 +226,16 @@ Thursday 53 1998 %W %u %Y 00:00:00
|
||||
select date,format,concat(TIME(str_to_date(date, format))) as time2 from t1;
|
||||
date format time2
|
||||
2003-01-02 10:11:12 %Y-%m-%d %H:%i:%S 10:11:12
|
||||
03-01-02 8:11:2.123456 %y-%m-%d %H:%i:%S 08:11:02
|
||||
03-01-02 8:11:2.123456 %y-%m-%d %H:%i:%S.%# 08:11:02
|
||||
2003-01-02 10:11:12 PM %Y-%m-%d %h:%i:%S %p 22:11:12
|
||||
2003-01-02 01:11:12.12345AM %Y-%m-%d %h:%i:%S.%f%p 01:11:12.012345
|
||||
2003-01-02 02:11:12.12345AM %Y-%m-%d %h:%i:%S.%f %p 02:11:12.012345
|
||||
2003-01-02 12:11:12.12345 am %Y-%m-%d %h:%i:%S.%f%p 00:11:12.012345
|
||||
2003-01-02 01:11:12.12345AM %Y-%m-%d %h:%i:%S.%f%p 01:11:12.123450
|
||||
2003-01-02 02:11:12.12345AM %Y-%m-%d %h:%i:%S.%f %p 02:11:12.123450
|
||||
2003-01-02 12:11:12.12345 am %Y-%m-%d %h:%i:%S.%f%p 00:11:12.123450
|
||||
2003-01-02 11:11:12Pm %Y-%m-%d %h:%i:%S%p 23:11:12
|
||||
10:20:10 %H:%i:%s 10:20:10
|
||||
10:20:10 %h:%i:%s.%f 10:20:10
|
||||
10:20:10AM %h:%i:%s%p 10:20:10
|
||||
10:20:10.44AM %h:%i:%s.%f%p 10:20:10.000044
|
||||
10:20:10.44AM %h:%i:%s.%f%p 10:20:10.440000
|
||||
15-01-2001 12:59:58 %d-%m-%Y %H:%i:%S 12:59:58
|
||||
15 September 2001 %d %M %Y 00:00:00
|
||||
15 SEPTEMB 2001 %d %M %Y 00:00:00
|
||||
@ -302,11 +302,15 @@ date format str_to_date
|
||||
10:20:10AM %h:%i:%s 0000-00-00 10:20:10
|
||||
2003-01-02 10:11:12 %Y-%m-%d %h:%i:%S 2003-01-02 10:11:12
|
||||
03-01-02 10:11:12 PM %Y-%m-%d %h:%i:%S %p 0003-01-02 22:11:12
|
||||
Warnings:
|
||||
Note 1292 Truncated wrong string value: '10:20:10AM'
|
||||
select date,format,concat(str_to_date(date, format),'') as con from t1;
|
||||
date format con
|
||||
10:20:10AM %h:%i:%s 0000-00-00 10:20:10
|
||||
2003-01-02 10:11:12 %Y-%m-%d %h:%i:%S 2003-01-02 10:11:12
|
||||
03-01-02 10:11:12 PM %Y-%m-%d %h:%i:%S %p 0003-01-02 22:11:12
|
||||
Warnings:
|
||||
Note 1292 Truncated wrong string value: '10:20:10AM'
|
||||
drop table t1;
|
||||
select get_format(DATE, 'USA') as a;
|
||||
a
|
||||
@ -335,3 +339,56 @@ date_format(d,"%d")
|
||||
14
|
||||
14
|
||||
drop table t1;
|
||||
select str_to_date("2003-....01ABCD-02 10:11:12.0012", "%Y-%.%m%@-%d %H:%i:%S.%f") as a;
|
||||
a
|
||||
2003-01-02 10:11:12.001200
|
||||
create table t1 select str_to_date("2003-01-02 10:11:12.0012", "%Y-%m-%d %H:%i:%S.%f") as f1,
|
||||
str_to_date("10:11:12.0012", "%H:%i:%S.%f") as f2,
|
||||
str_to_date("2003-01-02", "%Y-%m-%d") as f3,
|
||||
str_to_date("02", "%d") as f4, str_to_date("02 10", "%d %H") as f5;
|
||||
describe t1;
|
||||
Field Type Null Key Default Extra
|
||||
f1 datetime YES NULL
|
||||
f2 time YES NULL
|
||||
f3 date YES NULL
|
||||
f4 date YES NULL
|
||||
f5 time YES NULL
|
||||
select * from t1;
|
||||
f1 f2 f3 f4 f5
|
||||
2003-01-02 10:11:12 10:11:12 2003-01-02 0000-00-02 58:00:00
|
||||
drop table t1;
|
||||
create table t1 select "02 10" as a, "%d %H" as b;
|
||||
select str_to_date(a,b) from t1;
|
||||
str_to_date(a,b)
|
||||
0000-00-02 10:00:00
|
||||
create table t2 select str_to_date(a,b) from t1;
|
||||
describe t2;
|
||||
Field Type Null Key Default Extra
|
||||
str_to_date(a,b) char(29) YES NULL
|
||||
select str_to_date("2003-01-02 10:11:12.0012", "%Y-%m-%d %H:%i:%S.%f") as f1,
|
||||
str_to_date("2003-01-02 10:11:12.0012", "%Y-%m-%d %H:%i:%S") as f2,
|
||||
str_to_date("2003-01-02", "%Y-%m-%d") as f3,
|
||||
str_to_date("02 10:11:12", "%d %H:%i:%S.%f") as f4,
|
||||
str_to_date("02 10:11:12", "%d %H:%i:%S") as f5,
|
||||
str_to_date("02 10", "%d %f") as f6;
|
||||
f1 f2 f3 f4 f5 f6
|
||||
2003-01-02 10:11:12.001200 2003-01-02 10:11:12 2003-01-02 58:11:12 58:11:12 48:00:00.100000
|
||||
Warnings:
|
||||
Note 1292 Truncated wrong datetime value: '2003-01-02 10:11:12.0012'
|
||||
drop table t1, t2;
|
||||
select str_to_date("2003-01-02 10:11:12.0012ABCD", "%Y-%m-%d %H:%i:%S.%f") as f1,
|
||||
addtime("-01:01:01.01 GGG", "-23:59:59.1") as f2,
|
||||
microsecond("1997-12-31 23:59:59.01XXXX") as f3;
|
||||
f1 f2 f3
|
||||
2003-01-02 10:11:12.001200 -25:01:00.110000 10000
|
||||
Warnings:
|
||||
Note 1292 Truncated wrong datetime value: '2003-01-02 10:11:12.0012ABCD'
|
||||
Note 1292 Truncated wrong time value: '-01:01:01.01 GG'
|
||||
Note 1292 Truncated wrong datetime value: '1997-12-31 23:59:59.01XXXX'
|
||||
select str_to_date("2003-04-05 g", "%Y-%m-%d") as f1,
|
||||
str_to_date("2003-04-05 10:11:12.101010234567", "%Y-%m-%d %H:%i:%S.%f") as f2;
|
||||
f1 f2
|
||||
2003-04-05 2003-04-05 10:11:12.101010
|
||||
Warnings:
|
||||
Note 1292 Truncated wrong date value: '2003-04-05 g'
|
||||
Note 1292 Truncated wrong datetime value: '2003-04-05 10:11:12.101010234567'
|
||||
|
@ -198,3 +198,18 @@ NULL NULL
|
||||
NULL NULL
|
||||
00:00:00 -24:00:00
|
||||
drop table t1, test;
|
||||
select addtime("-01:01:01.01", "-23:59:59.1") as a;
|
||||
a
|
||||
-25:01:00.110000
|
||||
select microsecond("1997-12-31 23:59:59.01") as a;
|
||||
a
|
||||
10000
|
||||
select microsecond(19971231235959.01) as a;
|
||||
a
|
||||
10000
|
||||
select date_add("1997-12-31",INTERVAL "10.09" SECOND_MICROSECOND) as a;
|
||||
a
|
||||
1997-12-31 00:00:10.090000
|
||||
select str_to_date("2003-01-02 10:11:12.0012", "%Y-%m-%d %H:%i:%S.%f");
|
||||
str_to_date("2003-01-02 10:11:12.0012", "%Y-%m-%d %H:%i:%S.%f")
|
||||
2003-01-02 10:11:12.001200
|
||||
|
@ -624,6 +624,9 @@ Note 1003 select high_priority md5(_latin1'hello') AS `md5('hello')`,sha(_latin1
|
||||
SELECT lpad(12345, 5, "#");
|
||||
lpad(12345, 5, "#")
|
||||
12345
|
||||
SELECT conv(71, 10, 36), conv('1Z', 36, 10);
|
||||
conv(71, 10, 36) conv('1Z', 36, 10)
|
||||
1Z 71
|
||||
create table t1 (id int(1), str varchar(10)) DEFAULT CHARSET=utf8;
|
||||
insert into t1 values (1,'aaaaaaaaaa'), (2,'bbbbbbbbbb');
|
||||
create table t2 (id int(1), str varchar(10)) DEFAULT CHARSET=utf8;
|
||||
|
@ -506,17 +506,32 @@ last_day('2001-01-01 01:01:01') as f5, last_day(NULL),
|
||||
last_day('2001-02-12');
|
||||
f1 f2 f3 f4 f5 last_day(NULL) last_day('2001-02-12')
|
||||
2000-02-29 2002-12-31 NULL 2003-04-30 2001-01-31 NULL 2001-02-28
|
||||
create table t1 select last_day('2000-02-05') as a;
|
||||
create table t1 select last_day('2000-02-05') as a,
|
||||
from_days(to_days("960101")) as b;
|
||||
describe t1;
|
||||
Field Type Null Key Default Extra
|
||||
a date 0000-00-00
|
||||
b date YES NULL
|
||||
select * from t1;
|
||||
a
|
||||
2000-02-29
|
||||
a b
|
||||
2000-02-29 1996-01-01
|
||||
drop table t1;
|
||||
select last_day('2000-02-05');
|
||||
last_day('2000-02-05')
|
||||
2000-02-29
|
||||
select last_day('2000-02-05') as a,
|
||||
from_days(to_days("960101")) as b;
|
||||
a b
|
||||
2000-02-29 1996-01-01
|
||||
select date_add(last_day("1997-12-1"), INTERVAL 1 DAY);
|
||||
date_add(last_day("1997-12-1"), INTERVAL 1 DAY)
|
||||
1998-01-01
|
||||
select length(last_day("1997-12-1"));
|
||||
length(last_day("1997-12-1"))
|
||||
10
|
||||
select last_day("1997-12-1")+0;
|
||||
last_day("1997-12-1")+0
|
||||
19971231
|
||||
select last_day("1997-12-1")+0.0;
|
||||
last_day("1997-12-1")+0.0
|
||||
19971231.0
|
||||
select strcmp(date_sub(localtimestamp(), interval 3 hour), utc_timestamp())=0;
|
||||
strcmp(date_sub(localtimestamp(), interval 3 hour), utc_timestamp())=0
|
||||
1
|
||||
|
@ -25,9 +25,11 @@ t
|
||||
36:30:31
|
||||
insert into t1 values("10.22.22"),(1234567),(123456789),(123456789.10),("10 22:22"),("12.45a");
|
||||
Warnings:
|
||||
Note 1292 Truncated wrong time value: '10.22.22'
|
||||
Warning 1264 Data truncated, out of range for column 't' at row 2
|
||||
Warning 1264 Data truncated, out of range for column 't' at row 3
|
||||
Warning 1264 Data truncated, out of range for column 't' at row 4
|
||||
Note 1292 Truncated wrong time value: '12.45a'
|
||||
select * from t1;
|
||||
t
|
||||
10:22:33
|
||||
|
@ -124,7 +124,7 @@ select str_to_date(concat('15-01-2001',' 2:59:58.999'),
|
||||
create table t1 (date char(30), format char(30) not null);
|
||||
insert into t1 values
|
||||
('2003-01-02 10:11:12', '%Y-%m-%d %H:%i:%S'),
|
||||
('03-01-02 8:11:2.123456', '%y-%m-%d %H:%i:%S'),
|
||||
('03-01-02 8:11:2.123456', '%y-%m-%d %H:%i:%S.%#'),
|
||||
('2003-01-02 10:11:12 PM', '%Y-%m-%d %h:%i:%S %p'),
|
||||
('2003-01-02 01:11:12.12345AM', '%Y-%m-%d %h:%i:%S.%f%p'),
|
||||
('2003-01-02 02:11:12.12345AM', '%Y-%m-%d %h:%i:%S.%f %p'),
|
||||
@ -209,3 +209,32 @@ create table t1 (d date);
|
||||
insert into t1 values ('2004-07-14'),('2005-07-14');
|
||||
select date_format(d,"%d") from t1 order by 1;
|
||||
drop table t1;
|
||||
|
||||
select str_to_date("2003-....01ABCD-02 10:11:12.0012", "%Y-%.%m%@-%d %H:%i:%S.%f") as a;
|
||||
|
||||
|
||||
create table t1 select str_to_date("2003-01-02 10:11:12.0012", "%Y-%m-%d %H:%i:%S.%f") as f1,
|
||||
str_to_date("10:11:12.0012", "%H:%i:%S.%f") as f2,
|
||||
str_to_date("2003-01-02", "%Y-%m-%d") as f3,
|
||||
str_to_date("02", "%d") as f4, str_to_date("02 10", "%d %H") as f5;
|
||||
describe t1;
|
||||
select * from t1;
|
||||
drop table t1;
|
||||
|
||||
create table t1 select "02 10" as a, "%d %H" as b;
|
||||
select str_to_date(a,b) from t1;
|
||||
create table t2 select str_to_date(a,b) from t1;
|
||||
describe t2;
|
||||
select str_to_date("2003-01-02 10:11:12.0012", "%Y-%m-%d %H:%i:%S.%f") as f1,
|
||||
str_to_date("2003-01-02 10:11:12.0012", "%Y-%m-%d %H:%i:%S") as f2,
|
||||
str_to_date("2003-01-02", "%Y-%m-%d") as f3,
|
||||
str_to_date("02 10:11:12", "%d %H:%i:%S.%f") as f4,
|
||||
str_to_date("02 10:11:12", "%d %H:%i:%S") as f5,
|
||||
str_to_date("02 10", "%d %f") as f6;
|
||||
drop table t1, t2;
|
||||
select str_to_date("2003-01-02 10:11:12.0012ABCD", "%Y-%m-%d %H:%i:%S.%f") as f1,
|
||||
addtime("-01:01:01.01 GGG", "-23:59:59.1") as f2,
|
||||
microsecond("1997-12-31 23:59:59.01XXXX") as f3;
|
||||
|
||||
select str_to_date("2003-04-05 g", "%Y-%m-%d") as f1,
|
||||
str_to_date("2003-04-05 10:11:12.101010234567", "%Y-%m-%d %H:%i:%S.%f") as f2;
|
||||
|
@ -97,3 +97,9 @@ SELECT ADDTIME(t1,t2) As ttt, ADDTIME(t2, t3) As qqq from test;
|
||||
SELECT TIMEDIFF(t1,t4) As ttt, TIMEDIFF(t2, t3) As qqq from test;
|
||||
|
||||
drop table t1, test;
|
||||
|
||||
select addtime("-01:01:01.01", "-23:59:59.1") as a;
|
||||
select microsecond("1997-12-31 23:59:59.01") as a;
|
||||
select microsecond(19971231235959.01) as a;
|
||||
select date_add("1997-12-31",INTERVAL "10.09" SECOND_MICROSECOND) as a;
|
||||
select str_to_date("2003-01-02 10:11:12.0012", "%Y-%m-%d %H:%i:%S.%f");
|
||||
|
@ -361,6 +361,13 @@ explain extended select md5('hello'), sha('abc'), sha1('abc'), soundex(''), 'moo
|
||||
|
||||
SELECT lpad(12345, 5, "#");
|
||||
|
||||
#
|
||||
# Bug #2972
|
||||
#
|
||||
|
||||
SELECT conv(71, 10, 36), conv('1Z', 36, 10);
|
||||
|
||||
|
||||
|
||||
#
|
||||
# Bug #3089
|
||||
|
@ -249,12 +249,18 @@ select last_day('2000-02-05') as f1, last_day('2002-12-31') as f2,
|
||||
last_day('2001-01-01 01:01:01') as f5, last_day(NULL),
|
||||
last_day('2001-02-12');
|
||||
|
||||
create table t1 select last_day('2000-02-05') as a;
|
||||
create table t1 select last_day('2000-02-05') as a,
|
||||
from_days(to_days("960101")) as b;
|
||||
describe t1;
|
||||
select * from t1;
|
||||
drop table t1;
|
||||
select last_day('2000-02-05');
|
||||
select last_day('2000-02-05') as a,
|
||||
from_days(to_days("960101")) as b;
|
||||
|
||||
select date_add(last_day("1997-12-1"), INTERVAL 1 DAY);
|
||||
select length(last_day("1997-12-1"));
|
||||
select last_day("1997-12-1")+0;
|
||||
select last_day("1997-12-1")+0.0;
|
||||
|
||||
# Test SAPDB UTC_% functions. This part is TZ dependant (It is supposed that
|
||||
# TZ variable set to GMT-3
|
||||
|
@ -712,6 +712,34 @@ void set_mysql_error(MYSQL *mysql, int errcode, const char *sqlstate)
|
||||
net->last_errno= errcode;
|
||||
strmov(net->last_error, ER(errcode));
|
||||
strmov(net->sqlstate, sqlstate);
|
||||
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
/*
|
||||
Flush result set sent from server
|
||||
*/
|
||||
|
||||
void flush_use_result(MYSQL *mysql)
|
||||
{
|
||||
/* 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)
|
||||
{
|
||||
if (protocol_41(mysql))
|
||||
{
|
||||
char *pos= (char*) mysql->net.read_pos;
|
||||
mysql->warning_count=uint2korr(pos); pos+=2;
|
||||
mysql->server_status=uint2korr(pos); pos+=2;
|
||||
}
|
||||
break; /* End of data */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -752,26 +780,16 @@ mysql_free_result(MYSQL_RES *result)
|
||||
DBUG_PRINT("enter",("mysql_res: %lx",result));
|
||||
if (result)
|
||||
{
|
||||
if (result->handle && result->handle->status == MYSQL_STATUS_USE_RESULT)
|
||||
MYSQL *mysql= result->handle;
|
||||
if (mysql)
|
||||
{
|
||||
DBUG_PRINT("warning",("Not all rows in set where read; Ignoring rows"));
|
||||
for (;;)
|
||||
if (mysql->unbuffered_fetch_owner == &result->unbuffered_fetch_cancelled)
|
||||
mysql->unbuffered_fetch_owner= 0;
|
||||
if (mysql->status == MYSQL_STATUS_USE_RESULT)
|
||||
{
|
||||
ulong pkt_len;
|
||||
if ((pkt_len=net_safe_read(result->handle)) == packet_error)
|
||||
break;
|
||||
if (pkt_len <= 8 && result->handle->net.read_pos[0] == 254)
|
||||
{
|
||||
if (protocol_41(result->handle))
|
||||
{
|
||||
char *pos= (char*) result->handle->net.read_pos;
|
||||
result->handle->warning_count=uint2korr(pos); pos+=2;
|
||||
result->handle->server_status=uint2korr(pos); pos+=2;
|
||||
}
|
||||
break; /* End of data */
|
||||
}
|
||||
flush_use_result(mysql);
|
||||
mysql->status=MYSQL_STATUS_READY;
|
||||
}
|
||||
result->handle->status=MYSQL_STATUS_READY;
|
||||
}
|
||||
free_rows(result->data);
|
||||
if (result->fields)
|
||||
@ -2177,12 +2195,13 @@ void STDCALL mysql_close(MYSQL *mysql)
|
||||
#ifdef MYSQL_CLIENT
|
||||
if (mysql->stmts)
|
||||
{
|
||||
/* Free any open prepared statements */
|
||||
LIST *element, *next_element;
|
||||
for (element= mysql->stmts; element; element= next_element)
|
||||
/* Reset connection handle in all prepared statements. */
|
||||
LIST *element;
|
||||
for (element= mysql->stmts; element; element= element->next)
|
||||
{
|
||||
next_element= element->next;
|
||||
stmt_close((MYSQL_STMT *)element->data, 1);
|
||||
MYSQL_STMT *stmt= (MYSQL_STMT *) element->data;
|
||||
stmt->mysql= 0;
|
||||
/* No need to call list_delete for statement here */
|
||||
}
|
||||
mysql->stmts= 0;
|
||||
}
|
||||
@ -2372,9 +2391,10 @@ MYSQL_RES * STDCALL mysql_store_result(MYSQL *mysql)
|
||||
result->fields= mysql->fields;
|
||||
result->field_alloc= mysql->field_alloc;
|
||||
result->field_count= mysql->field_count;
|
||||
result->current_field=0;
|
||||
result->current_row=0; /* Must do a fetch first */
|
||||
/* The rest of result members is bzeroed in malloc */
|
||||
mysql->fields=0; /* fields is now in result */
|
||||
/* just in case this was mistakenly called after mysql_stmt_execute() */
|
||||
mysql->unbuffered_fetch_owner= 0;
|
||||
DBUG_RETURN(result); /* Data fetched */
|
||||
}
|
||||
|
||||
@ -2423,6 +2443,7 @@ static MYSQL_RES * cli_use_result(MYSQL *mysql)
|
||||
result->current_row= 0;
|
||||
mysql->fields=0; /* fields is now in result */
|
||||
mysql->status=MYSQL_STATUS_USE_RESULT;
|
||||
mysql->unbuffered_fetch_owner= &result->unbuffered_fetch_cancelled;
|
||||
DBUG_RETURN(result); /* Data is read to be fetched */
|
||||
}
|
||||
|
||||
@ -2439,19 +2460,30 @@ mysql_fetch_row(MYSQL_RES *res)
|
||||
{ /* Unbufferred fetch */
|
||||
if (!res->eof)
|
||||
{
|
||||
if (!(read_one_row(res->handle,res->field_count,res->row, res->lengths)))
|
||||
MYSQL *mysql= res->handle;
|
||||
if (mysql->status != MYSQL_STATUS_USE_RESULT)
|
||||
{
|
||||
set_mysql_error(mysql,
|
||||
res->unbuffered_fetch_cancelled ?
|
||||
CR_FETCH_CANCELLED : CR_COMMANDS_OUT_OF_SYNC,
|
||||
unknown_sqlstate);
|
||||
}
|
||||
else if (!(read_one_row(mysql, res->field_count, res->row, res->lengths)))
|
||||
{
|
||||
res->row_count++;
|
||||
DBUG_RETURN(res->current_row=res->row);
|
||||
}
|
||||
else
|
||||
{
|
||||
DBUG_PRINT("info",("end of data"));
|
||||
res->eof=1;
|
||||
res->handle->status=MYSQL_STATUS_READY;
|
||||
/* Don't clear handle in mysql_free_results */
|
||||
res->handle=0;
|
||||
}
|
||||
DBUG_PRINT("info",("end of data"));
|
||||
res->eof=1;
|
||||
mysql->status=MYSQL_STATUS_READY;
|
||||
/*
|
||||
Reset only if owner points to us: there is a chance that somebody
|
||||
started new query after mysql_stmt_close():
|
||||
*/
|
||||
if (mysql->unbuffered_fetch_owner == &res->unbuffered_fetch_cancelled)
|
||||
mysql->unbuffered_fetch_owner= 0;
|
||||
/* Don't clear handle in mysql_free_result */
|
||||
res->handle=0;
|
||||
}
|
||||
DBUG_RETURN((MYSQL_ROW) NULL);
|
||||
}
|
||||
|
@ -24,7 +24,7 @@
|
||||
enum Gis_read_stream::enum_tok_types Gis_read_stream::get_next_toc_type()
|
||||
{
|
||||
skip_space();
|
||||
if (!*m_cur)
|
||||
if (m_cur >= m_limit)
|
||||
return eostream;
|
||||
if (my_isvar_start(&my_charset_bin, *m_cur))
|
||||
return word;
|
||||
@ -53,7 +53,7 @@ bool Gis_read_stream::get_next_word(LEX_STRING *res)
|
||||
my_isvar() is a macro that would cause side effects
|
||||
*/
|
||||
m_cur++;
|
||||
while (my_isvar(&my_charset_bin, *m_cur))
|
||||
while ((m_cur < m_limit) && my_isvar(&my_charset_bin, *m_cur))
|
||||
m_cur++;
|
||||
|
||||
res->length= (uint32) (m_cur - res->str);
|
||||
@ -71,16 +71,21 @@ bool Gis_read_stream::get_next_word(LEX_STRING *res)
|
||||
bool Gis_read_stream::get_next_number(double *d)
|
||||
{
|
||||
char *endptr;
|
||||
int err;
|
||||
|
||||
skip_space();
|
||||
/* The following will also test for end \0 */
|
||||
if ((*m_cur < '0' || *m_cur > '9') && *m_cur != '-' && *m_cur != '+')
|
||||
|
||||
if ((m_cur >= m_limit) ||
|
||||
(*m_cur < '0' || *m_cur > '9') && *m_cur != '-' && *m_cur != '+')
|
||||
{
|
||||
set_error_msg("Numeric constant expected");
|
||||
return 1;
|
||||
}
|
||||
|
||||
*d = my_strtod(m_cur, &endptr);
|
||||
*d = my_strntod(m_charset, (char *)m_cur,
|
||||
m_limit-m_cur, &endptr, &err);
|
||||
if (err)
|
||||
return 1;
|
||||
if (endptr)
|
||||
m_cur = endptr;
|
||||
return 0;
|
||||
@ -90,7 +95,7 @@ bool Gis_read_stream::get_next_number(double *d)
|
||||
bool Gis_read_stream::check_next_symbol(char symbol)
|
||||
{
|
||||
skip_space();
|
||||
if (*m_cur != symbol)
|
||||
if ((m_cur >= m_limit) || (*m_cur != symbol))
|
||||
{
|
||||
char buff[32];
|
||||
strmov(buff, "'?' expected");
|
||||
|
@ -29,8 +29,8 @@ public:
|
||||
comma
|
||||
};
|
||||
|
||||
Gis_read_stream(const char *buffer, int size)
|
||||
:m_cur(buffer), m_limit(buffer + size), m_err_msg(NULL)
|
||||
Gis_read_stream(CHARSET_INFO *charset, const char *buffer, int size)
|
||||
:m_cur(buffer), m_limit(buffer + size), m_err_msg(NULL), m_charset(charset)
|
||||
{}
|
||||
Gis_read_stream(): m_cur(NullS), m_limit(NullS), m_err_msg(NullS)
|
||||
{}
|
||||
@ -46,14 +46,14 @@ public:
|
||||
|
||||
inline void skip_space()
|
||||
{
|
||||
while (my_isspace(&my_charset_latin1, *m_cur))
|
||||
while ((m_cur < m_limit) && my_isspace(&my_charset_latin1, *m_cur))
|
||||
m_cur++;
|
||||
}
|
||||
/* Skip next character, if match. Return 1 if no match */
|
||||
inline bool skip_char(char skip)
|
||||
{
|
||||
skip_space();
|
||||
if (*m_cur != skip)
|
||||
if ((m_cur >= m_limit) || *m_cur != skip)
|
||||
return 1; /* Didn't find char */
|
||||
m_cur++;
|
||||
return 0;
|
||||
@ -72,4 +72,5 @@ protected:
|
||||
const char *m_cur;
|
||||
const char *m_limit;
|
||||
char *m_err_msg;
|
||||
CHARSET_INFO *m_charset;
|
||||
};
|
||||
|
28
sql/item.cc
28
sql/item.cc
@ -517,7 +517,33 @@ String *Item_null::val_str(String *str)
|
||||
{ null_value=1; return 0;}
|
||||
|
||||
|
||||
/* Item_param related */
|
||||
/*********************** Item_param related ******************************/
|
||||
|
||||
/*
|
||||
Default function of Item_param::set_param_func, so in case
|
||||
of malformed packet the server won't SIGSEGV
|
||||
*/
|
||||
|
||||
static void
|
||||
default_set_param_func(Item_param *param,
|
||||
uchar **pos __attribute__((unused)),
|
||||
ulong len __attribute__((unused)))
|
||||
{
|
||||
param->set_null();
|
||||
}
|
||||
|
||||
Item_param::Item_param(unsigned position) :
|
||||
value_is_set(FALSE),
|
||||
item_result_type(STRING_RESULT),
|
||||
item_type(STRING_ITEM),
|
||||
item_is_time(FALSE),
|
||||
long_data_supplied(FALSE),
|
||||
pos_in_query(position),
|
||||
set_param_func(default_set_param_func)
|
||||
{
|
||||
name= (char*) "?";
|
||||
}
|
||||
|
||||
void Item_param::set_null()
|
||||
{
|
||||
DBUG_ENTER("Item_param::set_null");
|
||||
|
24
sql/item.h
24
sql/item.h
@ -348,16 +348,7 @@ public:
|
||||
bool long_data_supplied;
|
||||
uint pos_in_query;
|
||||
|
||||
Item_param(uint position)
|
||||
{
|
||||
name= (char*) "?";
|
||||
pos_in_query= position;
|
||||
item_type= STRING_ITEM;
|
||||
item_result_type = STRING_RESULT;
|
||||
item_is_time= false;
|
||||
long_data_supplied= false;
|
||||
value_is_set= 0;
|
||||
}
|
||||
Item_param(uint position);
|
||||
enum Type type() const { return item_type; }
|
||||
double val();
|
||||
longlong val_int();
|
||||
@ -374,11 +365,14 @@ public:
|
||||
void set_time(TIME *tm, timestamp_type type);
|
||||
bool get_time(TIME *tm);
|
||||
void reset() {}
|
||||
#ifndef EMBEDDED_LIBRARY
|
||||
void (*set_param_func)(Item_param *param, uchar **pos);
|
||||
#else
|
||||
void (*set_param_func)(Item_param *param, uchar **pos, ulong data_len);
|
||||
#endif
|
||||
/*
|
||||
Assign placeholder value from bind data.
|
||||
Note, that 'len' has different semantics in embedded library (as we
|
||||
don't need to check that packet is not broken there). See
|
||||
sql_prepare.cc for details.
|
||||
*/
|
||||
void (*set_param_func)(Item_param *param, uchar **pos, ulong len);
|
||||
|
||||
enum Item_result result_type () const
|
||||
{ return item_result_type; }
|
||||
String *query_val_str(String *str);
|
||||
|
@ -1728,7 +1728,7 @@ bool udf_handler::get_arguments() { return 0; }
|
||||
pthread_mutex_t LOCK_user_locks;
|
||||
static HASH hash_user_locks;
|
||||
|
||||
class ULL
|
||||
class User_level_lock
|
||||
{
|
||||
char *key;
|
||||
uint key_length;
|
||||
@ -1740,7 +1740,7 @@ public:
|
||||
pthread_t thread;
|
||||
ulong thread_id;
|
||||
|
||||
ULL(const char *key_arg,uint length, ulong id)
|
||||
User_level_lock(const char *key_arg,uint length, ulong id)
|
||||
:key_length(length),count(1),locked(1), thread_id(id)
|
||||
{
|
||||
key=(char*) my_memdup((byte*) key_arg,length,MYF(0));
|
||||
@ -1754,7 +1754,7 @@ public:
|
||||
}
|
||||
}
|
||||
}
|
||||
~ULL()
|
||||
~User_level_lock()
|
||||
{
|
||||
if (key)
|
||||
{
|
||||
@ -1764,11 +1764,12 @@ public:
|
||||
pthread_cond_destroy(&cond);
|
||||
}
|
||||
inline bool initialized() { return key != 0; }
|
||||
friend void item_user_lock_release(ULL *ull);
|
||||
friend char *ull_get_key(const ULL *ull,uint *length,my_bool not_used);
|
||||
friend void item_user_lock_release(User_level_lock *ull);
|
||||
friend char *ull_get_key(const User_level_lock *ull, uint *length,
|
||||
my_bool not_used);
|
||||
};
|
||||
|
||||
char *ull_get_key(const ULL *ull,uint *length,
|
||||
char *ull_get_key(const User_level_lock *ull, uint *length,
|
||||
my_bool not_used __attribute__((unused)))
|
||||
{
|
||||
*length=(uint) ull->key_length;
|
||||
@ -1796,7 +1797,7 @@ void item_user_lock_free(void)
|
||||
}
|
||||
}
|
||||
|
||||
void item_user_lock_release(ULL *ull)
|
||||
void item_user_lock_release(User_level_lock *ull)
|
||||
{
|
||||
ull->locked=0;
|
||||
if (mysql_bin_log.is_open())
|
||||
@ -1852,7 +1853,7 @@ longlong Item_master_pos_wait::val_int()
|
||||
void debug_sync_point(const char* lock_name, uint lock_timeout)
|
||||
{
|
||||
THD* thd=current_thd;
|
||||
ULL* ull;
|
||||
User_level_lock* ull;
|
||||
struct timespec abstime;
|
||||
int lock_name_len,error=0;
|
||||
lock_name_len=strlen(lock_name);
|
||||
@ -1870,7 +1871,7 @@ void debug_sync_point(const char* lock_name, uint lock_timeout)
|
||||
this case, we will not be waiting, but rather, just waste CPU and
|
||||
memory on the whole deal
|
||||
*/
|
||||
if (!(ull= ((ULL*) hash_search(&hash_user_locks,lock_name,
|
||||
if (!(ull= ((User_level_lock*) hash_search(&hash_user_locks, lock_name,
|
||||
lock_name_len))))
|
||||
{
|
||||
pthread_mutex_unlock(&LOCK_user_locks);
|
||||
@ -1931,7 +1932,7 @@ longlong Item_func_get_lock::val_int()
|
||||
longlong timeout=args[1]->val_int();
|
||||
struct timespec abstime;
|
||||
THD *thd=current_thd;
|
||||
ULL *ull;
|
||||
User_level_lock *ull;
|
||||
int error=0;
|
||||
|
||||
pthread_mutex_lock(&LOCK_user_locks);
|
||||
@ -1950,10 +1951,11 @@ longlong Item_func_get_lock::val_int()
|
||||
thd->ull=0;
|
||||
}
|
||||
|
||||
if (!(ull= ((ULL*) hash_search(&hash_user_locks,(byte*) res->ptr(),
|
||||
res->length()))))
|
||||
if (!(ull= ((User_level_lock *) hash_search(&hash_user_locks,
|
||||
(byte*) res->ptr(),
|
||||
res->length()))))
|
||||
{
|
||||
ull=new ULL(res->ptr(),res->length(), thd->thread_id);
|
||||
ull=new User_level_lock(res->ptr(),res->length(), thd->thread_id);
|
||||
if (!ull || !ull->initialized())
|
||||
{
|
||||
delete ull;
|
||||
@ -2022,7 +2024,7 @@ longlong Item_func_get_lock::val_int()
|
||||
longlong Item_func_release_lock::val_int()
|
||||
{
|
||||
String *res=args[0]->val_str(&value);
|
||||
ULL *ull;
|
||||
User_level_lock *ull;
|
||||
longlong result;
|
||||
if (!res || !res->length())
|
||||
{
|
||||
@ -2033,8 +2035,9 @@ longlong Item_func_release_lock::val_int()
|
||||
|
||||
result=0;
|
||||
pthread_mutex_lock(&LOCK_user_locks);
|
||||
if (!(ull= ((ULL*) hash_search(&hash_user_locks,(const byte*) res->ptr(),
|
||||
res->length()))))
|
||||
if (!(ull= ((User_level_lock*) hash_search(&hash_user_locks,
|
||||
(const byte*) res->ptr(),
|
||||
res->length()))))
|
||||
{
|
||||
null_value=1;
|
||||
}
|
||||
@ -3041,7 +3044,7 @@ longlong Item_func_is_free_lock::val_int()
|
||||
{
|
||||
String *res=args[0]->val_str(&value);
|
||||
THD *thd=current_thd;
|
||||
ULL *ull;
|
||||
User_level_lock *ull;
|
||||
|
||||
null_value=0;
|
||||
if (!res || !res->length())
|
||||
@ -3051,7 +3054,7 @@ longlong Item_func_is_free_lock::val_int()
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&LOCK_user_locks);
|
||||
ull= (ULL*) hash_search(&hash_user_locks,(byte*) res->ptr(),
|
||||
ull= (User_level_lock *) hash_search(&hash_user_locks, (byte*) res->ptr(),
|
||||
res->length());
|
||||
pthread_mutex_unlock(&LOCK_user_locks);
|
||||
if (!ull || !ull->locked)
|
||||
@ -3063,14 +3066,14 @@ longlong Item_func_is_used_lock::val_int()
|
||||
{
|
||||
String *res=args[0]->val_str(&value);
|
||||
THD *thd=current_thd;
|
||||
ULL *ull;
|
||||
User_level_lock *ull;
|
||||
|
||||
null_value=1;
|
||||
if (!res || !res->length())
|
||||
return 0;
|
||||
|
||||
pthread_mutex_lock(&LOCK_user_locks);
|
||||
ull= (ULL*) hash_search(&hash_user_locks,(byte*) res->ptr(),
|
||||
ull= (User_level_lock *) hash_search(&hash_user_locks, (byte*) res->ptr(),
|
||||
res->length());
|
||||
pthread_mutex_unlock(&LOCK_user_locks);
|
||||
if (!ull || !ull->locked)
|
||||
|
@ -864,9 +864,9 @@ public:
|
||||
** User level locks
|
||||
*/
|
||||
|
||||
class ULL;
|
||||
class User_level_lock;
|
||||
void item_user_lock_init(void);
|
||||
void item_user_lock_release(ULL *ull);
|
||||
void item_user_lock_release(User_level_lock *ull);
|
||||
void item_user_lock_free(void);
|
||||
|
||||
class Item_func_get_lock :public Item_int_func
|
||||
|
@ -31,10 +31,13 @@
|
||||
String *Item_func_geometry_from_text::val_str(String *str)
|
||||
{
|
||||
Geometry_buffer buffer;
|
||||
Geometry *geom;
|
||||
String arg_val;
|
||||
String *wkt= args[0]->val_str(&arg_val);
|
||||
Gis_read_stream trs(wkt->c_ptr(), wkt->length());
|
||||
|
||||
if ((null_value= args[0]->null_value))
|
||||
return 0;
|
||||
|
||||
Gis_read_stream trs(wkt->charset(), wkt->ptr(), wkt->length());
|
||||
uint32 srid= 0;
|
||||
|
||||
if ((arg_count == 2) && !args[1]->null_value)
|
||||
@ -44,8 +47,7 @@ String *Item_func_geometry_from_text::val_str(String *str)
|
||||
return 0;
|
||||
str->length(0);
|
||||
str->q_append(srid);
|
||||
if ((null_value=(args[0]->null_value ||
|
||||
!(geom= Geometry::create_from_wkt(&buffer, &trs, str, 0)))))
|
||||
if ((null_value= !Geometry::create_from_wkt(&buffer, &trs, str, 0)))
|
||||
return 0;
|
||||
return str;
|
||||
}
|
||||
|
@ -2241,7 +2241,7 @@ String *Item_func_hex::val_str(String *str)
|
||||
return &tmp_value;
|
||||
}
|
||||
|
||||
int inline hexchar_to_int(char c)
|
||||
inline int hexchar_to_int(char c)
|
||||
{
|
||||
if (c <= '9' && c >= '0')
|
||||
return c-'0';
|
||||
@ -2731,7 +2731,7 @@ String *Item_func_uuid::val_str(String *str)
|
||||
randominit() here
|
||||
*/
|
||||
randominit(&uuid_rand, tmp + (ulong)current_thd, tmp + query_id);
|
||||
for (i=0; i < sizeof(mac); i++)
|
||||
for (i=0; i < (int)sizeof(mac); i++)
|
||||
mac[i]=(uchar)(my_rnd(&uuid_rand)*255);
|
||||
}
|
||||
s=clock_seq_and_node_str+sizeof(clock_seq_and_node_str)-1;
|
||||
|
@ -48,11 +48,6 @@ TYPELIB day_names_typelib=
|
||||
{ array_elements(day_names)-1,"", day_names};
|
||||
|
||||
|
||||
enum date_time_format_types
|
||||
{
|
||||
TIME_ONLY= 0, TIME_MICROSECOND, DATE_ONLY, DATE_TIME, DATE_TIME_MICROSECOND
|
||||
};
|
||||
|
||||
/*
|
||||
OPTIMIZATION TODO:
|
||||
- Replace the switch with a function that should be called for each
|
||||
@ -128,6 +123,9 @@ static bool make_datetime(date_time_format_types format, TIME *ltime,
|
||||
val String to decode
|
||||
length Length of string
|
||||
l_time Store result here
|
||||
cached_timestamp_type
|
||||
It uses to get an appropriate warning
|
||||
in the case when the value is truncated.
|
||||
|
||||
RETURN
|
||||
0 ok
|
||||
@ -135,7 +133,8 @@ static bool make_datetime(date_time_format_types format, TIME *ltime,
|
||||
*/
|
||||
|
||||
static bool extract_date_time(DATE_TIME_FORMAT *format,
|
||||
const char *val, uint length, TIME *l_time)
|
||||
const char *val, uint length, TIME *l_time,
|
||||
timestamp_type cached_timestamp_type)
|
||||
{
|
||||
int weekday= 0, yearday= 0, daypart= 0;
|
||||
int week_number= -1;
|
||||
@ -143,9 +142,11 @@ static bool extract_date_time(DATE_TIME_FORMAT *format,
|
||||
int error= 0;
|
||||
bool usa_time= 0;
|
||||
bool sunday_first= 0;
|
||||
int frac_part;
|
||||
const char *val_begin= val;
|
||||
const char *val_end= val + length;
|
||||
const char *ptr= format->format.str;
|
||||
const char *end= ptr+ format->format.length;
|
||||
const char *end= ptr + format->format.length;
|
||||
DBUG_ENTER("extract_date_time");
|
||||
|
||||
bzero((char*) l_time, sizeof(*l_time));
|
||||
@ -235,7 +236,12 @@ static bool extract_date_time(DATE_TIME_FORMAT *format,
|
||||
/* Second part */
|
||||
case 'f':
|
||||
tmp= (char*) val_end;
|
||||
if (tmp - val > 6)
|
||||
tmp= (char*) val + 6;
|
||||
l_time->second_part= (int) my_strtoll10(val, &tmp, &error);
|
||||
frac_part= 6 - (tmp - val);
|
||||
if (frac_part > 0)
|
||||
l_time->second_part*= (ulong) log_10_int[frac_part];
|
||||
val= tmp;
|
||||
break;
|
||||
|
||||
@ -251,6 +257,7 @@ static bool extract_date_time(DATE_TIME_FORMAT *format,
|
||||
(const uchar *) val, 2,
|
||||
(const uchar *) "AM", 2))
|
||||
goto err;
|
||||
val+= 2;
|
||||
break;
|
||||
|
||||
/* Exotic things */
|
||||
@ -281,6 +288,18 @@ static bool extract_date_time(DATE_TIME_FORMAT *format,
|
||||
val= tmp;
|
||||
break;
|
||||
|
||||
case '.':
|
||||
while (my_ispunct(cs, *val) && val != val_end)
|
||||
val++;
|
||||
break;
|
||||
case '@':
|
||||
while (my_isalpha(cs, *val) && val != val_end)
|
||||
val++;
|
||||
break;
|
||||
case '#':
|
||||
while (my_isdigit(cs, *val) && val != val_end)
|
||||
val++;
|
||||
break;
|
||||
default:
|
||||
goto err;
|
||||
}
|
||||
@ -348,6 +367,18 @@ static bool extract_date_time(DATE_TIME_FORMAT *format,
|
||||
l_time->minute > 59 || l_time->second > 59)
|
||||
goto err;
|
||||
|
||||
if (val != val_end)
|
||||
{
|
||||
do
|
||||
{
|
||||
if (!my_isspace(&my_charset_latin1,*val))
|
||||
{
|
||||
make_truncated_value_warning(current_thd, val_begin, length,
|
||||
cached_timestamp_type);
|
||||
break;
|
||||
}
|
||||
} while (++val != val_end);
|
||||
}
|
||||
DBUG_RETURN(0);
|
||||
|
||||
err:
|
||||
@ -584,16 +615,27 @@ bool make_date_time(DATE_TIME_FORMAT *format, TIME *l_time,
|
||||
|
||||
|
||||
/*
|
||||
** Get a array of positive numbers from a string object.
|
||||
** Each number is separated by 1 non digit character
|
||||
** Return error if there is too many numbers.
|
||||
** If there is too few numbers, assume that the numbers are left out
|
||||
** from the high end. This allows one to give:
|
||||
** DAY_TO_SECOND as "D MM:HH:SS", "MM:HH:SS" "HH:SS" or as seconds.
|
||||
Get a array of positive numbers from a string object.
|
||||
Each number is separated by 1 non digit character
|
||||
Return error if there is too many numbers.
|
||||
If there is too few numbers, assume that the numbers are left out
|
||||
from the high end. This allows one to give:
|
||||
DAY_TO_SECOND as "D MM:HH:SS", "MM:HH:SS" "HH:SS" or as seconds.
|
||||
|
||||
SYNOPSIS
|
||||
str: string value
|
||||
length: length of str
|
||||
cs: charset of str
|
||||
values: array of results
|
||||
count: count of elements in result array
|
||||
transform_msec: if value is true we suppose
|
||||
that the last part of string value is microseconds
|
||||
and we should transform value to six digit value.
|
||||
For example, '1.1' -> '1.100000'
|
||||
*/
|
||||
|
||||
bool get_interval_info(const char *str,uint length,CHARSET_INFO *cs,
|
||||
uint count, long *values)
|
||||
uint count, long *values, bool transform_msec)
|
||||
{
|
||||
const char *end=str+length;
|
||||
uint i;
|
||||
@ -603,8 +645,15 @@ bool get_interval_info(const char *str,uint length,CHARSET_INFO *cs,
|
||||
for (i=0 ; i < count ; i++)
|
||||
{
|
||||
long value;
|
||||
const char *start= str;
|
||||
for (value=0; str != end && my_isdigit(cs,*str) ; str++)
|
||||
value=value*10L + (long) (*str - '0');
|
||||
if (transform_msec && i == count - 1) // microseconds always last
|
||||
{
|
||||
long msec_length= 6 - (str - start);
|
||||
if (msec_length > 0)
|
||||
value*= (long) log_10_int[msec_length];
|
||||
}
|
||||
values[i]= value;
|
||||
while (str != end && !my_isdigit(cs,*str))
|
||||
str++;
|
||||
@ -925,19 +974,19 @@ static bool get_interval_value(Item *args,interval_type int_type,
|
||||
interval->second=value;
|
||||
break;
|
||||
case INTERVAL_YEAR_MONTH: // Allow YEAR-MONTH YYYYYMM
|
||||
if (get_interval_info(str,length,cs,2,array))
|
||||
if (get_interval_info(str,length,cs,2,array,0))
|
||||
return (1);
|
||||
interval->year=array[0];
|
||||
interval->month=array[1];
|
||||
break;
|
||||
case INTERVAL_DAY_HOUR:
|
||||
if (get_interval_info(str,length,cs,2,array))
|
||||
if (get_interval_info(str,length,cs,2,array,0))
|
||||
return (1);
|
||||
interval->day=array[0];
|
||||
interval->hour=array[1];
|
||||
break;
|
||||
case INTERVAL_DAY_MICROSECOND:
|
||||
if (get_interval_info(str,length,cs,5,array))
|
||||
if (get_interval_info(str,length,cs,5,array,1))
|
||||
return (1);
|
||||
interval->day=array[0];
|
||||
interval->hour=array[1];
|
||||
@ -946,14 +995,14 @@ static bool get_interval_value(Item *args,interval_type int_type,
|
||||
interval->second_part=array[4];
|
||||
break;
|
||||
case INTERVAL_DAY_MINUTE:
|
||||
if (get_interval_info(str,length,cs,3,array))
|
||||
if (get_interval_info(str,length,cs,3,array,0))
|
||||
return (1);
|
||||
interval->day=array[0];
|
||||
interval->hour=array[1];
|
||||
interval->minute=array[2];
|
||||
break;
|
||||
case INTERVAL_DAY_SECOND:
|
||||
if (get_interval_info(str,length,cs,4,array))
|
||||
if (get_interval_info(str,length,cs,4,array,0))
|
||||
return (1);
|
||||
interval->day=array[0];
|
||||
interval->hour=array[1];
|
||||
@ -961,7 +1010,7 @@ static bool get_interval_value(Item *args,interval_type int_type,
|
||||
interval->second=array[3];
|
||||
break;
|
||||
case INTERVAL_HOUR_MICROSECOND:
|
||||
if (get_interval_info(str,length,cs,4,array))
|
||||
if (get_interval_info(str,length,cs,4,array,1))
|
||||
return (1);
|
||||
interval->hour=array[0];
|
||||
interval->minute=array[1];
|
||||
@ -969,33 +1018,33 @@ static bool get_interval_value(Item *args,interval_type int_type,
|
||||
interval->second_part=array[3];
|
||||
break;
|
||||
case INTERVAL_HOUR_MINUTE:
|
||||
if (get_interval_info(str,length,cs,2,array))
|
||||
if (get_interval_info(str,length,cs,2,array,0))
|
||||
return (1);
|
||||
interval->hour=array[0];
|
||||
interval->minute=array[1];
|
||||
break;
|
||||
case INTERVAL_HOUR_SECOND:
|
||||
if (get_interval_info(str,length,cs,3,array))
|
||||
if (get_interval_info(str,length,cs,3,array,0))
|
||||
return (1);
|
||||
interval->hour=array[0];
|
||||
interval->minute=array[1];
|
||||
interval->second=array[2];
|
||||
break;
|
||||
case INTERVAL_MINUTE_MICROSECOND:
|
||||
if (get_interval_info(str,length,cs,3,array))
|
||||
if (get_interval_info(str,length,cs,3,array,1))
|
||||
return (1);
|
||||
interval->minute=array[0];
|
||||
interval->second=array[1];
|
||||
interval->second_part=array[2];
|
||||
break;
|
||||
case INTERVAL_MINUTE_SECOND:
|
||||
if (get_interval_info(str,length,cs,2,array))
|
||||
if (get_interval_info(str,length,cs,2,array,0))
|
||||
return (1);
|
||||
interval->minute=array[0];
|
||||
interval->second=array[1];
|
||||
break;
|
||||
case INTERVAL_SECOND_MICROSECOND:
|
||||
if (get_interval_info(str,length,cs,2,array))
|
||||
if (get_interval_info(str,length,cs,2,array,1))
|
||||
return (1);
|
||||
interval->second=array[0];
|
||||
interval->second_part=array[1];
|
||||
@ -1008,22 +1057,13 @@ static bool get_interval_value(Item *args,interval_type int_type,
|
||||
String *Item_date::val_str(String *str)
|
||||
{
|
||||
TIME ltime;
|
||||
ulong value=(ulong) val_int();
|
||||
if (null_value)
|
||||
return (String*) 0;
|
||||
|
||||
if (get_date(<ime, TIME_FUZZY_DATE))
|
||||
return (String *) 0;
|
||||
if (str->alloc(11))
|
||||
{
|
||||
null_value= 1;
|
||||
return (String *) 0;
|
||||
}
|
||||
|
||||
ltime.year= (value/10000L) % 10000;
|
||||
ltime.month= (value/100)%100;
|
||||
ltime.day= (value%100);
|
||||
ltime.neg= 0;
|
||||
ltime.time_type=TIMESTAMP_DATE;
|
||||
|
||||
make_date((DATE_TIME_FORMAT *) 0, <ime, str);
|
||||
return str;
|
||||
}
|
||||
@ -1032,28 +1072,31 @@ String *Item_date::val_str(String *str)
|
||||
int Item_date::save_in_field(Field *field, bool no_conversions)
|
||||
{
|
||||
TIME ltime;
|
||||
timestamp_type t_type=TIMESTAMP_DATETIME;
|
||||
if (get_date(<ime, TIME_FUZZY_DATE))
|
||||
{
|
||||
if (null_value)
|
||||
return set_field_to_null(field);
|
||||
t_type=TIMESTAMP_NONE; // Error
|
||||
}
|
||||
return set_field_to_null(field);
|
||||
field->set_notnull();
|
||||
field->store_time(<ime,t_type);
|
||||
field->store_time(<ime, TIMESTAMP_DATE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
longlong Item_func_from_days::val_int()
|
||||
longlong Item_date::val_int()
|
||||
{
|
||||
TIME ltime;
|
||||
if (get_date(<ime, TIME_FUZZY_DATE))
|
||||
return 0;
|
||||
return (longlong) (ltime.year*10000L+ltime.month*100+ltime.day);
|
||||
}
|
||||
|
||||
|
||||
bool Item_func_from_days::get_date(TIME *ltime, uint fuzzy_date)
|
||||
{
|
||||
longlong value=args[0]->val_int();
|
||||
if ((null_value=args[0]->null_value))
|
||||
return 0; /* purecov: inspected */
|
||||
|
||||
uint year,month,day;
|
||||
get_date_from_daynr((long) value,&year,&month,&day);
|
||||
return (longlong) (year*10000L+month*100+day);
|
||||
return 1;
|
||||
get_date_from_daynr((long) value, <ime->year, <ime->month, <ime->day);
|
||||
ltime->time_type= TIMESTAMP_DATE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -1082,6 +1125,16 @@ void Item_func_curdate::fix_length_and_dec()
|
||||
ltime.time_type=TIMESTAMP_DATE;
|
||||
}
|
||||
|
||||
String *Item_func_curdate::val_str(String *str)
|
||||
{
|
||||
if (str->alloc(11))
|
||||
{
|
||||
null_value= 1;
|
||||
return (String *) 0;
|
||||
}
|
||||
make_date((DATE_TIME_FORMAT *) 0, <ime, str);
|
||||
return str;
|
||||
}
|
||||
|
||||
bool Item_func_curdate::get_date(TIME *res,
|
||||
uint fuzzy_date __attribute__((unused)))
|
||||
@ -2311,6 +2364,103 @@ void Item_func_get_format::print(String *str)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
check_result_type(s, l) returns DATE/TIME type
|
||||
according to format string
|
||||
|
||||
s: DATE/TIME format string
|
||||
l: length of s
|
||||
Result: date_time_format_types value:
|
||||
DATE_TIME_MICROSECOND, DATE_TIME,
|
||||
TIME_MICROSECOND, TIME_ONLY
|
||||
|
||||
We don't process day format's characters('D', 'd', 'e')
|
||||
because day may be a member of all date/time types.
|
||||
If only day format's character and no time part present
|
||||
the result type is MYSQL_TYPE_DATE
|
||||
*/
|
||||
|
||||
date_time_format_types check_result_type(const char *format, uint length)
|
||||
{
|
||||
const char *time_part_frms= "HISThiklrs";
|
||||
const char *date_part_frms= "MUYWabcjmuyw";
|
||||
bool date_part_used= 0, time_part_used= 0, frac_second_used= 0;
|
||||
|
||||
const char *val= format;
|
||||
const char *end= format + length;
|
||||
|
||||
for (; val != end && val != end; val++)
|
||||
{
|
||||
if (*val == '%' && val+1 != end)
|
||||
{
|
||||
val++;
|
||||
if ((frac_second_used= (*val == 'f')) ||
|
||||
(!time_part_used && strchr(time_part_frms, *val)))
|
||||
time_part_used= 1;
|
||||
else if (!date_part_used && strchr(date_part_frms, *val))
|
||||
date_part_used= 1;
|
||||
if (time_part_used && date_part_used && frac_second_used)
|
||||
return DATE_TIME_MICROSECOND;
|
||||
}
|
||||
}
|
||||
|
||||
if (time_part_used)
|
||||
{
|
||||
if (date_part_used)
|
||||
return DATE_TIME;
|
||||
if (frac_second_used)
|
||||
return TIME_MICROSECOND;
|
||||
return TIME_ONLY;
|
||||
}
|
||||
return DATE_ONLY;
|
||||
}
|
||||
|
||||
|
||||
Field *Item_func_str_to_date::tmp_table_field(TABLE *t_arg)
|
||||
{
|
||||
if (cached_field_type == MYSQL_TYPE_TIME)
|
||||
return (new Field_time(maybe_null, name, t_arg, &my_charset_bin));
|
||||
if (cached_field_type == MYSQL_TYPE_DATE)
|
||||
return (new Field_date(maybe_null, name, t_arg, &my_charset_bin));
|
||||
if (cached_field_type == MYSQL_TYPE_DATETIME)
|
||||
return (new Field_datetime(maybe_null, name, t_arg, &my_charset_bin));
|
||||
return (new Field_string(max_length, maybe_null, name, t_arg, &my_charset_bin));
|
||||
}
|
||||
|
||||
|
||||
void Item_func_str_to_date::fix_length_and_dec()
|
||||
{
|
||||
char format_buff[64];
|
||||
String format_str(format_buff, sizeof(format_buff), &my_charset_bin), *format;
|
||||
maybe_null= 1;
|
||||
decimals=0;
|
||||
cached_field_type= MYSQL_TYPE_STRING;
|
||||
max_length= MAX_DATETIME_FULL_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
|
||||
cached_timestamp_type= TIMESTAMP_NONE;
|
||||
if ((const_item= args[1]->const_item()))
|
||||
{
|
||||
format= args[1]->val_str(&format_str);
|
||||
cached_format_type= check_result_type(format->ptr(), format->length());
|
||||
switch (cached_format_type) {
|
||||
case DATE_ONLY:
|
||||
cached_timestamp_type= TIMESTAMP_DATE;
|
||||
cached_field_type= MYSQL_TYPE_DATE;
|
||||
max_length= MAX_DATE_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
|
||||
break;
|
||||
case TIME_ONLY:
|
||||
case TIME_MICROSECOND:
|
||||
cached_timestamp_type= TIMESTAMP_TIME;
|
||||
cached_field_type= MYSQL_TYPE_TIME;
|
||||
max_length= MAX_TIME_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
|
||||
break;
|
||||
default:
|
||||
cached_timestamp_type= TIMESTAMP_DATETIME;
|
||||
cached_field_type= MYSQL_TYPE_DATETIME;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Item_func_str_to_date::get_date(TIME *ltime, uint fuzzy_date)
|
||||
{
|
||||
DATE_TIME_FORMAT date_time_format;
|
||||
@ -2328,8 +2478,18 @@ bool Item_func_str_to_date::get_date(TIME *ltime, uint fuzzy_date)
|
||||
date_time_format.format.str= (char*) format->ptr();
|
||||
date_time_format.format.length= format->length();
|
||||
if (extract_date_time(&date_time_format, val->ptr(), val->length(),
|
||||
ltime))
|
||||
ltime, cached_timestamp_type))
|
||||
goto null_date;
|
||||
if (cached_timestamp_type == TIMESTAMP_TIME && ltime->day)
|
||||
{
|
||||
/*
|
||||
Day part for time type can be nonzero value and so
|
||||
we should add hours from day part to hour part to
|
||||
keep valid time value.
|
||||
*/
|
||||
ltime->hour+= ltime->day*24;
|
||||
ltime->day= 0;
|
||||
}
|
||||
return 0;
|
||||
|
||||
null_date:
|
||||
@ -2344,29 +2504,22 @@ String *Item_func_str_to_date::val_str(String *str)
|
||||
if (Item_func_str_to_date::get_date(<ime, TIME_FUZZY_DATE))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
The following DATE_TIME should be done dynamicly based on the
|
||||
format string (wen it's a constant). For example, we should only return
|
||||
microseconds if there was an %f in the format
|
||||
*/
|
||||
if (!make_datetime(ltime.second_part ? DATE_TIME_MICROSECOND : DATE_TIME,
|
||||
if (!make_datetime((const_item ? cached_format_type :
|
||||
(ltime.second_part ? DATE_TIME_MICROSECOND : DATE_TIME)),
|
||||
<ime, str))
|
||||
return str;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
String *Item_func_last_day::val_str(String *str)
|
||||
bool Item_func_last_day::get_date(TIME *ltime, uint fuzzy_date)
|
||||
{
|
||||
TIME ltime;
|
||||
if (!get_arg0_date(<ime,0))
|
||||
{
|
||||
uint month_idx= ltime.month-1;
|
||||
ltime.day= days_in_month[month_idx];
|
||||
if ( month_idx == 1 && calc_days_in_year(ltime.year) == 366)
|
||||
ltime.day+= 1;
|
||||
if (!make_datetime(DATE_ONLY, <ime, str))
|
||||
return str;
|
||||
}
|
||||
if (get_arg0_date(ltime,fuzzy_date))
|
||||
return 1;
|
||||
uint month_idx= ltime->month-1;
|
||||
ltime->day= days_in_month[month_idx];
|
||||
if ( month_idx == 1 && calc_days_in_year(ltime->year) == 366)
|
||||
ltime->day= 29;
|
||||
ltime->time_type= TIMESTAMP_DATE;
|
||||
return 0;
|
||||
}
|
||||
|
@ -21,6 +21,11 @@
|
||||
#pragma interface /* gcc class implementation */
|
||||
#endif
|
||||
|
||||
enum date_time_format_types
|
||||
{
|
||||
TIME_ONLY= 0, TIME_MICROSECOND, DATE_ONLY, DATE_TIME, DATE_TIME_MICROSECOND
|
||||
};
|
||||
|
||||
class Item_func_period_add :public Item_int_func
|
||||
{
|
||||
public:
|
||||
@ -318,6 +323,7 @@ public:
|
||||
enum Item_result result_type () const { return STRING_RESULT; }
|
||||
enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
|
||||
String *val_str(String *str);
|
||||
longlong val_int();
|
||||
double val() { return (double) val_int(); }
|
||||
const char *func_name() const { return "date"; }
|
||||
void fix_length_and_dec()
|
||||
@ -407,6 +413,7 @@ public:
|
||||
Item_func_curdate() :Item_date() {}
|
||||
void set_result_from_tm(struct tm *now);
|
||||
longlong val_int() { return (value) ; }
|
||||
String *val_str(String *str);
|
||||
void fix_length_and_dec();
|
||||
bool get_date(TIME *res, uint fuzzy_date);
|
||||
virtual void store_now_in_tm(time_t now, struct tm *now_tm)=0;
|
||||
@ -477,8 +484,8 @@ class Item_func_from_days :public Item_date
|
||||
{
|
||||
public:
|
||||
Item_func_from_days(Item *a) :Item_date(a) {}
|
||||
longlong val_int();
|
||||
const char *func_name() const { return "from_days"; }
|
||||
bool get_date(TIME *res, uint fuzzy_date);
|
||||
};
|
||||
|
||||
|
||||
@ -806,37 +813,29 @@ public:
|
||||
};
|
||||
|
||||
|
||||
class Item_func_str_to_date :public Item_date_func
|
||||
class Item_func_str_to_date :public Item_str_func
|
||||
{
|
||||
enum_field_types cached_field_type;
|
||||
date_time_format_types cached_format_type;
|
||||
timestamp_type cached_timestamp_type;
|
||||
bool const_item;
|
||||
public:
|
||||
Item_func_str_to_date(Item *a, Item *b)
|
||||
:Item_date_func(a, b)
|
||||
:Item_str_func(a, b)
|
||||
{}
|
||||
String *val_str(String *str);
|
||||
bool get_date(TIME *ltime, uint fuzzy_date);
|
||||
const char *func_name() const { return "str_to_date"; }
|
||||
void fix_length_and_dec()
|
||||
{
|
||||
maybe_null= 1;
|
||||
decimals=0;
|
||||
max_length=MAX_DATETIME_FULL_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
|
||||
}
|
||||
enum_field_types field_type() const { return cached_field_type; }
|
||||
void fix_length_and_dec();
|
||||
Field *tmp_table_field(TABLE *t_arg);
|
||||
};
|
||||
|
||||
class Item_func_last_day :public Item_str_func
|
||||
|
||||
class Item_func_last_day :public Item_date
|
||||
{
|
||||
public:
|
||||
Item_func_last_day(Item *a) :Item_str_func(a) {}
|
||||
String *val_str(String *str);
|
||||
Item_func_last_day(Item *a) :Item_date(a) {}
|
||||
const char *func_name() const { return "last_day"; }
|
||||
enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
|
||||
void fix_length_and_dec()
|
||||
{
|
||||
decimals=0;
|
||||
max_length=MAX_DATE_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
|
||||
}
|
||||
Field *tmp_table_field(TABLE *t_arg)
|
||||
{
|
||||
return (new Field_date(maybe_null, name, t_arg, &my_charset_bin));
|
||||
}
|
||||
bool get_date(TIME *res, uint fuzzy_date);
|
||||
};
|
||||
|
@ -64,14 +64,6 @@ char* query_table_status(THD *thd,const char *db,const char *table_name);
|
||||
#define PREV_BITS(type,A) ((type) (((type) 1 << (A)) -1))
|
||||
#define all_bits_set(A,B) ((A) & (B) != (B))
|
||||
|
||||
#ifndef LL
|
||||
#ifdef HAVE_LONG_LONG
|
||||
#define LL(A) A ## LL
|
||||
#else
|
||||
#define LL(A) A ## L
|
||||
#endif
|
||||
#endif
|
||||
|
||||
extern CHARSET_INFO *system_charset_info, *files_charset_info ;
|
||||
extern CHARSET_INFO *national_charset_info, *table_alias_charset;
|
||||
|
||||
@ -621,7 +613,7 @@ int mysqld_help (THD *thd, const char *text);
|
||||
|
||||
/* sql_prepare.cc */
|
||||
void mysql_stmt_prepare(THD *thd, char *packet, uint packet_length);
|
||||
void mysql_stmt_execute(THD *thd, char *packet);
|
||||
void mysql_stmt_execute(THD *thd, char *packet, uint packet_length);
|
||||
void mysql_stmt_free(THD *thd, char *packet);
|
||||
void mysql_stmt_reset(THD *thd, char *packet);
|
||||
void mysql_stmt_get_longdata(THD *thd, char *pos, ulong packet_length);
|
||||
@ -799,6 +791,7 @@ extern char glob_hostname[FN_REFLEN], mysql_home[FN_REFLEN];
|
||||
extern char pidfile_name[FN_REFLEN], time_zone[30], *opt_init_file;
|
||||
extern char log_error_file[FN_REFLEN];
|
||||
extern double log_10[32];
|
||||
extern ulonglong log_10_int[20];
|
||||
extern ulonglong keybuff_size;
|
||||
extern ulong refresh_version,flush_version, thread_id,query_id,opened_tables;
|
||||
extern ulong created_tmp_tables, created_tmp_disk_tables, bytes_sent;
|
||||
@ -958,6 +951,8 @@ timestamp_type str_to_TIME(const char *str, uint length, TIME *l_time,
|
||||
void localtime_to_TIME(TIME *to, struct tm *from);
|
||||
void calc_time_from_sec(TIME *to, long seconds, long microseconds);
|
||||
|
||||
void make_truncated_value_warning(THD *thd, const char *str_val,
|
||||
uint str_length, timestamp_type time_type);
|
||||
extern DATE_TIME_FORMAT *date_time_format_make(timestamp_type format_type,
|
||||
const char *format_str,
|
||||
uint format_length);
|
||||
|
@ -305,6 +305,14 @@ ulong my_bind_addr; /* the address we bind to */
|
||||
volatile ulong cached_thread_count= 0;
|
||||
|
||||
double log_10[32]; /* 10 potences */
|
||||
ulonglong log_10_int[20]=
|
||||
{
|
||||
1, 10, 100, 1000, 10000UL, 100000UL, 1000000UL, 10000000UL,
|
||||
ULL(100000000), ULL(1000000000), ULL(10000000000), ULL(100000000000),
|
||||
ULL(1000000000000), ULL(10000000000000), ULL(100000000000000),
|
||||
ULL(1000000000000000), ULL(10000000000000000), ULL(100000000000000000),
|
||||
ULL(1000000000000000000), ULL(10000000000000000000)
|
||||
};
|
||||
|
||||
time_t start_time;
|
||||
|
||||
|
@ -304,3 +304,4 @@ character-set=latin2
|
||||
"The '%s' feature was disabled; you need MySQL built with '%s' to have it working",
|
||||
"The MySQL server is running with the %s option so it cannot execute this statement",
|
||||
"Column '%-.100s' has duplicated value '%-.64s' in %s"
|
||||
"Truncated wrong %-.32s value: '%-.128s'"
|
||||
|
@ -298,3 +298,4 @@ character-set=latin1
|
||||
"The '%s' feature was disabled; you need MySQL built with '%s' to have it working",
|
||||
"The MySQL server is running with the %s option so it cannot execute this statement",
|
||||
"Column '%-.100s' has duplicated value '%-.64s' in %s"
|
||||
"Truncated wrong %-.32s value: '%-.128s'"
|
||||
|
@ -306,3 +306,4 @@ character-set=latin1
|
||||
"The '%s' feature was disabled; you need MySQL built with '%s' to have it working",
|
||||
"The MySQL server is running with the %s option so it cannot execute this statement",
|
||||
"Column '%-.100s' has duplicated value '%-.64s' in %s"
|
||||
"Truncated wrong %-.32s value: '%-.128s'"
|
||||
|
@ -295,3 +295,4 @@ character-set=latin1
|
||||
"The '%s' feature was disabled; you need MySQL built with '%s' to have it working",
|
||||
"The MySQL server is running with the %s option so it cannot execute this statement",
|
||||
"Column '%-.100s' has duplicated value '%-.64s' in %s"
|
||||
"Truncated wrong %-.32s value: '%-.128s'"
|
||||
|
@ -300,3 +300,4 @@ character-set=latin7
|
||||
"The '%s' feature was disabled; you need MySQL built with '%s' to have it working",
|
||||
"The MySQL server is running with the %s option so it cannot execute this statement",
|
||||
"Column '%-.100s' has duplicated value '%-.64s' in %s"
|
||||
"Truncated wrong %-.32s value: '%-.128s'"
|
||||
|
@ -295,3 +295,4 @@ character-set=latin1
|
||||
"The '%s' feature was disabled; you need MySQL built with '%s' to have it working",
|
||||
"The MySQL server is running with the %s option so it cannot execute this statement",
|
||||
"Column '%-.100s' has duplicated value '%-.64s' in %s"
|
||||
"Truncated wrong %-.32s value: '%-.128s'"
|
||||
|
@ -307,3 +307,4 @@ character-set=latin1
|
||||
"The '%s' feature was disabled; you need MySQL built with '%s' to have it working",
|
||||
"The MySQL server is running with the %s option so it cannot execute this statement",
|
||||
"Column '%-.100s' has duplicated value '%-.64s' in %s"
|
||||
"Truncated wrong %-.32s value: '%-.128s'"
|
||||
|
@ -295,3 +295,4 @@ character-set=greek
|
||||
"The '%s' feature was disabled; you need MySQL built with '%s' to have it working",
|
||||
"The MySQL server is running with the %s option so it cannot execute this statement",
|
||||
"Column '%-.100s' has duplicated value '%-.64s' in %s"
|
||||
"Truncated wrong %-.32s value: '%-.128s'"
|
||||
|
@ -297,3 +297,4 @@ character-set=latin2
|
||||
"The '%s' feature was disabled; you need MySQL built with '%s' to have it working",
|
||||
"The MySQL server is running with the %s option so it cannot execute this statement",
|
||||
"Column '%-.100s' has duplicated value '%-.64s' in %s"
|
||||
"Truncated wrong %-.32s value: '%-.128s'"
|
||||
|
@ -295,3 +295,4 @@ character-set=latin1
|
||||
"The '%s' feature was disabled; you need MySQL built with '%s' to have it working",
|
||||
"The MySQL server is running with the %s option so it cannot execute this statement",
|
||||
"Column '%-.100s' has duplicated value '%-.64s' in %s"
|
||||
"Truncated wrong %-.32s value: '%-.128s'"
|
||||
|
@ -297,3 +297,4 @@ character-set=ujis
|
||||
"The '%s' feature was disabled; you need MySQL built with '%s' to have it working",
|
||||
"The MySQL server is running with the %s option so it cannot execute this statement",
|
||||
"Column '%-.100s' has duplicated value '%-.64s' in %s"
|
||||
"Truncated wrong %-.32s value: '%-.128s'"
|
||||
|
@ -295,3 +295,4 @@ character-set=euckr
|
||||
"The '%s' feature was disabled; you need MySQL built with '%s' to have it working",
|
||||
"The MySQL server is running with the %s option so it cannot execute this statement",
|
||||
"Column '%-.100s' has duplicated value '%-.64s' in %s"
|
||||
"Truncated wrong %-.32s value: '%-.128s'"
|
||||
|
@ -297,3 +297,4 @@ character-set=latin1
|
||||
"The '%s' feature was disabled; you need MySQL built with '%s' to have it working",
|
||||
"The MySQL server is running with the %s option so it cannot execute this statement",
|
||||
"Column '%-.100s' has duplicated value '%-.64s' in %s"
|
||||
"Truncated wrong %-.32s value: '%-.128s'"
|
||||
|
@ -297,3 +297,4 @@ character-set=latin1
|
||||
"The '%s' feature was disabled; you need MySQL built with '%s' to have it working",
|
||||
"The MySQL server is running with the %s option so it cannot execute this statement",
|
||||
"Column '%-.100s' has duplicated value '%-.64s' in %s"
|
||||
"Truncated wrong %-.32s value: '%-.128s'"
|
||||
|
@ -299,3 +299,4 @@ character-set=latin2
|
||||
"The '%s' feature was disabled; you need MySQL built with '%s' to have it working",
|
||||
"The MySQL server is running with the %s option so it cannot execute this statement",
|
||||
"Column '%-.100s' has duplicated value '%-.64s' in %s"
|
||||
"Truncated wrong %-.32s value: '%-.128s'"
|
||||
|
@ -296,3 +296,4 @@ character-set=latin1
|
||||
"The '%s' feature was disabled; you need MySQL built with '%s' to have it working",
|
||||
"The MySQL server is running with the %s option so it cannot execute this statement",
|
||||
"Column '%-.100s' has duplicated value '%-.64s' in %s"
|
||||
"Truncated wrong %-.32s value: '%-.128s'"
|
||||
|
@ -299,3 +299,4 @@ character-set=latin2
|
||||
"The '%s' feature was disabled; you need MySQL built with '%s' to have it working",
|
||||
"The MySQL server is running with the %s option so it cannot execute this statement",
|
||||
"Column '%-.100s' has duplicated value '%-.64s' in %s"
|
||||
"Truncated wrong %-.32s value: '%-.128s'"
|
||||
|
@ -297,3 +297,4 @@ character-set=koi8r
|
||||
"The '%s' feature was disabled; you need MySQL built with '%s' to have it working",
|
||||
"The MySQL server is running with the %s option so it cannot execute this statement",
|
||||
"Column '%-.100s' has duplicated value '%-.64s' in %s"
|
||||
"Truncated wrong %-.32s value: '%-.128s'"
|
||||
|
@ -289,3 +289,4 @@ character-set=cp1250
|
||||
"The '%s' feature was disabled; you need MySQL built with '%s' to have it working"
|
||||
"The MySQL server is running with the %s option so it cannot execute this statement"
|
||||
"Column '%-.100s' has duplicated value '%-.64s' in %s"
|
||||
"Truncated wrong %-.32s value: '%-.128s'"
|
||||
|
@ -303,3 +303,4 @@ character-set=latin2
|
||||
"The '%s' feature was disabled; you need MySQL built with '%s' to have it working",
|
||||
"The MySQL server is running with the %s option so it cannot execute this statement",
|
||||
"Column '%-.100s' has duplicated value '%-.64s' in %s"
|
||||
"Truncated wrong %-.32s value: '%-.128s'"
|
||||
|
@ -297,3 +297,4 @@ character-set=latin1
|
||||
"The '%s' feature was disabled; you need MySQL built with '%s' to have it working",
|
||||
"The MySQL server is running with the %s option so it cannot execute this statement",
|
||||
"Column '%-.100s' has duplicated value '%-.64s' in %s"
|
||||
"Truncated wrong %-.32s value: '%-.128s'"
|
||||
|
@ -295,3 +295,4 @@ character-set=latin1
|
||||
"MySQL är started i --skip-grant-tables mod. Pga av detta kan du inte använda detta program",
|
||||
|
||||
"Column '%-.100s' has duplicated value '%-.64s' in %s"
|
||||
"Truncated wrong %-.32s value: '%-.128s'"
|
||||
|
@ -300,3 +300,4 @@ character-set=koi8u
|
||||
"The '%s' feature was disabled; you need MySQL built with '%s' to have it working",
|
||||
"The MySQL server is running with the %s option so it cannot execute this statement",
|
||||
"Column '%-.100s' has duplicated value '%-.64s' in %s"
|
||||
"Truncated wrong %-.32s value: '%-.128s'"
|
||||
|
@ -25,7 +25,7 @@ Geometry::Class_info *Geometry::ci_collection[Geometry::wkb_end]=
|
||||
};
|
||||
|
||||
static Geometry::Class_info **ci_collection_end=
|
||||
Geometry::ci_collection+Geometry::wkb_end;
|
||||
Geometry::ci_collection+Geometry::wkb_end + 1;
|
||||
|
||||
Geometry::Class_info::Class_info(const char *name, int type_id,
|
||||
void(*create_func)(void *)):
|
||||
|
@ -157,7 +157,7 @@ struct Geometry_buffer;
|
||||
class Geometry
|
||||
{
|
||||
public:
|
||||
static void *operator new(unsigned size_t, void *buffer)
|
||||
static void *operator new(size_t size, void *buffer)
|
||||
{
|
||||
return buffer;
|
||||
}
|
||||
|
@ -657,7 +657,7 @@ public:
|
||||
points to a lock object if the lock is present. See item_func.cc and
|
||||
chapter 'Miscellaneous functions', for functions GET_LOCK, RELEASE_LOCK.
|
||||
*/
|
||||
ULL *ull;
|
||||
User_level_lock *ull;
|
||||
#ifndef DBUG_OFF
|
||||
uint dbug_sentry; // watch out for memory corruption
|
||||
#endif
|
||||
|
@ -1405,7 +1405,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
|
||||
}
|
||||
case COM_EXECUTE:
|
||||
{
|
||||
mysql_stmt_execute(thd, packet);
|
||||
mysql_stmt_execute(thd, packet, packet_length);
|
||||
break;
|
||||
}
|
||||
case COM_LONG_DATA:
|
||||
|
@ -94,7 +94,8 @@ public:
|
||||
bool long_data_used;
|
||||
bool log_full_query;
|
||||
#ifndef EMBEDDED_LIBRARY
|
||||
bool (*set_params)(Prepared_statement *st, uchar *pos, uchar *read_pos);
|
||||
bool (*set_params)(Prepared_statement *st, uchar *data, uchar *data_end,
|
||||
uchar *read_pos);
|
||||
#else
|
||||
bool (*set_params_data)(Prepared_statement *st);
|
||||
#endif
|
||||
@ -117,14 +118,6 @@ inline bool is_param_null(const uchar *pos, ulong param_no)
|
||||
|
||||
enum { STMT_QUERY_LOG_LENGTH= 8192 };
|
||||
|
||||
#ifdef EMBEDDED_LIBRARY
|
||||
#define SET_PARAM_FUNCTION(fn_name) \
|
||||
static void fn_name(Item_param *param, uchar **pos, ulong data_len)
|
||||
#else
|
||||
#define SET_PARAM_FUNCTION(fn_name) \
|
||||
static void fn_name(Item_param *param, uchar **pos)
|
||||
#endif
|
||||
|
||||
enum enum_send_error { DONT_SEND_ERROR= 0, SEND_ERROR };
|
||||
|
||||
/*
|
||||
@ -186,29 +179,38 @@ static bool send_prep_stmt(Prepared_statement *stmt,
|
||||
*/
|
||||
|
||||
#ifndef EMBEDDED_LIBRARY
|
||||
static ulong get_param_length(uchar **packet)
|
||||
static ulong get_param_length(uchar **packet, ulong len)
|
||||
{
|
||||
reg1 uchar *pos= *packet;
|
||||
if (len < 1)
|
||||
return 0;
|
||||
if (*pos < 251)
|
||||
{
|
||||
(*packet)++;
|
||||
return (ulong) *pos;
|
||||
}
|
||||
if (len < 3)
|
||||
return 0;
|
||||
if (*pos == 252)
|
||||
{
|
||||
(*packet)+=3;
|
||||
return (ulong) uint2korr(pos+1);
|
||||
}
|
||||
if (len < 4)
|
||||
return 0;
|
||||
if (*pos == 253)
|
||||
{
|
||||
(*packet)+=4;
|
||||
return (ulong) uint3korr(pos+1);
|
||||
}
|
||||
if (len < 5)
|
||||
return 0;
|
||||
(*packet)+=9; // Must be 254 when here
|
||||
/* TODO: why uint4korr here? (should be uint8korr) */
|
||||
return (ulong) uint4korr(pos+1);
|
||||
}
|
||||
#else
|
||||
#define get_param_length(A) data_len
|
||||
#define get_param_length(packet, len) len
|
||||
#endif /*!EMBEDDED_LIBRARY*/
|
||||
|
||||
/*
|
||||
@ -230,55 +232,80 @@ static ulong get_param_length(uchar **packet)
|
||||
none
|
||||
*/
|
||||
|
||||
SET_PARAM_FUNCTION(set_param_tiny)
|
||||
void set_param_tiny(Item_param *param, uchar **pos, ulong len)
|
||||
{
|
||||
#ifndef EMBEDDED_LIBRARY
|
||||
if (len < 1)
|
||||
return;
|
||||
#endif
|
||||
param->set_int((longlong)(**pos));
|
||||
*pos+= 1;
|
||||
}
|
||||
|
||||
SET_PARAM_FUNCTION(set_param_short)
|
||||
void set_param_short(Item_param *param, uchar **pos, ulong len)
|
||||
{
|
||||
#ifndef EMBEDDED_LIBRARY
|
||||
if (len < 2)
|
||||
return;
|
||||
#endif
|
||||
param->set_int((longlong)sint2korr(*pos));
|
||||
*pos+= 2;
|
||||
}
|
||||
|
||||
SET_PARAM_FUNCTION(set_param_int32)
|
||||
void set_param_int32(Item_param *param, uchar **pos, ulong len)
|
||||
{
|
||||
#ifndef EMBEDDED_LIBRARY
|
||||
if (len < 4)
|
||||
return;
|
||||
#endif
|
||||
param->set_int((longlong)sint4korr(*pos));
|
||||
*pos+= 4;
|
||||
}
|
||||
|
||||
SET_PARAM_FUNCTION(set_param_int64)
|
||||
void set_param_int64(Item_param *param, uchar **pos, ulong len)
|
||||
{
|
||||
#ifndef EMBEDDED_LIBRARY
|
||||
if (len < 8)
|
||||
return;
|
||||
#endif
|
||||
param->set_int((longlong)sint8korr(*pos));
|
||||
*pos+= 8;
|
||||
}
|
||||
|
||||
SET_PARAM_FUNCTION(set_param_float)
|
||||
void set_param_float(Item_param *param, uchar **pos, ulong len)
|
||||
{
|
||||
#ifndef EMBEDDED_LIBRARY
|
||||
if (len < 4)
|
||||
return;
|
||||
#endif
|
||||
float data;
|
||||
float4get(data,*pos);
|
||||
param->set_double((double) data);
|
||||
*pos+= 4;
|
||||
}
|
||||
|
||||
SET_PARAM_FUNCTION(set_param_double)
|
||||
void set_param_double(Item_param *param, uchar **pos, ulong len)
|
||||
{
|
||||
#ifndef EMBEDDED_LIBRARY
|
||||
if (len < 8)
|
||||
return;
|
||||
#endif
|
||||
double data;
|
||||
float8get(data,*pos);
|
||||
param->set_double((double) data);
|
||||
*pos+= 8;
|
||||
}
|
||||
|
||||
SET_PARAM_FUNCTION(set_param_time)
|
||||
void set_param_time(Item_param *param, uchar **pos, ulong len)
|
||||
{
|
||||
ulong length;
|
||||
|
||||
if ((length= get_param_length(pos)))
|
||||
if ((length= get_param_length(pos, len)) >= 8)
|
||||
{
|
||||
uchar *to= *pos;
|
||||
TIME tm;
|
||||
|
||||
/* TODO: why length is compared with 8 here? */
|
||||
tm.second_part= (length > 8 ) ? (ulong) sint4korr(to+7): 0;
|
||||
|
||||
tm.day= (ulong) sint4korr(to+1);
|
||||
@ -294,11 +321,11 @@ SET_PARAM_FUNCTION(set_param_time)
|
||||
*pos+= length;
|
||||
}
|
||||
|
||||
SET_PARAM_FUNCTION(set_param_datetime)
|
||||
void set_param_datetime(Item_param *param, uchar **pos, ulong len)
|
||||
{
|
||||
uint length;
|
||||
|
||||
if ((length= get_param_length(pos)))
|
||||
if ((length= get_param_length(pos, len)) >= 4)
|
||||
{
|
||||
uchar *to= *pos;
|
||||
TIME tm;
|
||||
@ -324,11 +351,11 @@ SET_PARAM_FUNCTION(set_param_datetime)
|
||||
*pos+= length;
|
||||
}
|
||||
|
||||
SET_PARAM_FUNCTION(set_param_date)
|
||||
void set_param_date(Item_param *param, uchar **pos, ulong len)
|
||||
{
|
||||
ulong length;
|
||||
|
||||
if ((length= get_param_length(pos)))
|
||||
if ((length= get_param_length(pos, len)) >= 4)
|
||||
{
|
||||
uchar *to= *pos;
|
||||
TIME tm;
|
||||
@ -346,11 +373,11 @@ SET_PARAM_FUNCTION(set_param_date)
|
||||
*pos+= length;
|
||||
}
|
||||
|
||||
SET_PARAM_FUNCTION(set_param_str)
|
||||
void set_param_str(Item_param *param, uchar **pos, ulong len)
|
||||
{
|
||||
ulong len= get_param_length(pos);
|
||||
param->set_value((const char *)*pos, len);
|
||||
*pos+= len;
|
||||
ulong length= get_param_length(pos, len);
|
||||
param->set_value((const char *)*pos, length);
|
||||
*pos+= length;
|
||||
}
|
||||
|
||||
static void setup_one_conversion_function(Item_param *param, uchar param_type)
|
||||
@ -405,8 +432,8 @@ static void setup_one_conversion_function(Item_param *param, uchar param_type)
|
||||
and if binary/update log is set, generate the valid query.
|
||||
*/
|
||||
|
||||
static bool insert_params_withlog(Prepared_statement *stmt, uchar *pos,
|
||||
uchar *read_pos)
|
||||
static bool insert_params_withlog(Prepared_statement *stmt, uchar *null_array,
|
||||
uchar *read_pos, uchar *data_end)
|
||||
{
|
||||
THD *thd= stmt->thd;
|
||||
Item_param **begin= stmt->param_array;
|
||||
@ -428,7 +455,7 @@ static bool insert_params_withlog(Prepared_statement *stmt, uchar *pos,
|
||||
res= param->query_val_str(&str);
|
||||
else
|
||||
{
|
||||
if (is_param_null(pos, it - begin))
|
||||
if (is_param_null(null_array, it - begin))
|
||||
{
|
||||
param->maybe_null= param->null_value= 1;
|
||||
res= &my_null_string;
|
||||
@ -436,7 +463,9 @@ static bool insert_params_withlog(Prepared_statement *stmt, uchar *pos,
|
||||
else
|
||||
{
|
||||
param->maybe_null= param->null_value= 0;
|
||||
param->set_param_func(param, &read_pos);
|
||||
if (read_pos >= data_end)
|
||||
DBUG_RETURN(1);
|
||||
param->set_param_func(param, &read_pos, data_end - read_pos);
|
||||
res= param->query_val_str(&str);
|
||||
}
|
||||
}
|
||||
@ -452,8 +481,8 @@ static bool insert_params_withlog(Prepared_statement *stmt, uchar *pos,
|
||||
}
|
||||
|
||||
|
||||
static bool insert_params(Prepared_statement *stmt, uchar *pos,
|
||||
uchar *read_pos)
|
||||
static bool insert_params(Prepared_statement *stmt, uchar *null_array,
|
||||
uchar *read_pos, uchar *data_end)
|
||||
{
|
||||
Item_param **begin= stmt->param_array;
|
||||
Item_param **end= begin + stmt->param_count;
|
||||
@ -465,20 +494,23 @@ static bool insert_params(Prepared_statement *stmt, uchar *pos,
|
||||
Item_param *param= *it;
|
||||
if (!param->long_data_supplied)
|
||||
{
|
||||
if (is_param_null(pos, it - begin))
|
||||
if (is_param_null(null_array, it - begin))
|
||||
param->maybe_null= param->null_value= 1;
|
||||
else
|
||||
{
|
||||
param->maybe_null= param->null_value= 0;
|
||||
param->set_param_func(param, &read_pos);
|
||||
if (read_pos >= data_end)
|
||||
DBUG_RETURN(1);
|
||||
param->set_param_func(param, &read_pos, data_end - read_pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
||||
static bool setup_conversion_functions(Prepared_statement *stmt,
|
||||
uchar **data)
|
||||
uchar **data, uchar *data_end)
|
||||
{
|
||||
/* skip null bits */
|
||||
uchar *read_pos= *data + (stmt->param_count+7) / 8;
|
||||
@ -495,6 +527,8 @@ static bool setup_conversion_functions(Prepared_statement *stmt,
|
||||
Item_param **end= it + stmt->param_count;
|
||||
for (; it < end; ++it)
|
||||
{
|
||||
if (read_pos >= data_end)
|
||||
DBUG_RETURN(1);
|
||||
setup_one_conversion_function(*it, *read_pos);
|
||||
read_pos+= 2;
|
||||
}
|
||||
@ -1072,7 +1106,7 @@ static void reset_stmt_for_execute(Prepared_statement *stmt)
|
||||
*/
|
||||
|
||||
|
||||
void mysql_stmt_execute(THD *thd, char *packet)
|
||||
void mysql_stmt_execute(THD *thd, char *packet, uint packet_length)
|
||||
{
|
||||
ulong stmt_id= uint4korr(packet);
|
||||
Prepared_statement *stmt;
|
||||
@ -1097,10 +1131,11 @@ void mysql_stmt_execute(THD *thd, char *packet)
|
||||
#ifndef EMBEDDED_LIBRARY
|
||||
if (stmt->param_count)
|
||||
{
|
||||
uchar *packet_end= (uchar *) packet + packet_length - 1;
|
||||
packet+= 4;
|
||||
uchar *null_array= (uchar *) packet;
|
||||
if (setup_conversion_functions(stmt, (uchar **) &packet) ||
|
||||
stmt->set_params(stmt, null_array, (uchar *) packet))
|
||||
if (setup_conversion_functions(stmt, (uchar **) &packet, packet_end) ||
|
||||
stmt->set_params(stmt, null_array, (uchar *) packet, packet_end))
|
||||
goto set_params_data_err;
|
||||
}
|
||||
#else
|
||||
@ -1159,6 +1194,7 @@ set_params_data_err:
|
||||
|
||||
void mysql_stmt_reset(THD *thd, char *packet)
|
||||
{
|
||||
/* There is always space for 4 bytes in buffer */
|
||||
ulong stmt_id= uint4korr(packet);
|
||||
Prepared_statement *stmt;
|
||||
|
||||
@ -1189,6 +1225,7 @@ void mysql_stmt_reset(THD *thd, char *packet)
|
||||
|
||||
void mysql_stmt_free(THD *thd, char *packet)
|
||||
{
|
||||
/* There is always space for 4 bytes in packet buffer */
|
||||
ulong stmt_id= uint4korr(packet);
|
||||
Prepared_statement *stmt;
|
||||
|
||||
|
80
sql/time.cc
80
sql/time.cc
@ -391,9 +391,11 @@ str_to_TIME(const char *str, uint length, TIME *l_time, uint flags)
|
||||
ulong not_zero_date, allow_space;
|
||||
bool is_internal_format;
|
||||
const char *pos, *last_field_pos;
|
||||
const char *str_begin= str;
|
||||
const char *end=str+length;
|
||||
const uchar *format_position;
|
||||
bool found_delimitier= 0, found_space= 0;
|
||||
uint frac_pos, frac_len;
|
||||
DBUG_ENTER("str_to_TIME");
|
||||
DBUG_PRINT("ENTER",("str: %.*s",length,str));
|
||||
|
||||
@ -482,7 +484,7 @@ str_to_TIME(const char *str, uint length, TIME *l_time, uint flags)
|
||||
tmp_value=tmp_value*10 + (ulong) (uchar) (*str - '0');
|
||||
str++;
|
||||
}
|
||||
date_len[i]+= (uint) (str - start);
|
||||
date_len[i]= (uint) (str - start);
|
||||
if (tmp_value > 999999) // Impossible date part
|
||||
DBUG_RETURN(TIMESTAMP_NONE);
|
||||
date[i]=tmp_value;
|
||||
@ -535,9 +537,9 @@ str_to_TIME(const char *str, uint length, TIME *l_time, uint flags)
|
||||
{
|
||||
if (str+2 <= end && (str[1] == 'M' || str[1] == 'm'))
|
||||
{
|
||||
if (str[1] == 'p' || str[1] == 'P')
|
||||
if (str[0] == 'p' || str[0] == 'P')
|
||||
add_hours= 12;
|
||||
else if (str[1] != 'a' || str[1] != 'A')
|
||||
else if (str[0] != 'a' || str[0] != 'A')
|
||||
continue; // Not AM/PM
|
||||
str+= 2; // Skip AM/PM
|
||||
/* Skip space after AM/PM */
|
||||
@ -569,7 +571,13 @@ str_to_TIME(const char *str, uint length, TIME *l_time, uint flags)
|
||||
l_time->hour= date[(uint) format_position[3]];
|
||||
l_time->minute= date[(uint) format_position[4]];
|
||||
l_time->second= date[(uint) format_position[5]];
|
||||
l_time->second_part= date[(uint) format_position[6]];
|
||||
|
||||
frac_pos= (uint) format_position[6];
|
||||
frac_len= date_len[frac_pos];
|
||||
if (frac_len < 6)
|
||||
date[frac_pos]*= (uint) log_10_int[6 - frac_len];
|
||||
l_time->second_part= date[frac_pos];
|
||||
|
||||
if (format_position[7] != (uchar) 255)
|
||||
{
|
||||
if (l_time->hour > 12)
|
||||
@ -585,6 +593,8 @@ str_to_TIME(const char *str, uint length, TIME *l_time, uint flags)
|
||||
l_time->hour= date[3];
|
||||
l_time->minute= date[4];
|
||||
l_time->second= date[5];
|
||||
if (date_len[6] < 6)
|
||||
date[6]*= (uint) log_10_int[6 - date_len[6]];
|
||||
l_time->second_part=date[6];
|
||||
}
|
||||
l_time->neg= 0;
|
||||
@ -614,15 +624,17 @@ str_to_TIME(const char *str, uint length, TIME *l_time, uint flags)
|
||||
current_thd->cuted_fields++;
|
||||
goto err;
|
||||
}
|
||||
if (str != end && current_thd->count_cuted_fields)
|
||||
|
||||
l_time->time_type= (number_of_fields <= 3 ?
|
||||
TIMESTAMP_DATE : TIMESTAMP_DATETIME);
|
||||
|
||||
for (; str != end ; str++)
|
||||
{
|
||||
for (; str != end ; str++)
|
||||
if (!my_isspace(&my_charset_latin1,*str))
|
||||
{
|
||||
if (!my_isspace(&my_charset_latin1,*str))
|
||||
{
|
||||
current_thd->cuted_fields++;
|
||||
break;
|
||||
}
|
||||
make_truncated_value_warning(current_thd, str_begin, length,
|
||||
l_time->time_type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -686,6 +698,7 @@ bool str_to_time(const char *str,uint length,TIME *l_time)
|
||||
{
|
||||
long date[5],value;
|
||||
const char *end=str+length, *end_of_days;
|
||||
const char *str_begin= str;
|
||||
bool found_days,found_hours;
|
||||
uint state;
|
||||
|
||||
@ -706,7 +719,7 @@ bool str_to_time(const char *str,uint length,TIME *l_time)
|
||||
{ // Probably full timestamp
|
||||
enum timestamp_type res= str_to_TIME(str,length,l_time,
|
||||
(TIME_FUZZY_DATE |
|
||||
TIME_DATETIME_ONLY));
|
||||
TIME_DATETIME_ONLY));
|
||||
if ((int) res >= (int) TIMESTAMP_DATETIME_ERROR)
|
||||
return res == TIMESTAMP_DATETIME_ERROR;
|
||||
}
|
||||
@ -784,6 +797,8 @@ fractional:
|
||||
my_isdigit(&my_charset_latin1,str[0]) &&
|
||||
field_length--)
|
||||
value=value*10 + (uint) (uchar) (*str - '0');
|
||||
if (field_length)
|
||||
value*= (long) log_10_int[field_length];
|
||||
date[4]=value;
|
||||
}
|
||||
else
|
||||
@ -796,12 +811,12 @@ fractional:
|
||||
str++;
|
||||
if (str+2 <= end && (str[1] == 'M' || str[1] == 'm'))
|
||||
{
|
||||
if (str[1] == 'p' || str[1] == 'P')
|
||||
if (str[0] == 'p' || str[0] == 'P')
|
||||
{
|
||||
str+= 2;
|
||||
date[1]= date[1]%12 + 12;
|
||||
}
|
||||
else if (str[1] == 'a' || str[1] == 'A')
|
||||
else if (str[0] == 'a' || str[0] == 'A')
|
||||
str+=2;
|
||||
}
|
||||
}
|
||||
@ -822,13 +837,14 @@ fractional:
|
||||
l_time->time_type= TIMESTAMP_TIME;
|
||||
|
||||
/* Check if there is garbage at end of the TIME specification */
|
||||
if (str != end && current_thd->count_cuted_fields)
|
||||
if (str != end)
|
||||
{
|
||||
do
|
||||
{
|
||||
if (!my_isspace(&my_charset_latin1,*str))
|
||||
{
|
||||
current_thd->cuted_fields++;
|
||||
make_truncated_value_warning(current_thd, str_begin, length,
|
||||
TIMESTAMP_TIME);
|
||||
break;
|
||||
}
|
||||
} while (++str != end);
|
||||
@ -1265,3 +1281,35 @@ void make_datetime(DATE_TIME_FORMAT *format, TIME *l_time, String *str)
|
||||
str->length(length);
|
||||
str->set_charset(&my_charset_bin);
|
||||
}
|
||||
|
||||
void make_truncated_value_warning(THD *thd, const char *str_val,
|
||||
uint str_length, timestamp_type time_type)
|
||||
{
|
||||
char warn_buff[MYSQL_ERRMSG_SIZE];
|
||||
const char *type_str;
|
||||
|
||||
char buff[128];
|
||||
String str(buff,(uint32) sizeof(buff), system_charset_info);
|
||||
str.length(0);
|
||||
str.append(str_val, str_length);
|
||||
str.append('\0');
|
||||
|
||||
switch (time_type) {
|
||||
case TIMESTAMP_DATE:
|
||||
type_str= "date";
|
||||
break;
|
||||
case TIMESTAMP_DATETIME:
|
||||
type_str= "datetime";
|
||||
break;
|
||||
case TIMESTAMP_TIME:
|
||||
type_str= "time";
|
||||
break;
|
||||
default:
|
||||
type_str= "string";
|
||||
break;
|
||||
}
|
||||
sprintf(warn_buff, ER(ER_TRUNCATED_WRONG_VALUE),
|
||||
type_str, str.ptr());
|
||||
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
|
||||
ER_TRUNCATED_WRONG_VALUE, warn_buff);
|
||||
}
|
||||
|
@ -262,9 +262,9 @@ long my_strntol_8bit(CHARSET_INFO *cs,
|
||||
{
|
||||
if (c>='0' && c<='9')
|
||||
c -= '0';
|
||||
else if (c>='A' && c<='F')
|
||||
else if (c>='A' && c<='Z')
|
||||
c = c - 'A' + 10;
|
||||
else if (c>='a' && c<='f')
|
||||
else if (c>='a' && c<='z')
|
||||
c = c - 'a' + 10;
|
||||
else
|
||||
break;
|
||||
@ -384,9 +384,9 @@ ulong my_strntoul_8bit(CHARSET_INFO *cs,
|
||||
{
|
||||
if (c>='0' && c<='9')
|
||||
c -= '0';
|
||||
else if (c>='A' && c<='F')
|
||||
else if (c>='A' && c<='Z')
|
||||
c = c - 'A' + 10;
|
||||
else if (c>='a' && c<='f')
|
||||
else if (c>='a' && c<='z')
|
||||
c = c - 'a' + 10;
|
||||
else
|
||||
break;
|
||||
@ -499,9 +499,9 @@ longlong my_strntoll_8bit(CHARSET_INFO *cs __attribute__((unused)),
|
||||
{
|
||||
if (c>='0' && c<='9')
|
||||
c -= '0';
|
||||
else if (c>='A' && c<='F')
|
||||
else if (c>='A' && c<='Z')
|
||||
c = c - 'A' + 10;
|
||||
else if (c>='a' && c<='f')
|
||||
else if (c>='a' && c<='z')
|
||||
c = c - 'a' + 10;
|
||||
else
|
||||
break;
|
||||
@ -622,9 +622,9 @@ ulonglong my_strntoull_8bit(CHARSET_INFO *cs,
|
||||
{
|
||||
if (c>='0' && c<='9')
|
||||
c -= '0';
|
||||
else if (c>='A' && c<='F')
|
||||
else if (c>='A' && c<='Z')
|
||||
c = c - 'A' + 10;
|
||||
else if (c>='a' && c<='f')
|
||||
else if (c>='a' && c<='z')
|
||||
c = c - 'a' + 10;
|
||||
else
|
||||
break;
|
||||
|
Loading…
x
Reference in New Issue
Block a user