From 3a5555302e9b06eb5461016462900f1412ae3f7c Mon Sep 17 00:00:00 2001 From: David Bariod Date: Sat, 2 Apr 2016 12:32:47 +0200 Subject: Move sqlite3 amalgation files a directory up. The purpose is to ease the use of vendoring files like godep. The C sqlite3 files have been added a go compilation conditional flag Fix #293 --- backup.go | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'backup.go') diff --git a/backup.go b/backup.go index 3807c60..4c1e38c 100644 --- a/backup.go +++ b/backup.go @@ -6,7 +6,11 @@ package sqlite3 /* +#ifndef USE_LIBSQLITE3 #include +#else +#include +#endif #include */ import "C" -- cgit v1.2.3 From bdab31cc98cdf61a93567c55e85e835ba6fb364f Mon Sep 17 00:00:00 2001 From: Joe Shaw Date: Thu, 27 Oct 2016 16:44:56 -0700 Subject: fix double free in SQLiteBackup.Close() on error The sqlite3_backup_finish() function never fails, it just returns the error code from previous operations. Previously if it returned an error, the finalizer wouldn't be unset and sqlite3_backup_finish() would be run again on an already-finished backup. This results in a double-free and often segfaults. The error handling is described in more detail in the "Error handling" section of https://www.sqlite.org/backup.html. --- backup.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'backup.go') diff --git a/backup.go b/backup.go index 4c1e38c..05f8038 100644 --- a/backup.go +++ b/backup.go @@ -65,10 +65,15 @@ func (b *SQLiteBackup) Finish() error { func (b *SQLiteBackup) Close() error { ret := C.sqlite3_backup_finish(b.b) + + // sqlite3_backup_finish() never fails, it just returns the + // error code from previous operations, so clean up before + // checking and returning an error + b.b = nil + runtime.SetFinalizer(b, nil) + if ret != 0 { return Error{Code: ErrNo(ret)} } - b.b = nil - runtime.SetFinalizer(b, nil) return nil } -- cgit v1.2.3 From 0d1d1a644e704714e7ccf5e28dc53601c4e9cf37 Mon Sep 17 00:00:00 2001 From: Yasuhiro Matsumoto Date: Sat, 5 Nov 2016 00:40:06 +0900 Subject: go vet && golint --- backup.go | 14 +++++++++---- error.go | 1 + sqlite3.go | 50 +++++++++++++++++++++++------------------------ sqlite3_go18.go | 6 ++++++ sqlite3_load_extension.go | 1 + tracecallback_noimpl.go | 1 + 6 files changed, 44 insertions(+), 29 deletions(-) (limited to 'backup.go') diff --git a/backup.go b/backup.go index 05f8038..5ab3a54 100644 --- a/backup.go +++ b/backup.go @@ -19,10 +19,12 @@ import ( "unsafe" ) +// SQLiteBackup implement interface of Backup. type SQLiteBackup struct { b *C.sqlite3_backup } +// Backup make backup from src to dest. func (c *SQLiteConn) Backup(dest string, conn *SQLiteConn, src string) (*SQLiteBackup, error) { destptr := C.CString(dest) defer C.free(unsafe.Pointer(destptr)) @@ -37,10 +39,10 @@ func (c *SQLiteConn) Backup(dest string, conn *SQLiteConn, src string) (*SQLiteB return nil, c.lastError() } -// Backs up for one step. Calls the underlying `sqlite3_backup_step` function. -// This function returns a boolean indicating if the backup is done and -// an error signalling any other error. Done is returned if the underlying C -// function returns SQLITE_DONE (Code 101) +// Step to backs up for one step. Calls the underlying `sqlite3_backup_step` +// function. This function returns a boolean indicating if the backup is done +// and an error signalling any other error. Done is returned if the underlying +// C function returns SQLITE_DONE (Code 101) func (b *SQLiteBackup) Step(p int) (bool, error) { ret := C.sqlite3_backup_step(b.b, C.int(p)) if ret == C.SQLITE_DONE { @@ -51,18 +53,22 @@ func (b *SQLiteBackup) Step(p int) (bool, error) { return false, nil } +// Remaining return whether have the rest for backup. func (b *SQLiteBackup) Remaining() int { return int(C.sqlite3_backup_remaining(b.b)) } +// PageCount return count of pages. func (b *SQLiteBackup) PageCount() int { return int(C.sqlite3_backup_pagecount(b.b)) } +// Finish close backup. func (b *SQLiteBackup) Finish() error { return b.Close() } +// Close close backup. func (b *SQLiteBackup) Close() error { ret := C.sqlite3_backup_finish(b.b) diff --git a/error.go b/error.go index b910108..474f8e6 100644 --- a/error.go +++ b/error.go @@ -7,6 +7,7 @@ package sqlite3 import "C" +// ErrNo inherit errno. type ErrNo int const ErrNoMask C.int = 0xff diff --git a/sqlite3.go b/sqlite3.go index cf5e99a..b018918 100644 --- a/sqlite3.go +++ b/sqlite3.go @@ -118,10 +118,10 @@ import ( "golang.org/x/net/context" ) -// Timestamp formats understood by both this module and SQLite. -// The first format in the slice will be used when saving time values -// into the database. When parsing a string from a timestamp or -// datetime column, the formats are tried in order. +// SQLiteTimestampFormats is timestamp formats understood by both this module +// and SQLite. The first format in the slice will be used when saving time +// values into the database. When parsing a string from a timestamp or datetime +// column, the formats are tried in order. var SQLiteTimestampFormats = []string{ // By default, store timestamps with whatever timezone they come with. // When parsed, they will be returned with the same timezone. @@ -141,20 +141,20 @@ func init() { } // Version returns SQLite library version information. -func Version() (libVersion string, libVersionNumber int, sourceId string) { +func Version() (libVersion string, libVersionNumber int, sourceID string) { libVersion = C.GoString(C.sqlite3_libversion()) libVersionNumber = int(C.sqlite3_libversion_number()) - sourceId = C.GoString(C.sqlite3_sourceid()) - return libVersion, libVersionNumber, sourceId + sourceID = C.GoString(C.sqlite3_sourceid()) + return libVersion, libVersionNumber, sourceID } -// Driver struct. +// SQLiteDriver implement sql.Driver. type SQLiteDriver struct { Extensions []string ConnectHook func(*SQLiteConn) error } -// Conn struct. +// SQLiteConn implement sql.Conn. type SQLiteConn struct { db *C.sqlite3 loc *time.Location @@ -163,12 +163,12 @@ type SQLiteConn struct { aggregators []*aggInfo } -// Tx struct. +// SQLiteTx implemen sql.Tx. type SQLiteTx struct { c *SQLiteConn } -// Stmt struct. +// SQLiteStmt implement sql.Stmt. type SQLiteStmt struct { c *SQLiteConn s *C.sqlite3_stmt @@ -177,13 +177,13 @@ type SQLiteStmt struct { cls bool } -// Result struct. +// SQLiteResult implement sql.Result. type SQLiteResult struct { id int64 changes int64 } -// Rows struct. +// SQLiteRows implement sql.Rows. type SQLiteRows struct { s *SQLiteStmt nc int @@ -401,7 +401,7 @@ func (c *SQLiteConn) lastError() Error { } } -// Implements Execer +// Exec implements Execer. func (c *SQLiteConn) Exec(query string, args []driver.Value) (driver.Result, error) { if len(args) == 0 { return c.execQuery(query) @@ -456,7 +456,7 @@ type namedValue struct { Value driver.Value } -// Implements Queryer +// Query implements Queryer. func (c *SQLiteConn) Query(query string, args []driver.Value) (driver.Rows, error) { list := make([]namedValue, len(args)) for i, v := range args { @@ -549,7 +549,7 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) { var loc *time.Location txlock := "BEGIN" - busy_timeout := 5000 + busyTimeout := 5000 pos := strings.IndexRune(dsn, '?') if pos >= 1 { params, err := url.ParseQuery(dsn[pos+1:]) @@ -575,7 +575,7 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) { if err != nil { return nil, fmt.Errorf("Invalid _busy_timeout: %v: %v", val, err) } - busy_timeout = int(iv) + busyTimeout = int(iv) } // _txlock @@ -612,7 +612,7 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) { return nil, errors.New("sqlite succeeded without returning a database") } - rv = C.sqlite3_busy_timeout(db, C.int(busy_timeout)) + rv = C.sqlite3_busy_timeout(db, C.int(busyTimeout)) if rv != C.SQLITE_OK { return nil, Error{Code: ErrNo(rv)} } @@ -686,7 +686,7 @@ func (s *SQLiteStmt) Close() error { return nil } -// Return a number of parameters. +// NumInput return a number of parameters. func (s *SQLiteStmt) NumInput() int { return int(C.sqlite3_bind_parameter_count(s.s)) } @@ -769,17 +769,17 @@ func (s *SQLiteStmt) query(ctx context.Context, args []namedValue) (driver.Rows, return &SQLiteRows{s, int(C.sqlite3_column_count(s.s)), nil, nil, s.cls}, nil } -// Return last inserted ID. +// LastInsertId teturn last inserted ID. func (r *SQLiteResult) LastInsertId() (int64, error) { return r.id, nil } -// Return how many rows affected. +// RowsAffected return how many rows affected. func (r *SQLiteResult) RowsAffected() (int64, error) { return r.changes, nil } -// Execute the statement with arguments. Return result object. +// Exec execute the statement with arguments. Return result object. func (s *SQLiteStmt) Exec(args []driver.Value) (driver.Result, error) { list := make([]namedValue, len(args)) for i, v := range args { @@ -823,7 +823,7 @@ func (rc *SQLiteRows) Close() error { return nil } -// Return column names. +// Columns return column names. func (rc *SQLiteRows) Columns() []string { if rc.nc != len(rc.cols) { rc.cols = make([]string, rc.nc) @@ -834,7 +834,7 @@ func (rc *SQLiteRows) Columns() []string { return rc.cols } -// Return column types. +// DeclTypes return column types. func (rc *SQLiteRows) DeclTypes() []string { if rc.decltype == nil { rc.decltype = make([]string, rc.nc) @@ -845,7 +845,7 @@ func (rc *SQLiteRows) DeclTypes() []string { return rc.decltype } -// Move cursor to next. +// Next move cursor to next. func (rc *SQLiteRows) Next(dest []driver.Value) error { rv := C.sqlite3_step(rc.s.s) if rv == C.SQLITE_DONE { diff --git a/sqlite3_go18.go b/sqlite3_go18.go index 7109d58..9ad7baf 100644 --- a/sqlite3_go18.go +++ b/sqlite3_go18.go @@ -17,6 +17,7 @@ func (c *SQLiteConn) Ping(ctx context.Context) error { return nil } +// QueryContext implement QueryerContext. func (c *SQLiteConn) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Rows, error) { list := make([]namedValue, len(args)) for i, nv := range args { @@ -25,6 +26,7 @@ func (c *SQLiteConn) QueryContext(ctx context.Context, query string, args []driv return c.query(ctx, query, list) } +// ExecContext implement ExecerContext. func (c *SQLiteConn) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error) { list := make([]namedValue, len(args)) for i, nv := range args { @@ -33,14 +35,17 @@ func (c *SQLiteConn) ExecContext(ctx context.Context, query string, args []drive return c.exec(ctx, query, list) } +// PrepareContext implement ConnPrepareContext. func (c *SQLiteConn) PrepareContext(ctx context.Context, query string) (driver.Stmt, error) { return c.prepare(ctx, query) } +// BeginContext implement ConnBeginContext. func (c *SQLiteConn) BeginContext(ctx context.Context) (driver.Tx, error) { return c.begin(ctx) } +// QueryContext implement QueryerContext. func (s *SQLiteStmt) QueryContext(ctx context.Context, args []driver.NamedValue) (driver.Rows, error) { list := make([]namedValue, len(args)) for i, nv := range args { @@ -49,6 +54,7 @@ func (s *SQLiteStmt) QueryContext(ctx context.Context, args []driver.NamedValue) return s.query(ctx, list) } +// ExecContext implement ExecerContext. func (s *SQLiteStmt) ExecContext(ctx context.Context, args []driver.NamedValue) (driver.Result, error) { list := make([]namedValue, len(args)) for i, nv := range args { diff --git a/sqlite3_load_extension.go b/sqlite3_load_extension.go index e6e0801..b5bccb1 100644 --- a/sqlite3_load_extension.go +++ b/sqlite3_load_extension.go @@ -42,6 +42,7 @@ func (c *SQLiteConn) loadExtensions(extensions []string) error { return nil } +// LoadExtension load the sqlite3 extension. func (c *SQLiteConn) LoadExtension(lib string, entry string) error { rv := C.sqlite3_enable_load_extension(c.db, 1) if rv != C.SQLITE_OK { diff --git a/tracecallback_noimpl.go b/tracecallback_noimpl.go index c0a49e9..f270415 100644 --- a/tracecallback_noimpl.go +++ b/tracecallback_noimpl.go @@ -4,6 +4,7 @@ package sqlite3 import "errors" +// RegisterAggregator register the aggregator. func (c *SQLiteConn) RegisterAggregator(name string, impl interface{}, pure bool) error { return errors.New("This feature is not implemented") } -- cgit v1.2.3 From 997cab809454bae9b2af4cfaebc2ee6a7062a5c9 Mon Sep 17 00:00:00 2001 From: Yasuhiro Matsumoto Date: Mon, 20 Mar 2017 23:31:22 +0900 Subject: fix build --- backup.go | 4 ++-- error.go | 4 ++-- sqlite3.go | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'backup.go') diff --git a/backup.go b/backup.go index 5ab3a54..7f1eec9 100644 --- a/backup.go +++ b/backup.go @@ -48,7 +48,7 @@ func (b *SQLiteBackup) Step(p int) (bool, error) { if ret == C.SQLITE_DONE { return true, nil } else if ret != 0 && ret != C.SQLITE_LOCKED && ret != C.SQLITE_BUSY { - return false, Error{Code: ErrNo(ret)} + return false, &Error{Code: ErrNo(ret)} } return false, nil } @@ -79,7 +79,7 @@ func (b *SQLiteBackup) Close() error { runtime.SetFinalizer(b, nil) if ret != 0 { - return Error{Code: ErrNo(ret)} + return &Error{Code: ErrNo(ret)} } return nil } diff --git a/error.go b/error.go index 7d29b4b..be530e5 100644 --- a/error.go +++ b/error.go @@ -58,7 +58,7 @@ var ( // Error return error message from errno. func (err ErrNo) Error() string { - return Error{Code: err}.Error() + return (&Error{Code: err}).Error() } // Extend return extended errno. @@ -68,7 +68,7 @@ func (err ErrNo) Extend(by int) ErrNoExtended { // Error return error message that is extended code. func (err ErrNoExtended) Error() string { - return Error{Code: ErrNo(C.int(err) & ErrNoMask), ExtendedCode: err}.Error() + return (&Error{Code: ErrNo(C.int(err) & ErrNoMask), ExtendedCode: err}).Error() } // Error return error message. diff --git a/sqlite3.go b/sqlite3.go index 6230b29..0ae415f 100644 --- a/sqlite3.go +++ b/sqlite3.go @@ -404,7 +404,7 @@ func (c *SQLiteConn) lastError() *Error { if rv == C.SQLITE_OK { return nil } - return Error{ + return &Error{ Code: ErrNo(rv), ExtendedCode: ErrNoExtended(C.sqlite3_extended_errcode(c.db)), err: C.GoString(C.sqlite3_errmsg(c.db)), @@ -601,7 +601,7 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) { C.SQLITE_OPEN_CREATE, nil) if rv != 0 { - return nil, Error{Code: ErrNo(rv)} + return nil, &Error{Code: ErrNo(rv)} } if db == nil { return nil, errors.New("sqlite succeeded without returning a database") @@ -609,7 +609,7 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) { rv = C.sqlite3_busy_timeout(db, C.int(busyTimeout)) if rv != C.SQLITE_OK { - return nil, Error{Code: ErrNo(rv)} + return nil, &Error{Code: ErrNo(rv)} } conn := &SQLiteConn{db: db, loc: loc, txlock: txlock} -- cgit v1.2.3 From 866c3293d9a76aa491e56cc978d0d7fb0e63e121 Mon Sep 17 00:00:00 2001 From: Yasuhiro Matsumoto Date: Tue, 21 Mar 2017 09:14:48 +0900 Subject: fix breaking compatibility. revert cf4bd560f1588d96c502b4c3407fe1a10cef4a28 close #394 --- backup.go | 4 ++-- error.go | 7 +++---- error_test.go | 8 ++++---- sqlite3.go | 12 ++++++------ 4 files changed, 15 insertions(+), 16 deletions(-) (limited to 'backup.go') diff --git a/backup.go b/backup.go index 7f1eec9..5ab3a54 100644 --- a/backup.go +++ b/backup.go @@ -48,7 +48,7 @@ func (b *SQLiteBackup) Step(p int) (bool, error) { if ret == C.SQLITE_DONE { return true, nil } else if ret != 0 && ret != C.SQLITE_LOCKED && ret != C.SQLITE_BUSY { - return false, &Error{Code: ErrNo(ret)} + return false, Error{Code: ErrNo(ret)} } return false, nil } @@ -79,7 +79,7 @@ func (b *SQLiteBackup) Close() error { runtime.SetFinalizer(b, nil) if ret != 0 { - return &Error{Code: ErrNo(ret)} + return Error{Code: ErrNo(ret)} } return nil } diff --git a/error.go b/error.go index be530e5..49ab890 100644 --- a/error.go +++ b/error.go @@ -58,7 +58,7 @@ var ( // Error return error message from errno. func (err ErrNo) Error() string { - return (&Error{Code: err}).Error() + return Error{Code: err}.Error() } // Extend return extended errno. @@ -68,11 +68,10 @@ func (err ErrNo) Extend(by int) ErrNoExtended { // Error return error message that is extended code. func (err ErrNoExtended) Error() string { - return (&Error{Code: ErrNo(C.int(err) & ErrNoMask), ExtendedCode: err}).Error() + return Error{Code: ErrNo(C.int(err) & ErrNoMask), ExtendedCode: err}.Error() } -// Error return error message. -func (err *Error) Error() string { +func (err Error) Error() string { if err.err != "" { return err.err } diff --git a/error_test.go b/error_test.go index 339b57a..1ccbe5b 100644 --- a/error_test.go +++ b/error_test.go @@ -40,7 +40,7 @@ func TestCorruptDbErrors(t *testing.T) { _, err = db.Exec("drop table foo") } - sqliteErr := err.(*Error) + sqliteErr := err.(Error) if sqliteErr.Code != ErrNotADB { t.Error("wrong error code for corrupted DB") } @@ -110,7 +110,7 @@ func TestExtendedErrorCodes_ForeignKey(t *testing.T) { if err == nil { t.Error("No error!") } else { - sqliteErr := err.(*Error) + sqliteErr := err.(Error) if sqliteErr.Code != ErrConstraint { t.Errorf("Wrong basic error code: %d != %d", sqliteErr.Code, ErrConstraint) @@ -166,7 +166,7 @@ func TestExtendedErrorCodes_NotNull(t *testing.T) { if err == nil { t.Error("No error!") } else { - sqliteErr := err.(*Error) + sqliteErr := err.(Error) if sqliteErr.Code != ErrConstraint { t.Errorf("Wrong basic error code: %d != %d", sqliteErr.Code, ErrConstraint) @@ -222,7 +222,7 @@ func TestExtendedErrorCodes_Unique(t *testing.T) { if err == nil { t.Error("No error!") } else { - sqliteErr := err.(*Error) + sqliteErr := err.(Error) if sqliteErr.Code != ErrConstraint { t.Errorf("Wrong basic error code: %d != %d", sqliteErr.Code, ErrConstraint) diff --git a/sqlite3.go b/sqlite3.go index 2d504d9..3a9a4dd 100644 --- a/sqlite3.go +++ b/sqlite3.go @@ -298,7 +298,7 @@ func (ai *aggInfo) Done(ctx *C.sqlite3_context) { // Commit transaction. func (tx *SQLiteTx) Commit() error { _, err := tx.c.exec(context.Background(), "COMMIT", nil) - if err != nil && err.(*Error).Code == C.SQLITE_BUSY { + if err != nil && err.(Error).Code == C.SQLITE_BUSY { // sqlite3 will leave the transaction open in this scenario. // However, database/sql considers the transaction complete once we // return from Commit() - we must clean up to honour its semantics. @@ -399,12 +399,12 @@ func (c *SQLiteConn) AutoCommit() bool { return int(C.sqlite3_get_autocommit(c.db)) != 0 } -func (c *SQLiteConn) lastError() *Error { +func (c *SQLiteConn) lastError() error { rv := C.sqlite3_errcode(c.db) if rv == C.SQLITE_OK { return nil } - return &Error{ + return Error{ Code: ErrNo(rv), ExtendedCode: ErrNoExtended(C.sqlite3_extended_errcode(c.db)), err: C.GoString(C.sqlite3_errmsg(c.db)), @@ -519,7 +519,7 @@ func (c *SQLiteConn) begin(ctx context.Context) (driver.Tx, error) { return &SQLiteTx{c}, nil } -func errorString(err *Error) string { +func errorString(err Error) string { return C.GoString(C.sqlite3_errstr(C.int(err.Code))) } @@ -601,7 +601,7 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) { C.SQLITE_OPEN_CREATE, nil) if rv != 0 { - return nil, &Error{Code: ErrNo(rv)} + return nil, Error{Code: ErrNo(rv)} } if db == nil { return nil, errors.New("sqlite succeeded without returning a database") @@ -609,7 +609,7 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) { rv = C.sqlite3_busy_timeout(db, C.int(busyTimeout)) if rv != C.SQLITE_OK { - return nil, &Error{Code: ErrNo(rv)} + return nil, Error{Code: ErrNo(rv)} } conn := &SQLiteConn{db: db, loc: loc, txlock: txlock} -- cgit v1.2.3