aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/functional/extension.go79
-rw-r--r--tests/functional/json.go96
-rw-r--r--tests/functional/libbuild.go (renamed from tests/libbuild.go)0
-rw-r--r--tests/functional/limit.go102
-rw-r--r--tests/functional/streq.c36
5 files changed, 313 insertions, 0 deletions
diff --git a/tests/functional/extension.go b/tests/functional/extension.go
new file mode 100644
index 0000000..81c4494
--- /dev/null
+++ b/tests/functional/extension.go
@@ -0,0 +1,79 @@
+package main
+
+import (
+ "database/sql"
+ "fmt"
+ "log"
+ "os"
+ "reflect"
+
+ "golite"
+)
+
+
+
+func fatalif(err error) {
+ if err != nil {
+ log.Fatal(err)
+ }
+}
+
+func eq(given any, expected any) {
+ if !reflect.DeepEqual(given, expected) {
+ fmt.Fprintf(os.Stderr, "given != expected\n")
+ fmt.Fprintf(os.Stderr, "given: %#v\n", given)
+ fmt.Fprintf(os.Stderr, "expected: %#v\n", expected)
+ }
+}
+
+
+
+func main() {
+ driver := golite.SQLiteDriver{
+ Extensions: []string{
+ "streq",
+ },
+ }
+ sql.Register("sqlite3-streq", &driver)
+
+ db, err := sql.Open("sqlite3-streq", ":memory:")
+ fatalif(err)
+ defer db.Close()
+
+ rows, err := db.Query(`
+ SELECT str, n FROM (
+ SELECT 'hello' as str, 1 as n
+ UNION
+ SELECT 'not' as str, 2 as n
+ UNION
+ SELECT 'hello' as str, 3 as n
+ ) WHERE streq(str, 'hello');
+ `)
+ fatalif(err)
+ defer rows.Close()
+
+ type pairT struct{
+ str string
+ id int
+ }
+ var pairs []pairT
+ for rows.Next() {
+ var pair pairT
+ err := rows.Scan(&pair.str, &pair.id)
+ fatalif(err)
+ pairs = append(pairs, pair)
+ }
+ fatalif(rows.Err())
+
+ expected := []pairT{
+ pairT{
+ str: "hello",
+ id: 1,
+ },
+ pairT{
+ str: "hello",
+ id: 3,
+ },
+ }
+ eq(pairs, expected)
+}
diff --git a/tests/functional/json.go b/tests/functional/json.go
new file mode 100644
index 0000000..54954f7
--- /dev/null
+++ b/tests/functional/json.go
@@ -0,0 +1,96 @@
+package main
+
+import (
+ "database/sql"
+ "database/sql/driver"
+ "encoding/json"
+ "errors"
+ "log"
+ "os"
+
+ _ "golite"
+)
+
+type Tag struct {
+ Name string `json:"name"`
+ Place string `json:"place"`
+}
+
+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("json.db")
+ defer os.Remove("json.db")
+
+ db, err := sql.Open("sqlite3", "json.db")
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer db.Close()
+
+ _, err = db.Exec(`create table myjsontable (tag jsonb)`)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ stmt, err := db.Prepare("insert into myjsontable(tag) values(?)")
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer stmt.Close()
+
+ _, err = stmt.Exec(`{"name": "name1", "place": "right-here"}`)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ _, err = stmt.Exec(`{"name": "michael", "place": "usa"}`)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ var place string
+ err = db.QueryRow("select tag->>'place' from myjsontable where tag->>'name' = 'name1'").Scan(&place)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ if place != "right-here" {
+ log.Fatal(errors.New("expected right-here, got: " + place))
+ }
+
+ var tag Tag
+ err = db.QueryRow("select tag from myjsontable where tag->>'name' = 'name1'").Scan(&tag)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ if tag.Name != "name1" {
+ log.Fatal(errors.New("expected name1, got: " + tag.Name))
+ }
+ if tag.Place != "right-here" {
+ log.Fatal(errors.New("expected right-here, got: " + tag.Place))
+ }
+
+ tag.Place = "日本"
+ _, err = db.Exec(`update myjsontable set tag = ? where tag->>'name' == 'name1'`, &tag)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ err = db.QueryRow("select tag->>'place' from myjsontable where tag->>'name' = 'name1'").Scan(&place)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ if place != "日本" {
+ log.Fatal(errors.New("expected 日本, got: " + place))
+ }
+}
diff --git a/tests/libbuild.go b/tests/functional/libbuild.go
index 3de29ae..3de29ae 100644
--- a/tests/libbuild.go
+++ b/tests/functional/libbuild.go
diff --git a/tests/functional/limit.go b/tests/functional/limit.go
new file mode 100644
index 0000000..8c65a25
--- /dev/null
+++ b/tests/functional/limit.go
@@ -0,0 +1,102 @@
+package main
+
+import (
+ "database/sql"
+ "fmt"
+ "log"
+ "os"
+ "strings"
+
+ "golite"
+)
+
+func createBulkInsertQuery(n int, start int) (string, []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 mylimittable(id, name) values %s",
+ strings.Join(values, ", "),
+ )
+ return query, args
+}
+
+func bulkInsert(db *sql.DB, query string, args []any) error {
+ stmt, err := db.Prepare(query)
+ if err != nil {
+ return err
+ }
+
+ _, err = stmt.Exec(args...)
+ return err
+}
+
+func main() {
+ const (
+ num = 400
+ smallLimit = 100
+ bigLimit = 999999
+ )
+
+ const SQL = `
+ create table mylimittable (id integer not null primary key, name text);
+ delete from mylimittable;
+ `
+
+ var conn *golite.SQLiteConn
+ sql.Register("sqlite3_with_limit", &golite.SQLiteDriver{
+ ConnectHook: func(c *golite.SQLiteConn) error {
+ conn = c
+ return nil
+ },
+ })
+
+ os.Remove("limit.db")
+ defer os.Remove("limit.db")
+ db, err := sql.Open("sqlite3_with_limit", "limit.db")
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer db.Close()
+
+ _, err = db.Exec(SQL)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ if conn == nil {
+ log.Fatal("not set sqlite3 connection")
+ }
+
+ {
+ query, args := createBulkInsertQuery(num, 0)
+ err := bulkInsert(db, query, args)
+ if err != nil {
+ log.Fatal(err)
+ }
+ }
+
+ conn.SetLimit(golite.SQLITE_LIMIT_VARIABLE_NUMBER, smallLimit)
+ {
+ query, args := createBulkInsertQuery(num, num)
+ err := bulkInsert(db, query, args)
+ if err == nil {
+ log.Fatal("expected failure didn't happen")
+ }
+ }
+
+ conn.SetLimit(golite.SQLITE_LIMIT_VARIABLE_NUMBER, bigLimit)
+ {
+ query, args := createBulkInsertQuery(500, num+num)
+ err := bulkInsert(db, query, args)
+ if err != nil {
+ log.Fatal(err)
+ }
+ }
+}
diff --git a/tests/functional/streq.c b/tests/functional/streq.c
new file mode 100644
index 0000000..bbf3763
--- /dev/null
+++ b/tests/functional/streq.c
@@ -0,0 +1,36 @@
+#include <assert.h>
+#include <stdbool.h>
+#include <string.h>
+#include <sqlite3ext.h>
+
+
+
+SQLITE_EXTENSION_INIT1
+static void
+streq(sqlite3_context *const ctx, const int argc, sqlite3_value **const argv) {
+ assert(argc == 2);
+ const char *const str1 = (const char *)sqlite3_value_text(argv[0]);
+ const char *const str2 = (const char *)sqlite3_value_text(argv[1]);
+ const bool equal = strcmp(str1, str2) == 0;
+ const int result = equal ? 1 : 0;
+ sqlite3_result_int(ctx, result);
+}
+
+int
+sqlite3_extension_init(
+ sqlite3 *const db,
+ const char *const *const errmsg,
+ const sqlite3_api_routines *const api
+) {
+ SQLITE_EXTENSION_INIT2(api);
+ return sqlite3_create_function(
+ db,
+ "streq",
+ 2,
+ SQLITE_UTF8,
+ (void *)db,
+ streq,
+ NULL,
+ NULL
+ );
+}