diff options
author | EuAndreh <eu@euandre.org> | 2024-08-14 17:31:36 -0300 |
---|---|---|
committer | EuAndreh <eu@euandre.org> | 2024-08-14 17:31:36 -0300 |
commit | 0b8d97f96dd4db0e50a1cb68a0740a55017c469b (patch) | |
tree | aeb75b31cec46c6de5a8e28aceabeb10143d98f2 /doc/examples | |
parent | Remove most files from _example/ (diff) | |
download | golite-0b8d97f96dd4db0e50a1cb68a0740a55017c469b.tar.gz golite-0b8d97f96dd4db0e50a1cb68a0740a55017c469b.tar.xz |
git mv _example doc/examples/
Diffstat (limited to 'doc/examples')
-rw-r--r-- | doc/examples/fuzz/fuzz_openexec.go | 30 | ||||
-rw-r--r-- | doc/examples/json/json.go | 81 | ||||
-rw-r--r-- | doc/examples/limit/limit.go | 113 | ||||
-rw-r--r-- | doc/examples/mod_regexp/Makefile | 27 | ||||
-rw-r--r-- | doc/examples/mod_regexp/extension.go | 43 | ||||
-rw-r--r-- | doc/examples/mod_regexp/sqlite3_mod_regexp.c | 35 |
6 files changed, 329 insertions, 0 deletions
diff --git a/doc/examples/fuzz/fuzz_openexec.go b/doc/examples/fuzz/fuzz_openexec.go new file mode 100644 index 0000000..5326044 --- /dev/null +++ b/doc/examples/fuzz/fuzz_openexec.go @@ -0,0 +1,30 @@ +package sqlite3_fuzz + +import ( + "bytes" + "database/sql" + "io/ioutil" + + _ "github.com/mattn/go-sqlite3" +) + +func FuzzOpenExec(data []byte) int { + sep := bytes.IndexByte(data, 0) + if sep <= 0 { + return 0 + } + err := ioutil.WriteFile("/tmp/fuzz.db", data[sep+1:], 0644) + if err != nil { + return 0 + } + db, err := sql.Open("sqlite3", "/tmp/fuzz.db") + if err != nil { + return 0 + } + defer db.Close() + _, err = db.Exec(string(data[:sep-1])) + if err != nil { + return 0 + } + return 1 +} diff --git a/doc/examples/json/json.go b/doc/examples/json/json.go new file mode 100644 index 0000000..181934b --- /dev/null +++ b/doc/examples/json/json.go @@ -0,0 +1,81 @@ +package main + +import ( + "database/sql" + "database/sql/driver" + "encoding/json" + "fmt" + _ "github.com/mattn/go-sqlite3" + "log" + "os" +) + +type Tag struct { + Name string `json:"name"` + Country string `json:"country"` +} + +func (t *Tag) Scan(value interface{}) error { + return json.Unmarshal([]byte(value.(string)), t) +} + +func (t *Tag) Value() (driver.Value, error) { + b, err := json.Marshal(t) + return string(b), err +} + +func main() { + os.Remove("./foo.db") + + db, err := sql.Open("sqlite3", "./foo.db") + if err != nil { + log.Fatal(err) + } + defer db.Close() + + _, err = db.Exec(`create table foo (tag jsonb)`) + if err != nil { + log.Fatal(err) + } + + stmt, err := db.Prepare("insert into foo(tag) values(?)") + if err != nil { + log.Fatal(err) + } + defer stmt.Close() + _, err = stmt.Exec(`{"name": "mattn", "country": "japan"}`) + if err != nil { + log.Fatal(err) + } + _, err = stmt.Exec(`{"name": "michael", "country": "usa"}`) + if err != nil { + log.Fatal(err) + } + + var country string + err = db.QueryRow("select tag->>'country' from foo where tag->>'name' = 'mattn'").Scan(&country) + if err != nil { + log.Fatal(err) + } + fmt.Println(country) + + var tag Tag + err = db.QueryRow("select tag from foo where tag->>'name' = 'mattn'").Scan(&tag) + if err != nil { + log.Fatal(err) + } + + fmt.Println(tag.Name) + + tag.Country = "日本" + _, err = db.Exec(`update foo set tag = ? where tag->>'name' == 'mattn'`, &tag) + if err != nil { + log.Fatal(err) + } + + err = db.QueryRow("select tag->>'country' from foo where tag->>'name' = 'mattn'").Scan(&country) + if err != nil { + log.Fatal(err) + } + fmt.Println(country) +} diff --git a/doc/examples/limit/limit.go b/doc/examples/limit/limit.go new file mode 100644 index 0000000..c1adfe8 --- /dev/null +++ b/doc/examples/limit/limit.go @@ -0,0 +1,113 @@ +package main + +import ( + "database/sql" + "fmt" + "log" + "os" + "strings" + + "github.com/mattn/go-sqlite3" +) + +func createBulkInsertQuery(n int, start int) (query string, args []any) { + values := make([]string, n) + args = make([]any, n*2) + pos := 0 + for i := 0; i < n; i++ { + values[i] = "(?, ?)" + args[pos] = start + i + args[pos+1] = fmt.Sprintf("こんにちは世界%03d", i) + pos += 2 + } + query = fmt.Sprintf( + "insert into foo(id, name) values %s", + strings.Join(values, ", "), + ) + return +} + +func bulkInsert(db *sql.DB, query string, args []any) (err error) { + stmt, err := db.Prepare(query) + if err != nil { + return + } + + _, err = stmt.Exec(args...) + if err != nil { + return + } + + return +} + +func main() { + var sqlite3conn *sqlite3.SQLiteConn + sql.Register("sqlite3_with_limit", &sqlite3.SQLiteDriver{ + ConnectHook: func(conn *sqlite3.SQLiteConn) error { + sqlite3conn = conn + return nil + }, + }) + + os.Remove("./foo.db") + db, err := sql.Open("sqlite3_with_limit", "./foo.db") + if err != nil { + log.Fatal(err) + } + defer db.Close() + + sqlStmt := ` + create table foo (id integer not null primary key, name text); + delete from foo; + ` + _, err = db.Exec(sqlStmt) + if err != nil { + log.Printf("%q: %s\n", err, sqlStmt) + return + } + + if sqlite3conn == nil { + log.Fatal("not set sqlite3 connection") + } + + limitVariableNumber := sqlite3conn.GetLimit(sqlite3.SQLITE_LIMIT_VARIABLE_NUMBER) + log.Printf("default SQLITE_LIMIT_VARIABLE_NUMBER: %d", limitVariableNumber) + + num := 400 + query, args := createBulkInsertQuery(num, 0) + err = bulkInsert(db, query, args) + if err != nil { + log.Fatal(err) + } + + smallLimitVariableNumber := 100 + sqlite3conn.SetLimit(sqlite3.SQLITE_LIMIT_VARIABLE_NUMBER, smallLimitVariableNumber) + + limitVariableNumber = sqlite3conn.GetLimit(sqlite3.SQLITE_LIMIT_VARIABLE_NUMBER) + log.Printf("updated SQLITE_LIMIT_VARIABLE_NUMBER: %d", limitVariableNumber) + + query, args = createBulkInsertQuery(num, num) + err = bulkInsert(db, query, args) + if err != nil { + if err != nil { + log.Printf("expect failed since SQLITE_LIMIT_VARIABLE_NUMBER is too small: %v", err) + } + } + + bigLimitVariableNumber := 999999 + sqlite3conn.SetLimit(sqlite3.SQLITE_LIMIT_VARIABLE_NUMBER, bigLimitVariableNumber) + limitVariableNumber = sqlite3conn.GetLimit(sqlite3.SQLITE_LIMIT_VARIABLE_NUMBER) + log.Printf("set SQLITE_LIMIT_VARIABLE_NUMBER: %d", bigLimitVariableNumber) + log.Printf("updated SQLITE_LIMIT_VARIABLE_NUMBER: %d", limitVariableNumber) + + query, args = createBulkInsertQuery(500, num+num) + err = bulkInsert(db, query, args) + if err != nil { + if err != nil { + log.Fatal(err) + } + } + + log.Println("no error if SQLITE_LIMIT_VARIABLE_NUMBER > 999") +} diff --git a/doc/examples/mod_regexp/Makefile b/doc/examples/mod_regexp/Makefile new file mode 100644 index 0000000..1ef69a6 --- /dev/null +++ b/doc/examples/mod_regexp/Makefile @@ -0,0 +1,27 @@ +ifeq ($(OS),Windows_NT) +EXE=extension.exe +LIB_EXT=dll +RM=cmd /c del +LDFLAG= +else +EXE=extension +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) $(LIB) + +$(EXE) : extension.go + go build $< + +$(LIB) : sqlite3_mod_regexp.c + gcc $(LDFLAG) -shared -o $@ $< -lsqlite3 -lpcre + +clean : + @-$(RM) $(EXE) $(LIB) diff --git a/doc/examples/mod_regexp/extension.go b/doc/examples/mod_regexp/extension.go new file mode 100644 index 0000000..61ceb55 --- /dev/null +++ b/doc/examples/mod_regexp/extension.go @@ -0,0 +1,43 @@ +package main + +import ( + "database/sql" + "fmt" + "github.com/mattn/go-sqlite3" + "log" +) + +func main() { + sql.Register("sqlite3_with_extensions", + &sqlite3.SQLiteDriver{ + Extensions: []string{ + "sqlite3_mod_regexp", + }, + }) + + db, err := sql.Open("sqlite3_with_extensions", ":memory:") + if err != nil { + log.Fatal(err) + } + defer db.Close() + + // Force db to make a new connection in pool + // by putting the original in a transaction + tx, err := db.Begin() + if err != nil { + log.Fatal(err) + } + defer tx.Commit() + + // New connection works (hopefully!) + rows, err := db.Query("select 'hello world' where 'hello world' regexp '^hello.*d$'") + if err != nil { + log.Fatal(err) + } + defer rows.Close() + for rows.Next() { + var helloworld string + rows.Scan(&helloworld) + fmt.Println(helloworld) + } +} diff --git a/doc/examples/mod_regexp/sqlite3_mod_regexp.c b/doc/examples/mod_regexp/sqlite3_mod_regexp.c new file mode 100644 index 0000000..d3ad149 --- /dev/null +++ b/doc/examples/mod_regexp/sqlite3_mod_regexp.c @@ -0,0 +1,35 @@ +#include <pcre.h> +#include <string.h> +#include <stdio.h> +#include <sqlite3ext.h> + +SQLITE_EXTENSION_INIT1 +static void regexp_func(sqlite3_context *context, int argc, sqlite3_value **argv) { + if (argc >= 2) { + const char *target = (const char *)sqlite3_value_text(argv[1]); + const char *pattern = (const char *)sqlite3_value_text(argv[0]); + const char* errstr = NULL; + int erroff = 0; + int vec[500]; + int n, rc; + pcre* re = pcre_compile(pattern, 0, &errstr, &erroff, NULL); + if (!re) { + sqlite3_result_error(context, errstr, 0); + return; + } + rc = pcre_exec(re, NULL, target, strlen(target), 0, 0, vec, 500); + if (rc <= 0) { + sqlite3_result_int(context, 0); + return; + } + sqlite3_result_int(context, 1); + } +} + +#ifdef _WIN32 +__declspec(dllexport) +#endif +int sqlite3_extension_init(sqlite3 *db, char **errmsg, const sqlite3_api_routines *api) { + SQLITE_EXTENSION_INIT2(api); + return sqlite3_create_function(db, "regexp", 2, SQLITE_UTF8, (void*)db, regexp_func, NULL, NULL); +} |