*
* varbit.c
* Functions for the SQL datatypes BIT() and BIT VARYING().
*
* Code originally contributed by Adriaan Joubert.
*
* Portions Copyright (c) 1996-2012, 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 "knl/knl_variable.h"
#include "access/htup.h"
#include "common/int.h"
#include "libpq/pqformat.h"
#include "nodes/nodeFuncs.h"
#include "nodes/supportnodes.h"
#include "utils/array.h"
#include "access/tuptoaster.h"
#include "plugin_postgres.h"
#ifdef DOLPHIN
#include "utils/float.h"
#include "plugin_commands/mysqlmode.h"
#include "plugin_utils/int8.h"
#include "plugin_utils/year.h"
#include "plugin_utils/varbit.h"
#define BYTE_SIZE 8
#define SMALL_SIZE 16
#define M_BIT_LEN 64
#else
#include "utils/varbit.h"
#endif
#define HEXDIG(z) ((z) < 10 ? ((z) + '0') : ((z)-10 + 'A'))
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);
#ifdef DOLPHIN
extern int GetLeadingZeroLen(VarBit* arg);
extern Datum dolphin_bitposition(PG_FUNCTION_ARGS);
static int32 bit_cmp(VarBit* arg1, VarBit* arg2, int leadingZeroLen1 = -1, int leadingZeroLen2 = -1);
extern "C" Datum ui8toi1(PG_FUNCTION_ARGS);
extern "C" Datum ui8toi2(PG_FUNCTION_ARGS);
extern "C" Datum ui8toi4(PG_FUNCTION_ARGS);
extern "C" Datum ui8toui1(PG_FUNCTION_ARGS);
extern "C" Datum ui8toui2(PG_FUNCTION_ARGS);
extern "C" Datum ui8toui4(PG_FUNCTION_ARGS);
extern "C" Datum date_int8(PG_FUNCTION_ARGS);
extern "C" Datum datetime_float(PG_FUNCTION_ARGS);
extern "C" Datum timestamptz_int8(PG_FUNCTION_ARGS);
extern "C" Datum time_int8(PG_FUNCTION_ARGS);
extern "C" Datum year_integer(PG_FUNCTION_ARGS);
extern "C" Datum uint8out(PG_FUNCTION_ARGS);
extern "C" Datum dolphin_binaryin(PG_FUNCTION_ARGS);
Datum bittobigint(VarBit* arg, bool isUnsigned, bool canIgnore = false);
PG_FUNCTION_INFO_V1_PUBLIC(cot_bit);
extern "C" DLL_PUBLIC Datum cot_bit(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1_PUBLIC(bit_bin_in);
extern "C" DLL_PUBLIC Datum bit_bin_in(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1_PUBLIC(acos_bit);
extern "C" DLL_PUBLIC Datum acos_bit(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1_PUBLIC(cos_bit);
extern "C" DLL_PUBLIC Datum cos_bit(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1_PUBLIC(asin_bit);
extern "C" DLL_PUBLIC Datum asin_bit(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1_PUBLIC(atan_bit);
extern "C" DLL_PUBLIC Datum atan_bit(PG_FUNCTION_ARGS);
#endif
PG_FUNCTION_INFO_V1_PUBLIC(c_bitoctetlength);
extern "C" DLL_PUBLIC Datum c_bitoctetlength(PG_FUNCTION_ARGS);
* common code for bittypmodin and varbittypmodin
*/
static int32 anybit_typmodin(ArrayType* ta, const char* typname)
{
int32 typmod;
int32* tl = NULL;
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", typname)));
if (*tl > (MaxAttrSize * BITS_PER_BYTE))
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("length for type %s cannot exceed %d", typname, MaxAttrSize * BITS_PER_BYTE)));
typmod = *tl;
return typmod;
}
* common code for bittypmodout and varbittypmodout
*/
static char* anybit_typmodout(int32 typmod)
{
const size_t buffer_len = 64;
char* res = (char*)palloc(buffer_len);
errno_t rc = 0;
if (typmod >= 0) {
rc = snprintf_s(res, buffer_len, buffer_len - 1, "(%d)", typmod);
securec_check_ss(rc, "\0", "\0");
} else
*res = '\0';
return res;
}
* attypmod -- contains the length of the bit string in bits, or for
* varying bits the maximum length.
*
* 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.
* ----------
*/
* 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.
*/
#ifdef DOLPHIN
Datum bit_in_internal(char* input_string, int32 atttypmod, bool can_ignore)
{
VarBit* result = NULL;
char* sp = NULL;
bits8* r = NULL;
int len,
bitlen,
slen;
bool bit_not_hex = false;
int bc;
bits8 x = 0;
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)
ereport(ERROR,
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
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)
ereport(ERROR,
(errcode(ERRCODE_STRING_DATA_LENGTH_MISMATCH),
errmsg("bit string length %d does not match type bit(%d)", bitlen, atttypmod)));
len = VARBITTOTALLEN(atttypmod);
result = (VarBit*)palloc0(len);
SET_VARSIZE(result, len);
VARBITLEN(result) = atttypmod;
r = VARBITS(result);
if (bit_not_hex) {
x = HIGHBIT;
for (; *sp; sp++) {
if (*sp == '1')
*r |= x;
else if (*sp != '0') {
ereport(can_ignore ? WARNING : ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("\"%c\" is not a valid binary digit", *sp)));
PG_RETURN_DATUM((Datum)DirectFunctionCall3(bit_in, CStringGetDatum(""), ObjectIdGetDatum(0), Int32GetDatum(-1)));
}
x >>= 1;
if (x == 0) {
x = HIGHBIT;
r++;
}
}
} else {
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 {
ereport(can_ignore ? WARNING : ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("\"%c\" is not a valid hexadecimal digit", *sp)));
PG_RETURN_DATUM((Datum)DirectFunctionCall3(bit_in, CStringGetDatum(""), ObjectIdGetDatum(0), Int32GetDatum(-1)));
}
if (bc) {
*r++ |= x;
bc = 0;
} else {
*r = x << 4;
bc = 1;
}
}
}
PG_RETURN_VARBIT_P(result);
}
#endif
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);
bool can_ignore = fcinfo->can_ignore;
VarBit* result = NULL;
char* sp = NULL;
int len,
bitlen,
slen;
#ifdef DOLPHIN
if (ENABLE_B_CMPT_MODE) {
sp = input_string;
slen = strlen(sp);
if (slen == 0) {
PG_RETURN_DATUM((Datum)DirectFunctionCall3(bit_bin_in, CStringGetDatum(""),
ObjectIdGetDatum(0), Int32GetDatum(-1)));
}
if (slen > VARBITMAXLEN / BYTE_SIZE) {
ereport(ERROR,
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("bit string length exceeds the maximum allowed (%d)", VARBITMAXLEN)));
}
bitlen = slen * BYTE_SIZE;
if (atttypmod <= 0) {
atttypmod = bitlen;
} else if (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(atttypmod);
result = (VarBit*)palloc0(len);
SET_VARSIZE(result, len);
VARBITLEN(result) = atttypmod;
errno_t ss_rc = 0;
ss_rc = memcpy_s(VARBITS(result), slen, sp, slen);
securec_check(ss_rc, "\0", "\0");
PG_RETURN_VARBIT_P(result);
}
#endif
PG_RETURN_VARBIT_P(bit_in_internal(input_string, atttypmod, can_ignore));
}
bool is_req_from_gsql_or_jdbc()
{
return is_req_from_jdbc() || is_req_from_gsql();
}
Datum bit_out_encode_as_str(VarBit *bits)
{
char* rp = NULL;
rp = bit_to_str(bits, true);
PG_RETURN_CSTRING(rp);
}
Datum bit_out_encode_as_int64(VarBit *bits)
{
Datum arg_int_datum = DirectFunctionCall1(bittoint8, VarBitPGetDatum(bits));
return DirectFunctionCall1(int8out, arg_int_datum);
}
Datum bit_out_as_hex(VarBit *bits)
{
int len = 0;
char* result = NULL;
char* rp = NULL;
int64 arg_int = DatumGetInt64(DirectFunctionCall1(bittoint8, VarBitPGetDatum(bits)));
len = VARBITBYTES(bits) * 2;
result = (char*)palloc(len + 3);
result[len + 2] = '\0';
rp = &result[len + 1];
do {
*rp-- = HEX_CHARS[arg_int & 15];
len--;
arg_int >>= 4;
} while (len > 0);
*rp-- = 'x';
*rp = '\\';
PG_RETURN_CSTRING(rp);
}
Datum bit_out(PG_FUNCTION_ARGS)
{
#ifdef DOLPHIN
VarBit *bits = PG_GETARG_VARBIT_P(0);
if (likely(is_req_from_gsql_or_jdbc())) {
if (GetSessionContext()->bit_output == BIT_OUTPUT_DEC) {
if (is_req_from_gsql()) {
return bit_out_encode_as_str(bits);
} else {
return bit_out_encode_as_int64(bits);
}
} else if (GetSessionContext()->bit_output == BIT_OUTPUT_HEX) {
return bit_out_as_hex(bits);
}
}
#endif
return varbit_out(fcinfo);
}
* 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 = NULL;
int len, bitlen;
int ipad;
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));
#ifdef DOLPHIN
* do left padding, just call shift right to pad 0
*/
ipad = VARBITPAD(result);
if (ipad > 0) {
PG_RETURN_DATUM(DirectFunctionCall3(bitshiftright, VarBitPGetDatum(result),
Int32GetDatum(ipad), BoolGetDatum(false)));
}
#else
ipad = VARBITPAD(result);
if (ipad > 0) {
mask = BITMASK << ipad;
*(VARBITS(result) + VARBITBYTES(result) - 1) &= mask;
}
#endif
PG_RETURN_VARBIT_P(result);
}
* bit_send - converts bit to binary format
*/
Datum bit_send(PG_FUNCTION_ARGS)
{
return varbit_send(fcinfo);
}
* bit()
* Converts a bit() type to a specific internal length.
* len is the bitlength specified in the column definition.
*
* 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);
VarBit* result = NULL;
int rlen;
errno_t ss_rc = 0;
if (len <= 0 || len > VARBITMAXLEN || len == VARBITLEN(arg))
PG_RETURN_VARBIT_P(arg);
#ifdef DOLPHIN
int errlevel = (!fcinfo->can_ignore && SQL_MODE_STRICT() ? ERROR : WARNING);
if (VARBITLEN(arg) - GetLeadingZeroLen(arg) > len) {
ereport(errlevel,
(errcode(ERRCODE_STRING_DATA_LENGTH_MISMATCH),
errmsg("bit string length %d does not match type bit(%d)", VARBITLEN(arg), len)));
rlen = VARBITTOTALLEN(len);
result = (VarBit*)palloc0(rlen);
SET_VARSIZE(result, rlen);
VARBITLEN(result) = len;
securec_check(memset_s(VARBITS(result), VARBITBYTES(result), __UINT8_MAX__, VARBITBYTES(result)), "\0", "\0");
PG_RETURN_VARBIT_P(result);
}
#else
bool isExplicit = PG_GETARG_BOOL(2);
if (!isExplicit && !fcinfo->can_ignore) {
ereport(ERROR,
(errcode(ERRCODE_STRING_DATA_LENGTH_MISMATCH),
errmsg("bit string length %d does not match type bit(%d)", VARBITLEN(arg), len)));
}
#endif
rlen = VARBITTOTALLEN(len);
result = (VarBit*)palloc0(rlen);
SET_VARSIZE(result, rlen);
VARBITLEN(result) = len;
#ifdef DOLPHIN
int shift = VARBITLEN(result) - VARBITLEN(arg);
size_t min_size = Min(VARBITBYTES(result), VARBITBYTES(arg));
if (shift < 0) {
if (min_size > 0) {
Datum cpy = DirectFunctionCall3(bitshiftright, VarBitPGetDatum(arg),
Int32GetDatum(shift), BoolGetDatum(false));
ss_rc = memcpy_s(VARBITS(result), min_size, VARBITS((VarBit*)cpy), min_size);
securec_check(ss_rc, "\0", "\0");
pfree((void*)cpy);
}
} else {
if (min_size > 0) {
ss_rc = memcpy_s(VARBITS(result), min_size, VARBITS(arg), min_size);
securec_check(ss_rc, "\0", "\0");
}
* do left padding, just call shift right to pad 0
*/
PG_RETURN_DATUM(DirectFunctionCall3(bitshiftright, VarBitPGetDatum(result),
Int32GetDatum(shift), BoolGetDatum(false)));
}
#else
size_t min_size = Min(VARBITBYTES(result), VARBITBYTES(arg));
if (min_size > 0) {
ss_rc = memcpy_s(VARBITS(result), min_size, VARBITS(arg), min_size);
securec_check(ss_rc, "\0", "\0");
}
* 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).
*/
ipad = VARBITPAD(result);
if (ipad > 0) {
mask = BITMASK << ipad;
*(VARBITS(result) + VARBITBYTES(result) - 1) &= mask;
}
#endif
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);
VarBit* result = NULL;
char* sp = NULL;
bits8* r = NULL;
int len,
bitlen,
slen;
bool bit_not_hex = false;
int bc;
bits8 x = 0;
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)
ereport(ERROR,
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
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)
ereport(ERROR,
(errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
errmsg("bit string too long for type bit varying(%d)", atttypmod)));
len = VARBITTOTALLEN(bitlen);
result = (VarBit*)palloc0(len);
SET_VARSIZE(result, len);
VARBITLEN(result) = Min(bitlen, atttypmod);
r = VARBITS(result);
if (bit_not_hex) {
x = HIGHBIT;
for (; *sp; sp++) {
if (*sp == '1')
*r |= x;
else if (*sp != '0')
ereport(ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("\"%c\" is not a valid binary digit", *sp)));
x >>= 1;
if (x == 0) {
x = HIGHBIT;
r++;
}
}
} else {
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
ereport(ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("\"%c\" is not a valid hexadecimal digit", *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 = NULL, *r = NULL;
bits8* sp = NULL;
bits8 x;
int i, k, len;
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++) {
x = *sp;
for (k = 0; k < BITS_PER_BYTE; k++) {
*r++ = IS_HIGHBIT_SET(x) ? '1' : '0';
x <<= 1;
}
}
if (i < len) {
x = *sp;
for (k = i; k < len; k++) {
*r++ = IS_HIGHBIT_SET(x) ? '1' : '0';
x <<= 1;
}
}
*r = '\0';
PG_FREE_IF_COPY(s, 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 = NULL;
int len, bitlen;
int ipad;
bits8 mask;
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));
ipad = VARBITPAD(result);
if (ipad > 0) {
mask = BITMASK << ipad;
*(VARBITS(result) + VARBITBYTES(result) - 1) &= mask;
}
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, (char*)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 = NULL;
Assert(IsA(expr, FuncExpr));
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;
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.
*
* 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);
bool isExplicit = PG_GETARG_BOOL(2);
VarBit* result = NULL;
int rlen;
int ipad;
bits8 mask;
errno_t ss_rc = 0;
if (len <= 0 || len >= VARBITLEN(arg))
PG_RETURN_VARBIT_P(arg);
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;
if (VARBITBYTES(result) > 0) {
ss_rc = memcpy_s(VARBITS(result), VARBITBYTES(result), VARBITS(arg), VARBITBYTES(result));
securec_check(ss_rc, "\0", "\0");
}
ipad = VARBITPAD(result);
if (ipad > 0) {
mask = BITMASK << ipad;
*(VARBITS(result) + VARBITBYTES(result) - 1) &= mask;
}
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.
*/
#ifdef DOLPHIN
int GetLeadingZeroLen(VarBit* arg)
{
int leadingZeroLen = 0;
int i;
* example: for a value b'1' in bit(5), it will be b'00001000', the first 4 zero is left padding,
* the last 3 zero are not the real value, should be ignored. So we get the leading zero by:
* 1. traverse the all bytes
* 2. for every single byte, loop from the highest bit, check whether it's 0, end loop when meet 1
*/
for (bits8* r = VARBITS(arg); r < VARBITEND(arg) && leadingZeroLen < VARBITLEN(arg); r++) {
for (i = BITS_PER_BYTE - 1; i >= 0 && leadingZeroLen < VARBITLEN(arg); i--) {
if (*r >> i == 1) {
break;
}
leadingZeroLen++;
}
if (i != -1) {
break;
}
}
return leadingZeroLen;
}
#endif
* 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
* but additional zero bits won't affect the result.
*/
static int32 bit_cmp(VarBit* arg1, VarBit* arg2, int leadingZeroLen1, int leadingZeroLen2)
{
#ifdef DOLPHIN
leadingZeroLen1 = (leadingZeroLen1 == -1 ? GetLeadingZeroLen(arg1) : leadingZeroLen1);
leadingZeroLen2 = (leadingZeroLen2 == -1 ? GetLeadingZeroLen(arg2) : leadingZeroLen2);
VarBit* newArg1 = arg1;
VarBit* newArg2 = arg2;
if (leadingZeroLen1 > 0) {
newArg1 = DatumGetVarBitP(
DirectFunctionCall3(bitshiftleft, VarBitPGetDatum(arg1),
Int32GetDatum(leadingZeroLen1), BoolGetDatum(false)));
}
if (leadingZeroLen2 > 0) {
newArg2 = DatumGetVarBitP(
DirectFunctionCall3(bitshiftleft, VarBitPGetDatum(arg2),
Int32GetDatum(leadingZeroLen2), BoolGetDatum(false)));
}
int bytelen1 = VARBITBYTES(newArg1);
int bytelen2 = VARBITBYTES(newArg2);
int cmp = memcmp(VARBITS(newArg1), VARBITS(newArg2), Min(bytelen1, bytelen2));
* cmp == 0 doesn't mean they are equal, for example b'1' for bit(1) and b'10' for bit(2).
* we should check bitlen to get the final result.
* */
if (cmp == 0) {
int bitlen1 = VARBITLEN(newArg1) - leadingZeroLen1;
int bitlen2 = VARBITLEN(newArg2) - leadingZeroLen2;
if (bitlen1 != bitlen2) {
cmp = (bitlen1 < bitlen2) ? -1 : 1;
}
}
if (newArg1 != arg1) {
pfree(newArg1);
}
if (newArg2 != arg2) {
pfree(newArg2);
}
#else
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;
}
#endif
return cmp;
}
Datum biteq(PG_FUNCTION_ARGS)
{
VarBit* arg1 = PG_GETARG_VARBIT_P(0);
VarBit* arg2 = PG_GETARG_VARBIT_P(1);
bool result = false;
int bitlen1, bitlen2;
int leadingZeroLen1 = GetLeadingZeroLen(arg1);
int leadingZeroLen2 = GetLeadingZeroLen(arg2);
bitlen1 = VARBITLEN(arg1) - leadingZeroLen1;
bitlen2 = VARBITLEN(arg2) - leadingZeroLen2;
if (bitlen1 != bitlen2)
result = false;
else
result = (bit_cmp(arg1, arg2, leadingZeroLen1, leadingZeroLen2) == 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 = false;
int bitlen1, bitlen2;
int leadingZeroLen1 = GetLeadingZeroLen(arg1);
int leadingZeroLen2 = GetLeadingZeroLen(arg2);
bitlen1 = VARBITLEN(arg1) - leadingZeroLen1;
bitlen2 = VARBITLEN(arg2) - leadingZeroLen2;
if (bitlen1 != bitlen2)
result = true;
else
result = (bit_cmp(arg1, arg2, leadingZeroLen1, leadingZeroLen2) != 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 = false;
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 = false;
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 = false;
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 = false;
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 = NULL;
int bitlen1, bitlen2, bytelen, bit1pad, bit2shift;
bits8 *pr = NULL, *pa = NULL;
errno_t ss_rc = 0;
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;
if (VARBITBYTES(arg1) > 0) {
ss_rc = memcpy_s(VARBITS(result), VARBITBYTES(arg1), VARBITS(arg1), VARBITBYTES(arg1));
securec_check(ss_rc, "\0", "\0");
}
bit1pad = VARBITPAD(arg1);
if (bit1pad == 0) {
if (VARBITBYTES(arg2) > 0) {
ss_rc = memcpy_s(VARBITS(result) + VARBITBYTES(arg1), VARBITBYTES(arg2), VARBITS(arg2), VARBITBYTES(arg2));
securec_check(ss_rc, "\0", "\0");
}
} else if (bitlen2 > 0) {
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;
}
}
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 = NULL;
int bitlen, rbitlen, len, ipad = 0, ishift, i;
int e, s1, e1;
bits8 mask, *r = NULL, *ps = NULL;
errno_t ss_rc = 0;
bitlen = VARBITLEN(arg);
s1 = Max(s, 1);
if (length_not_specified) {
e1 = bitlen + 1;
} else if (l < 0) {
ereport(ERROR,
(errcode(ERRCODE_SUBSTRING_ERROR),
errmsg("negative substring length not allowed")));
e1 = -1;
} else if (pg_add_s32_overflow(s, l, &e)) {
* L could be large enough for S + L to overflow, in which case the
* substring must run to end of string.
*/
e1 = bitlen + 1;
} else {
e1 = Min(e, bitlen + 1);
}
if (s1 > bitlen || e1 <= s1) {
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;
if ((s1 - 1) % BITS_PER_BYTE == 0) {
if (len > 0) {
ss_rc = memcpy_s(VARBITS(result), len, VARBITS(arg) + (s1 - 1) / BITS_PER_BYTE, len);
securec_check(ss_rc, "\0", "\0");
}
} else {
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++;
}
}
ipad = VARBITPAD(result);
if (ipad > 0) {
mask = BITMASK << ipad;
*(VARBITS(result) + len - 1) &= mask;
}
}
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);
int sp = PG_GETARG_INT32(2);
int sl = PG_GETARG_INT32(3);
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);
int sp = PG_GETARG_INT32(2);
int sl;
sl = VARBITLEN(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 = NULL;
VarBit* s1 = NULL;
VarBit* s2 = NULL;
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;
}
* bitlength, bitoctetlength
* Return the length of a bit string
*/
Datum bitlength(PG_FUNCTION_ARGS)
{
VarBit* arg = PG_GETARG_VARBIT_P(0);
#ifdef DOLPHIN
PG_RETURN_INT32(VARBITBYTES(arg));
#else
PG_RETURN_INT32(VARBITLEN(arg));
#endif
}
Datum bitoctetlength(PG_FUNCTION_ARGS)
{
VarBit* arg = PG_GETARG_VARBIT_P(0);
PG_RETURN_INT32(VARBITBYTES(arg));
}
Datum c_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 = NULL;
int len, bitlen1, bitlen2, i;
bits8 *p1 = NULL, *p2 = NULL, *r = NULL;
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; (unsigned int)(i) < VARBITBYTES(arg1); i++)
*r++ = *p1++ & *p2++;
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 = NULL;
int len, bitlen1, bitlen2, i;
bits8 *p1 = NULL, *p2 = NULL, *r = NULL;
bits8 mask;
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; (unsigned int)(i) < VARBITBYTES(arg1); i++)
*r++ = *p1++ | *p2++;
mask = BITMASK << VARBITPAD(result);
if (mask) {
r--;
*r &= mask;
}
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 = NULL;
int len, bitlen1, bitlen2, i;
bits8 *p1 = NULL, *p2 = NULL, *r = NULL;
bits8 mask;
bitlen1 = VARBITLEN(arg1);
bitlen2 = VARBITLEN(arg2);
if (bitlen1 != bitlen2) {
#ifdef DOLPHIN
if (bitlen1 > bitlen2) {
arg2 = DatumGetVarBitP(DirectFunctionCall2Coll(bit, InvalidOid, VarBitPGetDatum(arg2), Int32GetDatum(bitlen1)));
} else {
arg1 = DatumGetVarBitP(DirectFunctionCall2Coll(bit, InvalidOid, VarBitPGetDatum(arg1), Int32GetDatum(bitlen2)));
}
#else
ereport(
ERROR, (errcode(ERRCODE_STRING_DATA_LENGTH_MISMATCH), errmsg("cannot XOR bit strings of different sizes")));
#endif
}
len = VARSIZE(arg1);
result = (VarBit*)palloc(len);
SET_VARSIZE(result, len);
VARBITLEN(result) = VARBITLEN(arg1);
p1 = VARBITS(arg1);
p2 = VARBITS(arg2);
r = VARBITS(result);
for (i = 0; (unsigned int)(i) < VARBITBYTES(arg1); i++)
*r++ = *p1++ ^ *p2++;
mask = BITMASK << VARBITPAD(result);
if (mask) {
r--;
*r &= mask;
}
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 = NULL;
bits8 *p = NULL, *r = NULL;
bits8 mask;
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;
mask = BITMASK << VARBITPAD(result);
if (mask) {
r--;
*r &= mask;
}
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);
#ifdef DOLPHIN
bool shft_more = PG_GETARG_BOOL(2);
#endif
VarBit* result = NULL;
int byte_shift, ishift, len;
bits8 *p = NULL, *r = NULL;
errno_t ss_rc = 0;
if (shft < 0) {
if (shft < -VARBITMAXLEN)
shft = -VARBITMAXLEN;
#ifdef DOLPHIN
PG_RETURN_DATUM(DirectFunctionCall3(bitshiftright, VarBitPGetDatum(arg),
Int32GetDatum(-shft), BoolGetDatum(shft_more)));
#else
PG_RETURN_DATUM(DirectFunctionCall2(bitshiftright, VarBitPGetDatum(arg), Int32GetDatum(-shft)));
#endif
}
result = (VarBit*)palloc(VARSIZE(arg));
SET_VARSIZE(result, VARSIZE(arg));
VARBITLEN(result) = VARBITLEN(arg);
r = VARBITS(result);
if (shft >= VARBITLEN(arg)) {
ss_rc = memset_s(r, VARBITBYTES(arg), 0, VARBITBYTES(arg));
securec_check(ss_rc, "\0", "\0");
PG_RETURN_VARBIT_P(result);
}
byte_shift = shft / BITS_PER_BYTE;
ishift = shft % BITS_PER_BYTE;
p = VARBITS(arg) + byte_shift;
if (ishift == 0) {
len = VARBITBYTES(arg) - byte_shift;
if (len > 0) {
ss_rc = memcpy_s(r, len, p, len);
securec_check(ss_rc, "\0", "\0");
}
ss_rc = memset_s(r + len, byte_shift, 0, byte_shift);
securec_check(ss_rc, "\0", "\0");
} 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;
}
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);
#ifdef DOLPHIN
bool shft_more = PG_GETARG_BOOL(2);
#endif
VarBit* result = NULL;
int byte_shift, ishift, len;
bits8 *p = NULL, *r = NULL;
errno_t ss_rc = 0;
if (shft < 0) {
if (shft < -VARBITMAXLEN)
shft = -VARBITMAXLEN;
#ifdef DOLPHIN
PG_RETURN_DATUM(DirectFunctionCall3(bitshiftleft, VarBitPGetDatum(arg),
Int32GetDatum(-shft), BoolGetDatum(false)));
#else
PG_RETURN_DATUM(DirectFunctionCall2(bitshiftleft, VarBitPGetDatum(arg), Int32GetDatum(-shft)));
#endif
}
result = (VarBit*)palloc(VARSIZE(arg));
SET_VARSIZE(result, VARSIZE(arg));
VARBITLEN(result) = VARBITLEN(arg);
r = VARBITS(result);
#ifdef DOLPHIN
if (shft >= VARBITLEN(arg) && !shft_more) {
#else
if (shft >= VARBITLEN(arg)) {
#endif
ss_rc = memset_s(r, VARBITBYTES(arg), 0, VARBITBYTES(arg));
securec_check(ss_rc, "\0", "\0");
PG_RETURN_VARBIT_P(result);
}
byte_shift = shft / BITS_PER_BYTE;
ishift = shft % BITS_PER_BYTE;
p = VARBITS(arg);
ss_rc = memset_s(r, byte_shift, 0, byte_shift);
securec_check(ss_rc, "\0", "\0");
r += byte_shift;
if (ishift == 0) {
len = VARBITBYTES(arg) - byte_shift;
if (len > 0) {
ss_rc = memcpy_s(r, len, p, len);
securec_check(ss_rc, "\0", "\0");
}
} else {
if (r < VARBITEND(result))
*r = 0;
for (; r < VARBITEND(result); p++) {
*r |= *p >> ishift;
if ((++r) < VARBITEND(result))
*r = (*p << (BITS_PER_BYTE - ishift)) & BITMASK;
}
}
PG_RETURN_VARBIT_P(result);
}
#ifdef DOLPHIN
Datum bittotinyint(VarBit* arg, bool isUnsigned)
{
uint8 result;
bits8* r = NULL;
int errlevel = SQL_MODE_STRICT() ? ERROR : WARNING;
if (ENABLE_B_CMPT_MODE) {
result = isUnsigned ? (uint8)DirectFunctionCall1(ui8toui1, Int64GetDatum(bittobigint(arg, true))) :
(uint8)DirectFunctionCall1(ui8toi1, Int64GetDatum(bittobigint(arg, true)));
PG_RETURN_INT8(result);
}
if ((uint32)VARBITLEN(arg) - GetLeadingZeroLen(arg) > sizeof(result) * BITS_PER_BYTE) {
if (isUnsigned) {
ereport(errlevel, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("tinyint unsigned out of range")));
PG_RETURN_UINT8(PG_UINT8_MAX);
} else {
ereport(errlevel, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("tinyint out of range")));
PG_RETURN_UINT8(PG_INT8_MAX);
}
}
result = 0;
for (r = VARBITS(arg); r < VARBITEND(arg); r++) {
result <<= BITS_PER_BYTE;
result |= *r;
}
result >>= VARBITPAD(arg);
if (isUnsigned)
PG_RETURN_UINT8(result);
PG_RETURN_INT8(result);
}
Datum bittosmallint(VarBit* arg, bool isUnsigned)
{
uint16 result;
bits8* r = NULL;
int errlevel = SQL_MODE_STRICT() ? ERROR : WARNING;
if (ENABLE_B_CMPT_MODE) {
result = isUnsigned ? (uint16)DirectFunctionCall1(ui8toui2, Int64GetDatum(bittobigint(arg, true))) :
(uint16)DirectFunctionCall1(ui8toi2, Int64GetDatum(bittobigint(arg, true)));
PG_RETURN_INT16(result);
}
if ((uint32)VARBITLEN(arg) - GetLeadingZeroLen(arg) > sizeof(result) * BITS_PER_BYTE) {
if (isUnsigned) {
ereport(errlevel, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("smallint unsigned out of range")));
PG_RETURN_UINT16(PG_UINT16_MAX);
} else {
ereport(errlevel, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("smallint out of range")));
PG_RETURN_UINT16(PG_INT16_MAX);
}
}
result = 0;
for (r = VARBITS(arg); r < VARBITEND(arg); r++) {
result <<= BITS_PER_BYTE;
result |= *r;
}
result >>= VARBITPAD(arg);
if (isUnsigned)
PG_RETURN_UINT16(result);
PG_RETURN_INT16(result);
}
Datum bittoint(VarBit* arg, bool isUnsigned)
{
uint32 result;
bits8* r = NULL;
int errlevel = SQL_MODE_STRICT() ? ERROR : WARNING;
if (ENABLE_B_CMPT_MODE) {
result = isUnsigned ? (uint32)DirectFunctionCall1(ui8toui4, Int64GetDatum(bittobigint(arg, true))) :
(uint32)DirectFunctionCall1(ui8toi4, Int64GetDatum(bittobigint(arg, true)));
PG_RETURN_INT32(result);
}
if ((uint32)VARBITLEN(arg) - GetLeadingZeroLen(arg) > sizeof(result) * BITS_PER_BYTE) {
if (isUnsigned) {
ereport(errlevel, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("integer unsigned out of range")));
PG_RETURN_UINT32(PG_UINT32_MAX);
} else {
ereport(errlevel, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("integer out of range")));
PG_RETURN_UINT32(PG_INT32_MAX);
}
}
result = 0;
for (r = VARBITS(arg); r < VARBITEND(arg); r++) {
result <<= BITS_PER_BYTE;
result |= *r;
}
result >>= VARBITPAD(arg);
if (isUnsigned)
PG_RETURN_UINT32(result);
PG_RETURN_INT32(result);
}
Datum bittobigint(VarBit* arg, bool isUnsigned, bool canIgnore)
{
uint64 result;
bits8* r = NULL;
int errlevel = !canIgnore && SQL_MODE_STRICT() ? ERROR : WARNING;
if ((uint32)VARBITLEN(arg) - GetLeadingZeroLen(arg) > sizeof(result) * BITS_PER_BYTE) {
if (isUnsigned) {
ereport(errlevel, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("bigint unsigned out of range")));
PG_RETURN_UINT64(PG_UINT64_MAX);
} else {
ereport(errlevel, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("bigint out of range")));
PG_RETURN_INT64(PG_INT64_MAX);
}
}
result = 0;
for (r = VARBITS(arg); r < VARBITEND(arg); r++) {
result <<= BITS_PER_BYTE;
result |= *r;
}
result >>= VARBITPAD(arg);
if (isUnsigned)
PG_RETURN_UINT64(result);
PG_RETURN_INT64(result);
}
Datum bitfromtinyint(int16 a, int32 typmod)
{
VarBit* result = NULL;
bits8* r = NULL;
int rlen;
int destbitsleft, srcbitsleft;
if (typmod <= 0 || typmod > VARBITMAXLEN)
typmod = 1;
if (typmod < M_BIT_LEN && ENABLE_B_CMPT_MODE) {
return DirectFunctionCall2(bit, bitfromtinyint(a, M_BIT_LEN), Int32GetDatum(typmod));
}
rlen = VARBITTOTALLEN(typmod);
result = (VarBit*)palloc(rlen);
SET_VARSIZE(result, rlen);
VARBITLEN(result) = typmod;
r = VARBITS(result);
destbitsleft = typmod;
srcbitsleft = BYTE_SIZE;
srcbitsleft = Min(srcbitsleft, destbitsleft);
while (destbitsleft >= srcbitsleft + 8) {
*r++ = (bits8)((a < 0) ? BITMASK : 0);
destbitsleft -= 8;
}
if (destbitsleft > srcbitsleft) {
int val = (int)(a >> (destbitsleft - 8));
if (a < 0)
val |= (-1) << (srcbitsleft + 8 - destbitsleft);
*r++ = (bits8)(val & BITMASK);
destbitsleft -= 8;
}
while (destbitsleft >= 8) {
*r++ = (bits8)((a >> (destbitsleft - 8)) & BITMASK);
destbitsleft -= 8;
}
if (destbitsleft > 0)
*r = (bits8)((a << (8 - destbitsleft)) & BITMASK);
PG_RETURN_VARBIT_P(result);
}
Datum bitfromsmallint(int32 a, int32 typmod)
{
VarBit* result = NULL;
bits8* r = NULL;
int rlen;
int destbitsleft, srcbitsleft;
if (typmod <= 0 || typmod > VARBITMAXLEN)
typmod = 1;
if (typmod < M_BIT_LEN && ENABLE_B_CMPT_MODE) {
return DirectFunctionCall2(bit, bitfromsmallint(a, M_BIT_LEN), Int32GetDatum(typmod));
}
rlen = VARBITTOTALLEN(typmod);
result = (VarBit*)palloc(rlen);
SET_VARSIZE(result, rlen);
VARBITLEN(result) = typmod;
r = VARBITS(result);
destbitsleft = typmod;
srcbitsleft = SMALL_SIZE;
srcbitsleft = Min(srcbitsleft, destbitsleft);
while (destbitsleft >= srcbitsleft + 8) {
*r++ = (bits8)((a < 0) ? BITMASK : 0);
destbitsleft -= 8;
}
if (destbitsleft > srcbitsleft) {
int val = (int)(a >> (destbitsleft - 8));
if (a < 0)
val |= (-1) << (srcbitsleft + 8 - destbitsleft);
*r++ = (bits8)(val & BITMASK);
destbitsleft -= 8;
}
while (destbitsleft >= 8) {
*r++ = (bits8)((a >> (destbitsleft - 8)) & BITMASK);
destbitsleft -= 8;
}
if (destbitsleft > 0)
*r = (bits8)((a << (8 - destbitsleft)) & BITMASK);
PG_RETURN_VARBIT_P(result);
}
Datum bitfromint(int64 a, int32 typmod)
{
VarBit* result = NULL;
bits8* r = NULL;
int rlen;
int destbitsleft, srcbitsleft;
if (typmod <= 0 || typmod > VARBITMAXLEN)
typmod = 1;
if (typmod < M_BIT_LEN && ENABLE_B_CMPT_MODE) {
return DirectFunctionCall2(bit, bitfromint(a, M_BIT_LEN), Int32GetDatum(typmod));
}
rlen = VARBITTOTALLEN(typmod);
result = (VarBit*)palloc(rlen);
SET_VARSIZE(result, rlen);
VARBITLEN(result) = typmod;
r = VARBITS(result);
destbitsleft = typmod;
srcbitsleft = 32;
srcbitsleft = Min(srcbitsleft, destbitsleft);
while (destbitsleft >= srcbitsleft + 8) {
*r++ = (bits8)((a < 0) ? BITMASK : 0);
destbitsleft -= 8;
}
if (destbitsleft > srcbitsleft) {
int val = (int)(a >> (destbitsleft - 8));
if (a < 0)
val |= (-1) << (srcbitsleft + 8 - destbitsleft);
*r++ = (bits8)(val & BITMASK);
destbitsleft -= 8;
}
while (destbitsleft >= 8) {
*r++ = (bits8)((a >> (destbitsleft - 8)) & BITMASK);
destbitsleft -= 8;
}
if (destbitsleft > 0)
*r = (bits8)((a << (8 - destbitsleft)) & BITMASK);
PG_RETURN_VARBIT_P(result);
}
Datum bitfrombigint(int128 a, int32 typmod, bool canIgnore = false)
{
VarBit* result = NULL;
bits8* r = NULL;
int rlen;
int destbitsleft, srcbitsleft;
if (typmod <= 0 || typmod > VARBITMAXLEN)
typmod = 1;
if (typmod < M_BIT_LEN && ENABLE_B_CMPT_MODE) {
return DirectFunctionCall2Coll(bit, InvalidOid, bitfrombigint(a, M_BIT_LEN, canIgnore),
Int32GetDatum(typmod), canIgnore);
}
rlen = VARBITTOTALLEN(typmod);
result = (VarBit*)palloc(rlen);
SET_VARSIZE(result, rlen);
VARBITLEN(result) = typmod;
r = VARBITS(result);
destbitsleft = typmod;
srcbitsleft = 64;
srcbitsleft = Min(srcbitsleft, destbitsleft);
while (destbitsleft >= srcbitsleft + 8) {
*r++ = (bits8)((a < 0) ? BITMASK : 0);
destbitsleft -= 8;
}
if (destbitsleft > srcbitsleft) {
int val = (int)(a >> (destbitsleft - 8));
if (a < 0)
val |= (-1) << (srcbitsleft + 8 - destbitsleft);
*r++ = (bits8)(val & BITMASK);
destbitsleft -= 8;
}
while (destbitsleft >= 8) {
*r++ = (bits8)((a >> (destbitsleft - 8)) & BITMASK);
destbitsleft -= 8;
}
if (destbitsleft > 0)
*r = (bits8)((a << (8 - destbitsleft)) & BITMASK);
PG_RETURN_VARBIT_P(result);
}
PG_FUNCTION_INFO_V1_PUBLIC(bitfromint1);
PG_FUNCTION_INFO_V1_PUBLIC(bittoint1);
PG_FUNCTION_INFO_V1_PUBLIC(bitfromint2);
PG_FUNCTION_INFO_V1_PUBLIC(bittoint2);
PG_FUNCTION_INFO_V1_PUBLIC(bitfromuint1);
PG_FUNCTION_INFO_V1_PUBLIC(bittouint1);
PG_FUNCTION_INFO_V1_PUBLIC(bitfromuint2);
PG_FUNCTION_INFO_V1_PUBLIC(bittouint2);
PG_FUNCTION_INFO_V1_PUBLIC(bitfromuint4);
PG_FUNCTION_INFO_V1_PUBLIC(bittouint4);
PG_FUNCTION_INFO_V1_PUBLIC(bitfromuint8);
PG_FUNCTION_INFO_V1_PUBLIC(bittouint8);
PG_FUNCTION_INFO_V1_PUBLIC(bitfromnumeric);
PG_FUNCTION_INFO_V1_PUBLIC(bitfromfloat4);
PG_FUNCTION_INFO_V1_PUBLIC(bitfromfloat8);
PG_FUNCTION_INFO_V1_PUBLIC(bitfromdate);
PG_FUNCTION_INFO_V1_PUBLIC(bitfromdatetime);
PG_FUNCTION_INFO_V1_PUBLIC(bitfromtimestamp);
PG_FUNCTION_INFO_V1_PUBLIC(bitfromtime);
PG_FUNCTION_INFO_V1_PUBLIC(bitfromyear);
extern "C" DLL_PUBLIC Datum bitfromint1(PG_FUNCTION_ARGS);
extern "C" DLL_PUBLIC Datum bittoint1(PG_FUNCTION_ARGS);
extern "C" DLL_PUBLIC Datum bitfromint2(PG_FUNCTION_ARGS);
extern "C" DLL_PUBLIC Datum bittoint2(PG_FUNCTION_ARGS);
extern "C" DLL_PUBLIC Datum bitfromuint1(PG_FUNCTION_ARGS);
extern "C" DLL_PUBLIC Datum bittouint1(PG_FUNCTION_ARGS);
extern "C" DLL_PUBLIC Datum bitfromuint2(PG_FUNCTION_ARGS);
extern "C" DLL_PUBLIC Datum bittouint2(PG_FUNCTION_ARGS);
extern "C" DLL_PUBLIC Datum bitfromuint4(PG_FUNCTION_ARGS);
extern "C" DLL_PUBLIC Datum bittouint4(PG_FUNCTION_ARGS);
extern "C" DLL_PUBLIC Datum bitfromuint8(PG_FUNCTION_ARGS);
extern "C" DLL_PUBLIC Datum bittouint8(PG_FUNCTION_ARGS);
extern "C" DLL_PUBLIC Datum bitfromnumeric(PG_FUNCTION_ARGS);
extern "C" DLL_PUBLIC Datum bitfromfloat4(PG_FUNCTION_ARGS);
extern "C" DLL_PUBLIC Datum bitfromfloat8(PG_FUNCTION_ARGS);
extern "C" DLL_PUBLIC Datum bitfromdate(PG_FUNCTION_ARGS);
extern "C" DLL_PUBLIC Datum bitfromdatetime(PG_FUNCTION_ARGS);
extern "C" DLL_PUBLIC Datum bitfromtimestamp(PG_FUNCTION_ARGS);
extern "C" DLL_PUBLIC Datum bitfromtime(PG_FUNCTION_ARGS);
extern "C" DLL_PUBLIC Datum bitfromyear(PG_FUNCTION_ARGS);
Datum bitfromuint1(PG_FUNCTION_ARGS)
{
uint8 a = PG_GETARG_UINT8(0);
int32 typmod = PG_GETARG_INT32(1);
return bitfromtinyint(a, typmod);
}
Datum bittouint1(PG_FUNCTION_ARGS)
{
VarBit* arg = PG_GETARG_VARBIT_P(0);
return bittotinyint(arg, true);
}
Datum bitfromuint2(PG_FUNCTION_ARGS)
{
uint16 a = PG_GETARG_UINT16(0);
int32 typmod = PG_GETARG_INT32(1);
return bitfromsmallint(a, typmod);
}
Datum bittouint2(PG_FUNCTION_ARGS)
{
VarBit* arg = PG_GETARG_VARBIT_P(0);
return bittosmallint(arg, true);
}
Datum bitfromuint4(PG_FUNCTION_ARGS)
{
uint32 a = PG_GETARG_UINT32(0);
int32 typmod = PG_GETARG_INT32(1);
return bitfromint(a, typmod);
}
Datum bittouint4(PG_FUNCTION_ARGS)
{
VarBit* arg = PG_GETARG_VARBIT_P(0);
return bittoint(arg, true);
}
Datum bitfromuint8(PG_FUNCTION_ARGS)
{
uint64 a = PG_GETARG_UINT64(0);
int32 typmod = PG_GETARG_INT32(1);
return bitfrombigint(a, typmod, fcinfo->can_ignore);
}
Datum bittouint8(PG_FUNCTION_ARGS)
{
VarBit* arg = PG_GETARG_VARBIT_P(0);
return bittobigint(arg, true);
}
Datum bitfromint1(PG_FUNCTION_ARGS)
{
int8 a = PG_GETARG_INT32(0);
int32 typmod = PG_GETARG_INT32(1);
return bitfromtinyint(a, typmod);
}
Datum bittoint1(PG_FUNCTION_ARGS)
{
VarBit* arg = PG_GETARG_VARBIT_P(0);
return bittotinyint(arg, false);
}
Datum bitfromint2(PG_FUNCTION_ARGS)
{
int16 a = PG_GETARG_INT32(0);
int32 typmod = PG_GETARG_INT32(1);
return bitfromsmallint(a, typmod);
}
Datum bittoint2(PG_FUNCTION_ARGS)
{
VarBit* arg = PG_GETARG_VARBIT_P(0);
return bittosmallint(arg, false);
}
Datum bitfromnumeric(PG_FUNCTION_ARGS)
{
Numeric num = PG_GETARG_NUMERIC(0);
int32 typmod = PG_GETARG_INT32(1);
int64 a = (int64)DirectFunctionCall1(numeric_int8, NumericGetDatum(num));
return bitfrombigint(a, typmod);
}
Datum bitfromfloat4(PG_FUNCTION_ARGS)
{
float4 num = PG_GETARG_FLOAT4(0);
int32 typmod = PG_GETARG_INT32(1);
int64 a = (int64)DirectFunctionCall1(ftoi8, Float4GetDatum(num));
return bitfrombigint(a, typmod);
}
Datum bitfromfloat8(PG_FUNCTION_ARGS)
{
float8 num = PG_GETARG_FLOAT8(0);
int32 typmod = PG_GETARG_INT32(1);
int64 a = (int64)DirectFunctionCall1(dtoi8, Float8GetDatum(num));
return bitfrombigint(a, typmod);
}
Datum bitfromdate(PG_FUNCTION_ARGS)
{
int64 a = (int64)DirectFunctionCall1(date_int8, PG_GETARG_DATEADT(0));
int32 typmod = PG_GETARG_INT32(1);
return bitfrombigint(a, typmod);
}
Datum bitfromdatetime(PG_FUNCTION_ARGS)
{
Datum a = DirectFunctionCall1(datetime_float, PG_GETARG_TIMESTAMP(0));
return DirectFunctionCall2(bitfromfloat8, a, PG_GETARG_INT32(1));
}
Datum bitfromtimestamp(PG_FUNCTION_ARGS)
{
int64 a = (int64)DirectFunctionCall1(timestamptz_int8, PG_GETARG_TIMESTAMPTZ(0));
int32 typmod = PG_GETARG_INT32(1);
return bitfrombigint(a, typmod);
}
Datum bitfromtime(PG_FUNCTION_ARGS)
{
int64 a = (int64)DirectFunctionCall1(time_int8, PG_GETARG_TIMEADT(0));
int32 typmod = PG_GETARG_INT32(1);
return bitfrombigint(a, typmod);
}
Datum bitfromyear(PG_FUNCTION_ARGS)
{
int32 a = (int32)DirectFunctionCall1(year_integer, PG_GETARG_YEARADT(0));
int32 typmod = PG_GETARG_INT32(1);
return bitfromint(a, typmod);
}
#endif
* 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);
#ifdef DOLPHIN
return bitfromint(a, typmod);
#else
VarBit* result = NULL;
bits8* r = NULL;
int rlen;
int destbitsleft, srcbitsleft;
if (typmod <= 0 || typmod > VARBITMAXLEN)
typmod = 1;
rlen = VARBITTOTALLEN(typmod);
result = (VarBit*)palloc(rlen);
SET_VARSIZE(result, rlen);
VARBITLEN(result) = typmod;
r = VARBITS(result);
destbitsleft = typmod;
srcbitsleft = 32;
srcbitsleft = Min(srcbitsleft, destbitsleft);
while (destbitsleft >= srcbitsleft + 8) {
*r++ = (bits8)((a < 0) ? BITMASK : 0);
destbitsleft -= 8;
}
if (destbitsleft > srcbitsleft) {
int val = (int)(a >> (destbitsleft - 8));
if (a < 0)
val |= (-1) << (srcbitsleft + 8 - destbitsleft);
*r++ = (bits8)(val & BITMASK);
destbitsleft -= 8;
}
while (destbitsleft >= 8) {
*r++ = (bits8)((a >> (destbitsleft - 8)) & BITMASK);
destbitsleft -= 8;
}
if (destbitsleft > 0)
*r = (bits8)((a << (8 - destbitsleft)) & BITMASK);
PG_RETURN_VARBIT_P(result);
#endif
}
Datum bittoint4(PG_FUNCTION_ARGS)
{
VarBit* arg = PG_GETARG_VARBIT_P(0);
#ifdef DOLPHIN
return bittoint(arg, false);
#else
uint32 result;
bits8* r = NULL;
if ((uint32)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;
}
result >>= VARBITPAD(arg);
PG_RETURN_INT32(result);
#endif
}
Datum bitfromint8(PG_FUNCTION_ARGS)
{
int64 a = PG_GETARG_INT64(0);
int32 typmod = PG_GETARG_INT32(1);
#ifdef DOLPHIN
return bitfrombigint(a, typmod);
#else
VarBit* result = NULL;
bits8* r = NULL;
int rlen;
int destbitsleft, srcbitsleft;
if (typmod <= 0 || typmod > VARBITMAXLEN)
typmod = 1;
rlen = VARBITTOTALLEN(typmod);
result = (VarBit*)palloc(rlen);
SET_VARSIZE(result, rlen);
VARBITLEN(result) = typmod;
r = VARBITS(result);
destbitsleft = typmod;
srcbitsleft = 64;
srcbitsleft = Min(srcbitsleft, destbitsleft);
while (destbitsleft >= srcbitsleft + 8) {
*r++ = (bits8)((a < 0) ? BITMASK : 0);
destbitsleft -= 8;
}
if (destbitsleft > srcbitsleft) {
int val = (int)(a >> (destbitsleft - 8));
if (a < 0)
val |= (-1) << (srcbitsleft + 8 - destbitsleft);
*r++ = (bits8)(val & BITMASK);
destbitsleft -= 8;
}
while (destbitsleft >= 8) {
*r++ = (bits8)((a >> (destbitsleft - 8)) & BITMASK);
destbitsleft -= 8;
}
if (destbitsleft > 0)
*r = (bits8)((a << (8 - destbitsleft)) & BITMASK);
PG_RETURN_VARBIT_P(result);
#endif
}
Datum bittoint8(PG_FUNCTION_ARGS)
{
VarBit* arg = PG_GETARG_VARBIT_P(0);
#ifdef DOLPHIN
return bittobigint(arg, false);
#else
uint64 result;
bits8* r = NULL;
if ((uint32)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;
}
result >>= VARBITPAD(arg);
PG_RETURN_INT64(result);
#endif
}
* 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)
{
#ifdef DOLPHIN
return dolphin_bitposition(fcinfo);
#else
VarBit* str = PG_GETARG_VARBIT_P(0);
VarBit* substr = PG_GETARG_VARBIT_P(1);
int substr_length, str_length, i, is;
bits8 *s = NULL,
*p = NULL;
bits8 cmp,
mask1,
mask2,
end_mask,
str_mask;
bool is_match = false;
substr_length = VARBITLEN(substr);
str_length = VARBITLEN(str);
if ((str_length == 0) || (substr_length > str_length))
PG_RETURN_INT32(0);
if (substr_length == 0)
PG_RETURN_INT32(1);
end_mask = BITMASK << VARBITPAD(substr);
str_mask = BITMASK << VARBITPAD(str);
if (VARBITBYTES(str) < VARBITBYTES(substr)) {
PG_RETURN_INT32(0);
}
for (i = 0; (unsigned int)(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) {
if (mask1 & ~str_mask) {
is_match = false;
break;
}
mask1 &= str_mask;
}
}
is_match = ((cmp ^ *p) & mask1) == 0;
if (!is_match)
break;
p++;
if (p == VARBITEND(str)) {
mask2 = end_mask << (BITS_PER_BYTE - is);
is_match = mask2 == 0;
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;
}
if (is_match)
PG_RETURN_INT32(i * BITS_PER_BYTE + is + 1);
}
}
PG_RETURN_INT32(0);
#endif
}
* 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 = NULL;
int len, bitlen;
bits8 *r = NULL, *p = NULL;
int byteNo, bitNo;
errno_t ss_rc = 0;
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);
if (VARBITBYTES(arg1) > 0) {
ss_rc = memcpy_s(r, VARBITBYTES(arg1), p, VARBITBYTES(arg1));
securec_check(ss_rc, "\0", "\0");
}
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 = NULL;
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);
}
Datum mp_bit_length_bit(PG_FUNCTION_ARGS)
{
VarBit* arg = PG_GETARG_VARBIT_P(0);
PG_RETURN_INT32(VARBITBYTES(arg) * 8);
}
Datum mp_bit_length_text(PG_FUNCTION_ARGS)
{
Datum str = PG_GETARG_DATUM(0);
PG_RETURN_INT32((toast_raw_datum_size(str) - VARHDRSZ) * 8);
}
Datum mp_bit_length_bytea(PG_FUNCTION_ARGS)
{
Datum str = PG_GETARG_DATUM(0);
PG_RETURN_INT32((toast_raw_datum_size(str) - VARHDRSZ) * 8);
}
#ifdef DOLPHIN
PG_FUNCTION_INFO_V1_PUBLIC(bit_bool);
extern "C" DLL_PUBLIC Datum bit_bool(PG_FUNCTION_ARGS);
Datum bit_bool(PG_FUNCTION_ARGS)
{
VarBit* arg1 = PG_GETARG_VARBIT_P(0);
bits8* p = NULL;
int bitlen, i;
bits8 t = 0;
bitlen = VARBITLEN(arg1);
p = VARBITS(arg1);
for(i=0; i < bitlen; i++) {
if(p[i/BITS_PER_BYTE] == t)
continue;
else
PG_RETURN_BOOL(true);
}
PG_RETURN_BOOL(false);
}
PG_FUNCTION_INFO_V1_PUBLIC(bitlike);
extern "C" DLL_PUBLIC Datum bitlike(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1_PUBLIC(bitnlike);
extern "C" DLL_PUBLIC Datum bitnlike(PG_FUNCTION_ARGS);
Datum bitlike(PG_FUNCTION_ARGS)
{
bool result = false;
result = DatumGetBool(biteq(fcinfo));
PG_RETURN_BOOL(result);
}
Datum bitnlike(PG_FUNCTION_ARGS)
{
bool result = false;
result = DatumGetBool(bitne(fcinfo));
PG_RETURN_BOOL(result);
}
Datum bittochar(VarBit* arg)
{
int lzero1 = VARBITLEN(arg) % BYTE_SIZE;
if (GetLeadingZeroLen(arg) < lzero1) {
lzero1 = lzero1 - BYTE_SIZE;
}
int lbytes = (GetLeadingZeroLen(arg) - lzero1) / BYTE_SIZE;
int lzero2 = lbytes * BYTE_SIZE;
int len = (VARBITLEN(arg) - lzero1 - lzero2) / BYTE_SIZE;
errno_t ss_rc = 0;
Datum cpy = DirectFunctionCall3(bitshiftleft, VarBitPGetDatum(arg),
Int32GetDatum(lzero1 + lzero2), BoolGetDatum(true));
char* data = (char*)palloc(len + 1);
if (len != 0) {
ss_rc = memcpy_s(data, len, VARBITS((VarBit*)cpy), len);
securec_check(ss_rc, "\0", "\0");
}
*(data + len) = '\0';
PG_RETURN_DATUM((Datum)data);
}
PG_FUNCTION_INFO_V1_PUBLIC(bittotext);
extern "C" DLL_PUBLIC Datum bittotext(PG_FUNCTION_ARGS);
Datum bittotext(PG_FUNCTION_ARGS)
{
Datum data = bittochar(PG_GETARG_VARBIT_P(0));
PG_RETURN_DATUM(DirectFunctionCall1(textin, data));
}
PG_FUNCTION_INFO_V1_PUBLIC(bittobpchar);
extern "C" DLL_PUBLIC Datum bittobpchar(PG_FUNCTION_ARGS);
Datum bittobpchar(PG_FUNCTION_ARGS)
{
Datum data = bittochar(PG_GETARG_VARBIT_P(0));
int32 typmod = PG_GETARG_INT32(1);
PG_RETURN_DATUM(DirectFunctionCall3(bpcharin, data, ObjectIdGetDatum(0), Int32GetDatum(typmod)));
}
PG_FUNCTION_INFO_V1_PUBLIC(bittovarchar);
extern "C" DLL_PUBLIC Datum bittovarchar(PG_FUNCTION_ARGS);
Datum bittovarchar(PG_FUNCTION_ARGS)
{
Datum data = bittochar(PG_GETARG_VARBIT_P(0));
int32 typmod = PG_GETARG_INT32(1);
PG_RETURN_DATUM(DirectFunctionCall3(varcharin, data, ObjectIdGetDatum(0), Int32GetDatum(typmod)));
}
PG_FUNCTION_INFO_V1_PUBLIC(bittobinary);
extern "C" DLL_PUBLIC Datum bittobinary(PG_FUNCTION_ARGS);
Datum bittobinary(PG_FUNCTION_ARGS)
{
Datum dec = bittobigint(PG_GETARG_VARBIT_P(0), true);
Datum str = DirectFunctionCall1(uint8out, dec);
PG_RETURN_DATUM(DirectFunctionCall1(dolphin_binaryin, str));
}
PG_FUNCTION_INFO_V1_PUBLIC(bittovarbinary);
extern "C" DLL_PUBLIC Datum bittovarbinary(PG_FUNCTION_ARGS);
Datum bittovarbinary(PG_FUNCTION_ARGS)
{
VarBit* bits = PG_GETARG_VARBIT_P(0);
int bytelen = VARBITBYTES(bits);
int charsperbyte = 2;
int bitcharlen = 4;
int strlen = bytelen * charsperbyte;
char* result = (char*)palloc(strlen + charsperbyte + 1);
char* str = result;
result[0] = '\\';
result[1] = 'x';
result[strlen + charsperbyte] = '\0';
result += charsperbyte;
do {
char s1 = char(bits->bit_dat[--bytelen] >> bitcharlen);
char s2 = char(bits->bit_dat[bytelen] & 0xf);
result[--strlen] = HEX_CHARS[s2];
result[--strlen] = HEX_CHARS[s1];
} while (bytelen > 0);
PG_RETURN_DATUM(DirectFunctionCall1(dolphin_binaryin, CStringGetDatum(str)));
}
Datum bit_bin_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);
bool can_ignore = fcinfo->can_ignore;
PG_RETURN_VARBIT_P(bit_in_internal(input_string, atttypmod, can_ignore));
}
PG_FUNCTION_INFO_V1_PUBLIC(bool_bit);
extern "C" DLL_PUBLIC Datum bool_bit(PG_FUNCTION_ARGS);
Datum bool_bit(PG_FUNCTION_ARGS)
{
int32 atttypmod = PG_GETARG_INT32(1);
if (PG_GETARG_BOOL(0) == false) {
return DirectFunctionCall2(bitfromint8, Int64GetDatum(0), Int32GetDatum(atttypmod));
} else {
return DirectFunctionCall2(bitfromint8, Int64GetDatum(1), Int32GetDatum(atttypmod));
}
}
PG_FUNCTION_INFO_V1_PUBLIC(dolphin_bitnot);
extern "C" DLL_PUBLIC Datum dolphin_bitnot(PG_FUNCTION_ARGS);
Datum dolphin_bitnot(PG_FUNCTION_ARGS)
{
VarBit* arg = PG_GETARG_VARBIT_P(0);
PG_RETURN_UINT64(~bittobigint(arg, true));
}
PG_FUNCTION_INFO_V1_PUBLIC(mp_bit_length_binary);
extern "C" DLL_PUBLIC Datum mp_bit_length_binary(PG_FUNCTION_ARGS);
Datum mp_bit_length_binary(PG_FUNCTION_ARGS)
{
Datum input = PG_GETARG_DATUM(0);
PG_RETURN_INT32((toast_raw_datum_size(input) - VARHDRSZ) * BITS_PER_BYTE);
}
static void cp_and_pad_left_zero(char *origin, int originLen, char *target, int targetLen)
{
char *op = origin, *tp =target;
int offset = targetLen - originLen;
int ret = memset_s(tp, targetLen, '0', offset);
securec_check_c(ret, "\0", "\0");
tp += offset;
for (int i = 0; i < originLen; i++) {
*tp++ = *op++;
}
}
static void binary_str_to_char(char *str, char *result, int len, bool is_escape_zero)
{
char *rp = result, *sp = str;
int zero = '0', s = 0, i, k;
for (i = 0; i < len; i++) {
s = 0;
for (k = BITS_PER_BYTE; k > 0; k--) {
int n = (int)(*sp++) - zero;
s = n == 0 ? s : s + (n << (k - 1));
}
if (is_escape_zero && s == 0) {
*rp++ = '\\';
*rp++ = '0';
*rp++ = '0';
*rp++ = '0';
} else {
*rp++ = (char) s;
}
}
}
* cast bit value to charater.
* - if the length of bit value is not a multiple of 8, pad left 0.
* - do not ignore '\0'
*/
char* bit_to_str(VarBit *bits, bool is_escape_zero)
{
char *result = NULL, *bitStr = NULL, *bitChars = NULL, *r = NULL;
bits8* sp = NULL;
bits8 x;
int i, k, len = VARBITLEN(bits), byteLen = VARBITBYTES(bits);
int zero_cnt = 0;
bitStr = (char*)palloc0(byteLen * BITS_PER_BYTE + 1);
bitChars = (char*)palloc0(len + 1);
sp = VARBITS(bits);
r = bitChars;
for (i = 0; i <= len - BITS_PER_BYTE; i += BITS_PER_BYTE, sp++) {
x = *sp;
for (k = 0; k < BITS_PER_BYTE; k++) {
*r++ = IS_HIGHBIT_SET(x) ? '1' : '0';
x <<= 1;
}
}
if (i < len) {
x = *sp;
for (k = i; k < len; k++) {
*r++ = IS_HIGHBIT_SET(x) ? '1' : '0';
x <<= 1;
}
}
cp_and_pad_left_zero(bitChars, len, bitStr, byteLen * BITS_PER_BYTE);
if (is_escape_zero) {
for (i = 0; i < byteLen; i++) {
r = bitStr + i * BITS_PER_BYTE;
if (memcmp(r, ZERO_BITS_PER_BYTE, ZERO_BITS_PER_BYTE_LENGTH) == 0) {
zero_cnt++;
}
}
result = (char*)palloc0(byteLen + ESCAPE_ZERO_SZIE * zero_cnt + 1);
} else {
result = (char*)palloc0(byteLen + 1);
}
binary_str_to_char(bitStr, result, byteLen, is_escape_zero);
pfree(bitChars);
pfree(bitStr);
return result;
}
* cast bit as char and substr.
* - first pad left 0 if bit length is not multi 8,
* - then substr like char, and don't ignore '\0'
* - start index from 1
* - length can't be negative
* - when start<0, amend the sartPosition to abs(start) from last char
*/
VarBit* bit_substr_with_byte_align(VarBit *bits, int start, int length, bool length_not_specified)
{
VarBit *result = NULL;
char *bitostr = NULL, *sp = NULL;
int len = length, bytelen = VARBITBYTES(bits);
if (!length_not_specified && length < 0)
ereport(ERROR, (errcode(ERRCODE_SUBSTRING_ERROR), errmsg("negative substring length not allowed")));
if (start < 0) {
start = bytelen + start;
}
if (start < 0 || start > bytelen || start > VARBITMAXLEN) {
len = VARBITTOTALLEN(0);
result = (VarBit*)palloc(len);
SET_VARSIZE(result, len);
VARBITLEN(result) = 0;
return result;
}
bitostr = bit_to_str(bits);
sp = bitostr + start - 1;
if (length_not_specified || start + length > bytelen ||
start + length < start
) {
len = bytelen - start + 1;
}
int resultlen = len + VARHDRSZ + VARBITHDRSZ;
result = (VarBit*)palloc0(resultlen);
SET_VARSIZE(result, resultlen);
VARBITLEN(result) = len * BITS_PER_BYTE;
int ret = memcpy_s(VARBITS(result), len, sp, len);
securec_check(ret, "\0", "\0");
pfree_ext(bitostr);
return result;
}
Datum cot_bit(PG_FUNCTION_ARGS)
{
VarBit* arg = PG_GETARG_VARBIT_P(0);
int64 arg1 = bittobigint(arg, false, fcinfo->can_ignore);
float8 res;
errno = 0;
res = tan(arg1);
if (errno != 0) {
ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("input is out of range")));
}
res = 1.0 / res;
if (isinf(res)) {
ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("value out of range: overflow")));
}
PG_RETURN_FLOAT8(res);
}
Datum acos_bit(PG_FUNCTION_ARGS)
{
VarBit* arg = PG_GETARG_VARBIT_P(0);
int64 arg1 = bittobigint(arg, false, fcinfo->can_ignore);
if (arg1 < -1 || arg1 > 1) {
PG_RETURN_NULL();
}
float8 res;
errno = 0;
res = acos(arg1);
if (errno != 0) {
ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("input is out of range")));
}
if (isinf(res)) {
ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("value out of range: overflow")));
}
PG_RETURN_FLOAT8(res);
}
Datum cos_bit(PG_FUNCTION_ARGS)
{
VarBit* arg = PG_GETARG_VARBIT_P(0);
int64 arg1 = bittobigint(arg, false, fcinfo->can_ignore);
float8 res;
errno = 0;
res = cos(arg1);
if (errno != 0) {
ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("input is out of range")));
}
if (isinf(res)) {
ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("value out of range: overflow")));
}
PG_RETURN_FLOAT8(res);
}
Datum asin_bit(PG_FUNCTION_ARGS)
{
VarBit* arg = PG_GETARG_VARBIT_P(0);
int64 arg1 = bittobigint(arg, false, fcinfo->can_ignore);
if (arg1 < -1 || arg1 > 1) {
PG_RETURN_NULL();
}
float8 res;
errno = 0;
res = asin(arg1);
if (errno != 0) {
ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("input is out of range")));
}
if (isinf(res)) {
ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("value out of range: overflow")));
}
PG_RETURN_FLOAT8(res);
}
Datum atan_bit(PG_FUNCTION_ARGS)
{
VarBit* arg = PG_GETARG_VARBIT_P(0);
int64 arg1 = bittobigint(arg, false, fcinfo->can_ignore);
float8 res;
errno = 0;
res = atan(arg1);
if (errno != 0) {
ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("input is out of range")));
}
if (isinf(res)) {
ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("value out of range: overflow")));
}
PG_RETURN_FLOAT8(res);
}
* search binary text position, ignore '\0' in text.
* - if string lenght is illegal, return -1
*/
int32 binary_text_position(const char *b, size_t b_length, const char *s, size_t s_length)
{
int32 result = -1;
const uint8 *pos, *search, *end, *search_end;
if (b_length <= 0 || s_length > b_length) return -1;
pos = (const uint8*)b;
search = (const uint8*)s;
end = (const uint8*)b + b_length - s_length + 1;
search_end = (const uint8*)s + s_length;
skip:
while (pos != end) {
if ((*pos++) != (*search)) continue;
const uint8 *i,*j;
i = pos;
j = search + 1;
while (j != search_end)
if ((*i++) != (*j++))
goto skip;
result = (pos - (const uint8*)b);
break;
}
return result;
}
Datum dolphin_bitposition(PG_FUNCTION_ARGS)
{
VarBit* bit_str = PG_GETARG_VARBIT_P(0);
VarBit* bit_substr = PG_GETARG_VARBIT_P(1);
int result = 0;
int substr_length, str_length;
char *str, *subStr;
substr_length = VARBITBYTES(bit_substr);
if (substr_length <= 0)
PG_RETURN_INT32(1);
str_length = VARBITBYTES(bit_str);
str = bit_to_str(bit_str);
subStr = bit_to_str(bit_substr);
result = binary_text_position(str, str_length, subStr, substr_length);
pfree_ext(str);
pfree_ext(subStr);
if (result < 0)
PG_RETURN_INT32(0);
else
PG_RETURN_INT32(result);
}
static Datum GetPeakVarBit(PG_FUNCTION_ARGS, bool isLarger)
{
VarBit* bit1 = (VarBit*)PG_GETARG_VARBIT_P(0);
VarBit* bit2 = (VarBit*)PG_GETARG_VARBIT_P(1);
if (PG_ARGISNULL(0)) {
if (PG_ARGISNULL(1)) {
PG_RETURN_NULL();
} else {
PG_RETURN_VARBIT_P(bit2);
}
} else if (PG_ARGISNULL(1)) {
PG_RETURN_VARBIT_P(bit1);
}
int cmpFlag = bit_cmp(bit1, bit2);
if ((isLarger && cmpFlag < 0) ||
(!isLarger && cmpFlag > 0)) {
PG_RETURN_VARBIT_P(bit2);
} else {
PG_RETURN_VARBIT_P(bit1);
}
}
PG_FUNCTION_INFO_V1_PUBLIC(varbit_larger);
extern "C" DLL_PUBLIC Datum varbit_larger(PG_FUNCTION_ARGS);
Datum varbit_larger(PG_FUNCTION_ARGS)
{
return GetPeakVarBit(fcinfo, true);
}
PG_FUNCTION_INFO_V1_PUBLIC(varbit_smaller);
extern "C" DLL_PUBLIC Datum varbit_smaller(PG_FUNCTION_ARGS);
Datum varbit_smaller(PG_FUNCTION_ARGS)
{
return GetPeakVarBit(fcinfo, false);
}
#endif