diff --git a/src/metabase/driver/sql_jdbc/execute.clj b/src/metabase/driver/sql_jdbc/execute.clj index 10d02abe8e64ae2181a93058ce684a1ddb6074a2..f96f0152c3e146cf26c0a1713693d0732c647e4d 100644 --- a/src/metabase/driver/sql_jdbc/execute.clj +++ b/src/metabase/driver/sql_jdbc/execute.clj @@ -32,7 +32,8 @@ [metabase.util.malli :as mu] [potemkin :as p]) (:import - (java.sql Connection JDBCType PreparedStatement ResultSet ResultSetMetaData Statement Types) + (java.sql Connection JDBCType PreparedStatement ResultSet ResultSetMetaData SQLFeatureNotSupportedException + Statement Types) (java.time Instant LocalDate LocalDateTime LocalTime OffsetDateTime OffsetTime ZonedDateTime) (javax.sql DataSource))) @@ -713,7 +714,18 @@ e))))] (let [rsmeta (.getMetaData rs) results-metadata {:cols (column-metadata driver rsmeta)}] - (respond results-metadata (reducible-rows driver rs rsmeta qp.pipeline/*canceled-chan*)))))))) + (try (respond results-metadata (reducible-rows driver rs rsmeta qp.pipeline/*canceled-chan*)) + ;; Following cancels the statment on the dbms side. + ;; It avoids blocking `.close` call, in case we reduced the results subset eg. by means of + ;; [[metabase.query-processor.middleware.limit/limit-xform]] middleware, while statment is still + ;; in progress. This problem was encountered on Redshift. For details see the issue #39018. + ;; It also handles situation where query is canceled through [[qp.pipeline/*canceled-chan*]] (#41448). + (finally (try (.cancel stmt) + (catch SQLFeatureNotSupportedException _ + (log/warnf "Statemet's `.cancel` method is not supported by the `%s` driver." + (name driver))) + (catch Throwable _ + (log/warn "Statement cancelation failed."))))))))))) (defn reducible-query "Returns a reducible collection of rows as maps from `db` and a given SQL query. This is similar to [[jdbc/reducible-query]] but reuses the