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
a6494fbe
Commit
a6494fbe
authored
Jan 23, 2006
by
andrey@lmy004
Browse files
Options
Browse Files
Download
Plain Diff
Merge ahristov@bk-internal.mysql.com:/home/bk/mysql-5.1-new
into lmy004.:/work/mysql-5.1-tt-copy-works
parents
869661ff
91ff153d
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
348 additions
and
168 deletions
+348
-168
include/my_time.h
include/my_time.h
+15
-0
scripts/mysql_create_system_tables.sh
scripts/mysql_create_system_tables.sh
+1
-0
sql/event.cc
sql/event.cc
+15
-4
sql/event.h
sql/event.h
+2
-2
sql/event_executor.cc
sql/event_executor.cc
+19
-4
sql/event_priv.h
sql/event_priv.h
+1
-0
sql/event_timed.cc
sql/event_timed.cc
+174
-42
sql/item_timefunc.cc
sql/item_timefunc.cc
+4
-99
sql/item_timefunc.h
sql/item_timefunc.h
+3
-14
sql/mysql_priv.h
sql/mysql_priv.h
+3
-0
sql/share/errmsg.txt
sql/share/errmsg.txt
+2
-2
sql/sql_yacc.yy
sql/sql_yacc.yy
+1
-1
sql/time.cc
sql/time.cc
+108
-0
No files found.
include/my_time.h
View file @
a6494fbe
...
...
@@ -89,6 +89,21 @@ int my_date_to_str(const MYSQL_TIME *l_time, char *to);
int
my_datetime_to_str
(
const
MYSQL_TIME
*
l_time
,
char
*
to
);
int
my_TIME_to_str
(
const
MYSQL_TIME
*
l_time
,
char
*
to
);
/*
The following must be sorted so that simple intervals comes first.
(get_interval_value() depends on this)
*/
enum
interval_type
{
INTERVAL_YEAR
,
INTERVAL_QUARTER
,
INTERVAL_MONTH
,
INTERVAL_DAY
,
INTERVAL_HOUR
,
INTERVAL_MINUTE
,
INTERVAL_WEEK
,
INTERVAL_SECOND
,
INTERVAL_MICROSECOND
,
INTERVAL_YEAR_MONTH
,
INTERVAL_DAY_HOUR
,
INTERVAL_DAY_MINUTE
,
INTERVAL_DAY_SECOND
,
INTERVAL_HOUR_MINUTE
,
INTERVAL_HOUR_SECOND
,
INTERVAL_MINUTE_SECOND
,
INTERVAL_DAY_MICROSECOND
,
INTERVAL_HOUR_MICROSECOND
,
INTERVAL_MINUTE_MICROSECOND
,
INTERVAL_SECOND_MICROSECOND
};
C_MODE_END
#endif
/* _my_time_h_ */
scripts/mysql_create_system_tables.sh
View file @
a6494fbe
...
...
@@ -43,6 +43,7 @@ c_tzn="" c_tz="" c_tzt="" c_tztt="" c_tzls="" c_pl=""
i_tzn
=
""
i_tz
=
""
i_tzt
=
""
i_tztt
=
""
i_tzls
=
""
i_pl
=
""
c_p
=
""
c_pp
=
""
c_gl
=
""
c_sl
=
""
c_ev
=
""
# Check for old tables
if
test
!
-f
$mdata
/db.frm
...
...
sql/event.cc
View file @
a6494fbe
...
...
@@ -88,8 +88,14 @@ int sortcmp_lex_string(LEX_STRING s, LEX_STRING t, CHARSET_INFO *cs)
int
my_time_compare
(
TIME
*
a
,
TIME
*
b
)
{
#ifdef ENABLE_WHEN_WE_HAVE_MILLISECOND_IN_TIMESTAMPS
my_ulonglong
a_t
=
TIME_to_ulonglong_datetime
(
a
)
*
100L
+
a
->
second_part
;
my_ulonglong
b_t
=
TIME_to_ulonglong_datetime
(
b
)
*
100L
+
b
->
second_part
;
#else
my_ulonglong
a_t
=
TIME_to_ulonglong_datetime
(
a
);
my_ulonglong
b_t
=
TIME_to_ulonglong_datetime
(
b
);
#endif
if
(
a_t
>
b_t
)
return
1
;
...
...
@@ -356,10 +362,15 @@ db_create_event(THD *thd, event_timed *et, my_bool create_if_not,
DBUG_PRINT
(
"info"
,
(
"check existance of an event with the same name"
));
if
(
!
evex_db_find_event_aux
(
thd
,
et
->
dbname
,
et
->
name
,
table
))
{
push_warning_printf
(
thd
,
MYSQL_ERROR
::
WARN_LEVEL_NOTE
,
ER_EVENT_ALREADY_EXISTS
,
ER
(
ER_EVENT_ALREADY_EXISTS
),
et
->
name
.
str
);
goto
ok
;
if
(
create_if_not
)
{
push_warning_printf
(
thd
,
MYSQL_ERROR
::
WARN_LEVEL_NOTE
,
ER_EVENT_ALREADY_EXISTS
,
ER
(
ER_EVENT_ALREADY_EXISTS
),
et
->
name
.
str
);
goto
ok
;
}
my_error
(
ER_EVENT_ALREADY_EXISTS
,
MYF
(
0
),
et
->
name
.
str
);
goto
err
;
}
DBUG_PRINT
(
"info"
,
(
"non-existant, go forward"
));
...
...
sql/event.h
View file @
a6494fbe
...
...
@@ -143,12 +143,12 @@ public:
int
load_from_row
(
MEM_ROOT
*
mem_root
,
TABLE
*
table
);
bool
compute_next_execution_time
();
void
mark_last_executed
();
mark_last_executed
(
THD
*
thd
);
int
drop
(
THD
*
thd
);
...
...
sql/event_executor.cc
View file @
a6494fbe
...
...
@@ -334,9 +334,19 @@ event_executor_main(void *arg)
{
pthread_t
th
;
DBUG_PRINT
(
"evex main thread"
,(
"mark_last_executed"
));
et
->
mark_last_executed
();
et
->
compute_next_execution_time
();
DBUG_PRINT
(
"evex main thread"
,
(
"[%10s] this exec at [%llu]"
,
et
->
name
.
str
,
TIME_to_ulonglong_datetime
(
&
et
->
execute_at
)));
et
->
mark_last_executed
(
thd
);
if
(
et
->
compute_next_execution_time
())
{
sql_print_error
(
"Error while computing time of %s.%s . "
"Disabling after execution."
,
et
->
dbname
.
str
,
et
->
name
.
str
);
et
->
status
=
MYSQL_EVENT_DISABLED
;
}
DBUG_PRINT
(
"evex main thread"
,
(
"[%10s] next exec at [%llu]"
,
et
->
name
.
str
,
TIME_to_ulonglong_datetime
(
&
et
->
execute_at
)));
et
->
update_fields
(
thd
);
DBUG_PRINT
(
"info"
,
(
" Spawning a thread %d"
,
++
iter_num
));
#ifndef DBUG_FAULTY_THR
...
...
@@ -605,7 +615,12 @@ evex_load_events_from_db(THD *thd)
}
// let's find when to be executed
et
->
compute_next_execution_time
();
if
(
et
->
compute_next_execution_time
())
{
sql_print_error
(
"Error while computing execution time of %s.%s. Skipping"
,
et
->
dbname
.
str
,
et
->
name
.
str
);
continue
;
}
DBUG_PRINT
(
"evex_load_events_from_db"
,
(
"Adding to the exec list."
));
...
...
sql/event_priv.h
View file @
a6494fbe
...
...
@@ -46,6 +46,7 @@ enum evex_table_field
#define EVEX_DB_FIELD_LEN 64
#define EVEX_NAME_FIELD_LEN 64
#define EVEX_MAX_INTERVAL_VALUE 2147483647L
int
my_time_compare
(
TIME
*
a
,
TIME
*
b
);
...
...
sql/event_timed.cc
View file @
a6494fbe
...
...
@@ -191,16 +191,78 @@ int
event_timed
::
init_interval
(
THD
*
thd
,
Item
*
expr
,
interval_type
new_interval
)
{
longlong
tmp
;
String
value
;
INTERVAL
interval
;
DBUG_ENTER
(
"event_timed::init_interval"
);
if
(
expr
->
fix_fields
(
thd
,
&
expr
))
DBUG_RETURN
(
EVEX_PARSE_ERROR
);
if
((
tmp
=
expr
->
val_int
())
<=
0
)
DBUG_RETURN
(
EVEX_BAD_PARAMS
);
value
.
alloc
(
MAX_DATETIME_FULL_WIDTH
*
MY_CHARSET_BIN_MB_MAXLEN
);
if
(
get_interval_value
(
expr
,
new_interval
,
&
value
,
&
interval
))
DBUG_RETURN
(
EVEX_PARSE_ERROR
);
expression
=
tmp
;
interval
=
new_interval
;
expression
=
0
;
switch
(
new_interval
)
{
case
INTERVAL_YEAR
:
expression
=
interval
.
year
;
break
;
case
INTERVAL_QUARTER
:
case
INTERVAL_MONTH
:
expression
=
interval
.
month
;
break
;
case
INTERVAL_WEEK
:
case
INTERVAL_DAY
:
expression
=
interval
.
day
;
break
;
case
INTERVAL_HOUR
:
expression
=
interval
.
hour
;
break
;
case
INTERVAL_MINUTE
:
expression
=
interval
.
minute
;
break
;
case
INTERVAL_SECOND
:
expression
=
interval
.
second
;
break
;
case
INTERVAL_YEAR_MONTH
:
// Allow YEAR-MONTH YYYYYMM
expression
=
interval
.
year
*
12
+
interval
.
month
;
break
;
case
INTERVAL_DAY_HOUR
:
expression
=
interval
.
day
*
24
+
interval
.
hour
;
break
;
case
INTERVAL_DAY_MINUTE
:
expression
=
(
interval
.
day
*
24
+
interval
.
hour
)
*
60
+
interval
.
minute
;
break
;
case
INTERVAL_HOUR_SECOND
:
// day is anyway 0
case
INTERVAL_DAY_SECOND
:
/* DAY_SECOND having problems because of leap seconds? */
expression
=
((
interval
.
day
*
24
+
interval
.
hour
)
*
60
+
interval
.
minute
)
*
60
+
interval
.
second
;
break
;
case
INTERVAL_MINUTE_MICROSECOND
:
// day and hour are 0
case
INTERVAL_HOUR_MICROSECOND
:
// day is anyway 0
case
INTERVAL_DAY_MICROSECOND
:
expression
=
((((
interval
.
day
*
24
)
+
interval
.
hour
)
*
60
+
interval
.
minute
)
*
60
+
interval
.
second
)
*
1000000L
+
interval
.
second_part
;
break
;
case
INTERVAL_HOUR_MINUTE
:
expression
=
interval
.
hour
*
60
+
interval
.
minute
;
break
;
case
INTERVAL_MINUTE_SECOND
:
expression
=
interval
.
minute
*
60
+
interval
.
second
;
break
;
case
INTERVAL_SECOND_MICROSECOND
:
expression
=
interval
.
second
*
1000000L
+
interval
.
second_part
;
break
;
default:
break
;
}
if
(
interval
.
neg
||
expression
>
EVEX_MAX_INTERVAL_VALUE
)
DBUG_RETURN
(
EVEX_BAD_PARAMS
);
this
->
interval
=
new_interval
;
DBUG_RETURN
(
0
);
}
...
...
@@ -355,7 +417,7 @@ event_timed::init_definer(THD *thd)
Loads an event from a row from mysql.event
SYNOPSIS
event_timed::load_from_row()
event_timed::load_from_row(
MEM_ROOT *mem_root, TABLE *table
)
REMARKS
This method is silent on errors and should behave like that. Callers
...
...
@@ -499,8 +561,83 @@ error:
/*
Note: In the comments this->ends is referenced as m_ends
Computes the sum of a timestamp plus interval
SYNOPSIS
get_next_time(TIME *start, int interval_value, interval_type interval)
next - the sum
start - add interval_value to this time
i_value - quantity of time type interval to add
i_type - type of interval to add (SECOND, MINUTE, HOUR, WEEK ...)
*/
static
bool
get_next_time
(
TIME
*
next
,
TIME
*
start
,
int
i_value
,
interval_type
i_type
)
{
bool
ret
;
INTERVAL
interval
;
TIME
tmp
;
bzero
(
&
interval
,
sizeof
(
interval
));
switch
(
i_type
)
{
case
INTERVAL_YEAR
:
interval
.
year
=
(
ulong
)
i_value
;
break
;
case
INTERVAL_QUARTER
:
interval
.
month
=
(
ulong
)(
i_value
*
3
);
break
;
case
INTERVAL_YEAR_MONTH
:
case
INTERVAL_MONTH
:
interval
.
month
=
(
ulong
)
i_value
;
break
;
case
INTERVAL_WEEK
:
interval
.
day
=
(
ulong
)(
i_value
*
7
);
break
;
case
INTERVAL_DAY
:
interval
.
day
=
(
ulong
)
i_value
;
break
;
case
INTERVAL_DAY_HOUR
:
case
INTERVAL_HOUR
:
interval
.
hour
=
(
ulong
)
i_value
;
break
;
case
INTERVAL_DAY_MINUTE
:
case
INTERVAL_HOUR_MINUTE
:
case
INTERVAL_MINUTE
:
interval
.
minute
=
i_value
;
break
;
case
INTERVAL_DAY_SECOND
:
case
INTERVAL_HOUR_SECOND
:
case
INTERVAL_MINUTE_SECOND
:
case
INTERVAL_SECOND
:
interval
.
second
=
i_value
;
break
;
case
INTERVAL_DAY_MICROSECOND
:
case
INTERVAL_HOUR_MICROSECOND
:
case
INTERVAL_MINUTE_MICROSECOND
:
case
INTERVAL_SECOND_MICROSECOND
:
case
INTERVAL_MICROSECOND
:
interval
.
second_part
=
i_value
;
break
;
}
tmp
=
*
start
;
if
(
!
(
ret
=
date_add_interval
(
&
tmp
,
i_type
,
interval
)))
*
next
=
tmp
;
return
ret
;
}
/*
Computes next execution time.
SYNOPSIS
event_timed::compute_next_execution_time()
REMARKS:
The time is set in execute_at, if no more executions the latter is set to
0000-00-00.
*/
bool
...
...
@@ -605,14 +742,13 @@ event_timed::compute_next_execution_time()
execute_at
=
time_now
;
else
{
my_time_t
last
,
ll_ends
;
// There was previous execution
last
=
sec_since_epoch_TIME
(
&
last_executed
)
+
expression
;
ll_ends
=
sec_since_epoch_TIME
(
&
ends
);
//now convert back to TIME
//ToDo Andrey: maybe check for error here?
if
(
ll_ends
<
last
)
TIME
next_exec
;
if
(
get_next_time
(
&
next_exec
,
&
last_executed
,
expression
,
interval
))
goto
err
;
// There was previous execution
if
(
my_time_compare
(
&
ends
,
&
next_exec
)
==
-
1
)
{
// Next execution after ends. No more executions
set_zero_time
(
&
execute_at
,
MYSQL_TIMESTAMP_DATETIME
);
...
...
@@ -620,7 +756,7 @@ event_timed::compute_next_execution_time()
dropped
=
true
;
}
else
my_tz_UTC
->
gmt_sec_to_TIME
(
&
execute_at
,
last
)
;
execute_at
=
next_exec
;
}
goto
ret
;
}
...
...
@@ -628,14 +764,14 @@ event_timed::compute_next_execution_time()
{
// both starts and m_ends are not set, se we schedule for the next
// based on last_executed
if
(
!
last_executed
.
year
)
if
(
last_executed
.
year
)
{
if
(
get_next_time
(
&
execute_at
,
&
last_executed
,
expression
,
interval
))
goto
err
;
}
else
//last_executed not set. Schedule the event for now
execute_at
=
time_now
;
else
//ToDo Andrey: maybe check for error here?
my_tz_UTC
->
gmt_sec_to_TIME
(
&
execute_at
,
sec_since_epoch_TIME
(
&
last_executed
)
+
expression
);
goto
ret
;
}
else
{
...
...
@@ -648,17 +784,13 @@ event_timed::compute_next_execution_time()
Hence schedule for starts + m_expression in case last_executed
is not set, otherwise to last_executed + m_expression
*/
my_time_t
last
;
//convert either last_executed or starts to seconds
if
(
last_executed
.
year
)
last
=
sec_since_epoch_TIME
(
&
last_executed
)
+
expression
;
{
if
(
get_next_time
(
&
execute_at
,
&
last_executed
,
expression
,
interval
))
goto
err
;
}
else
last
=
sec_since_epoch_TIME
(
&
starts
);
//now convert back to TIME
//ToDo Andrey: maybe check for error here?
my_tz_UTC
->
gmt_sec_to_TIME
(
&
execute_at
,
last
);
execute_at
=
starts
;
}
else
{
...
...
@@ -668,25 +800,24 @@ event_timed::compute_next_execution_time()
Hence check for m_last_execute and increment with m_expression.
If last_executed is not set then schedule for now
*/
my_time_t
last
,
ll_ends
;
if
(
!
last_executed
.
year
)
execute_at
=
time_now
;
else
{
last
=
sec_since_epoch_TIME
(
&
last_executed
)
;
ll_ends
=
sec_since_epoch_TIME
(
&
ends
);
last
+=
expression
;
//now convert back to TIME
//ToDo Andrey: maybe check for error here?
if
(
ll_ends
<
last
)
TIME
next_exec
;
if
(
get_next_time
(
&
next_exec
,
&
last_executed
,
expression
,
interval
))
goto
err
;
if
(
my_time_compare
(
&
ends
,
&
next_exec
)
==
-
1
)
{
set_zero_time
(
&
execute_at
,
MYSQL_TIMESTAMP_DATETIME
);
if
(
on_completion
==
MYSQL_EVENT_ON_COMPLETION_DROP
)
dropped
=
true
;
}
else
my_tz_UTC
->
gmt_sec_to_TIME
(
&
execute_at
,
last
)
;
execute_at
=
next_exec
;
}
}
goto
ret
;
...
...
@@ -694,17 +825,18 @@ event_timed::compute_next_execution_time()
ret:
DBUG_RETURN
(
false
);
err:
DBUG_RETURN
(
true
);
}
void
event_timed
::
mark_last_executed
()
event_timed
::
mark_last_executed
(
THD
*
thd
)
{
TIME
time_now
;
my_time_t
now
;
t
ime
((
time_t
*
)
&
now
);
my_tz_UTC
->
gmt_sec_to_TIME
(
&
time_now
,
now
);
t
hd
->
end_time
(
);
my_tz_UTC
->
gmt_sec_to_TIME
(
&
time_now
,
(
my_time_t
)
thd
->
query_start
()
);
last_executed
=
time_now
;
// was execute_at
#ifdef ANDREY_0
...
...
sql/item_timefunc.cc
View file @
a6494fbe
...
...
@@ -1135,7 +1135,7 @@ longlong Item_func_time_to_sec::val_int()
To make code easy, allow interval objects without separators.
*/
static
bool
get_interval_value
(
Item
*
args
,
interval_type
int_type
,
bool
get_interval_value
(
Item
*
args
,
interval_type
int_type
,
String
*
str_value
,
INTERVAL
*
interval
)
{
ulonglong
array
[
5
];
...
...
@@ -1994,110 +1994,15 @@ bool Item_date_add_interval::get_date(TIME *ltime, uint fuzzy_date)
long
period
,
sign
;
INTERVAL
interval
;
ltime
->
neg
=
0
;
if
(
args
[
0
]
->
get_date
(
ltime
,
TIME_NO_ZERO_DATE
)
||
get_interval_value
(
args
[
1
],
int_type
,
&
value
,
&
interval
))
goto
null_date
;
sign
=
(
interval
.
neg
?
-
1
:
1
);
if
(
date_sub_interval
)
sign
=
-
sign
;
interval
.
neg
=
!
interval
.
neg
;
null_value
=
0
;
switch
(
int_type
)
{
case
INTERVAL_SECOND
:
case
INTERVAL_SECOND_MICROSECOND
:
case
INTERVAL_MICROSECOND
:
case
INTERVAL_MINUTE
:
case
INTERVAL_HOUR
:
case
INTERVAL_MINUTE_MICROSECOND
:
case
INTERVAL_MINUTE_SECOND
:
case
INTERVAL_HOUR_MICROSECOND
:
case
INTERVAL_HOUR_SECOND
:
case
INTERVAL_HOUR_MINUTE
:
case
INTERVAL_DAY_MICROSECOND
:
case
INTERVAL_DAY_SECOND
:
case
INTERVAL_DAY_MINUTE
:
case
INTERVAL_DAY_HOUR
:
{
longlong
sec
,
days
,
daynr
,
microseconds
,
extra_sec
;
ltime
->
time_type
=
MYSQL_TIMESTAMP_DATETIME
;
// Return full date
microseconds
=
ltime
->
second_part
+
sign
*
interval
.
second_part
;
extra_sec
=
microseconds
/
1000000L
;
microseconds
=
microseconds
%
1000000L
;
sec
=
((
ltime
->
day
-
1
)
*
3600
*
24L
+
ltime
->
hour
*
3600
+
ltime
->
minute
*
60
+
ltime
->
second
+
sign
*
(
longlong
)
(
interval
.
day
*
3600
*
24L
+
interval
.
hour
*
LL
(
3600
)
+
interval
.
minute
*
LL
(
60
)
+
interval
.
second
))
+
extra_sec
;
if
(
microseconds
<
0
)
{
microseconds
+=
LL
(
1000000
);
sec
--
;
}
days
=
sec
/
(
3600
*
LL
(
24
));
sec
-=
days
*
3600
*
LL
(
24
);
if
(
sec
<
0
)
{
days
--
;
sec
+=
3600
*
LL
(
24
);
}
ltime
->
second_part
=
(
uint
)
microseconds
;
ltime
->
second
=
(
uint
)
(
sec
%
60
);
ltime
->
minute
=
(
uint
)
(
sec
/
60
%
60
);
ltime
->
hour
=
(
uint
)
(
sec
/
3600
);
daynr
=
calc_daynr
(
ltime
->
year
,
ltime
->
month
,
1
)
+
days
;
/* Day number from year 0 to 9999-12-31 */
if
((
ulonglong
)
daynr
>=
MAX_DAY_NUMBER
)
goto
invalid_date
;
get_date_from_daynr
((
long
)
daynr
,
&
ltime
->
year
,
&
ltime
->
month
,
&
ltime
->
day
);
break
;
}
case
INTERVAL_DAY
:
case
INTERVAL_WEEK
:
period
=
(
calc_daynr
(
ltime
->
year
,
ltime
->
month
,
ltime
->
day
)
+
sign
*
(
long
)
interval
.
day
);
/* Daynumber from year 0 to 9999-12-31 */
if
((
ulong
)
period
>=
MAX_DAY_NUMBER
)
goto
invalid_date
;
get_date_from_daynr
((
long
)
period
,
&
ltime
->
year
,
&
ltime
->
month
,
&
ltime
->
day
);
break
;
case
INTERVAL_YEAR
:
ltime
->
year
+=
sign
*
(
long
)
interval
.
year
;
if
((
ulong
)
ltime
->
year
>=
10000L
)
goto
invalid_date
;
if
(
ltime
->
month
==
2
&&
ltime
->
day
==
29
&&
calc_days_in_year
(
ltime
->
year
)
!=
366
)
ltime
->
day
=
28
;
// Was leap-year
break
;
case
INTERVAL_YEAR_MONTH
:
case
INTERVAL_QUARTER
:
case
INTERVAL_MONTH
:
period
=
(
ltime
->
year
*
12
+
sign
*
(
long
)
interval
.
year
*
12
+
ltime
->
month
-
1
+
sign
*
(
long
)
interval
.
month
);
if
((
ulong
)
period
>=
120000L
)
goto
invalid_date
;
ltime
->
year
=
(
uint
)
(
period
/
12
);
ltime
->
month
=
(
uint
)
(
period
%
12L
)
+
1
;
/* Adjust day if the new month doesn't have enough days */
if
(
ltime
->
day
>
days_in_month
[
ltime
->
month
-
1
])
{
ltime
->
day
=
days_in_month
[
ltime
->
month
-
1
];
if
(
ltime
->
month
==
2
&&
calc_days_in_year
(
ltime
->
year
)
==
366
)
ltime
->
day
++
;
// Leap-year
}
break
;
default:
goto
null_date
;
}
return
0
;
// Ok
return
(
null_value
=
date_add_interval
(
ltime
,
int_type
,
interval
));
invalid_date:
push_warning_printf
(
current_thd
,
MYSQL_ERROR
::
WARN_LEVEL_WARN
,
ER_DATETIME_FUNCTION_OVERFLOW
,
ER
(
ER_DATETIME_FUNCTION_OVERFLOW
),
"datetime"
);
null_date:
return
(
null_value
=
1
);
}
...
...
sql/item_timefunc.h
View file @
a6494fbe
...
...
@@ -26,6 +26,9 @@ 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
,
String
*
str_value
,
INTERVAL
*
interval
);
class
Item_func_period_add
:
public
Item_int_func
{
public:
...
...
@@ -626,20 +629,6 @@ public:
}
};
/*
The following must be sorted so that simple intervals comes first.
(get_interval_value() depends on this)
*/
enum
interval_type
{
INTERVAL_YEAR
,
INTERVAL_QUARTER
,
INTERVAL_MONTH
,
INTERVAL_DAY
,
INTERVAL_HOUR
,
INTERVAL_MINUTE
,
INTERVAL_WEEK
,
INTERVAL_SECOND
,
INTERVAL_MICROSECOND
,
INTERVAL_YEAR_MONTH
,
INTERVAL_DAY_HOUR
,
INTERVAL_DAY_MINUTE
,
INTERVAL_DAY_SECOND
,
INTERVAL_HOUR_MINUTE
,
INTERVAL_HOUR_SECOND
,
INTERVAL_MINUTE_SECOND
,
INTERVAL_DAY_MICROSECOND
,
INTERVAL_HOUR_MICROSECOND
,
INTERVAL_MINUTE_MICROSECOND
,
INTERVAL_SECOND_MICROSECOND
};
class
Item_date_add_interval
:
public
Item_date_func
{
...
...
sql/mysql_priv.h
View file @
a6494fbe
...
...
@@ -1532,6 +1532,9 @@ void calc_time_from_sec(TIME *to, long seconds, long microseconds);
void
make_truncated_value_warning
(
THD
*
thd
,
const
char
*
str_val
,
uint
str_length
,
timestamp_type
time_type
,
const
char
*
field_name
);
bool
date_add_interval
(
TIME
*
ltime
,
interval_type
int_type
,
INTERVAL
interval
);
extern
DATE_TIME_FORMAT
*
date_time_format_make
(
timestamp_type
format_type
,
const
char
*
format_str
,
uint
format_length
);
...
...
sql/share/errmsg.txt
View file @
a6494fbe
...
...
@@ -5769,8 +5769,8 @@ ER_EVENT_CANT_ALTER
eng "Failed to alter event '%-.64s'"
ER_EVENT_DROP_FAILED
eng "Failed to drop %s"
ER_EVENT_INTERVAL_NOT_POSITIVE
eng "INTERVAL
must be positive
"
ER_EVENT_INTERVAL_NOT_POSITIVE
_OR_TOO_BIG
eng "INTERVAL
is either not positive or too big
"
ER_EVENT_ENDS_BEFORE_STARTS
eng "ENDS must be after STARTS"
ER_EVENT_EXEC_TIME_IN_THE_PAST
...
...
sql/sql_yacc.yy
View file @
a6494fbe
...
...
@@ -1418,7 +1418,7 @@ ev_schedule_time: EVERY_SYM expr interval
YYABORT;
break;
case EVEX_BAD_PARAMS:
my_error(ER_EVENT_INTERVAL_NOT_POSITIVE, MYF(0));
my_error(ER_EVENT_INTERVAL_NOT_POSITIVE
_OR_TOO_BIG
, MYF(0));
YYABORT;
break;
}
...
...
sql/time.cc
View file @
a6494fbe
...
...
@@ -724,5 +724,113 @@ void make_truncated_value_warning(THD *thd, const char *str_val,
ER_TRUNCATED_WRONG_VALUE
,
warn_buff
);
}
#define MAX_DAY_NUMBER 3652424L
bool
date_add_interval
(
TIME
*
ltime
,
interval_type
int_type
,
INTERVAL
interval
)
{
long
period
,
sign
;
ltime
->
neg
=
0
;
sign
=
(
interval
.
neg
?
-
1
:
1
);
switch
(
int_type
)
{
case
INTERVAL_SECOND
:
case
INTERVAL_SECOND_MICROSECOND
:
case
INTERVAL_MICROSECOND
:
case
INTERVAL_MINUTE
:
case
INTERVAL_HOUR
:
case
INTERVAL_MINUTE_MICROSECOND
:
case
INTERVAL_MINUTE_SECOND
:
case
INTERVAL_HOUR_MICROSECOND
:
case
INTERVAL_HOUR_SECOND
:
case
INTERVAL_HOUR_MINUTE
:
case
INTERVAL_DAY_MICROSECOND
:
case
INTERVAL_DAY_SECOND
:
case
INTERVAL_DAY_MINUTE
:
case
INTERVAL_DAY_HOUR
:
{
longlong
sec
,
days
,
daynr
,
microseconds
,
extra_sec
;
ltime
->
time_type
=
MYSQL_TIMESTAMP_DATETIME
;
// Return full date
microseconds
=
ltime
->
second_part
+
sign
*
interval
.
second_part
;
extra_sec
=
microseconds
/
1000000L
;
microseconds
=
microseconds
%
1000000L
;
sec
=
((
ltime
->
day
-
1
)
*
3600
*
24L
+
ltime
->
hour
*
3600
+
ltime
->
minute
*
60
+
ltime
->
second
+
sign
*
(
longlong
)
(
interval
.
day
*
3600
*
24L
+
interval
.
hour
*
LL
(
3600
)
+
interval
.
minute
*
LL
(
60
)
+
interval
.
second
))
+
extra_sec
;
if
(
microseconds
<
0
)
{
microseconds
+=
LL
(
1000000
);
sec
--
;
}
days
=
sec
/
(
3600
*
LL
(
24
));
sec
-=
days
*
3600
*
LL
(
24
);
if
(
sec
<
0
)
{
days
--
;
sec
+=
3600
*
LL
(
24
);
}
ltime
->
second_part
=
(
uint
)
microseconds
;
ltime
->
second
=
(
uint
)
(
sec
%
60
);
ltime
->
minute
=
(
uint
)
(
sec
/
60
%
60
);
ltime
->
hour
=
(
uint
)
(
sec
/
3600
);
daynr
=
calc_daynr
(
ltime
->
year
,
ltime
->
month
,
1
)
+
days
;
/* Day number from year 0 to 9999-12-31 */
if
((
ulonglong
)
daynr
>=
MAX_DAY_NUMBER
)
goto
invalid_date
;
get_date_from_daynr
((
long
)
daynr
,
&
ltime
->
year
,
&
ltime
->
month
,
&
ltime
->
day
);
break
;
}
case
INTERVAL_DAY
:
case
INTERVAL_WEEK
:
period
=
(
calc_daynr
(
ltime
->
year
,
ltime
->
month
,
ltime
->
day
)
+
sign
*
(
long
)
interval
.
day
);
/* Daynumber from year 0 to 9999-12-31 */
if
((
ulong
)
period
>=
MAX_DAY_NUMBER
)
goto
invalid_date
;
get_date_from_daynr
((
long
)
period
,
&
ltime
->
year
,
&
ltime
->
month
,
&
ltime
->
day
);
break
;
case
INTERVAL_YEAR
:
ltime
->
year
+=
sign
*
(
long
)
interval
.
year
;
if
((
ulong
)
ltime
->
year
>=
10000L
)
goto
invalid_date
;
if
(
ltime
->
month
==
2
&&
ltime
->
day
==
29
&&
calc_days_in_year
(
ltime
->
year
)
!=
366
)
ltime
->
day
=
28
;
// Was leap-year
break
;
case
INTERVAL_YEAR_MONTH
:
case
INTERVAL_QUARTER
:
case
INTERVAL_MONTH
:
period
=
(
ltime
->
year
*
12
+
sign
*
(
long
)
interval
.
year
*
12
+
ltime
->
month
-
1
+
sign
*
(
long
)
interval
.
month
);
if
((
ulong
)
period
>=
120000L
)
goto
invalid_date
;
ltime
->
year
=
(
uint
)
(
period
/
12
);
ltime
->
month
=
(
uint
)
(
period
%
12L
)
+
1
;
/* Adjust day if the new month doesn't have enough days */
if
(
ltime
->
day
>
days_in_month
[
ltime
->
month
-
1
])
{
ltime
->
day
=
days_in_month
[
ltime
->
month
-
1
];
if
(
ltime
->
month
==
2
&&
calc_days_in_year
(
ltime
->
year
)
==
366
)
ltime
->
day
++
;
// Leap-year
}
break
;
default:
return
1
;
}
return
0
;
// Ok
invalid_date:
push_warning_printf
(
current_thd
,
MYSQL_ERROR
::
WARN_LEVEL_WARN
,
ER_DATETIME_FUNCTION_OVERFLOW
,
ER
(
ER_DATETIME_FUNCTION_OVERFLOW
),
"datetime"
);
return
1
;
}
#endif
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