Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions .github/workflows/go.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
go: ['1.22', '1.23']
go: ['1.23', '1.24']
fail-fast: false
env:
OS: ${{ matrix.os }}
Expand All @@ -46,8 +46,11 @@ jobs:
- name: 'Tags: libsqlite3'
run: go test -race -v -tags "libsqlite3"

- name: 'Tags: userauth deprecated'
run: make test_userauth_fails test_userauth_fails_libsqlite3

- name: 'Tags: full'
run: go test -race -v -tags "sqlite_allow_uri_authority sqlite_app_armor sqlite_column_metadata sqlite_foreign_keys sqlite_fts5 sqlite_icu sqlite_introspect sqlite_json sqlite_math_functions sqlite_os_trace sqlite_preupdate_hook sqlite_secure_delete sqlite_see sqlite_stat4 sqlite_trace sqlite_unlock_notify sqlite_userauth sqlite_vacuum_incr sqlite_vtable"
run: go test -race -v -tags "sqlite_allow_uri_authority sqlite_app_armor sqlite_column_metadata sqlite_foreign_keys sqlite_fts5 sqlite_icu sqlite_introspect sqlite_json sqlite_math_functions sqlite_os_trace sqlite_preupdate_hook sqlite_secure_delete sqlite_see sqlite_stat4 sqlite_trace sqlite_unlock_notify sqlite_vacuum_incr sqlite_vtable"

- name: 'Tags: vacuum'
run: go test -v -tags "sqlite_vacuum_full"
Expand Down
111 changes: 111 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# Benchmark options
NO_TESTS = ^$
# BENCHMARKS = ^BenchmarkIndex('\$'|Hard|Torture|Periodic(Unicode)?)
BENCH_SUITE = BenchmarkSuite
BENCH_QUERY = BenchmarkSuite/.*BenchmarkQuery$
BENCH_EXEC_STEP = BenchmarkSuite/.*BenchmarkExecStep$

# TODO: join these into a single list
ALL_TEST_TAGS := sqlite_allow_uri_authority
ALL_TEST_TAGS += sqlite_app_armor
ALL_TEST_TAGS += sqlite_column_metadata
ALL_TEST_TAGS += sqlite_foreign_keys
ALL_TEST_TAGS += sqlite_fts5
ALL_TEST_TAGS += sqlite_icu
ALL_TEST_TAGS += sqlite_introspect
ALL_TEST_TAGS += sqlite_json
ALL_TEST_TAGS += sqlite_math_functions
ALL_TEST_TAGS += sqlite_preupdate_hook
ALL_TEST_TAGS += sqlite_secure_delete
ALL_TEST_TAGS += sqlite_see
ALL_TEST_TAGS += sqlite_stat4
ALL_TEST_TAGS += sqlite_trace
ALL_TEST_TAGS += sqlite_unlock_notify
ALL_TEST_TAGS += sqlite_vacuum_incr
ALL_TEST_TAGS += sqlite_vtable

space := $(subst ,, )
comma := ,

ALL_TEST_TAGS_JOINED = $(subst $(space),$(comma),$(ALL_TEST_TAGS))

# GO_VERSION = $(shell go version | grep -oE 'go[1-9]\.[0-9]+(\.[0-9]+)?')
# ifeq (,$(shell echo $(GO_VERSION_NUMBER) | grep -E 'go1\.2[2-9]'))
# export GOEXPERIMENT=cgocheck2
# endif

.PHONY: all
all: build

.PHONY: build
build:
@go build -tags "libsqlite3"

.PHONY: test
test:
@GOEXPERIMENT=cgocheck2 go test -tags "libsqlite3" -v

.PHONY: test_all
test_all:
@GOEXPERIMENT=cgocheck2 go test -tags "$(ALL_TEST_TAGS_JOINED)" -v

# TODO: merge with the above target
.PHONY: test_all_libsqlite3
test_all_libsqlite3:
GOEXPERIMENT=cgocheck2 go test -tags "$(ALL_TEST_TAGS_JOINED),libsqlite3" -v

.PHONY: qtest
qtest:
@GOEXPERIMENT=cgocheck2 go test -tags "libsqlite3"

.PHONY: short
short:
@go test -tags "libsqlite3" -short

.PHONY: testrace
testrace:
@GOEXPERIMENT=cgocheck2 go test -tags "libsqlite3" -race

.PHONY: test_userauth_fails
test_userauth_fails:
@./scripts/test-userauth-fails.bash

.PHONY: test_userauth_fails_libsqlite3
test_userauth_fails_libsqlite3:
@./scripts/test-userauth-fails.bash -libsqlite3

.PHONY: testfull
testfull:
@./scripts/test-full.bash -v

.PHONY: testfull_race
testfull_race:
@./scripts/test-full.bash -v -race

.PHONY: bench
bench:
@go test -tags "libsqlite3 darwin" -run $(NO_TESTS) -bench $(BENCH_SUITE) -benchmem

.PHONY: bench_stmt_rows
bench_stmt_rows:
@go test -tags "libsqlite3 darwin" -run $(NO_TESTS) -bench $(BENCH_QUERY) -benchmem

.PHONY: bench_exec_step
bench_exec_step:
@go test -tags "libsqlite3 darwin" -run $(NO_TESTS) -bench $(BENCH_EXEC_STEP) -benchmem

.PHONY: bench_mem
bench_mem:
@go test -tags "libsqlite3 darwin" -run $(NO_TESTS) \
-bench $(BENCH_SUITE) \
-benchmem -memprofilerate 1 -memprofile mem.out -benchtime 5s

.PHONY: bench_cpu
bench_cpu:
@go test -tags "libsqlite3 darwin" -run $(NO_TESTS) \
-bench $(BENCH_SUITE) \
-cpuprofile cpu.out -benchtime 5s

