Change parse-time representation of float literals (which include oversize
authorTom Lane
Mon, 21 Feb 2000 18:47:12 +0000 (18:47 +0000)
committerTom Lane
Mon, 21 Feb 2000 18:47:12 +0000 (18:47 +0000)
integers) to be strings instead of 'double'.  We convert from string form
to internal representation only after type resolution has determined the
correct type for the constant.  This eliminates loss-of-precision worries
and gets rid of the change in behavior seen at 17 digits with the
previous kluge.

12 files changed:
src/backend/nodes/copyfuncs.c
src/backend/nodes/equalfuncs.c
src/backend/nodes/freefuncs.c
src/backend/nodes/list.c
src/backend/nodes/outfuncs.c
src/backend/nodes/read.c
src/backend/parser/gram.y
src/backend/parser/parse_expr.c
src/backend/parser/scan.l
src/backend/storage/buffer/bufmgr.c
src/backend/utils/adt/network.c
src/include/nodes/pg_list.h

index fbef91b35d8006b8d28739c65811b0ea5f9faa49..601b503ec114a50eae39d23ad5103c2e07156f97 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.107 2000/02/20 21:32:05 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.108 2000/02/21 18:47:00 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1501,14 +1501,12 @@ _copyValue(Value *from)
    newnode->type = from->type;
    switch (from->type)
    {
-       case T_String:
-           newnode->val.str = pstrdup(from->val.str);
-           break;
        case T_Integer:
            newnode->val.ival = from->val.ival;
            break;
        case T_Float:
-           newnode->val.dval = from->val.dval;
+       case T_String:
+           newnode->val.str = pstrdup(from->val.str);
            break;
        default:
            break;
@@ -1722,8 +1720,8 @@ copyObject(void *from)
             * VALUE NODES
             */
        case T_Integer:
-       case T_String:
        case T_Float:
+       case T_String:
            retval = _copyValue(from);
            break;
        case T_List:
index b4f5fc6285c2ba77e296d151014bd358350f1c6c..6cb9eada0f8a6c937c0578d04da98b66821923de 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.62 2000/02/20 21:32:05 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.63 2000/02/21 18:47:00 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -737,12 +737,11 @@ _equalValue(Value *a, Value *b)
 
    switch (a->type)
    {
-       case T_String:
-           return strcmp(a->val.str, b->val.str);
        case T_Integer:
            return a->val.ival == b->val.ival;
        case T_Float:
-           return a->val.dval == b->val.dval;
+       case T_String:
+           return strcmp(a->val.str, b->val.str) == 0;
        default:
            break;
    }
@@ -870,8 +869,8 @@ equal(void *a, void *b)
            retval = _equalEState(a, b);
            break;
        case T_Integer:
-       case T_String:
        case T_Float:
+       case T_String:
            retval = _equalValue(a, b);
            break;
        case T_List:
index daca4a6d96a18230f27010f93b76434ed531edc2..14a5ed12d9e90d9ed4c06597b0c28918216b454f 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/nodes/Attic/freefuncs.c,v 1.37 2000/02/20 21:32:05 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/nodes/Attic/freefuncs.c,v 1.38 2000/02/21 18:47:00 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1130,7 +1130,8 @@ _freeValue(Value *node)
 {
    switch (node->type)
    {
-           case T_String:
+       case T_Float:
+       case T_String:
            pfree(node->val.str);
            break;
        default:
@@ -1345,8 +1346,8 @@ freeObject(void *node)
             * VALUE NODES
             */
        case T_Integer:
-       case T_String:
        case T_Float:
+       case T_String:
            _freeValue(node);
            break;
        case T_List:
index 723930f36a8f0011b29d82a80863750f0cf64fe6..a47851f2420b8b066c5b23ea706658453b08dbb6 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/nodes/list.c,v 1.29 2000/02/06 03:27:32 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/nodes/list.c,v 1.30 2000/02/21 18:47:00 tgl Exp $
  *
  * NOTES
  *   XXX a few of the following functions are duplicated to handle
@@ -73,19 +73,23 @@ makeInteger(long i)
 
 /*
  * makeFloat
+ *
+ * Caller is responsible for passing a palloc'd string.
  */
 Value *
-makeFloat(double d)
+makeFloat(char *numericStr)
 {
    Value      *v = makeNode(Value);
 
    v->type = T_Float;
-   v->val.dval = d;
+   v->val.str = numericStr;
    return v;
 }
 
 /*
  * makeString
+ *
+ * Caller is responsible for passing a palloc'd string.
  */
 Value *
 makeString(char *str)
index db785afab9fa9ea4a91ef279d32eb18f3a29c815..eb2c1a7ffa8528b50243a5738aca739e90dc95aa 100644 (file)
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.109 2000/02/20 21:32:05 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.110 2000/02/21 18:47:00 tgl Exp $
  *
  * NOTES
  *   Every (plan) node in POSTGRES has an associated "out" routine which
@@ -1265,16 +1265,19 @@ _outValue(StringInfo str, Value *value)
 {
    switch (value->type)
    {
-       case T_String:
-           appendStringInfo(str, " \"");
-           _outToken(str, value->val.str);
-           appendStringInfo(str, "\" ");
-           break;
        case T_Integer:
            appendStringInfo(str, " %ld ", value->val.ival);
            break;
        case T_Float:
-           appendStringInfo(str, " %.17g ", value->val.dval);
+           /* We assume the value is a valid numeric literal
+            * and so does not need quoting.
+            */
+           appendStringInfo(str, " %s ", value->val.str);
+           break;
+       case T_String:
+           appendStringInfo(str, " \"");
+           _outToken(str, value->val.str);
+           appendStringInfo(str, "\" ");
            break;
        default:
            elog(NOTICE, "_outValue: don't know how to print type %d ",
index 75e10576d5b5fa30b3726d9a133b0656b2a6a852..9f68f4d0e90892e52f5062dbd1ab94b31170c051 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/nodes/read.c,v 1.20 2000/01/26 05:56:32 momjian Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/nodes/read.c,v 1.21 2000/02/21 18:47:00 tgl Exp $
  *
  * HISTORY
  *   AUTHOR            DATE            MAJOR EVENT
@@ -18,6 +18,7 @@
  *-------------------------------------------------------------------------
  */
 #include 
+#include 
 
 #include "postgres.h"
 
@@ -193,30 +194,32 @@ static NodeTag
 nodeTokenType(char *token, int length)
 {
    NodeTag     retval;
+   char       *numptr;
+   int         numlen;
+   char       *endptr;
 
    /*
-    * Check if the token is a number (decimal or integer, positive or
-    * negative)
+    * Check if the token is a number
     */
-   if (isdigit(*token) ||
-       (length >= 2 && *token == '-' && isdigit(token[1])))
+   numptr = token;
+   numlen = length;
+   if (*numptr == '+' || *numptr == '-')
+       numptr++, numlen--;
+   if ((numlen > 0 && isdigit(*numptr)) ||
+       (numlen > 1 && *numptr == '.' && isdigit(numptr[1])))
    {
        /*
-        * skip the optional '-' (i.e. negative number)
+        * Yes.  Figure out whether it is integral or float;
+        * this requires both a syntax check and a range check.
+        * strtol() can do both for us.
+        * We know the token will end at a character that strtol will
+        * stop at, so we do not need to modify the string.
         */
-       if (*token == '-')
-           token++, length--;
-
-       /*
-        * See if there is a decimal point
-        */
-       while (length > 0 && *token != '.')
-           token++, length--;
-
-       /*
-        * if there isn't, token's an int, otherwise it's a float.
-        */
-       retval = (*token != '.') ? T_Integer : T_Float;
+       errno = 0;
+       (void) strtol(token, &endptr, 10);
+       if (endptr != token+length || errno == ERANGE)
+           return T_Float;
+       return T_Integer;
    }
    /*
     * these three cases do not need length checks, since lsptok()
@@ -317,17 +320,23 @@ nodeRead(bool read_car_only)
                make_dotted_pair_cell = true;
            }
            break;
-       case T_Float:
-           /* we know that the token terminates on a char atof will stop at */
-           this_value = (Node *) makeFloat(atof(token));
-           make_dotted_pair_cell = true;
-           break;
        case T_Integer:
-           /* we know that the token terminates on a char atoi will stop at */
-           this_value = (Node *) makeInteger(atoi(token));
+           /* we know that the token terminates on a char atol will stop at */
+           this_value = (Node *) makeInteger(atol(token));
            make_dotted_pair_cell = true;
            break;
+       case T_Float:
+           {
+               char   *fval = (char *) palloc(tok_len + 1);
+
+               memcpy(fval, token, tok_len);
+               fval[tok_len] = '\0';
+               this_value = (Node *) makeFloat(fval);
+               make_dotted_pair_cell = true;
+           }
+           break;
        case T_String:
+           /* need to remove leading and trailing quotes, and backslashes */
            this_value = (Node *) makeString(debackslash(token+1, tok_len-2));
            make_dotted_pair_cell = true;
            break;
index f43393eeff872ca2477bf96c42336f264cd5e7fa..b81b6d387aba6c8dd7d48e57843abdd364ede543 100644 (file)
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.147 2000/02/20 02:14:58 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.148 2000/02/21 18:47:02 tgl Exp $
  *
  * HISTORY
  *   AUTHOR            DATE            MAJOR EVENT
@@ -78,6 +78,7 @@ static Node *makeRowExpr(char *opr, List *largs, List *rargs);
 static void mapTargetColumns(List *source, List *target);
 static void param_type_init(Oid *typev, int nargs);
 static Node *doNegate(Node *n);
+static void doNegateFloat(Value *v);
 
 /* old versions of flex define this as a macro */
 #if defined(yywrap)
@@ -88,7 +89,6 @@ static Node *doNegate(Node *n);
 
 %union
 {
-   double              dval;
    int                 ival;
    char                chr;
    char                *str;
@@ -352,9 +352,8 @@ static Node *doNegate(Node *n);
        UNLISTEN, UNTIL, VACUUM, VALID, VERBOSE, VERSION
 
 /* Special keywords, not in the query language - see the "lex" file */
-%token    IDENT, SCONST, Op
+%token    IDENT, FCONST, SCONST, Op
 %token   ICONST, PARAM
-%token   FCONST
 
 /* these are not real. they are here so that they get generated as #define's*/
 %token         OP
@@ -1567,7 +1566,7 @@ FloatOnly:  FCONST
            | '-' FCONST
                {
                    $$ = makeFloat($2);
-                   $$->val.dval = - $$->val.dval;
+                   doNegateFloat($$);
                }
        ;
 
@@ -1722,16 +1721,11 @@ TriggerFuncArgs:  TriggerFuncArg
 
 TriggerFuncArg:  ICONST
                {
-                   char *s = (char *) palloc (256);
+                   char *s = (char *) palloc(64);
                    sprintf (s, "%d", $1);
                    $$ = s;
                }
-           | FCONST
-               {
-                   char *s = (char *) palloc (256);
-                   sprintf (s, "%g", $1);
-                   $$ = s;
-               }
+           | FCONST                        {  $$ = $1; }
            | Sconst                        {  $$ = $1; }
            | IDENT                         {  $$ = $1; }
        ;
@@ -5183,7 +5177,7 @@ AexprConst:  Iconst
                {
                    A_Const *n = makeNode(A_Const);
                    n->val.type = T_Float;
-                   n->val.val.dval = $1;
+                   n->val.val.str = $1;
                    $$ = (Node *)n;
                }
        | Sconst
@@ -5621,7 +5615,8 @@ Oid param_type(int t)
  * a few cycles throughout the parse and rewrite stages if we collapse
  * the minus into the constant sooner rather than later...
  */
-static Node *doNegate(Node *n)
+static Node *
+doNegate(Node *n)
 {
    if (IsA(n, A_Const))
    {
@@ -5634,10 +5629,30 @@ static Node *doNegate(Node *n)
        }
        if (con->val.type == T_Float)
        {
-           con->val.val.dval = -con->val.val.dval;
+           doNegateFloat(&con->val);
            return n;
        }
    }
 
    return makeA_Expr(OP, "-", NULL, n);
 }
+
+static void
+doNegateFloat(Value *v)
+{
+   char   *oldval = v->val.str;
+
+   Assert(IsA(v, Float));
+   if (*oldval == '+')
+       oldval++;
+   if (*oldval == '-')
+       v->val.str = oldval;    /* just strip the '-' */
+   else
+   {
+       char   *newval = (char *) palloc(strlen(oldval) + 2);
+
+       *newval = '-';
+       strcpy(newval+1, oldval);
+       v->val.str = newval;
+   }
+}
index 3fd3370672ff40db0af42520cb4f3360c516fb92..2efdd136005ce3a181bd6685f40ee7b49950eeda 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.69 2000/02/20 21:32:10 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.70 2000/02/21 18:47:02 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -726,23 +726,19 @@ parser_typecast_constant(Value *expr, TypeName *typename)
 
    switch (nodeTag(expr))
    {
-       case T_String:
-           const_string = DatumGetPointer(expr->val.str);
-           break;
        case T_Integer:
            string_palloced = true;
            const_string = int4out(expr->val.ival);
            break;
        case T_Float:
-           string_palloced = true;
-           const_string = float8out(&expr->val.dval);
+       case T_String:
+           const_string = expr->val.str;
            break;
        case T_Null:
            isNull = true;
            break;
        default:
-           elog(ERROR,
-                "Cannot cast this expression to type '%s'",
+           elog(ERROR, "Cannot cast this expression to type '%s'",
                 typename->name);
    }
 
index fa3408c1f1df79e28ff1660cfde624e1d48af8eb..5b8dd16d81f93324a00d781095942471d62404dc 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/parser/scan.l,v 1.64 2000/02/19 04:17:25 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/parser/scan.l,v 1.65 2000/02/21 18:47:02 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -324,7 +324,7 @@ other           .
                }
 
 {param}            {
-                   yylval.ival = atoi((char*)&yytext[1]);
+                   yylval.ival = atol((char*)&yytext[1]);
                    return PARAM;
                }
 
@@ -332,46 +332,21 @@ other         .
                    char* endptr;
 
                    errno = 0;
-                   yylval.ival = strtol((char *)yytext,&endptr,10);
+                   yylval.ival = strtol((char *)yytext, &endptr, 10);
                    if (*endptr != '\0' || errno == ERANGE)
                    {
-                       errno = 0;
-#if 0
-                       yylval.dval = strtod(((char *)yytext),&endptr);
-                       if (*endptr != '\0' || errno == ERANGE)
-                           elog(ERROR,"Bad integer input '%s'",yytext);
-                       CheckFloat8Val(yylval.dval);
-                       elog(NOTICE,"Integer input '%s' is out of range; promoted to float", yytext);
-                       return FCONST;
-#endif
+                       /* integer too large, treat it as a float */
                        yylval.str = pstrdup((char*)yytext);
-                       return SCONST;
+                       return FCONST;
                    }
                    return ICONST;
                }
 {decimal}      {
-                   char* endptr;
-
-                   if (strlen((char *)yytext) <= 17)
-                   {
-                       errno = 0;
-                       yylval.dval = strtod((char *)yytext,&endptr);
-                       if (*endptr != '\0' || errno == ERANGE)
-                           elog(ERROR,"Bad float input '%s'",yytext);
-                       CheckFloat8Val(yylval.dval);
-                       return FCONST;
-                   }
                    yylval.str = pstrdup((char*)yytext);
-                   return SCONST;
+                   return FCONST;
                }
 {real}         {
-                   char* endptr;
-
-                   errno = 0;
-                   yylval.dval = strtod((char *)yytext,&endptr);
-                   if (*endptr != '\0' || errno == ERANGE)
-                       elog(ERROR,"Bad float input '%s'",yytext);
-                   CheckFloat8Val(yylval.dval);
+                   yylval.str = pstrdup((char*)yytext);
                    return FCONST;
                }
 
index d6120affabefda8efdcedbb5747e3f0f1e360619..f5d613233101ab2ac8e7458264cb345960d9bd98 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.73 2000/02/17 05:00:38 inoue Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.74 2000/02/21 18:47:03 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -453,6 +453,7 @@ BufferAlloc(Relation reln,
         */
        Assert(buf->refcount == 0);
        buf->refcount = 1;
+       Assert(PrivateRefCount[BufferDescriptorGetBuffer(buf) - 1] == 0);
        PrivateRefCount[BufferDescriptorGetBuffer(buf) - 1] = 1;
 
        if (buf->flags & BM_DIRTY)
@@ -542,6 +543,7 @@ BufferAlloc(Relation reln,
                inProgress = FALSE;
                buf->flags &= ~BM_IO_IN_PROGRESS;
                TerminateBufferIO(buf);
+               Assert(PrivateRefCount[BufferDescriptorGetBuffer(buf)-1] == 1);
                PrivateRefCount[BufferDescriptorGetBuffer(buf) - 1] = 0;
                buf->refcount--;
                buf = (BufferDesc *) NULL;
@@ -568,6 +570,7 @@ BufferAlloc(Relation reln,
                {
                    TerminateBufferIO(buf);
                    /* give up the buffer since we don't need it any more */
+                   Assert(PrivateRefCount[BufferDescriptorGetBuffer(buf)-1] == 1);
                    PrivateRefCount[BufferDescriptorGetBuffer(buf) - 1] = 0;
                    Assert(buf->refcount > 0);
                    buf->refcount--;
@@ -1469,8 +1472,16 @@ ReleaseRelationBuffers(Relation rel)
            if (!(buf->flags & BM_FREE))
            {
                /* Assert checks that buffer will actually get freed! */
-               Assert(PrivateRefCount[i - 1] == 1 &&
-                      buf->refcount == 1);
+               Assert(buf->refcount == 1);
+               if (PrivateRefCount[i - 1] <= 0)
+               {
+                   fprintf(stderr, "Nonpositive PrivateRefCount on buffer for %s\n",
+                           RelationGetRelationName(rel));
+                   fflush(stderr);
+                   * ((char *) 0) = 0;
+                   abort();
+               }
+               Assert(PrivateRefCount[i - 1] == 1);
                /* ReleaseBuffer expects we do not hold the lock at entry */
                SpinRelease(BufMgrLock);
                holding = false;
index cb1b9b90bfea4ed3b7e02d2d602c067fdc5df0f2..44045c184b5c591a8d619233c711457fc78ca4c0 100644 (file)
@@ -3,22 +3,23 @@
  * is for IP V4 CIDR notation, but prepared for V6: just
  * add the necessary bits where the comments indicate.
  *
- * $Id: network.c,v 1.16 1999/09/23 17:42:23 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/network.c,v 1.17 2000/02/21 18:47:07 tgl Exp $
+ *
  * Jon Postel RIP 16 Oct 1998
  */
 
+#include "postgres.h"
+
 #include 
 #include 
-
 #include 
-
 #include 
 #include 
 
-#include "postgres.h"
 #include "utils/builtins.h"
 
-static int v4bitncmp(unsigned int a1, unsigned int a2, int bits);
+
+static int v4bitncmp(unsigned long a1, unsigned long a2, int bits);
 
 /*
  * Access macros.  Add IPV6 support.
@@ -39,6 +40,7 @@ static int    v4bitncmp(unsigned int a1, unsigned int a2, int bits);
 #define ip_v4addr(inetptr) \
    (((inet_struct *)VARDATA(inetptr))->addr.ipv4_addr)
 
+
 /* Common input routine */
 static inet *
 network_in(char *src, int type)
@@ -127,7 +129,8 @@ cidr_out(inet *src)
 }
 
 /*
- * Boolean tests for magnitude.  Add V4/V6 testing!
+ * Boolean tests for ordering operators --- must agree with sorting
+ * operator network_cmp().
  */
 
 bool
@@ -135,19 +138,7 @@ network_lt(inet *a1, inet *a2)
 {
    if (!PointerIsValid(a1) || !PointerIsValid(a2))
        return FALSE;
-   if ((ip_family(a1) == AF_INET) && (ip_family(a2) == AF_INET))
-   {
-       int         order = v4bitncmp(ip_v4addr(a1), ip_v4addr(a2), ip_bits(a2));
-
-       return ((order < 0) || ((order == 0) && (ip_bits(a1) < ip_bits(a2))));
-   }
-   else
-   {
-       /* Go for an IPV6 address here, before faulting out: */
-       elog(ERROR, "cannot compare address families %d and %d",
-            ip_family(a1), ip_family(a2));
-       return FALSE;
-   }
+   return (bool) (network_cmp(a1, a2) < 0);
 }
 
 bool
@@ -155,7 +146,7 @@ network_le(inet *a1, inet *a2)
 {
    if (!PointerIsValid(a1) || !PointerIsValid(a2))
        return FALSE;
-   return (network_lt(a1, a2) || network_eq(a1, a2));
+   return (bool) (network_cmp(a1, a2) <= 0);
 }
 
 bool
@@ -163,18 +154,7 @@ network_eq(inet *a1, inet *a2)
 {
    if (!PointerIsValid(a1) || !PointerIsValid(a2))
        return FALSE;
-   if ((ip_family(a1) == AF_INET) && (ip_family(a2) == AF_INET))
-   {
-       return ((ip_bits(a1) == ip_bits(a2))
-        && (v4bitncmp(ip_v4addr(a1), ip_v4addr(a2), ip_bits(a1)) == 0));
-   }
-   else
-   {
-       /* Go for an IPV6 address here, before faulting out: */
-       elog(ERROR, "cannot compare address families %d and %d",
-            ip_family(a1), ip_family(a2));
-       return FALSE;
-   }
+   return (bool) (network_cmp(a1, a2) == 0);
 }
 
 bool
@@ -182,7 +162,7 @@ network_ge(inet *a1, inet *a2)
 {
    if (!PointerIsValid(a1) || !PointerIsValid(a2))
        return FALSE;
-   return (network_gt(a1, a2) || network_eq(a1, a2));
+   return (bool) (network_cmp(a1, a2) >= 0);
 }
 
 bool
@@ -190,29 +170,44 @@ network_gt(inet *a1, inet *a2)
 {
    if (!PointerIsValid(a1) || !PointerIsValid(a2))
        return FALSE;
+   return (bool) (network_cmp(a1, a2) > 0);
+}
+
+bool
+network_ne(inet *a1, inet *a2)
+{
+   if (!PointerIsValid(a1) || !PointerIsValid(a2))
+       return FALSE;
+   return (bool) (network_cmp(a1, a2) != 0);
+}
+
+/*
+ * Comparison function for sorting.  Add V4/V6 testing!
+ */
+
+int4
+network_cmp(inet *a1, inet *a2)
+{
    if ((ip_family(a1) == AF_INET) && (ip_family(a2) == AF_INET))
    {
-       int         order = v4bitncmp(ip_v4addr(a1), ip_v4addr(a2), ip_bits(a2));
-
-       return ((order > 0) || ((order == 0) && (ip_bits(a1) > ip_bits(a2))));
+       int     order = v4bitncmp(ip_v4addr(a1), ip_v4addr(a2),
+                                 (ip_bits(a1) < ip_bits(a2)) ?
+                                 ip_bits(a1) : ip_bits(a2));
+
+       if (order)
+           return order;
+       /* They agree in the first N bits, so shorter one comes first */
+       return (int) ip_bits(a1) - (int) ip_bits(a2);
    }
    else
    {
        /* Go for an IPV6 address here, before faulting out: */
        elog(ERROR, "cannot compare address families %d and %d",
             ip_family(a1), ip_family(a2));
-       return FALSE;
+       return 0;
    }
 }
 
-bool
-network_ne(inet *a1, inet *a2)
-{
-   if (!PointerIsValid(a1) || !PointerIsValid(a2))
-       return FALSE;
-   return (!network_eq(a1, a2));
-}
-
 bool
 network_sub(inet *a1, inet *a2)
 {
@@ -293,28 +288,6 @@ network_supeq(inet *a1, inet *a2)
    }
 }
 
-/*
- * Comparison function for sorting.  Add V4/V6 testing!
- */
-
-int4
-network_cmp(inet *a1, inet *a2)
-{
-   if (ntohl(ip_v4addr(a1)) < ntohl(ip_v4addr(a2)))
-       return (-1);
-
-   if (ntohl(ip_v4addr(a1)) > ntohl(ip_v4addr(a2)))
-       return (1);
-
-   if (ip_bits(a1) < ip_bits(a2))
-       return (-1);
-
-   if (ip_bits(a1) > ip_bits(a2))
-       return (1);
-
-   return 0;
-}
-
 text *
 network_host(inet *ip)
 {
@@ -476,7 +449,7 @@ network_netmask(inet *ip)
  */
 
 static int
-v4bitncmp(unsigned int a1, unsigned int a2, int bits)
+v4bitncmp(unsigned long a1, unsigned long a2, int bits)
 {
    unsigned long mask = 0;
    int         i;
@@ -485,9 +458,11 @@ v4bitncmp(unsigned int a1, unsigned int a2, int bits)
        mask = (mask >> 1) | 0x80000000;
    a1 = ntohl(a1);
    a2 = ntohl(a2);
-   if ((a1 & mask) < (a2 & mask))
+   a1 &= mask;
+   a2 &= mask;
+   if (a1 < a2)
        return (-1);
-   else if ((a1 & mask) > (a2 & mask))
+   else if (a1 > a2)
        return (1);
    return (0);
 }
index 94aa8d58c6b91882290c15366698695447a9dc3d..9f05bc7985ffd665a66f7e09ecaf6018d7e21027 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_list.h,v 1.15 2000/02/06 03:27:35 tgl Exp $
+ * $Id: pg_list.h,v 1.16 2000/02/21 18:47:12 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 /*----------------------
  *     Value node
+ *
+ * The same Value struct is used for three node types: T_Integer,
+ * T_Float, and T_String.  Integral values are actually represented
+ * by a machine integer, but both floats and strings are represented
+ * as strings.  Using T_Float as the node type simply indicates that
+ * the contents of the string look like a valid numeric literal.
+ *
+ * (Before Postgres 7.0, we used a double to represent T_Float,
+ * but that creates loss-of-precision problems when the value is
+ * ultimately destined to be converted to NUMERIC.  Since Value nodes
+ * are only used in the parsing process, not for runtime data, it's
+ * better to use the more general representation.)
+ *
+ * Note that an integer-looking string will get lexed as T_Float if
+ * the value is too large to fit in a 'long'.
  *----------------------
  */
 typedef struct Value
@@ -30,14 +45,13 @@ typedef struct Value
    NodeTag     type;           /* tag appropriately (eg. T_String) */
    union ValUnion
    {
+       long        ival;       /* machine integer */
        char       *str;        /* string */
-       long        ival;
-       double      dval;
    }           val;
 } Value;
 
 #define intVal(v)      (((Value *)(v))->val.ival)
-#define floatVal(v)        (((Value *)(v))->val.dval)
+#define floatVal(v)        atof(((Value *)(v))->val.str)
 #define strVal(v)      (((Value *)(v))->val.str)
 
 
@@ -89,9 +103,9 @@ extern List *lconsi(int datum, List *list);
 extern bool member(void *datum, List *list);
 extern bool intMember(int datum, List *list);
 extern Value *makeInteger(long i);
-extern Value *makeFloat(double d);
+extern Value *makeFloat(char *numericStr);
 extern Value *makeString(char *str);
-extern List *makeList(void *elem,...);
+extern List *makeList(void *elem, ...);
 extern List *lappend(List *list, void *datum);
 extern List *lappendi(List *list, int datum);
 extern List *lremove(void *elem, List *list);