Skip to content

Commit

Permalink
Dynamically handle SHOW statements
Browse files Browse the repository at this point in the history
  • Loading branch information
exAspArk committed Jan 7, 2025
1 parent 05099c9 commit 2e02f4f
Show file tree
Hide file tree
Showing 4 changed files with 130 additions and 6 deletions.
91 changes: 91 additions & 0 deletions src/parser_show.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package main

import (
pgQuery "github.com/pganalyze/pg_query_go/v5"
)

type ParserShow struct {
config *Config
}

func NewParserShow(config *Config) *ParserShow {
return &ParserShow{config: config}
}

func (parser *ParserShow) VariableName(stmt *pgQuery.RawStmt) string {
return stmt.Stmt.GetVariableShowStmt().Name
}

// SHOW var -> SELECT value AS var FROM duckdb_settings() WHERE LOWER(name) = 'var';
func (parser *ParserShow) MakeSelectFromDuckdbSettings(variableName string) *pgQuery.RawStmt {
return &pgQuery.RawStmt{
Stmt: &pgQuery.Node{
Node: &pgQuery.Node_SelectStmt{
SelectStmt: &pgQuery.SelectStmt{
TargetList: []*pgQuery.Node{
pgQuery.MakeResTargetNodeWithNameAndVal(
variableName,
pgQuery.MakeColumnRefNode(
[]*pgQuery.Node{pgQuery.MakeStrNode("value")},
0,
),
0,
),
},
FromClause: []*pgQuery.Node{
pgQuery.MakeSimpleRangeFunctionNode(
[]*pgQuery.Node{
pgQuery.MakeListNode(
[]*pgQuery.Node{
pgQuery.MakeFuncCallNode(
[]*pgQuery.Node{pgQuery.MakeStrNode("duckdb_settings")},
nil,
0,
),
},
),
},
),
},
WhereClause: pgQuery.MakeAExprNode(
pgQuery.A_Expr_Kind_AEXPR_OP,
[]*pgQuery.Node{pgQuery.MakeStrNode("=")},
pgQuery.MakeFuncCallNode(
[]*pgQuery.Node{pgQuery.MakeStrNode("lower")},
[]*pgQuery.Node{
pgQuery.MakeColumnRefNode(
[]*pgQuery.Node{pgQuery.MakeStrNode("name")},
0,
),
},
0,
),
pgQuery.MakeAConstStrNode(variableName, 0),
0,
),
},
},
},
}
}

// SHOW search_path -> SELECT CONCAT('"$user", ', value) AS search_path FROM duckdb_settings() WHERE name = 'search_path'
func (parser *ParserShow) SetTargetListForSearchPath(stmt *pgQuery.RawStmt) {
stmt.Stmt.GetSelectStmt().TargetList = []*pgQuery.Node{
pgQuery.MakeResTargetNodeWithNameAndVal(
"search_path",
pgQuery.MakeFuncCallNode(
[]*pgQuery.Node{pgQuery.MakeStrNode("concat")},
[]*pgQuery.Node{
pgQuery.MakeAConstStrNode(`"$user", `, 0),
pgQuery.MakeColumnRefNode(
[]*pgQuery.Node{pgQuery.MakeStrNode("value")},
0,
),
},
0,
),
0,
),
}
}
4 changes: 4 additions & 0 deletions src/query_handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,10 @@ func TestHandleQuery(t *testing.T) {
"types": {Uint32ToString(pgtype.TextOID)},
"values": {`"$user", public`},
},
"SHOW timezone": {
"description": {"timezone"},
"types": {Uint32ToString(pgtype.TextOID)},
},

// Iceberg data
"SELECT COUNT(*) AS count FROM public.test_table": {
Expand Down
9 changes: 3 additions & 6 deletions src/query_remapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ type QueryRemapper struct {
remapperTable *QueryRemapperTable
remapperWhere *QueryRemapperWhere
remapperSelect *QueryRemapperSelect
remapperShow *QueryRemapperShow
icebergReader *IcebergReader
duckdb *Duckdb
config *Config
Expand All @@ -40,6 +41,7 @@ func NewQueryRemapper(config *Config, icebergReader *IcebergReader, duckdb *Duck
remapperTable: NewQueryRemapperTable(config, icebergReader, duckdb),
remapperWhere: NewQueryRemapperWhere(config),
remapperSelect: NewQueryRemapperSelect(config),
remapperShow: NewQueryRemapperShow(config),
icebergReader: icebergReader,
duckdb: duckdb,
config: config,
Expand Down Expand Up @@ -75,12 +77,7 @@ func (remapper *QueryRemapper) RemapStatements(statements []*pgQuery.RawStmt) ([

// SHOW ...
case node.GetVariableShowStmt() != nil:
if node.GetVariableShowStmt().Name == "search_path" {
searchPathStmt, _ := pgQuery.Parse(`SELECT CONCAT('"$user", ', value) AS search_path FROM duckdb_settings() WHERE name = 'search_path'`)
statements[i] = searchPathStmt.Stmts[0]
} else {
statements[i] = FALLBACK_QUERY_TREE.Stmts[0]
}
statements[i] = remapper.remapperShow.RemapShowStatement(stmt)

// Unsupported query
default:
Expand Down
32 changes: 32 additions & 0 deletions src/query_remapper_show.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package main

import (
pgQuery "github.com/pganalyze/pg_query_go/v5"
)

type QueryRemapperShow struct {
config *Config
parserShow *ParserShow
}

func NewQueryRemapperShow(config *Config) *QueryRemapperShow {
return &QueryRemapperShow{
config: config,
parserShow: NewParserShow(config),
}
}

func (remapper *QueryRemapperShow) RemapShowStatement(stmt *pgQuery.RawStmt) *pgQuery.RawStmt {
parser := remapper.parserShow
variableName := parser.VariableName(stmt)

// SHOW var -> SELECT value AS variable FROM duckdb_settings() WHERE LOWER(name) = 'variable';
newStmt := parser.MakeSelectFromDuckdbSettings(variableName)

// SHOW search_path -> SELECT CONCAT('"$user", ', value) AS search_path FROM duckdb_settings() WHERE name = 'search_path'
if variableName == "search_path" {
parser.SetTargetListForSearchPath(newStmt)
}

return newStmt
}

0 comments on commit 2e02f4f

Please sign in to comment.