Rename Go driver to turso to not conflict with sqlite3, rename limbo->turso

This commit is contained in:
PThorpe92
2025-08-26 14:13:42 -04:00
parent 77476de547
commit 4cf111e3c2
16 changed files with 200 additions and 201 deletions

14
Cargo.lock generated
View File

@@ -2066,13 +2066,6 @@ dependencies = [
"vcpkg",
]
[[package]]
name = "limbo-go"
version = "0.1.4"
dependencies = [
"turso_core",
]
[[package]]
name = "limbo_completion"
version = "0.1.4"
@@ -3984,6 +3977,13 @@ dependencies = [
"turso_core",
]
[[package]]
name = "turso-go"
version = "0.1.4"
dependencies = [
"turso_core",
]
[[package]]
name = "turso-java"
version = "0.1.4"

View File

@@ -1,5 +1,5 @@
[package]
name = "limbo-go"
name = "turso-go"
version.workspace = true
authors.workspace = true
edition.workspace = true
@@ -8,7 +8,7 @@ repository.workspace = true
publish = false
[lib]
name = "_limbo_go"
name = "_turso_go"
crate-type = ["cdylib"]
path = "rs_src/lib.rs"

View File

@@ -1,4 +1,4 @@
# Limbo driver for Go's `database/sql` library
# Turso driver for Go's `database/sql` library
**NOTE:** this is currently __heavily__ W.I.P and is not yet in a usable state.
@@ -17,7 +17,7 @@ To build with embedded library support, follow these steps:
git clone https://github.com/tursodatabase/turso
# Navigate to the Go bindings directory
cd limbo/bindings/go
cd turso/bindings/go
# Build the library (defaults to release build)
./build_lib.sh
@@ -52,34 +52,34 @@ Build the driver with the embedded library as described above, then simply impor
#### Linux | MacOS
_All commands listed are relative to the bindings/go directory in the limbo repository_
_All commands listed are relative to the bindings/go directory in the turso repository_
```
cargo build --package limbo-go
cargo build --package turso-go
# Your LD_LIBRARY_PATH environment variable must include limbo's `target/debug` directory
# Your LD_LIBRARY_PATH environment variable must include turso's `target/debug` directory
export LD_LIBRARY_PATH="/path/to/limbo/target/debug:$LD_LIBRARY_PATH"
export LD_LIBRARY_PATH="/path/to/turso/target/debug:$LD_LIBRARY_PATH"
```
#### Windows
```
cargo build --package limbo-go
cargo build --package turso-go
# You must add limbo's `target/debug` directory to your PATH
# You must add turso'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 path\to\limbo\target\debug\lib_limbo_go.dll .
cp path\to\turso\target\debug\lib_turso_go.dll .
go test
```
**Temporarily** you may have to clone the limbo repository and run:
**Temporarily** you may have to clone the turso repository and run:
`go mod edit -replace github.com/tursodatabase/turso=/path/to/limbo/bindings/go`
`go mod edit -replace github.com/tursodatabase/turso=/path/to/turso/bindings/go`
```go
import (
@@ -89,19 +89,19 @@ import (
)
func main() {
conn, err := sql.Open("sqlite3", ":memory:")
conn, err := sql.Open("turso", ":memory:")
if err != nil {
fmt.Printf("Error: %v\n", err)
os.Exit(1)
}
sql := "CREATE table go_limbo (foo INTEGER, bar TEXT)"
sql := "CREATE table go_turso (foo INTEGER, bar TEXT)"
_ = conn.Exec(sql)
sql = "INSERT INTO go_limbo (foo, bar) values (?, ?)"
sql = "INSERT INTO go_turso (foo, bar) values (?, ?)"
stmt, _ := conn.Prepare(sql)
defer stmt.Close()
_ = stmt.Exec(42, "limbo")
rows, _ := conn.Query("SELECT * from go_limbo")
_ = stmt.Exec(42, "turso")
rows, _ := conn.Query("SELECT * from go_turso")
defer rows.Close()
for rows.Next() {
var a int

View File

@@ -6,12 +6,12 @@ set -e
# Accept build type as parameter, default to release
BUILD_TYPE=${1:-release}
echo "Building Limbo Go library for current platform (build type: $BUILD_TYPE)..."
echo "Building turso Go library for current platform (build type: $BUILD_TYPE)..."
# Determine platform-specific details
case "$(uname -s)" in
Darwin*)
OUTPUT_NAME="lib_limbo_go.dylib"
OUTPUT_NAME="lib_turso_go.dylib"
# Map x86_64 to amd64 for Go compatibility
ARCH=$(uname -m)
if [ "$ARCH" == "x86_64" ]; then
@@ -20,7 +20,7 @@ case "$(uname -s)" in
PLATFORM="darwin_${ARCH}"
;;
Linux*)
OUTPUT_NAME="lib_limbo_go.so"
OUTPUT_NAME="lib_turso_go.so"
# Map x86_64 to amd64 for Go compatibility
ARCH=$(uname -m)
if [ "$ARCH" == "x86_64" ]; then
@@ -29,7 +29,7 @@ case "$(uname -s)" in
PLATFORM="linux_${ARCH}"
;;
MINGW*|MSYS*|CYGWIN*)
OUTPUT_NAME="lib_limbo_go.dll"
OUTPUT_NAME="lib_turso_go.dll"
if [ "$(uname -m)" == "x86_64" ]; then
PLATFORM="windows_amd64"
else
@@ -60,11 +60,11 @@ else
fi
# Build the library
echo "Running cargo build ${CARGO_ARGS} --package limbo-go"
cargo build ${CARGO_ARGS} --package limbo-go
echo "Running cargo build ${CARGO_ARGS} --package turso-go"
cargo build ${CARGO_ARGS} --package turso-go
# Copy to the appropriate directory
echo "Copying $OUTPUT_NAME to $OUTPUT_DIR/"
cp "../../target/${TARGET_DIR}/$OUTPUT_NAME" "$OUTPUT_DIR/"
echo "Library built successfully for $PLATFORM ($BUILD_TYPE build)"
echo "Library built successfully for $PLATFORM ($BUILD_TYPE build)"

View File

@@ -1,4 +1,4 @@
package limbo
package turso
import (
"context"
@@ -16,16 +16,16 @@ func init() {
if err != nil {
panic(err)
}
sql.Register(driverName, &limboDriver{})
sql.Register(driverName, &tursoDriver{})
}
type limboDriver struct {
type tursoDriver struct {
sync.Mutex
}
var (
libOnce sync.Once
limboLib uintptr
tursoLib uintptr
loadErr error
dbOpen func(string) uintptr
dbClose func(uintptr) uintptr
@@ -49,32 +49,32 @@ var (
// Register all the symbols on library load
func ensureLibLoaded() error {
libOnce.Do(func() {
limboLib, loadErr = loadLibrary()
tursoLib, loadErr = loadLibrary()
if loadErr != nil {
return
}
purego.RegisterLibFunc(&dbOpen, limboLib, FfiDbOpen)
purego.RegisterLibFunc(&dbClose, limboLib, FfiDbClose)
purego.RegisterLibFunc(&connPrepare, limboLib, FfiDbPrepare)
purego.RegisterLibFunc(&connGetError, limboLib, FfiDbGetError)
purego.RegisterLibFunc(&freeBlobFunc, limboLib, FfiFreeBlob)
purego.RegisterLibFunc(&freeStringFunc, limboLib, FfiFreeCString)
purego.RegisterLibFunc(&rowsGetColumns, limboLib, FfiRowsGetColumns)
purego.RegisterLibFunc(&rowsGetColumnName, limboLib, FfiRowsGetColumnName)
purego.RegisterLibFunc(&rowsGetValue, limboLib, FfiRowsGetValue)
purego.RegisterLibFunc(&closeRows, limboLib, FfiRowsClose)
purego.RegisterLibFunc(&rowsNext, limboLib, FfiRowsNext)
purego.RegisterLibFunc(&rowsGetError, limboLib, FfiRowsGetError)
purego.RegisterLibFunc(&stmtQuery, limboLib, FfiStmtQuery)
purego.RegisterLibFunc(&stmtExec, limboLib, FfiStmtExec)
purego.RegisterLibFunc(&stmtParamCount, limboLib, FfiStmtParameterCount)
purego.RegisterLibFunc(&stmtGetError, limboLib, FfiStmtGetError)
purego.RegisterLibFunc(&stmtClose, limboLib, FfiStmtClose)
purego.RegisterLibFunc(&dbOpen, tursoLib, FfiDbOpen)
purego.RegisterLibFunc(&dbClose, tursoLib, FfiDbClose)
purego.RegisterLibFunc(&connPrepare, tursoLib, FfiDbPrepare)
purego.RegisterLibFunc(&connGetError, tursoLib, FfiDbGetError)
purego.RegisterLibFunc(&freeBlobFunc, tursoLib, FfiFreeBlob)
purego.RegisterLibFunc(&freeStringFunc, tursoLib, FfiFreeCString)
purego.RegisterLibFunc(&rowsGetColumns, tursoLib, FfiRowsGetColumns)
purego.RegisterLibFunc(&rowsGetColumnName, tursoLib, FfiRowsGetColumnName)
purego.RegisterLibFunc(&rowsGetValue, tursoLib, FfiRowsGetValue)
purego.RegisterLibFunc(&closeRows, tursoLib, FfiRowsClose)
purego.RegisterLibFunc(&rowsNext, tursoLib, FfiRowsNext)
purego.RegisterLibFunc(&rowsGetError, tursoLib, FfiRowsGetError)
purego.RegisterLibFunc(&stmtQuery, tursoLib, FfiStmtQuery)
purego.RegisterLibFunc(&stmtExec, tursoLib, FfiStmtExec)
purego.RegisterLibFunc(&stmtParamCount, tursoLib, FfiStmtParameterCount)
purego.RegisterLibFunc(&stmtGetError, tursoLib, FfiStmtGetError)
purego.RegisterLibFunc(&stmtClose, tursoLib, FfiStmtClose)
})
return loadErr
}
func (d *limboDriver) Open(name string) (driver.Conn, error) {
func (d *tursoDriver) Open(name string) (driver.Conn, error) {
d.Lock()
conn, err := openConn(name)
d.Unlock()
@@ -84,23 +84,23 @@ func (d *limboDriver) Open(name string) (driver.Conn, error) {
return conn, nil
}
type limboConn struct {
type tursoConn struct {
sync.Mutex
ctx uintptr
}
func openConn(dsn string) (*limboConn, error) {
func openConn(dsn string) (*tursoConn, error) {
ctx := dbOpen(dsn)
if ctx == 0 {
return nil, fmt.Errorf("failed to open database for dsn=%q", dsn)
}
return &limboConn{
return &tursoConn{
sync.Mutex{},
ctx,
}, loadErr
}
func (c *limboConn) Close() error {
func (c *tursoConn) Close() error {
if c.ctx == 0 {
return nil
}
@@ -111,7 +111,7 @@ func (c *limboConn) Close() error {
return nil
}
func (c *limboConn) getError() error {
func (c *tursoConn) getError() error {
if c.ctx == 0 {
return errors.New("connection closed")
}
@@ -124,7 +124,7 @@ func (c *limboConn) getError() error {
return errors.New(cpy)
}
func (c *limboConn) Prepare(query string) (driver.Stmt, error) {
func (c *tursoConn) Prepare(query string) (driver.Stmt, error) {
if c.ctx == 0 {
return nil, errors.New("connection closed")
}
@@ -137,13 +137,13 @@ func (c *limboConn) Prepare(query string) (driver.Stmt, error) {
return newStmt(stmtPtr, query), nil
}
// limboTx implements driver.Tx
type limboTx struct {
conn *limboConn
// tursoTx implements driver.Tx
type tursoTx struct {
conn *tursoConn
}
// Begin starts a new transaction with default isolation level
func (c *limboConn) Begin() (driver.Tx, error) {
func (c *tursoConn) Begin() (driver.Tx, error) {
c.Lock()
defer c.Unlock()
@@ -165,12 +165,12 @@ func (c *limboConn) Begin() (driver.Tx, error) {
return nil, err
}
return &limboTx{conn: c}, nil
return &tursoTx{conn: c}, nil
}
// BeginTx starts a transaction with the specified options.
// Currently only supports default isolation level and non-read-only transactions.
func (c *limboConn) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error) {
func (c *tursoConn) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error) {
// Skip handling non-default isolation levels and read-only mode
// for now, letting database/sql package handle these cases
if opts.Isolation != driver.IsolationLevel(sql.LevelDefault) || opts.ReadOnly {
@@ -187,7 +187,7 @@ func (c *limboConn) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.
}
// Commit commits the transaction
func (tx *limboTx) Commit() error {
func (tx *tursoTx) Commit() error {
tx.conn.Lock()
defer tx.conn.Unlock()
@@ -208,8 +208,7 @@ func (tx *limboTx) Commit() error {
}
// Rollback aborts the transaction.
// Note: This operation is not currently fully supported by Limbo and will return an error.
func (tx *limboTx) Rollback() error {
func (tx *tursoTx) Rollback() error {
tx.conn.Lock()
defer tx.conn.Unlock()

View File

@@ -1,4 +1,4 @@
// Go bindings for the Limbo database.
// Go bindings for the turso database.
//
// This file implements library embedding and extraction at runtime, a pattern
// also used in several other Go projects that need to distribute native binaries:
@@ -21,7 +21,7 @@
// The embedded library is extracted to a user-specific temporary directory and
// loaded dynamically. If extraction fails, the code falls back to the traditional
// method of searching system paths.
package limbo
package turso
import (
"embed"
@@ -52,11 +52,11 @@ func extractEmbeddedLibrary() (string, error) {
switch runtime.GOOS {
case "darwin":
libName = "lib_limbo_go.dylib"
libName = "lib_turso_go.dylib"
case "linux":
libName = "lib_limbo_go.so"
libName = "lib_turso_go.so"
case "windows":
libName = "lib_limbo_go.dll"
libName = "lib_turso_go.dll"
default:
extractErr = fmt.Errorf("unsupported operating system: %s", runtime.GOOS)
return
@@ -80,7 +80,7 @@ func extractEmbeddedLibrary() (string, error) {
platformDir = fmt.Sprintf("%s_%s", runtime.GOOS, archSuffix)
// Create a unique temporary directory for the current user
tempDir := filepath.Join(os.TempDir(), fmt.Sprintf("limbo-go-%d", os.Getuid()))
tempDir := filepath.Join(os.TempDir(), fmt.Sprintf("turso-go-%d", os.Getuid()))
if err := os.MkdirAll(tempDir, 0755); err != nil {
extractErr = fmt.Errorf("failed to create temp directory: %w", err)
return

View File

@@ -1,4 +1,4 @@
package limbo
package turso
import (
"database/sql/driver"
@@ -8,7 +8,7 @@ import (
"sync"
)
type limboRows struct {
type tursoRows struct {
mu sync.Mutex
ctx uintptr
columns []string
@@ -16,8 +16,8 @@ type limboRows struct {
closed bool
}
func newRows(ctx uintptr) *limboRows {
return &limboRows{
func newRows(ctx uintptr) *tursoRows {
return &tursoRows{
mu: sync.Mutex{},
ctx: ctx,
columns: nil,
@@ -26,14 +26,14 @@ func newRows(ctx uintptr) *limboRows {
}
}
func (r *limboRows) isClosed() bool {
func (r *tursoRows) isClosed() bool {
if r.ctx == 0 || r.closed {
return true
}
return false
}
func (r *limboRows) Columns() []string {
func (r *tursoRows) Columns() []string {
if r.isClosed() {
return nil
}
@@ -54,7 +54,7 @@ func (r *limboRows) Columns() []string {
return r.columns
}
func (r *limboRows) Close() error {
func (r *tursoRows) Close() error {
r.err = errors.New(RowsClosedErr)
if r.isClosed() {
return r.err
@@ -67,7 +67,7 @@ func (r *limboRows) Close() error {
return nil
}
func (r *limboRows) Err() error {
func (r *tursoRows) Err() error {
if r.err == nil {
r.mu.Lock()
defer r.mu.Unlock()
@@ -76,7 +76,7 @@ func (r *limboRows) Err() error {
return r.err
}
func (r *limboRows) Next(dest []driver.Value) error {
func (r *tursoRows) Next(dest []driver.Value) error {
r.mu.Lock()
defer r.mu.Unlock()
if r.isClosed() {
@@ -106,7 +106,7 @@ func (r *limboRows) Next(dest []driver.Value) error {
}
// mutex will already be locked. this is always called after FFI
func (r *limboRows) getError() error {
func (r *tursoRows) getError() error {
if r.isClosed() {
return r.err
}

View File

@@ -23,19 +23,19 @@ pub unsafe extern "C" fn db_open(path: *const c_char) -> *mut c_void {
let Ok((io, conn)) = Connection::from_uri(path, true, false, false) else {
panic!("Failed to open connection with path: {path}");
};
LimboConn::new(conn, io).to_ptr()
TursoConn::new(conn, io).to_ptr()
}
#[allow(dead_code)]
struct LimboConn {
struct TursoConn {
conn: Arc<Connection>,
io: Arc<dyn turso_core::IO>,
err: Option<LimboError>,
}
impl LimboConn {
impl TursoConn {
fn new(conn: Arc<Connection>, io: Arc<dyn turso_core::IO>) -> Self {
LimboConn {
TursoConn {
conn,
io,
err: None,
@@ -47,11 +47,11 @@ impl LimboConn {
Box::into_raw(Box::new(self)) as *mut c_void
}
fn from_ptr(ptr: *mut c_void) -> &'static mut LimboConn {
fn from_ptr(ptr: *mut c_void) -> &'static mut TursoConn {
if ptr.is_null() {
panic!("Null pointer");
}
unsafe { &mut *(ptr as *mut LimboConn) }
unsafe { &mut *(ptr as *mut TursoConn) }
}
fn get_error(&mut self) -> *const c_char {
@@ -73,7 +73,7 @@ pub extern "C" fn db_get_error(ctx: *mut c_void) -> *const c_char {
if ctx.is_null() {
return std::ptr::null();
}
let conn = LimboConn::from_ptr(ctx);
let conn = TursoConn::from_ptr(ctx);
conn.get_error()
}
@@ -83,6 +83,6 @@ pub extern "C" fn db_get_error(ctx: *mut c_void) -> *const c_char {
#[no_mangle]
pub unsafe extern "C" fn db_close(db: *mut c_void) {
if !db.is_null() {
let _ = unsafe { Box::from_raw(db as *mut LimboConn) };
let _ = unsafe { Box::from_raw(db as *mut TursoConn) };
}
}

View File

@@ -1,19 +1,19 @@
use crate::{
types::{LimboValue, ResultCode},
LimboConn,
types::{ResultCode, TursoValue},
TursoConn,
};
use std::ffi::{c_char, c_void};
use turso_core::{LimboError, Statement, StepResult, Value};
pub struct LimboRows<'conn> {
pub struct TursoRows<'conn> {
stmt: Box<Statement>,
_conn: &'conn mut LimboConn,
_conn: &'conn mut TursoConn,
err: Option<LimboError>,
}
impl<'conn> LimboRows<'conn> {
pub fn new(stmt: Statement, conn: &'conn mut LimboConn) -> Self {
LimboRows {
impl<'conn> TursoRows<'conn> {
pub fn new(stmt: Statement, conn: &'conn mut TursoConn) -> Self {
TursoRows {
stmt: Box::new(stmt),
_conn: conn,
err: None,
@@ -25,11 +25,11 @@ impl<'conn> LimboRows<'conn> {
Box::into_raw(Box::new(self)) as *mut c_void
}
pub fn from_ptr(ptr: *mut c_void) -> &'conn mut LimboRows<'conn> {
pub fn from_ptr(ptr: *mut c_void) -> &'conn mut TursoRows<'conn> {
if ptr.is_null() {
panic!("Null pointer");
}
unsafe { &mut *(ptr as *mut LimboRows) }
unsafe { &mut *(ptr as *mut TursoRows) }
}
fn get_error(&mut self) -> *const c_char {
@@ -49,7 +49,7 @@ pub extern "C" fn rows_next(ctx: *mut c_void) -> ResultCode {
if ctx.is_null() {
return ResultCode::Error;
}
let ctx = LimboRows::from_ptr(ctx);
let ctx = TursoRows::from_ptr(ctx);
match ctx.stmt.step() {
Ok(StepResult::Row) => ResultCode::Row,
@@ -76,11 +76,11 @@ pub extern "C" fn rows_get_value(ctx: *mut c_void, col_idx: usize) -> *const c_v
if ctx.is_null() {
return std::ptr::null();
}
let ctx = LimboRows::from_ptr(ctx);
let ctx = TursoRows::from_ptr(ctx);
if let Some(row) = ctx.stmt.row() {
if let Ok(value) = row.get::<&Value>(col_idx) {
return LimboValue::from_db_value(value).to_ptr();
return TursoValue::from_db_value(value).to_ptr();
}
}
std::ptr::null()
@@ -101,7 +101,7 @@ pub extern "C" fn rows_get_columns(rows_ptr: *mut c_void) -> i32 {
if rows_ptr.is_null() {
return -1;
}
let rows = LimboRows::from_ptr(rows_ptr);
let rows = TursoRows::from_ptr(rows_ptr);
rows.stmt.num_columns() as i32
}
@@ -113,7 +113,7 @@ pub extern "C" fn rows_get_column_name(rows_ptr: *mut c_void, idx: i32) -> *cons
if rows_ptr.is_null() {
return std::ptr::null_mut();
}
let rows = LimboRows::from_ptr(rows_ptr);
let rows = TursoRows::from_ptr(rows_ptr);
if idx < 0 || idx as usize >= rows.stmt.num_columns() {
return std::ptr::null_mut();
}
@@ -127,18 +127,18 @@ pub extern "C" fn rows_get_error(ctx: *mut c_void) -> *const c_char {
if ctx.is_null() {
return std::ptr::null();
}
let ctx = LimboRows::from_ptr(ctx);
let ctx = TursoRows::from_ptr(ctx);
ctx.get_error()
}
#[no_mangle]
pub extern "C" fn rows_close(ctx: *mut c_void) {
if !ctx.is_null() {
let rows = LimboRows::from_ptr(ctx);
let rows = TursoRows::from_ptr(ctx);
rows.stmt.reset();
rows.err = None;
}
unsafe {
let _ = Box::from_raw(ctx.cast::<LimboRows>());
let _ = Box::from_raw(ctx.cast::<TursoRows>());
}
}

View File

@@ -1,6 +1,6 @@
use crate::rows::LimboRows;
use crate::types::{AllocPool, LimboValue, ResultCode};
use crate::LimboConn;
use crate::rows::TursoRows;
use crate::types::{AllocPool, ResultCode, TursoValue};
use crate::TursoConn;
use std::ffi::{c_char, c_void};
use std::num::NonZero;
use turso_core::{LimboError, Statement, StepResult};
@@ -12,10 +12,10 @@ 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 db = TursoConn::from_ptr(ctx);
let stmt = db.conn.prepare(query_str);
match stmt {
Ok(stmt) => LimboStatement::new(Some(stmt), db).to_ptr(),
Ok(stmt) => TursoStatement::new(Some(stmt), db).to_ptr(),
Err(err) => {
db.err = Some(err);
std::ptr::null_mut()
@@ -26,14 +26,14 @@ pub extern "C" fn db_prepare(ctx: *mut c_void, query: *const c_char) -> *mut c_v
#[no_mangle]
pub extern "C" fn stmt_execute(
ctx: *mut c_void,
args_ptr: *mut LimboValue,
args_ptr: *mut TursoValue,
arg_count: usize,
changes: *mut i64,
) -> ResultCode {
if ctx.is_null() {
return ResultCode::Error;
}
let stmt = LimboStatement::from_ptr(ctx);
let stmt = TursoStatement::from_ptr(ctx);
let args = if !args_ptr.is_null() && arg_count > 0 {
unsafe { std::slice::from_raw_parts(args_ptr, arg_count) }
@@ -88,7 +88,7 @@ pub extern "C" fn stmt_parameter_count(ctx: *mut c_void) -> i32 {
if ctx.is_null() {
return -1;
}
let stmt = LimboStatement::from_ptr(ctx);
let stmt = TursoStatement::from_ptr(ctx);
let Some(statement) = stmt.statement.as_ref() else {
stmt.err = Some(LimboError::InternalError("Statement is closed".to_string()));
return -1;
@@ -99,13 +99,13 @@ pub extern "C" fn stmt_parameter_count(ctx: *mut c_void) -> i32 {
#[no_mangle]
pub extern "C" fn stmt_query(
ctx: *mut c_void,
args_ptr: *mut LimboValue,
args_ptr: *mut TursoValue,
args_count: usize,
) -> *mut c_void {
if ctx.is_null() {
return std::ptr::null_mut();
}
let stmt = LimboStatement::from_ptr(ctx);
let stmt = TursoStatement::from_ptr(ctx);
let args = if !args_ptr.is_null() && args_count > 0 {
unsafe { std::slice::from_raw_parts(args_ptr, args_count) }
} else {
@@ -119,21 +119,21 @@ pub extern "C" fn stmt_query(
let val = arg.to_value(&mut pool);
statement.bind_at(NonZero::new(i + 1).unwrap(), val);
}
// ownership of the statement is transferred to the LimboRows object.
LimboRows::new(statement, stmt.conn).to_ptr()
// ownership of the statement is transferred to the TursoRows object.
TursoRows::new(statement, stmt.conn).to_ptr()
}
pub struct LimboStatement<'conn> {
/// If 'query' is ran on the statement, ownership is transferred to the LimboRows object
pub struct TursoStatement<'conn> {
/// If 'query' is ran on the statement, ownership is transferred to the TursoRows object
pub statement: Option<Statement>,
pub conn: &'conn mut LimboConn,
pub conn: &'conn mut TursoConn,
pub err: Option<LimboError>,
}
#[no_mangle]
pub extern "C" fn stmt_close(ctx: *mut c_void) -> ResultCode {
if !ctx.is_null() {
let stmt = unsafe { Box::from_raw(ctx as *mut LimboStatement) };
let stmt = unsafe { Box::from_raw(ctx as *mut TursoStatement) };
drop(stmt);
return ResultCode::Ok;
}
@@ -145,13 +145,13 @@ pub extern "C" fn stmt_get_error(ctx: *mut c_void) -> *const c_char {
if ctx.is_null() {
return std::ptr::null();
}
let stmt = LimboStatement::from_ptr(ctx);
let stmt = TursoStatement::from_ptr(ctx);
stmt.get_error()
}
impl<'conn> LimboStatement<'conn> {
pub fn new(statement: Option<Statement>, conn: &'conn mut LimboConn) -> Self {
LimboStatement {
impl<'conn> TursoStatement<'conn> {
pub fn new(statement: Option<Statement>, conn: &'conn mut TursoConn) -> Self {
TursoStatement {
statement,
conn,
err: None,
@@ -163,11 +163,11 @@ impl<'conn> LimboStatement<'conn> {
Box::into_raw(Box::new(self)) as *mut c_void
}
fn from_ptr(ptr: *mut c_void) -> &'conn mut LimboStatement<'conn> {
fn from_ptr(ptr: *mut c_void) -> &'conn mut TursoStatement<'conn> {
if ptr.is_null() {
panic!("Null pointer");
}
unsafe { &mut *(ptr as *mut LimboStatement) }
unsafe { &mut *(ptr as *mut TursoStatement) }
}
fn get_error(&mut self) -> *const c_char {

View File

@@ -34,33 +34,33 @@ pub enum ValueType {
}
#[repr(C)]
pub struct LimboValue {
pub struct TursoValue {
value_type: ValueType,
value: ValueUnion,
}
impl Debug for LimboValue {
impl Debug for TursoValue {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self.value_type {
ValueType::Integer => {
let i = self.value.to_int();
f.debug_struct("LimboValue").field("value", &i).finish()
f.debug_struct("TursoValue").field("value", &i).finish()
}
ValueType::Real => {
let r = self.value.to_real();
f.debug_struct("LimboValue").field("value", &r).finish()
f.debug_struct("TursoValue").field("value", &r).finish()
}
ValueType::Text => {
let t = self.value.to_str();
f.debug_struct("LimboValue").field("value", &t).finish()
f.debug_struct("TursoValue").field("value", &t).finish()
}
ValueType::Blob => {
let blob = self.value.to_bytes();
f.debug_struct("LimboValue")
f.debug_struct("TursoValue")
.field("value", &blob.to_vec())
.finish()
}
ValueType::Null => f
.debug_struct("LimboValue")
.debug_struct("TursoValue")
.field("value", &"NULL")
.finish(),
}
@@ -164,9 +164,9 @@ impl ValueUnion {
}
}
impl LimboValue {
impl TursoValue {
fn new(value_type: ValueType, value: ValueUnion) -> Self {
LimboValue { value_type, value }
TursoValue { value_type, value }
}
#[allow(clippy::wrong_self_convention)]
@@ -177,18 +177,18 @@ impl LimboValue {
pub fn from_db_value(value: &turso_core::Value) -> Self {
match value {
turso_core::Value::Integer(i) => {
LimboValue::new(ValueType::Integer, ValueUnion::from_int(*i))
TursoValue::new(ValueType::Integer, ValueUnion::from_int(*i))
}
turso_core::Value::Float(r) => {
LimboValue::new(ValueType::Real, ValueUnion::from_real(*r))
TursoValue::new(ValueType::Real, ValueUnion::from_real(*r))
}
turso_core::Value::Text(s) => {
LimboValue::new(ValueType::Text, ValueUnion::from_str(s.as_str()))
TursoValue::new(ValueType::Text, ValueUnion::from_str(s.as_str()))
}
turso_core::Value::Blob(b) => {
LimboValue::new(ValueType::Blob, ValueUnion::from_bytes(b.as_slice()))
TursoValue::new(ValueType::Blob, ValueUnion::from_bytes(b.as_slice()))
}
turso_core::Value::Null => LimboValue::new(ValueType::Null, ValueUnion::from_null()),
turso_core::Value::Null => TursoValue::new(ValueType::Null, ValueUnion::from_null()),
}
}

View File

@@ -1,4 +1,4 @@
package limbo
package turso
import (
"context"
@@ -9,22 +9,22 @@ import (
"unsafe"
)
type limboStmt struct {
type tursoStmt struct {
mu sync.Mutex
ctx uintptr
sql string
err error
}
func newStmt(ctx uintptr, sql string) *limboStmt {
return &limboStmt{
func newStmt(ctx uintptr, sql string) *tursoStmt {
return &tursoStmt{
ctx: uintptr(ctx),
sql: sql,
err: nil,
}
}
func (ls *limboStmt) NumInput() int {
func (ls *tursoStmt) NumInput() int {
ls.mu.Lock()
defer ls.mu.Unlock()
res := int(stmtParamCount(ls.ctx))
@@ -35,7 +35,7 @@ func (ls *limboStmt) NumInput() int {
return res
}
func (ls *limboStmt) Close() error {
func (ls *tursoStmt) Close() error {
ls.mu.Lock()
defer ls.mu.Unlock()
if ls.ctx == 0 {
@@ -49,7 +49,7 @@ func (ls *limboStmt) Close() error {
return nil
}
func (ls *limboStmt) Exec(args []driver.Value) (driver.Result, error) {
func (ls *tursoStmt) Exec(args []driver.Value) (driver.Result, error) {
argArray, cleanup, err := buildArgs(args)
defer cleanup()
if err != nil {
@@ -80,7 +80,7 @@ func (ls *limboStmt) Exec(args []driver.Value) (driver.Result, error) {
}
}
func (ls *limboStmt) Query(args []driver.Value) (driver.Rows, error) {
func (ls *tursoStmt) Query(args []driver.Value) (driver.Rows, error) {
queryArgs, cleanup, err := buildArgs(args)
defer cleanup()
if err != nil {
@@ -99,7 +99,7 @@ func (ls *limboStmt) Query(args []driver.Value) (driver.Rows, error) {
return newRows(rowsPtr), nil
}
func (ls *limboStmt) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error) {
func (ls *tursoStmt) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error) {
stripped := namedValueToValue(args)
argArray, cleanup, err := getArgsPtr(stripped)
defer cleanup()
@@ -129,7 +129,7 @@ func (ls *limboStmt) ExecContext(ctx context.Context, query string, args []drive
}
}
func (ls *limboStmt) QueryContext(ctx context.Context, args []driver.NamedValue) (driver.Rows, error) {
func (ls *tursoStmt) QueryContext(ctx context.Context, args []driver.NamedValue) (driver.Rows, error) {
queryArgs, allocs, err := buildNamedArgs(args)
defer allocs()
if err != nil {
@@ -154,7 +154,7 @@ func (ls *limboStmt) QueryContext(ctx context.Context, args []driver.NamedValue)
}
}
func (ls *limboStmt) Err() error {
func (ls *tursoStmt) Err() error {
if ls.err == nil {
ls.mu.Lock()
defer ls.mu.Unlock()
@@ -164,7 +164,7 @@ func (ls *limboStmt) Err() error {
}
// mutex should always be locked when calling - always called after FFI
func (ls *limboStmt) getError() error {
func (ls *tursoStmt) getError() error {
err := stmtGetError(ls.ctx)
if err == 0 {
return nil

View File

@@ -1,4 +1,4 @@
package limbo_test
package turso_test
import (
"database/sql"
@@ -17,7 +17,7 @@ var (
)
func TestMain(m *testing.M) {
conn, connErr = sql.Open("sqlite3", ":memory:")
conn, connErr = sql.Open("turso", ":memory:")
if connErr != nil {
panic(connErr)
}
@@ -146,7 +146,7 @@ func TestFunctions(t *testing.T) {
}
func TestDuplicateConnection(t *testing.T) {
newConn, err := sql.Open("sqlite3", ":memory:")
newConn, err := sql.Open("turso", ":memory:")
if err != nil {
t.Fatalf("Error opening new connection: %v", err)
}
@@ -177,7 +177,7 @@ func TestDuplicateConnection(t *testing.T) {
}
func TestDuplicateConnection2(t *testing.T) {
newConn, err := sql.Open("sqlite3", ":memory:")
newConn, err := sql.Open("turso", ":memory:")
if err != nil {
t.Fatalf("Error opening new connection: %v", err)
}
@@ -209,7 +209,7 @@ func TestDuplicateConnection2(t *testing.T) {
}
func TestConnectionError(t *testing.T) {
newConn, err := sql.Open("sqlite3", ":memory:")
newConn, err := sql.Open("turso", ":memory:")
if err != nil {
t.Fatalf("Error opening new connection: %v", err)
}
@@ -228,7 +228,7 @@ func TestConnectionError(t *testing.T) {
}
func TestStatementError(t *testing.T) {
newConn, err := sql.Open("sqlite3", ":memory:")
newConn, err := sql.Open("turso", ":memory:")
if err != nil {
t.Fatalf("Error opening new connection: %v", err)
}
@@ -250,7 +250,7 @@ func TestStatementError(t *testing.T) {
}
func TestDriverRowsErrorMessages(t *testing.T) {
db, err := sql.Open("sqlite3", ":memory:")
db, err := sql.Open("turso", ":memory:")
if err != nil {
t.Fatalf("failed to open database: %v", err)
}
@@ -285,7 +285,7 @@ func TestDriverRowsErrorMessages(t *testing.T) {
func TestTransaction(t *testing.T) {
// Open database connection
db, err := sql.Open("sqlite3", ":memory:")
db, err := sql.Open("turso", ":memory:")
if err != nil {
t.Fatalf("Error opening database: %v", err)
}
@@ -359,7 +359,7 @@ func TestTransaction(t *testing.T) {
}
func TestVectorOperations(t *testing.T) {
db, err := sql.Open("sqlite3", ":memory:")
db, err := sql.Open("turso", ":memory:")
if err != nil {
t.Fatalf("Error opening connection: %v", err)
}
@@ -397,7 +397,7 @@ func TestVectorOperations(t *testing.T) {
}
func TestSQLFeatures(t *testing.T) {
db, err := sql.Open("sqlite3", ":memory:")
db, err := sql.Open("turso", ":memory:")
if err != nil {
t.Fatalf("Error opening connection: %v", err)
}
@@ -501,7 +501,7 @@ func TestSQLFeatures(t *testing.T) {
}
func TestDateTimeFunctions(t *testing.T) {
db, err := sql.Open("sqlite3", ":memory:")
db, err := sql.Open("turso", ":memory:")
if err != nil {
t.Fatalf("Error opening connection: %v", err)
}
@@ -536,7 +536,7 @@ func TestDateTimeFunctions(t *testing.T) {
}
func TestMathFunctions(t *testing.T) {
db, err := sql.Open("sqlite3", ":memory:")
db, err := sql.Open("turso", ":memory:")
if err != nil {
t.Fatalf("Error opening connection: %v", err)
}
@@ -572,7 +572,7 @@ func TestMathFunctions(t *testing.T) {
}
func TestJSONFunctions(t *testing.T) {
db, err := sql.Open("sqlite3", ":memory:")
db, err := sql.Open("turso", ":memory:")
if err != nil {
t.Fatalf("Error opening connection: %v", err)
}
@@ -610,7 +610,7 @@ func TestJSONFunctions(t *testing.T) {
}
func TestParameterOrdering(t *testing.T) {
newConn, err := sql.Open("sqlite3", ":memory:")
newConn, err := sql.Open("turso", ":memory:")
if err != nil {
t.Fatalf("Error opening new connection: %v", err)
}
@@ -685,7 +685,7 @@ func TestParameterOrdering(t *testing.T) {
}
func TestIndex(t *testing.T) {
newConn, err := sql.Open("sqlite3", ":memory:")
newConn, err := sql.Open("turso", ":memory:")
if err != nil {
t.Fatalf("Error opening new connection: %v", err)
}

View File

@@ -1,6 +1,6 @@
//go:build linux || darwin
package limbo
package turso
import (
"fmt"

View File

@@ -1,6 +1,6 @@
//go:build windows
package limbo
package turso
import (
"fmt"

View File

@@ -1,4 +1,4 @@
package limbo
package turso
import (
"database/sql/driver"
@@ -66,8 +66,8 @@ func (rc ResultCode) String() string {
}
const (
driverName = "sqlite3"
libName = "lib_limbo_go"
driverName = "turso"
libName = "lib_turso_go"
RowsClosedErr = "sql: Rows closed"
FfiDbOpen = "db_open"
FfiDbClose = "db_close"
@@ -98,7 +98,7 @@ func namedValueToValue(named []driver.NamedValue) []driver.Value {
return out
}
func buildNamedArgs(named []driver.NamedValue) ([]limboValue, func(), error) {
func buildNamedArgs(named []driver.NamedValue) ([]tursoValue, func(), error) {
args := namedValueToValue(named)
return buildArgs(args)
}
@@ -131,7 +131,7 @@ func (vt valueType) String() string {
}
// struct to pass Go values over FFI
type limboValue struct {
type tursoValue struct {
Type valueType
_ [4]byte
Value [8]byte
@@ -143,12 +143,12 @@ type Blob struct {
Len int64
}
// convert a limboValue to a native Go value
// convert a tursoValue to a native Go value
func toGoValue(valPtr uintptr) interface{} {
if valPtr == 0 {
return nil
}
val := (*limboValue)(unsafe.Pointer(valPtr))
val := (*tursoValue)(unsafe.Pointer(valPtr))
switch val.Type {
case intVal:
return *(*int64)(unsafe.Pointer(&val.Value))
@@ -228,50 +228,50 @@ func freeCString(cstrPtr uintptr) {
freeStringFunc(cstrPtr)
}
// convert a Go slice of driver.Value to a slice of limboValue that can be sent over FFI
// convert a Go slice of driver.Value to a slice of tursoValue that can be sent over FFI
// for Blob types, we have to pin them so they are not garbage collected before they can be copied
// into a buffer on the Rust side, so we return a function to unpin them that can be deferred after this call
func buildArgs(args []driver.Value) ([]limboValue, func(), error) {
func buildArgs(args []driver.Value) ([]tursoValue, func(), error) {
pinner := new(runtime.Pinner)
argSlice := make([]limboValue, len(args))
argSlice := make([]tursoValue, len(args))
for i, v := range args {
limboVal := limboValue{}
tursoVal := tursoValue{}
switch val := v.(type) {
case nil:
limboVal.Type = nullVal
tursoVal.Type = nullVal
case int64:
limboVal.Type = intVal
limboVal.Value = *(*[8]byte)(unsafe.Pointer(&val))
tursoVal.Type = intVal
tursoVal.Value = *(*[8]byte)(unsafe.Pointer(&val))
case float64:
limboVal.Type = realVal
limboVal.Value = *(*[8]byte)(unsafe.Pointer(&val))
tursoVal.Type = realVal
tursoVal.Value = *(*[8]byte)(unsafe.Pointer(&val))
case bool:
limboVal.Type = intVal
tursoVal.Type = intVal
boolAsInt := int64(0)
if val {
boolAsInt = 1
}
limboVal.Value = *(*[8]byte)(unsafe.Pointer(&boolAsInt))
tursoVal.Value = *(*[8]byte)(unsafe.Pointer(&boolAsInt))
case string:
limboVal.Type = textVal
tursoVal.Type = textVal
cstr := CString(val)
pinner.Pin(cstr)
*(*uintptr)(unsafe.Pointer(&limboVal.Value)) = uintptr(unsafe.Pointer(cstr))
*(*uintptr)(unsafe.Pointer(&tursoVal.Value)) = uintptr(unsafe.Pointer(cstr))
case []byte:
limboVal.Type = blobVal
tursoVal.Type = blobVal
blob := makeBlob(val)
pinner.Pin(blob)
*(*uintptr)(unsafe.Pointer(&limboVal.Value)) = uintptr(unsafe.Pointer(blob))
*(*uintptr)(unsafe.Pointer(&tursoVal.Value)) = uintptr(unsafe.Pointer(blob))
case time.Time:
limboVal.Type = textVal
tursoVal.Type = textVal
timeStr := val.Format(time.RFC3339)
cstr := CString(timeStr)
pinner.Pin(cstr)
*(*uintptr)(unsafe.Pointer(&limboVal.Value)) = uintptr(unsafe.Pointer(cstr))
*(*uintptr)(unsafe.Pointer(&tursoVal.Value)) = uintptr(unsafe.Pointer(cstr))
default:
return nil, pinner.Unpin, fmt.Errorf("unsupported type: %T", v)
}
argSlice[i] = limboVal
argSlice[i] = tursoVal
}
return argSlice, pinner.Unpin, nil
}