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
99413e46
Commit
99413e46
authored
Aug 28, 2009
by
Mattias Jonsson
Browse files
Options
Browse Files
Download
Plain Diff
merge
parents
f9e413a1
0a763971
Changes
14
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
1924 additions
and
68 deletions
+1924
-68
mysql-test/include/partition_date_range.inc
mysql-test/include/partition_date_range.inc
+63
-0
mysql-test/r/partition_pruning.result
mysql-test/r/partition_pruning.result
+1274
-0
mysql-test/r/partition_range.result
mysql-test/r/partition_range.result
+2
-2
mysql-test/t/partition_pruning.test
mysql-test/t/partition_pruning.test
+351
-0
sql-common/my_time.c
sql-common/my_time.c
+1
-3
sql/item.cc
sql/item.cc
+39
-11
sql/item.h
sql/item.h
+11
-4
sql/item_timefunc.cc
sql/item_timefunc.cc
+25
-6
sql/mysql_priv.h
sql/mysql_priv.h
+2
-1
sql/opt_range.cc
sql/opt_range.cc
+14
-12
sql/partition_info.h
sql/partition_info.h
+1
-0
sql/share/errmsg.txt
sql/share/errmsg.txt
+8
-8
sql/sql_partition.cc
sql/sql_partition.cc
+72
-6
sql/sql_table.cc
sql/sql_table.cc
+61
-15
No files found.
mysql-test/include/partition_date_range.inc
0 → 100644
View file @
99413e46
# Created for verifying bug#20577.
# expects TABLE t1 (... , a DATE, ...)
--
sorted_result
SELECT
*
FROM
t1
WHERE
a
<
'1001-01-01'
;
--
sorted_result
SELECT
*
FROM
t1
WHERE
a
<=
'1001-01-01'
;
--
sorted_result
SELECT
*
FROM
t1
WHERE
a
>=
'1001-01-01'
;
--
sorted_result
SELECT
*
FROM
t1
WHERE
a
>
'1001-01-01'
;
--
sorted_result
SELECT
*
FROM
t1
WHERE
a
=
'1001-01-01'
;
--
sorted_result
SELECT
*
FROM
t1
WHERE
a
<
'1001-00-00'
;
--
sorted_result
SELECT
*
FROM
t1
WHERE
a
<=
'1001-00-00'
;
--
sorted_result
SELECT
*
FROM
t1
WHERE
a
>=
'1001-00-00'
;
--
sorted_result
SELECT
*
FROM
t1
WHERE
a
>
'1001-00-00'
;
--
sorted_result
SELECT
*
FROM
t1
WHERE
a
=
'1001-00-00'
;
--
sorted_result
SELECT
*
FROM
t1
WHERE
a
<
'1999-02-31'
;
--
sorted_result
SELECT
*
FROM
t1
WHERE
a
<=
'1999-02-31'
;
--
sorted_result
SELECT
*
FROM
t1
WHERE
a
>=
'1999-02-31'
;
--
sorted_result
SELECT
*
FROM
t1
WHERE
a
>
'1999-02-31'
;
--
sorted_result
SELECT
*
FROM
t1
WHERE
a
=
'1999-02-31'
;
--
sorted_result
SELECT
*
FROM
t1
WHERE
a
BETWEEN
'0000-00-00'
AND
'1002-00-00'
;
--
sorted_result
SELECT
*
FROM
t1
WHERE
a
BETWEEN
'0000-00-00'
AND
'1001-01-01'
;
--
sorted_result
SELECT
*
FROM
t1
WHERE
a
BETWEEN
'0001-01-02'
AND
'1002-00-00'
;
--
sorted_result
SELECT
*
FROM
t1
WHERE
a
BETWEEN
'0001-01-01'
AND
'1001-01-01'
;
if
(
$explain_partitions
)
{
EXPLAIN
PARTITIONS
SELECT
*
FROM
t1
WHERE
a
<
'1001-01-01'
;
EXPLAIN
PARTITIONS
SELECT
*
FROM
t1
WHERE
a
<=
'1001-01-01'
;
EXPLAIN
PARTITIONS
SELECT
*
FROM
t1
WHERE
a
>=
'1001-01-01'
;
EXPLAIN
PARTITIONS
SELECT
*
FROM
t1
WHERE
a
>
'1001-01-01'
;
EXPLAIN
PARTITIONS
SELECT
*
FROM
t1
WHERE
a
=
'1001-01-01'
;
EXPLAIN
PARTITIONS
SELECT
*
FROM
t1
WHERE
a
<
'1001-00-00'
;
EXPLAIN
PARTITIONS
SELECT
*
FROM
t1
WHERE
a
<=
'1001-00-00'
;
EXPLAIN
PARTITIONS
SELECT
*
FROM
t1
WHERE
a
>=
'1001-00-00'
;
EXPLAIN
PARTITIONS
SELECT
*
FROM
t1
WHERE
a
>
'1001-00-00'
;
EXPLAIN
PARTITIONS
SELECT
*
FROM
t1
WHERE
a
=
'1001-00-00'
;
EXPLAIN
PARTITIONS
SELECT
*
FROM
t1
WHERE
a
<
'1999-02-31'
;
EXPLAIN
PARTITIONS
SELECT
*
FROM
t1
WHERE
a
<=
'1999-02-31'
;
EXPLAIN
PARTITIONS
SELECT
*
FROM
t1
WHERE
a
>=
'1999-02-31'
;
EXPLAIN
PARTITIONS
SELECT
*
FROM
t1
WHERE
a
>
'1999-02-31'
;
EXPLAIN
PARTITIONS
SELECT
*
FROM
t1
WHERE
a
=
'1999-02-31'
;
EXPLAIN
PARTITIONS
SELECT
*
FROM
t1
WHERE
a
BETWEEN
'0000-00-00'
AND
'1002-00-00'
;
EXPLAIN
PARTITIONS
SELECT
*
FROM
t1
WHERE
a
BETWEEN
'0000-00-00'
AND
'1001-01-01'
;
EXPLAIN
PARTITIONS
SELECT
*
FROM
t1
WHERE
a
BETWEEN
'0001-01-02'
AND
'1002-00-00'
;
EXPLAIN
PARTITIONS
SELECT
*
FROM
t1
WHERE
a
BETWEEN
'0001-01-01'
AND
'1001-01-01'
;
}
mysql-test/r/partition_pruning.result
View file @
99413e46
This diff is collapsed.
Click to expand it.
mysql-test/r/partition_range.result
View file @
99413e46
...
...
@@ -745,7 +745,7 @@ a
EXPLAIN PARTITIONS SELECT * FROM t1
WHERE a >= '2004-07-01' AND a <= '2004-09-30';
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p
407,p408,p409 ALL NULL NULL NULL NULL 9
Using where
1 SIMPLE t1 p
3xx,p407,p408,p409 ALL NULL NULL NULL NULL 18
Using where
SELECT * from t1
WHERE (a >= '2004-07-01' AND a <= '2004-09-30') OR
(a >= '2005-07-01' AND a <= '2005-09-30');
...
...
@@ -772,7 +772,7 @@ EXPLAIN PARTITIONS SELECT * from t1
WHERE (a >= '2004-07-01' AND a <= '2004-09-30') OR
(a >= '2005-07-01' AND a <= '2005-09-30');
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p
407,p408,p409,p507,p508,p509 ALL NULL NULL NULL NULL 18
Using where
1 SIMPLE t1 p
3xx,p407,p408,p409,p507,p508,p509 ALL NULL NULL NULL NULL 27
Using where
DROP TABLE t1;
create table t1 (a int);
insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
...
...
mysql-test/t/partition_pruning.test
View file @
99413e46
This diff is collapsed.
Click to expand it.
sql-common/my_time.c
View file @
99413e46
...
...
@@ -450,9 +450,7 @@ str_to_datetime(const char *str, uint length, MYSQL_TIME *l_time,
}
}
DBUG_RETURN
(
l_time
->
time_type
=
(
number_of_fields
<=
3
?
MYSQL_TIMESTAMP_DATE
:
MYSQL_TIMESTAMP_DATETIME
));
DBUG_RETURN
(
l_time
->
time_type
);
err:
bzero
((
char
*
)
l_time
,
sizeof
(
*
l_time
));
...
...
sql/item.cc
View file @
99413e46
...
...
@@ -6853,14 +6853,21 @@ void resolve_const_item(THD *thd, Item **ref, Item *comp_item)
}
/**
Return true if the value stored in the field is equal to the const
item.
Compare the value stored in field, with the original item.
We need to use this on the range optimizer because in some cases
we can't store the value in the field without some precision/character loss.
@param field field which the item is converted and stored in
@param item original item
@return Return an integer greater than, equal to, or less than 0 if
the value stored in the field is greater than, equal to,
or less than the original item
@note We only use this on the range optimizer/partition pruning,
because in some cases we can't store the value in the field
without some precision/character loss.
*/
bool
field_is_equal_to_item
(
Field
*
field
,
Item
*
item
)
int
stored_field_cmp_to_item
(
Field
*
field
,
Item
*
item
)
{
Item_result
res_type
=
item_cmp_type
(
field
->
result_type
(),
...
...
@@ -6871,28 +6878,49 @@ bool field_is_equal_to_item(Field *field,Item *item)
char
field_buff
[
MAX_FIELD_WIDTH
];
String
item_tmp
(
item_buff
,
sizeof
(
item_buff
),
&
my_charset_bin
),
*
item_result
;
String
field_tmp
(
field_buff
,
sizeof
(
field_buff
),
&
my_charset_bin
);
enum_field_types
field_type
;
item_result
=
item
->
val_str
(
&
item_tmp
);
if
(
item
->
null_value
)
return
1
;
// This must be true
return
0
;
field
->
val_str
(
&
field_tmp
);
return
!
stringcmp
(
&
field_tmp
,
item_result
);
/*
If comparing DATE with DATETIME, append the time-part to the DATE.
So that the strings are equally formatted.
A DATE converted to string is 10 characters, and a DATETIME converted
to string is 19 characters.
*/
field_type
=
field
->
type
();
if
(
field_type
==
MYSQL_TYPE_DATE
&&
item_result
->
length
()
==
19
)
field_tmp
.
append
(
" 00:00:00"
);
else
if
(
field_type
==
MYSQL_TYPE_DATETIME
&&
item_result
->
length
()
==
10
)
item_result
->
append
(
" 00:00:00"
);
return
stringcmp
(
&
field_tmp
,
item_result
);
}
if
(
res_type
==
INT_RESULT
)
return
1
;
// Both whe
re of type int
return
0
;
// Both a
re of type int
if
(
res_type
==
DECIMAL_RESULT
)
{
my_decimal
item_buf
,
*
item_val
,
field_buf
,
*
field_val
;
item_val
=
item
->
val_decimal
(
&
item_buf
);
if
(
item
->
null_value
)
return
1
;
// This must be true
return
0
;
field_val
=
field
->
val_decimal
(
&
field_buf
);
return
!
my_decimal_cmp
(
item_val
,
field_val
);
return
my_decimal_cmp
(
item_val
,
field_val
);
}
double
result
=
item
->
val_real
();
if
(
item
->
null_value
)
return
0
;
double
field_result
=
field
->
val_real
();
if
(
field_result
<
result
)
return
-
1
;
else
if
(
field_result
>
result
)
return
1
;
return
result
==
field
->
val_real
()
;
return
0
;
}
Item_cache
*
Item_cache
::
get_cache
(
const
Item
*
item
)
...
...
sql/item.h
View file @
99413e46
...
...
@@ -397,13 +397,20 @@ public:
from INT_RESULT, may be NULL, or are unsigned.
It will be possible to address this issue once the related partitioning bugs
(BUG#16002, BUG#15447, BUG#13436) are fixed.
The NOT_NULL enums are used in TO_DAYS, since TO_DAYS('2001-00-00') returns
NULL which puts those rows into the NULL partition, but
'2000-12-31' < '2001-00-00' < '2001-01-01'. So special handling is needed
for this (see Bug#20577).
*/
typedef
enum
monotonicity_info
{
NON_MONOTONIC
,
/* none of the below holds */
MONOTONIC_INCREASING
,
/* F() is unary and (x < y) => (F(x) <= F(y)) */
MONOTONIC_STRICT_INCREASING
/* F() is unary and (x < y) => (F(x) < F(y)) */
MONOTONIC_INCREASING_NOT_NULL
,
/* But only for valid/real x and y */
MONOTONIC_STRICT_INCREASING
,
/* F() is unary and (x < y) => (F(x) < F(y)) */
MONOTONIC_STRICT_INCREASING_NOT_NULL
/* But only for valid/real x and y */
}
enum_monotonicity_info
;
/*************************************************************************/
...
...
@@ -576,8 +583,8 @@ public:
left_endp FALSE <=> The interval is "x < const" or "x <= const"
TRUE <=> The interval is "x > const" or "x >= const"
incl_endp IN
TRU
E <=> the comparison is '<' or '>'
FALSE
<=> the comparison is '<=' or '>='
incl_endp IN
FALS
E <=> the comparison is '<' or '>'
TRUE
<=> the comparison is '<=' or '>='
OUT The same but for the "F(x) $CMP$ F(const)" comparison
DESCRIPTION
...
...
@@ -3118,4 +3125,4 @@ void mark_select_range_as_dependent(THD *thd,
extern
Cached_item
*
new_Cached_item
(
THD
*
thd
,
Item
*
item
);
extern
Item_result
item_cmp_type
(
Item_result
a
,
Item_result
b
);
extern
void
resolve_const_item
(
THD
*
thd
,
Item
**
ref
,
Item
*
cmp_item
);
extern
bool
field_is_equal_to_item
(
Field
*
field
,
Item
*
item
);
extern
int
stored_field_cmp_to_item
(
Field
*
field
,
Item
*
item
);
sql/item_timefunc.cc
View file @
99413e46
...
...
@@ -960,9 +960,9 @@ enum_monotonicity_info Item_func_to_days::get_monotonicity_info() const
if
(
args
[
0
]
->
type
()
==
Item
::
FIELD_ITEM
)
{
if
(
args
[
0
]
->
field_type
()
==
MYSQL_TYPE_DATE
)
return
MONOTONIC_STRICT_INCREASING
;
return
MONOTONIC_STRICT_INCREASING
_NOT_NULL
;
if
(
args
[
0
]
->
field_type
()
==
MYSQL_TYPE_DATETIME
)
return
MONOTONIC_INCREASING
;
return
MONOTONIC_INCREASING
_NOT_NULL
;
}
return
NON_MONOTONIC
;
}
...
...
@@ -973,12 +973,27 @@ longlong Item_func_to_days::val_int_endpoint(bool left_endp, bool *incl_endp)
DBUG_ASSERT
(
fixed
==
1
);
MYSQL_TIME
ltime
;
longlong
res
;
if
(
get_arg0_date
(
&
ltime
,
TIME_NO_ZERO_DATE
))
int
dummy
;
/* unused */
if
(
get_arg0_date
(
&
ltime
,
TIME_FUZZY_DATE
))
{
/* got NULL, leave the incl_endp intact */
return
LONGLONG_MIN
;
}
res
=
(
longlong
)
calc_daynr
(
ltime
.
year
,
ltime
.
month
,
ltime
.
day
);
/* Set to NULL if invalid date, but keep the value */
null_value
=
check_date
(
&
ltime
,
(
ltime
.
year
||
ltime
.
month
||
ltime
.
day
),
(
TIME_NO_ZERO_IN_DATE
|
TIME_NO_ZERO_DATE
),
&
dummy
);
if
(
null_value
)
{
/*
Even if the evaluation return NULL, the calc_daynr is useful for pruning
*/
if
(
args
[
0
]
->
field_type
()
!=
MYSQL_TYPE_DATE
)
*
incl_endp
=
TRUE
;
return
res
;
}
if
(
args
[
0
]
->
field_type
()
==
MYSQL_TYPE_DATE
)
{
...
...
@@ -991,15 +1006,19 @@ longlong Item_func_to_days::val_int_endpoint(bool left_endp, bool *incl_endp)
point to day bound ("strictly less" comparison stays intact):
col < '2007-09-15 00:00:00' -> TO_DAYS(col) < TO_DAYS('2007-09-15')
col > '2007-09-15 23:59:59' -> TO_DAYS(col) > TO_DAYS('2007-09-15')
which is different from the general case ("strictly less" changes to
"less or equal"):
col < '2007-09-15 12:34:56' -> TO_DAYS(col) <= TO_DAYS('2007-09-15')
*/
if
(
!
left_endp
&&
!
(
ltime
.
hour
||
ltime
.
minute
||
ltime
.
second
||
ltime
.
second_part
))
;
/* do nothing */
if
((
!
left_endp
&&
!
(
ltime
.
hour
||
ltime
.
minute
||
ltime
.
second
||
ltime
.
second_part
))
||
(
left_endp
&&
ltime
.
hour
==
23
&&
ltime
.
minute
==
59
&&
ltime
.
second
==
59
))
/* do nothing */
;
else
*
incl_endp
=
TRUE
;
return
res
;
...
...
sql/mysql_priv.h
View file @
99413e46
...
...
@@ -2277,7 +2277,8 @@ enum enum_explain_filename_mode
{
EXPLAIN_ALL_VERBOSE
=
0
,
EXPLAIN_PARTITIONS_VERBOSE
,
EXPLAIN_PARTITIONS_AS_COMMENT
EXPLAIN_PARTITIONS_AS_COMMENT
,
EXPLAIN_PARTITIONS_AS_COMMENT_NO_QUOTING
};
uint
explain_filename
(
const
char
*
from
,
char
*
to
,
uint
to_length
,
enum_explain_filename_mode
explain_mode
);
...
...
sql/opt_range.cc
View file @
99413e46
...
...
@@ -5826,6 +5826,7 @@ get_mm_leaf(RANGE_OPT_PARAM *param, COND *conf_func, Field *field,
{
tree
=
new
(
alloc
)
SEL_ARG
(
field
,
0
,
0
);
tree
->
type
=
SEL_ARG
::
IMPOSSIBLE
;
field
->
table
->
in_use
->
variables
.
sql_mode
=
orig_sql_mode
;
goto
end
;
}
else
...
...
@@ -5855,11 +5856,14 @@ get_mm_leaf(RANGE_OPT_PARAM *param, COND *conf_func, Field *field,
but we'll need to convert '>' to '>=' and '<' to '<='. This will
be done together with other types at the end of this function
(grep for
field_is_equal
_to_item)
(grep for
stored_field_cmp
_to_item)
*/
}
else
{
field
->
table
->
in_use
->
variables
.
sql_mode
=
orig_sql_mode
;
goto
end
;
}
}
}
...
...
@@ -5930,7 +5934,7 @@ get_mm_leaf(RANGE_OPT_PARAM *param, COND *conf_func, Field *field,
switch
(
type
)
{
case
Item_func
:
:
LT_FUNC
:
if
(
field_is_equal_to_item
(
field
,
value
)
)
if
(
stored_field_cmp_to_item
(
field
,
value
)
==
0
)
tree
->
max_flag
=
NEAR_MAX
;
/* fall through */
case
Item_func
:
:
LE_FUNC
:
...
...
@@ -5944,11 +5948,16 @@ get_mm_leaf(RANGE_OPT_PARAM *param, COND *conf_func, Field *field,
break
;
case
Item_func
:
:
GT_FUNC
:
/* Don't use open ranges for partial key_segments */
if
(
field_is_equal_to_item
(
field
,
value
)
&&
!
(
key_part
->
flag
&
HA_PART_KEY_SEG
))
if
(
(
!
(
key_part
->
flag
&
HA_PART_KEY_SEG
)
)
&&
(
stored_field_cmp_to_item
(
field
,
value
)
<=
0
))
tree
->
min_flag
=
NEAR_MIN
;
/* fall through */
tree
->
max_flag
=
NO_MAX_RANGE
;
break
;
case
Item_func
:
:
GE_FUNC
:
/* Don't use open ranges for partial key_segments */
if
((
!
(
key_part
->
flag
&
HA_PART_KEY_SEG
))
&&
(
stored_field_cmp_to_item
(
field
,
value
)
<
0
))
tree
->
min_flag
=
NEAR_MIN
;
tree
->
max_flag
=
NO_MAX_RANGE
;
break
;
case
Item_func
:
:
SP_EQUALS_FUNC
:
...
...
@@ -6439,13 +6448,6 @@ key_and(RANGE_OPT_PARAM *param, SEL_ARG *key1, SEL_ARG *key2, uint clone_flag)
return
0
;
// Can't optimize this
}
if
((
key1
->
min_flag
|
key2
->
min_flag
)
&
GEOM_FLAG
)
{
key1
->
free_tree
();
key2
->
free_tree
();
return
0
;
// Can't optimize this
}
key1
->
use_count
--
;
key2
->
use_count
--
;
SEL_ARG
*
e1
=
key1
->
first
(),
*
e2
=
key2
->
first
(),
*
new_tree
=
0
;
...
...
sql/partition_info.h
View file @
99413e46
...
...
@@ -300,6 +300,7 @@ static inline void init_single_partition_iterator(uint32 part_id,
{
part_iter
->
part_nums
.
start
=
part_iter
->
part_nums
.
cur
=
part_id
;
part_iter
->
part_nums
.
end
=
part_id
+
1
;
part_iter
->
ret_null_part
=
part_iter
->
ret_null_part_orig
=
FALSE
;
part_iter
->
get_next
=
get_next_partition_id_range
;
}
...
...
sql/share/errmsg.txt
View file @
99413e46
...
...
@@ -6184,17 +6184,17 @@ ER_FUNC_INEXISTENT_NAME_COLLISION 42000
# When updating these, please update EXPLAIN_FILENAME_MAX_EXTRA_LENGTH in
# mysql_priv.h with the new maximal additional length for explain_filename.
ER_DATABASE_NAME
eng "Database
`%s`
"
swe "Databas
`%s`
"
eng "Database"
swe "Databas"
ER_TABLE_NAME
eng "Table
`%s`
"
swe "Tabell
`%s`
"
eng "Table"
swe "Tabell"
ER_PARTITION_NAME
eng "Partition
`%s`
"
swe "Partition
`%s`
"
eng "Partition"
swe "Partition"
ER_SUBPARTITION_NAME
eng "Subpartition
`%s`
"
swe "Subpartition
`%s`
"
eng "Subpartition"
swe "Subpartition"
ER_TEMPORARY_NAME
eng "Temporary"
swe "Temporr"
...
...
sql/sql_partition.cc
View file @
99413e46
...
...
@@ -2766,8 +2766,24 @@ uint32 get_list_array_idx_for_endpoint(partition_info *part_info,
if
(
part_info
->
part_expr
->
null_value
)
{
DBUG_RETURN
(
0
);
/*
Special handling for MONOTONIC functions that can return NULL for
values that are comparable. I.e.
'2000-00-00' can be compared to '2000-01-01' but TO_DAYS('2000-00-00')
returns NULL which cannot be compared used <, >, <=, >= etc.
Otherwise, just return the the first index (lowest value).
*/
enum_monotonicity_info
monotonic
;
monotonic
=
part_info
->
part_expr
->
get_monotonicity_info
();
if
(
monotonic
!=
MONOTONIC_INCREASING_NOT_NULL
&&
monotonic
!=
MONOTONIC_STRICT_INCREASING_NOT_NULL
)
{
/* F(col) can not return NULL, return index with lowest value */
DBUG_RETURN
(
0
);
}
}
if
(
unsigned_flag
)
part_func_value
-=
0x8000000000000000ULL
;
DBUG_ASSERT
(
part_info
->
no_list_values
);
...
...
@@ -2916,11 +2932,29 @@ uint32 get_partition_id_range_for_endpoint(partition_info *part_info,
if
(
part_info
->
part_expr
->
null_value
)
{
uint32
ret_part_id
=
0
;
if
(
!
left_endpoint
&&
include_endpoint
)
ret_part_id
=
1
;
DBUG_RETURN
(
ret_part_id
);
/*
Special handling for MONOTONIC functions that can return NULL for
values that are comparable. I.e.
'2000-00-00' can be compared to '2000-01-01' but TO_DAYS('2000-00-00')
returns NULL which cannot be compared used <, >, <=, >= etc.
Otherwise, just return the first partition
(may be included if not left endpoint)
*/
enum_monotonicity_info
monotonic
;
monotonic
=
part_info
->
part_expr
->
get_monotonicity_info
();
if
(
monotonic
!=
MONOTONIC_INCREASING_NOT_NULL
&&
monotonic
!=
MONOTONIC_STRICT_INCREASING_NOT_NULL
)
{
/* F(col) can not return NULL, return partition with lowest value */
if
(
!
left_endpoint
&&
include_endpoint
)
DBUG_RETURN
(
1
);
DBUG_RETURN
(
0
);
}
}
if
(
unsigned_flag
)
part_func_value
-=
0x8000000000000000ULL
;
if
(
left_endpoint
&&
!
include_endpoint
)
...
...
@@ -6696,6 +6730,7 @@ int get_part_iter_for_interval_via_mapping(partition_info *part_info,
Field
*
field
=
part_info
->
part_field_array
[
0
];
uint32
max_endpoint_val
;
get_endpoint_func
get_endpoint
;
bool
can_match_multiple_values
;
/* is not '=' */
uint
field_len
=
field
->
pack_length_in_rec
();
part_iter
->
ret_null_part
=
part_iter
->
ret_null_part_orig
=
FALSE
;
...
...
@@ -6733,6 +6768,23 @@ int get_part_iter_for_interval_via_mapping(partition_info *part_info,
}
else
assert
(
0
);
can_match_multiple_values
=
(
flags
||
!
min_value
||
!
max_value
||
memcmp
(
min_value
,
max_value
,
field_len
));
if
(
can_match_multiple_values
&&
(
part_info
->
part_type
==
RANGE_PARTITION
||
part_info
->
has_null_value
))
{
/* Range scan on RANGE or LIST partitioned table */
enum_monotonicity_info
monotonic
;
monotonic
=
part_info
->
part_expr
->
get_monotonicity_info
();
if
(
monotonic
==
MONOTONIC_INCREASING_NOT_NULL
||
monotonic
==
MONOTONIC_STRICT_INCREASING_NOT_NULL
)
{
/* col is NOT NULL, but F(col) can return NULL, add NULL partition */
part_iter
->
ret_null_part
=
part_iter
->
ret_null_part_orig
=
TRUE
;
}
}
/*
Find minimum: Do special handling if the interval has left bound in form
...
...
@@ -6765,6 +6817,14 @@ int get_part_iter_for_interval_via_mapping(partition_info *part_info,
store_key_image_to_rec
(
field
,
min_value
,
field_len
);
bool
include_endp
=
!
test
(
flags
&
NEAR_MIN
);
part_iter
->
part_nums
.
start
=
get_endpoint
(
part_info
,
1
,
include_endp
);
if
(
!
can_match_multiple_values
&&
part_info
->
part_expr
->
null_value
)
{
/* col = x and F(x) = NULL -> only search NULL partition */
part_iter
->
part_nums
.
cur
=
part_iter
->
part_nums
.
start
=
0
;
part_iter
->
part_nums
.
end
=
0
;
part_iter
->
ret_null_part
=
part_iter
->
ret_null_part_orig
=
TRUE
;
return
1
;
}
part_iter
->
part_nums
.
cur
=
part_iter
->
part_nums
.
start
;
if
(
part_iter
->
part_nums
.
start
==
max_endpoint_val
)
return
0
;
/* No partitions */
...
...
@@ -6959,7 +7019,13 @@ uint32 get_next_partition_id_range(PARTITION_ITERATOR* part_iter)
{
if
(
part_iter
->
part_nums
.
cur
>=
part_iter
->
part_nums
.
end
)
{
if
(
part_iter
->
ret_null_part
)
{
part_iter
->
ret_null_part
=
FALSE
;
return
0
;
/* NULL always in first range partition */
}
part_iter
->
part_nums
.
cur
=
part_iter
->
part_nums
.
start
;
part_iter
->
ret_null_part
=
part_iter
->
ret_null_part_orig
;
return
NOT_A_PARTITION_ID
;
}
else
...
...
@@ -6987,7 +7053,7 @@ uint32 get_next_partition_id_range(PARTITION_ITERATOR* part_iter)
uint32
get_next_partition_id_list
(
PARTITION_ITERATOR
*
part_iter
)
{
if
(
part_iter
->
part_nums
.
cur
=
=
part_iter
->
part_nums
.
end
)
if
(
part_iter
->
part_nums
.
cur
>
=
part_iter
->
part_nums
.
end
)
{
if
(
part_iter
->
ret_null_part
)
{
...
...
sql/sql_table.cc
View file @
99413e46
...
...
@@ -72,7 +72,7 @@ static void wait_for_kill_signal(THD *thd)
@brief Helper function for explain_filename
*/
static
char
*
add_identifier
(
char
*
to_p
,
const
char
*
end_p
,
const
char
*
name
,
uint
name_len
,
int
errcode
)
const
char
*
name
,
uint
name_len
,
bool
add_quotes
)
{
uint
res
;
uint
errors
;
...
...
@@ -92,18 +92,44 @@ static char* add_identifier(char *to_p, const char * end_p,
res
=
strconvert
(
&
my_charset_filename
,
conv_name
,
system_charset_info
,
conv_string
,
FN_REFLEN
,
&
errors
);
if
(
!
res
||
errors
)
{
DBUG_PRINT
(
"error"
,
(
"strconvert of '%s' failed with %u (errors: %u)"
,
conv_name
,
res
,
errors
));
conv_name
=
name
;
}
else
{
DBUG_PRINT
(
"info"
,
(
"conv '%s' -> '%s'"
,
conv_name
,
conv_string
));
conv_name
=
conv_string
;
}
if
(
errcode
)
to_p
+=
my_snprintf
(
to_p
,
end_p
-
to_p
,
ER
(
errcode
),
conv_name
);
if
(
add_quotes
&&
(
end_p
-
to_p
>
2
))
{
*
(
to_p
++
)
=
'`'
;
while
(
*
conv_name
&&
(
end_p
-
to_p
-
1
)
>
0
)
{
uint
length
=
my_mbcharlen
(
system_charset_info
,
*
conv_name
);
if
(
!
length
)
length
=
1
;
if
(
length
==
1
&&
*
conv_name
==
'`'
)
{
if
((
end_p
-
to_p
)
<
3
)
break
;
*
(
to_p
++
)
=
'`'
;
*
(
to_p
++
)
=
*
(
conv_name
++
);
}
else
if
(
length
<
(
end_p
-
to_p
))
{
to_p
=
strnmov
(
to_p
,
conv_name
,
length
);
conv_name
+=
length
;
}
else
break
;
/* string already filled */
}
to_p
=
strnmov
(
to_p
,
"`"
,
end_p
-
to_p
);
}
else
to_p
+=
my_snprintf
(
to_p
,
end_p
-
to_p
,
"`%s`"
,
conv_name
);
return
to_p
;
to_p
=
strnmov
(
to_p
,
conv_name
,
end_p
-
to_p
);
DBUG_RETURN
(
to_p
)
;
}
...
...
@@ -135,6 +161,8 @@ static char* add_identifier(char *to_p, const char * end_p,
[,[ Temporary| Renamed] Partition `p`
[, Subpartition `sp`]] *|
(| is really a /, and it is all in one line)
EXPLAIN_PARTITIONS_AS_COMMENT_NO_QUOTING ->
same as above but no quotes are added.
@retval Length of returned string
*/
...
...
@@ -245,28 +273,39 @@ uint explain_filename(const char *from,
part_name_len
-=
5
;
}
}
else
table_name_len
=
strlen
(
table_name
);
if
(
db_name
)
{
if
(
explain_mode
==
EXPLAIN_ALL_VERBOSE
)
{
to_p
=
add_identifier
(
to_p
,
end_p
,
db_name
,
db_name_len
,
ER_DATABASE_NAME
);
to_p
=
strnmov
(
to_p
,
ER
(
ER_DATABASE_NAME
),
end_p
-
to_p
);
*
(
to_p
++
)
=
' '
;
to_p
=
add_identifier
(
to_p
,
end_p
,
db_name
,
db_name_len
,
1
);
to_p
=
strnmov
(
to_p
,
", "
,
end_p
-
to_p
);
}
else
{
to_p
=
add_identifier
(
to_p
,
end_p
,
db_name
,
db_name_len
,
0
);
to_p
=
add_identifier
(
to_p
,
end_p
,
db_name
,
db_name_len
,
(
explain_mode
!=
EXPLAIN_PARTITIONS_AS_COMMENT_NO_QUOTING
));
to_p
=
strnmov
(
to_p
,
"."
,
end_p
-
to_p
);
}
}
if
(
explain_mode
==
EXPLAIN_ALL_VERBOSE
)
to_p
=
add_identifier
(
to_p
,
end_p
,
table_name
,
table_name_len
,
ER_TABLE_NAME
);
{
to_p
=
strnmov
(
to_p
,
ER
(
ER_TABLE_NAME
),
end_p
-
to_p
);
*
(
to_p
++
)
=
' '
;
to_p
=
add_identifier
(
to_p
,
end_p
,
table_name
,
table_name_len
,
1
);
}
else
to_p
=
add_identifier
(
to_p
,
end_p
,
table_name
,
table_name_len
,
0
);
to_p
=
add_identifier
(
to_p
,
end_p
,
table_name
,
table_name_len
,
(
explain_mode
!=
EXPLAIN_PARTITIONS_AS_COMMENT_NO_QUOTING
));
if
(
part_name
)
{
if
(
explain_mode
==
EXPLAIN_PARTITIONS_AS_COMMENT
)
if
(
explain_mode
==
EXPLAIN_PARTITIONS_AS_COMMENT
||
explain_mode
==
EXPLAIN_PARTITIONS_AS_COMMENT_NO_QUOTING
)
to_p
=
strnmov
(
to_p
,
" /* "
,
end_p
-
to_p
);
else
if
(
explain_mode
==
EXPLAIN_PARTITIONS_VERBOSE
)
to_p
=
strnmov
(
to_p
,
" "
,
end_p
-
to_p
);
...
...
@@ -280,15 +319,22 @@ uint explain_filename(const char *from,
to_p
=
strnmov
(
to_p
,
ER
(
ER_RENAMED_NAME
),
end_p
-
to_p
);
to_p
=
strnmov
(
to_p
,
" "
,
end_p
-
to_p
);
}
to_p
=
strnmov
(
to_p
,
ER
(
ER_PARTITION_NAME
),
end_p
-
to_p
);
*
(
to_p
++
)
=
' '
;
to_p
=
add_identifier
(
to_p
,
end_p
,
part_name
,
part_name_len
,
ER_PARTITION_NAME
);
(
explain_mode
!=
EXPLAIN_PARTITIONS_AS_COMMENT_NO_QUOTING
));
if
(
subpart_name
)
{
to_p
=
strnmov
(
to_p
,
", "
,
end_p
-
to_p
);
to_p
=
strnmov
(
to_p
,
ER
(
ER_SUBPARTITION_NAME
),
end_p
-
to_p
);
*
(
to_p
++
)
=
' '
;
to_p
=
add_identifier
(
to_p
,
end_p
,
subpart_name
,
subpart_name_len
,
ER_SUBPARTITION_NAME
);
(
explain_mode
!=
EXPLAIN_PARTITIONS_AS_COMMENT_NO_QUOTING
));
}
if
(
explain_mode
==
EXPLAIN_PARTITIONS_AS_COMMENT
)
if
(
explain_mode
==
EXPLAIN_PARTITIONS_AS_COMMENT
||
explain_mode
==
EXPLAIN_PARTITIONS_AS_COMMENT_NO_QUOTING
)
to_p
=
strnmov
(
to_p
,
" */"
,
end_p
-
to_p
);
}
DBUG_PRINT
(
"exit"
,
(
"to '%s'"
,
to
));
...
...
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