Skip to content

Commit 38b8efe

Browse files
committed
initial setup + tests
1 parent 9c24e0e commit 38b8efe

File tree

2 files changed

+98
-0
lines changed

2 files changed

+98
-0
lines changed

libsql.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,36 @@ type conn struct {
395395
nativePtr C.libsql_connection_t
396396
}
397397

398+
type extension struct {
399+
Library string
400+
Entry string
401+
}
402+
403+
func (c *conn) loadExtensions(exts []extension) error {
404+
for _, ext := range exts {
405+
if err := c.loadExtension(ext.Library, ext.Entry); err != nil {
406+
return err
407+
}
408+
}
409+
return nil
410+
}
411+
412+
func (c *conn) LoadExtension(lib string, entry string) error {
413+
if err := c.loadExtension(lib, entry); err != nil {
414+
return err
415+
}
416+
return nil
417+
}
418+
419+
func (c *conn) loadExtension(lib string, entry string) error {
420+
var errMsg *C.char
421+
statusCode := C.libsql_load_extension(c.nativePtr, C.CString(lib), C.CString(entry), nil)
422+
if statusCode != 0 {
423+
return libsqlError(fmt.Sprintf("failed to load extension %s with entry point %s", lib, entry), statusCode, errMsg)
424+
}
425+
return nil
426+
}
427+
398428
func (c *conn) Prepare(query string) (sqldriver.Stmt, error) {
399429
return c.PrepareContext(context.Background(), query)
400430
}

libsql_test.go

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1359,3 +1359,71 @@ func TestErrorRowsNext(t *testing.T) {
13591359
}
13601360
})
13611361
}
1362+
1363+
// To run this, set LIBSQL_TEST_EXTENSION to the full path of a valid SQLite extension
1364+
// and (optionally) LIBSQL_TEST_EXTENSION_ENTRY to its init symbol (defaults to "sqlite3_extension_init").
1365+
func TestLoadExtension_Existing(t *testing.T) {
1366+
extPath := os.Getenv("LIBSQL_TEST_EXTENSION")
1367+
if extPath == "" {
1368+
t.Skip("LIBSQL_TEST_EXTENSION not set; skipping existing‐extension load test")
1369+
}
1370+
entryPoint := os.Getenv("LIBSQL_TEST_EXTENSION_ENTRY")
1371+
if entryPoint == "" {
1372+
entryPoint = "sqlite3_extension_init"
1373+
}
1374+
1375+
db, err := sql.Open("libsql", ":memory:")
1376+
if err != nil {
1377+
t.Fatal(err)
1378+
}
1379+
defer db.Close()
1380+
1381+
ctx := context.Background()
1382+
sqlConn, err := db.Conn(ctx)
1383+
if err != nil {
1384+
t.Fatal(err)
1385+
}
1386+
defer sqlConn.Close()
1387+
1388+
err = sqlConn.Raw(func(driverConn interface{}) error {
1389+
cImpl, ok := driverConn.(*conn)
1390+
if !ok {
1391+
return fmt.Errorf("unexpected driverConn type %T", driverConn)
1392+
}
1393+
return cImpl.LoadExtension(extPath, entryPoint)
1394+
})
1395+
1396+
if err != nil {
1397+
t.Fatalf("failed to load existing extension %q (entry %q): %v", extPath, entryPoint, err)
1398+
}
1399+
}
1400+
1401+
func TestLoadExtension_Nonexistent(t *testing.T) {
1402+
db, err := sql.Open("libsql", ":memory:")
1403+
if err != nil {
1404+
t.Fatal(err)
1405+
}
1406+
defer db.Close()
1407+
1408+
ctx := context.Background()
1409+
sqlConn, err := db.Conn(ctx)
1410+
if err != nil {
1411+
t.Fatal(err)
1412+
}
1413+
defer sqlConn.Close()
1414+
1415+
err = sqlConn.Raw(func(driverConn interface{}) error {
1416+
cImpl, ok := driverConn.(*conn)
1417+
if !ok {
1418+
return fmt.Errorf("unexpected driverConn type %T", driverConn)
1419+
}
1420+
return cImpl.LoadExtension("nonexistent_extension.so", "entry_point")
1421+
})
1422+
1423+
if err == nil {
1424+
t.Fatal("expected error loading nonexistent extension, got nil")
1425+
}
1426+
if !strings.Contains(err.Error(), "failed to load extension") {
1427+
t.Fatalf("unexpected error loading extension: %v", err)
1428+
}
1429+
}

0 commit comments

Comments
 (0)