featurebase/server/pg_test.go
2022-02-25 11:39:31 -06:00

313 lines
6.7 KiB
Go

// Copyright 2021 Molecula Corp. All rights reserved.
package server_test
import (
"context"
"math"
"reflect"
"testing"
"time"
pilosa "github.com/molecula/featurebase/v3"
"github.com/molecula/featurebase/v3/logger"
"github.com/molecula/featurebase/v3/pg"
"github.com/molecula/featurebase/v3/pg/pgtest"
"github.com/molecula/featurebase/v3/server"
"github.com/molecula/featurebase/v3/test"
)
func TestPostgresHandler(t *testing.T) {
m := test.RunCommand(t)
defer m.Close()
pgh := server.NewPostgresHandler(m.API, logger.NewLogfLogger(t), server.SqlV1)
m.MustCreateIndex(t, "i", pilosa.IndexOptions{TrackExistence: true})
m.MustCreateField(t, "i", "set")
m.MustCreateField(t, "i", "keyset", pilosa.OptFieldKeys())
m.MustCreateField(t, "i", "mutex", pilosa.OptFieldTypeMutex(pilosa.CacheTypeNone, 0))
m.MustCreateField(t, "i", "keymutex", pilosa.OptFieldKeys(), pilosa.OptFieldTypeMutex(pilosa.CacheTypeNone, 0))
m.MustCreateField(t, "i", "int", pilosa.OptFieldTypeInt(math.MinInt64, math.MaxInt64))
m.MustCreateField(t, "i", "decimal", pilosa.OptFieldTypeDecimal(2))
m.MustCreateField(t, "i", "time", pilosa.OptFieldTypeTime("YMDH", "0"))
m.MustCreateField(t, "i", "bool", pilosa.OptFieldTypeBool())
m.MustCreateIndex(t, "j", pilosa.IndexOptions{TrackExistence: true, Keys: true})
m.MustCreateField(t, "j", "set")
storeOK := pgtest.ResultSet{
Columns: []pg.ColumnInfo{
{
Name: "result",
Type: pg.TypeCharoid,
},
},
Data: [][]string{
{
"true",
},
},
}
cases := []struct {
Name string
Queries []string
Results []pgtest.ResultSet
}{
{
Name: "Extract-Nothing",
Queries: []string{
`[i]Extract(All(), Rows(set))`,
},
Results: []pgtest.ResultSet{
{
Columns: []pg.ColumnInfo{
{
Name: "_id",
Type: pg.TypeCharoid,
},
{
Name: "set",
Type: pg.TypeCharoid,
},
},
},
},
},
{
Name: "Store",
Queries: []string{
`[i]Store(ConstRow(columns=[1, 2, 3]), set=4)`,
`[i]Store(ConstRow(columns=[0, 2, 4]), set=5)`,
`[j]Store(ConstRow(columns=[1, 2, 3]), set=4)`,
`[j]Store(ConstRow(columns=[0, 2, 4]), set=5)`,
},
Results: []pgtest.ResultSet{
storeOK,
storeOK,
storeOK,
storeOK,
},
},
{
Name: "Set",
Queries: []string{
`[i]Set(1, keyset="a")`,
`[i]Set(2, keyset="b")`,
`[i]Set(3, mutex=3)`,
`[i]Set(4, keymutex="d")`,
`[i]Set(1, int=5)`,
`[i]Set(2, decimal=6.01)`,
`[i]Set(3, time=7, 2016-01-01T00:00)`,
`[i]Set(4, bool=false)`,
},
Results: []pgtest.ResultSet{
storeOK,
storeOK,
storeOK,
storeOK,
storeOK,
storeOK,
storeOK,
storeOK,
},
},
{
Name: "Extract",
Queries: []string{
`[i]Extract(
All(),
Rows(set), Rows(keyset),
Rows(mutex), Rows(keymutex),
Rows(int), Rows(decimal),
Rows(time),
Rows(bool)
)`,
},
Results: []pgtest.ResultSet{
{
Columns: []pg.ColumnInfo{
{Name: "_id", Type: pg.TypeCharoid},
{Name: "set", Type: pg.TypeCharoid},
{Name: "keyset", Type: pg.TypeCharoid},
{Name: "mutex", Type: pg.TypeCharoid},
{Name: "keymutex", Type: pg.TypeCharoid},
{Name: "int", Type: pg.TypeCharoid},
{Name: "decimal", Type: pg.TypeCharoid},
{Name: "time", Type: pg.TypeCharoid},
{Name: "bool", Type: pg.TypeCharoid},
},
Data: [][]string{
{`1`, `[4]`, `["a"]`, `null`, `null`, `5`, `null`, `[]`, `null`},
{`2`, `[4,5]`, `["b"]`, `null`, `null`, `null`, `6.01`, `[]`, `null`},
{`3`, `[4]`, `[]`, `3`, `null`, `null`, `null`, `[7]`, `null`},
{`4`, `[5]`, `[]`, `null`, `d`, `null`, `null`, `[]`, `false`},
},
},
},
},
{
Name: "GroupBy",
Queries: []string{
`[i]GroupBy(Rows(set))`,
},
Results: []pgtest.ResultSet{
{
Columns: []pg.ColumnInfo{
{Name: "set", Type: pg.TypeCharoid},
{Name: "count", Type: pg.TypeCharoid},
},
Data: [][]string{
{"4", "3"},
{"5", "3"},
},
},
},
},
{
Name: "Count",
Queries: []string{
`[i]Count(Row(set=4))`,
`[i]Count(Row(int > 0))`,
},
Results: []pgtest.ResultSet{
{
Columns: []pg.ColumnInfo{
{Name: "count", Type: pg.TypeCharoid},
},
Data: [][]string{{"3"}},
},
{
Columns: []pg.ColumnInfo{
{Name: "count", Type: pg.TypeCharoid},
},
Data: [][]string{{"1"}},
},
},
},
{
Name: "FieldValue",
Queries: []string{
`[i]FieldValue(field=int, column=1)`,
`[i]FieldValue(field=decimal, column=2)`,
},
Results: []pgtest.ResultSet{
{
Columns: []pg.ColumnInfo{
{Name: "value", Type: pg.TypeCharoid},
{Name: "count", Type: pg.TypeCharoid},
},
Data: [][]string{
{"5", "1"},
},
},
{
Columns: []pg.ColumnInfo{
{Name: "value", Type: pg.TypeCharoid},
{Name: "count", Type: pg.TypeCharoid},
},
Data: [][]string{
{"6.01", "1"},
},
},
},
},
{
Name: "Rows",
Queries: []string{
`[i]Rows(set)`,
`[i]Rows(keyset)`,
},
Results: []pgtest.ResultSet{
{
Columns: []pg.ColumnInfo{
{Name: "set", Type: pg.TypeCharoid},
},
Data: [][]string{
{"4"},
{"5"},
},
},
{
Columns: []pg.ColumnInfo{
{Name: "keyset", Type: pg.TypeCharoid},
},
Data: [][]string{
{"a"},
{"b"},
},
},
},
},
{
Name: "TopN",
Queries: []string{
`[i]TopN(set)`,
`[i]TopN(keyset)`,
},
Results: []pgtest.ResultSet{
{
Columns: []pg.ColumnInfo{
{Name: "set", Type: pg.TypeCharoid},
{Name: "count", Type: pg.TypeCharoid},
},
Data: [][]string{
{"5", "3"},
{"4", "3"},
},
},
{
Columns: []pg.ColumnInfo{
{Name: "keyset", Type: pg.TypeCharoid},
{Name: "count", Type: pg.TypeCharoid},
},
Data: [][]string{
{"b", "1"},
{"a", "1"},
},
},
},
},
{
Name: "SQL",
Queries: []string{
`select _id from i;`,
},
Results: []pgtest.ResultSet{
{
Columns: []pg.ColumnInfo{
{Name: "_id", Type: pg.TypeCharoid},
},
Data: [][]string{
{`1`},
{`2`},
{`3`},
{`4`},
},
},
},
},
}
for _, c := range cases {
c := c
t.Run(c.Name, func(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
for i, q := range c.Queries {
var res pgtest.ResultSet
err := pgh.HandleQuery(ctx, &res, pg.SimpleQuery(q))
if err != nil {
t.Errorf("query %q failed: %v", q, err)
continue
}
expected := c.Results[i]
if !reflect.DeepEqual(res, expected) {
t.Errorf("query %q returned incorrect results: expected %v but got %v", q, expected, res)
}
}
})
}
}