Skip to content

Commit 481a550

Browse files
authored
test: migrate psql test cases to BATS (#328)
1 parent 680ced2 commit 481a550

File tree

9 files changed

+162
-151
lines changed

9 files changed

+162
-151
lines changed

.github/workflows/bats-tests.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ jobs:
3232
run: |
3333
go get .
3434
35-
pip3 install "sqlglot[rs]"
35+
pip3 install "sqlglot[rs]" pyarrow pandas
3636
3737
curl -LJO https://github.com/duckdb/duckdb/releases/download/v1.1.3/duckdb_cli-linux-amd64.zip
3838
unzip duckdb_cli-linux-amd64.zip
@@ -49,4 +49,4 @@ jobs:
4949
5050
- name: Run BATS Tests
5151
run: |
52-
find test/bats -name "*.bats" -type f -exec bats {} +
52+
find test/bats -name "*.bats" -type f -exec bats --print-output-on-failure {} +

.github/workflows/psql.yml

Lines changed: 0 additions & 56 deletions
This file was deleted.

pgtest/psql/copy/arrow.sql

Lines changed: 0 additions & 19 deletions
This file was deleted.

pgtest/psql/copy/basic.sql

Lines changed: 0 additions & 11 deletions
This file was deleted.

pgtest/psql/copy/db.sql

Lines changed: 0 additions & 13 deletions
This file was deleted.

pgtest/psql/copy/parquet.sql

Lines changed: 0 additions & 31 deletions
This file was deleted.

pgtest/psql/copy/stdout.sql

Lines changed: 0 additions & 19 deletions
This file was deleted.

test/bats/postgres/copy_tests.bats

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
#!/usr/bin/env bats
2+
bats_require_minimum_version 1.5.0
3+
4+
load helper
5+
6+
setup() {
7+
psql_exec_stdin <<-EOF
8+
CREATE SCHEMA IF NOT EXISTS test_copy;
9+
USE test_copy;
10+
CREATE OR REPLACE TABLE t (a int, b text, c float);
11+
INSERT INTO t VALUES (1, 'one', 1.1), (2, 'two', 2.2), (3, 'three', 3.3);
12+
EOF
13+
}
14+
15+
teardown() {
16+
psql_exec "DROP SCHEMA IF EXISTS test_copy CASCADE;"
17+
rm -f test_*.{csv,parquet,arrow,db} 2>/dev/null
18+
}
19+
20+
@test "copy with csv format" {
21+
# Test copy to CSV file
22+
tmpfile=$(mktemp)
23+
psql_exec "\copy test_copy.t TO '${tmpfile}' (FORMAT CSV, HEADER false);"
24+
run -0 cat "${tmpfile}"
25+
[ "${lines[0]}" = "1,one,1.1" ]
26+
[ "${lines[1]}" = "2,two,2.2" ]
27+
[ "${lines[2]}" = "3,three,3.3" ]
28+
29+
rm "${tmpfile}"
30+
31+
# Test copy from CSV with headers
32+
psql_exec_stdin <<-EOF
33+
USE test_copy;
34+
CREATE TABLE csv_test (a int, b text);
35+
\copy csv_test FROM 'pgtest/testdata/basic.csv' (FORMAT CSV, HEADER);
36+
\copy csv_test FROM 'pgtest/testdata/basic.csv' WITH DELIMITER ',' CSV HEADER;
37+
EOF
38+
run -0 psql_exec "SELECT count(*) FROM test_copy.csv_test"
39+
[ "${output}" != "0" ]
40+
41+
# Test various CSV output formats
42+
tmpfile=$(mktemp)
43+
psql_exec_stdin <<-EOF
44+
USE test_copy;
45+
\o '${tmpfile}';
46+
\copy t TO STDOUT;
47+
\copy t (a, b) TO STDOUT (FORMAT CSV);
48+
\copy t TO STDOUT (FORMAT CSV, HEADER false, DELIMITER '|');
49+
\copy (SELECT a * a, b, c + a FROM t) TO STDOUT (FORMAT CSV, HEADER false, DELIMITER '|');
50+
EOF
51+
[ "$status" -eq 0 ]
52+
run -0 cat "${tmpfile}"
53+
[ "${#lines[@]}" -ge 12 ]
54+
[ "${lines[3]}" = "1,one" ]
55+
[ "${lines[6]}" = "1|one|1.1" ]
56+
[ "${lines[9]}" = "1|one|2.1" ]
57+
58+
rm "${tmpfile}"
59+
}
60+
61+
@test "copy with parquet format" {
62+
# Test basic COPY TO PARQUET
63+
tmpfile=$(mktemp).parquet
64+
run psql_exec_stdin <<-EOF
65+
USE test_copy;
66+
\copy t TO '${tmpfile}' (FORMAT PARQUET);
67+
EOF
68+
[ "$status" -eq 0 ]
69+
run -0 duckdb_exec "SELECT COUNT(*) FROM '${tmpfile}'"
70+
[ "${output}" = "3" ]
71+
rm "${tmpfile}"
72+
73+
# Test with column selection
74+
outfile="test_cols.parquet"
75+
psql_exec_stdin <<-EOF
76+
USE test_copy;
77+
\copy t (a, b) TO '${outfile}' (FORMAT PARQUET);
78+
EOF
79+
run -0 duckdb_exec "SELECT COUNT(*) FROM '${outfile}'"
80+
[ "${output}" = "3" ]
81+
82+
# Test with transformed data
83+
outfile="test_transform.parquet"
84+
psql_exec "\copy (SELECT a * a, b, c + a FROM test_copy.t) TO '${outfile}' (FORMAT PARQUET);"
85+
run duckdb_exec "SELECT COUNT(*) FROM '${outfile}'"
86+
[ "${output}" = "3" ]
87+
}
88+
89+
@test "copy with arrow format" {
90+
# Test basic COPY TO ARROW
91+
outfile="test_out.arrow"
92+
psql_exec_stdin <<-EOF
93+
USE test_copy;
94+
\copy t TO '${outfile}' (FORMAT ARROW);
95+
EOF
96+
run -0 python3 -c "import pyarrow as pa; reader = pa.ipc.open_stream('${outfile}'); print(len(reader.read_all()))"
97+
[ "${output}" = "3" ]
98+
99+
# Test with column selection
100+
outfile="test_cols.arrow"
101+
psql_exec_stdin <<-EOF
102+
USE test_copy;
103+
\copy t (a, b) TO '${outfile}' (FORMAT ARROW);
104+
EOF
105+
run -0 python3 -c "import pyarrow as pa; reader = pa.ipc.open_stream('${outfile}'); print(len(reader.read_all()))"
106+
[ "${output}" = "3" ]
107+
108+
# Test with transformed data
109+
outfile="test_transform.arrow"
110+
psql_exec "\copy (SELECT a * a, b, c + a FROM test_copy.t) TO '${outfile}' (FORMAT ARROW);"
111+
run -0 python3 -c "import pyarrow as pa; reader = pa.ipc.open_stream('${outfile}'); print(len(reader.read_all()))"
112+
[ "${output}" == "3" ]
113+
114+
# Test COPY FROM ARROW
115+
psql_exec_stdin <<-EOF
116+
USE test_copy;
117+
CREATE TABLE arrow_test (a int, b text, c float);
118+
\copy arrow_test FROM '${outfile}' (FORMAT ARROW);
119+
EOF
120+
run -0 psql_exec "SELECT COUNT(*) FROM test_copy.arrow_test"
121+
[ "${output}" == "3" ]
122+
}
123+
124+
@test "copy from database" {
125+
psql_exec_stdin <<-EOF
126+
USE test_copy;
127+
CREATE TABLE db_test (a int, b text);
128+
INSERT INTO db_test VALUES (1, 'a'), (2, 'b'), (3, 'c');
129+
ATTACH 'test_copy.db' AS tmp;
130+
COPY FROM DATABASE myduck TO tmp;
131+
DETACH tmp;
132+
EOF
133+
}
134+
135+
@test "copy error handling" {
136+
skip
137+
# Test copying from non-existent schema
138+
run psql_exec "\copy nonexistent_schema.t TO STDOUT;"
139+
[ "$status" -ne 0 ]
140+
141+
# Test copying from non-existent table
142+
run psql_exec "\copy test_copy.nonexistent_table TO STDOUT;"
143+
[ "$status" -ne 0 ]
144+
145+
# Test invalid SQL syntax
146+
run psql_exec "\copy (SELECT FROM t) TO STDOUT;"
147+
[ "$status" -ne 0 ]
148+
149+
# Test copying to non-existent schema
150+
tmpfile=$(mktemp)
151+
run psql_exec "\copy nonexistent_schema.new_table FROM '${tmpfile}';"
152+
[ "$status" -ne 0 ]
153+
rm "${tmpfile}"
154+
}

test/bats/postgres/helper.bash

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,10 @@ psql_exec() {
1313

1414
psql_exec_stdin() {
1515
psql -h "$PG_HOST" -U "$PG_USER" -F ',' --no-align --field-separator ',' -t --pset footer=off -v "ON_ERROR_STOP=1" "$@"
16+
}
17+
18+
duckdb_exec() {
19+
local query="$1"
20+
shift
21+
duckdb --csv --noheader "$@" -c "$query"
1622
}

0 commit comments

Comments
 (0)