未验证 提交 221f733a 编写于 作者: S sandynz 提交者: GitHub

Fix #6408 : Cannot find JDBC type '2003' in PostgreSQL column type (#6474)

* Support PostgreSQL array type (#6408)

* Support PostgreSQL array type, unit test (#6408)

* Support PostgreSQL array type, follow review suggestion (#6408)
上级 263a4926
/*
* 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.db.protocol.postgresql.constant;
import java.util.HashMap;
import java.util.Map;
/**
* Array column types for PostgreSQL.
*/
public class PostgreSQLArrayColumnType {
private static final String ORIGINAL_RECORD_LINES =
"_aclitem 1034\n"
+ "_array_tc_0 16425\n"
+ "_array_tc_1 16433\n"
+ "_bit 1561\n"
+ "_bool 1000\n"
+ "_box 1020\n"
+ "_bpchar 1014\n"
+ "_bytea 1001\n"
+ "_cardinal_number 13031\n"
+ "_char 1002\n"
+ "_character_data 13034\n"
+ "_cid 1012\n"
+ "_cidr 651\n"
+ "_circle 719\n"
+ "_cstring 1263\n"
+ "_date 1182\n"
+ "_daterange 3913\n"
+ "_float4 1021\n"
+ "_float8 1022\n"
+ "_gtsvector 3644\n"
+ "_inet 1041\n"
+ "_int2 1005\n"
+ "_int2vector 1006\n"
+ "_int4 1007\n"
+ "_int4range 3905\n"
+ "_int8 1016\n"
+ "_int8range 3927\n"
+ "_interval 1187\n"
+ "_json 199\n"
+ "_jsonb 3807\n"
+ "_jsonpath 4073\n"
+ "_line 629\n"
+ "_lseg 1018\n"
+ "_macaddr 1040\n"
+ "_macaddr8 775\n"
+ "_money 791\n"
+ "_name 1003\n"
+ "_numeric 1231\n"
+ "_numrange 3907\n"
+ "_oid 1028\n"
+ "_oidvector 1013\n"
+ "_path 1019\n"
+ "_pg_foreign_data_wrappers 13265\n"
+ "_pg_foreign_servers 13274\n"
+ "_pg_foreign_table_columns 13258\n"
+ "_pg_foreign_tables 13284\n"
+ "_pg_lsn 3221\n"
+ "_pg_user_mappings 13294\n"
+ "_point 1017\n"
+ "_polygon 1027\n"
+ "_record 2287\n"
+ "_refcursor 2201\n"
+ "_regclass 2210\n"
+ "_regconfig 3735\n"
+ "_regdictionary 3770\n"
+ "_regnamespace 4090\n"
+ "_regoper 2208\n"
+ "_regoperator 2209\n"
+ "_regproc 1008\n"
+ "_regprocedure 2207\n"
+ "_regrole 4097\n"
+ "_regtype 2211\n"
+ "_sql_identifier 13036\n"
+ "_test_array 16395\n"
+ "_text 1009\n"
+ "_tid 1010\n"
+ "_time 1183\n"
+ "_time_stamp 13041\n"
+ "_timestamp 1115\n"
+ "_timestamptz 1185\n"
+ "_timetz 1270\n"
+ "_tsquery 3645\n"
+ "_tsrange 3909\n"
+ "_tstzrange 3911\n"
+ "_tsvector 3643\n"
+ "_txid_snapshot 2949\n"
+ "_uuid 2951\n"
+ "_varbit 1563\n"
+ "_varchar 1015\n"
+ "_xid 1011\n"
+ "_xml 143\n"
+ "_yes_or_no 13043";
private static final Map<String, Integer> COLUMN_TYPE_NAME_OID_MAP = new HashMap<>(128, 1.0F);
static {
for (String line : ORIGINAL_RECORD_LINES.split("\n")) {
String[] values = line.split(" ");
COLUMN_TYPE_NAME_OID_MAP.put(values[0], Integer.parseInt(values[1]));
}
}
/**
* Get type oid by database-specific column type name.
*
* @param columnTypeName PostgreSQL column type name, e.g. <code>int4</code>
* @return type oid, e.g. <code>23</code> for <code>int4</code>
* @throws IllegalArgumentException if no type oid could be found
*/
public static int getTypeOidByColumnTypeName(final String columnTypeName) throws IllegalArgumentException {
if (COLUMN_TYPE_NAME_OID_MAP.containsKey(columnTypeName)) {
return COLUMN_TYPE_NAME_OID_MAP.get(columnTypeName);
}
throw new IllegalArgumentException(String.format("Cannot find PostgreSQL type oid for columnTypeName '%s'", columnTypeName));
}
}
......@@ -17,13 +17,19 @@
package org.apache.shardingsphere.db.protocol.postgresql.packet.command.query;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Types;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.apache.shardingsphere.db.protocol.postgresql.constant.PostgreSQLArrayColumnType;
import org.apache.shardingsphere.db.protocol.postgresql.constant.PostgreSQLColumnType;
/**
* Column description for PostgreSQL.
*/
@Getter
@Slf4j
public final class PostgreSQLColumnDescription {
private final String columnName;
......@@ -40,10 +46,20 @@ public final class PostgreSQLColumnDescription {
private final int dataFormat = 0;
public PostgreSQLColumnDescription(final String columnName, final int columnIndex, final int columnType, final int columnLength) {
public PostgreSQLColumnDescription(final String columnName, final int columnIndex, final int columnType, final int columnLength, final ResultSetMetaData resultSetMetaData) {
this.columnName = columnName;
this.columnIndex = columnIndex;
this.typeOID = PostgreSQLColumnType.valueOfJDBCType(columnType).getValue();
if (Types.ARRAY == columnType && null != resultSetMetaData) {
String columnTypeName = null;
try {
columnTypeName = resultSetMetaData.getColumnTypeName(columnIndex);
} catch (final SQLException ex) {
log.error("getColumnTypeName failed, columnName={}, columnIndex={}", columnName, columnIndex, ex);
}
this.typeOID = PostgreSQLArrayColumnType.getTypeOidByColumnTypeName(columnTypeName);
} else {
this.typeOID = PostgreSQLColumnType.valueOfJDBCType(columnType).getValue();
}
this.columnLength = columnLength;
}
}
/*
* 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.db.protocol.postgresql.constant;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
public class PostgreSQLArrayColumnTypeTest {
@Test
public void assertIntegerArrayGot() {
int columnTypeName = PostgreSQLArrayColumnType.getTypeOidByColumnTypeName("_int4");
assertThat(columnTypeName, is(1007));
}
@Test(expected = IllegalArgumentException.class)
public void assertIllegalArgExThrown() {
PostgreSQLArrayColumnType.getTypeOidByColumnTypeName("not_exist_type");
}
}
/*
* 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.db.protocol.postgresql.packet.command.query;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Types;
import org.junit.Test;
import org.mockito.Mockito;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
public class PostgreSQLColumnDescriptionTest {
@Test
public void assertIntegerTypeOid() {
PostgreSQLColumnDescription description = new PostgreSQLColumnDescription("age", 1, Types.INTEGER, 4, null);
assertThat(description.getTypeOID(), is(23));
}
@Test
public void assertIntegerArrayTypeOid() throws SQLException {
ResultSetMetaData resultSetMetaData = Mockito.mock(ResultSetMetaData.class);
Mockito.when(resultSetMetaData.getColumnTypeName(2)).thenReturn("_int4");
PostgreSQLColumnDescription description = new PostgreSQLColumnDescription("ages", 2, Types.ARRAY, 12, resultSetMetaData);
assertThat(description.getTypeOID(), is(1007));
}
}
......@@ -18,6 +18,7 @@
package org.apache.shardingsphere.infra.executor.sql;
import java.io.InputStream;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.Calendar;
......@@ -25,7 +26,14 @@ import java.util.Calendar;
* Query result form SQL.
*/
public interface QueryResult {
/**
* Get JDBC ResultSetMetaData.
*
* @return JDBC ResultSetMetaData
*/
ResultSetMetaData getResultSetMetaData();
/**
* iterate next data.
*
......
......@@ -111,7 +111,12 @@ public final class MemoryQueryResult implements QueryResult {
return resultSet.getObject(columnIndex);
}
}
@Override
public ResultSetMetaData getResultSetMetaData() {
return resultSetMetaData;
}
@Override
public boolean next() {
if (rows.hasNext()) {
......
......@@ -44,7 +44,12 @@ public final class StreamQueryResult implements QueryResult {
resultSetMetaData = resultSet.getMetaData();
this.resultSet = resultSet;
}
@Override
public ResultSetMetaData getResultSetMetaData() {
return resultSetMetaData;
}
@Override
public boolean next() throws SQLException {
return resultSet.next();
......
......@@ -17,6 +17,7 @@
package org.apache.shardingsphere.proxy.frontend.postgresql.command.query.binary.bind;
import java.sql.ResultSetMetaData;
import lombok.Getter;
import org.apache.shardingsphere.db.protocol.packet.DatabasePacket;
import org.apache.shardingsphere.db.protocol.postgresql.constant.PostgreSQLColumnType;
......@@ -29,6 +30,7 @@ import org.apache.shardingsphere.db.protocol.postgresql.packet.command.query.bin
import org.apache.shardingsphere.db.protocol.postgresql.packet.command.query.text.PostgreSQLDataRowPacket;
import org.apache.shardingsphere.db.protocol.postgresql.packet.generic.PostgreSQLCommandCompletePacket;
import org.apache.shardingsphere.db.protocol.postgresql.packet.generic.PostgreSQLErrorResponsePacket;
import org.apache.shardingsphere.infra.executor.sql.QueryResult;
import org.apache.shardingsphere.infra.executor.sql.raw.execute.result.query.QueryHeader;
import org.apache.shardingsphere.proxy.backend.communication.DatabaseCommunicationEngine;
import org.apache.shardingsphere.proxy.backend.communication.DatabaseCommunicationEngineFactory;
......@@ -117,9 +119,11 @@ public final class PostgreSQLComBindExecutor implements QueryCommandExecutor {
private List<PostgreSQLColumnDescription> getPostgreSQLColumnDescriptions(final QueryResponse queryResponse) {
List<PostgreSQLColumnDescription> result = new LinkedList<>();
List<QueryResult> queryResults = queryResponse.getQueryResults();
ResultSetMetaData resultSetMetaData = queryResults.size() > 0 ? queryResults.get(0).getResultSetMetaData() : null;
int columnIndex = 0;
for (QueryHeader each : queryResponse.getQueryHeaders()) {
result.add(new PostgreSQLColumnDescription(each.getColumnName(), ++columnIndex, each.getColumnType(), each.getColumnLength()));
result.add(new PostgreSQLColumnDescription(each.getColumnName(), ++columnIndex, each.getColumnType(), each.getColumnLength(), resultSetMetaData));
}
return result;
}
......
......@@ -17,6 +17,7 @@
package org.apache.shardingsphere.proxy.frontend.postgresql.command.query.text;
import java.sql.ResultSetMetaData;
import lombok.Getter;
import org.apache.shardingsphere.db.protocol.packet.DatabasePacket;
import org.apache.shardingsphere.db.protocol.postgresql.packet.PostgreSQLPacket;
......@@ -27,6 +28,7 @@ import org.apache.shardingsphere.db.protocol.postgresql.packet.command.query.tex
import org.apache.shardingsphere.db.protocol.postgresql.packet.generic.PostgreSQLCommandCompletePacket;
import org.apache.shardingsphere.db.protocol.postgresql.packet.generic.PostgreSQLErrorResponsePacket;
import org.apache.shardingsphere.infra.database.type.DatabaseTypes;
import org.apache.shardingsphere.infra.executor.sql.QueryResult;
import org.apache.shardingsphere.infra.executor.sql.raw.execute.result.query.QueryHeader;
import org.apache.shardingsphere.proxy.backend.communication.jdbc.connection.BackendConnection;
import org.apache.shardingsphere.proxy.backend.response.BackendResponse;
......@@ -102,9 +104,11 @@ public final class PostgreSQLComQueryExecutor implements QueryCommandExecutor {
private List<PostgreSQLColumnDescription> getPostgreSQLColumnDescriptions(final QueryResponse queryResponse) {
List<PostgreSQLColumnDescription> result = new LinkedList<>();
List<QueryResult> queryResults = queryResponse.getQueryResults();
ResultSetMetaData resultSetMetaData = queryResults.size() > 0 ? queryResults.get(0).getResultSetMetaData() : null;
int columnIndex = 0;
for (QueryHeader each : queryResponse.getQueryHeaders()) {
result.add(new PostgreSQLColumnDescription(each.getColumnName(), ++columnIndex, each.getColumnType(), each.getColumnLength()));
result.add(new PostgreSQLColumnDescription(each.getColumnName(), ++columnIndex, each.getColumnType(), each.getColumnLength(), resultSetMetaData));
}
return result;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册