.PHONY: tags
tags:
@\grep -ohP '(?<=//go:build )\w+(\s+\w+)?' *.go | sort -u
15 changes: 14 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -468,10 +468,21 @@ For example the TDM-GCC Toolchain can be found [here](https://jmeubank.github.io

# User Authentication

This package supports the SQLite User Authentication module.
### ***This is deprecated***

~~This package supports the SQLite User Authentication module.~~

User authentication deprecated as of [#28](https://github.com/charlievieth/go-sqlite3/pull/28)
and building with the `sqlite_userauth` tag will cause [`Open()`](https://pkg.go.dev/github.com/charlievieth/go-sqlite3#SQLiteDriver.Open)
to fail.

<details>
<summary>Deprecated User Authentication</summary>

## Compile

### WARN: THIS IS DEPRECATED

To use the User authentication module, the package has to be compiled with the tag `sqlite_userauth`. See [Features](#features).

## Usage
Expand Down Expand Up @@ -577,6 +588,8 @@ The following functions are available for User authentication from the `*SQLiteC

When using attached databases, SQLite will use the authentication from the `main` database for the attached database(s).

</details>

# Extensions

If you want your own extension to be listed here, or you want to add a reference to an extension; please submit an Issue for this.
Expand Down
10 changes: 8 additions & 2 deletions error_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,10 @@ func TestCorruptDbErrors(t *testing.T) {
_, err = db.Exec("drop table foo")
}

sqliteErr := err.(Error)
sqliteErr, ok := err.(Error)
if !ok {
t.Fatalf("Not a sqlite3.Error: %#v", err)
}
if sqliteErr.Code != ErrNotADB {
t.Error("wrong error code for corrupted DB")
}
Expand Down Expand Up @@ -113,7 +116,10 @@ func TestExtendedErrorCodes_ForeignKey(t *testing.T) {
if err == nil {
t.Error("No error!")
} else {
sqliteErr := err.(Error)
sqliteErr, ok := err.(Error)
if !ok {
t.Fatalf("Not a sqlite3.Error: %#v", err)
}
if sqliteErr.Code != ErrConstraint {
t.Errorf("Wrong basic error code: %d != %d",
sqliteErr.Code, ErrConstraint)
Expand Down
47 changes: 47 additions & 0 deletions scripts/test-userauth-fails.bash
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#!/usr/bin/env bash

# Test that the userauth tests fail, but don't panic.
# Pass "-libsqlite3" as an argument to the script to
# run the tests with the "libsqlite3" build tag.

set -euo pipefail

OUT="$(mktemp -t 'go-sqlite3.XXXXXX')"
trap 'rm "${OUT}"' EXIT

function test_sqlite_userauth() {
local tags='sqlite_userauth'
while (( $# > 0 )); do
if [[ -n $1 ]]; then
tags+=",$1"
fi
shift
done

echo "Running: \`go test -tags=${tags}\`"
if go test -tags="${tags}" &> "${OUT}"; then
cat "${OUT}"
echo >&2 ''
echo >&2 'FAIL: tests passed: expected them to fail'
return 2
fi

if \grep -qF 'panic:' "${OUT}"; then
cat "${OUT}"
echo >&2 ''
echo >&2 'FAIL: test panicked'
return 2
fi

echo "PASS"
}

function main() {
local tags=''
if [[ ${1:-} == '-libsqlite3' ]]; then
tags='libsqlite3'
fi
test_sqlite_userauth "${tags}"
}

main "$@"
66 changes: 7 additions & 59 deletions sqlite3.go
Original file line number Diff line number Diff line change
Expand Up @@ -1906,64 +1906,10 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
}

// Preform Authentication
if err := conn.Authenticate(authUser, authPass); err != nil {
return err
}

// Register: authenticate
// Authenticate will perform an authentication of the provided username
// and password against the database.
//
// If a database contains the SQLITE_USER table, then the
// call to Authenticate must be invoked with an
// appropriate username and password prior to enable read and write
//access to the database.
//
// Return SQLITE_OK on success or SQLITE_ERROR if the username/password
// combination is incorrect or unknown.
//
// If the SQLITE_USER table is not present in the database file, then
// this interface is a harmless no-op returnning SQLITE_OK.
if err := conn.registerAuthFunc("authenticate", conn.authenticate, true); err != nil {
return err
}
//
// Register: auth_user_add
// auth_user_add can be used (by an admin user only)
// to create a new user. When called on a no-authentication-required
// database, this routine converts the database into an authentication-
// required database, automatically makes the added user an
// administrator, and logs in the current connection as that user.
// The AuthUserAdd only works for the "main" database, not
// for any ATTACH-ed databases. Any call to AuthUserAdd by a
// non-admin user results in an error.
if err := conn.registerAuthFunc("auth_user_add", conn.authUserAdd, true); err != nil {
return err
}
//
// Register: auth_user_change
// auth_user_change can be used to change a users
// login credentials or admin privilege. Any user can change their own
// login credentials. Only an admin user can change another users login
// credentials or admin privilege setting. No user may change their own
// admin privilege setting.
if err := conn.registerAuthFunc("auth_user_change", conn.authUserChange, true); err != nil {
return err
}
//
// Register: auth_user_delete
// auth_user_delete can be used (by an admin user only)
// to delete a user. The currently logged-in user cannot be deleted,
// which guarantees that there is always an admin user and hence that
// the database cannot be converted into a no-authentication-required
// database.
if err := conn.registerAuthFunc("auth_user_delete", conn.authUserDelete, true); err != nil {
return err
}

// Register: auth_enabled
// auth_enabled can be used to check if user authentication is enabled
if err := conn.registerAuthFunc("auth_enabled", conn.authEnabled, true); err != nil {
// NB: This will always fail if built with the "sqlite_userauth"
// build tag since user authentication is now deprecated.
if err := conn.Authenticate(authUser, authPass); err != nil {
return err
}

Expand All @@ -1980,6 +1926,9 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
}

// Check if user wants to activate User Authentication
//
// NB: This will always fail if built with the "sqlite_userauth"
// build tag since user authentication is now deprecated.
if authCreate {
// Before going any further, we need to check that the user
// has provided an username and password within the DSN.
Expand All @@ -1992,8 +1941,7 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
}

// Check if User Authentication is Enabled
authExists := conn.AuthEnabled()
if !authExists {
if !conn.AuthEnabled() {
if err := conn.AuthUserAdd(authUser, authPass, true); err != nil {
return err
}
Expand Down
Loading