Skip to content

Commit 46f1dcb

Browse files
author
Sebastian Bär
authored
Merge pull request #6 from EXASOL/develop
0.1.0
2 parents d25eea3 + de1a121 commit 46f1dcb

File tree

90 files changed

+4554
-1
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

90 files changed

+4554
-1
lines changed

.classpath

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<classpath>
3+
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
4+
<attributes>
5+
<attribute name="optional" value="true"/>
6+
<attribute name="maven.pomderived" value="true"/>
7+
</attributes>
8+
</classpathentry>
9+
<classpathentry kind="src" output="target/classes" path="src/main/java">
10+
<attributes>
11+
<attribute name="optional" value="true"/>
12+
<attribute name="maven.pomderived" value="true"/>
13+
</attributes>
14+
</classpathentry>
15+
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
16+
<attributes>
17+
<attribute name="maven.pomderived" value="true"/>
18+
</attributes>
19+
</classpathentry>
20+
<classpathentry kind="var" path="M2_REPO/org/junit/jupiter/junit-jupiter-api/5.3.1/junit-jupiter-api-5.3.1.jar" sourcepath="M2_REPO/org/junit/jupiter/junit-jupiter-api/5.3.1/junit-jupiter-api-5.3.1-sources.jar"/>
21+
<classpathentry kind="var" path="M2_REPO/org/apiguardian/apiguardian-api/1.0.0/apiguardian-api-1.0.0.jar" sourcepath="M2_REPO/org/apiguardian/apiguardian-api/1.0.0/apiguardian-api-1.0.0-sources.jar"/>
22+
<classpathentry kind="var" path="M2_REPO/org/opentest4j/opentest4j/1.1.1/opentest4j-1.1.1.jar" sourcepath="M2_REPO/org/opentest4j/opentest4j/1.1.1/opentest4j-1.1.1-sources.jar"/>
23+
<classpathentry kind="var" path="M2_REPO/org/junit/platform/junit-platform-commons/1.3.1/junit-platform-commons-1.3.1.jar" sourcepath="M2_REPO/org/junit/platform/junit-platform-commons/1.3.1/junit-platform-commons-1.3.1-sources.jar"/>
24+
<classpathentry kind="var" path="M2_REPO/org/junit/jupiter/junit-jupiter-engine/5.3.1/junit-jupiter-engine-5.3.1.jar" sourcepath="M2_REPO/org/junit/jupiter/junit-jupiter-engine/5.3.1/junit-jupiter-engine-5.3.1-sources.jar"/>
25+
<classpathentry kind="var" path="M2_REPO/org/junit/platform/junit-platform-engine/1.3.1/junit-platform-engine-1.3.1.jar" sourcepath="M2_REPO/org/junit/platform/junit-platform-engine/1.3.1/junit-platform-engine-1.3.1-sources.jar"/>
26+
<classpathentry kind="var" path="M2_REPO/org/junit/platform/junit-platform-launcher/1.3.1/junit-platform-launcher-1.3.1.jar" sourcepath="M2_REPO/org/junit/platform/junit-platform-launcher/1.3.1/junit-platform-launcher-1.3.1-sources.jar"/>
27+
<classpathentry kind="var" path="M2_REPO/org/hamcrest/hamcrest-all/1.3/hamcrest-all-1.3.jar" sourcepath="M2_REPO/org/hamcrest/hamcrest-all/1.3/hamcrest-all-1.3-sources.jar"/>
28+
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
29+
<attributes>
30+
<attribute name="maven.pomderived" value="true"/>
31+
</attributes>
32+
</classpathentry>
33+
<classpathentry kind="output" path="target/classes"/>
34+
</classpath>

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/bin/
2+
/target/
3+
**/*.md.html
4+
**/*.bak
5+
**/*.swp
6+
**/*.log
7+
**/*.out

.project

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<projectDescription>
3+
<name>sql-statement-builder</name>
4+
<comment>This module provides a Builder for SQL statements that helps creating the correct structure and validates variable parts of the statements. NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse.</comment>
5+
<projects/>
6+
<buildSpec>
7+
<buildCommand>
8+
<name>org.eclipse.jdt.core.javabuilder</name>
9+
</buildCommand>
10+
<buildCommand>
11+
<name>org.eclipse.m2e.core.maven2Builder</name>
12+
</buildCommand>
13+
</buildSpec>
14+
<natures>
15+
<nature>org.eclipse.jdt.core.javanature</nature>
16+
<nature>org.eclipse.m2e.core.maven2Nature</nature>
17+
</natures>
18+
</projectDescription>
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
eclipse.preferences.version=1
2+
encoding//src/main/java=UTF-8
3+
encoding//src/test/java=UTF-8
4+
encoding/<project>=UTF-8
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
eclipse.preferences.version=1
2+
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
3+
org.eclipse.jdt.core.compiler.compliance=1.8
4+
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
5+
org.eclipse.jdt.core.compiler.release=disabled
6+
org.eclipse.jdt.core.compiler.source=1.8

.travis.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
language: java
2+
3+
jdk:
4+
- openjdk8
5+
- openjdk11
6+
7+
before_script:
8+
- version=$(grep -oP '(?<=^ <version>)[^<]*' pom.xml)
9+
10+
script:
11+
- mvn clean install

README.md

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,74 @@
1-
# sql-statement-builder
1+
# sql-statement-builder
2+
3+
[![Build Status](https://travis-ci.com/EXASOL/sql-statement-builder.svg?branch=develop)](https://travis-ci.com/EXASOL/sql-statement-builder)
4+
5+
The Exasol SQL Statement Builder abstracts programmatic creation of SQL statements and is intended to replace ubiquitous string concatenation solutions which make the code hard to read and are prone to error and security risks.
6+
7+
Goals:
8+
9+
1. Foster clean and readable code
10+
1. Allow for thorough validation of dynamic parts
11+
1. Detect as many errors as possible at *compile time*
12+
1. Don't repeat yourself (DRY)
13+
1. Allow extension for different SQL dialects
14+
15+
## Usage
16+
17+
```java
18+
import com.exasol.sql.StatementFactory;
19+
import com.exasol.sql.SqlStatement;
20+
import com.exasol.sql.rendering.SelectRenderer;
21+
22+
SqlStatement statement = StatementFactory.getInstance()
23+
.select().field("firstname", "lastname")
24+
.from().table("person");
25+
26+
String statementText = SqlStatementRenderer.render(statement);
27+
```
28+
29+
## Development
30+
31+
The following sub-sections provide information about building and extending the project.
32+
33+
### Build Time Dependencies
34+
35+
The list below show all build time dependencies in alphabetical order. Note that except the Maven build tool all required modules are downloaded automatically by Maven.
36+
37+
| Dependency | Purpose | License |
38+
------------------------------------------------------------|--------------------------------------------------------|--------------------------------
39+
| [Apache Maven](https://maven.apache.org/) | Build tool | Apache License 2.0 |
40+
| [Equals Verifier](https://github.com/jqno/equalsverifier) | Automatic contract checker for `equals()` and `hash()` | Apache License 2.0 |
41+
| [Hamcrest](http://hamcrest.org/) | Advanced matchers for JUnit | GNU BSD-3-Clause |
42+
| [JUnit 5](https://junit.org/junit5/) | Unit testing framework | Eclipse Public License 1.0 |
43+
| [Mockito](http://site.mockito.org/) | Mocking framework | MIT License |
44+
45+
### Planned Milestones
46+
47+
The milestones listed below are a rough outline and might be subject to change depending on which constructs are needed more. The plan will be updated accordingly.
48+
49+
#### M1
50+
51+
* Basic support for Data Query Language (DQL) statement constructs (SELECT, FROM, JOIN, WHERE)
52+
* Rendering to string
53+
* Exasol Dialect only
54+
55+
#### M2
56+
57+
* Validation for constructs from M1
58+
59+
(Later milestones will always include validation of the newly learned milestones)
60+
61+
#### M3
62+
63+
* Scalar functions
64+
65+
#### M4
66+
67+
* Sub-Selects including validation
68+
69+
#### Later Milstones (very coarse)
70+
71+
* Data Manipulation Language (DML) statements
72+
* Data Definition Language (DDL) statements
73+
* Support for Standard SQL
74+
* Support for other dialects (help welcome!)

doc/design.md

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
# Software Architectural Design -- Exasol SQL Statement Builder
2+
3+
## Building Block View
4+
5+
### Select Statement
6+
`dsn~dql-statement~1`
7+
8+
The Data Query Language (DQL) building block is responsible for managing `SELECT` statements.
9+
10+
## Solution Strategy
11+
12+
### Fluent Programming
13+
14+
#### Statement Construction With Fluent Programming
15+
`dsn~statement-construction-with-fluent-programming~1`
16+
17+
All statement builders use the "fluent programming" model, where the return type of each builder step determines the possible next structural elements that can be added.
18+
19+
Comment:
20+
21+
This is a design principle that cuts across the whole project. Therefore locating it in a single test or implementation part makes no sense.
22+
23+
Covers:
24+
25+
* `req~statement-structure-limited-at-compile-time~1`
26+
27+
## Runtime View
28+
29+
### Building Select Statements
30+
31+
#### Accessing the Clauses That Make Up a SELECT Statement
32+
`dsn~select-statement.out-of-order-clauses~1`
33+
34+
`SELECT` commands allow attaching the following clauses in any order:
35+
36+
* `FROM` clause
37+
* `WHERE` clause
38+
* `LIMIT` clause
39+
40+
Covers:
41+
42+
* `req~statement-structure.step-wise~1`
43+
44+
Needs: impl, utest
45+
46+
Tags: Select Statement Builder
47+
48+
### Building Boolean Expressions
49+
50+
#### Forwarded Requirements
51+
52+
* `dsn --> impl, utest: req~boolean-operators~1`
53+
* `dsn --> impl, utest: req~comparison-operations~1`
54+
55+
#### Constructing Boolean Comparison Operations From Operator Strings
56+
`dsn~boolean-operation.comparison.constructing-from-strings~1`
57+
58+
The Boolean Expression builder allows creating expression objects from a string representing the comparison operator (options listed below) and a list of operands.
59+
60+
* `>`
61+
* `<`
62+
* `=`
63+
* `>=`
64+
* `<=`
65+
* `<>`
66+
67+
Covers:
68+
69+
* `req~boolean-operators~1`
70+
71+
Needs: impl, utest
72+
73+
#### Constructing Boolean Comparison Operations From Operator Enumeration
74+
`dsn~boolean-operation.comparison.constructing-from-enum~1`
75+
76+
The Boolean Expression builder allows creating expression objects from a enumeration of comparison operators.
77+
Covers:
78+
79+
* `req~boolean-operators~1`
80+
81+
Needs: impl, utest
82+
83+
### Building INSERT Statements
84+
85+
#### Forwarded Requirements
86+
87+
* `dsn --> impl, utest: req~insert-statements~1`
88+
* `dsn --> impl, utest: req~values-as-insert-source~1`
89+
90+
### Rendering Statements
91+
92+
#### Forwarded Requirements
93+
94+
* `dsn --> impl, utest: req~rendering.sql.configurable-case~1`
95+
* `dsn --> impl, utest: req~rendering.sql.select~1`
96+
* `dsn --> impl, utest: req~rendering.sql.insert~1`
97+
98+
#### Renderer add Double Quotes for Schema, Table and Column Identifiers
99+
`dsn~rendering.add-double-quotes-for-schema-table-and-column-identifiers~1`
100+
101+
The renderer sets the following identifiers in double quotes if configured:
102+
103+
* Schema identifiers
104+
* Table identifiers
105+
* Column identifiers (except the asterisks)
106+
107+
Comment:
108+
109+
Examples are `"my_schema"."my_table"."my_field"`, `"MY_TABLE"."MyField"` and `"MyTable".*`
110+
111+
Covers:
112+
113+
* `req~rendering.sql.confiugrable-identifier-quoting~1`
114+
115+
Needs: impl, utest
116+
117+
### Exasol Dialect Specific
118+
119+
#### Converting from 64 bit Integers to INTERVAL DAY TO SECOND
120+
`dsn~exasol.converting-int-to-interval-day-to-second~1`
121+
122+
The data converter converts integers to `INTERVAL DAY TO SECOND`.
123+
124+
Covers:
125+
126+
* `req~integer-interval-conversion~1`
127+
128+
Needs: impl, utest
129+
130+
#### Parsing INTERVAL DAY TO SECOND From Strings
131+
`dsn~exasol.parsing-interval-day-to-second-from-strings~1`
132+
133+
The data converter can parse `INTERVAL DAY TO SECOND` from strings in the following format:
134+
135+
interval-d2s = [ days SP ] hours ":" minutes [ ":" seconds [ "." milliseconds ] ]
136+
137+
hours = ( "2" "0" - "3" ) / ( [ "0" / "1" ] DIGIT )
138+
139+
minutes = ( "5" DIGIT ) / ( [ "0" - "4" ] DIGIT )
140+
141+
seconds = ( "5" DIGIT ) / ( [ "0" - "4" ] DIGIT )
142+
143+
milliseconds = 1*3DIGIT
144+
145+
Examples are `12:30`, `12:30.081` or `100 12:30:00.081`.
146+
147+
Covers:
148+
149+
* `req~integer-interval-conversion~1`
150+
151+
Needs: impl, utest
152+
153+
#### Converting from 64 bit Integers to INTERVAL YEAR TO MONTH
154+
`dsn~exasol.converting-int-to-interval-year-to-month~1`
155+
156+
The data converter converts integers to `INTERVAL YEAR TO MONTH`.
157+
158+
Covers:
159+
160+
* `req~integer-interval-conversion~1`
161+
162+
Needs: impl, utest
163+
164+
#### Parsing INTERVAL YEAR TO MONTH From Strings
165+
`dsn~exasol.parsing-interval-year-to-month-from-strings~1`
166+
167+
The data converter can parse `INTERVAL YEAR TO MONTH` from strings in the following format:
168+
169+
interval-y2m = days "-" months
170+
171+
days = 1*9DIGIT
172+
173+
months = ( "1" "0" - "2" ) / DIGIT
174+
175+
Examples are `0-1` and `100-11`.
176+
177+
Covers:
178+
179+
* `req~integer-interval-conversion~1`
180+
181+
Needs: impl, utest

0 commit comments

Comments
 (0)