From 7ee52fca4dd37dbc7a678a895d4c484c0a820338 Mon Sep 17 00:00:00 2001 From: PThorpe92 Date: Fri, 31 Jan 2025 15:03:14 -0500 Subject: [PATCH] bindings/go: update readme with example, change module name --- bindings/go/README.md | 58 +++++++++++++++++++++++++-------- bindings/go/go.mod | 2 +- bindings/go/limbo_test.go | 2 +- bindings/go/rs_src/lib.rs | 11 +++---- bindings/go/rs_src/rows.rs | 3 ++ bindings/go/rs_src/statement.rs | 10 ++---- 6 files changed, 55 insertions(+), 31 deletions(-) diff --git a/bindings/go/README.md b/bindings/go/README.md index 3dbffdb45..ab50140bb 100644 --- a/bindings/go/README.md +++ b/bindings/go/README.md @@ -1,41 +1,71 @@ -## Limbo driver for Go's `database/sql` library +# Limbo driver for Go's `database/sql` library -**NOTE:** this is currently __heavily__ W.I.P and is not yet in a usable state. This is merged in only for the purposes of incremental progress and not because the existing code here proper. Expect many and frequent changes. +**NOTE:** this is currently __heavily__ W.I.P and is not yet in a usable state. -This uses the [purego](https://github.com/ebitengine/purego) library to call C (in this case Rust with C ABI) functions from Go without the use of `CGO`. +This driver uses the awesome [purego](https://github.com/ebitengine/purego) library to call C (in this case Rust with C ABI) functions from Go without the use of `CGO`. +## To use: (_UNSTABLE_ testing or development purposes only) - -### To test - - -## Linux | MacOS +### Linux | MacOS _All commands listed are relative to the bindings/go directory in the limbo repository_ ``` cargo build --package limbo-go - # Your LD_LIBRARY_PATH environment variable must include limbo's `target/debug` directory -LD_LIBRARY_PATH="../../target/debug:$LD_LIBRARY_PATH" go test +export LD_LIBRARY_PATH="/path/to/limbo/target/debug:$LD_LIBRARY_PATH" ``` - ## Windows ``` cargo build --package limbo-go -# Copy the lib_limbo_go.dll into the current working directory (bindings/go) -# Alternatively, you could add the .dll to a location in your PATH +# You must add limbo's `target/debug` directory to your PATH +# or you could built + copy the .dll to a location in your PATH +# or just the CWD of your go module -cp ../../target/debug/lib_limbo_go.dll . +cp path\to\limbo\target\debug\lib_limbo_go.dll . go test ``` +**Temporarily** you may have to clone the limbo repository and run: + +`go mod edit -replace github.com/tursodatabase/limbo=/path/to/limbo/bindings/go` + +```go +import ( + "fmt" + "database/sql" + _"github.com/tursodatabase/limbo" +) + +func main() { + conn, err := sql.Open("sqlite3", ":memory:") + if err != nil { + fmt.Printf("Error: %v\n", err) + os.Exit(1) + } + sql := "CREATE table go_limbo (foo INTEGER, bar TEXT)" + _ = conn.Exec(sql) + + sql = "INSERT INTO go_limbo (foo, bar) values (?, ?)" + stmt, _ := conn.Prepare(sql) + defer stmt.Close() + _ = stmt.Exec(42, "limbo") + rows, _ := conn.Query("SELECT * from go_limbo") + defer rows.Close() + for rows.Next() { + var a int + var b string + _ = rows.Scan(&a, &b) + fmt.Printf("%d, %s", a, b) + } +} +``` diff --git a/bindings/go/go.mod b/bindings/go/go.mod index e49ba4c96..a9145591b 100644 --- a/bindings/go/go.mod +++ b/bindings/go/go.mod @@ -1,4 +1,4 @@ -module limbo +module github.com/tursodatabase/limbo go 1.23.4 diff --git a/bindings/go/limbo_test.go b/bindings/go/limbo_test.go index a688cb34e..45d1dc786 100644 --- a/bindings/go/limbo_test.go +++ b/bindings/go/limbo_test.go @@ -6,7 +6,7 @@ import ( "log" "testing" - _ "limbo" + _ "github.com/tursodatabase/limbo" ) var conn *sql.DB diff --git a/bindings/go/rs_src/lib.rs b/bindings/go/rs_src/lib.rs index 70dbce89a..fd0172cdf 100644 --- a/bindings/go/rs_src/lib.rs +++ b/bindings/go/rs_src/lib.rs @@ -7,7 +7,7 @@ use std::{ ffi::{c_char, c_void}, rc::Rc, str::FromStr, - sync::{Arc, RwLock}, + sync::Arc, }; /// # Safety @@ -40,21 +40,18 @@ pub unsafe extern "C" fn db_open(path: *const c_char) -> *mut c_void { #[allow(dead_code)] struct LimboConn { - conn: RwLock>, + conn: Rc, io: Arc, } impl<'conn> LimboConn { fn new(conn: Rc, io: Arc) -> Self { - LimboConn { - conn: conn.into(), - io, - } + LimboConn { conn, io } } #[allow(clippy::wrong_self_convention)] fn to_ptr(self) -> *mut c_void { - Arc::into_raw(Arc::new(self)) as *mut c_void + Box::into_raw(Box::new(self)) as *mut c_void } fn from_ptr(ptr: *mut c_void) -> &'conn mut LimboConn { diff --git a/bindings/go/rs_src/rows.rs b/bindings/go/rs_src/rows.rs index c8ec7642a..e089c9f4c 100644 --- a/bindings/go/rs_src/rows.rs +++ b/bindings/go/rs_src/rows.rs @@ -90,6 +90,9 @@ pub extern "C" fn rows_get_columns(rows_ptr: *mut c_void) -> i32 { rows.stmt.columns().len() as i32 } +/// Returns a pointer to a string with the name of the column at the given index. +/// The caller is responsible for freeing the memory, it should be copied on the Go side +/// immediately and 'free_string' called #[no_mangle] pub extern "C" fn rows_get_column_name(rows_ptr: *mut c_void, idx: i32) -> *const c_char { if rows_ptr.is_null() { diff --git a/bindings/go/rs_src/statement.rs b/bindings/go/rs_src/statement.rs index 8ad015ded..7d5c6c92a 100644 --- a/bindings/go/rs_src/statement.rs +++ b/bindings/go/rs_src/statement.rs @@ -13,10 +13,7 @@ pub extern "C" fn db_prepare(ctx: *mut c_void, query: *const c_char) -> *mut c_v let query_str = unsafe { std::ffi::CStr::from_ptr(query) }.to_str().unwrap(); let db = LimboConn::from_ptr(ctx); - let Ok(conn) = db.conn.read() else { - return std::ptr::null_mut(); - }; - let stmt = conn.prepare(query_str); + let stmt = db.conn.prepare(query_str); match stmt { Ok(stmt) => LimboStatement::new(Some(stmt), LimboConn::from_ptr(ctx)).to_ptr(), Err(_) => std::ptr::null_mut(), @@ -55,10 +52,7 @@ pub extern "C" fn stmt_execute( return ResultCode::Error; } Ok(StepResult::Done) => { - let Ok(conn) = stmt.conn.conn.read() else { - return ResultCode::Done; - }; - let total_changes = conn.total_changes(); + let total_changes = stmt.conn.conn.total_changes(); if !changes.is_null() { unsafe { *changes = total_changes;