Skip to content

Commit

Permalink
Support default as params for function and procedure (babelfish-for-p…
Browse files Browse the repository at this point in the history
…ostgresql#242)

* Support default as params for function and procedure

Previously when we call functions/procedures, we don't support default
keyword usage like :

select foofunc(default);
or
exec fooproc default

This commit support to use default keyword as function or procedure
param when the default value is previously defined in create proc/func

Task: BABEL-335
Signed-off-by: Zhibai Song <[email protected]>
  • Loading branch information
forestkeeper authored and priyansx committed Nov 22, 2023
1 parent a011fbb commit a0bb316
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 8 deletions.
60 changes: 60 additions & 0 deletions src/backend/optimizer/util/clauses.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
#include "optimizer/plancat.h"
#include "optimizer/planmain.h"
#include "parser/analyze.h"
#include "parser/parser.h"
#include "parser/parse_agg.h"
#include "parser/parse_coerce.h"
#include "parser/parse_func.h"
Expand Down Expand Up @@ -96,6 +97,7 @@ typedef struct
} max_parallel_hazard_context;

insert_pltsql_function_defaults_hook_type insert_pltsql_function_defaults_hook = NULL;
replace_pltsql_function_defaults_hook_type replace_pltsql_function_defaults_hook = NULL;

static bool contain_agg_clause_walker(Node *node, void *context);
static bool find_window_functions_walker(Node *node, WindowFuncLists *lists);
Expand Down Expand Up @@ -133,6 +135,8 @@ static Expr *simplify_function(Oid funcid,
eval_const_expressions_context *context);
static List *reorder_function_arguments(List *args, int pronargs,
HeapTuple func_tuple);
static List *replace_function_defaults(List *args, HeapTuple func_tuple, bool *need_replace);

static List *add_function_defaults(List *args, int pronargs,
HeapTuple func_tuple);
static List *fetch_function_defaults(HeapTuple func_tuple);
Expand Down Expand Up @@ -4127,6 +4131,19 @@ expand_function_arguments(List *args, bool include_out_arguments,
func_tuple);
}

/* Not add else here, for the reason to also replace the default keyword after add function defaults */
if (list_length(args) == pronargs && sql_dialect == SQL_DIALECT_TSQL)
{
bool need_replace = false;
args = replace_function_defaults(args, func_tuple, &need_replace);
if (need_replace)
{
recheck_cast_function_args(args, result_type,
proargtypes, pronargs,
func_tuple);
}
}

return args;
}

Expand Down Expand Up @@ -4206,6 +4223,49 @@ reorder_function_arguments(List *args, int pronargs, HeapTuple func_tuple)
return args;
}

/*
* replace_function_defaults: replace default keyword item with default values
*/
static List *
replace_function_defaults(List *args, HeapTuple func_tuple, bool *need_replace)
{
List *defaults;
ListCell *lc;
List *ret = NIL;
int nargs = list_length(args);

*need_replace = false;
if (nargs == 0)
return args;

foreach(lc, args)
{
if (nodeTag((Node*)lfirst(lc)) == T_RelabelType)
{
if( nodeTag(((RelabelType*)lfirst(lc))->arg) == T_SetToDefault)
*need_replace = true;
}
else if (nodeTag((Node*)lfirst(lc)) == T_FuncExpr)
{
if(((FuncExpr*)lfirst(lc))->funcformat == COERCE_IMPLICIT_CAST &&
nodeTag(linitial(((FuncExpr*)lfirst(lc))->args)) == T_SetToDefault)
*need_replace = true;
}
}

if (!(*need_replace))
return args;

/* Get all the default expressions from the pg_proc tuple */
defaults = fetch_function_defaults(func_tuple);

if (replace_pltsql_function_defaults_hook)
ret = replace_pltsql_function_defaults_hook(func_tuple, defaults, args);
else return args;

return ret;
}

