*** ./sql/sql_lex.h	Thu Mar  8 17:29:58 2007
--- ../mysql-5.0.bk/./sql/sql_lex.h	Thu Mar 15 00:21:50 2007
***************
*** 985,992 ****
--- 985,1041 ----
      MIN(i) in the WHERE clause is not allowed in the opposite to MIN(i)
      in the HAVING clause. Due to possible nesting of select construct
      the variable can contain 0 or 1 for each nest level.
    */
+ 
+   /**
+      @brief   BitMask of Bits used in "type" (only used in sql_yacc)
+      @details Keep track of each bit which has been explicit set to 0 or 1.
+               This allows to detect conlflicts, between user options
+               Otherwise a user cut specify "c int  PRIMARY KEY  NULL"
+   */
+   ulong type_explicit;
+ 
+   /**
+      @brief   Set Bits in "type" (only used in sql_yacc)
+      @details Raise an error if the bit is explicitly unset
+   */
+   inline bool set_type_bits(ulong bits) {
+     if ((type_explicit & bits) != (type_explicit & bits & type))
+       return 0; // some of the bits we want to set, are explicitly unset
+     type|= bits;
+     type_explicit|= bits;
+     return 1;
+   }
+ 
+   /**
+      @brief   Unset Bits in "type" (only used in sql_yacc)
+      @details Raise an error if the bit is explicitly set
+   */
+   inline bool unset_type_bits(ulong bits) {
+     if ((type_explicit & bits) != (type_explicit & bits & (~type)))
+       return 0; // some of the bits we want to unset, are explicitly set
+     type&= ~bits;
+     type_explicit|= bits;
+     return 1;
+   }
+ 
+   /**
+      @brief   BitMask of attributes used in column def (only used in sql_yacc)
+   */
+   ulong attrib_used;
+   /**
+      @brief   Check if attribute was used before (only used in sql_yacc)
+      @details Check if an attribute is given more than once and
+               set an error.
+               "c char(1) default 'a' default 'b'"
+   */
+   inline bool test_attrib_used(ulong attrib) {
+     if (attrib_used & attrib) return 0;
+     attrib_used|= attrib;
+     return 1;
+   }
+ 
    nesting_map allow_sum_func;
    enum_sql_command sql_command, orig_sql_command;
    thr_lock_type lock_option;
    enum SSL_type ssl_type;			/* defined in violite.h */
*** ./sql/sql_yacc.yy	Wed Mar  7 09:24:42 2007
--- ../mysql-5.0.bk/./sql/sql_yacc.yy	Thu Mar 15 12:15:20 2007
***************
*** 1044,1052 ****
  %type <string>
  	text_string opt_gconcat_separator
  
  %type <num>
! 	type int_type real_type order_dir lock_option
  	udf_type if_exists opt_local opt_table_options table_options
          table_option opt_if_not_exists opt_no_write_to_binlog
          delete_option opt_temporary all_or_any opt_distinct
          opt_ignore_leaves fulltext_options spatial_type union_option
--- 1044,1052 ----
  %type <string>
  	text_string opt_gconcat_separator
  
  %type <num>
! 	type type2 int_type real_type order_dir lock_option
  	udf_type if_exists opt_local opt_table_options table_options
          table_option opt_if_not_exists opt_no_write_to_binlog
          delete_option opt_temporary all_or_any opt_distinct
          opt_ignore_leaves fulltext_options spatial_type union_option
***************
*** 3140,3147 ****
--- 3140,3157 ----
  	    MYSQL_YYABORT;
  	};
  
  type:
+         {
+           LEX *lex=Lex;
+           lex->type_explicit= 0;
+           lex->attrib_used= 0;
+         }
+         type2
+         { $$ = $2; }
+         ;
+ 
+ type2:
  	int_type opt_len field_options	{ $$=$1; }
  	| real_type opt_precision field_options { $$=$1; }
  	| FLOAT_SYM float_options field_options { $$=FIELD_TYPE_FLOAT; }
  	| BIT_SYM			{ Lex->length= (char*) "1";
***************
*** 3187,3195 ****
              {
                /* 
                  Unlike other types TIMESTAMP fields are NOT NULL by default.
                */
!               Lex->type|= NOT_NULL_FLAG;
  	      $$=FIELD_TYPE_TIMESTAMP;
              }
  	   }
  	| DATETIME			{ $$=FIELD_TYPE_DATETIME; }
--- 3197,3205 ----
              {
                /* 
                  Unlike other types TIMESTAMP fields are NOT NULL by default.
                */
!               Lex->type|= NOT_NULL_FLAG; // Do not use set_type_bits
  	      $$=FIELD_TYPE_TIMESTAMP;
              }
  	   }
  	| DATETIME			{ $$=FIELD_TYPE_DATETIME; }
