Support EXTRACT (#95)

* EXTRACT support

* formatting

* formatting

* formatting
This commit is contained in:
Moritz Eyssen 2018-05-23 03:02:14 +02:00 committed by mrks
parent 82e73f66d2
commit 73ed061d7d
10 changed files with 3082 additions and 3441 deletions

File diff suppressed because it is too large Load Diff

View File

@ -117,99 +117,106 @@ extern int hsql_debug;
SQL_ESCAPE = 293, SQL_ESCAPE = 293,
SQL_EXCEPT = 294, SQL_EXCEPT = 294,
SQL_EXISTS = 295, SQL_EXISTS = 295,
SQL_GLOBAL = 296, SQL_EXTRACT = 296,
SQL_HAVING = 297, SQL_GLOBAL = 297,
SQL_IMPORT = 298, SQL_HAVING = 298,
SQL_INSERT = 299, SQL_IMPORT = 299,
SQL_ISNULL = 300, SQL_INSERT = 300,
SQL_OFFSET = 301, SQL_ISNULL = 301,
SQL_RENAME = 302, SQL_OFFSET = 302,
SQL_SCHEMA = 303, SQL_RENAME = 303,
SQL_SELECT = 304, SQL_SCHEMA = 304,
SQL_SORTED = 305, SQL_SELECT = 305,
SQL_TABLES = 306, SQL_SORTED = 306,
SQL_UNIQUE = 307, SQL_TABLES = 307,
SQL_UNLOAD = 308, SQL_UNIQUE = 308,
SQL_UPDATE = 309, SQL_UNLOAD = 309,
SQL_VALUES = 310, SQL_UPDATE = 310,
SQL_AFTER = 311, SQL_VALUES = 311,
SQL_ALTER = 312, SQL_AFTER = 312,
SQL_CROSS = 313, SQL_ALTER = 313,
SQL_DELTA = 314, SQL_CROSS = 314,
SQL_GROUP = 315, SQL_DELTA = 315,
SQL_INDEX = 316, SQL_GROUP = 316,
SQL_INNER = 317, SQL_INDEX = 317,
SQL_LIMIT = 318, SQL_INNER = 318,
SQL_LOCAL = 319, SQL_LIMIT = 319,
SQL_MERGE = 320, SQL_LOCAL = 320,
SQL_MINUS = 321, SQL_MERGE = 321,
SQL_ORDER = 322, SQL_MINUS = 322,
SQL_OUTER = 323, SQL_ORDER = 323,
SQL_RIGHT = 324, SQL_OUTER = 324,
SQL_TABLE = 325, SQL_RIGHT = 325,
SQL_UNION = 326, SQL_TABLE = 326,
SQL_USING = 327, SQL_UNION = 327,
SQL_WHERE = 328, SQL_USING = 328,
SQL_CALL = 329, SQL_WHERE = 329,
SQL_CASE = 330, SQL_CALL = 330,
SQL_DATE = 331, SQL_CASE = 331,
SQL_DESC = 332, SQL_DATE = 332,
SQL_DROP = 333, SQL_DESC = 333,
SQL_ELSE = 334, SQL_DROP = 334,
SQL_FILE = 335, SQL_ELSE = 335,
SQL_FROM = 336, SQL_FILE = 336,
SQL_FULL = 337, SQL_FROM = 337,
SQL_HASH = 338, SQL_FULL = 338,
SQL_HINT = 339, SQL_HASH = 339,
SQL_INTO = 340, SQL_HINT = 340,
SQL_JOIN = 341, SQL_INTO = 341,
SQL_LEFT = 342, SQL_JOIN = 342,
SQL_LIKE = 343, SQL_LEFT = 343,
SQL_LOAD = 344, SQL_LIKE = 344,
SQL_NULL = 345, SQL_LOAD = 345,
SQL_PART = 346, SQL_NULL = 346,
SQL_PLAN = 347, SQL_PART = 347,
SQL_SHOW = 348, SQL_PLAN = 348,
SQL_TEXT = 349, SQL_SHOW = 349,
SQL_THEN = 350, SQL_TEXT = 350,
SQL_TIME = 351, SQL_THEN = 351,
SQL_VIEW = 352, SQL_TIME = 352,
SQL_WHEN = 353, SQL_VIEW = 353,
SQL_WITH = 354, SQL_WHEN = 354,
SQL_ADD = 355, SQL_WITH = 355,
SQL_ALL = 356, SQL_ADD = 356,
SQL_AND = 357, SQL_ALL = 357,
SQL_ASC = 358, SQL_AND = 358,
SQL_CSV = 359, SQL_ASC = 359,
SQL_END = 360, SQL_CSV = 360,
SQL_FOR = 361, SQL_END = 361,
SQL_INT = 362, SQL_FOR = 362,
SQL_KEY = 363, SQL_INT = 363,
SQL_NOT = 364, SQL_KEY = 364,
SQL_OFF = 365, SQL_NOT = 365,
SQL_SET = 366, SQL_OFF = 366,
SQL_TBL = 367, SQL_SET = 367,
SQL_TOP = 368, SQL_TBL = 368,
SQL_AS = 369, SQL_TOP = 369,
SQL_BY = 370, SQL_AS = 370,
SQL_IF = 371, SQL_BY = 371,
SQL_IN = 372, SQL_IF = 372,
SQL_IS = 373, SQL_IN = 373,
SQL_OF = 374, SQL_IS = 374,
SQL_ON = 375, SQL_OF = 375,
SQL_OR = 376, SQL_ON = 376,
SQL_TO = 377, SQL_OR = 377,
SQL_ARRAY = 378, SQL_TO = 378,
SQL_CONCAT = 379, SQL_ARRAY = 379,
SQL_ILIKE = 380, SQL_CONCAT = 380,
SQL_EQUALS = 381, SQL_ILIKE = 381,
SQL_NOTEQUALS = 382, SQL_SECOND = 382,
SQL_LESS = 383, SQL_MINUTE = 383,
SQL_GREATER = 384, SQL_HOUR = 384,
SQL_LESSEQ = 385, SQL_DAY = 385,
SQL_GREATEREQ = 386, SQL_MONTH = 386,
SQL_NOTNULL = 387, SQL_YEAR = 387,
SQL_UMINUS = 388 SQL_EQUALS = 388,
SQL_NOTEQUALS = 389,
SQL_LESS = 390,
SQL_GREATER = 391,
SQL_LESSEQ = 392,
SQL_GREATEREQ = 393,
SQL_NOTNULL = 394,
SQL_UMINUS = 395
}; };
#endif #endif
@ -243,6 +250,7 @@ union HSQL_STYPE
hsql::Expr* expr; hsql::Expr* expr;
hsql::OrderDescription* order; hsql::OrderDescription* order;
hsql::OrderType order_type; hsql::OrderType order_type;
hsql::DatetimeField datetime_field;
hsql::LimitDescription* limit; hsql::LimitDescription* limit;
hsql::ColumnDefinition* column_t; hsql::ColumnDefinition* column_t;
hsql::GroupByDescription* group_t; hsql::GroupByDescription* group_t;
@ -258,7 +266,7 @@ union HSQL_STYPE
std::vector<hsql::Expr*>* expr_vec; std::vector<hsql::Expr*>* expr_vec;
std::vector<hsql::OrderDescription*>* order_vec; std::vector<hsql::OrderDescription*>* order_vec;
#line 262 "bison_parser.h" /* yacc.c:1909 */ #line 270 "bison_parser.h" /* yacc.c:1909 */
}; };
typedef union HSQL_STYPE HSQL_STYPE; typedef union HSQL_STYPE HSQL_STYPE;

