summaryrefslogtreecommitdiff
path: root/sql/partition_info.cc
diff options
context:
space:
mode:
authorAleksey Midenkov <midenok@gmail.com>2019-11-07 19:21:42 +0300
committerAleksey Midenkov <midenok@gmail.com>2019-11-07 19:24:06 +0300
commit1e73d7d6c658e881ec50d3b968647b2b45605a19 (patch)
tree2d5e7ca68ea2a3dc31fc8e1b79117fec17af0034 /sql/partition_info.cc
parent77e8a311e1f919f15845c75d08de4340965c0bc4 (diff)
downloadmariadb-git-1e73d7d6c658e881ec50d3b968647b2b45605a19.tar.gz
MDEV-17553 Enable setting start datetime for interval partitioned history of system versioned tables
* Explicit STARTS syntax * SHOW CREATE * Default STARTS rounding depending on INTERVAL type * Warn when STARTS timestamp is later than query time * Fix uninitialized Lex->create_last_non_select_table under mysql_unpack_partition() Default STARTS rounding depending on INTERVAL type If STARTS clause is omitted, default one is assigned with value derived from query timestamp. The rounding is done on STARTS value depending on INTERVAL type: SECOND: no rounding is done; MINUTE: timestamp seconds is set to 0; HOUR: timestamp seconds and minutes are set to 0; DAY, WEEK, MONTH and YEAR: timestamp seconds, minutes and hours are set to 0 (the date of rotation is kept as current date).
Diffstat (limited to 'sql/partition_info.cc')
-rw-r--r--sql/partition_info.cc113
1 files changed, 105 insertions, 8 deletions
diff --git a/sql/partition_info.cc b/sql/partition_info.cc
index 38e085b3be9..f1c4fb52e83 100644
--- a/sql/partition_info.cc
+++ b/sql/partition_info.cc
@@ -851,8 +851,13 @@ void partition_info::vers_set_hist_part(THD *thd)
if (records > vers_info->limit)
{
if (next == vers_info->now_part)
- goto warn;
- vers_info->hist_part= next;
+ {
+ my_error(WARN_VERS_PART_FULL, MYF(ME_WARNING|ME_ERROR_LOG),
+ table->s->db.str, table->s->table_name.str,
+ vers_info->hist_part->partition_name, "LIMIT");
+ }
+ else
+ vers_info->hist_part= next;
}
return;
}
@@ -873,13 +878,10 @@ void partition_info::vers_set_hist_part(THD *thd)
if (next->range_value > thd->query_start())
return;
}
- goto warn;
+ my_error(WARN_VERS_PART_FULL, MYF(ME_WARNING|ME_ERROR_LOG),
+ table->s->db.str, table->s->table_name.str,
+ vers_info->hist_part->partition_name, "INTERVAL");
}
- return;
-warn:
- my_error(WARN_VERS_PART_FULL, MYF(ME_WARNING|ME_ERROR_LOG),
- table->s->db.str, table->s->table_name.str,
- vers_info->hist_part->partition_name);
}
@@ -2371,6 +2373,101 @@ static bool strcmp_null(const char *a, const char *b)
return true;
}
+/**
+ Assign INTERVAL and STARTS for SYSTEM_TIME partitions.
+
+ @return true on error
+*/
+
+bool partition_info::vers_set_interval(THD* thd, Item* interval,
+ interval_type int_type, Item* starts,
+ const char *table_name)
+{
+ DBUG_ASSERT(part_type == VERSIONING_PARTITION);
+
+ MYSQL_TIME ltime;
+ uint err;
+ vers_info->interval.type= int_type;
+
+ /* 1. assign INTERVAL to interval.step */
+ if (interval->fix_fields_if_needed_for_scalar(thd, &interval))
+ return true;
+ bool error= get_interval_value(thd, interval, int_type, &vers_info->interval.step) ||
+ vers_info->interval.step.neg || vers_info->interval.step.second_part ||
+ !(vers_info->interval.step.year || vers_info->interval.step.month ||
+ vers_info->interval.step.day || vers_info->interval.step.hour ||
+ vers_info->interval.step.minute || vers_info->interval.step.second);
+ if (error)
+ {
+ my_error(ER_PART_WRONG_VALUE, MYF(0), table_name, "INTERVAL");
+ return true;
+ }
+
+ /* 2. assign STARTS to interval.start */
+ if (starts)
+ {
+ if (starts->fix_fields_if_needed_for_scalar(thd, &starts))
+ return true;
+ switch (starts->result_type())
+ {
+ case INT_RESULT:
+ case DECIMAL_RESULT:
+ case REAL_RESULT:
+ /* When table member is defined, we are inside mysql_unpack_partition(). */
+ if (!table || starts->val_int() > TIMESTAMP_MAX_VALUE)
+ goto interval_starts_error;
+ vers_info->interval.start= (my_time_t) starts->val_int();
+ break;
+ case STRING_RESULT:
+ case TIME_RESULT:
+ {
+ Datetime::Options opt(TIME_NO_ZERO_DATE | TIME_NO_ZERO_IN_DATE, thd);
+ starts->get_date(thd, &ltime, opt);
+ vers_info->interval.start= TIME_to_timestamp(thd, &ltime, &err);
+ if (err)
+ goto interval_starts_error;
+ break;
+ }
+ case ROW_RESULT:
+ default:
+ goto interval_starts_error;
+ }
+ if (!table)
+ {
+ if (thd->query_start() < vers_info->interval.start) {
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_PART_STARTS_BEYOND_INTERVAL,
+ ER_THD(thd, ER_PART_STARTS_BEYOND_INTERVAL),
+ table_name);
+ }
+ }
+ }
+ else // calculate default STARTS depending on INTERVAL
+ {
+ thd->variables.time_zone->gmt_sec_to_TIME(&ltime, thd->query_start());
+ if (vers_info->interval.step.second)
+ goto interval_set_starts;
+ ltime.second= 0;
+ if (vers_info->interval.step.minute)
+ goto interval_set_starts;
+ ltime.minute= 0;
+ if (vers_info->interval.step.hour)
+ goto interval_set_starts;
+ ltime.hour= 0;
+
+interval_set_starts:
+ vers_info->interval.start= TIME_to_timestamp(thd, &ltime, &err);
+ if (err)
+ goto interval_starts_error;
+ }
+
+ return false;
+
+interval_starts_error:
+ my_error(ER_PART_WRONG_VALUE, MYF(0), table_name, "STARTS");
+ return true;
+}
+
/**
Check if the new part_info has the same partitioning.