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.
This commit is contained in:
vmgolovin
2020-02-04 11:56:18 +04:00
parent 1047d59c49
commit 17e157e06e
5 changed files with 62 additions and 29 deletions
+3 -1
View File
@@ -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
+3 -1
View File
@@ -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
}
+3 -1
View File
@@ -146,7 +146,9 @@ typedef struct
int len_bytes;
int32_t len_bits;
char *data;
} PGbit;
} PGvarbit;
typedef PGvarbit PGbit;
/* ----------------
* Numeric types
+24 -11
View File
@@ -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);
}
+29 -15
View File
@@ -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);
}