Repository: GoogleCloudPlatform/pgadapter
Pull request #2229 (2024-08-26 09:26:24)

feat: support all 'spanner.*' options in pg_settings
Re-writes the pg_settings common table expression to use an array of jsonb instead of a list of UNION ALL statements. This circumvents the limitation that a query cannot contain more than 60 UNION ALLs, which means that we can put a larger value for the limitation on the number of settings included in the CTE. We still restrict the number of elements in the CTE to prevent the query text from becoming too long.


Patch:
diff --git a/.github/workflows/snippets.yaml b/.github/workflows/snippets.yaml
index 871c46dd..bb118436 100644
--- a/.github/workflows/snippets.yaml
+++ b/.github/workflows/snippets.yaml
@@ -80,3 +80,18 @@ jobs:
       - name: Run dotnet snippets
         working-directory: ./samples/snippets/dotnet-snippets
         run: dotnet test
+  php-snippets:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v4
+      - uses: shivammathur/setup-php@v2
+        with:
+          php-version: '8.3'
+          tools: composer
+      - run: php --version
+      - name: Install dependencies
+        working-directory: ./samples/snippets/php-snippets
+        run: composer install
+      - name: Run PHP snippets
+        working-directory: ./samples/snippets/php-snippets/test
+        run: ../vendor/bin/phpunit SamplesTest.php
diff --git a/.gitignore b/.gitignore
index ec2e7eaf..e9bc04d3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -37,5 +37,6 @@ samples/**/ruby/**/Gemfile.lock
 
 samples/**/vendor
 samples/**/composer.lock
+samples/**/.phpunit.result.cache
 src/test/**/vendor
 src/test/**/composer.lock
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e1db6aa9..5aa039df 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,36 @@
 # Changelog
 
