2424import com .google .cloud .spanner .connection .Connection ;
2525import com .google .cloud .spanner .connection .StatementResult ;
2626import com .google .cloud .spanner .connection .StatementResult .ClientSideStatementType ;
27+ import com .google .common .annotations .VisibleForTesting ;
2728import com .google .common .base .Stopwatch ;
2829import com .google .rpc .Code ;
2930import java .sql .ResultSet ;
3536import java .util .concurrent .TimeUnit ;
3637import java .util .function .Function ;
3738import java .util .function .Supplier ;
39+ import javax .annotation .Nonnull ;
3840
3941/** Base class for Cloud Spanner JDBC {@link Statement}s */
4042abstract class AbstractJdbcStatement extends AbstractJdbcWrapper implements Statement {
@@ -45,7 +47,7 @@ abstract class AbstractJdbcStatement extends AbstractJdbcWrapper implements Stat
4547 private boolean closeOnCompletion ;
4648 private boolean poolable ;
4749 private final JdbcConnection connection ;
48- private int queryTimeout ;
50+ private Duration queryTimeout = Duration . ZERO ;
4951
5052 AbstractJdbcStatement (JdbcConnection connection ) throws SQLException {
5153 this .connection = connection ;
@@ -148,13 +150,22 @@ protected <T> T runWithStatementTimeout(JdbcFunction<Connection, T> function)
148150 */
149151 StatementTimeout setTemporaryStatementTimeout () throws SQLException {
150152 StatementTimeout originalTimeout = null ;
151- if (getQueryTimeout () > 0 ) {
153+ if (! getQueryTimeoutDuration (). isZero () ) {
152154 if (connection .getSpannerConnection ().hasStatementTimeout ()) {
153155 TimeUnit unit = getAppropriateTimeUnit ();
154156 originalTimeout =
155157 StatementTimeout .of (connection .getSpannerConnection ().getStatementTimeout (unit ), unit );
156158 }
157- connection .getSpannerConnection ().setStatementTimeout (getQueryTimeout (), TimeUnit .SECONDS );
159+ Duration queryTimeout = getQueryTimeoutDuration ();
160+ if (queryTimeout .getNano () > 0 ) {
161+ connection
162+ .getSpannerConnection ()
163+ .setStatementTimeout (queryTimeout .toMillis (), TimeUnit .MILLISECONDS );
164+ } else {
165+ connection
166+ .getSpannerConnection ()
167+ .setStatementTimeout (queryTimeout .getSeconds (), TimeUnit .SECONDS );
168+ }
158169 }
159170 return originalTimeout ;
160171 }
@@ -164,7 +175,7 @@ StatementTimeout setTemporaryStatementTimeout() throws SQLException {
164175 * has been executed.
165176 */
166177 void resetStatementTimeout (StatementTimeout originalTimeout ) throws SQLException {
167- if (getQueryTimeout () > 0 ) {
178+ if (! getQueryTimeoutDuration (). isZero () ) {
168179 if (originalTimeout == null ) {
169180 connection .getSpannerConnection ().clearStatementTimeout ();
170181 } else {
@@ -317,14 +328,26 @@ private StatementResult rerunShowStatementTimeout(com.google.cloud.spanner.State
317328
318329 @ Override
319330 public int getQueryTimeout () throws SQLException {
331+ return (int ) getQueryTimeoutDuration ().getSeconds ();
332+ }
333+
334+ @ VisibleForTesting
335+ @ Nonnull
336+ Duration getQueryTimeoutDuration () throws SQLException {
320337 checkClosed ();
321- return queryTimeout ;
338+ return this . queryTimeout ;
322339 }
323340
324341 @ Override
325342 public void setQueryTimeout (int seconds ) throws SQLException {
343+ setQueryTimeout (Duration .ofSeconds (seconds ));
344+ }
345+
346+ @ VisibleForTesting
347+ void setQueryTimeout (@ Nonnull Duration duration ) throws SQLException {
348+ JdbcPreconditions .checkArgument (!duration .isNegative (), "Timeout must be >= 0" );
326349 checkClosed ();
327- this .queryTimeout = seconds ;
350+ this .queryTimeout = duration ;
328351 }
329352
330353 @ Override
0 commit comments