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
eaa4d106
Commit
eaa4d106
authored
May 31, 2004
by
konstantin@mysql.com
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix for Bug#3796 "Prepared statement, select concat(<parameter>,<column>), wrong
result": new Item_param member for use in val_str()
parent
c942a7ec
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
136 additions
and
6 deletions
+136
-6
sql/item.cc
sql/item.cc
+10
-3
sql/item.h
sql/item.h
+39
-0
tests/client_test.c
tests/client_test.c
+87
-3
No files found.
sql/item.cc
View file @
eaa4d106
...
...
@@ -753,9 +753,10 @@ void Item_param::reset()
str_value
.
free
();
else
str_value
.
length
(
0
);
str_value_ptr
.
length
(
0
);
/*
We must prevent all charset conversions un
less data of str_value
has been written
to the binary log.
We must prevent all charset conversions un
till data has been written
to the binary log.
*/
str_value
.
set_charset
(
&
my_charset_bin
);
state
=
NO_VALUE
;
...
...
@@ -866,7 +867,7 @@ String *Item_param::val_str(String* str)
switch
(
state
)
{
case
STRING_VALUE
:
case
LONG_DATA_VALUE
:
return
&
str_value
;
return
&
str_value
_ptr
;
case
REAL_VALUE
:
str
->
set
(
value
.
real
,
NOT_FIXED_DEC
,
&
my_charset_bin
);
return
str
;
...
...
@@ -980,6 +981,12 @@ bool Item_param::convert_str_value(THD *thd)
}
max_length
=
str_value
.
length
();
decimals
=
0
;
/*
str_value_ptr is returned from val_str(). It must be not alloced
to prevent it's modification by val_str() invoker.
*/
str_value_ptr
.
set
(
str_value
.
ptr
(),
str_value
.
length
(),
str_value
.
charset
());
}
return
rc
;
}
...
...
sql/item.h
View file @
eaa4d106
...
...
@@ -160,6 +160,31 @@ public:
/* valXXX methods must return NULL or 0 or 0.0 if null_value is set. */
virtual
double
val
()
=
0
;
virtual
longlong
val_int
()
=
0
;
/*
Return string representation of this item object.
The argument to val_str() is an allocated buffer this or any
nested Item object can use to store return value of this method.
This buffer should only be used if the item itself doesn't have an
own String buffer. In case when the item maintains it's own string
buffer, it's preferrable to return it instead to minimize number of
mallocs/memcpys.
The caller of this method can modify returned string, but only in
case when it was allocated on heap, (is_alloced() is true). This
allows the caller to efficiently use a buffer allocated by a child
without having to allocate a buffer of it's own. The buffer, given
to val_str() as agrument, belongs to the caller and is later used
by the caller at it's own choosing.
A few implications from the above:
- unless you return a string object which only points to your buffer
but doesn't manages it you should be ready that it will be
modified.
- even for not allocated strings (is_alloced() == false) the caller
can change charset (see Item_func_{typecast/binary}. XXX: is this
a bug?
- still you should try to minimize data copying and return internal
object whenever possible.
*/
virtual
String
*
val_str
(
String
*
)
=
0
;
virtual
Field
*
get_tmp_table_field
()
{
return
0
;
}
virtual
Field
*
tmp_table_field
(
TABLE
*
t_arg
)
{
return
0
;
}
...
...
@@ -390,6 +415,9 @@ public:
void
print
(
String
*
str
)
{
str
->
append
(
"NULL"
,
4
);
}
};
/* Item represents one placeholder ('?') of prepared statement */
class
Item_param
:
public
Item
{
public:
...
...
@@ -399,6 +427,17 @@ public:
STRING_VALUE
,
TIME_VALUE
,
LONG_DATA_VALUE
}
state
;
/*
A buffer for string and long data values. Historically all allocated
values returned from val_str() were treated as eligible to
modification. I. e. in some cases Item_func_concat can append it's
second argument to return value of the first one. Because of that we
can't return the original buffer holding string data from val_str(),
and have to have one buffer for data and another just pointing to
the data. This is the latter one and it's returned from val_str().
Can not be declared inside the union as it's not a POD type.
*/
String
str_value_ptr
;
union
{
longlong
integer
;
...
...
tests/client_test.c
View file @
eaa4d106
...
...
@@ -9670,12 +9670,12 @@ static void test_union_param()
/* bind parameters */
bind
[
0
].
buffer_type
=
FIELD_TYPE_STRING
;
bind
[
0
].
buffer
=
&
my_val
;
bind
[
0
].
buffer
=
(
char
*
)
&
my_val
;
bind
[
0
].
buffer_length
=
4
;
bind
[
0
].
length
=
&
my_length
;
bind
[
0
].
is_null
=
(
char
*
)
&
my_null
;
bind
[
1
].
buffer_type
=
FIELD_TYPE_STRING
;
bind
[
1
].
buffer
=
&
my_val
;
bind
[
1
].
buffer
=
(
char
*
)
&
my_val
;
bind
[
1
].
buffer_length
=
4
;
bind
[
1
].
length
=
&
my_length
;
bind
[
1
].
is_null
=
(
char
*
)
&
my_null
;
...
...
@@ -9872,7 +9872,90 @@ static void test_ps_i18n()
mysql_stmt_close
(
stmt
);
stmt_text
=
"DROP TABLE t1"
;
mysql_real_query
(
mysql
,
stmt_text
,
strlen
(
stmt_text
));
rc
=
mysql_real_query
(
mysql
,
stmt_text
,
strlen
(
stmt_text
));
myquery
(
rc
);
stmt_text
=
"SET NAMES DEFAULT"
;
rc
=
mysql_real_query
(
mysql
,
stmt_text
,
strlen
(
stmt_text
));
myquery
(
rc
);
}
static
void
test_bug3796
()
{
MYSQL_STMT
*
stmt
;
MYSQL_BIND
bind
[
1
];
const
char
*
concat_arg0
=
"concat_with_"
;
const
int
OUT_BUFF_SIZE
=
30
;
char
out_buff
[
OUT_BUFF_SIZE
];
char
canonical_buff
[
OUT_BUFF_SIZE
];
ulong
out_length
;
const
char
*
stmt_text
;
int
rc
;
myheader
(
"test_bug3796"
);
/* Create and fill test table */
stmt_text
=
"DROP TABLE IF EXISTS t1"
;
rc
=
mysql_real_query
(
mysql
,
stmt_text
,
strlen
(
stmt_text
));
myquery
(
rc
);
stmt_text
=
"CREATE TABLE t1 (a INT, b VARCHAR(30))"
;
rc
=
mysql_real_query
(
mysql
,
stmt_text
,
strlen
(
stmt_text
));
myquery
(
rc
);
stmt_text
=
"INSERT INTO t1 VALUES(1,'ONE'), (2,'TWO')"
;
rc
=
mysql_real_query
(
mysql
,
stmt_text
,
strlen
(
stmt_text
));
myquery
(
rc
);
/* Create statement handle and prepare it with select */
stmt
=
mysql_stmt_init
(
mysql
);
stmt_text
=
"SELECT concat(?, b) FROM t1"
;
rc
=
mysql_stmt_prepare
(
stmt
,
stmt_text
,
strlen
(
stmt_text
));
check_execute
(
stmt
,
rc
);
/* Bind input buffers */
bzero
(
bind
,
sizeof
(
bind
));
bind
[
0
].
buffer_type
=
MYSQL_TYPE_STRING
;
bind
[
0
].
buffer
=
(
char
*
)
concat_arg0
;
bind
[
0
].
buffer_length
=
strlen
(
concat_arg0
);
mysql_stmt_bind_param
(
stmt
,
bind
);
/* Execute the select statement */
rc
=
mysql_stmt_execute
(
stmt
);
check_execute
(
stmt
,
rc
);
bind
[
0
].
buffer
=
(
char
*
)
out_buff
;
bind
[
0
].
buffer_length
=
OUT_BUFF_SIZE
;
bind
[
0
].
length
=
&
out_length
;
mysql_stmt_bind_result
(
stmt
,
bind
);
rc
=
mysql_stmt_fetch
(
stmt
);
printf
(
"Concat result: '%s'
\n
"
,
out_buff
);
check_execute
(
stmt
,
rc
);
strcpy
(
canonical_buff
,
concat_arg0
);
strcat
(
canonical_buff
,
"ONE"
);
assert
(
strlen
(
canonical_buff
)
==
out_length
&&
strncmp
(
out_buff
,
canonical_buff
,
out_length
)
==
0
);
rc
=
mysql_stmt_fetch
(
stmt
);
check_execute
(
stmt
,
rc
);
strcpy
(
canonical_buff
+
strlen
(
concat_arg0
),
"TWO"
);
assert
(
strlen
(
canonical_buff
)
==
out_length
&&
strncmp
(
out_buff
,
canonical_buff
,
out_length
)
==
0
);
printf
(
"Concat result: '%s'
\n
"
,
out_buff
);
rc
=
mysql_stmt_fetch
(
stmt
);
assert
(
rc
==
MYSQL_NO_DATA
);
mysql_stmt_close
(
stmt
);
stmt_text
=
"DROP TABLE IF EXISTS t1"
;
rc
=
mysql_real_query
(
mysql
,
stmt_text
,
strlen
(
stmt_text
));
myquery
(
rc
);
}
/*
...
...
@@ -10164,6 +10247,7 @@ int main(int argc, char **argv)
test_order_param
();
/* ORDER BY with parameters in select list
(Bug #3686 */
test_ps_i18n
();
/* test for i18n support in binary protocol */
test_bug3796
();
/* test for select concat(?, <string>) */
end_time
=
time
((
time_t
*
)
0
);
total_time
+=
difftime
(
end_time
,
start_time
);
...
...
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