@Override
 public Expression optimize(Session session) {
   userConnection = session.createConnection(false);
   int len = args.length;
   argTypes = new int[len];
   for (int i = 0; i < len; i++) {
     Expression expr = args[i];
     args[i] = expr.optimize(session);
     int type = expr.getType();
     argTypes[i] = type;
   }
   try {
     Aggregate aggregate = getInstance();
     dataType = aggregate.getInternalType(argTypes);
   } catch (SQLException e) {
     throw DbException.convert(e);
   }
   return this;
 }
Example #2
0
    /**
     * Call the user-defined function and return the value.
     *
     * @param session the session
     * @param args the argument list
     * @param columnList true if the function should only return the column list
     * @return the value
     */
    public Value getValue(Session session, Expression[] args, boolean columnList)
        throws SQLException {
      Class<?>[] paramClasses = method.getParameterTypes();
      Object[] params = new Object[paramClasses.length];
      int p = 0;
      if (hasConnectionParam && params.length > 0) {
        params[p++] = session.createConnection(columnList);
      }

      // allocate array for varArgs parameters
      Object varArg = null;
      if (varArgs) {
        int len = args.length - params.length + 1 + (hasConnectionParam ? 1 : 0);
        varArg = Array.newInstance(varArgClass, len);
        params[params.length - 1] = varArg;
      }

      for (int a = 0; a < args.length; a++, p++) {
        boolean currentIsVarArg = varArgs && p >= paramClasses.length - 1;
        Class<?> paramClass;
        if (currentIsVarArg) {
          paramClass = varArgClass;
        } else {
          paramClass = paramClasses[p];
        }
        int type = DataType.getTypeFromClass(paramClass);
        Value v = args[a].getValue(session);
        v = v.convertTo(type);
        Object o = v.getObject();
        if (o == null) {
          if (paramClass.isPrimitive()) {
            if (columnList) {
              // if the column list is requested, the parameters may
              // be null
              // need to set to default value otherwise the function
              // can't be called at all
              o = DataType.getDefaultForPrimitiveType(paramClass);
            } else {
              // NULL for a java primitive: return NULL
              return ValueNull.INSTANCE;
            }
          }
        } else {
          if (!paramClass.isAssignableFrom(o.getClass()) && !paramClass.isPrimitive()) {
            o = DataType.convertTo(session, session.createConnection(false), v, paramClass);
          }
        }
        if (currentIsVarArg) {
          Array.set(varArg, p - params.length + 1, o);
        } else {
          params[p] = o;
        }
      }
      boolean old = session.getAutoCommit();
      Value identity = session.getScopeIdentity();
      try {
        session.setAutoCommit(false);
        try {
          Object returnValue;
          returnValue = method.invoke(null, params);
          if (returnValue == null) {
            return ValueNull.INSTANCE;
          }
          Value ret = DataType.convertToValue(session, returnValue, dataType);
          return ret.convertTo(dataType);
        } catch (Exception e) {
          throw Message.convert(e);
        }
      } finally {
        session.setScopeIdentity(identity);
        session.setAutoCommit(old);
      }
    }