From 0337938fbfee45a2406b12e34cc594e72af58c3c Mon Sep 17 00:00:00 2001
From: "Thomas G. Lockhart" <lockhart@fourpalms.org>
Date: Sat, 8 Apr 2000 02:13:11 +0000
Subject: [PATCH] Add zpbit and varbit data types from Adrian Joubert 
 <a.joubert@albourne.com>.

---
 src/backend/utils/adt/Makefile    |   7 +-
 src/backend/utils/adt/varbit.c    | 937 ++++++++++++++++++++++++++++++
 src/include/catalog/pg_operator.h |  31 +-
 src/include/catalog/pg_proc.h     |  81 ++-
 src/include/catalog/pg_type.h     |  22 +-
 src/include/utils/builtins.h      |   3 +-
 src/include/utils/varbit.h        |  87 +++
 7 files changed, 1155 insertions(+), 13 deletions(-)
 create mode 100644 src/backend/utils/adt/varbit.c
 create mode 100644 src/include/utils/varbit.h

diff --git a/src/backend/utils/adt/Makefile b/src/backend/utils/adt/Makefile
index b6b02082e0a..8ed27fe8933 100644
--- a/src/backend/utils/adt/Makefile
+++ b/src/backend/utils/adt/Makefile
@@ -4,7 +4,7 @@
 #    Makefile for utils/adt
 #
 # IDENTIFICATION
-#    $Header: /cvsroot/pgsql/src/backend/utils/adt/Makefile,v 1.35 2000/02/27 12:02:32 wieck Exp $
+#    $Header: /cvsroot/pgsql/src/backend/utils/adt/Makefile,v 1.36 2000/04/08 02:12:54 thomas Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -29,7 +29,7 @@ OBJS = acl.o arrayfuncs.o arrayutils.o bool.o cash.o char.o chunk.o \
 	misc.o nabstime.o name.o not_in.o numeric.o numutils.o \
 	oid.o oracle_compat.o \
 	regexp.o regproc.o ruleutils.o selfuncs.o sets.o \
-	tid.o timestamp.o varchar.o varlena.o version.o \
+	tid.o timestamp.o varbit.o varchar.o varlena.o version.o \
 	network.o mac.o inet_net_ntop.o inet_net_pton.o \
 	ri_triggers.o pg_lzcompress.o pg_locale.o formatting.o
 
@@ -47,3 +47,6 @@ clean:
 ifeq (depend,$(wildcard depend))
 include depend
 endif
