Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit2b7ec40

Browse files
committed
Code review for IS DISTINCT FROM patch. Fix incorrect constant-folding
logic, dissuade planner from thinking that 'x IS DISTINCT FROM 42' maybe optimized into 'x = 42' (!!), cause dependency on = operator to berecorded correctly, minor other improvements.
1 parent36c356e commit2b7ec40

File tree

7 files changed

+72
-117
lines changed

7 files changed

+72
-117
lines changed

‎src/backend/catalog/dependency.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/catalog/dependency.c,v 1.12 2002/09/22 00:37:09 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/catalog/dependency.c,v 1.13 2002/11/30 21:25:04 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -803,7 +803,8 @@ find_expr_references_walker(Node *node,
803803
{
804804
Expr*expr= (Expr*)node;
805805

806-
if (expr->opType==OP_EXPR)
806+
if (expr->opType==OP_EXPR||
807+
expr->opType==DISTINCT_EXPR)
807808
{
808809
Oper*oper= (Oper*)expr->oper;
809810

‎src/backend/executor/execQual.c

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.110 2002/11/25 21:29:35 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.111 2002/11/30 21:25:04 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -1144,7 +1144,7 @@ ExecEvalFunc(Expr *funcClause,
11441144
* they are NULL; if either is NULL then the result is already
11451145
* known. If neither is NULL, then proceed to evaluate the
11461146
* function. Note that this is *always* derived from the equals
1147-
* operator, but since we've already evaluated the arguments
1147+
* operator, but since we need special processing of the arguments
11481148
* we can not simply reuse ExecEvalOper() or ExecEvalFunc().
11491149
* ----------------------------------------------------------------
11501150
*/
@@ -1154,18 +1154,15 @@ ExecEvalDistinct(Expr *opClause,
11541154
bool*isNull,
11551155
ExprDoneCond*isDone)
11561156
{
1157-
boolresult;
1157+
Datumresult;
11581158
FunctionCachePtrfcache;
11591159
FunctionCallInfoDatafcinfo;
11601160
ExprDoneCondargDone;
11611161
Oper*op;
11621162
List*argList;
11631163

11641164
/*
1165-
* we extract the oid of the function associated with the op and then
1166-
* pass the work onto ExecMakeFunctionResult which evaluates the
1167-
* arguments and returns the result of calling the function on the
1168-
* evaluated arguments.
1165+
* extract info from opClause
11691166
*/
11701167
op= (Oper*)opClause->oper;
11711168
argList=opClause->args;
@@ -1181,34 +1178,36 @@ ExecEvalDistinct(Expr *opClause,
11811178
econtext->ecxt_per_query_memory);
11821179
op->op_fcache=fcache;
11831180
}
1184-
Assert(fcache->func.fn_retset== FALSE);
1181+
Assert(!fcache->func.fn_retset);
11851182

11861183
/* Need to prep callinfo structure */
11871184
MemSet(&fcinfo,0,sizeof(fcinfo));
11881185
fcinfo.flinfo=&(fcache->func);
11891186
argDone=ExecEvalFuncArgs(&fcinfo,argList,econtext);
1187+
if (argDone!=ExprSingleResult)
1188+
elog(ERROR,"IS DISTINCT FROM does not support set arguments");
11901189
Assert(fcinfo.nargs==2);
11911190

11921191
if (fcinfo.argnull[0]&&fcinfo.argnull[1])
11931192
{
11941193
/* Both NULL? Then is not distinct... */
1195-
result= FALSE;
1194+
result=BoolGetDatum(FALSE);
11961195
}
11971196
elseif (fcinfo.argnull[0]||fcinfo.argnull[1])
11981197
{
1199-
/*One is NULL? Then is distinct... */
1200-
result= TRUE;
1198+
/*Only one is NULL? Then is distinct... */
1199+
result=BoolGetDatum(TRUE);
12011200
}
12021201
else
12031202
{
12041203
fcinfo.isnull= false;
12051204
result=FunctionCallInvoke(&fcinfo);
12061205
*isNull=fcinfo.isnull;
1207-
1208-
result= (!DatumGetBool(result));
1206+
/* Must invert result of "=" */
1207+
result=BoolGetDatum(!DatumGetBool(result));
12091208
}
12101209

1211-
returnBoolGetDatum(result);
1210+
returnresult;
12121211
}
12131212

12141213
/* ----------------------------------------------------------------

‎src/backend/optimizer/plan/setrefs.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*
1010
*
1111
* IDENTIFICATION
12-
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.82 2002/11/19 23:21:59 tgl Exp $
12+
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.83 2002/11/3021:25:04 tgl Exp $
1313
*
1414
*-------------------------------------------------------------------------
1515
*/
@@ -575,7 +575,13 @@ fix_opids_walker(Node *node, void *context)
575575
{
576576
if (node==NULL)
577577
return false;
578-
if (is_opclause(node))
579-
replace_opid((Oper*) ((Expr*)node)->oper);
578+
if (IsA(node,Expr))
579+
{
580+
Expr*expr= (Expr*)node;
581+
582+
if (expr->opType==OP_EXPR||
583+
expr->opType==DISTINCT_EXPR)
584+
replace_opid((Oper*)expr->oper);
585+
}
580586
returnexpression_tree_walker(node,fix_opids_walker,context);
581587
}

‎src/backend/optimizer/util/clauses.c

Lines changed: 34 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.113 2002/11/26 03:01:58 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.114 2002/11/30 21:25:04 tgl Exp $
1212
*
1313
* HISTORY
1414
* AUTHORDATEMAJOR EVENT
@@ -98,25 +98,19 @@ make_clause(int type, Node *oper, List *args)
9898
*
9999
* Returns t iff the clause is an operator clause:
100100
*(op expr expr) or (op expr).
101-
*
102-
* [historical note: is_clause has the exact functionality and is used
103-
*throughout the code. They're renamed to is_opclause for clarity.
104-
*- ay 10/94.]
105101
*/
106102
bool
107103
is_opclause(Node*clause)
108104
{
109105
return (clause!=NULL&&
110106
IsA(clause,Expr)&&
111-
((((Expr*)clause)->opType==OP_EXPR)||
112-
((Expr*)clause)->opType==DISTINCT_EXPR));
107+
((Expr*)clause)->opType==OP_EXPR);
113108
}
114109

115110
/*
116111
* make_opclause
117-
* Creates a clause given its operator left operand and right
118-
* operand (if it is non-null).
119-
*
112+
* Creates a clause given its operator, left operand, and right
113+
* operand (pass NULL to create single-operand clause).
120114
*/
121115
Expr*
122116
make_opclause(Oper*op,Var*leftop,Var*rightop)
@@ -1191,10 +1185,10 @@ eval_const_expressions_mutator(Node *node, void *context)
11911185
boolhas_nonconst_input= false;
11921186

11931187
/*
1194-
* Check for constant inputs and especially
1195-
* constant-NULL inputs.
1188+
* We must do our own check for NULLs because
1189+
* DISTINCT_EXPR has different results for NULL input
1190+
* than the underlying operator does.
11961191
*/
1197-
Assert(length(args)==2);
11981192
foreach(arg,args)
11991193
{
12001194
if (IsA(lfirst(arg),Const))
@@ -1205,82 +1199,28 @@ eval_const_expressions_mutator(Node *node, void *context)
12051199
else
12061200
has_nonconst_input= true;
12071201
}
1208-
/* all nulls? then not distinct */
1209-
if (all_null_input)
1210-
returnMAKEBOOLCONST(false, false);
12111202

1212-
/* one null? then distinct */
1213-
if (has_null_input)
1214-
returnMAKEBOOLCONST(true, false);
1215-
1216-
/* all constants? then optimize this out */
1203+
/* all constants? then can optimize this out */
12171204
if (!has_nonconst_input)
12181205
{
1219-
Oidresult_typeid;
1220-
int16resultTypLen;
1221-
boolresultTypByVal;
1222-
ExprContext*econtext;
1223-
Datumconst_val;
1224-
boolconst_is_null;
1225-
1226-
Oper*oper= (Oper*)expr->oper;
1227-
1228-
replace_opid(oper);/* OK to scribble on input
1229-
* to this extent */
1230-
result_typeid=oper->opresulttype;
1231-
1232-
/*
1233-
* OK, looks like we can simplify this
1234-
* operator/function.
1235-
*
1236-
* We use the executor's routine ExecEvalExpr() to
1237-
* avoid duplication of code and ensure we get the
1238-
* same result as the executor would get.
1239-
*
1240-
* Build a new Expr node containing the
1241-
* already-simplified arguments. The only other
1242-
* setup needed here is the replace_opid() that we
1243-
* already did for the OP_EXPR case.
1244-
*/
1245-
newexpr=makeNode(Expr);
1246-
newexpr->typeOid=expr->typeOid;
1247-
newexpr->opType=expr->opType;
1248-
newexpr->oper=expr->oper;
1249-
newexpr->args=args;
1250-
1251-
/* Get info needed about result datatype */
1252-
get_typlenbyval(result_typeid,&resultTypLen,&resultTypByVal);
1253-
1254-
/*
1255-
* It is OK to pass a dummy econtext because none
1256-
* of the ExecEvalExpr() code used in this
1257-
* situation will use econtext. That might seem
1258-
* fortuitous, but it's not so unreasonable --- a
1259-
* constant expression does not depend on context,
1260-
* by definition, n'est ce pas?
1261-
*/
1262-
econtext=MakeExprContext(NULL,CurrentMemoryContext);
1263-
1264-
const_val=ExecEvalExprSwitchContext((Node*)newexpr,econtext,
1265-
&const_is_null,NULL);
1266-
1267-
/*
1268-
* Must copy result out of sub-context used by
1269-
* expression eval
1270-
*/
1271-
if (!const_is_null)
1272-
const_val=datumCopy(const_val,resultTypByVal,resultTypLen);
1273-
1274-
FreeExprContext(econtext);
1275-
pfree(newexpr);
1276-
1277-
/*
1278-
* Make the constant result node.
1279-
*/
1280-
return (Node*)makeConst(result_typeid,resultTypLen,
1281-
const_val,const_is_null,
1282-
resultTypByVal);
1206+
/* all nulls? then not distinct */
1207+
if (all_null_input)
1208+
returnMAKEBOOLCONST(false, false);
1209+
1210+
/* one null? then distinct */
1211+
if (has_null_input)
1212+
returnMAKEBOOLCONST(true, false);
1213+
1214+
/* otherwise try to evaluate the '=' operator */
1215+
newexpr=simplify_op_or_func(expr,args);
1216+
if (newexpr)/* successfully simplified it */
1217+
return (Node*)newexpr;
12831218
}
1219+
1220+
/*
1221+
* else fall out to build new Expr node with simplified
1222+
* args
1223+
*/
12841224
break;
12851225
}
12861226
caseOR_EXPR:
@@ -1624,21 +1564,21 @@ simplify_op_or_func(Expr *expr, List *args)
16241564
* Note we take the result type from the Oper or Func node, not the
16251565
* pg_proc tuple; probably necessary for binary-compatibility cases.
16261566
*/
1627-
if (expr->opType==OP_EXPR)
1567+
if (expr->opType==FUNC_EXPR)
1568+
{
1569+
Func*func= (Func*)expr->oper;
1570+
1571+
funcid=func->funcid;
1572+
result_typeid=func->funcresulttype;
1573+
}
1574+
else/* OP_EXPR or DISTINCT_EXPR */
16281575
{
16291576
Oper*oper= (Oper*)expr->oper;
16301577

16311578
replace_opid(oper);/* OK to scribble on input to this extent */
16321579
funcid=oper->opid;
16331580
result_typeid=oper->opresulttype;
16341581
}
1635-
else
1636-
{
1637-
Func*func= (Func*)expr->oper;
1638-
1639-
funcid=func->funcid;
1640-
result_typeid=func->funcresulttype;
1641-
}
16421582

16431583
/*
16441584
* we could use func_volatile() here, but we need several fields out
@@ -1693,7 +1633,7 @@ simplify_op_or_func(Expr *expr, List *args)
16931633
*
16941634
* Build a new Expr node containing the already-simplified arguments. The
16951635
* only other setup needed here is the replace_opid() that we already
1696-
* did for the OP_EXPR case.
1636+
* did for the OP_EXPR/DISTINCT_EXPR case.
16971637
*/
16981638
newexpr=makeNode(Expr);
16991639
newexpr->typeOid=expr->typeOid;

‎src/backend/parser/parse_expr.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.131 2002/11/26 03:01:58 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.132 2002/11/30 21:25:05 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -277,6 +277,8 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal)
277277
result= (Node*)make_op(a->name,
278278
lexpr,
279279
rexpr);
280+
if (((Expr*)result)->typeOid!=BOOLOID)
281+
elog(ERROR,"IS DISTINCT FROM requires = operator to yield boolean");
280282
((Expr*)result)->opType=DISTINCT_EXPR;
281283
}
282284
break;

