diff --git a/shardingsphere-db-protocol/shardingsphere-db-protocol-core/src/main/java/org/apache/shardingsphere/db/protocol/parameter/TypeUnspecifiedSQLParameter.java b/shardingsphere-db-protocol/shardingsphere-db-protocol-core/src/main/java/org/apache/shardingsphere/db/protocol/parameter/TypeUnspecifiedSQLParameter.java new file mode 100644 index 0000000000000000000000000000000000000000..a7766bd9e83dcd5ddfeeac21527a1fa31cf47cfe --- /dev/null +++ b/shardingsphere-db-protocol/shardingsphere-db-protocol-core/src/main/java/org/apache/shardingsphere/db/protocol/parameter/TypeUnspecifiedSQLParameter.java @@ -0,0 +1,24 @@ +/* + * 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.parameter; + +/** + * Type unspecified SQL parameter. + */ +public interface TypeUnspecifiedSQLParameter { +} diff --git a/shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/main/java/org/apache/shardingsphere/db/protocol/postgresql/packet/command/query/binary/bind/PostgreSQLComBindPacket.java b/shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/main/java/org/apache/shardingsphere/db/protocol/postgresql/packet/command/query/binary/bind/PostgreSQLComBindPacket.java index 3045fe9b230fba91d3f03b3268af76f61e82eedd..1f3133d7a160662f3ba66431afd6a3bb4013ad81 100644 --- a/shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/main/java/org/apache/shardingsphere/db/protocol/postgresql/packet/command/query/binary/bind/PostgreSQLComBindPacket.java +++ b/shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/main/java/org/apache/shardingsphere/db/protocol/postgresql/packet/command/query/binary/bind/PostgreSQLComBindPacket.java @@ -70,7 +70,11 @@ public final class PostgreSQLComBindPacket extends PostgreSQLCommandPacket { int parametersCount = payload.readInt2(); List result = new ArrayList<>(parametersCount); for (int parameterIndex = 0; parameterIndex < parametersCount; parameterIndex++) { - payload.readInt4(); + int paramValueLen = payload.readInt4(); + if (-1 == paramValueLen) { + result.add(null); + continue; + } PostgreSQLBinaryProtocolValue binaryProtocolValue = PostgreSQLBinaryProtocolValueFactory.getBinaryProtocolValue(parameterTypes.get(parameterIndex).getColumnType()); result.add(binaryProtocolValue.read(payload)); } diff --git a/shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/main/java/org/apache/shardingsphere/db/protocol/postgresql/packet/command/query/binary/bind/PostgreSQLTypeUnspecifiedSQLParameter.java b/shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/main/java/org/apache/shardingsphere/db/protocol/postgresql/packet/command/query/binary/bind/PostgreSQLTypeUnspecifiedSQLParameter.java new file mode 100644 index 0000000000000000000000000000000000000000..374905501fcb36fc932703fe221cf94bc1de8e79 --- /dev/null +++ b/shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/main/java/org/apache/shardingsphere/db/protocol/postgresql/packet/command/query/binary/bind/PostgreSQLTypeUnspecifiedSQLParameter.java @@ -0,0 +1,37 @@ +/* + * 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.binary.bind; + +import org.apache.shardingsphere.db.protocol.parameter.TypeUnspecifiedSQLParameter; + +/** + * Type unspecified SQL parameter for PostgreSQL. + */ +public final class PostgreSQLTypeUnspecifiedSQLParameter implements TypeUnspecifiedSQLParameter { + + private final String parameterValue; + + public PostgreSQLTypeUnspecifiedSQLParameter(final String parameterValue) { + this.parameterValue = parameterValue; + } + + @Override + public String toString() { + return parameterValue; + } +} diff --git a/shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/main/java/org/apache/shardingsphere/db/protocol/postgresql/packet/command/query/binary/bind/protocol/PostgreSQLBinaryProtocolValueFactory.java b/shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/main/java/org/apache/shardingsphere/db/protocol/postgresql/packet/command/query/binary/bind/protocol/PostgreSQLBinaryProtocolValueFactory.java index 9773deebd013e5c78c71ffad66c21fb3f5e6704e..625e3fc7cb7250ab8505e3a00dfeaa02741fcdaf 100644 --- a/shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/main/java/org/apache/shardingsphere/db/protocol/postgresql/packet/command/query/binary/bind/protocol/PostgreSQLBinaryProtocolValueFactory.java +++ b/shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/main/java/org/apache/shardingsphere/db/protocol/postgresql/packet/command/query/binary/bind/protocol/PostgreSQLBinaryProtocolValueFactory.java @@ -34,6 +34,7 @@ public final class PostgreSQLBinaryProtocolValueFactory { private static final Map BINARY_PROTOCOL_VALUES = new HashMap<>(); static { + setUnspecifiedBinaryProtocolValue(); setStringLenencBinaryProtocolValue(); setInt8BinaryProtocolValue(); setInt4BinaryProtocolValue(); @@ -44,6 +45,11 @@ public final class PostgreSQLBinaryProtocolValueFactory { setTimeBinaryProtocolValue(); } + private static void setUnspecifiedBinaryProtocolValue() { + PostgreSQLUnspecifiedBinaryProtocolValue binaryProtocolValue = new PostgreSQLUnspecifiedBinaryProtocolValue(); + BINARY_PROTOCOL_VALUES.put(PostgreSQLColumnType.POSTGRESQL_TYPE_UNSPECIFIED, binaryProtocolValue); + } + private static void setStringLenencBinaryProtocolValue() { PostgreSQLStringBinaryProtocolValue binaryProtocolValue = new PostgreSQLStringBinaryProtocolValue(); BINARY_PROTOCOL_VALUES.put(PostgreSQLColumnType.POSTGRESQL_TYPE_VARCHAR, binaryProtocolValue); diff --git a/shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/main/java/org/apache/shardingsphere/db/protocol/postgresql/packet/command/query/binary/bind/protocol/PostgreSQLUnspecifiedBinaryProtocolValue.java b/shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/main/java/org/apache/shardingsphere/db/protocol/postgresql/packet/command/query/binary/bind/protocol/PostgreSQLUnspecifiedBinaryProtocolValue.java new file mode 100644 index 0000000000000000000000000000000000000000..5acb86fa0d1cb2e9ca0ba6a8e27845b12a67bfb2 --- /dev/null +++ b/shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/main/java/org/apache/shardingsphere/db/protocol/postgresql/packet/command/query/binary/bind/protocol/PostgreSQLUnspecifiedBinaryProtocolValue.java @@ -0,0 +1,46 @@ +/* + * 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.binary.bind.protocol; + +import org.apache.shardingsphere.db.protocol.postgresql.packet.command.query.binary.bind.PostgreSQLTypeUnspecifiedSQLParameter; +import org.apache.shardingsphere.db.protocol.postgresql.payload.PostgreSQLPacketPayload; + +/** + * Binary protocol value for unspecified for PostgreSQL. + */ +public final class PostgreSQLUnspecifiedBinaryProtocolValue implements PostgreSQLBinaryProtocolValue { + + @Override + public int getColumnLength(final Object value) { + throw new UnsupportedOperationException(); + } + + @Override + public Object read(final PostgreSQLPacketPayload payload) { + payload.getByteBuf().readerIndex(payload.getByteBuf().readerIndex() - 4); + byte[] bytes = new byte[payload.readInt4()]; + payload.getByteBuf().readBytes(bytes); + String result = new String(bytes); + return new PostgreSQLTypeUnspecifiedSQLParameter(result); + } + + @Override + public void write(final PostgreSQLPacketPayload payload, final Object value) { + throw new UnsupportedOperationException(); + } +} diff --git a/shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/test/java/org/apache/shardingsphere/db/protocol/postgresql/packet/command/query/binary/bind/PostgreSQLTypeUnspecifiedSQLParameterTest.java b/shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/test/java/org/apache/shardingsphere/db/protocol/postgresql/packet/command/query/binary/bind/PostgreSQLTypeUnspecifiedSQLParameterTest.java new file mode 100644 index 0000000000000000000000000000000000000000..236db1e699bc3ffbb5c4452f7e143b3af556616d --- /dev/null +++ b/shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/test/java/org/apache/shardingsphere/db/protocol/postgresql/packet/command/query/binary/bind/PostgreSQLTypeUnspecifiedSQLParameterTest.java @@ -0,0 +1,34 @@ +/* + * 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.binary.bind; + +import org.junit.Test; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +public final class PostgreSQLTypeUnspecifiedSQLParameterTest { + + @Test + public void assertToString() { + String timestampStr = "2020-08-23 15:57:03+08"; + PostgreSQLTypeUnspecifiedSQLParameter parameter = new PostgreSQLTypeUnspecifiedSQLParameter(timestampStr); + assertThat(parameter.toString(), is(timestampStr)); + } + +} diff --git a/shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/test/java/org/apache/shardingsphere/db/protocol/postgresql/packet/command/query/binary/bind/protocol/PostgreSQLUnspecifiedBinaryProtocolValueTest.java b/shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/test/java/org/apache/shardingsphere/db/protocol/postgresql/packet/command/query/binary/bind/protocol/PostgreSQLUnspecifiedBinaryProtocolValueTest.java new file mode 100644 index 0000000000000000000000000000000000000000..8ebf7dcb4511658e852812375b5cf865de7101d6 --- /dev/null +++ b/shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/test/java/org/apache/shardingsphere/db/protocol/postgresql/packet/command/query/binary/bind/protocol/PostgreSQLUnspecifiedBinaryProtocolValueTest.java @@ -0,0 +1,62 @@ +/* + * 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.binary.bind.protocol; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.PooledByteBufAllocator; +import io.netty.buffer.UnpooledHeapByteBuf; +import java.nio.charset.StandardCharsets; +import org.apache.shardingsphere.db.protocol.postgresql.packet.command.query.binary.bind.PostgreSQLTypeUnspecifiedSQLParameter; +import org.apache.shardingsphere.db.protocol.postgresql.payload.PostgreSQLPacketPayload; +import org.junit.Test; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; + +public final class PostgreSQLUnspecifiedBinaryProtocolValueTest { + + @Test(expected = UnsupportedOperationException.class) + public void assertGetColumnLength() { + new PostgreSQLUnspecifiedBinaryProtocolValue().getColumnLength("val"); + } + + @Test + public void assertRead() { + String timestampStr = "2020-08-23 15:57:03+08"; + PooledByteBufAllocator byteBufAllocator = new PooledByteBufAllocator(); + ByteBuf byteBuf = new UnpooledHeapByteBuf(byteBufAllocator, 4 + timestampStr.length(), 64); + byteBuf.writeInt(timestampStr.length()); + byteBuf.writeCharSequence(timestampStr, StandardCharsets.ISO_8859_1); + byteBuf.readInt(); + PostgreSQLPacketPayload payload = new PostgreSQLPacketPayload(byteBuf); + Object result = new PostgreSQLUnspecifiedBinaryProtocolValue().read(payload); + byteBuf.release(); + assertNotNull(result); + assertTrue(result instanceof PostgreSQLTypeUnspecifiedSQLParameter); + assertThat(result.toString(), is(timestampStr)); + } + + @Test(expected = UnsupportedOperationException.class) + public void assertWrite() { + new PostgreSQLUnspecifiedBinaryProtocolValue().write(mock(PostgreSQLPacketPayload.class), "val"); + } + +} diff --git a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/communication/jdbc/connection/BackendConnection.java b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/communication/jdbc/connection/BackendConnection.java index e559619c0ae93296e373651b808ca08e0ecc9aff..bc08737f46fe7e42518e831aa75101ff41b7a201 100644 --- a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/communication/jdbc/connection/BackendConnection.java +++ b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/communication/jdbc/connection/BackendConnection.java @@ -20,10 +20,12 @@ package org.apache.shardingsphere.proxy.backend.communication.jdbc.connection; import com.google.common.base.Preconditions; import com.google.common.collect.LinkedHashMultimap; import com.google.common.collect.Multimap; +import java.sql.Types; import lombok.Getter; import lombok.Setter; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; +import org.apache.shardingsphere.db.protocol.parameter.TypeUnspecifiedSQLParameter; import org.apache.shardingsphere.infra.database.type.DatabaseType; import org.apache.shardingsphere.infra.database.type.dialect.MySQLDatabaseType; import org.apache.shardingsphere.infra.database.type.dialect.PostgreSQLDatabaseType; @@ -204,7 +206,12 @@ public final class BackendConnection implements JDBCExecutionConnection, AutoClo PreparedStatement result = option.isReturnGeneratedKeys() ? connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS) : connection.prepareStatement(sql); for (int i = 0; i < parameters.size(); i++) { - result.setObject(i + 1, parameters.get(i)); + Object parameter = parameters.get(i); + if (parameter instanceof TypeUnspecifiedSQLParameter) { + result.setObject(i + 1, parameter, Types.OTHER); + } else { + result.setObject(i + 1, parameter); + } } if (ConnectionMode.MEMORY_STRICTLY == connectionMode) { setFetchSize(result); diff --git a/shardingsphere-proxy/shardingsphere-proxy-frontend/shardingsphere-proxy-frontend-postgresql/src/main/java/org/apache/shardingsphere/proxy/frontend/postgresql/PostgreSQLErrPacketFactory.java b/shardingsphere-proxy/shardingsphere-proxy-frontend/shardingsphere-proxy-frontend-postgresql/src/main/java/org/apache/shardingsphere/proxy/frontend/postgresql/PostgreSQLErrPacketFactory.java index ae24df84eae9421acbeb1d34c9d1aee3a0ca875a..55993637f9b9623940efd1cb71e3e2b215b4e835 100644 --- a/shardingsphere-proxy/shardingsphere-proxy-frontend/shardingsphere-proxy-frontend-postgresql/src/main/java/org/apache/shardingsphere/proxy/frontend/postgresql/PostgreSQLErrPacketFactory.java +++ b/shardingsphere-proxy/shardingsphere-proxy-frontend/shardingsphere-proxy-frontend-postgresql/src/main/java/org/apache/shardingsphere/proxy/frontend/postgresql/PostgreSQLErrPacketFactory.java @@ -39,10 +39,16 @@ public final class PostgreSQLErrPacketFactory { if (cause instanceof PSQLException) { ServerErrorMessage serverErrorMessage = ((PSQLException) cause).getServerErrorMessage(); PostgreSQLErrorResponsePacket errorResponsePacket = new PostgreSQLErrorResponsePacket(); - errorResponsePacket.addField(PostgreSQLErrorResponsePacket.FIELD_TYPE_SEVERITY, serverErrorMessage.getSeverity()); - errorResponsePacket.addField(PostgreSQLErrorResponsePacket.FIELD_TYPE_CODE, serverErrorMessage.getSQLState()); - errorResponsePacket.addField(PostgreSQLErrorResponsePacket.FIELD_TYPE_MESSAGE, serverErrorMessage.getMessage()); - errorResponsePacket.addField(PostgreSQLErrorResponsePacket.FIELD_TYPE_POSITION, Integer.toString(serverErrorMessage.getPosition())); + if (null != serverErrorMessage) { + errorResponsePacket.addField(PostgreSQLErrorResponsePacket.FIELD_TYPE_SEVERITY, serverErrorMessage.getSeverity()); + errorResponsePacket.addField(PostgreSQLErrorResponsePacket.FIELD_TYPE_CODE, serverErrorMessage.getSQLState()); + errorResponsePacket.addField(PostgreSQLErrorResponsePacket.FIELD_TYPE_MESSAGE, serverErrorMessage.getMessage()); + errorResponsePacket.addField(PostgreSQLErrorResponsePacket.FIELD_TYPE_POSITION, Integer.toString(serverErrorMessage.getPosition())); + } else { + PSQLException ex = (PSQLException) cause; + errorResponsePacket.addField(PostgreSQLErrorResponsePacket.FIELD_TYPE_CODE, ex.getSQLState()); + errorResponsePacket.addField(PostgreSQLErrorResponsePacket.FIELD_TYPE_MESSAGE, ex.getMessage()); + } return errorResponsePacket; } PostgreSQLErrorResponsePacket errorResponsePacket = new PostgreSQLErrorResponsePacket();