/*
* add_function_defaults: add missing function arguments from its defaults
*
Expand Down
16 changes: 13 additions & 3 deletions src/backend/parser/analyze.c
Original file line number Diff line number Diff line change
Expand Up @@ -3119,9 +3119,19 @@ transformCallStmt(ParseState *pstate, CallStmt *stmt)
targs = NIL;
foreach(lc, stmt->funccall->args)
{
targs = lappend(targs, transformExpr(pstate,
(Node *) lfirst(lc),
EXPR_KIND_CALL_ARGUMENT));
if (sql_dialect == SQL_DIALECT_TSQL && nodeTag((Node*)lfirst(lc)) == T_SetToDefault)
{
// For Tsql Default in function call, we set it to UNKNOWN in parser stage
// In analyzer it'll use other types to detect the right func candidate
((SetToDefault *)lfirst(lc))->typeId = UNKNOWNOID;
targs = lappend(targs, (Node *) lfirst(lc));
}
else
{
targs = lappend(targs, transformExpr(pstate,
(Node *) lfirst(lc),
EXPR_KIND_CALL_ARGUMENT));
}
}

node = ParseFuncOrColumn(pstate,
Expand Down
4 changes: 4 additions & 0 deletions src/backend/parser/parse_coerce.c
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,10 @@ coerce_type(ParseState *pstate, Node *node,
/* no conversion needed */
return node;
}
if (nodeTag((Node*)node) == T_SetToDefault)
{
return node;
}
if (targetTypeId == ANYOID ||
targetTypeId == ANYELEMENTOID ||
targetTypeId == ANYNONARRAYOID ||
Expand Down
22 changes: 17 additions & 5 deletions src/backend/parser/parse_expr.c
Original file line number Diff line number Diff line change
Expand Up @@ -1551,8 +1551,18 @@ transformFuncCall(ParseState *pstate, FuncCall *fn)
targs = NIL;
foreach(args, fn->args)
{
targs = lappend(targs, transformExprRecurse(pstate,
if (sql_dialect == SQL_DIALECT_TSQL && nodeTag((Node*)lfirst(args)) == T_SetToDefault)
{
// For Tsql Default in function call, we set it to UNKNOWN in parser stage
// In analyzer it'll use other types to detect the right func candidate
((SetToDefault *)lfirst(args))->typeId = UNKNOWNOID;
targs = lappend(targs, (Node *) lfirst(args));
}
else
{
targs = lappend(targs, transformExprRecurse(pstate,
(Node *) lfirst(args)));
}
}

/*
Expand Down Expand Up @@ -1584,10 +1594,12 @@ transformFuncCall(ParseState *pstate, FuncCall *fn)
*/

if (!schemaname || (strlen(schemaname) == 3 && strncmp(schemaname, "sys", 3) == 0))
if (strlen(functionname) == 8 &&
strncmp(functionname, "checksum", 8) == 0 &&
fn->agg_star == true)
targs = ExpandChecksumStar(pstate, fn, fn->location);
{
if (strlen(functionname) == 8 &&
strncmp(functionname, "checksum", 8) == 0 &&
fn->agg_star == true)
targs = ExpandChecksumStar(pstate, fn, fn->location);
}

/* ... and hand off to ParseFuncOrColumn */
return ParseFuncOrColumn(pstate,
Expand Down
3 changes: 3 additions & 0 deletions src/include/optimizer/clauses.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,7 @@ extern Bitmapset *pull_paramids(Expr *expr);
typedef void (*insert_pltsql_function_defaults_hook_type)(HeapTuple func_tuple, List *defaults, Node **argarray);
extern PGDLLIMPORT insert_pltsql_function_defaults_hook_type insert_pltsql_function_defaults_hook;

typedef List* (*replace_pltsql_function_defaults_hook_type)(HeapTuple func_tuple, List *defaults, List *fargs);
extern PGDLLIMPORT replace_pltsql_function_defaults_hook_type replace_pltsql_function_defaults_hook;

#endif /* CLAUSES_H */

0 comments on commit a0bb316

Please sign in to comment.