-
Notifications
You must be signed in to change notification settings - Fork 130
feat: support unnamed parameters #3820
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
Conversation
9aaf37b
to
899400c
Compare
google-cloud-spanner/src/main/java/com/google/cloud/spanner/DatabaseClient.java
Outdated
Show resolved
Hide resolved
google-cloud-spanner/src/main/java/com/google/cloud/spanner/DatabaseClient.java
Outdated
Show resolved
Hide resolved
google-cloud-spanner/src/main/java/com/google/cloud/spanner/DatabaseClientImpl.java
Outdated
Show resolved
Hide resolved
google-cloud-spanner/src/main/java/com/google/cloud/spanner/DatabaseClientImpl.java
Outdated
Show resolved
Hide resolved
...e-cloud-spanner/src/main/java/com/google/cloud/spanner/MultiplexedSessionDatabaseClient.java
Outdated
Show resolved
Hide resolved
} | ||
|
||
static ZonedDateTime convertToUTCTimezone(LocalDateTime localDateTime) { | ||
return localDateTime.atZone(UTC_ZONE); |
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.
Would it not make more sense to interpret this value with the system default timezone?
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.
Done
google-cloud-spanner/src/main/java/com/google/cloud/spanner/Statement.java
Outdated
Show resolved
Hide resolved
if (value instanceof java.util.Date) { | ||
return Value.date(SpannerTypeConverter.convertUtilDateToSpannerDate((java.util.Date) value)); | ||
} |
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'm not entirely sure about this conversion. java.util.Date
is actually more like a TIMESTAMP
than a DATE
. We should consider:
- Just disallowing the use of
java.util.Date
in the first place, as this class has serious flaws. - Or converting it to a
TIMESTAMP
rather than aDATE
.
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.
Removed java.util.Date
Statement statement = client.newStatementFactory().of("select id from test where b=?", true); | ||
Statement generatedStatement = | ||
Statement.newBuilder("select id from test where b=@p1").bind("p1").to(true).build(); | ||
mockSpanner.putStatementResult(StatementResult.query(generatedStatement, SELECT1_RESULTSET)); |
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.
We should add tests for statements with:
- Comments with question marks inside the comments
- String literals with question marks inside the string literals
- Statement hints at the start
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.
Done
@@ -41,6 +46,8 @@ class DatabaseClientImpl implements DatabaseClient { | |||
@VisibleForTesting final boolean useMultiplexedSessionPartitionedOps; | |||
@VisibleForTesting final boolean useMultiplexedSessionForRW; | |||
|
|||
private StatementFactory statementFactory = null; |
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.
nit: this can be removed
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.
Done
google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerTypeConverter.java
Show resolved
Hide resolved
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.
LGTM, with some minor nits on javadoc, and missing null handling
/** | ||
* Returns StatementFactory for the given dialect. | ||
* | ||
* <p>A {@link StatementFactory}, can be used to create statements with unnamed parameters. | ||
* | ||
* <p>Examples using {@link StatementFactory} | ||
* | ||
* <p>databaseClient.getStatementFactory().of("SELECT NAME FROM TABLE WHERE ID = ?", 10) | ||
*/ |
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.
/** | |
* Returns StatementFactory for the given dialect. | |
* | |
* <p>A {@link StatementFactory}, can be used to create statements with unnamed parameters. | |
* | |
* <p>Examples using {@link StatementFactory} | |
* | |
* <p>databaseClient.getStatementFactory().of("SELECT NAME FROM TABLE WHERE ID = ?", 10) | |
*/ | |
/** | |
* Returns a {@link StatementFactory} for the given dialect. | |
* | |
* <p>A {@link StatementFactory} can be used to create statements with unnamed parameters. | |
* This is primarily intended for framework developers who want to integrate the Spanner client | |
* with frameworks that use unnamed parameters. Developers who just want to use the Spanner | |
* client in their application, should use named parameters. | |
* | |
* <p>Examples using {@link StatementFactory} | |
* | |
* <pre>{@code | |
* Statement statement = databaseClient | |
* .getStatementFactory() | |
* .withUnnamedParameters("SELECT NAME FROM TABLE WHERE ID = ?", 10); | |
* }</pre> | |
*/ |
/** | ||
* Factory for creating {@link Statement}. | ||
* | ||
* <p>This factory class supports creating {@link Statement} with positional(or unnamed) |
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.
nit:
* <p>This factory class supports creating {@link Statement} with positional(or unnamed) | |
* <p>This factory class supports creating {@link Statement} with positional (or unnamed) |
* .withUnnamedParameters("SELECT * FROM TABLE WHERE ID = ?", 10L) | ||
* }</pre> | ||
* | ||
* How to use SQL queries with IN command |
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.
* How to use SQL queries with IN command | |
* How to use arrays with the IN operator |
* Statement statement = databaseClient.getStatementFactory() | ||
* .withUnnamedParameters("SELECT * FROM TABLE WHERE ID = ?", 10L) | ||
* }</pre> | ||
* |
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.
Can we add an example here (so after the simple query, but before the array example) that shows how to use it with multiple parameters. This could for example be an INSERT statement that inserts a row with 2 or 3 column values.
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.
done
@@ -246,4 +248,90 @@ StringBuilder toString(StringBuilder b) { | |||
} | |||
return b; | |||
} | |||
|
|||
/** | |||
* Factory for creating {@link Statement}. |
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.
* Factory for creating {@link Statement}. | |
* Factory for creating {@link Statement}s with unnamed parameters. | |
* This class is primarily intended for framework developers who want to integrate the Spanner | |
* client with a framework that uses unnamed parameters. Developers who want to use the | |
* Spanner client in their application, should use named parameters. |
* <p>For Date column, following types are supported | ||
* | ||
* <ul> | ||
* <li>java.util.Date |
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.
* <li>java.util.Date |
* | ||
* <ul> | ||
* <li>java.util.Date | ||
* <li>LocalDate |
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.
* <li>LocalDate | |
* <li>java.time.LocalDate |
* <p>For Timestamp column, following types are supported. All the dates should be in UTC | ||
* format. Incase if the timezone is not in UTC, spanner client will convert that to UTC | ||
* automatically |
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.
* <p>For Timestamp column, following types are supported. All the dates should be in UTC | |
* format. Incase if the timezone is not in UTC, spanner client will convert that to UTC | |
* automatically | |
* <p>For parameters of type TIMESTAMP, the following types are supported. Note that Spanner stores all | |
* timestamps in UTC. Instances of LocalDateTime and OffsetDateTime that use other timezones than UTC, | |
* will be converted to the corresponding UTC values before being sent to Spanner. | |
* Instances of LocalDateTime will be converted to a ZonedDateTime using the system default timezone, | |
* and then converted to UTC before being sent to Spanner. |
google-cloud-spanner/src/test/java/com/google/cloud/spanner/ValueTest.java
Show resolved
Hide resolved
* * .withUnnamedParameters("INSERT INTO TABLE (ID, name, phonenumbers) | ||
* // VALUES(?, ?, ?)", id, name, phoneNumbers) |
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.
nit: this seems like a misformat / failed copy-paste
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.
done
Currently Spanner Client Library doesn't support passing positional (or unnamed) parameters while creating the statement. This feature provides the support for unnamed parameters which helps customers to create SQL Statement with unnamed parameter(?)
Thank you for opening a Pull Request! Before submitting your PR, there are a few things you can do to make sure it goes smoothly:
Fixes #<issue_number_goes_here> ☕️
If you write sample code, please follow the samples format.