]> granicus.if.org Git - postgresql/commitdiff
First pass at integrating BIT and BIT VARYING code from Adriaan Joubert.
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 21 Aug 2000 04:48:57 +0000 (04:48 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 21 Aug 2000 04:48:57 +0000 (04:48 +0000)
Update functions to new-style fmgr, make BIT and VARBIT be binary-
equivalent, add entries to allow these types to be btree indexed,
correct a few bugs.  BIT/VARBIT are now toastable, too.
NOTE: initdb forced due to catalog updates.

src/backend/utils/adt/varbit.c
src/include/catalog/catversion.h
src/include/catalog/pg_amop.h
src/include/catalog/pg_amproc.h
src/include/catalog/pg_opclass.h
src/include/catalog/pg_operator.h
src/include/catalog/pg_proc.h
src/include/catalog/pg_type.h
src/include/parser/parse_coerce.h
src/include/utils/varbit.h
src/test/regress/expected/opr_sanity.out

index cba4085bd2a9e57be5a81c2953bfc75c0265e805..6437324c43257486746ea7342254f8f8e193f2d0 100644 (file)
 /*-------------------------------------------------------------------------
  *
  * varbit.c
- *       Functions for the built-in type bit() and varying bit().
+ *       Functions for the SQL datatypes BIT() and BIT VARYING().
+ *
+ * Code originally contributed by Adriaan Joubert.
+ *
+ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
+ * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/adt/varbit.c,v 1.7 2000/08/07 20:15:37 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/adt/varbit.c,v 1.8 2000/08/21 04:48:50 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 #include "postgres.h"
 
-/* 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 <limits.h>
-
-#include "fmgr.h"
-#include "utils/builtins.h"
+#include "catalog/pg_type.h"
+#include "utils/array.h"
+#include "utils/fmgroids.h"
 #include "utils/varbit.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);
-}
+#define HEXDIG(z)       ((z)<10 ? ((z)+'0') : ((z)-10+'A'))
+
+
+/*----------
+ *     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 -- length of the bit string in bits
+ *             bitdata   -- bit string, most significant byte first
+ *----------
+ */
 
 /*
  * zpbit_in -
- *       converts a string to the internal representation of a bitstring.
+ *       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.
- *       (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)
+Datum
+zpbit_in(PG_FUNCTION_ARGS)
 {
-       bits8      *result;                     /* the bits string that was read in   */
+       char       *s = PG_GETARG_CSTRING(0);
+#ifdef NOT_USED
+       Oid                     typelem = PG_GETARG_OID(1);
+#endif
+       int32           atttypmod = PG_GETARG_INT32(2);
+       VarBit     *result;                     /* The resulting bit string                       */
        char       *sp;                         /* pointer into the character string  */
-       bits8      *r;
+       bits8      *r;                          /* pointer into the result */
        int                     len,                    /* Length of the whole data structure */
                                bitlen,                 /* Number of bits in the bit string   */
                                slen;                   /* Length of the input string             */
-       int                     bit_not_hex = 0;/* 0 = hex string  1=bit string           */
+       bool            bit_not_hex;    /* false = hex string  true = 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;
+               bit_not_hex = true;
        else if (s[0] == 'x' || s[0] == 'X')
-               bit_not_hex = 0;
+               bit_not_hex = false;
        else
+       {
                elog(ERROR, "zpbit_in: %s is not a valid bitstring", s);
+               bit_not_hex = false;    /* keep compiler quiet */
+       }
 
        slen = strlen(s) - 1;
        /* Determine bitlength from input string */
-       bitlen = slen;
-       if (!bit_not_hex)
-               bitlen *= 4;
+       if (bit_not_hex)
+               bitlen = slen;
+       else
+               bitlen = slen * 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
+        * hex string gives an accurate length up to 4 bits
         */
-       if (atttypmod == -1)
+       if (atttypmod <= 0)
                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);
-
+       else if (bit_not_hex ? (bitlen > atttypmod) : (bitlen > atttypmod + 3))
+               elog(ERROR, "zpbit_in: bit string too long for bit(%d)",
+                        atttypmod);
 
-       len = VARBITDATALEN(atttypmod);
-
-       if (len > MaxAttrSize)
-               elog(ERROR, "zpbit_in: length of bit() must be less than %ld",
-                        (long) ((MaxAttrSize - VARHDRSZ - VARBITHDRSZ) * BITSPERBYTE));
-
-       result = (bits8 *) palloc(len);
-       /* set to 0 so that *r is always initialised and strin is zero-padded */
+       len = VARBITTOTALLEN(atttypmod);
+       result = (VarBit *) palloc(len);
+       /* set to 0 so that *r is always initialised and string is zero-padded */
        memset(result, 0, len);
        VARATT_SIZEP(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)
@@ -127,24 +111,24 @@ zpbit_in(char *s, int dummy, int32 atttypmod)
                /* 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++)
+               for (; *sp; sp++)
                {
                        if (*sp == '1')
                                *r |= x;
-                       if (bc == 7)
+                       else if (*sp != '0')
+                               elog(ERROR, "Cannot parse %c as a binary digit", *sp);
+                       x >>= 1;
+                       if (x == 0)
                        {
-                               bc = 0;
                                x = BITHIGH;
                                r++;
                        }
-                       else
-                               x >>= 1;
                }
        }
        else
        {
                /* Parse the hex representation of the string */
-               for (bc = 0; sp != s + slen + 1; sp++)
+               for (bc = 0; *sp; sp++)
                {
                        if (*sp >= '0' && *sp <= '9')
                                x = (bits8) (*sp - '0');
@@ -156,13 +140,13 @@ zpbit_in(char *s, int dummy, int32 atttypmod)
                                elog(ERROR, "Cannot parse %c as a hex digit", *sp);
                        if (bc)
                        {
-                               bc = 0;
                                *r++ |= x;
+                               bc = 0;
                        }
                        else
                        {
-                               bc++;
                                *r = x << 4;
+                               bc = 1;
                        }
                }
        }
@@ -170,19 +154,19 @@ zpbit_in(char *s, int dummy, int32 atttypmod)
        if (bitlen > atttypmod)
        {
                /* Check that this fitted */
-               r = (bits8 *) (result + len - 1);
+               r = VARBITEND(result) - 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",
+               if (((*r << (BITSPERBYTE - ipad)) & BITMASK) != 0)
+                       elog(ERROR, "zpbit_in: bit string too long for bit(%d)",
                                 atttypmod);
        }
 
-       return result;
+       PG_RETURN_VARBIT_P(result);
 }
 
 /* zpbit_out -
@@ -190,9 +174,10 @@ zpbit_in(char *s, int dummy, int32 atttypmod)
  *       to be more compact than bit strings, and consequently much more efficient
  *       for long strings
  */
-char *
-zpbit_out(bits8 *s)
+Datum
+zpbit_out(PG_FUNCTION_ARGS)
 {
+       VarBit     *s = PG_GETARG_VARBIT_P(0);
        char       *result,
                           *r;
        bits8      *sp;
@@ -200,180 +185,176 @@ zpbit_out(bits8 *s)
                                len,
                                bitlen;
 
-       if (s == NULL)
+       bitlen = VARBITLEN(s);
+       len = (bitlen + 3) / 4;
+       result = (char *) palloc(len + 2);
+       sp = VARBITS(s);
+       r = result;
+       *r++ = 'X';
+       /* we cheat by knowing that we store full bytes zero padded */
+       for (i = 0; i < len; i += 2, sp++)
        {
-               result = (char *) palloc(2);
-               result[0] = '-';
-               result[1] = '\0';
+               *r++ = HEXDIG((*sp) >> 4);
+               *r++ = HEXDIG((*sp) & 0xF);
        }
-       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;
+       /*
+        * Go back one step if we printed a hex number that was not part
+        * of the bitstring anymore
+        */
+       if (i > len)
+               r--;
+       *r = '\0';
+
+       PG_RETURN_CSTRING(result);
 }
 
-/* zpbits_out -
- *       Prints the string a bits
+/* zpbit()
+ * Converts a bit() type to a specific internal length.
+ * len is the bitlength specified in the column definition.
  */
-char *
-zpbits_out(bits8 *s)
+Datum
+zpbit(PG_FUNCTION_ARGS)
 {
-       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     *arg = PG_GETARG_VARBIT_P(0);
+       int32           len = PG_GETARG_INT32(1);
+       VarBit     *result;
+       int                     rlen;
+
+       /* No work if typmod is invalid or supplied data matches it already */
+       if (len <= 0 || len == VARBITLEN(arg))
+               PG_RETURN_VARBIT_P(arg);
+
+       rlen = VARBITTOTALLEN(len);
+       result = (VarBit *) palloc(rlen);
+       /* set to 0 so that result is zero-padded if input is shorter */
+       memset(result, 0, rlen);
+       VARATT_SIZEP(result) = rlen;
+       VARBITLEN(result) = len;
+
+       memcpy(VARBITS(result), VARBITS(arg),
+                  Min(VARBITBYTES(result), VARBITBYTES(arg)));
+
+       PG_RETURN_VARBIT_P(result);
 }
 
+/* _zpbit()
+ * Converts an array of bit() elements to a specific internal length.
+ * len is the bitlength specified in the column definition.
+ */
+Datum
+_zpbit(PG_FUNCTION_ARGS)
+{
+       ArrayType  *v = (ArrayType *) PG_GETARG_VARLENA_P(0);
+       int32           len = PG_GETARG_INT32(1);
+       FunctionCallInfoData    locfcinfo;
+       /*
+        * Since zpbit() is a built-in function, we should only need to
+        * look it up once per run.
+        */
+       static FmgrInfo                 zpbit_finfo;
+
+       if (zpbit_finfo.fn_oid == InvalidOid)
+               fmgr_info(F_ZPBIT, &zpbit_finfo);
+
+       MemSet(&locfcinfo, 0, sizeof(locfcinfo));
+       locfcinfo.flinfo = &zpbit_finfo;
+       locfcinfo.nargs = 2;
+       /* We assume we are "strict" and need not worry about null inputs */
+       locfcinfo.arg[0] = PointerGetDatum(v);
+       locfcinfo.arg[1] = Int32GetDatum(len);
+
+       return array_map(&locfcinfo, ZPBITOID, ZPBITOID);
+}
 
 /*
  * varbit_in -
  *       converts a string to the internal representation of a bitstring.
-*/
-bits8 *
-varbit_in(char *s, int dummy, int32 atttypmod)
+ *             This is the same as zpbit_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)
 {
-       bits8      *result;                     /* The resulting bit string                       */
+       char       *s = PG_GETARG_CSTRING(0);
+#ifdef NOT_USED
+       Oid                     typelem = PG_GETARG_OID(1);
+#endif
+       int32           atttypmod = PG_GETARG_INT32(2);
+       VarBit     *result;                     /* The resulting bit string                       */
        char       *sp;                         /* pointer into the character string  */
-       bits8      *r;
+       bits8      *r;                          /* pointer into the result */
        int                     len,                    /* Length of the whole data structure */
                                bitlen,                 /* Number of bits in the bit string   */
                                slen;                   /* Length of the input string             */
-       int                     bit_not_hex = 0;
+       bool            bit_not_hex;    /* false = hex string  true = 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;
+               bit_not_hex = true;
        else if (s[0] == 'x' || s[0] == 'X')
-               bit_not_hex = 0;
+               bit_not_hex = false;
        else
-               elog(ERROR, "zpbit_in: %s is not a valid bitstring", s);
+       {
+               elog(ERROR, "varbit_in: %s is not a valid bitstring", s);
+               bit_not_hex = false;    /* keep compiler quiet */
+       }
 
        slen = strlen(s) - 1;
        /* Determine bitlength from input string */
-       bitlen = slen;
-       if (!bit_not_hex)
-               bitlen *= 4;
+       if (bit_not_hex)
+               bitlen = slen;
+       else
+               bitlen = slen * 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
+        * hex string gives an accurate length up to 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",
-                        (long) ((MaxAttrSize - VARHDRSZ - VARBITHDRSZ) * BITSPERBYTE));
+       if (atttypmod <= 0)
+               atttypmod = bitlen;
+       else if (bit_not_hex ? (bitlen > atttypmod) : (bitlen > atttypmod + 3))
+               elog(ERROR, "varbit_in: bit string too long for bit varying(%d)",
+                        atttypmod);
 
-       result = (bits8 *) palloc(len);
-       /* set to 0 so that *r is always initialised and strin is zero-padded */
+       len = VARBITTOTALLEN(bitlen);
+       result = (VarBit *) palloc(len);
+       /* set to 0 so that *r is always initialised and string is zero-padded */
        memset(result, 0, len);
        VARATT_SIZEP(result) = len;
-       VARBITLEN(result) = bitlen;
+       VARBITLEN(result) = Min(bitlen, 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++)
+               for (; *sp; sp++)
                {
                        if (*sp == '1')
                                *r |= x;
-                       if (bc == 7)
+                       else if (*sp != '0')
+                               elog(ERROR, "Cannot parse %c as a binary digit", *sp);
+                       x >>= 1;
+                       if (x == 0)
                        {
-                               bc = 0;
                                x = BITHIGH;
                                r++;
                        }
-                       else
-                               x >>= 1;
                }
        }
        else
        {
-               for (bc = 0; sp != s + slen + 1; sp++)
+               /* Parse the hex representation of the string */
+               for (bc = 0; *sp; sp++)
                {
                        if (*sp >= '0' && *sp <= '9')
                                x = (bits8) (*sp - '0');
@@ -385,13 +366,13 @@ varbit_in(char *s, int dummy, int32 atttypmod)
                                elog(ERROR, "Cannot parse %c as a hex digit", *sp);
                        if (bc)
                        {
-                               bc = 0;
                                *r++ |= x;
+                               bc = 0;
                        }
                        else
                        {
-                               bc++;
                                *r = x << 4;
+                               bc = 1;
                        }
                }
        }
@@ -399,24 +380,115 @@ varbit_in(char *s, int dummy, int32 atttypmod)
        if (bitlen > atttypmod)
        {
                /* Check that this fitted */
-               r = (bits8 *) (result + len - 1);
+               r = VARBITEND(result) - 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",
+               if (((*r << (BITSPERBYTE - ipad)) & BITMASK) != 0)
+                       elog(ERROR, "varbit_in: bit string too long for bit varying(%d)",
                                 atttypmod);
        }
 
-       return result;
+       PG_RETURN_VARBIT_P(result);
 }
 
