First off, can you create a jira case? This is clearly a bug. 

I think AggregateCall.rexList is new and will need to be explicitly handled in 
serialization and deserialization. Testing shouldn’t be difficult if you extend 
or modify existing RelJson tests. 

> On Aug 28, 2023, at 7:30 AM, stanilovsky evgeny <[email protected]> 
> wrote:
> 
> hello, please can someone explain me how LITERAL_AGG need to be correctly 
> serialized\deserealized and how to write appropriate tests.
> 
> Problem :
> we have LITERAL_AGG
> further:
> toJson(org.apache.calcite.rel.core.AggregateCall) {
>        Map<String, Object> map = map();
>        map.put("agg", toJson(node.getAggregation()));
>        map.put("type", toJson(node.getType()));
>        map.put("distinct", node.isDistinct());
>        map.put("operands", node.getArgList());
>        map.put("filter", node.filterArg);
>        map.put("name", node.getName());
>        return map;
>    }
> 
> not serialized "rexList" here ^
> 
> deserialization part:
> 
> RelJsonReader#toAggCall(Map<String, Object> jsonAggCall) {
>    ... cut ...
>    return AggregateCall.create(aggregation, distinct, false, false,
>        ImmutableList.of(), <-- empty list
>        operands,
>        filterOperand == null ? -1 : filterOperand,
>        null, RelCollations.EMPTY, type, name);
> }
> 
> used ImmutableList.of() instead of "rexList" (no place where we can obtain it 
> here, ok)
> 
> and further call for assembly:
> 
> public static AggregateCall create(...
> ...
>      final List<RelDataType> preTypes = RexUtil.types(rexList); <- pre types 
> are empty
>      final List<RelDataType> types =
>          SqlTypeUtil.projectTypes(input.getRowType(), argList); <- argList is 
> empty too
>      final Aggregate.AggCallBinding callBinding =
>          new Aggregate.AggCallBinding(typeFactory, aggFunction, preTypes,
>              types, groupCount, filterArg >= 0);
>       type = aggFunction.inferReturnType(callBinding);
> 
> 
> 
>  private static RelDataType inferReturnType(SqlOperatorBinding opBinding) {
>    // LITERAL_AGG takes one pre-operand and zero (post-)operands.
>    if (opBinding.getPreOperandCount() != 1
>        || opBinding.getOperandCount() != 1) {
>      throw new AssertionError(); <-- brings this assertion
>    }
>    return opBinding.getOperandType(0);
>  }
> 
> it`s not clear for me how to write test for such a case.
> I realize that description is probably not clear but i tried to make it as 
> informative as i can.
> 
> If all above is not clear, brief question : how to write 
> serizlization\deserialization tests for such Operands, yes i found 
> RelWriterTest but it still unclear for me:
> 
>  @Test void testWriter1() {
>    int i = Frameworks.withPlanner((cluster, relOptSchema, rootSchema) -> {
>      final RelDataTypeFactory typeFactory = cluster.getTypeFactory();
> 
>      RelDataTypeField field = new RelDataTypeFieldImpl(
>          "ID", 0, typeFactory.createSqlType(SqlTypeName.INTEGER)
>      );
>      RelRecordType rowType = new 
> RelRecordType(Collections.singletonList(field));
>      RelOptAbstractTable t1 = new RelOptAbstractTable(null, "t1", rowType) {
>        @Override
>        public <T> T unwrap(Class<T> clazz) {
>          return null;
>        }
>      };
> 
>      LogicalTableScan lt = new LogicalTableScan(cluster, null, List.of(), t1);
>      RelDataTypeSystem typeSys = cluster.getTypeFactory().getTypeSystem();
> 
>      SqlBasicAggFunction literalFunc = SqlLiteralAggFunction.INSTANCE;
>      RexLiteral rex = RexLiteral.fromJdbcString(
>          new BasicSqlType(typeSys, SqlTypeName.BOOLEAN), SqlTypeName.BOOLEAN, 
> "true");
>      AggregateCall type = AggregateCall.create(literalFunc, false, false, 
> false, List.of(rex),
>          ImmutableList.of(), -1, null,
>          RelCollations.of(new RelFieldCollation(1)), new 
> BasicSqlType(typeSys, SqlTypeName.BOOLEAN), "i");
> 
>      LogicalAggregate la = new LogicalAggregate(cluster, null, List.of(), lt, 
> ImmutableBitSet.of(), null, List.of(type));
> 
>      final JsonBuilder jsonBuilder = new JsonBuilder();
>      final RelJson json = RelJson.create().withJsonBuilder(jsonBuilder);
>      final Object o = json.toJson(la);
>      assertThat(o, notNullValue());
>      final String s = jsonBuilder.toJsonString(o);
>      //final String expectedJson = "";
>      //assertThat(s, is(expectedJson));
>      final RelDataType type2 = json.toType(typeFactory, o);
>      assertThat(type2, is(type));
>      return 0;
>    });
>  }
> 
> Thanks !

Reply via email to