From 7839d35991f1c79a291e67635d5f4c5750c16e9b Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Fri, 1 Jan 2010 23:03:10 +0000 Subject: [PATCH] Add an "argisrow" field to NullTest nodes, following a plan made way back in 8.2beta but never carried out. This avoids repetitive tests of whether the argument is of scalar or composite type. Also, be a bit more paranoid about composite arguments in some places where we previously weren't checking. --- src/backend/executor/execQual.c | 5 ++--- src/backend/nodes/copyfuncs.c | 3 ++- src/backend/nodes/equalfuncs.c | 3 ++- src/backend/nodes/outfuncs.c | 3 ++- src/backend/nodes/readfuncs.c | 3 ++- src/backend/optimizer/path/indxpath.c | 5 +++-- src/backend/optimizer/plan/planagg.c | 5 ++++- src/backend/optimizer/util/clauses.c | 12 +++++++----- src/backend/optimizer/util/plancat.c | 3 ++- src/backend/optimizer/util/predtest.c | 10 ++++++---- src/backend/parser/parse_expr.c | 3 ++- src/include/catalog/catversion.h | 4 ++-- src/include/nodes/execnodes.h | 5 ++--- src/include/nodes/primnodes.h | 7 +++---- 14 files changed, 41 insertions(+), 30 deletions(-) diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c index a5604537515..8f025cfba5e 100644 --- a/src/backend/executor/execQual.c +++ b/src/backend/executor/execQual.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.257 2009/12/29 17:40:59 heikki Exp $ + * $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.258 2010/01/01 23:03:09 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -3475,7 +3475,7 @@ ExecEvalNullTest(NullTestState *nstate, if (isDone && *isDone == ExprEndResult) return result; /* nothing to check */ - if (nstate->argisrow && !(*isNull)) + if (ntest->argisrow && !(*isNull)) { HeapTupleHeader tuple; Oid tupType; @@ -4704,7 +4704,6 @@ ExecInitExpr(Expr *node, PlanState *parent) nstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalNullTest; nstate->arg = ExecInitExpr(ntest->arg, parent); - nstate->argisrow = type_is_rowtype(exprType((Node *) ntest->arg)); nstate->argdesc = NULL; state = (ExprState *) nstate; } diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index afbc3edaf62..88c1318a807 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -15,7 +15,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.456 2009/12/29 20:11:45 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.457 2010/01/01 23:03:09 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1506,6 +1506,7 @@ _copyNullTest(NullTest *from) COPY_NODE_FIELD(arg); COPY_SCALAR_FIELD(nulltesttype); + COPY_SCALAR_FIELD(argisrow); return newnode; } diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index e53b4a89e6e..8764ea99601 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -22,7 +22,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.377 2009/12/23 02:35:21 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.378 2010/01/01 23:03:10 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -623,6 +623,7 @@ _equalNullTest(NullTest *a, NullTest *b) { COMPARE_NODE_FIELD(arg); COMPARE_SCALAR_FIELD(nulltesttype); + COMPARE_SCALAR_FIELD(argisrow); return true; } diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index b35b0beaf19..b48ffe778a5 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.377 2009/12/29 20:11:45 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.378 2010/01/01 23:03:10 tgl Exp $ * * NOTES * Every node type that can appear in stored rules' parsetrees *must* @@ -1229,6 +1229,7 @@ _outNullTest(StringInfo str, NullTest *node) WRITE_NODE_FIELD(arg); WRITE_ENUM_FIELD(nulltesttype, NullTestType); + WRITE_BOOL_FIELD(argisrow); } static void diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c index 3e4a595e827..043f436d55a 100644 --- a/src/backend/nodes/readfuncs.c +++ b/src/backend/nodes/readfuncs.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.228 2009/12/15 17:57:46 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.229 2010/01/01 23:03:10 tgl Exp $ * * NOTES * Path and Plan nodes do not have any readfuncs support, because we @@ -963,6 +963,7 @@ _readNullTest(void) READ_NODE_FIELD(arg); READ_ENUM_FIELD(nulltesttype, NullTestType); + READ_BOOL_FIELD(argisrow); READ_DONE(); } diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c index 456a5b9be48..c69dd8686dd 100644 --- a/src/backend/optimizer/path/indxpath.c +++ b/src/backend/optimizer/path/indxpath.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.243 2010/01/01 21:53:49 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.244 2010/01/01 23:03:10 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1256,7 +1256,8 @@ match_clause_to_indexcol(IndexOptInfo *index, { NullTest *nt = (NullTest *) clause; - if (match_index_to_operand((Node *) nt->arg, indexcol, index)) + if (!nt->argisrow && + match_index_to_operand((Node *) nt->arg, indexcol, index)) return true; return false; } diff --git a/src/backend/optimizer/plan/planagg.c b/src/backend/optimizer/plan/planagg.c index a32a06fc28d..aa841ccff56 100644 --- a/src/backend/optimizer/plan/planagg.c +++ b/src/backend/optimizer/plan/planagg.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/plan/planagg.c,v 1.48 2010/01/01 21:53:49 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/plan/planagg.c,v 1.49 2010/01/01 23:03:10 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -308,6 +308,9 @@ build_minmax_path(PlannerInfo *root, RelOptInfo *rel, MinMaxAggInfo *info) ntest = makeNode(NullTest); ntest->nulltesttype = IS_NOT_NULL; ntest->arg = copyObject(info->target); + ntest->argisrow = type_is_rowtype(exprType((Node *) ntest->arg)); + if (ntest->argisrow) + return false; /* punt on composites */ info->notnulltest = ntest; /* diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c index 56b432c9bb2..b7db0e9d164 100644 --- a/src/backend/optimizer/util/clauses.c +++ b/src/backend/optimizer/util/clauses.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.281 2009/12/15 17:57:47 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.282 2010/01/01 23:03:10 tgl Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -1295,7 +1295,7 @@ find_nonnullable_rels_walker(Node *node, bool top_level) /* IS NOT NULL can be considered strict, but only at top level */ NullTest *expr = (NullTest *) node; - if (top_level && expr->nulltesttype == IS_NOT_NULL) + if (top_level && expr->nulltesttype == IS_NOT_NULL && !expr->argisrow) result = find_nonnullable_rels_walker((Node *) expr->arg, false); } else if (IsA(node, BooleanTest)) @@ -1497,7 +1497,7 @@ find_nonnullable_vars_walker(Node *node, bool top_level) /* IS NOT NULL can be considered strict, but only at top level */ NullTest *expr = (NullTest *) node; - if (top_level && expr->nulltesttype == IS_NOT_NULL) + if (top_level && expr->nulltesttype == IS_NOT_NULL && !expr->argisrow) result = find_nonnullable_vars_walker((Node *) expr->arg, false); } else if (IsA(node, BooleanTest)) @@ -1601,7 +1601,7 @@ find_forced_null_var(Node *node) /* check for var IS NULL */ NullTest *expr = (NullTest *) node; - if (expr->nulltesttype == IS_NULL) + if (expr->nulltesttype == IS_NULL && !expr->argisrow) { Var *var = (Var *) expr->arg; @@ -2856,6 +2856,7 @@ eval_const_expressions_mutator(Node *node, newntest = makeNode(NullTest); newntest->arg = (Expr *) relem; newntest->nulltesttype = ntest->nulltesttype; + newntest->argisrow = ntest->argisrow; newargs = lappend(newargs, newntest); } /* If all the inputs were constants, result is TRUE */ @@ -2867,7 +2868,7 @@ eval_const_expressions_mutator(Node *node, /* Else we need an AND node */ return (Node *) make_andclause(newargs); } - if (arg && IsA(arg, Const)) + if (!ntest->argisrow && arg && IsA(arg, Const)) { Const *carg = (Const *) arg; bool result; @@ -2893,6 +2894,7 @@ eval_const_expressions_mutator(Node *node, newntest = makeNode(NullTest); newntest->arg = (Expr *) arg; newntest->nulltesttype = ntest->nulltesttype; + newntest->argisrow = ntest->argisrow; return (Node *) newntest; } if (IsA(node, BooleanTest)) diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index 4640bbd205d..f18b66ca146 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.159 2009/07/16 06:33:43 petere Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.160 2010/01/01 23:03:10 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -541,6 +541,7 @@ get_relation_constraints(PlannerInfo *root, att->atttypmod, 0); ntest->nulltesttype = IS_NOT_NULL; + ntest->argisrow = type_is_rowtype(att->atttypid); result = lappend(result, ntest); } } diff --git a/src/backend/optimizer/util/predtest.c b/src/backend/optimizer/util/predtest.c index 87a822dce07..7c30c62a2a2 100644 --- a/src/backend/optimizer/util/predtest.c +++ b/src/backend/optimizer/util/predtest.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/util/predtest.c,v 1.28 2009/12/27 18:55:52 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/util/predtest.c,v 1.29 2010/01/01 23:03:10 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1043,7 +1043,7 @@ predicate_implied_by_simple_clause(Expr *predicate, Node *clause) Expr *nonnullarg = ((NullTest *) predicate)->arg; /* row IS NOT NULL does not act in the simple way we have in mind */ - if (!type_is_rowtype(exprType((Node *) nonnullarg))) + if (!((NullTest *) predicate)->argisrow) { if (is_opclause(clause) && list_member_strip(((OpExpr *) clause)->args, nonnullarg) && @@ -1102,7 +1102,7 @@ predicate_refuted_by_simple_clause(Expr *predicate, Node *clause) Expr *isnullarg = ((NullTest *) predicate)->arg; /* row IS NULL does not act in the simple way we have in mind */ - if (type_is_rowtype(exprType((Node *) isnullarg))) + if (((NullTest *) predicate)->argisrow) return false; /* Any strict op/func on foo refutes foo IS NULL */ @@ -1118,6 +1118,7 @@ predicate_refuted_by_simple_clause(Expr *predicate, Node *clause) /* foo IS NOT NULL refutes foo IS NULL */ if (clause && IsA(clause, NullTest) && ((NullTest *) clause)->nulltesttype == IS_NOT_NULL && + !((NullTest *) clause)->argisrow && equal(((NullTest *) clause)->arg, isnullarg)) return true; @@ -1131,12 +1132,13 @@ predicate_refuted_by_simple_clause(Expr *predicate, Node *clause) Expr *isnullarg = ((NullTest *) clause)->arg; /* row IS NULL does not act in the simple way we have in mind */ - if (type_is_rowtype(exprType((Node *) isnullarg))) + if (((NullTest *) clause)->argisrow) return false; /* foo IS NULL refutes foo IS NOT NULL */ if (predicate && IsA(predicate, NullTest) && ((NullTest *) predicate)->nulltesttype == IS_NOT_NULL && + !((NullTest *) predicate)->argisrow && equal(((NullTest *) predicate)->arg, isnullarg)) return true; diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c index 7dc20b4d6a7..c5c7e7e873d 100644 --- a/src/backend/parser/parse_expr.c +++ b/src/backend/parser/parse_expr.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.251 2009/12/15 17:57:47 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.252 2010/01/01 23:03:10 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -276,6 +276,7 @@ transformExpr(ParseState *pstate, Node *expr) n->arg = (Expr *) transformExpr(pstate, (Node *) n->arg); /* the argument can be any type, so don't coerce it */ + n->argisrow = type_is_rowtype(exprType((Node *) n->arg)); result = expr; break; } diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index 05ee9590260..50b6f33a1e2 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -37,7 +37,7 @@ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.563 2009/12/29 22:00:14 tgl Exp $ + * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.564 2010/01/01 23:03:10 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 200912291 +#define CATALOG_VERSION_NO 201001011 #endif diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h index ac11b496fcf..12cfcc4fdfa 100644 --- a/src/include/nodes/execnodes.h +++ b/src/include/nodes/execnodes.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.214 2009/12/15 04:57:48 rhaas Exp $ + * $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.215 2010/01/01 23:03:10 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -886,8 +886,7 @@ typedef struct NullTestState { ExprState xprstate; ExprState *arg; /* input expression */ - bool argisrow; /* T if input is of a composite type */ - /* used only if argisrow: */ + /* used only if input is of composite type: */ TupleDesc argdesc; /* tupdesc for most recent input */ } NullTestState; diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h index 58d286ab9c8..601f9c6470c 100644 --- a/src/include/nodes/primnodes.h +++ b/src/include/nodes/primnodes.h @@ -10,7 +10,7 @@ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.152 2009/12/15 17:57:47 tgl Exp $ + * $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.153 2010/01/01 23:03:10 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -936,9 +936,7 @@ typedef OpExpr NullIfExpr; * The appropriate test is performed and returned as a boolean Datum. * * NOTE: the semantics of this for rowtype inputs are noticeably different - * from the scalar case. It would probably be a good idea to include an - * "argisrow" flag in the struct to reflect that, but for the moment, - * we do not do so to avoid forcing an initdb during 8.2beta. + * from the scalar case. We provide an "argisrow" flag to reflect that. * ---------------- */ @@ -952,6 +950,7 @@ typedef struct NullTest Expr xpr; Expr *arg; /* input expression */ NullTestType nulltesttype; /* IS NULL, IS NOT NULL */ + bool argisrow; /* T if input is of a composite type */ } NullTest; /* -- 2.30.2