Skip to content

Commit 4248c76

Browse files
authored
Adds support for date literals (#174)
1 parent 55f9dd2 commit 4248c76

File tree

9 files changed

+864
-780
lines changed

9 files changed

+864
-780
lines changed

src/parser/bison_parser.cpp

Lines changed: 811 additions & 775 deletions
Large diffs are not rendered by default.

src/parser/bison_parser.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
/* A Bison parser, made by GNU Bison 3.7.4. */
1+
/* A Bison parser, made by GNU Bison 3.7.6. */
22

33
/* Bison interface for Yacc-like parsers in C
44
5-
Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 Free Software Foundation,
5+
Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation,
66
Inc.
77
88
This program is free software: you can redistribute it and/or modify
@@ -16,7 +16,7 @@
1616
GNU General Public License for more details.
1717
1818
You should have received a copy of the GNU General Public License
19-
along with this program. If not, see <http://www.gnu.org/licenses/>. */
19+
along with this program. If not, see <https://www.gnu.org/licenses/>. */
2020

2121
/* As a special exception, you may create a larger work that contains
2222
part or all of the Bison parser skeleton and distribute that work

src/parser/bison_parser.y

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ int yyerror(YYLTYPE* llocp, SQLParserResult* result, yyscan_t scanner, const cha
209209
%type <table> join_clause table_ref_name_no_alias
210210
%type <expr> expr operand scalar_expr unary_expr binary_expr logic_expr exists_expr extract_expr cast_expr
211211
%type <expr> function_expr between_expr expr_alias param_expr
212-
%type <expr> column_name literal int_literal num_literal string_literal bool_literal
212+
%type <expr> column_name literal int_literal num_literal string_literal bool_literal date_literal
213213
%type <expr> comp_expr opt_where join_condition opt_having case_expr case_list in_expr hint
214214
%type <expr> array_expr array_index null_literal
215215
%type <limit> opt_limit opt_top
@@ -1031,6 +1031,7 @@ literal:
10311031
| bool_literal
10321032
| num_literal
10331033
| null_literal
1034+
| date_literal
10341035
| param_expr
10351036
;
10361037

@@ -1056,6 +1057,19 @@ null_literal:
10561057
NULL { $$ = Expr::makeNullLiteral(); }
10571058
;
10581059

1060+
date_literal:
1061+
DATE STRING {
1062+
int day{0}, month{0}, year{0}, chars_parsed{0};
1063+
// If the whole string is parsed, chars_parsed points to the terminating null byte after the last character
1064+
if (sscanf($2, "%4d-%2d-%2d%n", &day, &month, &year, &chars_parsed) != 3 || $2[chars_parsed] != 0) {
1065+
free($2);
1066+
yyerror(&yyloc, result, scanner, "Found incorrect date format. Expected format: YYYY-MM-DD");
1067+
YYERROR;
1068+
}
1069+
$$ = Expr::makeDateLiteral($2);
1070+
}
1071+
;
1072+
10591073
param_expr:
10601074
'?' {
10611075
$$ = Expr::makeParameter(yylloc.total_column);

src/sql/Expr.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,12 @@ Expr* Expr::makeNullLiteral() {
134134
return e;
135135
}
136136

137+
Expr* Expr::makeDateLiteral(char* string) {
138+
Expr* e = new Expr(kExprLiteralDate);
139+
e->name = string;
140+
return e;
141+
}
142+
137143
Expr* Expr::makeColumnRef(char* name) {
138144
Expr* e = new Expr(kExprColumnRef);
139145
e->name = name;

src/sql/Expr.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ enum ExprType {
1818
kExprLiteralString,
1919
kExprLiteralInt,
2020
kExprLiteralNull,
21+
kExprLiteralDate,
2122
kExprStar,
2223
kExprParameter,
2324
kExprColumnRef,
@@ -150,6 +151,8 @@ struct Expr {
150151

151152
static Expr* makeNullLiteral();
152153

154+
static Expr* makeDateLiteral(char* val);
155+
153156
static Expr* makeColumnRef(char* name);
154157

155158
static Expr* makeColumnRef(char* table, char* name);

src/util/sqlhelper.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,12 @@ namespace hsql {
121121
case kExprLiteralString:
122122
inprint(expr->name, numIndent);
123123
break;
124+
case kExprLiteralDate:
125+
inprint(expr->name, numIndent);
126+
break;
127+
case kExprLiteralNull:
128+
inprint("NULL", numIndent);
129+
break;
124130
case kExprFunctionRef:
125131
inprint(expr->name, numIndent);
126132
for (Expr* e : *expr->exprList) printExpression(e, numIndent + 1);

test/queries/queries-bad.sql

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,9 @@
2121
!WITH a AS (SELECT ) b AS (SELECT ) SELECT 1; # Missing comma between WITH descriptions
2222
!BEGIN TRANSACTION transName; # Transaction naming is currently not supported
2323
!SELECT -9223372036854775809; # Out of int64_t range
24-
!SELECT 9223372036854775808; # Out of int64_t range
24+
!SELECT 9223372036854775808; # Out of int64_t range
25+
!SELECT * FROM t WHERE a = DATE 'anystring';
26+
!SELECT * FROM t WHERE a = DATE '1996-12-310';
27+
!SELECT * FROM t WHERE a = DATE '1996-120-31';
28+
!SELECT * FROM t WHERE a = DATE '19960-12-31';
29+
!SELECT * FROM t WHERE a = DATE 'asdf-gh-jkl';

test/queries/queries-good.sql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ SELECT * FROM t WHERE a BETWEEN 1 and c;
1717
SELECT * FROM t WHERE a = ? AND b = ?;
1818
SELECT City.name, Product.category, SUM(price) FROM fact INNER JOIN City ON fact.city_id = City.id INNER JOIN Product ON fact.product_id = Product.id GROUP BY City.name, Product.category;
1919
SELECT SUBSTR(a, 3, 5) FROM t;
20+
SELECT * FROM t WHERE a = DATE '1996-12-31';
2021
# JOIN
2122
SELECT t1.a, t1.b, t2.c FROM "table" AS t1 JOIN (SELECT * FROM foo JOIN bar ON foo.id = bar.id) t2 ON t1.a = t2.b WHERE (t1.b OR NOT t1.a) AND t2.c = 12.5
2223
SELECT * FROM t1 JOIN t2 ON c1 = c2;

test/select_tests.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -836,3 +836,16 @@ TEST(CastAsDate) {
836836
ASSERT_STREQ("CAST", stmt->selectList->front()->name);
837837
ASSERT_EQ(DataType::DATE, stmt->selectList->front()->columnType.data_type);
838838
}
839+
840+
TEST(DateLiteral) {
841+
TEST_PARSE_SINGLE_SQL(
842+
"SELECT * FROM t WHERE a = DATE '1996-12-31'",
843+
kStmtSelect,
844+
SelectStatement,
845+
result,
846+
stmt);
847+
ASSERT_TRUE(result.isValid());
848+
stmt = (SelectStatement*) result.getStatement(0);
849+
ASSERT_EQ(stmt->whereClause->opType, kOpEquals);
850+
ASSERT_STREQ(stmt->whereClause->expr2->name, "1996-12-31");
851+
}

0 commit comments

Comments
 (0)