You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by zh...@apache.org on 2020/08/25 09:57:43 UTC

[shardingsphere] branch master updated: Fix #6579 : Support PostgreSQL unspecified parameter data type (#6998)

This is an automated email from the ASF dual-hosted git repository.

zhangyonglun pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shardingsphere.git


The following commit(s) were added to refs/heads/master by this push:
     new 3656853  Fix #6579 : Support PostgreSQL unspecified parameter data type (#6998)
3656853 is described below

commit 3656853a91a45b08565eae675462b880b9cefb4d
Author: sandynz <42...@users.noreply.github.com>
AuthorDate: Tue Aug 25 17:57:24 2020 +0800

    Fix #6579 : Support PostgreSQL unspecified parameter data type (#6998)
    
    * Support unspecified parameter data type (#6579)
    
    * Support unspecified parameter data type (#6579)
    
    * Support PostgreSQL unspecified parameter data type
    
    * Support unspecified parameter data type, follow review suggestion
---
 .../parameter/TypeUnspecifiedSQLParameter.java     | 24 +++++++++
 .../query/binary/bind/PostgreSQLComBindPacket.java |  6 ++-
 .../PostgreSQLTypeUnspecifiedSQLParameter.java     | 37 +++++++++++++
 .../PostgreSQLBinaryProtocolValueFactory.java      |  6 +++
 .../PostgreSQLUnspecifiedBinaryProtocolValue.java  | 46 ++++++++++++++++
 .../PostgreSQLTypeUnspecifiedSQLParameterTest.java | 34 ++++++++++++
 ...stgreSQLUnspecifiedBinaryProtocolValueTest.java | 62 ++++++++++++++++++++++
 .../jdbc/connection/BackendConnection.java         |  9 +++-
 .../postgresql/PostgreSQLErrPacketFactory.java     | 14 +++--
 9 files changed, 232 insertions(+), 6 deletions(-)

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 0000000..a7766bd
--- /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 3045fe9..1f3133d 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<Object> 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 0000000..3749055
--- /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 9773dee..625e3fc7 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<PostgreSQLColumnType, PostgreSQLBinaryProtocolValue> 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 0000000..5acb86f
--- /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 0000000..236db1e
--- /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 0000000..8ebf7dc
--- /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 e559619..bc08737 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 ae24df8..5599363 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();