16
16
import com .google .common .collect .ImmutableSet ;
17
17
import com .google .inject .Inject ;
18
18
import io .airlift .slice .Slices ;
19
+ import io .trino .plugin .base .aggregation .AggregateFunctionRewriter ;
20
+ import io .trino .plugin .base .aggregation .AggregateFunctionRule ;
19
21
import io .trino .plugin .base .expression .ConnectorExpressionRewriter ;
20
22
import io .trino .plugin .base .mapping .IdentifierMapping ;
21
23
import io .trino .plugin .jdbc .BaseJdbcClient ;
36
38
import io .trino .plugin .jdbc .SliceWriteFunction ;
37
39
import io .trino .plugin .jdbc .WriteFunction ;
38
40
import io .trino .plugin .jdbc .WriteMapping ;
41
+ import io .trino .plugin .jdbc .aggregation .ImplementAvgDecimal ;
42
+ import io .trino .plugin .jdbc .aggregation .ImplementAvgFloatingPoint ;
43
+ import io .trino .plugin .jdbc .aggregation .ImplementCorr ;
44
+ import io .trino .plugin .jdbc .aggregation .ImplementCount ;
45
+ import io .trino .plugin .jdbc .aggregation .ImplementCountAll ;
46
+ import io .trino .plugin .jdbc .aggregation .ImplementCountDistinct ;
47
+ import io .trino .plugin .jdbc .aggregation .ImplementCovariancePop ;
48
+ import io .trino .plugin .jdbc .aggregation .ImplementCovarianceSamp ;
49
+ import io .trino .plugin .jdbc .aggregation .ImplementMinMax ;
50
+ import io .trino .plugin .jdbc .aggregation .ImplementRegrIntercept ;
51
+ import io .trino .plugin .jdbc .aggregation .ImplementRegrSlope ;
52
+ import io .trino .plugin .jdbc .aggregation .ImplementStddevPop ;
53
+ import io .trino .plugin .jdbc .aggregation .ImplementStddevSamp ;
54
+ import io .trino .plugin .jdbc .aggregation .ImplementSum ;
55
+ import io .trino .plugin .jdbc .aggregation .ImplementVariancePop ;
56
+ import io .trino .plugin .jdbc .aggregation .ImplementVarianceSamp ;
39
57
import io .trino .plugin .jdbc .expression .JdbcConnectorExpressionRewriterBuilder ;
40
58
import io .trino .plugin .jdbc .expression .ParameterizedExpression ;
41
59
import io .trino .plugin .jdbc .expression .RewriteIn ;
50
68
import io .trino .spi .expression .ConnectorExpression ;
51
69
import io .trino .spi .type .DecimalType ;
52
70
import io .trino .spi .type .Type ;
71
+ import io .trino .spi .type .VarcharType ;
53
72
54
73
import java .sql .Connection ;
55
74
import java .sql .Date ;
73
92
import static io .trino .plugin .jdbc .StandardColumnMappings .longDecimalWriteFunction ;
74
93
import static io .trino .plugin .jdbc .StandardColumnMappings .shortDecimalWriteFunction ;
75
94
import static io .trino .plugin .jdbc .StandardColumnMappings .smallintColumnMapping ;
95
+ import static io .trino .plugin .jdbc .StandardColumnMappings .varcharWriteFunction ;
76
96
import static io .trino .plugin .jdbc .TypeHandlingJdbcSessionProperties .getUnsupportedTypeHandling ;
77
97
import static io .trino .plugin .jdbc .UnsupportedTypeHandling .CONVERT_TO_VARCHAR ;
78
98
import static io .trino .spi .StandardErrorCode .NOT_SUPPORTED ;
@@ -91,7 +111,9 @@ public class ExasolClient
91
111
.add ("EXA_STATISTICS" )
92
112
.add ("SYS" )
93
113
.build ();
114
+ public static final int MAX_EXASOL_DECIMAL_PRECISION = 36 ;
94
115
private final ConnectorExpressionRewriter <ParameterizedExpression > connectorExpressionRewriter ;
116
+ private final AggregateFunctionRewriter <JdbcExpression , ?> aggregateFunctionRewriter ;
95
117
96
118
@ Inject
97
119
public ExasolClient (
@@ -102,12 +124,13 @@ public ExasolClient(
102
124
RemoteQueryModifier queryModifier )
103
125
{
104
126
super ("\" " , connectionFactory , queryBuilder , config .getJdbcTypesMappedToVarchar (), identifierMapping , queryModifier , false );
105
- // Basic implementation required to enable JOIN pushdown support
106
- // It is covered by "testJoinpushdown " integration tests.
107
- // More detailed test case scenarios are covered by Unit tests in "TestConvertPredicate "
127
+ // Basic implementation required to enable JOIN and AGGREGATION pushdown support
128
+ // It is covered by "testJoinPushdown" and "testAggregationPushdown " integration tests.
129
+ // More detailed test case scenarios are covered by Unit tests in "TestExasolClient "
108
130
this .connectorExpressionRewriter = JdbcConnectorExpressionRewriterBuilder .newBuilder ()
109
131
.addStandardRules (this ::quoted )
110
132
.add (new RewriteIn ())
133
+ .withTypeClass ("numeric_type" , ImmutableSet .of ("decimal" , "double" ))
111
134
.map ("$equal(left, right)" ).to ("left = right" )
112
135
.map ("$not_equal(left, right)" ).to ("left <> right" )
113
136
// Exasol doesn't support "IS NOT DISTINCT FROM" expression,
@@ -120,7 +143,38 @@ public ExasolClient(
120
143
.map ("$not($is_null(value))" ).to ("value IS NOT NULL" )
121
144
.map ("$not(value: boolean)" ).to ("NOT value" )
122
145
.map ("$is_null(value)" ).to ("value IS NULL" )
146
+ .map ("$add(left: numeric_type, right: numeric_type)" ).to ("left + right" )
147
+ .map ("$subtract(left: numeric_type, right: numeric_type)" ).to ("left - right" )
148
+ .map ("$multiply(left: numeric_type, right: numeric_type)" ).to ("left * right" )
149
+ .map ("$divide(left: numeric_type, right: numeric_type)" ).to ("left / right" )
150
+ .map ("$modulus(left: numeric_type, right: numeric_type)" ).to ("mod(left, right)" )
151
+ .map ("$negate(value: numeric_type)" ).to ("-value" )
152
+ .map ("$like(value: varchar, pattern: varchar): boolean" ).to ("value LIKE pattern" )
153
+ .map ("$like(value: varchar, pattern: varchar, escape: varchar(1)): boolean" ).to ("value LIKE pattern ESCAPE escape" )
154
+ .map ("$nullif(first, second)" ).to ("NULLIF(first, second)" )
123
155
.build ();
156
+ JdbcTypeHandle bigintTypeHandle = new JdbcTypeHandle (Types .BIGINT , Optional .of ("bigint" ), Optional .empty (), Optional .empty (), Optional .empty (), Optional .empty ());
157
+ this .aggregateFunctionRewriter = new AggregateFunctionRewriter <>(
158
+ this .connectorExpressionRewriter ,
159
+ ImmutableSet .<AggregateFunctionRule <JdbcExpression , ParameterizedExpression >>builder ()
160
+ .add (new ImplementCountAll (bigintTypeHandle ))
161
+ .add (new ImplementMinMax (true ))
162
+ .add (new ImplementCount (bigintTypeHandle ))
163
+ .add (new ImplementCountDistinct (bigintTypeHandle , true ))
164
+ .add (new ImplementSum (ExasolClient ::toSumTypeHandle ))
165
+ .add (new ImplementAvgFloatingPoint ())
166
+ .add (new ImplementAvgDecimal ())
167
+ .add (new ImplementExasolAvgBigInt ())
168
+ .add (new ImplementStddevSamp ())
169
+ .add (new ImplementStddevPop ())
170
+ .add (new ImplementVarianceSamp ())
171
+ .add (new ImplementVariancePop ())
172
+ .add (new ImplementCovarianceSamp ())
173
+ .add (new ImplementCovariancePop ())
174
+ .add (new ImplementCorr ())
175
+ .add (new ImplementRegrIntercept ())
176
+ .add (new ImplementRegrSlope ())
177
+ .build ());
124
178
}
125
179
126
180
@ Override
@@ -234,11 +288,22 @@ protected boolean isSupportedJoinCondition(ConnectorSession session, JdbcJoinCon
234
288
return true ;
235
289
}
236
290
291
+ @ Override
292
+ public boolean supportsTopN (ConnectorSession session , JdbcTableHandle handle , List <JdbcSortItem > sortOrder )
293
+ {
294
+ return true ;
295
+ }
296
+
237
297
@ Override
238
298
public Optional <JdbcExpression > implementAggregation (ConnectorSession session , AggregateFunction aggregate , Map <String , ColumnHandle > assignments )
239
299
{
240
- // Deactivated because test 'testCaseSensitiveAggregationPushdown()' requires write access which is not implemented for Exasol
241
- return Optional .empty ();
300
+ return aggregateFunctionRewriter .rewrite (session , aggregate , assignments );
301
+ }
302
+
303
+ @ Override
304
+ public boolean supportsAggregationPushdown (ConnectorSession session , JdbcTableHandle table , List <AggregateFunction > aggregates , Map <String , ColumnHandle > assignments , List <List <ColumnHandle >> groupingSets )
305
+ {
306
+ return true ;
242
307
}
243
308
244
309
@ Override
@@ -263,9 +328,9 @@ public Optional<ColumnMapping> toColumnMapping(ConnectorSession session, Connect
263
328
case Types .DOUBLE :
264
329
return Optional .of (doubleColumnMapping ());
265
330
case Types .DECIMAL :
266
- int decimalDigits = typeHandle .requiredDecimalDigits ();
267
- int columnSize = typeHandle .requiredColumnSize ();
268
- return Optional .of (decimalColumnMapping (createDecimalType (columnSize , decimalDigits )));
331
+ int precision = typeHandle .requiredColumnSize ();
332
+ int scale = typeHandle .requiredDecimalDigits ();
333
+ return Optional .of (decimalColumnMapping (createDecimalType (precision , scale )));
269
334
case Types .CHAR :
270
335
return Optional .of (defaultCharColumnMapping (typeHandle .requiredColumnSize (), true ));
271
336
case Types .VARCHAR :
@@ -289,6 +354,12 @@ private boolean isHashType(JdbcTypeHandle typeHandle)
289
354
&& typeHandle .jdbcTypeName ().get ().equalsIgnoreCase ("HASHTYPE" );
290
355
}
291
356
357
+ private static Optional <JdbcTypeHandle > toSumTypeHandle (DecimalType decimalType )
358
+ {
359
+ return Optional .of (new JdbcTypeHandle (Types .DECIMAL , Optional .of ("decimal" ),
360
+ Optional .of (decimalType .getPrecision ()), Optional .of (decimalType .getScale ()), Optional .empty (), Optional .empty ()));
361
+ }
362
+
292
363
private static ColumnMapping dateColumnMapping ()
293
364
{
294
365
// Exasol driver does not support LocalDate
@@ -350,6 +421,16 @@ public WriteMapping toWriteMapping(ConnectorSession session, Type type)
350
421
}
351
422
return WriteMapping .objectMapping (dataType , longDecimalWriteFunction (decimalType ));
352
423
}
424
+ if (type instanceof VarcharType varcharType ) {
425
+ String dataType ;
426
+ if (varcharType .isUnbounded ()) {
427
+ dataType = "varchar" ;
428
+ }
429
+ else {
430
+ dataType = "varchar(" + varcharType .getBoundedLength () + ")" ;
431
+ }
432
+ return WriteMapping .sliceMapping (dataType , varcharWriteFunction ());
433
+ }
353
434
354
435
throw new TrinoException (NOT_SUPPORTED , "Unsupported column type: " + type .getDisplayName ());
355
436
}
@@ -398,10 +479,4 @@ public boolean isLimitGuaranteed(ConnectorSession session)
398
479
{
399
480
return true ;
400
481
}
401
-
402
- @ Override
403
- public boolean supportsTopN (ConnectorSession session , JdbcTableHandle handle , List <JdbcSortItem > sortOrder )
404
- {
405
- return true ;
406
- }
407
482
}
0 commit comments