View File

@ -116,6 +116,7 @@ int yyerror(YYLTYPE* llocp, SQLParserResult* result, yyscan_t scanner, const cha
hsql::Expr* expr; hsql::Expr* expr;
hsql::OrderDescription* order; hsql::OrderDescription* order;
hsql::OrderType order_type; hsql::OrderType order_type;
hsql::DatetimeField datetime_field;
hsql::LimitDescription* limit; hsql::LimitDescription* limit;
hsql::ColumnDefinition* column_t; hsql::ColumnDefinition* column_t;
hsql::GroupByDescription* group_t; hsql::GroupByDescription* group_t;
@ -136,7 +137,7 @@ int yyerror(YYLTYPE* llocp, SQLParserResult* result, yyscan_t scanner, const cha
/********************************* /*********************************
** Destructor symbols ** Destructor symbols
*********************************/ *********************************/
%destructor { } <fval> <ival> <uval> <bval> <order_type> %destructor { } <fval> <ival> <uval> <bval> <order_type> <datetime_field>
%destructor { free( ($$.name) ); free( ($$.schema) ); } <table_name> %destructor { free( ($$.name) ); free( ($$.schema) ); } <table_name>
%destructor { free( ($$) ); } <sval> %destructor { free( ($$) ); } <sval>
%destructor { %destructor {
@ -163,7 +164,7 @@ int yyerror(YYLTYPE* llocp, SQLParserResult* result, yyscan_t scanner, const cha
%token CASCADE COLUMNS CONTROL DEFAULT EXECUTE EXPLAIN %token CASCADE COLUMNS CONTROL DEFAULT EXECUTE EXPLAIN
%token HISTORY INTEGER NATURAL PREPARE PRIMARY SCHEMAS %token HISTORY INTEGER NATURAL PREPARE PRIMARY SCHEMAS
%token SPATIAL VIRTUAL BEFORE COLUMN CREATE DELETE DIRECT %token SPATIAL VIRTUAL BEFORE COLUMN CREATE DELETE DIRECT
%token DOUBLE ESCAPE EXCEPT EXISTS GLOBAL HAVING IMPORT %token DOUBLE ESCAPE EXCEPT EXISTS EXTRACT GLOBAL HAVING IMPORT
%token INSERT ISNULL OFFSET RENAME SCHEMA SELECT SORTED %token INSERT ISNULL OFFSET RENAME SCHEMA SELECT SORTED
%token TABLES UNIQUE UNLOAD UPDATE VALUES AFTER ALTER CROSS %token TABLES UNIQUE UNLOAD UPDATE VALUES AFTER ALTER CROSS
%token DELTA GROUP INDEX INNER LIMIT LOCAL MERGE MINUS ORDER %token DELTA GROUP INDEX INNER LIMIT LOCAL MERGE MINUS ORDER
@ -172,7 +173,7 @@ int yyerror(YYLTYPE* llocp, SQLParserResult* result, yyscan_t scanner, const cha
%token LEFT LIKE LOAD NULL PART PLAN SHOW TEXT THEN TIME %token LEFT LIKE LOAD NULL PART PLAN SHOW TEXT THEN TIME
%token VIEW WHEN WITH ADD ALL AND ASC CSV END FOR INT KEY %token VIEW WHEN WITH ADD ALL AND ASC CSV END FOR INT KEY
%token NOT OFF SET TBL TOP AS BY IF IN IS OF ON OR TO %token NOT OFF SET TBL TOP AS BY IF IN IS OF ON OR TO
%token ARRAY CONCAT ILIKE %token ARRAY CONCAT ILIKE SECOND MINUTE HOUR DAY MONTH YEAR
/********************************* /*********************************
** Non-Terminal types (http://www.gnu.org/software/bison/manual/html_node/Type-Decl.html) ** Non-Terminal types (http://www.gnu.org/software/bison/manual/html_node/Type-Decl.html)
@ -195,7 +196,7 @@ int yyerror(YYLTYPE* llocp, SQLParserResult* result, yyscan_t scanner, const cha
%type <uval> import_file_type opt_join_type column_type %type <uval> import_file_type opt_join_type column_type
%type <table> opt_from_clause from_clause table_ref table_ref_atomic table_ref_name nonjoin_table_ref_atomic %type <table> opt_from_clause from_clause table_ref table_ref_atomic table_ref_name nonjoin_table_ref_atomic
%type <table> join_clause table_ref_name_no_alias %type <table> join_clause table_ref_name_no_alias
%type <expr> expr operand scalar_expr unary_expr binary_expr logic_expr exists_expr %type <expr> expr operand scalar_expr unary_expr binary_expr logic_expr exists_expr extract_expr
%type <expr> function_expr between_expr expr_alias param_expr %type <expr> function_expr between_expr expr_alias param_expr
%type <expr> column_name literal int_literal num_literal string_literal %type <expr> column_name literal int_literal num_literal string_literal
%type <expr> comp_expr opt_where join_condition opt_having case_expr case_list in_expr hint %type <expr> comp_expr opt_where join_condition opt_having case_expr case_list in_expr hint
@ -203,6 +204,7 @@ int yyerror(YYLTYPE* llocp, SQLParserResult* result, yyscan_t scanner, const cha
%type <limit> opt_limit opt_top %type <limit> opt_limit opt_top
%type <order> order_desc %type <order> order_desc
%type <order_type> opt_order_type %type <order_type> opt_order_type
%type <datetime_field> datetime_field
%type <column_t> column_def %type <column_t> column_def
%type <update_t> update_clause %type <update_t> update_clause
%type <group_t> opt_group %type <group_t> opt_group
@ -764,6 +766,7 @@ operand:
| binary_expr | binary_expr
| case_expr | case_expr
| function_expr | function_expr
| extract_expr
| array_expr | array_expr
| '(' select_no_paren ')' { $$ = Expr::makeSelect($2); } | '(' select_no_paren ')' { $$ = Expr::makeSelect($2); }
; ;
@ -837,9 +840,21 @@ comp_expr:
; ;
function_expr: function_expr:
IDENTIFIER '(' ')' { $$ = Expr::makeFunctionRef($1, new std::vector<Expr*>(), false); } IDENTIFIER '(' ')' { $$ = Expr::makeFunctionRef($1, new std::vector<Expr*>(), false); }
| IDENTIFIER '(' opt_distinct expr_list ')' { $$ = Expr::makeFunctionRef($1, $4, $3); } | IDENTIFIER '(' opt_distinct expr_list ')' { $$ = Expr::makeFunctionRef($1, $4, $3); }
; ;
extract_expr:
EXTRACT '(' datetime_field FROM expr ')' { $$ = Expr::makeExtract($3, $5); }
;
datetime_field:
SECOND { $$ = kDatetimeSecond; }
| MINUTE { $$ = kDatetimeMinute; }
| HOUR { $$ = kDatetimeHour; }
| DAY { $$ = kDatetimeDay; }
| MONTH { $$ = kDatetimeMonth; }
| YEAR { $$ = kDatetimeYear; }
array_expr: array_expr:
ARRAY '[' expr_list ']' { $$ = Expr::makeArray($3); } ARRAY '[' expr_list ']' { $$ = Expr::makeArray($3); }

File diff suppressed because it is too large Load Diff

View File

@ -2,9 +2,9 @@
#define hsql_HEADER_H 1 #define hsql_HEADER_H 1
#define hsql_IN_HEADER 1 #define hsql_IN_HEADER 1
#line 5 "flex_lexer.h" #line 6 "flex_lexer.h"
#line 7 "flex_lexer.h" #line 8 "flex_lexer.h"
#define YY_INT_ALIGNED short int #define YY_INT_ALIGNED short int
@ -13,245 +13,11 @@
#define FLEX_SCANNER #define FLEX_SCANNER
#define YY_FLEX_MAJOR_VERSION 2 #define YY_FLEX_MAJOR_VERSION 2
#define YY_FLEX_MINOR_VERSION 6 #define YY_FLEX_MINOR_VERSION 6
#define YY_FLEX_SUBMINOR_VERSION 4 #define YY_FLEX_SUBMINOR_VERSION 1
#if YY_FLEX_SUBMINOR_VERSION > 0 #if YY_FLEX_SUBMINOR_VERSION > 0
#define FLEX_BETA #define FLEX_BETA
#endif #endif
#ifdef yy_create_buffer
#define hsql__create_buffer_ALREADY_DEFINED
#else
#define yy_create_buffer hsql__create_buffer
#endif
#ifdef yy_delete_buffer
#define hsql__delete_buffer_ALREADY_DEFINED
#else
#define yy_delete_buffer hsql__delete_buffer
#endif
#ifdef yy_scan_buffer
#define hsql__scan_buffer_ALREADY_DEFINED
#else
#define yy_scan_buffer hsql__scan_buffer
#endif
#ifdef yy_scan_string
#define hsql__scan_string_ALREADY_DEFINED
#else
#define yy_scan_string hsql__scan_string
#endif
#ifdef yy_scan_bytes
#define hsql__scan_bytes_ALREADY_DEFINED
#else
#define yy_scan_bytes hsql__scan_bytes
#endif
#ifdef yy_init_buffer
#define hsql__init_buffer_ALREADY_DEFINED
#else
#define yy_init_buffer hsql__init_buffer
#endif
#ifdef yy_flush_buffer
#define hsql__flush_buffer_ALREADY_DEFINED
#else
#define yy_flush_buffer hsql__flush_buffer
#endif
#ifdef yy_load_buffer_state
#define hsql__load_buffer_state_ALREADY_DEFINED
#else
#define yy_load_buffer_state hsql__load_buffer_state
#endif
#ifdef yy_switch_to_buffer
#define hsql__switch_to_buffer_ALREADY_DEFINED
#else
#define yy_switch_to_buffer hsql__switch_to_buffer
#endif
#ifdef yypush_buffer_state
#define hsql_push_buffer_state_ALREADY_DEFINED
#else
#define yypush_buffer_state hsql_push_buffer_state
#endif
#ifdef yypop_buffer_state
#define hsql_pop_buffer_state_ALREADY_DEFINED
#else
#define yypop_buffer_state hsql_pop_buffer_state
#endif
#ifdef yyensure_buffer_stack
#define hsql_ensure_buffer_stack_ALREADY_DEFINED
#else
#define yyensure_buffer_stack hsql_ensure_buffer_stack
#endif
#ifdef yylex
#define hsql_lex_ALREADY_DEFINED
#else
#define yylex hsql_lex
#endif
#ifdef yyrestart
#define hsql_restart_ALREADY_DEFINED
#else
#define yyrestart hsql_restart
#endif
#ifdef yylex_init
#define hsql_lex_init_ALREADY_DEFINED
#else
#define yylex_init hsql_lex_init
#endif
#ifdef yylex_init_extra
#define hsql_lex_init_extra_ALREADY_DEFINED
#else
#define yylex_init_extra hsql_lex_init_extra
#endif
#ifdef yylex_destroy
#define hsql_lex_destroy_ALREADY_DEFINED
#else
#define yylex_destroy hsql_lex_destroy
#endif
#ifdef yyget_debug
#define hsql_get_debug_ALREADY_DEFINED
#else
#define yyget_debug hsql_get_debug
#endif
#ifdef yyset_debug
#define hsql_set_debug_ALREADY_DEFINED
#else
#define yyset_debug hsql_set_debug
#endif
#ifdef yyget_extra
#define hsql_get_extra_ALREADY_DEFINED
#else
#define yyget_extra hsql_get_extra
#endif
#ifdef yyset_extra
#define hsql_set_extra_ALREADY_DEFINED
#else
#define yyset_extra hsql_set_extra
#endif
#ifdef yyget_in
#define hsql_get_in_ALREADY_DEFINED
#else
#define yyget_in hsql_get_in
#endif
#ifdef yyset_in
#define hsql_set_in_ALREADY_DEFINED
#else
#define yyset_in hsql_set_in
#endif
#ifdef yyget_out
#define hsql_get_out_ALREADY_DEFINED
#else
#define yyget_out hsql_get_out
#endif
#ifdef yyset_out
#define hsql_set_out_ALREADY_DEFINED
#else
#define yyset_out hsql_set_out
#endif
#ifdef yyget_leng
#define hsql_get_leng_ALREADY_DEFINED
#else
#define yyget_leng hsql_get_leng
#endif
#ifdef yyget_text
#define hsql_get_text_ALREADY_DEFINED
#else
#define yyget_text hsql_get_text
#endif
#ifdef yyget_lineno
#define hsql_get_lineno_ALREADY_DEFINED
#else
#define yyget_lineno hsql_get_lineno
#endif
#ifdef yyset_lineno
#define hsql_set_lineno_ALREADY_DEFINED
#else
#define yyset_lineno hsql_set_lineno
#endif
#ifdef yyget_column
#define hsql_get_column_ALREADY_DEFINED
#else
#define yyget_column hsql_get_column
#endif
#ifdef yyset_column
#define hsql_set_column_ALREADY_DEFINED
#else
#define yyset_column hsql_set_column
#endif
#ifdef yywrap
#define hsql_wrap_ALREADY_DEFINED
#else
#define yywrap hsql_wrap
#endif
#ifdef yyget_lval
#define hsql_get_lval_ALREADY_DEFINED
#else
#define yyget_lval hsql_get_lval
#endif
#ifdef yyset_lval
#define hsql_set_lval_ALREADY_DEFINED
#else
#define yyset_lval hsql_set_lval
#endif
#ifdef yyget_lloc
#define hsql_get_lloc_ALREADY_DEFINED
#else
#define yyget_lloc hsql_get_lloc
#endif
#ifdef yyset_lloc
#define hsql_set_lloc_ALREADY_DEFINED
#else
#define yyset_lloc hsql_set_lloc
#endif
#ifdef yyalloc
#define hsql_alloc_ALREADY_DEFINED
#else
#define yyalloc hsql_alloc
#endif
#ifdef yyrealloc
#define hsql_realloc_ALREADY_DEFINED
#else
#define yyrealloc hsql_realloc
#endif
#ifdef yyfree
#define hsql_free_ALREADY_DEFINED
#else
#define yyfree hsql_free
#endif
/* First, we deal with platform-specific or compiler-specific issues. */ /* First, we deal with platform-specific or compiler-specific issues. */
/* begin standard C headers. */ /* begin standard C headers. */
@ -322,16 +88,10 @@ typedef unsigned int flex_uint32_t;
#define UINT32_MAX (4294967295U) #define UINT32_MAX (4294967295U)
#endif #endif
#ifndef SIZE_MAX
#define SIZE_MAX (~(size_t)0)
#endif
#endif /* ! C99 */ #endif /* ! C99 */
#endif /* ! FLEXINT_H */ #endif /* ! FLEXINT_H */
/* begin standard C++ headers. */
/* TODO: this is always defined, so inline it */ /* TODO: this is always defined, so inline it */
#define yyconst const #define yyconst const
@ -432,21 +192,21 @@ struct yy_buffer_state
}; };
#endif /* !YY_STRUCT_YY_BUFFER_STATE */ #endif /* !YY_STRUCT_YY_BUFFER_STATE */
void yyrestart ( FILE *input_file , yyscan_t yyscanner ); void hsql_restart (FILE *input_file ,yyscan_t yyscanner );
void yy_switch_to_buffer ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner ); void hsql__switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size , yyscan_t yyscanner ); YY_BUFFER_STATE hsql__create_buffer (FILE *file,int size ,yyscan_t yyscanner );
void yy_delete_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner ); void hsql__delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
void yy_flush_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner ); void hsql__flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
void yypush_buffer_state ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner ); void hsql_push_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
void yypop_buffer_state ( yyscan_t yyscanner ); void hsql_pop_buffer_state (yyscan_t yyscanner );
YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size , yyscan_t yyscanner ); YY_BUFFER_STATE hsql__scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
YY_BUFFER_STATE yy_scan_string ( const char *yy_str , yyscan_t yyscanner ); YY_BUFFER_STATE hsql__scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len , yyscan_t yyscanner ); YY_BUFFER_STATE hsql__scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner );
void *yyalloc ( yy_size_t , yyscan_t yyscanner ); void *hsql_alloc (yy_size_t ,yyscan_t yyscanner );
void *yyrealloc ( void *, yy_size_t , yyscan_t yyscanner ); void *hsql_realloc (void *,yy_size_t ,yyscan_t yyscanner );
void yyfree ( void * , yyscan_t yyscanner ); void hsql_free (void * ,yyscan_t yyscanner );
/* Begin user sect3 */ /* Begin user sect3 */
@ -473,50 +233,50 @@ void yyfree ( void * , yyscan_t yyscanner );
#define YY_EXTRA_TYPE void * #define YY_EXTRA_TYPE void *
#endif #endif
int yylex_init (yyscan_t* scanner); int hsql_lex_init (yyscan_t* scanner);
int yylex_init_extra ( YY_EXTRA_TYPE user_defined, yyscan_t* scanner); int hsql_lex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
/* Accessor methods to globals. /* Accessor methods to globals.
These are made visible to non-reentrant scanners for convenience. */ These are made visible to non-reentrant scanners for convenience. */
int yylex_destroy ( yyscan_t yyscanner ); int hsql_lex_destroy (yyscan_t yyscanner );
int yyget_debug ( yyscan_t yyscanner ); int hsql_get_debug (yyscan_t yyscanner );
void yyset_debug ( int debug_flag , yyscan_t yyscanner ); void hsql_set_debug (int debug_flag ,yyscan_t yyscanner );
YY_EXTRA_TYPE yyget_extra ( yyscan_t yyscanner ); YY_EXTRA_TYPE hsql_get_extra (yyscan_t yyscanner );
void yyset_extra ( YY_EXTRA_TYPE user_defined , yyscan_t yyscanner ); void hsql_set_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
FILE *yyget_in ( yyscan_t yyscanner ); FILE *hsql_get_in (yyscan_t yyscanner );
void yyset_in ( FILE * _in_str , yyscan_t yyscanner ); void hsql_set_in (FILE * _in_str ,yyscan_t yyscanner );
FILE *yyget_out ( yyscan_t yyscanner ); FILE *hsql_get_out (yyscan_t yyscanner );
void yyset_out ( FILE * _out_str , yyscan_t yyscanner ); void hsql_set_out (FILE * _out_str ,yyscan_t yyscanner );
int yyget_leng ( yyscan_t yyscanner ); int hsql_get_leng (yyscan_t yyscanner );
char *yyget_text ( yyscan_t yyscanner ); char *hsql_get_text (yyscan_t yyscanner );
int yyget_lineno ( yyscan_t yyscanner ); int hsql_get_lineno (yyscan_t yyscanner );
void yyset_lineno ( int _line_number , yyscan_t yyscanner ); void hsql_set_lineno (int _line_number ,yyscan_t yyscanner );
int yyget_column ( yyscan_t yyscanner ); int hsql_get_column (yyscan_t yyscanner );
void yyset_column ( int _column_no , yyscan_t yyscanner ); void hsql_set_column (int _column_no ,yyscan_t yyscanner );
YYSTYPE * yyget_lval ( yyscan_t yyscanner ); YYSTYPE * hsql_get_lval (yyscan_t yyscanner );
void yyset_lval ( YYSTYPE * yylval_param , yyscan_t yyscanner ); void hsql_set_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner );
YYLTYPE *yyget_lloc ( yyscan_t yyscanner ); YYLTYPE *hsql_get_lloc (yyscan_t yyscanner );
void yyset_lloc ( YYLTYPE * yylloc_param , yyscan_t yyscanner ); void hsql_set_lloc (YYLTYPE * yylloc_param ,yyscan_t yyscanner );
/* Macros after this point can all be overridden by user definitions in /* Macros after this point can all be overridden by user definitions in
* section 1. * section 1.
@ -524,18 +284,18 @@ void yyset_lval ( YYSTYPE * yylval_param , yyscan_t yyscanner );
#ifndef YY_SKIP_YYWRAP #ifndef YY_SKIP_YYWRAP
#ifdef __cplusplus #ifdef __cplusplus
extern "C" int yywrap ( yyscan_t yyscanner ); extern "C" int hsql_wrap (yyscan_t yyscanner );
#else #else
extern int yywrap ( yyscan_t yyscanner ); extern int hsql_wrap (yyscan_t yyscanner );
#endif #endif
#endif #endif
#ifndef yytext_ptr #ifndef yytext_ptr
static void yy_flex_strncpy ( char *, const char *, int , yyscan_t yyscanner); static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
#endif #endif
#ifdef YY_NEED_STRLEN #ifdef YY_NEED_STRLEN
static int yy_flex_strlen ( const char * , yyscan_t yyscanner); static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
#endif #endif
#ifndef YY_NO_INPUT #ifndef YY_NO_INPUT
@ -563,10 +323,10 @@ static int yy_flex_strlen ( const char * , yyscan_t yyscanner);
#ifndef YY_DECL #ifndef YY_DECL
#define YY_DECL_IS_OURS 1 #define YY_DECL_IS_OURS 1
extern int yylex \ extern int hsql_lex \
(YYSTYPE * yylval_param, YYLTYPE * yylloc_param , yyscan_t yyscanner); (YYSTYPE * yylval_param,YYLTYPE * yylloc_param ,yyscan_t yyscanner);
#define YY_DECL int yylex \ #define YY_DECL int hsql_lex \
(YYSTYPE * yylval_param, YYLTYPE * yylloc_param , yyscan_t yyscanner) (YYSTYPE * yylval_param, YYLTYPE * yylloc_param , yyscan_t yyscanner)
#endif /* !YY_DECL */ #endif /* !YY_DECL */
@ -584,154 +344,9 @@ extern int yylex \
#undef YY_DECL #undef YY_DECL
#endif #endif
#ifndef hsql__create_buffer_ALREADY_DEFINED #line 226 "flex_lexer.l"
#undef yy_create_buffer
#endif
#ifndef hsql__delete_buffer_ALREADY_DEFINED
#undef yy_delete_buffer
#endif
#ifndef hsql__scan_buffer_ALREADY_DEFINED
#undef yy_scan_buffer
#endif
#ifndef hsql__scan_string_ALREADY_DEFINED
#undef yy_scan_string
#endif
#ifndef hsql__scan_bytes_ALREADY_DEFINED
#undef yy_scan_bytes
#endif
#ifndef hsql__init_buffer_ALREADY_DEFINED
#undef yy_init_buffer
#endif
#ifndef hsql__flush_buffer_ALREADY_DEFINED
#undef yy_flush_buffer
#endif
#ifndef hsql__load_buffer_state_ALREADY_DEFINED
#undef yy_load_buffer_state
#endif
#ifndef hsql__switch_to_buffer_ALREADY_DEFINED
#undef yy_switch_to_buffer
#endif
#ifndef hsql_push_buffer_state_ALREADY_DEFINED
#undef yypush_buffer_state
#endif
#ifndef hsql_pop_buffer_state_ALREADY_DEFINED
#undef yypop_buffer_state
#endif
#ifndef hsql_ensure_buffer_stack_ALREADY_DEFINED
#undef yyensure_buffer_stack
#endif
#ifndef hsql_lex_ALREADY_DEFINED
#undef yylex
#endif
#ifndef hsql_restart_ALREADY_DEFINED
#undef yyrestart
#endif
#ifndef hsql_lex_init_ALREADY_DEFINED
#undef yylex_init
#endif
#ifndef hsql_lex_init_extra_ALREADY_DEFINED
#undef yylex_init_extra
#endif
#ifndef hsql_lex_destroy_ALREADY_DEFINED
#undef yylex_destroy
#endif
#ifndef hsql_get_debug_ALREADY_DEFINED
#undef yyget_debug
#endif
#ifndef hsql_set_debug_ALREADY_DEFINED
#undef yyset_debug
#endif
#ifndef hsql_get_extra_ALREADY_DEFINED
#undef yyget_extra
#endif
#ifndef hsql_set_extra_ALREADY_DEFINED
#undef yyset_extra
#endif
#ifndef hsql_get_in_ALREADY_DEFINED
#undef yyget_in
#endif
#ifndef hsql_set_in_ALREADY_DEFINED
#undef yyset_in
#endif
#ifndef hsql_get_out_ALREADY_DEFINED
#undef yyget_out
#endif
#ifndef hsql_set_out_ALREADY_DEFINED
#undef yyset_out
#endif
#ifndef hsql_get_leng_ALREADY_DEFINED
#undef yyget_leng
#endif
#ifndef hsql_get_text_ALREADY_DEFINED
#undef yyget_text
#endif
#ifndef hsql_get_lineno_ALREADY_DEFINED
#undef yyget_lineno
#endif
#ifndef hsql_set_lineno_ALREADY_DEFINED
#undef yyset_lineno
#endif
#ifndef hsql_get_column_ALREADY_DEFINED
#undef yyget_column
#endif
#ifndef hsql_set_column_ALREADY_DEFINED
#undef yyset_column
#endif
#ifndef hsql_wrap_ALREADY_DEFINED
#undef yywrap
#endif
#ifndef hsql_get_lval_ALREADY_DEFINED
#undef yyget_lval
#endif
#ifndef hsql_set_lval_ALREADY_DEFINED
#undef yyset_lval
#endif
#ifndef hsql_get_lloc_ALREADY_DEFINED
#undef yyget_lloc
#endif
#ifndef hsql_set_lloc_ALREADY_DEFINED
#undef yyset_lloc
#endif
#ifndef hsql_alloc_ALREADY_DEFINED
#undef yyalloc
#endif
#ifndef hsql_realloc_ALREADY_DEFINED
#undef yyrealloc
#endif
#ifndef hsql_free_ALREADY_DEFINED
#undef yyfree
#endif
#ifndef hsql_text_ALREADY_DEFINED
#undef yytext
#endif
#ifndef hsql_leng_ALREADY_DEFINED
#undef yyleng
#endif
#ifndef hsql_in_ALREADY_DEFINED
#undef yyin
#endif
#ifndef hsql_out_ALREADY_DEFINED
#undef yyout
#endif
#ifndef hsql__flex_debug_ALREADY_DEFINED
#undef yy_flex_debug
#endif
#ifndef hsql_lineno_ALREADY_DEFINED
#undef yylineno
#endif
#ifndef hsql_tables_fload_ALREADY_DEFINED
#undef yytables_fload
#endif
#ifndef hsql_tables_destroy_ALREADY_DEFINED
#undef yytables_destroy
#endif
#ifndef hsql_TABLES_NAME_ALREADY_DEFINED
#undef yyTABLES_NAME
#endif
#line 219 "flex_lexer.l"
#line 735 "flex_lexer.h" #line 351 "flex_lexer.h"
#undef hsql_IN_HEADER #undef hsql_IN_HEADER
#endif /* hsql_HEADER_H */ #endif /* hsql_HEADER_H */

