Merge bk-internal.mysql.com:/home/bk/mysql-4.1

into mysql.com:/home/my/mysql-4.1
This commit is contained in:
unknown 2004-03-16 00:04:05 +02:00
commit a6f89625fc
62 changed files with 1220 additions and 507 deletions

View File

@ -619,10 +619,10 @@ static struct my_option my_long_options[] =
(gptr*) &current_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},

View File

@ -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 */

View File

@ -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

View File

@ -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.

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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= &param->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= &param->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 */

View File

@ -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'

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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");

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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");

View File

@ -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;
};

View File

@ -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");

View File

@ -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);

View File

@ -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)

View File

@ -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

View File

@ -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;
}

View File

@ -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;

View File

@ -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(&ltime, 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, &ltime, 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(&ltime, 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(&ltime,t_type);
field->store_time(&ltime, TIMESTAMP_DATE);
return 0;
}
longlong Item_func_from_days::val_int()
longlong Item_date::val_int()
{
TIME ltime;
if (get_date(&ltime, 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, &ltime->year, &ltime->month, &ltime->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, &ltime, 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(&ltime, 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)),
&ltime, 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(&ltime,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, &ltime, 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;
}

View File

@ -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);
};

View File

@ -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);

View File

@ -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;

View File

@ -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'"

View File

@ -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'"

View File

@ -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'"

View File

@ -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'"

View File

@ -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'"

View File

@ -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'"

View File

@ -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'"

View File

@ -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'"

View File

@ -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'"

View File

@ -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'"

View File

@ -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'"

View File

@ -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'"

View File

@ -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'"

View File

@ -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'"

View File

@ -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'"

View File

@ -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'"

View File

@ -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'"

View File

@ -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'"

View File

@ -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'"

View File

@ -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'"

View File

@ -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'"

View File

@ -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'"

View File

@ -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'"

View File

@ -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 *)):

View File

@ -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;
}

View File

@ -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

View File

@ -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:

View File

@ -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;

View File

@ -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);
}

View File

@ -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;