Skip to content

Commit ba4bf45

Browse files
committed
fix: report and handle errors
1 parent 0ad4df6 commit ba4bf45

File tree

6 files changed

+63
-4
lines changed

6 files changed

+63
-4
lines changed

nix/pgScript.nix

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ let
2323
cp ${../test/samples/all_movies.csv} $tmpdir/all_movies.csv
2424
cp ${../test/samples/all_movies.csv.bz2} $tmpdir/all_movies.csv.bz2
2525
26+
dd if=$tmpdir/all_movies.csv.bz2 of=$tmpdir/damaged_all_movies.csv.bz2 bs=1 count=1K
27+
28+
dd if=$tmpdir/all_movies.csv.bz2 of=$tmpdir/empty_file count=0
29+
30+
dd if=$tmpdir/all_movies.csv.bz2 of=$tmpdir/wrong_header_all_movies.csv.bz2 bs=1 skip=2
31+
2632
"$@"
2733
'';
2834
in

src/pg_bzip.c

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,26 @@ PG_MODULE_MAGIC;
1818
PG_FUNCTION_INFO_V1(bzcat);
1919
PG_FUNCTION_INFO_V1(bzip2);
2020

21+
/*error handling*/
22+
typedef struct {
23+
char buf[40];
24+
} bz2_error_msg;
25+
26+
static bz2_error_msg get_bz2_error_msg(int bz2_code){
27+
switch(bz2_code){
28+
case BZ_SEQUENCE_ERROR: return (bz2_error_msg){"internal error"};
29+
case BZ_PARAM_ERROR: return (bz2_error_msg){"incorrect parameter"};
30+
case BZ_MEM_ERROR: return (bz2_error_msg){"memory allocation failed"};
31+
case BZ_DATA_ERROR: return (bz2_error_msg){"integrity error"};
32+
case BZ_DATA_ERROR_MAGIC: return (bz2_error_msg){"data is not in bzip2 format"};
33+
case BZ_IO_ERROR: return (bz2_error_msg){"i/o error"};
34+
case BZ_UNEXPECTED_EOF: return (bz2_error_msg){"compressed data ends unexpectedly"};
35+
case BZ_OUTBUFF_FULL: return (bz2_error_msg){"buffer size exceeded"};
36+
case BZ_CONFIG_ERROR: return (bz2_error_msg){"bad bzlib library"};
37+
default: return (bz2_error_msg){"unknown"};
38+
}
39+
}
40+
2141
/*
2242
*custom memory allocators for bzip2
2343
*/
@@ -60,7 +80,7 @@ Datum bzip2(PG_FUNCTION_ARGS){
6080
0); // according to the man pages (on --repetitive-fast --repetitive-best), the workFactor is unused, so we just leave it at 0 which will take the default.
6181

6282
if ( status != BZ_OK ) {
63-
ereport(ERROR, errmsg("bzip2 compression initialization failed"));
83+
ereport(ERROR, errmsg("bzip2 compression initialization failed: %s", get_bz2_error_msg(status).buf));
6484
}
6585

6686
StringInfoData si;
@@ -82,7 +102,7 @@ Datum bzip2(PG_FUNCTION_ARGS){
82102

83103
if ( status != BZ_STREAM_END) {
84104
BZ2_bzCompressEnd(&stream);
85-
ereport(ERROR, errmsg("bzip2 compression failed"));
105+
ereport(ERROR, errmsg("bzip2 compression failed: %s", get_bz2_error_msg(status).buf));
86106
}
87107

88108
BZ2_bzCompressEnd(&stream);
@@ -114,7 +134,7 @@ Datum bzcat(PG_FUNCTION_ARGS){
114134
status = BZ2_bzDecompressInit(&stream, BZ2_VERBOSITY, 0);
115135

116136
if ( status != BZ_OK ) {
117-
ereport(ERROR, errmsg("bzip2 decompression initialization failed"));
137+
ereport(ERROR, errmsg("bzip2 decompression initialization failed: %s", get_bz2_error_msg(status).buf));
118138
}
119139

120140
StringInfoData si;
@@ -127,11 +147,17 @@ Datum bzcat(PG_FUNCTION_ARGS){
127147

128148
stream.avail_out = BZ_MAX_UNUSED;
129149
stream.next_out = buffer;
150+
151+
if (status == BZ_OK && stream.avail_in == 0 && stream.avail_out > 0){
152+
status = BZ_UNEXPECTED_EOF;
153+
break;
154+
};
155+
130156
} while (status == BZ_OK);
131157

132158
if ( status != BZ_STREAM_END ){
133159
BZ2_bzDecompressEnd(&stream);
134-
ereport(ERROR, errmsg("bzip2 decompression failed"));
160+
ereport(ERROR, errmsg("bzip2 decompression failed: %s", get_bz2_error_msg(status).buf));
135161
}
136162

137163
BZ2_bzDecompressEnd(&stream);

test/expected/errors.out

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
create extension if not exists bzip;
2+
NOTICE: extension "bzip" already exists, skipping
3+
\echo
4+
5+
select bzcat(pg_read_binary_file('./damaged_all_movies.csv.bz2'));
6+
ERROR: bzip2 decompression failed: compressed data ends unexpectedly
7+
\echo
8+
9+
select bzcat(pg_read_binary_file('./empty_file'));
10+
ERROR: bzip2 decompression failed: compressed data ends unexpectedly
11+
\echo
12+
13+
select bzcat(pg_read_binary_file('./wrong_header_all_movies.csv.bz2'));
14+
ERROR: bzip2 decompression failed: data is not in bzip2 format

test/samples/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
## Sample bz2 files
2+
3+
`all_movies.csv.bz2` was downloaded from https://www.omdb.org/en/us/content/Help:DataDownload.

test/samples/empty_file

Whitespace-only changes.

test/sql/errors.sql

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
create extension if not exists bzip;
2+
\echo
3+
4+
select bzcat(pg_read_binary_file('./damaged_all_movies.csv.bz2'));
5+
\echo
6+
7+
select bzcat(pg_read_binary_file('./empty_file'));
8+
\echo
9+
10+
select bzcat(pg_read_binary_file('./wrong_header_all_movies.csv.bz2'));

0 commit comments

Comments
 (0)