Implement execute batch

This commit is contained in:
김선우
2025-08-24 09:15:07 +09:00
parent b113c497aa
commit df41994ecc
2 changed files with 290 additions and 4 deletions

View File

@@ -7,6 +7,7 @@ import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.sql.BatchUpdateException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
@@ -120,4 +121,218 @@ class JDBC4StatementTest {
assertThat(stmt.executeUpdate("DELETE FROM s1")).isEqualTo(3);
}
/** Tests for batch processing functionality */
@Test
void testAddBatch_single_statement() throws SQLException {
stmt.execute("CREATE TABLE batch_test (id INTEGER PRIMARY KEY, value TEXT);");
// Add a single batch command
stmt.addBatch("INSERT INTO batch_test VALUES (1, 'test1');");
// Execute batch
int[] updateCounts = stmt.executeBatch();
// Verify results
assertThat(updateCounts).hasSize(1);
assertThat(updateCounts[0]).isEqualTo(1);
// Verify data was inserted
ResultSet rs = stmt.executeQuery("SELECT COUNT(*) FROM batch_test;");
assertTrue(rs.next());
assertThat(rs.getInt(1)).isEqualTo(1);
}
@Test
void testAddBatch_multiple_statements() throws SQLException {
stmt.execute("CREATE TABLE batch_test (id INTEGER PRIMARY KEY, value TEXT);");
// Add multiple batch commands
stmt.addBatch("INSERT INTO batch_test VALUES (1, 'test1');");
stmt.addBatch("INSERT INTO batch_test VALUES (2, 'test2');");
stmt.addBatch("INSERT INTO batch_test VALUES (3, 'test3');");
// Execute batch
int[] updateCounts = stmt.executeBatch();
// Verify results
assertThat(updateCounts).hasSize(3);
assertThat(updateCounts[0]).isEqualTo(1);
assertThat(updateCounts[1]).isEqualTo(1);
assertThat(updateCounts[2]).isEqualTo(1);
// Verify all data was inserted
ResultSet rs = stmt.executeQuery("SELECT COUNT(*) FROM batch_test;");
assertTrue(rs.next());
assertThat(rs.getInt(1)).isEqualTo(3);
}
@Test
void testAddBatch_with_updates_and_deletes() throws SQLException {
stmt.execute("CREATE TABLE batch_test (id INTEGER PRIMARY KEY, value TEXT);");
// Insert initial data
stmt.execute(
"INSERT INTO batch_test VALUES (1, 'initial1'), (2, 'initial2'), (3, 'initial3');");
// Add batch commands with different operations
stmt.addBatch("UPDATE batch_test SET value = 'updated' WHERE id = 1;");
stmt.addBatch("DELETE FROM batch_test WHERE id = 2;");
stmt.addBatch("INSERT INTO batch_test VALUES (4, 'new');");
// Execute batch
int[] updateCounts = stmt.executeBatch();
// Verify update counts
assertThat(updateCounts).hasSize(3);
assertThat(updateCounts[0]).isEqualTo(1); // UPDATE affected 1 row
assertThat(updateCounts[1]).isEqualTo(1); // DELETE affected 1 row
assertThat(updateCounts[2]).isEqualTo(1); // INSERT affected 1 row
// Verify final state
ResultSet rs = stmt.executeQuery("SELECT COUNT(*) FROM batch_test;");
assertTrue(rs.next());
assertThat(rs.getInt(1)).isEqualTo(3); // 3 initial - 1 deleted + 1 inserted = 3
}
@Test
void testClearBatch() throws SQLException {
stmt.execute("CREATE TABLE batch_test (id INTEGER PRIMARY KEY, value TEXT);");
// Add batch commands
stmt.addBatch("INSERT INTO batch_test VALUES (1, 'test1');");
stmt.addBatch("INSERT INTO batch_test VALUES (2, 'test2');");
// Clear the batch
stmt.clearBatch();
// Execute batch should return empty array
int[] updateCounts = stmt.executeBatch();
assertThat(updateCounts).isEmpty();
// Verify no data was inserted
ResultSet rs = stmt.executeQuery("SELECT COUNT(*) FROM batch_test;");
assertTrue(rs.next());
assertThat(rs.getInt(1)).isEqualTo(0);
}
@Test
void testBatch_with_DDL_statements() throws SQLException {
// DDL statements should work in batch
stmt.addBatch("CREATE TABLE batch_test1 (id INTEGER);");
stmt.addBatch("CREATE TABLE batch_test2 (id INTEGER);");
stmt.addBatch("CREATE TABLE batch_test3 (id INTEGER);");
// Execute batch
int[] updateCounts = stmt.executeBatch();
// DDL statements typically return 0 for update count
assertThat(updateCounts).hasSize(3);
assertThat(updateCounts[0]).isEqualTo(0);
assertThat(updateCounts[1]).isEqualTo(0);
assertThat(updateCounts[2]).isEqualTo(0);
// Verify tables were created by inserting data
assertDoesNotThrow(() -> stmt.execute("INSERT INTO batch_test1 VALUES (1);"));
assertDoesNotThrow(() -> stmt.execute("INSERT INTO batch_test2 VALUES (1);"));
assertDoesNotThrow(() -> stmt.execute("INSERT INTO batch_test3 VALUES (1);"));
}
@Test
void testBatch_with_SELECT_should_throw_exception() throws SQLException {
stmt.execute("CREATE TABLE batch_test (id INTEGER PRIMARY KEY, value TEXT);");
stmt.execute("INSERT INTO batch_test VALUES (1, 'test1');");
// Add a SELECT statement to batch (not allowed)
stmt.addBatch("INSERT INTO batch_test VALUES (2, 'test2');");
stmt.addBatch("SELECT * FROM batch_test;"); // This should cause an exception
stmt.addBatch("INSERT INTO batch_test VALUES (3, 'test3');");
// Execute batch should throw BatchUpdateException
BatchUpdateException exception =
assertThrows(BatchUpdateException.class, () -> stmt.executeBatch());
// Verify exception message
assertTrue(exception.getMessage().contains("Batch commands cannot return result sets"));
// Verify update counts for executed statements before the failure
int[] updateCounts = exception.getUpdateCounts();
assertThat(updateCounts).hasSize(3);
assertThat(updateCounts[0]).isEqualTo(1); // First INSERT succeeded
assertThat(updateCounts[1]).isEqualTo(Statement.EXECUTE_FAILED); // SELECT failed
// The third statement may not have been executed depending on implementation
}
@Test
void testBatch_with_null_command_should_throw_exception() throws SQLException {
// Adding null command should throw SQLException
assertThrows(SQLException.class, () -> stmt.addBatch(null));
}
@Test
void testBatch_operations_on_closed_statement_should_throw_exception() throws SQLException {
stmt.close();
// All batch operations should throw SQLException on closed statement
assertThrows(SQLException.class, () -> stmt.addBatch("INSERT INTO test VALUES (1);"));
assertThrows(SQLException.class, () -> stmt.clearBatch());
assertThrows(SQLException.class, () -> stmt.executeBatch());
}
@Test
void testBatch_with_syntax_error_should_throw_exception() throws SQLException {
stmt.execute("CREATE TABLE batch_test (id INTEGER PRIMARY KEY, value TEXT);");
// Add batch commands with a syntax error
stmt.addBatch("INSERT INTO batch_test VALUES (1, 'test1');");
stmt.addBatch("INVALID SQL SYNTAX;"); // This should cause an exception
stmt.addBatch("INSERT INTO batch_test VALUES (3, 'test3');");
// Execute batch should throw BatchUpdateException
BatchUpdateException exception =
assertThrows(BatchUpdateException.class, () -> stmt.executeBatch());
// Verify update counts show partial execution
int[] updateCounts = exception.getUpdateCounts();
assertThat(updateCounts).hasSize(3);
assertThat(updateCounts[0]).isEqualTo(1); // First INSERT succeeded
assertThat(updateCounts[1]).isEqualTo(Statement.EXECUTE_FAILED); // Invalid SQL failed
}
@Test
void testBatch_empty_batch_returns_empty_array() throws SQLException {
// Execute empty batch
int[] updateCounts = stmt.executeBatch();
// Should return empty array
assertThat(updateCounts).isEmpty();
}
@Test
void testBatch_clears_after_successful_execution() throws SQLException {
stmt.execute("CREATE TABLE batch_test (id INTEGER PRIMARY KEY, value TEXT);");
// Add and execute batch
stmt.addBatch("INSERT INTO batch_test VALUES (1, 'test1');");
stmt.executeBatch();
// Execute batch again should return empty array (batch was cleared)
int[] updateCounts = stmt.executeBatch();
assertThat(updateCounts).isEmpty();
}
@Test
void testBatch_clears_after_failed_execution() throws SQLException {
stmt.execute("CREATE TABLE batch_test (id INTEGER PRIMARY KEY, value TEXT);");
// Add batch with SELECT statement that will fail
stmt.addBatch("SELECT * FROM batch_test;");
// Execute batch should fail
assertThrows(BatchUpdateException.class, () -> stmt.executeBatch());
// Execute batch again should return empty array (batch was cleared after failure)
int[] updateCounts = stmt.executeBatch();
assertThat(updateCounts).isEmpty();
}
}