View File

@ -90,6 +90,7 @@ DOUBLE TOKEN(DOUBLE)
ESCAPE TOKEN(ESCAPE) ESCAPE TOKEN(ESCAPE)
EXCEPT TOKEN(EXCEPT) EXCEPT TOKEN(EXCEPT)
EXISTS TOKEN(EXISTS) EXISTS TOKEN(EXISTS)
EXTRACT TOKEN(EXTRACT)
GLOBAL TOKEN(GLOBAL) GLOBAL TOKEN(GLOBAL)
HAVING TOKEN(HAVING) HAVING TOKEN(HAVING)
IMPORT TOKEN(IMPORT) IMPORT TOKEN(IMPORT)
@ -174,6 +175,12 @@ OF TOKEN(OF)
ON TOKEN(ON) ON TOKEN(ON)
OR TOKEN(OR) OR TOKEN(OR)
TO TOKEN(TO) TO TOKEN(TO)
SECOND TOKEN(SECOND)
MINUTE TOKEN(MINUTE)
HOUR TOKEN(HOUR)
DAY TOKEN(DAY)
MONTH TOKEN(MONTH)
YEAR TOKEN(YEAR)
/* Allow =/== see https://sqlite.org/lang_expr.html#collateop */ /* Allow =/== see https://sqlite.org/lang_expr.html#collateop */
"==" TOKEN(EQUALS) "==" TOKEN(EQUALS)

