mdayakar commented on code in PR #5084:
URL: https://github.com/apache/hive/pull/5084#discussion_r1502679370
##########
hplsql/src/main/java/org/apache/hive/hplsql/functions/InMemoryFunctionRegistry.java:
##########
@@ -132,39 +133,84 @@ private boolean execProc(String name,
HplsqlParser.Expr_func_paramsContext ctx)
/**
* Set parameters for user-defined function call
*/
- public static void setCallParameters(String procName,
HplsqlParser.Expr_func_paramsContext actual, ArrayList<Var> actualValues,
- HplsqlParser.Create_routine_paramsContext formal,
- HashMap<String, Var> out,
- Exec exec) {
- if (actual == null || actual.func_param() == null || actualValues == null)
{
+ public static void setCallParameters(String procName,
HplsqlParser.Expr_func_paramsContext actual,
+ ArrayList<Var> actualValues, HplsqlParser.Create_routine_paramsContext
formal, HashMap<String, Var> out,
+ Exec exec) {
+ // if it is a non-parameter function then just return.
+ if (actual == null && formal == null) {
return;
}
- int actualCnt = actualValues.size();
- int formalCnt = formal.create_routine_param_item().size();
- if (formalCnt != actualCnt) {
- throw new ArityException(actual.getParent(), procName, formalCnt,
actualCnt);
+ int actualCnt = (actualValues == null) ? 0 : actualValues.size();
+ int passedParamCnt = actualCnt;
+ List<HplsqlParser.Create_routine_param_itemContext> routineParamItem =
formal.create_routine_param_item();
+ int formalCnt = routineParamItem.size();
+ ParserRuleContext ruleContext = (actual == null) ? null :
actual.getParent();
+ if (actualCnt > formalCnt) {
+ throw new ArityException(ruleContext, procName, formalCnt, actualCnt);
}
- for (int i = 0; i < actualCnt; i++) {
- HplsqlParser.ExprContext a = actual.func_param(i).expr();
- HplsqlParser.Create_routine_param_itemContext p =
getCallParameter(actual, formal, i);
- String name = p.ident().getText();
- String type = p.dtype().getText();
- String len = null;
- String scale = null;
- if (p.dtype_len() != null) {
- len = p.dtype_len().L_INT(0).getText();
- if (p.dtype_len().L_INT(1) != null) {
- scale = p.dtype_len().L_INT(1).getText();
- }
+ Map<String, Integer> defaultParamNamesVsIndexes = new HashMap<>();
+ if (actualCnt != formalCnt) {
+ populateDefaultParamDetails(routineParamItem, formalCnt,
defaultParamNamesVsIndexes);
+ actualCnt = actualCnt + defaultParamNamesVsIndexes.size();
+ if (actualCnt < formalCnt) {
+ throw new ArityException(ruleContext, procName, formalCnt,
passedParamCnt);
+ }
Review Comment:
> actualCnt can be higher then formalCnt. Let's say we have a function with
2 formal parameters both has default values. When calling the function we pass
only one actual parameter. The result is actualCnt = 1 + 2 = 3 which is
incorrect.
Here `actualCnt` contains the actual parameters passed + all default
parameters of the procedure. Which can be greater than `formalCnt` as user can
pass values for some default params along with non-default params. For the same
example a function with 2 formal parameters both has default values. When
calling the function we pass only one actual parameter then `actualCnt = 1 + 2
= 3` is correct why because user passed one parameter and for other parameter
we take default value and execute the procedure. Thats why here we are checking
only `actualCnt < formalCnt`.
> What is the purpose of this check here? if (actualCnt < formalCnt)
As explained above if user passes lesser parameters than the required
parameters then we should throw exception. For example if a function has 5
total params, in that lets say 2 default params, so here user has to pass
minimum 3 param values but if user passes only 2 then 2+2=4 which is lesser
than formal count so need to throw exception.
> The check in the end of the method should catch such cases too
if ((passedParamCnt + defaultParamNamesVsIndexes.size()) < formalCnt) {
This check is done after processing the values. This is useful if user
passes param values in named parameter binding. For example if a function takes
3 params in that 1 param is default one. Here user passes the values for one
non-default param and default param using named parameter binding then we
should throw exception as one non-default param value is not passed.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]