|
47 | 47 | import org.apache.arrow.flight.FlightStatusCode; |
48 | 48 | import org.apache.arrow.flight.Location; |
49 | 49 | import org.apache.arrow.flight.LocationSchemes; |
50 | | -import org.apache.arrow.flight.SessionOptionValue; |
51 | 50 | import org.apache.arrow.flight.SessionOptionValueFactory; |
52 | 51 | import org.apache.arrow.flight.SetSessionOptionsRequest; |
53 | 52 | import org.apache.arrow.flight.SetSessionOptionsResult; |
@@ -147,20 +146,26 @@ public List<CloseableEndpointStreamPair> getStreams(final FlightInfo flightInfo) |
147 | 146 | try { |
148 | 147 | for (FlightEndpoint endpoint : flightInfo.getEndpoints()) { |
149 | 148 | if (endpoint.getLocations().isEmpty()) { |
150 | | - // Create a stream using the current client only and do not close the client at the end. |
| 149 | + // Create a stream using the current client only and do not close the client at |
| 150 | + // the end. |
151 | 151 | endpoints.add( |
152 | 152 | new CloseableEndpointStreamPair( |
153 | 153 | sqlClient.getStream(endpoint.getTicket(), getOptions()), null)); |
154 | 154 | } else { |
155 | 155 | // Clone the builder and then set the new endpoint on it. |
156 | 156 |
|
157 | | - // GH-38574: Currently a new FlightClient will be made for each partition that returns a |
158 | | - // non-empty Location then disposed of. It may be better to cache clients because a server |
159 | | - // may report the same Locations. It would also be good to identify when the reported |
| 157 | + // GH-38574: Currently a new FlightClient will be made for each partition that |
| 158 | + // returns a |
| 159 | + // non-empty Location then disposed of. It may be better to cache clients |
| 160 | + // because a server |
| 161 | + // may report the same Locations. It would also be good to identify when the |
| 162 | + // reported |
160 | 163 | // location |
161 | | - // is the same as the original connection's Location and skip creating a FlightClient in |
| 164 | + // is the same as the original connection's Location and skip creating a |
| 165 | + // FlightClient in |
162 | 166 | // that scenario. |
163 | | - // Also copy the cache to the client so we can share a cache. Cache needs to cache |
| 167 | + // Also copy the cache to the client so we can share a cache. Cache needs to |
| 168 | + // cache |
164 | 169 | // negative attempts too. |
165 | 170 | List<Exception> exceptions = new ArrayList<>(); |
166 | 171 | CloseableEndpointStreamPair stream = null; |
@@ -337,7 +342,8 @@ private boolean isBenignCloseException(FlightRuntimeException fre) { |
337 | 342 | */ |
338 | 343 | private void logSuppressedCloseException( |
339 | 344 | FlightRuntimeException fre, String operationDescription) { |
340 | | - // ARROW-17785 and GH-863: suppress exceptions caused by flaky gRPC layer during shutdown |
| 345 | + // ARROW-17785 and GH-863: suppress exceptions caused by flaky gRPC layer during |
| 346 | + // shutdown |
341 | 347 | LOGGER.debug("Suppressed error {}", operationDescription, fre); |
342 | 348 | } |
343 | 349 |
|
@@ -388,25 +394,40 @@ public interface PreparedStatement extends AutoCloseable { |
388 | 394 | /** A connection is created with catalog set as a session option. */ |
389 | 395 | private void setSetCatalogInSessionIfPresent() { |
390 | 396 | if (catalog.isPresent()) { |
391 | | - final SetSessionOptionsRequest setSessionOptionRequest = |
392 | | - new SetSessionOptionsRequest( |
393 | | - ImmutableMap.<String, SessionOptionValue>builder() |
394 | | - .put(CATALOG, SessionOptionValueFactory.makeSessionOptionValue(catalog.get())) |
395 | | - .build()); |
396 | | - final SetSessionOptionsResult result = |
397 | | - sqlClient.setSessionOptions(setSessionOptionRequest, getOptions()); |
| 397 | + try { |
| 398 | + setCatalog(catalog.get()); |
| 399 | + } catch (SQLException e) { |
| 400 | + throw CallStatus.INVALID_ARGUMENT |
| 401 | + .withDescription(e.getMessage()) |
| 402 | + .withCause(e) |
| 403 | + .toRuntimeException(); |
| 404 | + } |
| 405 | + } |
| 406 | + } |
398 | 407 |
|
| 408 | + /** |
| 409 | + * Sets the catalog for the current session. |
| 410 | + * |
| 411 | + * @param catalog the catalog to set. |
| 412 | + * @throws SQLException if an error occurs while setting the catalog. |
| 413 | + */ |
| 414 | + public void setCatalog(final String catalog) throws SQLException { |
| 415 | + final SetSessionOptionsRequest request = |
| 416 | + new SetSessionOptionsRequest( |
| 417 | + ImmutableMap.of(CATALOG, SessionOptionValueFactory.makeSessionOptionValue(catalog))); |
| 418 | + try { |
| 419 | + final SetSessionOptionsResult result = sqlClient.setSessionOptions(request, getOptions()); |
399 | 420 | if (result.hasErrors()) { |
400 | | - Map<String, SetSessionOptionsResult.Error> errors = result.getErrors(); |
401 | | - for (Map.Entry<String, SetSessionOptionsResult.Error> error : errors.entrySet()) { |
| 421 | + final Map<String, SetSessionOptionsResult.Error> errors = result.getErrors(); |
| 422 | + for (final Map.Entry<String, SetSessionOptionsResult.Error> error : errors.entrySet()) { |
402 | 423 | LOGGER.warn(error.toString()); |
403 | 424 | } |
404 | | - throw CallStatus.INVALID_ARGUMENT |
405 | | - .withDescription( |
406 | | - String.format( |
407 | | - "Cannot set session option for catalog = %s. Check log for details.", catalog)) |
408 | | - .toRuntimeException(); |
| 425 | + throw new SQLException( |
| 426 | + String.format( |
| 427 | + "Cannot set session option for catalog = %s. Check log for details.", catalog)); |
409 | 428 | } |
| 429 | + } catch (final FlightRuntimeException e) { |
| 430 | + throw new SQLException(e); |
410 | 431 | } |
411 | 432 | } |
412 | 433 |
|
@@ -654,7 +675,8 @@ public static final class Builder { |
654 | 675 |
|
655 | 676 | @VisibleForTesting @Nullable Duration connectTimeout; |
656 | 677 |
|
657 | | - // These two middleware are for internal use within build() and should not be exposed by builder |
| 678 | + // These two middleware are for internal use within build() and should not be |
| 679 | + // exposed by builder |
658 | 680 | // APIs. |
659 | 681 | // Note that these middleware may not necessarily be registered. |
660 | 682 | @VisibleForTesting |
@@ -980,15 +1002,17 @@ public Location getLocation() { |
980 | 1002 | * @throws SQLException on error. |
981 | 1003 | */ |
982 | 1004 | public ArrowFlightSqlClientHandler build() throws SQLException { |
983 | | - // Copy middleware so that the build method doesn't change the state of the builder fields |
| 1005 | + // Copy middleware so that the build method doesn't change the state of the |
| 1006 | + // builder fields |
984 | 1007 | // itself. |
985 | 1008 | Set<FlightClientMiddleware.Factory> buildTimeMiddlewareFactories = |
986 | 1009 | new HashSet<>(this.middlewareFactories); |
987 | 1010 | FlightClient client = null; |
988 | 1011 | boolean isUsingUserPasswordAuth = username != null && token == null; |
989 | 1012 |
|
990 | 1013 | try { |
991 | | - // Token should take priority since some apps pass in a username/password even when a token |
| 1014 | + // Token should take priority since some apps pass in a username/password even |
| 1015 | + // when a token |
992 | 1016 | // is provided |
993 | 1017 | if (isUsingUserPasswordAuth) { |
994 | 1018 | buildTimeMiddlewareFactories.add(authFactory); |
@@ -1047,8 +1071,10 @@ public ArrowFlightSqlClientHandler build() throws SQLException { |
1047 | 1071 | allocator, channelBuilder.build(), clientBuilder.middleware()); |
1048 | 1072 | final ArrayList<CallOption> credentialOptions = new ArrayList<>(); |
1049 | 1073 | if (isUsingUserPasswordAuth) { |
1050 | | - // If the authFactory has already been used for a handshake, use the existing token. |
1051 | | - // This can occur if the authFactory is being re-used for a new connection spawned for |
| 1074 | + // If the authFactory has already been used for a handshake, use the existing |
| 1075 | + // token. |
| 1076 | + // This can occur if the authFactory is being re-used for a new connection |
| 1077 | + // spawned for |
1052 | 1078 | // getStream(). |
1053 | 1079 | if (authFactory.getCredentialCallOption() != null) { |
1054 | 1080 | credentialOptions.add(authFactory.getCredentialCallOption()); |
|
0 commit comments