📄 varbit.c
字号:
* * External format is the bitlen as an int32, then the byte array. */Datumvarbit_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; int ipad; bits8 mask; bitlen = pq_getmsgint(buf, sizeof(int32)); if (bitlen < 0) 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); VARATT_SIZEP(result) = len; VARBITLEN(result) = bitlen; pq_copymsgbytes(buf, (char *) VARBITS(result), VARBITBYTES(result)); /* Make sure last byte is zero-padded if needed */ 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 */Datumvarbit_send(PG_FUNCTION_ARGS){ VarBit *s = PG_GETARG_VARBIT_P(0); StringInfoData buf; pq_begintypsend(&buf); pq_sendint(&buf, VARBITLEN(s), sizeof(int32)); pq_sendbytes(&buf, (char *) VARBITS(s), VARBITBYTES(s)); PG_RETURN_BYTEA_P(pq_endtypsend(&buf));}/* 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. */Datumvarbit(PG_FUNCTION_ARGS){ VarBit *arg = PG_GETARG_VARBIT_P(0); int32 len = PG_GETARG_INT32(1); bool isExplicit = PG_GETARG_BOOL(2); VarBit *result; int rlen; int ipad; bits8 mask; /* No work if typmod is invalid or supplied data matches it already */ 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); VARATT_SIZEP(result) = rlen; VARBITLEN(result) = len; memcpy(VARBITS(result), VARBITS(arg), VARBITBYTES(result)); /* Make sure last byte is zero-padded if needed */ ipad = VARBITPAD(result); if (ipad > 0) { mask = BITMASK << ipad; *(VARBITS(result) + VARBITBYTES(result) - 1) &= mask; } PG_RETURN_VARBIT_P(result);}/* * 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 int32bit_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;}Datumbiteq(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);}Datumbitne(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);}Datumbitlt(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);}Datumbitle(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);}Datumbitgt(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);}Datumbitge(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);}Datumbitcmp(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 */Datumbitcat(PG_FUNCTION_ARGS){ VarBit *arg1 = PG_GETARG_VARBIT_P(0); VarBit *arg2 = PG_GETARG_VARBIT_P(1); VarBit *result; int bitlen1, bitlen2, bytelen, bit1pad, bit2shift; bits8 *pr, *pa; bitlen1 = VARBITLEN(arg1); bitlen2 = VARBITLEN(arg2); bytelen = VARBITTOTALLEN(bitlen1 + bitlen2); result = (VarBit *) palloc(bytelen); VARATT_SIZEP(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; } } PG_RETURN_VARBIT_P(result);}/* bitsubstr * retrieve a substring from the bit string. * Note, s is 1-based. * SQL draft 6.10 9) */Datumbitsubstr(PG_FUNCTION_ARGS){ VarBit *arg = PG_GETARG_VARBIT_P(0); int32 s = PG_GETARG_INT32(1); int32 l = PG_GETARG_INT32(2); VarBit *result; int bitlen, rbitlen, len, ipad = 0, ishift, i; int e, s1, e1; bits8 mask, *r, *ps; bitlen = VARBITLEN(arg); /* If we do not have an upper bound, set bitlen */ if (l == -1) l = bitlen; e = s + l; s1 = Max(s, 1); e1 = Min(e, bitlen + 1); if (s1 > bitlen || e1 < 1) { /* Need to return a zero-length bitstring */ len = VARBITTOTALLEN(0); result = (VarBit *) palloc(len); VARATT_SIZEP(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); VARATT_SIZEP(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++; } } /* Do we need to pad at the end? */ ipad = VARBITPAD(result); if (ipad > 0) { mask = BITMASK << ipad; *(VARBITS(result) + len - 1) &= mask; } } PG_RETURN_VARBIT_P(result);}/* bitlength, bitoctetlength * Return the length of a bit string */Datumbitlength(PG_FUNCTION_ARGS){ VarBit *arg = PG_GETARG_VARBIT_P(0); PG_RETURN_INT32(VARBITLEN(arg));}Datumbitoctetlength(PG_FUNCTION_ARGS){ VarBit *arg = PG_GETARG_VARBIT_P(0); PG_RETURN_INT32(VARBITBYTES(arg));}/* bitand * perform a logical AND on two bit strings. */Datumbitand(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); VARATT_SIZEP(result) = len; VARBITLEN(result) = bitlen1; p1 = VARBITS(arg1); p2 = VARBITS(arg2); r = VARBITS(result); for (i = 0; i < VARBITBYTES(arg1); i++) *r++ = *p1++ & *p2++; /* Padding is not needed as & of 0 pad is 0 */ PG_RETURN_VARBIT_P(result);}/* bitor * perform a logical OR on two bit strings. */Datumbitor(PG_FUNCTION_ARGS){ VarBit *arg1 = PG_GETARG_VARBIT_P(0); VarBit *arg2 = PG_GETARG_VARBIT_P(1); VarBit *result; int len, bitlen1, bitlen2, i;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -