Skip to content

Commit

Permalink
sql: deserialize user defined type OIDs in UDF body
Browse files Browse the repository at this point in the history
Release note: None.
Release justification: low risk display enhancement.
  • Loading branch information
chengxiong-ruan committed Sep 7, 2022
1 parent 0d5f6e4 commit c400eec
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 2 deletions.
6 changes: 5 additions & 1 deletion pkg/sql/crdb_internal.go
Original file line number Diff line number Diff line change
Expand Up @@ -2648,7 +2648,11 @@ CREATE TABLE crdb_internal.create_function_statements (
}
for i := range treeNode.Options {
if body, ok := treeNode.Options[i].(tree.FunctionBodyStr); ok {
seqReplacedBody, err := formatQuerySequencesForDisplay(ctx, &p.semaCtx, string(body), true /* multiStmt */)
typeReplacedBody, err := formatFunctionQueryTypesForDisplay(ctx, &p.semaCtx, p.SessionData(), string(body))
if err != nil {
return err
}
seqReplacedBody, err := formatQuerySequencesForDisplay(ctx, &p.semaCtx, typeReplacedBody, true /* multiStmt */)
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/sql/logictest/testdata/logic_test/udf
Original file line number Diff line number Diff line change
Expand Up @@ -1251,7 +1251,7 @@ CREATE FUNCTION public.f_udt_rewrite()
CALLED ON NULL INPUT
LANGUAGE SQL
AS $$
SELECT b'@':::@100115;
SELECT 'Monday':::test.public.notmyworkday;
$$

query T
Expand Down
71 changes: 71 additions & 0 deletions pkg/sql/show_create_clauses.go
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,77 @@ func formatViewQueryTypesForDisplay(
return newStmt.String(), nil
}

// formatFunctionQueryTypesForDisplay is similar to
// formatViewQueryTypesForDisplay but can only be used for function.
// nil is used as the table descriptor for schemaexpr.FormatExprForDisplay call.
// This is fine assuming that UDFs cannot be created with expression casting a
// column/var to an enum in function body. This is super rare case for now, and
// it's tracked with issue #87475. We should also unify this function with
// formatViewQueryTypesForDisplay.
func formatFunctionQueryTypesForDisplay(
ctx context.Context,
semaCtx *tree.SemaContext,
sessionData *sessiondata.SessionData,
queries string,
) (string, error) {
replaceFunc := func(expr tree.Expr) (recurse bool, newExpr tree.Expr, err error) {
// We need to resolve the type to check if it's user-defined. If not,
// no other work is needed.
var typRef tree.ResolvableTypeReference
switch n := expr.(type) {
case *tree.CastExpr:
typRef = n.Type
case *tree.AnnotateTypeExpr:
typRef = n.Type
default:
return true, expr, nil
}
var typ *types.T
typ, err = tree.ResolveType(ctx, typRef, semaCtx.TypeResolver)
if err != nil {
return false, expr, err
}
if !typ.UserDefined() {
return true, expr, nil
}
formattedExpr, err := schemaexpr.FormatExprForDisplay(
ctx, nil, expr.String(), semaCtx, sessionData, tree.FmtParsable,
)
if err != nil {
return false, expr, err
}
newExpr, err = parser.ParseExpr(formattedExpr)
if err != nil {
return false, expr, err
}
return false, newExpr, nil
}

var stmts tree.Statements
parsedStmts, err := parser.Parse(queries)
if err != nil {
return "", errors.Wrap(err, "failed to parse query")
}
stmts = make(tree.Statements, len(parsedStmts))
for i, stmt := range parsedStmts {
stmts[i] = stmt.AST
}

fmtCtx := tree.NewFmtCtx(tree.FmtSimple)
for i, stmt := range stmts {
newStmt, err := tree.SimpleStmtVisit(stmt, replaceFunc)
if err != nil {
return "", err
}
if i > 0 {
fmtCtx.WriteString("\n")
}
fmtCtx.FormatNode(newStmt)
fmtCtx.WriteString(";")
}
return fmtCtx.CloseAndGetString(), nil
}

// showComments prints out the COMMENT statements sufficient to populate a
// table's comments, including its index and column comments.
func showComments(
Expand Down

0 comments on commit c400eec

Please sign in to comment.