mirror of
https://github.com/chaisql/chai.git
synced 2025-10-04 15:22:51 +08:00
Move tests to query package
This commit is contained in:
389
db_test.go
389
db_test.go
@@ -1,8 +1,6 @@
|
||||
package genji_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"log"
|
||||
"testing"
|
||||
@@ -305,390 +303,3 @@ func ExampleResult_Iterate() {
|
||||
// {10 foo10 100}
|
||||
// 10 foo10 100
|
||||
}
|
||||
|
||||
func TestCreateTable(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
query string
|
||||
fails bool
|
||||
}{
|
||||
{"Basic", `CREATE TABLE test`, false},
|
||||
{"Exists", "CREATE TABLE test;CREATE TABLE test", true},
|
||||
{"If not exists", "CREATE TABLE IF NOT EXISTS test", false},
|
||||
{"If not exists, twice", "CREATE TABLE IF NOT EXISTS test;CREATE TABLE IF NOT EXISTS test", false},
|
||||
{"With primary key", "CREATE TABLE test(foo STRING PRIMARY KEY)", false},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
db, err := genji.New(memoryengine.NewEngine())
|
||||
require.NoError(t, err)
|
||||
defer db.Close()
|
||||
|
||||
err = db.Exec(test.query)
|
||||
if test.fails {
|
||||
require.Error(t, err)
|
||||
return
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
err = db.ViewTable("test", func(_ *genji.Tx, _ *database.Table) error {
|
||||
return nil
|
||||
})
|
||||
require.NoError(t, err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateIndex(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
query string
|
||||
fails bool
|
||||
}{
|
||||
{"Basic", "CREATE INDEX idx ON test (foo)", false},
|
||||
{"If not exists", "CREATE INDEX IF NOT EXISTS idx ON test (foo)", false},
|
||||
{"Unique", "CREATE UNIQUE INDEX IF NOT EXISTS idx ON test (foo)", false},
|
||||
{"No fields", "CREATE INDEX idx ON test", true},
|
||||
{"More than 1 field", "CREATE INDEX idx ON test (foo, bar)", true},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
db, err := genji.New(memoryengine.NewEngine())
|
||||
require.NoError(t, err)
|
||||
defer db.Close()
|
||||
|
||||
err = db.Exec("CREATE TABLE test")
|
||||
require.NoError(t, err)
|
||||
|
||||
err = db.Exec(test.query)
|
||||
if test.fails {
|
||||
require.Error(t, err)
|
||||
return
|
||||
}
|
||||
require.NoError(t, err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDrop(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
query string
|
||||
fails bool
|
||||
}{
|
||||
{"Drop table", "DROP TABLE test", false},
|
||||
{"Drop table If not exists", "DROP TABLE IF EXISTS test", false},
|
||||
{"Drop index", "DROP INDEX idx", false},
|
||||
{"Drop index if exists", "DROP INDEX IF EXISTS idx", false},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
db, err := genji.New(memoryengine.NewEngine())
|
||||
require.NoError(t, err)
|
||||
defer db.Close()
|
||||
|
||||
err = db.Exec("CREATE TABLE test; CREATE INDEX idx ON test (foo)")
|
||||
require.NoError(t, err)
|
||||
|
||||
err = db.Exec(test.query)
|
||||
if test.fails {
|
||||
require.Error(t, err)
|
||||
return
|
||||
}
|
||||
require.NoError(t, err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeleteStmt(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
query string
|
||||
fails bool
|
||||
expected string
|
||||
params []interface{}
|
||||
}{
|
||||
{"No cond", `DELETE FROM test`, false, "", nil},
|
||||
{"With cond", "DELETE FROM test WHERE b = 'bar1'", false, "bar2,foo3,bar3\n", nil},
|
||||
{"Table not found", "DELETE FROM foo WHERE b = 'bar1'", true, "", nil},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
db, err := genji.New(memoryengine.NewEngine())
|
||||
require.NoError(t, err)
|
||||
defer db.Close()
|
||||
|
||||
err = db.Exec("CREATE TABLE test")
|
||||
require.NoError(t, err)
|
||||
err = db.Exec("INSERT INTO test (a, b, c) VALUES ('foo1', 'bar1', 'baz1')")
|
||||
require.NoError(t, err)
|
||||
err = db.Exec("INSERT INTO test (a, b) VALUES ('foo2', 'bar1')")
|
||||
require.NoError(t, err)
|
||||
err = db.Exec("INSERT INTO test (d, b, e) VALUES ('foo3', 'bar2', 'bar3')")
|
||||
require.NoError(t, err)
|
||||
|
||||
err = db.Exec(test.query, test.params...)
|
||||
if test.fails {
|
||||
require.Error(t, err)
|
||||
return
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
st, err := db.Query("SELECT * FROM test")
|
||||
require.NoError(t, err)
|
||||
defer st.Close()
|
||||
|
||||
var buf bytes.Buffer
|
||||
err = document.IteratorToCSV(&buf, st)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, test.expected, buf.String())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestInsertStmt(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
query string
|
||||
fails bool
|
||||
expected string
|
||||
params []interface{}
|
||||
}{
|
||||
{"Values / No columns", `INSERT INTO test VALUES ("a", 'b', 'c')`, true, ``, nil},
|
||||
{"Values / With columns", `INSERT INTO test (a, b, c) VALUES ('a', 'b', 'c')`, false, "1,a,b,c\n", nil},
|
||||
{"Values / Ident", `INSERT INTO test (a) VALUES (a)`, true, ``, nil},
|
||||
{"Values / Ident string", `INSERT INTO test (a) VALUES ("a")`, true, ``, nil},
|
||||
{"Values / With fields ident string", `INSERT INTO test (a, "foo bar") VALUES ('c', 'd')`, false, "1,c,d\n", nil},
|
||||
{"Values / Positional Params", "INSERT INTO test (a, b, c) VALUES (?, 'e', ?)", false, "1,d,e,f\n", []interface{}{"d", "f"}},
|
||||
{"Values / Named Params", "INSERT INTO test (a, b, c) VALUES ($d, 'e', $f)", false, "1,d,e,f\n", []interface{}{sql.Named("f", "f"), sql.Named("d", "d")}},
|
||||
{"Values / Invalid params", "INSERT INTO test (a, b, c) VALUES ('d', ?)", true, "", []interface{}{'e'}},
|
||||
{"Values / List", `INSERT INTO test (a, b, c) VALUES ("a", 'b', (1, 2, 3))`, true, "", nil},
|
||||
{"Records", "INSERT INTO test DOCUMENTS (a: 'a', b: 2.3, c: 1 = 1)", false, "1,a,2.3,true\n", nil},
|
||||
{"Records / Positional Params", "INSERT INTO test DOCUMENTS (a: ?, b: 2.3, c: ?)", false, "1,a,2.3,true\n", []interface{}{"a", true}},
|
||||
{"Records / Named Params", "INSERT INTO test DOCUMENTS (a: $a, b: 2.3, c: $c)", false, "1,1,2.3,true\n", []interface{}{sql.Named("c", true), sql.Named("a", 1)}},
|
||||
{"Records / List ", "INSERT INTO test DOCUMENTS (a: (1, 2, 3))", true, "", nil},
|
||||
{"Records / strings", `INSERT INTO test DOCUMENTS ('a': 'a', b: 2.3)`, true, "", nil},
|
||||
{"Records / ident value", `INSERT INTO test DOCUMENTS ("a": "a")`, true, "", nil},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
testFn := func(withIndexes bool) func(t *testing.T) {
|
||||
return func(t *testing.T) {
|
||||
db, err := genji.New(memoryengine.NewEngine())
|
||||
require.NoError(t, err)
|
||||
defer db.Close()
|
||||
|
||||
err = db.Exec("CREATE TABLE test")
|
||||
require.NoError(t, err)
|
||||
if withIndexes {
|
||||
err = db.Exec(`
|
||||
CREATE INDEX idx_a ON test (a);
|
||||
CREATE INDEX idx_b ON test (b);
|
||||
CREATE INDEX idx_c ON test (c);
|
||||
`)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
err = db.Exec(test.query, test.params...)
|
||||
if test.fails {
|
||||
require.Error(t, err)
|
||||
return
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
st, err := db.Query("SELECT key(), * FROM test")
|
||||
require.NoError(t, err)
|
||||
defer st.Close()
|
||||
|
||||
var buf bytes.Buffer
|
||||
err = document.IteratorToCSV(&buf, st)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, test.expected, buf.String())
|
||||
}
|
||||
}
|
||||
|
||||
t.Run("No Index/"+test.name, testFn(false))
|
||||
t.Run("With Index/"+test.name, testFn(true))
|
||||
}
|
||||
|
||||
t.Run("with primary key", func(t *testing.T) {
|
||||
db, err := genji.New(memoryengine.NewEngine())
|
||||
require.NoError(t, err)
|
||||
defer db.Close()
|
||||
|
||||
err = db.Exec("CREATE TABLE test (foo INTEGER PRIMARY KEY)")
|
||||
require.NoError(t, err)
|
||||
|
||||
err = db.Exec(`INSERT INTO test (bar) VALUES (1)`)
|
||||
require.Error(t, err)
|
||||
err = db.Exec(`INSERT INTO test (bar, foo) VALUES (1, 2)`)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = db.Exec(`INSERT INTO test (bar, foo) VALUES (1, 2)`)
|
||||
require.Equal(t, err, database.ErrDuplicateRecord)
|
||||
})
|
||||
|
||||
t.Run("with shadowing", func(t *testing.T) {
|
||||
db, err := genji.New(memoryengine.NewEngine())
|
||||
require.NoError(t, err)
|
||||
defer db.Close()
|
||||
|
||||
err = db.Exec("CREATE TABLE test")
|
||||
require.NoError(t, err)
|
||||
|
||||
err = db.Exec(`INSERT INTO test ("key()", "key") VALUES (1, 2)`)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
}
|
||||
|
||||
func TestSelectStmt(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
query string
|
||||
fails bool
|
||||
expected string
|
||||
params []interface{}
|
||||
}{
|
||||
{"No cond", "SELECT * FROM test", false, "foo1,bar1,baz1,1\nfoo2,bar1,1,2\nfoo3,bar2,3\n", nil},
|
||||
{"Multiple wildcards cond", "SELECT *, *, a FROM test", false, "foo1,bar1,baz1,1,foo1,bar1,baz1,1,foo1\nfoo2,bar1,1,2,foo2,bar1,1,2,foo2\nfoo3,bar2,3,foo3,bar2,3\n", nil},
|
||||
{"With fields", "SELECT a, c FROM test", false, "foo1,baz1\nfoo2\n\n", nil},
|
||||
{"With eq cond", "SELECT * FROM test WHERE b = 'bar1'", false, "foo1,bar1,baz1,1\nfoo2,bar1,1,2\n", nil},
|
||||
{"With neq cond", "SELECT * FROM test WHERE a != 'foo1'", false, "foo2,bar1,1,2\nfoo3,bar2,3\n", nil},
|
||||
{"With gt cond", "SELECT * FROM test WHERE b > 'bar1'", false, "", nil},
|
||||
{"With lt cond", "SELECT * FROM test WHERE a < 'zzzzz'", false, "foo1,bar1,baz1,1\nfoo2,bar1,1,2\n", nil},
|
||||
{"With lte cond", "SELECT * FROM test WHERE a <= 'foo3'", false, "foo1,bar1,baz1,1\nfoo2,bar1,1,2\n", nil},
|
||||
{"With field comparison", "SELECT * FROM test WHERE b < a", false, "foo1,bar1,baz1,1\nfoo2,bar1,1,2\n", nil},
|
||||
{"With limit", "SELECT * FROM test WHERE b = 'bar1' LIMIT 1", false, "foo1,bar1,baz1,1\n", nil},
|
||||
{"With offset", "SELECT *, key() FROM test WHERE b = 'bar1' OFFSET 1", false, "foo2,bar1,1,2,2\n", nil},
|
||||
{"With limit then offset", "SELECT * FROM test WHERE b = 'bar1' LIMIT 1 OFFSET 1", false, "foo2,bar1,1,2\n", nil},
|
||||
{"With offset then limit", "SELECT * FROM test WHERE b = 'bar1' OFFSET 1 LIMIT 1", true, "", nil},
|
||||
{"With positional params", "SELECT * FROM test WHERE a = ? OR d = ?", false, "foo1,bar1,baz1,1\nfoo3,bar2,3\n", []interface{}{"foo1", "foo3"}},
|
||||
{"With named params", "SELECT * FROM test WHERE a = $a OR d = $d", false, "foo1,bar1,baz1,1\nfoo3,bar2,3\n", []interface{}{sql.Named("a", "foo1"), sql.Named("d", "foo3")}},
|
||||
{"With key()", "SELECT key(), a FROM test", false, "1,foo1\n2,foo2\n3\n", []interface{}{sql.Named("a", "foo1"), sql.Named("d", "foo3")}},
|
||||
{"With pk in cond, gt", "SELECT * FROM test WHERE k > 0 AND e = 1", false, "foo2,bar1,1,2\n", nil},
|
||||
{"With pk in cond, =", "SELECT * FROM test WHERE k = 2.0 AND e = 1", false, "foo2,bar1,1,2\n", nil},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
testFn := func(withIndexes bool) func(t *testing.T) {
|
||||
return func(t *testing.T) {
|
||||
db, err := genji.New(memoryengine.NewEngine())
|
||||
require.NoError(t, err)
|
||||
defer db.Close()
|
||||
|
||||
err = db.Exec("CREATE TABLE test (k INTEGER PRIMARY KEY)")
|
||||
require.NoError(t, err)
|
||||
if withIndexes {
|
||||
err = db.Exec(`
|
||||
CREATE INDEX idx_a ON test (a);
|
||||
CREATE INDEX idx_b ON test (b);
|
||||
CREATE INDEX idx_c ON test (c);
|
||||
CREATE INDEX idx_d ON test (d);
|
||||
`)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
err = db.Exec("INSERT INTO test (k, a, b, c) VALUES (1, 'foo1', 'bar1', 'baz1')")
|
||||
require.NoError(t, err)
|
||||
err = db.Exec("INSERT INTO test (k, a, b, e) VALUES (2, 'foo2', 'bar1', 1)")
|
||||
require.NoError(t, err)
|
||||
err = db.Exec("INSERT INTO test (k, d, e) VALUES (3, 'foo3', 'bar2')")
|
||||
require.NoError(t, err)
|
||||
|
||||
st, err := db.Query(test.query, test.params...)
|
||||
if test.fails {
|
||||
require.Error(t, err)
|
||||
return
|
||||
}
|
||||
require.NoError(t, err)
|
||||
defer st.Close()
|
||||
|
||||
var buf bytes.Buffer
|
||||
err = document.IteratorToCSV(&buf, st)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, test.expected, buf.String())
|
||||
}
|
||||
}
|
||||
t.Run("No Index/"+test.name, testFn(false))
|
||||
t.Run("With Index/"+test.name, testFn(true))
|
||||
}
|
||||
|
||||
t.Run("with primary key only", func(t *testing.T) {
|
||||
db, err := genji.New(memoryengine.NewEngine())
|
||||
require.NoError(t, err)
|
||||
defer db.Close()
|
||||
|
||||
err = db.Exec("CREATE TABLE test (foo UINT8 PRIMARY KEY)")
|
||||
require.NoError(t, err)
|
||||
|
||||
err = db.Exec(`INSERT INTO test (foo, bar) VALUES (1, 'a')`)
|
||||
err = db.Exec(`INSERT INTO test (foo, bar) VALUES (2, 'b')`)
|
||||
err = db.Exec(`INSERT INTO test (foo, bar) VALUES (3, 'c')`)
|
||||
err = db.Exec(`INSERT INTO test (foo, bar) VALUES (4, 'd')`)
|
||||
require.NoError(t, err)
|
||||
|
||||
st, err := db.Query("SELECT * FROM test WHERE foo < 400 AND foo >= 2")
|
||||
require.NoError(t, err)
|
||||
defer st.Close()
|
||||
|
||||
var buf bytes.Buffer
|
||||
err = document.IteratorToCSV(&buf, st)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "b,2\nc,3\nd,4\n", buf.String())
|
||||
})
|
||||
}
|
||||
|
||||
func TestUpdateStmt(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
query string
|
||||
fails bool
|
||||
expected string
|
||||
params []interface{}
|
||||
}{
|
||||
{"No cond", `UPDATE test SET a = 'boo'`, false, "boo,bar1,baz1\nboo,bar2\nfoo3,bar3\n", nil},
|
||||
{"No cond / with ident string", `UPDATE test SET "a" = 'boo'`, false, "boo,bar1,baz1\nboo,bar2\nfoo3,bar3\n", nil},
|
||||
{"No cond / with multiple idents", `UPDATE test SET a = c`, false, "baz1,bar1,baz1\nNULL,bar2\nfoo3,bar3\n", nil},
|
||||
{"No cond / with string", `UPDATE test SET 'a' = 'boo'`, true, "", nil},
|
||||
{"With cond", "UPDATE test SET a = 1, b = 2 WHERE a = 'foo2'", false, "foo1,bar1,baz1\n1,2\nfoo3,bar3\n", nil},
|
||||
{"Field not found", "UPDATE test SET a = 1, b = 2 WHERE a = f", false, "foo1,bar1,baz1\nfoo2,bar2\nfoo3,bar3\n", nil},
|
||||
{"Positional params", "UPDATE test SET a = ?, b = ? WHERE a = ?", false, "a,b,baz1\nfoo2,bar2\nfoo3,bar3\n", []interface{}{"a", "b", "foo1"}},
|
||||
{"Named params", "UPDATE test SET a = $a, b = $b WHERE a = $c", false, "a,b,baz1\nfoo2,bar2\nfoo3,bar3\n", []interface{}{sql.Named("b", "b"), sql.Named("a", "a"), sql.Named("c", "foo1")}},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
db, err := genji.New(memoryengine.NewEngine())
|
||||
require.NoError(t, err)
|
||||
defer db.Close()
|
||||
|
||||
err = db.Exec("CREATE TABLE test")
|
||||
require.NoError(t, err)
|
||||
err = db.Exec("INSERT INTO test (a, b, c) VALUES ('foo1', 'bar1', 'baz1')")
|
||||
require.NoError(t, err)
|
||||
err = db.Exec("INSERT INTO test (a, b) VALUES ('foo2', 'bar2')")
|
||||
require.NoError(t, err)
|
||||
err = db.Exec("INSERT INTO test (d, e) VALUES ('foo3', 'bar3')")
|
||||
require.NoError(t, err)
|
||||
|
||||
err = db.Exec(test.query, test.params...)
|
||||
if test.fails {
|
||||
require.Error(t, err)
|
||||
return
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
st, err := db.Query("SELECT * FROM test")
|
||||
require.NoError(t, err)
|
||||
defer st.Close()
|
||||
|
||||
var buf bytes.Buffer
|
||||
err = document.IteratorToCSV(&buf, st)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, test.expected, buf.String())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user