1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.shardingsphere.sqlfederation.optimizer.planner.util;
19
20 import lombok.AccessLevel;
21 import lombok.NoArgsConstructor;
22 import org.apache.calcite.adapter.enumerable.EnumerableRules;
23 import org.apache.calcite.config.CalciteConnectionConfig;
24 import org.apache.calcite.jdbc.CalciteSchema;
25 import org.apache.calcite.plan.ConventionTraitDef;
26 import org.apache.calcite.plan.RelOptCluster;
27 import org.apache.calcite.plan.RelOptPlanner;
28 import org.apache.calcite.plan.RelOptRule;
29 import org.apache.calcite.plan.RelOptTable.ViewExpander;
30 import org.apache.calcite.plan.hep.HepMatchOrder;
31 import org.apache.calcite.plan.hep.HepPlanner;
32 import org.apache.calcite.plan.hep.HepProgramBuilder;
33 import org.apache.calcite.plan.volcano.VolcanoPlanner;
34 import org.apache.calcite.prepare.CalciteCatalogReader;
35 import org.apache.calcite.rel.RelCollationTraitDef;
36 import org.apache.calcite.rel.rules.AggregateExpandDistinctAggregatesRule;
37 import org.apache.calcite.rel.rules.CoreRules;
38 import org.apache.calcite.rel.rules.ProjectRemoveRule;
39 import org.apache.calcite.rel.type.RelDataTypeFactory;
40 import org.apache.calcite.rex.RexBuilder;
41 import org.apache.calcite.schema.Schema;
42 import org.apache.calcite.sql.SqlOperatorTable;
43 import org.apache.calcite.sql.fun.SqlLibrary;
44 import org.apache.calcite.sql.fun.SqlLibraryOperatorTableFactory;
45 import org.apache.calcite.sql.util.SqlOperatorTables;
46 import org.apache.calcite.sql.validate.SqlValidator;
47 import org.apache.calcite.sql.validate.SqlValidatorUtil;
48 import org.apache.calcite.sql2rel.SqlToRelConverter;
49 import org.apache.calcite.sql2rel.SqlToRelConverter.Config;
50 import org.apache.calcite.sql2rel.StandardConvertletTable;
51 import org.apache.shardingsphere.infra.database.core.type.DatabaseType;
52 import org.apache.shardingsphere.parser.rule.SQLParserRule;
53 import org.apache.shardingsphere.sqlfederation.optimizer.metadata.view.ShardingSphereViewExpander;
54 import org.apache.shardingsphere.sqlfederation.optimizer.planner.rule.converter.EnumerableModifyConverterRule;
55 import org.apache.shardingsphere.sqlfederation.optimizer.planner.rule.converter.EnumerableScanConverterRule;
56 import org.apache.shardingsphere.sqlfederation.optimizer.planner.rule.transformation.PushFilterIntoScanRule;
57 import org.apache.shardingsphere.sqlfederation.optimizer.planner.rule.transformation.PushProjectIntoScanRule;
58
59 import java.util.Arrays;
60 import java.util.Collection;
61 import java.util.Collections;
62 import java.util.HashMap;
63 import java.util.LinkedList;
64 import java.util.Map;
65
66
67
68
69 @NoArgsConstructor(access = AccessLevel.PRIVATE)
70 public final class SQLFederationPlannerUtils {
71
72 private static final int DEFAULT_MATCH_LIMIT = 1024;
73
74 private static final Map<String, SqlLibrary> DATABASE_TYPE_SQL_LIBRARIES = new HashMap<>();
75
76 static {
77 DATABASE_TYPE_SQL_LIBRARIES.put("MySQL", SqlLibrary.MYSQL);
78 DATABASE_TYPE_SQL_LIBRARIES.put("PostgreSQL", SqlLibrary.POSTGRESQL);
79 DATABASE_TYPE_SQL_LIBRARIES.put("openGauss", SqlLibrary.POSTGRESQL);
80 DATABASE_TYPE_SQL_LIBRARIES.put("Oracle", SqlLibrary.ORACLE);
81 }
82
83
84
85
86
87
88 public static RelOptPlanner createVolcanoPlanner() {
89 RelOptPlanner result = new VolcanoPlanner();
90 setUpRules(result);
91 return result;
92 }
93
94
95
96
97
98
99 public static RelOptPlanner createHepPlanner() {
100 HepProgramBuilder builder = new HepProgramBuilder();
101 builder.addGroupBegin().addRuleCollection(getFilterRules()).addGroupEnd().addMatchOrder(HepMatchOrder.BOTTOM_UP);
102 builder.addGroupBegin().addRuleCollection(getProjectRules()).addGroupEnd().addMatchOrder(HepMatchOrder.BOTTOM_UP);
103 builder.addGroupBegin().addRuleCollection(getAggregationRules()).addGroupEnd().addMatchOrder(HepMatchOrder.BOTTOM_UP);
104 builder.addGroupBegin().addRuleCollection(getCalcRules()).addGroupEnd().addMatchOrder(HepMatchOrder.BOTTOM_UP);
105 builder.addGroupBegin().addRuleCollection(getSubQueryRules()).addGroupEnd().addMatchOrder(HepMatchOrder.BOTTOM_UP);
106 builder.addMatchLimit(DEFAULT_MATCH_LIMIT);
107 return new HepPlanner(builder.build());
108 }
109
110 private static void setUpRules(final RelOptPlanner planner) {
111 planner.addRelTraitDef(ConventionTraitDef.INSTANCE);
112 planner.addRelTraitDef(RelCollationTraitDef.INSTANCE);
113 planner.addRule(EnumerableRules.ENUMERABLE_JOIN_RULE);
114 planner.addRule(EnumerableRules.ENUMERABLE_MERGE_JOIN_RULE);
115 planner.addRule(EnumerableRules.ENUMERABLE_CORRELATE_RULE);
116 planner.addRule(EnumerableRules.ENUMERABLE_PROJECT_RULE);
117 planner.addRule(EnumerableRules.ENUMERABLE_FILTER_RULE);
118 planner.addRule(EnumerableRules.ENUMERABLE_CALC_RULE);
119 planner.addRule(EnumerableRules.ENUMERABLE_AGGREGATE_RULE);
120 planner.addRule(EnumerableRules.ENUMERABLE_SORT_RULE);
121 planner.addRule(EnumerableRules.ENUMERABLE_LIMIT_RULE);
122 planner.addRule(EnumerableRules.ENUMERABLE_COLLECT_RULE);
123 planner.addRule(EnumerableRules.ENUMERABLE_UNCOLLECT_RULE);
124 planner.addRule(EnumerableRules.ENUMERABLE_UNION_RULE);
125 planner.addRule(EnumerableRules.ENUMERABLE_REPEAT_UNION_RULE);
126 planner.addRule(EnumerableRules.ENUMERABLE_TABLE_SPOOL_RULE);
127 planner.addRule(EnumerableRules.ENUMERABLE_INTERSECT_RULE);
128 planner.addRule(EnumerableRules.ENUMERABLE_MINUS_RULE);
129 planner.addRule(EnumerableRules.ENUMERABLE_VALUES_RULE);
130 planner.addRule(EnumerableRules.ENUMERABLE_WINDOW_RULE);
131 planner.addRule(EnumerableRules.ENUMERABLE_TABLE_SCAN_RULE);
132 planner.addRule(EnumerableRules.ENUMERABLE_TABLE_FUNCTION_SCAN_RULE);
133 planner.addRule(EnumerableRules.ENUMERABLE_MATCH_RULE);
134 planner.addRule(EnumerableScanConverterRule.DEFAULT_CONFIG.toRule());
135 planner.addRule(EnumerableModifyConverterRule.DEFAULT_CONFIG.toRule());
136 }
137
138 private static Collection<RelOptRule> getSubQueryRules() {
139 Collection<RelOptRule> result = new LinkedList<>();
140 result.add(CoreRules.FILTER_SUB_QUERY_TO_CORRELATE);
141 result.add(CoreRules.PROJECT_SUB_QUERY_TO_CORRELATE);
142 result.add(CoreRules.JOIN_SUB_QUERY_TO_CORRELATE);
143 return result;
144 }
145
146 private static Collection<RelOptRule> getCalcRules() {
147 Collection<RelOptRule> result = new LinkedList<>();
148 result.add(AggregateExpandDistinctAggregatesRule.Config.DEFAULT.toRule());
149 result.add(CoreRules.PROJECT_TO_CALC);
150 result.add(CoreRules.FILTER_TO_CALC);
151 result.add(CoreRules.PROJECT_CALC_MERGE);
152 result.add(CoreRules.FILTER_CALC_MERGE);
153 result.add(EnumerableRules.ENUMERABLE_FILTER_TO_CALC_RULE);
154 result.add(EnumerableRules.ENUMERABLE_PROJECT_TO_CALC_RULE);
155 result.add(CoreRules.CALC_MERGE);
156 return result;
157 }
158
159 private static Collection<RelOptRule> getProjectRules() {
160 Collection<RelOptRule> result = new LinkedList<>();
161 result.add(CoreRules.PROJECT_MERGE);
162 result.add(CoreRules.PROJECT_CORRELATE_TRANSPOSE);
163 result.add(CoreRules.PROJECT_SET_OP_TRANSPOSE);
164 result.add(CoreRules.PROJECT_JOIN_TRANSPOSE);
165 result.add(CoreRules.PROJECT_REDUCE_EXPRESSIONS);
166 result.add(ProjectRemoveRule.Config.DEFAULT.toRule());
167 result.add(PushProjectIntoScanRule.Config.DEFAULT.toRule());
168 return result;
169 }
170
171 private static Collection<RelOptRule> getFilterRules() {
172 Collection<RelOptRule> result = new LinkedList<>();
173 result.add(CoreRules.FILTER_INTO_JOIN);
174 result.add(CoreRules.JOIN_CONDITION_PUSH);
175 result.add(CoreRules.SORT_JOIN_TRANSPOSE);
176 result.add(CoreRules.FILTER_AGGREGATE_TRANSPOSE);
177 result.add(CoreRules.FILTER_PROJECT_TRANSPOSE);
178 result.add(CoreRules.FILTER_SET_OP_TRANSPOSE);
179 result.add(CoreRules.FILTER_REDUCE_EXPRESSIONS);
180 result.add(CoreRules.FILTER_MERGE);
181 result.add(CoreRules.JOIN_PUSH_EXPRESSIONS);
182 result.add(CoreRules.JOIN_PUSH_TRANSITIVE_PREDICATES);
183 result.add(PushFilterIntoScanRule.Config.DEFAULT.toRule());
184 return result;
185 }
186
187 private static Collection<RelOptRule> getAggregationRules() {
188 Collection<RelOptRule> result = new LinkedList<>();
189 result.add(CoreRules.AGGREGATE_MERGE);
190 result.add(CoreRules.AGGREGATE_REDUCE_FUNCTIONS);
191 return result;
192 }
193
194
195
196
197
198
199
200
201
202
203 public static CalciteCatalogReader createCatalogReader(final String schemaName, final Schema schema, final RelDataTypeFactory relDataTypeFactory, final CalciteConnectionConfig connectionConfig) {
204 CalciteSchema rootSchema = CalciteSchema.createRootSchema(true);
205 rootSchema.add(schemaName, schema);
206 SQLFederationFunctionUtils.registryUserDefinedFunction(schemaName, rootSchema.plus());
207 return new CalciteCatalogReader(rootSchema, Collections.singletonList(schemaName), relDataTypeFactory, connectionConfig);
208 }
209
210
211
212
213
214
215
216
217
218
219 public static SqlValidator createSqlValidator(final CalciteCatalogReader catalogReader, final RelDataTypeFactory relDataTypeFactory,
220 final DatabaseType databaseType, final CalciteConnectionConfig connectionConfig) {
221 SqlValidator.Config validatorConfig = SqlValidator.Config.DEFAULT
222 .withLenientOperatorLookup(connectionConfig.lenientOperatorLookup())
223 .withConformance(connectionConfig.conformance())
224 .withDefaultNullCollation(connectionConfig.defaultNullCollation())
225 .withIdentifierExpansion(true);
226 SqlOperatorTable sqlOperatorTable = getSQLOperatorTable(catalogReader, databaseType.getTrunkDatabaseType().orElse(databaseType));
227 return SqlValidatorUtil.newValidator(sqlOperatorTable, catalogReader, relDataTypeFactory, validatorConfig);
228 }
229
230 private static SqlOperatorTable getSQLOperatorTable(final CalciteCatalogReader catalogReader, final DatabaseType databaseType) {
231 return SqlOperatorTables.chain(Arrays.asList(SqlLibraryOperatorTableFactory.INSTANCE.getOperatorTable(
232 Arrays.asList(SqlLibrary.STANDARD, DATABASE_TYPE_SQL_LIBRARIES.getOrDefault(databaseType.getType(), SqlLibrary.MYSQL))), catalogReader));
233 }
234
235
236
237
238
239
240
241
242
243
244
245
246 public static SqlToRelConverter createSqlToRelConverter(final CalciteCatalogReader catalogReader, final SqlValidator validator, final RelOptCluster cluster,
247 final SQLParserRule sqlParserRule, final DatabaseType databaseType, final boolean needsViewExpand) {
248 ViewExpander expander = needsViewExpand ? new ShardingSphereViewExpander(sqlParserRule, databaseType,
249 createSqlToRelConverter(catalogReader, validator, cluster, sqlParserRule, databaseType, false)) : (rowType, queryString, schemaPath, viewPath) -> null;
250
251 Config converterConfig = SqlToRelConverter.config().withTrimUnusedFields(true).withRemoveSortInSubQuery(false).withExpand(true);
252 return new SqlToRelConverter(expander, validator, catalogReader, cluster, StandardConvertletTable.INSTANCE, converterConfig);
253 }
254
255
256
257
258
259
260
261 public static RelOptCluster createRelOptCluster(final RelDataTypeFactory relDataTypeFactory) {
262 return RelOptCluster.create(SQLFederationPlannerUtils.createVolcanoPlanner(), new RexBuilder(relDataTypeFactory));
263 }
264 }