diff options
Diffstat (limited to 'sql/sql_yacc.yy')
-rw-r--r-- | sql/sql_yacc.yy | 79 |
1 files changed, 72 insertions, 7 deletions
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 83b5692d606..0dc8ed7037e 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -32,6 +32,7 @@ #define YYTHD ((THD *)yythd) #define YYLIP (& YYTHD->m_parser_state->m_lip) #define YYPS (& YYTHD->m_parser_state->m_yacc) +#define YYCSCL YYTHD->variables.character_set_client #define MYSQL_YACC #define YYINITDEPTH 100 @@ -899,10 +900,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %pure_parser /* We have threads */ /* - Currently there are 170 shift/reduce conflicts. + Currently there are 167 shift/reduce conflicts. We should not introduce new conflicts any more. */ -%expect 170 +%expect 167 /* Comments for TOKENS. @@ -1628,7 +1629,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); replace_lock_option opt_low_priority insert_lock_option load_data_lock %type <item> - literal text_literal insert_ident order_ident + literal text_literal insert_ident order_ident temporal_literal simple_ident expr opt_expr opt_else sum_expr in_sum_expr variable variable_aux bool_pri predicate bit_expr @@ -8741,7 +8742,48 @@ simple_expr: MYSQL_YYABORT; } | '{' ident expr '}' - { $$= $3; } + { + Item_string *item; + $$= NULL; + /* + If "expr" is reasonably short pure ASCII string literal, + try to parse known ODBC style date, time or timestamp literals, + e.g: + SELECT {d'2001-01-01'}; + SELECT {t'10:20:30'}; + SELECT {ts'2001-01-01 10:20:30'}; + */ + if ($3->type() == Item::STRING_ITEM && + (item= (Item_string *) $3) && + item->collation.repertoire == MY_REPERTOIRE_ASCII && + item->str_value.length() < MAX_DATE_STRING_REP_LENGTH * 4) + { + enum_field_types type= MYSQL_TYPE_STRING; + LEX_STRING *ls= &$2; + if (ls->length == 1) + { + if (ls->str[0] == 'd') /* {d'2001-01-01'} */ + type= MYSQL_TYPE_DATE; + else if (ls->str[0] == 't') /* {t'10:20:30'} */ + type= MYSQL_TYPE_TIME; + } + else if (ls->length == 2) /* {ts'2001-01-01 10:20:30'} */ + { + if (ls->str[0] == 't' && ls->str[1] == 's') + type= MYSQL_TYPE_DATETIME; + } + if (type != MYSQL_TYPE_STRING) + { + $$= create_temporal_literal(YYTHD, + item->str_value.ptr(), + item->str_value.length(), + item->str_value.charset(), + type, false); + } + } + if ($$ == NULL) + $$= $3; + } | MATCH ident_list_arg AGAINST '(' bit_expr fulltext_options ')' { $2->push_front($5); @@ -12730,6 +12772,7 @@ signed_literal: literal: text_literal { $$ = $1; } | NUM_literal { $$ = $1; } + | temporal_literal { $$= $1; } | NULL_SYM { $$ = new (YYTHD->mem_root) Item_null(); @@ -12824,9 +12867,6 @@ literal: $$= item_str; } - | DATE_SYM text_literal { $$ = $2; } - | TIME_SYM text_literal { $$ = $2; } - | TIMESTAMP text_literal { $$ = $2; } ; NUM_literal: @@ -12875,6 +12915,31 @@ NUM_literal: } ; + +temporal_literal: + DATE_SYM TEXT_STRING + { + if (!($$= create_temporal_literal(YYTHD, $2.str, $2.length, YYCSCL, + MYSQL_TYPE_DATE, true))) + MYSQL_YYABORT; + } + | TIME_SYM TEXT_STRING + { + if (!($$= create_temporal_literal(YYTHD, $2.str, $2.length, YYCSCL, + MYSQL_TYPE_TIME, true))) + MYSQL_YYABORT; + } + | TIMESTAMP TEXT_STRING + { + if (!($$= create_temporal_literal(YYTHD, $2.str, $2.length, YYCSCL, + MYSQL_TYPE_DATETIME, true))) + MYSQL_YYABORT; + } + ; + + + + /********************************************************************** ** Creating different items. **********************************************************************/ |