Skip to content

Commit 13f4bcf

Browse files
committed
fix: resolve compatibility issues with Java and Rust clients
1 parent 69db038 commit 13f4bcf

File tree

8 files changed

+40
-41
lines changed

8 files changed

+40
-41
lines changed

.github/workflows/clients-compatibility.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ jobs:
105105
sudo mv duckdb /usr/local/bin
106106
107107
cd compatibility/pg/
108-
# curl -L -o ./java/postgresql-42.7.4.jar https://jdbc.postgresql.org/download/postgresql-42.7.4.jar
108+
curl -L -o ./java/postgresql-42.7.4.jar https://jdbc.postgresql.org/download/postgresql-42.7.4.jar
109109
npm install pg
110110
sudo cpanm --notest DBD::Pg
111111
pip3 install "psycopg[binary]" pandas pyarrow polars

compatibility/pg/csharp/PGTest.cs

+11-15
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,28 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Data;
4-
using Microsoft.Data.SqlClient;
4+
using Npgsql;
55
using System.IO;
66

77
public class PGTest
88
{
99
public class Tests
1010
{
11-
private SqlConnection conn;
12-
private SqlCommand cmd;
11+
private NpgsqlConnection conn;
12+
private NpgsqlCommand cmd;
1313
private List<Test> tests = new List<Test>();
1414

1515
public void Connect(string ip, int port, string user, string password)
1616
{
17-
string connectionString = $"Server={ip},{port};User Id={user};Password={password};";
17+
string connectionString = $"Host={ip};Port={port};Username={user};Password={password};Database=postgres;";
1818
try
1919
{
20-
conn = new SqlConnection(connectionString);
20+
conn = new NpgsqlConnection(connectionString);
2121
conn.Open();
2222
cmd = conn.CreateCommand();
2323
cmd.CommandType = CommandType.Text;
2424
}
25-
catch (SqlException e)
25+
catch (NpgsqlException e)
2626
{
2727
throw new Exception($"Error connecting to database: {e.Message}", e);
2828
}
@@ -35,7 +35,7 @@ public void Disconnect()
3535
cmd.Dispose();
3636
conn.Close();
3737
}
38-
catch (SqlException e)
38+
catch (NpgsqlException e)
3939
{
4040
throw new Exception(e.Message);
4141
}
@@ -97,7 +97,7 @@ public Test(string query, string[][] expectedResults)
9797
this.expectedResults = expectedResults;
9898
}
9999

100-
public bool Run(SqlCommand cmd)
100+
public bool Run(NpgsqlCommand cmd)
101101
{
102102
try
103103
{
@@ -125,15 +125,11 @@ public bool Run(SqlCommand cmd)
125125
{
126126
for (int col = 0; col < expectedResults[rows].Length; col++)
127127
{
128-
string result = reader.GetString(col);
128+
string result = reader.GetValue(col).ToString().Trim();
129129
if (expectedResults[rows][col] != result)
130130
{
131131
Console.Error.WriteLine($"Expected:\n'{expectedResults[rows][col]}'");
132-
Console.Error.WriteLine($"Result:\n'{result}'\nRest of the results:");
133-
while (reader.Read())
134-
{
135-
Console.Error.WriteLine(reader.GetString(0));
136-
}
132+
Console.Error.WriteLine($"Result:\n'{result}'");
137133
return false;
138134
}
139135
}
@@ -148,7 +144,7 @@ public bool Run(SqlCommand cmd)
148144
return true;
149145
}
150146
}
151-
catch (SqlException e)
147+
catch (NpgsqlException e)
152148
{
153149
Console.Error.WriteLine(e.Message);
154150
return false;

compatibility/pg/csharp/PGTest.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
</PropertyGroup>
77

88
<ItemGroup>
9-
<PackageReference Include="Microsoft.Data.SqlClient" Version="5.2" />
9+
<PackageReference Include="Npgsql" Version="7.0.0" />
1010
</ItemGroup>
1111

1212
</Project>

compatibility/pg/java/PGTest.java

+2-5
Original file line numberDiff line numberDiff line change
@@ -89,13 +89,10 @@ public boolean run() {
8989
while (rs.next()) {
9090
int cols = 0;
9191
for (String expected : expectedResults[rows]) {
92-
String result = rs.getString(cols + 1);
92+
String result = rs.getString(cols + 1).trim();
9393
if (!expected.equals(result)) {
9494
System.err.println("Expected:\n'" + expected + "'");
95-
System.err.println("Result:\n'" + result + "'\nRest of the results:");
96-
while (rs.next()) {
97-
System.err.println(rs.getString(1));
98-
}
95+
System.err.println("Result:\n'" + result + "'");
9996
return false;
10097
}
10198
cols++;

compatibility/pg/rust/pg_test.rs

+8-5
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,16 @@ impl Test {
3333
}
3434
for (i, row) in rows.iter().enumerate() {
3535
for (j, expected) in self.expected_results[i].iter().enumerate() {
36-
let result: String = row.get(j);
36+
let result: String = row.try_get::<usize, String>(j)
37+
.or_else(|_| row.try_get::<usize, i32>(j).map(|v| v.to_string()))
38+
.or_else(|_| row.try_get::<usize, i64>(j).map(|v| v.to_string()))
39+
.or_else(|_| row.try_get::<usize, f64>(j).map(|v| v.to_string()))
40+
.unwrap_or_default()
41+
.trim()
42+
.to_string();
3743
if expected != &result {
3844
eprintln!("Expected:\n'{}'", expected);
39-
eprintln!("Result:\n'{}'\nRest of the results:", result);
40-
for row in rows.iter().skip(i + 1) {
41-
eprintln!("{}", row.get::<usize, String>(0));
42-
}
45+
eprintln!("Result:\n'{}'", result);
4346
return false;
4447
}
4548
}

compatibility/pg/test.bats

+9-11
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/usr/bin/env bats
22

33
setup() {
4-
psql -h 127.0.0.1 -p 5432 -U postgres -c "DROP SCHEMA IF EXISTS test CASCADE;"
4+
psql -h 127.0.0.1 -p 5432 -U postgres -d postgres -c "DROP SCHEMA IF EXISTS test CASCADE;"
55
touch /tmp/test_pids
66
}
77

@@ -52,12 +52,10 @@ start_process() {
5252
start_process $BATS_TEST_DIRNAME/go/pg 127.0.0.1 5432 postgres "" $BATS_TEST_DIRNAME/test.data
5353
}
5454

55-
# Before you uncomment the following tests, you need to uncomment the corresponding lines in
56-
# .github/workflows/clients-compatibility.yml, which will download the necessary dependencies.
57-
# @test "pg-java" {
58-
# start_process javac $BATS_TEST_DIRNAME/java/PGTest.java
59-
# start_process java -cp $BATS_TEST_DIRNAME/java:$BATS_TEST_DIRNAME/java/postgresql-42.7.4.jar PGTest 127.0.0.1 5432 postgres "" $BATS_TEST_DIRNAME/test.data
60-
# }
55+
@test "pg-java" {
56+
start_process javac $BATS_TEST_DIRNAME/java/PGTest.java
57+
start_process java -cp $BATS_TEST_DIRNAME/java:$BATS_TEST_DIRNAME/java/postgresql-42.7.4.jar PGTest 127.0.0.1 5432 postgres "" $BATS_TEST_DIRNAME/test.data
58+
}
6159

6260
@test "pg-node" {
6361
start_process node $BATS_TEST_DIRNAME/node/pg_test.js 127.0.0.1 5432 postgres "" $BATS_TEST_DIRNAME/test.data
@@ -83,7 +81,7 @@ start_process() {
8381
start_process ruby $BATS_TEST_DIRNAME/ruby/pg_test.rb 127.0.0.1 5432 postgres "" $BATS_TEST_DIRNAME/test.data
8482
}
8583

86-
# @test "pg-rust" {
87-
# start_process cargo build --release --manifest-path $BATS_TEST_DIRNAME/rust/Cargo.toml
88-
# start_process $BATS_TEST_DIRNAME/rust/target/release/pg_test 127.0.0.1 5432 postgres "" $BATS_TEST_DIRNAME/test.data
89-
# }
84+
@test "pg-rust" {
85+
start_process cargo build --release --manifest-path $BATS_TEST_DIRNAME/rust/Cargo.toml
86+
start_process $BATS_TEST_DIRNAME/rust/target/release/pg_test 127.0.0.1 5432 postgres "" $BATS_TEST_DIRNAME/test.data
87+
}

pgserver/connection_handler.go

+7-3
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ func (h *ConnectionHandler) sendClientStartupMessages() error {
265265
// which lists all the available parameters in PostgreSQL. In that case,
266266
// we will use a mock value for that parameter. e.g. "on" for "is_superuser".
267267
{"in_hot_standby", nil},
268-
{"integer_datetimes", nil},
268+
{"integer_datetimes", "on"},
269269
{"TimeZone", nil},
270270
{"IntervalStyle", nil},
271271
{"is_superuser", "on"}, // This is not specified in postgresConfigParameters now.
@@ -470,7 +470,7 @@ func (h *ConnectionHandler) handleQuery(message *pgproto3.Query) (endOfMessages
470470
return true, err
471471
}
472472

473-
query, err := h.convertQuery(message.String)
473+
query, err := h.convertQuery(message.String, convertFloatToF64)
474474
if err != nil {
475475
return true, err
476476
}
@@ -551,7 +551,7 @@ func (h *ConnectionHandler) handleParse(message *pgproto3.Parse) error {
551551
h.waitForSync = true
552552

553553
// TODO: "Named prepared statements must be explicitly closed before they can be redefined by another Parse message, but this is not required for the unnamed statement"
554-
query, err := h.convertQuery(message.Query)
554+
query, err := h.convertQuery(message.Query, convertFloatToF64)
555555
if err != nil {
556556
return err
557557
}
@@ -641,6 +641,10 @@ func (h *ConnectionHandler) handleDescribe(message *pgproto3.Describe) error {
641641
bindvarTypes = preparedStatementData.BindVarTypes
642642
tag = preparedStatementData.Query.StatementTag
643643
}
644+
645+
if bindvarTypes == nil {
646+
bindvarTypes = make([]uint32, 0)
647+
}
644648
} else {
645649
portalData, ok := h.portals[message.Name]
646650
if !ok {

pgserver/query_modifier.go

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ func NewQueryRemover(regex string) QueryModifier {
1717
}
1818

1919
var (
20+
convertFloatToF64 = NewQueryReplacer(`(?i)\bFLOAT\b`, `DOUBLE`)
2021
removeLocaleProvider = NewQueryRemover(`(?i)LOCALE_PROVIDER = [^ ;]*`)
2122
removeLocale = NewQueryRemover(`(?i)LOCALE = [^ ;]*`)
2223
)

0 commit comments

Comments
 (0)