-/*
-  the zpbit_out routines are fine for varying bits as well
-*/
+/* varbit_out -
+ *       Prints the string as bits to preserve length accurately
+ */
+Datum
+varbit_out(PG_FUNCTION_ARGS)
+{
+       VarBit     *s = PG_GETARG_VARBIT_P(0);
+       char       *result,
+                          *r;
+       bits8      *sp;
+       bits8           x;
+       int                     i,
+                               k,
+                               len;
+
+       len = VARBITLEN(s);
+       result = (char *) palloc(len + 2);
+       sp = VARBITS(s);
+       r = result;
+       *r++ = 'B';
+       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 = '\0';
+
+       PG_RETURN_CSTRING(result);
+}
+
+/* varbit()
+ * Converts a varbit() type to a specific internal length.
+ * len is the maximum bitlength specified in the column definition.
+ */
+Datum
+varbit(PG_FUNCTION_ARGS)
+{
+       VarBit     *arg = PG_GETARG_VARBIT_P(0);
+       int32           len = PG_GETARG_INT32(1);
+       VarBit     *result;
+       int                     rlen;
+
+       /* No work if typmod is invalid or supplied data matches it already */
+       if (len <= 0 || len >= VARBITLEN(arg))
+               PG_RETURN_VARBIT_P(arg);
+
+       rlen = VARBITTOTALLEN(len);
+       result = (VarBit *) palloc(rlen);
+       VARATT_SIZEP(result) = rlen;
+       VARBITLEN(result) = len;
+
+       memcpy(VARBITS(result), VARBITS(arg), VARBITBYTES(result));
+
+       PG_RETURN_VARBIT_P(result);
+}
+
+/* _varbit()
+ * Converts an array of bit() elements to a specific internal length.
+ * len is the maximum bitlength specified in the column definition.
+ */
+Datum
+_varbit(PG_FUNCTION_ARGS)
+{
+       ArrayType  *v = (ArrayType *) PG_GETARG_VARLENA_P(0);
+       int32           len = PG_GETARG_INT32(1);
+       FunctionCallInfoData    locfcinfo;
+       /*
+        * Since varbit() is a built-in function, we should only need to
+        * look it up once per run.
+        */
+       static FmgrInfo                 varbit_finfo;
+
+       if (varbit_finfo.fn_oid == InvalidOid)
+               fmgr_info(F_VARBIT, &varbit_finfo);
+
+       MemSet(&locfcinfo, 0, sizeof(locfcinfo));
+       locfcinfo.flinfo = &varbit_finfo;
+       locfcinfo.nargs = 2;
+       /* We assume we are "strict" and need not worry about null inputs */
+       locfcinfo.arg[0] = PointerGetDatum(v);
+       locfcinfo.arg[1] = Int32GetDatum(len);
+
+       return array_map(&locfcinfo, VARBITOID, VARBITOID);
+}
 
 
 /*
@@ -432,63 +504,78 @@ varbit_in(char *s, int dummy, int32 atttypmod)
  *
  * 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.
  */
 
-bool
-biteq(bits8 *arg1, bits8 *arg2)
+Datum
+biteq(PG_FUNCTION_ARGS)
 {
+       VarBit     *arg1 = PG_GETARG_VARBIT_P(0);
+       VarBit     *arg2 = PG_GETARG_VARBIT_P(1);
+       bool            result;
        int                     bitlen1,
                                bitlen2;
 
-       if (!PointerIsValid(arg1) || !PointerIsValid(arg2))
-               return (bool) 0;
        bitlen1 = VARBITLEN(arg1);
        bitlen2 = VARBITLEN(arg2);
        if (bitlen1 != bitlen2)
-               return (bool) 0;
+               result = false;
+       else
+       {
+               /* bit strings are always stored in a full number of bytes */
+               result = memcmp(VARBITS(arg1), VARBITS(arg2), VARBITBYTES(arg1)) == 0;
+       }
+
+       PG_FREE_IF_COPY(arg1, 0);
+       PG_FREE_IF_COPY(arg2, 1);
 
-       /* bit strings are always stored in a full number of bytes */
-       return memcmp((void *) VARBITS(arg1), (void *) VARBITS(arg2),
-                                 VARBITBYTES(arg1)) == 0;
+       PG_RETURN_BOOL(result);
 }
 
-bool
-bitne(bits8 *arg1, bits8 *arg2)
+Datum
+bitne(PG_FUNCTION_ARGS)
 {
+       VarBit     *arg1 = PG_GETARG_VARBIT_P(0);
+       VarBit     *arg2 = PG_GETARG_VARBIT_P(1);
+       bool            result;
        int                     bitlen1,
                                bitlen2;
 
-       if (!PointerIsValid(arg1) || !PointerIsValid(arg2))
-               return (bool) 0;
        bitlen1 = VARBITLEN(arg1);
        bitlen2 = VARBITLEN(arg2);
        if (bitlen1 != bitlen2)
-               return (bool) 1;
+               result = true;
+       else
+       {
+               /* bit strings are always stored in a full number of bytes */
+               result = memcmp(VARBITS(arg1), VARBITS(arg2), VARBITBYTES(arg1)) != 0;
+       }
+
+       PG_FREE_IF_COPY(arg1, 0);
+       PG_FREE_IF_COPY(arg2, 1);
 
-       /* bit strings are always stored in a full number of bytes */
-       return memcmp((void *) VARBITS(arg1), (void *) VARBITS(arg2),
-                                 VARBITBYTES(arg1)) != 0;
+       PG_RETURN_BOOL(result);
 }
 
-/* bitcmp
+/* bit_cmp
  *
- * Compares two bitstrings and returns -1, 0, 1 depending on whether the first
+ * 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.
- *      Anything is equal to undefined.
  */
-int
-bitcmp(bits8 *arg1, bits8 *arg2)
+static int32
+bit_cmp(VarBit *arg1, VarBit *arg2)
 {
        int                     bitlen1,
                                bytelen1,
                                bitlen2,
                                bytelen2;
-       int                     cmp;
+       int32           cmp;
 
-       if (!PointerIsValid(arg1) || !PointerIsValid(arg2))
-               return (bool) 0;
        bytelen1 = VARBITBYTES(arg1);
        bytelen2 = VARBITBYTES(arg2);
 
@@ -498,63 +585,115 @@ bitcmp(bits8 *arg1, bits8 *arg2)
                bitlen1 = VARBITLEN(arg1);
                bitlen2 = VARBITLEN(arg2);
                if (bitlen1 != bitlen2)
-                       return bitlen1 < bitlen2 ? -1 : 1;
+                       cmp = (bitlen1 < bitlen2) ? -1 : 1;
        }
        return cmp;
 }
 
-bool
-bitlt(bits8 *arg1, bits8 *arg2)
+Datum
+bitlt(PG_FUNCTION_ARGS)
+{
+       VarBit     *arg1 = PG_GETARG_VARBIT_P(0);
+       VarBit     *arg2 = PG_GETARG_VARBIT_P(1);
+       bool            result;
+
+       result = (bit_cmp(arg1, arg2) < 0);
+
+       PG_FREE_IF_COPY(arg1, 0);
+       PG_FREE_IF_COPY(arg2, 1);
+
+       PG_RETURN_BOOL(result);
+}
+
+Datum
+bitle(PG_FUNCTION_ARGS)
 {
-       return (bool) (bitcmp(arg1, arg2) == -1);
+       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);
 }
 
-bool
-bitle(bits8 *arg1, bits8 *arg2)
+Datum
+bitgt(PG_FUNCTION_ARGS)
 {
-       return (bool) (bitcmp(arg1, arg2) <= 0);
+       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);
 }
 
-bool
-bitge(bits8 *arg1, bits8 *arg2)
+Datum
+bitge(PG_FUNCTION_ARGS)
 {
-       return (bool) (bitcmp(arg1, arg2) >= 0);
+       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);
 }
 
-bool
-bitgt(bits8 *arg1, bits8 *arg2)
+Datum
+bitcmp(PG_FUNCTION_ARGS)
 {
-       return (bool) (bitcmp(arg1, arg2) == 1);
+       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
  */
-bits8 *
-bitcat(bits8 *arg1, bits8 *arg2)
+Datum
+bitcat(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      *result;
        bits8      *pr,
                           *pa;
 
-       if (!PointerIsValid(arg1) || !PointerIsValid(arg2))
-               return NULL;
-
        bitlen1 = VARBITLEN(arg1);
        bitlen2 = VARBITLEN(arg2);
 
-       bytelen = VARBITDATALEN(bitlen1 + bitlen2);
+       bytelen = VARBITTOTALLEN(bitlen1 + bitlen2);
 
-       result = (bits8 *) palloc(bytelen * sizeof(bits8));
+       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)
@@ -564,11 +703,10 @@ bitcat(bits8 *arg1, bits8 *arg2)
        }
        else if (bitlen2 > 0)
        {
-               /* We need to shift all the results to fit */
+               /* We need to shift all the bits to fit */
                bit2shift = BITSPERBYTE - bit1pad;
-               pa = VARBITS(arg2);
                pr = VARBITS(result) + VARBITBYTES(arg1) - 1;
-               for (; pa < VARBITEND(arg2); pa++)
+               for (pa = VARBITS(arg2); pa < VARBITEND(arg2); pa++)
                {
                        *pr |= ((*pa >> bit2shift) & BITMASK);
                        pr++;
@@ -577,7 +715,7 @@ bitcat(bits8 *arg1, bits8 *arg2)
                }
        }
 
-       return result;
+       PG_RETURN_VARBIT_P(result);
 }
 
 /* bitsubstr
@@ -585,9 +723,13 @@ bitcat(bits8 *arg1, bits8 *arg2)
  * Note, s is 1-based.
  * SQL draft 6.10 9)
  */
-bits8 *
-bitsubstr(bits8 *arg, int32 s, int32 l)
+Datum
+bitsubstr(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,
@@ -597,44 +739,40 @@ bitsubstr(bits8 *arg, int32 s, int32 l)
        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;
+               /* 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 = VARBITDATALEN(rbitlen);
-               result = (bits8 *) palloc(len);
-               VARBITLEN(result) = rbitlen;
+               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) % BITSPERBYTE == 0)
                {
                        /* Yep, we are copying bytes */
-                       memcpy(VARBITS(result), VARBITS(arg) + (s1 - 1) / BITSPERBYTE, len);
+                       memcpy(VARBITS(result), VARBITS(arg) + (s1 - 1) / BITSPERBYTE,
+                                  len);
                }
                else
                {
@@ -659,172 +797,221 @@ bitsubstr(bits8 *arg, int32 s, int32 l)
                }
        }
 
-       return result;
+       PG_RETURN_VARBIT_P(result);
+}
+
+/* bitlength, bitoctetlength 
+ * Return the length of a bit string
+ */
+Datum
+bitlength(PG_FUNCTION_ARGS)
+{
+       VarBit     *arg = PG_GETARG_VARBIT_P(0);
+
+       PG_RETURN_INT32(VARBITLEN(arg));
+}
+
+Datum
+bitoctetlength(PG_FUNCTION_ARGS)
+{
+       VarBit     *arg = PG_GETARG_VARBIT_P(0);
+
+       PG_RETURN_INT32(VARBITBYTES(arg));
 }
 
 /* bitand
- * perform a logical AND on two bit strings. The result is automatically
- * truncated to the shorter bit string
+ * perform a logical AND on two bit strings.
  */
-bits8 *
-bitand(bits8 *arg1, bits8 *arg2)
+Datum
+bitand(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      *result;
        bits8      *p1,
                           *p2,
                           *r;
 
-       if (!PointerIsValid(arg1) || !PointerIsValid(arg2))
-               return (bool) 0;
-
-       len = Min(VARSIZE(arg1), VARSIZE(arg2));
-       result = (bits8 *) palloc(len);
+       bitlen1 = VARBITLEN(arg1);
+       bitlen2 = VARBITLEN(arg2);
+       if (bitlen1 != bitlen2)
+               elog(ERROR, "bitand: Cannot AND bitstrings of different sizes");
+       len = VARSIZE(arg1);
+       result = (VarBit *) palloc(len);
        VARATT_SIZEP(result) = len;
-       VARBITLEN(result) = Min(VARBITLEN(arg1), VARBITLEN(arg2));
+       VARBITLEN(result) = bitlen1;
 
-       p1 = (bits8 *) VARBITS(arg1);
-       p2 = (bits8 *) VARBITS(arg2);
-       r = (bits8 *) VARBITS(result);
-       for (i = 0; i < Min(VARBITBYTES(arg1), VARBITBYTES(arg2)); i++)
+       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 */
 
-       return result;
+       PG_RETURN_VARBIT_P(result);
 }
 
 /* bitor
- * perform a logical OR on two bit strings. The result is automatically
- * truncated to the shorter bit string.
+ * perform a logical OR on two bit strings.
  */
-bits8 *
-bitor(bits8 *arg1, bits8 *arg2)
+Datum
+bitor(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      *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);
+       bitlen1 = VARBITLEN(arg1);
+       bitlen2 = VARBITLEN(arg2);
+       if (bitlen1 != bitlen2)
+               elog(ERROR, "bitor: Cannot OR bitstrings of different sizes");
+       len = VARSIZE(arg1);
+       result = (VarBit *) palloc(len);
        VARATT_SIZEP(result) = len;
-       VARBITLEN(result) = Min(VARBITLEN(arg1), VARBITLEN(arg2));
+       VARBITLEN(result) = bitlen1;
 
-       p1 = (bits8 *) VARBITS(arg1);
-       p2 = (bits8 *) VARBITS(arg2);
-       r = (bits8 *) VARBITS(result);
-       for (i = 0; i < Min(VARBITBYTES(arg1), VARBITBYTES(arg2)); i++)
+       p1 = VARBITS(arg1);
+       p2 = VARBITS(arg2);
+       r = VARBITS(result);
+       for (i = 0; i < VARBITBYTES(arg1); i++)
                *r++ = *p1++ | *p2++;
 
        /* Pad the result */
        mask = BITMASK << VARBITPAD(result);
-       *r &= mask;
+       if (mask)
+       {
+               r--;
+               *r &= mask;
+       }
 
-       return result;
+       PG_RETURN_VARBIT_P(result);
 }
 
 /* bitxor
- * perform a logical XOR on two bit strings. The result is automatically
- * truncated to the shorter bit string.
+ * perform a logical XOR on two bit strings.
  */
-bits8 *
-bitxor(bits8 *arg1, bits8 *arg2)
+Datum
+bitxor(PG_FUNCTION_ARGS)
 {
+       VarBit     *arg1 = PG_GETARG_VARBIT_P(0);
+       VarBit     *arg2 = PG_GETARG_VARBIT_P(1);
+       VarBit     *result;
        int                     len,
+                               bitlen1,
+                               bitlen2,
                                i;
-       bits8      *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);
+       bitlen1 = VARBITLEN(arg1);
+       bitlen2 = VARBITLEN(arg2);
+       if (bitlen1 != bitlen2)
+               elog(ERROR, "bitxor: Cannot XOR bitstrings of different sizes");
+       len = VARSIZE(arg1);
+       result = (VarBit *) palloc(len);
        VARATT_SIZEP(result) = len;
