Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
mariadb
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
mariadb
Commits
5cacc972
Commit
5cacc972
authored
Mar 02, 2004
by
serg@serg.mylan
Browse files
Options
Browse Files
Download
Plain Diff
Merge bk-internal:/home/bk/mysql-4.1/
into serg.mylan:/usr/home/serg/Abk/mysql-4.1
parents
a05c54b6
8cc8b0ea
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
436 additions
and
394 deletions
+436
-394
include/my_sys.h
include/my_sys.h
+1
-0
sql/item.h
sql/item.h
+2
-2
sql/mysql_priv.h
sql/mysql_priv.h
+1
-2
sql/protocol.h
sql/protocol.h
+0
-5
sql/sql_class.cc
sql/sql_class.cc
+2
-11
sql/sql_class.h
sql/sql_class.h
+14
-14
sql/sql_lex.h
sql/sql_lex.h
+1
-2
sql/sql_parse.cc
sql/sql_parse.cc
+24
-0
sql/sql_prepare.cc
sql/sql_prepare.cc
+381
-352
sql/sql_yacc.yy
sql/sql_yacc.yy
+10
-4
tests/client_test.c
tests/client_test.c
+0
-2
No files found.
include/my_sys.h
View file @
5cacc972
...
...
@@ -714,6 +714,7 @@ extern void my_free_lock(byte *ptr,myf flags);
#define my_free_lock(A,B) my_free((A),(B))
#endif
#define alloc_root_inited(A) ((A)->min_malloc != 0)
#define clear_alloc_root(A) bzero((void *) (A), sizeof(MEM_ROOT))
extern
void
init_alloc_root
(
MEM_ROOT
*
mem_root
,
uint
block_size
,
uint
pre_alloc_size
);
extern
gptr
alloc_root
(
MEM_ROOT
*
mem_root
,
unsigned
int
Size
);
...
...
sql/item.h
View file @
5cacc972
...
...
@@ -375,9 +375,9 @@ public:
bool
get_time
(
TIME
*
tm
);
void
reset
()
{}
#ifndef EMBEDDED_LIBRARY
void
(
*
set
up
_param_func
)(
Item_param
*
param
,
uchar
**
pos
);
void
(
*
set_param_func
)(
Item_param
*
param
,
uchar
**
pos
);
#else
void
(
*
set
up
_param_func
)(
Item_param
*
param
,
uchar
**
pos
,
ulong
data_len
);
void
(
*
set_param_func
)(
Item_param
*
param
,
uchar
**
pos
,
ulong
data_len
);
#endif
enum
Item_result
result_type
()
const
{
return
item_result_type
;
}
...
...
sql/mysql_priv.h
View file @
5cacc972
...
...
@@ -620,14 +620,13 @@ int mysqld_show_column_types(THD *thd);
int
mysqld_help
(
THD
*
thd
,
const
char
*
text
);
/* sql_prepare.cc */
bool
mysql_stmt_prepare
(
THD
*
thd
,
char
*
packet
,
uint
packet_length
);
void
mysql_stmt_prepare
(
THD
*
thd
,
char
*
packet
,
uint
packet_length
);
void
mysql_stmt_execute
(
THD
*
thd
,
char
*
packet
);
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
);
int
check_insert_fields
(
THD
*
thd
,
TABLE
*
table
,
List
<
Item
>
&
fields
,
List
<
Item
>
&
values
,
ulong
counter
);
void
setup_param_functions
(
Item_param
*
param
,
uchar
param_type
);
/* sql_error.cc */
MYSQL_ERROR
*
push_warning
(
THD
*
thd
,
MYSQL_ERROR
::
enum_warning_level
level
,
uint
code
,
...
...
sql/protocol.h
View file @
5cacc972
...
...
@@ -178,8 +178,3 @@ char *net_store_data(char *to,const char *from, uint length);
char
*
net_store_data
(
char
*
to
,
int32
from
);
char
*
net_store_data
(
char
*
to
,
longlong
from
);
#ifdef EMBEDDED_LIBRARY
bool
setup_params_data
(
struct
st_prep_stmt
*
stmt
);
bool
setup_params_data_withlog
(
struct
st_prep_stmt
*
stmt
);
#endif
sql/sql_class.cc
View file @
5cacc972
...
...
@@ -145,8 +145,7 @@ THD::THD():user_time(0), current_statement(0), is_fatal_error(0),
init
();
/* Initialize sub structures */
bzero
((
char
*
)
&
transaction
.
mem_root
,
sizeof
(
transaction
.
mem_root
));
bzero
((
char
*
)
&
warn_root
,
sizeof
(
warn_root
));
clear_alloc_root
(
&
transaction
.
mem_root
);
init_alloc_root
(
&
warn_root
,
WARN_ALLOC_BLOCK_SIZE
,
WARN_ALLOC_PREALLOC_SIZE
);
user_connect
=
(
USER_CONN
*
)
0
;
hash_init
(
&
user_vars
,
&
my_charset_bin
,
USER_VARS_HASH_SIZE
,
0
,
0
,
...
...
@@ -331,7 +330,7 @@ THD::~THD()
dbug_sentry
=
THD_SENTRY_GONE
;
#endif
/* Reset stmt_backup.mem_root to not double-free memory from thd.mem_root */
init_alloc_root
(
&
stmt_backup
.
mem_root
,
0
,
0
);
clear_alloc_root
(
&
stmt_backup
.
mem_root
);
DBUG_VOID_RETURN
;
}
...
...
@@ -1185,10 +1184,8 @@ int select_dumpvar::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
Statement
::
Statement
(
THD
*
thd
)
:
id
(
++
thd
->
statement_id_counter
),
query_id
(
thd
->
query_id
),
set_query_id
(
1
),
allow_sum_func
(
0
),
command
(
thd
->
command
),
lex
(
&
main_lex
),
query
(
0
),
query_length
(
0
),
...
...
@@ -1207,10 +1204,8 @@ Statement::Statement(THD *thd)
Statement
::
Statement
()
:
id
(
0
),
query_id
(
0
),
/* initialized later */
set_query_id
(
1
),
allow_sum_func
(
0
),
/* initialized later */
command
(
COM_SLEEP
),
/* initialized later */
lex
(
&
main_lex
),
query
(
0
),
/* these two are set */
query_length
(
0
),
/* in alloc_query() */
...
...
@@ -1229,15 +1224,11 @@ Statement::Type Statement::type() const
void
Statement
::
set_statement
(
Statement
*
stmt
)
{
id
=
stmt
->
id
;
query_id
=
stmt
->
query_id
;
set_query_id
=
stmt
->
set_query_id
;
allow_sum_func
=
stmt
->
allow_sum_func
;
command
=
stmt
->
command
;
lex
=
stmt
->
lex
;
query
=
stmt
->
query
;
query_length
=
stmt
->
query_length
;
free_list
=
stmt
->
free_list
;
mem_root
=
stmt
->
mem_root
;
}
...
...
sql/sql_class.h
View file @
5cacc972
...
...
@@ -434,15 +434,6 @@ public:
*/
ulong
id
;
/*
Id of current query. Statement can be reused to execute several queries
query_id is global in context of the whole MySQL server.
ID is automatically generated from mutex-protected counter.
It's used in handler code for various purposes: to check which columns
from table are necessary for this select, to check if it's necessary to
update auto-updatable fields (like auto_increment and timestamp).
*/
ulong
query_id
;
/*
- if set_query_id=1, we set field->query_id for all fields. In that case
field list can not contain duplicates.
...
...
@@ -461,11 +452,6 @@ public:
See item_sum.cc for details.
*/
bool
allow_sum_func
;
/*
Type of current query: COM_PREPARE, COM_QUERY, etc. Set from
first byte of the packet in do_command()
*/
enum
enum_server_command
command
;
LEX
*
lex
;
// parse tree descriptor
/*
...
...
@@ -676,6 +662,11 @@ public:
uint
dbug_sentry
;
// watch out for memory corruption
#endif
struct
st_my_thread_var
*
mysys_var
;
/*
Type of current query: COM_PREPARE, COM_QUERY, etc. Set from
first byte of the packet in do_command()
*/
enum
enum_server_command
command
;
uint32
server_id
;
uint32
file_id
;
// for LOAD DATA INFILE
/*
...
...
@@ -751,6 +742,15 @@ public:
List
<
MYSQL_ERROR
>
warn_list
;
uint
warn_count
[(
uint
)
MYSQL_ERROR
::
WARN_LEVEL_END
];
uint
total_warn_count
;
/*
Id of current query. Statement can be reused to execute several queries
query_id is global in context of the whole MySQL server.
ID is automatically generated from mutex-protected counter.
It's used in handler code for various purposes: to check which columns
from table are necessary for this select, to check if it's necessary to
update auto-updatable fields (like auto_increment and timestamp).
*/
ulong
query_id
;
ulong
warn_id
,
version
,
options
,
thread_id
,
col_access
;
/* Statement id is thread-wide. This counter is used to generate ids */
...
...
sql/sql_lex.h
View file @
5cacc972
...
...
@@ -552,7 +552,7 @@ typedef struct st_lex
List
<
Item
>
*
insert_list
,
field_list
,
value_list
;
List
<
List_item
>
many_values
;
List
<
set_var_base
>
var_list
;
List
<
Item
>
param_list
;
List
<
Item
_param
>
param_list
;
SQL_LIST
proc_list
,
auxilliary_table_list
,
save_list
;
TYPELIB
*
interval
;
create_field
*
last_field
;
...
...
@@ -577,7 +577,6 @@ typedef struct st_lex
uint
uint_geom_type
;
uint
grant
,
grant_tot_col
,
which_columns
;
uint
fk_delete_opt
,
fk_update_opt
,
fk_match_option
;
uint
param_count
;
uint
slave_thd_opt
;
uint8
describe
;
bool
drop_if_exists
,
drop_temporary
,
local_file
;
...
...
sql/sql_parse.cc
View file @
5cacc972
...
...
@@ -1232,10 +1232,34 @@ bool do_command(THD *thd)
command_name
[
command
]));
}
net
->
read_timeout
=
old_timeout
;
// restore it
/*
packet_length contains length of data, as it was stored in packet
header. In case of malformed header, packet_length can be zero.
If packet_length is not zero, my_net_read ensures that this number
of bytes was actually read from network. Additionally my_net_read
sets packet[packet_length]= 0 (thus if packet_length == 0,
command == packet[0] == COM_SLEEP).
In dispatch_command packet[packet_length] points beyond the end of packet.
*/
DBUG_RETURN
(
dispatch_command
(
command
,
thd
,
packet
+
1
,
(
uint
)
packet_length
));
}
#endif
/* EMBEDDED_LIBRARY */
/*
Perform one connection-level (COM_XXXX) command.
SYNOPSIS
dispatch_command()
thd connection handle
command type of command to perform
packet data for the command, packet is always null-terminated
packet_length length of packet + 1 (to show that data is
null-terminated) except for COM_SLEEP, where it
can be zero.
RETURN VALUE
0 ok
1 request of thread shutdown, i. e. if command is
COM_QUIT/COM_SHUTDOWN
*/
bool
dispatch_command
(
enum
enum_server_command
command
,
THD
*
thd
,
char
*
packet
,
uint
packet_length
)
...
...
sql/sql_prepare.cc
View file @
5cacc972
...
...
@@ -39,7 +39,7 @@ Prepare-execute:
- Server gets the command 'COM_EXECUTE' to execute the
previously prepared query. If there is any param markers; then client
will send the data in the following format:
will send the data in the following format:
[COM_EXECUTE:1]
[STMT_ID:4]
[NULL_BITS:(param_count+7)/8)]
...
...
@@ -86,16 +86,17 @@ class Prepared_statement: public Statement
{
public:
THD
*
thd
;
Item_param
**
param
;
/* array of all placeholders */
Item_param
**
param
_array
;
uint
param_count
;
uint
last_errno
;
char
last_error
[
MYSQL_ERRMSG_SIZE
];
bool
error_in_prepare
,
long_data_used
;
bool
get_longdata_error
;
bool
long_data_used
;
bool
log_full_query
;
#ifndef EMBEDDED_LIBRARY
bool
(
*
set
up
_params
)(
Prepared_statement
*
st
,
uchar
*
pos
,
uchar
*
read_pos
);
bool
(
*
set_params
)(
Prepared_statement
*
st
,
uchar
*
pos
,
uchar
*
read_pos
);
#else
bool
(
*
set
up
_params_data
)(
Prepared_statement
*
st
);
bool
(
*
set_params_data
)(
Prepared_statement
*
st
);
#endif
public:
Prepared_statement
(
THD
*
thd_arg
);
...
...
@@ -117,13 +118,14 @@ inline bool is_param_null(const uchar *pos, ulong param_no)
enum
{
STMT_QUERY_LOG_LENGTH
=
8192
};
#ifdef EMBEDDED_LIBRARY
#define SET
UP
_PARAM_FUNCTION(fn_name) \
#define SET_PARAM_FUNCTION(fn_name) \
static void fn_name(Item_param *param, uchar **pos, ulong data_len)
#else
#define SET
UP
_PARAM_FUNCTION(fn_name) \
#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
};
/*
Seek prepared statement in statement map by id: returns zero if statement
...
...
@@ -131,14 +133,16 @@ static void fn_name(Item_param *param, uchar **pos)
*/
static
Prepared_statement
*
find_prepared_statement
(
THD
*
thd
,
ulong
id
,
const
char
*
where
)
find_prepared_statement
(
THD
*
thd
,
ulong
id
,
const
char
*
where
,
enum
enum_send_error
se
)
{
Statement
*
stmt
=
thd
->
stmt_map
.
find
(
id
);
if
(
stmt
==
0
||
stmt
->
type
()
!=
Statement
::
PREPARED_STATEMENT
)
{
my_error
(
ER_UNKNOWN_STMT_HANDLER
,
MYF
(
0
),
id
,
where
);
send_error
(
thd
);
if
(
se
==
SEND_ERROR
)
send_error
(
thd
);
return
0
;
}
return
(
Prepared_statement
*
)
stmt
;
...
...
@@ -154,11 +158,11 @@ static bool send_prep_stmt(Prepared_statement *stmt, uint columns)
{
NET
*
net
=
&
stmt
->
thd
->
net
;
char
buff
[
9
];
buff
[
0
]
=
0
;
buff
[
0
]
=
0
;
/* OK packet indicator */
int4store
(
buff
+
1
,
stmt
->
id
);
int2store
(
buff
+
5
,
columns
);
int2store
(
buff
+
7
,
stmt
->
param_count
);
/* T
his should be fixed to work with prepared statements
*/
/* T
ODO: send types of placeholders here
*/
return
(
my_net_write
(
net
,
buff
,
sizeof
(
buff
))
||
net_flush
(
net
));
}
#else
...
...
@@ -177,8 +181,8 @@ static bool send_prep_stmt(Prepared_statement *stmt,
/*
Read the length of the parameter data and retu
n back to
caller by positing the pointer to param data
Read the length of the parameter data and retu
rn back to
caller by positing the pointer to param data
.
*/
#ifndef EMBEDDED_LIBRARY
...
...
@@ -208,49 +212,49 @@ static ulong get_param_length(uchar **packet)
#endif
/*!EMBEDDED_LIBRARY*/
/*
Setup param conversion routines
setup_param_xx()
param Parameter Item
pos Input data buffer
Data conversion routines
SYNOPSIS
set_param_xx()
param parameter item
pos input data buffer
len length of data in the buffer
All these functions reads the data from pos and sets up that data
through 'param' and advances the buffer position to predifined
length position.
All these functions read the data from pos, convert it to requested type
and assign to param; pos is advanced to predefined length.
Make a note that the NULL handling is examined at first execution
(i.e. when input types altered) and for all subsequent executions
we don't read any values for this.
RETURN VALUE
S
RETURN VALUE
none
*/
SET
UP_PARAM_FUNCTION
(
setup
_param_tiny
)
SET
_PARAM_FUNCTION
(
set
_param_tiny
)
{
param
->
set_int
((
longlong
)(
**
pos
));
*
pos
+=
1
;
}
SET
UP_PARAM_FUNCTION
(
setup
_param_short
)
SET
_PARAM_FUNCTION
(
set
_param_short
)
{
param
->
set_int
((
longlong
)
sint2korr
(
*
pos
));
*
pos
+=
2
;
}
SET
UP_PARAM_FUNCTION
(
setup
_param_int32
)
SET
_PARAM_FUNCTION
(
set
_param_int32
)
{
param
->
set_int
((
longlong
)
sint4korr
(
*
pos
));
*
pos
+=
4
;
}
SET
UP_PARAM_FUNCTION
(
setup
_param_int64
)
SET
_PARAM_FUNCTION
(
set
_param_int64
)
{
param
->
set_int
((
longlong
)
sint8korr
(
*
pos
));
*
pos
+=
8
;
}
SET
UP_PARAM_FUNCTION
(
setup
_param_float
)
SET
_PARAM_FUNCTION
(
set
_param_float
)
{
float
data
;
float4get
(
data
,
*
pos
);
...
...
@@ -258,7 +262,7 @@ SETUP_PARAM_FUNCTION(setup_param_float)
*
pos
+=
4
;
}
SET
UP_PARAM_FUNCTION
(
setup
_param_double
)
SET
_PARAM_FUNCTION
(
set
_param_double
)
{
double
data
;
float8get
(
data
,
*
pos
);
...
...
@@ -266,14 +270,14 @@ SETUP_PARAM_FUNCTION(setup_param_double)
*
pos
+=
8
;
}
SET
UP_PARAM_FUNCTION
(
setup
_param_time
)
SET
_PARAM_FUNCTION
(
set
_param_time
)
{
ulong
length
;
if
((
length
=
get_param_length
(
pos
)))
{
uchar
*
to
=
*
pos
;
TIME
tm
;
TIME
tm
;
tm
.
second_part
=
(
length
>
8
)
?
(
ulong
)
sint4korr
(
to
+
7
)
:
0
;
...
...
@@ -290,11 +294,11 @@ SETUP_PARAM_FUNCTION(setup_param_time)
*
pos
+=
length
;
}
SET
UP_PARAM_FUNCTION
(
setup
_param_datetime
)
SET
_PARAM_FUNCTION
(
set
_param_datetime
)
{
uint
length
=
get_param_length
(
pos
)
;
uint
length
;
if
(
length
)
if
(
(
length
=
get_param_length
(
pos
))
)
{
uchar
*
to
=
*
pos
;
TIME
tm
;
...
...
@@ -320,7 +324,7 @@ SETUP_PARAM_FUNCTION(setup_param_datetime)
*
pos
+=
length
;
}
SET
UP_PARAM_FUNCTION
(
setup
_param_date
)
SET
_PARAM_FUNCTION
(
set
_param_date
)
{
ulong
length
;
...
...
@@ -342,55 +346,55 @@ SETUP_PARAM_FUNCTION(setup_param_date)
*
pos
+=
length
;
}
SET
UP_PARAM_FUNCTION
(
setup
_param_str
)
SET
_PARAM_FUNCTION
(
set
_param_str
)
{
ulong
len
=
get_param_length
(
pos
);
param
->
set_value
((
const
char
*
)
*
pos
,
len
);
*
pos
+=
len
;
*
pos
+=
len
;
}
void
setup_param_functions
(
Item_param
*
param
,
uchar
param_type
)
static
void
setup_one_conversion_function
(
Item_param
*
param
,
uchar
param_type
)
{
switch
(
param_type
)
{
case
FIELD_TYPE_TINY
:
param
->
set
up_param_func
=
setup
_param_tiny
;
param
->
set
_param_func
=
set
_param_tiny
;
param
->
item_result_type
=
INT_RESULT
;
break
;
case
FIELD_TYPE_SHORT
:
param
->
set
up_param_func
=
setup
_param_short
;
param
->
set
_param_func
=
set
_param_short
;
param
->
item_result_type
=
INT_RESULT
;
break
;
case
FIELD_TYPE_LONG
:
param
->
set
up_param_func
=
setup
_param_int32
;
param
->
set
_param_func
=
set
_param_int32
;
param
->
item_result_type
=
INT_RESULT
;
break
;
case
FIELD_TYPE_LONGLONG
:
param
->
set
up_param_func
=
setup
_param_int64
;
param
->
set
_param_func
=
set
_param_int64
;
param
->
item_result_type
=
INT_RESULT
;
break
;
case
FIELD_TYPE_FLOAT
:
param
->
set
up_param_func
=
setup
_param_float
;
param
->
set
_param_func
=
set
_param_float
;
param
->
item_result_type
=
REAL_RESULT
;
break
;
case
FIELD_TYPE_DOUBLE
:
param
->
set
up_param_func
=
setup
_param_double
;
param
->
set
_param_func
=
set
_param_double
;
param
->
item_result_type
=
REAL_RESULT
;
break
;
case
FIELD_TYPE_TIME
:
param
->
set
up_param_func
=
setup
_param_time
;
param
->
set
_param_func
=
set
_param_time
;
param
->
item_result_type
=
STRING_RESULT
;
break
;
case
FIELD_TYPE_DATE
:
param
->
set
up_param_func
=
setup
_param_date
;
param
->
set
_param_func
=
set
_param_date
;
param
->
item_result_type
=
STRING_RESULT
;
break
;
case
MYSQL_TYPE_DATETIME
:
case
MYSQL_TYPE_TIMESTAMP
:
param
->
set
up_param_func
=
setup
_param_datetime
;
param
->
set
_param_func
=
set
_param_datetime
;
param
->
item_result_type
=
STRING_RESULT
;
break
;
default:
param
->
set
up_param_func
=
setup
_param_str
;
param
->
set
_param_func
=
set
_param_str
;
param
->
item_result_type
=
STRING_RESULT
;
}
}
...
...
@@ -404,11 +408,11 @@ void setup_param_functions(Item_param *param, uchar param_type)
static
bool
insert_params_withlog
(
Prepared_statement
*
stmt
,
uchar
*
pos
,
uchar
*
read_pos
)
{
THD
*
thd
=
stmt
->
thd
;
List
<
Item
>
&
params
=
stmt
->
lex
->
param_list
;
List_iterator
<
Item
>
param_iterator
(
params
)
;
Item_param
*
param
;
THD
*
thd
=
stmt
->
thd
;
Item_param
**
begin
=
stmt
->
param_array
;
Item_param
**
end
=
begin
+
stmt
->
param_count
;
uint32
length
=
0
;
String
str
,
query
;
const
String
*
res
;
...
...
@@ -417,16 +421,14 @@ static bool insert_params_withlog(Prepared_statement *stmt, uchar *pos,
if
(
query
.
copy
(
stmt
->
query
,
stmt
->
query_length
,
default_charset_info
))
DBUG_RETURN
(
1
);
ulong
param_no
=
0
;
uint32
length
=
0
;
while
((
param
=
(
Item_param
*
)
param_iterator
++
))
for
(
Item_param
**
it
=
begin
;
it
<
end
;
++
it
)
{
Item_param
*
param
=
*
it
;
if
(
param
->
long_data_supplied
)
res
=
param
->
query_val_str
(
&
str
);
res
=
param
->
query_val_str
(
&
str
);
else
{
if
(
is_param_null
(
pos
,
param_no
))
if
(
is_param_null
(
pos
,
it
-
begin
))
{
param
->
maybe_null
=
param
->
null_value
=
1
;
res
=
&
my_null_string
;
...
...
@@ -434,7 +436,7 @@ static bool insert_params_withlog(Prepared_statement *stmt, uchar *pos,
else
{
param
->
maybe_null
=
param
->
null_value
=
0
;
param
->
set
up_param_func
(
param
,
&
read_pos
);
param
->
set
_param_func
(
param
,
&
read_pos
);
res
=
param
->
query_val_str
(
&
str
);
}
}
...
...
@@ -442,7 +444,6 @@ static bool insert_params_withlog(Prepared_statement *stmt, uchar *pos,
DBUG_RETURN
(
1
);
length
+=
res
->
length
()
-
1
;
param_no
++
;
}
if
(
alloc_query
(
thd
,
(
char
*
)
query
.
ptr
(),
query
.
length
()
+
1
))
DBUG_RETURN
(
1
);
...
...
@@ -454,73 +455,68 @@ static bool insert_params_withlog(Prepared_statement *stmt, uchar *pos,
static
bool
insert_params
(
Prepared_statement
*
stmt
,
uchar
*
pos
,
uchar
*
read_pos
)
{
List
<
Item
>
&
params
=
stmt
->
lex
->
param_list
;
List_iterator
<
Item
>
param_iterator
(
params
);
Item_param
*
param
;
ulong
param_no
=
0
;
Item_param
**
begin
=
stmt
->
param_array
;
Item_param
**
end
=
begin
+
stmt
->
param_count
;
DBUG_ENTER
(
"insert_params"
);
while
((
param
=
(
Item_param
*
)
param_iterator
++
)
)
for
(
Item_param
**
it
=
begin
;
it
<
end
;
++
it
)
{
if
(
!
param
->
long_data_supplied
)
Item_param
*
param
=
*
it
;
if
(
!
param
->
long_data_supplied
)
{
if
(
is_param_null
(
pos
,
param_no
))
if
(
is_param_null
(
pos
,
it
-
begin
))
param
->
maybe_null
=
param
->
null_value
=
1
;
else
{
param
->
maybe_null
=
param
->
null_value
=
0
;
param
->
set
up_param_func
(
param
,
&
read_pos
);
param
->
set
_param_func
(
param
,
&
read_pos
);
}
}
param_no
++
;
}
DBUG_RETURN
(
0
);
}
static
bool
setup_params_data
(
Prepared_statement
*
stmt
)
{
List
<
Item
>
&
params
=
stmt
->
lex
->
param_list
;
List_iterator
<
Item
>
param_iterator
(
params
);
Item_param
*
param
;
uchar
*
pos
=
(
uchar
*
)
stmt
->
thd
->
net
.
read_pos
+
1
+
MYSQL_STMT_HEADER
;
//skip header
uchar
*
read_pos
=
pos
+
(
stmt
->
param_count
+
7
)
/
8
;
//skip null bits
static
bool
setup_conversion_functions
(
Prepared_statement
*
stmt
,
uchar
**
data
)
{
/* skip null bits */
uchar
*
read_pos
=
*
data
+
(
stmt
->
param_count
+
7
)
/
8
;
DBUG_ENTER
(
"setup_
params_data
"
);
DBUG_ENTER
(
"setup_
conversion_functions
"
);
if
(
*
read_pos
++
)
//types supplied / first execute
{
{
/*
First execute or types altered by the client, setup the
conversion routines for all parameters (one time)
*/
while
((
param
=
(
Item_param
*
)
param_iterator
++
))
{
setup_param_functions
(
param
,
*
read_pos
);
Item_param
**
it
=
stmt
->
param_array
;
Item_param
**
end
=
it
+
stmt
->
param_count
;
for
(;
it
<
end
;
++
it
)
{
setup_one_conversion_function
(
*
it
,
*
read_pos
);
read_pos
+=
2
;
}
param_iterator
.
rewind
();
}
stmt
->
setup_params
(
stmt
,
pos
,
read_pos
);
}
*
data
=
read_pos
;
DBUG_RETURN
(
0
);
}
#else
bool
setup_params_data
(
Prepared_statement
*
stmt
)
{
List
<
Item
>
&
params
=
stmt
->
lex
->
param_list
;
List_iterator
<
Item
>
param_iterator
(
params
);
Item_param
*
param
;
static
bool
emb_insert_params
(
Prepared_statement
*
stmt
)
{
Item_param
**
it
=
stmt
->
param_array
;
Item_param
**
end
=
it
+
stmt
->
param_count
;
MYSQL_BIND
*
client_param
=
stmt
->
thd
->
client_params
;
DBUG_ENTER
(
"
setup_params_data
"
);
DBUG_ENTER
(
"
emb_insert_params
"
);
for
(;(
param
=
(
Item_param
*
)
param_iterator
++
);
client_param
++
)
{
setup_param_functions
(
param
,
client_param
->
buffer_type
);
for
(;
it
<
end
;
++
it
,
++
client_param
)
{
Item_param
*
param
=
*
it
;
setup_one_conversion_function
(
param
,
client_param
->
buffer_type
);
if
(
!
param
->
long_data_supplied
)
{
if
(
*
client_param
->
is_null
)
...
...
@@ -529,39 +525,39 @@ bool setup_params_data(Prepared_statement *stmt)
{
uchar
*
buff
=
(
uchar
*
)
client_param
->
buffer
;
param
->
maybe_null
=
param
->
null_value
=
0
;
param
->
set
up_param_func
(
param
,
&
buff
,
client_param
->
length
?
*
client_param
->
length
:
client_param
->
buffer_length
);
param
->
set
_param_func
(
param
,
&
buff
,
client_param
->
length
?
*
client_param
->
length
:
client_param
->
buffer_length
);
}
}
}
DBUG_RETURN
(
0
);
}
bool
setup_params_data_withlog
(
Prepared_statement
*
stmt
)
{
static
bool
emb_insert_params_withlog
(
Prepared_statement
*
stmt
)
{
THD
*
thd
=
stmt
->
thd
;
List
<
Item
>
&
params
=
stmt
->
lex
->
param_list
;
List_iterator
<
Item
>
param_iterator
(
params
);
Item_param
*
param
;
Item_param
**
it
=
stmt
->
param_array
;
Item_param
**
end
=
it
+
stmt
->
param_count
;
MYSQL_BIND
*
client_param
=
thd
->
client_params
;
String
str
,
query
;
const
String
*
res
;
uint32
length
=
0
;
DBUG_ENTER
(
"
setup_params_data
_withlog"
);
DBUG_ENTER
(
"
emb_insert_params
_withlog"
);
if
(
query
.
copy
(
stmt
->
query
,
stmt
->
query_length
,
default_charset_info
))
DBUG_RETURN
(
1
);
uint32
length
=
0
;
for
(;(
param
=
(
Item_param
*
)
param_iterator
++
);
client_param
++
)
{
setup_param_functions
(
param
,
client_param
->
buffer_type
);
for
(;
it
<
end
;
++
it
,
++
client_param
)
{
Item_param
*
param
=
*
it
;
setup_one_conversion_function
(
param
,
client_param
->
buffer_type
);
if
(
param
->
long_data_supplied
)
res
=
param
->
query_val_str
(
&
str
);
res
=
param
->
query_val_str
(
&
str
);
else
{
if
(
*
client_param
->
is_null
)
...
...
@@ -573,16 +569,15 @@ bool setup_params_data_withlog(Prepared_statement *stmt)
{
uchar
*
buff
=
(
uchar
*
)
client_param
->
buffer
;
param
->
maybe_null
=
param
->
null_value
=
0
;
param
->
set
up_param_func
(
param
,
&
buff
,
client_param
->
length
?
*
client_param
->
length
:
client_param
->
buffer_length
);
param
->
set
_param_func
(
param
,
&
buff
,
client_param
->
length
?
*
client_param
->
length
:
client_param
->
buffer_length
);
res
=
param
->
query_val_str
(
&
str
);
}
}
if
(
query
.
replace
(
param
->
pos_in_query
+
length
,
1
,
*
res
))
DBUG_RETURN
(
1
);
length
+=
res
->
length
()
-
1
;
}
...
...
@@ -595,15 +590,21 @@ bool setup_params_data_withlog(Prepared_statement *stmt)
#endif
/*!EMBEDDED_LIBRARY*/
/*
Validate the following information for INSERT statement:
- field existance
- fields count
Validate the following information for INSERT statement:
- field existence
- fields count
SYNOPSIS
mysql_test_insert_fields()
RETURN VALUE
0 ok
1 error, sent to the client
-1 error, not sent to client
*/
static
bool
mysql_test_insert_fields
(
Prepared_statement
*
stmt
,
TABLE_LIST
*
table_list
,
List
<
Item
>
&
fields
,
List
<
List_item
>
&
values_list
)
static
int
mysql_test_insert_fields
(
Prepared_statement
*
stmt
,
TABLE_LIST
*
table_list
,
List
<
Item
>
&
fields
,
List
<
List_item
>
&
values_list
)
{
THD
*
thd
=
stmt
->
thd
;
TABLE
*
table
;
...
...
@@ -630,7 +631,7 @@ static bool mysql_test_insert_fields(Prepared_statement *stmt,
if
(
open_and_lock_tables
(
thd
,
table_list
))
{
thd
->
free_temporary_memory_pool_for_ps_preparing
();
DBUG_RETURN
(
1
);
DBUG_RETURN
(
-
1
);
}
table
=
table_list
->
table
;
...
...
@@ -643,7 +644,7 @@ static bool mysql_test_insert_fields(Prepared_statement *stmt,
if
(
check_insert_fields
(
thd
,
table
,
fields
,
*
values
,
1
))
{
thd
->
free_temporary_memory_pool_for_ps_preparing
();
DBUG_RETURN
(
1
);
DBUG_RETURN
(
-
1
);
}
thd
->
free_temporary_memory_pool_for_ps_preparing
();
...
...
@@ -658,7 +659,7 @@ static bool mysql_test_insert_fields(Prepared_statement *stmt,
my_printf_error
(
ER_WRONG_VALUE_COUNT_ON_ROW
,
ER
(
ER_WRONG_VALUE_COUNT_ON_ROW
),
MYF
(
0
),
counter
);
DBUG_RETURN
(
1
);
DBUG_RETURN
(
-
1
);
}
}
}
...
...
@@ -666,25 +667,26 @@ static bool mysql_test_insert_fields(Prepared_statement *stmt,
{
thd
->
free_temporary_memory_pool_for_ps_preparing
();
}
if
(
send_prep_stmt
(
stmt
,
0
))
DBUG_RETURN
(
1
);
DBUG_RETURN
(
0
);
}
/*
Validate the following information
UPDATE - set and where clause DELETE - where clause
And send update-set clause column list fields info
back to client. For DELETE, just validate where clause
and return no fields information back to client.
Validate the following information:
UPDATE - set and where clause
DELETE - where clause
SYNOPSIS
mysql_test_upd_fields()
RETURN VALUE
0 success
1 error, sent to client
-1 error, not sent to client
*/
static
bool
mysql_test_upd_fields
(
Prepared_statement
*
stmt
,
TABLE_LIST
*
table_list
,
List
<
Item
>
&
fields
,
List
<
Item
>
&
values
,
COND
*
conds
)
static
int
mysql_test_upd_fields
(
Prepared_statement
*
stmt
,
TABLE_LIST
*
table_list
,
List
<
Item
>
&
fields
,
List
<
Item
>
&
values
,
COND
*
conds
)
{
THD
*
thd
=
stmt
->
thd
;
...
...
@@ -711,44 +713,43 @@ static bool mysql_test_upd_fields(Prepared_statement *stmt,
thd
->
free_temporary_memory_pool_for_ps_preparing
();
/*
Currently return only column list info only, and we are not
sending any info on where clause.
*/
if
(
send_prep_stmt
(
stmt
,
0
))
DBUG_RETURN
(
1
);
/* TODO: here we should send types of placeholders to the client. */
DBUG_RETURN
(
0
);
err:
thd
->
free_temporary_memory_pool_for_ps_preparing
();
DBUG_RETURN
(
1
);
DBUG_RETURN
(
-
1
);
}
/*
Validate the following information:
Validate the following information:
SELECT - column list
- where clause
- order clause
- having clause
- group by clause
- if no column spec i.e. '*', then setup all fields
And send column list fields info back to client.
In case of success, if this query is not EXPLAIN, send column list info
back to client.
SYNOPSIS
mysql_test_select_fields()
RETURN VALUE
0 success
1 error, sent to client
-1 error, not sent to client
*/
static
bool
mysql_test_select_fields
(
Prepared_statement
*
stmt
,
TABLE_LIST
*
tables
,
uint
wild_num
,
List
<
Item
>
&
fields
,
COND
*
conds
,
uint
og_num
,
ORDER
*
order
,
ORDER
*
group
,
Item
*
having
,
ORDER
*
proc
,
ulong
select_options
,
SELECT_LEX_UNIT
*
unit
,
SELECT_LEX
*
select_lex
)
static
int
mysql_test_select_fields
(
Prepared_statement
*
stmt
,
TABLE_LIST
*
tables
,
uint
wild_num
,
List
<
Item
>
&
fields
,
COND
*
conds
,
uint
og_num
,
ORDER
*
order
,
ORDER
*
group
,
Item
*
having
,
ORDER
*
proc
,
ulong
select_options
,
SELECT_LEX_UNIT
*
unit
,
SELECT_LEX
*
select_lex
)
{
THD
*
thd
=
stmt
->
thd
;
LEX
*
lex
=
stmt
->
lex
;
select_result
*
result
=
lex
->
result
;
DBUG_ENTER
(
"mysql_test_select_fields"
);
...
...
@@ -772,7 +773,10 @@ static bool mysql_test_select_fields(Prepared_statement *stmt,
*/
thd
->
allocate_temporary_memory_pool_for_ps_preparing
();
if
(
open_and_lock_tables
(
thd
,
tables
))
{
send_error
(
thd
);
goto
err
;
}
if
(
lex
->
describe
)
{
...
...
@@ -781,23 +785,27 @@ static bool mysql_test_select_fields(Prepared_statement *stmt,
}
else
{
select_result
*
result
=
lex
->
result
;
if
(
!
result
&&
!
(
result
=
new
select_send
()))
{
send_error
(
thd
,
ER_OUT_OF_RESOURCES
);
goto
err
;
}
thd
->
used_tables
=
0
;
// Updated by setup_fields
thd
->
used_tables
=
0
;
// Updated by setup_fields
if
(
unit
->
prepare
(
thd
,
result
,
0
))
{
send_error
(
thd
);
goto
err_prep
;
}
if
(
send_prep_stmt
(
stmt
,
fields
.
elements
)
||
thd
->
protocol_simple
.
send_fields
(
&
fields
,
0
)
#ifndef EMBEDDED_LIBRARY
||
net_flush
(
&
thd
->
net
)
||
net_flush
(
&
thd
->
net
)
#endif
)
)
goto
err_prep
;
unit
->
cleanup
();
...
...
@@ -814,97 +822,104 @@ err:
/*
Send the prepare query results back to client
Send the prepare query results back to client
SYNOPSIS
send_prepare_results()
stmt prepared statement
RETURN VALUE
0 success
1 error, sent to client
*/
static
bool
send_prepare_results
(
Prepared_statement
*
stmt
)
static
int
send_prepare_results
(
Prepared_statement
*
stmt
)
{
THD
*
thd
=
stmt
->
thd
;
LEX
*
lex
=
stmt
->
lex
;
SELECT_LEX
*
select_lex
=
&
lex
->
select_lex
;
TABLE_LIST
*
tables
=
(
TABLE_LIST
*
)
select_lex
->
table_list
.
first
;
enum
enum_sql_command
sql_command
=
lex
->
sql_command
;
int
res
;
DBUG_ENTER
(
"send_prepare_results"
);
DBUG_PRINT
(
"enter"
,(
"command: %d, param_count: %ld"
,
sql_command
,
lex
->
param_count
));
/* Setup prepared stmt */
stmt
->
param_count
=
lex
->
param_count
;
SELECT_LEX
*
select_lex
=
&
lex
->
select_lex
;
TABLE_LIST
*
tables
=
(
TABLE_LIST
*
)
select_lex
->
table_list
.
first
;
sql_command
,
stmt
->
param_count
));
switch
(
sql_command
)
{
case
SQLCOM_INSERT
:
if
(
mysql_test_insert_fields
(
stmt
,
tables
,
lex
->
field_list
,
lex
->
many_values
))
goto
abort
;
if
(
(
res
=
mysql_test_insert_fields
(
stmt
,
tables
,
lex
->
field_list
,
lex
->
many_values
)
))
goto
error
;
break
;
case
SQLCOM_UPDATE
:
if
(
mysql_test_upd_fields
(
stmt
,
tables
,
select_lex
->
item_list
,
lex
->
value_list
,
select_lex
->
where
))
goto
abort
;
break
;
/* XXX: fallthrough */
case
SQLCOM_DELETE
:
if
(
mysql_test_upd_fields
(
stmt
,
tables
,
select_lex
->
item_list
,
lex
->
value_list
,
select_lex
->
where
))
goto
abort
;
if
(
(
res
=
mysql_test_upd_fields
(
stmt
,
tables
,
select_lex
->
item_list
,
lex
->
value_list
,
select_lex
->
where
)
))
goto
error
;
break
;
case
SQLCOM_SELECT
:
if
(
mysql_test_select_fields
(
stmt
,
tables
,
select_lex
->
with_wild
,
select_lex
->
item_list
,
select_lex
->
where
,
select_lex
->
order_list
.
elements
+
select_lex
->
group_list
.
elements
,
(
ORDER
*
)
select_lex
->
order_list
.
first
,
(
ORDER
*
)
select_lex
->
group_list
.
first
,
select_lex
->
having
,
(
ORDER
*
)
lex
->
proc_list
.
first
,
select_lex
->
options
|
thd
->
options
,
&
(
lex
->
unit
),
select_lex
))
goto
abort
;
break
;
if
((
res
=
mysql_test_select_fields
(
stmt
,
tables
,
select_lex
->
with_wild
,
select_lex
->
item_list
,
select_lex
->
where
,
select_lex
->
order_list
.
elements
+
select_lex
->
group_list
.
elements
,
(
ORDER
*
)
select_lex
->
order_list
.
first
,
(
ORDER
*
)
select_lex
->
group_list
.
first
,
select_lex
->
having
,
(
ORDER
*
)
lex
->
proc_list
.
first
,
select_lex
->
options
|
thd
->
options
,
&
(
lex
->
unit
),
select_lex
)))
goto
error
;
/* Statement and field info has already been sent */
DBUG_RETURN
(
0
);
default:
{
/*
Rest fall through to default category, no parsing
for non-DML statements
*/
if
(
send_prep_stmt
(
stmt
,
0
))
goto
abort
;
}
/*
Rest fall through to default category, no parsing
for non-DML statements
*/
break
;
}
DBUG_RETURN
(
0
);
DBUG_RETURN
(
send_prep_stmt
(
stmt
,
0
)
);
abort:
send_error
(
thd
,
thd
->
killed
?
ER_SERVER_SHUTDOWN
:
0
);
error:
if
(
res
<
0
)
send_error
(
thd
,
thd
->
killed
?
ER_SERVER_SHUTDOWN
:
0
);
DBUG_RETURN
(
1
);
}
/*
Initialize parameter items in statement
Initialize array of parametes in statement from LEX.
(We need to have quick access to items by number in mysql_send_longdata).
This is to avoid using malloc/realloc in the parser.
*/
static
bool
init_param_
items
(
Prepared_statement
*
stmt
)
static
bool
init_param_
array
(
Prepared_statement
*
stmt
)
{
Item_param
**
to
;
if
(
!
stmt
->
param_count
)
stmt
->
param
=
(
Item_param
**
)
0
;
else
{
if
(
!
(
stmt
->
param
=
to
=
(
Item_param
**
)
my_malloc
(
sizeof
(
Item_param
*
)
*
(
stmt
->
param_count
+
1
),
MYF
(
MY_WME
))))
LEX
*
lex
=
stmt
->
lex
;
if
((
stmt
->
param_count
=
lex
->
param_list
.
elements
))
{
Item_param
**
to
;
List_iterator
<
Item_param
>
param_iterator
(
lex
->
param_list
);
/* Use thd->mem_root as it points at statement mem_root */
stmt
->
param_array
=
(
Item_param
**
)
alloc_root
(
&
stmt
->
thd
->
mem_root
,
sizeof
(
Item_param
*
)
*
stmt
->
param_count
);
if
(
!
stmt
->
param_array
)
{
send_error
(
stmt
->
thd
,
ER_OUT_OF_RESOURCES
);
return
1
;
List_iterator
<
Item
>
param_iterator
(
stmt
->
lex
->
param_list
);
while
((
*
(
to
++
)
=
(
Item_param
*
)
param_iterator
++
));
}
}
for
(
to
=
stmt
->
param_array
;
to
<
stmt
->
param_array
+
stmt
->
param_count
;
++
to
)
{
*
to
=
param_iterator
++
;
}
}
return
0
;
}
...
...
@@ -912,137 +927,104 @@ static bool init_param_items(Prepared_statement *stmt)
/*
Parse the query and send the total number of parameters
and resultset metadata information back to client (if any),
without executing the query i.e. with
out any log/disk
without executing the query i.e. without any log/disk
writes. This will allow the queries to be re-executed
without re-parsing during execute.
If parameter markers are found in the query, then store
the information using Item_param along with maintaining a
list in lex->param_
list, so that a fast and direct
retrieval can be made without going through all field
items.
without re-parsing during execute.
If parameter markers are found in the query, then store
the information using Item_param along with maintaining a
list in lex->param_
array, so that a fast and direct
retrieval can be made without going through all field
items.
*/
bool
mysql_stmt_prepare
(
THD
*
thd
,
char
*
packet
,
uint
packet_length
)
void
mysql_stmt_prepare
(
THD
*
thd
,
char
*
packet
,
uint
packet_length
)
{
LEX
*
lex
;
Prepared_statement
*
stmt
=
new
Prepared_statement
(
thd
);
SELECT_LEX
*
sl
;
int
error
;
DBUG_ENTER
(
"mysql_stmt_prepare"
);
if
(
stmt
==
0
)
DBUG_RETURN
(
0
);
{
send_error
(
thd
,
ER_OUT_OF_RESOURCES
);
DBUG_VOID_RETURN
;
}
if
(
thd
->
stmt_map
.
insert
(
stmt
))
goto
insert_stmt_err
;
{
delete
stmt
;
send_error
(
thd
,
ER_OUT_OF_RESOURCES
);
DBUG_VOID_RETURN
;
}
thd
->
stmt_backup
.
set_statement
(
thd
);
thd
->
stmt_backup
.
set_item_arena
(
thd
);
thd
->
set_statement
(
stmt
);
thd
->
current_statement
=
stmt
;
thd
->
set_item_arena
(
stmt
)
;
if
(
alloc_query
(
thd
,
packet
,
packet_length
))
goto
alloc_query_err
;
{
stmt
->
set_statement
(
thd
);
stmt
->
set_item_arena
(
thd
);
thd
->
set_statement
(
&
thd
->
stmt_backup
);
thd
->
set_item_arena
(
&
thd
->
stmt_backup
);
/* Statement map deletes statement on erase */
thd
->
stmt_map
.
erase
(
stmt
);
send_error
(
thd
,
ER_OUT_OF_RESOURCES
);
DBUG_VOID_RETURN
;
}
mysql_log
.
write
(
thd
,
COM_PREPARE
,
"%s"
,
packet
);
mysql_log
.
write
(
thd
,
COM_PREPARE
,
"%s"
,
packet
);
thd
->
current_statement
=
stmt
;
lex
=
lex_start
(
thd
,
(
uchar
*
)
thd
->
query
,
thd
->
query_length
);
mysql_init_query
(
thd
);
lex
->
safe_to_cache_query
=
0
;
lex
->
param_count
=
0
;
if
(
yyparse
((
void
*
)
thd
)
||
thd
->
is_fatal_error
||
send_prepare_results
(
stmt
))
goto
yyparse_err
;
lex_end
(
lex
);
error
=
yyparse
((
void
*
)
thd
)
||
thd
->
is_fatal_error
||
init_param_array
(
stmt
)
||
send_prepare_results
(
stmt
);
/* restore to WAIT_PRIOR: QUERY_PRIOR is set inside alloc_query */
if
(
!
(
specialflag
&
SPECIAL_NO_PRIOR
))
my_pthread_setprio
(
pthread_self
(),
WAIT_PRIOR
);
// save WHERE clause pointers to avoid damaging they by optimisation
for
(
sl
=
thd
->
lex
->
all_selects_list
;
sl
;
sl
=
sl
->
next_select_in_list
())
{
sl
->
prep_where
=
sl
->
where
;
}
stmt
->
set_statement
(
thd
);
thd
->
set_statement
(
&
thd
->
stmt_backup
);
thd
->
current_statement
=
0
;
if
(
init_param_items
(
stmt
))
goto
init_param_err
;
stmt
->
command
=
COM_EXECUTE
;
// set it only once here
DBUG_RETURN
(
0
);
yyparse_err:
lex_end
(
lex
);
stmt
->
set_statement
(
thd
);
stmt
->
set_item_arena
(
thd
);
thd
->
set_statement
(
&
thd
->
stmt_backup
);
init_param_err:
alloc_query_err:
/* Statement map deletes statement on erase */
thd
->
stmt_map
.
erase
(
stmt
);
thd
->
current_statement
=
0
;
DBUG_RETURN
(
1
);
insert_stmt_err:
stmt
->
set_statement
(
thd
);
thd
->
set_statement
(
&
thd
->
stmt_backup
);
/* Statement map deletes statement on erase */
thd
->
stmt_map
.
erase
(
stmt
);
thd
->
set_item_arena
(
&
thd
->
stmt_backup
);
thd
->
current_statement
=
0
;
delete
stmt
;
DBUG_RETURN
(
1
);
}
/*
Executes previously prepared query
If there is any parameters (stmt->param_count), then replace
markers with the data supplied from client, and then
execute the query
*/
void
mysql_stmt_execute
(
THD
*
thd
,
char
*
packet
)
{
ulong
stmt_id
=
uint4korr
(
packet
);
Prepared_statement
*
stmt
;
DBUG_ENTER
(
"mysql_stmt_execute"
);
if
(
!
(
stmt
=
find_prepared_statement
(
thd
,
stmt_id
,
"execute"
)))
DBUG_VOID_RETURN
;
/* Check if we got an error when sending long data */
if
(
stmt
->
error_in_prepare
)
if
(
error
)
{
send_error
(
thd
,
stmt
->
last_errno
,
stmt
->
last_error
);
DBUG_VOID_RETURN
;
/* Statement map deletes statement on erase */
thd
->
stmt_map
.
erase
(
stmt
);
/* error is sent inside yyparse/send_prepare_results */
}
else
{
SELECT_LEX
*
sl
=
stmt
->
lex
->
all_selects_list
;
/*
Save WHERE clause pointers, because they may be changed during query
optimisation.
*/
for
(;
sl
;
sl
=
sl
->
next_select_in_list
())
{
sl
->
prep_where
=
sl
->
where
;
}
}
DBUG_VOID_RETURN
;
}
stmt
->
query_id
=
thd
->
query_id
;
thd
->
stmt_backup
.
set_statement
(
thd
);
thd
->
set_statement
(
stmt
);
thd
->
free_list
=
0
;
/*
To make sure that all runtime data is stored in its own memory root and
does not interfere with data possibly present in thd->mem_root.
This root is cleaned up in the end of execution.
FIXME: to be replaced with more efficient approach, and verified why we
can not use thd->mem_root safely.
*/
init_sql_alloc
(
&
thd
->
mem_root
,
thd
->
variables
.
query_alloc_block_size
,
thd
->
variables
.
query_prealloc_size
);
/* Reinit statement before execution */
static
void
reset_stmt_for_execute
(
Prepared_statement
*
stmt
)
{
THD
*
thd
=
stmt
->
thd
;
SELECT_LEX
*
sl
=
stmt
->
lex
->
all_selects_list
;
for
(
SELECT_LEX
*
sl
=
stmt
->
lex
->
all_selects_list
;
sl
;
sl
=
sl
->
next_select_in_list
())
for
(;
sl
;
sl
=
sl
->
next_select_in_list
())
{
/*
Copy WHERE clause pointers to avoid damaging they by optimisation
...
...
@@ -1075,58 +1057,104 @@ void mysql_stmt_execute(THD *thd, char *packet)
SELECT_LEX_UNIT
*
unit
=
sl
->
master_unit
();
unit
->
unclean
();
unit
->
types
.
empty
();
/
/ for derived tables & PS (which can't be reset by Item_subquery)
/
* for derived tables & PS (which can't be reset by Item_subquery) */
unit
->
reinit_exec_mechanism
();
}
}
}
/*
Executes previously prepared query.
If there is any parameters, then replace markers with the data supplied
from client, and then execute the query.
SYNOPSYS
mysql_stmt_execute()
*/
void
mysql_stmt_execute
(
THD
*
thd
,
char
*
packet
)
{
ulong
stmt_id
=
uint4korr
(
packet
);
Prepared_statement
*
stmt
;
DBUG_ENTER
(
"mysql_stmt_execute"
);
if
(
!
(
stmt
=
find_prepared_statement
(
thd
,
stmt_id
,
"execute"
,
SEND_ERROR
)))
DBUG_VOID_RETURN
;
/* Check if we got an error when sending long data */
if
(
stmt
->
get_longdata_error
)
{
send_error
(
thd
,
stmt
->
last_errno
,
stmt
->
last_error
);
DBUG_VOID_RETURN
;
}
thd
->
stmt_backup
.
set_statement
(
thd
);
thd
->
set_statement
(
stmt
);
reset_stmt_for_execute
(
stmt
);
#ifndef EMBEDDED_LIBRARY
if
(
stmt
->
param_count
&&
setup_params_data
(
stmt
))
goto
end
;
if
(
stmt
->
param_count
)
{
packet
+=
4
;
uchar
*
null_array
=
(
uchar
*
)
packet
;
if
(
setup_conversion_functions
(
stmt
,
(
uchar
**
)
&
packet
)
||
stmt
->
set_params
(
stmt
,
null_array
,
(
uchar
*
)
packet
))
goto
set_params_data_err
;
}
#else
if
(
stmt
->
param_count
&&
(
*
stmt
->
setup_params_data
)(
stmt
))
goto
end
;
/*
In embedded library we re-install conversion routines each time
we set params, and also we don't need to parse packet.
So we do it in one function.
*/
if
(
stmt
->
param_count
&&
stmt
->
set_params_data
(
stmt
))
goto
set_params_data_err
;
#endif
if
(
!
(
specialflag
&
SPECIAL_NO_PRIOR
))
my_pthread_setprio
(
pthread_self
(),
QUERY_PRIOR
);
my_pthread_setprio
(
pthread_self
(),
QUERY_PRIOR
);
/*
TODO:
Also, have checks on basic executions such as mysql_insert(),
mysql_delete(), mysql_update() and mysql_select() to not to
have re-check on setup_* and other things ..
*/
thd
->
protocol
=
&
thd
->
protocol_prep
;
// Switch to binary protocol
*/
thd
->
protocol
=
&
thd
->
protocol_prep
;
// Switch to binary protocol
mysql_execute_command
(
thd
);
thd
->
protocol
=
&
thd
->
protocol_simple
;
// Use normal protocol
thd
->
protocol
=
&
thd
->
protocol_simple
;
// Use normal protocol
if
(
!
(
specialflag
&
SPECIAL_NO_PRIOR
))
my_pthread_setprio
(
pthread_self
(),
WAIT_PRIOR
);
free_items
(
thd
->
free_list
);
cleanup_items
(
stmt
->
free_list
);
close_thread_tables
(
thd
);
// to close derived tables
free_root
(
&
thd
->
mem_root
,
MYF
(
0
));
thd
->
set_statement
(
&
thd
->
stmt_backup
);
end:
DBUG_VOID_RETURN
;
set_params_data_err:
thd
->
set_statement
(
&
thd
->
stmt_backup
);
my_error
(
ER_WRONG_ARGUMENTS
,
MYF
(
0
),
"mysql_execute"
);
send_error
(
thd
);
DBUG_VOID_RETURN
;
}
/*
Reset a prepared statement
Reset a prepared statement, in case there was an error in send_longdata.
Note: we don't send any reply to that command.
SYNOPSIS
mysql_stmt_reset()
thd Thread handle
packet Packet with stmt
handle
packet Packet with stmt
id
DESCRIPTION
This function is useful when one gets an error after calling
mysql_stmt_getlongdata() and
one
wants to reset the handle
mysql_stmt_getlongdata() and wants to reset the handle
so that one can call execute again.
See also bug #1664
*/
void
mysql_stmt_reset
(
THD
*
thd
,
char
*
packet
)
...
...
@@ -1136,25 +1164,27 @@ void mysql_stmt_reset(THD *thd, char *packet)
DBUG_ENTER
(
"mysql_stmt_reset"
);
if
(
!
(
stmt
=
find_prepared_statement
(
thd
,
stmt_id
,
"reset"
)))
if
(
!
(
stmt
=
find_prepared_statement
(
thd
,
stmt_id
,
"reset"
,
DONT_SEND_ERROR
)))
DBUG_VOID_RETURN
;
stmt
->
error_in_prepare
=
0
;
Item_param
*
item
=
*
stmt
->
param
,
*
end
=
item
+
stmt
->
param_count
;
stmt
->
get_longdata_error
=
0
;
/* Free long data if used */
if
(
stmt
->
long_data_used
)
{
Item_param
**
item
=
stmt
->
param_array
;
Item_param
**
end
=
item
+
stmt
->
param_count
;
stmt
->
long_data_used
=
0
;
for
(;
item
<
end
;
item
++
)
item
->
reset
();
(
**
item
).
reset
();
}
DBUG_VOID_RETURN
;
}
/*
Delete a prepared statement from memory
Delete a prepared statement from memory.
Note: we don't send any reply to that command.
*/
void
mysql_stmt_free
(
THD
*
thd
,
char
*
packet
)
...
...
@@ -1164,7 +1194,7 @@ void mysql_stmt_free(THD *thd, char *packet)
DBUG_ENTER
(
"mysql_stmt_free"
);
if
(
!
(
stmt
=
find_prepared_statement
(
thd
,
stmt_id
,
"close"
)))
if
(
!
(
stmt
=
find_prepared_statement
(
thd
,
stmt_id
,
"close"
,
DONT_SEND_ERROR
)))
DBUG_VOID_RETURN
;
/* Statement map deletes statement on erase */
...
...
@@ -1174,7 +1204,7 @@ void mysql_stmt_free(THD *thd, char *packet)
/*
Long data in pieces from client
Long data in pieces from client
SYNOPSIS
mysql_stmt_get_longdata()
...
...
@@ -1210,14 +1240,15 @@ void mysql_stmt_get_longdata(THD *thd, char *pos, ulong packet_length)
ulong
stmt_id
=
uint4korr
(
pos
);
uint
param_number
=
uint2korr
(
pos
+
4
);
if
(
!
(
stmt
=
find_prepared_statement
(
thd
,
stmt_id
,
"get_longdata"
)))
if
(
!
(
stmt
=
find_prepared_statement
(
thd
,
stmt_id
,
"get_longdata"
,
DONT_SEND_ERROR
)))
DBUG_VOID_RETURN
;
#ifndef EMBEDDED_LIBRARY
if
(
param_number
>=
stmt
->
param_count
)
{
/* Error will be sent in execute call */
stmt
->
error_in_prepare
=
1
;
stmt
->
get_longdata_error
=
1
;
stmt
->
last_errno
=
ER_WRONG_ARGUMENTS
;
sprintf
(
stmt
->
last_error
,
ER
(
ER_WRONG_ARGUMENTS
),
"get_longdata"
);
DBUG_VOID_RETURN
;
...
...
@@ -1225,7 +1256,7 @@ void mysql_stmt_get_longdata(THD *thd, char *pos, ulong packet_length)
pos
+=
MYSQL_LONG_DATA_HEADER
;
// Point to data
#endif
Item_param
*
param
=
*
(
stmt
->
param
+
param_number
)
;
Item_param
*
param
=
stmt
->
param_array
[
param_number
]
;
#ifndef EMBEDDED_LIBRARY
param
->
set_longdata
(
pos
,
packet_length
-
MYSQL_LONG_DATA_HEADER
-
1
);
#else
...
...
@@ -1239,10 +1270,10 @@ void mysql_stmt_get_longdata(THD *thd, char *pos, ulong packet_length)
Prepared_statement
::
Prepared_statement
(
THD
*
thd_arg
)
:
Statement
(
thd_arg
),
thd
(
thd_arg
),
param
(
0
),
param
_array
(
0
),
param_count
(
0
),
last_errno
(
0
),
error_in_prepare
(
0
),
get_longdata_error
(
0
),
long_data_used
(
0
),
log_full_query
(
0
)
{
...
...
@@ -1251,23 +1282,22 @@ Prepared_statement::Prepared_statement(THD *thd_arg)
{
log_full_query
=
1
;
#ifndef EMBEDDED_LIBRARY
set
up
_params
=
insert_params_withlog
;
set_params
=
insert_params_withlog
;
#else
set
up_params_data
=
setup_params_data
_withlog
;
set
_params_data
=
emb_insert_params
_withlog
;
#endif
}
else
#ifndef EMBEDDED_LIBRARY
set
up_params
=
insert_params
;
// not fully qualified query
set
_params
=
insert_params
;
#else
set
up_params_data
=
::
setup_params_data
;
set
_params_data
=
emb_insert_params
;
#endif
}
Prepared_statement
::~
Prepared_statement
()
{
my_free
((
char
*
)
param
,
MYF
(
MY_ALLOW_ZERO_PTR
));
free_items
(
free_list
);
}
...
...
@@ -1277,4 +1307,3 @@ Statement::Type Prepared_statement::type() const
return
PREPARED_STATEMENT
;
}
sql/sql_yacc.yy
View file @
5cacc972
...
...
@@ -4478,11 +4478,17 @@ text_string:
param_marker:
'?'
{
LEX *lex=Lex;
if (YYTHD->command == COM_PREPARE)
THD *thd=YYTHD;
LEX *lex= thd->lex;
if (thd->command == COM_PREPARE)
{
lex->param_list.push_back($$=new Item_param((uint)(lex->tok_start-(uchar *)YYTHD->query)));
lex->param_count++;
Item_param *item= new Item_param((uint) (lex->tok_start -
(uchar *) thd->query));
if (!($$= item) || lex->param_list.push_back(item))
{
send_error(thd, ER_OUT_OF_RESOURCES);
YYABORT;
}
}
else
{
...
...
tests/client_test.c
View file @
5cacc972
...
...
@@ -8470,8 +8470,6 @@ int main(int argc, char **argv)
start_time
=
time
((
time_t
*
)
0
);
test_subqueries
();
client_query
();
/* simple client query test */
#if NOT_YET_WORKING
/* Used for internal new development debugging */
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment