-
Notifications
You must be signed in to change notification settings - Fork 479
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Parameter binding in InfluxQL (influxdata/influxdb-java#274) #429
Merged
+309
−9
Merged
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
2ea9ec6
First simple implementation of "prepared statements"
hampelratte 658fa1d
Added another test for BoundParameterQuery
hampelratte d71f316
Implemented Builder mechanism for BoundParameterQuery
hampelratte 929cfde
Removed unnecessary method
hampelratte 7eb0b5a
Added test for the different parameter types
hampelratte f03fa37
Added equals and hashcode
hampelratte 966d781
Code cleanup
hampelratte be08bcd
Added test for BoundParameterQuery
hampelratte 58cd9eb
Improved test coverage for BoundParameterQuery
hampelratte f761e61
Removed unnecessary placeholder checks
hampelratte 2fc928e
Added paragraph for parameter binding in queries in README
hampelratte File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
101 changes: 101 additions & 0 deletions
101
src/main/java/org/influxdb/dto/BoundParameterQuery.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
package org.influxdb.dto; | ||
|
||
import com.squareup.moshi.JsonWriter; | ||
import java.io.IOException; | ||
import java.nio.charset.Charset; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
import java.util.Map.Entry; | ||
|
||
import org.influxdb.InfluxDBIOException; | ||
|
||
import okio.Buffer; | ||
|
||
public final class BoundParameterQuery extends Query { | ||
|
||
private final Map<String, Object> params = new HashMap<>(); | ||
|
||
private BoundParameterQuery(final String command, final String database) { | ||
super(command, database, true); | ||
} | ||
|
||
public String getParameterJsonWithUrlEncoded() { | ||
try { | ||
String jsonParameterObject = createJsonObject(params); | ||
String urlEncodedJsonParameterObject = encode(jsonParameterObject); | ||
return urlEncodedJsonParameterObject; | ||
} catch (IOException e) { | ||
throw new InfluxDBIOException(e); | ||
} | ||
} | ||
|
||
private String createJsonObject(final Map<String, Object> parameterMap) throws IOException { | ||
Buffer b = new Buffer(); | ||
JsonWriter writer = JsonWriter.of(b); | ||
writer.beginObject(); | ||
for (Entry<String, Object> pair : parameterMap.entrySet()) { | ||
String name = pair.getKey(); | ||
Object value = pair.getValue(); | ||
if (value instanceof Number) { | ||
Number number = (Number) value; | ||
writer.name(name).value(number); | ||
} else if (value instanceof String) { | ||
writer.name(name).value((String) value); | ||
} else if (value instanceof Boolean) { | ||
writer.name(name).value((Boolean) value); | ||
} else { | ||
writer.name(name).value(String.valueOf(value)); | ||
} | ||
} | ||
writer.endObject(); | ||
return b.readString(Charset.forName("utf-8")); | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
final int prime = 31; | ||
int result = super.hashCode(); | ||
result = prime * result + params.hashCode(); | ||
return result; | ||
} | ||
|
||
@Override | ||
public boolean equals(final Object obj) { | ||
if (this == obj) { | ||
return true; | ||
} | ||
if (!super.equals(obj)) { | ||
return false; | ||
} | ||
BoundParameterQuery other = (BoundParameterQuery) obj; | ||
if (!params.equals(other.params)) { | ||
return false; | ||
} | ||
return true; | ||
} | ||
|
||
public static class QueryBuilder { | ||
private BoundParameterQuery query; | ||
private String influxQL; | ||
|
||
public static QueryBuilder newQuery(final String influxQL) { | ||
QueryBuilder instance = new QueryBuilder(); | ||
instance.influxQL = influxQL; | ||
return instance; | ||
} | ||
|
||
public QueryBuilder forDatabase(final String database) { | ||
query = new BoundParameterQuery(influxQL, database); | ||
return this; | ||
} | ||
|
||
public QueryBuilder bind(final String placeholder, final Object value) { | ||
query.params.put(placeholder, value); | ||
return this; | ||
} | ||
|
||
public BoundParameterQuery create() { | ||
return query; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
91 changes: 91 additions & 0 deletions
91
src/test/java/org/influxdb/dto/BoundParameterQueryTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
package org.influxdb.dto; | ||
|
||
import static org.assertj.core.api.Assertions.assertThat; | ||
|
||
import java.io.IOException; | ||
import java.io.UnsupportedEncodingException; | ||
import java.net.URLDecoder; | ||
import java.nio.charset.StandardCharsets; | ||
|
||
import org.influxdb.dto.BoundParameterQuery.QueryBuilder; | ||
import org.junit.Assert; | ||
import org.junit.jupiter.api.Test; | ||
import org.junit.platform.runner.JUnitPlatform; | ||
import org.junit.runner.RunWith; | ||
|
||
import com.squareup.moshi.JsonAdapter; | ||
import com.squareup.moshi.Moshi; | ||
|
||
/** | ||
* Test for the BoundParameterQuery DTO. | ||
*/ | ||
@RunWith(JUnitPlatform.class) | ||
public class BoundParameterQueryTest { | ||
|
||
@Test | ||
public void testGetParameterJsonWithUrlEncoded() throws IOException { | ||
BoundParameterQuery query = QueryBuilder.newQuery("SELECT * FROM abc WHERE integer > $i" | ||
+ "AND double = $d AND bool = $bool AND string = $string AND other = $object") | ||
.forDatabase("foobar") | ||
.bind("i", 0) | ||
.bind("d", 1.0) | ||
.bind("bool", true) | ||
.bind("string", "test") | ||
.bind("object", new Object()) | ||
.create(); | ||
|
||
Moshi moshi = new Moshi.Builder().build(); | ||
JsonAdapter<Point> adapter = moshi.adapter(Point.class); | ||
Point point = adapter.fromJson(decode(query.getParameterJsonWithUrlEncoded())); | ||
Assert.assertEquals(0, point.i); | ||
Assert.assertEquals(1.0, point.d, 0.0); | ||
Assert.assertEquals(true, point.bool); | ||
Assert.assertEquals("test", point.string); | ||
Assert.assertTrue(point.object.matches("java.lang.Object@[a-z0-9]+")); | ||
} | ||
|
||
@Test | ||
public void testEqualsAndHashCode() { | ||
String stringA0 = "SELECT * FROM foobar WHERE a = $a"; | ||
String stringA1 = "SELECT * FROM foobar WHERE a = $a"; | ||
String stringB0 = "SELECT * FROM foobar WHERE b = $b"; | ||
|
||
Query queryA0 = QueryBuilder.newQuery(stringA0) | ||
.forDatabase(stringA0) | ||
.bind("a", 0) | ||
.create(); | ||
Query queryA1 = QueryBuilder.newQuery(stringA1) | ||
.forDatabase(stringA1) | ||
.bind("a", 0) | ||
.create(); | ||
Query queryA2 = QueryBuilder.newQuery(stringA1) | ||
.forDatabase(stringA1) | ||
.bind("a", 10) | ||
.create(); | ||
Query queryB0 = QueryBuilder.newQuery(stringB0) | ||
.forDatabase(stringB0) | ||
.bind("b", 10) | ||
.create(); | ||
|
||
assertThat(queryA0).isEqualTo(queryA0); | ||
assertThat(queryA0).isEqualTo(queryA1); | ||
assertThat(queryA0).isNotEqualTo(queryA2); | ||
assertThat(queryA0).isNotEqualTo(queryB0); | ||
assertThat(queryA0).isNotEqualTo("foobar"); | ||
|
||
assertThat(queryA0.hashCode()).isEqualTo(queryA1.hashCode()); | ||
assertThat(queryA0.hashCode()).isNotEqualTo(queryB0.hashCode()); | ||
} | ||
|
||
private static String decode(String str) throws UnsupportedEncodingException { | ||
return URLDecoder.decode(str, StandardCharsets.UTF_8.toString()); | ||
} | ||
|
||
private static class Point { | ||
int i; | ||
double d; | ||
String string; | ||
Boolean bool; | ||
String object; | ||
} | ||
} |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The moshi library has a specific behavior when deserializing numbers: #153 (comment)
I hope casting to
Number
is enough to keep the data type on the JSON object being created here.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had a look at the moshi code and tested it. This works as intended.