***************
*** 3233,3241 ****
  	| LONG_SYM opt_binary		{ $$=FIELD_TYPE_MEDIUM_BLOB; }
  	| SERIAL_SYM
  	  {
  	    $$=FIELD_TYPE_LONGLONG;
! 	    Lex->type|= (AUTO_INCREMENT_FLAG | NOT_NULL_FLAG | UNSIGNED_FLAG |
  		         UNIQUE_FLAG);
  	  }
  	;
  
--- 3243,3251 ----
  	| LONG_SYM opt_binary		{ $$=FIELD_TYPE_MEDIUM_BLOB; }
  	| SERIAL_SYM
  	  {
  	    $$=FIELD_TYPE_LONGLONG;
! 	    Lex->set_type_bits(AUTO_INCREMENT_FLAG | NOT_NULL_FLAG | UNSIGNED_FLAG |
  		         UNIQUE_FLAG);
  	  }
          ;
  
***************
*** 3308,3318 ****
  	field_opt_list field_option {}
  	| field_option {};
  
  field_option:
! 	SIGNED_SYM	{}
! 	| UNSIGNED	{ Lex->type|= UNSIGNED_FLAG;}
! 	| ZEROFILL	{ Lex->type|= UNSIGNED_FLAG | ZEROFILL_FLAG; };
  
  opt_len:
  	/* empty */	{ Lex->length=(char*) 0; } /* use default length */
  	| '(' NUM ')'	{ Lex->length= $2.str; };
--- 3318,3336 ----
  	field_opt_list field_option {}
  	| field_option {};
  
  field_option:
! 	SIGNED_SYM {
!             MYSQL_YYABORT_UNLESS(!(Lex->type_explicit & UNSIGNED_FLAG) &&  Lex->unset_type_bits(UNSIGNED_FLAG));
!           }
! 	| UNSIGNED {
!             MYSQL_YYABORT_UNLESS(Lex->test_attrib_used(UNSIGNED_FLAG));
!             MYSQL_YYABORT_UNLESS(Lex->set_type_bits(UNSIGNED_FLAG));
!           }
! 	| ZEROFILL {
!             MYSQL_YYABORT_UNLESS(Lex->test_attrib_used(ZEROFILL_FLAG));
!             MYSQL_YYABORT_UNLESS(Lex->set_type_bits(UNSIGNED_FLAG | ZEROFILL_FLAG));
!           };
  
  opt_len:
  	/* empty */	{ Lex->length=(char*) 0; } /* use default length */
  	| '(' NUM ')'	{ Lex->length= $2.str; };
***************
*** 3329,3367 ****
  	opt_attribute_list attribute {}
  	| attribute;
  
  attribute:
! 	NULL_SYM	  { Lex->type&= ~ NOT_NULL_FLAG; }
! 	| not NULL_SYM	  { Lex->type|= NOT_NULL_FLAG; }
! 	| DEFAULT now_or_signed_literal { Lex->default_value=$2; }
  	| ON UPDATE_SYM NOW_SYM optional_braces 
!           { Lex->on_update_value= new Item_func_now_local(); }
! 	| AUTO_INC	  { Lex->type|= AUTO_INCREMENT_FLAG | NOT_NULL_FLAG; }
  	| SERIAL_SYM DEFAULT VALUE_SYM
  	  { 
  	    LEX *lex=Lex;
! 	    lex->type|= AUTO_INCREMENT_FLAG | NOT_NULL_FLAG | UNIQUE_FLAG; 
  	    lex->alter_info.flags|= ALTER_ADD_INDEX; 
  	  }
  	| opt_primary KEY_SYM 
  	  {
  	    LEX *lex=Lex;
! 	    lex->type|= PRI_KEY_FLAG | NOT_NULL_FLAG; 
  	    lex->alter_info.flags|= ALTER_ADD_INDEX; 
  	  }
  	| UNIQUE_SYM	  
  	  {
  	    LEX *lex=Lex;
! 	    lex->type|= UNIQUE_FLAG; 
  	    lex->alter_info.flags|= ALTER_ADD_INDEX; 
  	  }
  	| UNIQUE_SYM KEY_SYM 
  	  {
  	    LEX *lex=Lex;
  	    lex->type|= UNIQUE_KEY_FLAG; 
  	    lex->alter_info.flags|= ALTER_ADD_INDEX; 
  	  }
