From 54bc9c3d779e659f101f317d1925b7fd95064064 Mon Sep 17 00:00:00 2001
From: "gluh@mysql.com/eagle.(none)" <>
Date: Mon, 2 Apr 2007 15:01:19 +0500
Subject: [PATCH] Bug#27069 set with identical elements are created added the
 check for unique elements count in SET

---
 mysql-test/r/type_set.result | 19 +++++++++++++++++++
 mysql-test/t/type_set.test   | 17 +++++++++++++++++
 sql/field.cc                 |  5 -----
 sql/sql_table.cc             | 16 +++++++++++++---
 4 files changed, 49 insertions(+), 8 deletions(-)

diff --git a/mysql-test/r/type_set.result b/mysql-test/r/type_set.result
index fdda4aca25c..03de20baef2 100644
--- a/mysql-test/r/type_set.result
+++ b/mysql-test/r/type_set.result
@@ -66,3 +66,22 @@ ss
 ue
 ue
 DROP TABLE t1;
+create table t1(f1
+set('1','2','3','4','5','6','7','8','9','10','11','12','13','14','15','16','17',
+'18','19','20','21','22','23','24','25','26','27','28','29','30','31','32','33',
+'34','35','36','37','38','39','40','41','42','43','44','45','46','47','48','49',
+'50','51','52','53','54','55','56','57','58','59','60','61','62','63','64','128'));
+ERROR HY000: Too many strings for column f1 and SET
+create table t1(f1
+set('1','2','3','4','5','6','7','8','9','10','11','12','13','14','15','16','17',
+'18','19','20','21','22','23','24','25','26','27','28','29','30','31','32','33',
+'34','35','36','37','38','39','40','41','42','43','44','45','46','47','48','49',
+'50','51','52','53','54','55','56','57','58','59','60','61','62','63','64','1'));
+Warnings:
+Note	1291	Column 'f1' has duplicated value '1' in SET
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `f1` set('1','2','3','4','5','6','7','8','9','10','11','12','13','14','15','16','17','18','19','20','21','22','23','24','25','26','27','28','29','30','31','32','33','34','35','36','37','38','39','40','41','42','43','44','45','46','47','48','49','50','51','52','53','54','55','56','57','58','59','60','61','62','63','64','1') default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
diff --git a/mysql-test/t/type_set.test b/mysql-test/t/type_set.test
index 56df3328246..b1c816f3371 100644
--- a/mysql-test/t/type_set.test
+++ b/mysql-test/t/type_set.test
@@ -39,3 +39,20 @@ SELECT c FROM t1 ORDER BY concat(c);
 DROP TABLE t1;
 
 # End of 4.1 tests
+
+#
+# Bug#27069 set with identical elements are created
+#
+--error 1097
+create table t1(f1
+set('1','2','3','4','5','6','7','8','9','10','11','12','13','14','15','16','17',
+'18','19','20','21','22','23','24','25','26','27','28','29','30','31','32','33',
+'34','35','36','37','38','39','40','41','42','43','44','45','46','47','48','49',
+'50','51','52','53','54','55','56','57','58','59','60','61','62','63','64','128'));
+create table t1(f1
+set('1','2','3','4','5','6','7','8','9','10','11','12','13','14','15','16','17',
+'18','19','20','21','22','23','24','25','26','27','28','29','30','31','32','33',
+'34','35','36','37','38','39','40','41','42','43','44','45','46','47','48','49',
+'50','51','52','53','54','55','56','57','58','59','60','61','62','63','64','1'));
+show create table t1;
+drop table t1;
diff --git a/sql/field.cc b/sql/field.cc
index 152c1bdc364..24cec4e1c74 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -8676,11 +8676,6 @@ bool create_field::init(THD *thd, char *fld_name, enum_field_types fld_type,
     break;
   case FIELD_TYPE_SET:
     {
-      if (fld_interval_list->elements > sizeof(longlong)*8)
-      {
-        my_error(ER_TOO_BIG_SET, MYF(0), fld_name); /* purecov: inspected */
-        DBUG_RETURN(TRUE);
-      }
       pack_length= get_set_pack_length(fld_interval_list->elements);
 
       List_iterator<String> it(*fld_interval_list);
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 8b3028f5370..a71579fb74f 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -407,6 +407,7 @@ static int sort_keys(KEY *a, KEY *b)
     set_or_name   "SET" or "ENUM" string for warning message
     name	  name of the checked column
     typelib	  list of values for the column
+    dup_val_count  returns count of duplicate elements
 
   DESCRIPTION
     This function prints an warning for each value in list
@@ -418,11 +419,12 @@ static int sort_keys(KEY *a, KEY *b)
 
 void check_duplicates_in_interval(const char *set_or_name,
                                   const char *name, TYPELIB *typelib,
-                                  CHARSET_INFO *cs)
+                                  CHARSET_INFO *cs, unsigned int *dup_val_count)
 {
   TYPELIB tmp= *typelib;
   const char **cur_value= typelib->type_names;
   unsigned int *cur_length= typelib->type_lengths;
+  *dup_val_count= 0;  
   
   for ( ; tmp.count > 1; cur_value++, cur_length++)
   {
@@ -435,6 +437,7 @@ void check_duplicates_in_interval(const char *set_or_name,
 			  ER_DUPLICATED_VALUE_IN_TYPE,
 			  ER(ER_DUPLICATED_VALUE_IN_TYPE),
 			  name,*cur_value,set_or_name);
+      (*dup_val_count)++;
     }
   }
 }
@@ -498,6 +501,7 @@ int prepare_create_field(create_field *sql_field,
 			 int *timestamps, int *timestamps_with_niladic,
 			 uint table_flags)
 {
+  unsigned int dup_val_count;
   DBUG_ENTER("prepare_field");
 
   /*
@@ -573,7 +577,7 @@ int prepare_create_field(create_field *sql_field,
     sql_field->unireg_check=Field::INTERVAL_FIELD;
     check_duplicates_in_interval("ENUM",sql_field->field_name,
                                  sql_field->interval,
-                                 sql_field->charset);
+                                 sql_field->charset, &dup_val_count);
     break;
   case FIELD_TYPE_SET:
     sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) |
@@ -583,7 +587,13 @@ int prepare_create_field(create_field *sql_field,
     sql_field->unireg_check=Field::BIT_FIELD;
     check_duplicates_in_interval("SET",sql_field->field_name,
                                  sql_field->interval,
-                                 sql_field->charset);
+                                 sql_field->charset, &dup_val_count);
+    /* Check that count of unique members is not more then 64 */
+    if (sql_field->interval->count -  dup_val_count > sizeof(longlong)*8)
+    {
+       my_error(ER_TOO_BIG_SET, MYF(0), sql_field->field_name);
+       DBUG_RETURN(1);
+    }
     break;
   case FIELD_TYPE_DATE:			// Rest of string types
   case FIELD_TYPE_NEWDATE:
-- 
2.30.9