mirror of
https://github.com/chaisql/chai.git
synced 2026-04-22 23:07:05 +08:00
Add tree package
This commit is contained in:
@@ -1,10 +1,11 @@
|
||||
package parser_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/genjidb/genji/internal/database"
|
||||
"github.com/genjidb/genji/internal/expr"
|
||||
"github.com/genjidb/genji/internal/query"
|
||||
"github.com/genjidb/genji/internal/query/statement"
|
||||
"github.com/genjidb/genji/internal/sql/parser"
|
||||
"github.com/genjidb/genji/internal/stream"
|
||||
@@ -31,7 +32,9 @@ func TestParserInsert(t *testing.T) {
|
||||
{K: "f", V: testutil.TextValue("baz")},
|
||||
}}},
|
||||
}},
|
||||
)).Pipe(stream.TableInsert("test", nil)),
|
||||
)).
|
||||
Pipe(stream.TableValidate("test")).
|
||||
Pipe(stream.TableInsert("test")),
|
||||
false},
|
||||
{"Documents / Multiple", `INSERT INTO test VALUES {"a": 'a', b: -2.3}, {a: 1, d: true}`,
|
||||
stream.New(stream.Expressions(
|
||||
@@ -40,19 +43,25 @@ func TestParserInsert(t *testing.T) {
|
||||
{K: "b", V: testutil.DoubleValue(-2.3)},
|
||||
}},
|
||||
&expr.KVPairs{SelfReferenced: true, Pairs: []expr.KVPair{{K: "a", V: testutil.IntegerValue(1)}, {K: "d", V: testutil.BoolValue(true)}}},
|
||||
)).Pipe(stream.TableInsert("test", nil)),
|
||||
)).
|
||||
Pipe(stream.TableValidate("test")).
|
||||
Pipe(stream.TableInsert("test")),
|
||||
false},
|
||||
{"Documents / Positional Param", "INSERT INTO test VALUES ?, ?",
|
||||
stream.New(stream.Expressions(
|
||||
expr.PositionalParam(1),
|
||||
expr.PositionalParam(2),
|
||||
)).Pipe(stream.TableInsert("test", nil)),
|
||||
)).
|
||||
Pipe(stream.TableValidate("test")).
|
||||
Pipe(stream.TableInsert("test")),
|
||||
false},
|
||||
{"Documents / Named Param", "INSERT INTO test VALUES $foo, $bar",
|
||||
stream.New(stream.Expressions(
|
||||
expr.NamedParam("foo"),
|
||||
expr.NamedParam("bar"),
|
||||
)).Pipe(stream.TableInsert("test", nil)),
|
||||
)).
|
||||
Pipe(stream.TableValidate("test")).
|
||||
Pipe(stream.TableInsert("test")),
|
||||
false},
|
||||
{"Values / With fields", "INSERT INTO test (a, b) VALUES ('c', 'd')",
|
||||
stream.New(stream.Expressions(
|
||||
@@ -60,7 +69,9 @@ func TestParserInsert(t *testing.T) {
|
||||
{K: "a", V: testutil.TextValue("c")},
|
||||
{K: "b", V: testutil.TextValue("d")},
|
||||
}},
|
||||
)).Pipe(stream.TableInsert("test", nil)),
|
||||
)).
|
||||
Pipe(stream.TableValidate("test")).
|
||||
Pipe(stream.TableInsert("test")),
|
||||
false},
|
||||
{"Values / With too many values", "INSERT INTO test (a, b) VALUES ('c', 'd', 'e')",
|
||||
nil, true},
|
||||
@@ -74,7 +85,9 @@ func TestParserInsert(t *testing.T) {
|
||||
{K: "a", V: testutil.TextValue("e")},
|
||||
{K: "b", V: testutil.TextValue("f")},
|
||||
}},
|
||||
)).Pipe(stream.TableInsert("test", nil)),
|
||||
)).
|
||||
Pipe(stream.TableValidate("test")).
|
||||
Pipe(stream.TableInsert("test")),
|
||||
false},
|
||||
{"Values / Returning", "INSERT INTO test (a, b) VALUES ('c', 'd') RETURNING *, a, b as B, c",
|
||||
stream.New(stream.Expressions(
|
||||
@@ -82,7 +95,9 @@ func TestParserInsert(t *testing.T) {
|
||||
{K: "a", V: testutil.TextValue("c")},
|
||||
{K: "b", V: testutil.TextValue("d")},
|
||||
}},
|
||||
)).Pipe(stream.TableInsert("test", nil)).
|
||||
)).
|
||||
Pipe(stream.TableValidate("test")).
|
||||
Pipe(stream.TableInsert("test")).
|
||||
Pipe(stream.Project(expr.Wildcard{}, testutil.ParseNamedExpr(t, "a"), testutil.ParseNamedExpr(t, "b", "B"), testutil.ParseNamedExpr(t, "c"))),
|
||||
false},
|
||||
{"Values / With fields / Wrong values", "INSERT INTO test (a, b) VALUES {a: 1}, ('e', 'f')",
|
||||
@@ -95,8 +110,10 @@ func TestParserInsert(t *testing.T) {
|
||||
{K: "a", V: testutil.TextValue("c")},
|
||||
{K: "b", V: testutil.TextValue("d")},
|
||||
}},
|
||||
)).Pipe(stream.TableInsert("test", database.OnInsertConflictDoNothing)).
|
||||
Pipe(stream.Project(expr.Wildcard{})),
|
||||
)).
|
||||
Pipe(stream.TableValidate("test")).
|
||||
Pipe(stream.HandleConflict(stream.New(stream.NoOp()))).
|
||||
Pipe(stream.TableInsert("test")),
|
||||
false},
|
||||
{"Values / ON CONFLICT IGNORE", "INSERT INTO test (a, b) VALUES ('c', 'd') ON CONFLICT IGNORE RETURNING *",
|
||||
stream.New(stream.Expressions(
|
||||
@@ -104,8 +121,9 @@ func TestParserInsert(t *testing.T) {
|
||||
{K: "a", V: testutil.TextValue("c")},
|
||||
{K: "b", V: testutil.TextValue("d")},
|
||||
}},
|
||||
)).Pipe(stream.TableInsert("test", database.OnInsertConflictDoNothing)).
|
||||
Pipe(stream.Project(expr.Wildcard{})),
|
||||
)).Pipe(stream.TableValidate("test")).
|
||||
Pipe(stream.HandleConflict(stream.New(stream.NoOp()))).
|
||||
Pipe(stream.TableInsert("test")),
|
||||
false},
|
||||
{"Values / ON CONFLICT DO REPLACE", "INSERT INTO test (a, b) VALUES ('c', 'd') ON CONFLICT DO REPLACE RETURNING *",
|
||||
stream.New(stream.Expressions(
|
||||
@@ -113,8 +131,10 @@ func TestParserInsert(t *testing.T) {
|
||||
{K: "a", V: testutil.TextValue("c")},
|
||||
{K: "b", V: testutil.TextValue("d")},
|
||||
}},
|
||||
)).Pipe(stream.TableInsert("test", database.OnInsertConflictDoReplace)).
|
||||
Pipe(stream.Project(expr.Wildcard{})),
|
||||
)).
|
||||
Pipe(stream.TableValidate("test")).
|
||||
Pipe(stream.HandleConflict(stream.New(stream.TableReplace("test")))).
|
||||
Pipe(stream.TableInsert("test")),
|
||||
false},
|
||||
{"Values / ON CONFLICT REPLACE", "INSERT INTO test (a, b) VALUES ('c', 'd') ON CONFLICT REPLACE RETURNING *",
|
||||
stream.New(stream.Expressions(
|
||||
@@ -122,8 +142,10 @@ func TestParserInsert(t *testing.T) {
|
||||
{K: "a", V: testutil.TextValue("c")},
|
||||
{K: "b", V: testutil.TextValue("d")},
|
||||
}},
|
||||
)).Pipe(stream.TableInsert("test", database.OnInsertConflictDoReplace)).
|
||||
Pipe(stream.Project(expr.Wildcard{})),
|
||||
)).
|
||||
Pipe(stream.TableValidate("test")).
|
||||
Pipe(stream.HandleConflict(stream.New(stream.TableReplace("test")))).
|
||||
Pipe(stream.TableInsert("test")),
|
||||
false},
|
||||
{"Values / ON CONFLICT BLA", "INSERT INTO test (a, b) VALUES ('c', 'd') ON CONFLICT BLA RETURNING *",
|
||||
nil, true},
|
||||
@@ -131,58 +153,76 @@ func TestParserInsert(t *testing.T) {
|
||||
nil, true},
|
||||
{"Select / Without fields", "INSERT INTO test SELECT * FROM foo",
|
||||
stream.New(stream.SeqScan("foo")).
|
||||
Pipe(stream.Project(expr.Wildcard{})).
|
||||
Pipe(stream.TableInsert("test", nil)),
|
||||
Pipe(stream.TableValidate("test")).
|
||||
Pipe(stream.TableInsert("test")),
|
||||
false},
|
||||
{"Select / Without fields / With projection", "INSERT INTO test SELECT a, b FROM foo",
|
||||
stream.New(stream.SeqScan("foo")).
|
||||
Pipe(stream.Project(testutil.ParseNamedExpr(t, "a"), testutil.ParseNamedExpr(t, "b"))).
|
||||
Pipe(stream.TableInsert("test", nil)),
|
||||
Pipe(stream.TableValidate("test")).
|
||||
Pipe(stream.TableInsert("test")),
|
||||
false},
|
||||
{"Select / With fields", "INSERT INTO test (a, b) SELECT * FROM foo",
|
||||
stream.New(stream.SeqScan("foo")).
|
||||
Pipe(stream.Project(expr.Wildcard{})).
|
||||
Pipe(stream.IterRename("a", "b")).
|
||||
Pipe(stream.TableInsert("test", nil)),
|
||||
Pipe(stream.TableValidate("test")).
|
||||
Pipe(stream.TableInsert("test")),
|
||||
false},
|
||||
{"Select / With fields / With projection", "INSERT INTO test (a, b) SELECT a, b FROM foo",
|
||||
stream.New(stream.SeqScan("foo")).
|
||||
Pipe(stream.Project(testutil.ParseNamedExpr(t, "a"), testutil.ParseNamedExpr(t, "b"))).
|
||||
Pipe(stream.IterRename("a", "b")).
|
||||
Pipe(stream.TableInsert("test", nil)),
|
||||
Pipe(stream.TableValidate("test")).
|
||||
Pipe(stream.TableInsert("test")),
|
||||
false},
|
||||
{"Select / With fields / With projection / different fields", "INSERT INTO test (a, b) SELECT c, d FROM foo",
|
||||
stream.New(stream.SeqScan("foo")).
|
||||
Pipe(stream.Project(testutil.ParseNamedExpr(t, "c"), testutil.ParseNamedExpr(t, "d"))).
|
||||
Pipe(stream.IterRename("a", "b")).
|
||||
Pipe(stream.TableInsert("test", nil)),
|
||||
Pipe(stream.TableValidate("test")).
|
||||
Pipe(stream.TableInsert("test")),
|
||||
false},
|
||||
{"Select / With fields / With projection / different fields / Returning", "INSERT INTO test (a, b) SELECT c, d FROM foo RETURNING a",
|
||||
stream.New(stream.SeqScan("foo")).
|
||||
Pipe(stream.Project(testutil.ParseNamedExpr(t, "c"), testutil.ParseNamedExpr(t, "d"))).
|
||||
Pipe(stream.IterRename("a", "b")).
|
||||
Pipe(stream.TableInsert("test", nil)).
|
||||
Pipe(stream.TableValidate("test")).
|
||||
Pipe(stream.TableInsert("test")).
|
||||
Pipe(stream.Project(testutil.ParseNamedExpr(t, "a"))),
|
||||
false},
|
||||
{"Select / With fields / With projection / different fields / On conflict / Returning", "INSERT INTO test (a, b) SELECT c, d FROM foo ON CONFLICT DO NOTHING RETURNING a",
|
||||
stream.New(stream.SeqScan("foo")).
|
||||
Pipe(stream.Project(testutil.ParseNamedExpr(t, "c"), testutil.ParseNamedExpr(t, "d"))).
|
||||
Pipe(stream.IterRename("a", "b")).
|
||||
Pipe(stream.TableInsert("test", database.OnInsertConflictDoNothing)).
|
||||
Pipe(stream.TableValidate("test")).
|
||||
Pipe(stream.HandleConflict(stream.New(stream.NoOp()))).
|
||||
Pipe(stream.TableInsert("test")).
|
||||
Pipe(stream.Project(testutil.ParseNamedExpr(t, "a"))),
|
||||
false},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
db, cleanup := testutil.NewTestDB(t)
|
||||
defer cleanup()
|
||||
|
||||
testutil.MustExec(t, db, nil, "CREATE TABLE test; CREATE TABLE foo;")
|
||||
|
||||
q, err := parser.ParseQuery(test.s)
|
||||
if test.fails {
|
||||
assert.Error(t, err)
|
||||
return
|
||||
}
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = q.Prepare(&query.Context{
|
||||
Ctx: context.Background(),
|
||||
DB: db,
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
|
||||
require.Len(t, q.Statements, 1)
|
||||
require.EqualValues(t, test.expected.String(), q.Statements[0].(*statement.StreamStmt).Stream.String())
|
||||
require.EqualValues(t, &statement.PreparedStreamStmt{Stream: test.expected}, q.Statements[0].(*statement.PreparedStreamStmt))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user