@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; }
/** * 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); } }