Documentation & Result Move Constructor (#39)

Updates documentation, adds a move constructor to SQLParserResult, fixes compile-time warnings
This commit is contained in:
Pedro Flemming 2017-04-21 16:15:07 +02:00 committed by GitHub
parent 9184d5d0c2
commit 0909c6a89a
27 changed files with 251 additions and 156 deletions

View File

@ -4,8 +4,8 @@ SRC = src
SRCPARSER = src/parser
# files
PARSERFILES = $(SRCPARSER)/bison_parser.cpp $(SRCPARSER)/flex_lexer.cpp
LIBCPP = $(shell find $(SRC) -name '*.cpp' -not -path "$(SRCPARSER)/*") $(SRCPARSER)/bison_parser.cpp $(SRCPARSER)/flex_lexer.cpp
PARSERCPP = $(SRCPARSER)/bison_parser.cpp $(SRCPARSER)/flex_lexer.cpp
LIBCPP = $(shell find $(SRC) -name '*.cpp' -not -path "$(SRCPARSER)/*") $(PARSERCPP)
LIBOBJ = $(LIBCPP:%.cpp=%.o)
TESTCPP = $(shell find test/ -name '*.cpp')
@ -27,13 +27,16 @@ library: $(TARGET)
$(TARGET): $(LIBOBJ)
$(CXX) $(LIBFLAGS) -o $(TARGET) $(LIBOBJ)
%.o: %.cpp $(PARSERFILES)
$(SRCPARSER)/flex_lexer.o: $(SRCPARSER)/flex_lexer.cpp
$(CXX) $(CFLAGS) -c -o $@ $< -Wno-sign-compare -Wno-unneeded-internal-declaration -Wno-deprecated-register
%.o: %.cpp $(PARSERCPP)
$(CXX) $(CFLAGS) -c -o $@ $<
$(SRCPARSER)/bison_parser.cpp:
$(SRCPARSER)/bison_parser.cpp: $(SRCPARSER)/bison_parser.y
make -C $(SRCPARSER)/ bison_parser.cpp
$(SRCPARSER)/flex_lexer.cpp:
$(SRCPARSER)/flex_lexer.cpp: $(SRCPARSER)/flex_lexer.l
make -C $(SRCPARSER)/ flex_lexer.cpp
parser:
@ -51,6 +54,7 @@ cleanall: clean cleanparser
install:
cp $(TARGET) $(INSTALL)/lib/$(TARGET)
rm -rf $(INSTALL)/include/hsql
cp -r src $(INSTALL)/include/hsql
find $(INSTALL)/include/hsql -not -name '*.h' -type f | xargs rm

View File

@ -1,16 +1,16 @@
C++ SQL Parser for Hyrise
C++ SQL Parser
=========================
[![GitHub release](https://img.shields.io/github/release/hyrise/sql-parser.svg?maxAge=2592000)]()
[![Build Status](https://img.shields.io/travis/hyrise/sql-parser.svg?maxAge=2592000)](https://travis-ci.org/hyrise/sql-parser)
This is a SQL Parser for C++. It parses the given SQL query into C++ objects.
It is developed for integration in hyrise (https://github.com/hyrise/hyrise), but can be used in other environments as well.
It has been developed for integration in [Hyrise](https://github.com/hyrise/hyrise), but can be used perfectly well in other environments as well.
In March 2015 we've also written a short paper outlining discussing some development details and the integration into our database Hyrise. You can find the paper [here](http://torpedro.com/paper/HyriseSQL-03-2015.pdf).
### Usage
## Usage
**Note:** You can also find a detailed usage description at this [blog post](http://torpedro.github.io/tech/c++/sql/parser/2016/02/27/c++-sql-parser.html).
@ -21,52 +21,53 @@ To use the SQL parser in your own projects you simply have to follow these few s
1. Download the [latest release here](https://github.com/hyrise/sql-parser/releases)
2. Compile the library `make` to create `libsqlparser.so`
3. *(Optional)* Run `make install` to copy the library to `/usr/local/lib/`
3. Run the tests `make test` to make sure everything worked
4. Take a look at the [example project here](https://github.com/hyrise/sql-parser/tree/master/example)
5. Include the `SQLParser.h` from `src/` and link the library in your project
3. *(Optional, Recommended)* Run `make install` to copy the library to `/usr/local/lib/`
4. Run the tests `make test` to make sure everything worked
5. Include the `SQLParser.h` from `src/` (or from `/usr/local/lib/hsql/` if you installed it) and link the library in your project
6. Take a look at the [example project here](https://github.com/hyrise/sql-parser/tree/master/example)
```cpp
#include "hsql/SQLParser.h"
### Extending the parser
/* ... */
**Requirements for development:**
* gcc 4.8+ (or clang 3.4+)
* [bison](https://www.gnu.org/software/bison/) (v3.0.2+)
* [flex](http://flex.sourceforge.net/) (v2.5.5+)
{
// Basic Usage Example
First step to extending this parser is cloning the repository `git clone git@github.com:hyrise/sql-parser.git` and making sure everything works by running the following steps:
const std::string query = "...";
hsql::SQLParserResult result;
hsql::SQLParser::parseSQLString(query, &result);
```bash
make parser # builds the bison parser and flex lexer
make library # builds the libsqlparser.so
make test # runs the tests with the library
if (result.isValid() && result.size() > 0) {
const hsql::SQLStatement* statement = result.getStatement(0);
if (statement.isType(hsql::SelectStatement)) {
const hsql::SelectStatement* select = (const hsql::SelectStatement*) statement;
/* ... */
}
}
}
```
Rerun these steps whenever you change part of the parse. To execute the entire pipeline automatically you can run:
Quick Links:
```bash
make cleanall # cleans the parser build and library build
make test # build parser, library and runs the tests
```
* [SQLParser.h](src/SQLParser.h)
* [SQLParserResult.h](src/SQLParserResult.h)
* [SelectStatement.h](src/sql/SelectStatement.h)
## How to Contribute
#### How to contribute
**[Developer Documentation](docs/)**
We strongly encourage you to contribute to this project! If you want to contribute to this project there are several options. If you've noticed a bug or would like an improvement let us know by creating a [new issue](https://github.com/hyrise/sql-parser/issues). If you want to develop a new feature yourself or just improve the quality of the system, feel free to fork the reposistory and implement your changes. Open a pull request as soon as your done and we will look over it. If we think it's good then your pull request will be merged into this repository.
### Resources
* [Working Syntax Examples](docs/syntax.md)
* [Developer Documentation](docs/dev-docs.md)
### License
## License
HYRISE sql-parser is licensed as open source after the OpenSource "Licence of the Hasso-Plattner Institute" declared in the LICENSE file of this project.
### Contributers
## Contributers
The following people contributed to HYRISE sql-parser in various forms.

15
docs/README.md Normal file
View File

@ -0,0 +1,15 @@
Documentation
=============
Internal Links:
* [Developer Documentation](dev-docs.md)
* [Working SQL Syntax Examples](syntax-examples.md)
External Resources:
* [Original Dev-Paper (2015)](http://torpedro.com/paper/HyriseSQL-03-2015.pdf)
* [Blog Post about Basic Usage](http://torpedro.github.io/tech/c++/sql/parser/2016/02/27/c++-sql-parser.html)

View File

@ -1,6 +1,29 @@
Developer Documentation
=======================
## Basic Requirements
**Requirements for development:**
* gcc 4.8+ (or clang 3.4+)
* [bison](https://www.gnu.org/software/bison/) (v3.0.2+)
* [flex](http://flex.sourceforge.net/) (v2.5.5+)
First step to extending this parser is cloning the repository `git clone git@github.com:hyrise/sql-parser.git` and making sure everything works by running the following steps:
```bash
make parser # builds the bison parser and flex lexer
make library # builds the libsqlparser.so
make test # runs the tests with the library
```
Rerun these steps whenever you change part of the parse. To execute the entire pipeline automatically you can run:
```bash
make cleanall # cleans the parser build and library build
make test # build parser, library and runs the tests
```
## Developing New Functionality
This section contains information about how to extend this parser with new functionalities.
@ -18,7 +41,7 @@ Finally you will need to include your new file in `src/sql/statements.h`.
### Extending the Grammar
Related files:
````
```
src/parser/bison_parser.y
src/parser/flex_lexer.l
src/parser/keywordlist_generator.py

View File

@ -13,6 +13,16 @@ namespace hsql {
addStatement(stmt);
};
// Move constructor.
SQLParserResult::SQLParserResult(SQLParserResult&& moved) {
isValid_ = moved.isValid_;
errorMsg_ = moved.errorMsg_;
statements_ = std::move(moved.statements_);
moved.errorMsg_ = NULL;
moved.reset();
}
SQLParserResult::~SQLParserResult() {
reset();
}

View File

@ -15,6 +15,9 @@ namespace hsql {
// Takes ownership of the statement.
SQLParserResult(SQLStatement* stmt);
// Move constructor.
SQLParserResult(SQLParserResult&& moved);
// Deletes all statements in the result.
virtual ~SQLParserResult();

View File

@ -1 +1,2 @@
*.output
conflict_test.cpp

View File

@ -3,7 +3,7 @@ all: bison_parser.cpp flex_lexer.cpp
bison_parser.cpp: bison_parser.y
@bison --version | head -n 1
bison bison_parser.y -v
bison bison_parser.y --output=bison_parser.cpp --defines=bison_parser.h --verbose
flex_lexer.cpp: flex_lexer.l
@flex --version
@ -14,4 +14,4 @@ clean:
# Tests if the parser builds correctly and doesn't contain conflicts.
test:
! bison bison_parser.y -v 2>&1 | grep "conflict" >&2
! bison bison_parser.y -v --output=conflict_test.cpp 2>&1 | grep "conflict" >&2

View File

@ -2558,7 +2558,7 @@ yyreduce:
case 20:
#line 315 "bison_parser.y" /* yacc.c:1646 */
{
(yyval.import_stmt) = new ImportStatement((ImportStatement::ImportType) (yyvsp[-4].uval));
(yyval.import_stmt) = new ImportStatement((ImportType) (yyvsp[-4].uval));
(yyval.import_stmt)->filePath = (yyvsp[-2].sval);
(yyval.import_stmt)->tableName = (yyvsp[0].sval);
}
@ -2567,7 +2567,7 @@ yyreduce:
case 21:
#line 323 "bison_parser.y" /* yacc.c:1646 */
{ (yyval.uval) = ImportStatement::kImportCSV; }
{ (yyval.uval) = kImportCSV; }
#line 2572 "bison_parser.cpp" /* yacc.c:1646 */
break;
@ -2580,7 +2580,7 @@ yyreduce:
case 23:
#line 337 "bison_parser.y" /* yacc.c:1646 */
{
(yyval.create_stmt) = new CreateStatement(CreateStatement::kTableFromTbl);
(yyval.create_stmt) = new CreateStatement(kCreateTableFromTbl);
(yyval.create_stmt)->ifNotExists = (yyvsp[-5].bval);
(yyval.create_stmt)->tableName = (yyvsp[-4].sval);
(yyval.create_stmt)->filePath = (yyvsp[0].sval);
@ -2591,7 +2591,7 @@ yyreduce:
case 24:
#line 343 "bison_parser.y" /* yacc.c:1646 */
{
(yyval.create_stmt) = new CreateStatement(CreateStatement::kTable);
(yyval.create_stmt) = new CreateStatement(kCreateTable);
(yyval.create_stmt)->ifNotExists = (yyvsp[-4].bval);
(yyval.create_stmt)->tableName = (yyvsp[-3].sval);
(yyval.create_stmt)->columns = (yyvsp[-1].column_vec);
@ -2602,7 +2602,7 @@ yyreduce:
case 25:
#line 349 "bison_parser.y" /* yacc.c:1646 */
{
(yyval.create_stmt) = new CreateStatement(CreateStatement::kView);
(yyval.create_stmt) = new CreateStatement(kCreateView);
(yyval.create_stmt)->ifNotExists = (yyvsp[-4].bval);
(yyval.create_stmt)->tableName = (yyvsp[-3].sval);
(yyval.create_stmt)->viewColumns = (yyvsp[-2].str_vec);
@ -2670,7 +2670,7 @@ yyreduce:
case 35:
#line 389 "bison_parser.y" /* yacc.c:1646 */
{
(yyval.drop_stmt) = new DropStatement(DropStatement::kTable);
(yyval.drop_stmt) = new DropStatement(kDropTable);
(yyval.drop_stmt)->name = (yyvsp[0].sval);
}
#line 2677 "bison_parser.cpp" /* yacc.c:1646 */
@ -2679,7 +2679,7 @@ yyreduce:
case 36:
#line 393 "bison_parser.y" /* yacc.c:1646 */
{
(yyval.drop_stmt) = new DropStatement(DropStatement::kView);
(yyval.drop_stmt) = new DropStatement(kDropView);
(yyval.drop_stmt)->name = (yyvsp[0].sval);
}
#line 2686 "bison_parser.cpp" /* yacc.c:1646 */
@ -2688,7 +2688,7 @@ yyreduce:
case 37:
#line 397 "bison_parser.y" /* yacc.c:1646 */
{
(yyval.drop_stmt) = new DropStatement(DropStatement::kPreparedStatement);
(yyval.drop_stmt) = new DropStatement(kDropPreparedStatement);
(yyval.drop_stmt)->name = (yyvsp[0].sval);
}
#line 2695 "bison_parser.cpp" /* yacc.c:1646 */
@ -2716,7 +2716,7 @@ yyreduce:
case 40:
#line 429 "bison_parser.y" /* yacc.c:1646 */
{
(yyval.insert_stmt) = new InsertStatement(InsertStatement::kInsertValues);
(yyval.insert_stmt) = new InsertStatement(kInsertValues);
(yyval.insert_stmt)->tableName = (yyvsp[-5].sval);
(yyval.insert_stmt)->columns = (yyvsp[-4].str_vec);
(yyval.insert_stmt)->values = (yyvsp[-1].expr_vec);
@ -2727,7 +2727,7 @@ yyreduce:
case 41:
#line 435 "bison_parser.y" /* yacc.c:1646 */
{
(yyval.insert_stmt) = new InsertStatement(InsertStatement::kInsertSelect);
(yyval.insert_stmt) = new InsertStatement(kInsertSelect);
(yyval.insert_stmt)->tableName = (yyvsp[-2].sval);
(yyval.insert_stmt)->columns = (yyvsp[-1].str_vec);
(yyval.insert_stmt)->select = (yyvsp[0].select_stmt);

View File

@ -56,9 +56,9 @@ int yyerror(YYLTYPE* llocp, SQLParserResult* result, yyscan_t scanner, const cha
}
}
// Define the names of the created files
%output "bison_parser.cpp"
%defines "bison_parser.h"
// Define the names of the created files (defined in Makefile)
// %output "bison_parser.cpp"
// %defines "bison_parser.h"
// Tell bison to create a reentrant parser
%define api.pure full
@ -313,14 +313,14 @@ execute_statement:
******************************/
import_statement:
IMPORT FROM import_file_type FILE file_path INTO table_name {
$$ = new ImportStatement((ImportStatement::ImportType) $3);
$$ = new ImportStatement((ImportType) $3);
$$->filePath = $5;
$$->tableName = $7;
}
;
import_file_type:
CSV { $$ = ImportStatement::kImportCSV; }
CSV { $$ = kImportCSV; }
;
file_path:
@ -335,19 +335,19 @@ file_path:
******************************/
create_statement:
CREATE TABLE opt_not_exists table_name FROM TBL FILE file_path {
$$ = new CreateStatement(CreateStatement::kTableFromTbl);
$$ = new CreateStatement(kCreateTableFromTbl);
$$->ifNotExists = $3;
$$->tableName = $4;
$$->filePath = $8;
}
| CREATE TABLE opt_not_exists table_name '(' column_def_commalist ')' {
$$ = new CreateStatement(CreateStatement::kTable);
$$ = new CreateStatement(kCreateTable);
$$->ifNotExists = $3;
$$->tableName = $4;
$$->columns = $6;
}
| CREATE VIEW opt_not_exists table_name opt_column_list AS select_statement {
$$ = new CreateStatement(CreateStatement::kView);
$$ = new CreateStatement(kCreateView);
$$->ifNotExists = $3;
$$->tableName = $4;
$$->viewColumns = $5;
@ -387,15 +387,15 @@ column_type:
drop_statement:
DROP TABLE table_name {
$$ = new DropStatement(DropStatement::kTable);
$$ = new DropStatement(kDropTable);
$$->name = $3;
}
| DROP VIEW table_name {
$$ = new DropStatement(DropStatement::kView);
$$ = new DropStatement(kDropView);
$$->name = $3;
}
| DEALLOCATE PREPARE IDENTIFIER {
$$ = new DropStatement(DropStatement::kPreparedStatement);
$$ = new DropStatement(kDropPreparedStatement);
$$->name = $3;
}
;
@ -427,13 +427,13 @@ truncate_statement:
******************************/
insert_statement:
INSERT INTO table_name opt_column_list VALUES '(' literal_list ')' {
$$ = new InsertStatement(InsertStatement::kInsertValues);
$$ = new InsertStatement(kInsertValues);
$$->tableName = $3;
$$->columns = $4;
$$->values = $7;
}
| INSERT INTO table_name opt_column_list select_no_paren {
$$ = new InsertStatement(InsertStatement::kInsertSelect);
$$ = new InsertStatement(kInsertSelect);
$$->tableName = $3;
$$->columns = $4;
$$->select = $5;

View File

@ -23,16 +23,15 @@ namespace hsql {
DataType type;
};
enum CreateType {
kCreateTable,
kCreateTableFromTbl, // Hyrise file format
kCreateView
};
// Represents SQL Create statements.
// Example: "CREATE TABLE students (name TEXT, student_number INTEGER, city TEXT, grade DOUBLE)"
struct CreateStatement : SQLStatement {
enum CreateType {
kTable,
kTableFromTbl, // Hyrise file format
kView
};
CreateStatement(CreateType type);
virtual ~CreateStatement();
@ -46,4 +45,5 @@ namespace hsql {
};
} // namespace hsql
#endif

View File

@ -5,6 +5,7 @@
// Note: Implementations of constructors and destructors can be found in statements.cpp.
namespace hsql {
// Represents SQL Delete statements.
// Example: "DELETE FROM students WHERE grade > 3.0"
// Note: if (expr == NULL) => delete all rows (truncate)
@ -17,4 +18,5 @@ namespace hsql {
};
} // namespace hsql
#endif

View File

@ -5,21 +5,23 @@
// Note: Implementations of constructors and destructors can be found in statements.cpp.
namespace hsql {
enum DropType {
kDropTable,
kDropSchema,
kDropIndex,
kDropView,
kDropPreparedStatement
};
// Represents SQL Delete statements.
// Example "DROP TABLE students;"
struct DropStatement : SQLStatement {
enum EntityType {
kTable,
kSchema,
kIndex,
kView,
kPreparedStatement
};
DropStatement(EntityType type);
DropStatement(DropType type);
virtual ~DropStatement();
EntityType type;
DropType type;
char* name;
};

View File

@ -4,10 +4,9 @@
#include "SQLStatement.h"
namespace hsql {
/**
* Represents SQL Execute statements.
* Example: "EXECUTE ins_prep(100, "test", 2.3);"
*/
// Represents SQL Execute statements.
// Example: "EXECUTE ins_prep(100, "test", 2.3);"
struct ExecuteStatement : SQLStatement {
ExecuteStatement();
virtual ~ExecuteStatement();
@ -17,4 +16,5 @@ namespace hsql {
};
} // namsepace hsql
#endif

View File

@ -6,7 +6,7 @@
#include <vector>
namespace hsql {
class SelectStatement;
struct SelectStatement;
// Helper function used by the lexer.
// TODO: move to more appropriate place.

View File

@ -4,15 +4,13 @@
#include "SQLStatement.h"
namespace hsql {
/**
* Represents SQL Import statements.
*/
struct ImportStatement : SQLStatement {
enum ImportType {
kImportCSV,
kImportTbl, // Hyrise file format
};
enum ImportType {
kImportCSV,
kImportTbl, // Hyrise file format
};
// Represents SQL Import statements.
struct ImportStatement : SQLStatement {
ImportStatement(ImportType type);
virtual ~ImportStatement();
@ -23,5 +21,4 @@ namespace hsql {
} // namespace hsql
#endif

View File

@ -5,16 +5,14 @@
#include "SelectStatement.h"
namespace hsql {
/**
* Represents SQL Insert statements.
* Example: "INSERT INTO students VALUES ('Max', 1112233, 'Musterhausen', 2.3)"
*/
struct InsertStatement : SQLStatement {
enum InsertType {
kInsertValues,
kInsertSelect
};
enum InsertType {
kInsertValues,
kInsertSelect
};
// Represents SQL Insert statements.
// Example: "INSERT INTO students VALUES ('Max', 1112233, 'Musterhausen', 2.3)"
struct InsertStatement : SQLStatement {
InsertStatement(InsertType type);
virtual ~InsertStatement();
@ -26,4 +24,5 @@ namespace hsql {
};
} // namsepace hsql
#endif

View File

@ -7,20 +7,15 @@
#include <algorithm>
namespace hsql {
/**
* Represents SQL Prepare statements.
* Example: "PREPARE ins_prep: SELECT * FROM t1 WHERE c1 = ? AND c2 = ?"
*/
// Represents SQL Prepare statements.
// Example: "PREPARE ins_prep: SELECT * FROM t1 WHERE c1 = ? AND c2 = ?"
struct PrepareStatement : SQLStatement {
PrepareStatement();
virtual ~PrepareStatement();
/**
* When setting the placeholders we need to make sure that they are in the correct order.
* To ensure that, during parsing we store the character position use that to sort the list here.
*
* @param vector of placeholders that the parser found
*/
// When setting the placeholders we need to make sure that they are in the correct order.
// To ensure that, during parsing we store the character position use that to sort the list here.
void setPlaceholders(std::vector<void*> ph);
char* name;
@ -35,4 +30,5 @@ namespace hsql {
};
} // namsepace hsql
#endif

View File

@ -21,10 +21,9 @@ namespace hsql {
kStmtAlter
};
/**
* Base struct for every SQL statement
*/
// Base struct for every SQL statement
struct SQLStatement {
SQLStatement(StatementType type);
virtual ~SQLStatement();
@ -33,9 +32,14 @@ namespace hsql {
bool isType(StatementType type) const;
// Shorthand for isType(type).
bool is(StatementType type) const;
private:
StatementType type_;
};
} // namespace hsql
#endif // __SQLPARSER__SQLSTATEMENT_H__

View File

@ -11,9 +11,8 @@ namespace hsql {
kOrderDesc
};
/**
* Description of the order by clause within a select statement
*/
// Description of the order by clause within a select statement.
struct OrderDescription {
OrderDescription(OrderType type, Expr* expr);
virtual ~OrderDescription();
@ -25,9 +24,7 @@ namespace hsql {
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 {
LimitDescription(int64_t limit, int64_t offset);
@ -35,9 +32,7 @@ namespace hsql {
int64_t offset;
};
/**
* Description of the group-by clause within a select statement
*/
// Description of the group-by clause within a select statement.
struct GroupByDescription {
GroupByDescription();
virtual ~GroupByDescription();
@ -46,10 +41,8 @@ namespace hsql {
Expr* having;
};
/**
* Representation of a full SQL select statement.
* TODO: add union_order and union_limit
*/
// Representation of a full SQL select statement.
// TODO: add union_order and union_limit.
struct SelectStatement : SQLStatement {
SelectStatement();
virtual ~SelectStatement();
@ -66,4 +59,5 @@ namespace hsql {
};
} // namespace hsql
#endif

View File

@ -4,17 +4,14 @@
#include "SQLStatement.h"
namespace hsql {
/**
* Represents "column = value" expressions
*/
// Represents "column = value" expressions.
struct UpdateClause {
char* column;
Expr* value;
};
/**
* Represents SQL Update statements.
*/
// Represents SQL Update statements.
struct UpdateStatement : SQLStatement {
UpdateStatement();
virtual ~UpdateStatement();
@ -26,4 +23,5 @@ namespace hsql {
};
} // namsepace hsql
#endif

View File

@ -17,6 +17,10 @@ namespace hsql {
return (type_ == type);
}
bool SQLStatement::is(StatementType type) const {
return isType(type);
}
// ColumnDefinition
ColumnDefinition::ColumnDefinition(char* name, DataType type) :
name(name),
@ -69,7 +73,7 @@ namespace hsql {
}
// DropStatament
DropStatement::DropStatement(EntityType type) :
DropStatement::DropStatement(DropType type) :
SQLStatement(kStmtDrop),
type(type),
name(NULL) {}

View File

@ -11,7 +11,7 @@ namespace hsql {
return std::string(numIndent, '\t');
}
void inprint(int64_t val, uintmax_t numIndent) {
printf("%s%lld \n", indent(numIndent).c_str(), val);
printf("%s%ld \n", indent(numIndent).c_str(), val);
}
void inprint(float val, uintmax_t numIndent) {
printf("%s%f\n", indent(numIndent).c_str(), val);
@ -26,7 +26,7 @@ namespace hsql {
printf("%s%c\n", indent(numIndent).c_str(), val);
}
void inprintU(uint64_t val, uintmax_t numIndent) {
printf("%s%llu\n", indent(numIndent).c_str(), val);
printf("%s%lu\n", indent(numIndent).c_str(), val);
}
void printTableRefInfo(TableRef* table, uintmax_t numIndent) {
@ -174,13 +174,13 @@ namespace hsql {
}
}
switch (stmt->type) {
case InsertStatement::kInsertValues:
case kInsertValues:
inprint("Values", numIndent + 1);
for (Expr* expr : *stmt->values) {
printExpression(expr, numIndent + 2);
}
break;
case InsertStatement::kInsertSelect:
case kInsertSelect:
printSelectStatementInfo(stmt->select, numIndent + 1);
break;
}

View File

@ -11,6 +11,8 @@ using hsql::kStmtInsert;
using hsql::kStmtPrepare;
using hsql::kStmtSelect;
using hsql::kDropPreparedStatement;
using hsql::DropStatement;
using hsql::ExecuteStatement;
using hsql::InsertStatement;
@ -69,7 +71,7 @@ TEST(PrepareMultiStatementTest) {
ASSERT_EQ(prep2->placeholders.size(), 1);
// Deallocate Statement
ASSERT_EQ(drop->type, DropStatement::kPreparedStatement);
ASSERT_EQ(drop->type, kDropPreparedStatement);
ASSERT_STREQ(drop->name, "stmt");
}

View File

@ -37,7 +37,7 @@ TEST(CreateStatementTest) {
ASSERT_EQ(result.getStatement(0)->type(), kStmtCreate);
const CreateStatement* stmt = (const CreateStatement*) result.getStatement(0);
ASSERT_EQ(stmt->type, CreateStatement::kTable);
ASSERT_EQ(stmt->type, kCreateTable);
ASSERT_STREQ(stmt->tableName, "students");
ASSERT_NOTNULL(stmt->columns);
ASSERT_EQ(stmt->columns->size(), 4);
@ -102,7 +102,7 @@ TEST(DropTableStatementTest) {
result,
stmt);
ASSERT_EQ(stmt->type, DropStatement::kTable);
ASSERT_EQ(stmt->type, kDropTable);
ASSERT_NOTNULL(stmt->name);
ASSERT_STREQ(stmt->name, "students");
}
@ -127,4 +127,33 @@ TEST(ReleaseStatementTest) {
}
}
SQLParserResult parse_and_move(std::string query) {
hsql::SQLParserResult result;
hsql::SQLParser::parseSQLString(query, &result);
// Moves on return.
return result;
}
SQLParserResult move_in_and_back(SQLParserResult res) {
// Moves on return.
return res;
}
TEST(MoveSQLResultTest) {
SQLParserResult res = parse_and_move("SELECT * FROM test;");
ASSERT(res.isValid());
ASSERT_EQ(1, res.size());
// Moved around.
SQLParserResult new_res = move_in_and_back(std::move(res));
// Original object should be invalid.
ASSERT_FALSE(res.isValid());
ASSERT_EQ(0, res.size());
ASSERT(new_res.isValid());
ASSERT_EQ(1, new_res.size());
}
TEST_MAIN();

View File

@ -1,9 +1,9 @@
//
// microtest
// microtest.h
//
// URL: https://github.com/torpedro/microtest
// URL: https://github.com/torpedro/microtest.h
// Author: Pedro Flemming (http://torpedro.com/)
// License: MIT License (https://github.com/torpedro/microtest/blob/master/LICENSE)
// License: MIT License (https://github.com/torpedro/microtest.h/blob/master/LICENSE)
// Copyright (c) 2017 Pedro Flemming
//
// This is a small header-only C++ unit testing framework.
@ -37,8 +37,18 @@
ASSERT_TRUE(value != NULL);
#define ASSERT_STREQ(a, b)\
if (std::string(a).compare(std::string(b)) != 0)\
throw mt::AssertFailedException(#a " == " #b, __FILE__, __LINE__);
if (std::string(a).compare(std::string(b)) != 0) {\
printf("%s{ info} %s", mt::yellow(), mt::def());\
std::cout << "Actual values: " << a << " != " << b << std::endl;\
throw mt::AssertFailedException(#a " == " #b, __FILE__, __LINE__);\
}
#define ASSERT_STRNEQ(a, b)\
if (std::string(a).compare(std::string(b)) !== 0) {\
printf("%s{ info} %s", mt::yellow(), mt::def());\
std::cout << "Actual values: " << a << " == " << b << std::endl;\
throw mt::AssertFailedException(#a " != " #b, __FILE__, __LINE__);\
}
#define ASSERT_EQ(a, b)\
if (a != b) {\
@ -175,7 +185,8 @@ namespace mt {
}
}
return num_failed;
int return_code = (num_failed > 0) ? 1 : 0;
return return_code;
}
};