summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorMattias Jonsson <mattias.jonsson@oracle.com>2010-08-30 17:33:55 +0200
committerMattias Jonsson <mattias.jonsson@oracle.com>2010-08-30 17:33:55 +0200
commit86327002fe29e70f0e29d97e0cf0b1e14806c2f8 (patch)
tree95c1677d57c85cadeb341aee06221cfbe98753ec /sql
parent1ed02deea0986ee2aefd7b8bc61390f3675c2e94 (diff)
downloadmariadb-git-86327002fe29e70f0e29d97e0cf0b1e14806c2f8.tar.gz
Bug#50036: Inconsistent errors when using TIMESTAMP columns/expressions
It was hard to understand what the error really meant. The error checking in partitioning is done in several different parts during the execution of a query which can make it hard to return useful errors. Added a new error for bad VALUES part in the per PARTITION clause. Using the more verbose error that a column is not allowed in the partitioning function instead of just that the function is not allowed. mysql-test/r/partition.result: changed error to be more specific mysql-test/r/partition_error.result: updated result mysql-test/std_data/parts/t1TIMESTAMP.frm: .frm file of CREATE TABLE t1 (a TIMESTAMP) PARTITION BY HASH(TO_DAYS(a)); mysql-test/t/partition.test: changed error to be more specific mysql-test/t/partition_error.test: Added test (also for verifying behaviour of previously created tables which is no longer allowed). Updated expected errors in other places sql/partition_info.cc: Added function report_part_expr_error to be able to return a more specific error. Renamed fix_func_partition to fix_partition_values since the function really fixes/checks the VALUES clause. sql/partition_info.h: removed part_result_type, since it was unused. renamed fix_funk_partition->fix_partition_values added report_part_expr_error sql/share/errmsg-utf8.txt: Added a more specific error. sql/sql_partition.cc: made use of report_part_expr_error to get a more specific error. sql/sql_yacc.yy: Changed error message to be more specific. And return an other error code.
Diffstat (limited to 'sql')
-rw-r--r--sql/partition_info.cc66
-rw-r--r--sql/partition_info.h11
-rw-r--r--sql/share/errmsg-utf8.txt4
-rw-r--r--sql/sql_partition.cc18
-rw-r--r--sql/sql_yacc.yy2
5 files changed, 76 insertions, 25 deletions
diff --git a/sql/partition_info.cc b/sql/partition_info.cc
index caf28fdd83e..879e7b10023 100644
--- a/sql/partition_info.cc
+++ b/sql/partition_info.cc
@@ -742,7 +742,6 @@ bool partition_info::check_range_constants(THD *thd)
longlong part_range_value;
bool signed_flag= !part_expr->unsigned_flag;
- part_result_type= INT_RESULT;
range_int_array= (longlong*)sql_alloc(num_parts * sizeof(longlong));
if (unlikely(range_int_array == NULL))
{
@@ -917,7 +916,6 @@ bool partition_info::check_list_constants(THD *thd)
List_iterator<partition_element> list_func_it(partitions);
DBUG_ENTER("partition_info::check_list_constants");
- part_result_type= INT_RESULT;
num_list_values= 0;
/*
We begin by calculating the number of list values that have been
@@ -1608,6 +1606,52 @@ id_err:
return 1;
}
+
+/**
+ Check what kind of error to report
+
+ @param use_subpart_expr Use the subpart_expr instead of part_expr
+ @param part_str Name of partition to report error (or NULL)
+*/
+void partition_info::report_part_expr_error(bool use_subpart_expr)
+{
+ Item *expr= part_expr;
+ DBUG_ENTER("partition_info::report_part_expr_error");
+ if (use_subpart_expr)
+ expr= subpart_expr;
+
+ if (expr->type() == Item::FIELD_ITEM)
+ {
+ partition_type type= part_type;
+ bool list_of_fields= list_of_part_fields;
+ Item_field *item_field= (Item_field*) expr;
+ /*
+ The expression consists of a single field.
+ It must be of integer type unless KEY or COLUMNS partitioning.
+ */
+ if (use_subpart_expr)
+ {
+ type= subpart_type;
+ list_of_fields= list_of_subpart_fields;
+ }
+ if (!column_list &&
+ item_field->field &&
+ item_field->field->result_type() != INT_RESULT &&
+ !(type == HASH_PARTITION && list_of_fields))
+ {
+ my_error(ER_FIELD_TYPE_NOT_ALLOWED_AS_PARTITION_FIELD, MYF(0),
+ item_field->name);
+ DBUG_VOID_RETURN;
+ }
+ }
+ if (use_subpart_expr)
+ my_error(ER_PARTITION_FUNC_NOT_ALLOWED_ERROR, MYF(0), "SUBPARTITION");
+ else
+ my_error(ER_PARTITION_FUNC_NOT_ALLOWED_ERROR, MYF(0), "PARTITION");
+ DBUG_VOID_RETURN;
+}
+
+
/*
Create a new column value in current list with maxvalue
Called from parser
@@ -1891,7 +1935,7 @@ int partition_info::reorganize_into_single_field_col_val()
code.
SYNOPSIS
- fix_func_partition()
+ fix_partition_values()
thd Thread object
col_val Array of one value
part_elem The partition instance
@@ -1901,13 +1945,13 @@ int partition_info::reorganize_into_single_field_col_val()
TRUE Failure
FALSE Success
*/
-int partition_info::fix_func_partition(THD *thd,
- part_elem_value *val,
- partition_element *part_elem,
- uint part_id)
+int partition_info::fix_partition_values(THD *thd,
+ part_elem_value *val,
+ partition_element *part_elem,
+ uint part_id)
{
part_column_list_val *col_val= val->col_val_array;
- DBUG_ENTER("partition_info::fix_func_partition");
+ DBUG_ENTER("partition_info::fix_partition_values");
if (col_val->fixed)
{
@@ -1953,7 +1997,9 @@ int partition_info::fix_func_partition(THD *thd,
}
else if (item_expr->result_type() != INT_RESULT)
{
- my_error(ER_INCONSISTENT_TYPE_OF_FUNCTIONS_ERROR, MYF(0));
+ /* VALUES clause only allowed on partitions, not subpartitions */
+ my_error(ER_VALUES_IS_NOT_INT_TYPE_ERROR, MYF(0),
+ part_elem->partition_name);
DBUG_RETURN(TRUE);
}
if (part_type == RANGE_PARTITION)
@@ -2168,7 +2214,7 @@ int partition_info::fix_parser_data(THD *thd)
}
else
{
- if (fix_func_partition(thd, val, part_elem, i))
+ if (fix_partition_values(thd, val, part_elem, i))
{
DBUG_RETURN(TRUE);
}
diff --git a/sql/partition_info.h b/sql/partition_info.h
index b196d0b59a2..6ae210d9574 100644
--- a/sql/partition_info.h
+++ b/sql/partition_info.h
@@ -166,7 +166,6 @@ public:
key_map some_fields_in_PF;
handlerton *default_engine_type;
- Item_result part_result_type;
partition_type part_type;
partition_type subpart_type;
@@ -226,7 +225,6 @@ public:
curr_part_elem(NULL), current_partition(NULL),
curr_list_object(0), num_columns(0),
default_engine_type(NULL),
- part_result_type(INT_RESULT),
part_type(NOT_A_PARTITION), subpart_type(NOT_A_PARTITION),
part_info_len(0),
part_func_len(0), subpart_func_len(0),
@@ -279,10 +277,10 @@ public:
void print_no_partition_found(TABLE *table);
void print_debug(const char *str, uint*);
Item* get_column_item(Item *item, Field *field);
- int fix_func_partition(THD *thd,
- part_elem_value *val,
- partition_element *part_elem,
- uint part_id);
+ int fix_partition_values(THD *thd,
+ part_elem_value *val,
+ partition_element *part_elem,
+ uint part_id);
bool fix_column_value_functions(THD *thd,
part_elem_value *val,
uint part_id);
@@ -299,6 +297,7 @@ public:
bool init_column_part();
bool add_column_list_value(THD *thd, Item *item);
void set_show_version_string(String *packet);
+ void report_part_expr_error(bool use_subpart_expr);
private:
static int list_part_cmp(const void* a, const void* b);
bool set_up_default_partitions(handler *file, HA_CREATE_INFO *info,
diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt
index 9e7fdbfeae5..7b7f9024a63 100644
--- a/sql/share/errmsg-utf8.txt
+++ b/sql/share/errmsg-utf8.txt
@@ -6346,3 +6346,7 @@ ER_STORED_FUNCTION_PREVENTS_SWITCH_SQL_LOG_BIN
ER_FAILED_READ_FROM_PAR_FILE
eng "Failed to read from the .par file"
swe "Misslyckades läsa från .par filen"
+
+ER_VALUES_IS_NOT_INT_TYPE_ERROR
+ eng "VALUES value for partition '%-.64s' must have type INT"
+ swe "Värden i VALUES för partition '%-.64s' måste ha typen INT"
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc
index b72816f8ce3..d95ba3fa71e 100644
--- a/sql/sql_partition.cc
+++ b/sql/sql_partition.cc
@@ -1762,8 +1762,7 @@ bool fix_partition_func(THD *thd, TABLE *table,
goto end;
if (unlikely(part_info->subpart_expr->result_type() != INT_RESULT))
{
- my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0),
- subpart_str);
+ part_info->report_part_expr_error(TRUE);
goto end;
}
}
@@ -1790,10 +1789,9 @@ bool fix_partition_func(THD *thd, TABLE *table,
goto end;
if (unlikely(part_info->part_expr->result_type() != INT_RESULT))
{
- my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0), part_str);
+ part_info->report_part_expr_error(FALSE);
goto end;
}
- part_info->part_result_type= INT_RESULT;
}
part_info->fixed= TRUE;
}
@@ -1839,18 +1837,22 @@ bool fix_partition_func(THD *thd, TABLE *table,
if (unlikely(!part_info->column_list &&
part_info->part_expr->result_type() != INT_RESULT))
{
- my_error(ER_PARTITION_FUNC_NOT_ALLOWED_ERROR, MYF(0), part_str);
+ part_info->report_part_expr_error(FALSE);
goto end;
}
}
if (((part_info->part_type != HASH_PARTITION ||
- part_info->list_of_part_fields == FALSE) &&
- (!part_info->column_list &&
- check_part_func_fields(part_info->part_field_array, TRUE))) ||
+ part_info->list_of_part_fields == FALSE) &&
+ !part_info->column_list &&
+ check_part_func_fields(part_info->part_field_array, TRUE)) ||
(part_info->list_of_subpart_fields == FALSE &&
part_info->is_sub_partitioned() &&
check_part_func_fields(part_info->subpart_field_array, TRUE)))
{
+ /*
+ Range/List/HASH (but not KEY) and not COLUMNS or HASH subpartitioning
+ with columns in the partitioning expression using unallowed charset.
+ */
my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0));
goto end;
}
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 6a510c04054..70e7e21cef4 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -4813,7 +4813,7 @@ part_value_expr_item:
if (!lex->safe_to_cache_query)
{
- my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0));
+ my_parse_error(ER(ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR));
MYSQL_YYABORT;
}
if (part_info->add_column_list_value(YYTHD, part_expr))