private ExprNodeDesc replaceDynamicParamsWithConstant(ExprNodeDesc expr, TypeInfo typeInfo,
      Map<Integer, ASTNode> paramMap) throws SemanticException{
    if (expr.getChildren() == null || expr.getChildren().isEmpty()) {
      if (expr instanceof ExprDynamicParamDesc) {
        return getConstant((ExprDynamicParamDesc)expr, typeInfo, paramMap);
      }
      return expr;
    }

    for(ExprNodeDesc child:expr.getChildren()) {
      // we need typeinfo
      if(child instanceof ExprDynamicParamDesc) {
        continue;
      } else if( child.getTypeInfo() != TypeInfoFactory.voidTypeInfo) {
        typeInfo = child.getTypeInfo();
        break;
      }
    }
    Preconditions.checkArgument(typeInfo != null, "TypeInfo is null");

    List<ExprNodeDesc> exprList = new ArrayList<>();
    for(ExprNodeDesc child: expr.getChildren()) {
      child = replaceDynamicParamsWithConstant(child, typeInfo, paramMap);
      exprList.add(child);
    }
    expr.getChildren().clear();
    expr.getChildren().addAll(exprList);
    return expr;
  }
Given an expression tree root at expr and type info of the expression this method traverse
the expression tree and replaces all dynamic expression with the constant expression.
This method also does type inference for the new constant expression.
Note about type inference
Since dynamic parameter lacks type we need to figure out appropriate type to create constant
out of string value. To do this, we choose the type of first child of the parent expression
which isn't dynamic parameter
ql/src/java/org/apache/hadoop/hive/ql/parse/ExecuteStatementAnalyzer.java