+
+
+
diff --git a/src/backend/utils/adt/varbit.c b/src/backend/utils/adt/varbit.c
new file mode 100644
index 00000000000..47946faccc0
--- /dev/null
+++ b/src/backend/utils/adt/varbit.c
@@ -0,0 +1,937 @@
+/*-------------------------------------------------------------------------
+ *
+ * varbit.c
+ *	  Functions for the built-in type bit() and varying bit().
+ *
+ * IDENTIFICATION
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/varbit.c,v 1.1 2000/04/08 02:12:54 thomas Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/* Include file list stolen from float.c.
+ * Can probably get rid of some of these.
+ * - thomas 2000-04-07
+ */
+#include <ctype.h>
+#include <errno.h>
+
+#include <float.h>				/* faked on sunos4 */
+
+#include <math.h>
+
+#include "postgres.h"
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#ifndef MAXINT
+#define MAXINT		  INT_MAX
+#endif
+#else
+#ifdef HAVE_VALUES_H
+#include <values.h>
+#endif
+#endif
+#include "fmgr.h"
+#include "utils/builtins.h"
+#include "access/htup.h"
+
+/* 
+   Prefixes:
+     zp    -- zero-padded fixed length bit string
+     var   -- varying bit string
+
+   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 -- lenght of the bit string in bits
+	 bitdata   -- least significant byte first string
+*/
+
+char * 
+varbit_out (bits8 *s) {
+  return zpbits_out(s);
+}
+
+/*
+ * zpbit_in -
+ *	  converts a string to the internal representation of a bitstring.
+ *        The length is determined by the number of bits required plus
+ *        VARHDRSZ bytes or from atttypmod. 
+ *	  (XXX dummy is here because we pass typelem as the second argument 
+ *        for array_in. copied this, no idea what it means??)
+ */
+bits8 *
+zpbit_in(char *s, int dummy,  int32 atttypmod)
+{
+  bits8 *result;	/* the bits string that was read in   */ 
+  char  *sp;		/* pointer into the character string  */
+  bits8 *r;
+  int len,		/* Length of the whole data structure */
+    bitlen,		/* Number of bits in the bit string   */
+    slen;		/* Length of the input string         */
+  int bit_not_hex = 0;  /* 0 = hex string  1=bit string       */
+  int bc, ipad;
+  bits8 x = 0;
+
+
+  if (s == NULL)
+    return (bits8 *) NULL;
+
+  /* Check that the first character is a b or an x */
+  if (s[0]=='b' || s[0]=='B') 
+      bit_not_hex = 1;
+  else if (s[0]=='x' || s[0]=='X') 
+      bit_not_hex = 0;
+  else 
+    elog(ERROR, "zpbit_in: %s is not a valid bitstring",s);
+
+  slen = strlen(s) - 1;
+  /* Determine bitlength from input string */
+  bitlen = slen;
+  if (!bit_not_hex)
+    bitlen *= 4;
+  
+  /* Sometimes atttypmod is not supplied. If it is supplied we need to make
+     sure that the bitstring fits. Note that the number of infered bits can
+     be larger than the number of actual bits needed, but only if we are 
+     reading a hex string and not by more than 3 bits, as a hex string gives 
+     and accurate length upto 4 bits */
+  if (atttypmod == -1)
+    atttypmod = bitlen;
+  else
+    if ((bitlen>atttypmod && bit_not_hex) || 
+	(bitlen>atttypmod+3 && !bit_not_hex))
+	  elog(ERROR, "zpbit_in: bit string of size %d cannot be written into bits(%d)",
+	       bitlen,atttypmod);
+
+
+  len = VARBITDATALEN(atttypmod);
+
+  if (len > MaxAttrSize)
+    elog(ERROR, "zpbit_in: length of bit() must be less than %ld",
+	 (MaxAttrSize-VARHDRSZ-VARBITHDRSZ)*BITSPERBYTE);
+
+  result = (bits8 *) palloc(len);
+  /* set to 0 so that *r is always initialised and strin is zero-padded */
+  memset(result, 0, len);
+  VARSIZE(result) = len;
+  VARBITLEN(result) = atttypmod;
+
+  /* We need to read the bitstring from the end, as we store it least 
+     significant byte first. s points to the byte before the beginning
+     of the bitstring */
+  sp = s+1;
+  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 = BITHIGH;
+      for (bc = 0; sp != s+slen+1; sp++, bc++)
+	{
+	  if (*sp=='1')
+	    *r |= x;
+	  if (bc==7) {
+	    bc = 0;
+	    x = BITHIGH;
+	    r++;
+	  } else 
+	    x >>= 1;
+	}
+     }
+  else 
+    {
+      /* Parse the hex representation of the string */
+      for (bc = 0; sp != s+slen+1; 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 
+	    elog(ERROR,"Cannot parse %c as a hex digit",*sp);
+	  if (bc) {
+	    bc = 0;
+	    *r++ |= x;
+	  } else {
+	    bc++;
+	    *r = x<<4;
+	  }
+	}
+    }
+
+  if (bitlen > atttypmod) {
+    /* Check that this fitted */
+    r = (bits8 *) (result + len - 1);
+    ipad = VARBITPAD(result);
+    /* The bottom ipad bits of the byte pointed to by r need to be zero */
+    if (((*r << (BITSPERBYTE-ipad)) & BITMASK) > 0)
+      elog(ERROR, "zpbit_in: bit string too large for bit(%d) data type",
+	   atttypmod);
+  }
+
+  return result;
+}
+
+/* zpbit_out -
+ *    for the time being we print everything as hex strings, as this is likely 
+ *    to be more compact than bit strings, and consequently much more efficient
+ *    for long strings
+ */
+char *
+zpbit_out(bits8 *s)
+{
+  char	   *result, *r;
+  bits8    *sp;
+  int	   i, len, bitlen;
+  
+  if (s == NULL)
+    {
+      result = (char *) palloc(2);
+      result[0] = '-';
+      result[1] = '\0';
+    }
+  else
+    {
+      bitlen = VARBITLEN(s);
+      len = bitlen/4 + (bitlen%4>0 ? 1 : 0);
+      result = (char *) palloc(len + 4);
+      sp = VARBITS(s);
+      r = result;
+      *r++ = 'X';
+      *r++ = '\'';
+      /* 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+1)
+	r--;
+      *r++ = '\'';
+      *r = '\0';
+    }
+  return result;
+}
+
+/* zpbits_out -
+ *    Prints the string a bits
+ */
+char *
+zpbits_out(bits8 *s)
+{
+  char	   *result, *r;
+  bits8    *sp;
+  bits8    x;
+  int	   i, k, len;
+  
+  if (s == NULL)
+    {
+      result = (char *) palloc(2);
+      result[0] = '-';
+      result[1] = '\0';
+    }
+  else
+    {
+      len = VARBITLEN(s);
+      result = (char *) palloc(len + 4);
+      sp = VARBITS(s);
+      r = result;
+      *r++ = 'B';
+      *r++ = '\'';
+      for (i=0; i<len-BITSPERBYTE; i+=BITSPERBYTE, sp++) {
+	x = *sp;
+	for (k=0; k<BITSPERBYTE; k++) 
+	  {
+	    *r++ = (x & BITHIGH) ? '1' : '0';
+	    x <<= 1;
+	  }
+      }
+      x = *sp;
+      for (k=i; k<len; k++)
+	{
+	  *r++ = (x & BITHIGH) ? '1' : '0';
+	  x <<= 1;
+	}
+      *r++ = '\'';
+      *r = '\0';
+    }
+  return result;
+}
+
+
+/*
+ * varbit_in -
+ *	  converts a string to the internal representation of a bitstring.
+*/
+bits8 *
+varbit_in(char *s, int dummy,  int32 atttypmod)
+{
+  bits8 *result;	/* The resulting bit string           */
+  char *sp;		/* pointer into the character string  */
+  bits8 *r;
+  int len,		/* Length of the whole data structure */
+    bitlen,		/* Number of bits in the bit string   */
+    slen;		/* Length of the input string         */
+  int bit_not_hex = 0;
+  int bc, ipad;
+  bits8 x = 0;
+
+
+  if (s == NULL)
+    return (bits8 *) NULL;
+
+  /* Check that the first character is a b or an x */
+  if (s[0]=='b' || s[0]=='B') 
+      bit_not_hex = 1;
+  else if (s[0]=='x' || s[0]=='X') 
+      bit_not_hex = 0;
+  else 
+    elog(ERROR, "zpbit_in: %s is not a valid bitstring",s);
+
+  slen = strlen(s) - 1;
+  /* Determine bitlength from input string */
+  bitlen = slen;
+  if (!bit_not_hex)
+    bitlen *= 4;
+  
+  /* Sometimes atttypmod is not supplied. If it is supplied we need to make
+     sure that the bitstring fits. Note that the number of infered bits can
+     be larger than the number of actual bits needed, but only if we are 
+     reading a hex string and not by more than 3 bits, as a hex string gives 
+     and accurate length upto 4 bits */
+  if (atttypmod > -1)
+    if ((bitlen>atttypmod && bit_not_hex) || 
+	(bitlen>atttypmod+3 && !bit_not_hex))
+	  elog(ERROR, "varbit_in: bit string of size %d cannot be written into varying bits(%d)",
+	       bitlen,atttypmod);
+
+
+  len = VARBITDATALEN(bitlen);
+
+  if (len > MaxAttrSize)
+    elog(ERROR, "varbit_in: length of bit() must be less than %ld",
+	 (MaxAttrSize-VARHDRSZ-VARBITHDRSZ)*BITSPERBYTE);
+
+  result = (bits8 *) palloc(len);
+  /* set to 0 so that *r is always initialised and strin is zero-padded */
+  memset(result, 0, len);
+  VARSIZE(result) = len;
+  VARBITLEN(result) = bitlen;
+
+  /* We need to read the bitstring from the end, as we store it least 
+     significant byte first. s points to the byte before the beginning
+     of the bitstring */
+  sp = s + 1;
+  r = VARBITS(result);
+  if (bit_not_hex) 
+    {
+      /* Parse the bit representation of the string */
+      x = BITHIGH;
+      for (bc = 0; sp != s+slen+1; sp++, bc++)
+	{
+	  if (*sp=='1')
+	    *r |= x;
+	  if (bc==7) {
+	    bc = 0;
+	    x = BITHIGH;
+	    r++;
+	  } else 
+	    x >>= 1;
+	}
+     }
+  else 
+    {
+      for (bc = 0; sp != s+slen+1; 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 
+	    elog(ERROR,"Cannot parse %c as a hex digit",*sp);
+	  if (bc) {
+	    bc = 0;
+	    *r++ |= x;
+	  } else {
+	    bc++;
+	    *r = x<<4;
+	  }
+	}
+    }
+
+  if (bitlen > atttypmod) {
+    /* Check that this fitted */
+    r = (bits8 *) (result + len - 1);
+    ipad = VARBITPAD(result);
+    /* The bottom ipad bits of the byte pointed to by r need to be zero */
+    if (((*r << (BITSPERBYTE-ipad)) & BITMASK) > 0)
+      elog(ERROR, "varbit_in: bit string too large for varying bit(%d) data type",
+	   atttypmod);
+  }
+
+  return result;
+}
+
+/*
+  the zpbit_out routines are fine for varying bits as well 
+*/
+
+
+/*
+ * 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.
+ */
+
+bool
+biteq (bits8 *arg1, bits8 *arg2)
+{
+  int bitlen1,
+    bitlen2;
+
+  if (!PointerIsValid(arg1) || !PointerIsValid(arg2))
+    return (bool) 0;
+  bitlen1 = VARBITLEN(arg1);
+  bitlen2 = VARBITLEN(arg2);
+  if (bitlen1 != bitlen2)
+    return (bool) 0;
+  
+  /* bit strings are always stored in a full number of bytes */
+  return memcmp((void *)VARBITS(arg1),(void *)VARBITS(arg2),
+		VARBITBYTES(arg1)) == 0;
+}
+
+bool
+bitne (bits8 *arg1, bits8 *arg2)
+{
+  int bitlen1,
+    bitlen2;
+
+  if (!PointerIsValid(arg1) || !PointerIsValid(arg2))
+    return (bool) 0;
+  bitlen1 = VARBITLEN(arg1);
+  bitlen2 = VARBITLEN(arg2);
+  if (bitlen1 != bitlen2)
+    return (bool) 1;
+  
+  /* bit strings are always stored in a full number of bytes */
+  return memcmp((void *)VARBITS(arg1),(void *)VARBITS(arg2),
+		VARBITBYTES(arg1)) != 0;
+}
+
+/* bitcmp
+ * 
+ * Compares two bitstrings and returns -1, 0, 1 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.
+ *   Anything is equal to undefined.
+ */
+int 
+bitcmp (bits8 *arg1, bits8 *arg2)
+{
+  int bitlen1, bytelen1,
+    bitlen2, bytelen2;
+  int cmp;
+
+  if (!PointerIsValid(arg1) || !PointerIsValid(arg2))
+    return (bool) 0;
+  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) 
+      return bitlen1 < bitlen2 ? -1 : 1;
+  }
+  return cmp;
+}
+
+bool
+bitlt (bits8 *arg1, bits8 *arg2)
+{
+  return (bool) (bitcmp(arg1,arg2) == -1);
+}
+
+bool
+bitle (bits8 *arg1, bits8 *arg2)
+{
+  return (bool) (bitcmp(arg1,arg2) <= 0);
+}
+
+bool
+bitge (bits8 *arg1, bits8 *arg2)
+{
+  return (bool) (bitcmp(arg1,arg2) >= 0);
+}
+
+bool
+bitgt (bits8 *arg1, bits8 *arg2)
+{
+  return (bool) (bitcmp(arg1,arg2) == 1);
+}
+
+/* bitcat
+ * Concatenation of bit strings
+ */
+bits8 *
+bitcat (bits8 *arg1, bits8 *arg2)
+{
+  int bitlen1, bitlen2, bytelen, bit1pad, bit2shift;
+  bits8 *result;
+  bits8 *pr, *pa;
+
+  if (!PointerIsValid(arg1) || !PointerIsValid(arg2))
+    return NULL;
+
+  bitlen1 = VARBITLEN(arg1);
+  bitlen2 = VARBITLEN(arg2);
+
+  bytelen = VARBITDATALEN(bitlen1+bitlen2);
+  
+  result = (bits8 *) palloc(bytelen*sizeof(bits8));
+  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 results to fit */
+      bit2shift = BITSPERBYTE - bit1pad;
+      pa = VARBITS(arg2);
+      pr = VARBITS(result)+VARBITBYTES(arg1)-1;
+      for ( ; 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)
+ */
+bits8 * 
+bitsubstr (bits8 *arg, int32 s, int32 l)
+{
+  int bitlen,
+    rbitlen,
+    len,
+    ipad = 0,
+    ishift,
+    i;
+  int e, s1, e1;
+  bits8 * result;
+  bits8 mask, *r, *ps;
+
+  if (!PointerIsValid(arg))
+    return NULL;
+
+  bitlen = VARBITLEN(arg);
+  e = s+l;
+  s1 = Max(s,1);
+  e1 = Min(e,bitlen+1);
+  if (s1>bitlen || e1<1) 
+    {
+      /* Need to return a null string */
+      len = VARBITDATALEN(0);
+      result = (bits8 *) palloc(len);
+      VARBITLEN(result) = 0;
+      VARSIZE(result) = len;
+    } 
+  else 
+    {
+      /* OK, we've got a true substring starting at position s1-1 and 
+	 ending at position e1-1 */
+      rbitlen = e1-s1;
+      len = VARBITDATALEN(rbitlen);
+      result = (bits8 *) palloc(len);
+      VARBITLEN(result) = rbitlen;
+      VARSIZE(result) = len;
+      len -= VARHDRSZ + VARBITHDRSZ;
+      /* Are we copying from a byte boundary? */
+      if ((s1-1)%BITSPERBYTE==0) 
+	{
+	  /* Yep, we are copying bytes */
+	  memcpy(VARBITS(result),VARBITS(arg)+(s1-1)/BITSPERBYTE,len);
+	} 
+      else 
+	{
+	  /* Figure out how much we need to shift the sequence by */
+	  ishift = (s1-1)%BITSPERBYTE;
+	  r = VARBITS(result);
+	  ps = VARBITS(arg) + (s1-1)/BITSPERBYTE;
+	  for (i=0; i<len; i++) 
+	    {
+	      *r = (*ps <<ishift) & BITMASK;
+	      if ((++ps) < VARBITEND(arg))
+		*r |= *ps >>(BITSPERBYTE-ishift);
+	      r++;
+	    }
+	}
+      /* Do we need to pad at the end? */
+      ipad = VARBITPAD(result);
+      if (ipad > 0) 
+	{
+	  mask = BITMASK << ipad;
+	  *(VARBITS(result) + len - 1) &= mask;
+	}
+    }
+
+  return result;
+}
+
+/* bitand
+ * perform a logical AND on two bit strings. The result is automatically
+ * truncated to the shorter bit string
+ */
+bits8 *
+bitand (bits8 * arg1, bits8 * arg2)
+{
+  int len,
+    i;
+  bits8 *result;
+  bits8 *p1, 
+    *p2, 
+    *r;
+
+  if (!PointerIsValid(arg1) || !PointerIsValid(arg2))
+    return (bool) 0;
+
+  len = Min(VARSIZE(arg1),VARSIZE(arg2));
+  result = (bits8 *) palloc(len);
+  VARSIZE(result) = len;
+  VARBITLEN(result) = Min(VARBITLEN(arg1),VARBITLEN(arg2));
+
+  p1 = (bits8 *) VARBITS(arg1);
+  p2 = (bits8 *) VARBITS(arg2);
+  r = (bits8 *) VARBITS(result);
+  for (i=0; i<Min(VARBITBYTES(arg1),VARBITBYTES(arg2)); i++)
+    *r++ = *p1++ & *p2++;
+  
+  /* Padding is not needed as & of 0 pad is 0 */
+  
+  return result;
+}
+
+/* bitor
+ * perform a logical OR on two bit strings. The result is automatically
+ * truncated to the shorter bit string.
+ */
+bits8 *
+bitor (bits8 * arg1, bits8 * arg2)
+{
+  int len,
+    i;
+  bits8 *result;
+  bits8 *p1, 
+    *p2, 
+    *r;
+  bits8 mask;
+
+  if (!PointerIsValid(arg1) || !PointerIsValid(arg2))
+    return (bool) 0;
+
+  len = Min(VARSIZE(arg1),VARSIZE(arg2));
+  result = (bits8 *) palloc(len);
+  VARSIZE(result) = len;
+  VARBITLEN(result) = Min(VARBITLEN(arg1),VARBITLEN(arg2));
+
+  p1 = (bits8 *) VARBITS(arg1);
+  p2 = (bits8 *) VARBITS(arg2);
+  r = (bits8 *) VARBITS(result);
+  for (i=0; i<Min(VARBITBYTES(arg1),VARBITBYTES(arg2)); i++)
+    *r++ = *p1++ | *p2++;
+
+  /* Pad the result */
+  mask = BITMASK << VARBITPAD(result);
+  *r &= mask;
+  
+  return result;
+}
+
+/* bitxor
+ * perform a logical XOR on two bit strings. The result is automatically
+ * truncated to the shorter bit string.
+ */
+bits8 *
+bitxor (bits8 * arg1, bits8 * arg2)
+{
+  int len,
+    i;
+  bits8 *result;
+  bits8 *p1, 
+    *p2, 
+    *r;
+  bits8 mask;
+
+  if (!PointerIsValid(arg1) || !PointerIsValid(arg2))
+    return (bool) 0;
+
+  len = Min(VARSIZE(arg1),VARSIZE(arg2));
+  result = (bits8 *) palloc(len);
+  VARSIZE(result) = len;
+  VARBITLEN(result) = Min(VARBITLEN(arg1),VARBITLEN(arg2));
+
+  p1 = (bits8 *) VARBITS(arg1);
+  p2 = (bits8 *) VARBITS(arg2);
+  r = (bits8 *) VARBITS(result);
+  for (i=0; i<Min(VARBITBYTES(arg1),VARBITBYTES(arg2)); i++)
+    {
+      *r++ = *p1++ ^ *p2++;
+    }
+
+  /* Pad the result */
+  mask = BITMASK << VARBITPAD(result);
+  *r &= mask;
+  
+  return result;
+}
+
+/* bitnot
+ * perform a logical NOT on a bit strings.
+ */
+bits8 *
+bitnot (bits8 * arg)
+{
+  bits8 *result;
+  bits8 *p, 
+    *r;
+  bits8 mask;
+
+  if (!PointerIsValid(arg))
+    return (bool) 0;
+
+  result = (bits8 *) palloc(VARSIZE(arg));
+  VARSIZE(result) = VARSIZE(arg);
+  VARBITLEN(result) = VARBITLEN(arg);
+
+  p = (bits8 *) VARBITS(arg);
+  r = (bits8 *) VARBITS(result);
+  for ( ; p < VARBITEND(arg); p++, r++)
+    *r = ~*p;
+
+  /* Pad the result */
+  mask = BITMASK << VARBITPAD(result);
+  *r &= mask;
+  
+  return result;
+}
+
+/* bitshiftleft
+ * do a left shift (i.e. to the beginning of the string) of the bit string
+ */
+bits8 *
+bitshiftleft (bits8 * arg, int shft)
+{
+  int byte_shift, ishift, len;
+  bits8 *result;
+  bits8 *p, 
+    *r;
+
+  if (!PointerIsValid(arg))
+    return (bool) 0;
+
+  /* Negative shift is a shift to the right */
+  if (shft < 0) 
+    return bitshiftright(arg, -shft);
+
+  result = (bits8 *) palloc(VARSIZE(arg));
+  VARSIZE(result) = VARSIZE(arg);
+  VARBITLEN(result) = VARBITLEN(arg);
+  r = (bits8 *) VARBITS(result);
+
+  byte_shift = shft/BITSPERBYTE;
+  ishift = shft % BITSPERBYTE;
+  p = ((bits8 *) VARBITS(arg)) + byte_shift;
+  
+  if (ishift == 0) {
+    /* Special case: we can do a memcpy */
+    len = VARBITBYTES(arg) - byte_shift;
+    memcpy(r, p, len);
+    memset(r+len, 0, byte_shift);
+  } else {
+    for ( ; p < VARBITEND(arg); r++) {
+      *r = *p <<ishift;
+      if ((++p) < VARBITEND(arg))
+	*r |= *p >>(BITSPERBYTE-ishift);
+    }
+    for ( ; r < VARBITEND(result) ; r++ ) 
+      *r = (bits8) 0;
+  }
+
+  return result;
+}
+
+/* bitshiftright
+ * do a right shift (i.e. to the beginning of the string) of the bit string
+ */
+bits8 *
+bitshiftright (bits8 * arg, int shft)
+{
+  int byte_shift, ishift, len;
+  bits8 *result;
+  bits8 *p, 
+    *r;
+
+  if (!PointerIsValid(arg))
+    return (bits8 *) 0;
+
+  /* Negative shift is a shift to the left */
+  if (shft < 0) 
+    return bitshiftleft(arg, -shft);
+
+  result = (bits8 *) palloc(VARSIZE(arg));
+  VARSIZE(result) = VARSIZE(arg);
+  VARBITLEN(result) = VARBITLEN(arg);
+  r = (bits8 *) VARBITS(result);
+
+  byte_shift = shft/BITSPERBYTE;
+  ishift = shft % BITSPERBYTE;
+  p = (bits8 *) VARBITS(arg);
+
+  /* Set the first part of the result to 0 */
+  memset(r, 0, byte_shift);
+  
+  if (ishift == 0) 
+    {
+      /* Special case: we can do a memcpy */
+      len = VARBITBYTES(arg) - byte_shift;
+      memcpy(r+byte_shift, p, len);
+    } 
+  else 
+    {
+      r += byte_shift;
+      *r = 0;    /* Initialise first byte */
+      for ( ; r < VARBITEND(result); p++) {
+	*r |= *p >> ishift;
+	if ((++r) < VARBITEND(result))
+	  *r = (*p <<(BITSPERBYTE-ishift)) & BITMASK;
+      }
+    }
+
+  return result;
+}
+
+bool
+varbiteq (bits8 *arg1, bits8 *arg2)
+{
+	return biteq(arg1, arg2);
+}
+
+bool
+varbitne (bits8 *arg1, bits8 *arg2)
+{
+	return bitne(arg1, arg2);
+}
+
+bool
+varbitge (bits8 *arg1, bits8 *arg2)
+{
+	return bitge(arg1, arg2);
+}
+
+bool
+varbitgt (bits8 *arg1, bits8 *arg2)
+{
+	return bitgt(arg1, arg2);
+}
+
+bool
+varbitle (bits8 *arg1, bits8 *arg2)
+{
+	return bitle(arg1, arg2);
+}
+
+bool
+varbitlt (bits8 *arg1, bits8 *arg2)
+{
+	return bitlt(arg1, arg2);
+}
+
+int
+varbitcmp (bits8 *arg1, bits8 *arg2)
+{
+	return bitcmp(arg1, arg2);
+}
+
+bits8 *
+varbitand (bits8 * arg1, bits8 * arg2)
+{
+	return bitand(arg1, arg2);
+}
+
+bits8 *
+varbitor (bits8 * arg1, bits8 * arg2)
+{
+	return bitor(arg1, arg2);
+}
+
+bits8 *
+varbitxor (bits8 * arg1, bits8 * arg2)
+{
+	return bitxor(arg1, arg2);
+}
+
+bits8 *
+varbitnot (bits8 * arg)
+{
+	return bitnot(arg);
+}
+
+bits8 *
+varbitshiftright (bits8 * arg, int shft)
+{
+	return bitshiftright(arg, shft);
+}
+
+bits8 *
+varbitshiftleft (bits8 * arg, int shft)
+{
+	return bitshiftleft(arg, shft);
+}
+
+bits8 *
+varbitcat (bits8 *arg1, bits8 *arg2)
+{
+	return bitcat(arg1, arg2);
+}
+
+bits8 *
+varbitsubstr (bits8 *arg, int32 s, int32 l)
+{
+	return bitsubstr(arg, s, l);
+}
diff --git a/src/include/catalog/pg_operator.h b/src/include/catalog/pg_operator.h
index 0189184cfc2..2150bac98de 100644
--- a/src/include/catalog/pg_operator.h
+++ b/src/include/catalog/pg_operator.h
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_operator.h,v 1.73 2000/04/07 13:39:49 thomas Exp $
+ * $Id: pg_operator.h,v 1.74 2000/04/08 02:13:00 thomas Exp $
  *
  * NOTES
  *	  the genbki.sh script reads this file and generates .bki
@@ -716,6 +716,35 @@ DATA(insert OID = 1660 (  "<="       PGUID 0 b t f 1625 1625   16 1662 1661 0 0
 DATA(insert OID = 1661 (  ">"    PGUID 0 b t f 1625 1625   16 1659 1660 0 0 lztext_gt intgtsel intgtjoinsel ));
 DATA(insert OID = 1662 (  ">="       PGUID 0 b t f 1625 1625   16 1660 1659 0 0 lztext_ge intgtsel intgtjoinsel ));
 
+DATA(insert OID = 1784 (  "="	  PGUID 0 b t f 1560 1560	16 1784 1785 1786 1786 biteq eqsel eqjoinsel ));
+DATA(insert OID = 1785 (  "<>"	  PGUID 0 b t f 1560 1560	16 1785 1784	0	 0 bitne neqsel neqjoinsel ));
+DATA(insert OID = 1786 (  "<"	  PGUID 0 b t f 1560 1560	16 1787 1789	0	 0 bitlt intltsel intltjoinsel ));
+DATA(insert OID = 1787 (  ">"	  PGUID 0 b t f 1560 1560	16 1786 1788	0	 0 bitgt intgtsel intgtjoinsel ));
+DATA(insert OID = 1788 (  "<="	  PGUID 0 b t f 1560 1560	16 1789 1787	0	 0 bitle intltsel intltjoinsel ));
+DATA(insert OID = 1789 (  ">="	  PGUID 0 b t f 1560 1560	16 1788 1786	0	 0 bitge intgtsel intgtjoinsel ));
+DATA(insert OID = 1790 (  "<=>"	  PGUID 0 b t f 1560 1560	23	  0    0	0	 0 bitcmp - - ));
+DATA(insert OID = 1791 (  "&"	  PGUID 0 b t f 1560 1560 1560	  0    0	0	 0 bitand - - ));
+DATA(insert OID = 1792 (  "|"	  PGUID 0 b t f 1560 1560 1560	  0    0	0	 0 bitor - - ));
+DATA(insert OID = 1793 (  "^"	  PGUID 0 b t f 1560 1560 1560	  0    0	0	 0 bitxor - - ));
+DATA(insert OID = 1794 (  "~"	  PGUID 0 b t f 1560 1560 1560	  0    0	0	 0 bitnot - - ));
+DATA(insert OID = 1795 (  "<<"	  PGUID 0 b t f 1560 1560 1560	  0    0	0	 0 bitshiftleft - - ));
+DATA(insert OID = 1796 (  ">>"	  PGUID 0 b t f 1560 1560 1560	  0    0	0	 0 bitshiftright - - ));
+DATA(insert OID = 1797 (  "||"	  PGUID 0 b t f 1560 1560 1560	  0    0	0	 0 bitcat - - ));
+
+DATA(insert OID = 1804 (  "="	  PGUID 0 b t f 1562 1562	16 1804 1805 1806 1806 varbiteq eqsel eqjoinsel ));
+DATA(insert OID = 1805 (  "<>"	  PGUID 0 b t f 1562 1562	16 1805 1804	0	 0 varbitne neqsel neqjoinsel ));
+DATA(insert OID = 1806 (  "<"	  PGUID 0 b t f 1562 1562	16 1807 1809	0	 0 varbitlt intltsel intltjoinsel ));
+DATA(insert OID = 1807 (  ">"	  PGUID 0 b t f 1562 1562	16 1806 1808	0	 0 varbitgt intgtsel intgtjoinsel ));
+DATA(insert OID = 1808 (  "<="	  PGUID 0 b t f 1562 1562	16 1809 1807	0	 0 varbitle intltsel intltjoinsel ));
+DATA(insert OID = 1809 (  ">="	  PGUID 0 b t f 1562 1562	16 1808 1806	0	 0 varbitge intgtsel intgtjoinsel ));
+DATA(insert OID = 1810 (  "<=>"	  PGUID 0 b t f 1562 1562	23	  0    0	0	 0 varbitcmp - - ));
+DATA(insert OID = 1811 (  "&"	  PGUID 0 b t f 1562 1562 1562	  0    0	0	 0 varbitand - - ));
+DATA(insert OID = 1812 (  "|"	  PGUID 0 b t f 1562 1562 1562	  0    0	0	 0 varbitor - - ));
+DATA(insert OID = 1813 (  "^"	  PGUID 0 b t f 1562 1562 1562	  0    0	0	 0 varbitxor - - ));
+DATA(insert OID = 1814 (  "~"	  PGUID 0 b t f 1562 1562 1562	  0    0	0	 0 varbitnot - - ));
+DATA(insert OID = 1815 (  "<<"	  PGUID 0 b t f 1562 1562 1562	  0    0	0	 0 varbitshiftleft - - ));
+DATA(insert OID = 1816 (  ">>"	  PGUID 0 b t f 1562 1562 1562	  0    0	0	 0 varbitshiftright - - ));
+DATA(insert OID = 1817 (  "||"	  PGUID 0 b t f 1562 1562 1562	  0    0	0	 0 varbitcat - - ));
 
 /*
  * function prototypes
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index 24fa3f7325f..c38c1c84a43 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_proc.h,v 1.130 2000/04/07 13:39:49 thomas Exp $
+ * $Id: pg_proc.h,v 1.131 2000/04/08 02:13:00 thomas Exp $
  *
  * NOTES
  *	  The script catalog/genbki.sh reads this file and generates .bki
@@ -1979,8 +1979,11 @@ DATA(insert OID = 1545 (  npoints			PGUID 11 f t t 1 f	23 "602" 100 0 0 100  pat
 DESCR("# points in path");
 DATA(insert OID = 1556 (  npoints			PGUID 11 f t t 1 f	23 "604" 100 0 0 100  poly_npoints - ));
 DESCR("number of points in polygon");
-DATA(insert OID = 1573 (  int8				PGUID 14 f t t 1 f	20 "20" 100 0 0 100  "select $1" - ));
-DESCR("convert int8 to int8 (no-op)");
+
+DATA(insert OID = 1564 (  zpbit_in			PGUID 11 f t t 1 f 1560 "0" 100 0 0 100  zpbit_in - ));
+DESCR("(internal)");
+DATA(insert OID = 1565 (  zpbit_out			PGUID 11 f t t 1 f   23 "0" 100 0 0 100  zpbit_out - ));
+DESCR("(internal)");
 
 DATA(insert OID = 1569 (  like				PGUID 11 f t t 2 f 16 "25 25" 100 0 1 0  textlike - ));
 DESCR("matches LIKE expression");
@@ -1990,6 +1993,9 @@ DATA(insert OID = 1571 (  like				PGUID 11 f t t 2 f 16 "19 25" 100 0 0 100  nam
 DESCR("matches LIKE expression");
 DATA(insert OID = 1572 (  notlike			PGUID 11 f t t 2 f 16 "19 25" 100 0 0 100  namenlike - ));
 DESCR("does not match LIKE expression");
+DATA(insert OID = 1573 (  int8				PGUID 14 f t t 1 f	20 "20" 100 0 0 100  "select $1" - ));
+DESCR("convert int8 to int8 (no-op)");
+
 
 /* SEQUENCEs nextval & currval functions */
 DATA(insert OID = 1574 (  nextval			PGUID 11 f t f 1 f 23 "25" 100 0 0 100  nextval - ));
@@ -1999,6 +2005,26 @@ DESCR("sequence current value");
 DATA(insert OID = 1576 (  setval			PGUID 11 f t f 2 f 23 "25 23" 100 0 0 100  setval - ));
 DESCR("sequence set value");
 
+DATA(insert OID = 1579 (  varbit_in			PGUID 11 f t t 1 f 1562 "0" 100 0 0 100  varbit_in - ));
+DESCR("(internal)");
+DATA(insert OID = 1580 (  varbit_out		PGUID 11 f t t 1 f   23 "0" 100 0 0 100  varbit_out - ));
+DESCR("(internal)");
+
+DATA(insert OID = 1581 (  biteq				PGUID 11 f t t 2 f 16 "1560 1560" 100 0 1 0  biteq - ));
+DESCR("equal");
+DATA(insert OID = 1582 (  bitne				PGUID 11 f t t 2 f 16 "1560 1560" 100 0 1 0  bitne - ));
+DESCR("not equal");
+DATA(insert OID = 1592 (  bitge				PGUID 11 f t t 2 f 16 "1560 1560" 100 0 1 0  bitge - ));
+DESCR("greater than or equal");
+DATA(insert OID = 1593 (  bitgt				PGUID 11 f t t 2 f 16 "1560 1560" 100 0 1 0  bitgt - ));
+DESCR("greater than");
+DATA(insert OID = 1594 (  bitle				PGUID 11 f t t 2 f 16 "1560 1560" 100 0 1 0  bitle - ));
+DESCR("less than or equal");
+DATA(insert OID = 1595 (  bitlt				PGUID 11 f t t 2 f 16 "1560 1560" 100 0 1 0  bitlt - ));
+DESCR("less than");
+DATA(insert OID = 1596 (  bitcmp			PGUID 11 f t t 2 f 23 "1560 1560" 100 0 1 0  bitcmp - ));
+DESCR("compare");
+
 DATA(insert OID = 1598 (  random			PGUID 11 f t f 0 f 701 "0" 100 0 0 100  drandom - ));
 DESCR("radians to degrees");
 DATA(insert OID = 1599 (  setseed			PGUID 11 f t t 1 f  23 "701" 100 0 0 100  setseed - ));
@@ -2159,6 +2185,55 @@ DESCR("referential integrity ON DELETE NO ACTION");
 DATA(insert OID = 1655 (  RI_FKey_noaction_upd PGUID 11 f t f 0 f 0 "" 100 0 0 100  RI_FKey_noaction_upd - ));
 DESCR("referential integrity ON UPDATE NO ACTION");
 
+DATA(insert OID = 1666 (  varbiteq			PGUID 11 f t t 2 f 16 "1562 1562" 100 0 1 0  varbiteq - ));
+DESCR("equal");
+DATA(insert OID = 1667 (  varbitne			PGUID 11 f t t 2 f 16 "1562 1562" 100 0 1 0  varbitne - ));
+DESCR("not equal");
+DATA(insert OID = 1668 (  varbitge			PGUID 11 f t t 2 f 16 "1562 1562" 100 0 1 0  varbitge - ));
+DESCR("greater than or equal");
+DATA(insert OID = 1669 (  varbitgt			PGUID 11 f t t 2 f 16 "1562 1562" 100 0 1 0  varbitgt - ));
+DESCR("greater than");
+DATA(insert OID = 1670 (  varbitle			PGUID 11 f t t 2 f 16 "1562 1562" 100 0 1 0  varbitle - ));
+DESCR("less than or equal");
+DATA(insert OID = 1671 (  varbitlt			PGUID 11 f t t 2 f 16 "1562 1562" 100 0 1 0  varbitlt - ));
+DESCR("less than");
+DATA(insert OID = 1672 (  varbitcmp			PGUID 11 f t t 2 f 23 "1562 1562" 100 0 1 0  varbitcmp - ));
+DESCR("compare");
+
+DATA(insert OID = 1673 (  bitand			PGUID 11 f t t 2 f 1560 "1560 1560" 100 0 1 0  bitand - ));
+DESCR("bitwise and");
+DATA(insert OID = 1674 (  bitor				PGUID 11 f t t 2 f 1560 "1560 1560" 100 0 1 0  bitor - ));
+DESCR("bitwise or");
+DATA(insert OID = 1675 (  bitxor			PGUID 11 f t t 2 f 1560 "1560 1560" 100 0 1 0  bitxor - ));
+DESCR("bitwise exclusive or");
+DATA(insert OID = 1676 (  bitnot			PGUID 11 f t t 2 f 1560 "1560 1560" 100 0 1 0  bitnot - ));
+DESCR("bitwise negation");
+DATA(insert OID = 1677 (  bitshiftright		PGUID 11 f t t 2 f 1560 "1560 1560" 100 0 1 0  bitshiftright - ));
+DESCR("bitwise right shift");
+DATA(insert OID = 1678 (  bitshiftleft		PGUID 11 f t t 2 f 1560 "1560 1560" 100 0 1 0  bitshiftleft - ));
+DESCR("bitwise left shift");
+DATA(insert OID = 1679 (  bitcat			PGUID 11 f t t 2 f 1560 "1560 1560" 100 0 1 0  bitcat - ));
+DESCR("bitwise concatenation");
+DATA(insert OID = 1680 (  bitsubstr			PGUID 11 f t t 2 f 1560 "1560 1560" 100 0 1 0  bitsubstr - ));
+DESCR("bitwise field");
+
+DATA(insert OID = 1681 (  varbitand			PGUID 11 f t t 2 f 1562 "1562 1562" 100 0 1 0  varbitand - ));
+DESCR("bitwise and");
+DATA(insert OID = 1682 (  varbitor			PGUID 11 f t t 2 f 1562 "1562 1562" 100 0 1 0  varbitor - ));
+DESCR("bitwise or");
+DATA(insert OID = 1683 (  varbitxor			PGUID 11 f t t 2 f 1562 "1562 1562" 100 0 1 0  varbitxor - ));
+DESCR("bitwise exclusive or");
+DATA(insert OID = 1684 (  varbitnot			PGUID 11 f t t 2 f 1562 "1562 1562" 100 0 1 0  varbitnot - ));
+DESCR("bitwise negation");
+DATA(insert OID = 1685 (  varbitshiftright	PGUID 11 f t t 2 f 1562 "1562 1562" 100 0 1 0  varbitshiftright - ));
+DESCR("bitwise right shift");
+DATA(insert OID = 1686 (  varbitshiftleft	PGUID 11 f t t 2 f 1562 "1562 1562" 100 0 1 0  varbitshiftleft - ));
+DESCR("bitwise left shift");
+DATA(insert OID = 1687 (  varbitcat			PGUID 11 f t t 2 f 1562 "1562 1562" 100 0 1 0  varbitcat - ));
+DESCR("bitwise concatenation");
+DATA(insert OID = 1688 (  varbitsubstr		PGUID 11 f t t 2 f 1562 "1562 1562" 100 0 1 0  varbitsubstr - ));
+DESCR("bitwise field");
+
 /* for mac type support */
 DATA(insert OID = 436 (  macaddr_in			PGUID 11 f t t 1 f 829 "0" 100 0 0 100	macaddr_in - ));
 DESCR("(internal)");
diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h
index d49ee9047ed..61bbfeab858 100644
--- a/src/include/catalog/pg_type.h
+++ b/src/include/catalog/pg_type.h
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_type.h,v 1.86 2000/03/18 20:50:10 momjian Exp $
+ * $Id: pg_type.h,v 1.87 2000/04/08 02:13:01 thomas Exp $
  *
  * NOTES
  *	  the genbki.sh script reads this file and generates .bki
@@ -382,16 +382,26 @@ DESCR("hh:mm:ss, ANSI SQL time");
 #define TIMETZOID		1266
 DATA(insert OID = 1270 ( _timetz	 PGUID	-1 -1 f b t \054 0	1266 array_in array_out array_in array_out d _null_ ));
 
+/* OIDS 1500 - 1599 */
+DATA(insert OID = 1560 ( bit         PGUID -1  -1 f b t \054 0  0 zpbit_in zpbit_out zpbit_in zpbit_out i _null_ ));
+DESCR("fixed-length bit string");
+#define ZPBITOID     1560
+DATA(insert OID = 1561 ( _bit        PGUID	-1 -1 f b t \054 0	1560 array_in array_out array_in array_out i _null_ ));
+DATA(insert OID = 1562 ( varbit      PGUID -1  -1 f b t \054 0  0 varbit_in varbit_out varbit_in varbit_out i _null_ ));
+DESCR("fixed-length bit string");
+#define VARBITOID     1562
+DATA(insert OID = 1563 ( _varbit     PGUID	-1 -1 f b t \054 0	1562 array_in array_out array_in array_out i _null_ ));
+
+/* OIDS 1600 - 1699 */
+DATA(insert OID = 1625 ( lztext      PGUID -1  -1 f b t \054 0  0 lztextin lztextout lztextin lztextout i _null_ ));
+DESCR("variable-length string, stored compressed");
+#define LZTEXTOID     1625
+
 /* OIDS 1700 - 1799 */
 DATA(insert OID = 1700 ( numeric	   PGUID -1  -1 f b t \054 0  0 numeric_in numeric_out numeric_in numeric_out i _null_ ));
 DESCR("numeric(precision, decimal), arbitrary precision number");
 #define NUMERICOID		1700
 
-/* OIDS 1625 - 1639 */
-DATA(insert OID = 1625 ( lztext      PGUID -1  -1 f b t \054 0  0 lztextin lztextout lztextin lztextout i _null_ ));
-DESCR("variable-length string, stored compressed");
-#define LZTEXTOID     1625
-
 #define VARLENA_FIXED_SIZE(attr)	((attr)->atttypid == BPCHAROID && (attr)->atttypmod > 0)
 
 /*
diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h
index 4e6cbaaace0..270187e9173 100644
--- a/src/include/utils/builtins.h
+++ b/src/include/utils/builtins.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: builtins.h,v 1.108 2000/04/07 13:40:12 thomas Exp $
+ * $Id: builtins.h,v 1.109 2000/04/08 02:13:10 thomas Exp $
  *
  * NOTES
  *	  This should normally only be included by fmgr.h.
@@ -36,6 +36,7 @@
 #include "utils/nabstime.h"
 #include "utils/date.h"
 #include "utils/lztext.h"
+#include "utils/varbit.h"
 
 /*
  *		Defined in adt/
diff --git a/src/include/utils/varbit.h b/src/include/utils/varbit.h
new file mode 100644
index 00000000000..9ee0724b01d
--- /dev/null
+++ b/src/include/utils/varbit.h
@@ -0,0 +1,87 @@
+#ifndef VARBIT_H
+#define VARBIT_H
+
+#include <math.h>
+
+#include "postgres.h"
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#ifndef MAXINT
+#define MAXINT INT_MAX
+#endif
+#else
+#ifdef HAVE_VALUES_H
+#include <values.h>
+#endif
+#endif
+#include "utils/builtins.h"
+
+
+#define HEXDIG(z)    (z)<10 ? ((z)+'0') : ((z)-10+'A')
+
+/* Modeled on struct varlena from postgres.h, bu data type is bits8 */
+struct varbita
+{
+	int32		vl_len;
+	bits8		vl_dat[1];
+};
+
+#define BITSPERBYTE		8
+#define VARBITHDRSZ		sizeof(int32)
+/* Number of bits in this bit string */
+#define VARBITLEN(PTR)		(((struct varbita *)VARDATA(PTR))->vl_len)
+/* Pointer tp the first byte containing bit string data */
+#define VARBITS(PTR)		(((struct varbita *)VARDATA(PTR))->vl_dat)
+/* Number of bytes in the data section of a bit string */
+#define VARBITBYTES(PTR)	(VARSIZE(PTR) - VARHDRSZ - VARBITHDRSZ)
+/* Padding of the bit string at the end */
+#define VARBITPAD(PTR)		(VARBITBYTES(PTR)*BITSPERBYTE - VARBITLEN(PTR))
+/* Number of bytes needed to store a bit string of a given length */
+#define VARBITDATALEN(BITLEN)	((BITLEN)/BITSPERBYTE + \
+				  ((BITLEN)%BITSPERBYTE > 0 ? 1 : 0) + \
+					VARHDRSZ + VARBITHDRSZ)
+/* pointer beyond the end of the bit string (like end() in STL containers) */
+#define VARBITEND(PTR)		((bits8 *) (PTR + VARSIZE(PTR)))
+/* Mask that will cover exactly one byte, i.e. BITSPERBYTE bits */
+#define BITMASK 0xFF
+#define BITHIGH 0x80
+
+
+bits8 * zpbit_in(char *s, int dummy,  int32 atttypmod);
+char * zpbit_out(bits8 *s);
+char * zpbits_out(bits8 *s);
+bits8 * varbit_in(char *s, int dummy,  int32 atttypmod);
+char * varbit_out (bits8 *s);
+bool biteq (bits8 *arg1, bits8 *arg2);
+bool bitne (bits8 *arg1, bits8 *arg2);
+bool bitge (bits8 *arg1, bits8 *arg2);
+bool bitgt (bits8 *arg1, bits8 *arg2);
+bool bitle (bits8 *arg1, bits8 *arg2);
+bool bitlt (bits8 *arg1, bits8 *arg2);
+int bitcmp (bits8 *arg1, bits8 *arg2);
+bits8 * bitand (bits8 * arg1, bits8 * arg2);
+bits8 * bitor (bits8 * arg1, bits8 * arg2);
+bits8 * bitxor (bits8 * arg1, bits8 * arg2);
+bits8 * bitnot (bits8 * arg);
+bits8 * bitshiftright (bits8 * arg, int shft);
+bits8 * bitshiftleft (bits8 * arg, int shft);
+bits8 * bitcat (bits8 *arg1, bits8 *arg2);
+bits8 * bitsubstr (bits8 *arg, int32 s, int32 l);
+
+bool varbiteq (bits8 *arg1, bits8 *arg2);
+bool varbitne (bits8 *arg1, bits8 *arg2);
+bool varbitge (bits8 *arg1, bits8 *arg2);
+bool varbitgt (bits8 *arg1, bits8 *arg2);
+bool varbitle (bits8 *arg1, bits8 *arg2);
+bool varbitlt (bits8 *arg1, bits8 *arg2);
+int varbitcmp (bits8 *arg1, bits8 *arg2);
+bits8 * varbitand (bits8 * arg1, bits8 * arg2);
+bits8 * varbitor (bits8 * arg1, bits8 * arg2);
+bits8 * varbitxor (bits8 * arg1, bits8 * arg2);
+bits8 * varbitnot (bits8 * arg);
+bits8 * varbitshiftright (bits8 * arg, int shft);
+bits8 * varbitshiftleft (bits8 * arg, int shft);
+bits8 * varbitcat (bits8 *arg1, bits8 *arg2);
+bits8 * varbitsubstr (bits8 *arg, int32 s, int32 l);
+
+#endif
-- 
GitLab