! 	| COMMENT_SYM TEXT_STRING_sys { Lex->comment= $2; }
  	| COLLATE_SYM collation_name
  	  {
  	    if (Lex->charset && !my_charset_same(Lex->charset,$2))
  	    {
--- 3347,3416 ----
  	opt_attribute_list attribute {}
  	| attribute;
  
  attribute:
! 	NULL_SYM
!           {
! 	    LEX *lex=Lex;
!             MYSQL_YYABORT_UNLESS(lex->test_attrib_used(NOT_NULL_FLAG));
!             MYSQL_YYABORT_UNLESS(lex->unset_type_bits(NOT_NULL_FLAG));
!           }
! 	| not NULL_SYM
!           {
!  	    LEX *lex=Lex;
!             MYSQL_YYABORT_UNLESS(lex->test_attrib_used(NOT_NULL_FLAG));
!             MYSQL_YYABORT_UNLESS(lex->set_type_bits(NOT_NULL_FLAG));
!           }
! 	| DEFAULT now_or_signed_literal
!           { 
!  	    LEX *lex=Lex;
!             MYSQL_YYABORT_UNLESS(lex->test_attrib_used(COL_HAS_DEFAULT));
!             lex->default_value=$2;
!           }
  	| ON UPDATE_SYM NOW_SYM optional_braces 
!           {
!  	    LEX *lex=Lex;
!             MYSQL_YYABORT_UNLESS(lex->on_update_value == 0);
!             lex->on_update_value= new Item_func_now_local();
!           }
! 	| AUTO_INC
!           { 
!  	    LEX *lex=Lex;
!             MYSQL_YYABORT_UNLESS(lex->test_attrib_used(AUTO_INCREMENT_FLAG));
!             MYSQL_YYABORT_UNLESS(lex->set_type_bits(AUTO_INCREMENT_FLAG | NOT_NULL_FLAG));
!           }
  	| SERIAL_SYM DEFAULT VALUE_SYM
  	  { 
  	    LEX *lex=Lex;
!             MYSQL_YYABORT_UNLESS(lex->test_attrib_used(COL_SERIAL_VAL));
!             MYSQL_YYABORT_UNLESS(lex->set_type_bits(AUTO_INCREMENT_FLAG | NOT_NULL_FLAG | UNIQUE_FLAG));
              lex->alter_info.flags|= ALTER_ADD_INDEX; 
  	  }
  	| opt_primary KEY_SYM 
  	  {
  	    LEX *lex=Lex;
!             MYSQL_YYABORT_UNLESS(lex->test_attrib_used(PRI_KEY_FLAG));
!             MYSQL_YYABORT_UNLESS(lex->set_type_bits(PRI_KEY_FLAG | NOT_NULL_FLAG));
  	    lex->alter_info.flags|= ALTER_ADD_INDEX; 
  	  }
  	| UNIQUE_SYM	  
  	  {
  	    LEX *lex=Lex;
!             MYSQL_YYABORT_UNLESS(lex->test_attrib_used(UNIQUE_FLAG));
!             MYSQL_YYABORT_UNLESS(lex->set_type_bits(UNIQUE_FLAG));
  	    lex->alter_info.flags|= ALTER_ADD_INDEX; 
  	  }
  	| UNIQUE_SYM KEY_SYM 
  	  {
  	    LEX *lex=Lex;
+             MYSQL_YYABORT_UNLESS(lex->test_attrib_used(UNIQUE_FLAG));
  	    lex->type|= UNIQUE_KEY_FLAG; 
  	    lex->alter_info.flags|= ALTER_ADD_INDEX; 
  	  }
! 	| COMMENT_SYM TEXT_STRING_sys {
!             MYSQL_YYABORT_UNLESS(Lex->test_attrib_used(COL_HAS_COMMENT));
!             Lex->comment= $2;
!           }
  	| COLLATE_SYM collation_name
  	  {
  	    if (Lex->charset && !my_charset_same(Lex->charset,$2))
  	    {
*** ./include/mysql_com.h	Wed Mar 14 11:05:36 2007
--- ../mysql-5.0.bk/./include/mysql_com.h	Wed Mar 14 15:28:56 2007
***************
*** 94,101 ****
--- 94,104 ----
  #define PART_KEY_FLAG	16384		/* Intern; Part of some key */
  #define GROUP_FLAG	32768		/* Intern: Group field */
  #define UNIQUE_FLAG	65536		/* Intern: Used by sql_yacc */
  #define BINCMP_FLAG	131072		/* Intern: Used by sql_yacc */
+ #define COL_HAS_DEFAULT	1<<18		/* Intern: Used by sql_yacc */
+ #define COL_SERIAL_VAL	1<<19		/* Intern: Used by sql_yacc */
+ #define COL_HAS_COMMENT	1<<20		/* Intern: Used by sql_yacc */
  
  #define REFRESH_GRANT		1	/* Refresh grant tables */
  #define REFRESH_LOG		2	/* Start on new log file */
  #define REFRESH_TABLES		4	/* close all tables */