-       VARBITLEN(result) = Min(VARBITLEN(arg1), VARBITLEN(arg2));
+       VARBITLEN(result) = bitlen1;
 
-       p1 = (bits8 *) VARBITS(arg1);
-       p2 = (bits8 *) VARBITS(arg2);
-       r = (bits8 *) VARBITS(result);
-       for (i = 0; i < Min(VARBITBYTES(arg1), VARBITBYTES(arg2)); i++)
+       p1 = VARBITS(arg1);
+       p2 = VARBITS(arg2);
+       r = VARBITS(result);
+       for (i = 0; i < VARBITBYTES(arg1); i++)
                *r++ = *p1++ ^ *p2++;
 
        /* Pad the result */
        mask = BITMASK << VARBITPAD(result);
-       *r &= mask;
+       if (mask)
+       {
+               r--;
+               *r &= mask;
+       }
 
-       return result;
+       PG_RETURN_VARBIT_P(result);
 }
 
 /* bitnot
- * perform a logical NOT on a bit strings.
+ * perform a logical NOT on a bit string.
  */
-bits8 *
-bitnot(bits8 *arg)
+Datum
+bitnot(PG_FUNCTION_ARGS)
 {
-       bits8      *result;
+       VarBit     *arg = PG_GETARG_VARBIT_P(0);
+       VarBit     *result;
        bits8      *p,
                           *r;
        bits8           mask;
 
-       if (!PointerIsValid(arg))
-               return (bool) 0;
-
-       result = (bits8 *) palloc(VARSIZE(arg));
+       result = (VarBit *) palloc(VARSIZE(arg));
        VARATT_SIZEP(result) = VARSIZE(arg);
        VARBITLEN(result) = VARBITLEN(arg);
 
-       p = (bits8 *) VARBITS(arg);
-       r = (bits8 *) VARBITS(result);
-       for (; p < VARBITEND(arg); p++, r++)
-               *r = ~*p;
+       p = VARBITS(arg);
+       r = VARBITS(result);
+       for (; p < VARBITEND(arg); p++)
+               *r++ = ~ *p;
 
        /* Pad the result */
        mask = BITMASK << VARBITPAD(result);
-       *r &= mask;
+       if (mask)
+       {
+               r--;
+               *r &= mask;
+       }
 
-       return result;
+       PG_RETURN_VARBIT_P(result);
 }
 
 /* bitshiftleft
- * do a left shift (i.e. to the beginning of the string) of the bit string
+ * do a left shift (i.e. towards the beginning of the string)
  */
-bits8 *
-bitshiftleft(bits8 *arg, int shft)
+Datum
+bitshiftleft(PG_FUNCTION_ARGS)
 {
+       VarBit     *arg = PG_GETARG_VARBIT_P(0);
+       int32           shft = PG_GETARG_INT32(1);
+       VarBit     *result;
        int                     byte_shift,
                                ishift,
                                len;
-       bits8      *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);
+               PG_RETURN_DATUM(DirectFunctionCall2(bitshiftright,
+                                                                                       VarBitPGetDatum(arg),
+                                                                                       Int32GetDatum(-shft)));
 
-       result = (bits8 *) palloc(VARSIZE(arg));
+       result = (VarBit *) palloc(VARSIZE(arg));
        VARATT_SIZEP(result) = VARSIZE(arg);
        VARBITLEN(result) = VARBITLEN(arg);
-       r = (bits8 *) VARBITS(result);
+       r = VARBITS(result);
+
+       /* If we shifted all the bits out, return an all-zero string */
+       if (shft >= VARBITLEN(arg))
+       {
+               memset(r, 0, VARBITBYTES(arg));
+               PG_RETURN_VARBIT_P(result);
+       }
 
        byte_shift = shft / BITSPERBYTE;
        ishift = shft % BITSPERBYTE;
-       p = ((bits8 *) VARBITS(arg)) + byte_shift;
+       p = VARBITS(arg) + byte_shift;
 
        if (ishift == 0)
        {
@@ -842,54 +1029,63 @@ bitshiftleft(bits8 *arg, int shft)
                                *r |= *p >> (BITSPERBYTE - ishift);
                }
                for (; r < VARBITEND(result); r++)
-                       *r = (bits8) 0;
+                       *r = 0;
        }
 
-       return result;
+       PG_RETURN_VARBIT_P(result);
 }
 
 /* bitshiftright
- * do a right shift (i.e. to the beginning of the string) of the bit string
+ * do a right shift (i.e. towards the end of the string)
  */
-bits8 *
-bitshiftright(bits8 *arg, int shft)
+Datum
+bitshiftright(PG_FUNCTION_ARGS)
 {
+       VarBit     *arg = PG_GETARG_VARBIT_P(0);
+       int32           shft = PG_GETARG_INT32(1);
+       VarBit     *result;
        int                     byte_shift,
                                ishift,
                                len;
-       bits8      *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);
+               PG_RETURN_DATUM(DirectFunctionCall2(bitshiftleft,
+                                                                                       VarBitPGetDatum(arg),
+                                                                                       Int32GetDatum(-shft)));
 
-       result = (bits8 *) palloc(VARSIZE(arg));
+       result = (VarBit *) palloc(VARSIZE(arg));
        VARATT_SIZEP(result) = VARSIZE(arg);
        VARBITLEN(result) = VARBITLEN(arg);
-       r = (bits8 *) VARBITS(result);
+       r = VARBITS(result);
+
+       /* If we shifted all the bits out, return an all-zero string */
+       if (shft >= VARBITLEN(arg))
+       {
+               memset(r, 0, VARBITBYTES(arg));
+               PG_RETURN_VARBIT_P(result);
+       }
 
        byte_shift = shft / BITSPERBYTE;
        ishift = shft % BITSPERBYTE;
-       p = (bits8 *) VARBITS(arg);
+       p = VARBITS(arg);
 
        /* Set the first part of the result to 0 */
        memset(r, 0, byte_shift);
+       r += byte_shift;
 
        if (ishift == 0)
        {
                /* Special case: we can do a memcpy */
                len = VARBITBYTES(arg) - byte_shift;
-               memcpy(r + byte_shift, p, len);
+               memcpy(r, p, len);
        }
        else
        {
-               r += byte_shift;
-               *r = 0;                                 /* Initialise first byte */
+               if (r < VARBITEND(result))
+                       *r = 0;                         /* initialize first byte */
                for (; r < VARBITEND(result); p++)
                {
                        *r |= *p >> ishift;
@@ -898,95 +1094,55 @@ bitshiftright(bits8 *arg, int shft)
                }
        }
 
-       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);
+       PG_RETURN_VARBIT_P(result);
 }
 
-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)
+/* 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)
 {
-       return bitnot(arg);
-}
+       int32           a = PG_GETARG_INT32(0);
+       VarBit     *result;
+       bits8      *r;
+       int                     len;
+  
+       /* allocate enough space for the bits in an int4 */
+       len = VARBITTOTALLEN(sizeof(int4)*BITSPERBYTE);
+       result = (VarBit *) palloc(len);
+       VARATT_SIZEP(result) = len;
+       VARBITLEN(result) = sizeof(int4)*BITSPERBYTE;
+       /* masks and shifts here are just too painful and we know that an int4 has
+        * got 4 bytes
+        */
+       r = VARBITS(result);
+       r[0] = (bits8) ((a >> (3*BITSPERBYTE)) & BITMASK);
+       r[1] = (bits8) ((a >> (2*BITSPERBYTE)) & BITMASK);
+       r[2] = (bits8) ((a >> (1*BITSPERBYTE)) & BITMASK);
+       r[3] = (bits8) (a & BITMASK);
 
-bits8 *
-varbitshiftright(bits8 *arg, int shft)
-{
-       return bitshiftright(arg, shft);
+       PG_RETURN_VARBIT_P(result);
 }
 
-bits8 *
-varbitshiftleft(bits8 *arg, int shft)
+Datum
+bittoint4(PG_FUNCTION_ARGS)
 {
-       return bitshiftleft(arg, shft);
-}
+       VarBit     *arg = PG_GETARG_VARBIT_P(0);
+       uint32          result;
+       bits8      *r;
 
-bits8 *
-varbitcat(bits8 *arg1, bits8 *arg2)
-{
-       return bitcat(arg1, arg2);
-}
+       /* Check that the bit string is not too long */
+       if (VARBITLEN(arg) > sizeof(int4)*BITSPERBYTE) 
+               elog(ERROR, "Bit string is too large to fit in an int4");
+       result = 0;
+       for (r = VARBITS(arg); r < VARBITEND(arg); r++)
+       {
+               result <<= BITSPERBYTE;
+               result |= *r;
+       }
+       /* Now shift the result to take account of the padding at the end */
+       result >>= VARBITPAD(arg);
 
-bits8 *
-varbitsubstr(bits8 *arg, int32 s, int32 l)
-{
-       return bitsubstr(arg, s, l);
+       PG_RETURN_INT32(result);
 }
index e69b5753e3a212d71b07ce94d45bd3edcedd0977..62c1c837e1a5905530a58d47c0059b284a0c498c 100644 (file)
@@ -37,7 +37,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: catversion.h,v 1.41 2000/08/08 15:42:33 tgl Exp $
+ * $Id: catversion.h,v 1.42 2000/08/21 04:48:51 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,6 +53,6 @@
  */
 
 /*                                                     yyyymmddN */
-#define CATALOG_VERSION_NO     200008071
+#define CATALOG_VERSION_NO     200008201
 
 #endif
index 9176820bc07c338e82398c303f2783ea0b3539a8..a8d0700b6b1a41926da3df3d028710069131453d 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_amop.h,v 1.35 2000/07/30 22:13:59 tgl Exp $
+ * $Id: pg_amop.h,v 1.36 2000/08/21 04:48:51 tgl Exp $
  *
  * NOTES
  *      the genbki.sh script reads this file and generates .bki
@@ -259,7 +259,6 @@ DATA(insert OID = 0 (  403 1114 1093 3 ));
 DATA(insert OID = 0 (  403 1114 1098 4 ));
 DATA(insert OID = 0 (  403 1114 1097 5 ));
 
-
 /*
  *     nbtree time_ops
  */
@@ -350,6 +349,26 @@ DATA(insert OID = 0 (  403 1690   91 3 ));
 DATA(insert OID = 0 (  403 1690 1695 4 ));
 DATA(insert OID = 0 (  403 1690   59 5 ));
 
+/*
+ *     nbtree bit
+ */
+
+DATA(insert OID = 0 (  403  424 1786 1 ));
+DATA(insert OID = 0 (  403  424 1788 2 ));
+DATA(insert OID = 0 (  403  424 1784 3 ));
+DATA(insert OID = 0 (  403  424 1789 4 ));
+DATA(insert OID = 0 (  403  424 1787 5 ));
+
+/*
+ *     nbtree varbit
+ */
+
+DATA(insert OID = 0 (  403  425 1806 1 ));
+DATA(insert OID = 0 (  403  425 1808 2 ));
+DATA(insert OID = 0 (  403  425 1804 3 ));
+DATA(insert OID = 0 (  403  425 1809 4 ));
+DATA(insert OID = 0 (  403  425 1807 5 ));
+
 
 /*
  *     hash table _ops
index 7b03f3c9b2a40bbebc9e8d0a3301f52fa617af27..dcca94f7f83afd42ecf82bdd13b202982a23eacc 100644 (file)
@@ -10,7 +10,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_amproc.h,v 1.24 2000/07/30 22:13:59 tgl Exp $
+ * $Id: pg_amproc.h,v 1.25 2000/08/21 04:48:51 tgl Exp $
  *
  * NOTES
  *       the genbki.sh script reads this file and generates .bki
@@ -99,7 +99,8 @@ DATA(insert OID = 0 (403  652  926 1));
 DATA(insert OID = 0 (403 1768 1769 1));
 DATA(insert OID = 0 (403 1690 1693 1));
 DATA(insert OID = 0 (403 1399 1358 1));
-
+DATA(insert OID = 0 (403  424 1596 1));
+DATA(insert OID = 0 (403  425 1672 1));
 
 
 /* hash */
index 277301d77d21cd1c6b05208a15f4ea373bd1e82f..47c07f1ce6e512e9785de1a9cbac3505f78401f8 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_opclass.h,v 1.35 2000/07/30 22:13:59 tgl Exp $
+ * $Id: pg_opclass.h,v 1.36 2000/08/21 04:48:51 tgl Exp $
  *
  * NOTES
  *       the genbki.sh script reads this file and generates .bki
@@ -119,5 +119,9 @@ DATA(insert OID = 1690 (    bool_ops                 16   ));
 DESCR("");
 DATA(insert OID = 1399 (       timetz_ops         1266   ));
 DESCR("");
+DATA(insert OID =  424 (       bit_ops            1560   ));
+DESCR("");
+DATA(insert OID =  425 (       varbit_ops         1562   ));
+DESCR("");
 
 #endif  /* PG_OPCLASS_H */
index 3981059426b37660d7c74163ce2ce8745f68cd34..746dd30043421941ad37511011bec5f523b56b15 100644 (file)
@@ -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.80 2000/08/12 05:15:22 tgl Exp $
+ * $Id: pg_operator.h,v 1.81 2000/08/21 04:48:51 tgl Exp $
  *
  * NOTES
  *       the genbki.sh script reads this file and generates .bki
