Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(embedded/sql): Add support for core pg_catalog tables (pg_class… #2036

Merged
merged 1 commit into from
Dec 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
*.out
coverage.txt

# Output of goyacc
embedded/sql/y.output

# Editor
.vscode
.idea
Expand Down Expand Up @@ -50,4 +53,4 @@ token_admin

swagger/dist
swagger/swaggerembedded
webconsole/webconsoleembedded
webconsole/webconsoleembedded
24 changes: 24 additions & 0 deletions embedded/sql/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ type Engine struct {
lazyIndexConstraintValidation bool
parseTxMetadata func([]byte) (map[string]interface{}, error)
multidbHandler MultiDBHandler
tableResolvers map[string]TableResolver
}

type MultiDBHandler interface {
Expand All @@ -134,6 +135,11 @@ type MultiDBHandler interface {
ExecPreparedStmts(ctx context.Context, opts *TxOptions, stmts []SQLStmt, params map[string]interface{}) (ntx *SQLTx, committedTxs []*SQLTx, err error)
}

type TableResolver interface {
Table() string
Resolve(ctx context.Context, tx *SQLTx, alias string) (RowReader, error)
}

type User interface {
Username() string
Permission() Permission
Expand Down Expand Up @@ -176,6 +182,10 @@ func NewEngine(st *store.ImmuStore, opts *Options) (*Engine, error) {
return nil, err
}

for _, r := range opts.tableResolvers {
e.registerTableResolver(r.Table(), r)
}

// TODO: find a better way to handle parsing errors
yyErrorVerbose = true

Expand Down Expand Up @@ -728,3 +738,17 @@ func (e *Engine) GetStore() *store.ImmuStore {
func (e *Engine) GetPrefix() []byte {
return e.prefix
}

func (e *Engine) tableResolveFor(tableName string) TableResolver {
if e.tableResolvers == nil {
return nil
}
return e.tableResolvers[tableName]
}

func (e *Engine) registerTableResolver(tableName string, r TableResolver) {
if e.tableResolvers == nil {
e.tableResolvers = make(map[string]TableResolver)
}
e.tableResolvers[tableName] = r
}
59 changes: 59 additions & 0 deletions embedded/sql/engine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4616,6 +4616,10 @@ func TestOrderBy(t *testing.T) {
directions: []int{1, -1},
positionalRefs: []int{4, 5},
},
{
exps: []string{"weight/(height*height)"},
directions: []int{1},
},
}

runTest := func(t *testing.T, test *test, expectedTempFiles int) []*Row {
Expand Down Expand Up @@ -9552,6 +9556,40 @@ func TestFunctions(t *testing.T) {
})
}

func TestTableResolver(t *testing.T) {
st, err := store.Open(t.TempDir(), store.DefaultOptions().WithMultiIndexing(true))
require.NoError(t, err)
defer closeStore(t, st)

r := &mockTableResolver{
name: "my_table",
cols: []ColDescriptor{
{Column: "varchar_col", Type: VarcharType},
{Column: "int_col", Type: IntegerType},
{Column: "bool_col", Type: BooleanType},
},
values: [][]ValueExp{{NewVarchar("test"), NewInteger(1), NewBool(true)}},
}

engine, err := NewEngine(
st,
DefaultOptions().
WithPrefix(sqlPrefix).
WithTableResolvers(r),
)
require.NoError(t, err)

assertQueryShouldProduceResults(
t,
engine,
"SELECT int_col, varchar_col, bool_col FROM my_table",
`SELECT * FROM (
VALUES
(1, 'test', true)
)`,
)
}

func assertQueryShouldProduceResults(t *testing.T, e *Engine, query, resultQuery string) {
queryReader, err := e.Query(context.Background(), nil, query, nil)
require.NoError(t, err)
Expand All @@ -9572,3 +9610,24 @@ func assertQueryShouldProduceResults(t *testing.T, e *Engine, query, resultQuery
require.Equal(t, expectedRow.ValuesByPosition, actualRow.ValuesByPosition)
}
}

type mockTableResolver struct {
name string
cols []ColDescriptor
values [][]ValueExp
}

func (r *mockTableResolver) Table() string {
return r.name
}

func (r *mockTableResolver) Resolve(ctx context.Context, tx *SQLTx, alias string) (RowReader, error) {
return NewValuesRowReader(
tx,
nil,
r.cols,
false,
r.name,
r.values,
)
}
Loading
Loading