Repository: mattn/go-sqlite3
Pull request #1084 (2022-09-01 22:25:52)

remove unuseful ldflags for windows platform.
Golang's linker add mingwex and mingw32 automatically,so we don't need add them manually.


Patch:
diff --git a/.github/workflows/go.yaml b/.github/workflows/go.yaml
index ec8b30a..2030c57 100644
--- a/.github/workflows/go.yaml
+++ b/.github/workflows/go.yaml
@@ -44,7 +44,7 @@ jobs:
         run: go-acc . -- -race -v -tags "libsqlite3"
 
       - name: 'Tags: full'
-        run: go-acc . -- -race -v -tags "sqlite_allow_uri_authority sqlite_app_armor sqlite_foreign_keys sqlite_fts5 sqlite_icu sqlite_introspect sqlite_json sqlite_os_trace sqlite_preupdate_hook sqlite_secure_delete sqlite_see sqlite_stat4 sqlite_trace sqlite_userauth sqlite_vacuum_incr sqlite_vtable sqlite_unlock_notify sqlite_column_metadata"
+        run: go-acc . -- -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"
 
       - name: 'Tags: vacuum'
         run: go-acc . -- -race -v -tags "sqlite_vacuum_full"
@@ -99,7 +99,7 @@ jobs:
       - name: 'Tags: full'
         run: |
           echo 'skip this test'
-          echo go build -race -v -tags "sqlite_allow_uri_authority sqlite_app_armor sqlite_foreign_keys sqlite_fts5 sqlite_icu sqlite_introspect sqlite_json sqlite_preupdate_hook sqlite_secure_delete sqlite_see sqlite_stat4 sqlite_trace sqlite_userauth sqlite_vacuum_incr sqlite_vtable sqlite_unlock_notify"
+          echo go build -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_preupdate_hook sqlite_secure_delete sqlite_see sqlite_stat4 sqlite_trace sqlite_unlock_notify sqlite_userauth sqlite_vacuum_incr sqlite_vtable"
         shell: msys2 {0}
 
       - name: 'Tags: vacuum'
diff --git a/README.md b/README.md
index 518cd0b..913bf6a 100644
--- a/README.md
+++ b/README.md
@@ -172,6 +172,7 @@ go build --tags "icu json1 fts5 secure_delete"
 |  International Components for Unicode | sqlite_icu | This option causes the International Components for Unicode or "ICU" extension to SQLite to be added to the build |
 | Introspect PRAGMAS | sqlite_introspect | This option adds some extra PRAGMA statements. <ul><li>PRAGMA function_list</li><li>PRAGMA module_list</li><li>PRAGMA pragma_list</li></ul> |
 | JSON SQL Functions | sqlite_json | When this option is defined in the amalgamation, the JSON SQL functions are added to the build automatically |
