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
54fc4796
Commit
54fc4796
authored
Aug 01, 2018
by
Alexander Barkov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
MDEV-16874 Implement class Item_handled_func
parent
af46c257
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
547 additions
and
258 deletions
+547
-258
mysql-test/main/func_time.result
mysql-test/main/func_time.result
+0
-1
sql/item_func.h
sql/item_func.h
+60
-2
sql/item_timefunc.cc
sql/item_timefunc.cc
+70
-208
sql/item_timefunc.h
sql/item_timefunc.h
+412
-47
sql/sql_type.h
sql/sql_type.h
+5
-0
No files found.
mysql-test/main/func_time.result
View file @
54fc4796
...
...
@@ -1716,7 +1716,6 @@ min(timestampadd(month, 1>'', from_days('%Z')))
NULL
Warnings:
Warning 1292 Truncated incorrect INTEGER value: '%Z'
Warning 1292 Truncated incorrect DOUBLE value: ''
Warning 1292 Incorrect datetime value: '0000-00-00'
SET timestamp=UNIX_TIMESTAMP('2001-01-01 00:00:00');
create table t1(a time);
...
...
sql/item_func.h
View file @
54fc4796
...
...
@@ -40,8 +40,6 @@ class Item_func :public Item_func_or_sum,
{
void
sync_with_sum_func_and_with_field
(
List
<
Item
>
&
list
);
protected:
String
*
val_str_from_val_str_ascii
(
String
*
str
,
String
*
str2
);
virtual
bool
check_arguments
()
const
{
return
check_argument_types_scalar
(
0
,
arg_count
);
...
...
@@ -188,6 +186,8 @@ class Item_func :public Item_func_or_sum,
update_null_value
();
return
null_value
;
}
String
*
val_str_from_val_str_ascii
(
String
*
str
,
String
*
str2
);
void
signal_divide_by_null
();
friend
class
udf_handler
;
Field
*
create_field_for_create_select
(
TABLE
*
table
)
...
...
@@ -450,6 +450,64 @@ class Item_hybrid_func: public Item_func,
};
class
Item_handled_func
:
public
Item_func
{
public:
class
Handler
{
public:
virtual
~
Handler
()
{
}
virtual
String
*
val_str
(
Item_handled_func
*
,
String
*
)
const
=
0
;
virtual
String
*
val_str_ascii
(
Item_handled_func
*
,
String
*
)
const
=
0
;
virtual
double
val_real
(
Item_handled_func
*
)
const
=
0
;
virtual
longlong
val_int
(
Item_handled_func
*
)
const
=
0
;
virtual
my_decimal
*
val_decimal
(
Item_handled_func
*
,
my_decimal
*
)
const
=
0
;
virtual
bool
get_date
(
Item_handled_func
*
,
MYSQL_TIME
*
,
ulonglong
fuzzydate
)
const
=
0
;
virtual
const
Type_handler
*
return_type_handler
()
const
=
0
;
virtual
bool
fix_length_and_dec
(
Item_handled_func
*
)
const
=
0
;
};
protected:
const
Handler
*
m_func_handler
;
public:
Item_handled_func
(
THD
*
thd
,
Item
*
a
)
:
Item_func
(
thd
,
a
),
m_func_handler
(
NULL
)
{
}
Item_handled_func
(
THD
*
thd
,
Item
*
a
,
Item
*
b
)
:
Item_func
(
thd
,
a
,
b
),
m_func_handler
(
NULL
)
{
}
void
set_func_handler
(
const
Handler
*
handler
)
{
m_func_handler
=
handler
;
}
const
Type_handler
*
type_handler
()
const
{
return
m_func_handler
->
return_type_handler
();
}
String
*
val_str
(
String
*
to
)
{
return
m_func_handler
->
val_str
(
this
,
to
);
}
String
*
val_str_ascii
(
String
*
to
)
{
return
m_func_handler
->
val_str_ascii
(
this
,
to
);
}
double
val_real
()
{
return
m_func_handler
->
val_real
(
this
);
}
longlong
val_int
()
{
return
m_func_handler
->
val_int
(
this
);
}
my_decimal
*
val_decimal
(
my_decimal
*
to
)
{
return
m_func_handler
->
val_decimal
(
this
,
to
);
}
bool
get_date
(
MYSQL_TIME
*
to
,
ulonglong
fuzzydate
)
{
return
m_func_handler
->
get_date
(
this
,
to
,
fuzzydate
);
}
};
/**
Functions that at fix_fields() time determine the returned field type,
trying to preserve the exact data type of the arguments.
...
...
sql/item_timefunc.cc
View file @
54fc4796
...
...
@@ -58,6 +58,29 @@
/** Day number for Dec 31st, 9999. */
#define MAX_DAY_NUMBER 3652424L
Func_handler_date_add_interval_datetime_arg0_time
func_handler_date_add_interval_datetime_arg0_time
;
Func_handler_date_add_interval_datetime
func_handler_date_add_interval_datetime
;
Func_handler_date_add_interval_date
func_handler_date_add_interval_date
;
Func_handler_date_add_interval_time
func_handler_date_add_interval_time
;
Func_handler_date_add_interval_string
func_handler_date_add_interval_string
;
Func_handler_add_time_datetime
func_handler_add_time_datetime_add
(
1
);
Func_handler_add_time_datetime
func_handler_add_time_datetime_sub
(
-
1
);
Func_handler_add_time_time
func_handler_add_time_time_add
(
1
);
Func_handler_add_time_time
func_handler_add_time_time_sub
(
-
1
);
Func_handler_add_time_string
func_handler_add_time_string_add
(
1
);
Func_handler_add_time_string
func_handler_add_time_string_sub
(
-
1
);
Func_handler_str_to_date_datetime_sec
func_handler_str_to_date_datetime_sec
;
Func_handler_str_to_date_datetime_usec
func_handler_str_to_date_datetime_usec
;
Func_handler_str_to_date_date
func_handler_str_to_date_date
;
Func_handler_str_to_date_time_sec
func_handler_str_to_date_time_sec
;
Func_handler_str_to_date_time_usec
func_handler_str_to_date_time_usec
;
/*
Date formats corresponding to compound %r and %T conversion specifiers
...
...
@@ -1482,19 +1505,20 @@ String *Item_temporal_func::val_str(String *str)
}
String
*
Item_temporal_hybrid_func
::
val_str_ascii
(
String
*
str
)
String
*
Func_handler_temporal_hybrid
::
val_str_ascii
(
Item_handled_func
*
item
,
String
*
str
)
const
{
DBUG_ASSERT
(
fixed
==
1
);
DBUG_ASSERT
(
item
->
is_fixed
()
);
MYSQL_TIME
ltime
;
if
(
get_date
(
&
ltime
,
0
)
||
(
null_value
=
my_TIME_to_str
(
&
ltime
,
str
,
decimals
)))
if
(
get_date
(
item
,
&
ltime
,
0
)
||
(
item
->
null_value
=
my_TIME_to_str
(
&
ltime
,
str
,
item
->
decimals
)))
return
(
String
*
)
0
;
/* Check that the returned timestamp type matches to the function type */
DBUG_ASSERT
(
field_type
()
==
MYSQL_TYPE_STRING
||
DBUG_ASSERT
(
item
->
field_type
()
==
MYSQL_TYPE_STRING
||
ltime
.
time_type
==
MYSQL_TIMESTAMP_NONE
||
ltime
.
time_type
==
mysql_timestamp_type
());
ltime
.
time_type
==
return_type_handler
()
->
mysql_timestamp_type
());
return
str
;
}
...
...
@@ -2088,115 +2112,44 @@ bool Item_date_add_interval::fix_length_and_dec()
MYSQL_TIME or DATETIME argument)
*/
arg0_field_type
=
args
[
0
]
->
field_type
();
uint
interval_dec
=
0
;
if
(
int_type
==
INTERVAL_MICROSECOND
||
(
int_type
>=
INTERVAL_DAY_MICROSECOND
&&
int_type
<=
INTERVAL_SECOND_MICROSECOND
))
interval_dec
=
TIME_SECOND_PART_DIGITS
;
else
if
(
int_type
==
INTERVAL_SECOND
&&
args
[
1
]
->
decimals
>
0
)
interval_dec
=
MY_MIN
(
args
[
1
]
->
decimals
,
TIME_SECOND_PART_DIGITS
);
if
(
arg0_field_type
==
MYSQL_TYPE_DATETIME
||
arg0_field_type
==
MYSQL_TYPE_TIMESTAMP
)
{
uint
dec
=
MY_MAX
(
args
[
0
]
->
datetime_precision
(),
interval_dec
);
set_handler
(
&
type_handler_datetime
);
fix_attributes_datetime
(
dec
);
set_func_handler
(
&
func_handler_date_add_interval_datetime
);
}
else
if
(
arg0_field_type
==
MYSQL_TYPE_DATE
)
{
if
(
int_type
<=
INTERVAL_DAY
||
int_type
==
INTERVAL_YEAR_MONTH
)
{
set_handler
(
&
type_handler_newdate
);
fix_attributes_date
();
}
set_func_handler
(
&
func_handler_date_add_interval_date
);
else
{
set_handler
(
&
type_handler_datetime2
);
fix_attributes_datetime
(
interval_dec
);
}
set_func_handler
(
&
func_handler_date_add_interval_datetime
);
}
else
if
(
arg0_field_type
==
MYSQL_TYPE_TIME
)
{
uint
dec
=
MY_MAX
(
args
[
0
]
->
time_precision
(),
interval_dec
);
if
(
int_type
>=
INTERVAL_DAY
&&
int_type
!=
INTERVAL_YEAR_MONTH
)
{
set_handler
(
&
type_handler_time2
);
fix_attributes_time
(
dec
);
}
set_func_handler
(
&
func_handler_date_add_interval_time
);
else
{
set_handler
(
&
type_handler_datetime2
);
fix_attributes_datetime
(
dec
);
}
set_func_handler
(
&
func_handler_date_add_interval_datetime_arg0_time
);
}
else
{
uint
dec
=
MY_MAX
(
args
[
0
]
->
datetime_precision
(),
interval_dec
);
set_handler
(
&
type_handler_string
);
collation
.
set
(
default_charset
(),
DERIVATION_COERCIBLE
,
MY_REPERTOIRE_ASCII
);
fix_char_length_temporal_not_fixed_dec
(
MAX_DATETIME_WIDTH
,
dec
);
set_func_handler
(
&
func_handler_date_add_interval_string
);
}
maybe_null
=
true
;
return
FALSE
;
return
m_func_handler
->
fix_length_and_dec
(
this
)
;
}
bool
Item_date_add_interval
::
get_date
(
MYSQL_TIME
*
ltime
,
ulonglong
fuzzy_date
)
bool
Func_handler_date_add_interval_datetime_arg0_time
::
get_date
(
Item_handled_func
*
item
,
MYSQL_TIME
*
to
,
ulonglong
fuzzy
)
const
{
INTERVAL
interval
;
if
(
field_type
()
==
MYSQL_TYPE_TIME
)
{
Time
t
(
args
[
0
]);
if
(
!
t
.
is_valid_time
())
return
(
null_value
=
true
);
t
.
copy_to_mysql_time
(
ltime
);
}
else
if
(
field_type
()
==
MYSQL_TYPE_DATETIME
)
{
THD
*
thd
=
current_thd
;
if
(
args
[
0
]
->
field_type
()
==
MYSQL_TYPE_TIME
)
{
// time_expr + INTERVAL {YEAR|QUARTER|MONTH|WEEK|YEAR_MONTH}
push_warning_printf
(
thd
,
Sql_condition
::
WARN_LEVEL_WARN
,
ER_DATETIME_FUNCTION_OVERFLOW
,
ER_THD
(
thd
,
ER_DATETIME_FUNCTION_OVERFLOW
),
"time"
);
return
(
null_value
=
true
);
}
Datetime
dt
(
thd
,
args
[
0
],
0
);
if
(
!
dt
.
is_valid_datetime
())
return
(
null_value
=
true
);
dt
.
copy_to_mysql_time
(
ltime
);
}
else
if
(
field_type
()
==
MYSQL_TYPE_DATE
)
{
Date
d
(
current_thd
,
args
[
0
],
0
);
if
(
!
d
.
is_valid_date
())
return
(
null_value
=
true
);
d
.
copy_to_mysql_time
(
ltime
);
}
else
{
if
(
args
[
0
]
->
get_date
(
ltime
,
0
))
return
(
null_value
=
true
);
}
if
(
get_interval_value
(
args
[
1
],
int_type
,
&
interval
))
return
(
null_value
=
true
);
if
(
ltime
->
time_type
!=
MYSQL_TIMESTAMP_TIME
&&
check_date_with_warn
(
ltime
,
TIME_NO_ZERO_DATE
|
TIME_NO_ZERO_IN_DATE
,
MYSQL_TIMESTAMP_ERROR
))
return
(
null_value
=
1
);
if
(
date_sub_interval
)
interval
.
neg
=
!
interval
.
neg
;
if
(
date_add_interval
(
ltime
,
int_type
,
interval
))
return
(
null_value
=
1
);
return
(
null_value
=
0
);
THD
*
thd
=
current_thd
;
// time_expr + INTERVAL {YEAR|QUARTER|MONTH|WEEK|YEAR_MONTH}
push_warning_printf
(
thd
,
Sql_condition
::
WARN_LEVEL_WARN
,
ER_DATETIME_FUNCTION_OVERFLOW
,
ER_THD
(
thd
,
ER_DATETIME_FUNCTION_OVERFLOW
),
"time"
);
return
(
item
->
null_value
=
true
);
}
...
...
@@ -2700,69 +2653,22 @@ bool Item_func_add_time::fix_length_and_dec()
arg0_field_type
==
MYSQL_TYPE_DATETIME
||
arg0_field_type
==
MYSQL_TYPE_TIMESTAMP
)
{
uint
dec
=
MY_MAX
(
args
[
0
]
->
datetime_precision
(),
args
[
1
]
->
time_precision
());
set_handler
(
&
type_handler_datetime2
);
fix_attributes_datetime
(
dec
);
set_func_handler
(
sign
>
0
?
&
func_handler_add_time_datetime_add
:
&
func_handler_add_time_datetime_sub
);
}
else
if
(
arg0_field_type
==
MYSQL_TYPE_TIME
)
{
uint
dec
=
MY_MAX
(
args
[
0
]
->
time_precision
(),
args
[
1
]
->
time_precision
());
set_handler
(
&
type_handler_time2
);
fix_attributes_time
(
dec
);
set_func_handler
(
sign
>
0
?
&
func_handler_add_time_time_add
:
&
func_handler_add_time_time_sub
);
}
else
{
uint
dec
=
MY_MAX
(
args
[
0
]
->
decimals
,
args
[
1
]
->
decimals
);
set_handler
(
&
type_handler_string
);
collation
.
set
(
default_charset
(),
DERIVATION_COERCIBLE
,
MY_REPERTOIRE_ASCII
);
fix_char_length_temporal_not_fixed_dec
(
MAX_DATETIME_WIDTH
,
dec
);
}
maybe_null
=
true
;
return
FALSE
;
}
/**
ADDTIME(t,a) and SUBTIME(t,a) are time functions that calculate a
time/datetime value
t: time_or_datetime_expression
a: time_expression
Result: Time value or datetime value
*/
bool
Item_func_add_time
::
get_date
(
MYSQL_TIME
*
ltime
,
ulonglong
fuzzy_date
)
{
DBUG_ASSERT
(
fixed
==
1
);
MYSQL_TIME
l_time2
;
if
(
Item_func_add_time
::
field_type
()
==
MYSQL_TYPE_DATETIME
)
{
// TIMESTAMP function OR the first argument is DATE/DATETIME/TIMESTAMP
Datetime
dt
(
current_thd
,
args
[
0
],
0
);
return
(
null_value
=
(
!
dt
.
is_valid_datetime
()
||
args
[
1
]
->
get_time
(
&
l_time2
)
||
Sec6_add
(
dt
.
get_mysql_time
(),
&
l_time2
,
sign
).
to_datetime
(
ltime
)));
set_func_handler
(
sign
>
0
?
&
func_handler_add_time_string_add
:
&
func_handler_add_time_string_sub
);
}
if
(
Item_func_add_time
::
field_type
()
==
MYSQL_TYPE_TIME
)
{
// ADDTIME() and the first argument is TIME
Time
t
(
args
[
0
]);
return
(
null_value
=
(
!
t
.
is_valid_time
()
||
args
[
1
]
->
get_time
(
&
l_time2
)
||
Sec6_add
(
t
.
get_mysql_time
(),
&
l_time2
,
sign
).
to_time
(
ltime
,
decimals
)));
}
// Detect a proper timestamp type based on the argument values
MYSQL_TIME
l_time1
;
if
(
args
[
0
]
->
get_time
(
&
l_time1
)
||
args
[
1
]
->
get_time
(
&
l_time2
))
return
(
null_value
=
true
);
Sec6_add
add
(
&
l_time1
,
&
l_time2
,
sign
);
return
(
null_value
=
(
l_time1
.
time_type
==
MYSQL_TIMESTAMP_TIME
?
add
.
to_time
(
ltime
,
decimals
)
:
add
.
to_datetime
(
ltime
)));
maybe_null
=
true
;
return
m_func_handler
->
fix_length_and_dec
(
this
);
}
...
...
@@ -3102,15 +3008,10 @@ void Item_func_get_format::print(String *str, enum_query_type query_type)
specifiers supported by extract_date_time() function.
@return
One of date_time_format_types values:
- DATE_TIME_MICROSECOND
- DATE_TIME
- DATE_ONLY
- TIME_MICROSECOND
- TIME_ONLY
A function handler corresponding the given format
*/
static
date_time_format_types
static
const
Item_handled_func
::
Handler
*
get_date_time_result_type
(
const
char
*
format
,
uint
length
)
{
const
char
*
time_part_frms
=
"HISThiklrs"
;
...
...
@@ -3137,21 +3038,21 @@ get_date_time_result_type(const char *format, uint length)
frac_second_used implies time_part_used, and thus we already
have all types of date-time components and can end our search.
*/
return
DATE_TIME_MICROSECOND
;
return
&
func_handler_str_to_date_datetime_usec
;
}
}
}
/* We don't have all three types of date-time components */
if
(
frac_second_used
)
return
TIME_MICROSECOND
;
return
&
func_handler_str_to_date_time_usec
;
if
(
time_part_used
)
{
if
(
date_part_used
)
return
DATE_TIME
;
return
TIME_ONLY
;
return
&
func_handler_str_to_date_datetime_sec
;
return
&
func_handler_str_to_date_time_sec
;
}
return
DATE_ONLY
;
return
&
func_handler_str_to_date_date
;
}
...
...
@@ -3171,56 +3072,27 @@ bool Item_func_str_to_date::fix_length_and_dec()
internal_charset
=
&
my_charset_utf8mb4_general_ci
;
maybe_null
=
true
;
set_handler
(
&
type_handler_datetime2
);
fix_attributes_datetime
(
TIME_SECOND_PART_DIGITS
);
set_func_handler
(
&
func_handler_str_to_date_datetime_usec
);
if
((
const_item
=
args
[
1
]
->
const_item
()))
{
char
format_buff
[
64
];
String
format_str
(
format_buff
,
sizeof
(
format_buff
),
&
my_charset_bin
);
StringBuffer
<
64
>
format_str
;
String
*
format
=
args
[
1
]
->
val_str
(
&
format_str
,
&
format_converter
,
internal_charset
);
decimals
=
0
;
if
(
!
args
[
1
]
->
null_value
)
{
date_time_format_types
cached_format_type
=
get_date_time_result_type
(
format
->
ptr
(),
format
->
length
());
switch
(
cached_format_type
)
{
case
DATE_ONLY
:
set_handler
(
&
type_handler_newdate
);
fix_attributes_date
();
break
;
case
TIME_MICROSECOND
:
set_handler
(
&
type_handler_time2
);
fix_attributes_time
(
TIME_SECOND_PART_DIGITS
);
break
;
case
TIME_ONLY
:
set_handler
(
&
type_handler_time2
);
fix_attributes_time
(
0
);
break
;
case
DATE_TIME_MICROSECOND
:
set_handler
(
&
type_handler_datetime2
);
fix_attributes_datetime
(
TIME_SECOND_PART_DIGITS
);
break
;
case
DATE_TIME
:
set_handler
(
&
type_handler_datetime2
);
fix_attributes_datetime
(
0
);
break
;
}
}
set_func_handler
(
get_date_time_result_type
(
format
->
ptr
(),
format
->
length
()));
}
cached_timestamp_type
=
mysql_timestamp_type
();
return
FALSE
;
return
m_func_handler
->
fix_length_and_dec
(
this
);
}
bool
Item_func_str_to_date
::
get_date
(
MYSQL_TIME
*
ltime
,
ulonglong
fuzzy_date
)
bool
Item_func_str_to_date
::
get_date_common
(
MYSQL_TIME
*
ltime
,
ulonglong
fuzzy_date
,
timestamp_type
tstype
)
{
DATE_TIME_FORMAT
date_time_format
;
char
val_buff
[
64
],
format_buff
[
64
];
String
val_string
(
val_buff
,
sizeof
(
val_buff
),
&
my_charset_bin
),
*
val
;
String
format_str
(
format_buff
,
sizeof
(
format_buff
),
&
my_charset_bin
),
*
format
;
StringBuffer
<
64
>
val_string
,
format_str
;
String
*
val
,
*
format
;
val
=
args
[
0
]
->
val_str
(
&
val_string
,
&
subject_converter
,
internal_charset
);
format
=
args
[
1
]
->
val_str
(
&
format_str
,
&
format_converter
,
internal_charset
);
...
...
@@ -3230,19 +3102,9 @@ bool Item_func_str_to_date::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date)
date_time_format
.
format
.
str
=
(
char
*
)
format
->
ptr
();
date_time_format
.
format
.
length
=
format
->
length
();
if
(
extract_date_time
(
&
date_time_format
,
val
->
ptr
(),
val
->
length
(),
ltime
,
cached_timestamp_
type
,
0
,
"datetime"
,
ltime
,
ts
type
,
0
,
"datetime"
,
fuzzy_date
|
sql_mode_for_dates
(
current_thd
)))
return
(
null_value
=
1
);
if
(
cached_timestamp_type
==
MYSQL_TIMESTAMP_TIME
&&
ltime
->
day
)
{
/*
Day part for time type can be nonzero value and so
we should add hours from day part to hour part to
keep valid time value.
*/
ltime
->
hour
+=
ltime
->
day
*
24
;
ltime
->
day
=
0
;
}
return
(
null_value
=
0
);
}
...
...
sql/item_timefunc.h
View file @
54fc4796
...
...
@@ -25,11 +25,6 @@
class
MY_LOCALE
;
enum
date_time_format_types
{
TIME_ONLY
=
0
,
TIME_MICROSECOND
,
DATE_ONLY
,
DATE_TIME
,
DATE_TIME_MICROSECOND
};
bool
get_interval_value
(
Item
*
args
,
interval_type
int_type
,
INTERVAL
*
interval
);
...
...
@@ -602,38 +597,6 @@ class Item_temporal_func: public Item_func
};
/**
Abstract class for functions returning TIME, DATE, DATETIME or string values,
whose data type depends on parameters and is set at fix_fields time.
*/
class
Item_temporal_hybrid_func
:
public
Item_hybrid_func
{
protected:
String
ascii_buf
;
// Conversion buffer
public:
Item_temporal_hybrid_func
(
THD
*
thd
,
Item
*
a
,
Item
*
b
)
:
Item_hybrid_func
(
thd
,
a
,
b
)
{}
longlong
val_int
()
{
return
val_int_from_date
();
}
double
val_real
()
{
return
val_real_from_date
();
}
bool
get_date
(
MYSQL_TIME
*
res
,
ulonglong
fuzzy_date
)
=
0
;
my_decimal
*
val_decimal
(
my_decimal
*
decimal_value
)
{
return
val_decimal_from_date
(
decimal_value
);
}
/**
Return string value in ASCII character set.
*/
String
*
val_str_ascii
(
String
*
str
);
/**
Return string value in @@character_set_connection.
*/
String
*
val_str
(
String
*
str
)
{
return
val_str_from_val_str_ascii
(
str
,
&
ascii_buf
);
}
};
class
Item_datefunc
:
public
Item_temporal_func
{
public:
...
...
@@ -985,18 +948,17 @@ class Item_func_sec_to_time :public Item_timefunc
};
class
Item_date_add_interval
:
public
Item_
temporal_hybri
d_func
class
Item_date_add_interval
:
public
Item_
handle
d_func
{
public:
const
interval_type
int_type
;
// keep it public
const
bool
date_sub_interval
;
// keep it public
Item_date_add_interval
(
THD
*
thd
,
Item
*
a
,
Item
*
b
,
interval_type
type_arg
,
bool
neg_arg
)
:
Item_
temporal_hybrid_func
(
thd
,
a
,
b
),
int_type
(
type_arg
),
Item_
handled_func
(
thd
,
a
,
b
),
int_type
(
type_arg
),
date_sub_interval
(
neg_arg
)
{}
const
char
*
func_name
()
const
{
return
"date_add_interval"
;
}
bool
fix_length_and_dec
();
bool
get_date
(
MYSQL_TIME
*
res
,
ulonglong
fuzzy_date
);
bool
eq
(
const
Item
*
item
,
bool
binary_cmp
)
const
;
void
print
(
String
*
str
,
enum_query_type
query_type
);
enum
precedence
precedence
()
const
{
return
ADDINTERVAL_PRECEDENCE
;
}
...
...
@@ -1264,20 +1226,30 @@ class Item_func_timestamp :public Item_datetimefunc
};
class
Item_func_add_time
:
public
Item_temporal_hybrid_func
/**
ADDTIME(t,a) and SUBTIME(t,a) are time functions that calculate a
time/datetime value
t: time_or_datetime_expression
a: time_expression
Result: Time value or datetime value
*/
class
Item_func_add_time
:
public
Item_handled_func
{
int
sign
;
public:
Item_func_add_time
(
THD
*
thd
,
Item
*
a
,
Item
*
b
,
bool
neg_arg
)
:
Item_
temporal_hybri
d_func
(
thd
,
a
,
b
),
sign
(
neg_arg
?
-
1
:
1
)
:
Item_
handle
d_func
(
thd
,
a
,
b
),
sign
(
neg_arg
?
-
1
:
1
)
{
}
bool
fix_length_and_dec
();
bool
get_date
(
MYSQL_TIME
*
ltime
,
ulonglong
fuzzy_date
);
const
char
*
func_name
()
const
{
return
sign
>
0
?
"addtime"
:
"subtime"
;
}
Item
*
get_copy
(
THD
*
thd
)
{
return
get_item_copy
<
Item_func_add_time
>
(
thd
,
this
);
}
};
class
Item_func_timediff
:
public
Item_timefunc
{
bool
check_arguments
()
const
...
...
@@ -1394,19 +1366,18 @@ class Item_func_get_format :public Item_str_ascii_func
};
class
Item_func_str_to_date
:
public
Item_
temporal_hybri
d_func
class
Item_func_str_to_date
:
public
Item_
handle
d_func
{
timestamp_type
cached_timestamp_type
;
bool
const_item
;
String
subject_converter
;
String
format_converter
;
CHARSET_INFO
*
internal_charset
;
public:
Item_func_str_to_date
(
THD
*
thd
,
Item
*
a
,
Item
*
b
)
:
Item_
temporal_hybri
d_func
(
thd
,
a
,
b
),
const_item
(
false
),
Item_
handle
d_func
(
thd
,
a
,
b
),
const_item
(
false
),
internal_charset
(
NULL
)
{}
bool
get_date
(
MYSQL_TIME
*
ltime
,
ulonglong
fuzzy_dat
e
);
bool
get_date
_common
(
MYSQL_TIME
*
ltime
,
ulonglong
fuzzy_date
,
timestamp_typ
e
);
const
char
*
func_name
()
const
{
return
"str_to_date"
;
}
bool
fix_length_and_dec
();
Item
*
get_copy
(
THD
*
thd
)
...
...
@@ -1426,4 +1397,398 @@ class Item_func_last_day :public Item_datefunc
{
return
get_item_copy
<
Item_func_last_day
>
(
thd
,
this
);
}
};
/*****************************************************************************/
/**
Abstract class for functions returning TIME, DATE, DATETIME or string values,
whose data type depends on parameters and is set at fix_fields time.
*/
class
Func_handler_temporal_hybrid
:
public
Item_handled_func
::
Handler
{
public:
double
val_real
(
Item_handled_func
*
item
)
const
{
return
item
->
val_real_from_date
();
}
longlong
val_int
(
Item_handled_func
*
item
)
const
{
return
item
->
val_int_from_date
();
}
my_decimal
*
val_decimal
(
Item_handled_func
*
item
,
my_decimal
*
to
)
const
{
return
item
->
val_decimal_from_date
(
to
);
}
String
*
val_str
(
Item_handled_func
*
item
,
String
*
to
)
const
{
StringBuffer
<
MAX_FIELD_WIDTH
>
ascii_buf
;
return
item
->
val_str_from_val_str_ascii
(
to
,
&
ascii_buf
);
}
String
*
val_str_ascii
(
Item_handled_func
*
,
String
*
to
)
const
;
};
class
Func_handler_date_add_interval
:
public
Func_handler_temporal_hybrid
{
protected:
static
uint
interval_dec
(
const
Item
*
item
,
interval_type
int_type
)
{
if
(
int_type
==
INTERVAL_MICROSECOND
||
(
int_type
>=
INTERVAL_DAY_MICROSECOND
&&
int_type
<=
INTERVAL_SECOND_MICROSECOND
))
return
TIME_SECOND_PART_DIGITS
;
if
(
int_type
==
INTERVAL_SECOND
&&
item
->
decimals
>
0
)
return
MY_MIN
(
item
->
decimals
,
TIME_SECOND_PART_DIGITS
);
return
0
;
}
interval_type
int_type
(
const
Item_handled_func
*
item
)
const
{
return
static_cast
<
const
Item_date_add_interval
*>
(
item
)
->
int_type
;
}
bool
sub
(
const
Item_handled_func
*
item
)
const
{
return
static_cast
<
const
Item_date_add_interval
*>
(
item
)
->
date_sub_interval
;
}
bool
add
(
Item
*
item
,
interval_type
type
,
bool
sub
,
MYSQL_TIME
*
to
)
const
{
INTERVAL
interval
;
if
(
get_interval_value
(
item
,
type
,
&
interval
))
return
true
;
if
(
sub
)
interval
.
neg
=
!
interval
.
neg
;
return
date_add_interval
(
to
,
type
,
interval
);
}
};
class
Func_handler_date_add_interval_datetime
:
public
Func_handler_date_add_interval
{
public:
const
Type_handler
*
return_type_handler
()
const
{
return
&
type_handler_datetime2
;
}
bool
fix_length_and_dec
(
Item_handled_func
*
item
)
const
{
uint
dec
=
MY_MAX
(
item
->
arguments
()[
0
]
->
datetime_precision
(),
interval_dec
(
item
->
arguments
()[
1
],
int_type
(
item
)));
item
->
fix_attributes_datetime
(
dec
);
return
false
;
}
bool
get_date
(
Item_handled_func
*
item
,
MYSQL_TIME
*
to
,
ulonglong
fuzzy
)
const
{
Datetime
dt
(
current_thd
,
item
->
arguments
()[
0
],
0
);
if
(
!
dt
.
is_valid_datetime
()
||
dt
.
check_date_with_warn
(
TIME_NO_ZERO_DATE
|
TIME_NO_ZERO_IN_DATE
))
return
(
item
->
null_value
=
true
);
dt
.
copy_to_mysql_time
(
to
);
return
(
item
->
null_value
=
add
(
item
->
arguments
()[
1
],
int_type
(
item
),
sub
(
item
),
to
));
}
};
class
Func_handler_date_add_interval_datetime_arg0_time
:
public
Func_handler_date_add_interval_datetime
{
public:
bool
get_date
(
Item_handled_func
*
item
,
MYSQL_TIME
*
to
,
ulonglong
fuzzy
)
const
;
};
class
Func_handler_date_add_interval_date
:
public
Func_handler_date_add_interval
{
public:
const
Type_handler
*
return_type_handler
()
const
{
return
&
type_handler_newdate
;
}
bool
fix_length_and_dec
(
Item_handled_func
*
item
)
const
{
item
->
fix_attributes_date
();
return
false
;
}
bool
get_date
(
Item_handled_func
*
item
,
MYSQL_TIME
*
to
,
ulonglong
fuzzy
)
const
{
Date
d
(
current_thd
,
item
->
arguments
()[
0
],
0
);
if
(
!
d
.
is_valid_date
()
||
d
.
check_date_with_warn
(
TIME_NO_ZERO_DATE
|
TIME_NO_ZERO_IN_DATE
))
return
(
item
->
null_value
=
true
);
d
.
copy_to_mysql_time
(
to
);
return
(
item
->
null_value
=
add
(
item
->
arguments
()[
1
],
int_type
(
item
),
sub
(
item
),
to
));
}
};
class
Func_handler_date_add_interval_time
:
public
Func_handler_date_add_interval
{
public:
const
Type_handler
*
return_type_handler
()
const
{
return
&
type_handler_time2
;
}
bool
fix_length_and_dec
(
Item_handled_func
*
item
)
const
{
uint
dec
=
MY_MAX
(
item
->
arguments
()[
0
]
->
time_precision
(),
interval_dec
(
item
->
arguments
()[
1
],
int_type
(
item
)));
item
->
fix_attributes_time
(
dec
);
return
false
;
}
bool
get_date
(
Item_handled_func
*
item
,
MYSQL_TIME
*
to
,
ulonglong
fuzzy
)
const
{
Time
t
(
item
->
arguments
()[
0
]);
if
(
!
t
.
is_valid_time
())
return
(
item
->
null_value
=
true
);
t
.
copy_to_mysql_time
(
to
);
return
(
item
->
null_value
=
add
(
item
->
arguments
()[
1
],
int_type
(
item
),
sub
(
item
),
to
));
}
};
class
Func_handler_date_add_interval_string
:
public
Func_handler_date_add_interval
{
public:
const
Type_handler
*
return_type_handler
()
const
{
return
&
type_handler_string
;
}
bool
fix_length_and_dec
(
Item_handled_func
*
item
)
const
{
uint
dec
=
MY_MAX
(
item
->
arguments
()[
0
]
->
datetime_precision
(),
interval_dec
(
item
->
arguments
()[
1
],
int_type
(
item
)));
item
->
collation
.
set
(
item
->
default_charset
(),
DERIVATION_COERCIBLE
,
MY_REPERTOIRE_ASCII
);
item
->
fix_char_length_temporal_not_fixed_dec
(
MAX_DATETIME_WIDTH
,
dec
);
return
false
;
}
bool
get_date
(
Item_handled_func
*
item
,
MYSQL_TIME
*
to
,
ulonglong
fuzzy
)
const
{
if
(
item
->
arguments
()[
0
]
->
get_date
(
to
,
0
)
||
(
to
->
time_type
!=
MYSQL_TIMESTAMP_TIME
&&
check_date_with_warn
(
to
,
TIME_NO_ZERO_DATE
|
TIME_NO_ZERO_IN_DATE
,
MYSQL_TIMESTAMP_ERROR
)))
return
(
item
->
null_value
=
true
);
return
(
item
->
null_value
=
add
(
item
->
arguments
()[
1
],
int_type
(
item
),
sub
(
item
),
to
));
}
};
class
Func_handler_add_time
:
public
Func_handler_temporal_hybrid
{
protected:
int
m_sign
;
Func_handler_add_time
(
int
sign
)
:
m_sign
(
sign
)
{
}
};
class
Func_handler_add_time_datetime
:
public
Func_handler_add_time
{
public:
Func_handler_add_time_datetime
(
int
sign
)
:
Func_handler_add_time
(
sign
)
{
}
const
Type_handler
*
return_type_handler
()
const
{
return
&
type_handler_datetime2
;
}
bool
fix_length_and_dec
(
Item_handled_func
*
item
)
const
{
uint
dec
=
MY_MAX
(
item
->
arguments
()[
0
]
->
datetime_precision
(),
item
->
arguments
()[
1
]
->
time_precision
());
item
->
fix_attributes_datetime
(
dec
);
return
false
;
}
bool
get_date
(
Item_handled_func
*
item
,
MYSQL_TIME
*
to
,
ulonglong
fuzzy
)
const
{
DBUG_ASSERT
(
item
->
is_fixed
());
MYSQL_TIME
l_time2
;
Datetime
dt
(
current_thd
,
item
->
arguments
()[
0
],
0
);
return
(
item
->
null_value
=
(
!
dt
.
is_valid_datetime
()
||
item
->
arguments
()[
1
]
->
get_time
(
&
l_time2
)
||
Sec6_add
(
dt
.
get_mysql_time
(),
&
l_time2
,
m_sign
).
to_datetime
(
to
)));
}
};
class
Func_handler_add_time_time
:
public
Func_handler_add_time
{
public:
Func_handler_add_time_time
(
int
sign
)
:
Func_handler_add_time
(
sign
)
{
}
const
Type_handler
*
return_type_handler
()
const
{
return
&
type_handler_time2
;
}
bool
fix_length_and_dec
(
Item_handled_func
*
item
)
const
{
uint
dec
=
MY_MAX
(
item
->
arguments
()[
0
]
->
time_precision
(),
item
->
arguments
()[
1
]
->
time_precision
());
item
->
fix_attributes_time
(
dec
);
return
false
;
}
bool
get_date
(
Item_handled_func
*
item
,
MYSQL_TIME
*
to
,
ulonglong
fuzzy
)
const
{
DBUG_ASSERT
(
item
->
is_fixed
());
MYSQL_TIME
l_time2
;
Time
t
(
item
->
arguments
()[
0
]);
return
(
item
->
null_value
=
(
!
t
.
is_valid_time
()
||
item
->
arguments
()[
1
]
->
get_time
(
&
l_time2
)
||
Sec6_add
(
t
.
get_mysql_time
(),
&
l_time2
,
m_sign
).
to_time
(
to
,
item
->
decimals
)));
}
};
class
Func_handler_add_time_string
:
public
Func_handler_add_time
{
public:
Func_handler_add_time_string
(
int
sign
)
:
Func_handler_add_time
(
sign
)
{
}
const
Type_handler
*
return_type_handler
()
const
{
return
&
type_handler_string
;
}
bool
fix_length_and_dec
(
Item_handled_func
*
item
)
const
{
uint
dec
=
MY_MAX
(
item
->
arguments
()[
0
]
->
decimals
,
item
->
arguments
()[
1
]
->
decimals
);
item
->
collation
.
set
(
item
->
default_charset
(),
DERIVATION_COERCIBLE
,
MY_REPERTOIRE_ASCII
);
item
->
fix_char_length_temporal_not_fixed_dec
(
MAX_DATETIME_WIDTH
,
dec
);
return
false
;
}
bool
get_date
(
Item_handled_func
*
item
,
MYSQL_TIME
*
to
,
ulonglong
fuzzy
)
const
{
DBUG_ASSERT
(
item
->
is_fixed
());
// Detect a proper timestamp type based on the argument values
MYSQL_TIME
l_time1
,
l_time2
;
if
(
item
->
arguments
()[
0
]
->
get_time
(
&
l_time1
)
||
item
->
arguments
()[
1
]
->
get_time
(
&
l_time2
))
return
(
item
->
null_value
=
true
);
Sec6_add
add
(
&
l_time1
,
&
l_time2
,
m_sign
);
return
(
item
->
null_value
=
(
l_time1
.
time_type
==
MYSQL_TIMESTAMP_TIME
?
add
.
to_time
(
to
,
item
->
decimals
)
:
add
.
to_datetime
(
to
)));
}
};
class
Func_handler_str_to_date_datetime
:
public
Func_handler_temporal_hybrid
{
public:
const
Type_handler
*
return_type_handler
()
const
{
return
&
type_handler_datetime2
;
}
bool
get_date
(
Item_handled_func
*
item
,
MYSQL_TIME
*
to
,
ulonglong
fuzzy
)
const
{
return
static_cast
<
Item_func_str_to_date
*>
(
item
)
->
get_date_common
(
to
,
fuzzy
,
MYSQL_TIMESTAMP_DATETIME
);
}
};
class
Func_handler_str_to_date_datetime_sec
:
public
Func_handler_str_to_date_datetime
{
public:
bool
fix_length_and_dec
(
Item_handled_func
*
item
)
const
{
item
->
fix_attributes_datetime
(
0
);
return
false
;
}
};
class
Func_handler_str_to_date_datetime_usec
:
public
Func_handler_str_to_date_datetime
{
public:
bool
fix_length_and_dec
(
Item_handled_func
*
item
)
const
{
item
->
fix_attributes_datetime
(
TIME_SECOND_PART_DIGITS
);
return
false
;
}
};
class
Func_handler_str_to_date_date
:
public
Func_handler_temporal_hybrid
{
public:
const
Type_handler
*
return_type_handler
()
const
{
return
&
type_handler_newdate
;
}
bool
get_date
(
Item_handled_func
*
item
,
MYSQL_TIME
*
to
,
ulonglong
fuzzy
)
const
{
return
static_cast
<
Item_func_str_to_date
*>
(
item
)
->
get_date_common
(
to
,
fuzzy
,
MYSQL_TIMESTAMP_DATE
);
}
bool
fix_length_and_dec
(
Item_handled_func
*
item
)
const
{
item
->
fix_attributes_date
();
return
false
;
}
};
class
Func_handler_str_to_date_time
:
public
Func_handler_temporal_hybrid
{
public:
const
Type_handler
*
return_type_handler
()
const
{
return
&
type_handler_time2
;
}
bool
get_date
(
Item_handled_func
*
item
,
MYSQL_TIME
*
to
,
ulonglong
fuzzy
)
const
{
if
(
static_cast
<
Item_func_str_to_date
*>
(
item
)
->
get_date_common
(
to
,
fuzzy
,
MYSQL_TIMESTAMP_TIME
))
return
true
;
if
(
to
->
day
)
{
/*
Day part for time type can be nonzero value and so
we should add hours from day part to hour part to
keep valid time value.
*/
to
->
hour
+=
to
->
day
*
24
;
to
->
day
=
0
;
}
return
false
;
}
};
class
Func_handler_str_to_date_time_sec
:
public
Func_handler_str_to_date_time
{
public:
bool
fix_length_and_dec
(
Item_handled_func
*
item
)
const
{
item
->
fix_attributes_time
(
0
);
return
false
;
}
};
class
Func_handler_str_to_date_time_usec
:
public
Func_handler_str_to_date_time
{
public:
bool
fix_length_and_dec
(
Item_handled_func
*
item
)
const
{
item
->
fix_attributes_time
(
TIME_SECOND_PART_DIGITS
);
return
false
;
}
};
#endif
/* ITEM_TIMEFUNC_INCLUDED */
sql/sql_type.h
View file @
54fc4796
...
...
@@ -367,6 +367,11 @@ class Temporal_with_date: protected MYSQL_TIME
{
make_from_item
(
thd
,
item
,
flags
);
}
public:
bool
check_date_with_warn
(
ulonglong
flags
)
{
return
::
check_date_with_warn
(
this
,
flags
,
MYSQL_TIMESTAMP_ERROR
);
}
};
...
...
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