Merge pull request #153 from msiomkin/cast-as-type

Add support of CAST(expression AS datatype(length))
Add DATETIME
This commit is contained in:
mrks 2020-06-18 12:45:46 +02:00 committed by GitHub
commit 2efd12d78c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 3587 additions and 3036 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,8 @@
/* A Bison parser, made by GNU Bison 3.4.2. */ /* A Bison parser, made by GNU Bison 3.6.4. */
/* Bison interface for Yacc-like parsers in C /* Bison interface for Yacc-like parsers in C
Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2019 Free Software Foundation, Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 Free Software Foundation,
Inc. Inc.
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
@ -31,8 +31,9 @@
This special exception was added by the Free Software Foundation in This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */ version 2.2 of Bison. */
/* Undocumented macros, especially those whose name start with YY_, /* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual,
are private implementation details. Do not rely on them. */ especially those whose name start with YY_ or yy_. They are
private implementation details that can be changed or removed. */
#ifndef YY_HSQL_BISON_PARSER_H_INCLUDED #ifndef YY_HSQL_BISON_PARSER_H_INCLUDED
# define YY_HSQL_BISON_PARSER_H_INCLUDED # define YY_HSQL_BISON_PARSER_H_INCLUDED
@ -76,161 +77,168 @@ extern int hsql_debug;
} \ } \
} }
#line 80 "bison_parser.h" #line 81 "bison_parser.h"
/* Token type. */ /* Token kinds. */
#ifndef HSQL_TOKENTYPE #ifndef HSQL_TOKENTYPE
# define HSQL_TOKENTYPE # define HSQL_TOKENTYPE
enum hsql_tokentype enum hsql_tokentype
{ {
SQL_IDENTIFIER = 258, SQL_HSQL_EMPTY = -2,
SQL_STRING = 259, SQL_YYEOF = 0, /* "end of file" */
SQL_FLOATVAL = 260, SQL_HSQL_error = 256, /* error */
SQL_INTVAL = 261, SQL_HSQL_UNDEF = 257, /* "invalid token" */
SQL_DEALLOCATE = 262, SQL_IDENTIFIER = 258, /* IDENTIFIER */
SQL_PARAMETERS = 263, SQL_STRING = 259, /* STRING */
SQL_INTERSECT = 264, SQL_FLOATVAL = 260, /* FLOATVAL */
SQL_TEMPORARY = 265, SQL_INTVAL = 261, /* INTVAL */
SQL_TIMESTAMP = 266, SQL_DEALLOCATE = 262, /* DEALLOCATE */
SQL_DISTINCT = 267, SQL_PARAMETERS = 263, /* PARAMETERS */
SQL_NVARCHAR = 268, SQL_INTERSECT = 264, /* INTERSECT */
SQL_RESTRICT = 269, SQL_TEMPORARY = 265, /* TEMPORARY */
SQL_TRUNCATE = 270, SQL_TIMESTAMP = 266, /* TIMESTAMP */
SQL_ANALYZE = 271, SQL_DISTINCT = 267, /* DISTINCT */
SQL_BETWEEN = 272, SQL_NVARCHAR = 268, /* NVARCHAR */
SQL_CASCADE = 273, SQL_RESTRICT = 269, /* RESTRICT */
SQL_COLUMNS = 274, SQL_TRUNCATE = 270, /* TRUNCATE */
SQL_CONTROL = 275, SQL_ANALYZE = 271, /* ANALYZE */
SQL_DEFAULT = 276, SQL_BETWEEN = 272, /* BETWEEN */
SQL_EXECUTE = 277, SQL_CASCADE = 273, /* CASCADE */
SQL_EXPLAIN = 278, SQL_COLUMNS = 274, /* COLUMNS */
SQL_INTEGER = 279, SQL_CONTROL = 275, /* CONTROL */
SQL_NATURAL = 280, SQL_DEFAULT = 276, /* DEFAULT */
SQL_PREPARE = 281, SQL_EXECUTE = 277, /* EXECUTE */
SQL_PRIMARY = 282, SQL_EXPLAIN = 278, /* EXPLAIN */
SQL_SCHEMAS = 283, SQL_INTEGER = 279, /* INTEGER */
SQL_SPATIAL = 284, SQL_NATURAL = 280, /* NATURAL */
SQL_VARCHAR = 285, SQL_PREPARE = 281, /* PREPARE */
SQL_VIRTUAL = 286, SQL_PRIMARY = 282, /* PRIMARY */
SQL_DESCRIBE = 287, SQL_SCHEMAS = 283, /* SCHEMAS */
SQL_BEFORE = 288, SQL_SPATIAL = 284, /* SPATIAL */
SQL_COLUMN = 289, SQL_VARCHAR = 285, /* VARCHAR */
SQL_CREATE = 290, SQL_VIRTUAL = 286, /* VIRTUAL */
SQL_DELETE = 291, SQL_DESCRIBE = 287, /* DESCRIBE */
SQL_DIRECT = 292, SQL_BEFORE = 288, /* BEFORE */
SQL_DOUBLE = 293, SQL_COLUMN = 289, /* COLUMN */
SQL_ESCAPE = 294, SQL_CREATE = 290, /* CREATE */
SQL_EXCEPT = 295, SQL_DELETE = 291, /* DELETE */
SQL_EXISTS = 296, SQL_DIRECT = 292, /* DIRECT */
SQL_EXTRACT = 297, SQL_DOUBLE = 293, /* DOUBLE */
SQL_FORMAT = 298, SQL_ESCAPE = 294, /* ESCAPE */
SQL_GLOBAL = 299, SQL_EXCEPT = 295, /* EXCEPT */
SQL_HAVING = 300, SQL_EXISTS = 296, /* EXISTS */
SQL_IMPORT = 301, SQL_EXTRACT = 297, /* EXTRACT */
SQL_INSERT = 302, SQL_CAST = 298, /* CAST */
SQL_ISNULL = 303, SQL_FORMAT = 299, /* FORMAT */
SQL_OFFSET = 304, SQL_GLOBAL = 300, /* GLOBAL */
SQL_RENAME = 305, SQL_HAVING = 301, /* HAVING */
SQL_SCHEMA = 306, SQL_IMPORT = 302, /* IMPORT */
SQL_SELECT = 307, SQL_INSERT = 303, /* INSERT */
SQL_SORTED = 308, SQL_ISNULL = 304, /* ISNULL */
SQL_TABLES = 309, SQL_OFFSET = 305, /* OFFSET */
SQL_UNIQUE = 310, SQL_RENAME = 306, /* RENAME */
SQL_UNLOAD = 311, SQL_SCHEMA = 307, /* SCHEMA */
SQL_UPDATE = 312, SQL_SELECT = 308, /* SELECT */
SQL_VALUES = 313, SQL_SORTED = 309, /* SORTED */
SQL_AFTER = 314, SQL_TABLES = 310, /* TABLES */
SQL_ALTER = 315, SQL_UNIQUE = 311, /* UNIQUE */
SQL_CROSS = 316, SQL_UNLOAD = 312, /* UNLOAD */
SQL_DELTA = 317, SQL_UPDATE = 313, /* UPDATE */
SQL_FLOAT = 318, SQL_VALUES = 314, /* VALUES */
SQL_GROUP = 319, SQL_AFTER = 315, /* AFTER */
SQL_INDEX = 320, SQL_ALTER = 316, /* ALTER */
SQL_INNER = 321, SQL_CROSS = 317, /* CROSS */
SQL_LIMIT = 322, SQL_DELTA = 318, /* DELTA */
SQL_LOCAL = 323, SQL_FLOAT = 319, /* FLOAT */
SQL_MERGE = 324, SQL_GROUP = 320, /* GROUP */
SQL_MINUS = 325, SQL_INDEX = 321, /* INDEX */
SQL_ORDER = 326, SQL_INNER = 322, /* INNER */
SQL_OUTER = 327, SQL_LIMIT = 323, /* LIMIT */
SQL_RIGHT = 328, SQL_LOCAL = 324, /* LOCAL */
SQL_TABLE = 329, SQL_MERGE = 325, /* MERGE */
SQL_UNION = 330, SQL_MINUS = 326, /* MINUS */
SQL_USING = 331, SQL_ORDER = 327, /* ORDER */
SQL_WHERE = 332, SQL_OUTER = 328, /* OUTER */
SQL_CALL = 333, SQL_RIGHT = 329, /* RIGHT */
SQL_CASE = 334, SQL_TABLE = 330, /* TABLE */
SQL_CHAR = 335, SQL_UNION = 331, /* UNION */
SQL_COPY = 336, SQL_USING = 332, /* USING */
SQL_DATE = 337, SQL_WHERE = 333, /* WHERE */
SQL_DESC = 338, SQL_CALL = 334, /* CALL */
SQL_DROP = 339, SQL_CASE = 335, /* CASE */
SQL_ELSE = 340, SQL_CHAR = 336, /* CHAR */
SQL_FILE = 341, SQL_COPY = 337, /* COPY */
SQL_FROM = 342, SQL_DATE = 338, /* DATE */
SQL_FULL = 343, SQL_DATETIME = 339, /* DATETIME */
SQL_HASH = 344, SQL_DESC = 340, /* DESC */
SQL_HINT = 345, SQL_DROP = 341, /* DROP */
SQL_INTO = 346, SQL_ELSE = 342, /* ELSE */
SQL_JOIN = 347, SQL_FILE = 343, /* FILE */
SQL_LEFT = 348, SQL_FROM = 344, /* FROM */
SQL_LIKE = 349, SQL_FULL = 345, /* FULL */
SQL_LOAD = 350, SQL_HASH = 346, /* HASH */
SQL_LONG = 351, SQL_HINT = 347, /* HINT */
SQL_NULL = 352, SQL_INTO = 348, /* INTO */
SQL_PLAN = 353, SQL_JOIN = 349, /* JOIN */
SQL_SHOW = 354, SQL_LEFT = 350, /* LEFT */
SQL_TEXT = 355, SQL_LIKE = 351, /* LIKE */
SQL_THEN = 356, SQL_LOAD = 352, /* LOAD */
SQL_TIME = 357, SQL_LONG = 353, /* LONG */
SQL_VIEW = 358, SQL_NULL = 354, /* NULL */
SQL_WHEN = 359, SQL_PLAN = 355, /* PLAN */
SQL_WITH = 360, SQL_SHOW = 356, /* SHOW */
SQL_ADD = 361, SQL_TEXT = 357, /* TEXT */
SQL_ALL = 362, SQL_THEN = 358, /* THEN */
SQL_AND = 363, SQL_TIME = 359, /* TIME */
SQL_ASC = 364, SQL_VIEW = 360, /* VIEW */
SQL_END = 365, SQL_WHEN = 361, /* WHEN */
SQL_FOR = 366, SQL_WITH = 362, /* WITH */
SQL_INT = 367, SQL_ADD = 363, /* ADD */
SQL_KEY = 368, SQL_ALL = 364, /* ALL */
SQL_NOT = 369, SQL_AND = 365, /* AND */
SQL_OFF = 370, SQL_ASC = 366, /* ASC */
SQL_SET = 371, SQL_END = 367, /* END */
SQL_TOP = 372, SQL_FOR = 368, /* FOR */
SQL_AS = 373, SQL_INT = 369, /* INT */
SQL_BY = 374, SQL_KEY = 370, /* KEY */
SQL_IF = 375, SQL_NOT = 371, /* NOT */
SQL_IN = 376, SQL_OFF = 372, /* OFF */
SQL_IS = 377, SQL_SET = 373, /* SET */
SQL_OF = 378, SQL_TOP = 374, /* TOP */
SQL_ON = 379, SQL_AS = 375, /* AS */
SQL_OR = 380, SQL_BY = 376, /* BY */
SQL_TO = 381, SQL_IF = 377, /* IF */
SQL_ARRAY = 382, SQL_IN = 378, /* IN */
SQL_CONCAT = 383, SQL_IS = 379, /* IS */
SQL_ILIKE = 384, SQL_OF = 380, /* OF */
SQL_SECOND = 385, SQL_ON = 381, /* ON */
SQL_MINUTE = 386, SQL_OR = 382, /* OR */
SQL_HOUR = 387, SQL_TO = 383, /* TO */
SQL_DAY = 388, SQL_ARRAY = 384, /* ARRAY */
SQL_MONTH = 389, SQL_CONCAT = 385, /* CONCAT */
SQL_YEAR = 390, SQL_ILIKE = 386, /* ILIKE */
SQL_TRUE = 391, SQL_SECOND = 387, /* SECOND */
SQL_FALSE = 392, SQL_MINUTE = 388, /* MINUTE */
SQL_TRANSACTION = 393, SQL_HOUR = 389, /* HOUR */
SQL_BEGIN = 394, SQL_DAY = 390, /* DAY */
SQL_COMMIT = 395, SQL_MONTH = 391, /* MONTH */
SQL_ROLLBACK = 396, SQL_YEAR = 392, /* YEAR */
SQL_EQUALS = 397, SQL_TRUE = 393, /* TRUE */
SQL_NOTEQUALS = 398, SQL_FALSE = 394, /* FALSE */
SQL_LESS = 399, SQL_TRANSACTION = 395, /* TRANSACTION */
SQL_GREATER = 400, SQL_BEGIN = 396, /* BEGIN */
SQL_LESSEQ = 401, SQL_COMMIT = 397, /* COMMIT */
SQL_GREATEREQ = 402, SQL_ROLLBACK = 398, /* ROLLBACK */
SQL_NOTNULL = 403, SQL_EQUALS = 399, /* EQUALS */
SQL_UMINUS = 404 SQL_NOTEQUALS = 400, /* NOTEQUALS */
SQL_LESS = 401, /* LESS */
SQL_GREATER = 402, /* GREATER */
SQL_LESSEQ = 403, /* LESSEQ */
SQL_GREATEREQ = 404, /* GREATEREQ */
SQL_NOTNULL = 405, /* NOTNULL */
SQL_UMINUS = 406 /* UMINUS */
}; };
typedef enum hsql_tokentype hsql_token_kind_t;
#endif #endif
/* Value type. */ /* Value type. */
@ -285,7 +293,7 @@ union HSQL_STYPE
std::vector<hsql::OrderDescription*>* order_vec; std::vector<hsql::OrderDescription*>* order_vec;
std::vector<hsql::WithDescription*>* with_description_vec; std::vector<hsql::WithDescription*>* with_description_vec;
#line 289 "bison_parser.h" #line 297 "bison_parser.h"
}; };
typedef union HSQL_STYPE HSQL_STYPE; typedef union HSQL_STYPE HSQL_STYPE;

