github.com/walf443/mgr@v0.0.0-20150203144449-6f7a3a548462/sqlparser/mysql/parser.go.y (about) 1 // vim: noet sw=8 sts=8 2 %{ 3 package mysql 4 5 import ( 6 "fmt" 7 "strconv" 8 "errors" 9 ) 10 11 type Token struct { 12 tok int 13 lit string 14 pos Position 15 } 16 17 %} 18 19 %union{ 20 statements []Statement 21 statement Statement 22 table_names []TableNameIdentifier 23 table_name TableNameIdentifier 24 table_options []TableOption 25 table_option TableOption 26 database_name DatabaseNameIdentifier 27 column_name ColumnNameIdentifier 28 column_names []ColumnNameIdentifier 29 index_name IndexNameIdentifier 30 column_definition ColumnDefinition 31 alter_specifications []AlterSpecification 32 alter_specification AlterSpecification 33 data_type DataTypeDefinition 34 create_definitions []CreateDefinition 35 create_definition CreateDefinition 36 bool bool 37 data_type_type DataType 38 default_definition DefaultDefinition 39 uint uint 40 fraction_option [2]uint 41 tok Token 42 str string 43 } 44 45 %type<statements> statements 46 %type<statement> statement 47 %type<table_names> table_names 48 %type<table_name> table_name 49 %type<database_name> database_name 50 %type<column_name> column_name 51 %type<column_names> index_column_names 52 %type<index_name> index_name skipable_index_name 53 %type<column_definition> column_definition 54 %type<alter_specifications> alter_specifications 55 %type<alter_specification> alter_specification 56 %type<create_definition> create_definition 57 %type<create_definitions> create_definitions 58 %type<data_type> data_type 59 %type<data_type_type> data_type_number data_type_fraction data_type_decimal 60 %type<bool> unsigned_option zerofill_option nullable autoincrement 61 %type<uint> length_option 62 %type<fraction_option> fraction_option decimal_option 63 %type<default_definition> default 64 %type<table_option> table_option 65 %type<table_options> skipable_table_options 66 %type<str> storage_engine_name string 67 68 %token<tok> IDENT NUMBER RAW COMMENT_START COMMENT_FINISH 69 %token<tok> DROP CREATE ALTER ADD 70 %token<tok> TABLE COLUMN DATABASE INDEX KEY NOT NULL AUTO_INCREMENT DEFAULT CURRENT_TIMESTAMP ON UPDATE PRIMARY UNIQUE 71 %token<tok> USING BTREE HASH CHARSET CHARACTER SET COLLATE 72 %token<tok> ENGINE AVG_ROW_LENGTH CHECKSUM COMMENT KEY_BLOCK_SIZE MAX_ROWS MIN_ROWS ROW_FORMAT DYNAMIC FIXED COMPRESSED REDUNDANT COMPACT 73 %token<tok> BIT TINYINT SMALLINT MEDIUMINT INT INTEGER BIGINT REAL DOUBLE FLOAT DECIMAL NUMERIC DATE TIME TIMESTAMP DATETIME YEAR CHAR VARCHAR BINARY VARBINARY TINYBLOB BLOB MEDIUMBLOB LONGBLOB TINYTEXT TEXT MEDIUMTEXT LONGTEXT UNSIGNED ZEROFILL 74 75 %% 76 77 statements 78 : 79 { 80 $$ = nil 81 if l, isLexerWrapper := yylex.(*LexerWrapper); isLexerWrapper { 82 l.statements = $$ 83 } 84 } 85 | statements statement 86 { 87 $$ = append($1, $2) 88 if l, isLexerWrapper := yylex.(*LexerWrapper); isLexerWrapper { 89 l.statements = $$ 90 } 91 } 92 93 statement 94 : DROP TABLE table_names ';' 95 { 96 $$ = &DropTableStatement{TableNames: $3} 97 } 98 | DROP DATABASE database_name ';' 99 { 100 $$ = &DropDatabaseStatement{DatabaseName: $3} 101 } 102 | CREATE DATABASE database_name ';' 103 { 104 $$ = &CreateDatabaseStatement{DatabaseName: $3} 105 } 106 | CREATE TABLE table_name '(' create_definitions ')' skipable_table_options optional_statement_finish 107 { 108 $$ = &CreateTableStatement{TableName: $3, CreateDefinitions: $5, TableOptions: $7} 109 } 110 | ALTER TABLE table_name alter_specifications ';' 111 { 112 $$ = &AlterTableStatement{TableName: $3, AlterSpecifications: $4} 113 } 114 | COMMENT_START RAW COMMENT_FINISH ';' 115 { 116 $$ = &CommentStatement{$2.lit} 117 } 118 119 optional_statement_finish 120 : 121 | ';' 122 123 create_definitions 124 : create_definition 125 { 126 $$ = []CreateDefinition{$1} 127 } 128 | create_definitions ',' create_definition 129 { 130 $$ = append($1, $3) 131 } 132 133 create_definition 134 : column_name column_definition 135 { 136 $$ = &CreateDefinitionColumn{ColumnName: $1, ColumnDefinition: $2} 137 } 138 | PRIMARY KEY skipable_index_type '(' index_column_names ')' 139 { 140 $$ = &CreateDefinitionPrimaryIndex{Columns: $5} 141 } 142 | index_or_key skipable_index_name skipable_index_type '(' index_column_names ')' skipable_index_type 143 { 144 $$ = &CreateDefinitionIndex{Name: $2, Columns: $5} 145 } 146 | UNIQUE index_or_key skipable_index_name skipable_index_type '(' index_column_names ')' 147 { 148 $$ = &CreateDefinitionUniqueIndex{Name: $3, Columns: $6} 149 } 150 151 skipable_table_options 152 : 153 { 154 $$ = []TableOption{} 155 } 156 | skipable_table_options table_option 157 { 158 $$ = append($1, $2) 159 } 160 161 table_option 162 : ENGINE skipable_equal storage_engine_name 163 { 164 var option TableOption 165 option.Key = "ENGINE" 166 option.Value = $3 167 $$ = option 168 } 169 | AUTO_INCREMENT skipable_equal NUMBER 170 { 171 var option TableOption 172 option.Key = "AUTO_INCREMENT" 173 option.Value = $3.lit 174 $$ = option 175 } 176 | AVG_ROW_LENGTH skipable_equal NUMBER 177 { 178 var option TableOption 179 option.Key = "AVG_ROW_LENGTH" 180 option.Value = $3.lit 181 $$ = option 182 } 183 | CHECKSUM skipable_equal NUMBER 184 { 185 var option TableOption 186 option.Key = "CHECKSUM" 187 option.Value = $3.lit 188 $$ = option 189 } 190 | COMMENT skipable_equal '\'' RAW '\'' 191 { 192 var option TableOption 193 option.Key = "COMMENT" 194 option.Value = $4.lit 195 $$ = option 196 } 197 | KEY_BLOCK_SIZE skipable_equal NUMBER 198 { 199 var option TableOption 200 option.Key = "KEY_BLOCK_SIZE" 201 option.Value = $3.lit 202 $$ = option 203 } 204 | MAX_ROWS skipable_equal NUMBER 205 { 206 var option TableOption 207 option.Key = "MAX_ROWS" 208 option.Value = $3.lit 209 $$ = option 210 } 211 | MIN_ROWS skipable_equal NUMBER 212 { 213 var option TableOption 214 option.Key = "MIN_ROWS" 215 option.Value = $3.lit 216 $$ = option 217 } 218 | ROW_FORMAT skipable_equal storage_engine_name 219 { 220 var option TableOption 221 option.Key = "ROW_FORMAT" 222 option.Value = $3 223 $$ = option 224 } 225 | DEFAULT CHARSET skipable_equal string 226 { 227 var option TableOption 228 option.Key = "DEFAULT CHARACTER SET" 229 option.Value = $4 230 $$ = option 231 } 232 | COLLATE skipable_equal string 233 { 234 var option TableOption 235 option.Key = "COLLATE" 236 option.Value = $3 237 $$ = option 238 } 239 240 charset_or_character_set 241 : CHARSET 242 | CHARACTER SET 243 244 skipable_equal 245 : 246 | '=' 247 248 index_column_names 249 : column_name 250 { 251 result := []ColumnNameIdentifier{} 252 result = append(result, $1) 253 $$ = result 254 } 255 | index_column_names ',' column_name 256 { 257 result := append($1, $3) 258 $$ = result 259 } 260 261 skipable_index_type 262 : 263 | USING BTREE 264 | USING HASH 265 266 table_names 267 : table_name 268 { 269 $$ = []TableNameIdentifier{$1} 270 } 271 | table_names ',' table_name 272 { 273 $$ = append([]TableNameIdentifier{$3}, $1...) 274 } 275 276 table_name 277 : IDENT 278 { 279 $$ = TableNameIdentifier{Name: $1.lit} 280 } 281 | '`' RAW '`' 282 { 283 $$ = TableNameIdentifier{Name: $2.lit} 284 } 285 | IDENT '.' IDENT 286 { 287 $$ = TableNameIdentifier{Database: $1.lit, Name: $3.lit} 288 } 289 290 database_name 291 : IDENT 292 { 293 $$ = DatabaseNameIdentifier{Name: $1.lit} 294 } 295 | '`' RAW '`' 296 { 297 $$ = DatabaseNameIdentifier{Name: $2.lit} 298 } 299 300 alter_specifications 301 : 302 { 303 $$ = nil 304 } 305 | alter_specification 306 { 307 $$ = []AlterSpecification{$1} 308 } 309 | alter_specifications ',' alter_specification 310 { 311 $$ = append($1, $3) 312 } 313 314 alter_specification 315 : ADD skipable_column column_name column_definition 316 { 317 $$ = &AlterSpecificationAddColumn{ColumnName: $3, ColumnDefinition: $4} 318 } 319 | ADD index_or_key skipable_index_name skipable_index_type '(' index_column_names ')' 320 { 321 $$ = &AlterSpecificationAddIndex{Name: $3, Columns: $6, Unique: false} 322 } 323 | ADD UNIQUE index_or_key skipable_index_name skipable_index_type '(' index_column_names ')' 324 { 325 $$ = &AlterSpecificationAddIndex{Name: $4, Columns: $7, Unique: true} 326 } 327 | DROP index_or_key index_name 328 { 329 $$ = &AlterSpecificationDropIndex{Name: $3} 330 } 331 | DROP skipable_column column_name 332 { 333 $$ = &AlterSpecificationDropColumn{ColumnName: $3} 334 } 335 336 skipable_column 337 : 338 | COLUMN 339 340 column_definition 341 : data_type nullable default autoincrement key_options column_comment 342 { 343 $$ = ColumnDefinition{$1, $2, $4, $3} 344 } 345 346 nullable 347 : 348 { 349 $$ = true 350 } 351 | NULL 352 { 353 $$ = true 354 } 355 | NOT NULL 356 { 357 $$ = false 358 } 359 360 default 361 : 362 { 363 $$ = &DefaultDefinitionEmpty{} 364 } 365 | DEFAULT NULL 366 { 367 $$ = &DefaultDefinitionNull{} 368 } 369 | DEFAULT NUMBER 370 { 371 value := DefaultDefinitionString{} 372 value.Value = $2.lit 373 $$ = &value 374 } 375 | DEFAULT '"' RAW '"' 376 { 377 value := DefaultDefinitionString{} 378 value.Value = $3.lit 379 $$ = &value 380 } 381 | DEFAULT '\'' RAW '\'' 382 { 383 value := DefaultDefinitionString{} 384 value.Value = $3.lit 385 $$ = &value 386 } 387 | DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP 388 { 389 $$ = &DefaultDefinitionCurrentTimestamp{true} 390 } 391 | DEFAULT CURRENT_TIMESTAMP 392 { 393 $$ = &DefaultDefinitionCurrentTimestamp{false} 394 } 395 396 string 397 : IDENT 398 { 399 $$ = $1.lit 400 } 401 | '\'' RAW '\'' 402 { 403 $$ = $2.lit 404 } 405 | '"' RAW '"' 406 { 407 $$ = $2.lit 408 } 409 410 autoincrement 411 : 412 { 413 $$ = false 414 } 415 | AUTO_INCREMENT 416 { 417 $$ = true 418 } 419 420 key_options 421 : 422 423 column_comment 424 : 425 | COMMENT string 426 427 data_type 428 : BIT 429 { 430 $$ = &DataTypeDefinitionSimple{Type: DATATYPE_BIT } 431 } 432 | data_type_number length_option unsigned_option zerofill_option 433 { 434 $$ = &DataTypeDefinitionNumber{Type: $1, Length: $2, Unsigned: $3, Zerofill: $4 } 435 } 436 | data_type_fraction fraction_option unsigned_option zerofill_option 437 { 438 fraction := $2 439 $$ = &DataTypeDefinitionFraction{Type: $1, Length: fraction[0], Decimals: fraction[1], Unsigned: $3, Zerofill: $4 } 440 } 441 | data_type_decimal decimal_option unsigned_option zerofill_option 442 { 443 fraction := $2 444 $$ = &DataTypeDefinitionFraction{Type: $1, Length: fraction[0], Decimals: fraction[1], Unsigned: $3, Zerofill: $4 } 445 } 446 | DATE 447 { 448 $$ = &DataTypeDefinitionSimple{Type: DATATYPE_DATE } 449 } 450 | TIME 451 { 452 $$ = &DataTypeDefinitionSimple{Type: DATATYPE_TIME } 453 } 454 | TIMESTAMP 455 { 456 $$ = &DataTypeDefinitionSimple{Type: DATATYPE_TIMESTAMP } 457 } 458 | DATETIME 459 { 460 $$ = &DataTypeDefinitionSimple{Type: DATATYPE_DATETIME } 461 } 462 | YEAR 463 { 464 $$ = &DataTypeDefinitionSimple{Type: DATATYPE_YEAR } 465 } 466 | CHAR length_option optional_character_set optional_collate 467 { 468 $$ = &DataTypeDefinitionString{Type: DATATYPE_CHAR, Length: $2 } 469 } 470 | VARCHAR length_option optional_character_set optional_collate 471 { 472 $$ = &DataTypeDefinitionString{Type: DATATYPE_VARCHAR, Length: $2 } 473 } 474 | BINARY 475 { 476 $$ = &DataTypeDefinitionSimple{Type: DATATYPE_BINARY } 477 } 478 | VARBINARY 479 { 480 $$ = &DataTypeDefinitionSimple{Type: DATATYPE_VARBINARY } 481 } 482 | TINYBLOB 483 { 484 $$ = &DataTypeDefinitionSimple{Type: DATATYPE_TINYBLOB } 485 } 486 | BLOB 487 { 488 $$ = &DataTypeDefinitionSimple{Type: DATATYPE_BLOB } 489 } 490 | MEDIUMBLOB 491 { 492 $$ = &DataTypeDefinitionSimple{Type: DATATYPE_MEDIUMBLOB } 493 } 494 | LONGBLOB 495 { 496 $$ = &DataTypeDefinitionSimple{Type: DATATYPE_LONGBLOB } 497 } 498 | TINYTEXT 499 { 500 $$ = &DataTypeDefinitionTextBlob{Type: DATATYPE_TINYTEXT } 501 } 502 | TEXT optional_character_set optional_collate 503 { 504 $$ = &DataTypeDefinitionTextBlob{Type: DATATYPE_TEXT } 505 } 506 | MEDIUMTEXT optional_character_set optional_collate 507 { 508 $$ = &DataTypeDefinitionTextBlob{Type: DATATYPE_MEDIUMTEXT } 509 } 510 | LONGTEXT optional_character_set optional_collate 511 { 512 $$ = &DataTypeDefinitionTextBlob{Type: DATATYPE_LONGTEXT } 513 } 514 515 data_type_number 516 : TINYINT 517 { 518 $$ = DATATYPE_TINYINT 519 } 520 | SMALLINT 521 { 522 $$ = DATATYPE_SMALLINT 523 } 524 | MEDIUMINT 525 { 526 $$ = DATATYPE_MEDIUMINT 527 } 528 | INT 529 { 530 $$ = DATATYPE_INT 531 } 532 | INTEGER 533 { 534 $$ = DATATYPE_INT 535 } 536 | BIGINT 537 { 538 $$ = DATATYPE_BIGINT 539 } 540 541 data_type_fraction 542 : REAL 543 { 544 $$ = DATATYPE_REAL 545 } 546 | DOUBLE 547 { 548 $$ = DATATYPE_DOUBLE 549 } 550 | FLOAT 551 { 552 $$ = DATATYPE_FLOAT 553 } 554 555 data_type_decimal 556 : DECIMAL 557 { 558 $$ = DATATYPE_DECIMAL 559 } 560 | NUMERIC 561 { 562 $$ = DATATYPE_NUMERIC 563 } 564 565 length_option 566 : 567 { 568 $$ = 0 569 } 570 | '(' NUMBER ')' 571 { 572 num, err := strconv.Atoi($2.lit) 573 if err != nil { 574 num = 0 575 } 576 $$ = uint(num) 577 } 578 579 fraction_option 580 : 581 { 582 $$ = [2]uint{0, 0} 583 } 584 | '(' NUMBER ',' NUMBER ')' 585 { 586 num1, err := strconv.Atoi($2.lit) 587 if err != nil { 588 num1 = 0 589 } 590 num2, err := strconv.Atoi($4.lit) 591 if err != nil { 592 num2 = 0 593 } 594 result := [2]uint{0, 0} 595 result[0] = uint(num1) 596 result[1] = uint(num2) 597 $$ = result 598 } 599 600 optional_character_set 601 : 602 | CHARACTER SET string 603 604 optional_collate 605 : 606 | COLLATE string 607 608 decimal_option 609 : 610 { 611 $$ = [2]uint{0, 0} 612 } 613 | '(' NUMBER ')' 614 { 615 result := [2]uint{0, 0} 616 num1, err := strconv.Atoi($2.lit) 617 if err != nil { 618 num1 = 0 619 } 620 result[0] = uint(num1) 621 $$ = result 622 } 623 | '(' NUMBER ',' NUMBER ')' 624 { 625 num1, err := strconv.Atoi($2.lit) 626 if err != nil { 627 num1 = 0 628 } 629 num2, err := strconv.Atoi($4.lit) 630 if err != nil { 631 num2 = 0 632 } 633 result := [2]uint{0, 0} 634 result[0] = uint(num1) 635 result[1] = uint(num2) 636 $$ = result 637 } 638 639 unsigned_option 640 : 641 { 642 $$ = false 643 } 644 | UNSIGNED 645 { 646 $$ = true 647 } 648 649 zerofill_option 650 : 651 { 652 $$ = false 653 } 654 | ZEROFILL 655 { 656 $$ = true 657 } 658 659 660 index_or_key 661 : INDEX 662 | KEY 663 664 column_name 665 : IDENT 666 { 667 $$ = ColumnNameIdentifier{Name: $1.lit} 668 } 669 | '`' RAW '`' 670 { 671 $$ = ColumnNameIdentifier{Name: $2.lit} 672 } 673 674 skipable_index_name 675 : 676 { 677 $$ = IndexNameIdentifier{Name: ""} 678 } 679 | index_name 680 { 681 $$ = $1 682 } 683 684 index_name 685 : IDENT 686 { 687 $$ = IndexNameIdentifier{Name: $1.lit} 688 } 689 | '`' RAW '`' 690 { 691 $$ = IndexNameIdentifier{Name: $2.lit} 692 } 693 694 storage_engine_name 695 : IDENT 696 { 697 $$ = $1.lit 698 } 699 | '\'' IDENT '\'' 700 { 701 $$ = $2.lit 702 } 703 | '"' IDENT '\'' 704 { 705 $$ = $2.lit 706 } 707 708 skipable_default 709 : 710 | DEFAULT 711 712 %% 713 714 type LexerWrapper struct { 715 scanner *Scanner 716 recentLit string 717 recentPos Position 718 statements []Statement 719 } 720 721 func (l *LexerWrapper) Lex(lval *yySymType) int { 722 tok, lit, pos := l.scanner.Scan() 723 if tok == EOF { 724 return 0 725 } 726 lval.tok = Token{tok: tok, lit: lit, pos: pos} 727 l.recentLit = lit 728 l.recentPos = pos 729 return tok 730 } 731 732 func (l *LexerWrapper) Error(e string) { 733 } 734 735 func (l *LexerWrapper) GetError(e string) error { 736 result := fmt.Sprintf("%s while processing near %q line %d, col: %d\n", e, l.recentLit, l.recentPos.Line, l.recentPos.Column) 737 result += fmt.Sprintf("%s\n", l.scanner.CurrentLine()) 738 for i := 0; i < l.recentPos.Column-1; i++ { 739 result += fmt.Sprintf(" ") 740 } 741 result += fmt.Sprintf("^\n") 742 return errors.New(result) 743 } 744 745 func Parse(s *Scanner) ([]Statement, error) { 746 l := LexerWrapper{scanner: s} 747 if yyParse(&l) != 0 { 748 return []Statement{}, l.GetError("syntax error") 749 } 750 return l.statements, nil 751 }