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
ffdae1a9
Commit
ffdae1a9
authored
Aug 09, 2018
by
Alexander Barkov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
MDEV-16926 CAST(COALESCE(year_field)) returns wrong value
parent
3f01c4fb
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
174 additions
and
33 deletions
+174
-33
mysql-test/main/type_year.result
mysql-test/main/type_year.result
+29
-0
mysql-test/main/type_year.test
mysql-test/main/type_year.test
+17
-0
sql/field.h
sql/field.h
+4
-1
sql/item.cc
sql/item.cc
+0
-20
sql/item.h
sql/item.h
+6
-3
sql/item_timefunc.cc
sql/item_timefunc.cc
+4
-7
sql/sql_type.cc
sql/sql_type.cc
+55
-2
sql/sql_type.h
sql/sql_type.h
+59
-0
No files found.
mysql-test/main/type_year.result
View file @
ffdae1a9
...
...
@@ -525,5 +525,34 @@ Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = 93
DROP TABLE t1;
#
# MDEV-16926 CAST(COALESCE(year_field)) returns wrong value
#
CREATE OR REPLACE TABLE t1 (a YEAR);
INSERT INTO t1 VALUES (1970),(1978),(2000),(2069);
SELECT a, CAST(a AS DATE), CAST(COALESCE(a) AS DATE) FROM t1;
a CAST(a AS DATE) CAST(COALESCE(a) AS DATE)
1970 1970-00-00 1970-00-00
1978 1978-00-00 1978-00-00
2000 2000-00-00 2000-00-00
2069 2069-00-00 2069-00-00
SELECT MIN(a), MAX(a) FROM t1;
MIN(a) MAX(a)
1970 2069
DROP TABLE t1;
CREATE OR REPLACE TABLE t1 (a YEAR(2));
Warnings:
Note 1287 'YEAR(2)' is deprecated and will be removed in a future release. Please use YEAR(4) instead
INSERT INTO t1 VALUES (1970),(1978),(2000),(2069);
SELECT a, CAST(a AS DATE), CAST(COALESCE(a) AS DATE) FROM t1;
a CAST(a AS DATE) CAST(COALESCE(a) AS DATE)
70 1970-00-00 1970-00-00
78 1978-00-00 1978-00-00
00 2000-00-00 2000-00-00
69 2069-00-00 2069-00-00
SELECT MIN(a), MAX(a) FROM t1;
MIN(a) MAX(a)
70 69
DROP TABLE t1;
#
# End of 10.4 tests
#
mysql-test/main/type_year.test
View file @
ffdae1a9
...
...
@@ -278,6 +278,23 @@ SELECT * FROM t1 WHERE a=1993 and a=93;
EXPLAIN
EXTENDED
SELECT
*
FROM
t1
WHERE
a
=
1993
and
a
=
93
;
DROP
TABLE
t1
;
--
echo
#
--
echo
# MDEV-16926 CAST(COALESCE(year_field)) returns wrong value
--
echo
#
CREATE
OR
REPLACE
TABLE
t1
(
a
YEAR
);
INSERT
INTO
t1
VALUES
(
1970
),(
1978
),(
2000
),(
2069
);
SELECT
a
,
CAST
(
a
AS
DATE
),
CAST
(
COALESCE
(
a
)
AS
DATE
)
FROM
t1
;
SELECT
MIN
(
a
),
MAX
(
a
)
FROM
t1
;
DROP
TABLE
t1
;
CREATE
OR
REPLACE
TABLE
t1
(
a
YEAR
(
2
));
INSERT
INTO
t1
VALUES
(
1970
),(
1978
),(
2000
),(
2069
);
SELECT
a
,
CAST
(
a
AS
DATE
),
CAST
(
COALESCE
(
a
)
AS
DATE
)
FROM
t1
;
SELECT
MIN
(
a
),
MAX
(
a
)
FROM
t1
;
DROP
TABLE
t1
;
--
echo
#
--
echo
# End of 10.4 tests
--
echo
#
sql/field.h
View file @
ffdae1a9
...
...
@@ -2881,7 +2881,10 @@ class Field_year :public Field_tiny {
:
Field_tiny
(
ptr_arg
,
len_arg
,
null_ptr_arg
,
null_bit_arg
,
unireg_check_arg
,
field_name_arg
,
1
,
1
)
{}
const
Type_handler
*
type_handler
()
const
{
return
&
type_handler_year
;
}
const
Type_handler
*
type_handler
()
const
{
return
field_length
==
2
?
&
type_handler_year2
:
&
type_handler_year
;
}
Copy_func
*
get_copy_func
(
const
Field
*
from
)
const
{
if
(
eq_def
(
from
))
...
...
sql/item.cc
View file @
ffdae1a9
...
...
@@ -1328,26 +1328,6 @@ bool Item::get_date_from_int(MYSQL_TIME *ltime, ulonglong fuzzydate)
}
bool
Item
::
get_date_from_year
(
MYSQL_TIME
*
ltime
,
ulonglong
fuzzydate
)
{
longlong
value
=
val_int
();
DBUG_ASSERT
(
unsigned_flag
||
value
>=
0
);
if
(
max_length
==
2
)
{
if
(
value
<
70
)
value
+=
2000
;
else
if
(
value
<=
1900
)
value
+=
1900
;
}
value
*=
10000
;
/* make it YYYYMMHH */
if
(
null_value
||
int_to_datetime_with_warn
(
false
,
value
,
ltime
,
fuzzydate
,
field_name_or_null
()))
return
null_value
|=
make_zero_date
(
ltime
,
fuzzydate
);
return
null_value
=
false
;
}
bool
Item
::
get_date_from_real
(
MYSQL_TIME
*
ltime
,
ulonglong
fuzzydate
)
{
double
value
=
val_real
();
...
...
sql/item.h
View file @
ffdae1a9
...
...
@@ -1607,7 +1607,6 @@ class Item: public Value_source,
Item
**
ref
,
uint
flags
);
virtual
bool
get_date
(
MYSQL_TIME
*
ltime
,
ulonglong
fuzzydate
)
=
0
;
bool
get_date_from_int
(
MYSQL_TIME
*
ltime
,
ulonglong
fuzzydate
);
bool
get_date_from_year
(
MYSQL_TIME
*
ltime
,
ulonglong
fuzzydate
);
bool
get_date_from_real
(
MYSQL_TIME
*
ltime
,
ulonglong
fuzzydate
);
bool
get_date_from_string
(
MYSQL_TIME
*
ltime
,
ulonglong
fuzzydate
);
bool
get_time
(
MYSQL_TIME
*
ltime
)
...
...
@@ -6476,9 +6475,13 @@ class Item_cache_int: public Item_cache
class
Item_cache_year
:
public
Item_cache_int
{
public:
Item_cache_year
(
THD
*
thd
)
:
Item_cache_int
(
thd
,
&
type_handler_year
)
{
}
Item_cache_year
(
THD
*
thd
,
const
Type_handler
*
handler
)
:
Item_cache_int
(
thd
,
handler
)
{
}
bool
get_date
(
MYSQL_TIME
*
ltime
,
ulonglong
fuzzydate
)
{
return
get_date_from_year
(
ltime
,
fuzzydate
);
}
{
return
null_value
=
VYear
(
this
).
to_mysql_time_with_warn
(
ltime
,
fuzzydate
,
NULL
);
}
};
...
...
sql/item_timefunc.cc
View file @
ffdae1a9
...
...
@@ -2528,17 +2528,14 @@ bool Item_datetime_typecast::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date)
bool
Item_func_makedate
::
get_date
(
MYSQL_TIME
*
ltime
,
ulonglong
fuzzy_date
)
{
DBUG_ASSERT
(
fixed
==
1
);
long
daynr
=
(
long
)
args
[
1
]
->
val_int
();
long
year
=
(
long
)
args
[
0
]
->
val_int
();
long
days
;
long
year
,
days
,
daynr
=
(
long
)
args
[
1
]
->
val_int
();
if
(
args
[
0
]
->
null_value
||
args
[
1
]
->
null_value
||
year
<
0
||
year
>
9999
||
daynr
<=
0
)
VYear
vyear
(
args
[
0
]);
if
(
vyear
.
is_null
()
||
args
[
1
]
->
null_value
||
vyear
.
truncated
()
||
daynr
<=
0
)
goto
err
;
if
(
year
<
100
)
if
(
(
year
=
(
long
)
vyear
.
year
())
<
100
)
year
=
year_2000_handling
(
year
);
days
=
calc_daynr
(
year
,
1
,
1
)
+
daynr
-
1
;
if
(
get_date_from_daynr
(
days
,
&
ltime
->
year
,
&
ltime
->
month
,
&
ltime
->
day
))
goto
err
;
...
...
sql/sql_type.cc
View file @
ffdae1a9
...
...
@@ -42,6 +42,7 @@ Type_handler_olddecimal type_handler_olddecimal;
Type_handler_newdecimal
type_handler_newdecimal
;
Type_handler_year
type_handler_year
;
Type_handler_year
type_handler_year2
;
Type_handler_time
type_handler_time
;
Type_handler_date
type_handler_date
;
Type_handler_timestamp
type_handler_timestamp
;
...
...
@@ -319,6 +320,45 @@ VSec6::VSec6(Item *item, const char *type_str, ulonglong limit)
}
Year
::
Year
(
longlong
value
,
bool
unsigned_flag
,
uint
length
)
{
if
((
m_truncated
=
(
value
<
0
&&
!
unsigned_flag
)))
m_year
=
0
;
else
if
(
value
>
9999
)
{
m_truncated
=
true
;
m_year
=
9999
;
}
else
if
(
length
==
2
)
{
m_year
=
value
<
70
?
(
uint
)
value
+
2000
:
value
<=
1900
?
(
uint
)
value
+
1900
:
(
uint
)
value
;
}
else
m_year
=
(
uint
)
value
;
DBUG_ASSERT
(
m_year
<=
9999
);
}
uint
Year
::
year_precision
(
const
Item
*
item
)
const
{
return
item
->
type_handler
()
==
&
type_handler_year2
?
2
:
4
;
}
VYear
::
VYear
(
Item
*
item
)
:
Year_null
(
Year
(
item
->
val_int
(),
item
->
unsigned_flag
,
year_precision
(
item
)),
item
->
null_value
)
{
}
VYear_op
::
VYear_op
(
Item_func_hybrid_field_type
*
item
)
:
Year_null
(
Year
(
item
->
int_op
(),
item
->
unsigned_flag
,
year_precision
(
item
)),
item
->
null_value
)
{
}
void
Time
::
make_from_item
(
Item
*
item
,
const
Options
opt
)
{
if
(
item
->
get_date
(
this
,
opt
.
get_date_flags
()))
...
...
@@ -3061,7 +3101,7 @@ Type_handler_int_result::Item_get_cache(THD *thd, const Item *item) const
Item_cache
*
Type_handler_year
::
Item_get_cache
(
THD
*
thd
,
const
Item
*
item
)
const
{
return
new
(
thd
->
mem_root
)
Item_cache_year
(
thd
);
return
new
(
thd
->
mem_root
)
Item_cache_year
(
thd
,
item
->
type_handler
()
);
}
Item_cache
*
...
...
@@ -3611,7 +3651,9 @@ bool Type_handler_int_result::Item_get_date(Item *item, MYSQL_TIME *ltime,
bool
Type_handler_year
::
Item_get_date
(
Item
*
item
,
MYSQL_TIME
*
ltime
,
ulonglong
fuzzydate
)
const
{
return
item
->
get_date_from_year
(
ltime
,
fuzzydate
);
return
item
->
null_value
=
VYear
(
item
).
to_mysql_time_with_warn
(
ltime
,
fuzzydate
,
item
->
field_name_or_null
());
}
...
...
@@ -3786,6 +3828,17 @@ Type_handler_decimal_result::Item_func_hybrid_field_type_get_date(
}
bool
Type_handler_year
::
Item_func_hybrid_field_type_get_date
(
Item_func_hybrid_field_type
*
item
,
MYSQL_TIME
*
ltime
,
ulonglong
fuzzydate
)
const
{
return
item
->
null_value
=
VYear_op
(
item
).
to_mysql_time_with_warn
(
ltime
,
fuzzydate
,
NULL
);
}
/***************************************************************************/
...
...
sql/sql_type.h
View file @
ffdae1a9
...
...
@@ -389,6 +389,61 @@ class Sec6_add
};
class
Year
{
protected:
uint
m_year
;
bool
m_truncated
;
bool
to_mysql_time_with_warn
(
MYSQL_TIME
*
to
,
ulonglong
fuzzydate
,
const
char
*
field_name
)
const
{
longlong
value
=
m_year
*
10000
;
// Make it YYYYMMDD
const
ErrConvInteger
str
(
value
,
true
);
Sec6
sec
(
false
,
value
,
0
);
return
sec
.
convert_to_mysql_time
(
to
,
fuzzydate
,
&
str
,
field_name
);
}
uint
year_precision
(
const
Item
*
item
)
const
;
public:
Year
()
:
m_year
(
0
),
m_truncated
(
false
)
{
}
Year
(
longlong
value
,
bool
unsigned_flag
,
uint
length
);
uint
year
()
const
{
return
m_year
;
}
bool
truncated
()
const
{
return
m_truncated
;
}
};
class
Year_null
:
public
Year
{
protected:
bool
m_is_null
;
public:
Year_null
(
const
Year
&
other
,
bool
is_null
)
:
Year
(
is_null
?
Year
()
:
other
),
m_is_null
(
is_null
)
{
}
bool
is_null
()
const
{
return
m_is_null
;
}
bool
to_mysql_time_with_warn
(
MYSQL_TIME
*
to
,
ulonglong
fuzzydate
,
const
char
*
field_name
)
const
{
return
m_is_null
?
true
:
Year
::
to_mysql_time_with_warn
(
to
,
fuzzydate
,
field_name
);
}
};
class
VYear
:
public
Year_null
{
public:
VYear
(
Item
*
item
);
};
class
VYear_op
:
public
Year_null
{
public:
VYear_op
(
Item_func_hybrid_field_type
*
item
);
};
class
Temporal
:
protected
MYSQL_TIME
{
protected:
...
...
@@ -3323,6 +3378,9 @@ class Type_handler_year: public Type_handler_int_result
uint32
flags
)
const
;
Item_cache
*
Item_get_cache
(
THD
*
thd
,
const
Item
*
item
)
const
;
bool
Item_get_date
(
Item
*
item
,
MYSQL_TIME
*
ltime
,
ulonglong
fuzzydate
)
const
;
bool
Item_func_hybrid_field_type_get_date
(
Item_func_hybrid_field_type
*
item
,
MYSQL_TIME
*
to
,
ulonglong
fuzzydate
)
const
;
};
...
...
@@ -4562,6 +4620,7 @@ extern MYSQL_PLUGIN_IMPORT Type_handler_newdecimal type_handler_newdecimal;
extern
MYSQL_PLUGIN_IMPORT
Type_handler_olddecimal
type_handler_olddecimal
;
extern
MYSQL_PLUGIN_IMPORT
Type_handler_year
type_handler_year
;
extern
MYSQL_PLUGIN_IMPORT
Type_handler_year
type_handler_year2
;
extern
MYSQL_PLUGIN_IMPORT
Type_handler_newdate
type_handler_newdate
;
extern
MYSQL_PLUGIN_IMPORT
Type_handler_date
type_handler_date
;
extern
MYSQL_PLUGIN_IMPORT
Type_handler_time
type_handler_time
;
...
...
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