+## [0.42.3](https://github.com/GoogleCloudPlatform/pgadapter/compare/v0.42.2...v0.42.3) (2025-01-18)
+
+
+### Dependencies
+
+* update alpine docker tag to v3.21.1 ([#2704](https://github.com/GoogleCloudPlatform/pgadapter/issues/2704)) ([4d2510b](https://github.com/GoogleCloudPlatform/pgadapter/commit/4d2510b15cdcc989eb0bc447530004d59a44617f))
+* update alpine docker tag to v3.21.2 ([#2722](https://github.com/GoogleCloudPlatform/pgadapter/issues/2722)) ([536413c](https://github.com/GoogleCloudPlatform/pgadapter/commit/536413cda6b1f253ee36f1da39765c74dffe2a17))
+* update dependency django to v5.1.5 [security] ([#2755](https://github.com/GoogleCloudPlatform/pgadapter/issues/2755)) ([9dc5ece](https://github.com/GoogleCloudPlatform/pgadapter/commit/9dc5ecec0ebdc25349115915658a883921c0c520))
+* update dependency go to v1.23.5 ([#2771](https://github.com/GoogleCloudPlatform/pgadapter/issues/2771)) ([1bf2007](https://github.com/GoogleCloudPlatform/pgadapter/commit/1bf20076a8dafdac351537cfd945a9bba5ddcefd))
+* update dependency io.opentelemetry:opentelemetry-bom to v1.46.0 ([#2739](https://github.com/GoogleCloudPlatform/pgadapter/issues/2739)) ([267c53e](https://github.com/GoogleCloudPlatform/pgadapter/commit/267c53e4b54f961be9aaa032c221c49f371b6988))
+* update dependency nunit.analyzers to 4.6.0 ([#2729](https://github.com/GoogleCloudPlatform/pgadapter/issues/2729)) ([402bf2d](https://github.com/GoogleCloudPlatform/pgadapter/commit/402bf2da33f78185e066e97ca192ae4cbac4c288))
+* update dependency org.apache.commons:commons-csv to v1.13.0 ([#2738](https://github.com/GoogleCloudPlatform/pgadapter/issues/2738)) ([3039967](https://github.com/GoogleCloudPlatform/pgadapter/commit/3039967f7281f91d5c2d29738ab5350314cbef12))
+* update dependency org.liquibase:liquibase-maven-plugin to v4.31.0 ([#2775](https://github.com/GoogleCloudPlatform/pgadapter/issues/2775)) ([9e5f7ad](https://github.com/GoogleCloudPlatform/pgadapter/commit/9e5f7ad2307b6fe477baa8b66752c174cb01f71a))
+* update dependency psycopg to v3.2.4 ([#2758](https://github.com/GoogleCloudPlatform/pgadapter/issues/2758)) ([6b73824](https://github.com/GoogleCloudPlatform/pgadapter/commit/6b73824ceb0e6b7485e1926130115e8704b45010))
+* update dependency psycopg-binary to v3.2.4 ([#2759](https://github.com/GoogleCloudPlatform/pgadapter/issues/2759)) ([44d28c7](https://github.com/GoogleCloudPlatform/pgadapter/commit/44d28c79560c81203b1572457d8ce83cf1275b77))
+* update dependency sqlalchemy to v2.0.37 ([#2730](https://github.com/GoogleCloudPlatform/pgadapter/issues/2730)) ([d585621](https://github.com/GoogleCloudPlatform/pgadapter/commit/d58562157c03a75d7cba62ca5c268e800def19e8))
+* update dependency typescript to v5.7.3 ([#2723](https://github.com/GoogleCloudPlatform/pgadapter/issues/2723)) ([c831073](https://github.com/GoogleCloudPlatform/pgadapter/commit/c8310736f03a2d05243788ecf052814c5dc3bef4))
+* update golang docker tag to v1.23.5 ([#2772](https://github.com/GoogleCloudPlatform/pgadapter/issues/2772)) ([76a4dc7](https://github.com/GoogleCloudPlatform/pgadapter/commit/76a4dc7d3241ea66cbafcca456bcf79f2e59de8e))
+* update module github.com/docker/docker to v27.5.0+incompatible ([#2744](https://github.com/GoogleCloudPlatform/pgadapter/issues/2744)) ([0e96f3c](https://github.com/GoogleCloudPlatform/pgadapter/commit/0e96f3c1b2b14fecefa8c12e39c54a8cb8a9aaea))
+* update module github.com/testcontainers/testcontainers-go to v0.35.0 ([#2732](https://github.com/GoogleCloudPlatform/pgadapter/issues/2732)) ([9065c73](https://github.com/GoogleCloudPlatform/pgadapter/commit/9065c73e9b999c44bf27764b39fd4942a909b0c7))
+* update module github.com/testcontainers/testcontainers-go/modules/postgres to v0.35.0 ([#2733](https://github.com/GoogleCloudPlatform/pgadapter/issues/2733)) ([3dda665](https://github.com/GoogleCloudPlatform/pgadapter/commit/3dda66527d11a22101dfec971c1c4ed2f69d7f2b))
+* update module google.golang.org/api to v0.215.0 ([#2705](https://github.com/GoogleCloudPlatform/pgadapter/issues/2705)) ([ded2638](https://github.com/GoogleCloudPlatform/pgadapter/commit/ded26385b926a5006295ecb247dd04f4cf3733f4))
+* update module google.golang.org/api to v0.216.0 ([#2726](https://github.com/GoogleCloudPlatform/pgadapter/issues/2726)) ([6948c4c](https://github.com/GoogleCloudPlatform/pgadapter/commit/6948c4c4d2bc99d2d93cfa46563dd162aa80ac8e))
+* update module google.golang.org/api to v0.217.0 ([#2776](https://github.com/GoogleCloudPlatform/pgadapter/issues/2776)) ([71d724b](https://github.com/GoogleCloudPlatform/pgadapter/commit/71d724b6fcc682406dd607bbb8896ace3005d165))
+
+
+### Documentation
+
+* add PHP snippets ([#2718](https://github.com/GoogleCloudPlatform/pgadapter/issues/2718)) ([a68ea20](https://github.com/GoogleCloudPlatform/pgadapter/commit/a68ea20bbd9a2240f805ac8a552efd09870bb093))
+* fix typo in allow_shutdown_statement documentation ([#2774](https://github.com/GoogleCloudPlatform/pgadapter/issues/2774)) ([4ae29f8](https://github.com/GoogleCloudPlatform/pgadapter/commit/4ae29f8ef44b4c48616427dda0ca96b43f6008ce)), closes [#2701](https://github.com/GoogleCloudPlatform/pgadapter/issues/2701)
+
 ## [0.42.2](https://github.com/GoogleCloudPlatform/pgadapter/compare/v0.42.1...v0.42.2) (2025-01-05)
 
 
diff --git a/README.md b/README.md
index ec182829..a287731c 100644
--- a/README.md
+++ b/README.md
@@ -116,9 +116,9 @@ Use the `-s` option to specify a different local port than the default 5432 if y
 PostgreSQL running on your local system.
 
 <!--- {x-version-update-start:google-cloud-spanner-pgadapter:released} -->
-You can also download a specific version of the jar. Example (replace `v0.42.2` with the version you want to download):
+You can also download a specific version of the jar. Example (replace `v0.42.3` with the version you want to download):
 ```shell
-VERSION=v0.42.2
+VERSION=v0.42.3
 wget https://storage.googleapis.com/pgadapter-jar-releases/pgadapter-${VERSION}.tar.gz \
   && tar -xzvf pgadapter-${VERSION}.tar.gz
 java -jar pgadapter.jar -p my-project -i my-instance -d my-database
@@ -153,7 +153,7 @@ This option is only available for Java/JVM-based applications.
 <dependency>
   <groupId>com.google.cloud</groupId>
   <artifactId>google-cloud-spanner-pgadapter</artifactId>
-  <version>0.42.2</version>
+  <version>0.42.3</version>
 </dependency>
 <!-- [END pgadapter_dependency] -->
 ```
diff --git a/benchmarks/latency-comparison/golang/go.mod b/benchmarks/latency-comparison/golang/go.mod
index 384d8e11..b179dcb3 100644
--- a/benchmarks/latency-comparison/golang/go.mod
+++ b/benchmarks/latency-comparison/golang/go.mod
@@ -6,13 +6,13 @@ toolchain go1.23.5
 
 require (
 	cloud.google.com/go/spanner v1.73.0
-	github.com/docker/docker v27.5.0+incompatible
+	github.com/docker/docker v27.5.1+incompatible
 	github.com/jackc/pgx/v4 v4.18.3
 	github.com/jackc/pgx/v5 v5.7.2
 	github.com/montanaflynn/stats v0.7.0
 	github.com/testcontainers/testcontainers-go v0.35.0
 	golang.org/x/oauth2 v0.25.0
-	google.golang.org/api v0.217.0
+	google.golang.org/api v0.218.0
 )
 
 require (
@@ -102,8 +102,8 @@ require (
 	golang.org/x/xerrors v0.0.0-20240716161551-93cc26a95ae9 // indirect
 	google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 // indirect
 	google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 // indirect
-	google.golang.org/genproto/googleapis/rpc v0.0.0-20250106144421-5f5ef82da422 // indirect
+	google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect
 	google.golang.org/grpc v1.69.4 // indirect
-	google.golang.org/protobuf v1.36.2 // indirect
+	google.golang.org/protobuf v1.36.3 // indirect
 	gopkg.in/yaml.v3 v3.0.1 // indirect
 )
diff --git a/benchmarks/latency-comparison/golang/go.sum b/benchmarks/latency-comparison/golang/go.sum
index 87c4b4a3..3e6d0196 100644
--- a/benchmarks/latency-comparison/golang/go.sum
+++ b/benchmarks/latency-comparison/golang/go.sum
@@ -803,6 +803,8 @@ github.com/docker/docker v27.4.1+incompatible h1:ZJvcY7gfwHn1JF48PfbyXg7Jyt9ZCWD
 github.com/docker/docker v27.4.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
 github.com/docker/docker v27.5.0+incompatible h1:um++2NcQtGRTz5eEgO6aJimo6/JxrTXC941hd05JO6U=
 github.com/docker/docker v27.5.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
+github.com/docker/docker v27.5.1+incompatible h1:4PYU5dnBYqRQi0294d1FBECqT9ECWeQAIfE8q4YnPY8=
+github.com/docker/docker v27.5.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
 github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
 github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
 github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
@@ -1858,6 +1860,8 @@ google.golang.org/api v0.216.0 h1:xnEHy+xWFrtYInWPy8OdGFsyIfWJjtVnO39g7pz2BFY=
 google.golang.org/api v0.216.0/go.mod h1:K9wzQMvWi47Z9IU7OgdOofvZuw75Ge3PPITImZR/UyI=
 google.golang.org/api v0.217.0 h1:GYrUtD289o4zl1AhiTZL0jvQGa2RDLyC+kX1N/lfGOU=
 google.golang.org/api v0.217.0/go.mod h1:qMc2E8cBAbQlRypBTBWHklNJlaZZJBwDv81B1Iu8oSI=
+google.golang.org/api v0.218.0 h1:x6JCjEWeZ9PFCRe9z0FBrNwj7pB7DOAqT35N+IPnAUA=
+google.golang.org/api v0.218.0/go.mod h1:5VGHBAkxrA/8EFjLVEYmMUJ8/8+gWWQ3s4cFH0FxG2M=
 google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
 google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
 google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
@@ -2057,6 +2061,8 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20250102185135-69823020774d h1:
 google.golang.org/genproto/googleapis/rpc v0.0.0-20250102185135-69823020774d/go.mod h1:3ENsm/5D1mzDyhpzeRi1NR784I0BcofWBoSc5QqqMK4=
 google.golang.org/genproto/googleapis/rpc v0.0.0-20250106144421-5f5ef82da422 h1:3UsHvIr4Wc2aW4brOaSCmcxh9ksica6fHEr8P1XhkYw=
 google.golang.org/genproto/googleapis/rpc v0.0.0-20250106144421-5f5ef82da422/go.mod h1:3ENsm/5D1mzDyhpzeRi1NR784I0BcofWBoSc5QqqMK4=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1:OxYkA3wjPsZyBylwymxSHa7ViiW1Sml4ToBrncvFehI=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50=
 google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
 google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
 google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
@@ -2144,6 +2150,8 @@ google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/g
 google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
 google.golang.org/protobuf v1.36.2 h1:R8FeyR1/eLmkutZOM5CWghmo5itiG9z0ktFlTVLuTmU=
 google.golang.org/protobuf v1.36.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
+google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU=
+google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
diff --git a/benchmarks/latency-comparison/java/pom.xml b/benchmarks/latency-comparison/java/pom.xml
index 3e6638d3..018a0d27 100644
--- a/benchmarks/latency-comparison/java/pom.xml
+++ b/benchmarks/latency-comparison/java/pom.xml
@@ -43,7 +43,7 @@
       <dependency>
         <groupId>com.google.cloud</groupId>
         <artifactId>libraries-bom</artifactId>
-        <version>26.52.0</version>
+        <version>26.53.0</version>
         <type>pom</type>
         <scope>import</scope>
       </dependency>
@@ -76,7 +76,7 @@
     <dependency>
       <groupId>com.google.cloud</groupId>
       <artifactId>google-cloud-spanner-pgadapter</artifactId>
-      <version>0.42.2</version>
+      <version>0.42.3</version>
       <exclusions>
         <exclusion>
           <groupId>io.opentelemetry</groupId>
@@ -106,6 +106,11 @@
       <artifactId>commons-cli</artifactId>
       <version>1.9.0</version>
     </dependency>
+    <dependency>
+      <groupId>commons-codec</groupId>
+      <artifactId>commons-codec</artifactId>
+      <version>1.17.2</version>
+    </dependency>
     <dependency>
       <groupId>org.checkerframework</groupId>
       <artifactId>checker-qual</artifactId>
diff --git a/benchmarks/tpcc/pom.xml b/benchmarks/tpcc/pom.xml
index 9ef3d5c0..6ea27877 100644
--- a/benchmarks/tpcc/pom.xml
+++ b/benchmarks/tpcc/pom.xml
@@ -5,7 +5,7 @@
   <parent>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-parent</artifactId>
-    <version>3.4.1</version>
+    <version>3.4.2</version>
     <relativePath/> <!-- lookup parent from repository -->
   </parent>
   <groupId>com.google.cloud.spanner</groupId>
@@ -21,7 +21,7 @@
       <dependency>
         <groupId>com.google.cloud</groupId>
         <artifactId>libraries-bom</artifactId>
-        <version>26.52.0</version>
+        <version>26.53.0</version>
         <type>pom</type>
         <scope>import</scope>
       </dependency>
@@ -61,7 +61,7 @@
     <dependency>
       <groupId>com.google.cloud</groupId>
       <artifactId>google-cloud-spanner-pgadapter</artifactId>
-      <version>0.42.2</version>
+      <version>0.42.3</version>
     </dependency>
     <dependency>
           <groupId>io.opentelemetry</groupId>
diff --git a/pom.xml b/pom.xml
index 5f51204b..f7d7de91 100644
--- a/pom.xml
+++ b/pom.xml
@@ -43,7 +43,7 @@
 
   <modelVersion>4.0.0</modelVersion>
   <artifactId>google-cloud-spanner-pgadapter</artifactId>
-  <version>0.42.3-SNAPSHOT</version><!-- {x-version-update:google-cloud-spanner-pgadapter:current} -->
+  <version>0.42.4-SNAPSHOT</version><!-- {x-version-update:google-cloud-spanner-pgadapter:current} -->
   <name>Google Cloud Spanner PostgreSQL Adapter</name>
   <packaging>jar</packaging>
   <description>
@@ -165,7 +165,7 @@
     <dependency>
       <groupId>org.postgresql</groupId>
       <artifactId>postgresql</artifactId>
-      <version>42.7.4</version>
+      <version>42.7.5</version>
     </dependency>
     <dependency>
       <groupId>com.kohlschutter.junixsocket</groupId>
diff --git a/samples/cloud-run/java/pom.xml b/samples/cloud-run/java/pom.xml
index 3b78afa7..57a0495e 100644
--- a/samples/cloud-run/java/pom.xml
+++ b/samples/cloud-run/java/pom.xml
@@ -21,7 +21,7 @@
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
     <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
 
-    <spring-boot.version>3.4.1</spring-boot.version>
+    <spring-boot.version>3.4.2</spring-boot.version>
     <junixsocket.version>2.10.1</junixsocket.version>
   </properties>
 
diff --git a/samples/java/cloud-run/pom.xml b/samples/java/cloud-run/pom.xml
index 4b297ea5..830468fe 100644
--- a/samples/java/cloud-run/pom.xml
+++ b/samples/java/cloud-run/pom.xml
@@ -36,7 +36,7 @@
       <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-dependencies</artifactId>
-        <version>3.4.1</version>
+        <version>3.4.2</version>
         <type>pom</type>
         <scope>import</scope>
       </dependency>
@@ -53,7 +53,7 @@
     <dependency>
       <groupId>com.google.cloud</groupId>
       <artifactId>google-cloud-spanner-pgadapter</artifactId>
-      <version>0.42.2</version>
+      <version>0.42.3</version>
     </dependency>
     <dependency>
       <groupId>com.kohlschutter.junixsocket</groupId>
diff --git a/samples/java/hibernate/pom.xml b/samples/java/hibernate/pom.xml
index 78396d95..ec49399c 100644
--- a/samples/java/hibernate/pom.xml
+++ b/samples/java/hibernate/pom.xml
@@ -33,13 +33,13 @@
     <dependency>
       <groupId>com.google.cloud</groupId>
       <artifactId>google-cloud-spanner-pgadapter</artifactId>
-      <version>0.42.2</version>
+      <version>0.42.3</version>
     </dependency>
     <!-- Hibernate core dependency -->
     <dependency>
       <groupId>org.hibernate.orm</groupId>
       <artifactId>hibernate-core</artifactId>
-      <version>6.6.4.Final</version>
+      <version>6.6.5.Final</version>
     </dependency>
     <!-- Postgresql JDBC driver dependency -->
     <dependency>
diff --git a/samples/java/jdbc/README.md b/samples/java/jdbc/README.md
index b33aaa54..25c88a5b 100644
--- a/samples/java/jdbc/README.md
+++ b/samples/java/jdbc/README.md
@@ -14,12 +14,12 @@ The sample application adds the following dependencies:
 <dependency>
   <groupId>org.postgresql</groupId>
   <artifactId>postgresql</artifactId>
-  <version>0.42.2</version>
+  <version>0.42.3</version>
 </dependency>
 <dependency>
   <groupId>com.google.cloud</groupId>
   <artifactId>google-cloud-spanner-pgadapter</artifactId>
-  <version>0.42.2</version>
+  <version>0.42.3</version>
 </dependency>
 <!-- [END pgadapter_and_jdbc_dependency] -->
 ```
diff --git a/samples/java/jdbc/pom.xml b/samples/java/jdbc/pom.xml
index 96e0bc97..59e52bfc 100644
--- a/samples/java/jdbc/pom.xml
+++ b/samples/java/jdbc/pom.xml
@@ -56,7 +56,7 @@
     <dependency>
       <groupId>com.google.cloud</groupId>
       <artifactId>google-cloud-spanner-pgadapter</artifactId>
-      <version>0.42.2</version>
+      <version>0.42.3</version>
     </dependency>
     <!-- [END pgadapter_and_jdbc_dependency] -->
     <dependency>
diff --git a/samples/java/r2dbc/pom.xml b/samples/java/r2dbc/pom.xml
index 58aa6ab5..f47fc99b 100644
--- a/samples/java/r2dbc/pom.xml
+++ b/samples/java/r2dbc/pom.xml
@@ -55,7 +55,7 @@
     <dependency>
       <groupId>com.google.cloud</groupId>
       <artifactId>google-cloud-spanner-pgadapter</artifactId>
-      <version>0.42.2</version>
+      <version>0.42.3</version>
     </dependency>
     <dependency>
       <groupId>org.testcontainers</groupId>
diff --git a/samples/java/spring-data-jpa/pom.xml b/samples/java/spring-data-jpa/pom.xml
index b6b4f56d..1947ae25 100644
--- a/samples/java/spring-data-jpa/pom.xml
+++ b/samples/java/spring-data-jpa/pom.xml
@@ -5,7 +5,7 @@
   <parent>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-parent</artifactId>
-    <version>3.4.1</version>
+    <version>3.4.2</version>
     <relativePath/> <!-- lookup parent from repository -->
   </parent>
   <groupId>com.google.cloud.spanner</groupId>
@@ -55,7 +55,7 @@
     <dependency>
       <groupId>com.google.cloud</groupId>
       <artifactId>google-cloud-spanner-pgadapter</artifactId>
-      <version>0.42.2</version>
+      <version>0.42.3</version>
     </dependency>
     <!-- Add Spanner Hibernate tools for access to the batch compatible bit-reversed sequence generator. -->
     <dependency>
diff --git a/samples/python/connectorx/requirements.txt b/samples/python/connectorx/requirements.txt
index c1d2e63a..7688564a 100644
--- a/samples/python/connectorx/requirements.txt
+++ b/samples/python/connectorx/requirements.txt
@@ -1,6 +1,6 @@
-connectorx==0.4.0
+connectorx==0.4.1
 pandas==2.2.3
 testcontainers~=4.9.0
 requests==2.32.3
 google~=3.0.0
-google.auth~=2.37.0
+google.auth~=2.38.0
diff --git a/samples/python/django/requirements.txt b/samples/python/django/requirements.txt
index c0c42206..62e96c5c 100644
--- a/samples/python/django/requirements.txt
+++ b/samples/python/django/requirements.txt
@@ -2,6 +2,6 @@ psycopg-binary==3.2.4
 pytz==2024.2
 Django==5.1.5
 google==3.0.0
-google.auth==2.37.0
+google.auth==2.38.0
 testcontainers==4.9.0
 requests==2.32.3
diff --git a/samples/python/psycopg3/requirements.txt b/samples/python/psycopg3/requirements.txt
index 17d04770..16d8a6f1 100644
--- a/samples/python/psycopg3/requirements.txt
+++ b/samples/python/psycopg3/requirements.txt
@@ -1,5 +1,5 @@
-psycopg[binary]~=3.2.3
+psycopg[binary]~=3.2.4
 testcontainers~=4.9.0
 requests==2.32.3
 google~=3.0.0
-google.auth~=2.37.0
\ No newline at end of file
+google.auth~=2.38.0
\ No newline at end of file
diff --git a/samples/python/sqlalchemy2-sample/requirements.txt b/samples/python/sqlalchemy2-sample/requirements.txt
index 96c28ad0..9f460602 100644
--- a/samples/python/sqlalchemy2-sample/requirements.txt
+++ b/samples/python/sqlalchemy2-sample/requirements.txt
@@ -2,6 +2,6 @@ psycopg[binary]==3.2.4
 pytz==2024.2
 sqlalchemy==2.0.37
 google~=3.0.0
-google.auth~=2.37.0
+google.auth~=2.38.0
 testcontainers~=4.9.0
 requests==2.32.3
diff --git a/samples/snippets/golang-snippets/go.mod b/samples/snippets/golang-snippets/go.mod
index 5737bc8e..60b4aa80 100644
--- a/samples/snippets/golang-snippets/go.mod
+++ b/samples/snippets/golang-snippets/go.mod
@@ -5,7 +5,7 @@ go 1.22
 toolchain go1.23.5
 
 require (
-	github.com/docker/docker v27.5.0+incompatible
+	github.com/docker/docker v27.5.1+incompatible
 	github.com/jackc/pgx/v5 v5.7.2
 	github.com/testcontainers/testcontainers-go v0.35.0
 )
diff --git a/samples/snippets/golang-snippets/go.sum b/samples/snippets/golang-snippets/go.sum
index 84209e05..d6ed32fe 100644
--- a/samples/snippets/golang-snippets/go.sum
+++ b/samples/snippets/golang-snippets/go.sum
@@ -49,6 +49,8 @@ github.com/docker/docker v27.4.1+incompatible h1:ZJvcY7gfwHn1JF48PfbyXg7Jyt9ZCWD
 github.com/docker/docker v27.4.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
 github.com/docker/docker v27.5.0+incompatible h1:um++2NcQtGRTz5eEgO6aJimo6/JxrTXC941hd05JO6U=
 github.com/docker/docker v27.5.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
+github.com/docker/docker v27.5.1+incompatible h1:4PYU5dnBYqRQi0294d1FBECqT9ECWeQAIfE8q4YnPY8=
+github.com/docker/docker v27.5.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
 github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
 github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
 github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
diff --git a/samples/snippets/php-snippets/composer.json b/samples/snippets/php-snippets/composer.json
new file mode 100644
index 00000000..303d1278
--- /dev/null
+++ b/samples/snippets/php-snippets/composer.json
@@ -0,0 +1,10 @@
+{
+  "require": {
+    "ext-pgsql": "*",
+    "ext-pdo": "*",
+    "testcontainers/testcontainers": "^0.2.0"
+  },
+  "require-dev": {
+    "phpunit/phpunit": "^11.5"
+  }
+}
diff --git a/samples/snippets/php-snippets/samples/add_column.php b/samples/snippets/php-snippets/samples/add_column.php
new file mode 100644
index 00000000..63663940
--- /dev/null
+++ b/samples/snippets/php-snippets/samples/add_column.php
@@ -0,0 +1,28 @@
+<?php
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// [START spanner_add_column]
+function add_column(string $host, string $port, string $database): void
+{
+    $dsn = sprintf("pgsql:host=%s;port=%s;dbname=%s", $host, $port, $database);
+    $connection = new PDO($dsn);
+    
+    $connection->exec("ALTER TABLE albums ADD COLUMN marketing_budget bigint");
+    print("Added marketing_budget column\n");
+
+    $connection = null;
+}
+// [END spanner_add_column]
diff --git a/samples/snippets/php-snippets/samples/albums_data.txt b/samples/snippets/php-snippets/samples/albums_data.txt
new file mode 100644
index 00000000..6580d0aa
--- /dev/null
+++ b/samples/snippets/php-snippets/samples/albums_data.txt
@@ -0,0 +1,5 @@
+1	1	Total Junk
+1	2	Go, Go, Go
+2	1	Green
+2	2	Forever Hold Your Peace
+2	3	Terrified
diff --git a/samples/snippets/php-snippets/samples/create_connection.php b/samples/snippets/php-snippets/samples/create_connection.php
new file mode 100644
index 00000000..b69d07de
--- /dev/null
+++ b/samples/snippets/php-snippets/samples/create_connection.php
@@ -0,0 +1,35 @@
+<?php
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// [START spanner_create_connection]
+function create_connection(string $host, string $port, string $database): void
+{
+    // Connect to Spanner through PGAdapter using the PostgreSQL PDO driver.
+    $dsn = sprintf("pgsql:host=%s;port=%s;dbname=%s", $host, $port, $database);
+    $connection = new PDO($dsn);
+
+    // Execute a query on Spanner through PGAdapter.
+    $statement = $connection->query("select 'Hello world!' as hello");
+    $rows = $statement->fetchAll();
+
+    printf("Greeting from Cloud Spanner PostgreSQL: %s\n", $rows[0][0]);
+
+    // Cleanup resources.
+    $rows = null;
+    $statement = null;
+    $connection = null;
+}
+// [END spanner_create_connection]
diff --git a/samples/snippets/php-snippets/samples/create_tables.php b/samples/snippets/php-snippets/samples/create_tables.php
new file mode 100644
index 00000000..de0e571a
--- /dev/null
+++ b/samples/snippets/php-snippets/samples/create_tables.php
@@ -0,0 +1,45 @@
+<?php
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// [START spanner_create_database]
+function create_tables(string $host, string $port, string $database): void
+{
+    // Connect to Spanner through PGAdapter using the PostgreSQL PDO driver.
+    $dsn = sprintf("pgsql:host=%s;port=%s;dbname=%s", $host, $port, $database);
+    $connection = new PDO($dsn);
+    
+    // Create two tables in one batch.
+    $connection->exec("start batch ddl");
+    $connection->exec("create table singers ("
+        ."  singer_id   bigint primary key not null,"
+        ."  first_name  character varying(1024),"
+        ."  last_name   character varying(1024),"
+        ."  singer_info bytea,"
+        ."  full_name   character varying(2048) generated "
+        ."  always as (first_name || ' ' || last_name) stored"
+        .")");
+    $connection->exec("create table albums ("
+        ."  singer_id     bigint not null,"
+        ."  album_id      bigint not null,"
+        ."  album_title   character varying(1024),"
+        ."  primary key (singer_id, album_id)"
+        .") interleave in parent singers on delete cascade");
+    $connection->exec("run batch");
+    print("Created Singers & Albums tables in database: [{$database}]\n");
+
+    $connection = null;
+}
+// [END spanner_create_database]
diff --git a/samples/snippets/php-snippets/samples/data_boost.php b/samples/snippets/php-snippets/samples/data_boost.php
new file mode 100644
index 00000000..34522a60
--- /dev/null
+++ b/samples/snippets/php-snippets/samples/data_boost.php
@@ -0,0 +1,42 @@
+<?php
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// [START spanner_data_boost]
+function data_boost(string $host, string $port, string $database): void
+{
+    $dsn = sprintf("pgsql:host=%s;port=%s;dbname=%s", $host, $port, $database);
+    $connection = new PDO($dsn);
+
+    // This enables Data Boost for all partitioned queries on this
+    // connection.
+    $connection->exec("set spanner.data_boost_enabled=true");
+
+    // Run a partitioned query. This query will use Data Boost.
+    $statement = $connection->query(
+        "run partitioned query "
+        ."select singer_id, first_name, last_name "
+        ."from singers"
+    );
+    $rows = $statement->fetchAll();
+    foreach ($rows as $singer) {
+        printf("%s\t%s\t%s\n", $singer["singer_id"], $singer["first_name"], $singer["last_name"]);
+    }
+
+    $rows = null;
+    $statement = null;
+    $connection = null;
+}
+// [END spanner_data_boost]
diff --git a/samples/snippets/php-snippets/samples/ddl_batch.php b/samples/snippets/php-snippets/samples/ddl_batch.php
new file mode 100644
index 00000000..5b424e9d
--- /dev/null
+++ b/samples/snippets/php-snippets/samples/ddl_batch.php
@@ -0,0 +1,48 @@
+<?php
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// [START spanner_ddl_batch]
+function ddl_batch(string $host, string $port, string $database): void
+{
+    $dsn = sprintf("pgsql:host=%s;port=%s;dbname=%s", $host, $port, $database);
+    $connection = new PDO($dsn);
+
+    // Executing multiple DDL statements as one batch is
+    // more efficient than executing each statement
+    // individually.
+    $connection->exec("start batch ddl");
+    $connection->exec("CREATE TABLE venues ("
+        ."  venue_id    bigint not null primary key,"
+        ."  name        varchar(1024),"
+        ."  description jsonb"
+        .")");
+    $connection->exec("CREATE TABLE concerts ("
+        ."  concert_id bigint not null primary key ,"
+        ."  venue_id   bigint not null,"
+        ."  singer_id  bigint not null,"
+        ."  start_time timestamptz,"
+        ."  end_time   timestamptz,"
+        ."  constraint fk_concerts_venues foreign key"
+        ."    (venue_id) references venues (venue_id),"
+        ."  constraint fk_concerts_singers foreign key"
+        ."    (singer_id) references singers (singer_id)"
+        .")");
+    $connection->exec("run batch");
+    print("Added venues and concerts tables\n");
+
+    $connection = null;
+}
+// [END spanner_ddl_batch]
diff --git a/samples/snippets/php-snippets/samples/partitioned_dml.php b/samples/snippets/php-snippets/samples/partitioned_dml.php
new file mode 100644
index 00000000..3f5ca0dc
--- /dev/null
+++ b/samples/snippets/php-snippets/samples/partitioned_dml.php
@@ -0,0 +1,40 @@
+<?php
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// [START spanner_partitioned_dml]
+function execute_partitioned_dml(string $host, string $port, string $database): void
+{
+    $dsn = sprintf("pgsql:host=%s;port=%s;dbname=%s", $host, $port, $database);
+    $connection = new PDO($dsn);
+
+    // Change the DML mode that is used by this connection to Partitioned
+    // DML. Partitioned DML is designed for bulk updates and deletes.
+    // See https://cloud.google.com/spanner/docs/dml-partitioned for more
+    // information.
+    $connection->exec("set spanner.autocommit_dml_mode='partitioned_non_atomic'");
+
+    // The following statement will use Partitioned DML.
+    $rowcount = $connection->exec(
+        "update albums "
+        ."set marketing_budget=0 "
+        ."where marketing_budget is null"
+    );
+    printf("Updated at least %d albums\n", $rowcount);
+
+    $statement = null;
+    $connection = null;
+}
+// [END spanner_partitioned_dml]
diff --git a/samples/snippets/php-snippets/samples/query_data.php b/samples/snippets/php-snippets/samples/query_data.php
new file mode 100644
index 00000000..60566057
--- /dev/null
+++ b/samples/snippets/php-snippets/samples/query_data.php
@@ -0,0 +1,37 @@
+<?php
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// [START spanner_query_data]
+function query_data(string $host, string $port, string $database): void
+{
+    $dsn = sprintf("pgsql:host=%s;port=%s;dbname=%s", $host, $port, $database);
+    $connection = new PDO($dsn);
+
+    $statement = $connection->query("SELECT singer_id, album_id, album_title "
+        ."FROM albums "
+        ."ORDER BY singer_id, album_id"
+    );
+    $rows = $statement->fetchAll();
+    foreach ($rows as $album)
+    {
+        printf("%s\t%s\t%s\n", $album["singer_id"], $album["album_id"], $album["album_title"]);
+    }
+
+    $rows = null;
+    $statement = null;
+    $connection = null;
+}
+// [END spanner_query_data]
diff --git a/samples/snippets/php-snippets/samples/query_data_with_new_column.php b/samples/snippets/php-snippets/samples/query_data_with_new_column.php
new file mode 100644
index 00000000..640a392d
--- /dev/null
+++ b/samples/snippets/php-snippets/samples/query_data_with_new_column.php
@@ -0,0 +1,38 @@
+<?php
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// [START spanner_query_data_with_new_column]
+function query_data_with_new_column(string $host, string $port, string $database): void
+{
+    $dsn = sprintf("pgsql:host=%s;port=%s;dbname=%s", $host, $port, $database);
+    $connection = new PDO($dsn);
+
+    $statement = $connection->query(
+        "SELECT singer_id, album_id, marketing_budget "
+        ."FROM albums "
+        ."ORDER BY singer_id, album_id"
+    );
+    $rows = $statement->fetchAll();
+    foreach ($rows as $album)
+    {
+        printf("%s\t%s\t%s\n", $album["singer_id"], $album["album_id"], $album["marketing_budget"]);
+    }
+
+    $rows = null;
+    $statement = null;
+    $connection = null;
+}
+// [END spanner_query_data_with_new_column]
diff --git a/samples/snippets/php-snippets/samples/query_data_with_parameter.php b/samples/snippets/php-snippets/samples/query_data_with_parameter.php
new file mode 100644
index 00000000..6116e2e9
--- /dev/null
+++ b/samples/snippets/php-snippets/samples/query_data_with_parameter.php
@@ -0,0 +1,38 @@
+<?php
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// [START spanner_query_with_parameter]
+function query_data_with_parameter(string $host, string $port, string $database): void
+{
+    $dsn = sprintf("pgsql:host=%s;port=%s;dbname=%s", $host, $port, $database);
+    $connection = new PDO($dsn);
+
+    $statement = $connection->prepare("SELECT singer_id, first_name, last_name "
+                        ."FROM singers "
+                        ."WHERE last_name = ?"
+    );
+    $statement->execute(["Garcia"]);
+    $rows = $statement->fetchAll();
+    foreach ($rows as $singer)
+    {
+        printf("%s\t%s\t%s\n", $singer["singer_id"], $singer["first_name"], $singer["last_name"]);
+    }
+
+    $rows = null;
+    $statement = null;
+    $connection = null;
+}
+// [END spanner_query_with_parameter]
diff --git a/samples/snippets/php-snippets/samples/read_only_transaction.php b/samples/snippets/php-snippets/samples/read_only_transaction.php
new file mode 100644
index 00000000..2f91ebdc
--- /dev/null
+++ b/samples/snippets/php-snippets/samples/read_only_transaction.php
@@ -0,0 +1,61 @@
+<?php
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// [START spanner_read_only_transaction]
+function read_only_transaction(string $host, string $port, string $database): void
+{
+    $dsn = sprintf("pgsql:host=%s;port=%s;dbname=%s", $host, $port, $database);
+    $connection = new PDO($dsn);
+    
+    // Start a transaction.
+    $connection->beginTransaction();
+    // Change the current transaction to a read-only transaction.
+    // This statement can only be executed at the start of a transaction.
+    $connection->exec("set transaction read only");
+    
+    // The following two queries use the same read-only transaction.
+    $statement = $connection->query(
+        "select singer_id, album_id, album_title "
+        ."from albums "
+        ."order by singer_id, album_id"
+    );
+    $rows = $statement->fetchAll();
+    foreach ($rows as $album)
+    {
+        printf("%s\t%s\t%s\n", $album["singer_id"], $album["album_id"], $album["album_title"]);
+    }
+
+    $statement = $connection->query(
+        "select singer_id, album_id, album_title "
+        ."from albums "
+        ."order by album_title"
+    );
+    $rows = $statement->fetchAll();
+    foreach ($rows as $album)
+    {
+        printf("%s\t%s\t%s\n", $album["singer_id"], $album["album_id"], $album["album_title"]);
+    }
+
+    # Read-only transactions must also be committed or rolled back to mark
+    # the end of the transaction. There is no semantic difference between
+    # rolling back or committing a read-only transaction.
+    $connection->commit();
+
+    $rows = null;
+    $statement = null;
+    $connection = null;
+}
+// [END spanner_read_only_transaction]
diff --git a/samples/snippets/php-snippets/samples/sample_runner.php b/samples/snippets/php-snippets/samples/sample_runner.php
new file mode 100644
index 00000000..3123bc47
--- /dev/null
+++ b/samples/snippets/php-snippets/samples/sample_runner.php
@@ -0,0 +1,25 @@
+<?php
+
+require 'create_tables.php';
+
+/**
+ * @throws Exception if the number of command line arguments is not equal to 4
+ */
+function parse_arguments(): array {
+    global $argc, $argv;
+    
+    if (!$argc == 4) {
+        throw new Exception(sprintf("Invalid number of arguments: %d\nExpected: 4", $argc));
+    }
+    $host = $argv[1];
+    $port = $argv[2];
+    $database = $argv[3];
+    return [$host, $port, $database];
+}
+
+try {
+    [$host, $port, $database] = parse_arguments();
+    create_tables($host, $port, $database);
+} catch (Exception $e) {
+    printf("Failed to run sample: %s\n", $e);
+}
diff --git a/samples/snippets/php-snippets/samples/singers_data.txt b/samples/snippets/php-snippets/samples/singers_data.txt
new file mode 100644
index 00000000..4af568a7
--- /dev/null
+++ b/samples/snippets/php-snippets/samples/singers_data.txt
@@ -0,0 +1,5 @@
+1	Marc	Richards
+2	Catalina	Smith
+3	Alice	Trentor
+4	Lea	Martin
+5	David	Lomond
diff --git a/samples/snippets/php-snippets/samples/statement_timeout.php b/samples/snippets/php-snippets/samples/statement_timeout.php
new file mode 100644
index 00000000..5898b388
--- /dev/null
+++ b/samples/snippets/php-snippets/samples/statement_timeout.php
@@ -0,0 +1,50 @@
+<?php
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// [START spanner_statement_timeout]
+function query_with_timeout(string $host, string $port, string $database): void
+{
+    $dsn = sprintf("pgsql:host=%s;port=%s;dbname=%s", $host, $port, $database);
+    $connection = new PDO($dsn);
+
+    // Set the statement timeout that should be used for all statements
+    // on this connection to 5 seconds.
+    // Supported time units are 's' (seconds), 'ms' (milliseconds),
+    // 'us' (microseconds), and 'ns' (nanoseconds).
+    $connection->exec("set statement_timeout='5s'");
+
+    try {
+        $statement = $connection->query("SELECT singer_id, album_id, album_title "
+            . "FROM albums "
+            . "WHERE album_title in ("
+            . "  SELECT first_name "
+            . "  FROM singers "
+            . "  WHERE last_name LIKE '%a%'"
+            . "     OR last_name LIKE '%m%'"
+            . ")");
+        $rows = $statement->fetchAll();
+        foreach ($rows as $album) {
+            printf("%s\t%s\t%s\n", $album["singer_id"], $album["album_id"], $album["album_title"]);
+        }
+    } catch (Exception $exception) {
+        printf("Error occurred during query execution: %s", $exception->getMessage());
+    }
+
+    $rows = null;
+    $statement = null;
+    $connection = null;
+}
+// [END spanner_statement_timeout]
diff --git a/samples/snippets/php-snippets/samples/tags.php b/samples/snippets/php-snippets/samples/tags.php
new file mode 100644
index 00000000..3b05df2c
--- /dev/null
+++ b/samples/snippets/php-snippets/samples/tags.php
@@ -0,0 +1,73 @@
+<?php
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// [START spanner_transaction_and_statement_tag]
+function tags(string $host, string $port, string $database): void
+{
+    $dsn = sprintf("pgsql:host=%s;port=%s;dbname=%s", $host, $port, $database);
+    $connection = new PDO($dsn);
+    
+    // Start a read/write transaction.
+    $connection->beginTransaction();
+    
+    // Set the TRANSACTION_TAG session variable to set a transaction tag
+    // for the current transaction.
+    $connection->exec("set spanner.transaction_TAG='example-tx-tag'");
+
+    // Set the STATEMENT_TAG session variable to set the request tag
+    // that should be included with the next SQL statement.
+    $connection->exec("set spanner.statement_tag='query-marketing-budget'");
+
+    $singer_id = 1;
+    $album_id = 1;
+    $statement = $connection->prepare(
+        "select marketing_budget "
+        ."from albums "
+        ."where singer_id = ? "
+        ."  and album_id  = ?"
+    );
+    $statement->execute([1, 1]);
+    $marketing_budget = $statement->fetchAll()[0][0];
+    $statement->closeCursor();
+
+    # Reduce the marketing budget by 10% if it is more than 1,000.
+    $max_marketing_budget = 1000;
+    $reduction = 0.1;
+    if ($marketing_budget > $max_marketing_budget) {
+        // Make sure the marketing_budget remains an int.
+        $marketing_budget -= intval($marketing_budget * $reduction);
+        // Set a statement tag for the update statement.
+        $connection->exec("set spanner.statement_tag='reduce-marketing-budget'");
+        $update_statement = $connection->prepare(
+            "update albums set marketing_budget = :budget "
+            ."where singer_id = :singer_id "
+            ."  and album_id  = :album_id"
+        );
+        $update_statement->execute([
+            "budget" => $marketing_budget,
+            "singer_id" => $singer_id,
+            "album_id" => $album_id,
+        ]);
+    } else {
+        print("Marketing budget already less than or equal to 1,000\n");
+    }
+    // Commit the transaction.
+    $connection->commit();
+    print("Reduced marketing budget\n");
+
+    $connection = null;
+}
+// [END spanner_transaction_and_statement_tag]
diff --git a/samples/snippets/php-snippets/samples/update_data_with_copy.php b/samples/snippets/php-snippets/samples/update_data_with_copy.php
new file mode 100644
index 00000000..93e3e2cd
--- /dev/null
+++ b/samples/snippets/php-snippets/samples/update_data_with_copy.php
@@ -0,0 +1,39 @@
+<?php
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// [START spanner_update_data]
+function update_data_with_copy(string $host, string $port, string $database): void
+{
+    $dsn = sprintf("pgsql:host=%s;port=%s;dbname=%s", $host, $port, $database);
+    $connection = new PDO($dsn);
+
+    // Instruct PGAdapter to use insert-or-update for COPY statements.
+    // This enables us to use COPY to update data.
+    $connection->exec("set spanner.copy_upsert=true");
+
+    // COPY uses mutations to insert or update existing data in Spanner.
+    $connection->pgsqlCopyFromArray(
+        "albums",
+        ["1\t1\t100000", "2\t2\t500000"],
+        "\t",
+        "\\\\N",
+        "singer_id, album_id, marketing_budget",
+    );
+    print("Updated 2 albums\n");
+
+    $connection = null;
+}
+// [END spanner_update_data]
diff --git a/samples/snippets/php-snippets/samples/update_data_with_transaction.php b/samples/snippets/php-snippets/samples/update_data_with_transaction.php
new file mode 100644
index 00000000..c35e6aa5
--- /dev/null
+++ b/samples/snippets/php-snippets/samples/update_data_with_transaction.php
@@ -0,0 +1,73 @@
+<?php
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// [START spanner_dml_getting_started_update]
+function update_data_with_transaction(string $host, string $port, string $database): void
+{
+    $dsn = sprintf("pgsql:host=%s;port=%s;dbname=%s", $host, $port, $database);
+    $connection = new PDO($dsn);
+    
+    // Start a read/write transaction.
+    $connection->beginTransaction();
+    // Transfer marketing budget from one album to another.
+    // We do it in a transaction to ensure that the transfer is atomic.
+    
+    // Create a prepared statement that we can use to execute the same
+    // SQL string multiple times with different parameter values.
+    $select_marketing_budget_statement = $connection->prepare(
+        "SELECT marketing_budget "
+        ."from albums "
+        ."WHERE singer_id = ? "
+        ."and album_id = ?"
+    );
+    // Get the marketing budget of Album #2.
+    $select_marketing_budget_statement->execute([2, 2]);
+    $album2_budget = $select_marketing_budget_statement->fetchAll()[0][0];
+    $select_marketing_budget_statement->closeCursor();
+        
+    $transfer = 200000;
+    if ($album2_budget > $transfer) {
+        // Get the marketing budget of Album #1.
+        $select_marketing_budget_statement->execute([1, 1]);
+        $album1_budget = $select_marketing_budget_statement->fetchAll()[0][0];
+        $select_marketing_budget_statement->closeCursor();
+        // Transfer the marketing budgets and write the update back
+        // to the database.
+        $album1_budget += $transfer;
+        $album2_budget -= $transfer;
+        // PHP PDO also supports named query parameters.
+        $update_statement = $connection->prepare(
+            "update albums "
+                ."set marketing_budget = :budget "
+                ."where singer_id = :singer_id "
+                ."and   album_id = :album_id"
+        );
+        // Start a DML batch. This batch will become part of the current transaction.
+        // $connection->exec("start batch dml");
+        // Update the marketing budget of both albums.
+        $update_statement->execute(["budget" => $album1_budget, "singer_id" => 1, "album_id" => 1]);
+        $update_statement->execute(["budget" => $album2_budget, "singer_id" => 2, "album_id" => 2]);
+        // $connection->exec("run batch");
+    } else {
+        print("Insufficient budget to transfer\n");
+    }
+    // Commit the transaction.
+    $connection->commit();
+    print("Transferred marketing budget from Album 2 to Album 1\n");
+
+    $connection = null;
+}
+// [END spanner_dml_getting_started_update]
diff --git a/samples/snippets/php-snippets/samples/write_data_with_copy.php b/samples/snippets/php-snippets/samples/write_data_with_copy.php
new file mode 100644
index 00000000..6824feac
--- /dev/null
+++ b/samples/snippets/php-snippets/samples/write_data_with_copy.php
@@ -0,0 +1,40 @@
+<?php
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// [START spanner_copy_from_stdin]
+function write_data_with_copy(string $host, string $port, string $database): void
+{
+    $dsn = sprintf("pgsql:host=%s;port=%s;dbname=%s", $host, $port, $database);
+    $connection = new PDO($dsn);
+    
+    $dir = dirname(__FILE__);
+    
+    $connection->pgsqlCopyFromFile(
+        "singers",
+        sprintf("%s/singers_data.txt", $dir),
+        "\t",
+        "\\\\N",
+        "singer_id, first_name, last_name");
+    print("Copied 5 singers\n");
+
+    $connection->pgsqlCopyFromFile(
+        "albums",
+        sprintf("%s/albums_data.txt", $dir));
+    print("Copied 5 albums\n");
+
+    $connection = null;
+}
+// [END spanner_copy_from_stdin]
diff --git a/samples/snippets/php-snippets/samples/write_data_with_dml.php b/samples/snippets/php-snippets/samples/write_data_with_dml.php
new file mode 100644
index 00000000..183a55b7
--- /dev/null
+++ b/samples/snippets/php-snippets/samples/write_data_with_dml.php
@@ -0,0 +1,38 @@
+<?php
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// [START spanner_dml_getting_started_insert]
+function write_data_with_dml(string $host, string $port, string $database): void
+{
+    $dsn = sprintf("pgsql:host=%s;port=%s;dbname=%s", $host, $port, $database);
+    $connection = new PDO($dsn);
+    
+    $sql = "INSERT INTO singers (singer_id, first_name, last_name)"
+                        ." VALUES (?, ?, ?), (?, ?, ?), "
+                        ."        (?, ?, ?), (?, ?, ?)";
+    $statement = $connection->prepare($sql);
+    $statement->execute([
+        12, "Melissa", "Garcia",
+        13, "Russel", "Morales",
+        14, "Jacqueline", "Long",
+        15, "Dylan", "Shaw"
+    ]);
+    printf("%d records inserted\n", $statement->rowCount());
+
+    $statement = null;
+    $connection = null;
+}
+// [END spanner_dml_getting_started_insert]
diff --git a/samples/snippets/php-snippets/samples/write_data_with_dml_batch.php b/samples/snippets/php-snippets/samples/write_data_with_dml_batch.php
new file mode 100644
index 00000000..70c52163
--- /dev/null
+++ b/samples/snippets/php-snippets/samples/write_data_with_dml_batch.php
@@ -0,0 +1,45 @@
+<?php
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// [START spanner_dml_batch]
+function write_data_with_dml_batch(string $host, string $port, string $database): void
+{
+    $dsn = sprintf("pgsql:host=%s;port=%s;dbname=%s", $host, $port, $database);
+    $connection = new PDO($dsn);
+
+    // Use START BATCH DML / RUN BATCH to run a batch of DML statements.
+    // Create a prepared statement for the DML that should be executed.
+    $sql = "INSERT INTO singers (singer_id, first_name, last_name) VALUES (?, ?, ?)";
+    $statement = $connection->prepare($sql);
+    // Start a DML batch.
+    $connection->exec("START BATCH DML");
+    
+    $statement->execute([16, "Sarah", "Wilson"]);
+    $statement->execute([17, "Ethan", "Miller"]);
+    $statement->execute([18, "Maya", "Patel"]);
+    
+    // Run the DML batch. Use the 'query(..)' method, as the update counts are returned as a row
+    // containing an array with the update count of each statement in the batch.
+    $statement = $connection->query("RUN BATCH");
+    $result = $statement->fetchAll();
+    $update_count = $result[0][0];
+    
+    printf("%s records inserted\n", $update_count);
+
+    $statement = null;
+    $connection = null;
+}
+// [END spanner_dml_batch]
diff --git a/src/main/java/com/google/cloud/spanner/pgadapter/metadata/OptionsMetadata.java b/src/main/java/com/google/cloud/spanner/pgadapter/metadata/OptionsMetadata.java
index 5f899034..9ae7e4c4 100644
--- a/src/main/java/com/google/cloud/spanner/pgadapter/metadata/OptionsMetadata.java
+++ b/src/main/java/com/google/cloud/spanner/pgadapter/metadata/OptionsMetadata.java
@@ -33,6 +33,7 @@ import com.google.common.base.Preconditions;
 import com.google.common.base.Strings;
 import com.google.common.collect.ImmutableList;
 import com.google.spanner.v1.DatabaseName;
+import io.grpc.ExperimentalApi;
 import java.io.File;
 import java.io.IOException;
 import java.nio.file.Files;
@@ -108,6 +109,8 @@ public class OptionsMetadata {
     private String endpoint;
     private boolean usePlainText;
     private Duration startupTimeout = DEFAULT_STARTUP_TIMEOUT;
+    private String clientCertificate;
+    private String clientKey;
 
     Builder() {}
 
@@ -413,6 +416,20 @@ public class OptionsMetadata {
       return this;
     }
 
+    /**
+     * Configures mTLS authentication using the provided client certificate and key files. mTLS is
+     * only supported for external spanner hosts.
+     *
+     * @param clientCertificate Path to the client certificate file.
+     * @param clientKey Path to the client private key file.
+     */
+    @ExperimentalApi("https://github.com/googleapis/java-spanner/pull/3574")
+    Builder useClientCert(String clientCertificate, String clientKey) {
+      this.clientCertificate = clientCertificate;
+      this.clientKey = clientKey;
+      return this;
+    }
+
     public OptionsMetadata build() {
       if (Strings.isNullOrEmpty(project) && !Strings.isNullOrEmpty(instance)) {
         throw SpannerExceptionFactory.newSpannerException(
@@ -484,7 +501,8 @@ public class OptionsMetadata {
           || databaseRole != null
           || autoConfigEmulator
           || useVirtualGrpcTransportThreads
-          || enableEndToEndTracing) {
+          || enableEndToEndTracing
+          || (clientKey != null && clientCertificate != null)) {
         StringBuilder jdbcOptionBuilder = new StringBuilder();
         if (usePlainText) {
           jdbcOptionBuilder.append("usePlainText=true;");
@@ -506,6 +524,10 @@ public class OptionsMetadata {
         if (enableEndToEndTracing) {
           jdbcOptionBuilder.append(ENABLE_END_TO_END_TRACING_PROPERTY_NAME).append("=true;");
         }
+        if (clientKey != null && clientCertificate != null) {
+          jdbcOptionBuilder.append("clientCertificate=").append(clientCertificate).append(";");
+          jdbcOptionBuilder.append("clientKey=").append(clientKey).append(";");
+        }
         addOption(args, OPTION_JDBC_PROPERTIES, jdbcOptionBuilder.toString());
       }
       if (logGrpcMessages) {
diff --git a/src/main/java/com/google/cloud/spanner/pgadapter/parsers/DateParser.java b/src/main/java/com/google/cloud/spanner/pgadapter/parsers/DateParser.java
index aa01c0df..71bd8b30 100644
--- a/src/main/java/com/google/cloud/spanner/pgadapter/parsers/DateParser.java
+++ b/src/main/java/com/google/cloud/spanner/pgadapter/parsers/DateParser.java
@@ -23,7 +23,6 @@ import com.google.cloud.spanner.Statement;
 import com.google.cloud.spanner.pgadapter.ProxyServer.DataFormat;
 import com.google.cloud.spanner.pgadapter.error.PGExceptionFactory;
 import java.nio.charset.StandardCharsets;
-import java.text.SimpleDateFormat;
 import java.time.LocalDate;
 import javax.annotation.Nonnull;
 import org.postgresql.util.ByteConverter;
@@ -31,17 +30,6 @@ import org.postgresql.util.ByteConverter;
 /** Translate wire protocol dates to desired formats. */
 @InternalApi
 public class DateParser extends Parser<Date> {
-  // Valid format for date: 'yyyy-MM-dd [+-]HH[:mi]'.
-  // Timezone information is optional. Timezone may also be specified using only hour value.
-  // NOTE: Following algorithm might perform slowly due to exception handling; sadly, this seems
-  //       to be the accepted default method for date validation.
-  private static final SimpleDateFormat[] VALID_DATE_FORMATS = {
-    new SimpleDateFormat("yyyy-MM-dd HH:mm"),
-    new SimpleDateFormat("yyyy-MM-dd +HH:mm"),
-    new SimpleDateFormat("yyyy-MM-dd -HH:mm"),
-    new SimpleDateFormat("yyyy-MM-dd +HH"),
-    new SimpleDateFormat("yyyy-MM-dd -HH")
-  };
 
   DateParser(ResultSet item, int position) {
     this.item = item.getDate(position);
diff --git a/src/main/java/com/google/cloud/spanner/pgadapter/session/PGSetting.java b/src/main/java/com/google/cloud/spanner/pgadapter/session/PGSetting.java
index 9a836f9f..73366515 100644
--- a/src/main/java/com/google/cloud/spanner/pgadapter/session/PGSetting.java
+++ b/src/main/java/com/google/cloud/spanner/pgadapter/session/PGSetting.java
@@ -95,7 +95,7 @@ public class PGSetting {
   private final String minVal;
   private final String maxVal;
   private final String[] enumVals;
-  private final ImmutableList upperCaseEnumVals;
+  private final ImmutableList<String> upperCaseEnumVals;
 
   private String setting;
   private String unit;
@@ -258,43 +258,68 @@ public class PGSetting {
     }
   }
 
-  /** Returns this setting as a SELECT statement that can be used in a query or CTE. */
-  String getSelectStatement() {
+  /**
+   * Returns a SELECT statement that can be used in a query or CTE to select jsonb-generated
+   * settings.
+   */
+  static String getSelectJsonbSetting() {
     return "select "
-        + toSelectExpression(getCasePreservingKey())
-        + " as name, "
-        + toSelectExpression(setting)
-        + " as setting, "
-        + toSelectExpression(unit)
-        + " as unit, "
-        + toSelectExpression(category)
-        + " as category, "
-        + toSelectExpression((String) null)
-        + " as short_desc, "
-        + toSelectExpression((String) null)
-        + " as extra_desc, "
-        + toSelectExpression(context.getSqlValue())
-        + " as context, "
-        + toSelectExpression(vartype)
-        + " as vartype, "
-        + toSelectExpression(minVal)
-        + " as min_val, "
-        + toSelectExpression(maxVal)
-        + " as max_val, "
-        + toSelectExpression(enumVals)
-        + " as enumvals, "
-        + toSelectExpression(bootVal)
-        + " as boot_val, "
-        + toSelectExpression(resetVal)
-        + " as reset_val, "
-        + toSelectExpression(source)
-        + " as source, "
-        + toSelectExpression((String) null)
-        + " as sourcefile, "
-        + toSelectExpression((Integer) null)
-        + "::bigint as sourceline, "
-        + toSelectExpression(pendingRestart)
-        + "::boolean as pending_restart";
+        + "t->>'name' as name, "
+        + "t->>'setting' as setting, "
+        + "t->>'unit' as unit, "
+        + "t->>'category' as category, "
+        + "t->>'short_desc' as short_desc, "
+        + "t->>'extra_desc' as extra_desc, "
+        + "t->>'context' as context, "
+        + "t->>'vartype' as vartype, "
+        + "t->>'min_val' as min_val, "
+        + "t->>'max_val' as max_val, "
+        + "case when t->>'enumvals' is null then null::text[] else spanner.string_array((t->>'enumvals')::jsonb) end as enumvals, "
+        + "t->>'boot_val' as boot_val, "
+        + "t->>'reset_val' as reset_val, "
+        + "t->>'source' as source, "
+        + "(t->>'sourcefile')::varchar as sourcefile, "
+        + "(t->>'sourceline')::bigint as sourceline, "
+        + "(t->>'pending_restart')::boolean as pending_restart\n";
+  }
+
+  /** Returns this setting as a jsonb literal expression that can be used in a query or CTE. */
+  String getJsonbLiteral() {
+    return "'{"
+        + toJsonbElement("name", getCasePreservingKey())
+        + ","
+        + toJsonbElement("setting", setting)
+        + ","
+        + toJsonbElement("unit", unit)
+        + ","
+        + toJsonbElement("category", category)
+        + ","
+        + toJsonbElement("short_desc", (String) null)
+        + ","
+        + toJsonbElement("extra_desc", (String) null)
+        + ","
+        + toJsonbElement("context", context.getSqlValue())
+        + ","
+        + toJsonbElement("vartype", vartype)
+        + ","
+        + toJsonbElement("min_val", minVal)
+        + ","
+        + toJsonbElement("max_val", maxVal)
+        + ","
+        + toJsonbElement("enum_vals", enumVals)
+        + ","
+        + toJsonbElement("boot_val", bootVal)
+        + ","
+        + toJsonbElement("reset_val", resetVal)
+        + ","
+        + toJsonbElement("source", source)
+        + ","
+        + toJsonbElement("sourcefile", (String) null)
+        + ","
+        + toJsonbElement("sourceline", (Integer) null)
+        + ","
+        + toJsonbElement("pending_restart", pendingRestart)
+        + "}'::jsonb";
   }
 
   /** Returns the column names of the pg_settings table. */
@@ -302,33 +327,42 @@ public class PGSetting {
     return COLUMN_NAMES;
   }
 
-  /** Converts a string to a SQL literal expression that can be used in a select statement. */
-  String toSelectExpression(String value) {
-    return value == null ? "null" : "'" + value + "'";
+  String toJsonbElement(String name, String value) {
+    return "\"" + name + "\":" + toJsonbExpression(value);
   }
 
-  /**
-   * Converts a string array to a SQL literal expression that can be used in a select statement. The
-   * expression is cast to text[].
-   */
-  String toSelectExpression(String[] value) {
-    return value == null
-        ? "null::text[]"
-        : "'{"
-            + Arrays.stream(value)
-                .map(s -> s.startsWith("\"") ? s : "\"" + s + "\"")
-                .collect(Collectors.joining(", "))
-            + "}'::text[]";
+  String toJsonbElement(String name, Integer value) {
+    return "\"" + name + "\":" + toJsonbExpression(value);
   }
 
-  /** Converts an Integer to a SQL literal expression that can be used in a select statement. */
-  String toSelectExpression(Integer value) {
+  String toJsonbElement(String name, Boolean value) {
+    return "\"" + name + "\":" + toJsonbExpression(value);
+  }
+
+  String toJsonbElement(String name, String[] value) {
+    return "\"" + name + "\":" + toJsonbExpression(value);
+  }
+
+  String toJsonbExpression(String value) {
+    return value == null ? "null" : "\"" + value + "\"";
+  }
+
+  String toJsonbExpression(Integer value) {
+    return value == null ? "null" : value.toString();
+  }
+
+  String toJsonbExpression(Boolean value) {
     return value == null ? "null" : value.toString();
   }
 
-  /** Converts a Boolean to a SQL literal expression that can be used in a select statement. */
-  String toSelectExpression(Boolean value) {
-    return value == null ? "null" : (value ? "'t'" : "'f'");
+  String toJsonbExpression(String[] value) {
+    return value == null
+        ? "null"
+        : "["
+            + Arrays.stream(value)
+                .map(s -> s.startsWith("\"") ? s : "\"" + s + "\"")
+                .collect(Collectors.joining(", "))
+            + "]";
   }
 
   /**
diff --git a/src/main/java/com/google/cloud/spanner/pgadapter/session/SessionState.java b/src/main/java/com/google/cloud/spanner/pgadapter/session/SessionState.java
index 692d643e..22658ba9 100644
--- a/src/main/java/com/google/cloud/spanner/pgadapter/session/SessionState.java
+++ b/src/main/java/com/google/cloud/spanner/pgadapter/session/SessionState.java
@@ -70,9 +70,7 @@ public class SessionState {
           "server_version_num",
           "TimeZone",
           "transaction_isolation",
-          "transaction_read_only",
-          "spanner.ddl_transaction_mode",
-          "spanner.replace_pg_catalog_tables");
+          "transaction_read_only");
 
   static final Map<String, PGSetting> SERVER_SETTINGS = new HashMap<>();
 
@@ -138,10 +136,16 @@ public class SessionState {
    */
   public String generatePGSettingsCte() {
     return "pg_settings_inmem_ as (\n"
+        + PGSetting.getSelectJsonbSetting()
+        + "from unnest(array[\n"
         + getAll().stream()
-            .filter(setting -> SUPPORTED_PG_SETTINGS_KEYS.contains(setting.getCasePreservingKey()))
-            .map(PGSetting::getSelectStatement)
-            .collect(Collectors.joining("\nunion all\n"))
+            .filter(
+                setting ->
+                    setting.getName().toLowerCase().startsWith("spanner.")
+                        || SUPPORTED_PG_SETTINGS_KEYS.contains(setting.getCasePreservingKey()))
+            .map(PGSetting::getJsonbLiteral)
+            .collect(Collectors.joining(",\n"))
+        + "\n]) t"
         + "\n),\n"
         + "pg_settings_names_ as (\n"
         + "select name from pg_settings_inmem_\n"
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 db846800..915e93ee 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
@@ -45,10 +45,18 @@ class JdbcMetadataStatementHelper {
     // with Spangres-compatible queries.
     if (sql.startsWith(PgJdbcCatalog.PG_JDBC_EXPORTED_IMPORTED_KEYS_PREFIX)
         || sql.startsWith(PgJdbcCatalog.PG_JDBC_EXPORTED_IMPORTED_KEYS_42_0_PREFIX)) {
-      return replaceImportedExportedKeysQuery(sql);
+      return replaceImportedExportedKeysQuery(
+          sql, PgJdbcCatalog.PG_JDBC_EXPORTED_IMPORTED_KEYS_REPLACEMENT, "KEY_SEQ");
+    }
+    if (sql.startsWith(PgJdbcCatalog.PG_JDBC_EXPORTED_IMPORTED_KEYS_PREFIX_V42_7_5)) {
+      return replaceImportedExportedKeysQuery(
+          sql, PgJdbcCatalog.PG_JDBC_EXPORTED_IMPORTED_KEYS_REPLACEMENT_UPPER_CASE, "\"KEY_SEQ\"");
     }
     if (sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_SCHEMAS_PREFIX)) {
-      return replaceGetSchemasQuery(sql);
+      return replaceGetSchemasQuery(sql, PgJdbcCatalog.PG_JDBC_GET_SCHEMAS_REPLACEMENT);
+    }
+    if (sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_SCHEMAS_PREFIX_V42_7_5)) {
+      return replaceGetSchemasQuery(sql, PgJdbcCatalog.PG_JDBC_GET_SCHEMAS_REPLACEMENT_UPPER_CASE);
     }
     if (sql.contains(LiquibaseStatementHelper.TAG_STATEMENT_PART)) {
       return LiquibaseStatementHelper.replaceTagStatement(sql);
@@ -65,10 +73,16 @@ class JdbcMetadataStatementHelper {
         || sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_TABLES_PREFIX_5)
         || sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_TABLES_PREFIX_6)
         || sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_TABLES_PREFIX_7)
-        || sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_TABLES_PREFIX_8)) {
-      return replaceGetTablesQuery(sql);
+        || sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_TABLES_PREFIX_8)
+        || sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_TABLES_PREFIX_9)) {
+      if (sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_TABLES_PREFIX_9)) {
+        return replaceGetTablesQuery(sql, PgJdbcCatalog.PG_JDBC_GET_TABLES_REPLACEMENT_UPPER_CASE);
+      } else {
+        return replaceGetTablesQuery(sql, PgJdbcCatalog.PG_JDBC_GET_TABLES_REPLACEMENT);
+      }
     }
-    if (sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_COLUMNS_PREFIX_1)
+    if (sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_COLUMNS_PREFIX_V42_7_5)
+        || sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_COLUMNS_PREFIX_1)
         || sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_COLUMNS_PREFIX_2)
         || sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_COLUMNS_PREFIX_3)
         || sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_COLUMNS_PREFIX_4)
@@ -78,22 +92,26 @@ class JdbcMetadataStatementHelper {
         || sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_COLUMNS_PREFIX_4_1)) {
       return replaceGetColumnsQuery(sql);
     }
-    if (sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_INDEXES_PREFIX_1)
+    if (sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_INDEXES_PREFIX_V42_7_5)
+        || sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_INDEXES_PREFIX_1)
         || sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_INDEXES_PREFIX_2)
         || sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_INDEXES_PREFIX_3)
         || sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_INDEXES_PREFIX_1_1)) {
       return replaceGetIndexInfoQuery(sql);
     }
     if (sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_PRIMARY_KEY_PREFIX_1)
-        || sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_PRIMARY_KEY_PREFIX_2)) {
+        || sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_PRIMARY_KEY_PREFIX_2)
+        || sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_PRIMARY_KEY_PREFIX_V42_7_5)) {
       return replaceGetPrimaryKeyQuery(sql);
     }
     if (sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_TABLE_PRIVILEGES_PREFIX_1)
-        || sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_TABLE_PRIVILEGES_PREFIX_2)) {
+        || sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_TABLE_PRIVILEGES_PREFIX_2)
+        || sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_TABLE_PRIVILEGES_PREFIX_3)) {
       return PgJdbcCatalog.PG_JDBC_GET_TABLE_PRIVILEGES_REPLACEMENT;
     }
     if (sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_COLUMN_PRIVILEGES_PREFIX_1)
-        || sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_COLUMN_PRIVILEGES_PREFIX_1_1)) {
+        || sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_COLUMN_PRIVILEGES_PREFIX_1_1)
+        || sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_COLUMN_PRIVILEGES_PREFIX_V42_7_5)) {
       return PgJdbcCatalog.PG_JDBC_GET_TABLE_PRIVILEGES_REPLACEMENT;
     }
     if (sql.startsWith(PgJdbcCatalog.PG_JDBC_BEST_ROW_IDENTIFIER_PREFIX)) {
@@ -101,16 +119,22 @@ class JdbcMetadataStatementHelper {
     }
 
     if (sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_FUNCTIONS_WITH_FUNC_TYPE_PREFIX)
-        || sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_FUNCTIONS_WITHOUT_FUNC_TYPE_PREFIX)) {
+        || sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_FUNCTIONS_WITHOUT_FUNC_TYPE_PREFIX)
+        || sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_FUNCTIONS_UPPER_CASE_PREFIX)) {
       return PgJdbcCatalog.PG_JDBC_GET_FUNCTIONS_REPLACEMENT;
     }
-    if (sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_FUNCTION_COLUMNS_PREFIX)) {
+    if (sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_FUNCTION_COLUMNS_PREFIX)
+        || sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_FUNCTION_COLUMNS_PREFIX_V42_7_5)) {
       return PgJdbcCatalog.PG_JDBC_GET_FUNCTION_COLUMNS_REPLACEMENT;
     }
     if (sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_PROCEDURES_PREFIX)) {
       return PgJdbcCatalog.PG_JDBC_GET_PROCEDURES_REPLACEMENT;
     }
-    if (sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_UDTS_PREFIX)) {
+    if (sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_PROCEDURES_PREFIX_V42_7_5)) {
+      return PgJdbcCatalog.PG_JDBC_GET_PROCEDURES_REPLACEMENT;
+    }
+    if (sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_UDTS_PREFIX)
+        || sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_UDTS_PREFIX_V42_7_5)) {
       return PgJdbcCatalog.PG_JDBC_GET_UDTS_REPLACEMENT;
     }
     if (sql.startsWith(PgJdbcCatalog.PG_JDBC_GET_MAX_NAME_LENGTH_PREFIX)) {
@@ -204,8 +228,7 @@ class JdbcMetadataStatementHelper {
     return replacedSql + whereClause + " ORDER BY ct.relname, pk_name, key_seq";
   }
 
-  private static String replaceGetSchemasQuery(String sql) {
-    String replacedSql = PgJdbcCatalog.PG_JDBC_GET_SCHEMAS_REPLACEMENT;
+  private static String replaceGetSchemasQuery(String sql, String replacedSql) {
     int startIndex;
     if (sql.contains(" AND nspname LIKE ")) {
       startIndex = sql.indexOf(" AND nspname LIKE ");
@@ -218,8 +241,7 @@ class JdbcMetadataStatementHelper {
         .replace(" ORDER BY TABLE_SCHEM", " ORDER BY schema_name");
   }
 
-  private static String replaceGetTablesQuery(String sql) {
-    String replacedSql = PgJdbcCatalog.PG_JDBC_GET_TABLES_REPLACEMENT;
+  private static String replaceGetTablesQuery(String sql, String replacedSql) {
     int startIndex;
     String wherePrefix = "WHERE c.relnamespace = n.oid";
     if (sql.contains(wherePrefix)) {
@@ -229,6 +251,7 @@ class JdbcMetadataStatementHelper {
     }
     replacedSql += " WHERE TRUE " + sql.substring(startIndex);
     return replacedSql
+        .replaceFirst(" AND current_database\\(\\) = '.*?'", "")
         .replace(" AND n.nspname LIKE ", " AND TABLE_SCHEMA LIKE ")
         .replace(" AND c.relname LIKE ", " AND TABLE_NAME LIKE ")
         .replace(
@@ -344,6 +367,9 @@ class JdbcMetadataStatementHelper {
         .replace(" AND n.nspname = ", " AND IDX.TABLE_SCHEMA = ")
         .replace(" AND ct.relname = ", " AND IDX.TABLE_NAME = ")
         .replace(" AND i.indisunique ", " AND IDX.IS_UNIQUE='YES' ")
+        .replace(
+            ") AS tmp ORDER BY \"NON_UNIQUE\", \"TYPE\", \"INDEX_NAME\", \"ORDINAL_POSITION\"",
+            " ORDER BY IDX.TABLE_NAME, IS_UNIQUE DESC, IDX.INDEX_NAME, CASE WHEN ORDINAL_POSITION IS NULL THEN 0 ELSE ORDINAL_POSITION END")
         .replace(
             ") AS tmp ORDER BY NON_UNIQUE, TYPE, INDEX_NAME, ORDINAL_POSITION",
             " ORDER BY IDX.TABLE_NAME, IS_UNIQUE DESC, IDX.INDEX_NAME, CASE WHEN ORDINAL_POSITION IS NULL THEN 0 ELSE ORDINAL_POSITION END")
@@ -364,6 +390,7 @@ class JdbcMetadataStatementHelper {
     replacedSql += " WHERE TRUE " + sql.substring(startIndex);
     return replacedSql
         .replace(") result where  result.A_ATTNUM = (result.KEYS).x", "")
+        .replace("AND result.KEY_SEQ <= KEY_COUNT", "")
         .replace(" AND n.nspname = ", " AND IDX.TABLE_SCHEMA = ")
         .replace(" AND ct.relname = ", " AND IDX.TABLE_NAME = ")
         .replace(" AND i.indisprimary ", " AND IDX.INDEX_TYPE='PRIMARY_KEY' ")
@@ -375,8 +402,8 @@ class JdbcMetadataStatementHelper {
             "ORDER BY COLS.TABLE_NAME, IDX.INDEX_NAME, COLS.ORDINAL_POSITION");
   }
 
-  private static String replaceImportedExportedKeysQuery(String sql) {
-    String replacedSql = PgJdbcCatalog.PG_JDBC_EXPORTED_IMPORTED_KEYS_REPLACEMENT;
+  private static String replaceImportedExportedKeysQuery(
+      String sql, String replacedSql, String keySeq) {
     int startIndex;
     if (sql.contains(" AND pkn.nspname = ")) {
       startIndex = sql.indexOf(" AND pkn.nspname = ");
@@ -397,9 +424,9 @@ class JdbcMetadataStatementHelper {
         .replace(" AND fkc.relname = ", " AND CHILD.TABLE_NAME = ")
         .replace(
             " ORDER BY fkn.nspname,fkc.relname,con.conname,pos.n",
-            " ORDER BY CHILD.TABLE_CATALOG, CHILD.TABLE_SCHEMA, CHILD.TABLE_NAME, KEY_SEQ")
+            " ORDER BY CHILD.TABLE_CATALOG, CHILD.TABLE_SCHEMA, CHILD.TABLE_NAME, " + keySeq)
         .replace(
             " ORDER BY pkn.nspname,pkc.relname, con.conname,pos.n",
-            " ORDER BY PARENT.TABLE_CATALOG, PARENT.TABLE_SCHEMA, PARENT.TABLE_NAME, KEY_SEQ");
+            " ORDER BY PARENT.TABLE_CATALOG, PARENT.TABLE_SCHEMA, PARENT.TABLE_NAME, " + keySeq);
   }
 }
diff --git a/src/main/java/com/google/cloud/spanner/pgadapter/utils/ClientAutoDetector.java b/src/main/java/com/google/cloud/spanner/pgadapter/utils/ClientAutoDetector.java
index d4d267fc..dea38054 100644
--- a/src/main/java/com/google/cloud/spanner/pgadapter/utils/ClientAutoDetector.java
+++ b/src/main/java/com/google/cloud/spanner/pgadapter/utils/ClientAutoDetector.java
@@ -46,7 +46,9 @@ import java.time.Duration;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Objects;
 import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
 import java.util.regex.Pattern;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
@@ -71,6 +73,11 @@ public class ClientAutoDetector {
   public static final String PGBENCH_USAGE_HINT =
       "See https://github.com/GoogleCloudPlatform/pgadapter/blob/-/docs/pgbench.md for how to use pgbench with PGAdapter";
 
+  /** Force the detector to return this client. This should only be used for testing. */
+  @VisibleForTesting
+  public static final AtomicReference<WellKnownClient> FORCE_DETECT_CLIENT =
+      new AtomicReference<>();
+
   public enum WellKnownClient {
     PSQL {
 
@@ -665,6 +672,9 @@ public class ClientAutoDetector {
   public static @Nonnull WellKnownClient detectClient(
       List<String> orderParameterKeys, Map<String, String> parameters) {
     for (WellKnownClient client : WellKnownClient.values()) {
+      if (Objects.equals(client, FORCE_DETECT_CLIENT.get())) {
+        return client;
+      }
       if (client.isClient(orderParameterKeys, parameters)) {
         return client;
       }
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 b0881e52..50fa7972 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
@@ -75,6 +75,8 @@ public class PgJdbcCatalog {
           + "FROM pg_catalog.pg_proc p "
           + "INNER JOIN pg_catalog.pg_namespace n ON p.pronamespace=n.oid "
           + "LEFT JOIN pg_catalog.pg_description d ON p.oid=d.objoid ";
+  public static final String PG_JDBC_GET_FUNCTIONS_UPPER_CASE_PREFIX =
+      "SELECT current_database() AS \"FUNCTION_CAT\",  n.nspname AS \"FUNCTION_SCHEM\", p.proname AS \"FUNCTION_NAME\",  d.description AS \"REMARKS\",";
   public static final String PG_JDBC_GET_FUNCTIONS_REPLACEMENT =
       "select * from (\n"
           + "\tselect ''::varchar as FUNCTION_CAT, ''::varchar as FUNCTION_SCHEM, ''::varchar as FUNCTION_NAME, ''::varchar as REMARKS, 0::bigint as FUNCTION_TYPE, ''::varchar as SPECIFIC_NAME\n"
@@ -91,6 +93,8 @@ public class PgJdbcCatalog {
           + " LEFT JOIN pg_catalog.pg_class c ON (d.classoid=c.oid AND c.relname='pg_proc') "
           + " LEFT JOIN pg_catalog.pg_namespace pn ON (c.relnamespace=pn.oid AND pn.nspname='pg_catalog') "
           + " WHERE p.pronamespace=n.oid ";
+  public static final String PG_JDBC_GET_PROCEDURES_PREFIX_V42_7_5 =
+      "SELECT current_database() AS \"PROCEDURE_CAT\",  n.nspname AS \"PROCEDURE_SCHEM\", p.proname AS \"PROCEDURE_NAME\", NULL, NULL, NULL, d.description AS \"REMARKS\", 2 AS \"PROCEDURE_TYPE\",";
   public static final String PG_JDBC_GET_PROCEDURES_REPLACEMENT =
       "select * from (\n"
           + "\tselect ''::varchar as PROCEDURE_CAT, ''::varchar as PROCEDURE_SCHEM, ''::varchar as PROCEDURE_NAME, ''::varchar as REMARKS, 0::bigint as PROCEDURE_TYPE, ''::varchar as SPECIFIC_NAME\n"
@@ -106,6 +110,8 @@ public class PgJdbcCatalog {
           + java.sql.Types.DISTINCT
           + " end as data_type, pg_catalog.obj_description(t.oid, 'pg_type')  "
           + "as remarks, CASE WHEN t.typtype = 'd' then  (select CASE";
+  public static final String PG_JDBC_GET_UDTS_PREFIX_V42_7_5 =
+      "select current_database() as \"TYPE_CAT\", n.nspname as \"TYPE_SCHEM\", t.typname as \"TYPE_NAME\", null as \"CLASS_NAME\", ";
   public static final String PG_JDBC_GET_UDTS_REPLACEMENT =
       "select * from (\n"
           + "\tselect ''::varchar as TYPE_CAT, ''::varchar as TYPE_SCHEM, ''::varchar as TYPE_NAME, ''::varchar as CLASS_NAME, 0::bigint as DATA_TYPE, ''::varchar as REMARKS, 0::bigint as BASE_TYPE\n"
@@ -117,6 +123,9 @@ public class PgJdbcCatalog {
           + " p.proargnames, p.proargmodes, p.proallargtypes, p.oid "
           + " FROM pg_catalog.pg_proc p, pg_catalog.pg_namespace n, pg_catalog.pg_type t "
           + " WHERE p.pronamespace=n.oid AND p.prorettype=t.oid ";
+  public static final String PG_JDBC_GET_FUNCTION_COLUMNS_PREFIX_V42_7_5 =
+      "SELECT current_database(), n.nspname,p.proname,p.prorettype,p.proargtypes, t.typtype,t.typrelid, "
+          + " p.proargnames, p.proargmodes, p.proallargtypes, p.oid ";
   public static final String PG_JDBC_GET_FUNCTION_COLUMNS_REPLACEMENT =
       "select * from (\n"
           + "\tselect ''::varchar as FUNCTION_CAT, ''::varchar as FUNCTION_SCHEM, ''::varchar as FUNCTION_NAME, ''::varchar as COLUMN_NAME, 0::bigint as COLUMN_TYPE,\n"
@@ -130,8 +139,15 @@ public class PgJdbcCatalog {
           + " WHERE nspname <> 'pg_toast' AND (nspname !~ '^pg_temp_' "
           + " OR nspname = (pg_catalog.current_schemas(true))[1]) AND (nspname !~ '^pg_toast_temp_' "
           + " OR nspname = replace((pg_catalog.current_schemas(true))[1], 'pg_temp_', 'pg_toast_temp_')) ";
+  public static final String PG_JDBC_GET_SCHEMAS_PREFIX_V42_7_5 =
+      "SELECT nspname AS \"TABLE_SCHEM\", current_database() AS \"TABLE_CATALOG\" FROM pg_catalog.pg_namespace "
+          + " WHERE nspname <> 'pg_toast' AND (nspname !~ '^pg_temp_' "
+          + " OR nspname = (pg_catalog.current_schemas(true))[1]) AND (nspname !~ '^pg_toast_temp_' "
+          + " OR nspname = replace((pg_catalog.current_schemas(true))[1], 'pg_temp_', 'pg_toast_temp_')) ";
   public static final String PG_JDBC_GET_SCHEMAS_REPLACEMENT =
       "select schema_name as TABLE_SCHEM, catalog_name AS TABLE_CATALOG from information_schema.schemata WHERE true ";
+  public static final String PG_JDBC_GET_SCHEMAS_REPLACEMENT_UPPER_CASE =
+      "select schema_name as \"TABLE_SCHEM\", catalog_name AS \"TABLE_CATALOG\" from information_schema.schemata WHERE true ";
 
   public static final String PG_JDBC_GET_TABLES_PREFIX_1 =
       "SELECT NULL AS TABLE_CAT, n.nspname AS TABLE_SCHEM, c.relname AS TABLE_NAME,  CASE n.nspname ~ '^pg_' OR n.nspname = 'information_schema'  WHEN true THEN CASE  WHEN n.nspname = 'pg_catalog' OR n.nspname = 'information_schema' THEN CASE c.relkind   WHEN 'r' THEN 'SYSTEM TABLE'   WHEN 'v' THEN 'SYSTEM VIEW'   WHEN 'i' THEN 'SYSTEM INDEX'   ELSE NULL   END  WHEN n.nspname = 'pg_toast' THEN CASE c.relkind   WHEN 'r' THEN 'SYSTEM TOAST TABLE'   WHEN 'i' THEN 'SYSTEM TOAST INDEX'   ELSE NULL   END  ELSE CASE c.relkind   WHEN 'r' THEN 'TEMPORARY TABLE'   WHEN 'p' THEN 'TEMPORARY TABLE'   WHEN 'i' THEN 'TEMPORARY INDEX'   WHEN 'S' THEN 'TEMPORARY SEQUENCE'   WHEN 'v' THEN 'TEMPORARY VIEW'   ELSE NULL   END  END  WHEN false THEN CASE c.relkind  WHEN 'r' THEN 'TABLE'  WHEN 'p' THEN 'PARTITIONED TABLE'  WHEN 'i' THEN 'INDEX'  WHEN 'P' then 'PARTITIONED INDEX'  WHEN 'S' THEN 'SEQUENCE'  WHEN 'v' THEN 'VIEW'  WHEN 'c' THEN 'TYPE'  WHEN 'f' THEN 'FOREIGN TABLE'  WHEN 'm' THEN 'MATERIALIZED VIEW'  ELSE NULL  END  ELSE NULL  END  AS TABLE_TYPE, d.description AS REMARKS,  '' as TYPE_CAT, '' as TYPE_SCHEM, '' as TYPE_NAME, '' AS SELF_REFERENCING_COL_NAME, '' AS REF_GENERATION  FROM pg_catalog.pg_namespace n, pg_catalog.pg_class c  LEFT JOIN (select * from (select 0 as objoid, 0 as classoid, 0 as objsubid, '' as description) pg_description where false) d ON (c.oid = d.objoid AND d.objsubid = 0  and d.classoid = 0)  WHERE c.relnamespace = n.oid";
@@ -149,14 +165,25 @@ public class PgJdbcCatalog {
       "SELECT NULL AS TABLE_CAT, n.nspname AS TABLE_SCHEM, c.relname AS TABLE_NAME,  CASE n.nspname ~ '^pg_' OR n.nspname = 'information_schema'  WHEN true THEN CASE  WHEN n.nspname = 'pg_catalog' OR n.nspname = 'information_schema' THEN CASE c.relkind   WHEN 'r' THEN 'SYSTEM TABLE'   WHEN 'v' THEN 'SYSTEM VIEW'   WHEN 'i' THEN 'SYSTEM INDEX'   ELSE NULL   END  WHEN n.nspname = 'pg_toast' THEN CASE c.relkind   WHEN 'r' THEN 'SYSTEM TOAST TABLE'   WHEN 'i' THEN 'SYSTEM TOAST INDEX'   ELSE NULL   END  ELSE CASE c.relkind   WHEN 'r' THEN 'TEMPORARY TABLE'   WHEN 'p' THEN 'TEMPORARY TABLE'   WHEN 'i' THEN 'TEMPORARY INDEX'   WHEN 'S' THEN 'TEMPORARY SEQUENCE'   WHEN 'v' THEN 'TEMPORARY VIEW'   ELSE NULL   END  END  WHEN false THEN CASE c.relkind  WHEN 'r' THEN 'TABLE'  WHEN 'p' THEN 'TABLE'  WHEN 'i' THEN 'INDEX'  WHEN 'S' THEN 'SEQUENCE'  WHEN 'v' THEN 'VIEW'  WHEN 'c' THEN 'TYPE'  WHEN 'f' THEN 'FOREIGN TABLE'  WHEN 'm' THEN 'MATERIALIZED VIEW'  ELSE NULL  END  ELSE NULL  END  AS TABLE_TYPE, d.description AS REMARKS  FROM pg_catalog.pg_namespace n, pg_catalog.pg_class c  LEFT JOIN pg_catalog.pg_description d ON (c.oid = d.objoid AND d.objsubid = 0)  LEFT JOIN pg_catalog.pg_class dc ON (d.classoid=dc.oid AND dc.relname='pg_class')  LEFT JOIN pg_catalog.pg_namespace dn ON (dn.oid=dc.relnamespace AND dn.nspname='pg_catalog')  WHERE c.relnamespace = n.oid  ";
   public static final String PG_JDBC_GET_TABLES_PREFIX_8 =
       "SELECT NULL AS TABLE_CAT, n.nspname AS TABLE_SCHEM, c.relname AS TABLE_NAME,  CASE n.nspname ~ '^pg_' OR n.nspname = 'information_schema'  WHEN true THEN CASE  WHEN n.nspname = 'pg_catalog' OR n.nspname = 'information_schema' THEN CASE c.relkind   WHEN 'r' THEN 'SYSTEM TABLE'   WHEN 'v' THEN 'SYSTEM VIEW'   WHEN 'i' THEN 'SYSTEM INDEX'   ELSE NULL   END  WHEN n.nspname = 'pg_toast' THEN CASE c.relkind   WHEN 'r' THEN 'SYSTEM TOAST TABLE'   WHEN 'i' THEN 'SYSTEM TOAST INDEX'   ELSE NULL   END  ELSE CASE c.relkind   WHEN 'r' THEN 'TEMPORARY TABLE'   WHEN 'i' THEN 'TEMPORARY INDEX'   WHEN 'S' THEN 'TEMPORARY SEQUENCE'   WHEN 'v' THEN 'TEMPORARY VIEW'   ELSE NULL   END  END  WHEN false THEN CASE c.relkind  WHEN 'r' THEN 'TABLE'  WHEN 'i' THEN 'INDEX'  WHEN 'S' THEN 'SEQUENCE'  WHEN 'v' THEN 'VIEW'  WHEN 'c' THEN 'TYPE'  WHEN 'f' THEN 'FOREIGN TABLE'  WHEN 'm' THEN 'MATERIALIZED VIEW'  ELSE NULL  END  ELSE NULL  END  AS TABLE_TYPE, d.description AS REMARKS  FROM pg_catalog.pg_namespace n, pg_catalog.pg_class c  LEFT JOIN pg_catalog.pg_description d ON (c.oid = d.objoid AND d.objsubid = 0)  LEFT JOIN pg_catalog.pg_class dc ON (d.classoid=dc.oid AND dc.relname='pg_class')  LEFT JOIN pg_catalog.pg_namespace dn ON (dn.oid=dc.relnamespace AND dn.nspname='pg_catalog')  WHERE c.relnamespace = n.oid  ";
+  public static final String PG_JDBC_GET_TABLES_PREFIX_9 =
+      "SELECT current_database() AS \"TABLE_CAT\", n.nspname AS \"TABLE_SCHEM\", c.relname AS \"TABLE_NAME\",  CASE n.nspname ~ '^pg_' OR n.nspname = 'information_schema'  WHEN true THEN CASE  WHEN n.nspname = 'pg_catalog' OR n.nspname = 'information_schema' THEN CASE c.relkind   WHEN 'r' THEN 'SYSTEM TABLE'   WHEN 'v' THEN 'SYSTEM VIEW'   WHEN 'i' THEN 'SYSTEM INDEX'   ELSE NULL   END  WHEN n.nspname = 'pg_toast' THEN CASE c.relkind   WHEN 'r' THEN 'SYSTEM TOAST TABLE'   WHEN 'i' THEN 'SYSTEM TOAST INDEX'   ELSE NULL   END  ELSE CASE c.relkind   WHEN 'r' THEN 'TEMPORARY TABLE'   WHEN 'p' THEN 'TEMPORARY TABLE'   WHEN 'i' THEN 'TEMPORARY INDEX'   WHEN 'S' THEN 'TEMPORARY SEQUENCE'   WHEN 'v' THEN 'TEMPORARY VIEW'   ELSE NULL   END  END  WHEN false THEN CASE c.relkind  WHEN 'r' THEN 'TABLE'  WHEN 'p' THEN 'PARTITIONED TABLE'  WHEN 'i' THEN 'INDEX'  WHEN 'P' then 'PARTITIONED INDEX'  WHEN 'S' THEN 'SEQUENCE'  WHEN 'v' THEN 'VIEW'  WHEN 'c' THEN 'TYPE'  WHEN 'f' THEN 'FOREIGN TABLE'  WHEN 'm' THEN 'MATERIALIZED VIEW'  ELSE NULL  END  ELSE NULL  END  AS \"TABLE_TYPE\", d.description AS \"REMARKS\",  '' as \"TYPE_CAT\", '' as \"TYPE_SCHEM\", '' as \"TYPE_NAME\", '' AS \"SELF_REFERENCING_COL_NAME\", '' AS \"REF_GENERATION\"";
   public static final String PG_JDBC_GET_TABLES_REPLACEMENT =
       "SELECT TABLE_CATALOG AS TABLE_CAT, TABLE_SCHEMA AS TABLE_SCHEM, TABLE_NAME AS TABLE_NAME,\n"
           + "       CASE WHEN TABLE_TYPE = 'BASE TABLE' THEN 'TABLE' ELSE TABLE_TYPE END AS TABLE_TYPE,\n"
           + "       NULL AS REMARKS, NULL AS TYPE_CAT, NULL AS TYPE_SCHEM, NULL AS TYPE_NAME,\n"
           + "       NULL AS SELF_REFERENCING_COL_NAME, NULL AS REF_GENERATION\n"
           + "FROM INFORMATION_SCHEMA.TABLES AS T\n";
+  public static final String PG_JDBC_GET_TABLES_REPLACEMENT_UPPER_CASE =
+      "SELECT TABLE_CATALOG AS \"TABLE_CAT\", TABLE_SCHEMA AS \"TABLE_SCHEM\", TABLE_NAME AS \"TABLE_NAME\",\n"
+          + "       CASE WHEN TABLE_TYPE = 'BASE TABLE' THEN 'TABLE' ELSE TABLE_TYPE END AS \"TABLE_TYPE\",\n"
+          + "       NULL AS \"REMARKS\", NULL AS \"TYPE_CAT\", NULL AS \"TYPE_SCHEM\", NULL AS \"TYPE_NAME\",\n"
+          + "       NULL AS \"SELF_REFERENCING_COL_NAME\", NULL AS \"REF_GENERATION\"\n"
+          + "FROM INFORMATION_SCHEMA.TABLES AS T\n";
 
-  // This prefix is used for versions [42.3.2, ...).
+  // This prefix is used for versions [42.7.5, ...).
+  public static final String PG_JDBC_GET_COLUMNS_PREFIX_V42_7_5 =
+      "SELECT * FROM (SELECT current_database(), n.nspname,c.relname,a.attname,a.atttypid,a.attnotnull  OR (t.typtype = 'd' AND t.typnotnull) AS attnotnull,a.atttypmod,a.attlen,t.typtypmod,row_number() OVER (PARTITION BY a.attrelid ORDER BY a.attnum) AS attnum, nullif(a.attidentity, '') as attidentity,nullif(a.attgenerated, '') as attgenerated,pg_catalog.pg_get_expr(def.adbin, def.adrelid) AS adsrc,dsc.description,t.typbasetype,t.typtype  FROM pg_catalog.pg_namespace n  JOIN pg_catalog.pg_class c ON (c.relnamespace = n.oid)  JOIN pg_catalog.pg_attribute a ON (a.attrelid=c.oid)  JOIN pg_catalog.pg_type t ON (a.atttypid = t.oid)  LEFT JOIN pg_catalog.pg_attrdef def ON (a.attrelid=def.adrelid AND a.attnum = def.adnum)  LEFT JOIN pg_catalog.pg_description dsc ON (c.oid=dsc.objoid AND a.attnum = dsc.objsubid)  LEFT JOIN pg_catalog.pg_class dc ON (dc.oid=dsc.classoid AND dc.relname='pg_class')  LEFT JOIN pg_catalog.pg_namespace dn ON (dc.relnamespace=dn.oid AND dn.nspname='pg_catalog')";
+  // This prefix is used for versions [42.3.2, 42.7.4].
   public static final String PG_JDBC_GET_COLUMNS_PREFIX_1 =
       "SELECT * FROM (SELECT n.nspname,c.relname,a.attname,a.atttypid,a.attnotnull OR (t.typtype = 'd' AND t.typnotnull) AS attnotnull,a.atttypmod,a.attlen,t.typtypmod,row_number() OVER (PARTITION BY a.attrelid ORDER BY a.attnum) AS attnum, nullif(a.attidentity, '') as attidentity,nullif(a.attgenerated, '') as attgenerated,pg_catalog.pg_get_expr(def.adbin, def.adrelid) AS adsrc,dsc.description,t.typbasetype,t.typtype  FROM pg_catalog.pg_namespace n  JOIN pg_catalog.pg_class c ON (c.relnamespace = n.oid)  JOIN pg_catalog.pg_attribute a ON (a.attrelid=c.oid)  JOIN pg_catalog.pg_type t ON (a.atttypid = t.oid)  LEFT JOIN pg_catalog.pg_attrdef def ON (a.attrelid=def.adrelid AND a.attnum = def.adnum)  LEFT JOIN pg_catalog.pg_description dsc ON (c.oid=dsc.objoid AND a.attnum = dsc.objsubid)  LEFT JOIN pg_catalog.pg_class dc ON (dc.oid=dsc.classoid AND dc.relname='pg_class')  LEFT JOIN pg_catalog.pg_namespace dn ON (dc.relnamespace=dn.oid AND dn.nspname='pg_catalog')";
   // This prefix is used for versions [42.2.9, 42.3.1].
@@ -211,7 +238,7 @@ public class PgJdbcCatalog {
       "SELECT n.nspname,c.relname,a.attname,a.atttypid,a.attnotnull OR (t.typtype = 'd' AND t.typnotnull) AS attnotnull,a.atttypmod,a.attlen,a.attnum,pg_catalog.pg_get_expr(def.adbin, def.adrelid) AS adsrc,dsc.description,t.typbasetype,t.typtype  FROM pg_catalog.pg_namespace n  JOIN pg_catalog.pg_class c ON (c.relnamespace = n.oid)  JOIN pg_catalog.pg_attribute a ON (a.attrelid=c.oid)  JOIN pg_catalog.pg_type t ON (a.atttypid = t.oid)  LEFT JOIN pg_catalog.pg_attrdef def ON (a.attrelid=def.adrelid AND a.attnum = def.adnum)  LEFT JOIN pg_catalog.pg_description dsc ON (c.oid=dsc.objoid AND a.attnum = dsc.objsubid)  LEFT JOIN pg_catalog.pg_class dc ON (dc.oid=dsc.classoid AND dc.relname='pg_class')  LEFT JOIN pg_catalog.pg_namespace dn ON (dc.relnamespace=dn.oid AND dn.nspname='pg_catalog')";
 
   public static final String PG_JDBC_GET_COLUMNS_REPLACEMENT =
-      "SELECT TABLE_CATALOG AS \"TABLE_CAT\", TABLE_SCHEMA AS nspname, TABLE_NAME AS relname, COLUMN_NAME AS attname, '' as typtype,\n"
+      "SELECT TABLE_CATALOG as current_database, TABLE_CATALOG AS \"TABLE_CAT\", TABLE_SCHEMA AS nspname, TABLE_NAME AS relname, COLUMN_NAME AS attname, '' as typtype,\n"
           + "       CASE\n"
           + "           WHEN SPANNER_TYPE = 'boolean' THEN 16\n"
           + "           WHEN SPANNER_TYPE = 'boolean[]' THEN 1000\n"
@@ -288,6 +315,28 @@ public class PgJdbcCatalog {
           + "        END AS \"IS_GENERATEDCOLUMN\"\n"
           + "FROM INFORMATION_SCHEMA.COLUMNS C\n";
 
+  public static final String PG_JDBC_GET_INDEXES_PREFIX_V42_7_5 =
+      "SELECT"
+          + "     tmp.TABLE_CAT AS \"TABLE_CAT\","
+          + "     tmp.TABLE_SCHEM AS \"TABLE_SCHEM\","
+          + "     tmp.TABLE_NAME AS \"TABLE_NAME\","
+          + "     tmp.NON_UNIQUE AS \"NON_UNIQUE\","
+          + "     tmp.INDEX_QUALIFIER AS \"INDEX_QUALIFIER\","
+          + "     tmp.INDEX_NAME AS \"INDEX_NAME\","
+          + "     tmp.TYPE AS \"TYPE\","
+          + "     tmp.ORDINAL_POSITION AS \"ORDINAL_POSITION\","
+          + "     trim(both '\"' from pg_catalog.pg_get_indexdef(tmp.CI_OID, tmp.ORDINAL_POSITION, false)) AS \"COLUMN_NAME\","
+          + "   CASE tmp.AM_NAME"
+          + "     WHEN 'btree' THEN CASE tmp.I_INDOPTION[tmp.ORDINAL_POSITION - 1] & 1::smallint"
+          + "       WHEN 1 THEN 'D'"
+          + "       ELSE 'A'"
+          + "     END"
+          + "     ELSE NULL"
+          + "   END AS \"ASC_OR_DESC\","
+          + "     tmp.CARDINALITY AS \"CARDINALITY\","
+          + "     tmp.PAGES AS \"PAGES\","
+          + "     tmp.FILTER_CONDITION AS \"FILTER_CONDITION\""
+          + "FROM (";
   public static final String PG_JDBC_GET_INDEXES_PREFIX_1 =
       "SELECT "
           + "    tmp.TABLE_CAT, "
@@ -386,6 +435,8 @@ public class PgJdbcCatalog {
           + "                AND IDX.TABLE_NAME=COL.TABLE_NAME\n"
           + "                AND IDX.INDEX_NAME=COL.INDEX_NAME\n";
 
+  public static final String PG_JDBC_GET_PRIMARY_KEY_PREFIX_V42_7_5 =
+      "SELECT        result.TABLE_CAT AS \"TABLE_CAT\",        result.TABLE_SCHEM AS \"TABLE_SCHEM\",        result.TABLE_NAME AS \"TABLE_NAME\",        result.COLUMN_NAME AS \"COLUMN_NAME\",        result.KEY_SEQ AS \"KEY_SEQ\",        result.PK_NAME AS \"PK_NAME\"";
   public static final String PG_JDBC_GET_PRIMARY_KEY_PREFIX_1 =
       "SELECT        result.TABLE_CAT,        result.TABLE_SCHEM,        result.TABLE_NAME,        result.COLUMN_NAME,        result.KEY_SEQ,        result.PK_NAME FROM      (SELECT NULL AS TABLE_CAT, n.nspname AS TABLE_SCHEM,   ct.relname AS TABLE_NAME, a.attname AS COLUMN_NAME,   (information_schema._pg_expandarray(i.indkey)).n AS KEY_SEQ, ci.relname AS PK_NAME,   information_schema._pg_expandarray(i.indkey) AS KEYS, a.attnum AS A_ATTNUM 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 pg_catalog.pg_index i ON ( a.attrelid = i.indrelid)   JOIN pg_catalog.pg_class ci ON (ci.oid = i.indexrelid)";
   public static final String PG_JDBC_GET_PRIMARY_KEY_PREFIX_2 =
@@ -404,12 +455,16 @@ public class PgJdbcCatalog {
       "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 =
       "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 = 'r'";
+  public static final String PG_JDBC_GET_TABLE_PRIVILEGES_PREFIX_3 =
+      "SELECT current_database(), n.nspname,c.relname,r.rolname,c.relacl  FROM pg_catalog.pg_namespace n, pg_catalog.pg_class c, pg_catalog.pg_roles r ";
   public static final String PG_JDBC_GET_TABLE_PRIVILEGES_REPLACEMENT =
-      "select '' as nspname, '' as relname, '' as rolname, '' as relacl from (select 1) t where false";
+      "select '' as current_database, '' as nspname, '' as relname, '' as rolname, '' as relacl from (select 1) t where false";
   public static final String PG_JDBC_GET_COLUMN_PRIVILEGES_PREFIX_1 =
       "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_PREFIX_V42_7_5 =
+      "SELECT current_database(), 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";
   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";
 
@@ -562,6 +617,9 @@ public class PgJdbcCatalog {
           + " pg_catalog.pg_constraint con, "
           + " pg_catalog.generate_series(1, 32) pos(n), "
           + " pg_catalog.pg_class pkic";
+  public static final String PG_JDBC_EXPORTED_IMPORTED_KEYS_PREFIX_V42_7_5 =
+      "SELECT current_database() AS \"PKTABLE_CAT\", pkn.nspname AS \"PKTABLE_SCHEM\", pkc.relname AS \"PKTABLE_NAME\", pka.attname AS \"PKCOLUMN_NAME\", "
+          + "current_database() AS \"FKTABLE_CAT\", fkn.nspname AS \"FKTABLE_SCHEM\", fkc.relname AS \"FKTABLE_NAME\", fka.attname AS \"FKCOLUMN_NAME\", ";
   public static final String PG_JDBC_EXPORTED_IMPORTED_KEYS_REPLACEMENT =
       "SELECT PARENT.TABLE_CATALOG AS PKTABLE_CAT, PARENT.TABLE_SCHEMA AS PKTABLE_SCHEM, PARENT.TABLE_NAME AS PKTABLE_NAME,\n"
           + "       PARENT.COLUMN_NAME AS PKCOLUMN_NAME, CHILD.TABLE_CATALOG AS FKTABLE_CAT, CHILD.TABLE_SCHEMA AS FKTABLE_SCHEM,\n"
@@ -575,6 +633,19 @@ public class PgJdbcCatalog {
           + "INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE CHILD  ON COALESCE(CONSTRAINTS.CONSTRAINT_CATALOG, '')=COALESCE(CHILD.CONSTRAINT_CATALOG, '') AND CONSTRAINTS.CONSTRAINT_SCHEMA= CHILD.CONSTRAINT_SCHEMA AND CONSTRAINTS.CONSTRAINT_NAME= CHILD.CONSTRAINT_NAME\n"
           + "INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE PARENT ON COALESCE(CONSTRAINTS.UNIQUE_CONSTRAINT_CATALOG, '')=COALESCE(PARENT.CONSTRAINT_CATALOG, '') AND CONSTRAINTS.UNIQUE_CONSTRAINT_SCHEMA=PARENT.CONSTRAINT_SCHEMA AND CONSTRAINTS.UNIQUE_CONSTRAINT_NAME=PARENT.CONSTRAINT_NAME AND PARENT.ORDINAL_POSITION=CHILD.POSITION_IN_UNIQUE_CONSTRAINT\n"
           + "WHERE TRUE\n";
+  public static final String PG_JDBC_EXPORTED_IMPORTED_KEYS_REPLACEMENT_UPPER_CASE =
+      "SELECT PARENT.TABLE_CATALOG AS \"PKTABLE_CAT\", PARENT.TABLE_SCHEMA AS \"PKTABLE_SCHEM\", PARENT.TABLE_NAME AS \"PKTABLE_NAME\",\n"
+          + "       PARENT.COLUMN_NAME AS \"PKCOLUMN_NAME\", CHILD.TABLE_CATALOG AS \"FKTABLE_CAT\", CHILD.TABLE_SCHEMA AS \"FKTABLE_SCHEM\",\n"
+          + "       CHILD.TABLE_NAME AS \"FKTABLE_NAME\", CHILD.COLUMN_NAME AS \"FKCOLUMN_NAME\",\n"
+          + "       CHILD.ORDINAL_POSITION AS \"KEY_SEQ\",\n"
+          + "       1 AS \"UPDATE_RULE\", -- 1 = importedKeyRestrict\n"
+          + "       1 AS \"DELETE_RULE\", -- 1 = importedKeyRestrict\n"
+          + "       CONSTRAINTS.CONSTRAINT_NAME AS \"FK_NAME\", CONSTRAINTS.UNIQUE_CONSTRAINT_NAME AS \"PK_NAME\",\n"
+          + "       7 AS \"DEFERRABILITY\" -- 7 = importedKeyNotDeferrable\n"
+          + "FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS CONSTRAINTS\n"
+          + "INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE CHILD  ON COALESCE(CONSTRAINTS.CONSTRAINT_CATALOG, '')=COALESCE(CHILD.CONSTRAINT_CATALOG, '') AND CONSTRAINTS.CONSTRAINT_SCHEMA= CHILD.CONSTRAINT_SCHEMA AND CONSTRAINTS.CONSTRAINT_NAME= CHILD.CONSTRAINT_NAME\n"
+          + "INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE PARENT ON COALESCE(CONSTRAINTS.UNIQUE_CONSTRAINT_CATALOG, '')=COALESCE(PARENT.CONSTRAINT_CATALOG, '') AND CONSTRAINTS.UNIQUE_CONSTRAINT_SCHEMA=PARENT.CONSTRAINT_SCHEMA AND CONSTRAINTS.UNIQUE_CONSTRAINT_NAME=PARENT.CONSTRAINT_NAME AND PARENT.ORDINAL_POSITION=CHILD.POSITION_IN_UNIQUE_CONSTRAINT\n"
+          + "WHERE TRUE\n";
 
   public static final String PG_DESCRIPTION =
       "select * from (select 0 as objoid, 0 as classoid, 0 as objsubid, '' as description) pg_description where false";
diff --git a/versions.txt b/versions.txt
index 7fd1f4dd..2098a69b 100644
--- a/versions.txt
+++ b/versions.txt
@@ -1,4 +1,4 @@
 # Format:
 # module:released-version:current-version
 
-google-cloud-spanner-pgadapter:0.42.2:0.42.3-SNAPSHOT
+google-cloud-spanner-pgadapter:0.42.3:0.42.4-SNAPSHOT
diff --git a/wrappers/golang/go.mod b/wrappers/golang/go.mod
index 5a870d75..210d5704 100644
--- a/wrappers/golang/go.mod
+++ b/wrappers/golang/go.mod
@@ -5,7 +5,7 @@ go 1.22
 toolchain go1.23.5
 
 require (
-	github.com/docker/docker v27.5.0+incompatible
+	github.com/docker/docker v27.5.1+incompatible
 	github.com/testcontainers/testcontainers-go v0.35.0
 	golang.org/x/oauth2 v0.25.0
 )
diff --git a/wrappers/golang/go.sum b/wrappers/golang/go.sum
index 9b305682..e6e0468c 100644
--- a/wrappers/golang/go.sum
+++ b/wrappers/golang/go.sum
@@ -27,6 +27,8 @@ github.com/docker/docker v27.4.1+incompatible h1:ZJvcY7gfwHn1JF48PfbyXg7Jyt9ZCWD
 github.com/docker/docker v27.4.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
 github.com/docker/docker v27.5.0+incompatible h1:um++2NcQtGRTz5eEgO6aJimo6/JxrTXC941hd05JO6U=
 github.com/docker/docker v27.5.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
+github.com/docker/docker v27.5.1+incompatible h1:4PYU5dnBYqRQi0294d1FBECqT9ECWeQAIfE8q4YnPY8=
+github.com/docker/docker v27.5.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
 github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
 github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
 github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=


Test patch:
diff --git a/samples/snippets/dotnet-snippets/sample-tests/sample-tests.csproj b/samples/snippets/dotnet-snippets/sample-tests/sample-tests.csproj
index 043240cf..0ecf1f63 100644
--- a/samples/snippets/dotnet-snippets/sample-tests/sample-tests.csproj
+++ b/samples/snippets/dotnet-snippets/sample-tests/sample-tests.csproj
@@ -11,7 +11,7 @@
     </PropertyGroup>
 
     <ItemGroup>
-        <PackageReference Include="coverlet.collector" Version="6.0.3"/>
+        <PackageReference Include="coverlet.collector" Version="6.0.4"/>
         <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
         <PackageReference Include="NUnit" Version="4.3.2" />
         <PackageReference Include="NUnit.Analyzers" Version="4.6.0"/>
diff --git a/samples/snippets/php-snippets/test/SamplesTest.php b/samples/snippets/php-snippets/test/SamplesTest.php
new file mode 100644
index 00000000..13fda330
--- /dev/null
+++ b/samples/snippets/php-snippets/test/SamplesTest.php
@@ -0,0 +1,162 @@
+<?php
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+require '../vendor/autoload.php';
+require '../samples/create_tables.php';
+require '../samples/create_connection.php';
+require '../samples/write_data_with_dml.php';
+require '../samples/write_data_with_dml_batch.php';
+require '../samples/write_data_with_copy.php';
+require '../samples/query_data.php';
+require '../samples/query_data_with_parameter.php';
+require '../samples/statement_timeout.php';
+require '../samples/add_column.php';
+require '../samples/ddl_batch.php';
+require '../samples/update_data_with_copy.php';
+require '../samples/query_data_with_new_column.php';
+require '../samples/update_data_with_transaction.php';
+require '../samples/tags.php';
+require '../samples/read_only_transaction.php';
+require '../samples/data_boost.php';
+require '../samples/partitioned_dml.php';
+
+use PHPUnit\Framework\TestCase;
+use Testcontainers\Container\Container;
+use Testcontainers\Wait\WaitForLog;
+
+class SamplesTest extends TestCase
+{
+    function test_run_samples(): void
+    {
+        [$pg_adapter, $port] = start_pg_adapter();
+        $host = "localhost";
+        $database = "test-database";
+
+        ob_start();
+        create_tables($host, $port, $database);
+        $this->assertEquals("Created Singers & Albums tables in database: [test-database]\n", ob_get_clean());
+
+        ob_start();
+        create_connection($host, $port, $database);
+        $this->assertEquals("Greeting from Cloud Spanner PostgreSQL: Hello world!\n", ob_get_clean());
+
+        ob_start();
+        write_data_with_dml($host, $port, $database);
+        $this->assertEquals("4 records inserted\n", ob_get_clean());
+
+        ob_start();
+        write_data_with_dml_batch($host, $port, $database);
+        $this->assertEquals("{1,1,1} records inserted\n", ob_get_clean());
+
+        ob_start();
+        write_data_with_copy($host, $port, $database);
+        $this->assertEquals("Copied 5 singers\nCopied 5 albums\n", ob_get_clean());
+
+        ob_start();
+        query_data($host, $port, $database);
+        $this->assertEquals("1\t1\tTotal Junk\n"
+            ."1\t2\tGo, Go, Go\n"
+            ."2\t1\tGreen\n"
+            ."2\t2\tForever Hold Your Peace\n"
+            ."2\t3\tTerrified\n",
+            ob_get_clean());
+
+        ob_start();
+        query_data_with_parameter($host, $port, $database);
+        $this->assertEquals("12\tMelissa\tGarcia\n", ob_get_clean());
+
+        ob_start();
+        query_with_timeout($host, $port, $database);
+        $this->assertEquals("", ob_get_clean());
+
+        ob_start();
+        add_column($host, $port, $database);
+        $this->assertEquals("Added marketing_budget column\n", ob_get_clean());
+
+        ob_start();
+        ddl_batch($host, $port, $database);
+        $this->assertEquals("Added venues and concerts tables\n", ob_get_clean());
+
+        ob_start();
+        update_data_with_copy($host, $port, $database);
+        $this->assertEquals("Updated 2 albums\n", ob_get_clean());
+
+        ob_start();
+        query_data_with_new_column($host, $port, $database);
+        $this->assertEquals("1\t1\t100000\n"
+            ."1\t2\t\n"
+            ."2\t1\t\n"
+            ."2\t2\t500000\n"
+            ."2\t3\t\n",
+            ob_get_clean());
+
+        ob_start();
+        update_data_with_transaction($host, $port, $database);
+        $this->assertEquals("Transferred marketing budget from Album 2 to Album 1\n", ob_get_clean());
+
+        ob_start();
+        tags($host, $port, $database);
+        $this->assertEquals("Reduced marketing budget\n", ob_get_clean());
+        
+        ob_start();
+        read_only_transaction($host, $port, $database);
+        $this->assertEquals(
+            "1\t1\tTotal Junk\n"
+            ."1\t2\tGo, Go, Go\n"
+            ."2\t1\tGreen\n"
+            ."2\t2\tForever Hold Your Peace\n"
+            ."2\t3\tTerrified\n"
+            ."2\t2\tForever Hold Your Peace\n"
+            ."1\t2\tGo, Go, Go\n"
+            ."2\t1\tGreen\n"
+            ."2\t3\tTerrified\n"
+            ."1\t1\tTotal Junk\n",
+            ob_get_clean());
+
+        ob_start();
+        data_boost($host, $port, $database);
+        $this->assertStringContainsString("17\tEthan\tMiller\n", ob_get_clean());
+
+        ob_start();
+        execute_partitioned_dml($host, $port, $database);
+        $this->assertEquals("Updated at least 3 albums\n", ob_get_clean());
+        
+        $pg_adapter->stop();
+    }
+    
+}
+
+function start_pg_adapter(): array
+{
+    // The 'pgadapter-emulator' Docker image is a combined Docker image of PGAdapter + the Spanner emulator.
+    // This Docker image automatically creates any Spanner instance and database that you try to connect to,
+    // which means that you don't have to manually create the instance/database before connecting to it.
+    $pg_adapter = Container::make("gcr.io/cloud-spanner-pg-adapter/pgadapter-emulator");
+    // Map port '5432' in the container to a random port on the host.
+    $pg_adapter->withPort("0", "5432");
+    $pg_adapter->withWait(new WaitForLog('Server started on port'));
+    $pg_adapter->run();
+
+    // Get the mapped host port of port '5432' in the container and use that port number to connect
+    // to PGAdapter using the PHP PDO driver.
+    $reflected_pg_adapter = new ReflectionObject($pg_adapter);
+    $inspected_data = $reflected_pg_adapter->getProperty('inspectedData');
+    $inspected_data->setAccessible(true);
+    $ports = $inspected_data->getValue($pg_adapter)[0]['NetworkSettings']['Ports'];
+    $port = $ports['5432/tcp'][0]['HostPort'];
+
+    return [$pg_adapter, $port];
+}
diff --git a/samples/snippets/php-snippets/test/config.xml b/samples/snippets/php-snippets/test/config.xml
new file mode 100644
index 00000000..93bd90a4
--- /dev/null
+++ b/samples/snippets/php-snippets/test/config.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<configuration>
+  
+</configuration>
\ No newline at end of file
diff --git a/src/test/java/com/google/cloud/spanner/pgadapter/AbortedMockServerTest.java b/src/test/java/com/google/cloud/spanner/pgadapter/AbortedMockServerTest.java
index fd706cc3..277216d4 100644
--- a/src/test/java/com/google/cloud/spanner/pgadapter/AbortedMockServerTest.java
+++ b/src/test/java/com/google/cloud/spanner/pgadapter/AbortedMockServerTest.java
@@ -39,8 +39,14 @@ import com.google.cloud.spanner.Statement;
 import com.google.cloud.spanner.connection.RandomResultSetGenerator;
 import com.google.cloud.spanner.pgadapter.error.SQLState;
 import com.google.common.collect.ImmutableList;
+import com.google.protobuf.ListValue;
+import com.google.protobuf.Value;
 import com.google.spanner.v1.ExecuteSqlRequest;
+import com.google.spanner.v1.ResultSetMetadata;
 import com.google.spanner.v1.ResultSetStats;
+import com.google.spanner.v1.StructType;
+import com.google.spanner.v1.StructType.Field;
+import com.google.spanner.v1.Type;
 import com.google.spanner.v1.TypeCode;
 import io.grpc.ManagedChannelBuilder;
 import io.grpc.Status;
@@ -85,6 +91,7 @@ public class AbortedMockServerTest extends AbstractMockServerTest {
     Class.forName("org.postgresql.Driver");
 
     addRandomResultResults();
+    JdbcMockServerTest.setupJsonbResults(mockSpanner);
     mockSpanner.setAbortProbability(0.2);
   }
 
@@ -237,8 +244,6 @@ public class AbortedMockServerTest extends AbstractMockServerTest {
 
   @Test
   public void testQueryWithParameters() throws SQLException {
-    JdbcMockServerTest.setupJsonbResults(mockSpanner);
-
     String jdbcSql =
         "select col_bigint, col_bool, col_bytea, col_float8, col_int, col_numeric, col_timestamptz, col_date, col_varchar, col_jsonb "
             + "from all_types "
@@ -914,19 +919,9 @@ public class AbortedMockServerTest extends AbstractMockServerTest {
             while (resultSet.next()) {
               assertTrue(spannerResult.next());
               for (int col = 0; col < resultSet.getMetaData().getColumnCount(); col++) {
-                // TODO: Remove once we have a replacement for pg_type, as the JDBC driver will
-                //       try to read type information from the backend when it hits an 'unknown'
-                //       type (jsonb is not one of the types that the JDBC driver will load
-                //       automatically).
-                final int jsonbColumnIndex = 6;
-                final int jsonbArrayColumnIndex = 16;
-                if (col == jsonbColumnIndex || col == jsonbArrayColumnIndex) {
-                  resultSet.getString(col + 1);
-                } else {
-                  resultSet.getObject(col + 1);
-                }
+                resultSet.getObject(col + 1);
               }
-              assertEqual(spannerResult, resultSet);
+              assertEqual(binary, spannerResult, resultSet);
               rowCount++;
             }
             assertEquals(RANDOM_RESULTS_ROW_COUNT, rowCount);
@@ -941,6 +936,74 @@ public class AbortedMockServerTest extends AbstractMockServerTest {
     }
   }
 
+  @Test
+  public void testBinaryDateYear100() throws SQLException {
+    String sql = "select dt from test";
+    Statement query = Statement.of(sql);
+    mockSpanner.putStatementResult(
+        StatementResult.query(
+            query,
+            com.google.spanner.v1.ResultSet.newBuilder()
+                .setMetadata(
+                    ResultSetMetadata.newBuilder()
+                        .setRowType(
+                            StructType.newBuilder()
+                                .addFields(
+                                    Field.newBuilder()
+                                        .setName("dt")
+                                        .setType(Type.newBuilder().setCode(TypeCode.DATE).build())
+                                        .build())
+                                .build())
+                        .build())
+                .addRows(
+                    ListValue.newBuilder()
+                        .addValues(Value.newBuilder().setStringValue("0100-02-19").build())
+                        .build())
+                .build()));
+
+    // Also get the random results using the normal Spanner client to compare the results with
+    // what is returned by PGAdapter.
+    Spanner spanner =
+        SpannerOptions.newBuilder()
+            .setProjectId("p")
+            .setHost(String.format("http://localhost:%d", spannerServer.getPort()))
+            .setCredentials(NoCredentials.getInstance())
+            .setChannelConfigurator(ManagedChannelBuilder::usePlaintext)
+            .setClientLibToken("pg-adapter")
+            .setEnableEndToEndTracing(true)
+            .build()
+            .getService();
+    DatabaseClient client = spanner.getDatabaseClient(DatabaseId.of("p", "i", "d"));
+    com.google.cloud.spanner.ResultSet spannerResult = client.singleUse().executeQuery(query);
+
+    String binaryTransferEnable =
+        "?binaryTransferEnable="
+            + ImmutableList.of(Oid.DATE).stream()
+                .map(String::valueOf)
+                .collect(Collectors.joining(","));
+
+    final int fetchSize = 3;
+    try (Connection connection = createConnection(binaryTransferEnable)) {
+      connection.createStatement().execute("set time zone utc");
+      connection.setAutoCommit(false);
+      connection.unwrap(PGConnection.class).setPrepareThreshold(-1);
+      try (PreparedStatement statement = connection.prepareStatement(sql)) {
+        statement.setFetchSize(fetchSize);
+        try (ResultSet resultSet = statement.executeQuery()) {
+          while (resultSet.next()) {
+            assertTrue(spannerResult.next());
+            assertEqual(/*binary=*/ true, spannerResult, resultSet);
+          }
+        }
+      }
+      connection.commit();
+    }
+
+    // Close the resources used by the normal Spanner client.
+    spannerResult.close();
+    spanner.close();
+  }
+
   @Test
   public void testCommitFailsDueToConcurrentModification() throws SQLException {
     String sql = "insert into foo (id, value) values (1, 'One') on conflict do nothing";
@@ -967,7 +1030,8 @@ public class AbortedMockServerTest extends AbstractMockServerTest {
     }
   }
 
-  private void assertEqual(com.google.cloud.spanner.ResultSet spannerResult, ResultSet pgResult)
+  private void assertEqual(
+      boolean binary, com.google.cloud.spanner.ResultSet spannerResult, ResultSet pgResult)
       throws SQLException {
     assertEquals(spannerResult.getColumnCount(), pgResult.getMetaData().getColumnCount());
     for (int col = 0; col < spannerResult.getColumnCount(); col++) {
@@ -1018,7 +1082,10 @@ public class AbortedMockServerTest extends AbstractMockServerTest {
             // are weird, as are potential intercalaris values.
             assertNotNull(pgResult.getDate(col + 1));
           } else {
-            assertEquals(expected, pgResult.getDate(col + 1).toLocalDate());
+            assertEquals(
+                "Date comparison failed for format " + (binary ? "binary" : "text"),
+                expected,
+                pgResult.getObject(col + 1, LocalDate.class));
           }
           break;
         case PG_JSONB:
@@ -1129,7 +1196,7 @@ public class AbortedMockServerTest extends AbstractMockServerTest {
       try (ResultSet resultSet =
           connection.createStatement().executeQuery("show application_name ")) {
         assertTrue(resultSet.next());
-        assertEquals(getExpectedInitialApplicationName(), resultSet.getString(1));
+        assertNull(resultSet.getString(1));
         assertFalse(resultSet.next());
       }
     }
@@ -1422,7 +1489,7 @@ public class AbortedMockServerTest extends AbstractMockServerTest {
 
       connection.createStatement().execute("reset all");
 
-      verifySettingValue(connection, "application_name", getExpectedInitialApplicationName());
+      verifySettingIsNull(connection, "application_name");
       verifySettingValue(connection, "search_path", "public");
     }
   }
@@ -1438,7 +1505,7 @@ public class AbortedMockServerTest extends AbstractMockServerTest {
       connection.createStatement().execute("set application_name to default");
       connection.createStatement().execute("set search_path to default");
 
-      verifySettingValue(connection, "application_name", getExpectedInitialApplicationName());
+      verifySettingIsNull(connection, "application_name");
       verifySettingValue(connection, "search_path", "public");
     }
   }
diff --git a/src/test/java/com/google/cloud/spanner/pgadapter/EmulatedPgbenchMockServerTest.java b/src/test/java/com/google/cloud/spanner/pgadapter/EmulatedPgbenchMockServerTest.java
index 9e477b2d..925aef50 100644
--- a/src/test/java/com/google/cloud/spanner/pgadapter/EmulatedPgbenchMockServerTest.java
+++ b/src/test/java/com/google/cloud/spanner/pgadapter/EmulatedPgbenchMockServerTest.java
@@ -31,11 +31,11 @@ import java.sql.Connection;
 import java.sql.DriverManager;
 import java.sql.SQLException;
 import java.sql.SQLWarning;
+import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
-import org.postgresql.PGProperty;
 import org.postgresql.util.PSQLException;
 import org.postgresql.util.PSQLWarning;
 
@@ -48,17 +48,23 @@ public class EmulatedPgbenchMockServerTest extends AbstractMockServerTest {
     Class.forName("org.postgresql.Driver");
   }
 
+  @BeforeClass
+  public static void setDetectClient() {
+    ClientAutoDetector.FORCE_DETECT_CLIENT.set(WellKnownClient.PGBENCH);
+  }
+
+  @AfterClass
+  public static void clearDetectClient() {
+    ClientAutoDetector.FORCE_DETECT_CLIENT.set(null);
+  }
+
   /**
    * Creates a JDBC connection string that instructs the PG JDBC driver to use the default simple
-   * mode. It also adds 'pgbench' as the application name, which will make PGAdapter automatically
-   * recognize the connection as a pgbench connection.
+   * mode.
    */
   private String createUrl() {
     return String.format(
-        "jdbc:postgresql://localhost:%d/db?preferQueryMode=simple&%s=pgbench&%s=090000",
-        pgServer.getLocalPort(),
-        PGProperty.APPLICATION_NAME.getName(),
-        PGProperty.ASSUME_MIN_SERVER_VERSION.getName());
+        "jdbc:postgresql://localhost:%d/db?preferQueryMode=simple", pgServer.getLocalPort());
   }
 
   @Test
diff --git a/src/test/java/com/google/cloud/spanner/pgadapter/EmulatedPsqlMockServerTest.java b/src/test/java/com/google/cloud/spanner/pgadapter/EmulatedPsqlMockServerTest.java
index 5ec2f0c1..4b6d2c8a 100644
--- a/src/test/java/com/google/cloud/spanner/pgadapter/EmulatedPsqlMockServerTest.java
+++ b/src/test/java/com/google/cloud/spanner/pgadapter/EmulatedPsqlMockServerTest.java
@@ -26,6 +26,8 @@ import com.google.cloud.spanner.MockSpannerServiceImpl.StatementResult;
 import com.google.cloud.spanner.Statement;
 import com.google.cloud.spanner.pgadapter.error.PGException;
 import com.google.cloud.spanner.pgadapter.statements.IntermediateStatement;
+import com.google.cloud.spanner.pgadapter.utils.ClientAutoDetector;
+import com.google.cloud.spanner.pgadapter.utils.ClientAutoDetector.WellKnownClient;
 import com.google.common.collect.ImmutableList;
 import com.google.protobuf.ListValue;
 import com.google.protobuf.Value;
@@ -57,12 +59,12 @@ import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.util.List;
 import org.junit.After;
+import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
-import org.postgresql.PGProperty;
 import org.postgresql.util.PSQLException;
 
 @RunWith(JUnit4.class)
@@ -77,6 +79,16 @@ public class EmulatedPsqlMockServerTest extends AbstractMockServerTest {
     Class.forName("org.postgresql.Driver");
   }
 
+  @BeforeClass
+  public static void setDetectClient() {
+    ClientAutoDetector.FORCE_DETECT_CLIENT.set(WellKnownClient.PSQL);
+  }
+
+  @AfterClass
+  public static void clearDetectClient() {
+    ClientAutoDetector.FORCE_DETECT_CLIENT.set(null);
+  }
+
   @BeforeClass
   public static void startMockSpannerAndPgAdapterServers() throws Exception {
     // Start PGAdapter without a default database.
@@ -95,21 +107,12 @@ public class EmulatedPsqlMockServerTest extends AbstractMockServerTest {
   /**
    * Creates a JDBC connection string that instructs the PG JDBC driver to use the default simple
    * mode for queries and DML statements. This makes the JDBC driver behave in (much) the same way
-   * as psql. It also adds 'psql' as the application name, which will make PGAdapter automatically
-   * recognize the connection as a psql connection.
+   * as psql.
    */
   private String createUrl(String database) {
-    return createUrl(database, "psql");
-  }
-
-  private String createUrl(String database, String applicationName) {
     return String.format(
-        "jdbc:postgresql://localhost:%d/%s?preferQueryMode=simple&%s=%s&%s=090000",
-        pgServer.getLocalPort(),
-        database,
-        PGProperty.APPLICATION_NAME.getName(),
-        applicationName,
-        PGProperty.ASSUME_MIN_SERVER_VERSION.getName());
+        "jdbc:postgresql://localhost:%d/%s?preferQueryMode=simple",
+        pgServer.getLocalPort(), database);
   }
 
   @Test
@@ -201,22 +204,15 @@ public class EmulatedPsqlMockServerTest extends AbstractMockServerTest {
     }
   }
 
-  @Test
-  public void testShowApplicationName() throws SQLException {
-    try (Connection connection = DriverManager.getConnection(createUrl("my-db"))) {
-      try (ResultSet resultSet =
-          connection.createStatement().executeQuery("show application_name")) {
-        assertTrue(resultSet.next());
-        assertEquals("psql", resultSet.getString(1));
-        assertFalse(resultSet.next());
-      }
-    }
-  }
-
   @Test
   public void testConnectToNonExistingInstance() {
-    for (String appName : new String[] {"psql", "other-app"}) {
+    for (boolean isPsql : new boolean[] {true, false}) {
       try {
+        if (isPsql) {
+          setDetectClient();
+        } else {
+          clearDetectClient();
+        }
         mockSpanner.setExecuteStreamingSqlExecutionTime(
             SimulatedExecutionTime.ofStickyException(
                 newStatusResourceNotFoundException(
@@ -241,10 +237,9 @@ public class EmulatedPsqlMockServerTest extends AbstractMockServerTest {
         SQLException exception =
             assertThrows(
                 SQLException.class,
-                () -> DriverManager.getConnection(createUrl("non-existing-db", appName)));
+                () -> DriverManager.getConnection(createUrl("non-existing-db")));
         assertTrue(exception.getMessage(), exception.getMessage().contains("NOT_FOUND"));
 
-        boolean isPsql = "psql".equals(appName);
         assertEquals(
             exception.getMessage(),
             isPsql,
@@ -255,6 +250,7 @@ public class EmulatedPsqlMockServerTest extends AbstractMockServerTest {
             exception.getMessage().contains("\tprojects/p/instances/i\n"));
       } finally {
         closeSpannerPool(true);
+        setDetectClient();
       }
     }
   }
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 daefa5a6..fa0ee6a2 100644
--- a/src/test/java/com/google/cloud/spanner/pgadapter/ITJdbcMetadataTest.java
+++ b/src/test/java/com/google/cloud/spanner/pgadapter/ITJdbcMetadataTest.java
@@ -53,13 +53,12 @@ import org.junit.runners.JUnit4;
 public class ITJdbcMetadataTest implements IntegrationTest {
   private static final String[] VERSIONS =
       new String[] {
-        "42.7.4", "42.7.3", "42.7.2", "42.7.1", "42.7.0", "42.6.0", "42.5.4", "42.5.3", "42.5.2",
-        "42.5.1", "42.5.0", "42.4.2", "42.4.1", "42.4.0", "42.3.6", "42.3.5", "42.3.4", "42.3.3",
-        "42.3.2", "42.3.1", "42.3.0", "42.2.25", "42.2.24", "42.2.23", "42.2.22", "42.2.21",
-        "42.2.20", "42.2.19", "42.2.18", "42.2.17", "42.2.16", "42.2.15", "42.2.14", "42.2.13",
-        "42.2.12", "42.2.11", "42.2.10", "42.2.9", "42.2.8", "42.2.7", "42.2.6", "42.2.5", "42.2.4",
-        "42.2.3", "42.2.2", "42.2.1", "42.2.0", "42.1.4",
-        /* "42.1.3", "42.1.2", "42.1.1", "42.1.0", "42.0.0" */
+        "42.7.5", "42.7.4", "42.7.3", "42.7.2", "42.7.1", "42.7.0", "42.6.0", "42.5.4", "42.5.3",
+        "42.5.2", "42.5.1", "42.5.0", "42.4.2", "42.4.1", "42.4.0", "42.3.6", "42.3.5", "42.3.4",
+        "42.3.3", "42.3.2", "42.3.1", "42.3.0", "42.2.25", "42.2.24", "42.2.23", "42.2.22",
+        "42.2.21", "42.2.20", "42.2.19", "42.2.18", "42.2.17", "42.2.16", "42.2.15", "42.2.14",
+        "42.2.13", "42.2.12", "42.2.11", "42.2.10", "42.2.9", "42.2.8", "42.2.7", "42.2.6",
+        "42.2.5", "42.2.4", "42.2.3", "42.2.2", "42.2.1", "42.2.0", "42.1.4"
       };
 
   private static final PgAdapterTestEnv testEnv = new PgAdapterTestEnv();
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 b16cbb8a..7c31f0e2 100644
--- a/src/test/java/com/google/cloud/spanner/pgadapter/ITJdbcTest.java
+++ b/src/test/java/com/google/cloud/spanner/pgadapter/ITJdbcTest.java
@@ -1112,7 +1112,7 @@ public class ITJdbcTest implements IntegrationTest {
         assertTrue(resultSet.next());
         originalDateStyle = resultSet.getString("setting");
         assertTrue(
-            originalDateStyle,
+            "Original value: " + originalDateStyle,
             "ISO".equals(originalDateStyle) || "ISO, MDY".equals(originalDateStyle));
         assertFalse(resultSet.next());
       }
@@ -1171,6 +1171,23 @@ public class ITJdbcTest implements IntegrationTest {
         assertEquals(originalDateStyle, resultSet.getString("setting"));
         assertFalse(resultSet.next());
       }
+
+      // Verify that we can get all pg_settings and that the number of setting is equal to the
+      // expected value.
+      int numExpectedSettings = 30;
+      int rowCount = 0;
+      try (ResultSet resultSet =
+          connection.createStatement().executeQuery("select * from pg_settings order by name")) {
+        while (resultSet.next()) {
+          for (int col = 1; col <= resultSet.getMetaData().getColumnCount(); col++) {
+            // Just verify that we can get the value.
+            resultSet.getObject(col);
+          }
+          assertNotNull(resultSet.getString("name"));
+          rowCount++;
+        }
+      }
+      assertEquals(numExpectedSettings, rowCount);
     }
   }
 
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 89fd118d..d050fdec 100644
--- a/src/test/java/com/google/cloud/spanner/pgadapter/JdbcMockServerTest.java
+++ b/src/test/java/com/google/cloud/spanner/pgadapter/JdbcMockServerTest.java
@@ -122,7 +122,9 @@ public class JdbcMockServerTest extends AbstractMockServerTest {
   private static final Statement SELECT_RANDOM = Statement.of("select * from random_table");
   private static final ImmutableList<String> JDBC_STARTUP_STATEMENTS =
       ImmutableList.of(
-          "SET extra_float_digits = 3", "SET application_name = 'PostgreSQL JDBC Driver'");
+          "SET extra_float_digits = 2",
+          "SET extra_float_digits = 3",
+          "SET application_name = 'PostgreSQL JDBC Driver'");
 
   @Parameter public String pgVersion;
 
@@ -403,7 +405,7 @@ public class JdbcMockServerTest extends AbstractMockServerTest {
   }
 
   private String getExpectedInitialApplicationName() {
-    return "PostgreSQL JDBC Driver";
+    return pgVersion.equals("1.0") ? "jdbc" : "PostgreSQL JDBC Driver";
   }
 
   @Test
@@ -522,7 +524,7 @@ public class JdbcMockServerTest extends AbstractMockServerTest {
                     + "  /* Preferably, this should use information_schema.information_schema_catalog_name, but that does not exist on the emulator. */\n"
                     + "  from (select distinct catalog_name from information_schema.schemata) catalogs\n"
                     + ")\n"
-                    + "SELECT datname AS TABLE_CAT FROM pg_database WHERE datallowconn = true ORDER BY datname"),
+                    + "SELECT datname AS \"TABLE_CAT\" FROM pg_database WHERE datallowconn = true ORDER BY datname"),
             com.google.spanner.v1.ResultSet.newBuilder()
                 .setMetadata(
                     ResultSetMetadata.newBuilder()
@@ -3863,7 +3865,7 @@ public class JdbcMockServerTest extends AbstractMockServerTest {
       try (ResultSet resultSet =
           connection.createStatement().executeQuery("show application_name ")) {
         assertTrue(resultSet.next());
-        assertEquals(getExpectedInitialApplicationName(), resultSet.getString(1));
+        assertNull(resultSet.getString(1));
         assertFalse(resultSet.next());
       }
     }
@@ -4162,7 +4164,7 @@ public class JdbcMockServerTest extends AbstractMockServerTest {
 
       connection.createStatement().execute("reset all");
 
-      verifySettingValue(connection, "application_name", getExpectedInitialApplicationName());
+      verifySettingIsNull(connection, "application_name");
       verifySettingValue(connection, "search_path", "public");
       verifySettingValue(connection, "spanner.autocommit_dml_mode", "TRANSACTIONAL");
     }
@@ -4171,6 +4173,8 @@ public class JdbcMockServerTest extends AbstractMockServerTest {
   @Test
   public void testSetToDefault() throws SQLException {
     try (Connection connection = DriverManager.getConnection(createUrl())) {
+      verifySettingValue(connection, "application_name", getExpectedInitialApplicationName());
+
       connection.createStatement().execute("set application_name to 'my-app'");
       connection.createStatement().execute("set search_path to 'my_schema'");
       verifySettingValue(connection, "application_name", "my-app");
@@ -4179,7 +4183,7 @@ public class JdbcMockServerTest extends AbstractMockServerTest {
       connection.createStatement().execute("set application_name to default");
       connection.createStatement().execute("set search_path to default");
 
-      verifySettingValue(connection, "application_name", getExpectedInitialApplicationName());
+      verifySettingIsNull(connection, "application_name");
       verifySettingValue(connection, "search_path", "public");
     }
   }
diff --git a/src/test/java/com/google/cloud/spanner/pgadapter/metadata/OptionsMetadataTest.java b/src/test/java/com/google/cloud/spanner/pgadapter/metadata/OptionsMetadataTest.java
index e55e1574..effb14c8 100644
--- a/src/test/java/com/google/cloud/spanner/pgadapter/metadata/OptionsMetadataTest.java
+++ b/src/test/java/com/google/cloud/spanner/pgadapter/metadata/OptionsMetadataTest.java
@@ -629,4 +629,12 @@ public class OptionsMetadataTest {
             .build()
             .buildConnectionURL("projects/my-project/instances/my-instance/databases/my-database"));
   }
+
+  @Test
+  public void testUseClientCertParameters() {
+    OptionsMetadata options =
+        OptionsMetadata.newBuilder().useClientCert("client.crt", "client.key").build();
+    assertEquals("client.crt", options.getPropertyMap().get("clientCertificate"));
+    assertEquals("client.key", options.getPropertyMap().get("clientKey"));
+  }
 }
diff --git a/src/test/java/com/google/cloud/spanner/pgadapter/ruby/ActiveRecordMockServerTest.java b/src/test/java/com/google/cloud/spanner/pgadapter/ruby/ActiveRecordMockServerTest.java
index a28362b6..b206ea23 100644
--- a/src/test/java/com/google/cloud/spanner/pgadapter/ruby/ActiveRecordMockServerTest.java
+++ b/src/test/java/com/google/cloud/spanner/pgadapter/ruby/ActiveRecordMockServerTest.java
@@ -25,6 +25,8 @@ import com.google.cloud.Date;
 import com.google.cloud.Timestamp;
 import com.google.cloud.spanner.MockSpannerServiceImpl.StatementResult;
 import com.google.cloud.spanner.Statement;
+import com.google.cloud.spanner.pgadapter.utils.ClientAutoDetector;
+import com.google.cloud.spanner.pgadapter.utils.ClientAutoDetector.WellKnownClient;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.protobuf.ListValue;
@@ -200,6 +202,7 @@ public class ActiveRecordMockServerTest extends AbstractRubyMockServerTest {
   @Test
   public void testErrorHints() throws SQLException {
     // Emulate an ActiveRecord connection.
+    ClientAutoDetector.FORCE_DETECT_CLIENT.set(WellKnownClient.RAILS);
     String url =
         String.format(
             "jdbc:postgresql://localhost:%d/db?%s=rails&%s=090000",
@@ -250,6 +253,8 @@ public class ActiveRecordMockServerTest extends AbstractRubyMockServerTest {
           exception.getServerErrorMessage().getMessage(),
           "Table foo not found - Statement: 'SELECT * FROM foo'");
       assertNull(exception.getServerErrorMessage().getHint());
+    } finally {
+      ClientAutoDetector.FORCE_DETECT_CLIENT.set(null);
     }
   }
 
diff --git a/src/test/java/com/google/cloud/spanner/pgadapter/session/SessionStateTest.java b/src/test/java/com/google/cloud/spanner/pgadapter/session/SessionStateTest.java
index 369f0388..71d35fec 100644
--- a/src/test/java/com/google/cloud/spanner/pgadapter/session/SessionStateTest.java
+++ b/src/test/java/com/google/cloud/spanner/pgadapter/session/SessionStateTest.java
@@ -405,39 +405,39 @@ public class SessionStateTest {
 
   static String getDefaultSessionStateExpression() {
     return "pg_settings_inmem_ as (\n"
-        + "select 'DateStyle' as name, 'ISO, MDY' as setting, null as unit, 'Client Connection Defaults / Locale and Formatting' as category, null as short_desc, null as extra_desc, 'user' as context, 'string' as vartype, null as min_val, null as max_val, null::text[] as enumvals, 'ISO, MDY' as boot_val, 'ISO, MDY' as reset_val, 'configuration file' as source, null as sourcefile, null::bigint as sourceline, 'f'::boolean as pending_restart\n"
-        + "union all\n"
-        + "select 'TimeZone' as name, 'Europe/Berlin' as setting, null as unit, 'Client Connection Defaults / Locale and Formatting' as category, null as short_desc, null as extra_desc, 'user' as context, 'string' as vartype, null as min_val, null as max_val, null::text[] as enumvals, 'GMT' as boot_val, 'Europe/Berlin' as reset_val, 'configuration file' as source, null as sourcefile, null::bigint as sourceline, 'f'::boolean as pending_restart\n"
-        + "union all\n"
-        + "select 'application_name' as name, null as setting, null as unit, 'Reporting and Logging / What to Log' as category, null as short_desc, null as extra_desc, 'user' as context, 'string' as vartype, null as min_val, null as max_val, null::text[] as enumvals, '' as boot_val, null as reset_val, 'client' as source, null as sourcefile, null::bigint as sourceline, 'f'::boolean as pending_restart\n"
-        + "union all\n"
-        + "select 'bytea_output' as name, 'hex' as setting, null as unit, 'Client Connection Defaults / Statement Behavior' as category, null as short_desc, null as extra_desc, 'user' as context, 'enum' as vartype, null as min_val, null as max_val, '{\"escape\", \"hex\"}'::text[] as enumvals, 'hex' as boot_val, 'hex' as reset_val, 'default' as source, null as sourcefile, null::bigint as sourceline, 'f'::boolean as pending_restart\n"
-        + "union all\n"
-        + "select 'default_transaction_isolation' as name, 'serializable' as setting, null as unit, 'Client Connection Defaults / Statement Behavior' as category, null as short_desc, null as extra_desc, 'user' as context, 'enum' as vartype, null as min_val, null as max_val, '{\"serializable\", \"repeatable read\", \"read committed\", \"read uncommitted\"}'::text[] as enumvals, 'serializable' as boot_val, 'serializable' as reset_val, 'default' as source, null as sourcefile, null::bigint as sourceline, 'f'::boolean as pending_restart\n"
-        + "union all\n"
-        + "select 'default_transaction_read_only' as name, 'off' as setting, null as unit, 'Client Connection Defaults / Statement Behavior' as category, null as short_desc, null as extra_desc, 'user' as context, 'bool' as vartype, null as min_val, null as max_val, null::text[] as enumvals, 'off' as boot_val, 'off' as reset_val, 'default' as source, null as sourcefile, null::bigint as sourceline, 'f'::boolean as pending_restart\n"
-        + "union all\n"
-        + "select 'extra_float_digits' as name, '1' as setting, null as unit, 'Client Connection Defaults / Locale and Formatting' as category, null as short_desc, null as extra_desc, 'user' as context, 'integer' as vartype, '-15' as min_val, '3' as max_val, null::text[] as enumvals, '1' as boot_val, '1' as reset_val, 'default' as source, null as sourcefile, null::bigint as sourceline, 'f'::boolean as pending_restart\n"
-        + "union all\n"
-        + "select 'max_connections' as name, '100' as setting, null as unit, 'Connections and Authentication / Connection Settings' as category, null as short_desc, null as extra_desc, 'postmaster' as context, 'integer' as vartype, '1' as min_val, '262143' as max_val, null::text[] as enumvals, '100' as boot_val, '100' as reset_val, 'configuration file' as source, null as sourcefile, null::bigint as sourceline, 'f'::boolean as pending_restart\n"
-        + "union all\n"
-        + "select 'max_index_keys' as name, '16' as setting, null as unit, 'Preset Options' as category, null as short_desc, null as extra_desc, 'internal' as context, 'integer' as vartype, '16' as min_val, '16' as max_val, null::text[] as enumvals, '16' as boot_val, '16' as reset_val, 'default' as source, null as sourcefile, null::bigint as sourceline, 'f'::boolean as pending_restart\n"
-        + "union all\n"
-        + "select 'port' as name, '5432' as setting, null as unit, 'Connections and Authentication / Connection Settings' as category, null as short_desc, null as extra_desc, 'postmaster' as context, 'integer' as vartype, '1' as min_val, '65535' as max_val, null::text[] as enumvals, '5432' as boot_val, '5432' as reset_val, 'configuration file' as source, null as sourcefile, null::bigint as sourceline, 'f'::boolean as pending_restart\n"
-        + "union all\n"
-        + "select 'search_path' as name, 'public' as setting, null as unit, 'Client Connection Defaults / Statement Behavior' as category, null as short_desc, null as extra_desc, 'user' as context, 'string' as vartype, null as min_val, null as max_val, null::text[] as enumvals, 'public' as boot_val, 'public' as reset_val, 'default' as source, null as sourcefile, null::bigint as sourceline, 'f'::boolean as pending_restart\n"
-        + "union all\n"
-        + "select 'server_version' as name, null as setting, null as unit, 'Preset Options' as category, null as short_desc, null as extra_desc, 'backend' as context, 'string' as vartype, null as min_val, null as max_val, null::text[] as enumvals, '14.1' as boot_val, '14.1' as reset_val, 'default' as source, null as sourcefile, null::bigint as sourceline, 'f'::boolean as pending_restart\n"
-        + "union all\n"
-        + "select 'server_version_num' as name, null as setting, null as unit, 'Preset Options' as category, null as short_desc, null as extra_desc, 'internal' as context, 'integer' as vartype, '140001' as min_val, '140001' as max_val, null::text[] as enumvals, '140001' as boot_val, '140001' as reset_val, 'default' as source, null as sourcefile, null::bigint as sourceline, 'f'::boolean as pending_restart\n"
-        + "union all\n"
-        + "select 'spanner.ddl_transaction_mode' as name, 'Batch' as setting, null as unit, 'PGAdapter Options' as category, null as short_desc, null as extra_desc, 'user' as context, 'enum' as vartype, null as min_val, null as max_val, '{\"Single\", \"Batch\", \"AutocommitImplicitTransaction\", \"AutocommitExplicitTransaction\"}'::text[] as enumvals, 'Batch' as boot_val, 'Batch' as reset_val, 'default' as source, null as sourcefile, null::bigint as sourceline, 'f'::boolean as pending_restart\n"
-        + "union all\n"
-        + "select 'spanner.replace_pg_catalog_tables' as name, 'false' as setting, null as unit, 'PGAdapter Options' as category, null as short_desc, null as extra_desc, 'user' as context, 'bool' as vartype, null as min_val, null as max_val, null::text[] as enumvals, 'on' as boot_val, 'on' as reset_val, 'default' as source, null as sourcefile, null::bigint as sourceline, 'f'::boolean as pending_restart\n"
-        + "union all\n"
-        + "select 'transaction_isolation' as name, 'serializable' as setting, null as unit, 'Client Connection Defaults / Statement Behavior' as category, null as short_desc, null as extra_desc, 'user' as context, 'enum' as vartype, null as min_val, null as max_val, '{\"serializable\", \"repeatable read\", \"read committed\", \"read uncommitted\"}'::text[] as enumvals, 'serializable' as boot_val, 'serializable' as reset_val, 'override' as source, null as sourcefile, null::bigint as sourceline, 'f'::boolean as pending_restart\n"
-        + "union all\n"
-        + "select 'transaction_read_only' as name, 'off' as setting, null as unit, 'Client Connection Defaults / Statement Behavior' as category, null as short_desc, null as extra_desc, 'user' as context, 'bool' as vartype, null as min_val, null as max_val, null::text[] as enumvals, 'off' as boot_val, 'off' as reset_val, 'override' as source, null as sourcefile, null::bigint as sourceline, 'f'::boolean as pending_restart\n"
+        + "select t->>'name' as name, t->>'setting' as setting, t->>'unit' as unit, t->>'category' as category, t->>'short_desc' as short_desc, t->>'extra_desc' as extra_desc, t->>'context' as context, t->>'vartype' as vartype, t->>'min_val' as min_val, t->>'max_val' as max_val, case when t->>'enumvals' is null then null::text[] else spanner.string_array((t->>'enumvals')::jsonb) end as enumvals, t->>'boot_val' as boot_val, t->>'reset_val' as reset_val, t->>'source' as source, (t->>'sourcefile')::varchar as sourcefile, (t->>'sourceline')::bigint as sourceline, (t->>'pending_restart')::boolean as pending_restart\n"
+        + "from unnest(array[\n"
+        + "'{\"name\":\"DateStyle\",\"setting\":\"ISO, MDY\",\"unit\":null,\"category\":\"Client Connection Defaults / Locale and Formatting\",\"short_desc\":null,\"extra_desc\":null,\"context\":\"user\",\"vartype\":\"string\",\"min_val\":null,\"max_val\":null,\"enum_vals\":null,\"boot_val\":\"ISO, MDY\",\"reset_val\":\"ISO, MDY\",\"source\":\"configuration file\",\"sourcefile\":null,\"sourceline\":null,\"pending_restart\":false}'::jsonb,\n"
+        + "'{\"name\":\"TimeZone\",\"setting\":\"Europe/Berlin\",\"unit\":null,\"category\":\"Client Connection Defaults / Locale and Formatting\",\"short_desc\":null,\"extra_desc\":null,\"context\":\"user\",\"vartype\":\"string\",\"min_val\":null,\"max_val\":null,\"enum_vals\":null,\"boot_val\":\"GMT\",\"reset_val\":\"Europe/Berlin\",\"source\":\"configuration file\",\"sourcefile\":null,\"sourceline\":null,\"pending_restart\":false}'::jsonb,\n"
+        + "'{\"name\":\"application_name\",\"setting\":null,\"unit\":null,\"category\":\"Reporting and Logging / What to Log\",\"short_desc\":null,\"extra_desc\":null,\"context\":\"user\",\"vartype\":\"string\",\"min_val\":null,\"max_val\":null,\"enum_vals\":null,\"boot_val\":\"\",\"reset_val\":null,\"source\":\"client\",\"sourcefile\":null,\"sourceline\":null,\"pending_restart\":false}'::jsonb,\n"
+        + "'{\"name\":\"bytea_output\",\"setting\":\"hex\",\"unit\":null,\"category\":\"Client Connection Defaults / Statement Behavior\",\"short_desc\":null,\"extra_desc\":null,\"context\":\"user\",\"vartype\":\"enum\",\"min_val\":null,\"max_val\":null,\"enum_vals\":[\"escape\", \"hex\"],\"boot_val\":\"hex\",\"reset_val\":\"hex\",\"source\":\"default\",\"sourcefile\":null,\"sourceline\":null,\"pending_restart\":false}'::jsonb,\n"
+        + "'{\"name\":\"default_transaction_isolation\",\"setting\":\"serializable\",\"unit\":null,\"category\":\"Client Connection Defaults / Statement Behavior\",\"short_desc\":null,\"extra_desc\":null,\"context\":\"user\",\"vartype\":\"enum\",\"min_val\":null,\"max_val\":null,\"enum_vals\":[\"serializable\", \"repeatable read\", \"read committed\", \"read uncommitted\"],\"boot_val\":\"serializable\",\"reset_val\":\"serializable\",\"source\":\"default\",\"sourcefile\":null,\"sourceline\":null,\"pending_restart\":false}'::jsonb,\n"
+        + "'{\"name\":\"default_transaction_read_only\",\"setting\":\"off\",\"unit\":null,\"category\":\"Client Connection Defaults / Statement Behavior\",\"short_desc\":null,\"extra_desc\":null,\"context\":\"user\",\"vartype\":\"bool\",\"min_val\":null,\"max_val\":null,\"enum_vals\":null,\"boot_val\":\"off\",\"reset_val\":\"off\",\"source\":\"default\",\"sourcefile\":null,\"sourceline\":null,\"pending_restart\":false}'::jsonb,\n"
+        + "'{\"name\":\"extra_float_digits\",\"setting\":\"1\",\"unit\":null,\"category\":\"Client Connection Defaults / Locale and Formatting\",\"short_desc\":null,\"extra_desc\":null,\"context\":\"user\",\"vartype\":\"integer\",\"min_val\":\"-15\",\"max_val\":\"3\",\"enum_vals\":null,\"boot_val\":\"1\",\"reset_val\":\"1\",\"source\":\"default\",\"sourcefile\":null,\"sourceline\":null,\"pending_restart\":false}'::jsonb,\n"
+        + "'{\"name\":\"max_connections\",\"setting\":\"100\",\"unit\":null,\"category\":\"Connections and Authentication / Connection Settings\",\"short_desc\":null,\"extra_desc\":null,\"context\":\"postmaster\",\"vartype\":\"integer\",\"min_val\":\"1\",\"max_val\":\"262143\",\"enum_vals\":null,\"boot_val\":\"100\",\"reset_val\":\"100\",\"source\":\"configuration file\",\"sourcefile\":null,\"sourceline\":null,\"pending_restart\":false}'::jsonb,\n"
+        + "'{\"name\":\"max_index_keys\",\"setting\":\"16\",\"unit\":null,\"category\":\"Preset Options\",\"short_desc\":null,\"extra_desc\":null,\"context\":\"internal\",\"vartype\":\"integer\",\"min_val\":\"16\",\"max_val\":\"16\",\"enum_vals\":null,\"boot_val\":\"16\",\"reset_val\":\"16\",\"source\":\"default\",\"sourcefile\":null,\"sourceline\":null,\"pending_restart\":false}'::jsonb,\n"
+        + "'{\"name\":\"port\",\"setting\":\"5432\",\"unit\":null,\"category\":\"Connections and Authentication / Connection Settings\",\"short_desc\":null,\"extra_desc\":null,\"context\":\"postmaster\",\"vartype\":\"integer\",\"min_val\":\"1\",\"max_val\":\"65535\",\"enum_vals\":null,\"boot_val\":\"5432\",\"reset_val\":\"5432\",\"source\":\"configuration file\",\"sourcefile\":null,\"sourceline\":null,\"pending_restart\":false}'::jsonb,\n"
+        + "'{\"name\":\"search_path\",\"setting\":\"public\",\"unit\":null,\"category\":\"Client Connection Defaults / Statement Behavior\",\"short_desc\":null,\"extra_desc\":null,\"context\":\"user\",\"vartype\":\"string\",\"min_val\":null,\"max_val\":null,\"enum_vals\":null,\"boot_val\":\"public\",\"reset_val\":\"public\",\"source\":\"default\",\"sourcefile\":null,\"sourceline\":null,\"pending_restart\":false}'::jsonb,\n"
+        + "'{\"name\":\"server_version\",\"setting\":null,\"unit\":null,\"category\":\"Preset Options\",\"short_desc\":null,\"extra_desc\":null,\"context\":\"backend\",\"vartype\":\"string\",\"min_val\":null,\"max_val\":null,\"enum_vals\":null,\"boot_val\":\"14.1\",\"reset_val\":\"14.1\",\"source\":\"default\",\"sourcefile\":null,\"sourceline\":null,\"pending_restart\":false}'::jsonb,\n"
+        + "'{\"name\":\"server_version_num\",\"setting\":null,\"unit\":null,\"category\":\"Preset Options\",\"short_desc\":null,\"extra_desc\":null,\"context\":\"internal\",\"vartype\":\"integer\",\"min_val\":\"140001\",\"max_val\":\"140001\",\"enum_vals\":null,\"boot_val\":\"140001\",\"reset_val\":\"140001\",\"source\":\"default\",\"sourcefile\":null,\"sourceline\":null,\"pending_restart\":false}'::jsonb,\n"
+        + "'{\"name\":\"spanner.copy_batch_size\",\"setting\":\"5000\",\"unit\":null,\"category\":\"COPY / Batch size for non-atomic COPY operations\",\"short_desc\":null,\"extra_desc\":null,\"context\":\"user\",\"vartype\":\"integer\",\"min_val\":null,\"max_val\":null,\"enum_vals\":null,\"boot_val\":\"5000\",\"reset_val\":\"5000\",\"source\":\"default\",\"sourcefile\":null,\"sourceline\":null,\"pending_restart\":false}'::jsonb,\n"
+        + "'{\"name\":\"spanner.copy_commit_priority\",\"setting\":\"medium\",\"unit\":null,\"category\":\"COPY / RPC priority for commits for COPY operations\",\"short_desc\":null,\"extra_desc\":null,\"context\":\"user\",\"vartype\":\"enum\",\"min_val\":null,\"max_val\":null,\"enum_vals\":[\"low\", \"medium\", \"high\"],\"boot_val\":\"medium\",\"reset_val\":\"medium\",\"source\":\"default\",\"sourcefile\":null,\"sourceline\":null,\"pending_restart\":false}'::jsonb,\n"
+        + "'{\"name\":\"spanner.copy_commit_size_multiplier_factor\",\"setting\":\"2.0\",\"unit\":null,\"category\":\"COPY / Factor for estimating COPY commit size\",\"short_desc\":null,\"extra_desc\":null,\"context\":\"user\",\"vartype\":\"real\",\"min_val\":null,\"max_val\":null,\"enum_vals\":null,\"boot_val\":\"2.0\",\"reset_val\":\"2.0\",\"source\":\"default\",\"sourcefile\":null,\"sourceline\":null,\"pending_restart\":false}'::jsonb,\n"
+        + "'{\"name\":\"spanner.copy_commit_timeout\",\"setting\":\"300\",\"unit\":null,\"category\":\"COPY / Timeout in seconds for commits for COPY operations\",\"short_desc\":null,\"extra_desc\":null,\"context\":\"user\",\"vartype\":\"integer\",\"min_val\":null,\"max_val\":null,\"enum_vals\":null,\"boot_val\":\"300\",\"reset_val\":\"300\",\"source\":\"default\",\"sourcefile\":null,\"sourceline\":null,\"pending_restart\":false}'::jsonb,\n"
+        + "'{\"name\":\"spanner.copy_max_atomic_commit_size\",\"setting\":\"100000000\",\"unit\":null,\"category\":\"COPY / Max number of bytes in an atomic COPY operation\",\"short_desc\":null,\"extra_desc\":null,\"context\":\"internal\",\"vartype\":\"integer\",\"min_val\":null,\"max_val\":null,\"enum_vals\":null,\"boot_val\":\"100000000\",\"reset_val\":\"100000000\",\"source\":\"default\",\"sourcefile\":null,\"sourceline\":null,\"pending_restart\":false}'::jsonb,\n"
+        + "'{\"name\":\"spanner.copy_max_atomic_mutations\",\"setting\":\"20000\",\"unit\":null,\"category\":\"COPY / Max number of mutations for atomic COPY operations\",\"short_desc\":null,\"extra_desc\":null,\"context\":\"internal\",\"vartype\":\"integer\",\"min_val\":null,\"max_val\":null,\"enum_vals\":null,\"boot_val\":\"20000\",\"reset_val\":\"20000\",\"source\":\"default\",\"sourcefile\":null,\"sourceline\":null,\"pending_restart\":false}'::jsonb,\n"
+        + "'{\"name\":\"spanner.copy_max_non_atomic_commit_size\",\"setting\":\"5000000\",\"unit\":null,\"category\":\"COPY / The max number of bytes per commit in a non-atomic COPY operation\",\"short_desc\":null,\"extra_desc\":null,\"context\":\"user\",\"vartype\":\"integer\",\"min_val\":null,\"max_val\":null,\"enum_vals\":null,\"boot_val\":\"5000000\",\"reset_val\":\"5000000\",\"source\":\"default\",\"sourcefile\":null,\"sourceline\":null,\"pending_restart\":false}'::jsonb,\n"
+        + "'{\"name\":\"spanner.copy_max_parallelism\",\"setting\":\"128\",\"unit\":null,\"category\":\"COPY / Max concurrent transactions for a non-atomic COPY operation\",\"short_desc\":null,\"extra_desc\":null,\"context\":\"user\",\"vartype\":\"integer\",\"min_val\":null,\"max_val\":null,\"enum_vals\":null,\"boot_val\":\"128\",\"reset_val\":\"128\",\"source\":\"default\",\"sourcefile\":null,\"sourceline\":null,\"pending_restart\":false}'::jsonb,\n"
+        + "'{\"name\":\"spanner.copy_pipe_buffer_size\",\"setting\":\"65536\",\"unit\":null,\"category\":\"COPY / Buffer size for incoming COPY data messages\",\"short_desc\":null,\"extra_desc\":null,\"context\":\"internal\",\"vartype\":\"integer\",\"min_val\":null,\"max_val\":null,\"enum_vals\":null,\"boot_val\":\"100000000\",\"reset_val\":\"100000000\",\"source\":\"default\",\"sourcefile\":null,\"sourceline\":null,\"pending_restart\":false}'::jsonb,\n"
+        + "'{\"name\":\"spanner.copy_upsert\",\"setting\":\"off\",\"unit\":null,\"category\":\"COPY / Use Upsert instead of Insert for COPY\",\"short_desc\":null,\"extra_desc\":null,\"context\":\"user\",\"vartype\":\"bool\",\"min_val\":null,\"max_val\":null,\"enum_vals\":null,\"boot_val\":\"off\",\"reset_val\":\"off\",\"source\":\"default\",\"sourcefile\":null,\"sourceline\":null,\"pending_restart\":false}'::jsonb,\n"
+        + "'{\"name\":\"spanner.ddl_transaction_mode\",\"setting\":\"Batch\",\"unit\":null,\"category\":\"PGAdapter Options\",\"short_desc\":null,\"extra_desc\":null,\"context\":\"user\",\"vartype\":\"enum\",\"min_val\":null,\"max_val\":null,\"enum_vals\":[\"Single\", \"Batch\", \"AutocommitImplicitTransaction\", \"AutocommitExplicitTransaction\"],\"boot_val\":\"Batch\",\"reset_val\":\"Batch\",\"source\":\"default\",\"sourcefile\":null,\"sourceline\":null,\"pending_restart\":false}'::jsonb,\n"
+        + "'{\"name\":\"spanner.emulate_pg_class_tables\",\"setting\":\"on\",\"unit\":null,\"category\":\"PGAdapter Options Emulate pg_class and related tables using common table expressions and textual OIDs\",\"short_desc\":null,\"extra_desc\":null,\"context\":\"user\",\"vartype\":\"bool\",\"min_val\":null,\"max_val\":null,\"enum_vals\":null,\"boot_val\":\"off\",\"reset_val\":\"off\",\"source\":\"default\",\"sourcefile\":null,\"sourceline\":null,\"pending_restart\":false}'::jsonb,\n"
+        + "'{\"name\":\"spanner.force_autocommit\",\"setting\":\"off\",\"unit\":null,\"category\":\"PGAdapter Options Execute all statements in autocommit mode\",\"short_desc\":null,\"extra_desc\":null,\"context\":\"user\",\"vartype\":\"bool\",\"min_val\":null,\"max_val\":null,\"enum_vals\":null,\"boot_val\":\"off\",\"reset_val\":\"off\",\"source\":\"default\",\"sourcefile\":null,\"sourceline\":null,\"pending_restart\":false}'::jsonb,\n"
+        + "'{\"name\":\"spanner.replace_pg_catalog_tables\",\"setting\":\"false\",\"unit\":null,\"category\":\"PGAdapter Options\",\"short_desc\":null,\"extra_desc\":null,\"context\":\"user\",\"vartype\":\"bool\",\"min_val\":null,\"max_val\":null,\"enum_vals\":null,\"boot_val\":\"on\",\"reset_val\":\"on\",\"source\":\"default\",\"sourcefile\":null,\"sourceline\":null,\"pending_restart\":false}'::jsonb,\n"
+        + "'{\"name\":\"spanner.well_known_client\",\"setting\":\"UNSPECIFIED\",\"unit\":null,\"category\":\"PGAdapter Options\",\"short_desc\":null,\"extra_desc\":null,\"context\":\"backend\",\"vartype\":\"string\",\"min_val\":null,\"max_val\":null,\"enum_vals\":null,\"boot_val\":\"UNSPECIFIED\",\"reset_val\":\"UNSPECIFIED\",\"source\":\"default\",\"sourcefile\":null,\"sourceline\":null,\"pending_restart\":false}'::jsonb,\n"
+        + "'{\"name\":\"transaction_isolation\",\"setting\":\"serializable\",\"unit\":null,\"category\":\"Client Connection Defaults / Statement Behavior\",\"short_desc\":null,\"extra_desc\":null,\"context\":\"user\",\"vartype\":\"enum\",\"min_val\":null,\"max_val\":null,\"enum_vals\":[\"serializable\", \"repeatable read\", \"read committed\", \"read uncommitted\"],\"boot_val\":\"serializable\",\"reset_val\":\"serializable\",\"source\":\"override\",\"sourcefile\":null,\"sourceline\":null,\"pending_restart\":false}'::jsonb,\n"
+        + "'{\"name\":\"transaction_read_only\",\"setting\":\"off\",\"unit\":null,\"category\":\"Client Connection Defaults / Statement Behavior\",\"short_desc\":null,\"extra_desc\":null,\"context\":\"user\",\"vartype\":\"bool\",\"min_val\":null,\"max_val\":null,\"enum_vals\":null,\"boot_val\":\"off\",\"reset_val\":\"off\",\"source\":\"override\",\"sourcefile\":null,\"sourceline\":null,\"pending_restart\":false}'::jsonb\n"
+        + "]) t\n"
         + "),\n"
         + "pg_settings_names_ as (\n"
         + "select name from pg_settings_inmem_\n"
diff --git a/src/test/ruby/activerecord/config/database.yml b/src/test/ruby/activerecord/config/database.yml
index 64cf5297..901a6ac7 100644
--- a/src/test/ruby/activerecord/config/database.yml
+++ b/src/test/ruby/activerecord/config/database.yml
@@ -1,6 +1,8 @@
 development:
   adapter: postgresql
   pool: 5
+  # Schema dumping uses pg_catalog tables and functions that are not supported by Spanner.
+  schema_dump: false
   # Advisory locks are not supported by PGAdapter
   advisory_locks: false
   # These settings ensure that migrations and schema inspections work.
diff --git a/src/test/ruby/activerecord/db/schema.rb b/src/test/ruby/activerecord/db/schema.rb
deleted file mode 100644
index 6ca4a69b..00000000
--- a/src/test/ruby/activerecord/db/schema.rb
+++ /dev/null
@@ -1,71 +0,0 @@
-# This file is auto-generated from the current state of the database. Instead
-# of editing this file, please use the migrations feature of Active Record to
-# incrementally modify your database, and then regenerate this schema definition.
-#
-# This file is the source Rails uses to define your schema when running `bin/rails
-# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to
-# be faster and is potentially less error prone than running all of your
-# migrations from scratch. Old migrations may fail to apply correctly if those
-# migrations use external dependencies or application code.
-#
-# It's strongly recommended that you check this file into your version control system.
-
-ActiveRecord::Schema[7.0].define(version: 1) do
-  create_table "albums", primary_key: "album_id", id: { type: :string, limit: 36 }, comment: "", force: :cascade do |t|
-    t.string "title"
-    t.decimal "marketing_budget"
-    t.date "release_date"
-    t.binary "cover_picture"
-    t.string "singer_id", limit: 36
-    t.datetime "created_at", precision: nil
-    t.datetime "updated_at", precision: nil
-    t.bigint "lock_version", null: false
-    t.index [], name: "IDX_albums_singer_id_N_90CD66D06B92DBCF"
-  end
-
-  create_table "concerts", primary_key: "concert_id", id: { type: :string, limit: 36 }, comment: "", force: :cascade do |t|
-    t.string "venue_id", limit: 36
-    t.string "singer_id", limit: 36
-    t.string "name"
-    t.datetime "start_time", precision: nil, null: false
-    t.datetime "end_time", precision: nil, null: false
-    t.datetime "created_at", precision: nil
-    t.datetime "updated_at", precision: nil
-    t.bigint "lock_version", null: false
-    t.index [], name: "IDX_concerts_singer_id_N_E92CCCE963BE681C"
-    t.index [], name: "IDX_concerts_venue_id_N_F08F98ABB662E6D5"
-    t.check_constraint nil, name: "chk_end_time_after_start_time"
-  end
-
-  create_table "singers", primary_key: "singer_id", id: { type: :string, limit: 36 }, comment: "", force: :cascade do |t|
-    t.string "first_name", limit: 100
-    t.string "last_name", limit: 200, null: false
-    t.virtual "full_name", type: :string, as: "COALESCE(concat(first_name, ' '::character varying, last_name), last_name)", stored: true
-    t.boolean "active"
-    t.datetime "created_at", precision: nil
-    t.datetime "updated_at", precision: nil
-    t.bigint "lock_version", null: false
-  end
-
-  create_table "tracks", primary_key: ["album_id", "track_number"], comment: "", force: :cascade do |t|
-    t.string "album_id", limit: 36, null: false
-    t.bigint "track_number", null: false
-    t.string "title", null: false
-    t.float "sample_rate", null: false
-    t.datetime "created_at", precision: nil
-    t.datetime "updated_at", precision: nil
-    t.bigint "lock_version", null: false
-  end
-
-  create_table "venues", primary_key: "venue_id", id: { type: :string, limit: 36 }, comment: "", force: :cascade do |t|
-    t.string "name"
-    t.jsonb "description"
-    t.datetime "created_at", precision: nil
-    t.datetime "updated_at", precision: nil
-    t.bigint "lock_version", null: false
-  end
-
-  add_foreign_key "albums", "singers", primary_key: "singer_id"
-  add_foreign_key "concerts", "singers", primary_key: "singer_id"
-  add_foreign_key "concerts", "venues", primary_key: "venue_id"
-end