@@ -306,8 +306,8 @@ DATA(insert OID = 622 (  "<"           PGUID 0 b t f  700  700      16 623 625      0 0 float4lt
 DATA(insert OID = 623 (  ">"      PGUID 0 b t f  700  700      16 622 624      0 0 float4gt scalargtsel scalargtjoinsel ));
 DATA(insert OID = 624 (  "<="     PGUID 0 b t f  700  700      16 625 623      0 0 float4le scalarltsel scalarltjoinsel ));
 DATA(insert OID = 625 (  ">="     PGUID 0 b t f  700  700      16 624 622      0 0 float4ge scalargtsel scalargtjoinsel ));
-DATA(insert OID = 626 (  "!!="    PGUID 0 b t f  23   19       16 0   0        0       0       int4notin - - ));
-DATA(insert OID = 627 (  "!!="    PGUID 0 b t f  26   19       16 0   0        0       0       oidnotin - - ));
+DATA(insert OID = 626 (  "!!="    PGUID 0 b t f  23   25       16 0   0        0       0       int4notin - - ));
+DATA(insert OID = 627 (  "!!="    PGUID 0 b t f  26   25       16 0   0        0       0       oidnotin - - ));
 DATA(insert OID = 630 (  "<>"     PGUID 0 b t f  18  18  16 630  92  0 0 charne neqsel neqjoinsel ));
 
 DATA(insert OID = 631 (  "<"      PGUID 0 b t f  18  18  16 633 634  0 0 charlt scalarltsel scalarltjoinsel ));
@@ -711,13 +711,12 @@ DATA(insert OID = 1786 (  "<"       PGUID 0 b t f 1560 1560       16 1787 1789    0        0 bitlt
 DATA(insert OID = 1787 (  ">"    PGUID 0 b t f 1560 1560       16 1786 1788    0        0 bitgt scalargtsel scalargtjoinsel ));
 DATA(insert OID = 1788 (  "<="   PGUID 0 b t f 1560 1560       16 1789 1787    0        0 bitle scalarltsel scalarltjoinsel ));
 DATA(insert OID = 1789 (  ">="   PGUID 0 b t f 1560 1560       16 1788 1786    0        0 bitge scalargtsel scalargtjoinsel ));
-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 = 1791 (  "&"    PGUID 0 b t f 1560 1560 1560 1791    0        0        0 bitand - - ));
+DATA(insert OID = 1792 (  "|"    PGUID 0 b t f 1560 1560 1560 1792    0        0        0 bitor - - ));
+DATA(insert OID = 1793 (  "^"    PGUID 0 b t f 1560 1560 1560 1793    0        0        0 bitxor - - ));
+DATA(insert OID = 1794 (  "~"    PGUID 0 l t f    0 1560 1560    0    0        0        0 bitnot - - ));
+DATA(insert OID = 1795 (  "<<"   PGUID 0 b t f 1560   23 1560    0    0        0        0 bitshiftleft - - ));
+DATA(insert OID = 1796 (  ">>"   PGUID 0 b t f 1560   23 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 ));
@@ -726,14 +725,6 @@ DATA(insert OID = 1806 (  "<"        PGUID 0 b t f 1562 1562       16 1807 1809    0        0 varbit
 DATA(insert OID = 1807 (  ">"    PGUID 0 b t f 1562 1562       16 1806 1808    0        0 varbitgt scalargtsel scalargtjoinsel ));
 DATA(insert OID = 1808 (  "<="   PGUID 0 b t f 1562 1562       16 1809 1807    0        0 varbitle scalarltsel scalarltjoinsel ));
 DATA(insert OID = 1809 (  ">="   PGUID 0 b t f 1562 1562       16 1808 1806    0        0 varbitge scalargtsel scalargtjoinsel ));
-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 - - ));
 
 DATA(insert OID = 1862 ( "="      PGUID 0 b t f  21  20  16 1868  1863  95 412 int28eq eqsel eqjoinsel ));
 DATA(insert OID = 1863 ( "<>"     PGUID 0 b t f  21  20  16 1869  1862   0   0 int28ne neqsel neqjoinsel ));
index 9f616dbc10158110eb12bd36cd5def081952bb26..1af007d7488d265f9b31c5b70b1ffedb7141a220 100644 (file)
@@ -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.161 2000/08/06 18:06:13 thomas Exp $
+ * $Id: pg_proc.h,v 1.162 2000/08/21 04:48:51 tgl Exp $
  *
  * NOTES
  *       The script catalog/genbki.sh reads this file and generates .bki
@@ -167,7 +167,7 @@ DATA(insert OID =  65 (  int4eq                        PGUID 12 f t t t 2 f 16 "23 23" 100 0 0 100
 DESCR("equal");
 DATA(insert OID =  66 (  int4lt                           PGUID 12 f t t t 2 f 16 "23 23" 100 0 0 100  int4lt - ));
 DESCR("less-than");
-DATA(insert OID =  67 (  texteq                           PGUID 12 f t t t 2 f 16 "25 25" 100 0 0 0    texteq - ));
+DATA(insert OID =  67 (  texteq                           PGUID 12 f t t t 2 f 16 "25 25" 100 0 0 100  texteq - ));
 DESCR("equal");
 DATA(insert OID =  68 (  xideq                    PGUID 12 f t t t 2 f 16 "28 28" 100 0 0 100  xideq - ));
 DESCR("equal");
@@ -196,13 +196,13 @@ DATA(insert OID =  79 (  nameregexeq         PGUID 12 f t t t 2 f 16 "19 25" 100 0 0
 DESCR("matches regex., case-sensitive");
 DATA(insert OID = 1252 (  nameregexne     PGUID 12 f t t t 2 f 16 "19 25" 100 0 0 100  nameregexne - ));
 DESCR("does not match regex., case-sensitive");
-DATA(insert OID = 1254 (  textregexeq     PGUID 12 f t t t 2 f 16 "25 25" 100 0 1 0    textregexeq - ));
+DATA(insert OID = 1254 (  textregexeq     PGUID 12 f t t t 2 f 16 "25 25" 100 0 0 100  textregexeq - ));
 DESCR("matches regex., case-sensitive");
-DATA(insert OID = 1256 (  textregexne     PGUID 12 f t t t 2 f 16 "25 25" 100 0 1 0    textregexne - ));
+DATA(insert OID = 1256 (  textregexne     PGUID 12 f t t t 2 f 16 "25 25" 100 0 0 100  textregexne - ));
 DESCR("does not match regex., case-sensitive");
-DATA(insert OID = 1257 (  textlen                 PGUID 12 f t t t 1 f 23 "25" 100 0 0  textlen - ));
+DATA(insert OID = 1257 (  textlen                 PGUID 12 f t t t 1 f 23 "25" 100 0 0 100  textlen - ));
 DESCR("length");
-DATA(insert OID = 1258 (  textcat                 PGUID 12 f t t t 2 f 25 "25 25" 100 0 1 0    textcat - ));
+DATA(insert OID = 1258 (  textcat                 PGUID 12 f t t t 2 f 25 "25 25" 100 0 0 100  textcat - ));
 DESCR("concatenate");
 
 DATA(insert OID =  84 (  boolne                           PGUID 12 f t t t 2 f 16 "16 16" 100 0 0 100  boolne - ));
@@ -243,9 +243,9 @@ DESCR("convert int2 to text");
 DATA(insert OID = 114 (  text                     PGUID 12 f t t t 1 f  25 "26" 100 0 0 100    oid_text - ));
 DESCR("convert oid to text");
 
-DATA(insert OID = 115 (  box_above                PGUID 12 f t t t 2 f  16 "603 603" 100 1 0 100  box_above - ));
+DATA(insert OID = 115 (  box_above                PGUID 12 f t t t 2 f  16 "603 603" 100 0 0 100  box_above - ));
 DESCR("is above");
-DATA(insert OID = 116 (  box_below                PGUID 12 f t t t 2 f  16 "603 603" 100 1 0 100  box_below - ));
+DATA(insert OID = 116 (  box_below                PGUID 12 f t t t 2 f  16 "603 603" 100 0 0 100  box_below - ));
 DESCR("is below");
 
 DATA(insert OID = 117 (  point_in                 PGUID 12 f t t t 1 f 600 "0" 100 0 0 100  point_in - ));
@@ -264,17 +264,17 @@ DATA(insert OID = 123 (  box_in                      PGUID 12 f t t t 1 f 603 "0" 100 0 0 100  b
 DESCR("(internal)");
 DATA(insert OID = 124 (  box_out                  PGUID 12 f t t t 1 f 23  "0" 100 0 0 100  box_out - ));
 DESCR("(internal)");
-DATA(insert OID = 125 (  box_overlap      PGUID 12 f t t t 2 f 16 "603 603" 100 1 0 100        box_overlap - ));
+DATA(insert OID = 125 (  box_overlap      PGUID 12 f t t t 2 f 16 "603 603" 100 0 0 100        box_overlap - ));
 DESCR("overlaps");
-DATA(insert OID = 126 (  box_ge                           PGUID 12 f t t t 2 f 16 "603 603" 100 1 0 100        box_ge - ));
+DATA(insert OID = 126 (  box_ge                           PGUID 12 f t t t 2 f 16 "603 603" 100 0 0 100        box_ge - ));
 DESCR("greater-than-or-equal by area");
-DATA(insert OID = 127 (  box_gt                           PGUID 12 f t t t 2 f 16 "603 603" 100 1 0 100        box_gt - ));
+DATA(insert OID = 127 (  box_gt                           PGUID 12 f t t t 2 f 16 "603 603" 100 0 0 100        box_gt - ));
 DESCR("greater-than by area");
-DATA(insert OID = 128 (  box_eq                           PGUID 12 f t t t 2 f 16 "603 603" 100 1 0 100        box_eq - ));
+DATA(insert OID = 128 (  box_eq                           PGUID 12 f t t t 2 f 16 "603 603" 100 0 0 100        box_eq - ));
 DESCR("equal by area");
-DATA(insert OID = 129 (  box_lt                           PGUID 12 f t t t 2 f 16 "603 603" 100 1 0 100        box_lt - ));
+DATA(insert OID = 129 (  box_lt                           PGUID 12 f t t t 2 f 16 "603 603" 100 0 0 100        box_lt - ));
 DESCR("less-than by area");
-DATA(insert OID = 130 (  box_le                           PGUID 12 f t t t 2 f 16 "603 603" 100 1 0 100        box_le - ));
+DATA(insert OID = 130 (  box_le                           PGUID 12 f t t t 2 f 16 "603 603" 100 0 0 100        box_le - ));
 DESCR("less-than-or-equal by area");
 DATA(insert OID = 131 (  point_above      PGUID 12 f t t t 2 f 16 "600 600" 100 0 0 100        point_above - ));
 DESCR("is above");
@@ -288,9 +288,9 @@ DATA(insert OID = 135 (  point_eq              PGUID 12 f t t t 2 f 16 "600 600" 100 0 0
 DESCR("same as");
 DATA(insert OID = 136 (  on_pb                    PGUID 12 f t t t 2 f 16 "600 603" 100 0 0 100        on_pb - ));
 DESCR("point is inside");
-DATA(insert OID = 137 (  on_ppath                 PGUID 12 f t t t 2 f 16 "600 602" 100 0 0  on_ppath - ));
+DATA(insert OID = 137 (  on_ppath                 PGUID 12 f t t t 2 f 16 "600 602" 100 0 0 100  on_ppath - ));
 DESCR("contained in");
-DATA(insert OID = 138 (  box_center               PGUID 12 f t t t 1 f 600 "603" 100 1 0 100  box_center - ));
+DATA(insert OID = 138 (  box_center               PGUID 12 f t t t 1 f 600 "603" 100 0 0 100  box_center - ));
 DESCR("center of");
 DATA(insert OID = 139 (  areasel                  PGUID 12 f t f t 5 f 701 "26 26 21 0 23" 100 0 0 100  areasel - ));
 DESCR("restriction selectivity for area-comparison operators");
@@ -326,7 +326,7 @@ DATA(insert OID = 155 (  int2mod               PGUID 12 f t t t 2 f 21 "21 21" 100 0 0 100
 DESCR("modulus");
 DATA(insert OID = 156 (  int4mod                  PGUID 12 f t t t 2 f 23 "23 23" 100 0 0 100  int4mod - ));
 DESCR("modulus");
-DATA(insert OID = 157 (  textne                           PGUID 12 f t t t 2 f 16 "25 25" 100 0 0 0    textne - ));
+DATA(insert OID = 157 (  textne                           PGUID 12 f t t t 2 f 16 "25 25" 100 0 0 100  textne - ));
 DESCR("not equal");
 DATA(insert OID = 158 (  int24eq                  PGUID 12 f t t t 2 f 16 "21 23" 100 0 0 100  int24eq - ));
 DESCR("equal");
@@ -707,25 +707,25 @@ DESCR("btree(internal)");
 DATA(insert OID = 338 (  btbuild                  PGUID 12 f t f t 5 f 23 "0 0 0 0 0" 100 0 0 100  btbuild - ));
 DESCR("btree(internal)");
 
-DATA(insert OID = 339 (  poly_same                PGUID 12 f t t t 2 f 16 "604 604" 100 0 0  poly_same - ));
+DATA(insert OID = 339 (  poly_same                PGUID 12 f t t t 2 f 16 "604 604" 100 0 0 100  poly_same - ));
 DESCR("same as");
-DATA(insert OID = 340 (  poly_contain     PGUID 12 f t t t 2 f 16 "604 604" 100 0 0  poly_contain - ));
+DATA(insert OID = 340 (  poly_contain     PGUID 12 f t t t 2 f 16 "604 604" 100 0 0 100  poly_contain - ));
 DESCR("contains");
-DATA(insert OID = 341 (  poly_left                PGUID 12 f t t t 2 f 16 "604 604" 100 0 0  poly_left - ));
+DATA(insert OID = 341 (  poly_left                PGUID 12 f t t t 2 f 16 "604 604" 100 0 0 100  poly_left - ));
 DESCR("is left of");
-DATA(insert OID = 342 (  poly_overleft    PGUID 12 f t t t 2 f 16 "604 604" 100 0 0  poly_overleft - ));
+DATA(insert OID = 342 (  poly_overleft    PGUID 12 f t t t 2 f 16 "604 604" 100 0 0 100  poly_overleft - ));
 DESCR("overlaps, but does not extend to right of");
-DATA(insert OID = 343 (  poly_overright    PGUID 12 f t t t 2 f 16 "604 604" 100 0 0  poly_overright - ));
+DATA(insert OID = 343 (  poly_overright    PGUID 12 f t t t 2 f 16 "604 604" 100 0 0 100  poly_overright - ));
 DESCR("overlaps, but does not extend to left of");
-DATA(insert OID = 344 (  poly_right               PGUID 12 f t t t 2 f 16 "604 604" 100 0 0  poly_right - ));
+DATA(insert OID = 344 (  poly_right               PGUID 12 f t t t 2 f 16 "604 604" 100 0 0 100  poly_right - ));
 DESCR("is right of");
-DATA(insert OID = 345 (  poly_contained    PGUID 12 f t t t 2 f 16 "604 604" 100 0 0  poly_contained - ));
+DATA(insert OID = 345 (  poly_contained    PGUID 12 f t t t 2 f 16 "604 604" 100 0 0 100  poly_contained - ));
 DESCR("contained in");
-DATA(insert OID = 346 (  poly_overlap     PGUID 12 f t t t 2 f 16 "604 604" 100 0 0  poly_overlap - ));
+DATA(insert OID = 346 (  poly_overlap     PGUID 12 f t t t 2 f 16 "604 604" 100 0 0 100  poly_overlap - ));
 DESCR("overlaps");
-DATA(insert OID = 347 (  poly_in                  PGUID 12 f t t t 1 f 604 "0" 100 0 0  poly_in - ));
+DATA(insert OID = 347 (  poly_in                  PGUID 12 f t t t 1 f 604 "0" 100 0 0 100  poly_in - ));
 DESCR("(internal)");
-DATA(insert OID = 348 (  poly_out                 PGUID 12 f t t t 1 f 23  "0" 100 0 0  poly_out - ));
+DATA(insert OID = 348 (  poly_out                 PGUID 12 f t t t 1 f 23  "0" 100 0 0 100  poly_out - ));
 DESCR("(internal)");
 
 DATA(insert OID = 350 (  btint2cmp                PGUID 12 f t t t 2 f 23 "21 21" 100 0 0 100  btint2cmp - ));
@@ -769,9 +769,9 @@ DATA(insert OID = 368 (  close_sb              PGUID 12 f t t t 2 f 600 "601 603" 100 0 0
 DESCR("closest point to line segment on box");
 DATA(insert OID = 369 (  on_ps                    PGUID 12 f t t t 2 f 16 "600 601" 100 0 0 100        on_ps - ));
 DESCR("point contained in segment");
-DATA(insert OID = 370 (  path_distance    PGUID 12 f t t t 2 f 701 "602 602" 100 0 0  path_distance - ));
+DATA(insert OID = 370 (  path_distance    PGUID 12 f t t t 2 f 701 "602 602" 100 0 0 100  path_distance - ));
 DESCR("distance between paths");
-DATA(insert OID = 371 (  dist_ppath               PGUID 12 f t t t 2 f 701 "600 602" 100 0 0  dist_ppath - ));
+DATA(insert OID = 371 (  dist_ppath               PGUID 12 f t t t 2 f 701 "600 602" 100 0 0 100  dist_ppath - ));
 DESCR("distance between point and path");
 DATA(insert OID = 372 (  on_sb                    PGUID 12 f t t t 2 f 16 "601 603" 100 0 0 100        on_sb - ));
 DESCR("contained in");
@@ -942,7 +942,7 @@ DATA(insert OID = 717 (  int4eqoid             PGUID 12 f t t t 2 f 16 "23 26" 100 0 0 1
 DESCR("equal");
 
 DATA(insert OID = 720 (  octet_length     PGUID 12 f t t t 1 f 23 "17" 100 0 0 100  byteaoctetlen - ));
-DESCR("");
+DESCR("octet length");
 DATA(insert OID = 721 (  get_byte                 PGUID 12 f t t t 2 f 23 "17 23" 100 0 0 100  byteaGetByte - ));
 DESCR("");
 DATA(insert OID = 722 (  set_byte                 PGUID 12 f t t t 3 f 17 "17 23 23" 100 0 0 100  byteaSetByte - ));
@@ -963,13 +963,13 @@ DESCR("distance between");
 DATA(insert OID = 729 (  poly_distance    PGUID 12 f t t t 2 f 701 "604 604" 100 0 0 100  poly_distance - ));
 DESCR("distance between");
 
-DATA(insert OID = 740 (  text_lt                  PGUID 12 f t t t 2 f 16 "25 25" 100 0 0 0    text_lt - ));
+DATA(insert OID = 740 (  text_lt                  PGUID 12 f t t t 2 f 16 "25 25" 100 0 0 100  text_lt - ));
 DESCR("less-than");
-DATA(insert OID = 741 (  text_le                  PGUID 12 f t t t 2 f 16 "25 25" 100 0 0 0    text_le - ));
+DATA(insert OID = 741 (  text_le                  PGUID 12 f t t t 2 f 16 "25 25" 100 0 0 100  text_le - ));
 DESCR("less-than-or-equal");
-DATA(insert OID = 742 (  text_gt                  PGUID 12 f t t t 2 f 16 "25 25" 100 0 0 0    text_gt - ));
+DATA(insert OID = 742 (  text_gt                  PGUID 12 f t t t 2 f 16 "25 25" 100 0 0 100  text_gt - ));
 DESCR("greater-than");
-DATA(insert OID = 743 (  text_ge                  PGUID 12 f t t t 2 f 16 "25 25" 100 0 0 0    text_ge - ));
+DATA(insert OID = 743 (  text_ge                  PGUID 12 f t t t 2 f 16 "25 25" 100 0 0 100  text_ge - ));
 DESCR("greater-than-or-equal");
 
 DATA(insert OID = 744 (  array_eq                 PGUID 12 f t t t 2 f 16 "0 0" 100 0 0 100 array_eq -));
@@ -1065,11 +1065,11 @@ DESCR("divide");
 DATA(insert OID =  848 (  flt4_mul_cash    PGUID 12 f t t t 2 f 790 "700 790" 100 0 0 100  flt4_mul_cash - ));
 DESCR("multiply");
 
-DATA(insert OID =  849 (  position                PGUID 12 f t t t 2 f 23 "25 25" 100 0 0 textpos - ));
+DATA(insert OID =  849 (  position                PGUID 12 f t t t 2 f 23 "25 25" 100 0 0 100 textpos - ));
 DESCR("return position of substring");
-DATA(insert OID =  850 (  textlike                PGUID 12 f t t t 2 f 16 "25 25" 100 0 0 textlike - ));
+DATA(insert OID =  850 (  textlike                PGUID 12 f t t t 2 f 16 "25 25" 100 0 0 100 textlike - ));
 DESCR("matches LIKE expression");
-DATA(insert OID =  851 (  textnlike               PGUID 12 f t t t 2 f 16 "25 25" 100 0 0 textnlike - ));
+DATA(insert OID =  851 (  textnlike               PGUID 12 f t t t 2 f 16 "25 25" 100 0 0 100 textnlike - ));
 DESCR("does not match LIKE expression");
 
 DATA(insert OID =  852 (  int48eq                 PGUID 12 f t t t 2 f 16 "23 20" 100 0 0 100  int48eq - ));
@@ -1183,15 +1183,15 @@ DESCR("large object create");
 DATA(insert OID = 958 (  lo_tell                  PGUID 12 f t f t 1 f 23 "23" 100 0 0 100  lo_tell - ));
 DESCR("large object position");
 
-DATA(insert OID = 959 (  on_pl                    PGUID 12 f t t t 2 f  16 "600 628" 100 0 10 100  on_pl - ));
+DATA(insert OID = 959 (  on_pl                    PGUID 12 f t t t 2 f  16 "600 628" 100 0 0 100  on_pl - ));
 DESCR("point on line?");
-DATA(insert OID = 960 (  on_sl                    PGUID 12 f t t t 2 f  16 "601 628" 100 0 10 100  on_sl - ));
+DATA(insert OID = 960 (  on_sl                    PGUID 12 f t t t 2 f  16 "601 628" 100 0 0 100  on_sl - ));
 DESCR("lseg on line?");
-DATA(insert OID = 961 (  close_pl                 PGUID 12 f t t t 2 f 600 "600 628" 100 0 10 100  close_pl - ));
+DATA(insert OID = 961 (  close_pl                 PGUID 12 f t t t 2 f 600 "600 628" 100 0 0 100  close_pl - ));
 DESCR("closest point on line");
-DATA(insert OID = 962 (  close_sl                 PGUID 12 f t t t 2 f 600 "601 628" 100 0 10 100  close_sl - ));
+DATA(insert OID = 962 (  close_sl                 PGUID 12 f t t t 2 f 600 "601 628" 100 0 0 100  close_sl - ));
 DESCR("closest point to line segment on line");
-DATA(insert OID = 963 (  close_lb                 PGUID 12 f t t t 2 f 600 "628 603" 100 0 10 100  close_lb - ));
+DATA(insert OID = 963 (  close_lb                 PGUID 12 f t t t 2 f 600 "628 603" 100 0 0 100  close_lb - ));
 DESCR("closest point to line on box");
 
 DATA(insert OID = 964 (  lo_unlink                PGUID 12 f t f t 1 f  23 "26" 100 0 0 100    lo_unlink - ));
@@ -1199,7 +1199,7 @@ DESCR("large object unlink(delete)");
 DATA(insert OID = 972 (  regproctooid     PGUID 12 f t t t 1 f  26 "24" 100 0 0 100    regproctooid - ));
 DESCR("get oid for regproc");
 
-DATA(insert OID = 973 (  path_inter               PGUID 12 f t t t 2 f  16 "602 602" 100 0 10 100  path_inter - ));
+DATA(insert OID = 973 (  path_inter               PGUID 12 f t t t 2 f  16 "602 602" 100 0 0 100  path_inter - ));
 DESCR("paths intersect?");
 DATA(insert OID = 975 (  area                     PGUID 12 f t t t 1 f 701 "603" 100 0 0 100  box_area - ));
 DESCR("box area");
@@ -1223,7 +1223,7 @@ DATA(insert OID = 985 (  path_n_le                   PGUID 12 f t t t 2 f 16 "602 602" 100 0 0
 DESCR("less-than-or-equal");
 DATA(insert OID = 986 (  path_n_ge                PGUID 12 f t t t 2 f 16 "602 602" 100 0 0 100        path_n_ge - ));
 DESCR("greater-than-or-equal");
-DATA(insert OID = 987 (  path_length      PGUID 12 f t t t 1 f 701 "602" 100 0 0  path_length - ));
+DATA(insert OID = 987 (  path_length      PGUID 12 f t t t 1 f 701 "602" 100 0 0 100  path_length - ));
 DESCR("sum of path segments");
 DATA(insert OID = 988 (  point_ne                 PGUID 12 f t t t 2 f 16 "600 600" 100 0 0 100        point_ne - ));
 DESCR("not equal");
@@ -1471,9 +1471,9 @@ DESCR("larger of two");
 DATA(insert OID = 1237 (  int8smaller     PGUID 12 f t t t 2 f 20 "20 20" 100 0 0 100  int8smaller - ));
 DESCR("smaller of two");
 
-DATA(insert OID = 1238 (  texticregexeq    PGUID 12 f t t t 2 f 16 "25 25" 100 0 1 0   texticregexeq - ));
+DATA(insert OID = 1238 (  texticregexeq    PGUID 12 f t t t 2 f 16 "25 25" 100 0 0 100 texticregexeq - ));
 DESCR("matches regex., case-insensitive");
-DATA(insert OID = 1239 (  texticregexne    PGUID 12 f t t t 2 f 16 "25 25" 100 0 1 0   texticregexne - ));
+DATA(insert OID = 1239 (  texticregexne    PGUID 12 f t t t 2 f 16 "25 25" 100 0 0 100 texticregexne - ));
 DESCR("does not match regex., case-insensitive");
 DATA(insert OID = 1240 (  nameicregexeq    PGUID 12 f t t t 2 f 16 "19 25" 100 0 0 100  nameicregexeq - ));
 DESCR("matches regex., case-insensitive");
@@ -1488,7 +1488,7 @@ DESCR("absolute value");
 DATA(insert OID = 1263 (  interval                PGUID 12 f t f t 1 f 1186 "25" 100 0 0 100  text_interval - ));
 DESCR("convert text to interval");
 
-DATA(insert OID = 1271 (  overlaps                PGUID 12 f t t t 4 f 16 "1266 1266 1266 1266" 100 0 0  overlaps_timetz - ));
+DATA(insert OID = 1271 (  overlaps                PGUID 12 f t t t 4 f 16 "1266 1266 1266 1266" 100 0 0 100  overlaps_timetz - ));
 DESCR("SQL92 interval comparison");
 DATA(insert OID = 1272 (  datetime_pl     PGUID 12 f t f t 2 f 1184 "1082 1083" 100 0 0 100    datetime_timestamp - ));
 DESCR("convert date and time to timestamp");
@@ -1547,22 +1547,22 @@ DESCR("restriction selectivity for containment comparison operators");
 DATA(insert OID = 1303 (  contjoinsel     PGUID 12 f t f t 5 f 701 "26 26 21 26 21" 100 0 0 100        contjoinsel - ));
 DESCR("join selectivity for containment comparison operators");
 
-DATA(insert OID = 1304 ( overlaps                       PGUID 12 f t t t 4 f 16 "1184 1184 1184 1184" 100 0 1 0        overlaps_timestamp - ));
+DATA(insert OID = 1304 ( overlaps                       PGUID 12 f t t t 4 f 16 "1184 1184 1184 1184" 100 0 0 100      overlaps_timestamp - ));
 DESCR("SQL92 interval comparison");
-DATA(insert OID = 1305 ( overlaps                       PGUID 14 f t t t 4 f 16 "1184 1186 1184 1186" 100 0 1 0        "select overlaps($1, ($1 + $2), $3, ($3 + $4))" - ));
+DATA(insert OID = 1305 ( overlaps                       PGUID 14 f t t t 4 f 16 "1184 1186 1184 1186" 100 0 0 100      "select overlaps($1, ($1 + $2), $3, ($3 + $4))" - ));
 DESCR("SQL92 interval comparison");
-DATA(insert OID = 1306 ( overlaps                       PGUID 14 f t t t 4 f 16 "1184 1184 1184 1186" 100 0 1 0        "select overlaps($1, $2, $3, ($3 + $4))" - ));
+DATA(insert OID = 1306 ( overlaps                       PGUID 14 f t t t 4 f 16 "1184 1184 1184 1186" 100 0 0 100      "select overlaps($1, $2, $3, ($3 + $4))" - ));
 DESCR("SQL92 interval comparison");
-DATA(insert OID = 1307 ( overlaps                       PGUID 14 f t t t 4 f 16 "1184 1186 1184 1184" 100 0 1 0        "select overlaps($1, ($1 + $2), $3, $4)" - ));
+DATA(insert OID = 1307 ( overlaps                       PGUID 14 f t t t 4 f 16 "1184 1186 1184 1184" 100 0 0 100      "select overlaps($1, ($1 + $2), $3, $4)" - ));
 DESCR("SQL92 interval comparison");
 
-DATA(insert OID = 1308 ( overlaps                       PGUID 12 f t t t 4 f 16 "1083 1083 1083 1083" 100 0 1 0        overlaps_time - ));
+DATA(insert OID = 1308 ( overlaps                       PGUID 12 f t t t 4 f 16 "1083 1083 1083 1083" 100 0 0 100      overlaps_time - ));
 DESCR("SQL92 interval comparison");
-DATA(insert OID = 1309 ( overlaps                       PGUID 14 f t t t 4 f 16 "1083 1186 1083 1186" 100 0 1 0        "select overlaps($1, ($1 + $2), $3, ($3 + $4))" - ));
+DATA(insert OID = 1309 ( overlaps                       PGUID 14 f t t t 4 f 16 "1083 1186 1083 1186" 100 0 0 100      "select overlaps($1, ($1 + $2), $3, ($3 + $4))" - ));
 DESCR("SQL92 interval comparison");
-DATA(insert OID = 1310 ( overlaps                       PGUID 14 f t t t 4 f 16 "1083 1083 1083 1186" 100 0 1 0        "select overlaps($1, $2, $3, ($3 + $4))" - ));
+DATA(insert OID = 1310 ( overlaps                       PGUID 14 f t t t 4 f 16 "1083 1083 1083 1186" 100 0 0 100      "select overlaps($1, $2, $3, ($3 + $4))" - ));
 DESCR("SQL92 interval comparison");
-DATA(insert OID = 1311 ( overlaps                       PGUID 14 f t t t 4 f 16 "1083 1186 1083 1083" 100 0 1 0        "select overlaps($1, ($1 + $2), $3, $4)" - ));
+DATA(insert OID = 1311 ( overlaps                       PGUID 14 f t t t 4 f 16 "1083 1186 1083 1083" 100 0 0 100      "select overlaps($1, ($1 + $2), $3, $4)" - ));
 DESCR("SQL92 interval comparison");
 
 DATA(insert OID = 1314 (  timestamp_cmp                 PGUID 12 f t f t 2 f   23 "1184 1184" 100 0 0 100  timestamp_cmp - ));
@@ -1572,7 +1572,7 @@ DESCR("less-equal-greater");
 DATA(insert OID = 1316 (  time                          PGUID 12 f t f t 1 f 1083 "1184" 100 0 0 100  timestamp_time - ));
 DESCR("convert timestamp to time");
 
-DATA(insert OID = 1317 (  length                        PGUID 12 f t t t 1 f   23 "25" 100 0 0  textlen - ));
+DATA(insert OID = 1317 (  length                        PGUID 12 f t t t 1 f   23 "25" 100 0 0 100  textlen - ));
 DESCR("length");
 DATA(insert OID = 1318 (  length                        PGUID 12 f t t t 1 f   23 "1042" 100 0 0 100  bpcharlen - ));
 DESCR("character length");
@@ -1665,7 +1665,7 @@ DESCR("larger of two");
 DATA(insert OID = 1380 (  timetz_smaller   PGUID 12 f t t t 2 f 1266 "1266 1266" 100 0 0 100   timetz_smaller - ));
 DESCR("smaller of two");
 
-DATA(insert OID = 1381 (  char_length     PGUID 12 f t t t 1 f 23 "25" 100 0 0  textlen - ));
+DATA(insert OID = 1381 (  char_length     PGUID 12 f t t t 1 f 23 "25" 100 0 0 100  textlen - ));
 DESCR("length");
 
 DATA(insert OID = 1382 (  date_part    PGUID 14 f t f t 2 f  701 "25 702" 100 0 0 100  "select date_part($1, timestamp($2))" - ));
@@ -1743,7 +1743,7 @@ DATA(insert OID = 1414 (  isvertical              PGUID 12 f t t t 1 f    16 "628" 100 0 0 100
 DESCR("lines vertical?");
 DATA(insert OID = 1415 (  ishorizontal         PGUID 12 f t t t 1 f    16 "628" 100 0 0 100  line_horizontal - ));
 DESCR("lines horizontal?");
-DATA(insert OID = 1416 (  point                                PGUID 12 f t t t 1 f 600 "718" 100 0 1 0        circle_center - ));
+DATA(insert OID = 1416 (  point                                PGUID 12 f t t t 1 f 600 "718" 100 0 0 100      circle_center - ));
 DESCR("center of");
 
 DATA(insert OID = 1417 (  isnottrue                    PGUID 12 f t t f 1 f 16 "16" 100 0 0 100  isnottrue - ));
@@ -1816,67 +1816,67 @@ DESCR("convert box to polygon");
 DATA(insert OID = 1449 (  polygon                      PGUID 12 f t t t 1 f 604 "602" 100 0 0 100  path_poly - ));
 DESCR("convert path to polygon");
 
-DATA(insert OID = 1450 (  circle_in                    PGUID 12 f t t t 1 f 718 "0" 100 0 0  circle_in - ));
+DATA(insert OID = 1450 (  circle_in                    PGUID 12 f t t t 1 f 718 "0" 100 0 0 100  circle_in - ));
 DESCR("(internal)");
-DATA(insert OID = 1451 (  circle_out           PGUID 12 f t t t 1 f    23      "718" 100 0 0  circle_out - ));
+DATA(insert OID = 1451 (  circle_out           PGUID 12 f t t t 1 f    23      "718" 100 0 0 100  circle_out - ));
 DESCR("(internal)");
-DATA(insert OID = 1452 (  circle_same          PGUID 12 f t t t 2 f    16 "718 718" 100 0 1 0  circle_same - ));
+DATA(insert OID = 1452 (  circle_same          PGUID 12 f t t t 2 f    16 "718 718" 100 0 0 100        circle_same - ));
 DESCR("same as");
-DATA(insert OID = 1453 (  circle_contain       PGUID 12 f t t t 2 f    16 "718 718" 100 0 1 0  circle_contain - ));
+DATA(insert OID = 1453 (  circle_contain       PGUID 12 f t t t 2 f    16 "718 718" 100 0 0 100        circle_contain - ));
 DESCR("contains");
-DATA(insert OID = 1454 (  circle_left          PGUID 12 f t t t 2 f    16 "718 718" 100 0 1 0  circle_left - ));
+DATA(insert OID = 1454 (  circle_left          PGUID 12 f t t t 2 f    16 "718 718" 100 0 0 100        circle_left - ));
 DESCR("is left of");
-DATA(insert OID = 1455 (  circle_overleft      PGUID 12 f t t t 2 f    16 "718 718" 100 0 1 0  circle_overleft - ));
+DATA(insert OID = 1455 (  circle_overleft      PGUID 12 f t t t 2 f    16 "718 718" 100 0 0 100        circle_overleft - ));
 DESCR("overlaps, but does not extend to right of");
-DATA(insert OID = 1456 (  circle_overright     PGUID 12 f t t t 2 f    16 "718 718" 100 0 1 0  circle_overright - ));
+DATA(insert OID = 1456 (  circle_overright     PGUID 12 f t t t 2 f    16 "718 718" 100 0 0 100        circle_overright - ));
 DESCR("");
-DATA(insert OID = 1457 (  circle_right         PGUID 12 f t t t 2 f    16 "718 718" 100 0 1 0  circle_right - ));
+DATA(insert OID = 1457 (  circle_right         PGUID 12 f t t t 2 f    16 "718 718" 100 0 0 100        circle_right - ));
 DESCR("is right of");
-DATA(insert OID = 1458 (  circle_contained     PGUID 12 f t t t 2 f    16 "718 718" 100 0 1 0  circle_contained - ));
+DATA(insert OID = 1458 (  circle_contained     PGUID 12 f t t t 2 f    16 "718 718" 100 0 0 100        circle_contained - ));
 DESCR("");
-DATA(insert OID = 1459 (  circle_overlap       PGUID 12 f t t t 2 f    16 "718 718" 100 0 1 0  circle_overlap - ));
+DATA(insert OID = 1459 (  circle_overlap       PGUID 12 f t t t 2 f    16 "718 718" 100 0 0 100        circle_overlap - ));
 DESCR("overlaps");
-DATA(insert OID = 1460 (  circle_below         PGUID 12 f t t t 2 f    16 "718 718" 100 0 1 0  circle_below - ));
+DATA(insert OID = 1460 (  circle_below         PGUID 12 f t t t 2 f    16 "718 718" 100 0 0 100        circle_below - ));
 DESCR("is below");
-DATA(insert OID = 1461 (  circle_above         PGUID 12 f t t t 2 f    16 "718 718" 100 0 1 0  circle_above - ));
+DATA(insert OID = 1461 (  circle_above         PGUID 12 f t t t 2 f    16 "718 718" 100 0 0 100        circle_above - ));
 DESCR("is above");
-DATA(insert OID = 1462 (  circle_eq                    PGUID 12 f t t t 2 f    16 "718 718" 100 0 1 0  circle_eq - ));
+DATA(insert OID = 1462 (  circle_eq                    PGUID 12 f t t t 2 f    16 "718 718" 100 0 0 100        circle_eq - ));
 DESCR("equal by area");
-DATA(insert OID = 1463 (  circle_ne                    PGUID 12 f t t t 2 f    16 "718 718" 100 0 1 0  circle_ne - ));
+DATA(insert OID = 1463 (  circle_ne                    PGUID 12 f t t t 2 f    16 "718 718" 100 0 0 100        circle_ne - ));
 DESCR("not equal by area");
-DATA(insert OID = 1464 (  circle_lt                    PGUID 12 f t t t 2 f    16 "718 718" 100 0 1 0  circle_lt - ));
+DATA(insert OID = 1464 (  circle_lt                    PGUID 12 f t t t 2 f    16 "718 718" 100 0 0 100        circle_lt - ));
 DESCR("less-than by area");
-DATA(insert OID = 1465 (  circle_gt                    PGUID 12 f t t t 2 f    16 "718 718" 100 0 1 0  circle_gt - ));
+DATA(insert OID = 1465 (  circle_gt                    PGUID 12 f t t t 2 f    16 "718 718" 100 0 0 100        circle_gt - ));
 DESCR("greater-than by area");
-DATA(insert OID = 1466 (  circle_le                    PGUID 12 f t t t 2 f    16 "718 718" 100 0 1 0  circle_le - ));
+DATA(insert OID = 1466 (  circle_le                    PGUID 12 f t t t 2 f    16 "718 718" 100 0 0 100        circle_le - ));
 DESCR("less-than-or-equal by area");
-DATA(insert OID = 1467 (  circle_ge                    PGUID 12 f t t t 2 f    16 "718 718" 100 0 1 0  circle_ge - ));
+DATA(insert OID = 1467 (  circle_ge                    PGUID 12 f t t t 2 f    16 "718 718" 100 0 0 100        circle_ge - ));
 DESCR("greater-than-or-equal by area");
-DATA(insert OID = 1468 (  area                         PGUID 12 f t t t 1 f 701 "718" 100 0 1 0        circle_area - ));
+DATA(insert OID = 1468 (  area                         PGUID 12 f t t t 1 f 701 "718" 100 0 0 100      circle_area - ));
 DESCR("area of circle");
-DATA(insert OID = 1469 (  diameter                     PGUID 12 f t t t 1 f 701 "718" 100 0 1 0        circle_diameter - ));
+DATA(insert OID = 1469 (  diameter                     PGUID 12 f t t t 1 f 701 "718" 100 0 0 100      circle_diameter - ));
 DESCR("diameter of circle");
-DATA(insert OID = 1470 (  radius                       PGUID 12 f t t t 1 f 701 "718" 100 0 1 0        circle_radius - ));
+DATA(insert OID = 1470 (  radius                       PGUID 12 f t t t 1 f 701 "718" 100 0 0 100      circle_radius - ));
 DESCR("radius of circle");
-DATA(insert OID = 1471 (  circle_distance      PGUID 12 f t t t 2 f 701 "718 718" 100 0 1 0    circle_distance - ));
+DATA(insert OID = 1471 (  circle_distance      PGUID 12 f t t t 2 f 701 "718 718" 100 0 0 100  circle_distance - ));
 DESCR("distance between");
-DATA(insert OID = 1472 (  circle_center                PGUID 12 f t t t 1 f 600 "718" 100 0 1 0        circle_center - ));
+DATA(insert OID = 1472 (  circle_center                PGUID 12 f t t t 1 f 600 "718" 100 0 0 100      circle_center - ));
 DESCR("center of");
-DATA(insert OID = 1473 (  circle                       PGUID 12 f t t t 2 f 718 "600 701" 100 0 1 0    cr_circle - ));
+DATA(insert OID = 1473 (  circle                       PGUID 12 f t t t 2 f 718 "600 701" 100 0 0 100  cr_circle - ));
 DESCR("convert point and radius to circle");
-DATA(insert OID = 1474 (  circle                       PGUID 12 f t t t 1 f 718 "604" 100 0 1 0        poly_circle - ));
+DATA(insert OID = 1474 (  circle                       PGUID 12 f t t t 1 f 718 "604" 100 0 0 100      poly_circle - ));
 DESCR("convert polygon to circle");
-DATA(insert OID = 1475 (  polygon                      PGUID 12 f t t t 2 f 604 "23 718" 100 0 0  circle_poly - ));
+DATA(insert OID = 1475 (  polygon                      PGUID 12 f t t t 2 f 604 "23 718" 100 0 0 100  circle_poly - ));
 DESCR("convert vertex count and circle to polygon");
-DATA(insert OID = 1476 (  dist_pc                      PGUID 12 f t t t 2 f 701 "600 718" 100 0 1 0    dist_pc - ));
+DATA(insert OID = 1476 (  dist_pc                      PGUID 12 f t t t 2 f 701 "600 718" 100 0 0 100  dist_pc - ));
 DESCR("distance between point and circle");
 DATA(insert OID = 1477 (  circle_contain_pt PGUID 12 f t t t 2 f       16 "718 600" 100 0 0 100  circle_contain_pt - ));
 DESCR("circle contains point?");
 DATA(insert OID = 1478 (  pt_contained_circle  PGUID 12 f t t t 2 f    16 "600 718" 100 0 0 100  pt_contained_circle - ));
 DESCR("point inside circle?");
-DATA(insert OID = 1479 (  circle                       PGUID 12 f t t t 1 f 718 "603" 100 0 1 0        box_circle - ));
+DATA(insert OID = 1479 (  circle                       PGUID 12 f t t t 1 f 718 "603" 100 0 0 100      box_circle - ));
 DESCR("convert box to circle");
-DATA(insert OID = 1480 (  box                          PGUID 12 f t t t 1 f 603 "718" 100 0 1 0        circle_box - ));
+DATA(insert OID = 1480 (  box                          PGUID 12 f t t t 1 f 603 "718" 100 0 0 100      circle_box - ));
 DESCR("convert circle to box");
 DATA(insert OID = 1481 (  tinterval                     PGUID 12 f t f t 2 f 704 "702 702" 100 0 0 100 mktinterval - ));
 DESCR("convert to tinterval");
@@ -1891,11 +1891,11 @@ DATA(insert OID = 1485 (  lseg_gt                       PGUID 12 f t t t 2 f    16 "601 601" 100 0 0 10
 DESCR("greater-than by length");
 DATA(insert OID = 1486 (  lseg_ge                      PGUID 12 f t t t 2 f    16 "601 601" 100 0 0 100  lseg_ge - ));
 DESCR("greater-than-or-equal by length");
-DATA(insert OID = 1487 (  lseg_length          PGUID 12 f t t t 1 f 701 "601" 100 0 1 0        lseg_length - ));
+DATA(insert OID = 1487 (  lseg_length          PGUID 12 f t t t 1 f 701 "601" 100 0 0 100      lseg_length - ));
 DESCR("distance between endpoints");
-DATA(insert OID = 1488 (  close_ls                     PGUID 12 f t t t 2 f 600 "628 601" 100 0 10 100  close_ls - ));
+DATA(insert OID = 1488 (  close_ls                     PGUID 12 f t t t 2 f 600 "628 601" 100 0 0 100  close_ls - ));
 DESCR("closest point to line on line segment");
-DATA(insert OID = 1489 (  close_lseg           PGUID 12 f t t t 2 f 600 "601 601" 100 0 10 100  close_lseg - ));
+DATA(insert OID = 1489 (  close_lseg           PGUID 12 f t t t 2 f 600 "601 601" 100 0 0 100  close_lseg - ));
 DESCR("closest point to line segment on line segment");
 
 DATA(insert OID = 1490 (  line_in                      PGUID 12 f t t t 1 f 628 "0" 100 0 0 100        line_in - ));
@@ -1921,9 +1921,9 @@ DESCR("lines horizontal?");
 
 /* OIDS 1500 - 1599 */
 
-DATA(insert OID = 1530 (  length                       PGUID 12 f t t t 1 f 701 "601" 100 0 1 0        lseg_length - ));
+DATA(insert OID = 1530 (  length                       PGUID 12 f t t t 1 f 701 "601" 100 0 0 100      lseg_length - ));
 DESCR("distance between endpoints");
-DATA(insert OID = 1531 (  length                       PGUID 12 f t t t 1 f 701 "602" 100 0 1 0        path_length - ));
+DATA(insert OID = 1531 (  length                       PGUID 12 f t t t 1 f 701 "602" 100 0 0 100      path_length - ));
 DESCR("sum of path segments");
 
 
@@ -1931,15 +1931,15 @@ DATA(insert OID = 1532 (  point                         PGUID 12 f t t t 1 f 600 "601" 100 0 0 100  l
 DESCR("center of");
 DATA(insert OID = 1533 (  point                                PGUID 12 f t t t 1 f 600 "602" 100 0 0 100  path_center - ));
 DESCR("center of");
-DATA(insert OID = 1534 (  point                                PGUID 12 f t t t 1 f 600 "603" 100 1 0 100  box_center - ));
+DATA(insert OID = 1534 (  point                                PGUID 12 f t t t 1 f 600 "603" 100 0 0 100  box_center - ));
 DESCR("center of");
 DATA(insert OID = 1540 (  point                                PGUID 12 f t t t 1 f 600 "604" 100 0 0 100  poly_center - ));
 DESCR("center of");
 DATA(insert OID = 1541 (  lseg                         PGUID 12 f t t t 1 f 601 "603" 100 0 0 100  box_diagonal - ));
 DESCR("diagonal of");
-DATA(insert OID = 1542 (  center                       PGUID 12 f t t t 1 f 600 "603" 100 1 0 100  box_center - ));
+DATA(insert OID = 1542 (  center                       PGUID 12 f t t t 1 f 600 "603" 100 0 0 100  box_center - ));
 DESCR("center of");
-DATA(insert OID = 1543 (  center                       PGUID 12 f t t t 1 f 600 "718" 100 0 1 0        circle_center - ));
+DATA(insert OID = 1543 (  center                       PGUID 12 f t t t 1 f 600 "718" 100 0 0 100      circle_center - ));
 DESCR("center of");
 DATA(insert OID = 1544 (  polygon                      PGUID 14 f t t t 1 f 604 "718" 100 0 0 100  "select polygon(12, $1)" - ));
 DESCR("convert circle to 12-vertex polygon");
@@ -1948,14 +1948,14 @@ DESCR("# points in path");
 DATA(insert OID = 1556 (  npoints                      PGUID 12 f t t t 1 f    23 "604" 100 0 0 100  poly_npoints - ));
 DESCR("number of points in polygon");
 
-DATA(insert OID = 1564 (  zpbit_in                     PGUID 11 f t t t 1 f 1560 "0" 100 0 0 100  zpbit_in - ));
+DATA(insert OID = 1564 (  zpbit_in                     PGUID 12 f t 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 t 1 f     23 "0" 100 0 0 100  zpbit_out - ));
+DATA(insert OID = 1565 (  zpbit_out                    PGUID 12 f t t t 1 f   23 "0" 100 0 0 100  zpbit_out - ));
 DESCR("(internal)");
 
-DATA(insert OID = 1569 (  like                         PGUID 12 f t t t 2 f 16 "25 25" 100 0 0  textlike - ));
+DATA(insert OID = 1569 (  like                         PGUID 12 f t t t 2 f 16 "25 25" 100 0 0 100  textlike - ));
 DESCR("matches LIKE expression");
-DATA(insert OID = 1570 (  notlike                      PGUID 12 f t t t 2 f 16 "25 25" 100 0 0  textnlike - ));
+DATA(insert OID = 1570 (  notlike                      PGUID 12 f t t t 2 f 16 "25 25" 100 0 0 100  textnlike - ));
 DESCR("does not match LIKE expression");
 DATA(insert OID = 1571 (  like                         PGUID 12 f t t t 2 f 16 "19 25" 100 0 0 100  namelike - ));
 DESCR("matches LIKE expression");
@@ -1973,24 +1973,24 @@ DESCR("sequence current value");
 DATA(insert OID = 1576 (  setval                       PGUID 12 f t f t 2 f 23 "25 23" 100 0 0 100  setval - ));
 DESCR("set sequence value");
 
-DATA(insert OID = 1579 (  varbit_in                    PGUID 11 f t t t 1 f 1562 "0" 100 0 0 100  varbit_in - ));
+DATA(insert OID = 1579 (  varbit_in                    PGUID 12 f t 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 t 1 f     23 "0" 100 0 0 100  varbit_out - ));
+DATA(insert OID = 1580 (  varbit_out           PGUID 12 f t t t 1 f   23 "0" 100 0 0 100  varbit_out - ));
 DESCR("(internal)");
 
-DATA(insert OID = 1581 (  biteq                                PGUID 11 f t t t 2 f 16 "1560 1560" 100 0 1 0  biteq - ));
+DATA(insert OID = 1581 (  biteq                                PGUID 12 f t t t 2 f 16 "1560 1560" 100 0 0 100  biteq - ));
 DESCR("equal");
-DATA(insert OID = 1582 (  bitne                                PGUID 11 f t t t 2 f 16 "1560 1560" 100 0 1 0  bitne - ));
+DATA(insert OID = 1582 (  bitne                                PGUID 12 f t t t 2 f 16 "1560 1560" 100 0 0 100  bitne - ));
 DESCR("not equal");
-DATA(insert OID = 1592 (  bitge                                PGUID 11 f t t t 2 f 16 "1560 1560" 100 0 1 0  bitge - ));
+DATA(insert OID = 1592 (  bitge                                PGUID 12 f t t t 2 f 16 "1560 1560" 100 0 0 100  bitge - ));
 DESCR("greater than or equal");
-DATA(insert OID = 1593 (  bitgt                                PGUID 11 f t t t 2 f 16 "1560 1560" 100 0 1 0  bitgt - ));
+DATA(insert OID = 1593 (  bitgt                                PGUID 12 f t t t 2 f 16 "1560 1560" 100 0 0 100  bitgt - ));
 DESCR("greater than");
-DATA(insert OID = 1594 (  bitle                                PGUID 11 f t t t 2 f 16 "1560 1560" 100 0 1 0  bitle - ));
+DATA(insert OID = 1594 (  bitle                                PGUID 12 f t t t 2 f 16 "1560 1560" 100 0 0 100  bitle - ));
 DESCR("less than or equal");
-DATA(insert OID = 1595 (  bitlt                                PGUID 11 f t t t 2 f 16 "1560 1560" 100 0 1 0  bitlt - ));
+DATA(insert OID = 1595 (  bitlt                                PGUID 12 f t t t 2 f 16 "1560 1560" 100 0 0 100  bitlt - ));
 DESCR("less than");
-DATA(insert OID = 1596 (  bitcmp                       PGUID 11 f t t t 2 f 23 "1560 1560" 100 0 1 0  bitcmp - ));
+DATA(insert OID = 1596 (  bitcmp                       PGUID 12 f t t t 2 f 23 "1560 1560" 100 0 0 100  bitcmp - ));
 DESCR("compare");
 
 DATA(insert OID = 1598 (  random                       PGUID 12 f t f t 0 f 701 "0" 100 0 0 100        drandom - ));
@@ -2039,25 +2039,25 @@ DATA(insert OID = 1623 (  varchar                       PGUID 12 f t t t 1 f 1043 "20" 100 0 0 100
 DESCR("convert int8 to varchar");
 DATA(insert OID = 1624 (  mul_d_interval       PGUID 12 f t t t 2 f 1186 "701 1186" 100 0 0 100        mul_d_interval - ));
 
-DATA(insert OID = 1625 (  like                         PGUID 12 f t t t 3 f 16 "19 25 25" 100 0 0  namelike_escape - ));
+DATA(insert OID = 1625 (  like                         PGUID 12 f t t t 3 f 16 "19 25 25" 100 0 0 100  namelike_escape - ));
 DESCR("matches LIKE expression");
-DATA(insert OID = 1626 (  notlike                      PGUID 12 f t t t 3 f 16 "19 25 25" 100 0 0  namenlike_escape - ));
+DATA(insert OID = 1626 (  notlike                      PGUID 12 f t t t 3 f 16 "19 25 25" 100 0 0 100  namenlike_escape - ));
 DESCR("does not match LIKE expression");
-DATA(insert OID = 1627 (  ilike                                PGUID 12 f t t t 3 f 16 "19 25 25" 100 0 0  inamelike_escape - ));
+DATA(insert OID = 1627 (  ilike                                PGUID 12 f t t t 3 f 16 "19 25 25" 100 0 0 100  inamelike_escape - ));
 DESCR("matches case-insensitive LIKE expression");
-DATA(insert OID = 1628 (  inotlike                     PGUID 12 f t t t 3 f 16 "19 25 25" 100 0 0  inamenlike_escape - ));
+DATA(insert OID = 1628 (  inotlike                     PGUID 12 f t t t 3 f 16 "19 25 25" 100 0 0 100  inamenlike_escape - ));
 DESCR("does not match case-insensitive LIKE expression");
-DATA(insert OID = 1629 (  like                         PGUID 12 f t t t 3 f 16 "25 25 25" 100 0 0  textlike_escape - ));
+DATA(insert OID = 1629 (  like                         PGUID 12 f t t t 3 f 16 "25 25 25" 100 0 0 100  textlike_escape - ));
 DESCR("matches LIKE expression");
-DATA(insert OID = 1630 (  notlike                      PGUID 12 f t t t 3 f 16 "25 25 25" 100 0 0  textnlike_escape - ));
+DATA(insert OID = 1630 (  notlike                      PGUID 12 f t t t 3 f 16 "25 25 25" 100 0 0 100  textnlike_escape - ));
 DESCR("does not match LIKE expression");
-DATA(insert OID = 1631 (  ilike                                PGUID 12 f t t t 3 f 16 "25 25 25" 100 0 0  itextlike_escape - ));
+DATA(insert OID = 1631 (  ilike                                PGUID 12 f t t t 3 f 16 "25 25 25" 100 0 0 100  itextlike_escape - ));
 DESCR("matches case-insensitive LIKE expression");
-DATA(insert OID = 1632 (  inotlike                     PGUID 12 f t t t 3 f 16 "25 25 25" 100 0 0  itextnlike_escape - ));
+DATA(insert OID = 1632 (  inotlike                     PGUID 12 f t t t 3 f 16 "25 25 25" 100 0 0 100  itextnlike_escape - ));
 DESCR("does not match case-insensitive LIKE expression");
-DATA(insert OID = 1633 (  ilike                                PGUID 12 f t t t 2 f 16 "25 25" 100 0 0  itextlike - ));
+DATA(insert OID = 1633 (  ilike                                PGUID 12 f t t t 2 f 16 "25 25" 100 0 0 100  itextlike - ));
 DESCR("matches case-insensitive LIKE expression");
-DATA(insert OID = 1634 (  inotlike                     PGUID 12 f t t t 2 f 16 "25 25" 100 0 0  itextnlike - ));
+DATA(insert OID = 1634 (  inotlike                     PGUID 12 f t t t 2 f 16 "25 25" 100 0 0 100  itextnlike - ));
 DESCR("does not match case-insensitive LIKE expression");
 DATA(insert OID = 1635 (  ilike                                PGUID 12 f t t t 2 f 16 "19 25" 100 0 0 100  inamelike - ));
 DESCR("matches case-insensitive LIKE expression");
@@ -2149,54 +2149,54 @@ DESCR("referential integrity ON DELETE NO ACTION");
 DATA(insert OID = 1655 (  RI_FKey_noaction_upd PGUID 12 f t f t 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 t 2 f 16 "1562 1562" 100 0 1 0  varbiteq - ));
+DATA(insert OID = 1666 (  varbiteq                     PGUID 12 f t t t 2 f 16 "1562 1562" 100 0 0 100  biteq - ));
 DESCR("equal");
-DATA(insert OID = 1667 (  varbitne                     PGUID 11 f t t t 2 f 16 "1562 1562" 100 0 1 0  varbitne - ));
+DATA(insert OID = 1667 (  varbitne                     PGUID 12 f t t t 2 f 16 "1562 1562" 100 0 0 100  bitne - ));
 DESCR("not equal");
-DATA(insert OID = 1668 (  varbitge                     PGUID 11 f t t t 2 f 16 "1562 1562" 100 0 1 0  varbitge - ));
+DATA(insert OID = 1668 (  varbitge                     PGUID 12 f t t t 2 f 16 "1562 1562" 100 0 0 100  bitge - ));
 DESCR("greater than or equal");
-DATA(insert OID = 1669 (  varbitgt                     PGUID 11 f t t t 2 f 16 "1562 1562" 100 0 1 0  varbitgt - ));
+DATA(insert OID = 1669 (  varbitgt                     PGUID 12 f t t t 2 f 16 "1562 1562" 100 0 0 100  bitgt - ));
 DESCR("greater than");
-DATA(insert OID = 1670 (  varbitle                     PGUID 11 f t t t 2 f 16 "1562 1562" 100 0 1 0  varbitle - ));
+DATA(insert OID = 1670 (  varbitle                     PGUID 12 f t t t 2 f 16 "1562 1562" 100 0 0 100  bitle - ));
 DESCR("less than or equal");
-DATA(insert OID = 1671 (  varbitlt                     PGUID 11 f t t t 2 f 16 "1562 1562" 100 0 1 0  varbitlt - ));
+DATA(insert OID = 1671 (  varbitlt                     PGUID 12 f t t t 2 f 16 "1562 1562" 100 0 0 100  bitlt - ));
 DESCR("less than");
-DATA(insert OID = 1672 (  varbitcmp                    PGUID 11 f t t t 2 f 23 "1562 1562" 100 0 1 0  varbitcmp - ));
+DATA(insert OID = 1672 (  varbitcmp                    PGUID 12 f t t t 2 f 23 "1562 1562" 100 0 0 100  bitcmp - ));
 DESCR("compare");
 
-DATA(insert OID = 1673 (  bitand                       PGUID 11 f t t t 2 f 1560 "1560 1560" 100 0 1 0  bitand - ));
+DATA(insert OID = 1673 (  bitand                       PGUID 12 f t t t 2 f 1560 "1560 1560" 100 0 0 100  bitand - ));
 DESCR("bitwise and");
-DATA(insert OID = 1674 (  bitor                                PGUID 11 f t t t 2 f 1560 "1560 1560" 100 0 1 0  bitor - ));
+DATA(insert OID = 1674 (  bitor                                PGUID 12 f t t t 2 f 1560 "1560 1560" 100 0 0 100  bitor - ));
 DESCR("bitwise or");
-DATA(insert OID = 1675 (  bitxor                       PGUID 11 f t t t 2 f 1560 "1560 1560" 100 0 1 0  bitxor - ));
+DATA(insert OID = 1675 (  bitxor                       PGUID 12 f t t t 2 f 1560 "1560 1560" 100 0 0 100  bitxor - ));
 DESCR("bitwise exclusive or");
-DATA(insert OID = 1676 (  bitnot                       PGUID 11 f t t t 2 f 1560 "1560 1560" 100 0 1 0  bitnot - ));
+DATA(insert OID = 1676 (  bitnot                       PGUID 12 f t t t 1 f 1560 "1560" 100 0 0 100  bitnot - ));
 DESCR("bitwise negation");
-DATA(insert OID = 1677 (  bitshiftright                PGUID 11 f t 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 t 2 f 1560 "1560 1560" 100 0 1 0  bitshiftleft - ));
+DATA(insert OID = 1677 (  bitshiftleft         PGUID 12 f t t t 2 f 1560 "1560 23" 100 0 0 100  bitshiftleft - ));
 DESCR("bitwise left shift");
-DATA(insert OID = 1679 (  bitcat                       PGUID 11 f t 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 t 2 f 1560 "1560 1560" 100 0 1 0  bitsubstr - ));
-DESCR("bitwise field");
-
-DATA(insert OID = 1681 (  varbitand                    PGUID 11 f t 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 t 2 f 1562 "1562 1562" 100 0 1 0  varbitor - ));
-DESCR("bitwise or");
-DATA(insert OID = 1683 (  varbitxor                    PGUID 11 f t 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 t 2 f 1562 "1562 1562" 100 0 1 0  varbitnot - ));
-DESCR("bitwise negation");
-DATA(insert OID = 1685 (  varbitshiftright     PGUID 11 f t t t 2 f 1562 "1562 1562" 100 0 1 0  varbitshiftright - ));
+DATA(insert OID = 1678 (  bitshiftright                PGUID 12 f t t t 2 f 1560 "1560 23" 100 0 0 100  bitshiftright - ));
 DESCR("bitwise right shift");
-DATA(insert OID = 1686 (  varbitshiftleft      PGUID 11 f t 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 t 2 f 1562 "1562 1562" 100 0 1 0  varbitcat - ));
+DATA(insert OID = 1679 (  bitcat                       PGUID 12 f t t t 2 f 1560 "1560 1560" 100 0 0 100  bitcat - ));
 DESCR("bitwise concatenation");
-DATA(insert OID = 1688 (  varbitsubstr         PGUID 11 f t t t 2 f 1562 "1562 1562" 100 0 1 0  varbitsubstr - ));
+DATA(insert OID = 1680 (  bitsubstr                    PGUID 12 f t t t 3 f 1560 "1560 23 23" 100 0 0 100  bitsubstr - ));
 DESCR("bitwise field");
+DATA(insert OID = 1681 (  length                       PGUID 12 f t t t 1 f 23 "1560" 100 0 0 100  bitlength - ));
+DESCR("bitstring length");
+DATA(insert OID = 1682 (  octet_length         PGUID 12 f t t t 1 f 23 "1560" 100 0 0 100  bitoctetlength - ));
+DESCR("octet length");
+DATA(insert OID = 1683 (  bitfromint4          PGUID 12 f t t t 1 f 1560 "23" 100 0 0 100  bitfromint4 - ));
+DESCR("int4 to bitstring");
+DATA(insert OID = 1684 (  bittoint4                    PGUID 12 f t t t 1 f 23 "1560" 100 0 0 100  bittoint4 - ));
+DESCR("bitstring to int4");
+
+DATA(insert OID = 1685 (  bit                     PGUID 12 f t t t 2 f 1560 "1560 23" 100 0 0 100  zpbit - ));
+DESCR("adjust bit() to typmod length");
+DATA(insert OID = 1686 (  _bit                    PGUID 12 f t t t 2 f 1561 "1561 23" 100 0 0 100  _zpbit - ));
+DESCR("adjust bit()[] to typmod length");
+DATA(insert OID = 1687 (  varbit                  PGUID 12 f t t t 2 f 1562 "1562 23" 100 0 0 100  varbit - ));
+DESCR("adjust varbit() to typmod length");
+DATA(insert OID = 1688 (  _varbit                 PGUID 12 f t t t 2 f 1563 "1563 23" 100 0 0 100  _varbit - ));
+DESCR("adjust varbit()[] to typmod length");
 
 /* for mac type support */
 DATA(insert OID = 436 (  macaddr_in                    PGUID 12 f t t t 1 f 829 "0" 100 0 0 100        macaddr_in - ));
index 7b9f702922205dd5078294b036291667b046483c..48cf26d172a27ad2b9114a586736218811ec2898 100644 (file)
@@ -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.96 2000/07/30 22:14:02 tgl Exp $
+ * $Id: pg_type.h,v 1.97 2000/08/21 04:48:52 tgl Exp $
  *
  * NOTES
  *       the genbki.sh script reads this file and generates .bki
@@ -399,12 +399,12 @@ DESCR("hh:mm:ss, ANSI SQL time");
 DATA(insert OID = 1270 ( _timetz        PGUID  -1 -1 f b t \054 0      1266 array_in array_out array_in array_out d x _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 p _null_ ));
+DATA(insert OID = 1560 ( bit            PGUID -1  -1 f b t \054 0      0 zpbit_in zpbit_out zpbit_in zpbit_out i x _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 x _null_ ));
-DATA(insert OID = 1562 ( varbit                 PGUID -1  -1 f b t \054 0      0 varbit_in varbit_out varbit_in varbit_out i p _null_ ));
-DESCR("fixed-length bit string");
+DATA(insert OID = 1562 ( varbit                 PGUID -1  -1 f b t \054 0      0 varbit_in varbit_out varbit_in varbit_out i x _null_ ));
+DESCR("variable-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 x _null_ ));
 
index 0bb324402fbc13b943186e2c285510123284598d..acea75d01dfdb7d5a0a9a23c5802026b9647ae52 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: parse_coerce.h,v 1.22 2000/04/12 17:16:45 momjian Exp $
+ * $Id: parse_coerce.h,v 1.23 2000/08/21 04:48:52 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -67,13 +67,16 @@ typedef enum CATEGORY
                || ((t) == POLYGONOID) \
                || ((t) == CIRCLEOID) \
                || ((t) == INETOID) \
-               || ((t) == CIDROID) )
+               || ((t) == CIDROID) \
+               || ((t) == ZPBITOID) \
+               || ((t) == VARBITOID) )
 
 
 /* IS_BINARY_COMPATIBLE()
  * Check for types with the same underlying binary representation.
  * This allows us to cheat and directly exchange values without
  *     going through the trouble of calling a conversion function.
+ *
  * Remove equivalencing of FLOAT8 and TIMESTAMP. They really are not
  *     close enough in behavior, with the TIMESTAMP reserved values
  *     and special formatting. - thomas 1999-01-24
@@ -96,7 +99,9 @@ typedef enum CATEGORY
                || ((a) == RELTIMEOID && (b) == INT4OID) \
                || ((a) == INT4OID && (b) == RELTIMEOID) \
                || ((a) == INETOID && (b) == CIDROID) \
-               || ((a) == CIDROID && (b) == INETOID))
+               || ((a) == CIDROID && (b) == INETOID) \
+               || ((a) == ZPBITOID && (b) == VARBITOID) \
+               || ((a) == VARBITOID && (b) == ZPBITOID))
 
 /* IS_HIGHER_TYPE()
  * These types are the most general in each of the type categories.
index 06f51f429cb338f36e17ca423e005b5a88d3ffa9..e3ff9a8efb4c0abfa617e6439402353ee632512b 100644 (file)
@@ -1,78 +1,91 @@
+/*-------------------------------------------------------------------------
+ *
+ * varbit.h
+ *       Functions for the SQL datatypes BIT() and BIT VARYING().
+ *
+ * Code originally contributed by Adriaan Joubert.
+ *
+ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * $Id: varbit.h,v 1.6 2000/08/21 04:48:54 tgl Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
 #ifndef VARBIT_H
 #define VARBIT_H
 
-#include "postgres.h"
+#include "fmgr.h"
 
-#include <math.h>
-#include <limits.h>
-
-#include "utils/builtins.h"
-
-
-#define HEXDIG(z)       ((z)<10 ? ((z)+'0') : ((z)-10+'A'))
-
-/* Modeled on struct varlena from postgres.h, but data type is bits8 */
-struct varbita
+/*
+ * Modeled on struct varlena from postgres.h, but data type is bits8.
+ */
+typedef struct
 {
-       int32           vl_len;
-       bits8           vl_dat[1];
-};
+       int32           vl_len;                 /* standard varlena header (total size in bytes) */
+       int32           bit_len;                /* number of valid bits */
+       bits8           bit_dat[1];             /* bit string, most sig. byte first */
+} VarBit;
+
+/*
+ * fmgr interface macros
+ *
+ * BIT and BIT VARYING are toastable varlena types.  They are the same
+ * as far as representation goes, so we just have one set of macros.
+ */
+#define DatumGetVarBitP(X)         ((VarBit *) PG_DETOAST_DATUM(X))
+#define DatumGetVarBitPCopy(X)     ((VarBit *) PG_DETOAST_DATUM_COPY(X))
+#define VarBitPGetDatum(X)         PointerGetDatum(X)
+#define PG_GETARG_VARBIT_P(n)      DatumGetVarBitP(PG_GETARG_DATUM(n))
+#define PG_GETARG_VARBIT_P_COPY(n) DatumGetVarBitPCopy(PG_GETARG_DATUM(n))
+#define PG_RETURN_VARBIT_P(x)      return VarBitPGetDatum(x)
 
-#define VARBITHDRSZ            sizeof(int32)
+/* Header overhead *in addition to* VARHDRSZ */
+#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)
+#define VARBITLEN(PTR)         (((VarBit *) (PTR))->bit_len)
+/* Pointer to the first byte containing bit string data */
+#define VARBITS(PTR)           (((VarBit *) (PTR))->bit_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 */
+/* Padding of the bit string at the end (in bits) */
 #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)
+#define VARBITTOTALLEN(BITLEN) (((BITLEN) + BITSPERBYTE-1)/BITSPERBYTE + \
+                                                                VARHDRSZ + VARBITHDRSZ)
 /* pointer beyond the end of the bit string (like end() in STL containers) */
-#define VARBITEND(PTR)         ((bits8 *) (PTR + VARSIZE(PTR)))
+#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);
+extern Datum zpbit_in(PG_FUNCTION_ARGS);
+extern Datum zpbit_out(PG_FUNCTION_ARGS);
+extern Datum varbit_in(PG_FUNCTION_ARGS);
+extern Datum varbit_out(PG_FUNCTION_ARGS);
+extern Datum zpbit(PG_FUNCTION_ARGS);
+extern Datum _zpbit(PG_FUNCTION_ARGS);
+extern Datum varbit(PG_FUNCTION_ARGS);
+extern Datum _varbit(PG_FUNCTION_ARGS);
+extern Datum biteq(PG_FUNCTION_ARGS);
+extern Datum bitne(PG_FUNCTION_ARGS);
+extern Datum bitlt(PG_FUNCTION_ARGS);
+extern Datum bitle(PG_FUNCTION_ARGS);
+extern Datum bitgt(PG_FUNCTION_ARGS);
+extern Datum bitge(PG_FUNCTION_ARGS);
+extern Datum bitcmp(PG_FUNCTION_ARGS);
+extern Datum bitand(PG_FUNCTION_ARGS);
+extern Datum bitor(PG_FUNCTION_ARGS);
+extern Datum bitxor(PG_FUNCTION_ARGS);
+extern Datum bitnot(PG_FUNCTION_ARGS);
+extern Datum bitshiftleft(PG_FUNCTION_ARGS);
+extern Datum bitshiftright(PG_FUNCTION_ARGS);
+extern Datum bitcat(PG_FUNCTION_ARGS);
+extern Datum bitsubstr(PG_FUNCTION_ARGS);
+extern Datum bitlength(PG_FUNCTION_ARGS);
+extern Datum bitoctetlength(PG_FUNCTION_ARGS);
+extern Datum bitfromint4(PG_FUNCTION_ARGS);
+extern Datum bittoint4(PG_FUNCTION_ARGS);
 
 #endif
index 8b84e833662fab105ce599811145167e7598faa0..f5d2427cfa1b7d048589d67ecb52d0a1c0a1ec11 100644 (file)
@@ -97,7 +97,8 @@ WHERE p1.oid != p2.oid AND
  proargtypes | proargtypes 
 -------------+-------------
           25 |        1043
-(1 row)
+        1560 |        1562
+(2 rows)
 
 SELECT DISTINCT p1.proargtypes[1], p2.proargtypes[1]
 FROM pg_proc AS p1, pg_proc AS p2
@@ -108,7 +109,8 @@ WHERE p1.oid != p2.oid AND
     (p1.proargtypes[1] < p2.proargtypes[1]);
  proargtypes | proargtypes 
 -------------+-------------
-(0 rows)
+        1560 |        1562
+(1 row)
 
 SELECT DISTINCT p1.proargtypes[2], p2.proargtypes[2]
 FROM pg_proc AS p1, pg_proc AS p2
@@ -480,8 +482,8 @@ WHERE p1.aggtransfn = p2.oid AND
           (p2.pronargs = 1 AND p1.aggbasetype = 0)));
   oid  | aggname | oid |   proname   
 -------+---------+-----+-------------
- 16972 | max     | 768 | int4larger
- 16986 | min     | 769 | int4smaller
+ 16984 | max     | 768 | int4larger
+ 16998 | min     | 769 | int4smaller
 (2 rows)
 
 -- Cross-check finalfn (if present) against its entry in pg_proc.