*** mysql-5.0.bk-orig/sql/sql_lex.h	Thu Mar  8 17:29:58 2007
--- mysql-5.0.bk-col_spec/sql/sql_lex.h	Sat Mar 24 16:13:14 2007
***************
*** 984,993 ****
--- 984,1053 ----
      SELECT ... FROM ...WHERE MIN(i) == 1 GROUP BY ... HAVING MIN(i) > 2
      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)
+      @see     set_type_bits()
+   */
+   ulong type_explicit;
+ 
+   /**
+      @brief   Set bits in "type" for each column attribute (used in sql_yacc)
+      @details Set bits in the type and type_explicit field.
+               The type field is used by the parser to remember column
+               attributes. The type_explicit field is used to keep track of
+               each bit which has been set to 0 or 1.
+               This allows to detect conflicts between user options.
+               Otherwise a user could specify "c int  PRIMARY KEY  NULL"
+      @param   bits indicates which bits to set
+      @return  true if the bits could all be set, false if there was a conflict
+   */
+   inline bool set_type_bits(ulong bits)
+   {
+     if ((type_explicit & bits) != (type_explicit & bits & type))
+       return 0;
+     type|= bits;
+     type_explicit|= bits;
+     return 1;
+   }
+ 
+   /**
+      @brief   Unset Bits in "type" (used in sql_yacc)
+      @see     set_type_bits()
+   */
+   inline bool unset_type_bits(ulong bits)
+   {
+     if ((type_explicit & bits) != (type_explicit & bits & (~type)))
+       return 0;
+     type&= ~bits;
+     type_explicit|= bits;
+     return 1;
+   }
+ 
+   /**
+      @brief BitMask of attribute specifiers used in column def
+      @see   test_attrib_used()
+   */
+   ulong attrib_used;
+   /**
+      @brief   Check if attribute specifier was used before (used in sql_yacc)
+      @details Check if the same literal attribute specifier is given more
+               than once.
+               "c char(1) default 'a' default 'b'"
+      @param   attrib A BitMask
+   */
+   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 */
    enum my_lex_states next_state;
*** mysql-5.0.bk-orig/sql/sql_yacc.yy	Mon Mar 19 20:59:22 2007
--- mysql-5.0.bk-col_spec/sql/sql_yacc.yy	Sat Mar 24 16:32:40 2007
***************
*** 1043,1054 ****
  
  %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
          start_transaction_opts opt_chain opt_release
          union_opt select_derived_init option_type2
--- 1043,1054 ----
  
  %type <string>
  	text_string opt_gconcat_separator
  
  %type <num>
!         type type_continued 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
          start_transaction_opts opt_chain opt_release
          union_opt select_derived_init option_type2
***************
*** 3128,3137 ****
--- 3128,3147 ----
  				lex->uint_geom_type))
  	    MYSQL_YYABORT;
  	};
  
  type:
+         {
+           LEX *lex=Lex;
+           lex->type_explicit= 0;
+           lex->attrib_used= 0;
+         }
+         type_continued
+         { $$ = $2; }
+         ;
+ 
+ type_continued:
  	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";
  					  $$=FIELD_TYPE_BIT; }
***************
*** 3175,3186 ****
  	    else
              {
                /* 
                  Unlike other types TIMESTAMP fields are NOT NULL by default.
                */
!               Lex->type|= NOT_NULL_FLAG;
! 	      $$=FIELD_TYPE_TIMESTAMP;
              }
  	   }
  	| DATETIME			{ $$=FIELD_TYPE_DATETIME; }
  	| TINYBLOB			{ Lex->charset=&my_charset_bin;
  					  $$=FIELD_TYPE_TINY_BLOB; }
--- 3185,3196 ----
  	    else
              {
                /* 
                  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; }
  	| TINYBLOB			{ Lex->charset=&my_charset_bin;
  					  $$=FIELD_TYPE_TINY_BLOB; }
***************
*** 3218,3234 ****
  	| ENUM {Lex->interval_list.empty();} '(' string_list ')' opt_binary
  	  { $$=FIELD_TYPE_ENUM; }
  	| SET { Lex->interval_list.empty();} '(' string_list ')' opt_binary
  	  { $$=FIELD_TYPE_SET; }
  	| 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);
! 	  }
! 	;
  
  spatial_type:
  	GEOMETRY_SYM	      { $$= Field::GEOM_GEOMETRY; }
  	| GEOMETRYCOLLECTION  { $$= Field::GEOM_GEOMETRYCOLLECTION; }
  	| POINT_SYM           { Lex->length= (char*)"21";
--- 3228,3244 ----
  	| ENUM {Lex->interval_list.empty();} '(' string_list ')' opt_binary
  	  { $$=FIELD_TYPE_ENUM; }
  	| SET { Lex->interval_list.empty();} '(' string_list ')' opt_binary
  	  { $$=FIELD_TYPE_SET; }
  	| 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);
!           }
!         ;
  
  spatial_type:
  	GEOMETRY_SYM	      { $$= Field::GEOM_GEOMETRY; }
  	| GEOMETRYCOLLECTION  { $$= Field::GEOM_GEOMETRYCOLLECTION; }
  	| POINT_SYM           { Lex->length= (char*)"21";
***************
*** 3296,3308 ****
  field_opt_list:
  	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; };
  
--- 3306,3326 ----
  field_opt_list:
  	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; };
  
***************
*** 3317,3371 ****
  opt_attribute_list:
  	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))
! 	    {
! 	      my_error(ER_COLLATION_CHARSET_MISMATCH, MYF(0),
!                        $2->name,Lex->charset->csname);
! 	      MYSQL_YYABORT;
! 	    }
! 	    else
! 	    {
! 	      Lex->charset=$2;
! 	    }
! 	  }
! 	;
  
  now_or_signed_literal:
          NOW_SYM optional_braces { $$= new Item_func_now_local(); }
          | signed_literal { $$=$1; }
          ;
--- 3335,3420 ----
  opt_attribute_list:
  	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))
!             {
!               my_error(ER_COLLATION_CHARSET_MISMATCH, MYF(0),
!                       $2->name,Lex->charset->csname);
!               MYSQL_YYABORT;
!             }
!             else
!             {
!               Lex->charset=$2;
!             }
!           }
!         ;
  
  now_or_signed_literal:
          NOW_SYM optional_braces { $$= new Item_func_now_local(); }
          | signed_literal { $$=$1; }
          ;
*** mysql-5.0.bk-orig/include/mysql_com.h	Fri Mar 23 10:21:51 2007
--- mysql-5.0.bk-col_spec/include/mysql_com.h	Sat Mar 24 16:27:10 2007
***************
*** 92,102 ****
  #define NO_DEFAULT_VALUE_FLAG 4096	/* Field doesn't have default value */
  #define NUM_FLAG	32768		/* Field is num (for clients) */
  #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 REFRESH_GRANT		1	/* Refresh grant tables */
  #define REFRESH_LOG		2	/* Start on new log file */
  #define REFRESH_TABLES		4	/* close all tables */
  #define REFRESH_HOSTS		8	/* Flush host cache */
--- 92,105 ----
  #define NO_DEFAULT_VALUE_FLAG 4096	/* Field doesn't have default value */
  #define NUM_FLAG	32768		/* Field is num (for clients) */
  #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 */
  #define REFRESH_HOSTS		8	/* Flush host cache */
