Bug #23723 Duplicate code in the parser for handling CHANGE/MODIFY clauses of ALTER TABLE
Submitted: 27 Oct 2006 15:25 Modified: 31 Oct 2006 9:15
Reporter: Andrey Hristov Email Updates:
Status: Not a Bug Impact on me:
None 
Category:MySQL Server: Parser Severity:S3 (Non-critical)
Version:5.1 OS:Any (All)
Assigned to: Andrey Hristov CPU Architecture:Any

[27 Oct 2006 15:25] Andrey Hristov
Description:
Currently the code in sql_yacc.yy is :
	| CHANGE opt_column field_ident
	  {
	     LEX *lex=Lex;
	     lex->change= $3.str;
	     lex->alter_info.flags|= ALTER_CHANGE_COLUMN;
	  }
          field_spec opt_place
        | MODIFY_SYM opt_column field_ident
          {
            LEX *lex=Lex;
            lex->length=lex->dec=0; lex->type=0;
            lex->default_value= lex->on_update_value= 0;
            lex->comment=null_lex_str;
	    lex->charset= NULL;
	    lex->alter_info.flags|= ALTER_CHANGE_COLUMN;
          }
          type opt_attribute
          {
            LEX *lex=Lex;
            if (add_field_to_list(lex->thd,$3.str,
                                  (enum enum_field_types) $5,
                                  lex->length,lex->dec,lex->type,
                                  lex->default_value, lex->on_update_value,
                                  &lex->comment,
				  $3.str, &lex->interval_list, lex->charset,
				  lex->uint_geom_type))
	       YYABORT;
          }
          opt_place

However, MODIFY does code duplication of field_spec non-terminal.

How to repeat:
See the source

Suggested fix:
Because the difference between CHANGE and MODIFY is that the former has the capability to rename the column
modify_change_tail:
          field_spec opt_place
          {
	    Lex->alter_info.flags|= ALTER_CHANGE_COLUMN;
          }
        ;

	| CHANGE opt_column field_ident 
	  {
            /*
              Don't move this block after opt_place because field_spec
              relies on lex->change being correctly set!
            */
	    Lex->change= $3.str;
	  }
          modify_change_tail
        | MODIFY_SYM modify_change_tail

Snippets from sql_yacc.cc before and after the change follow.

Before:
/* YYFINAL -- State number of the termination state. */
#define YYFINAL  520
/* YYLAST -- Last index in YYTABLE.  */
#define YYLAST   48668

/* YYNTOKENS -- Number of terminals. */
#define YYNTOKENS  611
/* YYNNTS -- Number of nonterminals. */
#define YYNNTS  812
/* YYNRULES -- Number of rules. */
#define YYNRULES  2344
/* YYNRULES -- Number of states. */
#define YYNSTATES  4193
---------------------------------------------------------
After:
/* YYFINAL -- State number of the termination state. */
#define YYFINAL  520
/* YYLAST -- Last index in YYTABLE.  */
#define YYLAST   47331

/* YYNTOKENS -- Number of terminals. */
#define YYNTOKENS  611
/* YYNNTS -- Number of nonterminals. */
#define YYNNTS  811
/* YYNRULES -- Number of rules. */
#define YYNRULES  2343
/* YYNRULES -- Number of states. */
#define YYNSTATES  4188