Allow Expressions in LIMIT and OFFSET. (#111)
* Allow Expressions in LIMIT and OFFSET. * Make NULL distinguishable from nullptr (not present) for LIMIT and OFFSET.
This commit is contained in:
parent
9701403ff5
commit
e0e58d0876
File diff suppressed because it is too large
Load Diff
|
@ -1,8 +1,8 @@
|
||||||
/* A Bison parser, made by GNU Bison 3.1. */
|
/* A Bison parser, made by GNU Bison 3.0.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 Free Software Foundation, Inc.
|
Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, 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
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -48,7 +48,7 @@
|
||||||
extern int hsql_debug;
|
extern int hsql_debug;
|
||||||
#endif
|
#endif
|
||||||
/* "%code requires" blocks. */
|
/* "%code requires" blocks. */
|
||||||
#line 35 "bison_parser.y" /* yacc.c:1919 */
|
#line 35 "bison_parser.y" /* yacc.c:1909 */
|
||||||
|
|
||||||
// %code requires block
|
// %code requires block
|
||||||
|
|
||||||
|
@ -72,7 +72,7 @@ extern int hsql_debug;
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
#line 76 "bison_parser.h" /* yacc.c:1919 */
|
#line 76 "bison_parser.h" /* yacc.c:1909 */
|
||||||
|
|
||||||
/* Token type. */
|
/* Token type. */
|
||||||
#ifndef HSQL_TOKENTYPE
|
#ifndef HSQL_TOKENTYPE
|
||||||
|
@ -230,7 +230,7 @@ extern int hsql_debug;
|
||||||
|
|
||||||
union HSQL_STYPE
|
union HSQL_STYPE
|
||||||
{
|
{
|
||||||
#line 95 "bison_parser.y" /* yacc.c:1919 */
|
#line 95 "bison_parser.y" /* yacc.c:1909 */
|
||||||
|
|
||||||
double fval;
|
double fval;
|
||||||
int64_t ival;
|
int64_t ival;
|
||||||
|
@ -272,7 +272,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 276 "bison_parser.h" /* yacc.c:1919 */
|
#line 276 "bison_parser.h" /* yacc.c:1909 */
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef union HSQL_STYPE HSQL_STYPE;
|
typedef union HSQL_STYPE HSQL_STYPE;
|
||||||
|
|
|
@ -724,18 +724,16 @@ opt_order_type:
|
||||||
// TODO: TOP and LIMIT can take more than just int literals.
|
// TODO: TOP and LIMIT can take more than just int literals.
|
||||||
|
|
||||||
opt_top:
|
opt_top:
|
||||||
TOP int_literal { $$ = new LimitDescription($2->ival, kNoOffset); delete $2; }
|
TOP int_literal { $$ = new LimitDescription($2, nullptr); }
|
||||||
| /* empty */ { $$ = nullptr; }
|
| /* empty */ { $$ = nullptr; }
|
||||||
;
|
;
|
||||||
|
|
||||||
opt_limit:
|
opt_limit:
|
||||||
LIMIT int_literal { $$ = new LimitDescription($2->ival, kNoOffset); delete $2; }
|
LIMIT expr { $$ = new LimitDescription($2, nullptr); }
|
||||||
| LIMIT int_literal OFFSET int_literal { $$ = new LimitDescription($2->ival, $4->ival); delete $2; delete $4; }
|
| OFFSET expr { $$ = new LimitDescription(nullptr, $2); }
|
||||||
| OFFSET int_literal { $$ = new LimitDescription(kNoLimit, $2->ival); delete $2; }
|
| LIMIT expr OFFSET expr { $$ = new LimitDescription($2, $4); }
|
||||||
| LIMIT ALL { $$ = nullptr; }
|
| LIMIT ALL { $$ = new LimitDescription(nullptr, nullptr); }
|
||||||
| LIMIT NULL { $$ = nullptr; }
|
| LIMIT ALL OFFSET expr { $$ = new LimitDescription(nullptr, $4); }
|
||||||
| LIMIT ALL OFFSET int_literal { $$ = new LimitDescription(kNoLimit, $4->ival); delete $4; }
|
|
||||||
| LIMIT NULL OFFSET int_literal { $$ = new LimitDescription(kNoLimit, $4->ival); delete $4; }
|
|
||||||
| /* empty */ { $$ = nullptr; }
|
| /* empty */ { $$ = nullptr; }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
|
@ -21,15 +21,13 @@ namespace hsql {
|
||||||
Expr* expr;
|
Expr* expr;
|
||||||
};
|
};
|
||||||
|
|
||||||
const int64_t kNoLimit = -1;
|
|
||||||
const int64_t kNoOffset = -1;
|
|
||||||
|
|
||||||
// Description of the limit clause within a select statement.
|
// Description of the limit clause within a select statement.
|
||||||
struct LimitDescription {
|
struct LimitDescription {
|
||||||
LimitDescription(int64_t limit, int64_t offset);
|
LimitDescription(Expr* limit, Expr* offset);
|
||||||
|
virtual ~LimitDescription();
|
||||||
|
|
||||||
int64_t limit;
|
Expr* limit;
|
||||||
int64_t offset;
|
Expr* offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Description of the group-by clause within a select statement.
|
// Description of the group-by clause within a select statement.
|
||||||
|
|
|
@ -202,9 +202,14 @@ namespace hsql {
|
||||||
}
|
}
|
||||||
|
|
||||||
// LimitDescription
|
// LimitDescription
|
||||||
LimitDescription::LimitDescription(int64_t limit, int64_t offset) :
|
LimitDescription::LimitDescription(Expr* limit, Expr* offset) :
|
||||||
limit(limit >= 0 ? limit : kNoLimit),
|
limit(limit),
|
||||||
offset(offset > 0 ? offset : kNoOffset) {}
|
offset(offset) {}
|
||||||
|
|
||||||
|
LimitDescription::~LimitDescription() {
|
||||||
|
delete limit;
|
||||||
|
delete offset;
|
||||||
|
}
|
||||||
|
|
||||||
// GroypByDescription
|
// GroypByDescription
|
||||||
GroupByDescription::GroupByDescription() :
|
GroupByDescription::GroupByDescription() :
|
||||||
|
|
|
@ -190,7 +190,9 @@ namespace hsql {
|
||||||
|
|
||||||
if (stmt->limit != nullptr) {
|
if (stmt->limit != nullptr) {
|
||||||
inprint("Limit:", numIndent + 1);
|
inprint("Limit:", numIndent + 1);
|
||||||
inprint(stmt->limit->limit, numIndent + 2);
|
printExpression(stmt->limit->limit, numIndent + 2);
|
||||||
|
inprint("Offset:", numIndent + 1);
|
||||||
|
printExpression(stmt->limit->offset, numIndent + 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -534,56 +534,97 @@ TEST(SetLimitOffset) {
|
||||||
SelectStatement* stmt;
|
SelectStatement* stmt;
|
||||||
|
|
||||||
TEST_PARSE_SQL_QUERY("select a from t1 limit 1; \
|
TEST_PARSE_SQL_QUERY("select a from t1 limit 1; \
|
||||||
|
select a from t1 limit 1 + 2; \
|
||||||
|
select a from t1 offset 1; \
|
||||||
|
select a from t1 offset 1 + 2; \
|
||||||
select a from t1 limit 1 offset 1; \
|
select a from t1 limit 1 offset 1; \
|
||||||
select a from t1 limit 0; \
|
select a from t1 limit 1 + 2 offset 1 + 2; \
|
||||||
select a from t1 limit 0 offset 1; \
|
select a from t1 limit 1 offset NULL; \
|
||||||
select a from t1 limit 1 offset 0; \
|
select a from t1 limit ALL; \
|
||||||
|
select a from t1 limit NULL; \
|
||||||
select a from t1 limit ALL offset 1; \
|
select a from t1 limit ALL offset 1; \
|
||||||
select a from t1 limit NULL offset 1; \
|
select a from t1 limit NULL offset 1; \
|
||||||
select a from t1 offset 1; \
|
|
||||||
select top 10 a from t1; \
|
select top 10 a from t1; \
|
||||||
select top 20 a from t1 limit 10;",
|
select top 20 a from t1 limit 10; \
|
||||||
result, 10);
|
select a from t1 limit (SELECT MAX(b) FROM t1) offset (SELECT MIN(b) FROM t1);",
|
||||||
|
result, 14);
|
||||||
|
|
||||||
stmt = (SelectStatement*) result.getStatement(0);
|
stmt = (SelectStatement*) result.getStatement(0);
|
||||||
ASSERT_EQ(stmt->limit->limit, 1);
|
ASSERT_EQ(stmt->limit->limit->type, kExprLiteralInt);
|
||||||
ASSERT_EQ(stmt->limit->offset, kNoOffset);
|
ASSERT_EQ(stmt->limit->limit->ival, 1);
|
||||||
|
ASSERT_NULL(stmt->limit->offset);
|
||||||
|
|
||||||
stmt = (SelectStatement*) result.getStatement(1);
|
stmt = (SelectStatement*) result.getStatement(1);
|
||||||
ASSERT_EQ(stmt->limit->limit, 1);
|
ASSERT_EQ(stmt->limit->limit->type, kExprOperator);
|
||||||
ASSERT_EQ(stmt->limit->offset, 1);
|
ASSERT_EQ(stmt->limit->limit->opType, kOpPlus);
|
||||||
|
ASSERT_EQ(stmt->limit->limit->expr->ival, 1);
|
||||||
|
ASSERT_EQ(stmt->limit->limit->expr2->ival, 2);
|
||||||
|
ASSERT_NULL(stmt->limit->offset);
|
||||||
|
|
||||||
stmt = (SelectStatement*) result.getStatement(2);
|
stmt = (SelectStatement*) result.getStatement(2);
|
||||||
ASSERT_EQ(stmt->limit->limit, 0);
|
ASSERT_NULL(stmt->limit->limit);
|
||||||
ASSERT_EQ(stmt->limit->offset, kNoOffset);
|
ASSERT_EQ(stmt->limit->offset->type, kExprLiteralInt);
|
||||||
|
ASSERT_EQ(stmt->limit->offset->ival, 1);
|
||||||
|
|
||||||
stmt = (SelectStatement*) result.getStatement(3);
|
stmt = (SelectStatement*) result.getStatement(3);
|
||||||
ASSERT_EQ(stmt->limit->limit, 0);
|
ASSERT_NULL(stmt->limit->limit);
|
||||||
ASSERT_EQ(stmt->limit->offset, 1);
|
ASSERT_EQ(stmt->limit->offset->type, kExprOperator);
|
||||||
|
ASSERT_EQ(stmt->limit->offset->opType, kOpPlus);
|
||||||
|
ASSERT_EQ(stmt->limit->offset->expr->ival, 1);
|
||||||
|
ASSERT_EQ(stmt->limit->offset->expr2->ival, 2);
|
||||||
|
|
||||||
stmt = (SelectStatement*) result.getStatement(4);
|
stmt = (SelectStatement*) result.getStatement(4);
|
||||||
ASSERT_EQ(stmt->limit->limit, 1);
|
ASSERT_EQ(stmt->limit->limit->type, kExprLiteralInt);
|
||||||
ASSERT_EQ(stmt->limit->offset, kNoOffset);
|
ASSERT_EQ(stmt->limit->limit->ival, 1);
|
||||||
|
ASSERT_EQ(stmt->limit->offset->type, kExprLiteralInt);
|
||||||
|
ASSERT_EQ(stmt->limit->offset->ival, 1);
|
||||||
|
|
||||||
stmt = (SelectStatement*) result.getStatement(5);
|
stmt = (SelectStatement*) result.getStatement(5);
|
||||||
ASSERT_EQ(stmt->limit->limit, kNoLimit);
|
ASSERT_EQ(stmt->limit->limit->type, kExprOperator);
|
||||||
ASSERT_EQ(stmt->limit->offset, 1);
|
ASSERT_EQ(stmt->limit->limit->opType, kOpPlus);
|
||||||
|
ASSERT_EQ(stmt->limit->limit->expr->ival, 1);
|
||||||
|
ASSERT_EQ(stmt->limit->limit->expr2->ival, 2);
|
||||||
|
ASSERT_EQ(stmt->limit->offset->type, kExprOperator);
|
||||||
|
ASSERT_EQ(stmt->limit->offset->opType, kOpPlus);
|
||||||
|
ASSERT_EQ(stmt->limit->offset->expr->ival, 1);
|
||||||
|
ASSERT_EQ(stmt->limit->offset->expr2->ival, 2);
|
||||||
|
|
||||||
stmt = (SelectStatement*) result.getStatement(6);
|
stmt = (SelectStatement*) result.getStatement(6);
|
||||||
ASSERT_EQ(stmt->limit->limit, kNoLimit);
|
ASSERT_EQ(stmt->limit->limit->type, kExprLiteralInt);
|
||||||
ASSERT_EQ(stmt->limit->offset, 1);
|
ASSERT_EQ(stmt->limit->limit->ival, 1);
|
||||||
|
ASSERT_EQ(stmt->limit->offset->type, kExprLiteralNull);
|
||||||
|
|
||||||
stmt = (SelectStatement*) result.getStatement(7);
|
stmt = (SelectStatement*) result.getStatement(7);
|
||||||
ASSERT_EQ(stmt->limit->limit, kNoLimit);
|
ASSERT_NULL(stmt->limit->limit);
|
||||||
ASSERT_EQ(stmt->limit->offset, 1);
|
ASSERT_NULL(stmt->limit->offset);
|
||||||
|
|
||||||
stmt = (SelectStatement*) result.getStatement(8);
|
stmt = (SelectStatement*) result.getStatement(8);
|
||||||
ASSERT_EQ(stmt->limit->limit, 10);
|
ASSERT_EQ(stmt->limit->limit->type, kExprLiteralNull);
|
||||||
ASSERT_EQ(stmt->limit->offset, kNoOffset);
|
ASSERT_NULL(stmt->limit->offset);
|
||||||
|
|
||||||
stmt = (SelectStatement*) result.getStatement(9);
|
stmt = (SelectStatement*) result.getStatement(9);
|
||||||
ASSERT_EQ(stmt->limit->limit, 10);
|
ASSERT_NULL(stmt->limit->limit);
|
||||||
ASSERT_EQ(stmt->limit->offset, kNoOffset);
|
ASSERT_EQ(stmt->limit->offset->type, kExprLiteralInt);
|
||||||
|
ASSERT_EQ(stmt->limit->offset->ival, 1);
|
||||||
|
|
||||||
|
stmt = (SelectStatement*) result.getStatement(10);
|
||||||
|
ASSERT_EQ(stmt->limit->limit->type, kExprLiteralNull);
|
||||||
|
ASSERT_EQ(stmt->limit->offset->type, kExprLiteralInt);
|
||||||
|
ASSERT_EQ(stmt->limit->offset->ival, 1);
|
||||||
|
|
||||||
|
stmt = (SelectStatement*) result.getStatement(11);
|
||||||
|
ASSERT_EQ(stmt->limit->limit->type, kExprLiteralInt);
|
||||||
|
ASSERT_EQ(stmt->limit->limit->ival, 10);
|
||||||
|
ASSERT_NULL(stmt->limit->offset);
|
||||||
|
|
||||||
|
stmt = (SelectStatement*) result.getStatement(12);
|
||||||
|
ASSERT_EQ(stmt->limit->limit->type, kExprLiteralInt);
|
||||||
|
ASSERT_EQ(stmt->limit->limit->ival, 10);
|
||||||
|
ASSERT_NULL(stmt->limit->offset);
|
||||||
|
|
||||||
|
stmt = (SelectStatement*) result.getStatement(13);
|
||||||
|
ASSERT_EQ(stmt->limit->limit->type, kExprSelect);
|
||||||
|
ASSERT_EQ(stmt->limit->offset->type, kExprSelect);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Extract) {
|
TEST(Extract) {
|
||||||
|
|
Loading…
Reference in New Issue