View File

@ -171,11 +171,11 @@ 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 INTEGER NATURAL PREPARE PRIMARY SCHEMAS %token INTEGER NATURAL PREPARE PRIMARY SCHEMAS
%token SPATIAL VARCHAR VIRTUAL DESCRIBE BEFORE COLUMN CREATE DELETE DIRECT %token SPATIAL VARCHAR VIRTUAL DESCRIBE BEFORE COLUMN CREATE DELETE DIRECT
%token DOUBLE ESCAPE EXCEPT EXISTS EXTRACT FORMAT GLOBAL HAVING IMPORT %token DOUBLE ESCAPE EXCEPT EXISTS EXTRACT CAST FORMAT 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 FLOAT GROUP INDEX INNER LIMIT LOCAL MERGE MINUS ORDER %token DELTA FLOAT GROUP INDEX INNER LIMIT LOCAL MERGE MINUS ORDER
%token OUTER RIGHT TABLE UNION USING WHERE CALL CASE CHAR COPY DATE %token OUTER RIGHT TABLE UNION USING WHERE CALL CASE CHAR COPY DATE DATETIME
%token DESC DROP ELSE FILE FROM FULL HASH HINT INTO JOIN %token DESC DROP ELSE FILE FROM FULL HASH HINT INTO JOIN
%token LEFT LIKE LOAD LONG NULL PLAN SHOW TEXT THEN TIME %token LEFT LIKE LOAD LONG NULL PLAN SHOW TEXT THEN TIME
%token VIEW WHEN WITH ADD ALL AND ASC END FOR INT KEY %token VIEW WHEN WITH ADD ALL AND ASC END FOR INT KEY
@ -207,7 +207,7 @@ int yyerror(YYLTYPE* llocp, SQLParserResult* result, yyscan_t scanner, const cha
%type <uval> opt_join_type %type <uval> opt_join_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 extract_expr %type <expr> expr operand scalar_expr unary_expr binary_expr logic_expr exists_expr extract_expr cast_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 bool_literal %type <expr> column_name literal int_literal num_literal string_literal bool_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
@ -561,6 +561,7 @@ column_type:
| VARCHAR '(' INTVAL ')' { $$ = ColumnType{DataType::VARCHAR, $3}; } | VARCHAR '(' INTVAL ')' { $$ = ColumnType{DataType::VARCHAR, $3}; }
| CHAR '(' INTVAL ')' { $$ = ColumnType{DataType::CHAR, $3}; } | CHAR '(' INTVAL ')' { $$ = ColumnType{DataType::CHAR, $3}; }
| TEXT { $$ = ColumnType{DataType::TEXT}; } | TEXT { $$ = ColumnType{DataType::TEXT}; }
| DATETIME { $$ = ColumnType{DataType::DATETIME}; }
; ;
opt_column_nullable: opt_column_nullable:
@ -910,6 +911,7 @@ operand:
| case_expr | case_expr
| function_expr | function_expr
| extract_expr | extract_expr
| cast_expr
| array_expr | array_expr
| '(' select_no_paren ')' { $$ = Expr::makeSelect($2); } | '(' select_no_paren ')' { $$ = Expr::makeSelect($2); }
; ;
@ -991,6 +993,10 @@ extract_expr:
EXTRACT '(' datetime_field FROM expr ')' { $$ = Expr::makeExtract($3, $5); } EXTRACT '(' datetime_field FROM expr ')' { $$ = Expr::makeExtract($3, $5); }
; ;
cast_expr:
CAST '(' expr AS column_type ')' { $$ = Expr::makeCast($3, $5); }
;
datetime_field: datetime_field:
SECOND { $$ = kDatetimeSecond; } SECOND { $$ = kDatetimeSecond; }
| MINUTE { $$ = kDatetimeMinute; } | MINUTE { $$ = kDatetimeMinute; }

File diff suppressed because it is too large Load Diff

View File

@ -730,7 +730,7 @@ extern int yylex \
#undef yyTABLES_NAME #undef yyTABLES_NAME
#endif #endif
#line 242 "flex_lexer.l" #line 244 "flex_lexer.l"
#line 736 "flex_lexer.h" #line 736 "flex_lexer.h"

View File

@ -97,6 +97,7 @@ ESCAPE TOKEN(ESCAPE)
EXCEPT TOKEN(EXCEPT) EXCEPT TOKEN(EXCEPT)
EXISTS TOKEN(EXISTS) EXISTS TOKEN(EXISTS)
EXTRACT TOKEN(EXTRACT) EXTRACT TOKEN(EXTRACT)
CAST TOKEN(CAST)
FORMAT TOKEN(FORMAT) FORMAT TOKEN(FORMAT)
GLOBAL TOKEN(GLOBAL) GLOBAL TOKEN(GLOBAL)
HAVING TOKEN(HAVING) HAVING TOKEN(HAVING)
@ -140,6 +141,7 @@ CASE TOKEN(CASE)
CHAR TOKEN(CHAR) CHAR TOKEN(CHAR)
COPY TOKEN(COPY) COPY TOKEN(COPY)
DATE TOKEN(DATE) DATE TOKEN(DATE)
DATETIME TOKEN(DATETIME)
DESC TOKEN(DESC) DESC TOKEN(DESC)
DROP TOKEN(DROP) DROP TOKEN(DROP)
ELSE TOKEN(ELSE) ELSE TOKEN(ELSE)

33
src/sql/ColumnType.h Executable file
View File

@ -0,0 +1,33 @@
#ifndef SQLPARSER_COLUMN_TYPE_H
#define SQLPARSER_COLUMN_TYPE_H
#include <ostream>
namespace hsql {
enum class DataType {
UNKNOWN,
INT,
LONG,
FLOAT,
DOUBLE,
CHAR,
VARCHAR,
TEXT,
DATETIME
};
// Represents the type of a column, e.g., FLOAT or VARCHAR(10)
struct ColumnType {
ColumnType() = default;
ColumnType(DataType data_type, int64_t length = 0);
DataType data_type;
int64_t length; // Used for, e.g., VARCHAR(10)
};
bool operator==(const ColumnType& lhs, const ColumnType& rhs);
bool operator!=(const ColumnType& lhs, const ColumnType& rhs);
std::ostream& operator<<(std::ostream&, const ColumnType&);
} // namespace hsql
#endif

View File

@ -2,6 +2,7 @@
#define SQLPARSER_CREATE_STATEMENT_H #define SQLPARSER_CREATE_STATEMENT_H
#include "SQLStatement.h" #include "SQLStatement.h"
#include "ColumnType.h"
#include <ostream> #include <ostream>
@ -9,29 +10,6 @@
namespace hsql { namespace hsql {
struct SelectStatement; struct SelectStatement;
enum class DataType {
UNKNOWN,
INT,
LONG,
FLOAT,
DOUBLE,
CHAR,
VARCHAR,
TEXT
};
// Represents the type of a column, e.g., FLOAT or VARCHAR(10)
struct ColumnType {
ColumnType() = default;
ColumnType(DataType data_type, int64_t length = 0);
DataType data_type;
int64_t length; // Used for, e.g., VARCHAR(10)
};
bool operator==(const ColumnType& lhs, const ColumnType& rhs);
bool operator!=(const ColumnType& lhs, const ColumnType& rhs);
std::ostream& operator<<(std::ostream&, const ColumnType&);
// Represents definition of a table column // Represents definition of a table column
struct ColumnDefinition { struct ColumnDefinition {
ColumnDefinition(char* name, ColumnType type, bool nullable); ColumnDefinition(char* name, ColumnType type, bool nullable);

View File

@ -18,6 +18,7 @@ Expr::Expr(ExprType type)
ival(0), ival(0),
ival2(0), ival2(0),
datetimeField(kDatetimeNone), datetimeField(kDatetimeNone),
columnType(DataType::UNKNOWN, 0),
isBoolLiteral(false), isBoolLiteral(false),
opType(kOpNone), opType(kOpNone),
distinct(false){}; distinct(false){};
@ -224,6 +225,14 @@ Expr* Expr::makeExtract(DatetimeField datetimeField, Expr* expr) {
return e; return e;
} }
Expr* Expr::makeCast(Expr* expr, ColumnType columnType) {
Expr* e = new Expr(kExprFunctionRef);
e->name = strdup("CAST");
e->columnType = columnType;
e->expr = expr;
return e;
}
bool Expr::isType(ExprType exprType) const { return exprType == type; } bool Expr::isType(ExprType exprType) const { return exprType == type; }
bool Expr::isLiteral() const { bool Expr::isLiteral() const {

View File

@ -4,6 +4,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <memory> #include <memory>
#include <vector> #include <vector>
#include "ColumnType.h"
namespace hsql { namespace hsql {
struct SelectStatement; struct SelectStatement;
@ -102,6 +103,7 @@ struct Expr {
int64_t ival; int64_t ival;
int64_t ival2; int64_t ival2;
DatetimeField datetimeField; DatetimeField datetimeField;
ColumnType columnType;
bool isBoolLiteral; bool isBoolLiteral;
OperatorType opType; OperatorType opType;
@ -173,6 +175,8 @@ struct Expr {
static Expr* makeInOperator(Expr* expr, SelectStatement* select); static Expr* makeInOperator(Expr* expr, SelectStatement* select);
static Expr* makeExtract(DatetimeField datetimeField1, Expr* expr); static Expr* makeExtract(DatetimeField datetimeField1, Expr* expr);
static Expr* makeCast(Expr* expr, ColumnType columnType);
}; };
// 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

@ -54,6 +54,9 @@ namespace hsql {
case DataType::TEXT: case DataType::TEXT:
stream << "TEXT"; stream << "TEXT";
break; break;
case DataType::DATETIME:
stream << "DATETIME";
break;
} }
return stream; return stream;
} }

View File

@ -528,4 +528,20 @@ TEST(CommitTransactionTest) {
ASSERT_EQ(transaction_stmt->command, kCommitTransaction); ASSERT_EQ(transaction_stmt->command, kCommitTransaction);
} }
TEST(CastAsType) {
TEST_PARSE_SINGLE_SQL(
"SELECT CAST(ID AS VARCHAR(8)) FROM TEST",
kStmtSelect,
SelectStatement,
result,
stmt);
ASSERT_TRUE(result.isValid());
ASSERT_EQ(1, stmt->selectList->size());
ASSERT_STREQ("CAST", stmt->selectList->front()->name);
ASSERT_EQ(DataType::VARCHAR, stmt->selectList->front()->columnType.data_type);
ASSERT_EQ(8, stmt->selectList->front()->columnType.length);
}
TEST_MAIN(); TEST_MAIN();