1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.shardingsphere.proxy.backend.mysql.handler.admin.executor;
19
20 import lombok.Getter;
21 import lombok.RequiredArgsConstructor;
22 import org.apache.shardingsphere.infra.binder.context.statement.SQLStatementContext;
23 import org.apache.shardingsphere.infra.binder.engine.SQLBindEngine;
24 import org.apache.shardingsphere.infra.exception.core.ShardingSpherePreconditions;
25 import org.apache.shardingsphere.infra.exception.dialect.exception.syntax.database.NoDatabaseSelectedException;
26 import org.apache.shardingsphere.infra.exception.kernel.metadata.resource.storageunit.EmptyStorageUnitException;
27 import org.apache.shardingsphere.infra.executor.sql.execute.result.query.QueryResult;
28 import org.apache.shardingsphere.infra.executor.sql.execute.result.query.QueryResultMetaData;
29 import org.apache.shardingsphere.infra.executor.sql.execute.result.query.impl.raw.metadata.RawQueryResultColumnMetaData;
30 import org.apache.shardingsphere.infra.executor.sql.execute.result.query.impl.raw.metadata.RawQueryResultMetaData;
31 import org.apache.shardingsphere.infra.executor.sql.execute.result.query.impl.raw.type.RawMemoryQueryResult;
32 import org.apache.shardingsphere.infra.executor.sql.execute.result.query.type.memory.row.MemoryQueryResultDataRow;
33 import org.apache.shardingsphere.infra.hint.HintValueContext;
34 import org.apache.shardingsphere.infra.hint.SQLHintUtils;
35 import org.apache.shardingsphere.infra.merge.result.MergedResult;
36 import org.apache.shardingsphere.infra.merge.result.impl.transparent.TransparentMergedResult;
37 import org.apache.shardingsphere.infra.session.query.QueryContext;
38 import org.apache.shardingsphere.proxy.backend.connector.DatabaseConnector;
39 import org.apache.shardingsphere.proxy.backend.connector.DatabaseConnectorFactory;
40 import org.apache.shardingsphere.proxy.backend.context.ProxyContext;
41 import org.apache.shardingsphere.proxy.backend.handler.admin.executor.DatabaseAdminQueryExecutor;
42 import org.apache.shardingsphere.proxy.backend.response.header.ResponseHeader;
43 import org.apache.shardingsphere.proxy.backend.response.header.query.QueryHeader;
44 import org.apache.shardingsphere.proxy.backend.response.header.query.QueryResponseHeader;
45 import org.apache.shardingsphere.proxy.backend.session.ConnectionSession;
46 import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.SelectStatement;
47
48 import java.sql.SQLException;
49 import java.sql.Types;
50 import java.util.Collection;
51 import java.util.Collections;
52 import java.util.LinkedList;
53 import java.util.List;
54 import java.util.Optional;
55 import java.util.stream.Collectors;
56
57
58
59
60 @RequiredArgsConstructor
61 @Getter
62 public final class UnicastResourceShowExecutor implements DatabaseAdminQueryExecutor {
63
64 private final DatabaseConnectorFactory databaseConnectorFactory = DatabaseConnectorFactory.getInstance();
65
66 private final SelectStatement sqlStatement;
67
68 private final String sql;
69
70 private MergedResult mergedResult;
71
72 private DatabaseConnector databaseConnector;
73
74 private ResponseHeader responseHeader;
75
76 @Override
77 public void execute(final ConnectionSession connectionSession) throws SQLException {
78 String originDatabase = connectionSession.getDatabaseName();
79 String databaseName = null == originDatabase ? getFirstDatabaseName() : originDatabase;
80 ShardingSpherePreconditions.checkState(ProxyContext.getInstance().getContextManager().getDatabase(databaseName).containsDataSource(), () -> new EmptyStorageUnitException(databaseName));
81 HintValueContext hintValueContext = SQLHintUtils.extractHint(sql);
82 try {
83 connectionSession.setCurrentDatabase(databaseName);
84 SQLStatementContext sqlStatementContext = new SQLBindEngine(ProxyContext.getInstance().getContextManager().getMetaDataContexts().getMetaData(),
85 connectionSession.getDefaultDatabaseName(), hintValueContext).bind(sqlStatement, Collections.emptyList());
86 databaseConnector = databaseConnectorFactory.newInstance(new QueryContext(sqlStatementContext, sql, Collections.emptyList(), hintValueContext),
87 connectionSession.getDatabaseConnectionManager(), false);
88 responseHeader = databaseConnector.execute();
89 mergedResult = new TransparentMergedResult(createQueryResult());
90 } finally {
91 connectionSession.setCurrentDatabase(originDatabase);
92 databaseConnector.close();
93 }
94 }
95
96 private String getFirstDatabaseName() {
97 Collection<String> databaseNames = ProxyContext.getInstance().getAllDatabaseNames();
98 if (databaseNames.isEmpty()) {
99 throw new NoDatabaseSelectedException();
100 }
101 Optional<String> result = databaseNames.stream().filter(each -> ProxyContext.getInstance().getContextManager().getDatabase(each).containsDataSource()).findFirst();
102 ShardingSpherePreconditions.checkState(result.isPresent(), EmptyStorageUnitException::new);
103 return result.get();
104 }
105
106 @Override
107 public QueryResultMetaData getQueryResultMetaData() {
108 List<RawQueryResultColumnMetaData> columns = ((QueryResponseHeader) responseHeader).getQueryHeaders().stream().map(QueryHeader::getColumnLabel)
109 .map(each -> new RawQueryResultColumnMetaData("", each, each, Types.VARCHAR, "VARCHAR", 100, 0))
110 .collect(Collectors.toList());
111 return new RawQueryResultMetaData(columns);
112 }
113
114 private QueryResult createQueryResult() throws SQLException {
115 List<MemoryQueryResultDataRow> rows = new LinkedList<>();
116 while (databaseConnector.next()) {
117 List<Object> data = databaseConnector.getRowData().getData();
118 rows.add(new MemoryQueryResultDataRow(data));
119 }
120 return new RawMemoryQueryResult(getQueryResultMetaData(), rows);
121 }
122 }