+| Math Functions | sqlite_math_functions | This compile-time option enables built-in scalar math functions. For more information see [Built-In Mathematical SQL Functions](https://www.sqlite.org/lang_mathfunc.html) |
 | OS Trace | sqlite_os_trace | This option enables OSTRACE() debug logging. This can be verbose and should not be used in production. |
 | Pre Update Hook | sqlite_preupdate_hook | Registers a callback function that is invoked prior to each INSERT, UPDATE, and DELETE operation on a database table. |
 | Secure Delete | sqlite_secure_delete | This compile-time option changes the default setting of the secure_delete pragma.<br><br>When this option is not used, secure_delete defaults to off. When this option is present, secure_delete defaults to on.<br><br>The secure_delete setting causes deleted content to be overwritten with zeros. There is a small performance penalty since additional I/O must occur.<br><br>On the other hand, secure_delete can prevent fragments of sensitive information from lingering in unused parts of the database file after it has been deleted. See the documentation on the secure_delete pragma for additional information |
@@ -181,7 +182,7 @@ go build --tags "icu json1 fts5 secure_delete"
 
 # Compilation
 
-This package requires the `CGO_ENABLED=1` ennvironment variable if not set by default, and the presence of the `gcc` compiler.
+This package requires the `CGO_ENABLED=1` environment variable if not set by default, and the presence of the `gcc` compiler.
 
 If you need to add additional CFLAGS or LDFLAGS to the build command, and do not want to modify this package, then this can be achieved by using the `CGO_CFLAGS` and `CGO_LDFLAGS` environment variables.
 
diff --git a/_example/limit/limit.go b/_example/limit/limit.go
index 1f33634..bcba819 100644
--- a/_example/limit/limit.go
+++ b/_example/limit/limit.go
@@ -17,7 +17,7 @@ func createBulkInsertQuery(n int, start int) (query string, args []interface{})
 	for i := 0; i < n; i++ {
 		values[i] = "(?, ?)"
 		args[pos] = start + i
-		args[pos+1] = fmt.Sprintf("こんにちわ世界%03d", i)
+		args[pos+1] = fmt.Sprintf("こんにちは世界%03d", i)
 		pos += 2
 	}
 	query = fmt.Sprintf(
diff --git a/_example/simple/Dockerfile b/_example/simple/Dockerfile
index 58f5ffd..c19f6e6 100644
--- a/_example/simple/Dockerfile
+++ b/_example/simple/Dockerfile
@@ -33,7 +33,7 @@ RUN \
 RUN \
     # Smoke test
     set -o pipefail; \
-    /go/bin/simple | grep 99\ こんにちわ世界099
+    /go/bin/simple | grep 99\ こんにちは世界099
 
 # -----------------------------------------------------------------------------
 #  Main Stage
diff --git a/_example/simple/simple.go b/_example/simple/simple.go
index 9d90773..0c34791 100644
--- a/_example/simple/simple.go
+++ b/_example/simple/simple.go
@@ -37,7 +37,7 @@ func main() {
 	}
 	defer stmt.Close()
 	for i := 0; i < 100; i++ {
-		_, err = stmt.Exec(i, fmt.Sprintf("こんにちわ世界%03d", i))
+		_, err = stmt.Exec(i, fmt.Sprintf("こんにちは世界%03d", i))
 		if err != nil {
 			log.Fatal(err)
 		}
diff --git a/sqlite3.go b/sqlite3.go
index e037857..9c0f4d8 100644
--- a/sqlite3.go
+++ b/sqlite3.go
@@ -494,10 +494,12 @@ 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 {
-		// sqlite3 will leave the transaction open in this scenario.
+	if err != nil {
+		// sqlite3 may 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.
+		// We don't know if the ROLLBACK is strictly necessary, but according
+		// to sqlite's docs, there is no harm in calling ROLLBACK unnecessarily.
 		tx.c.exec(context.Background(), "ROLLBACK", nil)
 	}
 	return err
diff --git a/sqlite3_opt_math_functions.go b/sqlite3_opt_math_functions.go
new file mode 100644
index 0000000..7cd68d3
--- /dev/null
+++ b/sqlite3_opt_math_functions.go
@@ -0,0 +1,14 @@
+// Copyright (C) 2022 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_math_functions
+
+package sqlite3
+
+/*
+#cgo CFLAGS: -DSQLITE_ENABLE_MATH_FUNCTIONS
+#cgo LDFLAGS: -lm
+*/
+import "C"
diff --git a/sqlite3_windows.go b/sqlite3_windows.go
index 9df1961..81aa2ab 100644
--- a/sqlite3_windows.go
+++ b/sqlite3_windows.go
@@ -12,7 +12,6 @@ package sqlite3
 #cgo CFLAGS: -fno-stack-check
 #cgo CFLAGS: -fno-stack-protector
 #cgo CFLAGS: -mno-stack-arg-probe
-#cgo LDFLAGS: -lmingwex -lmingw32
 #cgo windows,386 CFLAGS: -D_USE_32BIT_TIME_T
 */
 import "C"


Test patch:
diff --git a/sqlite3_opt_math_functions_test.go b/sqlite3_opt_math_functions_test.go
new file mode 100644
index 0000000..6ff076b
--- /dev/null
+++ b/sqlite3_opt_math_functions_test.go
@@ -0,0 +1,29 @@
+// +build sqlite_math_functions
+
+package sqlite3
+
+import (
+	"database/sql"
+	"testing"
+)
+
+func TestMathFunctions(t *testing.T) {
+	db, err := sql.Open("sqlite3", ":memory:")
+	if err != nil {
+		t.Fatal("Failed to open database:", err)
+	}
+	defer db.Close()
+
+	queries := []string{
+		`SELECT acos(1)`,
+		`SELECT log(10, 100)`,
+		`SELECT power(2, 2)`,
+	}
+
+	for _, query := range queries {
+		var result float64
+		if err := db.QueryRow(query).Scan(&result); err != nil {
+			t.Errorf("invoking math function query %q: %v", query, err)
+		}
+	}
+}
diff --git a/sqlite3_test.go b/sqlite3_test.go
index 33d03fd..326361e 100644
--- a/sqlite3_test.go
+++ b/sqlite3_test.go
@@ -248,6 +248,43 @@ func TestForeignKeys(t *testing.T) {
 	}
 }
 
+func TestDeferredForeignKey(t *testing.T) {
+	fname := TempFilename(t)
+	uri := "file:" + fname + "?_foreign_keys=1"
+	db, err := sql.Open("sqlite3", uri)
+	if err != nil {
+		os.Remove(fname)
+		t.Errorf("sql.Open(\"sqlite3\", %q): %v", uri, err)
+	}
+	_, err = db.Exec("CREATE TABLE bar (id INTEGER PRIMARY KEY)")
+	if err != nil {
+		t.Errorf("failed creating tables: %v", err)
+	}
+	_, err = db.Exec("CREATE TABLE foo (bar_id INTEGER, FOREIGN KEY(bar_id) REFERENCES bar(id) DEFERRABLE INITIALLY DEFERRED)")
+	if err != nil {
+		t.Errorf("failed creating tables: %v", err)
+	}
+	tx, err := db.Begin()
+	if err != nil {
+		t.Errorf("Failed to begin transaction: %v", err)
+	}
+	_, err = tx.Exec("INSERT INTO foo (bar_id) VALUES (123)")
+	if err != nil {
+		t.Errorf("Failed to insert row: %v", err)
+	}
+	err = tx.Commit()
+	if err == nil {
+		t.Errorf("Expected an error: %v", err)
+	}
+	_, err = db.Begin()
+	if err != nil {
+		t.Errorf("Failed to begin transaction: %v", err)
+	}
+
+	db.Close()
+	os.Remove(fname)
+}
+
 func TestRecursiveTriggers(t *testing.T) {
 	cases := map[string]bool{
 		"?_recursive_triggers=1": true,