View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.shardingsphere.sqlfederation.optimizer.metadata.schema;
19  
20  import lombok.RequiredArgsConstructor;
21  import lombok.Setter;
22  import org.apache.calcite.DataContext;
23  import org.apache.calcite.linq4j.AbstractEnumerable;
24  import org.apache.calcite.linq4j.Enumerable;
25  import org.apache.calcite.linq4j.Enumerator;
26  import org.apache.calcite.linq4j.QueryProvider;
27  import org.apache.calcite.linq4j.Queryable;
28  import org.apache.calcite.linq4j.tree.Expression;
29  import org.apache.calcite.plan.RelOptCluster;
30  import org.apache.calcite.plan.RelOptTable;
31  import org.apache.calcite.plan.RelOptTable.ToRelContext;
32  import org.apache.calcite.prepare.Prepare.CatalogReader;
33  import org.apache.calcite.rel.RelNode;
34  import org.apache.calcite.rel.core.TableModify;
35  import org.apache.calcite.rel.core.TableModify.Operation;
36  import org.apache.calcite.rel.logical.LogicalTableModify;
37  import org.apache.calcite.rel.logical.LogicalTableScan;
38  import org.apache.calcite.rel.type.RelDataType;
39  import org.apache.calcite.rel.type.RelDataTypeFactory;
40  import org.apache.calcite.rex.RexNode;
41  import org.apache.calcite.schema.ModifiableTable;
42  import org.apache.calcite.schema.SchemaPlus;
43  import org.apache.calcite.schema.Schemas;
44  import org.apache.calcite.schema.Statistic;
45  import org.apache.calcite.schema.TranslatableTable;
46  import org.apache.calcite.schema.impl.AbstractTable;
47  import org.apache.shardingsphere.infra.database.core.type.DatabaseType;
48  import org.apache.shardingsphere.infra.exception.generic.UnsupportedSQLOperationException;
49  import org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereTable;
50  import org.apache.shardingsphere.sqlfederation.optimizer.metadata.schema.table.EmptyRowEnumerator;
51  import org.apache.shardingsphere.sqlfederation.optimizer.metadata.schema.table.ScanExecutor;
52  import org.apache.shardingsphere.sqlfederation.optimizer.metadata.schema.table.ScanExecutorContext;
53  import org.apache.shardingsphere.sqlfederation.optimizer.metadata.util.SQLFederationDataTypeUtils;
54  import org.apache.shardingsphere.sqlfederation.optimizer.statistic.SQLFederationStatistic;
55  
56  import java.lang.reflect.Type;
57  import java.util.Collection;
58  import java.util.Collections;
59  import java.util.List;
60  
61  /**
62   * SQL federation table.
63   */
64  @RequiredArgsConstructor
65  public final class SQLFederationTable extends AbstractTable implements ModifiableTable, TranslatableTable {
66      
67      private final ShardingSphereTable table;
68      
69      private final SQLFederationStatistic statistic;
70      
71      private final DatabaseType protocolType;
72      
73      @Setter
74      private ScanExecutor scanExecutor;
75      
76      @Override
77      public RelDataType getRowType(final RelDataTypeFactory typeFactory) {
78          return SQLFederationDataTypeUtils.createRelDataType(table, protocolType, typeFactory);
79      }
80      
81      @Override
82      public Expression getExpression(final SchemaPlus schema, final String tableName, final Class clazz) {
83          return Schemas.tableExpression(schema, getElementType(), tableName, clazz);
84      }
85      
86      @Override
87      public Type getElementType() {
88          return Object[].class;
89      }
90      
91      @Override
92      public <T> Queryable<T> asQueryable(final QueryProvider queryProvider, final SchemaPlus schema, final String tableName) {
93          throw new UnsupportedSQLOperationException("asQueryable");
94      }
95      
96      @Override
97      public RelNode toRel(final ToRelContext context, final RelOptTable relOptTable) {
98          return LogicalTableScan.create(context.getCluster(), relOptTable, Collections.emptyList());
99      }
100     
101     /**
102      * Execute.
103      *
104      * @param root data context
105      * @param sql sql
106      * @param paramIndexes param indexes
107      * @return enumerable result
108      */
109     public Enumerable<Object> execute(final DataContext root, final String sql, final int[] paramIndexes) {
110         if (null == scanExecutor) {
111             return createEmptyEnumerable();
112         }
113         return scanExecutor.execute(table, new ScanExecutorContext(root, sql, paramIndexes));
114     }
115     
116     private AbstractEnumerable<Object> createEmptyEnumerable() {
117         return new AbstractEnumerable<Object>() {
118             
119             @Override
120             public Enumerator<Object> enumerator() {
121                 return new EmptyRowEnumerator();
122             }
123         };
124     }
125     
126     @Override
127     public String toString() {
128         return "SQLFederationTable";
129     }
130     
131     @Override
132     public Statistic getStatistic() {
133         return statistic;
134     }
135     
136     @Override
137     public Collection<Object[]> getModifiableCollection() {
138         throw new UnsupportedOperationException();
139     }
140     
141     @Override
142     public TableModify toModificationRel(final RelOptCluster relOptCluster, final RelOptTable table, final CatalogReader schema,
143                                          final RelNode relNode, final Operation operation, final List<String> updateColumnList,
144                                          final List<RexNode> sourceExpressionList, final boolean flattened) {
145         return LogicalTableModify.create(table, schema, relNode, operation, updateColumnList, sourceExpressionList, flattened);
146     }
147 }