mirror of
https://github.com/postgres/postgres.git
synced 2025-08-24 09:27:52 +03:00
Add IS UNKNOWN, IS NOT UNKNOWN boolean tests, fix the existing boolean
tests to return the correct results per SQL9x when given NULL inputs. Reimplement these tests as well as IS [NOT] NULL to have their own expression node types, instead of depending on special functions. From Joe Conway, with a little help from Tom Lane.
This commit is contained in:
@@ -15,7 +15,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.144 2001/06/09 23:21:54 petere Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.145 2001/06/19 22:39:11 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -1017,6 +1017,42 @@ _copyCaseWhen(CaseWhen *from)
|
||||
return newnode;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* _copyNullTest
|
||||
* ----------------
|
||||
*/
|
||||
static NullTest *
|
||||
_copyNullTest(NullTest *from)
|
||||
{
|
||||
NullTest *newnode = makeNode(NullTest);
|
||||
|
||||
/*
|
||||
* copy remainder of node
|
||||
*/
|
||||
Node_Copy(from, newnode, arg);
|
||||
newnode->nulltesttype = from->nulltesttype;
|
||||
|
||||
return newnode;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* _copyBooleanTest
|
||||
* ----------------
|
||||
*/
|
||||
static BooleanTest *
|
||||
_copyBooleanTest(BooleanTest *from)
|
||||
{
|
||||
BooleanTest *newnode = makeNode(BooleanTest);
|
||||
|
||||
/*
|
||||
* copy remainder of node
|
||||
*/
|
||||
Node_Copy(from, newnode, arg);
|
||||
newnode->booltesttype = from->booltesttype;
|
||||
|
||||
return newnode;
|
||||
}
|
||||
|
||||
static ArrayRef *
|
||||
_copyArrayRef(ArrayRef *from)
|
||||
{
|
||||
@@ -2954,6 +2990,12 @@ copyObject(void *from)
|
||||
case T_CaseWhen:
|
||||
retval = _copyCaseWhen(from);
|
||||
break;
|
||||
case T_NullTest:
|
||||
retval = _copyNullTest(from);
|
||||
break;
|
||||
case T_BooleanTest:
|
||||
retval = _copyBooleanTest(from);
|
||||
break;
|
||||
case T_FkConstraint:
|
||||
retval = _copyFkConstraint(from);
|
||||
break;
|
||||
|
@@ -20,7 +20,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.92 2001/06/09 23:21:54 petere Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.93 2001/06/19 22:39:11 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -1712,6 +1712,26 @@ _equalCaseWhen(CaseWhen *a, CaseWhen *b)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalNullTest(NullTest *a, NullTest *b)
|
||||
{
|
||||
if (!equal(a->arg, b->arg))
|
||||
return false;
|
||||
if (a->nulltesttype != b->nulltesttype)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalBooleanTest(BooleanTest *a, BooleanTest *b)
|
||||
{
|
||||
if (!equal(a->arg, b->arg))
|
||||
return false;
|
||||
if (a->booltesttype != b->booltesttype)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Stuff from pg_list.h
|
||||
*/
|
||||
@@ -2120,6 +2140,12 @@ equal(void *a, void *b)
|
||||
case T_CaseWhen:
|
||||
retval = _equalCaseWhen(a, b);
|
||||
break;
|
||||
case T_NullTest:
|
||||
retval = _equalNullTest(a, b);
|
||||
break;
|
||||
case T_BooleanTest:
|
||||
retval = _equalBooleanTest(a, b);
|
||||
break;
|
||||
case T_FkConstraint:
|
||||
retval = _equalFkConstraint(a, b);
|
||||
break;
|
||||
|
@@ -5,7 +5,7 @@
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.141 2001/05/20 20:28:18 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.142 2001/06/19 22:39:11 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* Every (plan) node in POSTGRES has an associated "out" routine which
|
||||
@@ -1259,12 +1259,6 @@ _outAExpr(StringInfo str, A_Expr *node)
|
||||
case NOT:
|
||||
appendStringInfo(str, "NOT ");
|
||||
break;
|
||||
case ISNULL:
|
||||
appendStringInfo(str, "ISNULL ");
|
||||
break;
|
||||
case NOTNULL:
|
||||
appendStringInfo(str, "NOTNULL ");
|
||||
break;
|
||||
case OP:
|
||||
_outToken(str, node->opname);
|
||||
appendStringInfo(str, " ");
|
||||
@@ -1402,6 +1396,32 @@ _outCaseWhen(StringInfo str, CaseWhen *node)
|
||||
_outNode(str, node->result);
|
||||
}
|
||||
|
||||
/*
|
||||
* NullTest
|
||||
*/
|
||||
static void
|
||||
_outNullTest(StringInfo str, NullTest *node)
|
||||
{
|
||||
appendStringInfo(str, " NULLTEST :arg ");
|
||||
_outNode(str, node->arg);
|
||||
|
||||
appendStringInfo(str, " :nulltesttype %d ",
|
||||
(int) node->nulltesttype);
|
||||
}
|
||||
|
||||
/*
|
||||
* BooleanTest
|
||||
*/
|
||||
static void
|
||||
_outBooleanTest(StringInfo str, BooleanTest *node)
|
||||
{
|
||||
appendStringInfo(str, " BOOLEANTEST :arg ");
|
||||
_outNode(str, node->arg);
|
||||
|
||||
appendStringInfo(str, " :booltesttype %d ",
|
||||
(int) node->booltesttype);
|
||||
}
|
||||
|
||||
/*
|
||||
* _outNode -
|
||||
* converts a Node into ascii string and append it to 'str'
|
||||
@@ -1639,7 +1659,12 @@ _outNode(StringInfo str, void *obj)
|
||||
case T_CaseWhen:
|
||||
_outCaseWhen(str, obj);
|
||||
break;
|
||||
|
||||
case T_NullTest:
|
||||
_outNullTest(str, obj);
|
||||
break;
|
||||
case T_BooleanTest:
|
||||
_outBooleanTest(str, obj);
|
||||
break;
|
||||
case T_VariableSetStmt:
|
||||
break;
|
||||
case T_SelectStmt:
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.110 2001/06/05 05:26:04 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.111 2001/06/19 22:39:11 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* Most of the read functions for plan nodes are tested. (In fact, they
|
||||
@@ -859,6 +859,56 @@ _readCaseWhen(void)
|
||||
return local_node;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* _readNullTest
|
||||
*
|
||||
* NullTest is a subclass of Node
|
||||
* ----------------
|
||||
*/
|
||||
static NullTest *
|
||||
_readNullTest(void)
|
||||
{
|
||||
NullTest *local_node;
|
||||
char *token;
|
||||
int length;
|
||||
|
||||
local_node = makeNode(NullTest);
|
||||
|
||||
token = pg_strtok(&length); /* eat :arg */
|
||||
local_node->arg = nodeRead(true); /* now read it */
|
||||
|
||||
token = pg_strtok(&length); /* eat :nulltesttype */
|
||||
token = pg_strtok(&length); /* get nulltesttype */
|
||||
local_node->nulltesttype = (NullTestType) atoi(token);
|
||||
|
||||
return local_node;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* _readBooleanTest
|
||||
*
|
||||
* BooleanTest is a subclass of Node
|
||||
* ----------------
|
||||
*/
|
||||
static BooleanTest *
|
||||
_readBooleanTest(void)
|
||||
{
|
||||
BooleanTest *local_node;
|
||||
char *token;
|
||||
int length;
|
||||
|
||||
local_node = makeNode(BooleanTest);
|
||||
|
||||
token = pg_strtok(&length); /* eat :arg */
|
||||
local_node->arg = nodeRead(true); /* now read it */
|
||||
|
||||
token = pg_strtok(&length); /* eat :booltesttype */
|
||||
token = pg_strtok(&length); /* get booltesttype */
|
||||
local_node->booltesttype = (BoolTestType) atoi(token);
|
||||
|
||||
return local_node;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* _readVar
|
||||
*
|
||||
@@ -1966,6 +2016,10 @@ parsePlanString(void)
|
||||
return_value = _readCaseExpr();
|
||||
else if (length == 4 && strncmp(token, "WHEN", length) == 0)
|
||||
return_value = _readCaseWhen();
|
||||
else if (length == 8 && strncmp(token, "NULLTEST", length) == 0)
|
||||
return_value = _readNullTest();
|
||||
else if (length == 11 && strncmp(token, "BOOLEANTEST", length) == 0)
|
||||
return_value = _readBooleanTest();
|
||||
else
|
||||
elog(ERROR, "badly formatted planstring \"%.10s\"...", token);
|
||||
|
||||
|
Reference in New Issue
Block a user