Loading mysql-test/r/row.result +18 −0 Original line number Diff line number Diff line Loading @@ -175,6 +175,24 @@ ROW(2,10) <=> ROW(3,4) SELECT ROW(NULL,10) <=> ROW(3,NULL); ROW(NULL,10) <=> ROW(3,NULL) 0 SELECT ROW(1,ROW(2,3)) IN (ROW(1,ROW(2,3)),ROW(1,1)); ERROR 21000: Operand should contain 2 column(s) SELECT ROW(1,ROW(2,3)) IN (ROW(1,ROW(2,3)),ROW(1,1),ROW(1,ROW(2,3))); ERROR 21000: Operand should contain 2 column(s) SELECT ROW(1,ROW(2,3)) IN (ROW(1,ROW(2,3)),ROW(1,ROW(2,2,2))); ERROR 21000: Operand should contain 2 column(s) SELECT ROW(1,ROW(2,3,4)) IN (ROW(1,ROW(2,3,4)),ROW(1,ROW(2,2))); ERROR 21000: Operand should contain 3 column(s) SELECT ROW(1,ROW(2,3)) IN (ROW(1,ROW(2,3)),(SELECT 1,1)); ERROR 21000: Operand should contain 2 column(s) SELECT ROW(1,ROW(2,3)) IN (ROW(1,ROW(2,3)),(SELECT 1,1),ROW(1,ROW(2,4))); ERROR 21000: Operand should contain 2 column(s) SELECT ROW(1,ROW(2,3)) IN ((SELECT 1,1),ROW(1,ROW(2,3))); ERROR 21000: Operand should contain 2 column(s) SELECT ROW(2,1) IN (ROW(21,2),ROW(ROW(1,1,3),0)); ERROR 21000: Operand should contain 1 column(s) SELECT ROW(2,1) IN (ROW(ROW(1,1,3),0),ROW(21,2)); ERROR 21000: Operand should contain 1 column(s) SELECT ROW(1,1,1) = ROW(1,1,1) as `1`, ROW(1,1,1) = ROW(1,2,1) as `0`, ROW(1,NULL,1) = ROW(2,2,1) as `0`, ROW(1,NULL,1) = ROW(1,2,2) as `0`, ROW(1,NULL,1) = ROW(1,2,1) as `null` ; 1 0 0 0 null 1 0 0 0 NULL Loading mysql-test/t/row.test +25 −0 Original line number Diff line number Diff line Loading @@ -85,6 +85,31 @@ drop table t1; SELECT ROW(2,10) <=> ROW(3,4); SELECT ROW(NULL,10) <=> ROW(3,NULL); # # Bug #27484: nested row expressions in IN predicate # --error 1241 SELECT ROW(1,ROW(2,3)) IN (ROW(1,ROW(2,3)),ROW(1,1)); --error 1241 SELECT ROW(1,ROW(2,3)) IN (ROW(1,ROW(2,3)),ROW(1,1),ROW(1,ROW(2,3))); --error 1241 SELECT ROW(1,ROW(2,3)) IN (ROW(1,ROW(2,3)),ROW(1,ROW(2,2,2))); --error 1241 SELECT ROW(1,ROW(2,3,4)) IN (ROW(1,ROW(2,3,4)),ROW(1,ROW(2,2))); --error 1241 SELECT ROW(1,ROW(2,3)) IN (ROW(1,ROW(2,3)),(SELECT 1,1)); --error 1241 SELECT ROW(1,ROW(2,3)) IN (ROW(1,ROW(2,3)),(SELECT 1,1),ROW(1,ROW(2,4))); --error 1241 SELECT ROW(1,ROW(2,3)) IN ((SELECT 1,1),ROW(1,ROW(2,3))); --error 1241 SELECT ROW(2,1) IN (ROW(21,2),ROW(ROW(1,1,3),0)); --error 1241 SELECT ROW(2,1) IN (ROW(ROW(1,1,3),0),ROW(21,2)); # End of 4.1 tests # Loading sql/item_cmpfunc.cc +61 −4 Original line number Diff line number Diff line Loading @@ -68,6 +68,42 @@ static void agg_result_type(Item_result *type, Item **items, uint nitems) } /* Compare row signature of two expressions SYNOPSIS: cmp_row_type() item1 the first expression item2 the second expression DESCRIPTION The function checks that two expressions have compatible row signatures i.e. that the number of columns they return are the same and that if they are both row expressions then each component from the first expression has a row signature compatible with the signature of the corresponding component of the second expression. RETURN VALUES 1 type incompatibility has been detected 0 otherwise */ static int cmp_row_type(Item* item1, Item* item2) { uint n= item1->cols(); if (item2->check_cols(n)) return 1; for (uint i=0; i<n; i++) { if (item2->element_index(i)->check_cols(item1->element_index(i)->cols()) || (item1->element_index(i)->result_type() == ROW_RESULT && cmp_row_type(item1->element_index(i), item2->element_index(i)))) return 1; } return 0; } /* Aggregates result types from the array of items. Loading @@ -82,14 +118,32 @@ static void agg_result_type(Item_result *type, Item **items, uint nitems) This function aggregates result types from the array of items. Found type supposed to be used later for comparison of values of these items. Aggregation itself is performed by the item_cmp_type() function. The function also checks compatibility of row signatures for the submitted items (see the spec for the cmp_row_type function). RETURN VALUES 1 type incompatibility has been detected 0 otherwise */ static void agg_cmp_type(THD *thd, Item_result *type, Item **items, uint nitems) static int agg_cmp_type(THD *thd, Item_result *type, Item **items, uint nitems) { uint i; type[0]= items[0]->result_type(); for (i= 1 ; i < nitems ; i++) { type[0]= item_cmp_type(type[0], items[i]->result_type()); /* When aggregating types of two row expressions we have to check that they have the same cardinality and that each component of the first row expression has a compatible row signature with the signature of the corresponding component of the second row expression. */ if (type[0] == ROW_RESULT && cmp_row_type(items[0], items[i])) return 1; // error found: invalid usage of rows } return 0; } Loading Loading @@ -1305,7 +1359,8 @@ void Item_func_between::fix_length_and_dec() */ if (!args[0] || !args[1] || !args[2]) return; agg_cmp_type(thd, &cmp_type, args, 3); if ( agg_cmp_type(thd, &cmp_type, args, 3)) return; if (cmp_type == STRING_RESULT && agg_arg_charsets(cmp_collation, args, 3, MY_COLL_CMP_CONV, 1)) return; Loading Loading @@ -2021,7 +2076,8 @@ void Item_func_case::fix_length_and_dec() for (nagg= 0; nagg < ncases/2 ; nagg++) agg[nagg+1]= args[nagg*2]; nagg++; agg_cmp_type(thd, &cmp_type, agg, nagg); if (agg_cmp_type(thd, &cmp_type, agg, nagg)) return; if ((cmp_type == STRING_RESULT) && agg_arg_charsets(cmp_collation, agg, nagg, MY_COLL_CMP_CONV, 1)) return; Loading Loading @@ -2710,7 +2766,8 @@ void Item_func_in::fix_length_and_dec() uint const_itm= 1; THD *thd= current_thd; agg_cmp_type(thd, &cmp_type, args, arg_count); if (agg_cmp_type(thd, &cmp_type, args, arg_count)) return; if (cmp_type == STRING_RESULT && agg_arg_charsets(cmp_collation, args, arg_count, MY_COLL_CMP_CONV, 1)) Loading Loading
mysql-test/r/row.result +18 −0 Original line number Diff line number Diff line Loading @@ -175,6 +175,24 @@ ROW(2,10) <=> ROW(3,4) SELECT ROW(NULL,10) <=> ROW(3,NULL); ROW(NULL,10) <=> ROW(3,NULL) 0 SELECT ROW(1,ROW(2,3)) IN (ROW(1,ROW(2,3)),ROW(1,1)); ERROR 21000: Operand should contain 2 column(s) SELECT ROW(1,ROW(2,3)) IN (ROW(1,ROW(2,3)),ROW(1,1),ROW(1,ROW(2,3))); ERROR 21000: Operand should contain 2 column(s) SELECT ROW(1,ROW(2,3)) IN (ROW(1,ROW(2,3)),ROW(1,ROW(2,2,2))); ERROR 21000: Operand should contain 2 column(s) SELECT ROW(1,ROW(2,3,4)) IN (ROW(1,ROW(2,3,4)),ROW(1,ROW(2,2))); ERROR 21000: Operand should contain 3 column(s) SELECT ROW(1,ROW(2,3)) IN (ROW(1,ROW(2,3)),(SELECT 1,1)); ERROR 21000: Operand should contain 2 column(s) SELECT ROW(1,ROW(2,3)) IN (ROW(1,ROW(2,3)),(SELECT 1,1),ROW(1,ROW(2,4))); ERROR 21000: Operand should contain 2 column(s) SELECT ROW(1,ROW(2,3)) IN ((SELECT 1,1),ROW(1,ROW(2,3))); ERROR 21000: Operand should contain 2 column(s) SELECT ROW(2,1) IN (ROW(21,2),ROW(ROW(1,1,3),0)); ERROR 21000: Operand should contain 1 column(s) SELECT ROW(2,1) IN (ROW(ROW(1,1,3),0),ROW(21,2)); ERROR 21000: Operand should contain 1 column(s) SELECT ROW(1,1,1) = ROW(1,1,1) as `1`, ROW(1,1,1) = ROW(1,2,1) as `0`, ROW(1,NULL,1) = ROW(2,2,1) as `0`, ROW(1,NULL,1) = ROW(1,2,2) as `0`, ROW(1,NULL,1) = ROW(1,2,1) as `null` ; 1 0 0 0 null 1 0 0 0 NULL Loading
mysql-test/t/row.test +25 −0 Original line number Diff line number Diff line Loading @@ -85,6 +85,31 @@ drop table t1; SELECT ROW(2,10) <=> ROW(3,4); SELECT ROW(NULL,10) <=> ROW(3,NULL); # # Bug #27484: nested row expressions in IN predicate # --error 1241 SELECT ROW(1,ROW(2,3)) IN (ROW(1,ROW(2,3)),ROW(1,1)); --error 1241 SELECT ROW(1,ROW(2,3)) IN (ROW(1,ROW(2,3)),ROW(1,1),ROW(1,ROW(2,3))); --error 1241 SELECT ROW(1,ROW(2,3)) IN (ROW(1,ROW(2,3)),ROW(1,ROW(2,2,2))); --error 1241 SELECT ROW(1,ROW(2,3,4)) IN (ROW(1,ROW(2,3,4)),ROW(1,ROW(2,2))); --error 1241 SELECT ROW(1,ROW(2,3)) IN (ROW(1,ROW(2,3)),(SELECT 1,1)); --error 1241 SELECT ROW(1,ROW(2,3)) IN (ROW(1,ROW(2,3)),(SELECT 1,1),ROW(1,ROW(2,4))); --error 1241 SELECT ROW(1,ROW(2,3)) IN ((SELECT 1,1),ROW(1,ROW(2,3))); --error 1241 SELECT ROW(2,1) IN (ROW(21,2),ROW(ROW(1,1,3),0)); --error 1241 SELECT ROW(2,1) IN (ROW(ROW(1,1,3),0),ROW(21,2)); # End of 4.1 tests # Loading
sql/item_cmpfunc.cc +61 −4 Original line number Diff line number Diff line Loading @@ -68,6 +68,42 @@ static void agg_result_type(Item_result *type, Item **items, uint nitems) } /* Compare row signature of two expressions SYNOPSIS: cmp_row_type() item1 the first expression item2 the second expression DESCRIPTION The function checks that two expressions have compatible row signatures i.e. that the number of columns they return are the same and that if they are both row expressions then each component from the first expression has a row signature compatible with the signature of the corresponding component of the second expression. RETURN VALUES 1 type incompatibility has been detected 0 otherwise */ static int cmp_row_type(Item* item1, Item* item2) { uint n= item1->cols(); if (item2->check_cols(n)) return 1; for (uint i=0; i<n; i++) { if (item2->element_index(i)->check_cols(item1->element_index(i)->cols()) || (item1->element_index(i)->result_type() == ROW_RESULT && cmp_row_type(item1->element_index(i), item2->element_index(i)))) return 1; } return 0; } /* Aggregates result types from the array of items. Loading @@ -82,14 +118,32 @@ static void agg_result_type(Item_result *type, Item **items, uint nitems) This function aggregates result types from the array of items. Found type supposed to be used later for comparison of values of these items. Aggregation itself is performed by the item_cmp_type() function. The function also checks compatibility of row signatures for the submitted items (see the spec for the cmp_row_type function). RETURN VALUES 1 type incompatibility has been detected 0 otherwise */ static void agg_cmp_type(THD *thd, Item_result *type, Item **items, uint nitems) static int agg_cmp_type(THD *thd, Item_result *type, Item **items, uint nitems) { uint i; type[0]= items[0]->result_type(); for (i= 1 ; i < nitems ; i++) { type[0]= item_cmp_type(type[0], items[i]->result_type()); /* When aggregating types of two row expressions we have to check that they have the same cardinality and that each component of the first row expression has a compatible row signature with the signature of the corresponding component of the second row expression. */ if (type[0] == ROW_RESULT && cmp_row_type(items[0], items[i])) return 1; // error found: invalid usage of rows } return 0; } Loading Loading @@ -1305,7 +1359,8 @@ void Item_func_between::fix_length_and_dec() */ if (!args[0] || !args[1] || !args[2]) return; agg_cmp_type(thd, &cmp_type, args, 3); if ( agg_cmp_type(thd, &cmp_type, args, 3)) return; if (cmp_type == STRING_RESULT && agg_arg_charsets(cmp_collation, args, 3, MY_COLL_CMP_CONV, 1)) return; Loading Loading @@ -2021,7 +2076,8 @@ void Item_func_case::fix_length_and_dec() for (nagg= 0; nagg < ncases/2 ; nagg++) agg[nagg+1]= args[nagg*2]; nagg++; agg_cmp_type(thd, &cmp_type, agg, nagg); if (agg_cmp_type(thd, &cmp_type, agg, nagg)) return; if ((cmp_type == STRING_RESULT) && agg_arg_charsets(cmp_collation, agg, nagg, MY_COLL_CMP_CONV, 1)) return; Loading Loading @@ -2710,7 +2766,8 @@ void Item_func_in::fix_length_and_dec() uint const_itm= 1; THD *thd= current_thd; agg_cmp_type(thd, &cmp_type, args, arg_count); if (agg_cmp_type(thd, &cmp_type, args, arg_count)) return; if (cmp_type == STRING_RESULT && agg_arg_charsets(cmp_collation, args, arg_count, MY_COLL_CMP_CONV, 1)) Loading