Skip to content

Commit

Permalink
sql: add SHOW FUNCTIONS command
Browse files Browse the repository at this point in the history
Release note (sql change): Added the SHOW FUNCTIONS command, which lists
user-defined functions. The SHOW FUNCTIONS FROM <schema> syntax is
supported too.
  • Loading branch information
rafiss committed Oct 10, 2022
1 parent bfbd07b commit a84835a
Show file tree
Hide file tree
Showing 15 changed files with 226 additions and 2 deletions.
1 change: 1 addition & 0 deletions docs/generated/sql/bnf/BUILD.bazel
Expand Up @@ -216,6 +216,7 @@ FILES = [
"show_default_privileges_stmt",
"show_enums",
"show_full_scans",
"show_functions_stmt",
"show_grants_stmt",
"show_indexes_stmt",
"show_jobs",
Expand Down
4 changes: 4 additions & 0 deletions docs/generated/sql/bnf/show_functions_stmt.bnf
@@ -0,0 +1,4 @@
show_functions_stmt ::=
'SHOW' 'FUNCTIONS' 'FROM' name '.' name
| 'SHOW' 'FUNCTIONS' 'FROM' name
| 'SHOW' 'FUNCTIONS'
1 change: 1 addition & 0 deletions docs/generated/sql/bnf/show_var.bnf
Expand Up @@ -9,6 +9,7 @@ show_stmt ::=
| show_databases_stmt
| show_enums_stmt
| show_types_stmt
| show_functions_stmt
| show_grants_stmt
| show_indexes_stmt
| show_partitions_stmt
Expand Down
6 changes: 6 additions & 0 deletions docs/generated/sql/bnf/stmt_block.bnf
Expand Up @@ -270,6 +270,7 @@ show_stmt ::=
| show_databases_stmt
| show_enums_stmt
| show_types_stmt
| show_functions_stmt
| show_grants_stmt
| show_indexes_stmt
| show_partitions_stmt
Expand Down Expand Up @@ -809,6 +810,11 @@ show_enums_stmt ::=
show_types_stmt ::=
'SHOW' 'TYPES'

show_functions_stmt ::=
'SHOW' 'FUNCTIONS' 'FROM' name '.' name
| 'SHOW' 'FUNCTIONS' 'FROM' name
| 'SHOW' 'FUNCTIONS'

show_grants_stmt ::=
'SHOW' 'GRANTS' opt_on_targets_roles for_grantee_clause
| 'SHOW' 'SYSTEM' 'GRANTS' for_grantee_clause
Expand Down
1 change: 1 addition & 0 deletions pkg/gen/bnf.bzl
Expand Up @@ -216,6 +216,7 @@ BNF_SRCS = [
"//docs/generated/sql/bnf:show_default_privileges_stmt.bnf",
"//docs/generated/sql/bnf:show_enums.bnf",
"//docs/generated/sql/bnf:show_full_scans.bnf",
"//docs/generated/sql/bnf:show_functions_stmt.bnf",
"//docs/generated/sql/bnf:show_grants_stmt.bnf",
"//docs/generated/sql/bnf:show_indexes_stmt.bnf",
"//docs/generated/sql/bnf:show_jobs.bnf",
Expand Down
1 change: 1 addition & 0 deletions pkg/gen/diagrams.bzl
Expand Up @@ -214,6 +214,7 @@ DIAGRAMS_SRCS = [
"//docs/generated/sql/bnf:show_default_privileges.html",
"//docs/generated/sql/bnf:show_enums.html",
"//docs/generated/sql/bnf:show_full_scans.html",
"//docs/generated/sql/bnf:show_functions.html",
"//docs/generated/sql/bnf:show_grants.html",
"//docs/generated/sql/bnf:show_indexes.html",
"//docs/generated/sql/bnf:show_jobs.html",
Expand Down
1 change: 1 addition & 0 deletions pkg/gen/docs.bzl
Expand Up @@ -228,6 +228,7 @@ DOCS_SRCS = [
"//docs/generated/sql/bnf:show_default_privileges_stmt.bnf",
"//docs/generated/sql/bnf:show_enums.bnf",
"//docs/generated/sql/bnf:show_full_scans.bnf",
"//docs/generated/sql/bnf:show_functions_stmt.bnf",
"//docs/generated/sql/bnf:show_grants_stmt.bnf",
"//docs/generated/sql/bnf:show_indexes_stmt.bnf",
"//docs/generated/sql/bnf:show_jobs.bnf",
Expand Down
1 change: 1 addition & 0 deletions pkg/sql/delegate/BUILD.bazel
Expand Up @@ -15,6 +15,7 @@ go_library(
"show_enums.go",
"show_full_table_scans.go",
"show_function.go",
"show_functions.go",
"show_grants.go",
"show_jobs.go",
"show_partitions.go",
Expand Down
3 changes: 3 additions & 0 deletions pkg/sql/delegate/delegate.go
Expand Up @@ -127,6 +127,9 @@ func TryDelegate(
case *tree.ShowSyntax:
return d.delegateShowSyntax(t)

case *tree.ShowFunctions:
return d.delegateShowFunctions(t)

case *tree.ShowTables:
return d.delegateShowTables(t)

Expand Down
83 changes: 83 additions & 0 deletions pkg/sql/delegate/show_functions.go
@@ -0,0 +1,83 @@
// Copyright 2022 The Cockroach Authors.
//
// Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt.
//
// As of the Change Date specified in that file, in accordance with
// the Business Source License, use of this software will be governed
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.

package delegate

import (
"fmt"

"github.com/cockroachdb/cockroach/pkg/sql/lexbase"
"github.com/cockroachdb/cockroach/pkg/sql/opt/cat"
"github.com/cockroachdb/cockroach/pkg/sql/sem/catconstants"
"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
)

// delegateShowFunctions implements SHOW FUNCTIONS which returns all the
// user-defined functions.
// Privileges: None.
//
// Notes: postgres does not have a SHOW FUNCTIONS statement.
func (d *delegator) delegateShowFunctions(n *tree.ShowFunctions) (tree.Statement, error) {
flags := cat.Flags{AvoidDescriptorCaches: true}
_, name, err := d.catalog.ResolveSchema(d.ctx, flags, &n.ObjectNamePrefix)
if err != nil {
return nil, err
}
// If we're resolved a one-part name into <db>.public (which is the behavior
// of ResolveSchema, not for any obviously good reason), rework the resolved
// name to have an explicit catalog but no explicit schema. This would arise
// when doing SHOW FUNCTIONS FROM <db>. Without this logic, we would not show the
// tables from other schemas than public.
if name.ExplicitSchema && name.ExplicitCatalog && name.SchemaName == tree.PublicSchemaName &&
n.ExplicitSchema && !n.ExplicitCatalog && n.SchemaName == name.CatalogName {
name.SchemaName, name.ExplicitSchema = "", false
}
var schemaClause string
if name.ExplicitSchema {
schema := lexbase.EscapeSQLString(name.Schema())
if name.Schema() == catconstants.PgTempSchemaName {
schema = lexbase.EscapeSQLString(d.evalCtx.SessionData().SearchPath.GetTemporarySchemaName())
}
schemaClause = fmt.Sprintf("AND n.nspname = %s", schema)
} else {
// These must be custom defined until the sql <-> sql/delegate cyclic dependency
// is resolved. When we have that, we should read the names off "virtualSchemas" instead.
schemaClause = "AND n.nspname NOT IN ('information_schema', 'pg_catalog', 'crdb_internal', 'pg_extension')"
}

const getFunctionsQuery = `
SELECT n.nspname as schema_name,
p.proname as function_name,
pg_catalog.pg_get_function_result(p.oid) as result_data_type,
pg_catalog.pg_get_function_identity_arguments(p.oid) as argument_data_types,
CASE p.prokind
WHEN 'a' THEN 'agg'
WHEN 'w' THEN 'window'
WHEN 'p' THEN 'proc'
ELSE 'func'
END as function_type,
CASE
WHEN p.provolatile = 'i' THEN 'immutable'
WHEN p.provolatile = 's' THEN 'stable'
WHEN p.provolatile = 'v' THEN 'volatile'
END as volatility
FROM %[1]s.pg_catalog.pg_proc p
LEFT JOIN %[1]s.pg_catalog.pg_namespace n ON n.oid = p.pronamespace
WHERE true
%[2]s
ORDER BY 1, 2, 4;
`
query := fmt.Sprintf(
getFunctionsQuery,
&name.CatalogName,
schemaClause,
)
return parse(query)
}
64 changes: 64 additions & 0 deletions pkg/sql/logictest/testdata/logic_test/udf
Expand Up @@ -637,6 +637,70 @@ test public 100137 test_priv_f1() root EXECUTE
test public 100138 test_priv_f2(int8) root EXECUTE true
test test_priv_sc1 100139 test_priv_f3() root EXECUTE true

query TTTTTT colnames
SHOW FUNCTIONS
----
schema_name function_name result_data_type argument_data_types function_type volatility
public a int8 int8 func volatile
public b int8 int8 func volatile
public c int8 int8, int8 func volatile
public d int4 int2 func volatile
public f int8 notmyworkday func immutable
public f_no_ref int8 int8 func immutable
public proc_f int8 int8 func volatile
public proc_f text text, int8 func immutable
public test_priv_f1 int8 · func volatile
public test_priv_f2 int8 int8 func volatile
public test_tbl_f int8 · func immutable
public test_vf_f text · func volatile
public test_vf_g text · func volatile
sc proc_f_2 text text func volatile
test_priv_sc1 test_priv_f3 int8 · func volatile

query TTTTTT colnames
SHOW FUNCTIONS FROM public
----
schema_name function_name result_data_type argument_data_types function_type volatility
public a int8 int8 func volatile
public b int8 int8 func volatile
public c int8 int8, int8 func volatile
public d int4 int2 func volatile
public f int8 notmyworkday func immutable
public f_no_ref int8 int8 func immutable
public proc_f int8 int8 func volatile
public proc_f text text, int8 func immutable
public test_priv_f1 int8 · func volatile
public test_priv_f2 int8 int8 func volatile
public test_tbl_f int8 · func immutable
public test_vf_f text · func volatile
public test_vf_g text · func volatile

query TTTTTT colnames
SHOW FUNCTIONS FROM test_priv_sc1
----
schema_name function_name result_data_type argument_data_types function_type volatility
test_priv_sc1 test_priv_f3 int8 · func volatile

query TTTTTT colnames
SHOW FUNCTIONS FROM test
----
schema_name function_name result_data_type argument_data_types function_type volatility
public a int8 int8 func volatile
public b int8 int8 func volatile
public c int8 int8, int8 func volatile
public d int4 int2 func volatile
public f int8 notmyworkday func immutable
public f_no_ref int8 int8 func immutable
public proc_f int8 int8 func volatile
public proc_f text text, int8 func immutable
public test_priv_f1 int8 · func volatile
public test_priv_f2 int8 int8 func volatile
public test_tbl_f int8 · func immutable
public test_vf_f text · func volatile
public test_vf_g text · func volatile
sc proc_f_2 text text func volatile
test_priv_sc1 test_priv_f3 int8 · func volatile

statement ok
GRANT EXECUTE ON FUNCTION test_priv_f1(), test_priv_f2(int), test_priv_sc1.test_priv_f3 TO udf_test_user WITH GRANT OPTION;

Expand Down
4 changes: 4 additions & 0 deletions pkg/sql/parser/help_test.go
Expand Up @@ -370,6 +370,10 @@ func TestContextualHelp(t *testing.T) {
{`SHOW ENUMS ??`, `SHOW ENUMS`},
{`SHOW TYPES ??`, `SHOW TYPES`},

{`SHOW FUNCTIONS ??`, `SHOW FUNCTIONS`},
{`SHOW FUNCTIONS FROM ??`, `SHOW FUNCTIONS`},
{`SHOW FUNCTIONS FROM blah ??`, `SHOW FUNCTIONS`},

{`SHOW GRANTS ON ??`, `SHOW GRANTS`},
{`SHOW GRANTS ON foo FOR ??`, `SHOW GRANTS`},
{`SHOW GRANTS ON foo FOR bar ??`, `SHOW GRANTS`},
Expand Down
34 changes: 32 additions & 2 deletions pkg/sql/parser/sql.y
Expand Up @@ -1189,6 +1189,7 @@ func (u *sqlSymUnion) functionObjs() tree.FuncObjs {
%type <tree.Statement> show_default_privileges_stmt
%type <tree.Statement> show_enums_stmt
%type <tree.Statement> show_fingerprints_stmt
%type <tree.Statement> show_functions_stmt
%type <tree.Statement> show_grants_stmt
%type <tree.Statement> show_histogram_stmt
%type <tree.Statement> show_indexes_stmt
Expand Down Expand Up @@ -6228,8 +6229,8 @@ zone_value:
// %Text:
// SHOW BACKUP, SHOW CLUSTER SETTING, SHOW COLUMNS, SHOW CONSTRAINTS,
// SHOW CREATE, SHOW CREATE SCHEDULES, SHOW DATABASES, SHOW ENUMS, SHOW
// FUNCTION, SHOW HISTOGRAM, SHOW INDEXES, SHOW PARTITIONS, SHOW JOBS, SHOW
// STATEMENTS, SHOW RANGE, SHOW RANGES, SHOW REGIONS, SHOW SURVIVAL GOAL,
// FUNCTION, SHOW FUNCTIONS, SHOW HISTOGRAM, SHOW INDEXES, SHOW PARTITIONS, SHOW JOBS,
// SHOW STATEMENTS, SHOW RANGE, SHOW RANGES, SHOW REGIONS, SHOW SURVIVAL GOAL,
// SHOW ROLES, SHOW SCHEMAS, SHOW SEQUENCES, SHOW SESSION, SHOW SESSIONS,
// SHOW STATISTICS, SHOW SYNTAX, SHOW TABLES, SHOW TRACE, SHOW TRANSACTION,
// SHOW TRANSACTIONS, SHOW TRANSFER, SHOW TYPES, SHOW USERS, SHOW LAST QUERY STATISTICS,
Expand All @@ -6247,6 +6248,7 @@ show_stmt:
| show_enums_stmt // EXTEND WITH HELP: SHOW ENUMS
| show_types_stmt // EXTEND WITH HELP: SHOW TYPES
| show_fingerprints_stmt
| show_functions_stmt // EXTEND WITH HELP: SHOW FUNCTIONS
| show_grants_stmt // EXTEND WITH HELP: SHOW GRANTS
| show_histogram_stmt // EXTEND WITH HELP: SHOW HISTOGRAM
| show_indexes_stmt // EXTEND WITH HELP: SHOW INDEXES
Expand Down Expand Up @@ -7173,6 +7175,34 @@ show_tables_stmt:
}
| SHOW TABLES error // SHOW HELP: SHOW TABLES

// %Help: SHOW FUNCTIONS - list functions
// %Category: DDL
// %Text: SHOW FUNCTIONS [FROM <databasename> [ . <schemaname> ] ]
show_functions_stmt:
SHOW FUNCTIONS FROM name '.' name
{
$$.val = &tree.ShowFunctions{ObjectNamePrefix:tree.ObjectNamePrefix{
CatalogName: tree.Name($4),
ExplicitCatalog: true,
SchemaName: tree.Name($6),
ExplicitSchema: true,
}}
}
| SHOW FUNCTIONS FROM name
{
$$.val = &tree.ShowFunctions{ObjectNamePrefix:tree.ObjectNamePrefix{
// Note: the schema name may be interpreted as database name,
// see name_resolution.go.
SchemaName: tree.Name($4),
ExplicitSchema: true,
}}
}
| SHOW FUNCTIONS
{
$$.val = &tree.ShowFunctions{}
}
| SHOW FUNCTIONS error // SHOW HELP: SHOW FUNCTIONS

// %Help: SHOW TRANSACTIONS - list open client transactions across the cluster
// %Category: Misc
// %Text: SHOW [ALL] [CLUSTER | LOCAL] TRANSACTIONS
Expand Down
14 changes: 14 additions & 0 deletions pkg/sql/sem/tree/show.go
Expand Up @@ -439,6 +439,20 @@ func (node *ShowTables) Format(ctx *FmtCtx) {
}
}

// ShowFunctions represents a SHOW FUNCTIONS statement.
type ShowFunctions struct {
ObjectNamePrefix
}

// Format implements the NodeFormatter interface.
func (node *ShowFunctions) Format(ctx *FmtCtx) {
ctx.WriteString("SHOW FUNCTIONS")
if node.ExplicitSchema {
ctx.WriteString(" FROM ")
ctx.FormatNode(&node.ObjectNamePrefix)
}
}

// ShowTransactions represents a SHOW TRANSACTIONS statement
type ShowTransactions struct {
All bool
Expand Down
10 changes: 10 additions & 0 deletions pkg/sql/sem/tree/stmt.go
Expand Up @@ -1761,6 +1761,15 @@ func (*ShowTables) StatementType() StatementType { return TypeDML }
// StatementTag returns a short string identifying the type of statement.
func (*ShowTables) StatementTag() string { return "SHOW TABLES" }

// StatementReturnType implements the Statement interface.
func (*ShowFunctions) StatementReturnType() StatementReturnType { return Rows }

// StatementType implements the Statement interface.
func (*ShowFunctions) StatementType() StatementType { return TypeDML }

// StatementTag returns a short string identifying the type of statement.
func (*ShowFunctions) StatementTag() string { return "SHOW FUNCTIONS" }

// StatementReturnType implements the Statement interface
func (*ShowTransactions) StatementReturnType() StatementReturnType { return Rows }

Expand Down Expand Up @@ -2131,6 +2140,7 @@ func (n *ShowEnums) String() string { return AsString(
func (n *ShowFullTableScans) String() string { return AsString(n) }
func (n *ShowCreateFunction) String() string { return AsString(n) }
func (n *ShowCreateExternalConnections) String() string { return AsString(n) }
func (n *ShowFunctions) String() string { return AsString(n) }
func (n *ShowGrants) String() string { return AsString(n) }
func (n *ShowHistogram) String() string { return AsString(n) }
func (n *ShowSchedules) String() string { return AsString(n) }
Expand Down

0 comments on commit a84835a

Please sign in to comment.