From 3df9533af39d984af204b53a3558dbd5f5690845 Mon Sep 17 00:00:00 2001
From: Kaitmazian Maksim <m.kaitmazian@picodata.io>
Date: Thu, 11 Jul 2024 14:29:50 +0300
Subject: [PATCH] feat(pgproto): support sending any values

---
 src/pgproto/backend/describe.rs |  3 +--
 src/pgproto/value.rs            |  1 +
 test/pgproto/types_test.py      | 32 ++++++++++++++++++++++++++++++++
 3 files changed, 34 insertions(+), 2 deletions(-)

diff --git a/src/pgproto/backend/describe.rs b/src/pgproto/backend/describe.rs
index 75b7feb354..7724a93ede 100644
--- a/src/pgproto/backend/describe.rs
+++ b/src/pgproto/backend/describe.rs
@@ -219,14 +219,13 @@ impl MetadataColumn {
 fn pg_type_from_sbroad(sbroad: &SbroadType) -> PgResult<Type> {
     match sbroad {
         SbroadType::Integer | SbroadType::Unsigned => Ok(Type::INT8),
-        SbroadType::Map | SbroadType::Array => Ok(Type::JSON),
+        SbroadType::Map | SbroadType::Array | SbroadType::Any => Ok(Type::JSON),
         SbroadType::String => Ok(Type::TEXT),
         SbroadType::Boolean => Ok(Type::BOOL),
         SbroadType::Double => Ok(Type::FLOAT8),
         SbroadType::Decimal => Ok(Type::NUMERIC),
         SbroadType::Uuid => Ok(Type::UUID),
         SbroadType::Datetime => Ok(Type::TIMESTAMPTZ),
-        SbroadType::Any => Ok(Type::ANY),
         // According to tarantool [documentation](https://www.tarantool.io/en/doc/latest/reference/reference_sql/sql_user_guide/#sql-data-type-conversion):
         // NUMBER values have the same range as DOUBLE values. But NUMBER values may also be integers.
         //
diff --git a/src/pgproto/value.rs b/src/pgproto/value.rs
index 999bc28ace..bd8cb3d0f0 100644
--- a/src/pgproto/value.rs
+++ b/src/pgproto/value.rs
@@ -389,6 +389,7 @@ impl PgValue {
                 let datetime = deserialize_rmpv_ext(&value)?;
                 Ok(PgValue::Timestamptz(datetime))
             }
+            (_any, Type::JSON | Type::JSONB) => Ok(PgValue::Json(Json(value))),
 
             (value, ty) => Err(PgError::FeatureNotSupported(format!(
                 "{value:?} cannot be represented as a value of type {ty:?}"
diff --git a/test/pgproto/types_test.py b/test/pgproto/types_test.py
index e8582677cc..c9bde12bf7 100644
--- a/test/pgproto/types_test.py
+++ b/test/pgproto/types_test.py
@@ -468,3 +468,35 @@ def test_datetime(postgres: Postgres):
     # test binary encoding
     cur = conn.execute(""" SELECT * FROM T; """, binary=True)
     assert sorted(cur.fetchall()) == [(d1,), (d2,)]
+
+
+# Verify that we can read from all system tables without errors.
+def test_select_from_system_tables(postgres: Postgres):
+    user = "postgres"
+    password = "Passw0rd"
+    host = postgres.host
+    port = postgres.port
+
+    # create a postgres user using a postgres compatible password
+    postgres.instance.sql(
+        f"CREATE USER \"{user}\" WITH PASSWORD '{password}' USING md5"
+    )
+    # grant read on tables
+    postgres.instance.sql(f'GRANT READ TABLE TO "{user}"', sudo=True)
+
+    # connect to the server and enable autocommit as we
+    # don't support interactive transactions
+    conn = psycopg.connect(
+        f"postgres://{user}:{password}@{host}:{port}?sslmode=disable"
+    )
+    conn.autocommit = True
+
+    # at the beginning there should be only '_pico' tables
+    cursor = conn.execute(""" SELECT "name" from "_pico_table" """)
+    tables = [row[0] for row in cursor.fetchall()]
+
+    # read from all tables
+    for table in tables:
+        sql = f""" SELECT * from "{table}" """
+        cur = conn.execute(bytes(sql, "utf-8"))
+        cur.fetchall()
-- 
GitLab