|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
|
|
|
* varbit.c
|
|
|
|
* Functions for the SQL datatypes BIT() and BIT VARYING().
|
|
|
|
*
|
Fix failure to zero-pad the result of bitshiftright().
If the bitstring length is not a multiple of 8, we'd shift the
rightmost bits into the pad space, which must be zeroes --- bit_cmp,
for one, depends on that. This'd lead to the result failing to
compare equal to what it should compare equal to, as reported in
bug #16013 from Daryl Waycott.
This is, if memory serves, not the first such bug in the bitstring
functions. In hopes of making it the last one, do a bit more work
than minimally necessary to fix the bug:
* Add assertion checks to bit_out() and varbit_out() to complain if
they are given incorrectly-padded input. This will improve the
odds that manual testing of any new patch finds problems.
* Encapsulate the padding-related logic in macros to make it
easier to use.
Also, remove unnecessary padding logic from bit_or() and bitxor().
Somebody had already noted that we need not re-pad the result of
bit_and() since the inputs are required to be the same length,
but failed to extrapolate that to the other two.
Also, move a comment block that once was near the head of varbit.c
(but people kept putting other stuff in front of it), to put it in
the header block.
Note for the release notes: if anyone has inconsistent data as a
result of saving the output of bitshiftright() in a table, it's
possible to fix it with something like
UPDATE mytab SET bitcol = ~(~bitcol) WHERE bitcol != ~(~bitcol);
This has been broken since day one, so back-patch to all supported
branches.
Discussion: https://postgr.es/m/16013-c2765b6996aacae9@postgresql.org
6 years ago
|
|
|
* The data structure contains the following elements:
|
|
|
|
* header -- length of the whole data structure (incl header)
|
|
|
|
* in bytes (as with all varying length datatypes)
|
|
|
|
* data section -- private data section for the bits data structures
|
|
|
|
* bitlength -- length of the bit string in bits
|
|
|
|
* bitdata -- bit string, most significant byte first
|
|
|
|
*
|
|
|
|
* The length of the bitdata vector should always be exactly as many
|
|
|
|
* bytes as are needed for the given bitlength. If the bitlength is
|
|
|
|
* not a multiple of 8, the extra low-order padding bits of the last
|
|
|
|
* byte must be zeroes.
|
|
|
|
*
|
|
|
|
* attypmod is defined as the length of the bit string in bits, or for
|
|
|
|
* varying bits the maximum length.
|
|
|
|
*
|
|
|
|
* Code originally contributed by Adriaan Joubert.
|
|
|
|
*
|
|
|
|
* Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
|
|
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
|
|
|
* src/backend/utils/adt/varbit.c
|
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "postgres.h"
|
|
|
|
|
|
|
|
#include "access/htup_details.h"
|
|
|
|
#include "common/int.h"
|
|
|
|
#include "libpq/pqformat.h"
|
|
|
|
#include "nodes/nodeFuncs.h"
|
|
|
|
#include "nodes/supportnodes.h"
|
|
|
|
#include "port/pg_bitutils.h"
|
|
|
|
#include "utils/array.h"
|
|
|
|
#include "utils/fmgrprotos.h"
|
|
|
|
#include "utils/varbit.h"
|
|
|
|
|
|
|
|
#define HEXDIG(z) ((z)<10 ? ((z)+'0') : ((z)-10+'A'))
|
|
|
|
|
Fix failure to zero-pad the result of bitshiftright().
If the bitstring length is not a multiple of 8, we'd shift the
rightmost bits into the pad space, which must be zeroes --- bit_cmp,
for one, depends on that. This'd lead to the result failing to
compare equal to what it should compare equal to, as reported in
bug #16013 from Daryl Waycott.
This is, if memory serves, not the first such bug in the bitstring
functions. In hopes of making it the last one, do a bit more work
than minimally necessary to fix the bug:
* Add assertion checks to bit_out() and varbit_out() to complain if
they are given incorrectly-padded input. This will improve the
odds that manual testing of any new patch finds problems.
* Encapsulate the padding-related logic in macros to make it
easier to use.
Also, remove unnecessary padding logic from bit_or() and bitxor().
Somebody had already noted that we need not re-pad the result of
bit_and() since the inputs are required to be the same length,
but failed to extrapolate that to the other two.
Also, move a comment block that once was near the head of varbit.c
(but people kept putting other stuff in front of it), to put it in
the header block.
Note for the release notes: if anyone has inconsistent data as a
result of saving the output of bitshiftright() in a table, it's
possible to fix it with something like
UPDATE mytab SET bitcol = ~(~bitcol) WHERE bitcol != ~(~bitcol);
This has been broken since day one, so back-patch to all supported
branches.
Discussion: https://postgr.es/m/16013-c2765b6996aacae9@postgresql.org
6 years ago
|
|
|
/* Mask off any bits that should be zero in the last byte of a bitstring */
|
|
|
|
#define VARBIT_PAD(vb) \
|
|
|
|
do { \
|
|
|
|
int32 pad_ = VARBITPAD(vb); \
|
|
|
|
Assert(pad_ >= 0 && pad_ < BITS_PER_BYTE); \
|
|
|
|
if (pad_ > 0) \
|
|
|
|
*(VARBITS(vb) + VARBITBYTES(vb) - 1) &= BITMASK << pad_; \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Many functions work byte-by-byte, so they have a pointer handy to the
|
|
|
|
* last-plus-one byte, which saves a cycle or two.
|
|
|
|
*/
|
|
|
|
#define VARBIT_PAD_LAST(vb, ptr) \
|
|
|
|
do { \
|
|
|
|
int32 pad_ = VARBITPAD(vb); \
|
|
|
|
Assert(pad_ >= 0 && pad_ < BITS_PER_BYTE); \
|
|
|
|
if (pad_ > 0) \
|
|
|
|
*((ptr) - 1) &= BITMASK << pad_; \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
/* Assert proper padding of a bitstring */
|
|
|
|
#ifdef USE_ASSERT_CHECKING
|
|
|
|
#define VARBIT_CORRECTLY_PADDED(vb) \
|
|
|
|
do { \
|
|
|
|
int32 pad_ = VARBITPAD(vb); \
|
|
|
|
Assert(pad_ >= 0 && pad_ < BITS_PER_BYTE); \
|
|
|
|
Assert(pad_ == 0 || \
|
|
|
|
(*(VARBITS(vb) + VARBITBYTES(vb) - 1) & ~(BITMASK << pad_)) == 0); \
|
|
|
|
} while (0)
|
|
|
|
#else
|
|
|
|
#define VARBIT_CORRECTLY_PADDED(vb) ((void) 0)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static VarBit *bit_catenate(VarBit *arg1, VarBit *arg2);
|
|
|
|
static VarBit *bitsubstring(VarBit *arg, int32 s, int32 l,
|
|
|
|
bool length_not_specified);
|
|
|
|
static VarBit *bit_overlay(VarBit *t1, VarBit *t2, int sp, int sl);
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* common code for bittypmodin and varbittypmodin
|
|
|
|
*/
|
|
|
|
static int32
|
|
|
|
anybit_typmodin(ArrayType *ta, const char *typename)
|
|
|
|
{
|
|
|
|
int32 typmod;
|
|
|
|
int32 *tl;
|
|
|
|
int n;
|
|
|
|
|
|
|
|
tl = ArrayGetIntegerTypmods(ta, &n);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* we're not too tense about good error message here because grammar
|
|
|
|
* shouldn't allow wrong number of modifiers for BIT
|
|
|
|
*/
|
|
|
|
if (n != 1)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
|
|
|
errmsg("invalid type modifier")));
|
|
|
|
|
|
|
|
if (*tl < 1)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
|
|
|
errmsg("length for type %s must be at least 1",
|
|
|
|
typename)));
|
|
|
|
if (*tl > (MaxAttrSize * BITS_PER_BYTE))
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
|
|
|
errmsg("length for type %s cannot exceed %d",
|
|
|
|
typename, MaxAttrSize * BITS_PER_BYTE)));
|
|
|
|
|
|
|
|
typmod = *tl;
|
|
|
|
|
|
|
|
return typmod;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* common code for bittypmodout and varbittypmodout
|
|
|
|
*/
|
|
|
|
static char *
|
|
|
|
anybit_typmodout(int32 typmod)
|
|
|
|
{
|
|
|
|
char *res = (char *) palloc(64);
|
|
|
|
|
|
|
|
if (typmod >= 0)
|
|
|
|
snprintf(res, 64, "(%d)", typmod);
|
|
|
|
else
|
|
|
|
*res = '\0';
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* bit_in -
|
|
|
|
* converts a char string to the internal representation of a bitstring.
|
|
|
|
* The length is determined by the number of bits required plus
|
|
|
|
* VARHDRSZ bytes or from atttypmod.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
bit_in(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
char *input_string = PG_GETARG_CSTRING(0);
|
|
|
|
#ifdef NOT_USED
|
|
|
|
Oid typelem = PG_GETARG_OID(1);
|
|
|
|
#endif
|
|
|
|
int32 atttypmod = PG_GETARG_INT32(2);
|
|
|
|
Node *escontext = fcinfo->context;
|
|
|
|
VarBit *result; /* The resulting bit string */
|
|
|
|
char *sp; /* pointer into the character string */
|
|
|
|
bits8 *r; /* pointer into the result */
|
|
|
|
int len, /* Length of the whole data structure */
|
|
|
|
bitlen, /* Number of bits in the bit string */
|
|
|
|
slen; /* Length of the input string */
|
|
|
|
bool bit_not_hex; /* false = hex string true = bit string */
|
|
|
|
int bc;
|
|
|
|
bits8 x = 0;
|
|
|
|
|
|
|
|
/* Check that the first character is a b or an x */
|
|
|
|
if (input_string[0] == 'b' || input_string[0] == 'B')
|
|
|
|
{
|
|
|
|
bit_not_hex = true;
|
|
|
|
sp = input_string + 1;
|
|
|
|
}
|
|
|
|
else if (input_string[0] == 'x' || input_string[0] == 'X')
|
|
|
|
{
|
|
|
|
bit_not_hex = false;
|
|
|
|
sp = input_string + 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Otherwise it's binary. This allows things like cast('1001' as bit)
|
|
|
|
* to work transparently.
|
|
|
|
*/
|
|
|
|
bit_not_hex = true;
|
|
|
|
sp = input_string;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Determine bitlength from input string. MaxAllocSize ensures a regular
|
|
|
|
* input is small enough, but we must check hex input.
|
|
|
|
*/
|
|
|
|
slen = strlen(sp);
|
|
|
|
if (bit_not_hex)
|
|
|
|
bitlen = slen;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (slen > VARBITMAXLEN / 4)
|
|
|
|
ereturn(escontext, (Datum) 0,
|
|
|
|
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
8 years ago
|
|
|
errmsg("bit string length exceeds the maximum allowed (%d)",
|
|
|
|
VARBITMAXLEN)));
|
|
|
|
bitlen = slen * 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Sometimes atttypmod is not supplied. If it is supplied we need to make
|
|
|
|
* sure that the bitstring fits.
|
|
|
|
*/
|
|
|
|
if (atttypmod <= 0)
|
|
|
|
atttypmod = bitlen;
|
|
|
|
else if (bitlen != atttypmod)
|
|
|
|
ereturn(escontext, (Datum) 0,
|
|
|
|
(errcode(ERRCODE_STRING_DATA_LENGTH_MISMATCH),
|
|
|
|
errmsg("bit string length %d does not match type bit(%d)",
|
|
|
|
bitlen, atttypmod)));
|
|
|
|
|
|
|
|
len = VARBITTOTALLEN(atttypmod);
|
|
|
|
/* set to 0 so that *r is always initialised and string is zero-padded */
|
|
|
|
result = (VarBit *) palloc0(len);
|
|
|
|
SET_VARSIZE(result, len);
|
|
|
|
VARBITLEN(result) = atttypmod;
|
|
|
|
|
|
|
|
r = VARBITS(result);
|
|
|
|
if (bit_not_hex)
|
|
|
|
{
|
|
|
|
/* Parse the bit representation of the string */
|
|
|
|
/* We know it fits, as bitlen was compared to atttypmod */
|
|
|
|
x = HIGHBIT;
|
|
|
|
for (; *sp; sp++)
|
|
|
|
{
|
|
|
|
if (*sp == '1')
|
|
|
|
*r |= x;
|
|
|
|
else if (*sp != '0')
|
|
|
|
ereturn(escontext, (Datum) 0,
|
|
|
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
Avoid using %c printf format for potentially non-ASCII characters.
Since %c only passes a C "char" to printf, it's incapable of dealing
with multibyte characters. Passing just the first byte of such a
character leads to an output string that is visibly not correctly
encoded, resulting in undesirable behavior such as encoding conversion
failures while sending error messages to clients.
We've lived with this issue for a long time because it was inconvenient
to avoid in a portable fashion. However, now that we always use our own
snprintf code, it's reasonable to use the %.*s format to print just one
possibly-multibyte character in a string. (We previously avoided that
obvious-looking answer in order to work around glibc's bug #6530, cf
commits 54cd4f045 and ed437e2b2.)
Hence, run around and fix a bunch of places that used %c to report
a character found in a user-supplied string. For simplicity, I did
not touch places that were emitting non-user-facing debug messages,
or reporting catalog data that should always be ASCII. (It's also
unclear how useful this approach could be in frontend code, where
it's less certain that we know what encoding we're dealing with.)
In passing, improve a couple of poorly-written error messages in
pageinspect/heapfuncs.c.
This is a longstanding issue, but I'm hesitant to back-patch because
of the impact on translatable message strings. In any case this fix
would not work reliably before v12.
Tom Lane and Quan Zongliang
Discussion: https://postgr.es/m/a120087c-4c88-d9d4-1ec5-808d7a7f133d@gmail.com
5 years ago
|
|
|
errmsg("\"%.*s\" is not a valid binary digit",
|
|
|
|
pg_mblen(sp), sp)));
|
|
|
|
|
|
|
|
x >>= 1;
|
|
|
|
if (x == 0)
|
|
|
|
{
|
|
|
|
x = HIGHBIT;
|
|
|
|
r++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Parse the hex representation of the string */
|
|
|
|
for (bc = 0; *sp; sp++)
|
|
|
|
{
|
|
|
|
if (*sp >= '0' && *sp <= '9')
|
|
|
|
x = (bits8) (*sp - '0');
|
|
|
|
else if (*sp >= 'A' && *sp <= 'F')
|
|
|
|
x = (bits8) (*sp - 'A') + 10;
|
|
|
|
else if (*sp >= 'a' && *sp <= 'f')
|
|
|
|
x = (bits8) (*sp - 'a') + 10;
|
|
|
|
else
|
|
|
|
ereturn(escontext, (Datum) 0,
|
|
|
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
Avoid using %c printf format for potentially non-ASCII characters.
Since %c only passes a C "char" to printf, it's incapable of dealing
with multibyte characters. Passing just the first byte of such a
character leads to an output string that is visibly not correctly
encoded, resulting in undesirable behavior such as encoding conversion
failures while sending error messages to clients.
We've lived with this issue for a long time because it was inconvenient
to avoid in a portable fashion. However, now that we always use our own
snprintf code, it's reasonable to use the %.*s format to print just one
possibly-multibyte character in a string. (We previously avoided that
obvious-looking answer in order to work around glibc's bug #6530, cf
commits 54cd4f045 and ed437e2b2.)
Hence, run around and fix a bunch of places that used %c to report
a character found in a user-supplied string. For simplicity, I did
not touch places that were emitting non-user-facing debug messages,
or reporting catalog data that should always be ASCII. (It's also
unclear how useful this approach could be in frontend code, where
it's less certain that we know what encoding we're dealing with.)
In passing, improve a couple of poorly-written error messages in
pageinspect/heapfuncs.c.
This is a longstanding issue, but I'm hesitant to back-patch because
of the impact on translatable message strings. In any case this fix
would not work reliably before v12.
Tom Lane and Quan Zongliang
Discussion: https://postgr.es/m/a120087c-4c88-d9d4-1ec5-808d7a7f133d@gmail.com
5 years ago
|
|
|
errmsg("\"%.*s\" is not a valid hexadecimal digit",
|
|
|
|
pg_mblen(sp), sp)));
|
|
|
|
|
|
|
|
if (bc)
|
|
|
|
{
|
|
|
|
*r++ |= x;
|
|
|
|
bc = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*r = x << 4;
|
|
|
|
bc = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
PG_RETURN_VARBIT_P(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Datum
|
|
|
|
bit_out(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
#if 1
|
|
|
|
/* same as varbit output */
|
|
|
|
return varbit_out(fcinfo);
|
|
|
|
#else
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This is how one would print a hex string, in case someone wants to
|
|
|
|
* write a formatting function.
|
|
|
|
*/
|
|
|
|
VarBit *s = PG_GETARG_VARBIT_P(0);
|
|
|
|
char *result,
|
|
|
|
*r;
|
|
|
|
bits8 *sp;
|
|
|
|
int i,
|
|
|
|
len,
|
|
|
|
bitlen;
|
|
|
|
|
Fix failure to zero-pad the result of bitshiftright().
If the bitstring length is not a multiple of 8, we'd shift the
rightmost bits into the pad space, which must be zeroes --- bit_cmp,
for one, depends on that. This'd lead to the result failing to
compare equal to what it should compare equal to, as reported in
bug #16013 from Daryl Waycott.
This is, if memory serves, not the first such bug in the bitstring
functions. In hopes of making it the last one, do a bit more work
than minimally necessary to fix the bug:
* Add assertion checks to bit_out() and varbit_out() to complain if
they are given incorrectly-padded input. This will improve the
odds that manual testing of any new patch finds problems.
* Encapsulate the padding-related logic in macros to make it
easier to use.
Also, remove unnecessary padding logic from bit_or() and bitxor().
Somebody had already noted that we need not re-pad the result of
bit_and() since the inputs are required to be the same length,
but failed to extrapolate that to the other two.
Also, move a comment block that once was near the head of varbit.c
(but people kept putting other stuff in front of it), to put it in
the header block.
Note for the release notes: if anyone has inconsistent data as a
result of saving the output of bitshiftright() in a table, it's
possible to fix it with something like
UPDATE mytab SET bitcol = ~(~bitcol) WHERE bitcol != ~(~bitcol);
This has been broken since day one, so back-patch to all supported
branches.
Discussion: https://postgr.es/m/16013-c2765b6996aacae9@postgresql.org
6 years ago
|
|
|
/* Assertion to help catch any bit functions that don't pad correctly */
|
|
|
|
VARBIT_CORRECTLY_PADDED(s);
|
|
|
|
|
|
|
|
bitlen = VARBITLEN(s);
|
|
|
|
len = (bitlen + 3) / 4;
|
|
|
|
result = (char *) palloc(len + 2);
|
|
|
|
sp = VARBITS(s);
|
|
|
|
r = result;
|
|
|
|
*r++ = 'X';
|
|
|
|
/* we cheat by knowing that we store full bytes zero padded */
|
|
|
|
for (i = 0; i < len; i += 2, sp++)
|
|
|
|
{
|
|
|
|
*r++ = HEXDIG((*sp) >> 4);
|
|
|
|
*r++ = HEXDIG((*sp) & 0xF);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Go back one step if we printed a hex number that was not part of the
|
|
|
|
* bitstring anymore
|
|
|
|
*/
|
|
|
|
if (i > len)
|
|
|
|
r--;
|
|
|
|
*r = '\0';
|
|
|
|
|
|
|
|
PG_RETURN_CSTRING(result);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* bit_recv - converts external binary format to bit
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
bit_recv(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
|
|
|
|
|
|
|
|
#ifdef NOT_USED
|
|
|
|
Oid typelem = PG_GETARG_OID(1);
|
|
|
|
#endif
|
|
|
|
int32 atttypmod = PG_GETARG_INT32(2);
|
|
|
|
VarBit *result;
|
|
|
|
int len,
|
|
|
|
bitlen;
|
|
|
|
|
|
|
|
bitlen = pq_getmsgint(buf, sizeof(int32));
|
|
|
|
if (bitlen < 0 || bitlen > VARBITMAXLEN)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
|
|
|
|
errmsg("invalid length in external bit string")));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Sometimes atttypmod is not supplied. If it is supplied we need to make
|
|
|
|
* sure that the bitstring fits.
|
|
|
|
*/
|
|
|
|
if (atttypmod > 0 && bitlen != atttypmod)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_STRING_DATA_LENGTH_MISMATCH),
|
|
|
|
errmsg("bit string length %d does not match type bit(%d)",
|
|
|
|
bitlen, atttypmod)));
|
|
|
|
|
|
|
|
len = VARBITTOTALLEN(bitlen);
|
|
|
|
result = (VarBit *) palloc(len);
|
|
|
|
SET_VARSIZE(result, len);
|
|
|
|
VARBITLEN(result) = bitlen;
|
|
|
|
|
|
|
|
pq_copymsgbytes(buf, (char *) VARBITS(result), VARBITBYTES(result));
|
|
|
|
|
Fix failure to zero-pad the result of bitshiftright().
If the bitstring length is not a multiple of 8, we'd shift the
rightmost bits into the pad space, which must be zeroes --- bit_cmp,
for one, depends on that. This'd lead to the result failing to
compare equal to what it should compare equal to, as reported in
bug #16013 from Daryl Waycott.
This is, if memory serves, not the first such bug in the bitstring
functions. In hopes of making it the last one, do a bit more work
than minimally necessary to fix the bug:
* Add assertion checks to bit_out() and varbit_out() to complain if
they are given incorrectly-padded input. This will improve the
odds that manual testing of any new patch finds problems.
* Encapsulate the padding-related logic in macros to make it
easier to use.
Also, remove unnecessary padding logic from bit_or() and bitxor().
Somebody had already noted that we need not re-pad the result of
bit_and() since the inputs are required to be the same length,
but failed to extrapolate that to the other two.
Also, move a comment block that once was near the head of varbit.c
(but people kept putting other stuff in front of it), to put it in
the header block.
Note for the release notes: if anyone has inconsistent data as a
result of saving the output of bitshiftright() in a table, it's
possible to fix it with something like
UPDATE mytab SET bitcol = ~(~bitcol) WHERE bitcol != ~(~bitcol);
This has been broken since day one, so back-patch to all supported
branches.
Discussion: https://postgr.es/m/16013-c2765b6996aacae9@postgresql.org
6 years ago
|
|
|
/* Make sure last byte is correctly zero-padded */
|
|
|
|
VARBIT_PAD(result);
|
|
|
|
|
|
|
|
PG_RETURN_VARBIT_P(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* bit_send - converts bit to binary format
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
bit_send(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
/* Exactly the same as varbit_send, so share code */
|
|
|
|
return varbit_send(fcinfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* bit()
|
|
|
|
* Converts a bit() type to a specific internal length.
|
|
|
|
* len is the bitlength specified in the column definition.
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
23 years ago
|
|
|
*
|
|
|
|
* If doing implicit cast, raise error when source data is wrong length.
|
|
|
|
* If doing explicit cast, silently truncate or zero-pad to specified length.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
bit(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
VarBit *arg = PG_GETARG_VARBIT_P(0);
|
|
|
|
int32 len = PG_GETARG_INT32(1);
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
23 years ago
|
|
|
bool isExplicit = PG_GETARG_BOOL(2);
|
|
|
|
VarBit *result;
|
|
|
|
int rlen;
|
|
|
|
|
|
|
|
/* No work if typmod is invalid or supplied data matches it already */
|
|
|
|
if (len <= 0 || len > VARBITMAXLEN || len == VARBITLEN(arg))
|
|
|
|
PG_RETURN_VARBIT_P(arg);
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
23 years ago
|
|
|
|
|
|
|
if (!isExplicit)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_STRING_DATA_LENGTH_MISMATCH),
|
|
|
|
errmsg("bit string length %d does not match type bit(%d)",
|
|
|
|
VARBITLEN(arg), len)));
|
|
|
|
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
23 years ago
|
|
|
rlen = VARBITTOTALLEN(len);
|
|
|
|
/* set to 0 so that string is zero-padded */
|
|
|
|
result = (VarBit *) palloc0(rlen);
|
|
|
|
SET_VARSIZE(result, rlen);
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
23 years ago
|
|
|
VARBITLEN(result) = len;
|
|
|
|
|
|
|
|
memcpy(VARBITS(result), VARBITS(arg),
|
|
|
|
Min(VARBITBYTES(result), VARBITBYTES(arg)));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Make sure last byte is zero-padded if needed. This is useless but safe
|
|
|
|
* if source data was shorter than target length (we assume the last byte
|
|
|
|
* of the source data was itself correctly zero-padded).
|
|
|
|
*/
|
Fix failure to zero-pad the result of bitshiftright().
If the bitstring length is not a multiple of 8, we'd shift the
rightmost bits into the pad space, which must be zeroes --- bit_cmp,
for one, depends on that. This'd lead to the result failing to
compare equal to what it should compare equal to, as reported in
bug #16013 from Daryl Waycott.
This is, if memory serves, not the first such bug in the bitstring
functions. In hopes of making it the last one, do a bit more work
than minimally necessary to fix the bug:
* Add assertion checks to bit_out() and varbit_out() to complain if
they are given incorrectly-padded input. This will improve the
odds that manual testing of any new patch finds problems.
* Encapsulate the padding-related logic in macros to make it
easier to use.
Also, remove unnecessary padding logic from bit_or() and bitxor().
Somebody had already noted that we need not re-pad the result of
bit_and() since the inputs are required to be the same length,
but failed to extrapolate that to the other two.
Also, move a comment block that once was near the head of varbit.c
(but people kept putting other stuff in front of it), to put it in
the header block.
Note for the release notes: if anyone has inconsistent data as a
result of saving the output of bitshiftright() in a table, it's
possible to fix it with something like
UPDATE mytab SET bitcol = ~(~bitcol) WHERE bitcol != ~(~bitcol);
This has been broken since day one, so back-patch to all supported
branches.
Discussion: https://postgr.es/m/16013-c2765b6996aacae9@postgresql.org
6 years ago
|
|
|
VARBIT_PAD(result);
|
|
|
|
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
23 years ago
|
|
|
PG_RETURN_VARBIT_P(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
Datum
|
|
|
|
bittypmodin(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
ArrayType *ta = PG_GETARG_ARRAYTYPE_P(0);
|
|
|
|
|
|
|
|
PG_RETURN_INT32(anybit_typmodin(ta, "bit"));
|
|
|
|
}
|
|
|
|
|
|
|
|
Datum
|
|
|
|
bittypmodout(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
int32 typmod = PG_GETARG_INT32(0);
|
|
|
|
|
|
|
|
PG_RETURN_CSTRING(anybit_typmodout(typmod));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* varbit_in -
|
|
|
|
* converts a string to the internal representation of a bitstring.
|
|
|
|
* This is the same as bit_in except that atttypmod is taken as
|
|
|
|
* the maximum length, not the exact length to force the bitstring to.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
varbit_in(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
char *input_string = PG_GETARG_CSTRING(0);
|
|
|
|
#ifdef NOT_USED
|
|
|
|
Oid typelem = PG_GETARG_OID(1);
|
|
|
|
#endif
|
|
|
|
int32 atttypmod = PG_GETARG_INT32(2);
|
|
|
|
Node *escontext = fcinfo->context;
|
|
|
|
VarBit *result; /* The resulting bit string */
|
|
|
|
char *sp; /* pointer into the character string */
|
|
|
|
bits8 *r; /* pointer into the result */
|
|
|
|
int len, /* Length of the whole data structure */
|
|
|
|
bitlen, /* Number of bits in the bit string */
|
|
|
|
slen; /* Length of the input string */
|
|
|
|
bool bit_not_hex; /* false = hex string true = bit string */
|
|
|
|
int bc;
|
|
|
|
bits8 x = 0;
|
|
|
|
|
|
|
|
/* Check that the first character is a b or an x */
|
|
|
|
if (input_string[0] == 'b' || input_string[0] == 'B')
|
|
|
|
{
|
|
|
|
bit_not_hex = true;
|
|
|
|
sp = input_string + 1;
|
|
|
|
}
|
|
|
|
else if (input_string[0] == 'x' || input_string[0] == 'X')
|
|
|
|
{
|
|
|
|
bit_not_hex = false;
|
|
|
|
sp = input_string + 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
bit_not_hex = true;
|
|
|
|
sp = input_string;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Determine bitlength from input string. MaxAllocSize ensures a regular
|
|
|
|
* input is small enough, but we must check hex input.
|
|
|
|
*/
|
|
|
|
slen = strlen(sp);
|
|
|
|
if (bit_not_hex)
|
|
|
|
bitlen = slen;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (slen > VARBITMAXLEN / 4)
|
|
|
|
ereturn(escontext, (Datum) 0,
|
|
|
|
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
8 years ago
|
|
|
errmsg("bit string length exceeds the maximum allowed (%d)",
|
|
|
|
VARBITMAXLEN)));
|
|
|
|
bitlen = slen * 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Sometimes atttypmod is not supplied. If it is supplied we need to make
|
|
|
|
* sure that the bitstring fits.
|
|
|
|
*/
|
|
|
|
if (atttypmod <= 0)
|
|
|
|
atttypmod = bitlen;
|
|
|
|
else if (bitlen > atttypmod)
|
|
|
|
ereturn(escontext, (Datum) 0,
|
|
|
|
(errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
|
|
|
|
errmsg("bit string too long for type bit varying(%d)",
|
|
|
|
atttypmod)));
|
|
|
|
|
|
|
|
len = VARBITTOTALLEN(bitlen);
|
|
|
|
/* set to 0 so that *r is always initialised and string is zero-padded */
|
|
|
|
result = (VarBit *) palloc0(len);
|
|
|
|
SET_VARSIZE(result, len);
|
|
|
|
VARBITLEN(result) = Min(bitlen, atttypmod);
|
|
|
|
|
|
|
|
r = VARBITS(result);
|
|
|
|
if (bit_not_hex)
|
|
|
|
{
|
|
|
|
/* Parse the bit representation of the string */
|
|
|
|
/* We know it fits, as bitlen was compared to atttypmod */
|
|
|
|
x = HIGHBIT;
|
|
|
|
for (; *sp; sp++)
|
|
|
|
{
|
|
|
|
if (*sp == '1')
|
|
|
|
*r |= x;
|
|
|
|
else if (*sp != '0')
|
|
|
|
ereturn(escontext, (Datum) 0,
|
|
|
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
Avoid using %c printf format for potentially non-ASCII characters.
Since %c only passes a C "char" to printf, it's incapable of dealing
with multibyte characters. Passing just the first byte of such a
character leads to an output string that is visibly not correctly
encoded, resulting in undesirable behavior such as encoding conversion
failures while sending error messages to clients.
We've lived with this issue for a long time because it was inconvenient
to avoid in a portable fashion. However, now that we always use our own
snprintf code, it's reasonable to use the %.*s format to print just one
possibly-multibyte character in a string. (We previously avoided that
obvious-looking answer in order to work around glibc's bug #6530, cf
commits 54cd4f045 and ed437e2b2.)
Hence, run around and fix a bunch of places that used %c to report
a character found in a user-supplied string. For simplicity, I did
not touch places that were emitting non-user-facing debug messages,
or reporting catalog data that should always be ASCII. (It's also
unclear how useful this approach could be in frontend code, where
it's less certain that we know what encoding we're dealing with.)
In passing, improve a couple of poorly-written error messages in
pageinspect/heapfuncs.c.
This is a longstanding issue, but I'm hesitant to back-patch because
of the impact on translatable message strings. In any case this fix
would not work reliably before v12.
Tom Lane and Quan Zongliang
Discussion: https://postgr.es/m/a120087c-4c88-d9d4-1ec5-808d7a7f133d@gmail.com
5 years ago
|
|
|
errmsg("\"%.*s\" is not a valid binary digit",
|
|
|
|
pg_mblen(sp), sp)));
|
|
|
|
|
|
|
|
x >>= 1;
|
|
|
|
if (x == 0)
|
|
|
|
{
|
|
|
|
x = HIGHBIT;
|
|
|
|
r++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Parse the hex representation of the string */
|
|
|
|
for (bc = 0; *sp; sp++)
|
|
|
|
{
|
|
|
|
if (*sp >= '0' && *sp <= '9')
|
|
|
|
x = (bits8) (*sp - '0');
|
|
|
|
else if (*sp >= 'A' && *sp <= 'F')
|
|
|
|
x = (bits8) (*sp - 'A') + 10;
|
|
|
|
else if (*sp >= 'a' && *sp <= 'f')
|
|
|
|
x = (bits8) (*sp - 'a') + 10;
|
|
|
|
else
|
|
|
|
ereturn(escontext, (Datum) 0,
|
|
|
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
Avoid using %c printf format for potentially non-ASCII characters.
Since %c only passes a C "char" to printf, it's incapable of dealing
with multibyte characters. Passing just the first byte of such a
character leads to an output string that is visibly not correctly
encoded, resulting in undesirable behavior such as encoding conversion
failures while sending error messages to clients.
We've lived with this issue for a long time because it was inconvenient
to avoid in a portable fashion. However, now that we always use our own
snprintf code, it's reasonable to use the %.*s format to print just one
possibly-multibyte character in a string. (We previously avoided that
obvious-looking answer in order to work around glibc's bug #6530, cf
commits 54cd4f045 and ed437e2b2.)
Hence, run around and fix a bunch of places that used %c to report
a character found in a user-supplied string. For simplicity, I did
not touch places that were emitting non-user-facing debug messages,
or reporting catalog data that should always be ASCII. (It's also
unclear how useful this approach could be in frontend code, where
it's less certain that we know what encoding we're dealing with.)
In passing, improve a couple of poorly-written error messages in
pageinspect/heapfuncs.c.
This is a longstanding issue, but I'm hesitant to back-patch because
of the impact on translatable message strings. In any case this fix
would not work reliably before v12.
Tom Lane and Quan Zongliang
Discussion: https://postgr.es/m/a120087c-4c88-d9d4-1ec5-808d7a7f133d@gmail.com
5 years ago
|
|
|
errmsg("\"%.*s\" is not a valid hexadecimal digit",
|
|
|
|
pg_mblen(sp), sp)));
|
|
|
|
|
|
|
|
if (bc)
|
|
|
|
{
|
|
|
|
*r++ |= x;
|
|
|
|
bc = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*r = x << 4;
|
|
|
|
bc = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
PG_RETURN_VARBIT_P(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* varbit_out -
|
|
|
|
* Prints the string as bits to preserve length accurately
|
|
|
|
*
|
|
|
|
* XXX varbit_recv() and hex input to varbit_in() can load a value that this
|
|
|
|
* cannot emit. Consider using hex output for such values.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
varbit_out(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
VarBit *s = PG_GETARG_VARBIT_P(0);
|
|
|
|
char *result,
|
|
|
|
*r;
|
|
|
|
bits8 *sp;
|
|
|
|
bits8 x;
|
|
|
|
int i,
|
|
|
|
k,
|
|
|
|
len;
|
|
|
|
|
Fix failure to zero-pad the result of bitshiftright().
If the bitstring length is not a multiple of 8, we'd shift the
rightmost bits into the pad space, which must be zeroes --- bit_cmp,
for one, depends on that. This'd lead to the result failing to
compare equal to what it should compare equal to, as reported in
bug #16013 from Daryl Waycott.
This is, if memory serves, not the first such bug in the bitstring
functions. In hopes of making it the last one, do a bit more work
than minimally necessary to fix the bug:
* Add assertion checks to bit_out() and varbit_out() to complain if
they are given incorrectly-padded input. This will improve the
odds that manual testing of any new patch finds problems.
* Encapsulate the padding-related logic in macros to make it
easier to use.
Also, remove unnecessary padding logic from bit_or() and bitxor().
Somebody had already noted that we need not re-pad the result of
bit_and() since the inputs are required to be the same length,
but failed to extrapolate that to the other two.
Also, move a comment block that once was near the head of varbit.c
(but people kept putting other stuff in front of it), to put it in
the header block.
Note for the release notes: if anyone has inconsistent data as a
result of saving the output of bitshiftright() in a table, it's
possible to fix it with something like
UPDATE mytab SET bitcol = ~(~bitcol) WHERE bitcol != ~(~bitcol);
This has been broken since day one, so back-patch to all supported
branches.
Discussion: https://postgr.es/m/16013-c2765b6996aacae9@postgresql.org
6 years ago
|
|
|
/* Assertion to help catch any bit functions that don't pad correctly */
|
|
|
|
VARBIT_CORRECTLY_PADDED(s);
|
|
|
|
|
|
|
|
len = VARBITLEN(s);
|
|
|
|
result = (char *) palloc(len + 1);
|
|
|
|
sp = VARBITS(s);
|
|
|
|
r = result;
|
|
|
|
for (i = 0; i <= len - BITS_PER_BYTE; i += BITS_PER_BYTE, sp++)
|
|
|
|
{
|
|
|
|
/* print full bytes */
|
|
|
|
x = *sp;
|
|
|
|
for (k = 0; k < BITS_PER_BYTE; k++)
|
|
|
|
{
|
|
|
|
*r++ = IS_HIGHBIT_SET(x) ? '1' : '0';
|
|
|
|
x <<= 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (i < len)
|
|
|
|
{
|
|
|
|
/* print the last partial byte */
|
|
|
|
x = *sp;
|
|
|
|
for (k = i; k < len; k++)
|
|
|
|
{
|
|
|
|
*r++ = IS_HIGHBIT_SET(x) ? '1' : '0';
|
|
|
|
x <<= 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*r = '\0';
|
|
|
|
|
|
|
|
PG_RETURN_CSTRING(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* varbit_recv - converts external binary format to varbit
|
|
|
|
*
|
|
|
|
* External format is the bitlen as an int32, then the byte array.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
varbit_recv(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
|
|
|
|
|
|
|
|
#ifdef NOT_USED
|
|
|
|
Oid typelem = PG_GETARG_OID(1);
|
|
|
|
#endif
|
|
|
|
int32 atttypmod = PG_GETARG_INT32(2);
|
|
|
|
VarBit *result;
|
|
|
|
int len,
|
|
|
|
bitlen;
|
|
|
|
|
|
|
|
bitlen = pq_getmsgint(buf, sizeof(int32));
|
|
|
|
if (bitlen < 0 || bitlen > VARBITMAXLEN)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
|
|
|
|
errmsg("invalid length in external bit string")));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Sometimes atttypmod is not supplied. If it is supplied we need to make
|
|
|
|
* sure that the bitstring fits.
|
|
|
|
*/
|
|
|
|
if (atttypmod > 0 && bitlen > atttypmod)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
|
|
|
|
errmsg("bit string too long for type bit varying(%d)",
|
|
|
|
atttypmod)));
|
|
|
|
|
|
|
|
len = VARBITTOTALLEN(bitlen);
|
|
|
|
result = (VarBit *) palloc(len);
|
|
|
|
SET_VARSIZE(result, len);
|
|
|
|
VARBITLEN(result) = bitlen;
|
|
|
|
|
|
|
|
pq_copymsgbytes(buf, (char *) VARBITS(result), VARBITBYTES(result));
|
|
|
|
|
Fix failure to zero-pad the result of bitshiftright().
If the bitstring length is not a multiple of 8, we'd shift the
rightmost bits into the pad space, which must be zeroes --- bit_cmp,
for one, depends on that. This'd lead to the result failing to
compare equal to what it should compare equal to, as reported in
bug #16013 from Daryl Waycott.
This is, if memory serves, not the first such bug in the bitstring
functions. In hopes of making it the last one, do a bit more work
than minimally necessary to fix the bug:
* Add assertion checks to bit_out() and varbit_out() to complain if
they are given incorrectly-padded input. This will improve the
odds that manual testing of any new patch finds problems.
* Encapsulate the padding-related logic in macros to make it
easier to use.
Also, remove unnecessary padding logic from bit_or() and bitxor().
Somebody had already noted that we need not re-pad the result of
bit_and() since the inputs are required to be the same length,
but failed to extrapolate that to the other two.
Also, move a comment block that once was near the head of varbit.c
(but people kept putting other stuff in front of it), to put it in
the header block.
Note for the release notes: if anyone has inconsistent data as a
result of saving the output of bitshiftright() in a table, it's
possible to fix it with something like
UPDATE mytab SET bitcol = ~(~bitcol) WHERE bitcol != ~(~bitcol);
This has been broken since day one, so back-patch to all supported
branches.
Discussion: https://postgr.es/m/16013-c2765b6996aacae9@postgresql.org
6 years ago
|
|
|
/* Make sure last byte is correctly zero-padded */
|
|
|
|
VARBIT_PAD(result);
|
|
|
|
|
|
|
|
PG_RETURN_VARBIT_P(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* varbit_send - converts varbit to binary format
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
varbit_send(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
VarBit *s = PG_GETARG_VARBIT_P(0);
|
|
|
|
StringInfoData buf;
|
|
|
|
|
|
|
|
pq_begintypsend(&buf);
|
|
|
|
pq_sendint32(&buf, VARBITLEN(s));
|
|
|
|
pq_sendbytes(&buf, VARBITS(s), VARBITBYTES(s));
|
|
|
|
PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* varbit_support()
|
|
|
|
*
|
|
|
|
* Planner support function for the varbit() length coercion function.
|
|
|
|
*
|
|
|
|
* Currently, the only interesting thing we can do is flatten calls that set
|
|
|
|
* the new maximum length >= the previous maximum length. We can ignore the
|
|
|
|
* isExplicit argument, since that only affects truncation cases.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
varbit_support(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
Node *rawreq = (Node *) PG_GETARG_POINTER(0);
|
|
|
|
Node *ret = NULL;
|
|
|
|
|
|
|
|
if (IsA(rawreq, SupportRequestSimplify))
|
|
|
|
{
|
|
|
|
SupportRequestSimplify *req = (SupportRequestSimplify *) rawreq;
|
|
|
|
FuncExpr *expr = req->fcall;
|
|
|
|
Node *typmod;
|
|
|
|
|
|
|
|
Assert(list_length(expr->args) >= 2);
|
|
|
|
|
|
|
|
typmod = (Node *) lsecond(expr->args);
|
|
|
|
|
|
|
|
if (IsA(typmod, Const) && !((Const *) typmod)->constisnull)
|
|
|
|
{
|
|
|
|
Node *source = (Node *) linitial(expr->args);
|
|
|
|
int32 new_typmod = DatumGetInt32(((Const *) typmod)->constvalue);
|
|
|
|
int32 old_max = exprTypmod(source);
|
|
|
|
int32 new_max = new_typmod;
|
|
|
|
|
|
|
|
/* Note: varbit() treats typmod 0 as invalid, so we do too */
|
|
|
|
if (new_max <= 0 || (old_max > 0 && old_max <= new_max))
|
|
|
|
ret = relabel_to_typmod(source, new_typmod);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
PG_RETURN_POINTER(ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* varbit()
|
|
|
|
* Converts a varbit() type to a specific internal length.
|
|
|
|
* len is the maximum bitlength specified in the column definition.
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
23 years ago
|
|
|
*
|
|
|
|
* If doing implicit cast, raise error when source data is too long.
|
|
|
|
* If doing explicit cast, silently truncate to max length.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
varbit(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
VarBit *arg = PG_GETARG_VARBIT_P(0);
|
|
|
|
int32 len = PG_GETARG_INT32(1);
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
23 years ago
|
|
|
bool isExplicit = PG_GETARG_BOOL(2);
|
|
|
|
VarBit *result;
|
|
|
|
int rlen;
|
|
|
|
|
|
|
|
/* No work if typmod is invalid or supplied data matches it already */
|
|
|
|
if (len <= 0 || len >= VARBITLEN(arg))
|
|
|
|
PG_RETURN_VARBIT_P(arg);
|
|
|
|
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
23 years ago
|
|
|
if (!isExplicit)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
|
|
|
|
errmsg("bit string too long for type bit varying(%d)",
|
|
|
|
len)));
|
|
|
|
|
|
|
|
rlen = VARBITTOTALLEN(len);
|
|
|
|
result = (VarBit *) palloc(rlen);
|
|
|
|
SET_VARSIZE(result, rlen);
|
|
|
|
VARBITLEN(result) = len;
|
|
|
|
|
|
|
|
memcpy(VARBITS(result), VARBITS(arg), VARBITBYTES(result));
|
|
|
|
|
Fix failure to zero-pad the result of bitshiftright().
If the bitstring length is not a multiple of 8, we'd shift the
rightmost bits into the pad space, which must be zeroes --- bit_cmp,
for one, depends on that. This'd lead to the result failing to
compare equal to what it should compare equal to, as reported in
bug #16013 from Daryl Waycott.
This is, if memory serves, not the first such bug in the bitstring
functions. In hopes of making it the last one, do a bit more work
than minimally necessary to fix the bug:
* Add assertion checks to bit_out() and varbit_out() to complain if
they are given incorrectly-padded input. This will improve the
odds that manual testing of any new patch finds problems.
* Encapsulate the padding-related logic in macros to make it
easier to use.
Also, remove unnecessary padding logic from bit_or() and bitxor().
Somebody had already noted that we need not re-pad the result of
bit_and() since the inputs are required to be the same length,
but failed to extrapolate that to the other two.
Also, move a comment block that once was near the head of varbit.c
(but people kept putting other stuff in front of it), to put it in
the header block.
Note for the release notes: if anyone has inconsistent data as a
result of saving the output of bitshiftright() in a table, it's
possible to fix it with something like
UPDATE mytab SET bitcol = ~(~bitcol) WHERE bitcol != ~(~bitcol);
This has been broken since day one, so back-patch to all supported
branches.
Discussion: https://postgr.es/m/16013-c2765b6996aacae9@postgresql.org
6 years ago
|
|
|
/* Make sure last byte is correctly zero-padded */
|
|
|
|
VARBIT_PAD(result);
|
|
|
|
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
23 years ago
|
|
|
PG_RETURN_VARBIT_P(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
Datum
|
|
|
|
varbittypmodin(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
ArrayType *ta = PG_GETARG_ARRAYTYPE_P(0);
|
|
|
|
|
|
|
|
PG_RETURN_INT32(anybit_typmodin(ta, "varbit"));
|
|
|
|
}
|
|
|
|
|
|
|
|
Datum
|
|
|
|
varbittypmodout(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
int32 typmod = PG_GETARG_INT32(0);
|
|
|
|
|
|
|
|
PG_RETURN_CSTRING(anybit_typmodout(typmod));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Comparison operators
|
|
|
|
*
|
|
|
|
* We only need one set of comparison operators for bitstrings, as the lengths
|
|
|
|
* are stored in the same way for zero-padded and varying bit strings.
|
|
|
|
*
|
|
|
|
* Note that the standard is not unambiguous about the comparison between
|
|
|
|
* zero-padded bit strings and varying bitstrings. If the same value is written
|
|
|
|
* into a zero padded bitstring as into a varying bitstring, but the zero
|
|
|
|
* padded bitstring has greater length, it will be bigger.
|
|
|
|
*
|
|
|
|
* Zeros from the beginning of a bitstring cannot simply be ignored, as they
|
|
|
|
* may be part of a bit string and may be significant.
|
|
|
|
*
|
|
|
|
* Note: btree indexes need these routines not to leak memory; therefore,
|
|
|
|
* be careful to free working copies of toasted datums. Most places don't
|
|
|
|
* need to be so careful.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* bit_cmp
|
|
|
|
*
|
|
|
|
* Compares two bitstrings and returns <0, 0, >0 depending on whether the first
|
|
|
|
* string is smaller, equal, or bigger than the second. All bits are considered
|
|
|
|
* and additional zero bits may make one string smaller/larger than the other,
|
|
|
|
* even if their zero-padded values would be the same.
|
|
|
|
*/
|
|
|
|
static int32
|
|
|
|
bit_cmp(VarBit *arg1, VarBit *arg2)
|
|
|
|
{
|
|
|
|
int bitlen1,
|
|
|
|
bytelen1,
|
|
|
|
bitlen2,
|
|
|
|
bytelen2;
|
|
|
|
int32 cmp;
|
|
|
|
|
|
|
|
bytelen1 = VARBITBYTES(arg1);
|
|
|
|
bytelen2 = VARBITBYTES(arg2);
|
|
|
|
|
|
|
|
cmp = memcmp(VARBITS(arg1), VARBITS(arg2), Min(bytelen1, bytelen2));
|
|
|
|
if (cmp == 0)
|
|
|
|
{
|
|
|
|
bitlen1 = VARBITLEN(arg1);
|
|
|
|
bitlen2 = VARBITLEN(arg2);
|
|
|
|
if (bitlen1 != bitlen2)
|
|
|
|
cmp = (bitlen1 < bitlen2) ? -1 : 1;
|
|
|
|
}
|
|
|
|
return cmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
Datum
|
|
|
|
biteq(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
VarBit *arg1 = PG_GETARG_VARBIT_P(0);
|
|
|
|
VarBit *arg2 = PG_GETARG_VARBIT_P(1);
|
|
|
|
bool result;
|
|
|
|
int bitlen1,
|
|
|
|
bitlen2;
|
|
|
|
|
|
|
|
bitlen1 = VARBITLEN(arg1);
|
|
|
|
bitlen2 = VARBITLEN(arg2);
|
|
|
|
|
|
|
|
/* fast path for different-length inputs */
|
|
|
|
if (bitlen1 != bitlen2)
|
|
|
|
result = false;
|
|
|
|
else
|
|
|
|
result = (bit_cmp(arg1, arg2) == 0);
|
|
|
|
|
|
|
|
PG_FREE_IF_COPY(arg1, 0);
|
|
|
|
PG_FREE_IF_COPY(arg2, 1);
|
|
|
|
|
|
|
|
PG_RETURN_BOOL(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
Datum
|
|
|
|
bitne(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
VarBit *arg1 = PG_GETARG_VARBIT_P(0);
|
|
|
|
VarBit *arg2 = PG_GETARG_VARBIT_P(1);
|
|
|
|
bool result;
|
|
|
|
int bitlen1,
|
|
|
|
bitlen2;
|
|
|
|
|
|
|
|
bitlen1 = VARBITLEN(arg1);
|
|
|
|
bitlen2 = VARBITLEN(arg2);
|
|
|
|
|
|
|
|
/* fast path for different-length inputs */
|
|
|
|
if (bitlen1 != bitlen2)
|
|
|
|
result = true;
|
|
|
|
else
|
|
|
|
result = (bit_cmp(arg1, arg2) != 0);
|
|
|
|
|
|
|
|
PG_FREE_IF_COPY(arg1, 0);
|
|
|
|
PG_FREE_IF_COPY(arg2, 1);
|
|
|
|
|
|
|
|
PG_RETURN_BOOL(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
Datum
|
|
|
|
bitlt(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
VarBit *arg1 = PG_GETARG_VARBIT_P(0);
|
|
|
|
VarBit *arg2 = PG_GETARG_VARBIT_P(1);
|
|
|
|
bool result;
|
|
|
|
|
|
|
|
result = (bit_cmp(arg1, arg2) < 0);
|
|
|
|
|
|
|
|
PG_FREE_IF_COPY(arg1, 0);
|
|
|
|
PG_FREE_IF_COPY(arg2, 1);
|
|
|
|
|
|
|
|
PG_RETURN_BOOL(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
Datum
|
|
|
|
bitle(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
VarBit *arg1 = PG_GETARG_VARBIT_P(0);
|
|
|
|
VarBit *arg2 = PG_GETARG_VARBIT_P(1);
|
|
|
|
bool result;
|
|
|
|
|
|
|
|
result = (bit_cmp(arg1, arg2) <= 0);
|
|
|
|
|
|
|
|
PG_FREE_IF_COPY(arg1, 0);
|
|
|
|
PG_FREE_IF_COPY(arg2, 1);
|
|
|
|
|
|
|
|
PG_RETURN_BOOL(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
Datum
|
|
|
|
bitgt(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
VarBit *arg1 = PG_GETARG_VARBIT_P(0);
|
|
|
|
VarBit *arg2 = PG_GETARG_VARBIT_P(1);
|
|
|
|
bool result;
|
|
|
|
|
|
|
|
result = (bit_cmp(arg1, arg2) > 0);
|
|
|
|
|
|
|
|
PG_FREE_IF_COPY(arg1, 0);
|
|
|
|
PG_FREE_IF_COPY(arg2, 1);
|
|
|
|
|
|
|
|
PG_RETURN_BOOL(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
Datum
|
|
|
|
bitge(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
VarBit *arg1 = PG_GETARG_VARBIT_P(0);
|
|
|
|
VarBit *arg2 = PG_GETARG_VARBIT_P(1);
|
|
|
|
bool result;
|
|
|
|
|
|
|
|
result = (bit_cmp(arg1, arg2) >= 0);
|
|
|
|
|
|
|
|
PG_FREE_IF_COPY(arg1, 0);
|
|
|
|
PG_FREE_IF_COPY(arg2, 1);
|
|
|
|
|
|
|
|
PG_RETURN_BOOL(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
Datum
|
|
|
|
bitcmp(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
VarBit *arg1 = PG_GETARG_VARBIT_P(0);
|
|
|
|
VarBit *arg2 = PG_GETARG_VARBIT_P(1);
|
|
|
|
int32 result;
|
|
|
|
|
|
|
|
result = bit_cmp(arg1, arg2);
|
|
|
|
|
|
|
|
PG_FREE_IF_COPY(arg1, 0);
|
|
|
|
PG_FREE_IF_COPY(arg2, 1);
|
|
|
|
|
|
|
|
PG_RETURN_INT32(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* bitcat
|
|
|
|
* Concatenation of bit strings
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
bitcat(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
VarBit *arg1 = PG_GETARG_VARBIT_P(0);
|
|
|
|
VarBit *arg2 = PG_GETARG_VARBIT_P(1);
|
|
|
|
|
|
|
|
PG_RETURN_VARBIT_P(bit_catenate(arg1, arg2));
|
|
|
|
}
|
|
|
|
|
|
|
|
static VarBit *
|
|
|
|
bit_catenate(VarBit *arg1, VarBit *arg2)
|
|
|
|
{
|
|
|
|
VarBit *result;
|
|
|
|
int bitlen1,
|
|
|
|
bitlen2,
|
|
|
|
bytelen,
|
|
|
|
bit1pad,
|
|
|
|
bit2shift;
|
|
|
|
bits8 *pr,
|
|
|
|
*pa;
|
|
|
|
|
|
|
|
bitlen1 = VARBITLEN(arg1);
|
|
|
|
bitlen2 = VARBITLEN(arg2);
|
|
|
|
|
|
|
|
if (bitlen1 > VARBITMAXLEN - bitlen2)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
|
|
|
|
errmsg("bit string length exceeds the maximum allowed (%d)",
|
|
|
|
VARBITMAXLEN)));
|
|
|
|
bytelen = VARBITTOTALLEN(bitlen1 + bitlen2);
|
|
|
|
|
|
|
|
result = (VarBit *) palloc(bytelen);
|
|
|
|
SET_VARSIZE(result, bytelen);
|
|
|
|
VARBITLEN(result) = bitlen1 + bitlen2;
|
|
|
|
|
|
|
|
/* Copy the first bitstring in */
|
|
|
|
memcpy(VARBITS(result), VARBITS(arg1), VARBITBYTES(arg1));
|
|
|
|
|
|
|
|
/* Copy the second bit string */
|
|
|
|
bit1pad = VARBITPAD(arg1);
|
|
|
|
if (bit1pad == 0)
|
|
|
|
{
|
|
|
|
memcpy(VARBITS(result) + VARBITBYTES(arg1), VARBITS(arg2),
|
|
|
|
VARBITBYTES(arg2));
|
|
|
|
}
|
|
|
|
else if (bitlen2 > 0)
|
|
|
|
{
|
|
|
|
/* We need to shift all the bits to fit */
|
|
|
|
bit2shift = BITS_PER_BYTE - bit1pad;
|
|
|
|
pr = VARBITS(result) + VARBITBYTES(arg1) - 1;
|
|
|
|
for (pa = VARBITS(arg2); pa < VARBITEND(arg2); pa++)
|
|
|
|
{
|
|
|
|
*pr |= ((*pa >> bit2shift) & BITMASK);
|
|
|
|
pr++;
|
|
|
|
if (pr < VARBITEND(result))
|
|
|
|
*pr = (*pa << bit1pad) & BITMASK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Fix failure to zero-pad the result of bitshiftright().
If the bitstring length is not a multiple of 8, we'd shift the
rightmost bits into the pad space, which must be zeroes --- bit_cmp,
for one, depends on that. This'd lead to the result failing to
compare equal to what it should compare equal to, as reported in
bug #16013 from Daryl Waycott.
This is, if memory serves, not the first such bug in the bitstring
functions. In hopes of making it the last one, do a bit more work
than minimally necessary to fix the bug:
* Add assertion checks to bit_out() and varbit_out() to complain if
they are given incorrectly-padded input. This will improve the
odds that manual testing of any new patch finds problems.
* Encapsulate the padding-related logic in macros to make it
easier to use.
Also, remove unnecessary padding logic from bit_or() and bitxor().
Somebody had already noted that we need not re-pad the result of
bit_and() since the inputs are required to be the same length,
but failed to extrapolate that to the other two.
Also, move a comment block that once was near the head of varbit.c
(but people kept putting other stuff in front of it), to put it in
the header block.
Note for the release notes: if anyone has inconsistent data as a
result of saving the output of bitshiftright() in a table, it's
possible to fix it with something like
UPDATE mytab SET bitcol = ~(~bitcol) WHERE bitcol != ~(~bitcol);
This has been broken since day one, so back-patch to all supported
branches.
Discussion: https://postgr.es/m/16013-c2765b6996aacae9@postgresql.org
6 years ago
|
|
|
/* The pad bits should be already zero at this point */
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* bitsubstr
|
|
|
|
* retrieve a substring from the bit string.
|
|
|
|
* Note, s is 1-based.
|
|
|
|
* SQL draft 6.10 9)
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
bitsubstr(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
PG_RETURN_VARBIT_P(bitsubstring(PG_GETARG_VARBIT_P(0),
|
|
|
|
PG_GETARG_INT32(1),
|
|
|
|
PG_GETARG_INT32(2),
|
|
|
|
false));
|
|
|
|
}
|
|
|
|
|
|
|
|
Datum
|
|
|
|
bitsubstr_no_len(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
PG_RETURN_VARBIT_P(bitsubstring(PG_GETARG_VARBIT_P(0),
|
|
|
|
PG_GETARG_INT32(1),
|
|
|
|
-1, true));
|
|
|
|
}
|
|
|
|
|
|
|
|
static VarBit *
|
|
|
|
bitsubstring(VarBit *arg, int32 s, int32 l, bool length_not_specified)
|
|
|
|
{
|
|
|
|
VarBit *result;
|
|
|
|
int bitlen,
|
|
|
|
rbitlen,
|
|
|
|
len,
|
|
|
|
ishift,
|
|
|
|
i;
|
Fix integer-overflow corner cases in substring() functions.
If the substring start index and length overflow when added together,
substring() misbehaved, either throwing a bogus "negative substring
length" error on a case that should succeed, or failing to complain that
a negative length is negative (and instead returning the whole string,
in most cases). Unsurprisingly, the text, bytea, and bit variants of
the function all had this issue. Rearrange the logic to ensure that
negative lengths are always rejected, and add an overflow check to
handle the other case.
Also install similar guards into detoast_attr_slice() (nee
heap_tuple_untoast_attr_slice()), since it's far from clear that
no other code paths leading to that function could pass it values
that would overflow.
Patch by myself and Pavel Stehule, per bug #16804 from Rafi Shamim.
Back-patch to v11. While these bugs are old, the common/int.h
infrastructure for overflow-detecting arithmetic didn't exist before
commit 4d6ad3125, and it doesn't seem like these misbehaviors are bad
enough to justify developing a standalone fix for the older branches.
Discussion: https://postgr.es/m/16804-f4eeeb6c11ba71d4@postgresql.org
5 years ago
|
|
|
int32 e,
|
|
|
|
s1,
|
|
|
|
e1;
|
Fix failure to zero-pad the result of bitshiftright().
If the bitstring length is not a multiple of 8, we'd shift the
rightmost bits into the pad space, which must be zeroes --- bit_cmp,
for one, depends on that. This'd lead to the result failing to
compare equal to what it should compare equal to, as reported in
bug #16013 from Daryl Waycott.
This is, if memory serves, not the first such bug in the bitstring
functions. In hopes of making it the last one, do a bit more work
than minimally necessary to fix the bug:
* Add assertion checks to bit_out() and varbit_out() to complain if
they are given incorrectly-padded input. This will improve the
odds that manual testing of any new patch finds problems.
* Encapsulate the padding-related logic in macros to make it
easier to use.
Also, remove unnecessary padding logic from bit_or() and bitxor().
Somebody had already noted that we need not re-pad the result of
bit_and() since the inputs are required to be the same length,
but failed to extrapolate that to the other two.
Also, move a comment block that once was near the head of varbit.c
(but people kept putting other stuff in front of it), to put it in
the header block.
Note for the release notes: if anyone has inconsistent data as a
result of saving the output of bitshiftright() in a table, it's
possible to fix it with something like
UPDATE mytab SET bitcol = ~(~bitcol) WHERE bitcol != ~(~bitcol);
This has been broken since day one, so back-patch to all supported
branches.
Discussion: https://postgr.es/m/16013-c2765b6996aacae9@postgresql.org
6 years ago
|
|
|
bits8 *r,
|
|
|
|
*ps;
|
|
|
|
|
|
|
|
bitlen = VARBITLEN(arg);
|
|
|
|
s1 = Max(s, 1);
|
|
|
|
/* If we do not have an upper bound, use end of string */
|
|
|
|
if (length_not_specified)
|
|
|
|
{
|
|
|
|
e1 = bitlen + 1;
|
|
|
|
}
|
Fix integer-overflow corner cases in substring() functions.
If the substring start index and length overflow when added together,
substring() misbehaved, either throwing a bogus "negative substring
length" error on a case that should succeed, or failing to complain that
a negative length is negative (and instead returning the whole string,
in most cases). Unsurprisingly, the text, bytea, and bit variants of
the function all had this issue. Rearrange the logic to ensure that
negative lengths are always rejected, and add an overflow check to
handle the other case.
Also install similar guards into detoast_attr_slice() (nee
heap_tuple_untoast_attr_slice()), since it's far from clear that
no other code paths leading to that function could pass it values
that would overflow.
Patch by myself and Pavel Stehule, per bug #16804 from Rafi Shamim.
Back-patch to v11. While these bugs are old, the common/int.h
infrastructure for overflow-detecting arithmetic didn't exist before
commit 4d6ad3125, and it doesn't seem like these misbehaviors are bad
enough to justify developing a standalone fix for the older branches.
Discussion: https://postgr.es/m/16804-f4eeeb6c11ba71d4@postgresql.org
5 years ago
|
|
|
else if (l < 0)
|
|
|
|
{
|
|
|
|
/* SQL99 says to throw an error for E < S, i.e., negative length */
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_SUBSTRING_ERROR),
|
|
|
|
errmsg("negative substring length not allowed")));
|
|
|
|
e1 = -1; /* silence stupider compilers */
|
|
|
|
}
|
|
|
|
else if (pg_add_s32_overflow(s, l, &e))
|
|
|
|
{
|
|
|
|
/*
|
Fix integer-overflow corner cases in substring() functions.
If the substring start index and length overflow when added together,
substring() misbehaved, either throwing a bogus "negative substring
length" error on a case that should succeed, or failing to complain that
a negative length is negative (and instead returning the whole string,
in most cases). Unsurprisingly, the text, bytea, and bit variants of
the function all had this issue. Rearrange the logic to ensure that
negative lengths are always rejected, and add an overflow check to
handle the other case.
Also install similar guards into detoast_attr_slice() (nee
heap_tuple_untoast_attr_slice()), since it's far from clear that
no other code paths leading to that function could pass it values
that would overflow.
Patch by myself and Pavel Stehule, per bug #16804 from Rafi Shamim.
Back-patch to v11. While these bugs are old, the common/int.h
infrastructure for overflow-detecting arithmetic didn't exist before
commit 4d6ad3125, and it doesn't seem like these misbehaviors are bad
enough to justify developing a standalone fix for the older branches.
Discussion: https://postgr.es/m/16804-f4eeeb6c11ba71d4@postgresql.org
5 years ago
|
|
|
* L could be large enough for S + L to overflow, in which case the
|
|
|
|
* substring must run to end of string.
|
|
|
|
*/
|
Fix integer-overflow corner cases in substring() functions.
If the substring start index and length overflow when added together,
substring() misbehaved, either throwing a bogus "negative substring
length" error on a case that should succeed, or failing to complain that
a negative length is negative (and instead returning the whole string,
in most cases). Unsurprisingly, the text, bytea, and bit variants of
the function all had this issue. Rearrange the logic to ensure that
negative lengths are always rejected, and add an overflow check to
handle the other case.
Also install similar guards into detoast_attr_slice() (nee
heap_tuple_untoast_attr_slice()), since it's far from clear that
no other code paths leading to that function could pass it values
that would overflow.
Patch by myself and Pavel Stehule, per bug #16804 from Rafi Shamim.
Back-patch to v11. While these bugs are old, the common/int.h
infrastructure for overflow-detecting arithmetic didn't exist before
commit 4d6ad3125, and it doesn't seem like these misbehaviors are bad
enough to justify developing a standalone fix for the older branches.
Discussion: https://postgr.es/m/16804-f4eeeb6c11ba71d4@postgresql.org
5 years ago
|
|
|
e1 = bitlen + 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
e1 = Min(e, bitlen + 1);
|
|
|
|
}
|
|
|
|
if (s1 > bitlen || e1 <= s1)
|
|
|
|
{
|
|
|
|
/* Need to return a zero-length bitstring */
|
|
|
|
len = VARBITTOTALLEN(0);
|
|
|
|
result = (VarBit *) palloc(len);
|
|
|
|
SET_VARSIZE(result, len);
|
|
|
|
VARBITLEN(result) = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* OK, we've got a true substring starting at position s1-1 and ending
|
|
|
|
* at position e1-1
|
|
|
|
*/
|
|
|
|
rbitlen = e1 - s1;
|
|
|
|
len = VARBITTOTALLEN(rbitlen);
|
|
|
|
result = (VarBit *) palloc(len);
|
|
|
|
SET_VARSIZE(result, len);
|
|
|
|
VARBITLEN(result) = rbitlen;
|
|
|
|
len -= VARHDRSZ + VARBITHDRSZ;
|
|
|
|
/* Are we copying from a byte boundary? */
|
|
|
|
if ((s1 - 1) % BITS_PER_BYTE == 0)
|
|
|
|
{
|
|
|
|
/* Yep, we are copying bytes */
|
|
|
|
memcpy(VARBITS(result), VARBITS(arg) + (s1 - 1) / BITS_PER_BYTE,
|
|
|
|
len);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Figure out how much we need to shift the sequence by */
|
|
|
|
ishift = (s1 - 1) % BITS_PER_BYTE;
|
|
|
|
r = VARBITS(result);
|
|
|
|
ps = VARBITS(arg) + (s1 - 1) / BITS_PER_BYTE;
|
|
|
|
for (i = 0; i < len; i++)
|
|
|
|
{
|
|
|
|
*r = (*ps << ishift) & BITMASK;
|
|
|
|
if ((++ps) < VARBITEND(arg))
|
|
|
|
*r |= *ps >> (BITS_PER_BYTE - ishift);
|
|
|
|
r++;
|
|
|
|
}
|
|
|
|
}
|
Fix failure to zero-pad the result of bitshiftright().
If the bitstring length is not a multiple of 8, we'd shift the
rightmost bits into the pad space, which must be zeroes --- bit_cmp,
for one, depends on that. This'd lead to the result failing to
compare equal to what it should compare equal to, as reported in
bug #16013 from Daryl Waycott.
This is, if memory serves, not the first such bug in the bitstring
functions. In hopes of making it the last one, do a bit more work
than minimally necessary to fix the bug:
* Add assertion checks to bit_out() and varbit_out() to complain if
they are given incorrectly-padded input. This will improve the
odds that manual testing of any new patch finds problems.
* Encapsulate the padding-related logic in macros to make it
easier to use.
Also, remove unnecessary padding logic from bit_or() and bitxor().
Somebody had already noted that we need not re-pad the result of
bit_and() since the inputs are required to be the same length,
but failed to extrapolate that to the other two.
Also, move a comment block that once was near the head of varbit.c
(but people kept putting other stuff in front of it), to put it in
the header block.
Note for the release notes: if anyone has inconsistent data as a
result of saving the output of bitshiftright() in a table, it's
possible to fix it with something like
UPDATE mytab SET bitcol = ~(~bitcol) WHERE bitcol != ~(~bitcol);
This has been broken since day one, so back-patch to all supported
branches.
Discussion: https://postgr.es/m/16013-c2765b6996aacae9@postgresql.org
6 years ago
|
|
|
|
|
|
|
/* Make sure last byte is correctly zero-padded */
|
|
|
|
VARBIT_PAD(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* bitoverlay
|
|
|
|
* Replace specified substring of first string with second
|
|
|
|
*
|
|
|
|
* The SQL standard defines OVERLAY() in terms of substring and concatenation.
|
|
|
|
* This code is a direct implementation of what the standard says.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
bitoverlay(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
VarBit *t1 = PG_GETARG_VARBIT_P(0);
|
|
|
|
VarBit *t2 = PG_GETARG_VARBIT_P(1);
|
Phase 2 of pgindent updates.
Change pg_bsd_indent to follow upstream rules for placement of comments
to the right of code, and remove pgindent hack that caused comments
following #endif to not obey the general rule.
Commit e3860ffa4dd0dad0dd9eea4be9cc1412373a8c89 wasn't actually using
the published version of pg_bsd_indent, but a hacked-up version that
tried to minimize the amount of movement of comments to the right of
code. The situation of interest is where such a comment has to be
moved to the right of its default placement at column 33 because there's
code there. BSD indent has always moved right in units of tab stops
in such cases --- but in the previous incarnation, indent was working
in 8-space tab stops, while now it knows we use 4-space tabs. So the
net result is that in about half the cases, such comments are placed
one tab stop left of before. This is better all around: it leaves
more room on the line for comment text, and it means that in such
cases the comment uniformly starts at the next 4-space tab stop after
the code, rather than sometimes one and sometimes two tabs after.
Also, ensure that comments following #endif are indented the same
as comments following other preprocessor commands such as #else.
That inconsistency turns out to have been self-inflicted damage
from a poorly-thought-through post-indent "fixup" in pgindent.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
8 years ago
|
|
|
int sp = PG_GETARG_INT32(2); /* substring start position */
|
|
|
|
int sl = PG_GETARG_INT32(3); /* substring length */
|
|
|
|
|
|
|
|
PG_RETURN_VARBIT_P(bit_overlay(t1, t2, sp, sl));
|
|
|
|
}
|
|
|
|
|
|
|
|
Datum
|
|
|
|
bitoverlay_no_len(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
VarBit *t1 = PG_GETARG_VARBIT_P(0);
|
|
|
|
VarBit *t2 = PG_GETARG_VARBIT_P(1);
|
Phase 2 of pgindent updates.
Change pg_bsd_indent to follow upstream rules for placement of comments
to the right of code, and remove pgindent hack that caused comments
following #endif to not obey the general rule.
Commit e3860ffa4dd0dad0dd9eea4be9cc1412373a8c89 wasn't actually using
the published version of pg_bsd_indent, but a hacked-up version that
tried to minimize the amount of movement of comments to the right of
code. The situation of interest is where such a comment has to be
moved to the right of its default placement at column 33 because there's
code there. BSD indent has always moved right in units of tab stops
in such cases --- but in the previous incarnation, indent was working
in 8-space tab stops, while now it knows we use 4-space tabs. So the
net result is that in about half the cases, such comments are placed
one tab stop left of before. This is better all around: it leaves
more room on the line for comment text, and it means that in such
cases the comment uniformly starts at the next 4-space tab stop after
the code, rather than sometimes one and sometimes two tabs after.
Also, ensure that comments following #endif are indented the same
as comments following other preprocessor commands such as #else.
That inconsistency turns out to have been self-inflicted damage
from a poorly-thought-through post-indent "fixup" in pgindent.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
8 years ago
|
|
|
int sp = PG_GETARG_INT32(2); /* substring start position */
|
|
|
|
int sl;
|
|
|
|
|
|
|
|
sl = VARBITLEN(t2); /* defaults to length(t2) */
|
|
|
|
PG_RETURN_VARBIT_P(bit_overlay(t1, t2, sp, sl));
|
|
|
|
}
|
|
|
|
|
|
|
|
static VarBit *
|
|
|
|
bit_overlay(VarBit *t1, VarBit *t2, int sp, int sl)
|
|
|
|
{
|
|
|
|
VarBit *result;
|
|
|
|
VarBit *s1;
|
|
|
|
VarBit *s2;
|
|
|
|
int sp_pl_sl;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check for possible integer-overflow cases. For negative sp, throw a
|
|
|
|
* "substring length" error because that's what should be expected
|
|
|
|
* according to the spec's definition of OVERLAY().
|
|
|
|
*/
|
|
|
|
if (sp <= 0)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_SUBSTRING_ERROR),
|
|
|
|
errmsg("negative substring length not allowed")));
|
|
|
|
if (pg_add_s32_overflow(sp, sl, &sp_pl_sl))
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
|
|
|
errmsg("integer out of range")));
|
|
|
|
|
|
|
|
s1 = bitsubstring(t1, 1, sp - 1, false);
|
|
|
|
s2 = bitsubstring(t1, sp_pl_sl, -1, true);
|
|
|
|
result = bit_catenate(s1, t2);
|
|
|
|
result = bit_catenate(result, s2);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* bit_count
|
|
|
|
*
|
|
|
|
* Returns the number of bits set in a bit string.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
bit_bit_count(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
VarBit *arg = PG_GETARG_VARBIT_P(0);
|
|
|
|
|
|
|
|
PG_RETURN_INT64(pg_popcount((char *) VARBITS(arg), VARBITBYTES(arg)));
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* bitlength, bitoctetlength
|
|
|
|
* Return the length of a bit string
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
bitlength(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
VarBit *arg = PG_GETARG_VARBIT_P(0);
|
|
|
|
|
|
|
|
PG_RETURN_INT32(VARBITLEN(arg));
|
|
|
|
}
|
|
|
|
|
|
|
|
Datum
|
|
|
|
bitoctetlength(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
VarBit *arg = PG_GETARG_VARBIT_P(0);
|
|
|
|
|
|
|
|
PG_RETURN_INT32(VARBITBYTES(arg));
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* bit_and
|
|
|
|
* perform a logical AND on two bit strings.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
bit_and(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
VarBit *arg1 = PG_GETARG_VARBIT_P(0);
|
|
|
|
VarBit *arg2 = PG_GETARG_VARBIT_P(1);
|
|
|
|
VarBit *result;
|
|
|
|
int len,
|
|
|
|
bitlen1,
|
|
|
|
bitlen2,
|
|
|
|
i;
|
|
|
|
bits8 *p1,
|
|
|
|
*p2,
|
|
|
|
*r;
|
|
|
|
|
|
|
|
bitlen1 = VARBITLEN(arg1);
|
|
|
|
bitlen2 = VARBITLEN(arg2);
|
|
|
|
if (bitlen1 != bitlen2)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_STRING_DATA_LENGTH_MISMATCH),
|
|
|
|
errmsg("cannot AND bit strings of different sizes")));
|
|
|
|
|
|
|
|
len = VARSIZE(arg1);
|
|
|
|
result = (VarBit *) palloc(len);
|
|
|
|
SET_VARSIZE(result, len);
|
|
|
|
VARBITLEN(result) = bitlen1;
|
|
|
|
|
|
|
|
p1 = VARBITS(arg1);
|
|
|
|
p2 = VARBITS(arg2);
|
|
|
|
r = VARBITS(result);
|
|
|
|
for (i = 0; i < VARBITBYTES(arg1); i++)
|
|
|
|
*r++ = *p1++ & *p2++;
|
|
|
|
|
Fix failure to zero-pad the result of bitshiftright().
If the bitstring length is not a multiple of 8, we'd shift the
rightmost bits into the pad space, which must be zeroes --- bit_cmp,
for one, depends on that. This'd lead to the result failing to
compare equal to what it should compare equal to, as reported in
bug #16013 from Daryl Waycott.
This is, if memory serves, not the first such bug in the bitstring
functions. In hopes of making it the last one, do a bit more work
than minimally necessary to fix the bug:
* Add assertion checks to bit_out() and varbit_out() to complain if
they are given incorrectly-padded input. This will improve the
odds that manual testing of any new patch finds problems.
* Encapsulate the padding-related logic in macros to make it
easier to use.
Also, remove unnecessary padding logic from bit_or() and bitxor().
Somebody had already noted that we need not re-pad the result of
bit_and() since the inputs are required to be the same length,
but failed to extrapolate that to the other two.
Also, move a comment block that once was near the head of varbit.c
(but people kept putting other stuff in front of it), to put it in
the header block.
Note for the release notes: if anyone has inconsistent data as a
result of saving the output of bitshiftright() in a table, it's
possible to fix it with something like
UPDATE mytab SET bitcol = ~(~bitcol) WHERE bitcol != ~(~bitcol);
This has been broken since day one, so back-patch to all supported
branches.
Discussion: https://postgr.es/m/16013-c2765b6996aacae9@postgresql.org
6 years ago
|
|
|
/* Padding is not needed as & of 0 pads is 0 */
|
|
|
|
|
|
|
|
PG_RETURN_VARBIT_P(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* bit_or
|
|
|
|
* perform a logical OR on two bit strings.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
bit_or(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
VarBit *arg1 = PG_GETARG_VARBIT_P(0);
|
|
|
|
VarBit *arg2 = PG_GETARG_VARBIT_P(1);
|
|
|
|
VarBit *result;
|
|
|
|
int len,
|
|
|
|
bitlen1,
|
|
|
|
bitlen2,
|
|
|
|
i;
|
|
|
|
bits8 *p1,
|
|
|
|
*p2,
|
|
|
|
*r;
|
|
|
|
|
|
|
|
bitlen1 = VARBITLEN(arg1);
|
|
|
|
bitlen2 = VARBITLEN(arg2);
|
|
|
|
if (bitlen1 != bitlen2)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_STRING_DATA_LENGTH_MISMATCH),
|
|
|
|
errmsg("cannot OR bit strings of different sizes")));
|
|
|
|
len = VARSIZE(arg1);
|
|
|
|
result = (VarBit *) palloc(len);
|
|
|
|
SET_VARSIZE(result, len);
|
|
|
|
VARBITLEN(result) = bitlen1;
|
|
|
|
|
|
|
|
p1 = VARBITS(arg1);
|
|
|
|
p2 = VARBITS(arg2);
|
|
|
|
r = VARBITS(result);
|
|
|
|
for (i = 0; i < VARBITBYTES(arg1); i++)
|
|
|
|
*r++ = *p1++ | *p2++;
|
|
|
|
|
Fix failure to zero-pad the result of bitshiftright().
If the bitstring length is not a multiple of 8, we'd shift the
rightmost bits into the pad space, which must be zeroes --- bit_cmp,
for one, depends on that. This'd lead to the result failing to
compare equal to what it should compare equal to, as reported in
bug #16013 from Daryl Waycott.
This is, if memory serves, not the first such bug in the bitstring
functions. In hopes of making it the last one, do a bit more work
than minimally necessary to fix the bug:
* Add assertion checks to bit_out() and varbit_out() to complain if
they are given incorrectly-padded input. This will improve the
odds that manual testing of any new patch finds problems.
* Encapsulate the padding-related logic in macros to make it
easier to use.
Also, remove unnecessary padding logic from bit_or() and bitxor().
Somebody had already noted that we need not re-pad the result of
bit_and() since the inputs are required to be the same length,
but failed to extrapolate that to the other two.
Also, move a comment block that once was near the head of varbit.c
(but people kept putting other stuff in front of it), to put it in
the header block.
Note for the release notes: if anyone has inconsistent data as a
result of saving the output of bitshiftright() in a table, it's
possible to fix it with something like
UPDATE mytab SET bitcol = ~(~bitcol) WHERE bitcol != ~(~bitcol);
This has been broken since day one, so back-patch to all supported
branches.
Discussion: https://postgr.es/m/16013-c2765b6996aacae9@postgresql.org
6 years ago
|
|
|
/* Padding is not needed as | of 0 pads is 0 */
|
|
|
|
|
|
|
|
PG_RETURN_VARBIT_P(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* bitxor
|
|
|
|
* perform a logical XOR on two bit strings.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
bitxor(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
VarBit *arg1 = PG_GETARG_VARBIT_P(0);
|
|
|
|
VarBit *arg2 = PG_GETARG_VARBIT_P(1);
|
|
|
|
VarBit *result;
|
|
|
|
int len,
|
|
|
|
bitlen1,
|
|
|
|
bitlen2,
|
|
|
|
i;
|
|
|
|
bits8 *p1,
|
|
|
|
*p2,
|
|
|
|
*r;
|
|
|
|
|
|
|
|
bitlen1 = VARBITLEN(arg1);
|
|
|
|
bitlen2 = VARBITLEN(arg2);
|
|
|
|
if (bitlen1 != bitlen2)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_STRING_DATA_LENGTH_MISMATCH),
|
|
|
|
errmsg("cannot XOR bit strings of different sizes")));
|
|
|
|
|
|
|
|
len = VARSIZE(arg1);
|
|
|
|
result = (VarBit *) palloc(len);
|
|
|
|
SET_VARSIZE(result, len);
|
|
|
|
VARBITLEN(result) = bitlen1;
|
|
|
|
|
|
|
|
p1 = VARBITS(arg1);
|
|
|
|
p2 = VARBITS(arg2);
|
|
|
|
r = VARBITS(result);
|
|
|
|
for (i = 0; i < VARBITBYTES(arg1); i++)
|
|
|
|
*r++ = *p1++ ^ *p2++;
|
|
|
|
|
Fix failure to zero-pad the result of bitshiftright().
If the bitstring length is not a multiple of 8, we'd shift the
rightmost bits into the pad space, which must be zeroes --- bit_cmp,
for one, depends on that. This'd lead to the result failing to
compare equal to what it should compare equal to, as reported in
bug #16013 from Daryl Waycott.
This is, if memory serves, not the first such bug in the bitstring
functions. In hopes of making it the last one, do a bit more work
than minimally necessary to fix the bug:
* Add assertion checks to bit_out() and varbit_out() to complain if
they are given incorrectly-padded input. This will improve the
odds that manual testing of any new patch finds problems.
* Encapsulate the padding-related logic in macros to make it
easier to use.
Also, remove unnecessary padding logic from bit_or() and bitxor().
Somebody had already noted that we need not re-pad the result of
bit_and() since the inputs are required to be the same length,
but failed to extrapolate that to the other two.
Also, move a comment block that once was near the head of varbit.c
(but people kept putting other stuff in front of it), to put it in
the header block.
Note for the release notes: if anyone has inconsistent data as a
result of saving the output of bitshiftright() in a table, it's
possible to fix it with something like
UPDATE mytab SET bitcol = ~(~bitcol) WHERE bitcol != ~(~bitcol);
This has been broken since day one, so back-patch to all supported
branches.
Discussion: https://postgr.es/m/16013-c2765b6996aacae9@postgresql.org
6 years ago
|
|
|
/* Padding is not needed as ^ of 0 pads is 0 */
|
|
|
|
|
|
|
|
PG_RETURN_VARBIT_P(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* bitnot
|
|
|
|
* perform a logical NOT on a bit string.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
bitnot(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
VarBit *arg = PG_GETARG_VARBIT_P(0);
|
|
|
|
VarBit *result;
|
|
|
|
bits8 *p,
|
|
|
|
*r;
|
|
|
|
|
|
|
|
result = (VarBit *) palloc(VARSIZE(arg));
|
|
|
|
SET_VARSIZE(result, VARSIZE(arg));
|
|
|
|
VARBITLEN(result) = VARBITLEN(arg);
|
|
|
|
|
|
|
|
p = VARBITS(arg);
|
|
|
|
r = VARBITS(result);
|
|
|
|
for (; p < VARBITEND(arg); p++)
|
|
|
|
*r++ = ~*p;
|
|
|
|
|
Fix failure to zero-pad the result of bitshiftright().
If the bitstring length is not a multiple of 8, we'd shift the
rightmost bits into the pad space, which must be zeroes --- bit_cmp,
for one, depends on that. This'd lead to the result failing to
compare equal to what it should compare equal to, as reported in
bug #16013 from Daryl Waycott.
This is, if memory serves, not the first such bug in the bitstring
functions. In hopes of making it the last one, do a bit more work
than minimally necessary to fix the bug:
* Add assertion checks to bit_out() and varbit_out() to complain if
they are given incorrectly-padded input. This will improve the
odds that manual testing of any new patch finds problems.
* Encapsulate the padding-related logic in macros to make it
easier to use.
Also, remove unnecessary padding logic from bit_or() and bitxor().
Somebody had already noted that we need not re-pad the result of
bit_and() since the inputs are required to be the same length,
but failed to extrapolate that to the other two.
Also, move a comment block that once was near the head of varbit.c
(but people kept putting other stuff in front of it), to put it in
the header block.
Note for the release notes: if anyone has inconsistent data as a
result of saving the output of bitshiftright() in a table, it's
possible to fix it with something like
UPDATE mytab SET bitcol = ~(~bitcol) WHERE bitcol != ~(~bitcol);
This has been broken since day one, so back-patch to all supported
branches.
Discussion: https://postgr.es/m/16013-c2765b6996aacae9@postgresql.org
6 years ago
|
|
|
/* Must zero-pad the result, because extra bits are surely 1's here */
|
|
|
|
VARBIT_PAD_LAST(result, r);
|
|
|
|
|
|
|
|
PG_RETURN_VARBIT_P(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* bitshiftleft
|
|
|
|
* do a left shift (i.e. towards the beginning of the string)
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
bitshiftleft(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
VarBit *arg = PG_GETARG_VARBIT_P(0);
|
|
|
|
int32 shft = PG_GETARG_INT32(1);
|
|
|
|
VarBit *result;
|
|
|
|
int byte_shift,
|
|
|
|
ishift,
|
|
|
|
len;
|
|
|
|
bits8 *p,
|
|
|
|
*r;
|
|
|
|
|
|
|
|
/* Negative shift is a shift to the right */
|
|
|
|
if (shft < 0)
|
|
|
|
{
|
|
|
|
/* Prevent integer overflow in negation */
|
|
|
|
if (shft < -VARBITMAXLEN)
|
|
|
|
shft = -VARBITMAXLEN;
|
|
|
|
PG_RETURN_DATUM(DirectFunctionCall2(bitshiftright,
|
|
|
|
VarBitPGetDatum(arg),
|
|
|
|
Int32GetDatum(-shft)));
|
|
|
|
}
|
|
|
|
|
|
|
|
result = (VarBit *) palloc(VARSIZE(arg));
|
|
|
|
SET_VARSIZE(result, VARSIZE(arg));
|
|
|
|
VARBITLEN(result) = VARBITLEN(arg);
|
|
|
|
r = VARBITS(result);
|
|
|
|
|
|
|
|
/* If we shifted all the bits out, return an all-zero string */
|
|
|
|
if (shft >= VARBITLEN(arg))
|
|
|
|
{
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
23 years ago
|
|
|
MemSet(r, 0, VARBITBYTES(arg));
|
|
|
|
PG_RETURN_VARBIT_P(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
byte_shift = shft / BITS_PER_BYTE;
|
|
|
|
ishift = shft % BITS_PER_BYTE;
|
|
|
|
p = VARBITS(arg) + byte_shift;
|
|
|
|
|
|
|
|
if (ishift == 0)
|
|
|
|
{
|
|
|
|
/* Special case: we can do a memcpy */
|
|
|
|
len = VARBITBYTES(arg) - byte_shift;
|
|
|
|
memcpy(r, p, len);
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
23 years ago
|
|
|
MemSet(r + len, 0, byte_shift);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (; p < VARBITEND(arg); r++)
|
|
|
|
{
|
|
|
|
*r = *p << ishift;
|
|
|
|
if ((++p) < VARBITEND(arg))
|
|
|
|
*r |= *p >> (BITS_PER_BYTE - ishift);
|
|
|
|
}
|
|
|
|
for (; r < VARBITEND(result); r++)
|
|
|
|
*r = 0;
|
|
|
|
}
|
|
|
|
|
Fix failure to zero-pad the result of bitshiftright().
If the bitstring length is not a multiple of 8, we'd shift the
rightmost bits into the pad space, which must be zeroes --- bit_cmp,
for one, depends on that. This'd lead to the result failing to
compare equal to what it should compare equal to, as reported in
bug #16013 from Daryl Waycott.
This is, if memory serves, not the first such bug in the bitstring
functions. In hopes of making it the last one, do a bit more work
than minimally necessary to fix the bug:
* Add assertion checks to bit_out() and varbit_out() to complain if
they are given incorrectly-padded input. This will improve the
odds that manual testing of any new patch finds problems.
* Encapsulate the padding-related logic in macros to make it
easier to use.
Also, remove unnecessary padding logic from bit_or() and bitxor().
Somebody had already noted that we need not re-pad the result of
bit_and() since the inputs are required to be the same length,
but failed to extrapolate that to the other two.
Also, move a comment block that once was near the head of varbit.c
(but people kept putting other stuff in front of it), to put it in
the header block.
Note for the release notes: if anyone has inconsistent data as a
result of saving the output of bitshiftright() in a table, it's
possible to fix it with something like
UPDATE mytab SET bitcol = ~(~bitcol) WHERE bitcol != ~(~bitcol);
This has been broken since day one, so back-patch to all supported
branches.
Discussion: https://postgr.es/m/16013-c2765b6996aacae9@postgresql.org
6 years ago
|
|
|
/* The pad bits should be already zero at this point */
|
|
|
|
|
|
|
|
PG_RETURN_VARBIT_P(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* bitshiftright
|
|
|
|
* do a right shift (i.e. towards the end of the string)
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
bitshiftright(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
VarBit *arg = PG_GETARG_VARBIT_P(0);
|
|
|
|
int32 shft = PG_GETARG_INT32(1);
|
|
|
|
VarBit *result;
|
|
|
|
int byte_shift,
|
|
|
|
ishift,
|
|
|
|
len;
|
|
|
|
bits8 *p,
|
|
|
|
*r;
|
|
|
|
|
|
|
|
/* Negative shift is a shift to the left */
|
|
|
|
if (shft < 0)
|
|
|
|
{
|
|
|
|
/* Prevent integer overflow in negation */
|
|
|
|
if (shft < -VARBITMAXLEN)
|
|
|
|
shft = -VARBITMAXLEN;
|
|
|
|
PG_RETURN_DATUM(DirectFunctionCall2(bitshiftleft,
|
|
|
|
VarBitPGetDatum(arg),
|
|
|
|
Int32GetDatum(-shft)));
|
|
|
|
}
|
|
|
|
|
|
|
|
result = (VarBit *) palloc(VARSIZE(arg));
|
|
|
|
SET_VARSIZE(result, VARSIZE(arg));
|
|
|
|
VARBITLEN(result) = VARBITLEN(arg);
|
|
|
|
r = VARBITS(result);
|
|
|
|
|
|
|
|
/* If we shifted all the bits out, return an all-zero string */
|
|
|
|
if (shft >= VARBITLEN(arg))
|
|
|
|
{
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
23 years ago
|
|
|
MemSet(r, 0, VARBITBYTES(arg));
|
|
|
|
PG_RETURN_VARBIT_P(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
byte_shift = shft / BITS_PER_BYTE;
|
|
|
|
ishift = shft % BITS_PER_BYTE;
|
|
|
|
p = VARBITS(arg);
|
|
|
|
|
|
|
|
/* Set the first part of the result to 0 */
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
23 years ago
|
|
|
MemSet(r, 0, byte_shift);
|
|
|
|
r += byte_shift;
|
|
|
|
|
|
|
|
if (ishift == 0)
|
|
|
|
{
|
|
|
|
/* Special case: we can do a memcpy */
|
|
|
|
len = VARBITBYTES(arg) - byte_shift;
|
|
|
|
memcpy(r, p, len);
|
|
|
|
r += len;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (r < VARBITEND(result))
|
|
|
|
*r = 0; /* initialize first byte */
|
|
|
|
for (; r < VARBITEND(result); p++)
|
|
|
|
{
|
|
|
|
*r |= *p >> ishift;
|
|
|
|
if ((++r) < VARBITEND(result))
|
|
|
|
*r = (*p << (BITS_PER_BYTE - ishift)) & BITMASK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We may have shifted 1's into the pad bits, so fix that */
|
|
|
|
VARBIT_PAD_LAST(result, r);
|
|
|
|
|
|
|
|
PG_RETURN_VARBIT_P(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This is not defined in any standard. We retain the natural ordering of
|
|
|
|
* bits here, as it just seems more intuitive.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
bitfromint4(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
int32 a = PG_GETARG_INT32(0);
|
|
|
|
int32 typmod = PG_GETARG_INT32(1);
|
|
|
|
VarBit *result;
|
|
|
|
bits8 *r;
|
|
|
|
int rlen;
|
|
|
|
int destbitsleft,
|
|
|
|
srcbitsleft;
|
|
|
|
|
|
|
|
if (typmod <= 0 || typmod > VARBITMAXLEN)
|
|
|
|
typmod = 1; /* default bit length */
|
|
|
|
|
|
|
|
rlen = VARBITTOTALLEN(typmod);
|
|
|
|
result = (VarBit *) palloc(rlen);
|
|
|
|
SET_VARSIZE(result, rlen);
|
|
|
|
VARBITLEN(result) = typmod;
|
|
|
|
|
|
|
|
r = VARBITS(result);
|
|
|
|
destbitsleft = typmod;
|
|
|
|
srcbitsleft = 32;
|
|
|
|
/* drop any input bits that don't fit */
|
|
|
|
srcbitsleft = Min(srcbitsleft, destbitsleft);
|
|
|
|
/* sign-fill any excess bytes in output */
|
|
|
|
while (destbitsleft >= srcbitsleft + 8)
|
|
|
|
{
|
|
|
|
*r++ = (bits8) ((a < 0) ? BITMASK : 0);
|
|
|
|
destbitsleft -= 8;
|
|
|
|
}
|
|
|
|
/* store first fractional byte */
|
|
|
|
if (destbitsleft > srcbitsleft)
|
|
|
|
{
|
|
|
|
unsigned int val = (unsigned int) (a >> (destbitsleft - 8));
|
|
|
|
|
|
|
|
/* Force sign-fill in case the compiler implements >> as zero-fill */
|
|
|
|
if (a < 0)
|
|
|
|
val |= ((unsigned int) -1) << (srcbitsleft + 8 - destbitsleft);
|
|
|
|
*r++ = (bits8) (val & BITMASK);
|
|
|
|
destbitsleft -= 8;
|
|
|
|
}
|
|
|
|
/* Now srcbitsleft and destbitsleft are the same, need not track both */
|
|
|
|
/* store whole bytes */
|
|
|
|
while (destbitsleft >= 8)
|
|
|
|
{
|
|
|
|
*r++ = (bits8) ((a >> (destbitsleft - 8)) & BITMASK);
|
|
|
|
destbitsleft -= 8;
|
|
|
|
}
|
|
|
|
/* store last fractional byte */
|
|
|
|
if (destbitsleft > 0)
|
|
|
|
*r = (bits8) ((a << (8 - destbitsleft)) & BITMASK);
|
|
|
|
|
|
|
|
PG_RETURN_VARBIT_P(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
Datum
|
|
|
|
bittoint4(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
VarBit *arg = PG_GETARG_VARBIT_P(0);
|
|
|
|
uint32 result;
|
|
|
|
bits8 *r;
|
|
|
|
|
|
|
|
/* Check that the bit string is not too long */
|
|
|
|
if (VARBITLEN(arg) > sizeof(result) * BITS_PER_BYTE)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
|
|
|
errmsg("integer out of range")));
|
|
|
|
|
|
|
|
result = 0;
|
|
|
|
for (r = VARBITS(arg); r < VARBITEND(arg); r++)
|
|
|
|
{
|
|
|
|
result <<= BITS_PER_BYTE;
|
|
|
|
result |= *r;
|
|
|
|
}
|
|
|
|
/* Now shift the result to take account of the padding at the end */
|
|
|
|
result >>= VARBITPAD(arg);
|
|
|
|
|
|
|
|
PG_RETURN_INT32(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
Datum
|
|
|
|
bitfromint8(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
int64 a = PG_GETARG_INT64(0);
|
|
|
|
int32 typmod = PG_GETARG_INT32(1);
|
|
|
|
VarBit *result;
|
|
|
|
bits8 *r;
|
|
|
|
int rlen;
|
|
|
|
int destbitsleft,
|
|
|
|
srcbitsleft;
|
|
|
|
|
|
|
|
if (typmod <= 0 || typmod > VARBITMAXLEN)
|
|
|
|
typmod = 1; /* default bit length */
|
|
|
|
|
|
|
|
rlen = VARBITTOTALLEN(typmod);
|
|
|
|
result = (VarBit *) palloc(rlen);
|
|
|
|
SET_VARSIZE(result, rlen);
|
|
|
|
VARBITLEN(result) = typmod;
|
|
|
|
|
|
|
|
r = VARBITS(result);
|
|
|
|
destbitsleft = typmod;
|
|
|
|
srcbitsleft = 64;
|
|
|
|
/* drop any input bits that don't fit */
|
|
|
|
srcbitsleft = Min(srcbitsleft, destbitsleft);
|
|
|
|
/* sign-fill any excess bytes in output */
|
|
|
|
while (destbitsleft >= srcbitsleft + 8)
|
|
|
|
{
|
|
|
|
*r++ = (bits8) ((a < 0) ? BITMASK : 0);
|
|
|
|
destbitsleft -= 8;
|
|
|
|
}
|
|
|
|
/* store first fractional byte */
|
|
|
|
if (destbitsleft > srcbitsleft)
|
|
|
|
{
|
|
|
|
unsigned int val = (unsigned int) (a >> (destbitsleft - 8));
|
|
|
|
|
|
|
|
/* Force sign-fill in case the compiler implements >> as zero-fill */
|
|
|
|
if (a < 0)
|
|
|
|
val |= ((unsigned int) -1) << (srcbitsleft + 8 - destbitsleft);
|
|
|
|
*r++ = (bits8) (val & BITMASK);
|
|
|
|
destbitsleft -= 8;
|
|
|
|
}
|
|
|
|
/* Now srcbitsleft and destbitsleft are the same, need not track both */
|
|
|
|
/* store whole bytes */
|
|
|
|
while (destbitsleft >= 8)
|
|
|
|
{
|
|
|
|
*r++ = (bits8) ((a >> (destbitsleft - 8)) & BITMASK);
|
|
|
|
destbitsleft -= 8;
|
|
|
|
}
|
|
|
|
/* store last fractional byte */
|
|
|
|
if (destbitsleft > 0)
|
|
|
|
*r = (bits8) ((a << (8 - destbitsleft)) & BITMASK);
|
|
|
|
|
|
|
|
PG_RETURN_VARBIT_P(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
Datum
|
|
|
|
bittoint8(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
VarBit *arg = PG_GETARG_VARBIT_P(0);
|
|
|
|
uint64 result;
|
|
|
|
bits8 *r;
|
|
|
|
|
|
|
|
/* Check that the bit string is not too long */
|
|
|
|
if (VARBITLEN(arg) > sizeof(result) * BITS_PER_BYTE)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
|
|
|
errmsg("bigint out of range")));
|
|
|
|
|
|
|
|
result = 0;
|
|
|
|
for (r = VARBITS(arg); r < VARBITEND(arg); r++)
|
|
|
|
{
|
|
|
|
result <<= BITS_PER_BYTE;
|
|
|
|
result |= *r;
|
|
|
|
}
|
|
|
|
/* Now shift the result to take account of the padding at the end */
|
|
|
|
result >>= VARBITPAD(arg);
|
|
|
|
|
|
|
|
PG_RETURN_INT64(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Determines the position of S2 in the bitstring S1 (1-based string).
|
|
|
|
* If S2 does not appear in S1 this function returns 0.
|
|
|
|
* If S2 is of length 0 this function returns 1.
|
|
|
|
* Compatible in usage with POSITION() functions for other data types.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
bitposition(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
VarBit *str = PG_GETARG_VARBIT_P(0);
|
|
|
|
VarBit *substr = PG_GETARG_VARBIT_P(1);
|
|
|
|
int substr_length,
|
|
|
|
str_length,
|
|
|
|
i,
|
|
|
|
is;
|
|
|
|
bits8 *s, /* pointer into substring */
|
|
|
|
*p; /* pointer into str */
|
|
|
|
bits8 cmp, /* shifted substring byte to compare */
|
|
|
|
mask1, /* mask for substring byte shifted right */
|
|
|
|
mask2, /* mask for substring byte shifted left */
|
|
|
|
end_mask, /* pad mask for last substring byte */
|
|
|
|
str_mask; /* pad mask for last string byte */
|
|
|
|
bool is_match;
|
|
|
|
|
|
|
|
/* Get the substring length */
|
|
|
|
substr_length = VARBITLEN(substr);
|
|
|
|
str_length = VARBITLEN(str);
|
|
|
|
|
|
|
|
/* String has zero length or substring longer than string, return 0 */
|
|
|
|
if ((str_length == 0) || (substr_length > str_length))
|
|
|
|
PG_RETURN_INT32(0);
|
|
|
|
|
|
|
|
/* zero-length substring means return 1 */
|
|
|
|
if (substr_length == 0)
|
|
|
|
PG_RETURN_INT32(1);
|
|
|
|
|
|
|
|
/* Initialise the padding masks */
|
|
|
|
end_mask = BITMASK << VARBITPAD(substr);
|
|
|
|
str_mask = BITMASK << VARBITPAD(str);
|
|
|
|
for (i = 0; i < VARBITBYTES(str) - VARBITBYTES(substr) + 1; i++)
|
|
|
|
{
|
|
|
|
for (is = 0; is < BITS_PER_BYTE; is++)
|
|
|
|
{
|
|
|
|
is_match = true;
|
|
|
|
p = VARBITS(str) + i;
|
|
|
|
mask1 = BITMASK >> is;
|
|
|
|
mask2 = ~mask1;
|
|
|
|
for (s = VARBITS(substr);
|
|
|
|
is_match && s < VARBITEND(substr); s++)
|
|
|
|
{
|
|
|
|
cmp = *s >> is;
|
|
|
|
if (s == VARBITEND(substr) - 1)
|
|
|
|
{
|
|
|
|
mask1 &= end_mask >> is;
|
|
|
|
if (p == VARBITEND(str) - 1)
|
|
|
|
{
|
|
|
|
/* Check that there is enough of str left */
|
|
|
|
if (mask1 & ~str_mask)
|
|
|
|
{
|
|
|
|
is_match = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
mask1 &= str_mask;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
is_match = ((cmp ^ *p) & mask1) == 0;
|
|
|
|
if (!is_match)
|
|
|
|
break;
|
|
|
|
/* Move on to the next byte */
|
|
|
|
p++;
|
|
|
|
if (p == VARBITEND(str))
|
|
|
|
{
|
|
|
|
mask2 = end_mask << (BITS_PER_BYTE - is);
|
|
|
|
is_match = mask2 == 0;
|
|
|
|
#if 0
|
|
|
|
elog(DEBUG4, "S. %d %d em=%2x sm=%2x r=%d",
|
|
|
|
i, is, end_mask, mask2, is_match);
|
|
|
|
#endif
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
cmp = *s << (BITS_PER_BYTE - is);
|
|
|
|
if (s == VARBITEND(substr) - 1)
|
|
|
|
{
|
|
|
|
mask2 &= end_mask << (BITS_PER_BYTE - is);
|
|
|
|
if (p == VARBITEND(str) - 1)
|
|
|
|
{
|
|
|
|
if (mask2 & ~str_mask)
|
|
|
|
{
|
|
|
|
is_match = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
mask2 &= str_mask;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
is_match = ((cmp ^ *p) & mask2) == 0;
|
|
|
|
}
|
|
|
|
/* Have we found a match? */
|
|
|
|
if (is_match)
|
|
|
|
PG_RETURN_INT32(i * BITS_PER_BYTE + is + 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
PG_RETURN_INT32(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* bitsetbit
|
|
|
|
*
|
|
|
|
* Given an instance of type 'bit' creates a new one with
|
|
|
|
* the Nth bit set to the given value.
|
|
|
|
*
|
|
|
|
* The bit location is specified left-to-right in a zero-based fashion
|
|
|
|
* consistent with the other get_bit and set_bit functions, but
|
|
|
|
* inconsistent with the standard substring, position, overlay functions
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
bitsetbit(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
VarBit *arg1 = PG_GETARG_VARBIT_P(0);
|
|
|
|
int32 n = PG_GETARG_INT32(1);
|
|
|
|
int32 newBit = PG_GETARG_INT32(2);
|
|
|
|
VarBit *result;
|
|
|
|
int len,
|
|
|
|
bitlen;
|
|
|
|
bits8 *r,
|
|
|
|
*p;
|
|
|
|
int byteNo,
|
|
|
|
bitNo;
|
|
|
|
|
|
|
|
bitlen = VARBITLEN(arg1);
|
|
|
|
if (n < 0 || n >= bitlen)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
|
|
|
|
errmsg("bit index %d out of valid range (0..%d)",
|
|
|
|
n, bitlen - 1)));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* sanity check!
|
|
|
|
*/
|
|
|
|
if (newBit != 0 && newBit != 1)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
|
|
|
errmsg("new bit must be 0 or 1")));
|
|
|
|
|
|
|
|
len = VARSIZE(arg1);
|
|
|
|
result = (VarBit *) palloc(len);
|
|
|
|
SET_VARSIZE(result, len);
|
|
|
|
VARBITLEN(result) = bitlen;
|
|
|
|
|
|
|
|
p = VARBITS(arg1);
|
|
|
|
r = VARBITS(result);
|
|
|
|
|
|
|
|
memcpy(r, p, VARBITBYTES(arg1));
|
|
|
|
|
|
|
|
byteNo = n / BITS_PER_BYTE;
|
|
|
|
bitNo = BITS_PER_BYTE - 1 - (n % BITS_PER_BYTE);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Update the byte.
|
|
|
|
*/
|
|
|
|
if (newBit == 0)
|
|
|
|
r[byteNo] &= (~(1 << bitNo));
|
|
|
|
else
|
|
|
|
r[byteNo] |= (1 << bitNo);
|
|
|
|
|
|
|
|
PG_RETURN_VARBIT_P(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* bitgetbit
|
|
|
|
*
|
|
|
|
* returns the value of the Nth bit of a bit array (0 or 1).
|
|
|
|
*
|
|
|
|
* The bit location is specified left-to-right in a zero-based fashion
|
|
|
|
* consistent with the other get_bit and set_bit functions, but
|
|
|
|
* inconsistent with the standard substring, position, overlay functions
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
bitgetbit(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
VarBit *arg1 = PG_GETARG_VARBIT_P(0);
|
|
|
|
int32 n = PG_GETARG_INT32(1);
|
|
|
|
int bitlen;
|
|
|
|
bits8 *p;
|
|
|
|
int byteNo,
|
|
|
|
bitNo;
|
|
|
|
|
|
|
|
bitlen = VARBITLEN(arg1);
|
|
|
|
if (n < 0 || n >= bitlen)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
|
|
|
|
errmsg("bit index %d out of valid range (0..%d)",
|
|
|
|
n, bitlen - 1)));
|
|
|
|
|
|
|
|
p = VARBITS(arg1);
|
|
|
|
|
|
|
|
byteNo = n / BITS_PER_BYTE;
|
|
|
|
bitNo = BITS_PER_BYTE - 1 - (n % BITS_PER_BYTE);
|
|
|
|
|
|
|
|
if (p[byteNo] & (1 << bitNo))
|
|
|
|
PG_RETURN_INT32(1);
|
|
|
|
else
|
|
|
|
PG_RETURN_INT32(0);
|
|
|
|
}
|