Skip to content

Commit 5365357

Browse files
refactor: Streamline error handling for database operations in InsertHandler
Co-authored-by: Paolo Di Tommaso <[email protected]> Signed-off-by: Edmund Miller <[email protected]>
1 parent 1e5658e commit 5365357

File tree

1 file changed

+71
-74
lines changed

1 file changed

+71
-74
lines changed

plugins/nf-sqldb/src/main/nextflow/sql/InsertHandler.groovy

Lines changed: 71 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -66,19 +66,57 @@ class InsertHandler implements Closeable {
6666
throw new IllegalArgumentException("SQL batch option must be greater than zero: $batchSize")
6767
}
6868

69+
private void trySetObject(PreparedStatement stm, int index, Object value) {
70+
try {
71+
stm.setObject(index, value)
72+
}
73+
catch (UnsupportedOperationException e) {
74+
log.debug "setObject is not supported by this driver (likely Databricks), trying setString fallback: ${e.message}"
75+
stm.setString(index, value?.toString())
76+
}
77+
}
78+
79+
private void trySetAutoCommit(Connection connection, boolean value) {
80+
try {
81+
connection.setAutoCommit(value)
82+
}
83+
catch(UnsupportedOperationException e) {
84+
log.debug "setAutoCommit is not supported by this driver (likely Databricks), continuing: ${e.message}"
85+
}
86+
}
87+
88+
private void tryCommit(Connection connection) {
89+
try {
90+
connection.commit()
91+
}
92+
catch(UnsupportedOperationException e) {
93+
log.debug "commit is not supported by this driver (likely Databricks), continuing: ${e.message}"
94+
}
95+
}
96+
97+
private void tryClose(PreparedStatement stm) {
98+
try {
99+
stm.close()
100+
}
101+
catch(UnsupportedOperationException e) {
102+
log.debug "PreparedStatement.close is not supported by this driver (likely Databricks), continuing: ${e.message}"
103+
}
104+
}
105+
106+
private void tryClose(Connection connection) {
107+
try {
108+
connection.close()
109+
}
110+
catch(UnsupportedOperationException e) {
111+
log.debug "Connection.close is not supported by this driver (likely Databricks), continuing: ${e.message}"
112+
}
113+
}
114+
69115
private Connection getConnection() {
70116
if( connection == null ) {
71117
connection = Sql.newInstance(ds.toMap()).getConnection()
72118
checkCreate(connection)
73-
try {
74-
connection.setAutoCommit(false)
75-
}
76-
catch(UnsupportedOperationException e) {
77-
log.debug "setAutoCommit is not supported by this driver (likely Databricks), continuing: ${e.message}"
78-
}
79-
catch(Exception e) {
80-
log.debug "Database does not support setAutoCommit, continuing with default settings: ${e.message}"
81-
}
119+
trySetAutoCommit(connection, false)
82120
}
83121
return connection
84122
}
@@ -165,19 +203,7 @@ class InsertHandler implements Closeable {
165203
for(int i=0; i<columns.size(); i++ ) {
166204
final col = columns[i]
167205
final value = record.get(col)
168-
try {
169-
stm.setObject(i+1, value)
170-
}
171-
catch(UnsupportedOperationException e) {
172-
log.debug "setObject is not supported by this driver (likely Databricks), trying setString fallback: ${e.message}"
173-
// Fallback to setString for basic types
174-
try {
175-
stm.setString(i+1, value?.toString())
176-
}
177-
catch(Exception fallbackError) {
178-
throw new RuntimeException("Failed to set parameter ${i+1} with value '${value}': both setObject and setString failed", fallbackError)
179-
}
180-
}
206+
trySetObject(stm, i+1, value)
181207
}
182208
// report a debug line
183209
log.debug "[SQL] perform sql statemet=$sql; entry=$record"
@@ -189,19 +215,7 @@ class InsertHandler implements Closeable {
189215
// loop over the tuple values and set a corresponding sql statement value
190216
for(int i=0; i<tuple.size(); i++ ) {
191217
def value = tuple[i]
192-
try {
193-
stm.setObject(i+1, value)
194-
}
195-
catch(UnsupportedOperationException e) {
196-
log.debug "setObject is not supported by this driver (likely Databricks), trying setString fallback: ${e.message}"
197-
// Fallback to setString for basic types
198-
try {
199-
stm.setString(i+1, value?.toString())
200-
}
201-
catch(Exception fallbackError) {
202-
throw new RuntimeException("Failed to set parameter ${i+1} with value '${value}': both setObject and setString failed", fallbackError)
203-
}
204-
}
218+
trySetObject(stm, i+1, value)
205219
}
206220
// report a debug line
207221
log.debug "[SQL] perform sql statemet=$sql; entry=$tuple"
@@ -217,32 +231,32 @@ class InsertHandler implements Closeable {
217231
preparedStatement.clearParameters()
218232
// invoke the operation closure with setup the statement params
219233
operation.call(preparedStatement)
220-
// add to current batch
221-
preparedStatement.addBatch()
222-
// if the batch size is reached, perform the batch statement
223-
if( ++batchCount == batchSize ) {
234+
// when the batchSize is one, execute directly (without adding to a batch)
235+
if( batchSize==1 ) {
224236
try {
225-
preparedStatement.executeBatch()
226-
preparedStatement.clearBatch()
237+
preparedStatement.execute()
238+
}
239+
finally {
240+
tryCommit(connection)
227241
}
228-
catch(UnsupportedOperationException e) {
229-
log.debug "executeBatch is not supported by this driver (likely Databricks), executing statements individually: ${e.message}"
230-
// Fallback: execute each statement individually
242+
}
243+
else {
244+
// add to current batch
245+
preparedStatement.addBatch()
246+
// if the batch size is not reached, just return
247+
if( ++batchCount < batchSize ) {
248+
return
249+
}
250+
// otherwise, if the batch is full perform the batch statement
251+
try {
252+
preparedStatement.executeBatch()
231253
preparedStatement.clearBatch()
232-
// We need to re-add and execute each statement individually
233-
// This is a limitation - we lose the current batch, but at least we don't silently fail
234-
throw new RuntimeException("Batch execution not supported by driver. Consider setting batchSize=1 for this database type.", e)
235254
}
236255
finally {
237256
// reset the current batch count
238257
batchCount = 0
239258
// make sure to commit the current batch
240-
try {
241-
connection.commit()
242-
}
243-
catch(UnsupportedOperationException e) {
244-
log.debug "commit is not supported by this driver (likely Databricks), continuing: ${e.message}"
245-
}
259+
connection.commit()
246260
}
247261
}
248262
}
@@ -281,32 +295,15 @@ class InsertHandler implements Closeable {
281295
try {
282296
if( preparedStatement && batchCount>0 ) {
283297
log.debug("[SQL] flushing and committing open batch")
284-
try {
285-
preparedStatement.executeBatch()
286-
}
287-
catch(UnsupportedOperationException e) {
288-
log.warn "executeBatch is not supported by this driver (likely Databricks). Remaining ${batchCount} statements were not executed. Consider using batchSize=1 for this database type."
289-
// Clear the batch to prevent inconsistent state
290-
preparedStatement.clearBatch()
291-
}
292-
try {
293-
preparedStatement.close()
294-
}
295-
catch(Exception e) {
296-
log.debug "Error closing prepared statement: ${e.message}"
297-
}
298-
try {
299-
connection.commit()
300-
}
301-
catch(UnsupportedOperationException e) {
302-
log.debug "commit is not supported by this driver (likely Databricks), continuing: ${e.message}"
303-
}
298+
preparedStatement.executeBatch()
299+
tryClose(preparedStatement)
300+
tryCommit(connection)
304301
}
305302
}
306303
finally {
307304
if( connection ) {
308305
log.debug "[SQL] closing JDBC connection"
309-
connection.close()
306+
tryClose(connection)
310307
}
311308
}
312309
}

0 commit comments

Comments
 (0)