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
23740441
Commit
23740441
authored
Sep 29, 2018
by
Alexander Barkov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
MDEV-17325 NULL-ability problems with LEAST() in combination with NO_ZERO_DATE and NO_ZERO_IN_DATE
parent
ad8e02ac
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
284 additions
and
0 deletions
+284
-0
mysql-test/main/func_hybrid_type.result
mysql-test/main/func_hybrid_type.result
+120
-0
mysql-test/main/func_hybrid_type.test
mysql-test/main/func_hybrid_type.test
+71
-0
sql/sql_type.cc
sql/sql_type.cc
+91
-0
sql/sql_type.h
sql/sql_type.h
+2
-0
No files found.
mysql-test/main/func_hybrid_type.result
View file @
23740441
...
...
@@ -3755,3 +3755,123 @@ DROP TABLE t1;
#
# End of 10.3 tests
#
#
# Start of 10.4 tests
#
#
# MDEV-17325 NULL-ability problems with LEAST() in combination with NO_ZERO_DATE and NO_ZERO_IN_DATE
#
SET sql_mode='NO_ZERO_DATE,NO_ZERO_IN_DATE';
SELECT
LEAST('0000-00-00',DATE'2001-01-01') AS s1,
LEAST('0001-00-01',DATE'2001-01-01') AS s2,
LEAST('0000-00-00',TIMESTAMP'2001-01-01 00:00:00') AS s3,
LEAST('0001-00-01',TIMESTAMP'2001-01-01 00:00:00') AS s4,
LEAST(0,DATE'2001-01-01') AS i1,
LEAST(20010001,DATE'2001-01-01') AS i2,
LEAST(0,TIMESTAMP'2001-01-01 00:00:00') AS i3,
LEAST(20010001,TIMESTAMP'2001-01-01 00:00:00') AS i4;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def s1 10 10 0 Y 128 0 63
def s2 10 10 0 Y 128 0 63
def s3 12 26 0 Y 128 6 63
def s4 12 26 0 Y 128 6 63
def i1 10 10 0 Y 128 0 63
def i2 10 10 0 Y 128 0 63
def i3 12 19 0 Y 128 0 63
def i4 12 19 0 Y 128 0 63
s1 s2 s3 s4 i1 i2 i3 i4
NULL NULL NULL NULL NULL NULL NULL NULL
Warnings:
Warning 1292 Incorrect datetime value: '0000-00-00'
Warning 1292 Incorrect datetime value: '0001-00-01'
Warning 1292 Incorrect datetime value: '0000-00-00 00:00:00'
Warning 1292 Incorrect datetime value: '0001-00-01 00:00:00'
Warning 1292 Incorrect datetime value: '0000-00-00'
Warning 1292 Incorrect datetime value: '2001-00-01'
Warning 1292 Incorrect datetime value: '0000-00-00 00:00:00'
Warning 1292 Incorrect datetime value: '2001-00-01 00:00:00'
SET sql_mode='NO_ZERO_DATE,NO_ZERO_IN_DATE';
CREATE TABLE t1 AS SELECT
LEAST('0000-00-00',DATE'2001-01-01') AS s1,
LEAST('0001-00-01',DATE'2001-01-01') AS s2,
LEAST('0000-00-00',TIMESTAMP'2001-01-01 00:00:00') AS s3,
LEAST('0001-00-01',TIMESTAMP'2001-01-01 00:00:00') AS s4,
LEAST(0,DATE'2001-01-01') AS i1,
LEAST(20010001,DATE'2001-01-01') AS i2,
LEAST(0,TIMESTAMP'2001-01-01 00:00:00') AS i3,
LEAST(20010001,TIMESTAMP'2001-01-01 00:00:00') AS i4;
Warnings:
Warning 1292 Incorrect datetime value: '0000-00-00'
Warning 1292 Incorrect datetime value: '0001-00-01'
Warning 1292 Incorrect datetime value: '0000-00-00 00:00:00'
Warning 1292 Incorrect datetime value: '0001-00-01 00:00:00'
Warning 1292 Incorrect datetime value: '0000-00-00'
Warning 1292 Incorrect datetime value: '2001-00-01'
Warning 1292 Incorrect datetime value: '0000-00-00 00:00:00'
Warning 1292 Incorrect datetime value: '2001-00-01 00:00:00'
SELECT * FROM t1;
s1 s2 s3 s4 i1 i2 i3 i4
NULL NULL NULL NULL NULL NULL NULL NULL
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`s1` date DEFAULT NULL,
`s2` date DEFAULT NULL,
`s3` datetime(6) DEFAULT NULL,
`s4` datetime(6) DEFAULT NULL,
`i1` date DEFAULT NULL,
`i2` date DEFAULT NULL,
`i3` datetime DEFAULT NULL,
`i4` datetime DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
SET timestamp=UNIX_TIMESTAMP('2001-01-01 10:20:30');
CREATE TABLE t1 AS SELECT LEAST(CURRENT_DATE,CURRENT_TIME) AS c1;
SELECT * FROM t1;
c1
2001-01-01 00:00:00
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` datetime NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
SET old_mode=ZERO_DATE_TIME_CAST;
CREATE TABLE t1 AS SELECT LEAST(CURRENT_DATE,CURRENT_TIME) AS c1;
Warnings:
Warning 1292 Incorrect datetime value: '0000-00-00 10:20:30'
SELECT * FROM t1;
c1
NULL
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` datetime DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
SET old_mode=DEFAULT;
SET timestamp=DEFAULT;
SET sql_mode=DEFAULT;
SET sql_mode='';
SELECT LEAST(999,TIME'10:20:30') AS c1;
c1
NULL
Warnings:
Warning 1292 Incorrect time value: '999'
CREATE TABLE t1 AS SELECT LEAST(999,TIME'10:20:30') AS c1;
Warnings:
Warning 1292 Incorrect time value: '999'
SELECT * FROM t1;
c1
NULL
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` time DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
SET sql_mode=DEFAULT;
#
# End of 10.4 tests
#
mysql-test/main/func_hybrid_type.test
View file @
23740441
...
...
@@ -615,3 +615,74 @@ DROP TABLE t1;
--
echo
# End of 10.3 tests
--
echo
#
--
echo
#
--
echo
# Start of 10.4 tests
--
echo
#
--
echo
#
--
echo
# MDEV-17325 NULL-ability problems with LEAST() in combination with NO_ZERO_DATE and NO_ZERO_IN_DATE
--
echo
#
SET
sql_mode
=
'NO_ZERO_DATE,NO_ZERO_IN_DATE'
;
--
disable_ps_protocol
--
enable_metadata
SELECT
LEAST
(
'0000-00-00'
,
DATE
'2001-01-01'
)
AS
s1
,
LEAST
(
'0001-00-01'
,
DATE
'2001-01-01'
)
AS
s2
,
LEAST
(
'0000-00-00'
,
TIMESTAMP
'2001-01-01 00:00:00'
)
AS
s3
,
LEAST
(
'0001-00-01'
,
TIMESTAMP
'2001-01-01 00:00:00'
)
AS
s4
,
LEAST
(
0
,
DATE
'2001-01-01'
)
AS
i1
,
LEAST
(
20010001
,
DATE
'2001-01-01'
)
AS
i2
,
LEAST
(
0
,
TIMESTAMP
'2001-01-01 00:00:00'
)
AS
i3
,
LEAST
(
20010001
,
TIMESTAMP
'2001-01-01 00:00:00'
)
AS
i4
;
--
disable_metadata
--
enable_ps_protocol
SET
sql_mode
=
'NO_ZERO_DATE,NO_ZERO_IN_DATE'
;
CREATE
TABLE
t1
AS
SELECT
LEAST
(
'0000-00-00'
,
DATE
'2001-01-01'
)
AS
s1
,
LEAST
(
'0001-00-01'
,
DATE
'2001-01-01'
)
AS
s2
,
LEAST
(
'0000-00-00'
,
TIMESTAMP
'2001-01-01 00:00:00'
)
AS
s3
,
LEAST
(
'0001-00-01'
,
TIMESTAMP
'2001-01-01 00:00:00'
)
AS
s4
,
LEAST
(
0
,
DATE
'2001-01-01'
)
AS
i1
,
LEAST
(
20010001
,
DATE
'2001-01-01'
)
AS
i2
,
LEAST
(
0
,
TIMESTAMP
'2001-01-01 00:00:00'
)
AS
i3
,
LEAST
(
20010001
,
TIMESTAMP
'2001-01-01 00:00:00'
)
AS
i4
;
SELECT
*
FROM
t1
;
SHOW
CREATE
TABLE
t1
;
DROP
TABLE
t1
;
SET
timestamp
=
UNIX_TIMESTAMP
(
'2001-01-01 10:20:30'
);
# A TIME always converts to a non-NULL DATETIME with the new CAST style
# Expect a NOT NULL column
CREATE
TABLE
t1
AS
SELECT
LEAST
(
CURRENT_DATE
,
CURRENT_TIME
)
AS
c1
;
SELECT
*
FROM
t1
;
SHOW
CREATE
TABLE
t1
;
DROP
TABLE
t1
;
# A TIME can convert to a NULL DATETIME with old CAST style
# Expect a NULL-able column
SET
old_mode
=
ZERO_DATE_TIME_CAST
;
CREATE
TABLE
t1
AS
SELECT
LEAST
(
CURRENT_DATE
,
CURRENT_TIME
)
AS
c1
;
SELECT
*
FROM
t1
;
SHOW
CREATE
TABLE
t1
;
DROP
TABLE
t1
;
SET
old_mode
=
DEFAULT
;
SET
timestamp
=
DEFAULT
;
SET
sql_mode
=
DEFAULT
;
SET
sql_mode
=
''
;
SELECT
LEAST
(
999
,
TIME
'10:20:30'
)
AS
c1
;
CREATE
TABLE
t1
AS
SELECT
LEAST
(
999
,
TIME
'10:20:30'
)
AS
c1
;
SELECT
*
FROM
t1
;
SHOW
CREATE
TABLE
t1
;
DROP
TABLE
t1
;
SET
sql_mode
=
DEFAULT
;
--
echo
#
--
echo
# End of 10.4 tests
--
echo
#
sql/sql_type.cc
View file @
23740441
...
...
@@ -3480,6 +3480,97 @@ bool Type_handler::
}
bool
Type_handler_temporal_result
::
Item_func_min_max_fix_attributes
(
THD
*
thd
,
Item_func_min_max
*
func
,
Item
**
items
,
uint
nitems
)
const
{
bool
rc
=
Type_handler
::
Item_func_min_max_fix_attributes
(
thd
,
func
,
items
,
nitems
);
if
(
rc
||
func
->
maybe_null
)
return
rc
;
/*
LEAST/GREATES(non-temporal, temporal) can return NULL.
CAST functions Item_{time|datetime|date}_typecast always set maybe_full
to true. Here we try to detect nullability more thoroughly.
Perhaps CAST functions should also reuse this idea eventually.
*/
const
Type_handler
*
hf
=
func
->
type_handler
();
for
(
uint
i
=
0
;
i
<
nitems
;
i
++
)
{
/*
If items[i] does not need conversion to the current temporal data
type, then we trust items[i]->maybe_null, which was already ORred
to func->maybe_null in the argument loop in fix_fields().
If items[i] requires conversion to the current temporal data type,
then conversion can fail and return NULL even for NOT NULL items.
*/
const
Type_handler
*
ha
=
items
[
i
]
->
type_handler
();
if
(
hf
==
ha
)
continue
;
// No conversion.
if
(
ha
->
cmp_type
()
!=
TIME_RESULT
)
{
func
->
maybe_null
=
true
;
// Conversion from non-temporal is not safe
break
;
}
timestamp_type
tf
=
hf
->
mysql_timestamp_type
();
timestamp_type
ta
=
ha
->
mysql_timestamp_type
();
if
(
tf
==
ta
||
(
tf
==
MYSQL_TIMESTAMP_DATETIME
&&
ta
==
MYSQL_TIMESTAMP_DATE
))
{
/*
If handlers have the same mysql_timestamp_type(),
then conversion is NULL safe. Conversion from DATE to DATETIME
is also safe. This branch includes data type pairs:
Function return type Argument type Comment
-------------------- ------------- -------------
TIMESTAMP TIMESTAMP no conversion
TIMESTAMP DATETIME not possible
TIMESTAMP DATE not possible
DATETIME DATETIME no conversion
DATETIME TIMESTAMP safe conversion
DATETIME DATE safe conversion
DATE DATE no conversion
TIME TIME no conversion
Note, a function cannot return TIMESTAMP if it has non-TIMESTAMP
arguments (it would return DATETIME in such case).
*/
DBUG_ASSERT
(
hf
->
field_type
()
!=
MYSQL_TYPE_TIMESTAMP
||
tf
==
ta
);
continue
;
}
/*
Here we have the following data type pairs that did not match
the condition above:
Function return type Argument type Comment
-------------------- ------------- -------
TIMESTAMP TIME Not possible
DATETIME TIME depends on OLD_MODE_ZERO_DATE_TIME_CAST
DATE TIMESTAMP Not possible
DATE DATETIME Not possible
DATE TIME Not possible
TIME TIMESTAMP Not possible
TIME DATETIME Not possible
TIME DATE Not possible
Most pairs are not possible, because the function data type
would be DATETIME (according to LEAST/GREATEST aggregation rules).
Conversion to DATETIME from TIME is not safe when
OLD_MODE_ZERO_DATE_TIME_CAST is set:
- negative TIME values cannot be converted to not-NULL DATETIME values
- TIME values can produce DATETIME values that do not pass
NO_ZERO_DATE and NO_ZERO_IN_DATE tests.
*/
DBUG_ASSERT
(
hf
->
field_type
()
==
MYSQL_TYPE_DATETIME
);
if
(
!
(
thd
->
variables
.
old_behavior
&
OLD_MODE_ZERO_DATE_TIME_CAST
))
continue
;
func
->
maybe_null
=
true
;
break
;
}
return
rc
;
}
bool
Type_handler_real_result
::
Item_func_min_max_fix_attributes
(
THD
*
thd
,
Item_func_min_max
*
func
,
Item
**
items
,
uint
nitems
)
const
...
...
sql/sql_type.h
View file @
23740441
...
...
@@ -3283,6 +3283,8 @@ class Type_handler_temporal_result: public Type_handler
Item
*
source_expr
,
Item
*
source_const
)
const
;
bool
subquery_type_allows_materialization
(
const
Item
*
inner
,
const
Item
*
outer
)
const
;
bool
Item_func_min_max_fix_attributes
(
THD
*
thd
,
Item_func_min_max
*
func
,
Item
**
items
,
uint
nitems
)
const
;
bool
Item_sum_hybrid_fix_length_and_dec
(
Item_sum_hybrid
*
func
)
const
;
bool
Item_sum_sum_fix_length_and_dec
(
Item_sum_sum
*
)
const
;
bool
Item_sum_avg_fix_length_and_dec
(
Item_sum_avg
*
)
const
;
...
...
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