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 #1955

Merged
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
107 changes: 107 additions & 0 deletions contrib/babelfishpg_tsql/src/hooks.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,9 @@ static int find_attr_by_name_from_relation(Relation rd, const char *attname, boo
static void pre_transform_insert(ParseState *pstate, InsertStmt *stmt, Query *query);
static void modify_RangeTblFunction_tupdesc(char *funcname, Node *expr, TupleDesc *tupdesc);
static void sort_nulls_first(SortGroupClause * sortcl, bool reverse);
static int getDefaultPosition(const List *default_positions, const ListCell *def_idx, int argPosition);
static List* replace_pltsql_function_defaults(HeapTuple func_tuple, List *defaults, List *fargs);


/*****************************************
* Commands Hooks
Expand Down Expand Up @@ -202,6 +205,7 @@ static bbfViewHasInsteadofTrigger_hook_type prev_bbfViewHasInsteadofTrigger_hook
static detect_numeric_overflow_hook_type prev_detect_numeric_overflow_hook = NULL;
static match_pltsql_func_call_hook_type prev_match_pltsql_func_call_hook = NULL;
static insert_pltsql_function_defaults_hook_type prev_insert_pltsql_function_defaults_hook = NULL;
static replace_pltsql_function_defaults_hook_type prev_replace_pltsql_function_defaults_hook = NULL;
static print_pltsql_function_arguments_hook_type prev_print_pltsql_function_arguments_hook = NULL;
static planner_hook_type prev_planner_hook = NULL;
static transform_check_constraint_expr_hook_type prev_transform_check_constraint_expr_hook = NULL;
Expand Down Expand Up @@ -322,6 +326,9 @@ InstallExtendedHooks(void)
prev_insert_pltsql_function_defaults_hook = insert_pltsql_function_defaults_hook;
insert_pltsql_function_defaults_hook = insert_pltsql_function_defaults;

prev_replace_pltsql_function_defaults_hook = replace_pltsql_function_defaults_hook;
replace_pltsql_function_defaults_hook = replace_pltsql_function_defaults;

prev_print_pltsql_function_arguments_hook = print_pltsql_function_arguments_hook;
print_pltsql_function_arguments_hook = print_pltsql_function_arguments;

Expand Down Expand Up @@ -420,6 +427,7 @@ UninstallExtendedHooks(void)
detect_numeric_overflow_hook = prev_detect_numeric_overflow_hook;
match_pltsql_func_call_hook = prev_match_pltsql_func_call_hook;
insert_pltsql_function_defaults_hook = prev_insert_pltsql_function_defaults_hook;
replace_pltsql_function_defaults_hook = prev_replace_pltsql_function_defaults_hook;
print_pltsql_function_arguments_hook = prev_print_pltsql_function_arguments_hook;
planner_hook = prev_planner_hook;
transform_check_constraint_expr_hook = prev_transform_check_constraint_expr_hook;
Expand Down Expand Up @@ -3528,6 +3536,105 @@ PlTsqlMatchNamedCall(HeapTuple proctup, int nargs, List *argnames,
return true;
}

static int getDefaultPosition(const List *default_positions, const ListCell *def_idx, int argPosition)
{
int currPosition = intVal((Node *) lfirst(def_idx));
while (currPosition != argPosition)
{
def_idx = lnext(default_positions, def_idx);
if (def_idx == NULL)
{
elog(ERROR, "not enough default arguments");
return -1;
}
currPosition = intVal((Node *) lfirst(def_idx));
}
return list_cell_number(default_positions, def_idx);
}

/**
* @brief farg position default should get the corresponding default position value
*
* @param func_tuple
* @param defaults
* @param fargs
* @return List*
*/
static List*
replace_pltsql_function_defaults(HeapTuple func_tuple, List *defaults, List *fargs)

{
HeapTuple bbffunctuple;

if (sql_dialect != SQL_DIALECT_TSQL)
return fargs;

bbffunctuple = get_bbf_function_tuple_from_proctuple(func_tuple);
forestkeeper marked this conversation as resolved.
Show resolved Hide resolved

if (HeapTupleIsValid(bbffunctuple)){
Datum arg_default_positions;
bool isnull;
char *str;
List *default_positions = NIL, *ret = NIL;
ListCell *def_idx;
ListCell *lc;
int position,i,j;

/* Fetch default positions */
arg_default_positions = SysCacheGetAttr(PROCNSPSIGNATURE,
bbffunctuple,
Anum_bbf_function_ext_default_positions,
&isnull);

if (isnull)
elog(ERROR, "not enough default arguments");

str =TextDatumGetCString(arg_default_positions);
default_positions = castNode(List, stringToNode(str));
pfree(str);

def_idx = list_head(default_positions);
i = 0;

foreach(lc, fargs)
{
if (nodeTag((Node*)lfirst(lc)) == T_RelabelType &&
nodeTag(((RelabelType*)lfirst(lc))->arg) == T_SetToDefault)
{
position = getDefaultPosition(default_positions, def_idx, i);
ret = lappend(ret, list_nth(defaults, position));
}
else if (nodeTag((Node*)lfirst(lc)) == T_FuncExpr)
{
if(((FuncExpr*)lfirst(lc))->funcformat == COERCE_IMPLICIT_CAST &&
nodeTag(linitial(((FuncExpr*)lfirst(lc))->args)) == T_SetToDefault)
{
// We'll keep the implicit cast function when it needs implicit cast
FuncExpr *funcExpr = (FuncExpr*)lfirst(lc);
List *newArgs = NIL;
position = getDefaultPosition(default_positions, def_idx, i);
newArgs = lappend(newArgs, list_nth(defaults, position));
for (j = 1; j < list_length(funcExpr->args); ++j)
newArgs = lappend(newArgs, list_nth(funcExpr->args, j));
funcExpr->args = newArgs;
ret = lappend(ret, funcExpr);
}
}
else ret = lappend(ret, lfirst(lc));
++i;
}
return ret;

ReleaseSysCache(bbffunctuple);
}
else
{
elog(ERROR, "Can't use default in this function or procedure");
}

return fargs;
}

/*
* insert_pltsql_function_defaults
* Given a pg_proc heap tuple of a PL/tsql function and list of defaults,
Expand Down
17 changes: 0 additions & 17 deletions contrib/babelfishpg_tsql/src/tsqlUnsupportedFeatureHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,11 +192,9 @@ class TsqlUnsupportedFeatureHandlerImpl : public TsqlUnsupportedFeatureHandler
antlrcpp::Any visitOdbc_scalar_function(TSqlParser::Odbc_scalar_functionContext *ctx) override { handle(INSTR_UNSUPPORTED_TSQL_ODBC_SCALAR_FUNCTION, "ODBC scalar functions", getLineAndPos(ctx)); return visitChildren(ctx); }
antlrcpp::Any visitPartition_function_call(TSqlParser::Partition_function_callContext *ctx) override { handle(INSTR_UNSUPPORTED_TSQL_PARTITION_FUNCTION, "partition function", getLineAndPos(ctx)); return visitChildren(ctx); }

antlrcpp::Any visitDefault_expr(TSqlParser::Default_exprContext *ctx) override;
antlrcpp::Any visitHierarchyid_coloncolon(TSqlParser::Hierarchyid_coloncolonContext *ctx) override { handle(INSTR_UNSUPPORTED_TSQL_EXPRESSION_HIERARCHID, "hierarchid", getLineAndPos(ctx)); return visitChildren(ctx); }
antlrcpp::Any visitOdbc_literal_expr(TSqlParser::Odbc_literal_exprContext *ctx) override { handle(INSTR_UNSUPPORTED_TSQL_EXPRESSION_ODBC_LITERAL, "odbc literal", getLineAndPos(ctx)); return visitChildren(ctx); }
antlrcpp::Any visitDollar_action_expr(TSqlParser::Dollar_action_exprContext *ctx) override { handle(INSTR_UNSUPPORTED_TSQL_EXPRESSION_DOLLAR_ACTION, "$ACTION", getLineAndPos(ctx)); return visitChildren(ctx); }
antlrcpp::Any visitExecute_parameter(TSqlParser::Execute_parameterContext *ctx) override;

antlrcpp::Any visitFunc_proc_name_schema(TSqlParser::Func_proc_name_schemaContext *ctx) override;
antlrcpp::Any visitFunc_proc_name_database_schema(TSqlParser::Func_proc_name_database_schemaContext *ctx) override;
Expand Down Expand Up @@ -1401,21 +1399,6 @@ antlrcpp::Any TsqlUnsupportedFeatureHandlerImpl::visitAggregate_windowed_functio
return visitChildren(ctx);
}

antlrcpp::Any TsqlUnsupportedFeatureHandlerImpl::visitDefault_expr(TSqlParser::Default_exprContext *ctx)
{
TSqlParser::Expression_listContext *pctx = dynamic_cast<TSqlParser::Expression_listContext *>(ctx->parent);
if (!pctx || dynamic_cast<TSqlParser::Table_value_constructorContext *>(pctx->parent) == nullptr) /* if DEFAULT expression is used for VALUES ..., accept it */
handle(INSTR_UNSUPPORTED_TSQL_EXPRESSION_DEFAULT, ctx->DEFAULT());
return visitChildren(ctx);
}