View File

@ -18,6 +18,7 @@ namespace hsql {
fval(0), fval(0),
ival(0), ival(0),
ival2(0), ival2(0),
datetimeField(kDatetimeNone),
opType(kOpNone), opType(kOpNone),
distinct(false) {}; distinct(false) {};
@ -208,6 +209,14 @@ namespace hsql {
return e; return e;
} }
Expr* Expr::makeExtract(DatetimeField datetimeField, Expr* expr) {
Expr* e = new Expr(kExprFunctionRef);
e->name = strdup("EXTRACT");
e->datetimeField = datetimeField;
e->expr = expr;
return e;
}
bool Expr::isType(ExprType exprType) const { bool Expr::isType(ExprType exprType) const {
return exprType == type; return exprType == type;
} }

View File

@ -25,7 +25,8 @@ namespace hsql {
kExprSelect, kExprSelect,
kExprHint, kExprHint,
kExprArray, kExprArray,
kExprArrayIndex kExprArrayIndex,
kExprDatetimeField
}; };
// Operator types. These are important for expressions of type kExprOperator. // Operator types. These are important for expressions of type kExprOperator.
@ -68,6 +69,16 @@ namespace hsql {
kOpExists kOpExists
}; };
enum DatetimeField {
kDatetimeNone,
kDatetimeSecond,
kDatetimeMinute,
kDatetimeHour,
kDatetimeDay,
kDatetimeMonth,
kDatetimeYear,
};
typedef struct Expr Expr; typedef struct Expr Expr;
// Represents SQL expressions (i.e. literals, operators, column_refs). // Represents SQL expressions (i.e. literals, operators, column_refs).
@ -90,6 +101,7 @@ namespace hsql {
float fval; float fval;
int64_t ival; int64_t ival;
int64_t ival2; int64_t ival2;
DatetimeField datetimeField;
OperatorType opType; OperatorType opType;
bool distinct; bool distinct;
@ -156,6 +168,8 @@ namespace hsql {
static Expr* makeInOperator(Expr* expr, std::vector<Expr*>* exprList); static Expr* makeInOperator(Expr* expr, std::vector<Expr*>* exprList);
static Expr* makeInOperator(Expr* expr, SelectStatement* select); static Expr* makeInOperator(Expr* expr, SelectStatement* select);
static Expr* makeExtract(DatetimeField datetimeField1, Expr* expr);
}; };
// Zero initializes an Expr object and assigns it to a space in the heap // Zero initializes an Expr object and assigns it to a space in the heap

