提交 49a200e8 编写于 作者: 董宗磊 提交者: Liang Zhang

Fix Navicat connect Sharding-Proxy no primary key error. (#3379)

* fixes #3005, QueryHeader add primaryKey, nullable, autoIncrement, signed field.

* add apache license (#3005)

* fixes code review.(#3005)

* fixes column name.(#3005)

* add test case.(#3005)

* add QueryHeader test case.(#3005)

* fixes checkstyle.(#3005)

* fixes param name, nullable -> notNull.(#3005)
上级 409ae92f
......@@ -38,4 +38,8 @@ public class ColumnMetaData {
private final String dataType;
private final boolean primaryKey;
private final boolean notNull;
private final boolean autoIncrement;
}
......@@ -37,9 +37,9 @@ public final class EncryptColumnMetaData extends ColumnMetaData {
private final String assistedQueryColumnName;
public EncryptColumnMetaData(final String name, final String dataType, final boolean primaryKey,
public EncryptColumnMetaData(final String name, final String dataType, final boolean primaryKey, final boolean notNull, final boolean autoIncrement,
final String cipherColumnName, final String plainColumnName, final String assistedQueryColumnName) {
super(name, dataType, primaryKey);
super(name, dataType, primaryKey, notNull, autoIncrement);
this.cipherColumnName = cipherColumnName;
this.plainColumnName = plainColumnName;
this.assistedQueryColumnName = assistedQueryColumnName;
......
......@@ -31,7 +31,8 @@ import lombok.ToString;
@ToString(callSuper = true)
public final class ShardingGeneratedKeyColumnMetaData extends ColumnMetaData {
public ShardingGeneratedKeyColumnMetaData(final String name, final String dataType, final boolean primaryKey) {
super(name, dataType, primaryKey);
public ShardingGeneratedKeyColumnMetaData(final String name, final String dataType, final boolean primaryKey,
final boolean notNull, final boolean autoIncrement) {
super(name, dataType, primaryKey, notNull, autoIncrement);
}
}
......@@ -28,7 +28,25 @@ public final class TableMetaDataTest {
@Test
public void assertContainsIndex() {
TableMetaData tableMetaData = new TableMetaData(Collections.singletonList(new ColumnMetaData("name", "dataType", true)), Collections.singleton("indexName"));
TableMetaData tableMetaData = new TableMetaData(Collections.singletonList(new ColumnMetaData("name", "dataType", true, true, true)), Collections.singleton("indexName"));
assertTrue(tableMetaData.containsIndex("indexName"));
}
@Test
public void assertColumnPrimaryKey() {
TableMetaData tableMetaData = new TableMetaData(Collections.singletonList(new ColumnMetaData("id", "dataType", true, false, false)), Collections.<String>emptyList());
assertTrue(tableMetaData.getColumns().get("id").isPrimaryKey());
}
@Test
public void assertColumnNotNull() {
TableMetaData tableMetaData = new TableMetaData(Collections.singletonList(new ColumnMetaData("id", "dataType", false, true, false)), Collections.<String>emptyList());
assertTrue(tableMetaData.getColumns().get("id").isNotNull());
}
@Test
public void assertColumnAutoIncrement() {
TableMetaData tableMetaData = new TableMetaData(Collections.singletonList(new ColumnMetaData("id", "dataType", false, false, true)), Collections.<String>emptyList());
assertTrue(tableMetaData.getColumns().get("id").isAutoIncrement());
}
}
......@@ -63,19 +63,19 @@ public final class TableMetasTest {
@Test
public void assertContainsColumn() {
TableMetaData tableMetaData = new TableMetaData(Collections.singletonList(new ColumnMetaData("name", "dataType", false)), Collections.<String>emptyList());
TableMetaData tableMetaData = new TableMetaData(Collections.singletonList(new ColumnMetaData("name", "dataType", false, false, false)), Collections.<String>emptyList());
assertTrue(new TableMetas(ImmutableMap.of("tableMetaData", tableMetaData)).containsColumn("tableMetaData", "name"));
}
@Test
public void assertGetAllColumnNamesWhenContainsKey() {
TableMetaData tableMetaData = new TableMetaData(Collections.singletonList(new ColumnMetaData("name", "dataType", false)), Collections.<String>emptyList());
TableMetaData tableMetaData = new TableMetaData(Collections.singletonList(new ColumnMetaData("name", "dataType", false, false, false)), Collections.<String>emptyList());
assertThat(new TableMetas(ImmutableMap.of("tableMetaData", tableMetaData)).getAllColumnNames("tableMetaData"), is((List<String>) Collections.singletonList("name")));
}
@Test
public void assertGetAllColumnNamesWhenNotContainsKey() {
TableMetaData tableMetaData = new TableMetaData(Collections.singletonList(new ColumnMetaData("name", "dataType", false)), Collections.<String>emptyList());
TableMetaData tableMetaData = new TableMetaData(Collections.singletonList(new ColumnMetaData("name", "dataType", false, false, false)), Collections.<String>emptyList());
assertThat(new TableMetas(ImmutableMap.of("tableMetaData", tableMetaData)).getAllColumnNames("other_tableMetaData"), is(Collections.<String>emptyList()));
}
......
......@@ -60,6 +60,10 @@ public final class TableMetaDataLoader {
private static final String TYPE_NAME = "TYPE_NAME";
private static final String INDEX_NAME = "INDEX_NAME";
private static final String IS_NULLABLE = "IS_NULLABLE";
private static final String IS_AUTOINCREMENT = "IS_AUTOINCREMENT";
private final DataSourceMetas dataSourceMetas;
......@@ -161,7 +165,10 @@ public final class TableMetaDataLoader {
String columnName = resultSet.getString(COLUMN_NAME);
String columnType = resultSet.getString(TYPE_NAME);
boolean isPrimaryKey = primaryKeys.contains(columnName);
Optional<ColumnMetaData> columnMetaData = getColumnMetaData(logicTableName, columnName, columnType, isPrimaryKey, generateKeyColumnName, encryptRule, derivedColumns);
boolean isNotNull = isPrimaryKey || !resultSet.getBoolean(IS_NULLABLE);
boolean isAutoIncrement = resultSet.getBoolean(IS_AUTOINCREMENT);
Optional<ColumnMetaData> columnMetaData = getColumnMetaData(logicTableName, columnName, columnType, isPrimaryKey,
isNotNull, isAutoIncrement, generateKeyColumnName, encryptRule, derivedColumns);
if (columnMetaData.isPresent()) {
result.add(columnMetaData.get());
}
......@@ -181,7 +188,8 @@ public final class TableMetaDataLoader {
}
private Optional<ColumnMetaData> getColumnMetaData(final String logicTableName, final String columnName, final String columnType, final boolean isPrimaryKey,
final String generateKeyColumnName, final EncryptRule encryptRule, final Collection<String> derivedColumns) {
final boolean isNotNull, final boolean isAutoIncrement, final String generateKeyColumnName,
final EncryptRule encryptRule, final Collection<String> derivedColumns) {
if (derivedColumns.contains(columnName)) {
return Optional.absent();
}
......@@ -189,12 +197,12 @@ public final class TableMetaDataLoader {
String logicColumnName = encryptRule.getLogicColumn(logicTableName, columnName);
String plainColumnName = encryptRule.findPlainColumn(logicTableName, logicColumnName).orNull();
String assistedQueryColumnName = encryptRule.findAssistedQueryColumn(logicTableName, logicColumnName).orNull();
return Optional.<ColumnMetaData>of(new EncryptColumnMetaData(logicColumnName, columnType, isPrimaryKey, columnName, plainColumnName, assistedQueryColumnName));
return Optional.<ColumnMetaData>of(new EncryptColumnMetaData(logicColumnName, columnType, isPrimaryKey, isNotNull, isAutoIncrement, columnName, plainColumnName, assistedQueryColumnName));
}
if (columnName.equalsIgnoreCase(generateKeyColumnName)) {
return Optional.<ColumnMetaData>of(new ShardingGeneratedKeyColumnMetaData(columnName, columnType, isPrimaryKey));
return Optional.<ColumnMetaData>of(new ShardingGeneratedKeyColumnMetaData(columnName, columnType, isPrimaryKey, isNotNull, isAutoIncrement));
}
return Optional.of(new ColumnMetaData(columnName, columnType, isPrimaryKey));
return Optional.of(new ColumnMetaData(columnName, columnType, isPrimaryKey, isNotNull, isAutoIncrement));
}
private Collection<String> getLogicIndexes(final Connection connection, final String catalog, final String actualTableName) throws SQLException {
......
......@@ -190,7 +190,8 @@ public final class ProjectionsContextTest {
private TableMetas createTableMetas() {
Map<String, TableMetaData> tables = new HashMap<>(1, 1);
tables.put("table", new TableMetaData(Arrays.asList(new ColumnMetaData("id", "number", true), new ColumnMetaData("name", "varchar", false)), Collections.<String>emptyList()));
tables.put("table", new TableMetaData(Arrays.asList(new ColumnMetaData("id", "number", true, true, true),
new ColumnMetaData("name", "varchar", false, false, false)), Collections.<String>emptyList()));
return new TableMetas(tables);
}
......
......@@ -74,8 +74,8 @@ public final class DatabaseTest {
}
private ShardingSphereMetaData getMetaDataForAllRoutingSQL() {
ColumnMetaData idColumnMetaData = new ColumnMetaData("id", "int", true);
ColumnMetaData nameColumnMetaData = new ColumnMetaData("user_id", "int", false);
ColumnMetaData idColumnMetaData = new ColumnMetaData("id", "int", true, true, true);
ColumnMetaData nameColumnMetaData = new ColumnMetaData("user_id", "int", false, false, false);
TableMetas tableMetas = mock(TableMetas.class);
when(tableMetas.get("tesT")).thenReturn(new TableMetaData(Arrays.asList(idColumnMetaData, nameColumnMetaData), Arrays.asList("id", "user_id")));
when(tableMetas.containsTable("tesT")).thenReturn(true);
......@@ -101,8 +101,8 @@ public final class DatabaseTest {
}
private ShardingSphereMetaData getMetaDataForPagination() {
ColumnMetaData idColumnMetaData = new ColumnMetaData("id", "int", true);
ColumnMetaData nameColumnMetaData = new ColumnMetaData("user_id", "int", false);
ColumnMetaData idColumnMetaData = new ColumnMetaData("id", "int", true, true, true);
ColumnMetaData nameColumnMetaData = new ColumnMetaData("user_id", "int", false, false, false);
TableMetas tableMetas = mock(TableMetas.class);
when(tableMetas.get("tbl_pagination")).thenReturn(new TableMetaData(Arrays.asList(idColumnMetaData, nameColumnMetaData), Arrays.asList("id", "user_id")));
when(tableMetas.containsTable("tbl_pagination")).thenReturn(true);
......
......@@ -61,13 +61,16 @@ public abstract class AbstractSQLRouteTest extends AbstractRoutingEngineTest {
private TableMetas buildTableMetas() {
Map<String, TableMetaData> tableMetaDataMap = new HashMap<>(3, 1);
tableMetaDataMap.put("t_order", new TableMetaData(Arrays.asList(new ColumnMetaData("order_id", "int", true), new ColumnMetaData("user_id", "int", false),
new ColumnMetaData("status", "int", false)), Collections.<String>emptySet()));
tableMetaDataMap.put("t_order_item", new TableMetaData(Arrays.asList(new ColumnMetaData("item_id", "int", true), new ColumnMetaData("order_id", "int", false),
new ColumnMetaData("user_id", "int", false), new ColumnMetaData("status", "varchar", false),
new ColumnMetaData("c_date", "timestamp", false)), Collections.<String>emptySet()));
tableMetaDataMap.put("t_other", new TableMetaData(Arrays.asList(new ColumnMetaData("order_id", "int", true)), Collections.<String>emptySet()));
tableMetaDataMap.put("t_category", new TableMetaData(Arrays.asList(new ColumnMetaData("order_id", "int", true)), Collections.<String>emptySet()));
tableMetaDataMap.put("t_order", new TableMetaData(Arrays.asList(new ColumnMetaData("order_id", "int", true, true, true),
new ColumnMetaData("user_id", "int", false, false, false),
new ColumnMetaData("status", "int", false, false, false)), Collections.<String>emptySet()));
tableMetaDataMap.put("t_order_item", new TableMetaData(Arrays.asList(new ColumnMetaData("item_id", "int", true, true, true),
new ColumnMetaData("order_id", "int", false, false, false),
new ColumnMetaData("user_id", "int", false, false, false),
new ColumnMetaData("status", "varchar", false, false, false),
new ColumnMetaData("c_date", "timestamp", false, false, false)), Collections.<String>emptySet()));
tableMetaDataMap.put("t_other", new TableMetaData(Arrays.asList(new ColumnMetaData("order_id", "int", true, true, true)), Collections.<String>emptySet()));
tableMetaDataMap.put("t_category", new TableMetaData(Arrays.asList(new ColumnMetaData("order_id", "int", true, true, true)), Collections.<String>emptySet()));
return new TableMetas(tableMetaDataMap);
}
}
......@@ -52,6 +52,10 @@ public final class EncryptRuntimeContext extends AbstractRuntimeContext<EncryptR
private static final String TYPE_NAME = "TYPE_NAME";
private static final String INDEX_NAME = "INDEX_NAME";
private static final String IS_NULLABLE = "IS_NULLABLE";
private static final String IS_AUTOINCREMENT = "IS_AUTOINCREMENT";
private final TableMetas tableMetas;
......@@ -87,7 +91,9 @@ public final class EncryptRuntimeContext extends AbstractRuntimeContext<EncryptR
String columnName = resultSet.getString(COLUMN_NAME);
String columnType = resultSet.getString(TYPE_NAME);
boolean isPrimaryKey = primaryKeys.contains(columnName);
Optional<ColumnMetaData> columnMetaData = getColumnMetaData(tableName, columnName, columnType, isPrimaryKey, encryptRule, derivedColumns);
boolean isNotNull = isPrimaryKey || !resultSet.getBoolean(IS_NULLABLE);
boolean isAutoIncrement = resultSet.getBoolean(IS_AUTOINCREMENT);
Optional<ColumnMetaData> columnMetaData = getColumnMetaData(tableName, columnName, columnType, isPrimaryKey, isNotNull, isAutoIncrement, encryptRule, derivedColumns);
if (columnMetaData.isPresent()) {
result.add(columnMetaData.get());
}
......@@ -97,7 +103,7 @@ public final class EncryptRuntimeContext extends AbstractRuntimeContext<EncryptR
}
private Optional<ColumnMetaData> getColumnMetaData(final String logicTableName, final String columnName, final String columnType, final boolean isPrimaryKey,
final EncryptRule encryptRule, final Collection<String> derivedColumns) {
final boolean isNotNull, final boolean isAutoIncrement, final EncryptRule encryptRule, final Collection<String> derivedColumns) {
if (derivedColumns.contains(columnName)) {
return Optional.absent();
}
......@@ -105,9 +111,9 @@ public final class EncryptRuntimeContext extends AbstractRuntimeContext<EncryptR
String logicColumnName = encryptRule.getLogicColumn(logicTableName, columnName);
String plainColumnName = encryptRule.findPlainColumn(logicTableName, logicColumnName).orNull();
String assistedQueryColumnName = encryptRule.findAssistedQueryColumn(logicTableName, logicColumnName).orNull();
return Optional.<ColumnMetaData>of(new EncryptColumnMetaData(logicColumnName, columnType, isPrimaryKey, columnName, plainColumnName, assistedQueryColumnName));
return Optional.<ColumnMetaData>of(new EncryptColumnMetaData(logicColumnName, columnType, isPrimaryKey, isNotNull, isAutoIncrement, columnName, plainColumnName, assistedQueryColumnName));
}
return Optional.of(new ColumnMetaData(columnName, columnType, isPrimaryKey));
return Optional.of(new ColumnMetaData(columnName, columnType, isPrimaryKey, isNotNull, isAutoIncrement));
}
private Collection<String> getPrimaryKeys(final Connection connection, final String tableName) throws SQLException {
......
......@@ -48,20 +48,44 @@ public final class QueryHeader {
private final Integer columnType;
private final int decimals;
private final boolean signed;
private final boolean primaryKey;
private final boolean notNull;
private final boolean autoIncrement;
public QueryHeader(final ResultSetMetaData resultSetMetaData, final LogicSchema logicSchema, final int columnIndex) throws SQLException {
this.schema = logicSchema.getName();
if (logicSchema instanceof ShardingSchema) {
Collection<String> tableNames = logicSchema.getShardingRule().getLogicTableNames(resultSetMetaData.getTableName(columnIndex));
this.table = tableNames.isEmpty() ? "" : tableNames.iterator().next();
if (resultSetMetaData.getTableName(columnIndex).isEmpty()) {
this.primaryKey = false;
this.notNull = false;
this.autoIncrement = false;
} else {
this.primaryKey = logicSchema.getMetaData().getTables().get(resultSetMetaData.getTableName(columnIndex)).getColumns()
.get(resultSetMetaData.getColumnName(columnIndex).toLowerCase()).isPrimaryKey();
this.notNull = logicSchema.getMetaData().getTables().get(resultSetMetaData.getTableName(columnIndex)).getColumns()
.get(resultSetMetaData.getColumnName(columnIndex).toLowerCase()).isNotNull();
this.autoIncrement = logicSchema.getMetaData().getTables().get(resultSetMetaData.getTableName(columnIndex)).getColumns()
.get(resultSetMetaData.getColumnName(columnIndex).toLowerCase()).isAutoIncrement();
}
} else {
this.table = resultSetMetaData.getTableName(columnIndex);
this.primaryKey = false;
this.notNull = false;
this.autoIncrement = false;
}
this.columnLabel = resultSetMetaData.getColumnLabel(columnIndex);
this.columnName = resultSetMetaData.getColumnName(columnIndex);
this.columnLength = resultSetMetaData.getColumnDisplaySize(columnIndex);
this.columnType = resultSetMetaData.getColumnType(columnIndex);
this.decimals = resultSetMetaData.getScale(columnIndex);
this.signed = resultSetMetaData.isSigned(columnIndex);
}
/**
......
......@@ -53,7 +53,7 @@ public final class ShowDatabasesBackendHandler implements TextProtocolBackendHan
@Override
public BackendResponse execute() {
mergedResult = new ShowDatabasesMergedResult(getSchemaNames());
return new QueryResponse(Collections.singletonList(new QueryHeader("information_schema", "SCHEMATA", "Database", "SCHEMA_NAME", 100, Types.VARCHAR, 0)));
return new QueryResponse(Collections.singletonList(new QueryHeader("information_schema", "SCHEMATA", "Database", "SCHEMA_NAME", 100, Types.VARCHAR, 0, false, false, false, false)));
}
private List<String> getSchemaNames() {
......
......@@ -60,8 +60,8 @@ public final class ShardingCTLExplainBackendHandler implements TextProtocolBacke
StatementExecutorWrapper statementExecutorWrapper = new StatementExecutorWrapper(backendConnection.getLogicSchema());
routeUnits = statementExecutorWrapper.route(explainStatement.get().getSql()).getRouteUnits().iterator();
queryHeaders = new ArrayList<>(2);
queryHeaders.add(new QueryHeader("", "", "datasource_name", "", 255, Types.CHAR, 0));
queryHeaders.add(new QueryHeader("", "", "sql", "", 255, Types.CHAR, 0));
queryHeaders.add(new QueryHeader("", "", "datasource_name", "", 255, Types.CHAR, 0, false, false, false, false));
queryHeaders.add(new QueryHeader("", "", "sql", "", 255, Types.CHAR, 0, false, false, false, false));
return new QueryResponse(queryHeaders);
}
......
......@@ -39,8 +39,8 @@ public final class HintShowStatusExecutor extends AbstractHintQueryExecutor<Hint
@Override
protected List<QueryHeader> createQueryHeaders() {
List<QueryHeader> queryHeaders = new ArrayList<>(2);
queryHeaders.add(new QueryHeader("", "", "master_only", "", 5, Types.CHAR, 0));
queryHeaders.add(new QueryHeader("", "", "sharding_type", "", 255, Types.CHAR, 0));
queryHeaders.add(new QueryHeader("", "", "master_only", "", 5, Types.CHAR, 0, false, false, false, false));
queryHeaders.add(new QueryHeader("", "", "sharding_type", "", 255, Types.CHAR, 0, false, false, false, false));
return queryHeaders;
}
......
......@@ -50,9 +50,9 @@ public final class HintShowTableStatusExecutor extends AbstractHintQueryExecutor
@Override
protected List<QueryHeader> createQueryHeaders() {
List<QueryHeader> queryHeaders = new ArrayList<>(3);
queryHeaders.add(new QueryHeader("", "", "table_name", "", 255, Types.CHAR, 0));
queryHeaders.add(new QueryHeader("", "", "database_sharding_values", "", 255, Types.CHAR, 0));
queryHeaders.add(new QueryHeader("", "", "table_sharding_values", "", 255, Types.CHAR, 0));
queryHeaders.add(new QueryHeader("", "", "table_name", "", 255, Types.CHAR, 0, false, false, false, false));
queryHeaders.add(new QueryHeader("", "", "database_sharding_values", "", 255, Types.CHAR, 0, false, false, false, false));
queryHeaders.add(new QueryHeader("", "", "table_sharding_values", "", 255, Types.CHAR, 0, false, false, false, false));
return queryHeaders;
}
......
......@@ -71,7 +71,7 @@ public final class ShardingCTLShowBackendHandler implements TextProtocolBackendH
private BackendResponse createResponsePackets(final String columnName, final Object... values) {
mergedResult = new ShowShardingCTLMergedResult(Collections.singletonList(Arrays.asList(values)));
return new QueryResponse(Collections.singletonList(new QueryHeader("", "", columnName, columnName, 100, Types.VARCHAR, 0)));
return new QueryResponse(Collections.singletonList(new QueryHeader("", "", columnName, columnName, 100, Types.VARCHAR, 0, false, false, false, false)));
}
@Override
......
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.shardingsphere.shardingproxy.backend.response.query;
import lombok.SneakyThrows;
import org.apache.shardingsphere.core.metadata.ShardingSphereMetaData;
import org.apache.shardingsphere.core.metadata.column.ColumnMetaData;
import org.apache.shardingsphere.core.metadata.datasource.DataSourceMetas;
import org.apache.shardingsphere.core.metadata.table.TableMetaData;
import org.apache.shardingsphere.core.metadata.table.TableMetas;
import org.apache.shardingsphere.core.rule.ShardingRule;
import org.apache.shardingsphere.shardingproxy.backend.schema.impl.ShardingSchema;
import org.apache.shardingsphere.spi.database.DataSourceMetaData;
import org.junit.Test;
import java.sql.ResultSetMetaData;
import java.sql.Types;
import java.util.Arrays;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public final class QueryHeaderTest {
@Test
public void assertQueryHeaderSchema() throws Exception {
QueryHeader header = new QueryHeader(getResultSetMetaData(), getShardingSchema(), 1);
assertThat(header.getSchema(), is("sharding_schema"));
}
@Test
public void assertQueryHeaderTable() throws Exception {
QueryHeader header = new QueryHeader(getResultSetMetaData(), getShardingSchema(), 1);
assertThat(header.getTable(), is("t_logic_order"));
}
@Test
public void assertQueryHeaderColumnLabel() throws Exception {
QueryHeader header = new QueryHeader(getResultSetMetaData(), getShardingSchema(), 1);
assertThat(header.getColumnLabel(), is("order_id"));
}
@Test
public void assertQueryHeaderColumnName() throws Exception {
QueryHeader header = new QueryHeader(getResultSetMetaData(), getShardingSchema(), 1);
assertThat(header.getColumnName(), is("order_id"));
}
@Test
public void assertQueryHeaderColumnLength() throws Exception {
QueryHeader header = new QueryHeader(getResultSetMetaData(), getShardingSchema(), 1);
assertThat(header.getColumnLength(), is(Integer.valueOf(1)));
}
@Test
public void assertQueryHeaderColumnType() throws Exception {
QueryHeader header = new QueryHeader(getResultSetMetaData(), getShardingSchema(), 1);
assertThat(header.getColumnType(), is(Types.INTEGER));
}
@Test
public void assertQueryHeaderDecimals() throws Exception {
QueryHeader header = new QueryHeader(getResultSetMetaData(), getShardingSchema(), 1);
assertThat(header.getDecimals(), is(Integer.valueOf(1)));
}
@Test
public void assertQueryHeaderSigned() throws Exception {
QueryHeader header = new QueryHeader(getResultSetMetaData(), getShardingSchema(), 1);
assertTrue(header.isSigned());
}
@Test
public void assertQueryHeaderPrimaryKey() throws Exception {
QueryHeader header = new QueryHeader(getResultSetMetaData(), getShardingSchema(), 1);
assertTrue(header.isPrimaryKey());
}
@Test
public void assertQueryHeaderNotNull() throws Exception {
QueryHeader header = new QueryHeader(getResultSetMetaData(), getShardingSchema(), 1);
assertTrue(header.isNotNull());
}
@Test
public void assertQueryHeaderAutoIncrement() throws Exception {
QueryHeader header = new QueryHeader(getResultSetMetaData(), getShardingSchema(), 1);
assertTrue(header.isAutoIncrement());
}
@SneakyThrows
private ShardingSchema getShardingSchema() {
ShardingSchema result = mock(ShardingSchema.class);
ColumnMetaData columnMetaData = new ColumnMetaData("order_id", "int", true, true, true);
TableMetas tableMetas = mock(TableMetas.class);
when(tableMetas.get("t_order")).thenReturn(new TableMetaData(Arrays.asList(columnMetaData), Arrays.asList("order_id")));
ShardingSphereMetaData metaData = mock(ShardingSphereMetaData.class);
when(metaData.getTables()).thenReturn(tableMetas);
DataSourceMetas dataSourceMetas = mock(DataSourceMetas.class);
when(dataSourceMetas.getDataSourceMetaData("ds_0")).thenReturn(mock(DataSourceMetaData.class));
when(metaData.getDataSources()).thenReturn(dataSourceMetas);
when(result.getMetaData()).thenReturn(metaData);
ShardingRule shardingRule = mock(ShardingRule.class);
when(shardingRule.getLogicTableNames("t_order")).thenReturn(Arrays.asList("t_logic_order"));
when(result.getShardingRule()).thenReturn(shardingRule);
when(result.getName()).thenReturn("sharding_schema");
return result;
}
@SneakyThrows
private ResultSetMetaData getResultSetMetaData() {
ResultSetMetaData result = mock(ResultSetMetaData.class);
when(result.getTableName(1)).thenReturn("t_order");
when(result.getColumnLabel(1)).thenReturn("order_id");
when(result.getColumnName(1)).thenReturn("order_id");
when(result.getColumnType(1)).thenReturn(Types.INTEGER);
when(result.isSigned(1)).thenReturn(true);
when(result.getColumnDisplaySize(1)).thenReturn(1);
when(result.getScale(1)).thenReturn(1);
return result;
}
}
......@@ -33,6 +33,7 @@ import org.apache.shardingsphere.shardingproxy.frontend.mysql.MySQLErrPacketFact
import org.apache.shardingsphere.shardingproxy.transport.mysql.constant.MySQLColumnType;
import org.apache.shardingsphere.shardingproxy.transport.mysql.packet.MySQLPacket;
import org.apache.shardingsphere.shardingproxy.transport.mysql.packet.command.query.MySQLColumnDefinition41Packet;
import org.apache.shardingsphere.shardingproxy.transport.mysql.packet.command.query.MySQLColumnFieldDetailFlag;
import org.apache.shardingsphere.shardingproxy.transport.mysql.packet.command.query.MySQLFieldCountPacket;
import org.apache.shardingsphere.shardingproxy.transport.mysql.packet.command.query.text.MySQLTextResultSetRowPacket;
import org.apache.shardingsphere.shardingproxy.transport.mysql.packet.command.query.text.query.MySQLComQueryPacket;
......@@ -93,12 +94,29 @@ public final class MySQLComQueryPacketExecutor implements QueryCommandExecutor {
List<QueryHeader> queryHeader = backendResponse.getQueryHeaders();
result.add(new MySQLFieldCountPacket(++currentSequenceId, queryHeader.size()));
for (QueryHeader each : queryHeader) {
result.add(new MySQLColumnDefinition41Packet(++currentSequenceId, each.getSchema(), each.getTable(), each.getTable(),
result.add(new MySQLColumnDefinition41Packet(++currentSequenceId, getColumnFieldDetailFlag(each), each.getSchema(), each.getTable(), each.getTable(),
each.getColumnLabel(), each.getColumnName(), each.getColumnLength(), MySQLColumnType.valueOfJDBCType(each.getColumnType()), each.getDecimals()));
}
result.add(new MySQLEofPacket(++currentSequenceId));
return result;
}
private int getColumnFieldDetailFlag(final QueryHeader header) {
int result = 0;
if (header.isPrimaryKey()) {
result += MySQLColumnFieldDetailFlag.PRIMARY_KEY.getValue();
}
if (header.isNotNull()) {
result += MySQLColumnFieldDetailFlag.NOT_NULL.getValue();
}
if (!header.isSigned()) {
result += MySQLColumnFieldDetailFlag.UNSIGNED.getValue();
}
if (header.isAutoIncrement()) {
result += MySQLColumnFieldDetailFlag.AUTO_INCREMENT.getValue();
}
return result;
}
@Override
public boolean isQuery() {
......
......@@ -31,6 +31,7 @@ import java.sql.SQLException;
* Column definition above MySQL 4.1 packet protocol.
*
* @see <a href="https://dev.mysql.com/doc/internals/en/com-query-response.html#packet-Protocol::ColumnDefinition41">ColumnDefinition41</a>
* @see <a href="https://mariadb.com/kb/en/library/resultset/#column-definition-packet">Column definition packet</a>
*
* @author zhangliang
* @author zhangyonglun
......@@ -72,9 +73,14 @@ public final class MySQLColumnDefinition41Packet implements MySQLPacket {
public MySQLColumnDefinition41Packet(final int sequenceId, final String schema, final String table, final String orgTable,
final String name, final String orgName, final int columnLength, final MySQLColumnType columnType, final int decimals) {
this(sequenceId, 0, schema, table, orgTable, name, orgName, columnLength, columnType, decimals);
}
public MySQLColumnDefinition41Packet(final int sequenceId, final int flags, final String schema, final String table, final String orgTable,
final String name, final String orgName, final int columnLength, final MySQLColumnType columnType, final int decimals) {
this.sequenceId = sequenceId;
this.characterSet = MySQLServerInfo.CHARSET;
this.flags = 0;
this.flags = flags;
this.schema = schema;
this.table = table;
this.orgTable = orgTable;
......
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.shardingsphere.shardingproxy.transport.mysql.packet.command.query;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
/**
* MySQL Column Field Detail Flag.
*
* @see <a href="https://mariadb.com/kb/en/library/resultset/#field-detail-flag">Field detail flag</a>
*
* @author dongzonglei
*/
@RequiredArgsConstructor
@Getter
public enum MySQLColumnFieldDetailFlag {
NOT_NULL(1),
PRIMARY_KEY(2),
UNIQUE_KEY(4),
MULTIPLE_KEY(8),
BLOB(16),
UNSIGNED(32),
ZEROFILL_FLAG(64),
BINARY_COLLATION(128),
ENUM(256),
AUTO_INCREMENT(512),
TIMESTAMP(1024),
SET(2048),
NO_DEFAULT_VALUE_FLAG(4096),
ON_UPDATE_NOW_FLAG(8192),
NUM_FLAG(32768);
private final int value;
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册