antlrcpp::Any TsqlUnsupportedFeatureHandlerImpl::visitExecute_parameter(TSqlParser::Execute_parameterContext *ctx)
{
if (ctx->DEFAULT())
handle(INSTR_UNSUPPORTED_TSQL_EXECUTE_PARAMETER_DEFAULT, ctx->DEFAULT());
return visitChildren(ctx);
}

antlrcpp::Any TsqlUnsupportedFeatureHandlerImpl::visitTrigger_column_updated(TSqlParser::Trigger_column_updatedContext *ctx)
{
if (!is_inside_trigger && pltsql_curr_compile->fn_is_trigger == PLTSQL_NOT_TRIGGER){
Expand Down
4 changes: 2 additions & 2 deletions test/JDBC/expected/BABEL-UNSUPPORTED.out
Original file line number Diff line number Diff line change
Expand Up @@ -2676,14 +2676,14 @@ select func1(DEFAULT);
GO
~~ERROR (Code: 33557097)~~

~~ERROR (Message: 'DEFAULT' is not currently supported in Babelfish)~~
~~ERROR (Message: function func1(unknown) does not exist)~~


EXEC proc1 DEFAULT;
GO
~~ERROR (Code: 33557097)~~

~~ERROR (Message: 'DEFAULT' is not currently supported in Babelfish)~~
~~ERROR (Message: procedure proc1(unknown) does not exist)~~


-- NATIONAL/VARYING (BABEL-2360/2361)
Expand Down
20 changes: 20 additions & 0 deletions test/JDBC/expected/default_params-vu-cleanup.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
drop function default_params_func1;
GO

drop function default_params_func2;
GO

drop function default_params_func3;
GO

drop procedure default_params_proc1;
GO

drop procedure default_params_proc2;
GO

drop procedure default_params_proc3
GO

drop procedure default_params_proc4
GO
21 changes: 21 additions & 0 deletions test/JDBC/expected/default_params-vu-prepare.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
create function default_params_func1 (@p1 int=1,@p2 int = 2 ) returns int as begin return @p1 + @p2 end;
GO

create function default_params_func2 (@p1 int,@p2 int =2, @p3 int) returns int as begin return @p1 + @p2 + @p3 end;
GO

create function default_params_func3 (@p1 varchar(20) = 'abc') returns varchar as begin return @p1 end;
GO

create proc default_params_proc1 @p1 int=1, @p2 int=2, @p3 int=3 as select @p1, @p2, @p3
GO


create proc default_params_proc2 (@p1 varchar(20) = 'abc', @p2 int) as select @p1, @p2
GO

create proc default_params_proc3 (@p1 varchar = 'abc', @p2 int) as select @p1, @p2
GO

create proc default_params_proc4 @p1 int=1, @p2 int=2, @p3 varchar(20)='dbb' as select @p1, @p2, @p3
GO
143 changes: 143 additions & 0 deletions test/JDBC/expected/default_params-vu-verify.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
select default_params_func1(default, default);
GO
~~START~~
int
3
~~END~~


select default_params_func1(10, default);
GO
~~START~~
int
12
~~END~~


select default_params_func1(10);
GO
~~START~~
int
12
~~END~~


select default_params_func1();
GO
~~START~~
int
3
~~END~~


select default_params_func1(default);
GO
~~START~~
int
3
~~END~~


select default_params_func2(10,default,20);
GO
~~START~~
int
32
~~END~~


select default_params_func2(10,20,30);
GO
~~START~~
int
60
~~END~~


select default_params_func3(default);
go
~~START~~
varchar
a
~~END~~


select default_params_func3();
GO
~~START~~
varchar
a
~~END~~


select default_params_func3('dddd');
GO
~~START~~
varchar
d
~~END~~


exec default_params_proc1 111, default, 333
GO
~~START~~
int#!#int#!#int
111#!#2#!#333
~~END~~


exec default_params_proc1 default, default, default
GO
~~START~~
int#!#int#!#int
1#!#2#!#3
~~END~~


exec default_params_proc1 default
GO
~~START~~
int#!#int#!#int
1#!#2#!#3
~~END~~


exec default_params_proc2 default, 2
GO
~~START~~
varchar#!#int
abc#!#2
~~END~~


exec default_params_proc2 'dddd', 2
GO
~~START~~
varchar#!#int
dddd#!#2
~~END~~


exec default_params_proc3 default, 2
GO
~~START~~
varchar#!#int
a#!#2
~~END~~


exec default_params_proc3 'dddd', 3
GO
~~START~~
varchar#!#int
d#!#3
~~END~~


exec default_params_proc4 1,2,default
GO
~~START~~
int#!#int#!#varchar
1#!#2#!#dbb
~~END~~

Loading