View File

@ -7,7 +7,7 @@ SELECT a FROM some_schema.foo WHERE a > 12 OR b > 3 AND NOT c LIMIT 10
SELECT col1 AS myname, col2, 'test' FROM "table", foo AS t WHERE age > 12 AND zipcode = 12345 GROUP BY col1; SELECT col1 AS myname, col2, 'test' FROM "table", foo AS t WHERE age > 12 AND zipcode = 12345 GROUP BY col1;
SELECT * from "table" JOIN table2 ON a = b WHERE (b OR NOT a) AND a = 12.5 SELECT * from "table" JOIN table2 ON a = b WHERE (b OR NOT a) AND a = 12.5
(SELECT a FROM foo WHERE a > 12 OR b > 3 AND c NOT LIKE 's%' LIMIT 10); (SELECT a FROM foo WHERE a > 12 OR b > 3 AND c NOT LIKE 's%' LIMIT 10);
SELECT * FROM "table" LIMIT 10 OFFSET 10; SELECT * FROM second; SELECT * FROM "table" LIMIT 10 OFFSET 10; SELECT * FROM another;
SELECT * FROM t1 UNION SELECT * FROM t2 ORDER BY col1; SELECT * FROM t1 UNION SELECT * FROM t2 ORDER BY col1;
SELECT * FROM (SELECT * FROM t1); SELECT * FROM (SELECT * FROM t1);
SELECT * FROM t1 UNION (SELECT * FROM t2 UNION SELECT * FROM t3) ORDER BY col1; SELECT * FROM t1 UNION (SELECT * FROM t2 UNION SELECT * FROM t3) ORDER BY col1;

