Skip to content

Commit edf1f7d

Browse files
author
Olha Virolainen
authored
Merge pull request #15 from elasticio/issue-13-loggining-error
Issue 13 loggining error
2 parents d6ed1c7 + 5b8e59b commit edf1f7d

File tree

10 files changed

+263
-221
lines changed

10 files changed

+263
-221
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@ Internally we use prepared statements, so all incoming data is
123123
validated against SQL injection, however we had to build a connection from JavaScript types to the SQL data types
124124
therefore when doing a prepared statements, you would need to add ``:type`` to **each prepared statement variable**.
125125

126+
**Note:** prepared statement variables name could contain: any characters between a-z or A-Z, a digit and a character `_` (`[a-zA-Z0-9_]`).
127+
126128
For example if you have a following SQL statement:
127129

128130
```sql

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
group = 'io.elastic'
2-
version = '2.3.0-SNAPSHOT'
2+
version = '2.0.1'
33
apply plugin: 'java'
44
apply plugin: 'idea'
55
apply plugin: 'eclipse'

changelog.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,12 @@
99
### Fixed
1010
### Security
1111

12-
## [V2.0] 2018-09-19 elastic.io
12+
## [V2.0.1] 2019-06-24 elastic.io
13+
14+
### Fixed
15+
- Improvement error logging for generating metadata of `Select` action
16+
17+
## [V2.0.0] 2018-09-19 elastic.io
1318

1419
### Added
1520

src/main/java/io/elastic/jdbc/QueryColumnNamesProvider.java

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,16 +44,37 @@ public JsonObject getMetaModel(JsonObject configuration) {
4444
public JsonObject getColumns(JsonObject configuration) {
4545
JsonObjectBuilder properties = Json.createObjectBuilder();
4646
String sqlQuery = configuration.getString("sqlQuery");
47+
Pattern patternCheckCharacter = Pattern.compile(Utils.TEMPLATE_REGEXP);
48+
Matcher matcherCheckCharacter = patternCheckCharacter.matcher(sqlQuery);
4749
Pattern pattern = Pattern.compile(Utils.VARS_REGEXP);
4850
Matcher matcher = pattern.matcher(sqlQuery);
4951
Boolean isEmpty = true;
5052
if (matcher.find()) {
5153
do {
54+
matcherCheckCharacter.find();
5255
LOGGER.info("Var = {}", matcher.group());
56+
LOGGER.info("Var matcherCheckCharacter = {}", matcherCheckCharacter.group());
57+
if (!matcher.group().equals(matcherCheckCharacter.group())){
58+
throw new RuntimeException(
59+
"Prepared statement variables name '"
60+
+ matcherCheckCharacter.group()
61+
+ "' contains a forbidden character. "
62+
+ "The name could contain: any word character, a digit and a character '_'");
63+
}
5364
JsonObjectBuilder field = Json.createObjectBuilder();
5465
String result[] = matcher.group().split(":");
55-
String name = result[0].substring(1);
56-
String type = result[1];
66+
String name;
67+
String type;
68+
if (result.length > 0 && result.length < 3){
69+
name = result[0].substring(1);
70+
if (result.length == 1){
71+
type = "string";
72+
} else {
73+
type = result[1];
74+
}
75+
} else {
76+
throw new RuntimeException("Incorrect prepared statement" + matcher.group());
77+
}
5778
field.add("title", name)
5879
.add("type", type);
5980
properties.add(name, field);

src/main/java/io/elastic/jdbc/Utils.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ public class Utils {
3131
public static final String CFG_DB_ENGINE = "dbEngine";
3232
public static final String CFG_HOST = "host";
3333
public static final String CFG_USER = "user";
34-
public static final String VARS_REGEXP = "@([\\w_$][\\d\\w_$]*(:(string|boolean|date|number|bigint|float|real))?)";
34+
public static final String VARS_REGEXP = "\\B@([\\w_$][\\d\\w_$]*(:(string|boolean|date|number|bigint|float|real))?)";
35+
public static final String TEMPLATE_REGEXP = "\\B@\\S+";
3536
private static final Logger LOGGER = LoggerFactory.getLogger(Utils.class);
3637
public static Map<String, String> columnTypes = null;
3738

@@ -190,7 +191,7 @@ public static Map<String, String> getColumnTypes(Connection connection, Boolean
190191
String tableName) {
191192
DatabaseMetaData md;
192193
ResultSet rs = null;
193-
Map<String, String> columnTypes = new HashMap<String, String>();
194+
Map<String, String> columnTypes = new HashMap<>();
194195
String schemaName = null;
195196
try {
196197
md = connection.getMetaData();
@@ -219,7 +220,7 @@ public static Map<String, String> getColumnTypes(Connection connection, Boolean
219220
}
220221

221222
public static Map<String, String> getVariableTypes(String sqlQuery) {
222-
Map<String, String> columnTypes = new HashMap<String, String>();
223+
Map<String, String> columnTypes = new HashMap<>();
223224
Pattern pattern = Pattern.compile(Utils.VARS_REGEXP);
224225
Matcher matcher = pattern.matcher(sqlQuery);
225226
Boolean isEmpty;
@@ -299,5 +300,4 @@ public static JsonObjectBuilder getColumnDataByType(ResultSet rs, ResultSetMetaD
299300
}
300301
return row;
301302
}
302-
303303
}

src/main/java/io/elastic/jdbc/triggers/SelectTrigger.java

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,15 @@
77
import io.elastic.jdbc.QueryFactory;
88
import io.elastic.jdbc.Utils;
99
import java.sql.Connection;
10-
import java.sql.ResultSet;
1110
import java.sql.SQLException;
1211
import java.sql.Timestamp;
1312
import java.text.SimpleDateFormat;
1413
import java.util.ArrayList;
1514
import java.util.Calendar;
15+
import java.util.regex.Matcher;
16+
import java.util.regex.Pattern;
1617
import javax.json.Json;
1718
import javax.json.JsonObject;
18-
import javax.json.JsonString;
1919
import org.slf4j.Logger;
2020
import org.slf4j.LoggerFactory;
2121

@@ -34,8 +34,9 @@ public class SelectTrigger implements Module {
3434
public final void execute(ExecutionParameters parameters) {
3535
LOGGER.info("About to execute select trigger");
3636
final JsonObject configuration = parameters.getConfiguration();
37-
JsonObject snapshot = parameters.getSnapshot();
3837
checkConfig(configuration);
38+
String sqlQuery = configuration.getString(SQL_QUERY_VALUE);
39+
JsonObject snapshot = parameters.getSnapshot();
3940
Connection connection = Utils.getConnection(configuration);
4041
Integer skipNumber = 0;
4142

@@ -60,12 +61,11 @@ public final void execute(ExecutionParameters parameters) {
6061
pollingValue = cts;
6162
}
6263
LOGGER.info("EIO_LAST_POLL = {}", pollingValue);
63-
String sqlQuery = configuration.getString(SQL_QUERY_VALUE);
64+
6465
if (snapshot.get(PROPERTY_SKIP_NUMBER) != null) {
6566
skipNumber = snapshot.getInt(PROPERTY_SKIP_NUMBER);
6667
}
6768
LOGGER.info("SQL QUERY {} : ", sqlQuery);
68-
ResultSet rs = null;
6969
LOGGER.info("Executing select trigger");
7070
try {
7171
QueryFactory queryFactory = new QueryFactory();
@@ -97,11 +97,19 @@ public final void execute(ExecutionParameters parameters) {
9797
}
9898

9999
private void checkConfig(JsonObject config) {
100-
final JsonString sqlQuery = config.getJsonString(SQL_QUERY_VALUE);
100+
final String sqlQuery = config.getString(SQL_QUERY_VALUE);
101101

102-
if (sqlQuery == null || sqlQuery.toString().isEmpty()) {
102+
if (sqlQuery == null || sqlQuery.isEmpty()) {
103103
throw new RuntimeException("SQL Query is required field");
104104
}
105+
106+
Pattern pattern = Pattern.compile(Utils.TEMPLATE_REGEXP);
107+
Matcher matcher = pattern.matcher(sqlQuery);
108+
if (matcher.find()) {
109+
throw new RuntimeException("Use of prepared statement variables is forbidden: '"
110+
+ matcher.group()
111+
+ "'");
112+
}
105113
}
106114

107115
}

src/test/groovy/io/elastic/jdbc/QueryColumnNamesProviderSpec.groovy

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,15 @@ import javax.json.Json
66
import javax.json.JsonObject
77
import javax.json.JsonObjectBuilder
88

9-
@Ignore
109
class QueryColumnNamesProviderSpec extends Specification {
1110

1211
JsonObjectBuilder configuration = Json.createObjectBuilder()
1312
String sqlQuery
13+
String wrongSqlQuery
1414

1515
def setup() {
16-
sqlQuery = "SELECT * FROM films WHERE watched = @watched:boolean AND created = @created:date"
16+
sqlQuery = "SELECT * FROM films WHERE watched = @watched:boolean AND created = @created:date AND name = @name"
17+
wrongSqlQuery = "SELECT * FROM films WHERE watched = @watched.name:boolean"
1718
}
1819

1920
def "get metadata model, given json object"() {
@@ -23,6 +24,16 @@ class QueryColumnNamesProviderSpec extends Specification {
2324
JsonObject meta = provider.getMetaModel(configuration.build())
2425
print meta
2526
expect:
26-
meta.toString() == "{\"out\":{\"type\":\"object\",\"properties\":{\"watched\":{\"title\":\"watched\",\"type\":\"boolean\"},\"created\":{\"title\":\"created\",\"type\":\"date\"}}},\"in\":{\"type\":\"object\",\"properties\":{\"watched\":{\"title\":\"watched\",\"type\":\"boolean\"},\"created\":{\"title\":\"created\",\"type\":\"date\"}}}}"
27+
meta.toString() == "{\"out\":{\"type\":\"object\",\"properties\":{\"watched\":{\"title\":\"watched\",\"type\":\"boolean\"},\"created\":{\"title\":\"created\",\"type\":\"date\"},\"name\":{\"title\":\"name\",\"type\":\"string\"}}},\"in\":{\"type\":\"object\",\"properties\":{\"watched\":{\"title\":\"watched\",\"type\":\"boolean\"},\"created\":{\"title\":\"created\",\"type\":\"date\"},\"name\":{\"title\":\"name\",\"type\":\"string\"}}}}"
28+
}
29+
30+
def "get metadata model, wrong sqlQuery"() {
31+
configuration.add("sqlQuery", wrongSqlQuery)
32+
given :
33+
QueryColumnNamesProvider provider = new QueryColumnNamesProvider()
34+
when:
35+
provider.getMetaModel(configuration.build())
36+
then:
37+
thrown RuntimeException
2738
}
2839
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package io.elastic.jdbc
2+
3+
import spock.lang.Shared
4+
import spock.lang.Specification
5+
6+
import javax.json.Json
7+
import javax.json.JsonObjectBuilder
8+
import io.elastic.jdbc.triggers.SelectTrigger
9+
10+
class SelectTriggerCheckConfigSpec extends Specification {
11+
@Shared
12+
SelectTrigger trigger
13+
14+
JsonObjectBuilder configuration = Json.createObjectBuilder()
15+
String sqlQuery
16+
17+
def setup() {
18+
trigger = new SelectTrigger()
19+
}
20+
21+
def "check sqlQuery string with @parameter:type"() {
22+
sqlQuery = 'SELECT * from stars WHERE id= @id:number'
23+
configuration.add("sqlQuery", sqlQuery)
24+
25+
when:
26+
trigger.checkConfig(configuration.build())
27+
then:
28+
thrown RuntimeException
29+
}
30+
31+
def "check sqlQuery string with @parameter.name:type"() {
32+
sqlQuery = 'SELECT * from stars WHERE id= @id.name:number'
33+
configuration.add("sqlQuery", sqlQuery)
34+
35+
when:
36+
trigger.checkConfig(configuration.build())
37+
then:
38+
thrown RuntimeException
39+
}
40+
41+
def "sqlQuery string is empty"() {
42+
configuration.add("sqlQuery", '')
43+
when:
44+
trigger.checkConfig(configuration.build())
45+
then:
46+
thrown RuntimeException
47+
}
48+
49+
def "confid isn't contains sqlQuery string"() {
50+
when:
51+
trigger.checkConfig(configuration.build())
52+
then:
53+
thrown RuntimeException
54+
}
55+
56+
}

0 commit comments

Comments
 (0)