mirror of
https://github.com/aljazceru/turso.git
synced 2026-02-19 15:05:47 +01:00
Merge 'bindings/java: Implement batch operations for JDBC4Statement' from Kim Seon Woo
Implement the following methods for JDBC4Statement: - addBatch - clearBatch - executeBatch Closes #2754
This commit is contained in:
@@ -176,6 +176,11 @@ public final class JDBC4PreparedStatement extends JDBC4Statement implements Prep
|
||||
// TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBatch(String sql) throws SQLException {
|
||||
throw new SQLException("addBatch(String) cannot be called on a PreparedStatement");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCharacterStream(int parameterIndex, Reader reader, int length)
|
||||
throws SQLException {}
|
||||
|
||||
@@ -2,12 +2,16 @@ package tech.turso.jdbc4;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import java.sql.BatchUpdateException;
|
||||
import java.sql.Connection;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.SQLWarning;
|
||||
import java.sql.Statement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.regex.Pattern;
|
||||
import tech.turso.annotations.Nullable;
|
||||
import tech.turso.annotations.SkipNullableCheck;
|
||||
import tech.turso.core.TursoResultSet;
|
||||
@@ -15,6 +19,20 @@ import tech.turso.core.TursoStatement;
|
||||
|
||||
public class JDBC4Statement implements Statement {
|
||||
|
||||
private static final Pattern BATCH_COMPATIBLE_PATTERN =
|
||||
Pattern.compile(
|
||||
"^\\s*"
|
||||
+ // Leading whitespace
|
||||
"(?:/\\*.*?\\*/\\s*)*"
|
||||
+ // Optional C-style comments
|
||||
"(?:--[^\\n]*\\n\\s*)*"
|
||||
+ // Optional SQL line comments
|
||||
"(?:"
|
||||
+ // Start of keywords group
|
||||
"INSERT|UPDATE|DELETE"
|
||||
+ ")\\b",
|
||||
Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
|
||||
|
||||
private final JDBC4Connection connection;
|
||||
|
||||
@Nullable protected TursoStatement statement = null;
|
||||
@@ -33,6 +51,12 @@ public class JDBC4Statement implements Statement {
|
||||
|
||||
private ReentrantLock connectionLock = new ReentrantLock();
|
||||
|
||||
/**
|
||||
* List of SQL statements to be executed as a batch. Used for batch processing as per JDBC
|
||||
* specification.
|
||||
*/
|
||||
private List<String> batchCommands = new ArrayList<>();
|
||||
|
||||
public JDBC4Statement(JDBC4Connection connection) {
|
||||
this(
|
||||
connection,
|
||||
@@ -232,18 +256,82 @@ public class JDBC4Statement implements Statement {
|
||||
|
||||
@Override
|
||||
public void addBatch(String sql) throws SQLException {
|
||||
// TODO
|
||||
ensureOpen();
|
||||
if (sql == null) {
|
||||
throw new SQLException("SQL command cannot be null");
|
||||
}
|
||||
batchCommands.add(sql);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearBatch() throws SQLException {
|
||||
// TODO
|
||||
ensureOpen();
|
||||
batchCommands.clear();
|
||||
}
|
||||
|
||||
// TODO: let's make this batch operation atomic
|
||||
@Override
|
||||
public int[] executeBatch() throws SQLException {
|
||||
// TODO
|
||||
return new int[0];
|
||||
ensureOpen();
|
||||
|
||||
int[] updateCounts = new int[batchCommands.size()];
|
||||
List<String> failedCommands = new ArrayList<>();
|
||||
|
||||
// Execute each command in the batch
|
||||
for (int i = 0; i < batchCommands.size(); i++) {
|
||||
String sql = batchCommands.get(i);
|
||||
try {
|
||||
if (!isBatchCompatibleStatement(sql)) {
|
||||
failedCommands.add(sql);
|
||||
updateCounts[i] = EXECUTE_FAILED;
|
||||
BatchUpdateException bue =
|
||||
new BatchUpdateException(
|
||||
"Batch entry "
|
||||
+ i
|
||||
+ " ("
|
||||
+ sql
|
||||
+ ") was aborted. "
|
||||
+ "Batch commands cannot return result sets.",
|
||||
"HY000", // General error SQL state
|
||||
0,
|
||||
updateCounts);
|
||||
// Clear the batch after failure
|
||||
clearBatch();
|
||||
throw bue;
|
||||
}
|
||||
|
||||
execute(sql);
|
||||
// For DML statements, get the update count
|
||||
updateCounts[i] = getUpdateCount();
|
||||
} catch (SQLException e) {
|
||||
failedCommands.add(sql);
|
||||
updateCounts[i] = EXECUTE_FAILED;
|
||||
|
||||
// Create a BatchUpdateException with the partial results
|
||||
BatchUpdateException bue =
|
||||
new BatchUpdateException(
|
||||
"Batch entry " + i + " (" + sql + ") failed: " + e.getMessage(),
|
||||
e.getSQLState(),
|
||||
e.getErrorCode(),
|
||||
updateCounts,
|
||||
e.getCause());
|
||||
// Clear the batch after failure
|
||||
clearBatch();
|
||||
throw bue;
|
||||
}
|
||||
}
|
||||
|
||||
// Clear the batch after successful execution
|
||||
clearBatch();
|
||||
return updateCounts;
|
||||
}
|
||||
|
||||
boolean isBatchCompatibleStatement(String sql) {
|
||||
if (sql == null || sql.trim().isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return BATCH_COMPATIBLE_PATTERN.matcher(sql).find();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -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,277 @@ 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);");
|
||||
|
||||
stmt.addBatch("INSERT INTO batch_test VALUES (1, 'test1');");
|
||||
|
||||
int[] updateCounts = stmt.executeBatch();
|
||||
|
||||
assertThat(updateCounts).hasSize(1);
|
||||
assertThat(updateCounts[0]).isEqualTo(1);
|
||||
|
||||
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);");
|
||||
|
||||
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');");
|
||||
|
||||
int[] updateCounts = stmt.executeBatch();
|
||||
|
||||
assertThat(updateCounts).hasSize(3);
|
||||
assertThat(updateCounts[0]).isEqualTo(1);
|
||||
assertThat(updateCounts[1]).isEqualTo(1);
|
||||
assertThat(updateCounts[2]).isEqualTo(1);
|
||||
|
||||
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);");
|
||||
|
||||
stmt.execute(
|
||||
"INSERT INTO batch_test VALUES (1, 'initial1'), (2, 'initial2'), (3, 'initial3');");
|
||||
|
||||
stmt.addBatch("UPDATE batch_test SET value = 'updated';");
|
||||
stmt.addBatch("DELETE FROM batch_test WHERE id = 2;");
|
||||
stmt.addBatch("INSERT INTO batch_test VALUES (4, 'new');");
|
||||
|
||||
int[] updateCounts = stmt.executeBatch();
|
||||
|
||||
assertThat(updateCounts).hasSize(3);
|
||||
assertThat(updateCounts[0]).isEqualTo(3); // UPDATE affected 3 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);");
|
||||
|
||||
stmt.addBatch("INSERT INTO batch_test VALUES (1, 'test1');");
|
||||
stmt.addBatch("INSERT INTO batch_test VALUES (2, 'test2');");
|
||||
|
||||
stmt.clearBatch();
|
||||
|
||||
int[] updateCounts = stmt.executeBatch();
|
||||
assertThat(updateCounts).isEmpty();
|
||||
|
||||
ResultSet rs = stmt.executeQuery("SELECT COUNT(*) FROM batch_test;");
|
||||
assertTrue(rs.next());
|
||||
assertThat(rs.getInt(1)).isEqualTo(0);
|
||||
}
|
||||
|
||||
@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');");
|
||||
|
||||
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');");
|
||||
|
||||
BatchUpdateException exception =
|
||||
assertThrows(BatchUpdateException.class, () -> stmt.executeBatch());
|
||||
|
||||
assertTrue(exception.getMessage().contains("Batch commands cannot return result sets"));
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBatch_with_null_command_should_throw_exception() {
|
||||
assertThrows(SQLException.class, () -> stmt.addBatch(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBatch_operations_on_closed_statement_should_throw_exception() throws SQLException {
|
||||
stmt.close();
|
||||
|
||||
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);");
|
||||
|
||||
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');");
|
||||
|
||||
BatchUpdateException exception =
|
||||
assertThrows(BatchUpdateException.class, () -> stmt.executeBatch());
|
||||
|
||||
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 {
|
||||
int[] updateCounts = stmt.executeBatch();
|
||||
assertThat(updateCounts).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBatch_clears_after_successful_execution() throws SQLException {
|
||||
stmt.execute("CREATE TABLE batch_test (id INTEGER PRIMARY KEY, value TEXT);");
|
||||
|
||||
stmt.addBatch("INSERT INTO batch_test VALUES (1, 'test1');");
|
||||
stmt.executeBatch();
|
||||
|
||||
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);");
|
||||
|
||||
stmt.addBatch("SELECT * FROM batch_test;");
|
||||
|
||||
assertThrows(BatchUpdateException.class, () -> stmt.executeBatch());
|
||||
|
||||
int[] updateCounts = stmt.executeBatch();
|
||||
assertThat(updateCounts).isEmpty();
|
||||
}
|
||||
|
||||
/** Tests for isBatchCompatibleStatement method */
|
||||
@Test
|
||||
void testIsBatchCompatibleStatement_compatible_statements() {
|
||||
JDBC4Statement jdbc4Stmt = (JDBC4Statement) stmt;
|
||||
|
||||
assertTrue(jdbc4Stmt.isBatchCompatibleStatement("INSERT INTO table VALUES (1, 2);"));
|
||||
assertTrue(jdbc4Stmt.isBatchCompatibleStatement("insert into table values (1, 2);"));
|
||||
assertTrue(
|
||||
jdbc4Stmt.isBatchCompatibleStatement("INSERT INTO table (col1, col2) VALUES (1, 2);"));
|
||||
assertTrue(jdbc4Stmt.isBatchCompatibleStatement("INSERT OR REPLACE INTO table VALUES (1);"));
|
||||
assertTrue(jdbc4Stmt.isBatchCompatibleStatement("INSERT OR IGNORE INTO table VALUES (1);"));
|
||||
|
||||
assertTrue(jdbc4Stmt.isBatchCompatibleStatement(" INSERT INTO table VALUES (1);"));
|
||||
assertTrue(jdbc4Stmt.isBatchCompatibleStatement("\t\nINSERT INTO table VALUES (1);"));
|
||||
assertTrue(jdbc4Stmt.isBatchCompatibleStatement(" \n\t INSERT INTO table VALUES (1);"));
|
||||
|
||||
assertTrue(jdbc4Stmt.isBatchCompatibleStatement("/* comment */ INSERT INTO table VALUES (1);"));
|
||||
assertTrue(
|
||||
jdbc4Stmt.isBatchCompatibleStatement(
|
||||
"/* multi\nline\ncomment */ INSERT INTO table VALUES (1);"));
|
||||
assertTrue(
|
||||
jdbc4Stmt.isBatchCompatibleStatement("-- line comment\nINSERT INTO table VALUES (1);"));
|
||||
assertTrue(
|
||||
jdbc4Stmt.isBatchCompatibleStatement(
|
||||
"-- comment 1\n-- comment 2\nINSERT INTO table VALUES (1);"));
|
||||
|
||||
assertTrue(
|
||||
jdbc4Stmt.isBatchCompatibleStatement(
|
||||
" /* comment */ -- another\n INSERT INTO table VALUES (1);"));
|
||||
|
||||
assertTrue(jdbc4Stmt.isBatchCompatibleStatement("UPDATE table SET col = 1;"));
|
||||
assertTrue(jdbc4Stmt.isBatchCompatibleStatement("update table set col = 1;"));
|
||||
assertTrue(
|
||||
jdbc4Stmt.isBatchCompatibleStatement("UPDATE table SET col1 = 1, col2 = 2 WHERE id = 3;"));
|
||||
assertTrue(jdbc4Stmt.isBatchCompatibleStatement("UPDATE OR REPLACE table SET col = 1;"));
|
||||
|
||||
assertTrue(jdbc4Stmt.isBatchCompatibleStatement(" UPDATE table SET col = 1;"));
|
||||
assertTrue(jdbc4Stmt.isBatchCompatibleStatement("\t\nUPDATE table SET col = 1;"));
|
||||
|
||||
assertTrue(jdbc4Stmt.isBatchCompatibleStatement("/* comment */ UPDATE table SET col = 1;"));
|
||||
assertTrue(jdbc4Stmt.isBatchCompatibleStatement("-- comment\nUPDATE table SET col = 1;"));
|
||||
|
||||
assertTrue(jdbc4Stmt.isBatchCompatibleStatement("DELETE FROM table;"));
|
||||
assertTrue(jdbc4Stmt.isBatchCompatibleStatement("delete from table;"));
|
||||
assertTrue(jdbc4Stmt.isBatchCompatibleStatement("DELETE FROM table WHERE id = 1;"));
|
||||
|
||||
assertTrue(jdbc4Stmt.isBatchCompatibleStatement(" DELETE FROM table;"));
|
||||
assertTrue(jdbc4Stmt.isBatchCompatibleStatement("\t\nDELETE FROM table;"));
|
||||
|
||||
assertTrue(jdbc4Stmt.isBatchCompatibleStatement("/* comment */ DELETE FROM table;"));
|
||||
assertTrue(jdbc4Stmt.isBatchCompatibleStatement("-- comment\nDELETE FROM table;"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testIsBatchCompatibleStatement_non_compatible_statements() {
|
||||
JDBC4Statement jdbc4Stmt = (JDBC4Statement) stmt;
|
||||
|
||||
assertFalse(jdbc4Stmt.isBatchCompatibleStatement("SELECT * FROM table;"));
|
||||
assertFalse(jdbc4Stmt.isBatchCompatibleStatement("select * from table;"));
|
||||
assertFalse(jdbc4Stmt.isBatchCompatibleStatement(" SELECT * FROM table;"));
|
||||
assertFalse(jdbc4Stmt.isBatchCompatibleStatement("/* comment */ SELECT * FROM table;"));
|
||||
assertFalse(jdbc4Stmt.isBatchCompatibleStatement("-- comment\nSELECT * FROM table;"));
|
||||
|
||||
assertFalse(jdbc4Stmt.isBatchCompatibleStatement("EXPLAIN SELECT * FROM table;"));
|
||||
assertFalse(jdbc4Stmt.isBatchCompatibleStatement("EXPLAIN QUERY PLAN SELECT * FROM table;"));
|
||||
|
||||
assertFalse(jdbc4Stmt.isBatchCompatibleStatement("PRAGMA table_info(table);"));
|
||||
assertFalse(jdbc4Stmt.isBatchCompatibleStatement("PRAGMA foreign_keys = ON;"));
|
||||
|
||||
assertFalse(jdbc4Stmt.isBatchCompatibleStatement("ANALYZE;"));
|
||||
assertFalse(jdbc4Stmt.isBatchCompatibleStatement("ANALYZE table;"));
|
||||
|
||||
assertFalse(
|
||||
jdbc4Stmt.isBatchCompatibleStatement(
|
||||
"WITH cte AS (SELECT * FROM table) SELECT * FROM cte;"));
|
||||
|
||||
assertFalse(jdbc4Stmt.isBatchCompatibleStatement("VACUUM;"));
|
||||
|
||||
assertFalse(jdbc4Stmt.isBatchCompatibleStatement("VALUES (1, 2), (3, 4);"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testIsBatchCompatibleStatement_edge_cases() {
|
||||
JDBC4Statement jdbc4Stmt = (JDBC4Statement) stmt;
|
||||
|
||||
assertFalse(jdbc4Stmt.isBatchCompatibleStatement(null));
|
||||
assertFalse(jdbc4Stmt.isBatchCompatibleStatement(""));
|
||||
assertFalse(jdbc4Stmt.isBatchCompatibleStatement(" "));
|
||||
assertFalse(jdbc4Stmt.isBatchCompatibleStatement("\t\n"));
|
||||
|
||||
assertFalse(jdbc4Stmt.isBatchCompatibleStatement("/* comment only */"));
|
||||
assertFalse(jdbc4Stmt.isBatchCompatibleStatement("-- comment only"));
|
||||
assertFalse(jdbc4Stmt.isBatchCompatibleStatement("/* comment */ -- another comment"));
|
||||
|
||||
assertFalse(jdbc4Stmt.isBatchCompatibleStatement("SELECT * FROM table WHERE name = 'INSERT';"));
|
||||
assertFalse(
|
||||
jdbc4Stmt.isBatchCompatibleStatement("SELECT * FROM table WHERE action = 'DELETE';"));
|
||||
|
||||
assertFalse(jdbc4Stmt.isBatchCompatibleStatement("INSER INTO table VALUES (1);"));
|
||||
assertFalse(jdbc4Stmt.isBatchCompatibleStatement("UPDAT table SET col = 1;"));
|
||||
assertFalse(jdbc4Stmt.isBatchCompatibleStatement("DELET FROM table;"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testIsBatchCompatibleStatement_case_insensitive() {
|
||||
JDBC4Statement jdbc4Stmt = (JDBC4Statement) stmt;
|
||||
|
||||
assertTrue(jdbc4Stmt.isBatchCompatibleStatement("Insert INTO table VALUES (1);"));
|
||||
assertTrue(jdbc4Stmt.isBatchCompatibleStatement("InSeRt INTO table VALUES (1);"));
|
||||
assertTrue(jdbc4Stmt.isBatchCompatibleStatement("UPDATE table SET col = 1;"));
|
||||
assertTrue(jdbc4Stmt.isBatchCompatibleStatement("UpDaTe table SET col = 1;"));
|
||||
assertTrue(jdbc4Stmt.isBatchCompatibleStatement("Delete FROM table;"));
|
||||
assertTrue(jdbc4Stmt.isBatchCompatibleStatement("DeLeTe FROM table;"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
{"rustc_fingerprint":11551670960185020797,"outputs":{"14427667104029986310":{"success":true,"status":"","code":0,"stdout":"rustc 1.83.0 (90b35a623 2024-11-26)\nbinary: rustc\ncommit-hash: 90b35a6239c3d8bdabc530a6a0816f7ff89a0aaf\ncommit-date: 2024-11-26\nhost: x86_64-unknown-linux-gnu\nrelease: 1.83.0\nLLVM version: 19.1.1\n","stderr":""},"11399821309745579047":{"success":true,"status":"","code":0,"stdout":"___\nlib___.rlib\nlib___.so\nlib___.so\nlib___.a\nlib___.so\n/home/merlin/.rustup/toolchains/1.83.0-x86_64-unknown-linux-gnu\noff\npacked\nunpacked\n___\ndebug_assertions\npanic=\"unwind\"\nproc_macro\ntarget_abi=\"\"\ntarget_arch=\"x86_64\"\ntarget_endian=\"little\"\ntarget_env=\"gnu\"\ntarget_family=\"unix\"\ntarget_feature=\"fxsr\"\ntarget_feature=\"sse\"\ntarget_feature=\"sse2\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_os=\"linux\"\ntarget_pointer_width=\"64\"\ntarget_vendor=\"unknown\"\nunix\n","stderr":""}},"successes":{}}
|
||||
Reference in New Issue
Block a user