1818
1919import java .math .BigDecimal ;
2020import java .sql .Timestamp ;
21+ import java .util .List ;
22+ import java .util .function .Supplier ;
2123import com .google .common .collect .ImmutableList ;
2224import org .apache .calcite .adapter .enumerable .NullPolicy ;
2325import org .apache .calcite .avatica .util .TimeUnitRange ;
2426import org .apache .calcite .linq4j .tree .Expressions ;
27+ import org .apache .calcite .plan .Contexts ;
28+ import org .apache .calcite .rel .core .AggregateCall ;
29+ import org .apache .calcite .rel .type .RelDataType ;
2530import org .apache .calcite .rex .RexBuilder ;
2631import org .apache .calcite .rex .RexNode ;
32+ import org .apache .calcite .sql .SqlAggFunction ;
2733import org .apache .calcite .sql .SqlCall ;
2834import org .apache .calcite .sql .SqlFunction ;
2935import org .apache .calcite .sql .SqlFunctionCategory ;
4349import org .apache .calcite .tools .FrameworkConfig ;
4450import org .apache .calcite .tools .Frameworks ;
4551import org .apache .calcite .util .BuiltInMethod ;
52+ import org .apache .calcite .util .Optionality ;
4653import org .apache .ignite .configuration .IgniteConfiguration ;
4754import org .apache .ignite .internal .processors .query .calcite .CalciteQueryProcessor ;
55+ import org .apache .ignite .internal .processors .query .calcite .exec .ExecutionContext ;
56+ import org .apache .ignite .internal .processors .query .calcite .exec .RowHandler ;
4857import org .apache .ignite .internal .processors .query .calcite .exec .exp .RexImpTable ;
58+ import org .apache .ignite .internal .processors .query .calcite .exec .exp .agg .Accumulator ;
59+ import org .apache .ignite .internal .processors .query .calcite .exec .exp .agg .AccumulatorFactoryProvider ;
60+ import org .apache .ignite .internal .processors .query .calcite .exec .exp .agg .Accumulators ;
4961import org .apache .ignite .internal .processors .query .calcite .prepare .IgniteConvertletTable ;
5062import org .apache .ignite .internal .processors .query .calcite .prepare .IgniteSqlNodeRewriter ;
5163import org .apache .ignite .internal .processors .query .calcite .prepare .IgniteSqlValidator ;
64+ import org .apache .ignite .internal .processors .query .calcite .type .IgniteTypeFactory ;
5265import org .apache .ignite .plugin .AbstractTestPluginProvider ;
5366import org .apache .ignite .plugin .PluginContext ;
5467import org .jetbrains .annotations .Nullable ;
@@ -75,6 +88,9 @@ public class OperatorsExtensionIntegrationTest extends AbstractBasicIntegrationT
7588 .sqlValidatorConfig (
7689 ((IgniteSqlValidator .Config )CalciteQueryProcessor .FRAMEWORK_CONFIG .getSqlValidatorConfig ())
7790 .withSqlNodeRewriter (new SqlRewriter ()))
91+ .context (Contexts .chain (
92+ CalciteQueryProcessor .FRAMEWORK_CONFIG .getContext (),
93+ Contexts .of (new AccumulatorFactoryProviderImpl ())))
7894 .build ();
7995
8096 return (T )cfg ;
@@ -134,6 +150,14 @@ public void testOperatorsCallsInViews() {
134150 assertQuery ("SELECT val_str from my_view" ).returns (new BigDecimal ("0" )).check ();
135151 }
136152
153+ /** */
154+ @ Test
155+ public void testCustomAggregateFunction () {
156+ assertQuery ("SELECT TEST_SUM(x) FROM (VALUES (1), (2), (3)) t(x)" )
157+ .returns (6L )
158+ .check ();
159+ }
160+
137161 /** Rewrites LTRIM with 2 parameters. */
138162 public static SqlCall rewriteLtrim (SqlValidator validator , SqlCall call ) {
139163 if (call .operandCount () != 2 )
@@ -193,6 +217,9 @@ public static class OperatorTable extends ReflectiveSqlOperatorTable {
193217 OperandTypes .STRING_STRING ,
194218 SqlFunctionCategory .STRING
195219 );
220+
221+ /** */
222+ public static final SqlAggFunction TEST_SUM = new SqlTestSumAggFunction ();
196223 }
197224
198225 /** Extended convertlet table. */
@@ -229,4 +256,73 @@ private static class SqlRewriter implements IgniteSqlNodeRewriter {
229256 return node ;
230257 }
231258 }
259+
260+ /** */
261+ private static class AccumulatorFactoryProviderImpl implements AccumulatorFactoryProvider {
262+ /** {@inheritDoc} */
263+ @ Override public @ Nullable <Row > Supplier <Accumulator <Row >> factory (AggregateCall call , ExecutionContext <Row > ctx ) {
264+ if (call .getAggregation ().getName ().equals (OperatorTable .TEST_SUM .getName ()))
265+ return () -> new TestSum <>(call , ctx .rowHandler ());
266+
267+ return null ;
268+ }
269+ }
270+
271+ /** */
272+ public static class SqlTestSumAggFunction extends SqlAggFunction {
273+ /** */
274+ public SqlTestSumAggFunction () {
275+ super (
276+ "TEST_SUM" ,
277+ null ,
278+ SqlKind .SUM ,
279+ ReturnTypes .AGG_SUM ,
280+ null ,
281+ OperandTypes .NUMERIC ,
282+ SqlFunctionCategory .NUMERIC ,
283+ false ,
284+ false ,
285+ Optionality .FORBIDDEN
286+ );
287+ }
288+ }
289+
290+ /** */
291+ private static class TestSum <Row > extends Accumulators .AbstractAccumulator <Row > {
292+ /** */
293+ private long sum ;
294+
295+ /** */
296+ protected TestSum (AggregateCall aggCall , RowHandler <Row > hnd ) {
297+ super (aggCall , hnd );
298+ }
299+
300+ /** {@inheritDoc} */
301+ @ Override public void add (Row row ) {
302+ Number val = get (0 , row );
303+
304+ if (val != null )
305+ sum += val .longValue ();
306+ }
307+
308+ /** {@inheritDoc} */
309+ @ Override public void apply (Accumulator <Row > other ) {
310+ sum += ((TestSum <Row >)other ).sum ;
311+ }
312+
313+ /** {@inheritDoc} */
314+ @ Override public Object end () {
315+ return sum ;
316+ }
317+
318+ /** {@inheritDoc} */
319+ @ Override public List <RelDataType > argumentTypes (IgniteTypeFactory typeFactory ) {
320+ return List .of (typeFactory .createTypeWithNullability (typeFactory .createSqlType (SqlTypeName .BIGINT ), true ));
321+ }
322+
323+ /** {@inheritDoc} */
324+ @ Override public RelDataType returnType (IgniteTypeFactory typeFactory ) {
325+ return typeFactory .createSqlType (org .apache .calcite .sql .type .SqlTypeName .BIGINT );
326+ }
327+ }
232328}
0 commit comments