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
3aa89efc
Commit
3aa89efc
authored
May 03, 2005
by
unknown
Browse files
Options
Browse Files
Download
Plain Diff
Manual merge of Bug#9096
parents
9724795f
b883aeba
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
167 additions
and
7 deletions
+167
-7
mysql-test/t/ps.test
mysql-test/t/ps.test
+27
-0
sql/item.cc
sql/item.cc
+114
-1
sql/item.h
sql/item.h
+23
-4
sql/item_func.cc
sql/item_func.cc
+3
-2
No files found.
mysql-test/t/ps.test
View file @
3aa89efc
...
...
@@ -587,3 +587,30 @@ deallocate prepare stmt|
drop
procedure
p1
|
drop
table
t1
|
delimiter
;
|
#
# 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 @
3aa89efc
...
...
@@ -557,6 +557,11 @@ void Item::set_name(const char *str, uint length, CHARSET_INFO *cs)
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
&&
!
my_strcasecmp
(
system_charset_info
,
name
,
item
->
name
);
}
...
...
@@ -601,7 +606,7 @@ Item *Item_string::safe_charset_converter(CHARSET_INFO *tocs)
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
)
return
!
stringcmp
(
&
str_value
,
&
item
->
str_value
);
...
...
@@ -2194,6 +2199,72 @@ bool Item_param::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
}
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 */
void
Item_param
::
print
(
String
*
str
)
{
if
(
state
==
NO_VALUE
)
...
...
@@ -3346,6 +3417,22 @@ int Item_decimal::save_in_field(Field *field, bool no_conversions)
}
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_decimal
*
item
=
new
Item_decimal
(
value
,
0
);
...
...
@@ -3433,6 +3520,21 @@ void Item_float::print(String *str)
In number context this is a longlong value.
*/
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
;
}
inline
uint
char_val
(
char
X
)
{
return
(
uint
)
(
X
>=
'0'
&&
X
<=
'9'
?
X
-
'0'
:
...
...
@@ -3503,6 +3605,17 @@ int Item_hex_string::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
;
}
/*
bin item.
In string context this is a binary string.
...
...
sql/item.h
View file @
3aa89efc
...
...
@@ -434,7 +434,7 @@ public:
virtual
table_map
not_null_tables
()
const
{
return
used_tables
();
}
/*
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
;
}
/* cloning of constant items (0 if it is not const) */
...
...
@@ -914,7 +914,6 @@ public:
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
so noone will use parameters value in fix_fields still
...
...
@@ -923,12 +922,29 @@ public:
virtual
table_map
used_tables
()
const
{
return
state
!=
NO_VALUE
?
(
table_map
)
0
:
PARAM_TABLE_BIT
;
}
void
print
(
String
*
str
);
/* parameter never equal to other parameter of other item */
bool
eq
(
const
Item
*
item
,
bool
binary_cmp
)
const
{
return
0
;
}
bool
is_null
()
{
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
{
public:
...
...
@@ -956,6 +972,7 @@ public:
void
cleanup
()
{}
void
print
(
String
*
str
);
Item_num
*
neg
()
{
value
=
-
value
;
return
this
;
}
bool
eq
(
const
Item
*
,
bool
binary_cmp
)
const
;
};
...
...
@@ -1059,6 +1076,7 @@ public:
{
return
new
Item_float
(
name
,
value
,
decimals
,
max_length
);
}
Item_num
*
neg
()
{
value
=
-
value
;
return
this
;
}
void
print
(
String
*
str
);
bool
eq
(
const
Item
*
,
bool
binary_cmp
)
const
;
};
...
...
@@ -1198,6 +1216,7 @@ public:
enum_field_types
field_type
()
const
{
return
MYSQL_TYPE_VARCHAR
;
}
// to prevent drop fixed flag (no need parent cleanup call)
void
cleanup
()
{}
bool
eq
(
const
Item
*
item
,
bool
binary_cmp
)
const
;
};
...
...
sql/item_func.cc
View file @
3aa89efc
...
...
@@ -1395,11 +1395,12 @@ void Item_func_neg::fix_length_and_dec()
/*
If this is in integer context keep the context as integer if possible
(This is how multiplication and other integer functions works)
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
(
hybrid_type
==
INT_RESULT
&&
args
[
0
]
->
type
()
==
INT_ITEM
&&
((
ulonglong
)
((
Item_uint
*
)
args
[
0
])
->
value
>=
(
ulonglong
)
LONGLONG_MIN
))
((
ulonglong
)
args
[
0
]
->
val_int
()
>=
(
ulonglong
)
LONGLONG_MIN
))
{
/*
Ensure that result is converted to DECIMAL, as longlong can't hold
...
...
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