‎src/include/nodes/primnodes.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
1111
* Portions Copyright (c) 1994, Regents of the University of California
1212
*
13-
* $Id: primnodes.h,v 1.70 2002/11/26 03:01:59 tgl Exp $
13+
* $Id: primnodes.h,v 1.71 2002/11/30 21:25:06 tgl Exp $
1414
*
1515
*-------------------------------------------------------------------------
1616
*/
@@ -165,6 +165,12 @@ typedef enum CoercionForm
165165

166166
/*
167167
* Expr
168+
*
169+
* Note: DISTINCT_EXPR implements the "x IS DISTINCT FROM y" construct.
170+
* This is similar to an OP_EXPR, except for its handling of NULL inputs.
171+
* The oper field is always an Oper node for the "=" operator for x and y.
172+
* (We use "=", not the more obvious "<>", because more datatypes have "="
173+
* than "<>". This means the executor must invert the operator result.)
168174
*/
169175
typedefenumOpType
170176
{
@@ -183,7 +189,7 @@ typedef struct Expr
183189
}Expr;
184190

185191
/*
186-
* Oper - Expr subnode for an OP_EXPR
192+
* Oper - Expr subnode for an OP_EXPR (or DISTINCT_EXPR)
187193
*
188194
* NOTE: in the good old days 'opno' used to be both (or either, or
189195
* neither) the pg_operator oid, and/or the pg_proc oid depending

‎src/pl/plpgsql/src/pl_exec.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* procedural language
44
*
55
* IDENTIFICATION
6-
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.70 2002/11/23 03:59:09 momjian Exp $
6+
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.71 2002/11/30 21:25:08 tgl Exp $
77
*
88
* This software is copyrighted by Jan Wieck - Hamburg.
99
*
@@ -3509,6 +3509,7 @@ exec_simple_check_node(Node *node)
35093509
switch (expr->opType)
35103510
{
35113511
caseOP_EXPR:
3512+
caseDISTINCT_EXPR:
35123513
caseFUNC_EXPR:
35133514
caseOR_EXPR:
35143515
caseAND_EXPR:

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp