mirror of
https://github.com/aljazceru/turso.git
synced 2025-12-19 09:34:18 +01:00
Implement rust side connect and prepare function
This commit is contained in:
@@ -1,14 +1,19 @@
|
||||
use crate::cursor::Cursor;
|
||||
use jni::objects::JClass;
|
||||
use crate::errors::{
|
||||
LimboError, Result, LIMBO_ETC, LIMBO_FAILED_TO_PARSE_BYTE_ARRAY,
|
||||
LIMBO_FAILED_TO_PREPARE_STATEMENT,
|
||||
};
|
||||
use crate::utils::utf8_byte_arr_to_str;
|
||||
use jni::objects::{JByteArray, JClass, JObject};
|
||||
use jni::sys::jlong;
|
||||
use jni::JNIEnv;
|
||||
use std::rc::Rc;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::sync::Arc;
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Clone)]
|
||||
pub struct Connection {
|
||||
pub(crate) conn: Arc<Mutex<Rc<limbo_core::Connection>>>,
|
||||
pub(crate) io: Arc<limbo_core::PlatformIO>,
|
||||
pub(crate) conn: Rc<limbo_core::Connection>,
|
||||
pub(crate) io: Arc<dyn limbo_core::IO>,
|
||||
}
|
||||
|
||||
/// Returns a pointer to a `Cursor` object.
|
||||
@@ -26,20 +31,45 @@ pub struct Connection {
|
||||
///
|
||||
/// A `jlong` representing the pointer to the newly created `Cursor` object.
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_org_github_tursodatabase_limbo_Connection_cursor<'local>(
|
||||
_env: JNIEnv<'local>,
|
||||
_class: JClass<'local>,
|
||||
pub extern "system" fn Java_org_github_tursodatabase_limbo_LimboConnection_prepareUtf8<'local>(
|
||||
mut env: JNIEnv<'local>,
|
||||
obj: JObject<'local>,
|
||||
connection_ptr: jlong,
|
||||
sql_bytes: JByteArray<'local>,
|
||||
) -> jlong {
|
||||
let connection = to_connection(connection_ptr);
|
||||
let cursor = Cursor {
|
||||
array_size: 1,
|
||||
conn: connection.clone(),
|
||||
description: None,
|
||||
rowcount: -1,
|
||||
smt: None,
|
||||
let connection = match to_connection(connection_ptr) {
|
||||
Ok(conn) => conn,
|
||||
Err(e) => {
|
||||
set_err_msg_and_throw_exception(&mut env, obj, LIMBO_ETC, e.to_string());
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
Box::into_raw(Box::new(cursor)) as jlong
|
||||
|
||||
let sql = match utf8_byte_arr_to_str(&env, sql_bytes) {
|
||||
Ok(sql) => sql,
|
||||
Err(e) => {
|
||||
set_err_msg_and_throw_exception(
|
||||
&mut env,
|
||||
obj,
|
||||
LIMBO_FAILED_TO_PARSE_BYTE_ARRAY,
|
||||
e.to_string(),
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
match connection.conn.prepare(sql) {
|
||||
Ok(stmt) => Box::into_raw(Box::new(stmt)) as jlong,
|
||||
Err(e) => {
|
||||
set_err_msg_and_throw_exception(
|
||||
&mut env,
|
||||
obj,
|
||||
LIMBO_FAILED_TO_PREPARE_STATEMENT,
|
||||
e.to_string(),
|
||||
);
|
||||
0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Closes the connection and releases the associated resources.
|
||||
@@ -61,24 +91,34 @@ pub unsafe extern "system" fn Java_org_github_tursodatabase_limbo_Connection_clo
|
||||
let _boxed_connection = Box::from_raw(connection_ptr as *mut Connection);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_org_github_tursodatabase_limbo_Connection_commit<'local>(
|
||||
_env: &mut JNIEnv<'local>,
|
||||
_class: JClass<'local>,
|
||||
_connection_id: jlong,
|
||||
) {
|
||||
unimplemented!()
|
||||
fn to_connection(connection_ptr: jlong) -> Result<&'static mut Rc<Connection>> {
|
||||
if connection_ptr == 0 {
|
||||
Err(LimboError::InvalidConnectionPointer)
|
||||
} else {
|
||||
unsafe { Ok(&mut *(connection_ptr as *mut Rc<Connection>)) }
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_org_github_tursodatabase_limbo_Connection_rollback<'local>(
|
||||
_env: &mut JNIEnv<'local>,
|
||||
_class: JClass<'local>,
|
||||
_connection_id: jlong,
|
||||
fn set_err_msg_and_throw_exception<'local>(
|
||||
env: &mut JNIEnv<'local>,
|
||||
obj: JObject<'local>,
|
||||
err_code: i32,
|
||||
err_msg: String,
|
||||
) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn to_connection(connection_ptr: jlong) -> &'static mut Connection {
|
||||
unsafe { &mut *(connection_ptr as *mut Connection) }
|
||||
let error_message_bytes = env
|
||||
.byte_array_from_slice(err_msg.as_bytes())
|
||||
.expect("Failed to convert to byte array");
|
||||
match env.call_method(
|
||||
obj,
|
||||
"throwLimboException",
|
||||
"(I[B)V",
|
||||
&[err_code.into(), (&error_message_bytes).into()],
|
||||
) {
|
||||
Ok(_) => {
|
||||
// do nothing because above method will always return Err
|
||||
}
|
||||
Err(_e) => {
|
||||
// do nothing because our java app will handle Err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,240 +0,0 @@
|
||||
use crate::connection::Connection;
|
||||
use crate::errors::ErrorCode;
|
||||
use crate::utils::row_to_obj_array;
|
||||
use crate::{eprint_return, eprint_return_null};
|
||||
use jni::errors::JniError;
|
||||
use jni::objects::{JClass, JObject, JString};
|
||||
use jni::sys::jlong;
|
||||
use jni::JNIEnv;
|
||||
use limbo_core::IO;
|
||||
use std::fmt::{Debug, Formatter};
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Cursor {
|
||||
/// This read/write attribute specifies the number of rows to fetch at a time with `.fetchmany()`.
|
||||
/// It defaults to `1`, meaning it fetches a single row at a time.
|
||||
pub(crate) array_size: i64,
|
||||
|
||||
pub(crate) conn: Connection,
|
||||
|
||||
/// The `.description` attribute is a read-only sequence of 7-item, each describing a column in the result set:
|
||||
///
|
||||
/// - `name`: The column's name (always present).
|
||||
/// - `type_code`: The data type code (always present).
|
||||
/// - `display_size`: Column's display size (optional).
|
||||
/// - `internal_size`: Column's internal size (optional).
|
||||
/// - `precision`: Numeric precision (optional).
|
||||
/// - `scale`: Numeric scale (optional).
|
||||
/// - `null_ok`: Indicates if null values are allowed (optional).
|
||||
///
|
||||
/// The `name` and `type_code` fields are mandatory; others default to `None` if not applicable.
|
||||
///
|
||||
/// This attribute is `None` for operations that do not return rows or if no `.execute*()` method has been invoked.
|
||||
pub(crate) description: Option<Description>,
|
||||
|
||||
/// Read-only attribute that provides the number of modified rows for `INSERT`, `UPDATE`, `DELETE`,
|
||||
/// and `REPLACE` statements; it is `-1` for other statements, including CTE queries.
|
||||
/// It is only updated by the `execute()` and `executemany()` methods after the statement has run to completion.
|
||||
/// This means any resulting rows must be fetched for `rowcount` to be updated.
|
||||
pub(crate) rowcount: i64,
|
||||
|
||||
pub(crate) smt: Option<Arc<Mutex<limbo_core::Statement>>>,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub(crate) struct Description {
|
||||
_name: String,
|
||||
_type_code: String,
|
||||
_display_size: Option<String>,
|
||||
_internal_size: Option<String>,
|
||||
_precision: Option<String>,
|
||||
_scale: Option<String>,
|
||||
_null_ok: Option<String>,
|
||||
}
|
||||
|
||||
impl Debug for Cursor {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("Cursor")
|
||||
.field("array_size", &self.array_size)
|
||||
.field("description", &self.description)
|
||||
.field("rowcount", &self.rowcount)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
/// TODO: we should find a way to handle Error thrown by rust and how to handle those errors in java
|
||||
#[no_mangle]
|
||||
#[allow(improper_ctypes_definitions, clippy::arc_with_non_send_sync)]
|
||||
pub extern "system" fn Java_org_github_tursodatabase_limbo_Cursor_execute<'local>(
|
||||
mut env: JNIEnv<'local>,
|
||||
_class: JClass<'local>,
|
||||
cursor_ptr: jlong,
|
||||
sql: JString<'local>,
|
||||
) -> Result<(), JniError> {
|
||||
let sql: String = env
|
||||
.get_string(&sql)
|
||||
.expect("Could not extract query")
|
||||
.into();
|
||||
|
||||
let stmt_is_dml = stmt_is_dml(&sql);
|
||||
if stmt_is_dml {
|
||||
return eprint_return!(
|
||||
"DML statements (INSERT/UPDATE/DELETE) are not fully supported in this version",
|
||||
JniError::Other(ErrorCode::STATEMENT_IS_DML)
|
||||
);
|
||||
}
|
||||
|
||||
let cursor = to_cursor(cursor_ptr);
|
||||
let conn_lock = match cursor.conn.conn.lock() {
|
||||
Ok(lock) => lock,
|
||||
Err(_) => return eprint_return!("Failed to acquire connection lock", JniError::Other(-1)),
|
||||
};
|
||||
|
||||
match conn_lock.prepare(&sql) {
|
||||
Ok(statement) => {
|
||||
cursor.smt = Some(Arc::new(Mutex::new(statement)));
|
||||
Ok(())
|
||||
}
|
||||
Err(e) => {
|
||||
eprint_return!(
|
||||
&format!("Failed to prepare statement: {:?}", e),
|
||||
JniError::Other(-1)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_org_github_tursodatabase_limbo_Cursor_fetchOne<'local>(
|
||||
mut env: JNIEnv<'local>,
|
||||
_class: JClass<'local>,
|
||||
cursor_ptr: jlong,
|
||||
) -> JObject<'local> {
|
||||
let cursor = to_cursor(cursor_ptr);
|
||||
|
||||
if let Some(smt) = &cursor.smt {
|
||||
loop {
|
||||
let mut smt_lock = match smt.lock() {
|
||||
Ok(lock) => lock,
|
||||
Err(_) => {
|
||||
return eprint_return_null!(
|
||||
"Failed to acquire statement lock",
|
||||
JniError::Other(-1)
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
match smt_lock.step() {
|
||||
Ok(limbo_core::StepResult::Row(row)) => {
|
||||
return match row_to_obj_array(&mut env, &row) {
|
||||
Ok(r) => r,
|
||||
Err(e) => eprint_return_null!(&format!("{:?}", e), JniError::Other(-1)),
|
||||
}
|
||||
}
|
||||
Ok(limbo_core::StepResult::IO) => {
|
||||
if let Err(e) = cursor.conn.io.run_once() {
|
||||
return eprint_return_null!(
|
||||
&format!("IO Error: {:?}", e),
|
||||
JniError::Other(-1)
|
||||
);
|
||||
}
|
||||
}
|
||||
Ok(limbo_core::StepResult::Interrupt) => return JObject::null(),
|
||||
Ok(limbo_core::StepResult::Done) => return JObject::null(),
|
||||
Ok(limbo_core::StepResult::Busy) => {
|
||||
return eprint_return_null!("Busy error", JniError::Other(-1));
|
||||
}
|
||||
Err(e) => {
|
||||
return eprint_return_null!(
|
||||
format!("Step error: {:?}", e),
|
||||
JniError::Other(-1)
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
} else {
|
||||
eprint_return_null!("No statement prepared for execution", JniError::Other(-1))
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_org_github_tursodatabase_limbo_Cursor_fetchAll<'local>(
|
||||
mut env: JNIEnv<'local>,
|
||||
_class: JClass<'local>,
|
||||
cursor_ptr: jlong,
|
||||
) -> JObject<'local> {
|
||||
let cursor = to_cursor(cursor_ptr);
|
||||
|
||||
if let Some(smt) = &cursor.smt {
|
||||
let mut rows = Vec::new();
|
||||
loop {
|
||||
let mut smt_lock = match smt.lock() {
|
||||
Ok(lock) => lock,
|
||||
Err(_) => {
|
||||
return eprint_return_null!(
|
||||
"Failed to acquire statement lock",
|
||||
JniError::Other(-1)
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
match smt_lock.step() {
|
||||
Ok(limbo_core::StepResult::Row(row)) => match row_to_obj_array(&mut env, &row) {
|
||||
Ok(r) => rows.push(r),
|
||||
Err(e) => return eprint_return_null!(&format!("{:?}", e), JniError::Other(-1)),
|
||||
},
|
||||
Ok(limbo_core::StepResult::IO) => {
|
||||
if let Err(e) = cursor.conn.io.run_once() {
|
||||
return eprint_return_null!(
|
||||
&format!("IO Error: {:?}", e),
|
||||
JniError::Other(-1)
|
||||
);
|
||||
}
|
||||
}
|
||||
Ok(limbo_core::StepResult::Interrupt) => {
|
||||
return JObject::null();
|
||||
}
|
||||
Ok(limbo_core::StepResult::Done) => {
|
||||
break;
|
||||
}
|
||||
Ok(limbo_core::StepResult::Busy) => {
|
||||
return eprint_return_null!("Busy error", JniError::Other(-1));
|
||||
}
|
||||
Err(e) => {
|
||||
return eprint_return_null!(
|
||||
format!("Step error: {:?}", e),
|
||||
JniError::Other(-1)
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
let array_class = env
|
||||
.find_class("[Ljava/lang/Object;")
|
||||
.expect("Failed to find Object array class");
|
||||
let result_array = env
|
||||
.new_object_array(rows.len() as i32, array_class, JObject::null())
|
||||
.expect("Failed to create new object array");
|
||||
|
||||
for (i, row) in rows.into_iter().enumerate() {
|
||||
env.set_object_array_element(&result_array, i as i32, row)
|
||||
.expect("Failed to set object array element");
|
||||
}
|
||||
|
||||
result_array.into()
|
||||
} else {
|
||||
eprint_return_null!("No statement prepared for execution", JniError::Other(-1))
|
||||
}
|
||||
}
|
||||
|
||||
fn to_cursor(cursor_ptr: jlong) -> &'static mut Cursor {
|
||||
unsafe { &mut *(cursor_ptr as *mut Cursor) }
|
||||
}
|
||||
|
||||
fn stmt_is_dml(sql: &str) -> bool {
|
||||
let sql = sql.trim();
|
||||
let sql = sql.to_uppercase();
|
||||
sql.starts_with("INSERT") || sql.starts_with("UPDATE") || sql.starts_with("DELETE")
|
||||
}
|
||||
@@ -13,11 +13,11 @@ pub enum LimboError {
|
||||
InvalidConnectionPointer,
|
||||
|
||||
#[error("JNI Errors: `{0}`")]
|
||||
JNIErrors(Error)
|
||||
JNIErrors(Error),
|
||||
}
|
||||
|
||||
impl From<limbo_core::LimboError> for LimboError {
|
||||
fn from(value: limbo_core::LimboError) -> Self {
|
||||
fn from(_value: limbo_core::LimboError) -> Self {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
@@ -44,53 +44,70 @@ impl From<jni::errors::Error> for LimboError {
|
||||
|
||||
pub type Result<T> = std::result::Result<T, LimboError>;
|
||||
|
||||
/// This struct defines error codes that correspond to the constants defined in the
|
||||
/// Java package `org.github.tursodatabase.LimboErrorCode`.
|
||||
///
|
||||
/// These error codes are used to handle and represent specific error conditions
|
||||
/// that may occur within the Rust code and need to be communicated to the Java side.
|
||||
#[derive(Clone)]
|
||||
pub struct ErrorCode;
|
||||
|
||||
impl ErrorCode {
|
||||
// TODO: change CONNECTION_FAILURE_STATEMENT_IS_DML to appropriate error code number
|
||||
pub const STATEMENT_IS_DML: i32 = -1;
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub const SQLITE_OK: i32 = 0;
|
||||
#[allow(dead_code)]
|
||||
pub const SQLITE_ERROR: i32 = 1;
|
||||
#[allow(dead_code)]
|
||||
pub const SQLITE_INTERNAL: i32 = 2;
|
||||
#[allow(dead_code)]
|
||||
pub const SQLITE_PERM: i32 = 3;
|
||||
#[allow(dead_code)]
|
||||
pub const SQLITE_ABORT: i32 = 4;
|
||||
#[allow(dead_code)]
|
||||
pub const SQLITE_BUSY: i32 = 5;
|
||||
#[allow(dead_code)]
|
||||
pub const SQLITE_LOCKED: i32 = 6;
|
||||
#[allow(dead_code)]
|
||||
pub const SQLITE_NOMEM: i32 = 7;
|
||||
#[allow(dead_code)]
|
||||
pub const SQLITE_READONLY: i32 = 8;
|
||||
#[allow(dead_code)]
|
||||
pub const SQLITE_INTERRUPT: i32 = 9;
|
||||
#[allow(dead_code)]
|
||||
pub const SQLITE_IOERR: i32 = 10;
|
||||
#[allow(dead_code)]
|
||||
pub const SQLITE_CORRUPT: i32 = 11;
|
||||
#[allow(dead_code)]
|
||||
pub const SQLITE_NOTFOUND: i32 = 12;
|
||||
#[allow(dead_code)]
|
||||
pub const SQLITE_FULL: i32 = 13;
|
||||
#[allow(dead_code)]
|
||||
pub const SQLITE_CANTOPEN: i32 = 14;
|
||||
#[allow(dead_code)]
|
||||
pub const SQLITE_PROTOCOL: i32 = 15;
|
||||
#[allow(dead_code)]
|
||||
pub const SQLITE_EMPTY: i32 = 16;
|
||||
#[allow(dead_code)]
|
||||
pub const SQLITE_SCHEMA: i32 = 17;
|
||||
#[allow(dead_code)]
|
||||
pub const SQLITE_TOOBIG: i32 = 18;
|
||||
#[allow(dead_code)]
|
||||
pub const SQLITE_CONSTRAINT: i32 = 19;
|
||||
#[allow(dead_code)]
|
||||
pub const SQLITE_MISMATCH: i32 = 20;
|
||||
#[allow(dead_code)]
|
||||
pub const SQLITE_MISUSE: i32 = 21;
|
||||
#[allow(dead_code)]
|
||||
pub const SQLITE_NOLFS: i32 = 22;
|
||||
#[allow(dead_code)]
|
||||
pub const SQLITE_AUTH: i32 = 23;
|
||||
#[allow(dead_code)]
|
||||
pub const SQLITE_ROW: i32 = 100;
|
||||
#[allow(dead_code)]
|
||||
pub const SQLITE_DONE: i32 = 101;
|
||||
|
||||
// types returned by sqlite3_column_type()
|
||||
#[allow(dead_code)]
|
||||
pub const SQLITE_INTEGER: i32 = 1;
|
||||
#[allow(dead_code)]
|
||||
pub const SQLITE_FLOAT: i32 = 2;
|
||||
#[allow(dead_code)]
|
||||
pub const SQLITE_TEXT: i32 = 3;
|
||||
#[allow(dead_code)]
|
||||
pub const SQLITE_BLOB: i32 = 4;
|
||||
#[allow(dead_code)]
|
||||
pub const SQLITE_NULL: i32 = 5;
|
||||
|
||||
// Limbo custom error codes
|
||||
pub const LIMBO_DATABASE_ALREADY_CLOSED: i32 = 1000;
|
||||
pub const LIMBO_FAILED_TO_PARSE_BYTE_ARRAY: i32 = 1100;
|
||||
pub const LIMBO_FAILED_TO_PREPARE_STATEMENT: i32 = 1200;
|
||||
pub const LIMBO_ETC: i32 = 9999;
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
mod connection;
|
||||
mod cursor;
|
||||
mod errors;
|
||||
mod limbo_db;
|
||||
mod macros;
|
||||
mod utils;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use crate::connection::Connection;
|
||||
use crate::errors::{LimboError, Result};
|
||||
use jni::objects::{JByteArray, JObject};
|
||||
use jni::sys::{jint, jlong};
|
||||
@@ -12,7 +13,7 @@ const ERROR_CODE_ETC: i32 = 9999;
|
||||
pub extern "system" fn Java_org_github_tursodatabase_core_LimboDB_openUtf8<'local>(
|
||||
mut env: JNIEnv<'local>,
|
||||
obj: JObject<'local>,
|
||||
file_name_byte_arr: JByteArray<'local>,
|
||||
file_path_byte_arr: JByteArray<'local>,
|
||||
_open_flags: jint,
|
||||
) -> jlong {
|
||||
let io = match limbo_core::PlatformIO::new() {
|
||||
@@ -24,7 +25,7 @@ pub extern "system" fn Java_org_github_tursodatabase_core_LimboDB_openUtf8<'loca
|
||||
};
|
||||
|
||||
let path = match env
|
||||
.convert_byte_array(file_name_byte_arr)
|
||||
.convert_byte_array(file_path_byte_arr)
|
||||
.map_err(|e| e.to_string())
|
||||
{
|
||||
Ok(bytes) => match String::from_utf8(bytes) {
|
||||
@@ -52,9 +53,11 @@ pub extern "system" fn Java_org_github_tursodatabase_core_LimboDB_openUtf8<'loca
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
#[allow(clippy::arc_with_non_send_sync)]
|
||||
pub extern "system" fn Java_org_github_tursodatabase_core_LimboDB_connect0<'local>(
|
||||
mut env: JNIEnv<'local>,
|
||||
obj: JObject<'local>,
|
||||
file_path_byte_arr: JByteArray<'local>,
|
||||
db_pointer: jlong,
|
||||
) -> jlong {
|
||||
let db = match to_db(db_pointer) {
|
||||
@@ -65,7 +68,45 @@ pub extern "system" fn Java_org_github_tursodatabase_core_LimboDB_connect0<'loca
|
||||
}
|
||||
};
|
||||
|
||||
Box::into_raw(Box::new(db.connect())) as jlong
|
||||
let path = match env
|
||||
.convert_byte_array(file_path_byte_arr)
|
||||
.map_err(|e| e.to_string())
|
||||
{
|
||||
Ok(bytes) => match String::from_utf8(bytes) {
|
||||
Ok(s) => s,
|
||||
Err(e) => {
|
||||
set_err_msg_and_throw_exception(&mut env, obj, ERROR_CODE_ETC, e.to_string());
|
||||
return 0;
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
set_err_msg_and_throw_exception(&mut env, obj, ERROR_CODE_ETC, e.to_string());
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
let io: Arc<dyn limbo_core::IO> = match path.as_str() {
|
||||
":memory:" => match limbo_core::MemoryIO::new() {
|
||||
Ok(io) => Arc::new(io),
|
||||
Err(e) => {
|
||||
set_err_msg_and_throw_exception(&mut env, obj, ERROR_CODE_ETC, e.to_string());
|
||||
return 0;
|
||||
}
|
||||
},
|
||||
_ => match limbo_core::PlatformIO::new() {
|
||||
Ok(io) => Arc::new(io),
|
||||
Err(e) => {
|
||||
set_err_msg_and_throw_exception(&mut env, obj, ERROR_CODE_ETC, e.to_string());
|
||||
return 0;
|
||||
}
|
||||
},
|
||||
};
|
||||
let conn = Connection {
|
||||
conn: db.connect(),
|
||||
io,
|
||||
};
|
||||
|
||||
Box::into_raw(Box::new(conn)) as jlong
|
||||
}
|
||||
|
||||
fn to_db(db_pointer: jlong) -> Result<&'static mut Arc<Database>> {
|
||||
@@ -90,16 +131,6 @@ pub extern "system" fn Java_org_github_tursodatabase_core_LimboDB_throwJavaExcep
|
||||
);
|
||||
}
|
||||
|
||||
fn utf8_byte_arr_to_str(env: &JNIEnv, bytes: JByteArray) -> Result<String> {
|
||||
let bytes = env
|
||||
.convert_byte_array(bytes)
|
||||
.map_err(|e| LimboError::CustomError("Failed to retrieve bytes".to_string()))?;
|
||||
let str = String::from_utf8(bytes).map_err(|e| {
|
||||
LimboError::CustomError("Failed to convert utf8 byte array into string".to_string())
|
||||
})?;
|
||||
Ok(str)
|
||||
}
|
||||
|
||||
/// Sets the error message and throws a Java exception.
|
||||
///
|
||||
/// This function converts the provided error message to a byte array and calls the
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
// bindings/java/src/macros.rs
|
||||
#[macro_export]
|
||||
macro_rules! eprint_return {
|
||||
($log:expr, $error:expr) => {{
|
||||
eprintln!("{}", $log);
|
||||
Err($error)
|
||||
}};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! eprint_return_null {
|
||||
($log:expr, $error:expr) => {{
|
||||
eprintln!("{}", $log);
|
||||
JObject::null()
|
||||
}};
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
use crate::errors::LimboError;
|
||||
use jni::objects::{JObject, JValue};
|
||||
use jni::objects::{JByteArray, JObject, JValue};
|
||||
use jni::JNIEnv;
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn row_to_obj_array<'local>(
|
||||
env: &mut JNIEnv<'local>,
|
||||
row: &limbo_core::Row,
|
||||
@@ -28,3 +29,16 @@ pub(crate) fn row_to_obj_array<'local>(
|
||||
|
||||
Ok(obj_array.into())
|
||||
}
|
||||
|
||||
pub(crate) fn utf8_byte_arr_to_str(
|
||||
env: &JNIEnv,
|
||||
bytes: JByteArray,
|
||||
) -> crate::errors::Result<String> {
|
||||
let bytes = env
|
||||
.convert_byte_array(bytes)
|
||||
.map_err(|_| LimboError::CustomError("Failed to retrieve bytes".to_string()))?;
|
||||
let str = String::from_utf8(bytes).map_err(|_| {
|
||||
LimboError::CustomError("Failed to convert utf8 byte array into string".to_string())
|
||||
})?;
|
||||
Ok(str)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user