From 17e157e06e7402c9e1c6a44659390930961d644a Mon Sep 17 00:00:00 2001 From: vmgolovin Date: Tue, 4 Feb 2020 11:56:18 +0400 Subject: [PATCH] BIT VARYING data type support added BIT and BIT VARYING ("varbit") data types have the same binary format so we can just use for them the same C representation and the code of handlers. --- source/src/handler.c | 4 +++- source/src/libpqtypes-int.h | 4 +++- source/src/libpqtypes.h | 4 +++- source/src/regression-test.c | 35 +++++++++++++++++++--------- source/src/varlena.c | 44 ++++++++++++++++++++++++------------ 5 files changed, 62 insertions(+), 29 deletions(-) diff --git a/source/src/handler.c b/source/src/handler.c index 861b775..ed8fe43 100644 --- a/source/src/handler.c +++ b/source/src/handler.c @@ -115,7 +115,9 @@ static PGtypeHandler pg_handlers[] = { /* bit string types */ {34, "pg_catalog", "bit", -1, ZPBITOID, 1561, pqt_put_bit, - pqt_get_bit, __HANDLER_DEFAULTS__} + pqt_get_bit, __HANDLER_DEFAULTS__}, + {35, "pg_catalog", "varbit", -1, VARBITOID, 1563, pqt_put_varbit, + pqt_get_varbit, __HANDLER_DEFAULTS__} }; static int diff --git a/source/src/libpqtypes-int.h b/source/src/libpqtypes-int.h index adb4b68..d90fbf2 100644 --- a/source/src/libpqtypes-int.h +++ b/source/src/libpqtypes-int.h @@ -255,7 +255,7 @@ extern "C" { #define NAMEOID 19 #define TEXTOID 25 #define ZPBITOID 1560 -#define VARBITOID 1562 /* not supported yet */ +#define VARBITOID 1562 #define BYTEAOID 17 /* date and time types */ #define DATEOID 1082 @@ -526,6 +526,8 @@ int pqt_put_bytea(PGtypeArgs *args); int pqt_get_bytea(PGtypeArgs *args); int pqt_put_bit(PGtypeArgs *args); int pqt_get_bit(PGtypeArgs *args); +int pqt_put_varbit(PGtypeArgs *args); +int pqt_get_varbit(PGtypeArgs *args); #ifdef __cplusplus } diff --git a/source/src/libpqtypes.h b/source/src/libpqtypes.h index ee8051c..5bb502e 100644 --- a/source/src/libpqtypes.h +++ b/source/src/libpqtypes.h @@ -146,7 +146,9 @@ typedef struct int len_bytes; int32_t len_bits; char *data; -} PGbit; +} PGvarbit; + +typedef PGvarbit PGbit; /* ---------------- * Numeric types diff --git a/source/src/regression-test.c b/source/src/regression-test.c index 25d4838..57d31c7 100644 --- a/source/src/regression-test.c +++ b/source/src/regression-test.c @@ -842,15 +842,16 @@ static void test_varlen(int format) "-62731893541288039212143296120112.12431212671229121291821928918211"; static char bitdata[] = {7, 6, 5, 4, 3, 2, 1, 0}; PGbit bit; - PGbit bitin = {8, 59, bitdata}; + PGvarbit varbit; + PGvarbit varbitin = {8, 59, bitdata}; PQparamReset(param); printf("\nVariable-length types: (%s)\n", format ? "binary" : "text"); r = PQputf(param, "%bpchar %bpchar* %varchar %varchar* " - "%text %text* %bytea %bytea* %uuid %numeric %bit", + "%text %text* %bytea %bytea* %uuid %numeric %bit %varbit", bpcharin, bpcharin, varcharin, varcharin, textin, textin, - &byteain, &byteain, uuidin, numin, &bitin); + &byteain, &byteain, uuidin, numin, &varbitin, &varbitin); PUTOKAY(param, r, "PQputf(varlen)"); DROP_TABLE("libpq_varlen"); @@ -858,28 +859,29 @@ static void test_varlen(int format) result = PQexec(conn, "CREATE TABLE libpq_varlen (" "bp_a bpchar(32), bp_b bpchar(32), vc_a varchar(32), vc_b varchar(32), " "text_a text, text_b text, bytea_a bytea, bytea_b bytea, " - "uid uuid, n numeric, bit_a bit(59))"); + "uid uuid, n numeric, bit_a bit(59), varbit_a bit varying(62))"); CMDOKAY("creating libpq_varlen table"); PQclear(result); result = PQparamExec(conn, param, "INSERT INTO libpq_varlen VALUES" - "($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11)", format); + "($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12)", format); CMDOKAY("PQparamExec(INSERT:varlen)"); PQclear(result); result = PQparamExec(conn, NULL, - "SELECT bp_a,vc_a,text_a,bytea_a,uid,n,bit_a FROM libpq_varlen", format); + "SELECT bp_a,vc_a,text_a,bytea_a,uid,n,bit_a,varbit_a FROM libpq_varlen", format); TUPSOKAY("PQparamExec(SELECT:varlen)"); r = PQgetf(result, 0, - "%bpchar %varchar %text %bytea %uuid %numeric %bit", + "%bpchar %varchar %text %bytea %uuid %numeric %bit %varbit", 0, &bpcharp, /* field_num, PGbpchar* */ 1, &varcharp, /* field_num, PGvarchar* */ 2, &textp, /* field_num, PGtext* */ 3, &byteap, /* field_num, PGbytea* */ 4, &uuid, /* field_num, PGuuid* */ 5, &num, /* field_num, PGnumeric* */ - 6, &bit); /* field num, PGbit* */ + 6, &bit, /* field num, PGbit* */ + 7, &varbit); /* field num, PGvarbit* */ GETOKAY(r, "PQgetf(varlen)"); /* Because we are using the '*' specifier flag, we clear the results at @@ -920,9 +922,9 @@ static void test_varlen(int format) CHKVLEN("numeric", num, numin); testcnt++; - if (bitin.len_bytes != bit.len_bytes || - bitin.len_bits != bit.len_bits || - memcmp(bitin.data, bit.data, (size_t)bit.len_bytes)) + if (varbitin.len_bytes != bit.len_bytes || + varbitin.len_bits != bit.len_bits || + memcmp(varbitin.data, bit.data, (size_t)bit.len_bytes)) { failcnt++; fprintf(stderr, " %%bit - FAILED'n"); @@ -930,6 +932,17 @@ static void test_varlen(int format) else printf(" %%bit - passed\n"); + testcnt++; + if (varbitin.len_bytes != varbit.len_bytes || + varbitin.len_bits != varbit.len_bits || + memcmp(varbitin.data, varbit.data, (size_t)varbit.len_bytes)) + { + failcnt++; + fprintf(stderr, " %%varbit - FAILED'n"); + } + else + printf(" %%varbit - passed\n"); + PQclear(result); } diff --git a/source/src/varlena.c b/source/src/varlena.c index 0490bae..4114c26 100644 --- a/source/src/varlena.c +++ b/source/src/varlena.c @@ -84,31 +84,33 @@ pqt_get_bytea(PGtypeArgs *args) return 0; } +/* Bit string types */ + int -pqt_put_bit(PGtypeArgs *args) +pqt_put_varbit(PGtypeArgs *args) { int len_bytes; int total_bytes; char *out; - PGbit *bit = va_arg(args->ap, PGbit *); - PUTNULLCHK(args, bit); - len_bytes = bit->len_bytes; + PGvarbit *varbit = va_arg(args->ap, PGvarbit *); + PUTNULLCHK(args, varbit); + len_bytes = varbit->len_bytes; total_bytes = len_bytes + (int)sizeof(int32_t); if (args->put.expandBuffer(args, total_bytes) == -1) RERR_MEM(args); out = args->put.out; - pqt_buf_putint4(out, bit->len_bits); - memcpy(out + sizeof(int32_t), bit->data, (size_t)len_bytes); + pqt_buf_putint4(out, varbit->len_bits); + memcpy(out + sizeof(int32_t), varbit->data, (size_t)len_bytes); return total_bytes; } int -pqt_get_bit(PGtypeArgs *args) +pqt_get_varbit(PGtypeArgs *args) { DECLVALUE(args); DECLLENGTH(args); - PGbit *bit = va_arg(args->ap, PGbit *); - CHKGETVALS(args, bit); + PGvarbit *varbit = va_arg(args->ap, PGvarbit *); + CHKGETVALS(args, varbit); if (args->format == TEXTFMT) { unsigned char *cur_byte; @@ -139,14 +141,26 @@ pqt_get_bit(PGtypeArgs *args) mask_byte = 0x80; } } - bit->len_bytes = len_bytes; - bit->len_bits = (int32_t)len_bits; - bit->data = data; + varbit->len_bytes = len_bytes; + varbit->len_bits = (int32_t)len_bits; + varbit->data = data; return 0; } /* binary format */ - bit->len_bytes = valuel - (int)sizeof(int32_t); - bit->len_bits = pqt_buf_getint4(value); - bit->data = value + sizeof(int32_t); + varbit->len_bytes = valuel - (int)sizeof(int32_t); + varbit->len_bits = pqt_buf_getint4(value); + varbit->data = value + sizeof(int32_t); return 0; } + +int +pqt_put_bit(PGtypeArgs *args) +{ + return pqt_put_varbit(args); +} + +int +pqt_get_bit(PGtypeArgs *args) +{ + return pqt_get_varbit(args); +}