Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support default as params for function and procedure #242

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions src/backend/optimizer/util/clauses.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,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 @@ -92,6 +93,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 @@ -129,6 +131,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 @@ -4050,6 +4054,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 @@ -4129,6 +4146,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 @@ -1489,8 +1489,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 @@ -1522,10 +1532,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)
forestkeeper marked this conversation as resolved.
Show resolved Hide resolved
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 */
Loading