mirror of
https://github.com/tursodatabase/limbo.git
synced 2025-08-04 01:58:16 +00:00
Implement prepare on java side
This commit is contained in:
parent
3e2e998060
commit
b77bf879f7
7 changed files with 71 additions and 35 deletions
|
@ -2,6 +2,7 @@ package org.github.tursodatabase;
|
|||
|
||||
import org.github.tursodatabase.annotations.Nullable;
|
||||
import org.github.tursodatabase.annotations.SkipNullableCheck;
|
||||
import org.github.tursodatabase.core.LimboConnection;
|
||||
import org.github.tursodatabase.jdbc4.JDBC4Connection;
|
||||
|
||||
import java.sql.*;
|
||||
|
|
|
@ -39,7 +39,8 @@ public enum LimboErrorCode {
|
|||
SQLITE_NULL(SqliteCode.SQLITE_NULL, "Null type"),
|
||||
|
||||
UNKNOWN_ERROR(-1, "Unknown error"),
|
||||
LIMBO_DATABASE_ALREADY_CLOSED(1000, "Database already closed"),
|
||||
LIMBO_FAILED_TO_PARSE_BYTE_ARRAY(1100, "Failed to parse ut8 byte array"),
|
||||
LIMBO_FAILED_TO_PREPARE_STATEMENT(1200, "Failed to prepare statement"),
|
||||
LIMBO_ETC(9999, "Unclassified error");
|
||||
|
||||
public final int code;
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package org.github.tursodatabase.core;
|
||||
|
||||
import org.github.tursodatabase.LimboConnection;
|
||||
import org.github.tursodatabase.annotations.Nullable;
|
||||
import org.github.tursodatabase.jdbc4.JDBC4ResultSet;
|
||||
|
||||
|
@ -68,6 +67,6 @@ public abstract class CoreStatement {
|
|||
}
|
||||
}
|
||||
|
||||
return stmtPointer.safeRunInt(AbstractDB::columnCount) != 0;
|
||||
return this.stmtPointer.columnCount() != 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -72,6 +72,24 @@ public abstract class LimboConnection implements Connection {
|
|||
return database;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles an SQL statement.
|
||||
*
|
||||
* @param sql An SQL statement.
|
||||
* @return A SafeStmtPtr object.
|
||||
* @throws SQLException if a database access error occurs.
|
||||
*/
|
||||
public SafeStatementPointer 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));
|
||||
}
|
||||
|
||||
private native long prepareUtf8(long connectionPtr, byte[] sqlUtf8) throws SQLException;
|
||||
|
||||
/**
|
||||
* @return busy timeout in milliseconds.
|
||||
*/
|
||||
|
@ -108,4 +126,15 @@ public abstract class LimboConnection implements Connection {
|
|||
public void setBusyTimeout(int busyTimeout) {
|
||||
// TODO: add support for busy timeout
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws formatted SQLException with error code and message.
|
||||
*
|
||||
* @param errorCode Error code.
|
||||
* @param errorMessageBytes Error message.
|
||||
*/
|
||||
@NativeInvocation
|
||||
private void throwLimboException(int errorCode, byte[] errorMessageBytes) throws SQLException {
|
||||
LimboExceptionUtils.throwLimboException(errorCode, errorMessageBytes);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,16 +10,16 @@ import java.util.concurrent.locks.ReentrantLock;
|
|||
public class SafeStatementPointer {
|
||||
|
||||
// Store a reference to database, so we can lock it before calling any safe functions.
|
||||
private final AbstractDB database;
|
||||
private final long databasePointer;
|
||||
private final LimboConnection connection;
|
||||
private final long statementPtr;
|
||||
|
||||
private volatile boolean closed = false;
|
||||
|
||||
private final ReentrantLock databaseLock = new ReentrantLock();
|
||||
private final ReentrantLock connectionLock = new ReentrantLock();
|
||||
|
||||
public SafeStatementPointer(AbstractDB database, long databasePointer) {
|
||||
this.database = database;
|
||||
this.databasePointer = databasePointer;
|
||||
public SafeStatementPointer(LimboConnection connection, long statementPtr) {
|
||||
this.connection = connection;
|
||||
this.statementPtr = statementPtr;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -36,10 +36,10 @@ public class SafeStatementPointer {
|
|||
*/
|
||||
public int close() throws SQLException {
|
||||
try {
|
||||
databaseLock.lock();
|
||||
connectionLock.lock();
|
||||
return internalClose();
|
||||
} finally {
|
||||
databaseLock.unlock();
|
||||
connectionLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -48,24 +48,8 @@ public class SafeStatementPointer {
|
|||
return 0;
|
||||
}
|
||||
|
||||
public <E extends Throwable> int safeRunInt(SafePointerIntFunction<E> function) throws SQLException, E {
|
||||
try {
|
||||
databaseLock.lock();
|
||||
this.ensureOpen();
|
||||
return function.run(database, databasePointer);
|
||||
} finally {
|
||||
databaseLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private void ensureOpen() throws SQLException {
|
||||
if (this.closed) {
|
||||
throw new SQLException("Pointer is closed");
|
||||
}
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface SafePointerIntFunction<E extends Throwable> {
|
||||
int run(AbstractDB database, long pointer) throws E;
|
||||
public long columnCount() throws SQLException {
|
||||
// TODO
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
package org.github.tursodatabase.jdbc4;
|
||||
|
||||
import org.github.tursodatabase.LimboConnection;
|
||||
import org.github.tursodatabase.core.LimboConnection;
|
||||
import org.github.tursodatabase.annotations.SkipNullableCheck;
|
||||
import org.github.tursodatabase.core.AbstractDB;
|
||||
import org.github.tursodatabase.core.CoreStatement;
|
||||
|
||||
import java.sql.*;
|
||||
|
@ -126,13 +125,12 @@ public class JDBC4Statement extends CoreStatement implements Statement {
|
|||
|
||||
return this.withConnectionTimeout(
|
||||
() -> {
|
||||
final AbstractDB database = connection.getDatabase();
|
||||
try {
|
||||
connectionLock.lock();
|
||||
database.prepare(this);
|
||||
connection.prepare(sql);
|
||||
boolean result = exec();
|
||||
updateGeneratedKeys();
|
||||
updateCount = database.changes();
|
||||
// TODO: updateCount = connection.changes();
|
||||
exhaustedResults = false;
|
||||
return result;
|
||||
} finally {
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
package org.github.tursodatabase.utils;
|
||||
|
||||
import org.github.tursodatabase.annotations.Nullable;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public class ByteArrayUtils {
|
||||
@Nullable
|
||||
public static String utf8ByteBufferToString(@Nullable byte[] buffer) {
|
||||
if (buffer == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new String(buffer, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static byte[] stringToUtf8ByteArray(@Nullable String str) {
|
||||
if (str == null) {
|
||||
return null;
|
||||
}
|
||||
return str.getBytes(StandardCharsets.UTF_8);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue