OSDN Git Service

Change parse-time representation of float literals (which include oversize
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 21 Feb 2000 18:47:12 +0000 (18:47 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
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 fbef91b..601b503 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 b4f5fc6..6cb9ead 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 daca4a6..14a5ed1 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 723930f..a47851f 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 db785af..eb2c1a7 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 75e1057..9f68f4d 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 <ctype.h>
+#include <errno.h>
 
 #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 f43393e..b81b6d3 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 <str>   IDENT, SCONST, Op
+%token <str>   IDENT, FCONST, SCONST, Op
 %token <ival>  ICONST, PARAM
-%token <dval>  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 3fd3370..2efdd13 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 fa3408c..5b8dd16 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 d6120af..f5d6132 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 cb1b9b9..44045c1 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 <sys/types.h>
 #include <sys/socket.h>
-
 #include <errno.h>
-
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
-#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,30 +170,45 @@ 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)
 {
        if (!PointerIsValid(a1) || !PointerIsValid(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 94aa8d5..9f05bc7 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);