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
02fbe775
Commit
02fbe775
authored
Feb 02, 2004
by
unknown
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Indexes can be used for optimization if the operation
collation is the same with the index collation.
parent
d2517310
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
153 additions
and
34 deletions
+153
-34
mysql-test/r/ctype_collate.result
mysql-test/r/ctype_collate.result
+47
-0
mysql-test/t/ctype_collate.test
mysql-test/t/ctype_collate.test
+38
-0
sql/item.h
sql/item.h
+1
-0
sql/item_cmpfunc.h
sql/item_cmpfunc.h
+7
-0
sql/opt_range.cc
sql/opt_range.cc
+44
-29
sql/sql_select.cc
sql/sql_select.cc
+16
-5
No files found.
mysql-test/r/ctype_collate.result
View file @
02fbe775
...
...
@@ -541,3 +541,50 @@ s2 CHAR(5) COLLATE latin1_swedish_ci);
SELECT * FROM t1 WHERE s1 = s2;
ERROR HY000: Illegal mix of collations (latin1_german1_ci,IMPLICIT) and (latin1_swedish_ci,IMPLICIT) for operation '='
DROP TABLE t1;
SET NAMES latin1;
CREATE TABLE t1
(s1 char(10) COLLATE latin1_german1_ci,
s2 char(10) COLLATE latin1_swedish_ci,
KEY(s1),
KEY(s2));
INSERT INTO t1 VALUES ('a','a');
INSERT INTO t1 VALUES ('b','b');
INSERT INTO t1 VALUES ('c','c');
INSERT INTO t1 VALUES ('d','d');
INSERT INTO t1 VALUES ('e','e');
INSERT INTO t1 VALUES ('f','f');
INSERT INTO t1 VALUES ('g','g');
INSERT INTO t1 VALUES ('h','h');
INSERT INTO t1 VALUES ('i','i');
INSERT INTO t1 VALUES ('j','j');
EXPLAIN SELECT * FROM t1 WHERE s1='a';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref s1 s1 11 const 1 Using where
EXPLAIN SELECT * FROM t1 WHERE s2='a';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref s2 s2 11 const 1 Using where
EXPLAIN SELECT * FROM t1 WHERE s1='a' COLLATE latin1_german1_ci;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref s1 s1 11 const 1 Using where
EXPLAIN SELECT * FROM t1 WHERE s2='a' COLLATE latin1_german1_ci;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL s2 NULL NULL NULL 10 Using where
EXPLAIN SELECT * FROM t1 WHERE s1 BETWEEN 'a' AND 'b' COLLATE latin1_german1_ci;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range s1 s1 11 NULL 2 Using where
EXPLAIN SELECT * FROM t1 WHERE s2 BETWEEN 'a' AND 'b' COLLATE latin1_german1_ci;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL s2 NULL NULL NULL 10 Using where
EXPLAIN SELECT * FROM t1 WHERE s1 IN ('a','b' COLLATE latin1_german1_ci);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range s1 s1 11 NULL 2 Using where
EXPLAIN SELECT * FROM t1 WHERE s2 IN ('a','b' COLLATE latin1_german1_ci);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL s2 NULL NULL NULL 10 Using where
EXPLAIN SELECT * FROM t1 WHERE s1 LIKE 'a' COLLATE latin1_german1_ci;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range s1 s1 11 NULL 1 Using where
EXPLAIN SELECT * FROM t1 WHERE s2 LIKE 'a' COLLATE latin1_german1_ci;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL s2 NULL NULL NULL 10 Using where
DROP TABLE t1;
mysql-test/t/ctype_collate.test
View file @
02fbe775
...
...
@@ -156,3 +156,41 @@ CREATE TABLE t1
--
error
1266
SELECT
*
FROM
t1
WHERE
s1
=
s2
;
DROP
TABLE
t1
;
#
# Test that optimizer doesn't use indexes with wrong collation
#
SET
NAMES
latin1
;
CREATE
TABLE
t1
(
s1
char
(
10
)
COLLATE
latin1_german1_ci
,
s2
char
(
10
)
COLLATE
latin1_swedish_ci
,
KEY
(
s1
),
KEY
(
s2
));
INSERT
INTO
t1
VALUES
(
'a'
,
'a'
);
INSERT
INTO
t1
VALUES
(
'b'
,
'b'
);
INSERT
INTO
t1
VALUES
(
'c'
,
'c'
);
INSERT
INTO
t1
VALUES
(
'd'
,
'd'
);
INSERT
INTO
t1
VALUES
(
'e'
,
'e'
);
INSERT
INTO
t1
VALUES
(
'f'
,
'f'
);
INSERT
INTO
t1
VALUES
(
'g'
,
'g'
);
INSERT
INTO
t1
VALUES
(
'h'
,
'h'
);
INSERT
INTO
t1
VALUES
(
'i'
,
'i'
);
INSERT
INTO
t1
VALUES
(
'j'
,
'j'
);
EXPLAIN
SELECT
*
FROM
t1
WHERE
s1
=
'a'
;
EXPLAIN
SELECT
*
FROM
t1
WHERE
s2
=
'a'
;
EXPLAIN
SELECT
*
FROM
t1
WHERE
s1
=
'a'
COLLATE
latin1_german1_ci
;
EXPLAIN
SELECT
*
FROM
t1
WHERE
s2
=
'a'
COLLATE
latin1_german1_ci
;
EXPLAIN
SELECT
*
FROM
t1
WHERE
s1
BETWEEN
'a'
AND
'b'
COLLATE
latin1_german1_ci
;
EXPLAIN
SELECT
*
FROM
t1
WHERE
s2
BETWEEN
'a'
AND
'b'
COLLATE
latin1_german1_ci
;
EXPLAIN
SELECT
*
FROM
t1
WHERE
s1
IN
(
'a'
,
'b'
COLLATE
latin1_german1_ci
);
EXPLAIN
SELECT
*
FROM
t1
WHERE
s2
IN
(
'a'
,
'b'
COLLATE
latin1_german1_ci
);
EXPLAIN
SELECT
*
FROM
t1
WHERE
s1
LIKE
'a'
COLLATE
latin1_german1_ci
;
EXPLAIN
SELECT
*
FROM
t1
WHERE
s2
LIKE
'a'
COLLATE
latin1_german1_ci
;
DROP
TABLE
t1
;
sql/item.h
View file @
02fbe775
...
...
@@ -204,6 +204,7 @@ class Item {
virtual
Item
*
get_tmp_table_item
(
THD
*
thd
)
{
return
copy_or_same
(
thd
);
}
CHARSET_INFO
*
default_charset
()
const
;
virtual
CHARSET_INFO
*
compare_collation
()
{
return
NULL
;
}
virtual
bool
walk
(
Item_processor
processor
,
byte
*
arg
)
{
...
...
sql/item_cmpfunc.h
View file @
02fbe775
...
...
@@ -191,6 +191,7 @@ class Item_bool_func2 :public Item_int_func
bool
have_rev_func
()
const
{
return
rev_functype
()
!=
UNKNOWN_FUNC
;
}
void
print
(
String
*
str
)
{
Item_func
::
print_op
(
str
);
}
bool
is_null
()
{
return
test
(
args
[
0
]
->
is_null
()
||
args
[
1
]
->
is_null
());
}
CHARSET_INFO
*
compare_collation
()
{
return
cmp
.
cmp_collation
.
collation
;
}
friend
class
Arg_comparator
;
};
...
...
@@ -340,6 +341,7 @@ class Item_func_between :public Item_int_func
const
char
*
func_name
()
const
{
return
"between"
;
}
void
fix_length_and_dec
();
void
print
(
String
*
str
);
CHARSET_INFO
*
compare_collation
()
{
return
cmp_collation
.
collation
;
}
};
...
...
@@ -479,6 +481,7 @@ class Item_func_case :public Item_func
const
char
*
func_name
()
const
{
return
"case"
;
}
void
print
(
String
*
str
);
Item
*
find_item
(
String
*
str
);
CHARSET_INFO
*
compare_collation
()
{
return
cmp_collation
.
collation
;
}
};
...
...
@@ -726,6 +729,7 @@ class Item_func_in :public Item_int_func
enum
Functype
functype
()
const
{
return
IN_FUNC
;
}
const
char
*
func_name
()
const
{
return
" IN "
;
}
bool
nulls_in_row
();
CHARSET_INFO
*
compare_collation
()
{
return
cmp_collation
.
collation
;
}
};
/* Functions used by where clause */
...
...
@@ -766,6 +770,7 @@ class Item_func_isnull :public Item_bool_func
table_map
not_null_tables
()
const
{
return
0
;
}
optimize_type
select_optimize
()
const
{
return
OPTIMIZE_NULL
;
}
Item
*
neg_transformer
();
CHARSET_INFO
*
compare_collation
()
{
return
args
[
0
]
->
collation
.
collation
;
}
};
/* Functions used by HAVING for rewriting IN subquery */
...
...
@@ -800,6 +805,7 @@ class Item_func_isnotnull :public Item_bool_func
table_map
not_null_tables
()
const
{
return
0
;
}
Item
*
neg_transformer
();
void
print
(
String
*
str
);
CHARSET_INFO
*
compare_collation
()
{
return
args
[
0
]
->
collation
.
collation
;
}
};
...
...
@@ -854,6 +860,7 @@ class Item_func_regex :public Item_bool_func
bool
fix_fields
(
THD
*
thd
,
struct
st_table_list
*
tlist
,
Item
**
ref
);
const
char
*
func_name
()
const
{
return
"regexp"
;
}
void
print
(
String
*
str
)
{
print_op
(
str
);
}
CHARSET_INFO
*
compare_collation
()
{
return
cmp_collation
.
collation
;
}
};
#else
...
...
sql/opt_range.cc
View file @
02fbe775
...
...
@@ -291,10 +291,11 @@ typedef struct st_qsel_param {
bool
quick
;
// Don't calulate possible keys
}
PARAM
;
static
SEL_TREE
*
get_mm_parts
(
PARAM
*
param
,
Field
*
field
,
static
SEL_TREE
*
get_mm_parts
(
PARAM
*
param
,
COND
*
cond_func
,
Field
*
field
,
Item_func
::
Functype
type
,
Item
*
value
,
Item_result
cmp_type
);
static
SEL_ARG
*
get_mm_leaf
(
PARAM
*
param
,
Field
*
field
,
KEY_PART
*
key_part
,
static
SEL_ARG
*
get_mm_leaf
(
PARAM
*
param
,
COND
*
cond_func
,
Field
*
field
,
KEY_PART
*
key_part
,
Item_func
::
Functype
type
,
Item
*
value
);
static
SEL_TREE
*
get_mm_tree
(
PARAM
*
param
,
COND
*
cond
);
static
ha_rows
check_quick_select
(
PARAM
*
param
,
uint
index
,
SEL_ARG
*
key_tree
);
...
...
@@ -834,10 +835,10 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond)
Field
*
field
=
((
Item_field
*
)
(
cond_func
->
arguments
()[
0
]))
->
field
;
Item_result
cmp_type
=
field
->
cmp_type
();
DBUG_RETURN
(
tree_and
(
param
,
get_mm_parts
(
param
,
field
,
get_mm_parts
(
param
,
cond_func
,
field
,
Item_func
::
GE_FUNC
,
cond_func
->
arguments
()[
1
],
cmp_type
),
get_mm_parts
(
param
,
field
,
get_mm_parts
(
param
,
cond_func
,
field
,
Item_func
::
LE_FUNC
,
cond_func
->
arguments
()[
2
],
cmp_type
)));
}
...
...
@@ -850,13 +851,14 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond)
{
Field
*
field
=
((
Item_field
*
)
(
func
->
key_item
()))
->
field
;
Item_result
cmp_type
=
field
->
cmp_type
();
tree
=
get_mm_parts
(
param
,
field
,
Item_func
::
EQ_FUNC
,
tree
=
get_mm_parts
(
param
,
cond_func
,
field
,
Item_func
::
EQ_FUNC
,
func
->
arguments
()[
1
],
cmp_type
);
if
(
!
tree
)
DBUG_RETURN
(
tree
);
// Not key field
for
(
uint
i
=
2
;
i
<
func
->
argument_count
();
i
++
)
{
SEL_TREE
*
new_tree
=
get_mm_parts
(
param
,
field
,
Item_func
::
EQ_FUNC
,
SEL_TREE
*
new_tree
=
get_mm_parts
(
param
,
cond_func
,
field
,
Item_func
::
EQ_FUNC
,
func
->
arguments
()[
i
],
cmp_type
);
tree
=
tree_or
(
param
,
tree
,
new_tree
);
}
...
...
@@ -875,7 +877,7 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond)
/* btw, ft_func's arguments()[0] isn't FIELD_ITEM. SerG*/
if
(
cond_func
->
arguments
()[
0
]
->
type
()
==
Item
::
FIELD_ITEM
)
{
tree
=
get_mm_parts
(
param
,
tree
=
get_mm_parts
(
param
,
cond_func
,
((
Item_field
*
)
(
cond_func
->
arguments
()[
0
]))
->
field
,
cond_func
->
functype
(),
cond_func
->
arg_count
>
1
?
cond_func
->
arguments
()[
1
]
:
...
...
@@ -888,7 +890,7 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond)
cond_func
->
have_rev_func
()
&&
cond_func
->
arguments
()[
1
]
->
type
()
==
Item
::
FIELD_ITEM
)
{
DBUG_RETURN
(
get_mm_parts
(
param
,
DBUG_RETURN
(
get_mm_parts
(
param
,
cond_func
,
((
Item_field
*
)
(
cond_func
->
arguments
()[
1
]))
->
field
,
((
Item_bool_func2
*
)
cond_func
)
->
rev_functype
(),
...
...
@@ -902,7 +904,8 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond)
static
SEL_TREE
*
get_mm_parts
(
PARAM
*
param
,
Field
*
field
,
Item_func
::
Functype
type
,
get_mm_parts
(
PARAM
*
param
,
COND
*
cond_func
,
Field
*
field
,
Item_func
::
Functype
type
,
Item
*
value
,
Item_result
cmp_type
)
{
bool
ne_func
=
FALSE
;
...
...
@@ -931,7 +934,8 @@ get_mm_parts(PARAM *param, Field *field, Item_func::Functype type,
DBUG_RETURN
(
0
);
// OOM
if
(
!
value
||
!
(
value
->
used_tables
()
&
~
param
->
read_tables
))
{
sel_arg
=
get_mm_leaf
(
param
,
key_part
->
field
,
key_part
,
type
,
value
);
sel_arg
=
get_mm_leaf
(
param
,
cond_func
,
key_part
->
field
,
key_part
,
type
,
value
);
if
(
!
sel_arg
)
continue
;
if
(
sel_arg
->
type
==
SEL_ARG
::
IMPOSSIBLE
)
...
...
@@ -953,7 +957,8 @@ get_mm_parts(PARAM *param, Field *field, Item_func::Functype type,
if
(
ne_func
)
{
SEL_TREE
*
tree2
=
get_mm_parts
(
param
,
field
,
Item_func
::
GT_FUNC
,
SEL_TREE
*
tree2
=
get_mm_parts
(
param
,
cond_func
,
field
,
Item_func
::
GT_FUNC
,
value
,
cmp_type
);
if
(
tree2
)
tree
=
tree_or
(
param
,
tree
,
tree2
);
...
...
@@ -963,7 +968,7 @@ get_mm_parts(PARAM *param, Field *field, Item_func::Functype type,
static
SEL_ARG
*
get_mm_leaf
(
PARAM
*
param
,
Field
*
field
,
KEY_PART
*
key_part
,
get_mm_leaf
(
PARAM
*
param
,
COND
*
conf_func
,
Field
*
field
,
KEY_PART
*
key_part
,
Item_func
::
Functype
type
,
Item
*
value
)
{
uint
maybe_null
=
(
uint
)
field
->
real_maybe_null
(),
copies
;
...
...
@@ -972,6 +977,32 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part,
char
*
str
,
*
str2
;
DBUG_ENTER
(
"get_mm_leaf"
);
if
(
!
value
)
// IS NULL or IS NOT NULL
{
if
(
field
->
table
->
outer_join
)
// Can't use a key on this
DBUG_RETURN
(
0
);
if
(
!
maybe_null
)
// Not null field
DBUG_RETURN
(
type
==
Item_func
::
ISNULL_FUNC
?
&
null_element
:
0
);
if
(
!
(
tree
=
new
SEL_ARG
(
field
,
is_null_string
,
is_null_string
)))
DBUG_RETURN
(
0
);
// out of memory
if
(
type
==
Item_func
::
ISNOTNULL_FUNC
)
{
tree
->
min_flag
=
NEAR_MIN
;
/* IS NOT NULL -> X > NULL */
tree
->
max_flag
=
NO_MAX_RANGE
;
}
DBUG_RETURN
(
tree
);
}
/*
We can't use an index when comparing stings of
different collations
*/
if
(
field
->
result_type
()
==
STRING_RESULT
&&
value
->
result_type
()
==
STRING_RESULT
&&
key_part
->
image_type
==
Field
::
itRAW
&&
((
Field_str
*
)
field
)
->
charset
()
!=
conf_func
->
compare_collation
())
DBUG_RETURN
(
0
);
if
(
type
==
Item_func
::
LIKE_FUNC
)
{
bool
like_error
;
...
...
@@ -1035,22 +1066,6 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part,
DBUG_RETURN
(
new
SEL_ARG
(
field
,
min_str
,
max_str
));
}
if
(
!
value
)
// IS NULL or IS NOT NULL
{
if
(
field
->
table
->
outer_join
)
// Can't use a key on this
DBUG_RETURN
(
0
);
if
(
!
maybe_null
)
// Not null field
DBUG_RETURN
(
type
==
Item_func
::
ISNULL_FUNC
?
&
null_element
:
0
);
if
(
!
(
tree
=
new
SEL_ARG
(
field
,
is_null_string
,
is_null_string
)))
DBUG_RETURN
(
0
);
// out of memory
if
(
type
==
Item_func
::
ISNOTNULL_FUNC
)
{
tree
->
min_flag
=
NEAR_MIN
;
/* IS NOT NULL -> X > NULL */
tree
->
max_flag
=
NO_MAX_RANGE
;
}
DBUG_RETURN
(
tree
);
}
if
(
!
field
->
optimize_range
(
param
->
real_keynr
[
key_part
->
key
])
&&
type
!=
Item_func
::
EQ_FUNC
&&
type
!=
Item_func
::
EQUAL_FUNC
)
...
...
@@ -1064,7 +1079,7 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part,
value
->
result_type
()
!=
STRING_RESULT
&&
field
->
cmp_type
()
!=
value
->
result_type
())
DBUG_RETURN
(
0
);
if
(
value
->
save_in_field
(
field
,
1
)
>
0
)
{
/* This happens when we try to insert a NULL field in a not null column */
...
...
sql/sql_select.cc
View file @
02fbe775
...
...
@@ -2131,7 +2131,7 @@ merge_key_fields(KEY_FIELD *start,KEY_FIELD *new_fields,KEY_FIELD *end,
*/
static
void
add_key_field
(
KEY_FIELD
**
key_fields
,
uint
and_level
,
add_key_field
(
KEY_FIELD
**
key_fields
,
uint
and_level
,
COND
*
cond
,
Field
*
field
,
bool
eq_func
,
Item
**
value
,
uint
num_values
,
table_map
usable_tables
)
{
...
...
@@ -2198,6 +2198,17 @@ add_key_field(KEY_FIELD **key_fields,uint and_level,
(
*
value
)
->
result_type
()
!=
STRING_RESULT
&&
field
->
cmp_type
()
!=
(
*
value
)
->
result_type
())
return
;
/*
We can't use indexes if the effective collation
of the operation differ from the field collation.
*/
if
(
field
->
result_type
()
==
STRING_RESULT
&&
(
*
value
)
->
result_type
()
==
STRING_RESULT
&&
field
->
cmp_type
()
==
STRING_RESULT
&&
((
Field_str
*
)
field
)
->
charset
()
!=
cond
->
compare_collation
())
return
;
}
}
DBUG_ASSERT
(
num_values
==
1
);
...
...
@@ -2261,7 +2272,7 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level,
// BETWEEN or IN
if
(
cond_func
->
key_item
()
->
real_item
()
->
type
()
==
Item
::
FIELD_ITEM
&&
!
(
cond_func
->
used_tables
()
&
OUTER_REF_TABLE_BIT
))
add_key_field
(
key_fields
,
*
and_level
,
add_key_field
(
key_fields
,
*
and_level
,
cond_func
,
((
Item_field
*
)
(
cond_func
->
key_item
()
->
real_item
()))
->
field
,
0
,
cond_func
->
arguments
()
+
1
,
cond_func
->
argument_count
()
-
1
,
...
...
@@ -2275,7 +2286,7 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level,
if
(
cond_func
->
arguments
()[
0
]
->
real_item
()
->
type
()
==
Item
::
FIELD_ITEM
&&
!
(
cond_func
->
arguments
()[
0
]
->
used_tables
()
&
OUTER_REF_TABLE_BIT
))
{
add_key_field
(
key_fields
,
*
and_level
,
add_key_field
(
key_fields
,
*
and_level
,
cond_func
,
((
Item_field
*
)
(
cond_func
->
arguments
()[
0
])
->
real_item
())
->
field
,
equal_func
,
...
...
@@ -2285,7 +2296,7 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level,
cond_func
->
functype
()
!=
Item_func
::
LIKE_FUNC
&&
!
(
cond_func
->
arguments
()[
1
]
->
used_tables
()
&
OUTER_REF_TABLE_BIT
))
{
add_key_field
(
key_fields
,
*
and_level
,
add_key_field
(
key_fields
,
*
and_level
,
cond_func
,
((
Item_field
*
)
(
cond_func
->
arguments
()[
1
])
->
real_item
())
->
field
,
equal_func
,
...
...
@@ -2301,7 +2312,7 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level,
Item
*
tmp
=
new
Item_null
;
if
(
!
tmp
)
// Should never be true
return
;
add_key_field
(
key_fields
,
*
and_level
,
add_key_field
(
key_fields
,
*
and_level
,
cond_func
,
((
Item_field
*
)
(
cond_func
->
arguments
()[
0
])
->
real_item
())
->
field
,
cond_func
->
functype
()
==
Item_func
::
ISNULL_FUNC
,
...
...
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