diff --git a/bindings/java/src/main/java/org/github/tursodatabase/core/AbstractDB.java b/bindings/java/src/main/java/org/github/tursodatabase/core/AbstractDB.java index 7ec33edcc..b98fdc2a0 100644 --- a/bindings/java/src/main/java/org/github/tursodatabase/core/AbstractDB.java +++ b/bindings/java/src/main/java/org/github/tursodatabase/core/AbstractDB.java @@ -1,11 +1,7 @@ package org.github.tursodatabase.core; -import org.github.tursodatabase.annotations.Nullable; - import java.sql.SQLException; import java.sql.SQLFeatureNotSupportedException; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicBoolean; /** @@ -19,9 +15,6 @@ public abstract class AbstractDB { protected final String filePath; private final AtomicBoolean closed = new AtomicBoolean(true); - // Tracer for statements to avoid unfinalized statements on db close. - private final Set statementPointerSet = ConcurrentHashMap.newKeySet(); - public AbstractDB(String url, String filePath) { this.url = url; this.filePath = filePath; @@ -78,19 +71,6 @@ public abstract class AbstractDB { */ public abstract long connect() throws SQLException; - /** - * Destroys a statement. - * - * @param safePtr the pointer wrapper to remove from internal structures. - * @param ptr the raw pointer to free. - * @return Result Codes - * @throws SQLException if a database access error occurs. - */ - public synchronized int finalize(SafeStatementPointer safePtr, long ptr) throws SQLException { - // TODO: add implementation - throw new SQLFeatureNotSupportedException(); - } - /** * Creates an SQLite interface to a database with the provided open flags. * @@ -125,41 +105,4 @@ public abstract class AbstractDB { * @throws SQLException if a database access error occurs. */ protected abstract int finalize(long stmt) throws SQLException; - - /** - * Evaluates a statement. - * - * @param stmt Pointer to the statement. - * @return Result code. - * @throws SQLException if a database access error occurs. - */ - public abstract int step(long stmt) throws SQLException; - - /** - * Executes a statement with the provided parameters. - * - * @param stmt Stmt object. - * @param vals Array of parameter values. - * @return True if a row of ResultSet is ready; false otherwise. - * @throws SQLException if a database access error occurs. - * @see SQLite Exec - */ - public final synchronized boolean execute(CoreStatement stmt, @Nullable Object[] vals) throws SQLException { - throw new SQLFeatureNotSupportedException(); - } - - /** - * Executes an SQL INSERT, UPDATE or DELETE statement with the Stmt object and an array of - * parameter values of the SQL statement. - * - * @param stmt Stmt object. - * @param vals Array of parameter values. - * @return Number of database rows that were changed or inserted or deleted by the most recently - * completed SQL. - * @throws SQLException if a database access error occurs. - */ - public final synchronized long executeUpdate(CoreStatement stmt, Object[] vals) throws SQLException { - // TODO: add implementation - throw new SQLFeatureNotSupportedException(); - } } diff --git a/bindings/java/src/main/java/org/github/tursodatabase/core/CoreStatement.java b/bindings/java/src/main/java/org/github/tursodatabase/core/CoreStatement.java deleted file mode 100644 index 21848379b..000000000 --- a/bindings/java/src/main/java/org/github/tursodatabase/core/CoreStatement.java +++ /dev/null @@ -1,72 +0,0 @@ -package org.github.tursodatabase.core; - -import org.github.tursodatabase.annotations.Nullable; -import org.github.tursodatabase.jdbc4.JDBC4ResultSet; - -import java.sql.SQLException; - -public abstract class CoreStatement { - - protected final LimboConnection connection; - protected final CoreResultSet resultSet; - - @Nullable - protected String sql = null; - @Nullable - private SafeStatementPointer stmtPointer; - - protected boolean resultsWaiting = false; - - protected CoreStatement(LimboConnection connection) { - this.connection = connection; - this.resultSet = new JDBC4ResultSet(this); - } - - protected void internalClose() throws SQLException { - // TODO - } - - protected void clearGeneratedKeys() throws SQLException { - // TODO - } - - protected void updateGeneratedKeys() throws SQLException { - // TODO - } - - @Nullable - public SafeStatementPointer getStmtPointer() { - return this.stmtPointer; - } - - public void setStmtPointer(SafeStatementPointer stmtPointer) { - this.stmtPointer = stmtPointer; - } - - /** - * Calls sqlite3_step() and sets up results. - * - * @return true if the ResultSet has at least one row; false otherwise; - * @throws SQLException If the given SQL statement is nul or no database is open; - */ - protected boolean exec() throws SQLException { - if (sql == null) throw new SQLException("SQL must not be null"); - if (stmtPointer == null) throw new SQLException("stmtPointer must not be null"); - if (resultSet.isOpen()) throw new SQLException("ResultSet is open on exec"); - - boolean success = false; - boolean result = false; - - try { - result = connection.getDatabase().execute(this, null); - success = true; - } finally { - resultsWaiting = result; - if (!success) { - this.stmtPointer.close(); - } - } - - return this.stmtPointer.columnCount() != 0; - } -} diff --git a/bindings/java/src/main/java/org/github/tursodatabase/core/LimboConnection.java b/bindings/java/src/main/java/org/github/tursodatabase/core/LimboConnection.java index 91820c002..f0f000492 100644 --- a/bindings/java/src/main/java/org/github/tursodatabase/core/LimboConnection.java +++ b/bindings/java/src/main/java/org/github/tursodatabase/core/LimboConnection.java @@ -76,16 +76,16 @@ public abstract class LimboConnection implements Connection { * Compiles an SQL statement. * * @param sql An SQL statement. - * @return A SafeStmtPtr object. + * @return Pointer to statement. * @throws SQLException if a database access error occurs. */ - public SafeStatementPointer prepare(String sql) throws SQLException { + public long prepare(String sql) throws SQLException { logger.trace("DriverManager [{}] [SQLite EXEC] {}", Thread.currentThread().getName(), sql); byte[] sqlBytes = stringToUtf8ByteArray(sql); if (sqlBytes == null) { throw new SQLException("Failed to convert " + sql + " into bytes"); } - return new SafeStatementPointer(this, prepareUtf8(connectionPtr, sqlBytes)); + return prepareUtf8(connectionPtr, sqlBytes); } private native long prepareUtf8(long connectionPtr, byte[] sqlUtf8) throws SQLException; diff --git a/bindings/java/src/main/java/org/github/tursodatabase/core/LimboDB.java b/bindings/java/src/main/java/org/github/tursodatabase/core/LimboDB.java index 8bf5bfcb2..47536b1b6 100644 --- a/bindings/java/src/main/java/org/github/tursodatabase/core/LimboDB.java +++ b/bindings/java/src/main/java/org/github/tursodatabase/core/LimboDB.java @@ -115,10 +115,6 @@ public final class LimboDB extends AbstractDB { @Override protected native int finalize(long stmt); - // TODO: add support for JNI - @Override - public native int step(long stmt); - @VisibleForTesting native void throwJavaException(int errorCode) throws SQLException; diff --git a/bindings/java/src/main/java/org/github/tursodatabase/core/CoreResultSet.java b/bindings/java/src/main/java/org/github/tursodatabase/core/LimboResultSet.java similarity index 87% rename from bindings/java/src/main/java/org/github/tursodatabase/core/CoreResultSet.java rename to bindings/java/src/main/java/org/github/tursodatabase/core/LimboResultSet.java index 136ae2e7c..5d8b495ba 100644 --- a/bindings/java/src/main/java/org/github/tursodatabase/core/CoreResultSet.java +++ b/bindings/java/src/main/java/org/github/tursodatabase/core/LimboResultSet.java @@ -5,9 +5,9 @@ import java.sql.SQLException; /** * JDBC ResultSet. */ -public abstract class CoreResultSet { +public abstract class LimboResultSet { - protected final CoreStatement statement; + protected final LimboStatement statement; // Whether the result set does not have any rows. protected boolean isEmptyResultSet = false; @@ -18,7 +18,7 @@ public abstract class CoreResultSet { // number of current row, starts at 1 (0 is used to represent loading data) protected int row = 0; - protected CoreResultSet(CoreStatement statement) { + protected LimboResultSet(LimboStatement statement) { this.statement = statement; } diff --git a/bindings/java/src/main/java/org/github/tursodatabase/core/LimboStatement.java b/bindings/java/src/main/java/org/github/tursodatabase/core/LimboStatement.java new file mode 100644 index 000000000..74e18e46b --- /dev/null +++ b/bindings/java/src/main/java/org/github/tursodatabase/core/LimboStatement.java @@ -0,0 +1,49 @@ +package org.github.tursodatabase.core; + +import org.github.tursodatabase.annotations.Nullable; +import org.github.tursodatabase.jdbc4.JDBC4ResultSet; + +import java.sql.SQLException; + +public abstract class LimboStatement { + + protected final LimboConnection connection; + protected final LimboResultSet resultSet; + + @Nullable + protected String sql = null; + + protected LimboStatement(LimboConnection connection) { + this.connection = connection; + this.resultSet = new JDBC4ResultSet(this); + } + + protected void internalClose() throws SQLException { + // TODO + } + + protected void clearGeneratedKeys() throws SQLException { + // TODO + } + + protected void updateGeneratedKeys() throws SQLException { + // TODO + } + + /** + * Calls sqlite3_step() and sets up results. + * + * @return true if the ResultSet has at least one row; false otherwise; + * @throws SQLException If the given SQL statement is nul or no database is open; + */ + protected boolean exec(long stmtPointer) throws SQLException { + if (sql == null) throw new SQLException("SQL must not be null"); + + // TODO + return true; + } + + protected void step(long stmtPointer) throws SQLException { + // TODO + } +} diff --git a/bindings/java/src/main/java/org/github/tursodatabase/core/SafeStatementPointer.java b/bindings/java/src/main/java/org/github/tursodatabase/core/SafeStatementPointer.java deleted file mode 100644 index a8a90f3cd..000000000 --- a/bindings/java/src/main/java/org/github/tursodatabase/core/SafeStatementPointer.java +++ /dev/null @@ -1,55 +0,0 @@ -package org.github.tursodatabase.core; - -import java.sql.SQLException; -import java.util.concurrent.locks.ReentrantLock; - -/** - * A class for safely wrapping calls to a native pointer to a statement. - * Ensures that no other thread has access to the pointer while it is running. - */ -public class SafeStatementPointer { - - // Store a reference to database, so we can lock it before calling any safe functions. - private final LimboConnection connection; - private final long statementPtr; - - private volatile boolean closed = false; - - private final ReentrantLock connectionLock = new ReentrantLock(); - - public SafeStatementPointer(LimboConnection connection, long statementPtr) { - this.connection = connection; - this.statementPtr = statementPtr; - } - - /** - * Whether this safe pointer has been closed. - */ - public boolean isClosed() { - return closed; - } - - /** - * Close the pointer. - * - * @return the return code of the close callback function - */ - public int close() throws SQLException { - try { - connectionLock.lock(); - return internalClose(); - } finally { - connectionLock.unlock(); - } - } - - private int internalClose() throws SQLException { - // TODO - return 0; - } - - public long columnCount() throws SQLException { - // TODO - return 0; - } -} diff --git a/bindings/java/src/main/java/org/github/tursodatabase/jdbc4/JDBC4ResultSet.java b/bindings/java/src/main/java/org/github/tursodatabase/jdbc4/JDBC4ResultSet.java index 87b2aaa32..07bf6ed92 100644 --- a/bindings/java/src/main/java/org/github/tursodatabase/jdbc4/JDBC4ResultSet.java +++ b/bindings/java/src/main/java/org/github/tursodatabase/jdbc4/JDBC4ResultSet.java @@ -1,8 +1,8 @@ package org.github.tursodatabase.jdbc4; import org.github.tursodatabase.annotations.SkipNullableCheck; -import org.github.tursodatabase.core.CoreResultSet; -import org.github.tursodatabase.core.CoreStatement; +import org.github.tursodatabase.core.LimboResultSet; +import org.github.tursodatabase.core.LimboStatement; import java.io.InputStream; import java.io.Reader; @@ -12,9 +12,9 @@ import java.sql.*; import java.util.Calendar; import java.util.Map; -public class JDBC4ResultSet extends CoreResultSet implements ResultSet { +public class JDBC4ResultSet extends LimboResultSet implements ResultSet { - public JDBC4ResultSet(CoreStatement statement) { + public JDBC4ResultSet(LimboStatement statement) { super(statement); } diff --git a/bindings/java/src/main/java/org/github/tursodatabase/jdbc4/JDBC4Statement.java b/bindings/java/src/main/java/org/github/tursodatabase/jdbc4/JDBC4Statement.java index 3e370e329..428d14001 100644 --- a/bindings/java/src/main/java/org/github/tursodatabase/jdbc4/JDBC4Statement.java +++ b/bindings/java/src/main/java/org/github/tursodatabase/jdbc4/JDBC4Statement.java @@ -1,8 +1,8 @@ package org.github.tursodatabase.jdbc4; -import org.github.tursodatabase.core.LimboConnection; import org.github.tursodatabase.annotations.SkipNullableCheck; -import org.github.tursodatabase.core.CoreStatement; +import org.github.tursodatabase.core.LimboStatement; +import org.github.tursodatabase.core.LimboConnection; import java.sql.*; import java.util.concurrent.locks.ReentrantLock; @@ -10,7 +10,7 @@ import java.util.concurrent.locks.ReentrantLock; /** * Implementation of the {@link Statement} interface for JDBC 4. */ -public class JDBC4Statement extends CoreStatement implements Statement { +public class JDBC4Statement extends LimboStatement implements Statement { private boolean closed; private boolean closeOnCompletion; @@ -127,8 +127,8 @@ public class JDBC4Statement extends CoreStatement implements Statement { () -> { try { connectionLock.lock(); - connection.prepare(sql); - boolean result = exec(); + final long stmtPointer = connection.prepare(sql); + boolean result = exec(stmtPointer); updateGeneratedKeys(); // TODO: updateCount = connection.changes(); exhaustedResults = false; diff --git a/bindings/java/src/test/java/org/github/tursodatabase/jdbc4/JDBC4ConnectionTest.java b/bindings/java/src/test/java/org/github/tursodatabase/jdbc4/JDBC4ConnectionTest.java index b52164e7c..d7a53db9a 100644 --- a/bindings/java/src/test/java/org/github/tursodatabase/jdbc4/JDBC4ConnectionTest.java +++ b/bindings/java/src/test/java/org/github/tursodatabase/jdbc4/JDBC4ConnectionTest.java @@ -11,7 +11,6 @@ import java.sql.Statement; import java.util.Properties; import static org.junit.jupiter.api.Assertions.*; -import static org.junit.jupiter.api.Assertions.assertThrows; class JDBC4ConnectionTest { @@ -59,9 +58,16 @@ class JDBC4ConnectionTest { @Test void prepare_simple_create_table() throws Exception { - String filePath = TestUtils.createTempFile(); - String url = "jdbc:sqlite:" + filePath; - LimboConnection connection = new JDBC4Connection(url, filePath); connection.prepare("CREATE TABLE users (id INT PRIMARY KEY, username TEXT)"); } + + @Test + void exec_simple_create_table() throws Exception { + Statement stmt = createDefaultStatement(); + stmt.execute("CREATE TABLE users (id PRIMARY KEY INT, username TEXT)"); + } + + private Statement createDefaultStatement() throws SQLException { + return connection.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.CLOSE_CURSORS_AT_COMMIT); + } }