Skip to content

Commit a67a903

Browse files
authored
Add Ruby 2pc tests (#448)
* Add Ruby 2pc tests * 2pc setup * fix test warnings * tag 0.1.4 * prepared transactions note
1 parent e462f3e commit a67a903

File tree

11 files changed

+135
-64
lines changed

11 files changed

+135
-64
lines changed

CONTRIBUTING.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,18 @@
33
Contributions are welcome. If you see a bug, feel free to submit a PR with a fix or an issue to discuss. For any features, please open an issue to discuss first.
44

55
## Necessary crates - cargo install <name>
6+
67
- cargo-nextest
78
- cargo-watch
89

910
## Dev setup
1011

1112
1. Run cargo build in the project directory.
12-
2. Install Postgres (v17 currently supported).
13-
3. Run the setup script `bash integration/setup.sh`.
14-
4. Launch pgdog configured for integration: `bash integration/dev-server.sh`.
15-
5. Run the tests `cargo nextest run --test-threads=1`. If a test fails, try running it directly.
13+
2. Install Postgres (all Pg versions supported).
14+
3. Some tests used prepared transactions. Enable them with `ALTER SYSTEM SET max_prepared_transactions TO 1000` and restart Postgres.
15+
4. Run the setup script `bash integration/setup.sh`.
16+
5. Launch pgdog configured for integration: `bash integration/dev-server.sh`.
17+
6. Run the tests `cargo nextest run --test-threads=1`. If a test fails, try running it directly.
1618

1719
## Coding
1820

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

integration/load_balancer/pgx/pg_stat_statements.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,11 @@ func LoadStatsForQuery(conn *pgx.Conn, query string) PgStatStatement {
2929

3030
func LoadStatsForPrimary(query string) PgStatStatement {
3131
conn, err := pgx.Connect(context.Background(), "postgres://postgres:postgres@127.0.0.1:45000/postgres")
32-
defer conn.Close(context.Background())
3332

3433
if err != nil {
3534
panic(err)
3635
}
36+
defer conn.Close(context.Background())
3737

3838
return LoadStatsForQuery(conn, query)
3939
}
@@ -44,10 +44,10 @@ func LoadStatsForReplicas(query string) []PgStatStatement {
4444
for i := range 2 {
4545
port := 45001 + i
4646
conn, err := pgx.Connect(context.Background(), fmt.Sprintf("postgres://postgres:postgres@127.0.0.1:%d/postgres", port))
47-
defer conn.Close(context.Background())
4847
if err != nil {
4948
panic(err)
5049
}
50+
defer conn.Close(context.Background())
5151

5252
stats = append(stats, LoadStatsForQuery(conn, query))
5353
}
@@ -59,12 +59,13 @@ func ResetStats() {
5959
for i := range 3 {
6060
port := 45000 + i
6161
conn, err := pgx.Connect(context.Background(), fmt.Sprintf("postgres://postgres:postgres@127.0.0.1:%d/postgres?sslmode=disable", port))
62-
defer conn.Close(context.Background())
6362

6463
if err != nil {
6564
panic(err)
6665
}
6766

67+
defer conn.Close(context.Background())
68+
6869
_, err = conn.Exec(context.Background(), "SELECT pg_stat_statements_reset()")
6970
if err != nil {
7071
panic(err)

integration/ruby/pg_spec.rb

Lines changed: 63 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
require_relative 'rspec_helper'
44

5-
def connect(dbname = 'pgdog')
6-
PG.connect(dbname: dbname, user: 'pgdog', password: 'pgdog', port: 6432, host: '127.0.0.1')
5+
def connect(dbname = 'pgdog', user = 'pgdog')
6+
PG.connect(dbname: dbname, user: user, password: 'pgdog', port: 6432, host: '127.0.0.1')
77
end
88

99
describe 'pg' do
@@ -13,82 +13,90 @@ def connect(dbname = 'pgdog')
1313

1414
it 'simple query' do
1515
%w[pgdog pgdog_sharded].each do |db|
16-
conn = connect db
17-
res = conn.exec 'SELECT 1::bigint AS one'
18-
expect(res[0]['one']).to eq('1')
19-
res = conn.exec 'SELECT $1 AS one, $2 AS two', [1, 2]
20-
expect(res[0]['one']).to eq('1')
21-
expect(res[0]['two']).to eq('2')
16+
%w[pgdog pgdog_2pc].each do |user|
17+
conn = connect db, user
18+
res = conn.exec 'SELECT 1::bigint AS one'
19+
expect(res[0]['one']).to eq('1')
20+
res = conn.exec 'SELECT $1 AS one, $2 AS two', [1, 2]
21+
expect(res[0]['one']).to eq('1')
22+
expect(res[0]['two']).to eq('2')
23+
end
2224
end
2325
end
2426

2527
it 'prepared statements' do
2628
%w[pgdog pgdog_sharded].each do |db|
27-
conn = connect db
28-
15.times do |i|
29-
name = "_pg_#{i}"
30-
conn.prepare name, 'SELECT $1 AS one'
31-
res = conn.exec_prepared name, [i]
32-
expect(res[0]['one']).to eq(i.to_s)
33-
end
34-
30.times do |_i|
29+
%w[pgdog pgdog_2pc].each do |user|
30+
conn = connect db, user
3531
15.times do |i|
3632
name = "_pg_#{i}"
33+
conn.prepare name, 'SELECT $1 AS one'
3734
res = conn.exec_prepared name, [i]
3835
expect(res[0]['one']).to eq(i.to_s)
3936
end
37+
30.times do |_i|
38+
15.times do |i|
39+
name = "_pg_#{i}"
40+
res = conn.exec_prepared name, [i]
41+
expect(res[0]['one']).to eq(i.to_s)
42+
end
43+
end
4044
end
4145
end
4246
end
4347

4448
it 'sharded' do
45-
conn = connect 'pgdog_sharded'
46-
conn.exec 'DROP TABLE IF EXISTS sharded'
47-
conn.exec 'CREATE TABLE sharded (id BIGINT, value TEXT)'
48-
conn.prepare 'insert', 'INSERT INTO sharded (id, value) VALUES ($1, $2) RETURNING *'
49-
conn.prepare 'select', 'SELECT * FROM sharded WHERE id = $1'
50-
15.times do |i|
51-
[10, 10_000_000_000].each do |num|
52-
id = num + i
53-
results = []
54-
results << conn.exec('INSERT INTO sharded (id, value) VALUES ($1, $2) RETURNING *', [id, 'value_one'])
55-
results << conn.exec('SELECT * FROM sharded WHERE id = $1', [id])
56-
results.each do |result|
57-
expect(result.num_tuples).to eq(1)
58-
expect(result[0]['id']).to eq(id.to_s)
59-
expect(result[0]['value']).to eq('value_one')
60-
end
61-
conn.exec 'TRUNCATE TABLE sharded'
62-
results << conn.exec_prepared('insert', [id, 'value_one'])
63-
results << conn.exec_prepared('select', [id])
64-
results.each do |result|
65-
expect(result.num_tuples).to eq(1)
66-
expect(result[0]['id']).to eq(id.to_s)
67-
expect(result[0]['value']).to eq('value_one')
49+
%w[pgdog pgdog_2pc].each do |user|
50+
conn = connect 'pgdog_sharded', user
51+
conn.exec 'DROP TABLE IF EXISTS sharded'
52+
conn.exec 'CREATE TABLE sharded (id BIGINT, value TEXT)'
53+
conn.prepare 'insert', 'INSERT INTO sharded (id, value) VALUES ($1, $2) RETURNING *'
54+
conn.prepare 'select', 'SELECT * FROM sharded WHERE id = $1'
55+
15.times do |i|
56+
[10, 10_000_000_000].each do |num|
57+
id = num + i
58+
results = []
59+
results << conn.exec('INSERT INTO sharded (id, value) VALUES ($1, $2) RETURNING *', [id, 'value_one'])
60+
results << conn.exec('SELECT * FROM sharded WHERE id = $1', [id])
61+
results.each do |result|
62+
expect(result.num_tuples).to eq(1)
63+
expect(result[0]['id']).to eq(id.to_s)
64+
expect(result[0]['value']).to eq('value_one')
65+
end
66+
conn.exec 'TRUNCATE TABLE sharded'
67+
results << conn.exec_prepared('insert', [id, 'value_one'])
68+
results << conn.exec_prepared('select', [id])
69+
results.each do |result|
70+
expect(result.num_tuples).to eq(1)
71+
expect(result[0]['id']).to eq(id.to_s)
72+
expect(result[0]['value']).to eq('value_one')
73+
end
6874
end
6975
end
7076
end
7177
end
7278

7379
it 'transactions' do
7480
%w[pgdog pgdog_sharded].each do |db|
75-
conn = connect db
76-
conn.exec 'DROP TABLE IF EXISTS sharded'
77-
conn.exec 'CREATE TABLE sharded (id BIGINT, value TEXT)'
78-
conn.prepare 'insert', 'INSERT INTO sharded (id, value) VALUES ($1, $2) RETURNING *'
79-
conn.prepare 'select', 'SELECT * FROM sharded WHERE id = $1'
81+
%w[pgdog pgdog_2pc].each do |user|
82+
conn = connect db, user
83+
conn.exec 'DROP TABLE IF EXISTS sharded'
84+
conn.exec 'CREATE TABLE sharded (id BIGINT, value TEXT)'
85+
conn.prepare 'insert', 'INSERT INTO sharded (id, value) VALUES ($1, $2) RETURNING *'
86+
conn.prepare 'select', 'SELECT * FROM sharded WHERE id = $1'
8087

81-
conn.exec 'BEGIN'
82-
res = conn.exec_prepared 'insert', [1, 'test']
83-
conn.exec 'COMMIT'
84-
expect(res.num_tuples).to eq(1)
85-
expect(res[0]['id']).to eq(1.to_s)
86-
conn.exec 'BEGIN'
87-
res = conn.exec_prepared 'select', [1]
88-
expect(res.num_tuples).to eq(1)
89-
expect(res[0]['id']).to eq(1.to_s)
90-
conn.exec 'ROLLBACK'
91-
conn.exec 'SELECT 1'
88+
conn.exec 'BEGIN'
89+
res = conn.exec_prepared 'insert', [1, 'test']
90+
conn.exec 'COMMIT'
91+
expect(res.num_tuples).to eq(1)
92+
expect(res[0]['id']).to eq(1.to_s)
93+
conn.exec 'BEGIN'
94+
res = conn.exec_prepared 'select', [1]
95+
expect(res.num_tuples).to eq(1)
96+
expect(res[0]['id']).to eq(1.to_s)
97+
conn.exec 'ROLLBACK'
98+
conn.exec 'SELECT 1'
99+
end
92100
end
93101
end
94102

integration/two_pc/pgdog.toml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
[general]
2+
two_phase_commit = false
3+
4+
[[databases]]
5+
name = "pgdog"
6+
host = "127.0.0.1"
7+
shard = 0
8+
database_name = "shard_0"
9+
10+
[[databases]]
11+
name = "pgdog"
12+
host = "127.0.0.1"
13+
shard = 1
14+
database_name = "shard_1"
15+
16+
[admin]
17+
password = "pgdog"

integration/two_pc/run.sh

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#!/bin/bash
2+
export PGPASSWORD=pgdog
3+
export PGHOST=127.0.0.1
4+
export PGPORT=6432
5+
export PGUSER=pgdog
6+
export PGDATABASE=pgdog
7+
8+
pgbench -f script.sql -c 10 -t 1000 -P 1

integration/two_pc/script.sql

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
\set id (1021 * random(1, 10000000))
2+
3+
-- In a transaction.
4+
BEGIN;
5+
INSERT INTO sharded_2pc (id, value) VALUES (:id, 'some value') RETURNING *;
6+
SELECT * FROM sharded_2pc WHERE id = :id AND value = 'some value';
7+
UPDATE sharded_2pc SET value = 'another value' WHERE id = :id;
8+
DELETE FROM sharded_2pc WHERE id = :id AND value = 'another value';
9+
ROLLBACK;
10+
11+
-- Outside a transaction.
12+
INSERT INTO sharded_2pc (id, value) VALUES (:id, 'some value') RETURNING *;
13+
SELECT * FROM sharded_2pc WHERE id = :id AND value = 'some value';
14+
UPDATE sharded_2pc SET value = 'another value' WHERE id = :id;
15+
DELETE FROM sharded_2pc WHERE id = :id;

integration/two_pc/setup.sh

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#!/bin/bash
2+
export PGPASSWORD=pgdog
3+
export PGHOST=127.0.0.1
4+
export PGPORT=6432
5+
export PGUSER=pgdog
6+
export PGDATABASE=pgdog
7+
8+
psql -c 'CREATE TABLE IF NOT EXISTS sharded_2pc (id BIGINT PRIMARY KEY, value VARCHAR)'

integration/two_pc/users.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[[users]]
2+
name = "pgdog"
3+
database = "pgdog"
4+
password = "pgdog"

integration/users.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,14 @@ server_user = "pgdog"
3030
two_phase_commit = true
3131
min_pool_size = 0
3232

33+
[[users]]
34+
name = "pgdog_2pc"
35+
database = "pgdog"
36+
password = "pgdog"
37+
server_user = "pgdog"
38+
two_phase_commit = true
39+
min_pool_size = 0
40+
3341
[[users]]
3442
name = "pgdog_migrator"
3543
database = "pgdog_sharded"

0 commit comments

Comments
 (0)