Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

report actual error message if sqlite3_load_extension fails #800

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
17 changes: 11 additions & 6 deletions _example/mod_regexp/Makefile
@@ -1,22 +1,27 @@
ifeq ($(OS),Windows_NT)
EXE=extension.exe
EXT=sqlite3_mod_regexp.dll
LIB_EXT=dll
RM=cmd /c del
LDFLAG=
else
EXE=extension
EXT=sqlite3_mod_regexp.so
RM=rm
ifeq ($(shell uname -s),Darwin)
LIB_EXT=dylib
else
LIB_EXT=so
endif
RM=rm -f
LDFLAG=-fPIC
endif
LIB=sqlite3_mod_regexp.$(LIB_EXT)

all : $(EXE) $(EXT)
all : $(EXE) $(LIB)

$(EXE) : extension.go
go build $<

$(EXT) : sqlite3_mod_regexp.c
$(LIB) : sqlite3_mod_regexp.c
gcc $(LDFLAG) -shared -o $@ $< -lsqlite3 -lpcre

clean :
@-$(RM) $(EXE) $(EXT)
@-$(RM) $(EXE) $(LIB)
17 changes: 11 additions & 6 deletions _example/mod_vtable/Makefile
@@ -1,24 +1,29 @@
ifeq ($(OS),Windows_NT)
EXE=extension.exe
EXT=sqlite3_mod_vtable.dll
LIB_EXT=dll
RM=cmd /c del
LIBCURL=-lcurldll
LDFLAG=
else
EXE=extension
EXT=sqlite3_mod_vtable.so
RM=rm
ifeq ($(shell uname -s),Darwin)
LIB_EXT=dylib
else
LIB_EXT=so
endif
RM=rm -f
LDFLAG=-fPIC
LIBCURL=-lcurl
endif
LIB=sqlite3_mod_vtable.$(LIB_EXT)

all : $(EXE) $(EXT)
all : $(EXE) $(LIB)

$(EXE) : extension.go
go build $<

$(EXT) : sqlite3_mod_vtable.cc
$(LIB) : sqlite3_mod_vtable.cc
g++ $(LDFLAG) -shared -o $@ $< -lsqlite3 $(LIBCURL)

clean :
@-$(RM) $(EXE) $(EXT)
@-$(RM) $(EXE) $(LIB)
2 changes: 1 addition & 1 deletion _example/mod_vtable/sqlite3_mod_vtable.cc
@@ -1,6 +1,6 @@
#include <string>
#include <sstream>
#include <sqlite3-binding.h>
#include <sqlite3.h>
#include <sqlite3ext.h>
#include <curl/curl.h>
#include "picojson.h"
Expand Down
38 changes: 26 additions & 12 deletions sqlite3_load_extension.go
Expand Up @@ -28,19 +28,17 @@ func (c *SQLiteConn) loadExtensions(extensions []string) error {
}

for _, extension := range extensions {
cext := C.CString(extension)
defer C.free(unsafe.Pointer(cext))
rv = C.sqlite3_load_extension(c.db, cext, nil, nil)
if rv != C.SQLITE_OK {
if err := c.loadExtension(extension, nil); err != nil {
C.sqlite3_enable_load_extension(c.db, 0)
return errors.New(C.GoString(C.sqlite3_errmsg(c.db)))
return err
}
}

rv = C.sqlite3_enable_load_extension(c.db, 0)
if rv != C.SQLITE_OK {
return errors.New(C.GoString(C.sqlite3_errmsg(c.db)))
}

return nil
}

Expand All @@ -51,19 +49,35 @@ func (c *SQLiteConn) LoadExtension(lib string, entry string) error {
return errors.New(C.GoString(C.sqlite3_errmsg(c.db)))
}

clib := C.CString(lib)
defer C.free(unsafe.Pointer(clib))
centry := C.CString(entry)
defer C.free(unsafe.Pointer(centry))
if err := c.loadExtension(lib, &entry); err != nil {
C.sqlite3_enable_load_extension(c.db, 0)
return err
}

rv = C.sqlite3_load_extension(c.db, clib, centry, nil)
rv = C.sqlite3_enable_load_extension(c.db, 0)
if rv != C.SQLITE_OK {
return errors.New(C.GoString(C.sqlite3_errmsg(c.db)))
}

rv = C.sqlite3_enable_load_extension(c.db, 0)
return nil
}

func (c *SQLiteConn) loadExtension(lib string, entry *string) error {
clib := C.CString(lib)
defer C.free(unsafe.Pointer(clib))

var centry *C.char
if entry != nil {
centry := C.CString(*entry)
defer C.free(unsafe.Pointer(centry))
}

var errMsg *C.char
defer C.sqlite3_free(unsafe.Pointer(errMsg))

rv := C.sqlite3_load_extension(c.db, clib, centry, &errMsg)
if rv != C.SQLITE_OK {
return errors.New(C.GoString(C.sqlite3_errmsg(c.db)))
return errors.New(C.GoString(errMsg))
}

return nil
Expand Down
63 changes: 63 additions & 0 deletions sqlite3_load_extension_test.go
@@ -0,0 +1,63 @@
// Copyright (C) 2019 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.

// +build !sqlite_omit_load_extension

package sqlite3

import (
"database/sql"
"testing"
)

func TestExtensionsError(t *testing.T) {
sql.Register("sqlite3_TestExtensionsError",
&SQLiteDriver{
Extensions: []string{
"foobar",
},
},
)

db, err := sql.Open("sqlite3_TestExtensionsError", ":memory:")
if err != nil {
t.Fatal(err)
}
defer db.Close()

err = db.Ping()
if err == nil {
t.Fatal("expected error loading non-existent extension")
}

if err.Error() == "not an error" {
t.Fatal("expected error from sqlite3_enable_load_extension to be returned")
}
}

func TestLoadExtensionError(t *testing.T) {
sql.Register("sqlite3_TestLoadExtensionError",
&SQLiteDriver{
ConnectHook: func(c *SQLiteConn) error {
return c.LoadExtension("foobar", "")
},
},
)

db, err := sql.Open("sqlite3_TestLoadExtensionError", ":memory:")
if err != nil {
t.Fatal(err)
}
defer db.Close()

err = db.Ping()
if err == nil {
t.Fatal("expected error loading non-existent extension")
}

if err.Error() == "not an error" {
t.Fatal("expected error from sqlite3_enable_load_extension to be returned")
}
}