Skip to content

Commit

Permalink
Merge pull request #103364 from rytaft/backport23.1-102860
Browse files Browse the repository at this point in the history
release-23.1: sql: add relevant udfs to statement bundles (#103364)

Co-Authored-By: Eric.Yang <[email protected]>
  • Loading branch information
rytaft and Eric.Yang authored May 16, 2023
2 parents e07095e + b6d81db commit 830d80e
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 1 deletion.
39 changes: 39 additions & 0 deletions pkg/sql/explain_bundle.go
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,13 @@ func (b *stmtBundleBuilder) addEnv(ctx context.Context) {
fmt.Fprintf(&buf, "-- error getting schema for sequence %s: %v\n", sequences[i].String(), err)
}
}
if len(mem.Metadata().AllUserDefinedFunctions()) != 0 {
// Get all relevant user-defined functions.
blankLine()
if err := c.PrintRelevantCreateUdf(&buf, strings.ToLower(b.stmt), b.flags.RedactValues); err != nil {
fmt.Fprintf(&buf, "-- error getting schema for udfs: %v\n", err)
}
}
for i := range tables {
blankLine()
if err := c.PrintCreateTable(&buf, &tables[i], b.flags.RedactValues); err != nil {
Expand Down Expand Up @@ -796,6 +803,38 @@ func (c *stmtEnvCollector) PrintCreateSequence(w io.Writer, tn *tree.TableName)
return nil
}

func (c *stmtEnvCollector) PrintRelevantCreateUdf(
w io.Writer, stmt string, redactValues bool,
) error {
// The select function_name returns a DOidWrapper,
// we need to cast it to string for queryRows function to process.
// TODO: consider getting the udf sql body statements from the memo metadata.
functionNameQuery := "SELECT function_name::STRING as function_name_str FROM [SHOW FUNCTIONS]"
udfNames, err := c.queryRows(functionNameQuery)
if err != nil {
return err
}
for _, name := range udfNames {
if strings.Contains(stmt, name) {
createFunctionQuery := fmt.Sprintf(
"SELECT create_statement FROM [ SHOW CREATE FUNCTION \"%s\" ]", name,
)
if redactValues {
createFunctionQuery = fmt.Sprintf(
"SELECT crdb_internal.redact(crdb_internal.redactable_sql_constants(create_statement)) FROM [ SHOW CREATE FUNCTION \"%s\" ]", name,
)
}
createStatement, err := c.query(createFunctionQuery)
if err != nil {
fmt.Fprintf(w, "-- error getting user defined function %s: %s\n", name, err)
continue
}
fmt.Fprintf(w, "%s\n", createStatement)
}
}
return nil
}

func (c *stmtEnvCollector) PrintCreateView(
w io.Writer, tn *tree.TableName, redactValues bool,
) error {
Expand Down
24 changes: 23 additions & 1 deletion pkg/sql/explain_bundle_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -287,8 +287,9 @@ CREATE TABLE users(id UUID DEFAULT gen_random_uuid() PRIMARY KEY, promo_id INT R
r.Exec(t, "CREATE TABLE pterosaur (cardholder STRING PRIMARY KEY, cardno INT, INDEX (cardno));")
r.Exec(t, "INSERT INTO pterosaur VALUES ('pterodactyl', 5555555555554444);")
r.Exec(t, "CREATE STATISTICS jurassic FROM pterosaur;")
r.Exec(t, "CREATE FUNCTION test_redact() RETURNS STRING AS $body$ SELECT 'pterodactyl' $body$ LANGUAGE sql;")
rows := r.QueryStr(t,
"EXPLAIN ANALYZE (DEBUG, REDACT) SELECT max(cardno) FROM pterosaur WHERE cardholder = 'pterodactyl'",
"EXPLAIN ANALYZE (DEBUG, REDACT) SELECT max(cardno), test_redact() FROM pterosaur WHERE cardholder = 'pterodactyl'",
)
verboten := []string{"pterodactyl", "5555555555554444", fmt.Sprintf("%x", 5555555555554444)}
checkBundle(
Expand All @@ -304,6 +305,27 @@ CREATE TABLE users(id UUID DEFAULT gen_random_uuid() PRIMARY KEY, promo_id INT R
plans, "statement.sql stats-defaultdb.public.pterosaur.sql env.sql vec.txt vec-v.txt",
)
})

t.Run("udfs", func(t *testing.T) {
r.Exec(t, "CREATE FUNCTION add(a INT, b INT) RETURNS INT IMMUTABLE LEAKPROOF LANGUAGE SQL AS 'SELECT a + b';")
r.Exec(t, "CREATE FUNCTION subtract(a INT, b INT) RETURNS INT IMMUTABLE LEAKPROOF LANGUAGE SQL AS 'SELECT a - b';")
rows := r.QueryStr(t, "EXPLAIN ANALYZE (DEBUG) SELECT add(3, 4);")
checkBundle(
t, fmt.Sprint(rows), "add", func(name, contents string) error {
if name == "schema.sql" {
reg := regexp.MustCompile("add")
if reg.FindString(contents) == "" {
return errors.Errorf("could not find definition for 'add' function in schema.sql")
}
reg = regexp.MustCompile("subtract")
if reg.FindString(contents) != "" {
return errors.Errorf("Found irrelevant user defined function 'substract' in schema.sql")
}
}
return nil
}, base, plans,
"distsql-1-subquery.html distsql-2-main-query.html vec-1-subquery-v.txt vec-1-subquery.txt vec-2-main-query-v.txt vec-2-main-query.txt")
})
}

// checkBundle searches text strings for a bundle URL and then verifies that the
Expand Down
5 changes: 5 additions & 0 deletions pkg/sql/opt/metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,11 @@ func (md *Metadata) AllUserDefinedTypes() []*types.T {
return md.userDefinedTypesSlice
}

// AllUserDefinedFunctions returns all user defined functions used in this query.
func (md *Metadata) AllUserDefinedFunctions() map[cat.StableID]*tree.Overload {
return md.udfDeps
}

// AddUserDefinedFunction adds a user-defined function to the metadata for this
// query. If the function was resolved by name, the name will also be tracked.
func (md *Metadata) AddUserDefinedFunction(
Expand Down

0 comments on commit 830d80e

Please sign in to comment.