Repository: GoogleCloudPlatform/pgadapter
Pull request #530 (2022-12-04 17:49:10)

test: enable jsonb tests
Enables JSONB tests and cleans up some of the JDBC metadata query replacements. JSONB is a type that the JDBC driver does not have 'pre-programmed' support for. That is; it will query the `pg_type` table to verify that the type is supported in the database that it is connected to. This means that many of the mock server tests need additional query results to work with JSONB.

codecov[bot]: # [Codecov](https://codecov.io/gh/GoogleCloudPlatform/pgadapter/pull/530?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=GoogleCloudPlatform) Report
> Merging [#530](https://codecov.io/gh/GoogleCloudPlatform/pgadapter/pull/530?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=GoogleCloudPlatform) (720fca2) into [postgresql-dialect](https://codecov.io/gh/GoogleCloudPlatform/pgadapter/commit/1e7ae72a2d16a16dfb94009d89af56ddb5db3ced?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=GoogleCloudPlatform) (1e7ae72) will **increase** coverage by `0.10%`.
> The diff coverage is `100.00%`.

```diff
@@                   Coverage Diff                    @@
##             postgresql-dialect     #530      +/-   ##
========================================================
+ Coverage                 88.02%   88.12%   +0.10%     
+ Complexity                 2053     2047       -6     
========================================================
  Files                       122      122              
  Lines                      6779     6762      -17     
  Branches                    955      943      -12     
========================================================
- Hits                       5967     5959       -8     
+ Misses                      578      574       -4     
+ Partials                    234      229       -5     
```

| Flag | Coverage Δ | |
|---|---|---|
| all_tests | `88.12% <100.00%> (+0.10%)` | :arrow_up: |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=GoogleCloudPlatform#carryforward-flags-in-the-pull-request-comment) to find out more.

| [Impacted Files](https://codecov.io/gh/GoogleCloudPlatform/pgadapter/pull/530?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=GoogleCloudPlatform) | Coverage Δ | |
|---|---|---|
| [...e/cloud/spanner/pgadapter/utils/PgJdbcCatalog.java](https://codecov.io/gh/GoogleCloudPlatform/pgadapter/pull/530/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=GoogleCloudPlatform#diff-c3JjL21haW4vamF2YS9jb20vZ29vZ2xlL2Nsb3VkL3NwYW5uZXIvcGdhZGFwdGVyL3V0aWxzL1BnSmRiY0NhdGFsb2cuamF2YQ==) | `0.00% <ø> (ø)` | |
| [...e/cloud/spanner/pgadapter/parsers/JsonbParser.java](https://codecov.io/gh/GoogleCloudPlatform/pgadapter/pull/530/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=GoogleCloudPlatform#diff-c3JjL21haW4vamF2YS9jb20vZ29vZ2xlL2Nsb3VkL3NwYW5uZXIvcGdhZGFwdGVyL3BhcnNlcnMvSnNvbmJQYXJzZXIuamF2YQ==) | `91.89% <100.00%> (ø)` | |
| [...panner/pgadapter/statements/BackendConnection.java](https://codecov.io/gh/GoogleCloudPlatform/pgadapter/pull/530/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=GoogleCloudPlatform#diff-c3JjL21haW4vamF2YS9jb20vZ29vZ2xlL2Nsb3VkL3NwYW5uZXIvcGdhZGFwdGVyL3N0YXRlbWVudHMvQmFja2VuZENvbm5lY3Rpb24uamF2YQ==) | `92.67% <100.00%> (+0.01%)` | :arrow_up: |
| [...dapter/statements/JdbcMetadataStatementHelper.java](https://codecov.io/gh/GoogleCloudPlatform/pgadapter/pull/530/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=GoogleCloudPlatform#diff-c3JjL21haW4vamF2YS9jb20vZ29vZ2xlL2Nsb3VkL3NwYW5uZXIvcGdhZGFwdGVyL3N0YXRlbWVudHMvSmRiY01ldGFkYXRhU3RhdGVtZW50SGVscGVyLmphdmE=) | `83.85% <100.00%> (+2.33%)` | :arrow_up: |
| [.../cloud/spanner/pgadapter/statements/PgCatalog.java](https://codecov.io/gh/GoogleCloudPlatform/pgadapter/pull/530/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=GoogleCloudPlatform#diff-c3JjL21haW4vamF2YS9jb20vZ29vZ2xlL2Nsb3VkL3NwYW5uZXIvcGdhZGFwdGVyL3N0YXRlbWVudHMvUGdDYXRhbG9nLmphdmE=) | `93.93% <100.00%> (+0.09%)` | :arrow_up: |
| [...loud/spanner/pgadapter/utils/BinaryCopyParser.java](https://codecov.io/gh/GoogleCloudPlatform/pgadapter/pull/530/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=GoogleCloudPlatform#diff-c3JjL21haW4vamF2YS9jb20vZ29vZ2xlL2Nsb3VkL3NwYW5uZXIvcGdhZGFwdGVyL3V0aWxzL0JpbmFyeUNvcHlQYXJzZXIuamF2YQ==) | `93.39% <100.00%> (ø)` | |
| [...oud/spanner/pgadapter/statements/SimpleParser.java](https://codecov.io/gh/GoogleCloudPlatform/pgadapter/pull/530/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=GoogleCloudPlatform#diff-c3JjL21haW4vamF2YS9jb20vZ29vZ2xlL2Nsb3VkL3NwYW5uZXIvcGdhZGFwdGVyL3N0YXRlbWVudHMvU2ltcGxlUGFyc2VyLmphdmE=) | `92.20% <0.00%> (+0.22%)` | :arrow_up: |

:mega: We’re building smart automated test selection to slash your CI/CD build times. [Learn more](https://about.codecov.io/iterative-testing/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=GoogleCloudPlatform)


Patch:
diff --git a/src/main/java/com/google/cloud/spanner/pgadapter/parsers/JsonbParser.java b/src/main/java/com/google/cloud/spanner/pgadapter/parsers/JsonbParser.java
index 5aa65219..8feb19d5 100644
--- a/src/main/java/com/google/cloud/spanner/pgadapter/parsers/JsonbParser.java
+++ b/src/main/java/com/google/cloud/spanner/pgadapter/parsers/JsonbParser.java
@@ -17,6 +17,7 @@ package com.google.cloud.spanner.pgadapter.parsers;
 import com.google.api.core.InternalApi;
 import com.google.cloud.spanner.ResultSet;
 import com.google.cloud.spanner.Statement;
+import com.google.cloud.spanner.Value;
 import com.google.cloud.spanner.pgadapter.ProxyServer.DataFormat;
 import com.google.cloud.spanner.pgadapter.error.PGException;
 import com.google.cloud.spanner.pgadapter.error.SQLState;
@@ -41,21 +42,10 @@ public class JsonbParser extends Parser<String> {
     if (item != null) {
       switch (formatCode) {
         case TEXT:
-          this.item = toString(item);
+          this.item = new String(item, UTF8);
           break;
         case BINARY:
-          if (item.length > 0) {
-            if (item[0] == 1) {
-              this.item = toString(Arrays.copyOfRange(item, 1, item.length));
-            } else {
-              throw PGException.newBuilder("Unknown version in binary jsonb value: " + item[0])
-                  .setSQLState(SQLState.RaiseException)
-                  .setSeverity(Severity.ERROR)
-                  .build();
-            }
-          } else {
-            this.item = "";
-          }
+          this.item = toString(item);
           break;
         default:
       }
@@ -64,7 +54,18 @@ public class JsonbParser extends Parser<String> {
 
   /** Converts the binary data to an UTF8 string. */
   public static String toString(@Nonnull byte[] data) {
-    return new String(data, UTF8);
+    if (data.length > 0) {
+      if (data[0] == 1) {
+        return new String(Arrays.copyOfRange(data, 1, data.length), StandardCharsets.UTF_8);
+      } else {
+        throw PGException.newBuilder("Unknown version in binary jsonb value: " + data[0])
+            .setSQLState(SQLState.RaiseException)
+            .setSeverity(Severity.ERROR)
+            .build();
+      }
+    } else {
+      return "";
+    }
   }
 
   @Override
@@ -104,6 +105,6 @@ public class JsonbParser extends Parser<String> {
 
   @Override
   public void bind(Statement.Builder statementBuilder, String name) {
-    statementBuilder.bind(name).to(this.item);
+    statementBuilder.bind(name).to(Value.pgJsonb(this.item));
   }
 }
diff --git a/src/main/java/com/google/cloud/spanner/pgadapter/statements/BackendConnection.java b/src/main/java/com/google/cloud/spanner/pgadapter/statements/BackendConnection.java
index b94a7775..9ecfa858 100644
--- a/src/main/java/com/google/cloud/spanner/pgadapter/statements/BackendConnection.java
+++ b/src/main/java/com/google/cloud/spanner/pgadapter/statements/BackendConnection.java
@@ -248,7 +248,8 @@ public class BackendConnection {
               sessionState.isReplacePgCatalogTables()
                   ? pgCatalog.replacePgCatalogTables(statement)
                   : statement;
-          result.set(bindAndExecute(updatedStatement));
+          updatedStatement = bindStatement(updatedStatement);
+          result.set(analyzeOrExecute(updatedStatement));
         }
       } catch (SpannerException spannerException) {
         // Executing queries against the information schema in a transaction is unsupported.
@@ -277,8 +278,11 @@ public class BackendConnection {
       }
     }
 
-    StatementResult bindAndExecute(Statement statement) {
-      statement = statementBinder.apply(statement);
+    Statement bindStatement(Statement statement) {
+      return statementBinder.apply(statement);
+    }
+
+    StatementResult analyzeOrExecute(Statement statement) {
       if (analyze) {
         ResultSet resultSet;
         if (parsedStatement.isUpdate() && !parsedStatement.hasReturningClause()) {
@@ -922,7 +926,7 @@ public class BackendConnection {
                     bufferedStatements.get(index).statement));
           } else {
             Execute execute = (Execute) bufferedStatements.get(index);
-            execute.bindAndExecute(execute.statement);
+            execute.analyzeOrExecute(execute.bindStatement(execute.statement));
           }
           index++;
         } else {
diff --git a/src/main/java/com/google/cloud/spanner/pgadapter/statements/JdbcMetadataStatementHelper.java b/src/main/java/com/google/cloud/spanner/pgadapter/statements/JdbcMetadataStatementHelper.java
index 0a3fbb52..1fe63138 100644
--- a/src/main/java/com/google/cloud/spanner/pgadapter/statements/JdbcMetadataStatementHelper.java
+++ b/src/main/java/com/google/cloud/spanner/pgadapter/statements/JdbcMetadataStatementHelper.java
@@ -82,24 +82,6 @@ class JdbcMetadataStatementHelper {
         || sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_PRIMARY_KEY_PREFIX_2)) {
       return replaceGetPrimaryKeyQuery(sql);
     }
-    if (sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_TYPE_INFO_PREFIX_FULL)) {
-      return PgJdbcCatalog.PG_JDBC_GET_TYPE_INFO_REPLACEMENT_FULL;
-    }
-    if (sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_TYPE_INFO_WITH_TYPTYPE_PREFIX)) {
-      return PgJdbcCatalog.PG_JDBC_GET_TYPE_INFO_WITH_TYPTYPE_REPLACEMENT;
-    }
-    if (sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_TYPE_INFO_WITH_PARAMETER_PREFIX)) {
-      return PgJdbcCatalog.PG_JDBC_GET_TYPE_INFO_WITH_PARAMETER_REPLACEMENT;
-    }
-    if (sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_TYPE_INFO_WITHOUT_OID_PREFIX)) {
-      return PgJdbcCatalog.PG_JDBC_GET_TYPE_INFO_WITHOUT_OID_REPLACEMENT;
-    }
-    if (sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_TYPE_INFO_WITHOUT_OID_PARAM_PREFIX)) {
-      return PgJdbcCatalog.PG_JDBC_GET_TYPE_INFO_WITHOUT_OID_PARAM_REPLACEMENT;
-    }
-    if (sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_TYPE_INFO_NOT_TOAST_PREFIX)) {
-      return PgJdbcCatalog.PG_JDBC_GET_TYPE_INFO_NOT_TOAST_REPLACEMENT;
-    }
     if (sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_TABLE_PRIVILEGES_PREFIX_1)
         || sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_TABLE_PRIVILEGES_PREFIX_2)) {
       return PgJdbcCatalog.PG_JDBC_GET_TABLE_PRIVILEGES_REPLACEMENT;
@@ -131,21 +113,6 @@ class JdbcMetadataStatementHelper {
     if (sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_SQL_KEYWORDS_PREFIX)) {
       return PgJdbcCatalog.PG_JDBC_GET_SQL_KEYWORDS_REPLACEMENT;
     }
-    if (sql.equals(PgJdbcCatalog.PG_JDBC_GET_TYPE_NAME)) {
-      return PgJdbcCatalog.PG_JDBC_GET_TYPE_NAME_REPLACEMENT;
-    }
-    if (sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_TYPE_INFO_PREFIX)) {
-      return PgJdbcCatalog.PG_JDBC_GET_TYPE_INFO_REPLACEMENT;
-    }
-    if (sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_TYPE_INFO_PREFIX_42_3)) {
-      return PgJdbcCatalog.PG_JDBC_GET_TYPE_INFO_REPLACEMENT_42_3;
-    }
-    if (sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_TYPE_INFO_PREFIX_42_2_22)) {
-      return PgJdbcCatalog.PG_JDBC_GET_TYPE_INFO_REPLACEMENT_42_3;
-    }
-    if (sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_TYPE_INFO_SIMPLE_PREFIX_42_3)) {
-      return PgJdbcCatalog.PG_JDBC_GET_TYPE_INFO_REPLACEMENT_42_3;
-    }
     if (sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_SEQUENCES)) {
       return PgJdbcCatalog.PG_JDBC_GET_SEQUENCES_REPLACEMENT;
     }
@@ -164,6 +131,11 @@ class JdbcMetadataStatementHelper {
         .replace(
             PgJdbcCatalog.PG_JDBC_BEST_ROW_IDENTIFIER_PREFIX,
             PgJdbcCatalog.PG_JDBC_PK_QUERY_REPLACEMENT)
+        .replaceAll(
+            PgJdbcCatalog.PG_JDBC_GENERATE_SCHEMAS_ARRAY,
+            PgJdbcCatalog.PG_JDBC_GENERATE_SCHEMAS_ARRAY_REPLACEMENT)
+        .replaceAll("typinput='array_in'::regproc", "substring(typname, 1, 1)='_'")
+        .replaceAll("typinput='pg_catalog\\.array_in'::regproc", "substring(typname, 1, 1)='_'")
 
         // Replace unsupported pg_catalog tables with fixed (empty) sub-selects.
         .replace(
diff --git a/src/main/java/com/google/cloud/spanner/pgadapter/statements/PgCatalog.java b/src/main/java/com/google/cloud/spanner/pgadapter/statements/PgCatalog.java
index 7aa28a3d..182c6097 100644
--- a/src/main/java/com/google/cloud/spanner/pgadapter/statements/PgCatalog.java
+++ b/src/main/java/com/google/cloud/spanner/pgadapter/statements/PgCatalog.java
@@ -46,7 +46,8 @@ public class PgCatalog {
   private static final ImmutableMap<Pattern, String> FUNCTION_REPLACEMENTS =
       ImmutableMap.of(
           Pattern.compile("pg_catalog.pg_table_is_visible\\(.+\\)"), "true",
-          Pattern.compile("pg_table_is_visible\\(.+\\)"), "true");
+          Pattern.compile("pg_table_is_visible\\(.+\\)"), "true",
+          Pattern.compile("ANY\\(current_schemas\\(true\\)\\)"), "'public'");
 
   private final Map<TableOrIndexName, PgCatalogTable> pgCatalogTables =
       ImmutableMap.of(
diff --git a/src/main/java/com/google/cloud/spanner/pgadapter/utils/BinaryCopyParser.java b/src/main/java/com/google/cloud/spanner/pgadapter/utils/BinaryCopyParser.java
index ed057d79..d39e1bd7 100644
--- a/src/main/java/com/google/cloud/spanner/pgadapter/utils/BinaryCopyParser.java
+++ b/src/main/java/com/google/cloud/spanner/pgadapter/utils/BinaryCopyParser.java
@@ -24,6 +24,7 @@ import com.google.cloud.spanner.pgadapter.parsers.BinaryParser;
 import com.google.cloud.spanner.pgadapter.parsers.BooleanParser;
 import com.google.cloud.spanner.pgadapter.parsers.DateParser;
 import com.google.cloud.spanner.pgadapter.parsers.DoubleParser;
+import com.google.cloud.spanner.pgadapter.parsers.JsonbParser;
 import com.google.cloud.spanner.pgadapter.parsers.LongParser;
 import com.google.cloud.spanner.pgadapter.parsers.NumericParser;
 import com.google.cloud.spanner.pgadapter.parsers.StringParser;
@@ -259,7 +260,7 @@ class BinaryCopyParser implements CopyInParser {
         case STRING:
           return Value.string(field.data == null ? null : StringParser.toString(field.data));
         case PG_JSONB:
-          return Value.pgJsonb(field.data == null ? null : StringParser.toString(field.data));
+          return Value.pgJsonb(field.data == null ? null : JsonbParser.toString(field.data));
         case BYTES:
           return Value.bytes(field.data == null ? null : BinaryParser.toByteArray(field.data));
         case TIMESTAMP:
diff --git a/src/main/java/com/google/cloud/spanner/pgadapter/utils/PgJdbcCatalog.java b/src/main/java/com/google/cloud/spanner/pgadapter/utils/PgJdbcCatalog.java
index ce48b2d0..b5ce0542 100644
--- a/src/main/java/com/google/cloud/spanner/pgadapter/utils/PgJdbcCatalog.java
+++ b/src/main/java/com/google/cloud/spanner/pgadapter/utils/PgJdbcCatalog.java
@@ -39,61 +39,10 @@ public class PgJdbcCatalog {
           + "statistics,stdin,stdout,storage,strict,sysid,tablespace,temp,template,truncate,trusted,"
           + "unencrypted,unlisten,until,vacuum,valid,validator,verbose,volatile'";
 
-  public static final String PG_JDBC_GET_TYPE_NAME =
-      "SELECT n.nspname = ANY(current_schemas(true)), n.nspname, t.typname "
-          + "FROM pg_catalog.pg_type t "
-          + "JOIN pg_catalog.pg_namespace n ON t.typnamespace = n.oid WHERE t.oid = $1";
-  public static final String PG_JDBC_GET_TYPE_NAME_REPLACEMENT =
-      "SELECT true, n.nspname, t.typname "
-          + "FROM pg_catalog.pg_type t "
-          + "JOIN pg_catalog.pg_namespace n ON t.typnamespace = n.oid WHERE t.oid = $1";
-  public static final String PG_JDBC_GET_TYPE_INFO_PREFIX_42_2_22 =
-      "SELECT typinput='array_in'::regproc as is_array, typtype, typname "
-          + "  FROM pg_catalog.pg_type "
-          + "  LEFT JOIN (select ns.oid as nspoid, ns.nspname, r.r "
-          + "          from pg_namespace as ns "
-          + "          join ( select s.r, (current_schemas(false))[s.r] as nspname "
-          + "                   from generate_series(1, array_upper(current_schemas(false), 1)) as s(r) ) as r "
-          + "         using ( nspname ) "
-          + "       ) as sp "
-          + "    ON sp.nspoid = typnamespace ";
-  public static final String PG_JDBC_GET_TYPE_INFO_PREFIX_42_3 =
-      "SELECT typinput='array_in'::regproc as is_array, typtype, typname, pg_type.oid "
-          + "  FROM pg_catalog.pg_type "
-          + "  LEFT JOIN (select ns.oid as nspoid, ns.nspname, r.r "
-          + "          from pg_namespace as ns "
-          + "          join ( select s.r, (current_schemas(false))[s.r] as nspname "
-          + "                   from generate_series(1, array_upper(current_schemas(false), 1)) as s(r) ) as r "
-          + "         using ( nspname ) "
-          + "       ) as sp "
-          + "    ON sp.nspoid = typnamespace ";
-  public static final String PG_JDBC_GET_TYPE_INFO_SIMPLE_PREFIX_42_3 =
-      "SELECT pg_type.oid, typname "
-          + "  FROM pg_catalog.pg_type "
-          + "  LEFT "
-          + "  JOIN (select ns.oid as nspoid, ns.nspname, r.r "
-          + "          from pg_namespace as ns "
-          + "          join ( select s.r, (current_schemas(false))[s.r] as nspname "
-          + "                   from generate_series(1, array_upper(current_schemas(false), 1)) as s(r) ) as r "
-          + "         using ( nspname ) "
-          + "       ) as sp "
-          + "    ON sp.nspoid = typnamespace ";
-  public static final String PG_JDBC_GET_TYPE_INFO_REPLACEMENT_42_3 =
-      "SELECT * FROM (SELECT ''::varchar as typinput, 0::bigint as typtype, ''::varchar as typname, 0::bigint as oid) pg_type WHERE false";
-
-  public static final String PG_JDBC_GET_TYPE_INFO_PREFIX =
-      "SELECT typinput='array_in'::regproc, typtype "
-          + "  FROM pg_catalog.pg_type "
-          + "  LEFT "
-          + "  JOIN (select ns.oid as nspoid, ns.nspname, r.r "
-          + "          from pg_namespace as ns "
-          + "          join ( select s.r, (current_schemas(false))[s.r] as nspname "
-          + "                   from generate_series(1, array_upper(current_schemas(false), 1)) as s(r) ) as r "
-          + "         using ( nspname ) "
-          + "       ) as sp "
-          + "    ON sp.nspoid = typnamespace ";
-  public static final String PG_JDBC_GET_TYPE_INFO_REPLACEMENT =
-      "SELECT * FROM (SELECT ''::varchar as typinput, 0::bigint as typtype) pg_type WHERE false";
+  public static final String PG_JDBC_GENERATE_SCHEMAS_ARRAY =
+      "select s.r, \\(current_schemas\\(false\\)\\)\\[s.r\\] as nspname\\s+from generate_series\\(1, array_upper\\(current_schemas\\(false\\), 1\\)\\) as s\\(r\\)";
+  public static final String PG_JDBC_GENERATE_SCHEMAS_ARRAY_REPLACEMENT =
+      "select 1 as r, 'public' as nspname";
 
   private static final String PG_JDBC_FUNC_TYPE_UNKNOWN_SQL =
       DatabaseMetaData.functionResultUnknown + " ";
@@ -451,133 +400,6 @@ public class PgJdbcCatalog {
           + "                AND IDX.TABLE_NAME=COLS.TABLE_NAME\n"
           + "                AND IDX.INDEX_NAME=COLS.INDEX_NAME\n";
 
-  public static final String PG_JDBC_GET_TYPE_INFO_PREFIX_FULL =
-      "SELECT t.typname,t.oid FROM pg_catalog.pg_type t JOIN pg_catalog.pg_namespace n ON (t.typnamespace = n.oid)  WHERE n.nspname  != 'pg_toast' AND  (t.typrelid = 0 OR (SELECT c.relkind = 'c' FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid))";
-  public static final String PG_JDBC_GET_TYPE_INFO_REPLACEMENT_FULL =
-      " select 'bool' as typname, 16 as oid union all \n"
-          + " select 'bytea' as typname, 17 as oid union all \n"
-          + " select 'int8' as typname, 20 as oid union all \n"
-          + " select 'float8' as typname, 701 as oid union all \n"
-          + " select 'varchar' as typname, 1043 as oid union all \n"
-          + " select 'date' as typname, 1082 as oid union all \n"
-          + " select 'timestamptz' as typname, 1184 as oid union all \n"
-          + " select 'numeric' as typname, 1700 as oid union all \n"
-          + " select 'jsonb' as typname, 3802 as oid union all \n"
-          + " select '_bool' as typname, 1000 as oid union all \n"
-          + " select '_bytea' as typname, 1001 as oid union all \n"
-          + " select '_int8' as typname, 1016 as oid union all \n"
-          + " select '_float8' as typname, 1022 as oid union all \n"
-          + " select '_varchar' as typname, 1015 as oid union all \n"
-          + " select '_date' as typname, 1182 as oid union all \n"
-          + " select '_timestamptz' as typname, 1185 as oid union all \n"
-          + " select '_numeric' as typname, 1231 as oid union all \n"
-          + " select '_jsonb' as typname, 3807 as oid";
-  public static final String PG_JDBC_GET_TYPE_INFO_WITH_TYPTYPE_PREFIX =
-      "SELECT typinput='array_in'::regproc as is_array, typtype, typname, pg_type.oid   FROM pg_catalog.pg_type   LEFT JOIN (select ns.oid as nspoid, ns.nspname, r.r           from pg_namespace as ns           join ( select s.r, (current_schemas(false))[s.r] as nspname                    from generate_series(1, array_upper(current_schemas(false), 1)) as s(r) ) as r          using ( nspname )        ) as sp     ON sp.nspoid = typnamespace  ORDER BY sp.r, pg_type.oid DESC";
-  public static final String PG_JDBC_GET_TYPE_INFO_WITH_TYPTYPE_REPLACEMENT =
-      "select true as is_array, 'b' as typtype, '_jsonb' as typname, 3807 as oid union all\n"
-          + " select false as is_array, 'b' as typtype, 'jsonb' as typname, 3802 as oid union all\n"
-          + " select false as is_array, 'b' as typtype, 'numeric' as typname, 1700 as oid union all\n"
-          + " select true as is_array, 'b' as typtype, '_numeric' as typname, 1231 as oid union all\n"
-          + " select true as is_array, 'b' as typtype, '_timestamptz' as typname, 1185 as oid union all\n"
-          + " select false as is_array, 'b' as typtype, 'timestamptz' as typname, 1184 as oid union all\n"
-          + " select true as is_array, 'b' as typtype, '_date' as typname, 1182 as oid union all\n"
-          + " select false as is_array, 'b' as typtype, 'date' as typname, 1082 as oid union all\n"
-          + " select false as is_array, 'b' as typtype, 'varchar' as typname, 1043 as oid union all\n"
-          + " select true as is_array, 'b' as typtype, '_float8' as typname, 1022 as oid union all\n"
-          + " select true as is_array, 'b' as typtype, '_int8' as typname, 1016 as oid union all\n"
-          + " select true as is_array, 'b' as typtype, '_varchar' as typname, 1015 as oid union all\n"
-          + " select true as is_array, 'b' as typtype, '_bytea' as typname, 1001 as oid union all\n"
-          + " select true as is_array, 'b' as typtype, '_bool' as typname, 1000 as oid union all\n"
-          + " select false as is_array, 'b' as typtype, 'float8' as typname, 701 as oid union all\n"
-          + " select false as is_array, 'b' as typtype, 'int8' as typname, 20 as oid union all\n"
-          + " select false as is_array, 'b' as typtype, 'bytea' as typname, 17 as oid union all\n"
-          + " select false as is_array, 'b' as typtype, 'bool' as typname, 16 as oid";
-  public static final String PG_JDBC_GET_TYPE_INFO_WITH_PARAMETER_PREFIX =
-      "SELECT pg_type.oid, typname   FROM pg_catalog.pg_type   LEFT   JOIN (select ns.oid as nspoid, ns.nspname, r.r           from pg_namespace as ns           join ( select s.r, (current_schemas(false))[s.r] as nspname                    from generate_series(1, array_upper(current_schemas(false), 1)) as s(r) ) as r          using ( nspname )        ) as sp     ON sp.nspoid = typnamespace  WHERE typname = $1  ORDER BY sp.r, pg_type.oid DESC LIMIT 1";
-  public static final String PG_JDBC_GET_TYPE_INFO_WITH_PARAMETER_REPLACEMENT =
-      "select 16 as oid, 'bool' as typname from (select 1) t where 'bool'=$1 union all \n"
-          + " select 17 as oid, 'bytea' as typname from (select 1) t where 'bytea'=$1 union all \n"
-          + " select 20 as oid, 'int8' as typname from (select 1) t where 'int8'=$1 union all \n"
-          + " select 701 as oid, 'float8' as typname from (select 1) t where 'float8'=$1 union all \n"
-          + " select 1043 as oid, 'varchar' as typname from (select 1) t where 'varchar'=$1 union all \n"
-          + " select 1082 as oid, 'date' as typname from (select 1) t where 'date'=$1 union all \n"
-          + " select 1184 as oid, 'timestamptz' as typname from (select 1) t where 'timestamptz'=$1 union all \n"
-          + " select 1700 as oid, 'numeric' as typname from (select 1) t where 'numeric'=$1 union all \n"
-          + " select 3802 as oid, 'jsonb' as typname from (select 1) t where 'jsonb'=$1 union all \n"
-          + " select 1000 as oid, '_bool' as typname from (select 1) t where '_bool'=$1 union all \n"
-          + " select 1001 as oid, '_bytea' as typname from (select 1) t where '_bytea'=$1 union all \n"
-          + " select 1016 as oid, '_int8' as typname from (select 1) t where '_int8'=$1 union all \n"
-          + " select 1022 as oid, '_float8' as typname from (select 1) t where '_float8'=$1 union all \n"
-          + " select 1015 as oid, '_varchar' as typname from (select 1) t where '_varchar'=$1 union all \n"
-          + " select 1182 as oid, '_date' as typname from (select 1) t where '_date'=$1 union all \n"
-          + " select 1185 as oid, '_timestamptz' as typname from (select 1) t where '_timestamptz'=$1 union all \n"
-          + " select 1231 as oid, '_numeric' as typname from (select 1) t where '_numeric'=$1 union all \n"
-          + " select 3807 as oid, '_jsonb' as typname from (select 1) t where '_jsonb'=$1";
-  public static final String PG_JDBC_GET_TYPE_INFO_WITHOUT_OID_PREFIX =
-      "SELECT typinput='array_in'::regproc as is_array, typtype, typname   FROM pg_catalog.pg_type   LEFT JOIN (select ns.oid as nspoid, ns.nspname, r.r           from pg_namespace as ns           join ( select s.r, (current_schemas(false))[s.r] as nspname                    from generate_series(1, array_upper(current_schemas(false), 1)) as s(r) ) as r          using ( nspname )        ) as sp     ON sp.nspoid = typnamespace  ORDER BY sp.r, pg_type.oid DESC";
-  public static final String PG_JDBC_GET_TYPE_INFO_WITHOUT_OID_REPLACEMENT =
-      "select true as is_array, 'b' as typtype, '_jsonb' as typname union all\n"
-          + " select false as is_array, 'b' as typtype, 'jsonb' as typname union all\n"
-          + " select false as is_array, 'b' as typtype, 'numeric' as typname union all\n"
-          + " select true as is_array, 'b' as typtype, '_numeric' as typname union all\n"
-          + " select true as is_array, 'b' as typtype, '_timestamptz' as typname union all\n"
-          + " select false as is_array, 'b' as typtype, 'timestamptz' as typname union all\n"
-          + " select true as is_array, 'b' as typtype, '_date' as typname union all\n"
-          + " select false as is_array, 'b' as typtype, 'date' as typname union all\n"
-          + " select false as is_array, 'b' as typtype, 'varchar' as typname union all\n"
-          + " select true as is_array, 'b' as typtype, '_float8' as typname union all\n"
-          + " select true as is_array, 'b' as typtype, '_int8' as typname union all\n"
-          + " select true as is_array, 'b' as typtype, '_varchar' as typname union all\n"
-          + " select true as is_array, 'b' as typtype, '_bytea' as typname union all\n"
-          + " select true as is_array, 'b' as typtype, '_bool' as typname union all\n"
-          + " select false as is_array, 'b' as typtype, 'float8' as typname union all\n"
-          + " select false as is_array, 'b' as typtype, 'int8' as typname union all\n"
-          + " select false as is_array, 'b' as typtype, 'bytea' as typname union all\n"
-          + " select false as is_array, 'b' as typtype, 'bool' as typname";
-  public static final String PG_JDBC_GET_TYPE_INFO_WITHOUT_OID_PARAM_PREFIX =
-      "SELECT typinput='array_in'::regproc, typtype   FROM pg_catalog.pg_type   LEFT   JOIN (select ns.oid as nspoid, ns.nspname, r.r           from pg_namespace as ns           join ( select s.r, (current_schemas(false))[s.r] as nspname                    from generate_series(1, array_upper(current_schemas(false), 1)) as s(r) ) as r          using ( nspname )        ) as sp     ON sp.nspoid = typnamespace  WHERE typname = $1  ORDER BY sp.r, pg_type.oid DESC LIMIT 1";
-  public static final String PG_JDBC_GET_TYPE_INFO_WITHOUT_OID_PARAM_REPLACEMENT =
-      "select false as is_array, 'b' as typtype from (select 1) t where 'bool'=$1 union all \n"
-          + " select false as is_array, 'b' as typtype from (select 1) t where 'bytea'=$1 union all \n"
-          + " select false as is_array, 'b' as typtype from (select 1) t where 'int8'=$1 union all \n"
-          + " select false as is_array, 'b' as typtype from (select 1) t where 'float8'=$1 union all \n"
-          + " select false as is_array, 'b' as typtype from (select 1) t where 'varchar'=$1 union all \n"
-          + " select false as is_array, 'b' as typtype from (select 1) t where 'date'=$1 union all \n"
-          + " select false as is_array, 'b' as typtype from (select 1) t where 'timestamptz'=$1 union all \n"
-          + " select false as is_array, 'b' as typtype from (select 1) t where 'numeric'=$1 union all \n"
-          + " select false as is_array, 'b' as typtype from (select 1) t where 'jsonb'=$1 union all \n"
-          + " select true as is_array, 'b' as typtype from (select 1) t where '_bool'=$1 union all \n"
-          + " select true as is_array, 'b' as typtype from (select 1) t where '_bytea'=$1 union all \n"
-          + " select true as is_array, 'b' as typtype from (select 1) t where '_int8'=$1 union all \n"
-          + " select true as is_array, 'b' as typtype from (select 1) t where '_float8'=$1 union all \n"
-          + " select true as is_array, 'b' as typtype from (select 1) t where '_varchar'=$1 union all \n"
-          + " select true as is_array, 'b' as typtype from (select 1) t where '_date'=$1 union all \n"
-          + " select true as is_array, 'b' as typtype from (select 1) t where '_timestamptz'=$1 union all \n"
-          + " select true as is_array, 'b' as typtype from (select 1) t where '_numeric'=$1 union all \n"
-          + " select true as is_array, 'b' as typtype from (select 1) t where '_jsonb'=$1";
-  public static final String PG_JDBC_GET_TYPE_INFO_NOT_TOAST_PREFIX =
-      "SELECT t.typname,t.oid FROM pg_catalog.pg_type t JOIN pg_catalog.pg_namespace n ON (t.typnamespace = n.oid)  WHERE n.nspname  != 'pg_toast'";
-  public static final String PG_JDBC_GET_TYPE_INFO_NOT_TOAST_REPLACEMENT =
-      "select 'bool' as typname, 16 as oid union all\n"
-          + " select 'bytea' as typname, 17 as oid union all\n"
-          + " select 'int8' as typname, 20 as oid union all\n"
-          + " select 'float8' as typname, 701 as oid union all\n"
-          + " select 'varchar' as typname, 1043 as oid union all\n"
-          + " select 'date' as typname, 1082 as oid union all\n"
-          + " select 'timestamptz' as typname, 1184 as oid union all\n"
-          + " select 'numeric' as typname, 1700 as oid union all\n"
-          + " select 'jsonb' as typname, 3802 as oid union all\n"
-          + " select '_bool' as typname, 1000 as oid union all\n"
-          + " select '_bytea' as typname, 1001 as oid union all\n"
-          + " select '_int8' as typname, 1016 as oid union all\n"
-          + " select '_float8' as typname, 1022 as oid union all\n"
-          + " select '_varchar' as typname, 1015 as oid union all\n"
-          + " select '_date' as typname, 1182 as oid union all\n"
-          + " select '_timestamptz' as typname, 1185 as oid union all\n"
-          + " select '_numeric' as typname, 1231 as oid union all\n"
-          + " select '_jsonb' as typname, 3807 as oid";
-
   public static final String PG_JDBC_GET_TABLE_PRIVILEGES_PREFIX_1 =
       "SELECT n.nspname,c.relname,r.rolname,c.relacl  FROM pg_catalog.pg_namespace n, pg_catalog.pg_class c, pg_catalog.pg_roles r  WHERE c.relnamespace = n.oid  AND c.relowner = r.oid  AND c.relkind IN ('r','p'";
   public static final String PG_JDBC_GET_TABLE_PRIVILEGES_PREFIX_2 =
@@ -588,11 +410,6 @@ public class PgJdbcCatalog {
       "SELECT n.nspname,c.relname,r.rolname,c.relacl, a.attacl,  a.attname  FROM pg_catalog.pg_namespace n, pg_catalog.pg_class c,  pg_catalog.pg_roles r, pg_catalog.pg_attribute a  WHERE c.relnamespace = n.oid  AND c.relowner = r.oid  AND c.oid = a.attrelid  AND c.relkind = 'r'  AND a.attnum > 0 AND NOT a.attisdropped";
   public static final String PG_JDBC_GET_COLUMN_PRIVILEGES_PREFIX_1_1 =
       "SELECT n.nspname,c.relname,r.rolname,c.relacl,  a.attname  FROM pg_catalog.pg_namespace n, pg_catalog.pg_class c,  pg_catalog.pg_roles r, pg_catalog.pg_attribute a  WHERE c.relnamespace = n.oid  AND c.relowner = r.oid  AND c.oid = a.attrelid  AND c.relkind = 'r'  AND a.attnum > 0 AND NOT a.attisdropped";
-  public static final String PG_JDBC_GET_COLUMN_PRIVILEGES_REPLACEMENT =
-      "select '' as nspname, '' as relname, '' as rolname, '' as relacl, '' as attname from (select 1) t where false";
-
-  public static final String PG_JDBC_GET_BEST_ROW_IDENTIFIER_PREFIX =
-      "SELECT a.attname, a.atttypid, atttypmod FROM pg_catalog.pg_class ct   JOIN pg_catalog.pg_attribute a ON (ct.oid = a.attrelid)   JOIN pg_catalog.pg_namespace n ON (ct.relnamespace = n.oid)   JOIN (SELECT i.indexrelid, i.indrelid, i.indisprimary,              information_schema._pg_expandarray(i.indkey) AS keys         FROM pg_catalog.pg_index i) i     ON (a.attnum = (i.keys).x AND a.attrelid = i.indrelid) WHERE true";
   public static final String PG_JDBC_GET_BEST_ROW_IDENTIFIER_REPLACEMENT =
       "select '' as attname, 0 as atttypid, -1 as atttypmod from (select 1) t where false";
 
@@ -767,187 +584,6 @@ public class PgJdbcCatalog {
           + "\t''::varchar as sourcefile, 0::bigint as sourceline, false::bool as pending_restart";
   public static final String PG_AM =
       "select 1 as oid, 'spanner' as amname, 'spanner_default_handler' as amhandler, 't' as amtype";
-  public static final String PG_TYPE =
-      "select\n"
-          + "    case table_name\n"
-          + "        when 'pg_am'\t\tthen 16\n"
-          + "        when 'pg_attrdef'\tthen 17\n"
-          + "        when 'pg_attribute'\tthen 701\n"
-          + "        when 'pg_class'\t\tthen 20\n"
-          + "        when 'pg_collation'\tthen 1700\n"
-          + "        when 'pg_database'\tthen 1184\n"
-          + "        when 'pg_index'\t\tthen 1043\n"
-          + "        else 0\n"
-          + "        end as oid,\n"
-          + "    case table_name\n"
-          + "        when 'pg_am'\t\tthen 'bool'\n"
-          + "        when 'pg_attrdef'\tthen 'bytea'\n"
-          + "        when 'pg_attribute'\tthen 'float8'\n"
-          + "        when 'pg_class'\t\tthen 'int8'\n"
-          + "        when 'pg_collation'\tthen 'numeric'\n"
-          + "        when 'pg_database'\tthen 'timestamptz'\n"
-          + "        when 'pg_index'\t\tthen 'varchar'\n"
-          + "        else ''\n"
-          + "        end as typname,\n"
-          + "    (select oid from pg_catalog.pg_namespace where nspname='pg_catalog') as typnamespace,\n"
-          + "    null as typowner,\n"
-          + "    case table_name\n"
-          + "        when 'pg_am'\t\tthen 1\n"
-          + "        when 'pg_attrdef'\tthen -1\n"
-          + "        when 'pg_attribute'\tthen 8\n"
-          + "        when 'pg_class'\t\tthen 8\n"
-          + "        when 'pg_collation'\tthen -1\n"
-          + "        when 'pg_database'\tthen 8\n"
-          + "        when 'pg_index'\t\tthen -1\n"
-          + "        else -1\n"
-          + "        end as typlen,\n"
-          + "    case table_name\n"
-          + "        when 'pg_am'\t\tthen true\n"
-          + "        when 'pg_attrdef'\tthen false\n"
-          + "        when 'pg_attribute'\tthen true\n"
-          + "        when 'pg_class'\t\tthen true\n"
-          + "        when 'pg_collation'\tthen false\n"
-          + "        when 'pg_database'\tthen true\n"
-          + "        when 'pg_index'\t\tthen false\n"
-          + "        else false\n"
-          + "        end as typbyval,\n"
-          + "    'b' as typtype,\n"
-          + "    case table_name\n"
-          + "        when 'pg_am'\t\tthen 'B'\n"
-          + "        when 'pg_attrdef'\tthen 'U'\n"
-          + "        when 'pg_attribute'\tthen 'N'\n"
-          + "        when 'pg_class'\t\tthen 'N'\n"
-          + "        when 'pg_collation'\tthen 'N'\n"
-          + "        when 'pg_database'\tthen 'D'\n"
-          + "        when 'pg_index'\t\tthen 'S'\n"
-          + "        else ''\n"
-          + "        end as typcategory,\n"
-          + "    case table_name\n"
-          + "        when 'pg_am'\t\tthen true\n"
-          + "        when 'pg_attrdef'\tthen false\n"
-          + "        when 'pg_attribute'\tthen true\n"
-          + "        when 'pg_class'\t\tthen false\n"
-          + "        when 'pg_collation'\tthen false\n"
-          + "        when 'pg_database'\tthen true\n"
-          + "        when 'pg_index'\t\tthen false\n"
-          + "        else false\n"
-          + "        end as typispreferred,\n"
-          + "    true as typisdefined, true as typisdefined, ',' as typdelim, 0 as typrelid, '-' as typsubscript, 0 as typelem,\n"
-          + "    case table_name\n"
-          + "        when 'pg_am'\t\tthen 1000\n"
-          + "        when 'pg_attrdef'\tthen 1001\n"
-          + "        when 'pg_attribute'\tthen 1022\n"
-          + "        when 'pg_class'\t\tthen 1016\n"
-          + "        when 'pg_collation'\tthen 1231\n"
-          + "        when 'pg_database'\tthen 1185\n"
-          + "        when 'pg_index'\t\tthen 1015\n"
-          + "        else 0\n"
-          + "        end as typarray,\n"
-          + "    case table_name\n"
-          + "        when 'pg_am'\t\tthen 'boolin'\n"
-          + "        when 'pg_attrdef'\tthen 'byteain'\n"
-          + "        when 'pg_attribute'\tthen 'float8in'\n"
-          + "        when 'pg_class'\t\tthen 'int8in'\n"
-          + "        when 'pg_collation'\tthen 'numeric_in'\n"
-          + "        when 'pg_database'\tthen 'timestamptz_in'\n"
-          + "        when 'pg_index'\t\tthen 'varcharin'\n"
-          + "        else ''\n"
-          + "        end as typinput,\n"
-          + "    case table_name\n"
-          + "        when 'pg_am'\t\tthen 'boolout'\n"
-          + "        when 'pg_attrdef'\tthen 'byteaout'\n"
-          + "        when 'pg_attribute'\tthen 'float8out'\n"
-          + "        when 'pg_class'\t\tthen 'int8out'\n"
-          + "        when 'pg_collation'\tthen 'numeric_out'\n"
-          + "        when 'pg_database'\tthen 'timestamptz_out'\n"
-          + "        when 'pg_index'\t\tthen 'varcharout'\n"
-          + "        else ''\n"
-          + "        end as typoutput,\n"
-          + "    case table_name\n"
-          + "        when 'pg_am'\t\tthen 'boolrecv'\n"
-          + "        when 'pg_attrdef'\tthen 'bytearecv'\n"
-          + "        when 'pg_attribute'\tthen 'float8recv'\n"
-          + "        when 'pg_class'\t\tthen 'int8recv'\n"
-          + "        when 'pg_collation'\tthen 'numeric_recv'\n"
-          + "        when 'pg_database'\tthen 'timestamptz_recv'\n"
-          + "        when 'pg_index'\t\tthen 'varcharrecv'\n"
-          + "        else ''\n"
-          + "        end as typreceive,\n"
-          + "    case table_name\n"
-          + "        when 'pg_am'\t\tthen 'boolsend'\n"
-          + "        when 'pg_attrdef'\tthen 'byteasend'\n"
-          + "        when 'pg_attribute'\tthen 'float8send'\n"
-          + "        when 'pg_class'\t\tthen 'int8send'\n"
-          + "        when 'pg_collation'\tthen 'numeric_send'\n"
-          + "        when 'pg_database'\tthen 'timestamptz_send'\n"
-          + "        when 'pg_index'\t\tthen 'varcharsend'\n"
-          + "        else ''\n"
-          + "        end as typsend,\n"
-          + "    case table_name\n"
-          + "        when 'pg_am'\t\tthen '-'\n"
-          + "        when 'pg_attrdef'\tthen '-'\n"
-          + "        when 'pg_attribute'\tthen '-'\n"
-          + "        when 'pg_class'\t\tthen '-'\n"
-          + "        when 'pg_collation'\tthen 'numerictypmodin'\n"
-          + "        when 'pg_database'\tthen 'timestamptztypmodin'\n"
-          + "        when 'pg_index'\t\tthen 'varchartypmodin'\n"
-          + "        else ''\n"
-          + "        end as typmodin,\n"
-          + "    case table_name\n"
-          + "        when 'pg_am'\t\tthen '-'\n"
-          + "        when 'pg_attrdef'\tthen '-'\n"
-          + "        when 'pg_attribute'\tthen '-'\n"
-          + "        when 'pg_class'\t\tthen '-'\n"
-          + "        when 'pg_collation'\tthen 'numerictypmodout'\n"
-          + "        when 'pg_database'\tthen 'timestamptztypmodout'\n"
-          + "        when 'pg_index'\t\tthen 'varchartypmodout'\n"
-          + "        else ''\n"
-          + "        end as typmodout,\n"
-          + "    '-' as typanalyze,\n"
-          + "    case table_name\n"
-          + "        when 'pg_am'\t\tthen 'c'\n"
-          + "        when 'pg_attrdef'\tthen 'i'\n"
-          + "        when 'pg_attribute'\tthen 'd'\n"
-          + "        when 'pg_class'\t\tthen 'd'\n"
-          + "        when 'pg_collation'\tthen 'i'\n"
-          + "        when 'pg_database'\tthen 'd'\n"
-          + "        when 'pg_index'\t\tthen 'i'\n"
-          + "        else ''\n"
-          + "        end as typalign,\n"
-          + "    case table_name\n"
-          + "        when 'pg_am'\t\tthen 'p'\n"
-          + "        when 'pg_attrdef'\tthen 'x'\n"
-          + "        when 'pg_attribute'\tthen 'p'\n"
-          + "        when 'pg_class'\t\tthen 'p'\n"
-          + "        when 'pg_collation'\tthen 'm'\n"
-          + "        when 'pg_database'\tthen 'p'\n"
-          + "        when 'pg_index'\t\tthen 'x'\n"
-          + "        else ''\n"
-          + "        end as typstorage,\n"
-          + "    false as typnotnull, 0 as typbasetype, -1 as typtypmod, 0 as typndims, 0 as typcollation, null::varchar as typdefaultbin, null::varchar as typdefault, null as typacl,\n"
-          + "    case table_name\n"
-          + "        when 'pg_am'\t\tthen 'bool'\n"
-          + "        when 'pg_attrdef'\tthen 'bytea'\n"
-          + "        when 'pg_attribute'\tthen 'double precision'\n"
-          + "        when 'pg_class'\t\tthen 'bigint'\n"
-          + "        when 'pg_collation'\tthen 'numeric'\n"
-          + "        when 'pg_database'\tthen 'timestamp with time zone'\n"
-          + "        when 'pg_index'\t\tthen 'character varying'\n"
-          + "        else ''\n"
-          + "        end as spanner_data_type\n"
-          + "from information_schema.tables\n"
-          + "where table_schema='pg_catalog'\n"
-          + "and table_name in ('pg_am', 'pg_attrdef', 'pg_attribute', 'pg_class', 'pg_collation', 'pg_database', 'pg_index')\n"
-          + "order by case table_name\n"
-          + "  when 'pg_am'         then 'bool'\n"
-          + "  when 'pg_attrdef'    then 'bytea'\n"
-          + "  when 'pg_attribute'  then 'float8'\n"
-          + "  when 'pg_class'      then 'int8'\n"
-          + "  when 'pg_collation'  then 'numeric'\n"
-          + "  when 'pg_database'   then 'timestamptz'\n"
-          + "  when 'pg_index'      then 'varchar'\n"
-          + "  else ''\n"
-          + "end";
   public static final String PG_ATTR_TYPE =
       "select\n"
           + "\ta.attrelid, a.attname,\n"


Test patch:
diff --git a/src/test/golang/pgadapter_pgx_tests/pgx.go b/src/test/golang/pgadapter_pgx_tests/pgx.go
index 30179ba1..4afd39e0 100644
--- a/src/test/golang/pgadapter_pgx_tests/pgx.go
+++ b/src/test/golang/pgadapter_pgx_tests/pgx.go
@@ -682,8 +682,10 @@ func TestCopyIn(connString string) *C.char {
 	timestamptz, _ := time.Parse(time.RFC3339Nano, "2022-03-24T12:39:10.123456000Z")
 	date := pgtype.Date{}
 	date.Set("2022-07-01")
+	jsonb := pgtype.JSONB{}
+	jsonb.Set("{\"key\": \"value\"}")
 	rows := [][]interface{}{
-		{1, true, []byte{1, 2, 3}, 3.14, 10, numeric, timestamptz, date, "test", "{\"key\": \"value\"}"},
+		{1, true, []byte{1, 2, 3}, 3.14, 10, numeric, timestamptz, date, "test", jsonb},
 		{2, nil, nil, nil, nil, nil, nil, nil, nil, nil},
 	}
 	count, err := conn.CopyFrom(
diff --git a/src/test/java/com/google/cloud/spanner/pgadapter/AbstractMockServerTest.java b/src/test/java/com/google/cloud/spanner/pgadapter/AbstractMockServerTest.java
index 7b618032..e941b18e 100644
--- a/src/test/java/com/google/cloud/spanner/pgadapter/AbstractMockServerTest.java
+++ b/src/test/java/com/google/cloud/spanner/pgadapter/AbstractMockServerTest.java
@@ -59,6 +59,7 @@ import io.grpc.StatusRuntimeException;
 import io.grpc.netty.shaded.io.grpc.netty.NettyServerBuilder;
 import java.net.InetSocketAddress;
 import java.nio.charset.StandardCharsets;
+import java.sql.SQLException;
 import java.util.ArrayList;
 import java.util.Base64;
 import java.util.Collections;
@@ -69,6 +70,8 @@ import java.util.stream.Collectors;
 import org.junit.AfterClass;
 import org.junit.Before;
 import org.junit.BeforeClass;
+import org.postgresql.core.Oid;
+import org.postgresql.util.PGobject;
 
 /**
  * Abstract base class for tests that verify that PgAdapter is receiving wire protocol requests
@@ -92,6 +95,203 @@ import org.junit.BeforeClass;
 public abstract class AbstractMockServerTest {
   private static final Logger logger = Logger.getLogger(AbstractMockServerTest.class.getName());
 
+  protected static final Statement SELECT_JSONB_TYPE_BY_OID =
+      Statement.newBuilder(
+              "with pg_namespace as (\n"
+                  + "  select case schema_name when 'pg_catalog' then 11 when 'public' then 2200 else 0 end as oid,\n"
+                  + "        schema_name as nspname, null as nspowner, null as nspacl\n"
+                  + "  from information_schema.schemata\n"
+                  + "),\n"
+                  + "pg_type as (\n"
+                  + "  select 16 as oid, 'bool' as typname, (select oid from pg_namespace where nspname='pg_catalog') as typnamespace, null as typowner, 1 as typlen, true as typbyval, 'b' as typtype, 'B' as typcategory, true as typispreferred, true as typisdefined, ',' as typdelim, 0 as typrelid, 0 as typelem, 1000 as typarray, 'boolin' as typinput, 'boolout' as typoutput, 'boolrecv' as typreceive, 'boolsend' as typsend, '-' as typmodin, '-' as typmodout, '-' as typanalyze, 'c' as typalign, 'p' as typstorage, false as typnotnull, 0 as typbasetype, -1 as typtypmod, 0 as typndims, 0 as typcollation, null as typdefaultbin, null as typdefault, null as typacl union all\n"
+                  + "  select 17 as oid, 'bytea' as typname, (select oid from pg_namespace where nspname='pg_catalog') as typnamespace, null as typowner, -1 as typlen, false as typbyval, 'b' as typtype, 'U' as typcategory, false as typispreferred, true as typisdefined, ',' as typdelim, 0 as typrelid, 0 as typelem, 1001 as typarray, 'byteain' as typinput, 'byteaout' as typoutput, 'bytearecv' as typreceive, 'byteasend' as typsend, '-' as typmodin, '-' as typmodout, '-' as typanalyze, 'i' as typalign, 'x' as typstorage, false as typnotnull, 0 as typbasetype, -1 as typtypmod, 0 as typndims, 0 as typcollation, null as typdefaultbin, null as typdefault, null as typacl union all\n"
+                  + "  select 20 as oid, 'int8' as typname, (select oid from pg_namespace where nspname='pg_catalog') as typnamespace, null as typowner, 8 as typlen, true as typbyval, 'b' as typtype, 'N' as typcategory, false as typispreferred, true as typisdefined, ',' as typdelim, 0 as typrelid, 0 as typelem, 1016 as typarray, 'int8in' as typinput, 'int8out' as typoutput, 'int8recv' as typreceive, 'int8send' as typsend, '-' as typmodin, '-' as typmodout, '-' as typanalyze, 'd' as typalign, 'p' as typstorage, false as typnotnull, 0 as typbasetype, -1 as typtypmod, 0 as typndims, 0 as typcollation, null as typdefaultbin, null as typdefault, null as typacl union all\n"
+                  + "  select 21 as oid, 'int2' as typname, (select oid from pg_namespace where nspname='pg_catalog') as typnamespace, null as typowner, 2 as typlen, true as typbyval, 'b' as typtype, 'N' as typcategory, false as typispreferred, false as typisdefined, ',' as typdelim, 0 as typrelid, 0 as typelem, 1005 as typarray, 'int2in' as typinput, 'int2out' as typoutput, 'int2recv' as typreceive, 'int2send' as typsend, '-' as typmodin, '-' as typmodout, '-' as typanalyze, 's' as typalign, 'p' as typstorage, false as typnotnull, 0 as typbasetype, -1 as typtypmod, 0 as typndims, 0 as typcollation, null as typdefaultbin, null as typdefault, null as typacl union all\n"
+                  + "  select 23 as oid, 'int4' as typname, (select oid from pg_namespace where nspname='pg_catalog') as typnamespace, null as typowner, 4 as typlen, true as typbyval, 'b' as typtype, 'N' as typcategory, false as typispreferred, false as typisdefined, ',' as typdelim, 0 as typrelid, 0 as typelem, 1007 as typarray, 'int4in' as typinput, 'int4out' as typoutput, 'int4recv' as typreceive, 'int4send' as typsend, '-' as typmodin, '-' as typmodout, '-' as typanalyze, 'i' as typalign, 'p' as typstorage, false as typnotnull, 0 as typbasetype, -1 as typtypmod, 0 as typndims, 0 as typcollation, null as typdefaultbin, null as typdefault, null as typacl union all\n"
+                  + "  select 25 as oid, 'text' as typname, (select oid from pg_namespace where nspname='pg_catalog') as typnamespace, null as typowner, -1 as typlen, false as typbyval, 'b' as typtype, 'S' as typcategory, true as typispreferred, true as typisdefined, ',' as typdelim, 0 as typrelid, 0 as typelem, 1009 as typarray, 'textin' as typinput, 'textout' as typoutput, 'textrecv' as typreceive, 'textsend' as typsend, '-' as typmodin, '-' as typmodout, '-' as typanalyze, 'i' as typalign, 'x' as typstorage, false as typnotnull, 0 as typbasetype, -1 as typtypmod, 0 as typndims, 100 as typcollation, null as typdefaultbin, null as typdefault, null as typacl union all\n"
+                  + "  select 700 as oid, 'float4' as typname, (select oid from pg_namespace where nspname='pg_catalog') as typnamespace, null as typowner, 4 as typlen, true as typbyval, 'b' as typtype, 'N' as typcategory, false as typispreferred, false as typisdefined, ',' as typdelim, 0 as typrelid, 0 as typelem, 1021 as typarray, 'float4in' as typinput, 'float4out' as typoutput, 'float4recv' as typreceive, 'float4send' as typsend, '-' as typmodin, '-' as typmodout, '-' as typanalyze, 'i' as typalign, 'p' as typstorage, false as typnotnull, 0 as typbasetype, -1 as typtypmod, 0 as typndims, 0 as typcollation, null as typdefaultbin, null as typdefault, null as typacl union all\n"
+                  + "  select 701 as oid, 'float8' as typname, (select oid from pg_namespace where nspname='pg_catalog') as typnamespace, null as typowner, 8 as typlen, true as typbyval, 'b' as typtype, 'N' as typcategory, true as typispreferred, true as typisdefined, ',' as typdelim, 0 as typrelid, 0 as typelem, 1022 as typarray, 'float8in' as typinput, 'float8out' as typoutput, 'float8recv' as typreceive, 'float8send' as typsend, '-' as typmodin, '-' as typmodout, '-' as typanalyze, 'd' as typalign, 'p' as typstorage, false as typnotnull, 0 as typbasetype, -1 as typtypmod, 0 as typndims, 0 as typcollation, null as typdefaultbin, null as typdefault, null as typacl union all\n"
+                  + "  select 1043 as oid, 'varchar' as typname, (select oid from pg_namespace where nspname='pg_catalog') as typnamespace, null as typowner, -1 as typlen, false as typbyval, 'b' as typtype, 'S' as typcategory, false as typispreferred, true as typisdefined, ',' as typdelim, 0 as typrelid, 0 as typelem, 1015 as typarray, 'varcharin' as typinput, 'varcharout' as typoutput, 'varcharrecv' as typreceive, 'varcharsend' as typsend, 'varchartypmodin' as typmodin, 'varchartypmodout' as typmodout, '-' as typanalyze, 'i' as typalign, 'x' as typstorage, false as typnotnull, 0 as typbasetype, -1 as typtypmod, 0 as typndims, 100 as typcollation, null as typdefaultbin, null as typdefault, null as typacl union all\n"
+                  + "  select 1082 as oid, 'date' as typname, (select oid from pg_namespace where nspname='pg_catalog') as typnamespace, null as typowner, 4 as typlen, true as typbyval, 'b' as typtype, 'D' as typcategory, false as typispreferred, true as typisdefined, ',' as typdelim, 0 as typrelid, 0 as typelem, 1182 as typarray, 'date_in' as typinput, 'date_out' as typoutput, 'date_recv' as typreceive, 'date_send' as typsend, '-' as typmodin, '-' as typmodout, '-' as typanalyze, 'i' as typalign, 'p' as typstorage, false as typnotnull, 0 as typbasetype, -1 as typtypmod, 0 as typndims, 0 as typcollation, null as typdefaultbin, null as typdefault, null as typacl union all\n"
+                  + "  select 1114 as oid, 'timestamp' as typname, (select oid from pg_namespace where nspname='pg_catalog') as typnamespace, null as typowner, 8 as typlen, true as typbyval, 'b' as typtype, 'D' as typcategory, false as typispreferred, false as typisdefined, ',' as typdelim, 0 as typrelid, 0 as typelem, 1115 as typarray, 'timestamp_in' as typinput, 'timestamp_out' as typoutput, 'timestamp_recv' as typreceive, 'timestamp_send' as typsend, 'timestamptypmodin' as typmodin, 'timestamptypmodout' as typmodout, '-' as typanalyze, 'd' as typalign, 'p' as typstorage, false as typnotnull, 0 as typbasetype, -1 as typtypmod, 0 as typndims, 0 as typcollation, null as typdefaultbin, null as typdefault, null as typacl union all\n"
+                  + "  select 1184 as oid, 'timestamptz' as typname, (select oid from pg_namespace where nspname='pg_catalog') as typnamespace, null as typowner, 8 as typlen, true as typbyval, 'b' as typtype, 'D' as typcategory, true as typispreferred, true as typisdefined, ',' as typdelim, 0 as typrelid, 0 as typelem, 1185 as typarray, 'timestamptz_in' as typinput, 'timestamptz_out' as typoutput, 'timestamptz_recv' as typreceive, 'timestamptz_send' as typsend, 'timestamptztypmodin' as typmodin, 'timestamptztypmodout' as typmodout, '-' as typanalyze, 'd' as typalign, 'p' as typstorage, false as typnotnull, 0 as typbasetype, -1 as typtypmod, 0 as typndims, 0 as typcollation, null as typdefaultbin, null as typdefault, null as typacl union all\n"
+                  + "  select 1700 as oid, 'numeric' as typname, (select oid from pg_namespace where nspname='pg_catalog') as typnamespace, null as typowner, -1 as typlen, false as typbyval, 'b' as typtype, 'N' as typcategory, false as typispreferred, true as typisdefined, ',' as typdelim, 0 as typrelid, 0 as typelem, 1231 as typarray, 'numeric_in' as typinput, 'numeric_out' as typoutput, 'numeric_recv' as typreceive, 'numeric_send' as typsend, 'numerictypmodin' as typmodin, 'numerictypmodout' as typmodout, '-' as typanalyze, 'i' as typalign, 'm' as typstorage, false as typnotnull, 0 as typbasetype, -1 as typtypmod, 0 as typndims, 0 as typcollation, null as typdefaultbin, null as typdefault, null as typacl union all\n"
+                  + "  select 3802 as oid, 'jsonb' as typname, (select oid from pg_namespace where nspname='pg_catalog') as typnamespace, null as typowner, -1 as typlen, false as typbyval, 'b' as typtype, 'U' as typcategory, false as typispreferred, true as typisdefined, ',' as typdelim, 0 as typrelid, 0 as typelem, 3807 as typarray, 'jsonb_in' as typinput, 'jsonb_out' as typoutput, 'jsonb_recv' as typreceive, 'jsonb_send' as typsend, '-' as typmodin, '-' as typmodout, '-' as typanalyze, 'i' as typalign, 'x' as typstorage, false as typnotnull, 0 as typbasetype, -1 as typtypmod, 0 as typndims, 0 as typcollation, null as typdefaultbin, null as typdefault, null as typacl\n"
+                  + ")\n"
+                  + "SELECT substring(typname, 1, 1)='_' as is_array, typtype, typname, pg_type.oid   FROM pg_type   LEFT JOIN (select ns.oid as nspoid, ns.nspname, r.r           from pg_namespace as ns           join ( select 1 as r, 'public' as nspname ) as r          using ( nspname )        ) as sp     ON sp.nspoid = typnamespace  WHERE pg_type.oid = $1  ORDER BY sp.r, pg_type.oid DESC")
+          .bind("p1")
+          .to(Oid.JSONB)
+          .build();
+  protected static final ResultSet SELECT_JSONB_TYPE_BY_OID_RESULT_SET =
+      ResultSet.newBuilder()
+          .setMetadata(
+              ResultSetMetadata.newBuilder()
+                  .setRowType(
+                      StructType.newBuilder()
+                          .addFields(
+                              Field.newBuilder()
+                                  .setName("is_array")
+                                  .setType(Type.newBuilder().setCode(TypeCode.BOOL).build())
+                                  .build())
+                          .addFields(
+                              Field.newBuilder()
+                                  .setName("typtype")
+                                  .setType(Type.newBuilder().setCode(TypeCode.STRING).build())
+                                  .build())
+                          .addFields(
+                              Field.newBuilder()
+                                  .setName("typname")
+                                  .setType(Type.newBuilder().setCode(TypeCode.STRING).build())
+                                  .build())
+                          .addFields(
+                              Field.newBuilder()
+                                  .setName("oid")
+                                  .setType(Type.newBuilder().setCode(TypeCode.INT64).build())
+                                  .build())
+                          .build())
+                  .build())
+          .addRows(
+              ListValue.newBuilder()
+                  .addValues(Value.newBuilder().setBoolValue(false).build())
+                  .addValues(Value.newBuilder().setStringValue("b").build())
+                  .addValues(Value.newBuilder().setStringValue("jsonb").build())
+                  .addValues(Value.newBuilder().setStringValue("3802").build())
+                  .build())
+          .build();
+  protected static final Statement SELECT_JSONB_TYPE_BY_NAME =
+      Statement.newBuilder(
+              "with pg_namespace as (\n"
+                  + "  select case schema_name when 'pg_catalog' then 11 when 'public' then 2200 else 0 end as oid,\n"
+                  + "        schema_name as nspname, null as nspowner, null as nspacl\n"
+                  + "  from information_schema.schemata\n"
+                  + "),\n"
+                  + "pg_type as (\n"
+                  + "  select 16 as oid, 'bool' as typname, (select oid from pg_namespace where nspname='pg_catalog') as typnamespace, null as typowner, 1 as typlen, true as typbyval, 'b' as typtype, 'B' as typcategory, true as typispreferred, true as typisdefined, ',' as typdelim, 0 as typrelid, 0 as typelem, 1000 as typarray, 'boolin' as typinput, 'boolout' as typoutput, 'boolrecv' as typreceive, 'boolsend' as typsend, '-' as typmodin, '-' as typmodout, '-' as typanalyze, 'c' as typalign, 'p' as typstorage, false as typnotnull, 0 as typbasetype, -1 as typtypmod, 0 as typndims, 0 as typcollation, null as typdefaultbin, null as typdefault, null as typacl union all\n"
+                  + "  select 17 as oid, 'bytea' as typname, (select oid from pg_namespace where nspname='pg_catalog') as typnamespace, null as typowner, -1 as typlen, false as typbyval, 'b' as typtype, 'U' as typcategory, false as typispreferred, true as typisdefined, ',' as typdelim, 0 as typrelid, 0 as typelem, 1001 as typarray, 'byteain' as typinput, 'byteaout' as typoutput, 'bytearecv' as typreceive, 'byteasend' as typsend, '-' as typmodin, '-' as typmodout, '-' as typanalyze, 'i' as typalign, 'x' as typstorage, false as typnotnull, 0 as typbasetype, -1 as typtypmod, 0 as typndims, 0 as typcollation, null as typdefaultbin, null as typdefault, null as typacl union all\n"
+                  + "  select 20 as oid, 'int8' as typname, (select oid from pg_namespace where nspname='pg_catalog') as typnamespace, null as typowner, 8 as typlen, true as typbyval, 'b' as typtype, 'N' as typcategory, false as typispreferred, true as typisdefined, ',' as typdelim, 0 as typrelid, 0 as typelem, 1016 as typarray, 'int8in' as typinput, 'int8out' as typoutput, 'int8recv' as typreceive, 'int8send' as typsend, '-' as typmodin, '-' as typmodout, '-' as typanalyze, 'd' as typalign, 'p' as typstorage, false as typnotnull, 0 as typbasetype, -1 as typtypmod, 0 as typndims, 0 as typcollation, null as typdefaultbin, null as typdefault, null as typacl union all\n"
+                  + "  select 21 as oid, 'int2' as typname, (select oid from pg_namespace where nspname='pg_catalog') as typnamespace, null as typowner, 2 as typlen, true as typbyval, 'b' as typtype, 'N' as typcategory, false as typispreferred, false as typisdefined, ',' as typdelim, 0 as typrelid, 0 as typelem, 1005 as typarray, 'int2in' as typinput, 'int2out' as typoutput, 'int2recv' as typreceive, 'int2send' as typsend, '-' as typmodin, '-' as typmodout, '-' as typanalyze, 's' as typalign, 'p' as typstorage, false as typnotnull, 0 as typbasetype, -1 as typtypmod, 0 as typndims, 0 as typcollation, null as typdefaultbin, null as typdefault, null as typacl union all\n"
+                  + "  select 23 as oid, 'int4' as typname, (select oid from pg_namespace where nspname='pg_catalog') as typnamespace, null as typowner, 4 as typlen, true as typbyval, 'b' as typtype, 'N' as typcategory, false as typispreferred, false as typisdefined, ',' as typdelim, 0 as typrelid, 0 as typelem, 1007 as typarray, 'int4in' as typinput, 'int4out' as typoutput, 'int4recv' as typreceive, 'int4send' as typsend, '-' as typmodin, '-' as typmodout, '-' as typanalyze, 'i' as typalign, 'p' as typstorage, false as typnotnull, 0 as typbasetype, -1 as typtypmod, 0 as typndims, 0 as typcollation, null as typdefaultbin, null as typdefault, null as typacl union all\n"
+                  + "  select 25 as oid, 'text' as typname, (select oid from pg_namespace where nspname='pg_catalog') as typnamespace, null as typowner, -1 as typlen, false as typbyval, 'b' as typtype, 'S' as typcategory, true as typispreferred, true as typisdefined, ',' as typdelim, 0 as typrelid, 0 as typelem, 1009 as typarray, 'textin' as typinput, 'textout' as typoutput, 'textrecv' as typreceive, 'textsend' as typsend, '-' as typmodin, '-' as typmodout, '-' as typanalyze, 'i' as typalign, 'x' as typstorage, false as typnotnull, 0 as typbasetype, -1 as typtypmod, 0 as typndims, 100 as typcollation, null as typdefaultbin, null as typdefault, null as typacl union all\n"
+                  + "  select 700 as oid, 'float4' as typname, (select oid from pg_namespace where nspname='pg_catalog') as typnamespace, null as typowner, 4 as typlen, true as typbyval, 'b' as typtype, 'N' as typcategory, false as typispreferred, false as typisdefined, ',' as typdelim, 0 as typrelid, 0 as typelem, 1021 as typarray, 'float4in' as typinput, 'float4out' as typoutput, 'float4recv' as typreceive, 'float4send' as typsend, '-' as typmodin, '-' as typmodout, '-' as typanalyze, 'i' as typalign, 'p' as typstorage, false as typnotnull, 0 as typbasetype, -1 as typtypmod, 0 as typndims, 0 as typcollation, null as typdefaultbin, null as typdefault, null as typacl union all\n"
+                  + "  select 701 as oid, 'float8' as typname, (select oid from pg_namespace where nspname='pg_catalog') as typnamespace, null as typowner, 8 as typlen, true as typbyval, 'b' as typtype, 'N' as typcategory, true as typispreferred, true as typisdefined, ',' as typdelim, 0 as typrelid, 0 as typelem, 1022 as typarray, 'float8in' as typinput, 'float8out' as typoutput, 'float8recv' as typreceive, 'float8send' as typsend, '-' as typmodin, '-' as typmodout, '-' as typanalyze, 'd' as typalign, 'p' as typstorage, false as typnotnull, 0 as typbasetype, -1 as typtypmod, 0 as typndims, 0 as typcollation, null as typdefaultbin, null as typdefault, null as typacl union all\n"
+                  + "  select 1043 as oid, 'varchar' as typname, (select oid from pg_namespace where nspname='pg_catalog') as typnamespace, null as typowner, -1 as typlen, false as typbyval, 'b' as typtype, 'S' as typcategory, false as typispreferred, true as typisdefined, ',' as typdelim, 0 as typrelid, 0 as typelem, 1015 as typarray, 'varcharin' as typinput, 'varcharout' as typoutput, 'varcharrecv' as typreceive, 'varcharsend' as typsend, 'varchartypmodin' as typmodin, 'varchartypmodout' as typmodout, '-' as typanalyze, 'i' as typalign, 'x' as typstorage, false as typnotnull, 0 as typbasetype, -1 as typtypmod, 0 as typndims, 100 as typcollation, null as typdefaultbin, null as typdefault, null as typacl union all\n"
+                  + "  select 1082 as oid, 'date' as typname, (select oid from pg_namespace where nspname='pg_catalog') as typnamespace, null as typowner, 4 as typlen, true as typbyval, 'b' as typtype, 'D' as typcategory, false as typispreferred, true as typisdefined, ',' as typdelim, 0 as typrelid, 0 as typelem, 1182 as typarray, 'date_in' as typinput, 'date_out' as typoutput, 'date_recv' as typreceive, 'date_send' as typsend, '-' as typmodin, '-' as typmodout, '-' as typanalyze, 'i' as typalign, 'p' as typstorage, false as typnotnull, 0 as typbasetype, -1 as typtypmod, 0 as typndims, 0 as typcollation, null as typdefaultbin, null as typdefault, null as typacl union all\n"
+                  + "  select 1114 as oid, 'timestamp' as typname, (select oid from pg_namespace where nspname='pg_catalog') as typnamespace, null as typowner, 8 as typlen, true as typbyval, 'b' as typtype, 'D' as typcategory, false as typispreferred, false as typisdefined, ',' as typdelim, 0 as typrelid, 0 as typelem, 1115 as typarray, 'timestamp_in' as typinput, 'timestamp_out' as typoutput, 'timestamp_recv' as typreceive, 'timestamp_send' as typsend, 'timestamptypmodin' as typmodin, 'timestamptypmodout' as typmodout, '-' as typanalyze, 'd' as typalign, 'p' as typstorage, false as typnotnull, 0 as typbasetype, -1 as typtypmod, 0 as typndims, 0 as typcollation, null as typdefaultbin, null as typdefault, null as typacl union all\n"
+                  + "  select 1184 as oid, 'timestamptz' as typname, (select oid from pg_namespace where nspname='pg_catalog') as typnamespace, null as typowner, 8 as typlen, true as typbyval, 'b' as typtype, 'D' as typcategory, true as typispreferred, true as typisdefined, ',' as typdelim, 0 as typrelid, 0 as typelem, 1185 as typarray, 'timestamptz_in' as typinput, 'timestamptz_out' as typoutput, 'timestamptz_recv' as typreceive, 'timestamptz_send' as typsend, 'timestamptztypmodin' as typmodin, 'timestamptztypmodout' as typmodout, '-' as typanalyze, 'd' as typalign, 'p' as typstorage, false as typnotnull, 0 as typbasetype, -1 as typtypmod, 0 as typndims, 0 as typcollation, null as typdefaultbin, null as typdefault, null as typacl union all\n"
+                  + "  select 1700 as oid, 'numeric' as typname, (select oid from pg_namespace where nspname='pg_catalog') as typnamespace, null as typowner, -1 as typlen, false as typbyval, 'b' as typtype, 'N' as typcategory, false as typispreferred, true as typisdefined, ',' as typdelim, 0 as typrelid, 0 as typelem, 1231 as typarray, 'numeric_in' as typinput, 'numeric_out' as typoutput, 'numeric_recv' as typreceive, 'numeric_send' as typsend, 'numerictypmodin' as typmodin, 'numerictypmodout' as typmodout, '-' as typanalyze, 'i' as typalign, 'm' as typstorage, false as typnotnull, 0 as typbasetype, -1 as typtypmod, 0 as typndims, 0 as typcollation, null as typdefaultbin, null as typdefault, null as typacl union all\n"
+                  + "  select 3802 as oid, 'jsonb' as typname, (select oid from pg_namespace where nspname='pg_catalog') as typnamespace, null as typowner, -1 as typlen, false as typbyval, 'b' as typtype, 'U' as typcategory, false as typispreferred, true as typisdefined, ',' as typdelim, 0 as typrelid, 0 as typelem, 3807 as typarray, 'jsonb_in' as typinput, 'jsonb_out' as typoutput, 'jsonb_recv' as typreceive, 'jsonb_send' as typsend, '-' as typmodin, '-' as typmodout, '-' as typanalyze, 'i' as typalign, 'x' as typstorage, false as typnotnull, 0 as typbasetype, -1 as typtypmod, 0 as typndims, 0 as typcollation, null as typdefaultbin, null as typdefault, null as typacl\n"
+                  + ")\n"
+                  + "SELECT pg_type.oid, typname   FROM pg_type   LEFT   JOIN (select ns.oid as nspoid, ns.nspname, r.r           from pg_namespace as ns           join ( select 1 as r, 'public' as nspname ) as r          using ( nspname )        ) as sp     ON sp.nspoid = typnamespace  WHERE typname = $1  ORDER BY sp.r, pg_type.oid DESC LIMIT 1")
+          .bind("p1")
+          .to("jsonb")
+          .build();
+  protected static final Statement SELECT_JSONB_TYPE_BY_NAME_SIMPLE_PROTOCOL =
+      Statement.of(
+          "with pg_namespace as (\n"
+              + "  select case schema_name when 'pg_catalog' then 11 when 'public' then 2200 else 0 end as oid,\n"
+              + "        schema_name as nspname, null as nspowner, null as nspacl\n"
+              + "  from information_schema.schemata\n"
+              + "),\n"
+              + "pg_type as (\n"
+              + "  select 16 as oid, 'bool' as typname, (select oid from pg_namespace where nspname='pg_catalog') as typnamespace, null as typowner, 1 as typlen, true as typbyval, 'b' as typtype, 'B' as typcategory, true as typispreferred, true as typisdefined, ',' as typdelim, 0 as typrelid, 0 as typelem, 1000 as typarray, 'boolin' as typinput, 'boolout' as typoutput, 'boolrecv' as typreceive, 'boolsend' as typsend, '-' as typmodin, '-' as typmodout, '-' as typanalyze, 'c' as typalign, 'p' as typstorage, false as typnotnull, 0 as typbasetype, -1 as typtypmod, 0 as typndims, 0 as typcollation, null as typdefaultbin, null as typdefault, null as typacl union all\n"
+              + "  select 17 as oid, 'bytea' as typname, (select oid from pg_namespace where nspname='pg_catalog') as typnamespace, null as typowner, -1 as typlen, false as typbyval, 'b' as typtype, 'U' as typcategory, false as typispreferred, true as typisdefined, ',' as typdelim, 0 as typrelid, 0 as typelem, 1001 as typarray, 'byteain' as typinput, 'byteaout' as typoutput, 'bytearecv' as typreceive, 'byteasend' as typsend, '-' as typmodin, '-' as typmodout, '-' as typanalyze, 'i' as typalign, 'x' as typstorage, false as typnotnull, 0 as typbasetype, -1 as typtypmod, 0 as typndims, 0 as typcollation, null as typdefaultbin, null as typdefault, null as typacl union all\n"
+              + "  select 20 as oid, 'int8' as typname, (select oid from pg_namespace where nspname='pg_catalog') as typnamespace, null as typowner, 8 as typlen, true as typbyval, 'b' as typtype, 'N' as typcategory, false as typispreferred, true as typisdefined, ',' as typdelim, 0 as typrelid, 0 as typelem, 1016 as typarray, 'int8in' as typinput, 'int8out' as typoutput, 'int8recv' as typreceive, 'int8send' as typsend, '-' as typmodin, '-' as typmodout, '-' as typanalyze, 'd' as typalign, 'p' as typstorage, false as typnotnull, 0 as typbasetype, -1 as typtypmod, 0 as typndims, 0 as typcollation, null as typdefaultbin, null as typdefault, null as typacl union all\n"
+              + "  select 21 as oid, 'int2' as typname, (select oid from pg_namespace where nspname='pg_catalog') as typnamespace, null as typowner, 2 as typlen, true as typbyval, 'b' as typtype, 'N' as typcategory, false as typispreferred, false as typisdefined, ',' as typdelim, 0 as typrelid, 0 as typelem, 1005 as typarray, 'int2in' as typinput, 'int2out' as typoutput, 'int2recv' as typreceive, 'int2send' as typsend, '-' as typmodin, '-' as typmodout, '-' as typanalyze, 's' as typalign, 'p' as typstorage, false as typnotnull, 0 as typbasetype, -1 as typtypmod, 0 as typndims, 0 as typcollation, null as typdefaultbin, null as typdefault, null as typacl union all\n"
+              + "  select 23 as oid, 'int4' as typname, (select oid from pg_namespace where nspname='pg_catalog') as typnamespace, null as typowner, 4 as typlen, true as typbyval, 'b' as typtype, 'N' as typcategory, false as typispreferred, false as typisdefined, ',' as typdelim, 0 as typrelid, 0 as typelem, 1007 as typarray, 'int4in' as typinput, 'int4out' as typoutput, 'int4recv' as typreceive, 'int4send' as typsend, '-' as typmodin, '-' as typmodout, '-' as typanalyze, 'i' as typalign, 'p' as typstorage, false as typnotnull, 0 as typbasetype, -1 as typtypmod, 0 as typndims, 0 as typcollation, null as typdefaultbin, null as typdefault, null as typacl union all\n"
+              + "  select 25 as oid, 'text' as typname, (select oid from pg_namespace where nspname='pg_catalog') as typnamespace, null as typowner, -1 as typlen, false as typbyval, 'b' as typtype, 'S' as typcategory, true as typispreferred, true as typisdefined, ',' as typdelim, 0 as typrelid, 0 as typelem, 1009 as typarray, 'textin' as typinput, 'textout' as typoutput, 'textrecv' as typreceive, 'textsend' as typsend, '-' as typmodin, '-' as typmodout, '-' as typanalyze, 'i' as typalign, 'x' as typstorage, false as typnotnull, 0 as typbasetype, -1 as typtypmod, 0 as typndims, 100 as typcollation, null as typdefaultbin, null as typdefault, null as typacl union all\n"
+              + "  select 700 as oid, 'float4' as typname, (select oid from pg_namespace where nspname='pg_catalog') as typnamespace, null as typowner, 4 as typlen, true as typbyval, 'b' as typtype, 'N' as typcategory, false as typispreferred, false as typisdefined, ',' as typdelim, 0 as typrelid, 0 as typelem, 1021 as typarray, 'float4in' as typinput, 'float4out' as typoutput, 'float4recv' as typreceive, 'float4send' as typsend, '-' as typmodin, '-' as typmodout, '-' as typanalyze, 'i' as typalign, 'p' as typstorage, false as typnotnull, 0 as typbasetype, -1 as typtypmod, 0 as typndims, 0 as typcollation, null as typdefaultbin, null as typdefault, null as typacl union all\n"
+              + "  select 701 as oid, 'float8' as typname, (select oid from pg_namespace where nspname='pg_catalog') as typnamespace, null as typowner, 8 as typlen, true as typbyval, 'b' as typtype, 'N' as typcategory, true as typispreferred, true as typisdefined, ',' as typdelim, 0 as typrelid, 0 as typelem, 1022 as typarray, 'float8in' as typinput, 'float8out' as typoutput, 'float8recv' as typreceive, 'float8send' as typsend, '-' as typmodin, '-' as typmodout, '-' as typanalyze, 'd' as typalign, 'p' as typstorage, false as typnotnull, 0 as typbasetype, -1 as typtypmod, 0 as typndims, 0 as typcollation, null as typdefaultbin, null as typdefault, null as typacl union all\n"
+              + "  select 1043 as oid, 'varchar' as typname, (select oid from pg_namespace where nspname='pg_catalog') as typnamespace, null as typowner, -1 as typlen, false as typbyval, 'b' as typtype, 'S' as typcategory, false as typispreferred, true as typisdefined, ',' as typdelim, 0 as typrelid, 0 as typelem, 1015 as typarray, 'varcharin' as typinput, 'varcharout' as typoutput, 'varcharrecv' as typreceive, 'varcharsend' as typsend, 'varchartypmodin' as typmodin, 'varchartypmodout' as typmodout, '-' as typanalyze, 'i' as typalign, 'x' as typstorage, false as typnotnull, 0 as typbasetype, -1 as typtypmod, 0 as typndims, 100 as typcollation, null as typdefaultbin, null as typdefault, null as typacl union all\n"
+              + "  select 1082 as oid, 'date' as typname, (select oid from pg_namespace where nspname='pg_catalog') as typnamespace, null as typowner, 4 as typlen, true as typbyval, 'b' as typtype, 'D' as typcategory, false as typispreferred, true as typisdefined, ',' as typdelim, 0 as typrelid, 0 as typelem, 1182 as typarray, 'date_in' as typinput, 'date_out' as typoutput, 'date_recv' as typreceive, 'date_send' as typsend, '-' as typmodin, '-' as typmodout, '-' as typanalyze, 'i' as typalign, 'p' as typstorage, false as typnotnull, 0 as typbasetype, -1 as typtypmod, 0 as typndims, 0 as typcollation, null as typdefaultbin, null as typdefault, null as typacl union all\n"
+              + "  select 1114 as oid, 'timestamp' as typname, (select oid from pg_namespace where nspname='pg_catalog') as typnamespace, null as typowner, 8 as typlen, true as typbyval, 'b' as typtype, 'D' as typcategory, false as typispreferred, false as typisdefined, ',' as typdelim, 0 as typrelid, 0 as typelem, 1115 as typarray, 'timestamp_in' as typinput, 'timestamp_out' as typoutput, 'timestamp_recv' as typreceive, 'timestamp_send' as typsend, 'timestamptypmodin' as typmodin, 'timestamptypmodout' as typmodout, '-' as typanalyze, 'd' as typalign, 'p' as typstorage, false as typnotnull, 0 as typbasetype, -1 as typtypmod, 0 as typndims, 0 as typcollation, null as typdefaultbin, null as typdefault, null as typacl union all\n"
+              + "  select 1184 as oid, 'timestamptz' as typname, (select oid from pg_namespace where nspname='pg_catalog') as typnamespace, null as typowner, 8 as typlen, true as typbyval, 'b' as typtype, 'D' as typcategory, true as typispreferred, true as typisdefined, ',' as typdelim, 0 as typrelid, 0 as typelem, 1185 as typarray, 'timestamptz_in' as typinput, 'timestamptz_out' as typoutput, 'timestamptz_recv' as typreceive, 'timestamptz_send' as typsend, 'timestamptztypmodin' as typmodin, 'timestamptztypmodout' as typmodout, '-' as typanalyze, 'd' as typalign, 'p' as typstorage, false as typnotnull, 0 as typbasetype, -1 as typtypmod, 0 as typndims, 0 as typcollation, null as typdefaultbin, null as typdefault, null as typacl union all\n"
+              + "  select 1700 as oid, 'numeric' as typname, (select oid from pg_namespace where nspname='pg_catalog') as typnamespace, null as typowner, -1 as typlen, false as typbyval, 'b' as typtype, 'N' as typcategory, false as typispreferred, true as typisdefined, ',' as typdelim, 0 as typrelid, 0 as typelem, 1231 as typarray, 'numeric_in' as typinput, 'numeric_out' as typoutput, 'numeric_recv' as typreceive, 'numeric_send' as typsend, 'numerictypmodin' as typmodin, 'numerictypmodout' as typmodout, '-' as typanalyze, 'i' as typalign, 'm' as typstorage, false as typnotnull, 0 as typbasetype, -1 as typtypmod, 0 as typndims, 0 as typcollation, null as typdefaultbin, null as typdefault, null as typacl union all\n"
+              + "  select 3802 as oid, 'jsonb' as typname, (select oid from pg_namespace where nspname='pg_catalog') as typnamespace, null as typowner, -1 as typlen, false as typbyval, 'b' as typtype, 'U' as typcategory, false as typispreferred, true as typisdefined, ',' as typdelim, 0 as typrelid, 0 as typelem, 3807 as typarray, 'jsonb_in' as typinput, 'jsonb_out' as typoutput, 'jsonb_recv' as typreceive, 'jsonb_send' as typsend, '-' as typmodin, '-' as typmodout, '-' as typanalyze, 'i' as typalign, 'x' as typstorage, false as typnotnull, 0 as typbasetype, -1 as typtypmod, 0 as typndims, 0 as typcollation, null as typdefaultbin, null as typdefault, null as typacl\n"
+              + ")\n"
+              + "SELECT pg_type.oid, typname   FROM pg_type   LEFT   JOIN (select ns.oid as nspoid, ns.nspname, r.r           from pg_namespace as ns           join ( select 1 as r, 'public' as nspname ) as r          using ( nspname )        ) as sp     ON sp.nspoid = typnamespace  WHERE typname = 'jsonb'  ORDER BY sp.r, pg_type.oid DESC LIMIT 1");
+
+  protected static final ResultSet SELECT_JSONB_TYPE_BY_NAME_RESULT_SET =
+      ResultSet.newBuilder()
+          .setMetadata(
+              ResultSetMetadata.newBuilder()
+                  .setRowType(
+                      StructType.newBuilder()
+                          .addFields(
+                              Field.newBuilder()
+                                  .setName("oid")
+                                  .setType(Type.newBuilder().setCode(TypeCode.INT64).build())
+                                  .build())
+                          .addFields(
+                              Field.newBuilder()
+                                  .setName("typname")
+                                  .setType(Type.newBuilder().setCode(TypeCode.STRING).build())
+                                  .build())
+                          .build())
+                  .build())
+          .addRows(
+              ListValue.newBuilder()
+                  .addValues(Value.newBuilder().setStringValue("3802").build())
+                  .addValues(Value.newBuilder().setStringValue("jsonb").build())
+                  .build())
+          .build();
+  protected static final Statement SELECT_JSONB_TYPE_INFO =
+      Statement.newBuilder(
+              "with pg_namespace as (\n"
+                  + "  select case schema_name when 'pg_catalog' then 11 when 'public' then 2200 else 0 end as oid,\n"
+                  + "        schema_name as nspname, null as nspowner, null as nspacl\n"
+                  + "  from information_schema.schemata\n"
+                  + "),\n"
+                  + "pg_type as (\n"
+                  + "  select 16 as oid, 'bool' as typname, (select oid from pg_namespace where nspname='pg_catalog') as typnamespace, null as typowner, 1 as typlen, true as typbyval, 'b' as typtype, 'B' as typcategory, true as typispreferred, true as typisdefined, ',' as typdelim, 0 as typrelid, 0 as typelem, 1000 as typarray, 'boolin' as typinput, 'boolout' as typoutput, 'boolrecv' as typreceive, 'boolsend' as typsend, '-' as typmodin, '-' as typmodout, '-' as typanalyze, 'c' as typalign, 'p' as typstorage, false as typnotnull, 0 as typbasetype, -1 as typtypmod, 0 as typndims, 0 as typcollation, null as typdefaultbin, null as typdefault, null as typacl union all\n"
+                  + "  select 17 as oid, 'bytea' as typname, (select oid from pg_namespace where nspname='pg_catalog') as typnamespace, null as typowner, -1 as typlen, false as typbyval, 'b' as typtype, 'U' as typcategory, false as typispreferred, true as typisdefined, ',' as typdelim, 0 as typrelid, 0 as typelem, 1001 as typarray, 'byteain' as typinput, 'byteaout' as typoutput, 'bytearecv' as typreceive, 'byteasend' as typsend, '-' as typmodin, '-' as typmodout, '-' as typanalyze, 'i' as typalign, 'x' as typstorage, false as typnotnull, 0 as typbasetype, -1 as typtypmod, 0 as typndims, 0 as typcollation, null as typdefaultbin, null as typdefault, null as typacl union all\n"
+                  + "  select 20 as oid, 'int8' as typname, (select oid from pg_namespace where nspname='pg_catalog') as typnamespace, null as typowner, 8 as typlen, true as typbyval, 'b' as typtype, 'N' as typcategory, false as typispreferred, true as typisdefined, ',' as typdelim, 0 as typrelid, 0 as typelem, 1016 as typarray, 'int8in' as typinput, 'int8out' as typoutput, 'int8recv' as typreceive, 'int8send' as typsend, '-' as typmodin, '-' as typmodout, '-' as typanalyze, 'd' as typalign, 'p' as typstorage, false as typnotnull, 0 as typbasetype, -1 as typtypmod, 0 as typndims, 0 as typcollation, null as typdefaultbin, null as typdefault, null as typacl union all\n"
+                  + "  select 21 as oid, 'int2' as typname, (select oid from pg_namespace where nspname='pg_catalog') as typnamespace, null as typowner, 2 as typlen, true as typbyval, 'b' as typtype, 'N' as typcategory, false as typispreferred, false as typisdefined, ',' as typdelim, 0 as typrelid, 0 as typelem, 1005 as typarray, 'int2in' as typinput, 'int2out' as typoutput, 'int2recv' as typreceive, 'int2send' as typsend, '-' as typmodin, '-' as typmodout, '-' as typanalyze, 's' as typalign, 'p' as typstorage, false as typnotnull, 0 as typbasetype, -1 as typtypmod, 0 as typndims, 0 as typcollation, null as typdefaultbin, null as typdefault, null as typacl union all\n"
+                  + "  select 23 as oid, 'int4' as typname, (select oid from pg_namespace where nspname='pg_catalog') as typnamespace, null as typowner, 4 as typlen, true as typbyval, 'b' as typtype, 'N' as typcategory, false as typispreferred, false as typisdefined, ',' as typdelim, 0 as typrelid, 0 as typelem, 1007 as typarray, 'int4in' as typinput, 'int4out' as typoutput, 'int4recv' as typreceive, 'int4send' as typsend, '-' as typmodin, '-' as typmodout, '-' as typanalyze, 'i' as typalign, 'p' as typstorage, false as typnotnull, 0 as typbasetype, -1 as typtypmod, 0 as typndims, 0 as typcollation, null as typdefaultbin, null as typdefault, null as typacl union all\n"
+                  + "  select 25 as oid, 'text' as typname, (select oid from pg_namespace where nspname='pg_catalog') as typnamespace, null as typowner, -1 as typlen, false as typbyval, 'b' as typtype, 'S' as typcategory, true as typispreferred, true as typisdefined, ',' as typdelim, 0 as typrelid, 0 as typelem, 1009 as typarray, 'textin' as typinput, 'textout' as typoutput, 'textrecv' as typreceive, 'textsend' as typsend, '-' as typmodin, '-' as typmodout, '-' as typanalyze, 'i' as typalign, 'x' as typstorage, false as typnotnull, 0 as typbasetype, -1 as typtypmod, 0 as typndims, 100 as typcollation, null as typdefaultbin, null as typdefault, null as typacl union all\n"
+                  + "  select 700 as oid, 'float4' as typname, (select oid from pg_namespace where nspname='pg_catalog') as typnamespace, null as typowner, 4 as typlen, true as typbyval, 'b' as typtype, 'N' as typcategory, false as typispreferred, false as typisdefined, ',' as typdelim, 0 as typrelid, 0 as typelem, 1021 as typarray, 'float4in' as typinput, 'float4out' as typoutput, 'float4recv' as typreceive, 'float4send' as typsend, '-' as typmodin, '-' as typmodout, '-' as typanalyze, 'i' as typalign, 'p' as typstorage, false as typnotnull, 0 as typbasetype, -1 as typtypmod, 0 as typndims, 0 as typcollation, null as typdefaultbin, null as typdefault, null as typacl union all\n"
+                  + "  select 701 as oid, 'float8' as typname, (select oid from pg_namespace where nspname='pg_catalog') as typnamespace, null as typowner, 8 as typlen, true as typbyval, 'b' as typtype, 'N' as typcategory, true as typispreferred, true as typisdefined, ',' as typdelim, 0 as typrelid, 0 as typelem, 1022 as typarray, 'float8in' as typinput, 'float8out' as typoutput, 'float8recv' as typreceive, 'float8send' as typsend, '-' as typmodin, '-' as typmodout, '-' as typanalyze, 'd' as typalign, 'p' as typstorage, false as typnotnull, 0 as typbasetype, -1 as typtypmod, 0 as typndims, 0 as typcollation, null as typdefaultbin, null as typdefault, null as typacl union all\n"
+                  + "  select 1043 as oid, 'varchar' as typname, (select oid from pg_namespace where nspname='pg_catalog') as typnamespace, null as typowner, -1 as typlen, false as typbyval, 'b' as typtype, 'S' as typcategory, false as typispreferred, true as typisdefined, ',' as typdelim, 0 as typrelid, 0 as typelem, 1015 as typarray, 'varcharin' as typinput, 'varcharout' as typoutput, 'varcharrecv' as typreceive, 'varcharsend' as typsend, 'varchartypmodin' as typmodin, 'varchartypmodout' as typmodout, '-' as typanalyze, 'i' as typalign, 'x' as typstorage, false as typnotnull, 0 as typbasetype, -1 as typtypmod, 0 as typndims, 100 as typcollation, null as typdefaultbin, null as typdefault, null as typacl union all\n"
+                  + "  select 1082 as oid, 'date' as typname, (select oid from pg_namespace where nspname='pg_catalog') as typnamespace, null as typowner, 4 as typlen, true as typbyval, 'b' as typtype, 'D' as typcategory, false as typispreferred, true as typisdefined, ',' as typdelim, 0 as typrelid, 0 as typelem, 1182 as typarray, 'date_in' as typinput, 'date_out' as typoutput, 'date_recv' as typreceive, 'date_send' as typsend, '-' as typmodin, '-' as typmodout, '-' as typanalyze, 'i' as typalign, 'p' as typstorage, false as typnotnull, 0 as typbasetype, -1 as typtypmod, 0 as typndims, 0 as typcollation, null as typdefaultbin, null as typdefault, null as typacl union all\n"
+                  + "  select 1114 as oid, 'timestamp' as typname, (select oid from pg_namespace where nspname='pg_catalog') as typnamespace, null as typowner, 8 as typlen, true as typbyval, 'b' as typtype, 'D' as typcategory, false as typispreferred, false as typisdefined, ',' as typdelim, 0 as typrelid, 0 as typelem, 1115 as typarray, 'timestamp_in' as typinput, 'timestamp_out' as typoutput, 'timestamp_recv' as typreceive, 'timestamp_send' as typsend, 'timestamptypmodin' as typmodin, 'timestamptypmodout' as typmodout, '-' as typanalyze, 'd' as typalign, 'p' as typstorage, false as typnotnull, 0 as typbasetype, -1 as typtypmod, 0 as typndims, 0 as typcollation, null as typdefaultbin, null as typdefault, null as typacl union all\n"
+                  + "  select 1184 as oid, 'timestamptz' as typname, (select oid from pg_namespace where nspname='pg_catalog') as typnamespace, null as typowner, 8 as typlen, true as typbyval, 'b' as typtype, 'D' as typcategory, true as typispreferred, true as typisdefined, ',' as typdelim, 0 as typrelid, 0 as typelem, 1185 as typarray, 'timestamptz_in' as typinput, 'timestamptz_out' as typoutput, 'timestamptz_recv' as typreceive, 'timestamptz_send' as typsend, 'timestamptztypmodin' as typmodin, 'timestamptztypmodout' as typmodout, '-' as typanalyze, 'd' as typalign, 'p' as typstorage, false as typnotnull, 0 as typbasetype, -1 as typtypmod, 0 as typndims, 0 as typcollation, null as typdefaultbin, null as typdefault, null as typacl union all\n"
+                  + "  select 1700 as oid, 'numeric' as typname, (select oid from pg_namespace where nspname='pg_catalog') as typnamespace, null as typowner, -1 as typlen, false as typbyval, 'b' as typtype, 'N' as typcategory, false as typispreferred, true as typisdefined, ',' as typdelim, 0 as typrelid, 0 as typelem, 1231 as typarray, 'numeric_in' as typinput, 'numeric_out' as typoutput, 'numeric_recv' as typreceive, 'numeric_send' as typsend, 'numerictypmodin' as typmodin, 'numerictypmodout' as typmodout, '-' as typanalyze, 'i' as typalign, 'm' as typstorage, false as typnotnull, 0 as typbasetype, -1 as typtypmod, 0 as typndims, 0 as typcollation, null as typdefaultbin, null as typdefault, null as typacl union all\n"
+                  + "  select 3802 as oid, 'jsonb' as typname, (select oid from pg_namespace where nspname='pg_catalog') as typnamespace, null as typowner, -1 as typlen, false as typbyval, 'b' as typtype, 'U' as typcategory, false as typispreferred, true as typisdefined, ',' as typdelim, 0 as typrelid, 0 as typelem, 3807 as typarray, 'jsonb_in' as typinput, 'jsonb_out' as typoutput, 'jsonb_recv' as typreceive, 'jsonb_send' as typsend, '-' as typmodin, '-' as typmodout, '-' as typanalyze, 'i' as typalign, 'x' as typstorage, false as typnotnull, 0 as typbasetype, -1 as typtypmod, 0 as typndims, 0 as typcollation, null as typdefaultbin, null as typdefault, null as typacl\n"
+                  + ")\n"
+                  + "SELECT n.nspname = 'public', n.nspname, t.typname FROM pg_type t JOIN pg_namespace n ON t.typnamespace = n.oid WHERE t.oid = $1")
+          .bind("p1")
+          .to(Oid.JSONB)
+          .build();
+  protected static final ResultSet SELECT_JSONB_TYPE_INFO_RESULT_SET =
+      ResultSet.newBuilder()
+          .setMetadata(
+              ResultSetMetadata.newBuilder()
+                  .setRowType(
+                      StructType.newBuilder()
+                          .addFields(
+                              Field.newBuilder()
+                                  .setName("")
+                                  .setType(Type.newBuilder().setCode(TypeCode.BOOL).build())
+                                  .build())
+                          .addFields(
+                              Field.newBuilder()
+                                  .setName("nspname")
+                                  .setType(Type.newBuilder().setCode(TypeCode.STRING).build())
+                                  .build())
+                          .addFields(
+                              Field.newBuilder()
+                                  .setName("typname")
+                                  .setType(Type.newBuilder().setCode(TypeCode.STRING).build())
+                                  .build())
+                          .build())
+                  .build())
+          .addRows(
+              ListValue.newBuilder()
+                  .addValues(Value.newBuilder().setBoolValue(true).build())
+                  .addValues(Value.newBuilder().setStringValue("public").build())
+                  .addValues(Value.newBuilder().setStringValue("jsonb").build())
+                  .build())
+          .build();
+
   protected static final Statement SELECT1 = Statement.of("SELECT 1");
   protected static final Statement SELECT2 = Statement.of("SELECT 2");
   protected static final Statement SELECT_FIVE_ROWS =
@@ -359,6 +559,13 @@ public abstract class AbstractMockServerTest {
         new MockSpannerServiceImpl(), defaultDatabase, extraPGAdapterOptions);
   }
 
+  public static PGobject createJdbcPgJsonbObject(String value) throws SQLException {
+    PGobject result = new PGobject();
+    result.setValue(value);
+    result.setType("jsonb");
+    return result;
+  }
+
   protected static void doStartMockSpannerAndPgAdapterServers(
       MockSpannerServiceImpl mockSpannerService,
       String defaultDatabase,
@@ -366,6 +573,15 @@ public abstract class AbstractMockServerTest {
       throws Exception {
     mockSpanner = mockSpannerService;
     mockSpanner.setAbortProbability(0.0D); // We don't want any unpredictable aborted transactions.
+    mockSpanner.putStatementResult(
+        StatementResult.query(SELECT_JSONB_TYPE_BY_OID, SELECT_JSONB_TYPE_BY_OID_RESULT_SET));
+    mockSpanner.putStatementResult(
+        StatementResult.query(SELECT_JSONB_TYPE_BY_NAME, SELECT_JSONB_TYPE_BY_NAME_RESULT_SET));
+    mockSpanner.putStatementResult(
+        StatementResult.query(
+            SELECT_JSONB_TYPE_BY_NAME_SIMPLE_PROTOCOL, SELECT_JSONB_TYPE_BY_NAME_RESULT_SET));
+    mockSpannerService.putStatementResult(
+        StatementResult.query(SELECT_JSONB_TYPE_INFO, SELECT_JSONB_TYPE_INFO_RESULT_SET));
     mockSpanner.putStatementResult(StatementResult.query(SELECT1, SELECT1_RESULTSET));
     mockSpanner.putStatementResult(StatementResult.query(SELECT2, SELECT2_RESULTSET));
     mockSpanner.putStatementResult(
diff --git a/src/test/java/com/google/cloud/spanner/pgadapter/CopyInMockServerTest.java b/src/test/java/com/google/cloud/spanner/pgadapter/CopyInMockServerTest.java
index 433aa7e7..03f7a7b2 100644
--- a/src/test/java/com/google/cloud/spanner/pgadapter/CopyInMockServerTest.java
+++ b/src/test/java/com/google/cloud/spanner/pgadapter/CopyInMockServerTest.java
@@ -1428,13 +1428,13 @@ public class CopyInMockServerTest extends AbstractMockServerTest {
             + "           6.626::numeric as col_numeric,\n"
             + "           '2022-07-07 08:16:48.123456+02:00'::timestamptz as col_timestamptz,\n"
             + "           '2022-07-07'::date as col_date, 'hello world'::varchar as col_varchar,\n"
-            + "           '{\\\"key\\\": \\\"value\\\"}'::varchar as col_jsonb"
+            + "           '{\\\"key\\\": \\\"value\\\"}'::jsonb as col_jsonb"
             + "    union all\n"
             + "    select null::bigint as col_bigint, null::bool as col_bool,\n"
             + "           null::bytea as col_bytea, null::float8 as col_float8,\n"
             + "           null::bigint as col_int, null::numeric as col_numeric,"
             + "           null::timestamptz as col_timestamptz, null::date as col_date,"
-            + "           null::varchar as col_varchar, null::varchar as col_jsonb\n"
+            + "           null::varchar as col_varchar, null::jsonb as col_jsonb\n"
             + "  ) to stdout binary\" "
             + "  | psql "
             + " -h "
diff --git a/src/test/java/com/google/cloud/spanner/pgadapter/ITJdbcDescribeStatementTest.java b/src/test/java/com/google/cloud/spanner/pgadapter/ITJdbcDescribeStatementTest.java
index a347bf26..562e223a 100644
--- a/src/test/java/com/google/cloud/spanner/pgadapter/ITJdbcDescribeStatementTest.java
+++ b/src/test/java/com/google/cloud/spanner/pgadapter/ITJdbcDescribeStatementTest.java
@@ -159,7 +159,7 @@ public class ITJdbcDescribeStatementTest implements IntegrationTest {
               + "and col_timestamptz=? "
               + "and col_date=? "
               + "and col_varchar=? "
-              + "and col_jsonb=?",
+              + "and col_jsonb::text=?",
           "insert into all_types "
               + "(col_bigint, col_bool, col_bytea, col_float8, col_int, col_numeric, col_timestamptz, col_date, col_varchar, col_jsonb) "
               + "values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
@@ -176,7 +176,7 @@ public class ITJdbcDescribeStatementTest implements IntegrationTest {
               + "and col_timestamptz=? "
               + "and col_date=? "
               + "and col_varchar=? "
-              + "and col_jsonb=?",
+              + "and col_jsonb::text=?",
           "insert into all_types " + "values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
           "insert into all_types "
               + "select col_bigint, col_bool, col_bytea, col_float8, col_int, col_numeric, col_timestamptz, col_date, col_varchar, col_jsonb "
@@ -190,7 +190,7 @@ public class ITJdbcDescribeStatementTest implements IntegrationTest {
               + "and col_timestamptz=? "
               + "and col_date=? "
               + "and col_varchar=? "
-              + "and col_jsonb=?",
+              + "and col_jsonb::text=?",
           "update all_types set "
               + "col_bool=?, "
               + "col_bytea=?, "
@@ -220,7 +220,7 @@ public class ITJdbcDescribeStatementTest implements IntegrationTest {
               + "and col_timestamptz=? "
               + "and col_date=? "
               + "and col_varchar=? "
-              + "and col_jsonb=?",
+              + "and col_jsonb::text=?",
           "delete "
               + "from all_types "
               + "where col_bigint=? "
@@ -232,7 +232,7 @@ public class ITJdbcDescribeStatementTest implements IntegrationTest {
               + "and col_timestamptz=? "
               + "and col_date=? "
               + "and col_varchar=? "
-              + "and col_jsonb=?"
+              + "and col_jsonb::text=?"
         }) {
       try (Connection connection = DriverManager.getConnection(getConnectionUrl())) {
         try (PreparedStatement statement = connection.prepareStatement(sql)) {
@@ -258,7 +258,16 @@ public class ITJdbcDescribeStatementTest implements IntegrationTest {
           assertEquals(sql, Types.TIMESTAMP, metadata.getParameterType(++index));
           assertEquals(sql, Types.DATE, metadata.getParameterType(++index));
           assertEquals(sql, Types.VARCHAR, metadata.getParameterType(++index));
-          assertEquals(sql, Types.VARCHAR, metadata.getParameterType(++index));
+          // jsonb does not support the '=' operator, which means that when a jsonb parameter is
+          // used for comparison, we must cast it to text. That changes the parameter type to
+          // Types.VARCHAR.
+          if (sql.contains("col_jsonb::text=?")) {
+            assertEquals(sql, Types.VARCHAR, metadata.getParameterType(++index));
+          } else {
+            assertEquals(sql, Types.OTHER, metadata.getParameterType(++index));
+          }
+        } catch (SQLException e) {
+          throw new SQLException("Error for statement: " + sql, e);
         }
       }
     }
diff --git a/src/test/java/com/google/cloud/spanner/pgadapter/ITJdbcMetadataTest.java b/src/test/java/com/google/cloud/spanner/pgadapter/ITJdbcMetadataTest.java
index 43912c46..dc147388 100644
--- a/src/test/java/com/google/cloud/spanner/pgadapter/ITJdbcMetadataTest.java
+++ b/src/test/java/com/google/cloud/spanner/pgadapter/ITJdbcMetadataTest.java
@@ -428,9 +428,8 @@ public class ITJdbcMetadataTest implements IntegrationTest {
 
               assertTrue(columns.next());
               assertEquals("col_jsonb", columns.getString("COLUMN_NAME"));
-              // TODO: Change to jsonb when available.
-              assertEquals(Types.VARCHAR, columns.getInt("DATA_TYPE"));
-              assertEquals("varchar", columns.getString("TYPE_NAME"));
+              assertEquals(Types.OTHER, columns.getInt("DATA_TYPE"));
+              assertEquals("\"pg_catalog\".\"jsonb\"", columns.getString("TYPE_NAME"));
 
               assertFalse(columns.next());
             }
@@ -758,6 +757,8 @@ public class ITJdbcMetadataTest implements IntegrationTest {
             assertEquals(Types.DATE, results.get("date").intValue());
             assertTrue(results.containsKey("varchar"));
             assertEquals(Types.VARCHAR, results.get("varchar").intValue());
+            assertTrue(results.containsKey("jsonb"));
+            assertEquals(Types.OTHER, results.get("jsonb").intValue());
           } catch (SQLException e) {
             throw SpannerExceptionFactory.asSpannerException(e);
           }
diff --git a/src/test/java/com/google/cloud/spanner/pgadapter/ITJdbcTest.java b/src/test/java/com/google/cloud/spanner/pgadapter/ITJdbcTest.java
index e371a16e..e4794fd9 100644
--- a/src/test/java/com/google/cloud/spanner/pgadapter/ITJdbcTest.java
+++ b/src/test/java/com/google/cloud/spanner/pgadapter/ITJdbcTest.java
@@ -28,6 +28,7 @@ import com.google.cloud.Timestamp;
 import com.google.cloud.spanner.Database;
 import com.google.cloud.spanner.KeySet;
 import com.google.cloud.spanner.Mutation;
+import com.google.cloud.spanner.Value;
 import com.google.cloud.spanner.pgadapter.metadata.OptionsMetadata;
 import java.io.FileInputStream;
 import java.io.IOException;
@@ -57,6 +58,7 @@ import org.junit.runners.Parameterized.Parameters;
 import org.postgresql.PGConnection;
 import org.postgresql.copy.CopyManager;
 import org.postgresql.core.Oid;
+import org.postgresql.util.PGobject;
 
 @Category(IntegrationTest.class)
 @RunWith(Parameterized.class)
@@ -216,7 +218,7 @@ public class ITJdbcTest implements IntegrationTest {
             + "and col_timestamptz=? "
             + "and col_date=? "
             + "and col_varchar=? "
-            + "and col_jsonb=?";
+            + "and col_jsonb::text=?::text";
 
     try (Connection connection = DriverManager.getConnection(getConnectionUrl())) {
       try (PreparedStatement statement = connection.prepareStatement(sql)) {
@@ -289,7 +291,7 @@ public class ITJdbcTest implements IntegrationTest {
             ++index, Timestamp.parseTimestamp("2022-02-11T13:45:00.123456+01:00").toSqlTimestamp());
         statement.setObject(++index, LocalDate.parse("2000-02-29"));
         statement.setString(++index, "string_test");
-        statement.setString(++index, "{\"key1\": \"value1\", \"key2\": \"value2\"}");
+        statement.setObject(++index, "{\"key1\": \"value1\", \"key2\": \"value2\"}", Types.OTHER);
 
         assertEquals(1, statement.executeUpdate());
       }
@@ -356,7 +358,10 @@ public class ITJdbcTest implements IntegrationTest {
             Timestamp.parseTimestamp("2022-02-11T14:04:59.123456789+01:00").toSqlTimestamp());
         statement.setObject(++index, LocalDate.of(2000, 1, 1));
         statement.setString(++index, "updated");
-        statement.setString(++index, "{\"key1\": \"updated1\", \"key2\": \"updated2\"}");
+        PGobject jsonbObject = new PGobject();
+        jsonbObject.setType("jsonb");
+        jsonbObject.setValue("{\"key1\": \"updated1\", \"key2\": \"updated2\"}");
+        statement.setObject(++index, jsonbObject);
         statement.setLong(++index, 1);
 
         assertEquals(1, statement.executeUpdate());
@@ -411,7 +416,7 @@ public class ITJdbcTest implements IntegrationTest {
         statement.setNull(++index, Types.TIMESTAMP_WITH_TIMEZONE);
         statement.setNull(++index, Types.DATE);
         statement.setNull(++index, Types.VARCHAR);
-        statement.setNull(++index, Types.VARCHAR);
+        statement.setNull(++index, Types.OTHER);
 
         assertEquals(1, statement.executeUpdate());
       }
@@ -926,7 +931,7 @@ public class ITJdbcTest implements IntegrationTest {
                 .set("col_varchar")
                 .to("bar")
                 .set("col_jsonb")
-                .to("{\"key\": \"value2\"}")
+                .to(Value.pgJsonb("{\"key\": \"value2\"}"))
                 .build(),
             Mutation.newInsertBuilder("all_types")
                 .set("col_bigint")
@@ -948,7 +953,7 @@ public class ITJdbcTest implements IntegrationTest {
                 .set("col_varchar")
                 .to((String) null)
                 .set("col_jsonb")
-                .to((String) null)
+                .to(Value.pgJsonb(null))
                 .build(),
             Mutation.newInsertBuilder("all_types")
                 .set("col_bigint")
@@ -970,7 +975,7 @@ public class ITJdbcTest implements IntegrationTest {
                 .set("col_varchar")
                 .to("")
                 .set("col_jsonb")
-                .to("[]")
+                .to(Value.pgJsonb("[]"))
                 .build(),
             Mutation.newInsertBuilder("all_types")
                 .set("col_bigint")
@@ -992,7 +997,7 @@ public class ITJdbcTest implements IntegrationTest {
                 .set("col_varchar")
                 .to("")
                 .set("col_jsonb")
-                .to("{}")
+                .to(Value.pgJsonb("{}"))
                 .build()));
   }
 }
diff --git a/src/test/java/com/google/cloud/spanner/pgadapter/ITPsqlTest.java b/src/test/java/com/google/cloud/spanner/pgadapter/ITPsqlTest.java
index 56f25f52..59bddc2f 100644
--- a/src/test/java/com/google/cloud/spanner/pgadapter/ITPsqlTest.java
+++ b/src/test/java/com/google/cloud/spanner/pgadapter/ITPsqlTest.java
@@ -354,7 +354,7 @@ public class ITPsqlTest implements IntegrationTest {
                     + "and col_timestamptz=$7 "
                     + "and col_date=$8 "
                     + "and col_varchar=$9 "
-                    + "and col_jsonb=$10;\n",
+                    + "and col_jsonb::text=$10::text;\n",
                 "execute find_row (1, true, '\\xaabbcc', 3.14, 100, 6.626, "
                     + "'2022-09-06 17:14:49+02', '2022-09-06', 'hello world', '{\"key\": \"value\"}');\n",
                 "execute insert_row (1, true, '\\xaabbcc', 3.14, 100, 6.626, "
@@ -592,7 +592,7 @@ public class ITPsqlTest implements IntegrationTest {
             + "  random()<0.5, md5(random()::text || clock_timestamp()::text)::bytea, random()*123456789, "
             + "  (random()*999999)::int, (random()*999999999999)::numeric, now()-random()*interval '250 year', "
             + "  (current_date-random()*interval '400 year')::date, md5(random()::text || clock_timestamp()::text)::varchar,"
-            + "  ('{\\\"key\\\": \\\"' || md5(random()::text || clock_timestamp()::text)::varchar || '\\\"}')::json "
+            + "  ('{\\\"key\\\": \\\"' || md5(random()::text || clock_timestamp()::text)::varchar || '\\\"}')::jsonb "
             + String.format("  from generate_series(1, %d) s(i)) to stdout\" ", numRows)
             + "  | psql "
             + " -h "
@@ -606,7 +606,13 @@ public class ITPsqlTest implements IntegrationTest {
             + " -c \"copy all_types from stdin;\"\n");
     setPgPassword(builder);
     Process process = builder.start();
+    StringBuilder errors = new StringBuilder();
+    try (Scanner scanner = new Scanner(process.getErrorStream())) {
+      while (scanner.hasNextLine()) {
+        errors.append(scanner.nextLine()).append("\n");
+      }
+    }
     int res = process.waitFor();
-    assertEquals(0, res);
+    assertEquals(errors.toString(), 0, res);
   }
 }
diff --git a/src/test/java/com/google/cloud/spanner/pgadapter/JdbcMockServerTest.java b/src/test/java/com/google/cloud/spanner/pgadapter/JdbcMockServerTest.java
index 821cc556..20767cfe 100644
--- a/src/test/java/com/google/cloud/spanner/pgadapter/JdbcMockServerTest.java
+++ b/src/test/java/com/google/cloud/spanner/pgadapter/JdbcMockServerTest.java
@@ -512,12 +512,22 @@ public class JdbcMockServerTest extends AbstractMockServerTest {
             assertEquals(LocalDate.of(2022, 3, 29), resultSet.getObject(++index, LocalDate.class));
             assertEquals("test", resultSet.getString(++index));
             assertEquals("{\"key\": \"value\"}", resultSet.getString(++index));
+
+            for (int col = 1; col <= resultSet.getMetaData().getColumnCount(); col++) {
+              assertNotNull(resultSet.getObject(col));
+            }
+
             assertFalse(resultSet.next());
           }
         }
       }
 
-      List<ExecuteSqlRequest> requests = mockSpanner.getRequestsOfType(ExecuteSqlRequest.class);
+      List<ExecuteSqlRequest> requests =
+          mockSpanner.getRequests().stream()
+              .filter(request -> request instanceof ExecuteSqlRequest)
+              .map(request -> (ExecuteSqlRequest) request)
+              .filter(request -> request.getSql().equals(pgSql))
+              .collect(Collectors.toList());
       // Prepare threshold less than 0 means use binary transfer + DESCRIBE statement.
       assertEquals(preparedThreshold < 0 ? 2 : 1, requests.size());
 
@@ -1756,7 +1766,9 @@ public class JdbcMockServerTest extends AbstractMockServerTest {
                 .bind("p9")
                 .to("test")
                 .bind("p10")
-                .to("{\"key\": \"value\"}")
+                // TODO: Change to jsonb when https://github.com/googleapis/java-spanner/pull/2182
+                //       has been merged.
+                .to(com.google.cloud.spanner.Value.json("{\"key\": \"value\"}"))
                 .build(),
             com.google.spanner.v1.ResultSet.newBuilder()
                 .setMetadata(ALL_TYPES_METADATA)
@@ -1779,8 +1791,8 @@ public class JdbcMockServerTest extends AbstractMockServerTest {
         assertEquals(Types.TIMESTAMP, parameterMetaData.getParameterType(7));
         assertEquals(Types.DATE, parameterMetaData.getParameterType(8));
         assertEquals(Types.VARCHAR, parameterMetaData.getParameterType(9));
-        // TODO: Enable when support for JSONB has been enabled.
-        // assertEquals(Types.OTHER, parameterMetaData.getParameterType(10));
+        assertEquals(Types.OTHER, parameterMetaData.getParameterType(10));
+
         ResultSetMetaData metadata = statement.getMetaData();
         assertEquals(10, metadata.getColumnCount());
         assertEquals(Types.BIGINT, metadata.getColumnType(1));
@@ -1792,8 +1804,7 @@ public class JdbcMockServerTest extends AbstractMockServerTest {
         assertEquals(Types.TIMESTAMP, metadata.getColumnType(7));
         assertEquals(Types.DATE, metadata.getColumnType(8));
         assertEquals(Types.VARCHAR, metadata.getColumnType(9));
-        // TODO: Enable when support for JSONB has been enabled.
-        // assertEquals(Types.OTHER, metadata.getColumnType(10));
+        assertEquals(Types.OTHER, metadata.getColumnType(10));
 
         int index = 0;
         statement.setLong(++index, 1L);
@@ -1805,7 +1816,7 @@ public class JdbcMockServerTest extends AbstractMockServerTest {
         statement.setObject(++index, zonedDateTime);
         statement.setObject(++index, LocalDate.of(2022, 3, 29));
         statement.setString(++index, "test");
-        statement.setString(++index, "{\"key\": \"value\"}");
+        statement.setObject(++index, createJdbcPgJsonbObject("{\"key\": \"value\"}"));
 
         try (ResultSet resultSet = statement.executeQuery()) {
           assertTrue(resultSet.next());
diff --git a/src/test/java/com/google/cloud/spanner/pgadapter/JdbcSimpleModeMockServerTest.java b/src/test/java/com/google/cloud/spanner/pgadapter/JdbcSimpleModeMockServerTest.java
index ecfe42a4..14233eb1 100644
--- a/src/test/java/com/google/cloud/spanner/pgadapter/JdbcSimpleModeMockServerTest.java
+++ b/src/test/java/com/google/cloud/spanner/pgadapter/JdbcSimpleModeMockServerTest.java
@@ -370,23 +370,25 @@ public class JdbcSimpleModeMockServerTest extends AbstractMockServerTest {
             .timeToString(java.sql.Timestamp.from(Instant.from(zonedDateTime)), true);
 
     String pgSql =
-        "select col_bigint, col_bool, col_bytea, col_float8, col_numeric, col_timestamptz, col_varchar "
+        "select col_bigint, col_bool, col_bytea, col_float8, col_numeric, col_timestamptz, col_varchar, col_jsonb "
             + "from all_types "
             + "where col_bigint=1 "
             + "and col_bool='TRUE' "
             + "and col_float8=3.14 "
             + "and col_numeric=6.626 "
             + String.format("and col_timestamptz='%s' ", timestampString)
-            + "and col_varchar='test'";
+            + "and col_varchar='test' "
+            + "and col_jsonb='{\"key\": \"value\"}'";
     String jdbcSql =
-        "select col_bigint, col_bool, col_bytea, col_float8, col_numeric, col_timestamptz, col_varchar "
+        "select col_bigint, col_bool, col_bytea, col_float8, col_numeric, col_timestamptz, col_varchar, col_jsonb "
             + "from all_types "
             + "where col_bigint=? "
             + "and col_bool=? "
             + "and col_float8=? "
             + "and col_numeric=? "
             + "and col_timestamptz=? "
-            + "and col_varchar=?";
+            + "and col_varchar=? "
+            + "and col_jsonb=?";
     mockSpanner.putStatementResult(
         StatementResult.query(com.google.cloud.spanner.Statement.of(pgSql), ALL_TYPES_RESULTSET));
 
@@ -400,6 +402,7 @@ public class JdbcSimpleModeMockServerTest extends AbstractMockServerTest {
         preparedStatement.setTimestamp(
             ++index, java.sql.Timestamp.from(Instant.from(zonedDateTime)));
         preparedStatement.setString(++index, "test");
+        preparedStatement.setObject(++index, createJdbcPgJsonbObject("{\"key\": \"value\"}"));
         try (ResultSet resultSet = preparedStatement.executeQuery()) {
           assertTrue(resultSet.next());
           assertEquals(1L, resultSet.getLong(1));
@@ -409,8 +412,13 @@ public class JdbcSimpleModeMockServerTest extends AbstractMockServerTest {
     }
 
     // The statement is sent only once to the mock server in simple query mode.
-    assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class));
-    ExecuteSqlRequest request = mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0);
+    // But as the statement uses a JSONB parameter, the JDBC driver will execute a query to verify
+    // that the type is available.
+    assertEquals(2, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class));
+    ExecuteSqlRequest jsonbRequest = mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0);
+    assertEquals(jsonbRequest.getSql(), SELECT_JSONB_TYPE_BY_NAME_SIMPLE_PROTOCOL.getSql());
+
+    ExecuteSqlRequest request = mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(1);
     assertEquals(QueryMode.NORMAL, request.getQueryMode());
     assertEquals(pgSql, request.getSql());
     assertTrue(request.getTransaction().hasSingleUse());
diff --git a/src/test/java/com/google/cloud/spanner/pgadapter/PgAdapterTestEnv.java b/src/test/java/com/google/cloud/spanner/pgadapter/PgAdapterTestEnv.java
index ae1999bb..bdd77dbe 100644
--- a/src/test/java/com/google/cloud/spanner/pgadapter/PgAdapterTestEnv.java
+++ b/src/test/java/com/google/cloud/spanner/pgadapter/PgAdapterTestEnv.java
@@ -121,7 +121,7 @@ public class PgAdapterTestEnv {
               + "col_timestamptz timestamptz, "
               + "col_date date, "
               + "col_varchar varchar(100), "
-              + "col_jsonb text)");
+              + "col_jsonb jsonb)");
 
   // The project Id. This can be overwritten.
   private String projectId;
diff --git a/src/test/java/com/google/cloud/spanner/pgadapter/golang/PgxMockServerTest.java b/src/test/java/com/google/cloud/spanner/pgadapter/golang/PgxMockServerTest.java
index 410fd207..a2b62975 100644
--- a/src/test/java/com/google/cloud/spanner/pgadapter/golang/PgxMockServerTest.java
+++ b/src/test/java/com/google/cloud/spanner/pgadapter/golang/PgxMockServerTest.java
@@ -1068,7 +1068,7 @@ public class PgxMockServerTest extends AbstractMockServerTest {
                             TypeCode.TIMESTAMP,
                             TypeCode.DATE,
                             TypeCode.STRING,
-                            TypeCode.STRING)))
+                            TypeCode.JSON)))
                 .build()));
 
     String res = pgxTest.TestCopyIn(createConnString());
diff --git a/src/test/java/com/google/cloud/spanner/pgadapter/nodejs/NodePostgresMockServerTest.java b/src/test/java/com/google/cloud/spanner/pgadapter/nodejs/NodePostgresMockServerTest.java
index dcfafbec..0478148e 100644
--- a/src/test/java/com/google/cloud/spanner/pgadapter/nodejs/NodePostgresMockServerTest.java
+++ b/src/test/java/com/google/cloud/spanner/pgadapter/nodejs/NodePostgresMockServerTest.java
@@ -259,7 +259,9 @@ public class NodePostgresMockServerTest extends AbstractMockServerTest {
                 .bind("p9")
                 .to("some-random-string")
                 .bind("p10")
-                .to("{\"my_key\":\"my-value\"}")
+                // TODO: Change to jsonb when https://github.com/googleapis/java-spanner/pull/2182
+                //       has been merged.
+                .to(Value.json("{\"my_key\":\"my-value\"}"))
                 .build(),
             1L);
     mockSpanner.putStatementResult(updateResult);
@@ -384,7 +386,9 @@ public class NodePostgresMockServerTest extends AbstractMockServerTest {
                 .bind("p9")
                 .to("some-random-string")
                 .bind("p10")
-                .to("{\"my_key\":\"my-value\"}")
+                // TODO: Change to jsonb when https://github.com/googleapis/java-spanner/pull/2182
+                //       has been merged.
+                .to(Value.json("{\"my_key\":\"my-value\"}"))
                 .build(),
             1L);
     mockSpanner.putStatementResult(updateResult);
@@ -412,7 +416,9 @@ public class NodePostgresMockServerTest extends AbstractMockServerTest {
                 .bind("p9")
                 .to((String) null)
                 .bind("p10")
-                .to((String) null)
+                // TODO: Change to jsonb when https://github.com/googleapis/java-spanner/pull/2182
+                //       has been merged.
+                .to(Value.json(null))
                 .build(),
             1L));
 
diff --git a/src/test/java/com/google/cloud/spanner/pgadapter/nodejs/TypeORMMockServerTest.java b/src/test/java/com/google/cloud/spanner/pgadapter/nodejs/TypeORMMockServerTest.java
index 93e24140..a0f57da1 100644
--- a/src/test/java/com/google/cloud/spanner/pgadapter/nodejs/TypeORMMockServerTest.java
+++ b/src/test/java/com/google/cloud/spanner/pgadapter/nodejs/TypeORMMockServerTest.java
@@ -727,9 +727,10 @@ public class TypeORMMockServerTest extends AbstractMockServerTest {
                 .to(Date.parseDate("2022-07-22"))
                 .bind("p9")
                 .to("some random string")
-                // TODO: Change to JSONB
                 .bind("p10")
-                .to("{\"key\":\"value\"}")
+                // TODO: Change to jsonb when https://github.com/googleapis/java-spanner/pull/2182
+                //       has been merged.
+                .to(com.google.cloud.spanner.Value.json("{\"key\":\"value\"}"))
                 .build(),
             1L));