@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; }
@Override public Value getValue(Session session) { HashMap<Expression, Object> group = select.getCurrentGroup(); if (group == null) { throw DbException.get(ErrorCode.INVALID_USE_OF_AGGREGATE_FUNCTION_1, getSQL()); } try { Aggregate agg = (Aggregate) group.get(this); if (agg == null) { agg = getInstance(); } Object obj = agg.getResult(); if (obj == null) { return ValueNull.INSTANCE; } return DataType.convertToValue(session, obj, dataType); } catch (SQLException e) { throw DbException.convert(e); } }
@Override public void updateAggregate(Session session) { HashMap<Expression, Object> group = select.getCurrentGroup(); if (group == null) { // this is a different level (the enclosing query) return; } int groupRowId = select.getCurrentGroupRowId(); if (lastGroupRowId == groupRowId) { // already visited return; } lastGroupRowId = groupRowId; Aggregate agg = (Aggregate) group.get(this); try { if (agg == null) { agg = getInstance(); group.put(this, agg); } Object[] argValues = new Object[args.length]; Object arg = null; for (int i = 0, len = args.length; i < len; i++) { Value v = args[i].getValue(session); v = v.convertTo(argTypes[i]); arg = v.getObject(); argValues[i] = arg; } if (args.length == 1) { agg.add(arg); } else { agg.add(argValues); } } catch (SQLException e) { throw DbException.convert(e); } }
// 调用了两次,一次在optimize,另一次在updateAggregate private Aggregate getInstance() throws SQLException { Aggregate agg = userAggregate.getInstance(); agg.init(userConnection); return agg; }