1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.shardingsphere.driver.jdbc.core.datasource.metadata;
19
20 import com.google.common.base.Strings;
21 import org.apache.shardingsphere.driver.jdbc.adapter.AdaptedDatabaseMetaData;
22 import org.apache.shardingsphere.driver.jdbc.core.connection.ShardingSphereConnection;
23 import org.apache.shardingsphere.driver.jdbc.core.resultset.DatabaseMetaDataResultSet;
24 import org.apache.shardingsphere.infra.database.core.connector.ConnectionProperties;
25 import org.apache.shardingsphere.infra.rule.ShardingSphereRule;
26 import org.apache.shardingsphere.infra.rule.attribute.datanode.DataNodeRuleAttribute;
27
28 import java.sql.Connection;
29 import java.sql.DatabaseMetaData;
30 import java.sql.ResultSet;
31 import java.sql.SQLException;
32 import java.util.Collection;
33 import java.util.Optional;
34
35
36
37
38 public final class ShardingSphereDatabaseMetaData extends AdaptedDatabaseMetaData {
39
40 private final ShardingSphereConnection connection;
41
42 private final Collection<ShardingSphereRule> rules;
43
44 private String currentPhysicalDataSourceName;
45
46 private Connection currentPhysicalConnection;
47
48 private DatabaseMetaData currentDatabaseMetaData;
49
50 public ShardingSphereDatabaseMetaData(final ShardingSphereConnection connection) throws SQLException {
51 super(connection.getDatabaseConnectionManager().getRandomConnection().getMetaData());
52 this.connection = connection;
53 rules = connection.getContextManager().getMetaDataContexts().getMetaData().getDatabase(connection.getDatabaseName()).getRuleMetaData().getRules();
54 }
55
56 @Override
57 public Connection getConnection() throws SQLException {
58 if (null == currentPhysicalConnection) {
59 currentPhysicalConnection = connection.getDatabaseConnectionManager().getRandomConnection();
60 }
61 return currentPhysicalConnection;
62 }
63
64 @Override
65 public ResultSet getSuperTypes(final String catalog, final String schemaPattern, final String typeNamePattern) throws SQLException {
66 return createDatabaseMetaDataResultSet(getDatabaseMetaData().getSuperTypes(getActualCatalog(catalog), getActualSchema(schemaPattern), typeNamePattern));
67 }
68
69 @Override
70 public ResultSet getSuperTables(final String catalog, final String schemaPattern, final String tableNamePattern) throws SQLException {
71 return createDatabaseMetaDataResultSet(getDatabaseMetaData().getSuperTables(getActualCatalog(catalog), getActualSchema(schemaPattern), getActualTableNamePattern(tableNamePattern)));
72 }
73
74 @Override
75 public ResultSet getAttributes(final String catalog, final String schemaPattern, final String typeNamePattern, final String attributeNamePattern) throws SQLException {
76 return createDatabaseMetaDataResultSet(getDatabaseMetaData().getAttributes(getActualCatalog(catalog), getActualSchema(schemaPattern), typeNamePattern, attributeNamePattern));
77 }
78
79 @Override
80 public ResultSet getProcedures(final String catalog, final String schemaPattern, final String procedureNamePattern) throws SQLException {
81 return createDatabaseMetaDataResultSet(getDatabaseMetaData().getProcedures(getActualCatalog(catalog), getActualSchema(schemaPattern), procedureNamePattern));
82 }
83
84 @Override
85 public ResultSet getProcedureColumns(final String catalog, final String schemaPattern, final String procedureNamePattern, final String columnNamePattern) throws SQLException {
86 return createDatabaseMetaDataResultSet(getDatabaseMetaData().getProcedureColumns(getActualCatalog(catalog), getActualSchema(schemaPattern), procedureNamePattern, columnNamePattern));
87 }
88
89 @Override
90 public ResultSet getTables(final String catalog, final String schemaPattern, final String tableNamePattern, final String[] types) throws SQLException {
91 return createDatabaseMetaDataResultSet(getDatabaseMetaData().getTables(getActualCatalog(catalog), getActualSchema(schemaPattern), getActualTableNamePattern(tableNamePattern), types));
92 }
93
94 @Override
95 public ResultSet getSchemas() throws SQLException {
96 return createDatabaseMetaDataResultSet(getDatabaseMetaData().getSchemas());
97 }
98
99 @Override
100 public ResultSet getSchemas(final String catalog, final String schemaPattern) throws SQLException {
101 return createDatabaseMetaDataResultSet(getDatabaseMetaData().getSchemas(getActualCatalog(catalog), getActualSchema(schemaPattern)));
102 }
103
104 @Override
105 public ResultSet getCatalogs() throws SQLException {
106 return createDatabaseMetaDataResultSet(getDatabaseMetaData().getCatalogs());
107 }
108
109 @Override
110 public ResultSet getTableTypes() throws SQLException {
111 return createDatabaseMetaDataResultSet(getDatabaseMetaData().getTableTypes());
112 }
113
114 @Override
115 public ResultSet getColumns(final String catalog, final String schemaPattern, final String tableNamePattern, final String columnNamePattern) throws SQLException {
116 return createDatabaseMetaDataResultSet(
117 getDatabaseMetaData().getColumns(getActualCatalog(catalog), getActualSchema(schemaPattern), getActualTableNamePattern(tableNamePattern), columnNamePattern));
118 }
119
120 @Override
121 public ResultSet getColumnPrivileges(final String catalog, final String schema, final String table, final String columnNamePattern) throws SQLException {
122 return createDatabaseMetaDataResultSet(
123 getDatabaseMetaData().getColumnPrivileges(getActualCatalog(catalog), getActualSchema(schema), getActualTable(getActualCatalog(catalog), table), columnNamePattern));
124 }
125
126 @Override
127 public ResultSet getTablePrivileges(final String catalog, final String schemaPattern, final String tableNamePattern) throws SQLException {
128 return createDatabaseMetaDataResultSet(getDatabaseMetaData().getTablePrivileges(getActualCatalog(catalog), getActualSchema(schemaPattern), getActualTableNamePattern(tableNamePattern)));
129 }
130
131 @Override
132 public ResultSet getBestRowIdentifier(final String catalog, final String schema, final String table, final int scope, final boolean nullable) throws SQLException {
133 return createDatabaseMetaDataResultSet(getDatabaseMetaData().getBestRowIdentifier(getActualCatalog(catalog), getActualSchema(schema),
134 getActualTable(getActualCatalog(catalog), table), scope, nullable));
135 }
136
137 @Override
138 public ResultSet getVersionColumns(final String catalog, final String schema, final String table) throws SQLException {
139 return createDatabaseMetaDataResultSet(getDatabaseMetaData().getVersionColumns(getActualCatalog(catalog), getActualSchema(schema), getActualTable(getActualCatalog(catalog), table)));
140 }
141
142 @Override
143 public ResultSet getPrimaryKeys(final String catalog, final String schema, final String table) throws SQLException {
144 return createDatabaseMetaDataResultSet(getDatabaseMetaData().getPrimaryKeys(getActualCatalog(catalog), getActualSchema(schema), getActualTable(getActualCatalog(catalog), table)));
145 }
146
147 @Override
148 public ResultSet getImportedKeys(final String catalog, final String schema, final String table) throws SQLException {
149 return createDatabaseMetaDataResultSet(getDatabaseMetaData().getImportedKeys(getActualCatalog(catalog), getActualSchema(schema), getActualTable(getActualCatalog(catalog), table)));
150 }
151
152 @Override
153 public ResultSet getExportedKeys(final String catalog, final String schema, final String table) throws SQLException {
154 return createDatabaseMetaDataResultSet(getDatabaseMetaData().getExportedKeys(getActualCatalog(catalog), getActualSchema(schema), getActualTable(getActualCatalog(catalog), table)));
155 }
156
157 @Override
158 public ResultSet getCrossReference(final String parentCatalog,
159 final String parentSchema, final String parentTable, final String foreignCatalog, final String foreignSchema, final String foreignTable) throws SQLException {
160 return createDatabaseMetaDataResultSet(
161 getDatabaseMetaData().getCrossReference(getActualCatalog(parentCatalog), getActualSchema(parentSchema), parentTable, foreignCatalog, foreignSchema, foreignTable));
162 }
163
164 @Override
165 public ResultSet getTypeInfo() throws SQLException {
166 return createDatabaseMetaDataResultSet(getDatabaseMetaData().getTypeInfo());
167 }
168
169 @Override
170 public ResultSet getIndexInfo(final String catalog, final String schema, final String table, final boolean unique, final boolean approximate) throws SQLException {
171 return createDatabaseMetaDataResultSet(getDatabaseMetaData().getIndexInfo(getActualCatalog(catalog), getActualSchema(schema),
172 getActualTable(getActualCatalog(catalog), table), unique, approximate));
173 }
174
175 @Override
176 public ResultSet getUDTs(final String catalog, final String schemaPattern, final String typeNamePattern, final int[] types) throws SQLException {
177 return createDatabaseMetaDataResultSet(getDatabaseMetaData().getUDTs(getActualCatalog(catalog), getActualSchema(schemaPattern), typeNamePattern, types));
178 }
179
180 @Override
181 public ResultSet getClientInfoProperties() throws SQLException {
182 return createDatabaseMetaDataResultSet(getDatabaseMetaData().getClientInfoProperties());
183 }
184
185 @Override
186 public ResultSet getFunctions(final String catalog, final String schemaPattern, final String functionNamePattern) throws SQLException {
187 return createDatabaseMetaDataResultSet(getDatabaseMetaData().getFunctions(getActualCatalog(catalog), getActualSchema(schemaPattern), functionNamePattern));
188 }
189
190 @Override
191 public ResultSet getFunctionColumns(final String catalog, final String schemaPattern, final String functionNamePattern, final String columnNamePattern) throws SQLException {
192 return createDatabaseMetaDataResultSet(getDatabaseMetaData().getFunctionColumns(getActualCatalog(catalog), getActualSchema(schemaPattern), functionNamePattern, columnNamePattern));
193 }
194
195 @Override
196 public ResultSet getPseudoColumns(final String catalog, final String schemaPattern, final String tableNamePattern, final String columnNamePattern) throws SQLException {
197 return createDatabaseMetaDataResultSet(
198 getDatabaseMetaData().getPseudoColumns(getActualCatalog(catalog), getActualSchema(schemaPattern), getActualTableNamePattern(tableNamePattern), columnNamePattern));
199 }
200
201 private String getActualTableNamePattern(final String tableNamePattern) {
202 return null == tableNamePattern
203 ? null
204 : findDataNodeRuleAttribute().filter(optional -> optional.findFirstActualTable(tableNamePattern).isPresent()).map(optional -> "%" + tableNamePattern + "%").orElse(tableNamePattern);
205 }
206
207 private String getActualTable(final String catalog, final String table) {
208 return null == table ? null : findDataNodeRuleAttribute().map(each -> findActualTable(each, catalog, table).orElse(table)).orElse(table);
209 }
210
211 private Optional<String> findActualTable(final DataNodeRuleAttribute ruleAttribute, final String catalog, final String table) {
212 return Strings.isNullOrEmpty(catalog) ? ruleAttribute.findFirstActualTable(table) : ruleAttribute.findActualTableByCatalog(catalog, table);
213 }
214
215 private Optional<DataNodeRuleAttribute> findDataNodeRuleAttribute() {
216 for (ShardingSphereRule each : rules) {
217 Optional<DataNodeRuleAttribute> ruleAttribute = each.getAttributes().findAttribute(DataNodeRuleAttribute.class);
218 if (ruleAttribute.isPresent()) {
219 return ruleAttribute;
220 }
221 }
222 return Optional.empty();
223 }
224
225 private ResultSet createDatabaseMetaDataResultSet(final ResultSet resultSet) throws SQLException {
226 return new DatabaseMetaDataResultSet(resultSet, rules);
227 }
228
229 private String getActualCatalog(final String catalog) {
230 if (null == catalog) {
231 return null;
232 }
233
234 ConnectionProperties connectionProps = connection.getContextManager()
235 .getMetaDataContexts().getMetaData().getDatabase(connection.getDatabaseName()).getResourceMetaData().getStorageUnits().get(getDataSourceName()).getConnectionProperties();
236 return connectionProps.getCatalog();
237 }
238
239 private String getActualSchema(final String schema) {
240 if (null == schema) {
241 return null;
242 }
243
244 ConnectionProperties connectionProps = connection.getContextManager()
245 .getMetaDataContexts().getMetaData().getDatabase(connection.getDatabaseName()).getResourceMetaData().getStorageUnits().get(getDataSourceName()).getConnectionProperties();
246 return Optional.ofNullable(connectionProps.getSchema()).map(String::toUpperCase).orElse(null);
247 }
248
249 private String getDataSourceName() {
250 if (null == currentPhysicalDataSourceName) {
251 currentPhysicalDataSourceName = connection.getDatabaseConnectionManager().getRandomPhysicalDataSourceName();
252 }
253 return currentPhysicalDataSourceName;
254 }
255
256 private DatabaseMetaData getDatabaseMetaData() throws SQLException {
257 if (null == currentDatabaseMetaData) {
258 currentDatabaseMetaData = getConnection().getMetaData();
259 }
260 return currentDatabaseMetaData;
261 }
262 }