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
018b8025
Commit
018b8025
authored
May 03, 2005
by
konstantin@mysql.com
Browse files
Options
Browse Files
Download
Plain Diff
Merge mysql.com:/opt/local/work/mysql-4.1-root
into mysql.com:/opt/local/work/mysql-4.1-9096-fresh
parents
8e87db93
3589e78f
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
192 additions
and
9 deletions
+192
-9
mysql-test/r/ps.result
mysql-test/r/ps.result
+25
-0
mysql-test/t/ps.test
mysql-test/t/ps.test
+26
-0
sql/item.cc
sql/item.cc
+113
-1
sql/item.h
sql/item.h
+23
-4
sql/item_func.cc
sql/item_func.cc
+5
-4
No files found.
mysql-test/r/ps.result
View file @
018b8025
...
@@ -494,3 +494,28 @@ SELECT FOUND_ROWS();
...
@@ -494,3 +494,28 @@ SELECT FOUND_ROWS();
FOUND_ROWS()
FOUND_ROWS()
2
2
deallocate prepare stmt;
deallocate prepare stmt;
drop table if exists t1;
Warnings:
Note 1051 Unknown table 't1'
create table t1 (c1 int(11) not null, c2 int(11) not null,
primary key (c1,c2), key c2 (c2), key c1 (c1));
insert into t1 values (200887, 860);
insert into t1 values (200887, 200887);
select * from t1 where (c1=200887 and c2=200887) or c2=860;
c1 c2
200887 860
200887 200887
prepare stmt from
"select * from t1 where (c1=200887 and c2=200887) or c2=860";
execute stmt;
c1 c2
200887 860
200887 200887
prepare stmt from
"select * from t1 where (c1=200887 and c2=?) or c2=?";
set @a=200887, @b=860;
execute stmt using @a, @b;
c1 c2
200887 860
200887 200887
deallocate prepare stmt;
mysql-test/t/ps.test
View file @
018b8025
...
@@ -496,3 +496,29 @@ SELECT FOUND_ROWS();
...
@@ -496,3 +496,29 @@ SELECT FOUND_ROWS();
execute
stmt
;
execute
stmt
;
SELECT
FOUND_ROWS
();
SELECT
FOUND_ROWS
();
deallocate
prepare
stmt
;
deallocate
prepare
stmt
;
#
# Bug#9096 "select doesn't return all matched records if prepared statements
# is used"
# The bug was is bad co-operation of the optimizer's algorithm which determines
# which keys can be used to execute a query, constants propagation
# part of the optimizer and parameter markers used by prepared statements.
drop
table
if
exists
t1
;
create
table
t1
(
c1
int
(
11
)
not
null
,
c2
int
(
11
)
not
null
,
primary
key
(
c1
,
c2
),
key
c2
(
c2
),
key
c1
(
c1
));
insert
into
t1
values
(
200887
,
860
);
insert
into
t1
values
(
200887
,
200887
);
select
*
from
t1
where
(
c1
=
200887
and
c2
=
200887
)
or
c2
=
860
;
prepare
stmt
from
"select * from t1 where (c1=200887 and c2=200887) or c2=860"
;
execute
stmt
;
prepare
stmt
from
"select * from t1 where (c1=200887 and c2=?) or c2=?"
;
set
@
a
=
200887
,
@
b
=
860
;
# this query did not return all matching rows
execute
stmt
using
@
a
,
@
b
;
deallocate
prepare
stmt
;
sql/item.cc
View file @
018b8025
...
@@ -200,6 +200,11 @@ void Item::set_name(const char *str, uint length, CHARSET_INFO *cs)
...
@@ -200,6 +200,11 @@ void Item::set_name(const char *str, uint length, CHARSET_INFO *cs)
bool
Item
::
eq
(
const
Item
*
item
,
bool
binary_cmp
)
const
bool
Item
::
eq
(
const
Item
*
item
,
bool
binary_cmp
)
const
{
{
/*
Note, that this is never TRUE if item is a Item_param:
for all basic constants we have special checks, and Item_param's
type() can be only among basic constant types.
*/
return
type
()
==
item
->
type
()
&&
name
&&
item
->
name
&&
return
type
()
==
item
->
type
()
&&
name
&&
item
->
name
&&
!
my_strcasecmp
(
system_charset_info
,
name
,
item
->
name
);
!
my_strcasecmp
(
system_charset_info
,
name
,
item
->
name
);
}
}
...
@@ -254,7 +259,7 @@ Item *Item_string::safe_charset_converter(CHARSET_INFO *tocs)
...
@@ -254,7 +259,7 @@ Item *Item_string::safe_charset_converter(CHARSET_INFO *tocs)
bool
Item_string
::
eq
(
const
Item
*
item
,
bool
binary_cmp
)
const
bool
Item_string
::
eq
(
const
Item
*
item
,
bool
binary_cmp
)
const
{
{
if
(
type
()
==
item
->
type
())
if
(
type
()
==
item
->
type
()
&&
item
->
basic_const_item
()
)
{
{
if
(
binary_cmp
)
if
(
binary_cmp
)
return
!
stringcmp
(
&
str_value
,
&
item
->
str_value
);
return
!
stringcmp
(
&
str_value
,
&
item
->
str_value
);
...
@@ -1356,6 +1361,70 @@ bool Item_param::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
...
@@ -1356,6 +1361,70 @@ bool Item_param::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
return
0
;
return
0
;
}
}
bool
Item_param
::
basic_const_item
()
const
{
if
(
state
==
NO_VALUE
||
state
==
TIME_VALUE
)
return
FALSE
;
return
TRUE
;
}
Item
*
Item_param
::
new_item
()
{
/* see comments in the header file */
switch
(
state
)
{
case
NULL_VALUE
:
return
new
Item_null
(
name
);
case
INT_VALUE
:
return
new
Item_int
(
name
,
value
.
integer
,
max_length
);
case
REAL_VALUE
:
return
new
Item_real
(
name
,
value
.
real
,
decimals
,
max_length
);
case
STRING_VALUE
:
case
LONG_DATA_VALUE
:
return
new
Item_string
(
name
,
str_value
.
c_ptr_quick
(),
str_value
.
length
(),
str_value
.
charset
());
case
TIME_VALUE
:
break
;
case
NO_VALUE
:
default:
DBUG_ASSERT
(
0
);
};
return
0
;
}
bool
Item_param
::
eq
(
const
Item
*
arg
,
bool
binary_cmp
)
const
{
Item
*
item
;
if
(
!
basic_const_item
()
||
!
arg
->
basic_const_item
()
||
arg
->
type
()
!=
type
())
return
FALSE
;
/*
We need to cast off const to call val_int(). This should be OK for
a basic constant.
*/
item
=
(
Item
*
)
arg
;
switch
(
state
)
{
case
NULL_VALUE
:
return
TRUE
;
case
INT_VALUE
:
return
value
.
integer
==
item
->
val_int
()
&&
unsigned_flag
==
item
->
unsigned_flag
;
case
REAL_VALUE
:
return
value
.
real
==
item
->
val
();
case
STRING_VALUE
:
case
LONG_DATA_VALUE
:
if
(
binary_cmp
)
return
!
stringcmp
(
&
str_value
,
&
item
->
str_value
);
return
!
sortcmp
(
&
str_value
,
&
item
->
str_value
,
collation
.
collation
);
default:
break
;
}
return
FALSE
;
}
/* End of Item_param related */
/* End of Item_param related */
...
@@ -1937,6 +2006,23 @@ int Item_int::save_in_field(Field *field, bool no_conversions)
...
@@ -1937,6 +2006,23 @@ int Item_int::save_in_field(Field *field, bool no_conversions)
return
field
->
store
(
nr
);
return
field
->
store
(
nr
);
}
}
bool
Item_int
::
eq
(
const
Item
*
arg
,
bool
binary_cmp
)
const
{
/* No need to check for null value as basic constant can't be NULL */
if
(
arg
->
basic_const_item
()
&&
arg
->
type
()
==
type
())
{
/*
We need to cast off const to call val_int(). This should be OK for
a basic constant.
*/
Item
*
item
=
(
Item
*
)
arg
;
return
item
->
val_int
()
==
value
&&
item
->
unsigned_flag
==
unsigned_flag
;
}
return
FALSE
;
}
Item_num
*
Item_uint
::
neg
()
Item_num
*
Item_uint
::
neg
()
{
{
return
new
Item_real
(
name
,
-
((
double
)
value
),
0
,
max_length
);
return
new
Item_real
(
name
,
-
((
double
)
value
),
0
,
max_length
);
...
@@ -1951,6 +2037,21 @@ int Item_real::save_in_field(Field *field, bool no_conversions)
...
@@ -1951,6 +2037,21 @@ int Item_real::save_in_field(Field *field, bool no_conversions)
return
field
->
store
(
nr
);
return
field
->
store
(
nr
);
}
}
bool
Item_real
::
eq
(
const
Item
*
arg
,
bool
binary_cmp
)
const
{
if
(
arg
->
basic_const_item
()
&&
arg
->
type
()
==
type
())
{
/*
We need to cast off const to call val_int(). This should be OK for
a basic constant.
*/
Item
*
item
=
(
Item
*
)
arg
;
return
item
->
val
()
==
value
;
}
return
FALSE
;
}
/****************************************************************************
/****************************************************************************
** varbinary item
** varbinary item
** In string context this is a binary string
** In string context this is a binary string
...
@@ -2017,6 +2118,17 @@ int Item_varbinary::save_in_field(Field *field, bool no_conversions)
...
@@ -2017,6 +2118,17 @@ int Item_varbinary::save_in_field(Field *field, bool no_conversions)
}
}
bool
Item_varbinary
::
eq
(
const
Item
*
arg
,
bool
binary_cmp
)
const
{
if
(
arg
->
basic_const_item
()
&&
arg
->
type
()
==
type
())
{
if
(
binary_cmp
)
return
!
stringcmp
(
&
str_value
,
&
arg
->
str_value
);
return
!
sortcmp
(
&
str_value
,
&
arg
->
str_value
,
collation
.
collation
);
}
return
FALSE
;
}
/*
/*
Pack data in buffer for sending
Pack data in buffer for sending
*/
*/
...
...
sql/item.h
View file @
018b8025
...
@@ -235,7 +235,7 @@ public:
...
@@ -235,7 +235,7 @@ public:
virtual
table_map
not_null_tables
()
const
{
return
used_tables
();
}
virtual
table_map
not_null_tables
()
const
{
return
used_tables
();
}
/*
/*
Returns true if this is a simple constant item like an integer, not
Returns true if this is a simple constant item like an integer, not
a constant expression
a constant expression
. Used in the optimizer to propagate basic constants.
*/
*/
virtual
bool
basic_const_item
()
const
{
return
0
;
}
virtual
bool
basic_const_item
()
const
{
return
0
;
}
/* cloning of constant items (0 if it is not const) */
/* cloning of constant items (0 if it is not const) */
...
@@ -586,7 +586,6 @@ public:
...
@@ -586,7 +586,6 @@ public:
bool
convert_str_value
(
THD
*
thd
);
bool
convert_str_value
(
THD
*
thd
);
Item
*
new_item
()
{
return
new
Item_param
(
pos_in_query
);
}
/*
/*
If value for parameter was not set we treat it as non-const
If value for parameter was not set we treat it as non-const
so noone will use parameters value in fix_fields still
so noone will use parameters value in fix_fields still
...
@@ -595,12 +594,29 @@ public:
...
@@ -595,12 +594,29 @@ public:
virtual
table_map
used_tables
()
const
virtual
table_map
used_tables
()
const
{
return
state
!=
NO_VALUE
?
(
table_map
)
0
:
PARAM_TABLE_BIT
;
}
{
return
state
!=
NO_VALUE
?
(
table_map
)
0
:
PARAM_TABLE_BIT
;
}
void
print
(
String
*
str
)
{
str
->
append
(
'?'
);
}
void
print
(
String
*
str
)
{
str
->
append
(
'?'
);
}
/* parameter never equal to other parameter of other item */
bool
eq
(
const
Item
*
item
,
bool
binary_cmp
)
const
{
return
0
;
}
bool
is_null
()
bool
is_null
()
{
DBUG_ASSERT
(
state
!=
NO_VALUE
);
return
state
==
NULL_VALUE
;
}
{
DBUG_ASSERT
(
state
!=
NO_VALUE
);
return
state
==
NULL_VALUE
;
}
bool
basic_const_item
()
const
;
/*
This method is used to make a copy of a basic constant item when
propagating constants in the optimizer. The reason to create a new
item and not use the existing one is not precisely known (2005/04/16).
Probably we are trying to preserve tree structure of items, in other
words, avoid pointing at one item from two different nodes of the tree.
Return a new basic constant item if parameter value is a basic
constant, assert otherwise. This method is called only if
basic_const_item returned TRUE.
*/
Item
*
new_item
();
/*
Implement by-value equality evaluation if parameter value
is set and is a basic constant (integer, real or string).
Otherwise return FALSE.
*/
bool
eq
(
const
Item
*
item
,
bool
binary_cmp
)
const
;
};
};
class
Item_int
:
public
Item_num
class
Item_int
:
public
Item_num
{
{
public:
public:
...
@@ -627,6 +643,7 @@ public:
...
@@ -627,6 +643,7 @@ public:
void
cleanup
()
{}
void
cleanup
()
{}
void
print
(
String
*
str
);
void
print
(
String
*
str
);
Item_num
*
neg
()
{
value
=
-
value
;
return
this
;
}
Item_num
*
neg
()
{
value
=
-
value
;
return
this
;
}
bool
eq
(
const
Item
*
,
bool
binary_cmp
)
const
;
};
};
...
@@ -682,6 +699,7 @@ public:
...
@@ -682,6 +699,7 @@ public:
void
cleanup
()
{}
void
cleanup
()
{}
Item
*
new_item
()
{
return
new
Item_real
(
name
,
value
,
decimals
,
max_length
);
}
Item
*
new_item
()
{
return
new
Item_real
(
name
,
value
,
decimals
,
max_length
);
}
Item_num
*
neg
()
{
value
=
-
value
;
return
this
;
}
Item_num
*
neg
()
{
value
=
-
value
;
return
this
;
}
bool
eq
(
const
Item
*
,
bool
binary_cmp
)
const
;
};
};
...
@@ -815,6 +833,7 @@ public:
...
@@ -815,6 +833,7 @@ public:
enum_field_types
field_type
()
const
{
return
MYSQL_TYPE_STRING
;
}
enum_field_types
field_type
()
const
{
return
MYSQL_TYPE_STRING
;
}
// to prevent drop fixed flag (no need parent cleanup call)
// to prevent drop fixed flag (no need parent cleanup call)
void
cleanup
()
{}
void
cleanup
()
{}
bool
eq
(
const
Item
*
item
,
bool
binary_cmp
)
const
;
};
};
...
...
sql/item_func.cc
View file @
018b8025
...
@@ -863,10 +863,12 @@ void Item_func_neg::fix_length_and_dec()
...
@@ -863,10 +863,12 @@ void Item_func_neg::fix_length_and_dec()
maximum number of bytes real or integer may require. Note that all
maximum number of bytes real or integer may require. Note that all
constants are non negative so we don't need to account for removed '-'.
constants are non negative so we don't need to account for removed '-'.
B) argument returns a string.
B) argument returns a string.
Use val() to get value as arg_type doesn't mean that item is
Item_int or Item_real due to existence of Item_param.
*/
*/
if
(
arg_result
==
STRING_RESULT
||
if
(
arg_result
==
STRING_RESULT
||
(
arg_type
==
REAL_ITEM
&&
((
Item_real
*
)
args
[
0
])
->
value
>=
0
)
||
(
arg_type
==
REAL_ITEM
&&
args
[
0
]
->
val
()
>=
0
)
||
(
arg_type
==
INT_ITEM
&&
((
Item_int
*
)
args
[
0
])
->
value
>
0
))
(
arg_type
==
INT_ITEM
&&
args
[
0
]
->
val_int
()
>
0
))
max_length
++
;
max_length
++
;
if
(
args
[
0
]
->
result_type
()
==
INT_RESULT
)
if
(
args
[
0
]
->
result_type
()
==
INT_RESULT
)
...
@@ -882,8 +884,7 @@ void Item_func_neg::fix_length_and_dec()
...
@@ -882,8 +884,7 @@ void Item_func_neg::fix_length_and_dec()
signed integers)
signed integers)
*/
*/
if
(
args
[
0
]
->
type
()
!=
INT_ITEM
||
if
(
args
[
0
]
->
type
()
!=
INT_ITEM
||
((
ulonglong
)
((
Item_uint
*
)
args
[
0
])
->
value
<=
(((
ulonglong
)
args
[
0
]
->
val_int
())
<=
(
ulonglong
)
LONGLONG_MIN
))
(
ulonglong
)
LONGLONG_MIN
))
hybrid_type
=
INT_RESULT
;
hybrid_type
=
INT_RESULT
;
}
}
}
}
...
...
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