From 393f313227fba2b7905cfbd69b3e4c18d762bf4f Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Mon, 21 Feb 2000 18:47:12 +0000 Subject: [PATCH] Change parse-time representation of float literals (which include oversize 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. --- src/backend/nodes/copyfuncs.c | 10 +-- src/backend/nodes/equalfuncs.c | 9 +-- src/backend/nodes/freefuncs.c | 7 +- src/backend/nodes/list.c | 10 ++- src/backend/nodes/outfuncs.c | 17 ++-- src/backend/nodes/read.c | 61 ++++++++------ src/backend/parser/gram.y | 45 +++++++---- src/backend/parser/parse_expr.c | 12 +-- src/backend/parser/scan.l | 39 ++------- src/backend/storage/buffer/bufmgr.c | 17 +++- src/backend/utils/adt/network.c | 119 +++++++++++----------------- src/include/nodes/pg_list.h | 26 ++++-- 12 files changed, 186 insertions(+), 186 deletions(-) diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index fbef91b35d8..601b503ec11 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -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: diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index b4f5fc6285c..6cb9eada0f8 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -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: diff --git a/src/backend/nodes/freefuncs.c b/src/backend/nodes/freefuncs.c index daca4a6d96a..14a5ed12d9e 100644 --- a/src/backend/nodes/freefuncs.c +++ b/src/backend/nodes/freefuncs.c @@ -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: diff --git a/src/backend/nodes/list.c b/src/backend/nodes/list.c index 723930f36a8..a47851f2420 100644 --- a/src/backend/nodes/list.c +++ b/src/backend/nodes/list.c @@ -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) diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index db785afab9f..eb2c1a7ffa8 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -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 ", diff --git a/src/backend/nodes/read.c b/src/backend/nodes/read.c index 75e10576d5b..9f68f4d0e90 100644 --- a/src/backend/nodes/read.c +++ b/src/backend/nodes/read.c @@ -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)); + case T_Integer: + /* 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_Integer: - /* we know that the token terminates on a char atoi will stop at */ - this_value = (Node *) makeInteger(atoi(token)); - make_dotted_pair_cell = true; + 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; diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index f43393eeff8..b81b6d387ab 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -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; + } +} diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c index 3fd3370672f..2efdd136005 100644 --- a/src/backend/parser/parse_expr.c +++ b/src/backend/parser/parse_expr.c @@ -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); } diff --git a/src/backend/parser/scan.l b/src/backend/parser/scan.l index fa3408c1f1d..5b8dd16d81f 100644 --- a/src/backend/parser/scan.l +++ b/src/backend/parser/scan.l @@ -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; } diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c index d6120affabe..f5d61323310 100644 --- a/src/backend/storage/buffer/bufmgr.c +++ b/src/backend/storage/buffer/bufmgr.c @@ -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; diff --git a/src/backend/utils/adt/network.c b/src/backend/utils/adt/network.c index cb1b9b90bfe..44045c184b5 100644 --- a/src/backend/utils/adt/network.c +++ b/src/backend/utils/adt/network.c @@ -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,19 +170,7 @@ network_gt(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 @@ -210,7 +178,34 @@ network_ne(inet *a1, inet *a2) { if (!PointerIsValid(a1) || !PointerIsValid(a2)) return FALSE; - return (!network_eq(a1, a2)); + 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(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 0; + } } bool @@ -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); } diff --git a/src/include/nodes/pg_list.h b/src/include/nodes/pg_list.h index 94aa8d58c6b..9f05bc7985f 100644 --- a/src/include/nodes/pg_list.h +++ b/src/include/nodes/pg_list.h @@ -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 $ * *------------------------------------------------------------------------- */ @@ -23,6 +23,21 @@ /*---------------------- * 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);