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
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
MariaDB
Commits
cc566a79
Commit
cc566a79
authored
Dec 17, 2004
by
unknown
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Condition pushdown to storage engine
parent
5b08a9ed
Changes
16
Show whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
1093 additions
and
29 deletions
+1093
-29
include/mysql_com.h
include/mysql_com.h
+1
-1
mysql-test/r/ndb_condition_pushdown.result
mysql-test/r/ndb_condition_pushdown.result
+26
-0
mysql-test/t/ndb_condition_pushdown.test
mysql-test/t/ndb_condition_pushdown.test
+26
-0
ndb/src/ndbapi/NdbDictionaryImpl.hpp
ndb/src/ndbapi/NdbDictionaryImpl.hpp
+2
-2
sql/ha_ndbcluster.cc
sql/ha_ndbcluster.cc
+791
-11
sql/ha_ndbcluster.h
sql/ha_ndbcluster.h
+172
-13
sql/handler.h
sql/handler.h
+10
-1
sql/item.h
sql/item.h
+12
-1
sql/item_cmpfunc.cc
sql/item_cmpfunc.cc
+14
-0
sql/item_cmpfunc.h
sql/item_cmpfunc.h
+3
-0
sql/item_func.cc
sql/item_func.cc
+16
-0
sql/item_func.h
sql/item_func.h
+3
-0
sql/mysqld.cc
sql/mysqld.cc
+7
-0
sql/set_var.cc
sql/set_var.cc
+6
-0
sql/sql_class.h
sql/sql_class.h
+1
-0
sql/sql_select.cc
sql/sql_select.cc
+3
-0
No files found.
include/mysql_com.h
View file @
cc566a79
...
...
@@ -339,7 +339,7 @@ struct rand_struct {
/* The following is for user defined functions */
enum
Item_result
{
STRING_RESULT
,
REAL_RESULT
,
INT_RESULT
,
ROW_RESULT
};
enum
Item_result
{
STRING_RESULT
=
0
,
REAL_RESULT
,
INT_RESULT
,
ROW_RESULT
};
typedef
struct
st_udf_args
{
...
...
mysql-test/r/ndb_condition_pushdown.result
0 → 100644
View file @
cc566a79
DROP TABLE IF EXISTS t1,t2;
CREATE TABLE t1 (pk1 int unsigned NOT NULL PRIMARY KEY, attr1 int unsigned NOT NULL, attr2 int unsigned, attr3 VARCHAR(10) ) ENGINE=ndbcluster;
insert into t1 values (0,0,0, "a"),(1,1,1,"b"),(2,2,NULL,NULL),(3,3,3,"d"),(4,4,4,"e"),(5,5,5,"f");
CREATE TABLE t2 (pk1 int unsigned NOT NULL PRIMARY KEY, attr1 int unsigned NOT NULL, attr2 int unsigned, attr3 VARCHAR(10) ) ENGINE=ndbcluster;
insert into t2 values (0,0,0, "a"),(1,1,1,"b"),(2,2,2,"c"),(3,3,3,"d"),(4,4,4,"e"),(5,5,5,"f");
set @old_ndbcpd = @@session.ndb_condition_pushdown;
set ndb_condition_pushdown = off;
select * from t1 where attr3 is null or attr1 > 2 and pk1= 3 order by pk1;
pk1 attr1 attr2 attr3
2 2 NULL NULL
3 3 3 d
select * from t1,t2 where t1.attr1 > 1 and t1.attr2 = t2.attr2 and t2.attr1 < 5 order by t1.pk1;
pk1 attr1 attr2 attr3 pk1 attr1 attr2 attr3
3 3 3 d 3 3 3 d
4 4 4 e 4 4 4 e
set ndb_condition_pushdown = on;
select * from t1 where attr3 is null or attr1 > 2 and pk1= 3 order by pk1;
pk1 attr1 attr2 attr3
2 2 NULL NULL
3 3 3 d
select * from t1,t2 where t1.attr1 > 1 and t1.attr2 = t2.attr2 and t2.attr1 < 5 order by t1.pk1;
pk1 attr1 attr2 attr3 pk1 attr1 attr2 attr3
3 3 3 d 3 3 3 d
4 4 4 e 4 4 4 e
set ndb_condition_pushdown = @old_ndbcpd;
DROP TABLE t1,t2;
mysql-test/t/ndb_condition_pushdown.test
0 → 100644
View file @
cc566a79
--
source
include
/
have_ndb
.
inc
--
disable_warnings
DROP
TABLE
IF
EXISTS
t1
,
t2
;
--
enable_warnings
#
# Test of condition pushdown to storage engine
#
CREATE
TABLE
t1
(
pk1
int
unsigned
NOT
NULL
PRIMARY
KEY
,
attr1
int
unsigned
NOT
NULL
,
attr2
int
unsigned
,
attr3
VARCHAR
(
10
)
)
ENGINE
=
ndbcluster
;
insert
into
t1
values
(
0
,
0
,
0
,
"a"
),(
1
,
1
,
1
,
"b"
),(
2
,
2
,
NULL
,
NULL
),(
3
,
3
,
3
,
"d"
),(
4
,
4
,
4
,
"e"
),(
5
,
5
,
5
,
"f"
);
CREATE
TABLE
t2
(
pk1
int
unsigned
NOT
NULL
PRIMARY
KEY
,
attr1
int
unsigned
NOT
NULL
,
attr2
int
unsigned
,
attr3
VARCHAR
(
10
)
)
ENGINE
=
ndbcluster
;
insert
into
t2
values
(
0
,
0
,
0
,
"a"
),(
1
,
1
,
1
,
"b"
),(
2
,
2
,
2
,
"c"
),(
3
,
3
,
3
,
"d"
),(
4
,
4
,
4
,
"e"
),(
5
,
5
,
5
,
"f"
);
set
@
old_ndbcpd
=
@@
session
.
ndb_condition_pushdown
;
set
ndb_condition_pushdown
=
off
;
select
*
from
t1
where
attr3
is
null
or
attr1
>
2
and
pk1
=
3
order
by
pk1
;
select
*
from
t1
,
t2
where
t1
.
attr1
>
1
and
t1
.
attr2
=
t2
.
attr2
and
t2
.
attr1
<
5
order
by
t1
.
pk1
;
set
ndb_condition_pushdown
=
on
;
select
*
from
t1
where
attr3
is
null
or
attr1
>
2
and
pk1
=
3
order
by
pk1
;
select
*
from
t1
,
t2
where
t1
.
attr1
>
1
and
t1
.
attr2
=
t2
.
attr2
and
t2
.
attr1
<
5
order
by
t1
.
pk1
;
set
ndb_condition_pushdown
=
@
old_ndbcpd
;
DROP
TABLE
t1
,
t2
;
ndb/src/ndbapi/NdbDictionaryImpl.hpp
View file @
cc566a79
...
...
@@ -531,7 +531,7 @@ NdbTableImpl::getColumn(const char * name){
do
{
if
(
hashValue
==
(
tmp
&
0xFFFE
)){
NdbColumnImpl
*
col
=
cols
[
tmp
>>
16
];
if
(
str
cmp
(
name
,
col
->
m_name
.
c_str
()
)
==
0
){
if
(
str
ncmp
(
name
,
col
->
m_name
.
c_str
(),
NDB_MAX_ATTR_NAME_SIZE
-
1
)
==
0
){
return
col
;
}
}
...
...
@@ -549,7 +549,7 @@ NdbTableImpl::getColumn(const char * name){
}
else
{
for
(
Uint32
i
=
0
;
i
<
sz
;
i
++
){
NdbColumnImpl
*
col
=
*
cols
++
;
if
(
col
!=
0
&&
str
cmp
(
name
,
col
->
m_name
.
c_str
()
)
==
0
)
if
(
col
!=
0
&&
str
ncmp
(
name
,
col
->
m_name
.
c_str
(),
NDB_MAX_ATTR_NAME_SIZE
-
1
)
==
0
)
return
col
;
}
}
...
...
sql/ha_ndbcluster.cc
View file @
cc566a79
...
...
@@ -197,9 +197,211 @@ int execute_no_commit_ie(ha_ndbcluster *h, NdbConnection *trans)
}
/*
Place holder for ha_ndbcluster thread specific data
CPDH condition storage support
*/
Ndb_item
::
Ndb_item
(
NDB_ITEM_TYPE
item_type
,
NDB_ITEM_QUALIFICATION
item_qualification
,
const
Item
*
item_value
)
:
type
(
item_type
),
qualification
(
item_qualification
)
{
switch
(
item_type
)
{
case
(
NDB_VALUE
):
{
switch
(
item_qualification
.
value_type
)
{
case
(
Item
:
:
STRING_ITEM
)
:
{
Ndb_item_string_value
*
string_value
=
new
Ndb_item_string_value
();
Item_string
*
string_item
=
(
Item_string
*
)
item_value
;
string_value
->
s
=
string_item
->
str_value
;
string_value
->
c
=
string_item
->
collation
.
collation
;
value
.
string_value
=
string_value
;
break
;
}
case
(
Item
:
:
INT_ITEM
)
:
{
value
.
int_value
=
((
Item_int
*
)
item_value
)
->
val_int
();
break
;
}
case
(
Item
:
:
REAL_ITEM
)
:
{
value
.
real_value
=
((
Item_real
*
)
item_value
)
->
val_real
();
break
;
}
case
(
Item
:
:
NULL_ITEM
)
:
break
;
case
(
Item
:
:
VARBIN_ITEM
)
:
{
Ndb_item_string_value
*
string_value
=
new
Ndb_item_string_value
();
Item_varbinary
*
varbin_item
=
(
Item_varbinary
*
)
item_value
;
string_value
->
s
=
varbin_item
->
str_value
;
string_value
->
c
=
varbin_item
->
collation
.
collation
;
value
.
string_value
=
string_value
;
break
;
}
default:
break
;
}
}
break
;
case
(
NDB_FIELD
):
{
NDB_ITEM_FIELD_VALUE
*
field_value
=
new
NDB_ITEM_FIELD_VALUE
();
Item_field
*
field_item
=
(
Item_field
*
)
item_value
;
field_value
->
field
=
field_item
->
field
;
field_value
->
column_no
=
-
1
;
// Will be fetched at scan filter generation
value
.
field_value
=
field_value
;
break
;
}
case
(
NDB_FUNCTION
):
break
;
}
}
Ndb_item
::
Ndb_item
(
longlong
int_value
)
:
type
(
NDB_VALUE
)
{
qualification
.
value_type
=
Item
::
INT_ITEM
;
value
.
int_value
=
int_value
;
}
Ndb_item
::
Ndb_item
(
double
real_value
)
:
type
(
NDB_VALUE
)
{
qualification
.
value_type
=
Item
::
REAL_ITEM
;
value
.
real_value
=
real_value
;
}
Ndb_item
::
Ndb_item
()
:
type
(
NDB_VALUE
)
{
qualification
.
value_type
=
Item
::
NULL_ITEM
;
}
Ndb_item
::
Ndb_item
(
Field
*
field
,
int
column_no
)
:
type
(
NDB_FIELD
)
{
NDB_ITEM_FIELD_VALUE
*
field_value
=
new
NDB_ITEM_FIELD_VALUE
();
qualification
.
field_type
=
field
->
type
();
field_value
->
field
=
field
;
field_value
->
column_no
=
column_no
;
value
.
field_value
=
field_value
;
}
Ndb_item
::
Ndb_item
(
Item_func
::
Functype
func_type
)
:
type
(
NDB_FUNCTION
)
{
qualification
.
function_type
=
func_type
;
}
Ndb_item
::~
Ndb_item
()
{
if
(
type
==
NDB_VALUE
&&
(
qualification
.
value_type
==
Item
::
STRING_ITEM
||
qualification
.
value_type
==
Item
::
VARBIN_ITEM
))
{
delete
value
.
string_value
;
value
.
string_value
=
NULL
;
}
else
if
(
type
==
NDB_FIELD
)
{
delete
value
.
field_value
;
value
.
field_value
=
NULL
;
}
}
void
Ndb_item
::
print
(
String
*
str
)
{
switch
(
type
)
{
case
(
NDB_VALUE
):
str
->
append
(
"[#NDB_VALUE "
);
switch
(
qualification
.
value_type
)
{
case
(
Item
:
:
INT_ITEM
)
:
{
String
tmp
;
tmp
.
set
(
value
.
int_value
,
&
my_charset_bin
);
str
->
append
(
tmp
);
break
;
}
case
(
Item
:
:
REAL_ITEM
)
:
{
String
tmp
;
tmp
.
set
(
value
.
real_value
,
4
,
&
my_charset_bin
);
str
->
append
(
tmp
);
break
;
}
case
(
Item
:
:
STRING_ITEM
)
:
{
str
->
append
(
value
.
string_value
->
s
.
ptr
());
break
;
}
case
(
Item
:
:
VARBIN_ITEM
)
:
{
str
->
append
(
value
.
string_value
->
s
.
ptr
());
break
;
}
case
(
Item
:
:
NULL_ITEM
)
:
str
->
append
(
"NULL"
);
break
;
default:
str
->
append
(
"ILLEGAL VALUE"
);
}
str
->
append
(
"]"
);
break
;
case
(
NDB_FIELD
):
str
->
append
(
"[#NDB_FIELD "
);
str
->
append
(
value
.
field_value
->
field
->
field_name
);
str
->
append
(
"]"
);
break
;
case
(
NDB_FUNCTION
):
str
->
append
(
"[#NDB_FUNCTION "
);
switch
(
qualification
.
function_type
)
{
case
(
Item_func
:
:
UNKNOWN_FUNC
)
:
{
str
->
append
(
"UNKNOWN]"
);
break
;
}
case
(
Item_func
:
:
EQ_FUNC
)
:
{
str
->
append
(
"=]"
);
break
;
}
case
(
Item_func
:
:
NE_FUNC
)
:
{
str
->
append
(
"!=]"
);
break
;
}
case
(
Item_func
:
:
LT_FUNC
)
:
{
str
->
append
(
"<]"
);
break
;
}
case
(
Item_func
:
:
LE_FUNC
)
:
{
str
->
append
(
"<=]"
);
break
;
}
case
(
Item_func
:
:
GE_FUNC
)
:
{
str
->
append
(
">=]"
);
break
;
}
case
(
Item_func
:
:
GT_FUNC
)
:
{
str
->
append
(
">]"
);
break
;
}
case
(
Item_func
:
:
LIKE_FUNC
)
:
{
str
->
append
(
"like]"
);
break
;
}
case
(
Item_func
:
:
NOTLIKE_FUNC
)
:
{
str
->
append
(
"notlike]"
);
break
;
}
case
(
Item_func
:
:
ISNULL_FUNC
)
:
{
str
->
append
(
"isnull]"
);
break
;
}
case
(
Item_func
:
:
ISNOTNULL_FUNC
)
:
{
str
->
append
(
"isnotnull]"
);
break
;
}
case
(
Item_func
:
:
COND_AND_FUNC
)
:
{
str
->
append
(
"and]"
);
break
;
}
case
(
Item_func
:
:
COND_OR_FUNC
)
:
{
str
->
append
(
"or]"
);
break
;
}
default:
str
->
append
(
"UNSUPPORTED]"
);
}
}
}
/*
Place holder for ha_ndbcluster thread specific data
*/
Thd_ndb
::
Thd_ndb
()
{
ndb
=
new
Ndb
(
g_ndb_cluster_connection
,
""
);
...
...
@@ -1701,7 +1903,7 @@ int ha_ndbcluster::full_table_scan(byte *buf)
op
->
readTuples
(
lm
,
0
,
parallelism
))
ERR_RETURN
(
trans
->
getNdbError
());
m_active_cursor
=
op
;
generate_scan_filter
(
m_cond_stack
,
op
);
if
((
res
=
define_read_attrs
(
buf
,
op
)))
DBUG_RETURN
(
res
);
...
...
@@ -2723,6 +2925,8 @@ int ha_ndbcluster::extra(enum ha_extra_function operation)
break
;
case
HA_EXTRA_RESET
:
/* Reset database to after open */
DBUG_PRINT
(
"info"
,
(
"HA_EXTRA_RESET"
));
DBUG_PRINT
(
"info"
,
(
"Clearing condition stack"
));
cond_clear
();
break
;
case
HA_EXTRA_CACHE
:
/* Cash record in HA_rrnd() */
DBUG_PRINT
(
"info"
,
(
"HA_EXTRA_CACHE"
));
...
...
@@ -2916,14 +3120,6 @@ int ha_ndbcluster::extra_opt(enum ha_extra_function operation, ulong cache_size)
}
int
ha_ndbcluster
::
reset
()
{
DBUG_ENTER
(
"reset"
);
// Reset what?
DBUG_RETURN
(
1
);
}
const
char
**
ha_ndbcluster
::
bas_ext
()
const
{
static
const
char
*
ext
[]
=
{
ha_ndb_ext
,
NullS
};
return
ext
;
}
...
...
@@ -3832,7 +4028,8 @@ ha_ndbcluster::ha_ndbcluster(TABLE *table_arg):
m_force_send
(
TRUE
),
m_autoincrement_prefetch
(
32
),
m_transaction_on
(
TRUE
),
m_use_local_query_cache
(
FALSE
)
m_use_local_query_cache
(
FALSE
),
m_cond_stack
(
NULL
)
{
int
i
;
...
...
@@ -3877,6 +4074,10 @@ ha_ndbcluster::~ha_ndbcluster()
}
DBUG_ASSERT
(
m_active_trans
==
NULL
);
// Discard the condition stack
DBUG_PRINT
(
"info"
,
(
"Clearing condition stack"
));
cond_clear
();
DBUG_VOID_RETURN
;
}
...
...
@@ -5141,4 +5342,583 @@ ha_ndbcluster::setup_recattr(const NdbRecAttr* curr)
}
#endif
/*
Condition pushdown
*/
const
COND
*
ha_ndbcluster
::
cond_push
(
const
COND
*
cond
)
{
THD
*
thd
=
current_thd
;
Ndb_cond_stack
*
ndb_cond
=
new
Ndb_cond_stack
();
DBUG_ENTER
(
"cond_push"
);
if
(
thd
->
variables
.
ndb_condition_pushdown
)
{
DBUG_EXECUTE
(
"where"
,
print_where
((
COND
*
)
cond
,
m_tabname
););
if
(
m_cond_stack
)
ndb_cond
->
next
=
m_cond_stack
;
else
ndb_cond
->
next
=
NULL
;
m_cond_stack
=
ndb_cond
;
if
(
serialize_cond
(
cond
,
ndb_cond
))
{
DBUG_RETURN
(
NULL
);
}
else
{
cond_pop
();
}
}
DBUG_RETURN
(
cond
);
}
inline
void
ha_ndbcluster
::
cond_pop
()
{
Ndb_cond_stack
*
ndb_cond_stack
=
m_cond_stack
;
if
(
ndb_cond_stack
)
{
m_cond_stack
=
ndb_cond_stack
->
next
;
delete
ndb_cond_stack
;
}
};
void
ha_ndbcluster
::
cond_clear
()
{
DBUG_ENTER
(
"cond_clear"
);
while
(
m_cond_stack
)
cond_pop
();
DBUG_VOID_RETURN
;
}
void
ndb_serialize_cond
(
const
Item
*
item
,
void
*
arg
)
{
Ndb_cond_traverse_context
*
context
=
(
Ndb_cond_traverse_context
*
)
arg
;
DBUG_ENTER
(
"ndb_serialize_cond"
);
if
(
*
context
->
supported_ptr
)
{
Ndb_cond_stack
*
ndb_stack
=
context
->
stack_ptr
;
Ndb_cond
*
prev_cond
=
context
->
cond_ptr
;
Ndb_cond
*
curr_cond
=
context
->
cond_ptr
=
new
Ndb_cond
();
if
(
!
ndb_stack
->
ndb_cond
)
ndb_stack
->
ndb_cond
=
curr_cond
;
curr_cond
->
prev
=
prev_cond
;
if
(
prev_cond
)
prev_cond
->
next
=
curr_cond
;
switch
(
item
->
type
())
{
case
(
Item
:
:
FIELD_ITEM
)
:
{
Item_field
*
field_item
=
(
Item_field
*
)
item
;
Field
*
field
=
field_item
->
field
;
/*
Check that the field is part of the table of the handler
instance and that we expect a field with of this result type.
*/
if
(
context
->
table
==
field
->
table
)
{
const
NDBTAB
*
tab
=
(
const
NDBTAB
*
)
context
->
ndb_table
;
const
NDBCOL
*
col
=
tab
->
getColumn
(
field
->
field_name
);
DBUG_ASSERT
(
col
);
DBUG_PRINT
(
"info"
,
(
"FIELD_ITEM"
));
DBUG_PRINT
(
"info"
,
(
"table %s"
,
tab
->
getName
()));
DBUG_PRINT
(
"info"
,
(
"column %s"
,
field
->
field_name
));
if
(
context
->
expecting
(
Item
::
FIELD_ITEM
)
&&
context
->
expecting_field_result
(
field
->
result_type
()))
{
// Currently only support for unsigned int
if
(
field
->
result_type
()
==
INT_RESULT
&&
(
field
->
type
()
!=
MYSQL_TYPE_LONG
||
!
(
field
->
flags
&
UNSIGNED_FLAG
)))
*
context
->
supported_ptr
=
FALSE
;
else
{
curr_cond
->
ndb_item
=
new
Ndb_item
(
field
,
col
->
getColumnNo
());
context
->
dont_expect
(
Item
::
FIELD_ITEM
);
context
->
expect_no_field_result
();
break
;
}
}
}
*
context
->
supported_ptr
=
FALSE
;
break
;
}
case
(
Item
:
:
FUNC_ITEM
)
:
{
Item_func
*
func_item
=
(
Item_func
*
)
item
;
context
->
expect_nothing
();
switch
(
func_item
->
functype
())
{
case
(
Item_func
:
:
UNKNOWN_FUNC
)
:
{
DBUG_PRINT
(
"info"
,
(
"UNKNOWN_FUNC"
));
DBUG_PRINT
(
"info"
,
(
"value %d"
,
func_item
->
val_int
()));
break
;
}
case
(
Item_func
:
:
EQ_FUNC
)
:
{
DBUG_PRINT
(
"info"
,
(
"EQ_FUNC"
));
curr_cond
->
ndb_item
=
new
Ndb_item
(
func_item
->
functype
());
context
->
expect
(
Item
::
FIELD_ITEM
);
context
->
expect_field_result
(
INT_RESULT
);
context
->
expect
(
Item
::
INT_ITEM
);
break
;
}
case
(
Item_func
:
:
NE_FUNC
)
:
{
DBUG_PRINT
(
"info"
,
(
"NE_FUNC"
));
curr_cond
->
ndb_item
=
new
Ndb_item
(
func_item
->
functype
());
context
->
expect
(
Item
::
FIELD_ITEM
);
context
->
expect_field_result
(
INT_RESULT
);
context
->
expect
(
Item
::
INT_ITEM
);
break
;
}
case
(
Item_func
:
:
LT_FUNC
)
:
{
DBUG_PRINT
(
"info"
,
(
"LT_FUNC"
));
curr_cond
->
ndb_item
=
new
Ndb_item
(
func_item
->
functype
());
context
->
expect
(
Item
::
FIELD_ITEM
);
context
->
expect_field_result
(
INT_RESULT
);
context
->
expect
(
Item
::
INT_ITEM
);
break
;
}
case
(
Item_func
:
:
LE_FUNC
)
:
{
DBUG_PRINT
(
"info"
,
(
"LE_FUNC"
));
curr_cond
->
ndb_item
=
new
Ndb_item
(
func_item
->
functype
());
context
->
expect
(
Item
::
FIELD_ITEM
);
context
->
expect_field_result
(
INT_RESULT
);
context
->
expect
(
Item
::
INT_ITEM
);
break
;
}
case
(
Item_func
:
:
GE_FUNC
)
:
{
DBUG_PRINT
(
"info"
,
(
"GE_FUNC"
));
curr_cond
->
ndb_item
=
new
Ndb_item
(
func_item
->
functype
());
context
->
expect
(
Item
::
FIELD_ITEM
);
context
->
expect_field_result
(
INT_RESULT
);
context
->
expect
(
Item
::
INT_ITEM
);
break
;
}
case
(
Item_func
:
:
GT_FUNC
)
:
{
DBUG_PRINT
(
"info"
,
(
"GT_FUNC"
));
curr_cond
->
ndb_item
=
new
Ndb_item
(
func_item
->
functype
());
context
->
expect
(
Item
::
FIELD_ITEM
);
context
->
expect_field_result
(
INT_RESULT
);
context
->
expect
(
Item
::
INT_ITEM
);
break
;
}
case
(
Item_func
:
:
LIKE_FUNC
)
:
{
DBUG_PRINT
(
"info"
,
(
"LIKE_FUNC"
));
curr_cond
->
ndb_item
=
new
Ndb_item
(
func_item
->
functype
());
context
->
expect
(
Item
::
STRING_ITEM
);
*
context
->
supported_ptr
=
FALSE
;
// Currently not supported
break
;
}
case
(
Item_func
:
:
NOTLIKE_FUNC
)
:
{
DBUG_PRINT
(
"info"
,
(
"NOTLIKE_FUNC"
));
curr_cond
->
ndb_item
=
new
Ndb_item
(
func_item
->
functype
());
context
->
expect
(
Item
::
STRING_ITEM
);
*
context
->
supported_ptr
=
FALSE
;
// Currently not supported
break
;
}
case
(
Item_func
:
:
ISNULL_FUNC
)
:
{
DBUG_PRINT
(
"info"
,
(
"ISNULL_FUNC"
));
curr_cond
->
ndb_item
=
new
Ndb_item
(
func_item
->
functype
());
context
->
expect
(
Item
::
FIELD_ITEM
);
context
->
expect_field_result
(
STRING_RESULT
);
context
->
expect_field_result
(
REAL_RESULT
);
context
->
expect_field_result
(
INT_RESULT
);
break
;
}
case
(
Item_func
:
:
ISNOTNULL_FUNC
)
:
{
DBUG_PRINT
(
"info"
,
(
"ISNOTNULL_FUNC"
));
curr_cond
->
ndb_item
=
new
Ndb_item
(
func_item
->
functype
());
context
->
expect
(
Item
::
FIELD_ITEM
);
context
->
expect_field_result
(
STRING_RESULT
);
context
->
expect_field_result
(
REAL_RESULT
);
context
->
expect_field_result
(
INT_RESULT
);
break
;
}
default:
{
DBUG_PRINT
(
"info"
,
(
"Found func_item of type %d"
,
func_item
->
functype
()));
*
context
->
supported_ptr
=
FALSE
;
}
}
break
;
}
case
(
Item
:
:
STRING_ITEM
)
:
if
(
context
->
expecting
(
Item
::
STRING_ITEM
))
{
char
buff
[
256
];
String
str
(
buff
,(
uint32
)
sizeof
(
buff
),
system_charset_info
);
str
.
length
(
0
);
Item_string
*
string_item
=
(
Item_string
*
)
item
;
DBUG_PRINT
(
"info"
,
(
"STRING_ITEM"
));
DBUG_PRINT
(
"info"
,
(
"value
\"
%s
\"
"
,
string_item
->
val_str
(
&
str
)
->
ptr
()));
NDB_ITEM_QUALIFICATION
q
;
q
.
value_type
=
Item
::
STRING_ITEM
;
curr_cond
->
ndb_item
=
new
Ndb_item
(
NDB_VALUE
,
q
,
item
);
context
->
dont_expect
(
Item
::
STRING_ITEM
);
}
else
*
context
->
supported_ptr
=
FALSE
;
break
;
case
(
Item
:
:
INT_ITEM
)
:
if
(
context
->
expecting
(
Item
::
INT_ITEM
))
{
Item_int
*
int_item
=
(
Item_int
*
)
item
;
DBUG_PRINT
(
"info"
,
(
"INT_ITEM"
));
DBUG_PRINT
(
"info"
,
(
"value %d"
,
int_item
->
value
));
curr_cond
->
ndb_item
=
new
Ndb_item
(
int_item
->
value
);
context
->
dont_expect
(
Item
::
INT_ITEM
);
}
else
*
context
->
supported_ptr
=
FALSE
;
break
;
case
(
Item
:
:
REAL_ITEM
)
:
if
(
context
->
expecting
(
Item
::
REAL_ITEM
))
{
Item_real
*
real_item
=
(
Item_real
*
)
item
;
DBUG_PRINT
(
"info"
,
(
"REAL_ITEM %s"
));
DBUG_PRINT
(
"info"
,
(
"value %f"
,
real_item
->
value
));
curr_cond
->
ndb_item
=
new
Ndb_item
(
real_item
->
value
);
context
->
dont_expect
(
Item
::
REAL_ITEM
);
*
context
->
supported_ptr
=
FALSE
;
// Currently not supported
}
else
*
context
->
supported_ptr
=
FALSE
;
break
;
case
(
Item
:
:
COND_ITEM
)
:
{
Item_cond
*
cond_item
=
(
Item_cond
*
)
item
;
switch
(
cond_item
->
functype
())
{
case
(
Item_func
:
:
COND_AND_FUNC
)
:
DBUG_PRINT
(
"info"
,
(
"COND_AND_FUNC"
));
curr_cond
->
ndb_item
=
new
Ndb_item
(
cond_item
->
functype
());
break
;
case
(
Item_func
:
:
COND_OR_FUNC
)
:
DBUG_PRINT
(
"info"
,
(
"COND_OR_FUNC"
));
curr_cond
->
ndb_item
=
new
Ndb_item
(
cond_item
->
functype
());
break
;
default:
DBUG_PRINT
(
"info"
,
(
"COND_ITEM %d"
,
cond_item
->
functype
()));
*
context
->
supported_ptr
=
FALSE
;
break
;
}
break
;
}
default:
{
DBUG_PRINT
(
"info"
,
(
"Found item of type %d"
,
item
->
type
()));
*
context
->
supported_ptr
=
FALSE
;
}
}
}
DBUG_VOID_RETURN
;
}
bool
ha_ndbcluster
::
serialize_cond
(
const
COND
*
cond
,
Ndb_cond_stack
*
ndb_cond
)
{
DBUG_ENTER
(
"serialize_cond"
);
Item
*
item
=
(
Item
*
)
cond
;
bool
supported
=
TRUE
;
Ndb_cond_traverse_context
context
(
table
,
(
void
*
)
m_table
,
&
supported
,
ndb_cond
);
item
->
traverse_cond
(
&
ndb_serialize_cond
,
(
void
*
)
&
context
,
Item
::
PREFIX
);
DBUG_PRINT
(
"info"
,
(
"The pushed condition is %ssupported"
,
(
supported
)
?
""
:
"not "
));
DBUG_RETURN
(
supported
);
}
Ndb_cond
*
ha_ndbcluster
::
build_scan_filter_predicate
(
Ndb_cond
*
cond
,
NdbScanFilter
*
filter
)
{
DBUG_ENTER
(
"build_scan_filter_predicate"
);
switch
(
cond
->
ndb_item
->
type
)
{
case
(
NDB_FUNCTION
):
{
if
(
!
cond
->
next
)
break
;
Ndb_item
*
a
=
cond
->
next
->
ndb_item
;
switch
(
cond
->
ndb_item
->
qualification
.
function_type
)
{
case
(
Item_func
:
:
EQ_FUNC
)
:
{
if
(
!
cond
->
next
->
next
)
break
;
Ndb_item
*
b
=
cond
->
next
->
next
->
ndb_item
;
Ndb_item
*
value
=
(
a
->
type
==
NDB_VALUE
)
?
a
:
(
b
->
type
==
NDB_VALUE
)
?
b
:
NULL
;
Ndb_item
*
field
=
(
a
->
type
==
NDB_FIELD
)
?
a
:
(
b
->
type
==
NDB_FIELD
)
?
b
:
NULL
;
if
(
!
value
||
!
field
)
break
;
DBUG_PRINT
(
"info"
,
(
"Generating EQ filter"
));
filter
->
eq
(
field
->
getFieldNo
(),
(
Uint32
)
value
->
getIntValue
());
DBUG_RETURN
(
cond
->
next
->
next
->
next
);
}
case
(
Item_func
:
:
NE_FUNC
)
:
{
if
(
!
cond
->
next
->
next
)
break
;
Ndb_item
*
b
=
cond
->
next
->
next
->
ndb_item
;
Ndb_item
*
value
=
(
a
->
type
==
NDB_VALUE
)
?
a
:
(
b
->
type
==
NDB_VALUE
)
?
b
:
NULL
;
Ndb_item
*
field
=
(
a
->
type
==
NDB_FIELD
)
?
a
:
(
b
->
type
==
NDB_FIELD
)
?
b
:
NULL
;
if
(
!
value
||
!
field
)
break
;
DBUG_PRINT
(
"info"
,
(
"Generating NE filter"
));
filter
->
ne
(
field
->
getFieldNo
(),
(
Uint32
)
value
->
getIntValue
());
DBUG_RETURN
(
cond
->
next
->
next
->
next
);
}
case
(
Item_func
:
:
LT_FUNC
)
:
{
if
(
!
cond
->
next
->
next
)
break
;
Ndb_item
*
b
=
cond
->
next
->
next
->
ndb_item
;
Ndb_item
*
value
=
(
a
->
type
==
NDB_VALUE
)
?
a
:
(
b
->
type
==
NDB_VALUE
)
?
b
:
NULL
;
Ndb_item
*
field
=
(
a
->
type
==
NDB_FIELD
)
?
a
:
(
b
->
type
==
NDB_FIELD
)
?
b
:
NULL
;
if
(
!
value
||
!
field
)
break
;
DBUG_PRINT
(
"info"
,
(
"Generating LT filter"
));
if
(
a
==
field
)
filter
->
lt
(
field
->
getFieldNo
(),
(
Uint32
)
value
->
getIntValue
());
else
filter
->
gt
(
field
->
getFieldNo
(),
(
Uint32
)
value
->
getIntValue
());
DBUG_RETURN
(
cond
->
next
->
next
->
next
);
}
case
(
Item_func
:
:
LE_FUNC
)
:
{
if
(
!
cond
->
next
->
next
)
break
;
Ndb_item
*
b
=
cond
->
next
->
next
->
ndb_item
;
Ndb_item
*
value
=
(
a
->
type
==
NDB_VALUE
)
?
a
:
(
b
->
type
==
NDB_VALUE
)
?
b
:
NULL
;
Ndb_item
*
field
=
(
a
->
type
==
NDB_FIELD
)
?
a
:
(
b
->
type
==
NDB_FIELD
)
?
b
:
NULL
;
if
(
!
value
||
!
field
)
break
;
DBUG_PRINT
(
"info"
,
(
"Generating LE filter"
));
if
(
a
==
field
)
filter
->
le
(
field
->
getFieldNo
(),
(
Uint32
)
value
->
getIntValue
());
else
filter
->
ge
(
field
->
getFieldNo
(),
(
Uint32
)
value
->
getIntValue
());
DBUG_RETURN
(
cond
->
next
->
next
->
next
);
}
case
(
Item_func
:
:
GE_FUNC
)
:
{
if
(
!
cond
->
next
->
next
)
break
;
Ndb_item
*
b
=
cond
->
next
->
next
->
ndb_item
;
Ndb_item
*
value
=
(
a
->
type
==
NDB_VALUE
)
?
a
:
(
b
->
type
==
NDB_VALUE
)
?
b
:
NULL
;
Ndb_item
*
field
=
(
a
->
type
==
NDB_FIELD
)
?
a
:
(
b
->
type
==
NDB_FIELD
)
?
b
:
NULL
;
if
(
!
value
||
!
field
)
break
;
DBUG_PRINT
(
"info"
,
(
"Generating GE filter"
));
if
(
a
==
field
)
filter
->
ge
(
field
->
getFieldNo
(),
(
Uint32
)
value
->
getIntValue
());
else
filter
->
le
(
field
->
getFieldNo
(),
(
Uint32
)
value
->
getIntValue
());
DBUG_RETURN
(
cond
->
next
->
next
->
next
);
}
case
(
Item_func
:
:
GT_FUNC
)
:
{
if
(
!
cond
->
next
->
next
)
break
;
Ndb_item
*
b
=
cond
->
next
->
next
->
ndb_item
;
Ndb_item
*
value
=
(
a
->
type
==
NDB_VALUE
)
?
a
:
(
b
->
type
==
NDB_VALUE
)
?
b
:
NULL
;
Ndb_item
*
field
=
(
a
->
type
==
NDB_FIELD
)
?
a
:
(
b
->
type
==
NDB_FIELD
)
?
b
:
NULL
;
if
(
!
value
||
!
field
)
break
;
DBUG_PRINT
(
"info"
,
(
"Generating GT filter"
));
if
(
a
==
field
)
filter
->
gt
(
field
->
getFieldNo
(),
(
Uint32
)
value
->
getIntValue
());
else
filter
->
lt
(
field
->
getFieldNo
(),
(
Uint32
)
value
->
getIntValue
());
DBUG_RETURN
(
cond
->
next
->
next
->
next
);
}
case
(
Item_func
:
:
LIKE_FUNC
)
:
{
if
(
!
cond
->
next
->
next
)
break
;
Ndb_item
*
b
=
cond
->
next
->
next
->
ndb_item
;
Ndb_item
*
value
=
(
a
->
type
==
NDB_VALUE
)
?
a
:
(
b
->
type
==
NDB_VALUE
)
?
b
:
NULL
;
Ndb_item
*
field
=
(
a
->
type
==
NDB_FIELD
)
?
a
:
(
b
->
type
==
NDB_FIELD
)
?
b
:
NULL
;
if
(
!
value
||
!
field
)
break
;
if
(
value
->
qualification
.
value_type
!=
Item
::
STRING_ITEM
)
break
;
String
*
str
=
value
->
getStringValue
();
DBUG_PRINT
(
"info"
,
(
"Generating LIKE filter: like(%d,%s,%d)"
,
field
->
getFieldNo
(),
str
->
ptr
(),
str
->
length
()));
filter
->
like
(
field
->
getFieldNo
(),
str
->
ptr
(),
str
->
length
(),
TRUE
);
DBUG_RETURN
(
cond
->
next
->
next
->
next
);
}
case
(
Item_func
:
:
NOTLIKE_FUNC
)
:
{
if
(
!
cond
->
next
->
next
)
break
;
Ndb_item
*
b
=
cond
->
next
->
next
->
ndb_item
;
Ndb_item
*
value
=
(
a
->
type
==
NDB_VALUE
)
?
a
:
(
b
->
type
==
NDB_VALUE
)
?
b
:
NULL
;
Ndb_item
*
field
=
(
a
->
type
==
NDB_FIELD
)
?
a
:
(
b
->
type
==
NDB_FIELD
)
?
b
:
NULL
;
if
(
!
value
||
!
field
)
break
;
if
(
value
->
qualification
.
value_type
!=
Item
::
STRING_ITEM
)
break
;
String
*
str
=
value
->
getStringValue
();
DBUG_PRINT
(
"info"
,
(
"Generating NOTLIKE filter: notlike(%d,%s,%d)"
,
field
->
getFieldNo
(),
str
->
ptr
(),
str
->
length
()));
filter
->
notlike
(
field
->
getFieldNo
(),
str
->
ptr
(),
str
->
length
());
DBUG_RETURN
(
cond
->
next
->
next
->
next
);
}
case
(
Item_func
:
:
ISNULL_FUNC
)
:
if
(
a
->
type
==
NDB_FIELD
)
{
DBUG_PRINT
(
"info"
,
(
"Generating ISNULL filter"
));
filter
->
isnull
(
a
->
getFieldNo
());
}
DBUG_RETURN
(
cond
->
next
->
next
);
case
(
Item_func
:
:
ISNOTNULL_FUNC
)
:
{
if
(
a
->
type
==
NDB_FIELD
)
{
DBUG_PRINT
(
"info"
,
(
"Generating ISNOTNULL filter"
));
filter
->
isnotnull
(
a
->
getFieldNo
());
}
DBUG_RETURN
(
cond
->
next
->
next
);
}
default:
break
;
}
break
;
}
default:
break
;
}
DBUG_PRINT
(
"info"
,
(
"Found illegal condition"
));
DBUG_RETURN
(
NULL
);
}
Ndb_cond
*
ha_ndbcluster
::
build_scan_filter_group
(
Ndb_cond
*
cond
,
NdbScanFilter
*
filter
)
{
DBUG_ENTER
(
"build_scan_filter_group"
);
switch
(
cond
->
ndb_item
->
type
)
{
case
(
NDB_FUNCTION
):
switch
(
cond
->
ndb_item
->
qualification
.
function_type
)
{
case
(
Item_func
:
:
COND_AND_FUNC
)
:
{
DBUG_PRINT
(
"info"
,
(
"Generating AND group"
));
filter
->
begin
(
NdbScanFilter
::
AND
);
cond
=
cond
->
next
;
cond
=
build_scan_filter_group
(
cond
,
filter
);
cond
=
build_scan_filter_group
(
cond
,
filter
);
filter
->
end
();
break
;
}
case
(
Item_func
:
:
COND_OR_FUNC
)
:
{
DBUG_PRINT
(
"info"
,
(
"Generating OR group"
));
filter
->
begin
(
NdbScanFilter
::
OR
);
cond
=
cond
->
next
;
cond
=
build_scan_filter_group
(
cond
,
filter
);
cond
=
build_scan_filter_group
(
cond
,
filter
);
filter
->
end
();
break
;
}
default:
cond
=
build_scan_filter_predicate
(
cond
,
filter
);
}
break
;
default:
{
DBUG_PRINT
(
"info"
,
(
"Illegal scan filter"
));
}
}
DBUG_RETURN
(
cond
);
}
void
ha_ndbcluster
::
build_scan_filter
(
Ndb_cond
*
cond
,
NdbScanFilter
*
filter
)
{
bool
simple_cond
=
TRUE
;
DBUG_ENTER
(
"build_scan_filter"
);
switch
(
cond
->
ndb_item
->
type
)
{
case
(
Item_func
:
:
COND_AND_FUNC
)
:
simple_cond
=
FALSE
;
break
;
case
(
Item_func
:
:
COND_OR_FUNC
)
:
simple_cond
=
FALSE
;
break
;
default:
break
;
}
if
(
simple_cond
)
filter
->
begin
();
build_scan_filter_group
(
cond
,
filter
);
if
(
simple_cond
)
filter
->
end
();
DBUG_VOID_RETURN
;
}
void
ha_ndbcluster
::
generate_scan_filter
(
Ndb_cond_stack
*
ndb_cond_stack
,
NdbScanOperation
*
op
)
{
DBUG_ENTER
(
"generate_scan_filter"
);
if
(
ndb_cond_stack
)
{
NdbScanFilter
filter
(
op
);
bool
multiple_cond
=
FALSE
;
// Wrap an AND group around multiple conditions
if
(
ndb_cond_stack
->
next
)
{
multiple_cond
=
TRUE
;
filter
.
begin
();
}
for
(
Ndb_cond_stack
*
stack
=
ndb_cond_stack
;
(
stack
);
stack
=
stack
->
next
)
{
build_scan_filter
(
stack
->
ndb_cond
,
&
filter
);
}
if
(
multiple_cond
)
filter
.
end
();
}
else
{
DBUG_PRINT
(
"info"
,
(
"Empty stack"
));
}
DBUG_VOID_RETURN
;
}
#endif
/* HAVE_NDBCLUSTER_DB */
sql/ha_ndbcluster.h
View file @
cc566a79
...
...
@@ -32,6 +32,7 @@ class NdbOperation; // Forward declaration
class
NdbConnection
;
// Forward declaration
class
NdbRecAttr
;
// Forward declaration
class
NdbScanOperation
;
class
NdbScanFilter
;
class
NdbIndexScanOperation
;
class
NdbBlob
;
...
...
@@ -60,6 +61,145 @@ typedef struct st_ndbcluster_share {
uint
table_name_length
,
use_count
;
}
NDB_SHARE
;
typedef
enum
ndb_item_type
{
NDB_VALUE
=
0
,
// Qualified more with Item::Type
NDB_FIELD
=
1
,
// Qualified from table definition
NDB_FUNCTION
=
2
// Qualified from Item_func::Functype
}
NDB_ITEM_TYPE
;
typedef
union
ndb_item_qualification
{
Item
::
Type
value_type
;
enum_field_types
field_type
;
// Instead of Item::FIELD_ITEM
Item_func
::
Functype
function_type
;
// Instead of Item::FUNC_ITEM
}
NDB_ITEM_QUALIFICATION
;
class
Ndb_item_string_value
{
public:
String
s
;
CHARSET_INFO
*
c
;
};
typedef
struct
ndb_item_field_value
{
Field
*
field
;
int
column_no
;
}
NDB_ITEM_FIELD_VALUE
;
typedef
union
ndb_item_value
{
longlong
int_value
;
double
real_value
;
Ndb_item_string_value
*
string_value
;
NDB_ITEM_FIELD_VALUE
*
field_value
;
}
NDB_ITEM_VALUE
;
class
Ndb_item
{
public:
Ndb_item
(
NDB_ITEM_TYPE
item_type
,
NDB_ITEM_QUALIFICATION
item_qualification
,
const
Item
*
item_value
);
Ndb_item
(
longlong
int_value
);
Ndb_item
(
double
real_value
);
Ndb_item
();
Ndb_item
(
Field
*
field
,
int
column_no
);
Ndb_item
(
Item_func
::
Functype
func_type
);
~
Ndb_item
();
void
print
(
String
*
str
);
// Getters and Setters
longlong
getIntValue
()
{
return
value
.
int_value
;
};
double
getRealValue
()
{
return
value
.
real_value
;
};
String
*
getStringValue
()
{
return
&
value
.
string_value
->
s
;
};
CHARSET_INFO
*
getStringCharset
()
{
return
value
.
string_value
->
c
;
};
Field
*
getField
()
{
return
value
.
field_value
->
field
;
};
int
getFieldNo
()
{
return
value
.
field_value
->
column_no
;
};
public:
NDB_ITEM_TYPE
type
;
NDB_ITEM_QUALIFICATION
qualification
;
private:
NDB_ITEM_VALUE
value
;
};
class
Ndb_cond
{
public:
Ndb_cond
()
:
ndb_item
(
NULL
),
next
(
NULL
),
prev
(
NULL
)
{};
~
Ndb_cond
()
{
if
(
ndb_item
)
delete
ndb_item
;
ndb_item
=
NULL
;
if
(
next
)
delete
next
;
next
=
prev
=
NULL
;
};
Ndb_item
*
ndb_item
;
Ndb_cond
*
next
;
Ndb_cond
*
prev
;
};
class
Ndb_cond_stack
{
public:
Ndb_cond_stack
()
:
ndb_cond
(
NULL
),
next
(
NULL
)
{};
~
Ndb_cond_stack
()
{
if
(
ndb_cond
)
delete
ndb_cond
;
ndb_cond
=
NULL
;
next
=
NULL
;
};
Ndb_cond
*
ndb_cond
;
Ndb_cond_stack
*
next
;
};
class
Ndb_cond_traverse_context
{
public:
Ndb_cond_traverse_context
(
TABLE
*
tab
,
void
*
ndb_tab
,
bool
*
supported
,
Ndb_cond_stack
*
stack
)
:
table
(
tab
),
ndb_table
(
ndb_tab
),
supported_ptr
(
supported
),
stack_ptr
(
stack
),
cond_ptr
(
NULL
),
expect_mask
(
0
),
expect_field_result_mask
(
0
)
{
if
(
stack
)
cond_ptr
=
stack
->
ndb_cond
;
};
void
expect
(
Item
::
Type
type
)
{
expect_mask
|=
(
1
<<
type
);
};
void
dont_expect
(
Item
::
Type
type
)
{
expect_mask
&=
~
(
1
<<
type
);
};
bool
expecting
(
Item
::
Type
type
)
{
return
(
expect_mask
&
(
1
<<
type
));
};
void
expect_nothing
()
{
expect_mask
=
0
;
};
void
expect_field_result
(
Item_result
result
)
{
expect_field_result_mask
|=
(
1
<<
result
);
};
bool
expecting_field_result
(
Item_result
result
)
{
return
(
expect_field_result_mask
&
(
1
<<
result
));
};
void
expect_no_field_result
()
{
expect_field_result_mask
=
0
;
};
TABLE
*
table
;
void
*
ndb_table
;
bool
*
supported_ptr
;
Ndb_cond_stack
*
stack_ptr
;
Ndb_cond
*
cond_ptr
;
private:
uint
expect_mask
;
uint
expect_field_result_mask
;
};
/*
Place holder for ha_ndbcluster thread specific data
*/
...
...
@@ -122,7 +262,6 @@ class ha_ndbcluster: public handler
void
info
(
uint
);
int
extra
(
enum
ha_extra_function
operation
);
int
extra_opt
(
enum
ha_extra_function
operation
,
ulong
cache_size
);
int
reset
();
int
external_lock
(
THD
*
thd
,
int
lock_type
);
int
start_stmt
(
THD
*
thd
);
const
char
*
table_type
()
const
;
...
...
@@ -152,6 +291,13 @@ class ha_ndbcluster: public handler
static
Thd_ndb
*
seize_thd_ndb
();
static
void
release_thd_ndb
(
Thd_ndb
*
thd_ndb
);
/*
Condition pushdown
*/
const
COND
*
cond_push
(
const
COND
*
cond
);
void
cond_pop
();
uint8
table_cache_type
();
private:
...
...
@@ -214,9 +360,32 @@ class ha_ndbcluster: public handler
int
write_ndb_file
();
private:
int
check_ndb_connection
();
void
set_rec_per_key
();
void
records_update
();
void
no_uncommitted_rows_execute_failure
();
void
no_uncommitted_rows_update
(
int
);
void
no_uncommitted_rows_init
(
THD
*
);
void
no_uncommitted_rows_reset
(
THD
*
);
/*
Condition Pushdown to Handler (CPDH), private methods
*/
void
cond_clear
();
bool
serialize_cond
(
const
COND
*
cond
,
Ndb_cond_stack
*
ndb_cond
);
Ndb_cond
*
build_scan_filter_predicate
(
Ndb_cond
*
cond
,
NdbScanFilter
*
filter
);
Ndb_cond
*
build_scan_filter_group
(
Ndb_cond
*
cond
,
NdbScanFilter
*
filter
);
void
build_scan_filter
(
Ndb_cond
*
cond
,
NdbScanFilter
*
filter
);
void
generate_scan_filter
(
Ndb_cond_stack
*
cond_stack
,
NdbScanOperation
*
op
);
friend
int
execute_commit
(
ha_ndbcluster
*
,
NdbConnection
*
);
friend
int
execute_no_commit
(
ha_ndbcluster
*
,
NdbConnection
*
);
friend
int
execute_no_commit_ie
(
ha_ndbcluster
*
,
NdbConnection
*
);
NdbConnection
*
m_active_trans
;
NdbScanOperation
*
m_active_cursor
;
Ndb
*
m_ndb
;
...
...
@@ -254,7 +423,7 @@ class ha_ndbcluster: public handler
ha_rows
m_autoincrement_prefetch
;
bool
m_transaction_on
;
bool
m_use_local_query_cache
;
Ndb_cond_stack
*
m_cond_stack
;
bool
m_disable_multi_read
;
byte
*
m_multi_range_result_ptr
;
uint
m_multi_range_defined_count
;
...
...
@@ -263,16 +432,6 @@ class ha_ndbcluster: public handler
byte
*
m_multi_range_cursor_result_ptr
;
int
setup_recattr
(
const
NdbRecAttr
*
);
void
set_rec_per_key
();
void
records_update
();
void
no_uncommitted_rows_execute_failure
();
void
no_uncommitted_rows_update
(
int
);
void
no_uncommitted_rows_init
(
THD
*
);
void
no_uncommitted_rows_reset
(
THD
*
);
friend
int
execute_no_commit
(
ha_ndbcluster
*
,
NdbConnection
*
);
friend
int
execute_commit
(
ha_ndbcluster
*
,
NdbConnection
*
);
friend
int
execute_no_commit_ie
(
ha_ndbcluster
*
,
NdbConnection
*
);
};
bool
ndbcluster_init
(
void
);
...
...
sql/handler.h
View file @
cc566a79
...
...
@@ -264,6 +264,9 @@ typedef struct st_table TABLE;
struct
st_foreign_key_info
;
typedef
struct
st_foreign_key_info
FOREIGN_KEY_INFO
;
/* Forward declaration for Condition Pushdown to Handler (CPDH) */
typedef
struct
Item
COND
;
typedef
struct
st_ha_check_opt
{
ulong
sort_buffer_size
;
...
...
@@ -575,6 +578,12 @@ class handler :public Sql_alloc
{
return
memcmp
(
ref1
,
ref2
,
ref_length
);
}
/*
Condition pushdown to storage engines
*/
virtual
const
COND
*
cond_push
(
const
COND
*
cond
)
{
return
cond
;
};
virtual
void
cond_pop
()
{
return
;
};
};
/* Some extern variables used with handlers */
...
...
sql/item.h
View file @
cc566a79
...
...
@@ -113,6 +113,8 @@ class DTCollation {
typedef
bool
(
Item
::*
Item_processor
)(
byte
*
arg
);
typedef
Item
*
(
Item
::*
Item_transformer
)
(
byte
*
arg
);
typedef
void
(
*
Item_cond_traverser
)
(
const
Item
*
item
,
void
*
arg
);
class
Item
{
Item
(
const
Item
&
);
/* Prevent use of these */
void
operator
=
(
Item
&
);
...
...
@@ -124,7 +126,7 @@ class Item {
static
void
operator
delete
(
void
*
ptr
,
size_t
size
,
MEM_ROOT
*
mem_root
)
{
TRASH
(
ptr
,
size
);
}
enum
Type
{
FIELD_ITEM
,
FUNC_ITEM
,
SUM_FUNC_ITEM
,
STRING_ITEM
,
enum
Type
{
FIELD_ITEM
=
0
,
FUNC_ITEM
,
SUM_FUNC_ITEM
,
STRING_ITEM
,
INT_ITEM
,
REAL_ITEM
,
NULL_ITEM
,
VARBIN_ITEM
,
COPY_STR_ITEM
,
FIELD_AVG_ITEM
,
DEFAULT_VALUE_ITEM
,
PROC_ITEM
,
COND_ITEM
,
REF_ITEM
,
FIELD_STD_ITEM
,
...
...
@@ -134,6 +136,8 @@ class Item {
enum
cond_result
{
COND_UNDEF
,
COND_OK
,
COND_TRUE
,
COND_FALSE
};
enum
traverse_order
{
POSTFIX
,
PREFIX
};
/*
str_values's main purpose is to be used to cache the value in
save_in_field
...
...
@@ -315,6 +319,13 @@ class Item {
return
(
this
->*
transformer
)(
arg
);
}
virtual
void
traverse_cond
(
Item_cond_traverser
traverser
,
void
*
arg
,
traverse_order
order
=
POSTFIX
)
{
(
*
traverser
)(
this
,
arg
);
}
virtual
bool
remove_dependence_processor
(
byte
*
arg
)
{
return
0
;
}
virtual
bool
remove_fixed
(
byte
*
arg
)
{
fixed
=
0
;
return
0
;
}
virtual
bool
cleanup_processor
(
byte
*
arg
);
...
...
sql/item_cmpfunc.cc
View file @
cc566a79
...
...
@@ -2037,6 +2037,20 @@ Item *Item_cond::transform(Item_transformer transformer, byte *arg)
return
Item_func
::
transform
(
transformer
,
arg
);
}
void
Item_cond
::
traverse_cond
(
Item_cond_traverser
traverser
,
void
*
arg
,
traverse_order
order
)
{
List_iterator
<
Item
>
li
(
list
);
Item
*
item
;
if
(
order
==
PREFIX
)
(
*
traverser
)(
this
,
arg
);
while
((
item
=
li
++
))
{
item
->
traverse_cond
(
traverser
,
arg
,
order
);
}
if
(
order
==
POSTFIX
)
(
*
traverser
)(
this
,
arg
);
}
void
Item_cond
::
split_sum_func
(
THD
*
thd
,
Item
**
ref_pointer_array
,
List
<
Item
>
&
fields
)
...
...
sql/item_cmpfunc.h
View file @
cc566a79
...
...
@@ -965,6 +965,9 @@ class Item_cond :public Item_bool_func
void
copy_andor_arguments
(
THD
*
thd
,
Item_cond
*
item
);
bool
walk
(
Item_processor
processor
,
byte
*
arg
);
Item
*
transform
(
Item_transformer
transformer
,
byte
*
arg
);
void
traverse_cond
(
Item_cond_traverser
,
void
*
arg
,
traverse_order
order
=
POSTFIX
);
void
neg_arguments
(
THD
*
thd
);
};
...
...
sql/item_func.cc
View file @
cc566a79
...
...
@@ -342,6 +342,22 @@ bool Item_func::walk (Item_processor processor, byte *argument)
return
(
this
->*
processor
)(
argument
);
}
void
Item_func
::
traverse_cond
(
Item_cond_traverser
traverser
,
void
*
argument
,
traverse_order
order
)
{
if
(
arg_count
)
{
Item
**
arg
,
**
arg_end
;
if
(
order
==
PREFIX
)
(
traverser
)(
this
,
argument
);
for
(
arg
=
args
,
arg_end
=
args
+
arg_count
;
arg
!=
arg_end
;
arg
++
)
{
(
*
arg
)
->
traverse_cond
(
traverser
,
argument
,
order
);
}
}
if
(
order
==
POSTFIX
)
(
traverser
)(
this
,
argument
);
}
/*
Transform an Item_func object with a transformer callback function
...
...
sql/item_func.h
View file @
cc566a79
...
...
@@ -154,6 +154,9 @@ class Item_func :public Item_result_field
uint
flags
=
0
);
bool
walk
(
Item_processor
processor
,
byte
*
arg
);
Item
*
transform
(
Item_transformer
transformer
,
byte
*
arg
);
void
traverse_cond
(
Item_cond_traverser
traverser
,
void
*
arg
,
traverse_order
order
=
POSTFIX
);
};
...
...
sql/mysqld.cc
View file @
cc566a79
...
...
@@ -4093,6 +4093,7 @@ enum options_mysqld
OPT_INNODB
,
OPT_ISAM
,
OPT_NDBCLUSTER
,
OPT_NDB_CONNECTSTRING
,
OPT_NDB_USE_EXACT_COUNT
,
OPT_NDB_FORCE_SEND
,
OPT_NDB_AUTOINCREMENT_PREFETCH_SZ
,
OPT_NDB_CONDITION_PUSHDOWN
,
OPT_SKIP_SAFEMALLOC
,
OPT_TEMP_POOL
,
OPT_TX_ISOLATION
,
OPT_SKIP_STACK_TRACE
,
OPT_SKIP_SYMLINKS
,
...
...
@@ -4547,6 +4548,12 @@ Disable with --skip-ndbcluster (will save memory).",
(
gptr
*
)
&
opt_ndbcluster
,
(
gptr
*
)
&
opt_ndbcluster
,
0
,
GET_BOOL
,
NO_ARG
,
OPT_NDBCLUSTER_DEFAULT
,
0
,
0
,
0
,
0
,
0
},
#ifdef HAVE_NDBCLUSTER_DB
{
"ndb-condition-pushdown"
,
OPT_NDB_CONDITION_PUSHDOWN
,
"Push supported query conditions to the ndbcluster storage engine."
,
(
gptr
*
)
&
global_system_variables
.
ndb_condition_pushdown
,
(
gptr
*
)
&
global_system_variables
.
ndb_condition_pushdown
,
0
,
GET_BOOL
,
NO_ARG
,
0
,
0
,
0
,
0
,
0
,
0
},
{
"ndb-connectstring"
,
OPT_NDB_CONNECTSTRING
,
"Connect string for ndbcluster."
,
(
gptr
*
)
&
ndbcluster_connectstring
,
(
gptr
*
)
&
ndbcluster_connectstring
,
...
...
sql/set_var.cc
View file @
cc566a79
...
...
@@ -388,6 +388,9 @@ sys_ndb_use_exact_count("ndb_use_exact_count",
sys_var_thd_bool
sys_ndb_use_transactions
(
"ndb_use_transactions"
,
&
SV
::
ndb_use_transactions
);
sys_var_thd_bool
sys_ndb_condition_pushdown
(
"ndb_condition_pushdown"
,
&
SV
::
ndb_condition_pushdown
);
// ndb server global variable settings
// none
#endif
...
...
@@ -654,6 +657,7 @@ sys_var *sys_variables[]=
&
sys_ndb_force_send
,
&
sys_ndb_use_exact_count
,
&
sys_ndb_use_transactions
,
&
sys_ndb_condition_pushdown
,
#endif
&
sys_unique_checks
,
&
sys_updatable_views_with_limit
,
...
...
@@ -824,6 +828,8 @@ struct show_var_st init_vars[]= {
{
sys_ndb_force_send
.
name
,
(
char
*
)
&
sys_ndb_force_send
,
SHOW_SYS
},
{
sys_ndb_use_exact_count
.
name
,(
char
*
)
&
sys_ndb_use_exact_count
,
SHOW_SYS
},
{
sys_ndb_use_transactions
.
name
,(
char
*
)
&
sys_ndb_use_transactions
,
SHOW_SYS
},
{
sys_ndb_condition_pushdown
.
name
,
(
char
*
)
&
sys_ndb_condition_pushdown
,
SHOW_SYS
},
#endif
{
sys_net_buffer_length
.
name
,(
char
*
)
&
sys_net_buffer_length
,
SHOW_SYS
},
{
sys_net_read_timeout
.
name
,
(
char
*
)
&
sys_net_read_timeout
,
SHOW_SYS
},
...
...
sql/sql_class.h
View file @
cc566a79
...
...
@@ -436,6 +436,7 @@ struct system_variables
my_bool
ndb_force_send
;
my_bool
ndb_use_exact_count
;
my_bool
ndb_use_transactions
;
my_bool
ndb_condition_pushdown
;
#endif
/* HAVE_NDBCLUSTER_DB */
my_bool
old_passwords
;
...
...
sql/sql_select.cc
View file @
cc566a79
...
...
@@ -5269,6 +5269,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
if
(
!
(
tmp
=
add_found_match_trig_cond
(
first_inner_tab
,
tmp
,
0
)))
DBUG_RETURN
(
1
);
tab
->
select_cond
=
sel
->
cond
=
tmp
;
tab
->
table
->
file
->
cond_push
(
tmp
);
// Push condition to handler
}
else
tab
->
select_cond
=
sel
->
cond
=
NULL
;
...
...
@@ -5390,6 +5391,8 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
join
->
thd
->
memdup
((
gptr
)
sel
,
sizeof
(
SQL_SELECT
));
tab
->
cache
.
select
->
cond
=
tmp
;
tab
->
cache
.
select
->
read_tables
=
join
->
const_table_map
;
if
(
tmp
!=
tab
->
select_cond
)
tab
->
table
->
file
->
cond_push
(
tmp
);
// Push condition to handler
}
}
}
...
...
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