diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index fbef91b35d..601b503ec1 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 b4f5fc6285..6cb9eada0f 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 daca4a6d96..14a5ed12d9 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 723930f36a..a47851f242 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 db785afab9..eb2c1a7ffa 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 75e10576d5..9f68f4d0e9 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 f43393eeff..b81b6d387a 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 3fd3370672..2efdd13600 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 fa3408c1f1..5b8dd16d81 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 d6120affab..f5d6132331 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 cb1b9b90bf..44045c184b 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 94aa8d58c6..9f05bc7985 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);