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 SRCPARSER = src/parser
# files # files
PARSERFILES = $(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)/*") $(SRCPARSER)/bison_parser.cpp $(SRCPARSER)/flex_lexer.cpp LIBCPP = $(shell find $(SRC) -name '*.cpp' -not -path "$(SRCPARSER)/*") $(PARSERCPP)
LIBOBJ = $(LIBCPP:%.cpp=%.o) LIBOBJ = $(LIBCPP:%.cpp=%.o)
TESTCPP = $(shell find test/ -name '*.cpp') TESTCPP = $(shell find test/ -name '*.cpp')
@ -27,13 +27,16 @@ library: $(TARGET)
$(TARGET): $(LIBOBJ) $(TARGET): $(LIBOBJ)
$(CXX) $(LIBFLAGS) -o $(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 $@ $< $(CXX) $(CFLAGS) -c -o $@ $<
$(SRCPARSER)/bison_parser.cpp: $(SRCPARSER)/bison_parser.cpp: $(SRCPARSER)/bison_parser.y
make -C $(SRCPARSER)/ bison_parser.cpp make -C $(SRCPARSER)/ bison_parser.cpp
$(SRCPARSER)/flex_lexer.cpp: $(SRCPARSER)/flex_lexer.cpp: $(SRCPARSER)/flex_lexer.l
make -C $(SRCPARSER)/ flex_lexer.cpp make -C $(SRCPARSER)/ flex_lexer.cpp
parser: parser:
@ -51,6 +54,7 @@ cleanall: clean cleanparser
install: install:
cp $(TARGET) $(INSTALL)/lib/$(TARGET) cp $(TARGET) $(INSTALL)/lib/$(TARGET)
rm -rf $(INSTALL)/include/hsql
cp -r src $(INSTALL)/include/hsql cp -r src $(INSTALL)/include/hsql
find $(INSTALL)/include/hsql -not -name '*.h' -type f | xargs rm 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)]() [![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) [![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. 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). 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). **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) 1. Download the [latest release here](https://github.com/hyrise/sql-parser/releases)
2. Compile the library `make` to create `libsqlparser.so` 2. Compile the library `make` to create `libsqlparser.so`
3. *(Optional)* Run `make install` to copy the library to `/usr/local/lib/` 3. *(Optional, Recommended)* Run `make install` to copy the library to `/usr/local/lib/`
3. Run the tests `make test` to make sure everything worked 4. 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/` (or from `/usr/local/lib/hsql/` if you installed it) and link the library in your project
5. Include the `SQLParser.h` from `src/` 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+) // Basic Usage Example
* [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: const std::string query = "...";
hsql::SQLParserResult result;
hsql::SQLParser::parseSQLString(query, &result);
```bash if (result.isValid() && result.size() > 0) {
make parser # builds the bison parser and flex lexer const hsql::SQLStatement* statement = result.getStatement(0);
make library # builds the libsqlparser.so
make test # runs the tests with the library 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 * [SQLParser.h](src/SQLParser.h)
make cleanall # cleans the parser build and library build * [SQLParserResult.h](src/SQLParserResult.h)
make test # build parser, library and runs the tests * [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. 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 ## License
* [Working Syntax Examples](docs/syntax.md)
* [Developer Documentation](docs/dev-docs.md)
### 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. 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. 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 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 ## Developing New Functionality
This section contains information about how to extend this parser with new functionalities. 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 ### Extending the Grammar
Related files: Related files:
```` ```
src/parser/bison_parser.y src/parser/bison_parser.y
src/parser/flex_lexer.l src/parser/flex_lexer.l
src/parser/keywordlist_generator.py src/parser/keywordlist_generator.py

View File

@ -13,6 +13,16 @@ namespace hsql {
addStatement(stmt); 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() { SQLParserResult::~SQLParserResult() {
reset(); reset();
} }

View File

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

View File

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

View File

@ -3,7 +3,7 @@ all: bison_parser.cpp flex_lexer.cpp
bison_parser.cpp: bison_parser.y bison_parser.cpp: bison_parser.y
@bison --version | head -n 1 @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_lexer.cpp: flex_lexer.l
@flex --version @flex --version
@ -14,4 +14,4 @@ clean:
# Tests if the parser builds correctly and doesn't contain conflicts. # Tests if the parser builds correctly and doesn't contain conflicts.
test: 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: case 20:
#line 315 "bison_parser.y" /* yacc.c:1646 */ #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)->filePath = (yyvsp[-2].sval);
(yyval.import_stmt)->tableName = (yyvsp[0].sval); (yyval.import_stmt)->tableName = (yyvsp[0].sval);
} }
@ -2567,7 +2567,7 @@ yyreduce:
case 21: case 21:
#line 323 "bison_parser.y" /* yacc.c:1646 */ #line 323 "bison_parser.y" /* yacc.c:1646 */
{ (yyval.uval) = ImportStatement::kImportCSV; } { (yyval.uval) = kImportCSV; }
#line 2572 "bison_parser.cpp" /* yacc.c:1646 */ #line 2572 "bison_parser.cpp" /* yacc.c:1646 */
break; break;
@ -2580,7 +2580,7 @@ yyreduce:
case 23: case 23:
#line 337 "bison_parser.y" /* yacc.c:1646 */ #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)->ifNotExists = (yyvsp[-5].bval);
(yyval.create_stmt)->tableName = (yyvsp[-4].sval); (yyval.create_stmt)->tableName = (yyvsp[-4].sval);
(yyval.create_stmt)->filePath = (yyvsp[0].sval); (yyval.create_stmt)->filePath = (yyvsp[0].sval);
@ -2591,7 +2591,7 @@ yyreduce:
case 24: case 24:
#line 343 "bison_parser.y" /* yacc.c:1646 */ #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)->ifNotExists = (yyvsp[-4].bval);
(yyval.create_stmt)->tableName = (yyvsp[-3].sval); (yyval.create_stmt)->tableName = (yyvsp[-3].sval);
(yyval.create_stmt)->columns = (yyvsp[-1].column_vec); (yyval.create_stmt)->columns = (yyvsp[-1].column_vec);
@ -2602,7 +2602,7 @@ yyreduce:
case 25: case 25:
#line 349 "bison_parser.y" /* yacc.c:1646 */ #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)->ifNotExists = (yyvsp[-4].bval);
(yyval.create_stmt)->tableName = (yyvsp[-3].sval); (yyval.create_stmt)->tableName = (yyvsp[-3].sval);
(yyval.create_stmt)->viewColumns = (yyvsp[-2].str_vec); (yyval.create_stmt)->viewColumns = (yyvsp[-2].str_vec);
@ -2670,7 +2670,7 @@ yyreduce:
case 35: case 35:
#line 389 "bison_parser.y" /* yacc.c:1646 */ #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); (yyval.drop_stmt)->name = (yyvsp[0].sval);
} }
#line 2677 "bison_parser.cpp" /* yacc.c:1646 */ #line 2677 "bison_parser.cpp" /* yacc.c:1646 */
@ -2679,7 +2679,7 @@ yyreduce:
case 36: case 36:
#line 393 "bison_parser.y" /* yacc.c:1646 */ #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); (yyval.drop_stmt)->name = (yyvsp[0].sval);
} }
#line 2686 "bison_parser.cpp" /* yacc.c:1646 */ #line 2686 "bison_parser.cpp" /* yacc.c:1646 */
@ -2688,7 +2688,7 @@ yyreduce:
case 37: case 37:
#line 397 "bison_parser.y" /* yacc.c:1646 */ #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); (yyval.drop_stmt)->name = (yyvsp[0].sval);
} }
#line 2695 "bison_parser.cpp" /* yacc.c:1646 */ #line 2695 "bison_parser.cpp" /* yacc.c:1646 */
@ -2716,7 +2716,7 @@ yyreduce:
case 40: case 40:
#line 429 "bison_parser.y" /* yacc.c:1646 */ #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)->tableName = (yyvsp[-5].sval);
(yyval.insert_stmt)->columns = (yyvsp[-4].str_vec); (yyval.insert_stmt)->columns = (yyvsp[-4].str_vec);
(yyval.insert_stmt)->values = (yyvsp[-1].expr_vec); (yyval.insert_stmt)->values = (yyvsp[-1].expr_vec);
@ -2727,7 +2727,7 @@ yyreduce:
case 41: case 41:
#line 435 "bison_parser.y" /* yacc.c:1646 */ #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)->tableName = (yyvsp[-2].sval);
(yyval.insert_stmt)->columns = (yyvsp[-1].str_vec); (yyval.insert_stmt)->columns = (yyvsp[-1].str_vec);
(yyval.insert_stmt)->select = (yyvsp[0].select_stmt); (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 // Define the names of the created files (defined in Makefile)
%output "bison_parser.cpp" // %output "bison_parser.cpp"
%defines "bison_parser.h" // %defines "bison_parser.h"
// Tell bison to create a reentrant parser // Tell bison to create a reentrant parser
%define api.pure full %define api.pure full
@ -313,14 +313,14 @@ execute_statement:
******************************/ ******************************/
import_statement: import_statement:
IMPORT FROM import_file_type FILE file_path INTO table_name { IMPORT FROM import_file_type FILE file_path INTO table_name {
$$ = new ImportStatement((ImportStatement::ImportType) $3); $$ = new ImportStatement((ImportType) $3);
$$->filePath = $5; $$->filePath = $5;
$$->tableName = $7; $$->tableName = $7;
} }
; ;
import_file_type: import_file_type:
CSV { $$ = ImportStatement::kImportCSV; } CSV { $$ = kImportCSV; }
; ;
file_path: file_path:
@ -335,19 +335,19 @@ file_path:
******************************/ ******************************/
create_statement: create_statement:
CREATE TABLE opt_not_exists table_name FROM TBL FILE file_path { CREATE TABLE opt_not_exists table_name FROM TBL FILE file_path {
$$ = new CreateStatement(CreateStatement::kTableFromTbl); $$ = new CreateStatement(kCreateTableFromTbl);
$$->ifNotExists = $3; $$->ifNotExists = $3;
$$->tableName = $4; $$->tableName = $4;
$$->filePath = $8; $$->filePath = $8;
} }
| CREATE TABLE opt_not_exists table_name '(' column_def_commalist ')' { | CREATE TABLE opt_not_exists table_name '(' column_def_commalist ')' {
$$ = new CreateStatement(CreateStatement::kTable); $$ = new CreateStatement(kCreateTable);
$$->ifNotExists = $3; $$->ifNotExists = $3;
$$->tableName = $4; $$->tableName = $4;
$$->columns = $6; $$->columns = $6;
} }
| CREATE VIEW opt_not_exists table_name opt_column_list AS select_statement { | CREATE VIEW opt_not_exists table_name opt_column_list AS select_statement {
$$ = new CreateStatement(CreateStatement::kView); $$ = new CreateStatement(kCreateView);
$$->ifNotExists = $3; $$->ifNotExists = $3;
$$->tableName = $4; $$->tableName = $4;
$$->viewColumns = $5; $$->viewColumns = $5;
@ -387,15 +387,15 @@ column_type:
drop_statement: drop_statement:
DROP TABLE table_name { DROP TABLE table_name {
$$ = new DropStatement(DropStatement::kTable); $$ = new DropStatement(kDropTable);
$$->name = $3; $$->name = $3;
} }
| DROP VIEW table_name { | DROP VIEW table_name {
$$ = new DropStatement(DropStatement::kView); $$ = new DropStatement(kDropView);
$$->name = $3; $$->name = $3;
} }
| DEALLOCATE PREPARE IDENTIFIER { | DEALLOCATE PREPARE IDENTIFIER {
$$ = new DropStatement(DropStatement::kPreparedStatement); $$ = new DropStatement(kDropPreparedStatement);
$$->name = $3; $$->name = $3;
} }
; ;
@ -427,13 +427,13 @@ truncate_statement:
******************************/ ******************************/
insert_statement: insert_statement:
INSERT INTO table_name opt_column_list VALUES '(' literal_list ')' { INSERT INTO table_name opt_column_list VALUES '(' literal_list ')' {
$$ = new InsertStatement(InsertStatement::kInsertValues); $$ = new InsertStatement(kInsertValues);
$$->tableName = $3; $$->tableName = $3;
$$->columns = $4; $$->columns = $4;
$$->values = $7; $$->values = $7;
} }
| INSERT INTO table_name opt_column_list select_no_paren { | INSERT INTO table_name opt_column_list select_no_paren {
$$ = new InsertStatement(InsertStatement::kInsertSelect); $$ = new InsertStatement(kInsertSelect);
$$->tableName = $3; $$->tableName = $3;
$$->columns = $4; $$->columns = $4;
$$->select = $5; $$->select = $5;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -7,20 +7,15 @@
#include <algorithm> #include <algorithm>
namespace hsql { namespace hsql {
/**
* Represents SQL Prepare statements. // Represents SQL Prepare statements.
* Example: "PREPARE ins_prep: SELECT * FROM t1 WHERE c1 = ? AND c2 = ?" // Example: "PREPARE ins_prep: SELECT * FROM t1 WHERE c1 = ? AND c2 = ?"
*/
struct PrepareStatement : SQLStatement { struct PrepareStatement : SQLStatement {
PrepareStatement(); PrepareStatement();
virtual ~PrepareStatement(); virtual ~PrepareStatement();
/** // When setting the placeholders we need to make sure that they are in the correct order.
* 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.
* 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
*/
void setPlaceholders(std::vector<void*> ph); void setPlaceholders(std::vector<void*> ph);
char* name; char* name;
@ -35,4 +30,5 @@ namespace hsql {
}; };
} // namsepace hsql } // namsepace hsql
#endif #endif

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -37,7 +37,7 @@ TEST(CreateStatementTest) {
ASSERT_EQ(result.getStatement(0)->type(), kStmtCreate); ASSERT_EQ(result.getStatement(0)->type(), kStmtCreate);
const CreateStatement* stmt = (const CreateStatement*) result.getStatement(0); 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_STREQ(stmt->tableName, "students");
ASSERT_NOTNULL(stmt->columns); ASSERT_NOTNULL(stmt->columns);
ASSERT_EQ(stmt->columns->size(), 4); ASSERT_EQ(stmt->columns->size(), 4);
@ -102,7 +102,7 @@ TEST(DropTableStatementTest) {
result, result,
stmt); stmt);
ASSERT_EQ(stmt->type, DropStatement::kTable); ASSERT_EQ(stmt->type, kDropTable);
ASSERT_NOTNULL(stmt->name); ASSERT_NOTNULL(stmt->name);
ASSERT_STREQ(stmt->name, "students"); 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(); 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/) // 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 // Copyright (c) 2017 Pedro Flemming
// //
// This is a small header-only C++ unit testing framework. // This is a small header-only C++ unit testing framework.
@ -37,8 +37,18 @@
ASSERT_TRUE(value != NULL); ASSERT_TRUE(value != NULL);
#define ASSERT_STREQ(a, b)\ #define ASSERT_STREQ(a, b)\
if (std::string(a).compare(std::string(b)) != 0)\ if (std::string(a).compare(std::string(b)) != 0) {\
throw mt::AssertFailedException(#a " == " #b, __FILE__, __LINE__); 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)\ #define ASSERT_EQ(a, b)\
if (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;
} }
}; };