View File

@ -542,6 +542,42 @@ TEST(SetLimitOffset) {
ASSERT_EQ(stmt->limit->offset, kNoOffset); ASSERT_EQ(stmt->limit->offset, kNoOffset);
} }
TEST(Extract) {
SelectStatement* stmt;
TEST_PARSE_SQL_QUERY("select extract(year from dc) FROM t;"
"select x, extract(month from dc) AS t FROM t;"
"select x FROM t WHERE extract(minute from dc) > 2011;",
result, 3);
stmt = (SelectStatement*) result.getStatement(0);
ASSERT_TRUE(stmt->selectList);
ASSERT_EQ(stmt->selectList->size(), 1u);
ASSERT_EQ(stmt->selectList->at(0)->type, kExprFunctionRef);
ASSERT_EQ(stmt->selectList->at(0)->name, std::string("EXTRACT"));
ASSERT_EQ(stmt->selectList->at(0)->datetimeField, kDatetimeYear);
ASSERT_TRUE(stmt->selectList->at(0)->expr);
ASSERT_EQ(stmt->selectList->at(0)->expr->type, kExprColumnRef);
stmt = (SelectStatement*) result.getStatement(1);
ASSERT_TRUE(stmt->selectList);
ASSERT_EQ(stmt->selectList->size(), 2u);
ASSERT_EQ(stmt->selectList->at(1)->type, kExprFunctionRef);
ASSERT_EQ(stmt->selectList->at(1)->name, std::string("EXTRACT"));
ASSERT_EQ(stmt->selectList->at(1)->datetimeField, kDatetimeMonth);
ASSERT_TRUE(stmt->selectList->at(1)->expr);
ASSERT_EQ(stmt->selectList->at(1)->expr->type, kExprColumnRef);
ASSERT_TRUE(stmt->selectList->at(1)->alias);
ASSERT_EQ(stmt->selectList->at(1)->alias, std::string("t"));
stmt = (SelectStatement*) result.getStatement(2);
ASSERT_TRUE(stmt->whereClause);
ASSERT_TRUE(stmt->whereClause->expr);
ASSERT_EQ(stmt->whereClause->expr->type, kExprFunctionRef);
ASSERT_EQ(stmt->whereClause->expr->name, std::string("EXTRACT"));
ASSERT_EQ(stmt->whereClause->expr->datetimeField, kDatetimeMinute);
}
TEST(NoFromClause) { TEST(NoFromClause) {
TEST_PARSE_SINGLE_SQL( TEST_PARSE_SINGLE_SQL(
"SELECT 1 + 2;", "SELECT 1 + 2;",
@ -560,4 +596,3 @@ TEST(NoFromClause) {
ASSERT_EQ(stmt->selectList->at(0)->expr->type, kExprLiteralInt); ASSERT_EQ(stmt->selectList->at(0)->expr->type, kExprLiteralInt);
ASSERT_EQ(stmt->selectList->at(0)->expr2->type, kExprLiteralInt); ASSERT_EQ(stmt->selectList->at(0)->expr2->type, kExprLiteralInt);
} }