8
8
*
9
9
*
10
10
* IDENTIFICATION
11
- * $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.66 2000/04/16 01:55:45 tgl Exp $
11
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.67 2000/05/28 20:33:28 tgl Exp $
12
12
*
13
13
* HISTORY
14
14
* AUTHORDATEMAJOR EVENT
@@ -1307,7 +1307,7 @@ eval_const_expressions_mutator(Node *node, void *context)
1307
1307
* the expression here. This would avoid much runtime overhead, and perhaps
1308
1308
* expose opportunities for constant-folding within the expression even if
1309
1309
* not all the func's input args are constants. It'd be appropriate to do
1310
- * here, and not in the parser, since we wouldn't want it to happen until
1310
+ *that here, not in the parser, since we wouldn't want it to happen until
1311
1311
* after rule substitution/rewriting.
1312
1312
*/
1313
1313
static Expr *
@@ -1321,26 +1321,38 @@ simplify_op_or_func(Expr *expr, List *args)
1321
1321
Type resultType ;
1322
1322
Expr * newexpr ;
1323
1323
Datum const_val ;
1324
+ bool has_nonconst_input = false;
1325
+ bool has_null_input = false;
1324
1326
bool const_is_null ;
1325
1327
bool isDone ;
1326
1328
1327
1329
/*
1328
- * For an operator or function, we cannot simplify unless all the
1329
- * inputs are constants. (XXX possible future improvement: if the
1330
- * op/func is strict and at least one input is NULL, we could simplify
1331
- * to NULL. But we do not currently have any way to know if the
1332
- * op/func is strict or not. For now, a NULL input is treated the
1333
- * same as any other constant node.)
1330
+ * Check for constant inputs and especially constant-NULL inputs.
1334
1331
*/
1335
1332
foreach (arg ,args )
1336
1333
{
1337
- if (!IsA (lfirst (arg ),Const ))
1338
- return NULL ;
1334
+ if (IsA (lfirst (arg ),Const ))
1335
+ has_null_input |= ((Const * )lfirst (arg ))-> constisnull ;
1336
+ else
1337
+ has_nonconst_input = true;
1339
1338
}
1340
1339
1340
+ /*
1341
+ * If the function is strict and has a constant-NULL input, it will
1342
+ * never be called at all, so we can replace the call by a NULL
1343
+ * constant even if there are other inputs that aren't constant.
1344
+ * Otherwise, we can only simplify if all inputs are constants.
1345
+ * We can skip the function lookup if neither case applies.
1346
+ */
1347
+ if (has_nonconst_input && !has_null_input )
1348
+ return NULL ;
1349
+
1341
1350
/*
1342
1351
* Get the function procedure's OID and look to see whether it is
1343
1352
* marked proiscachable.
1353
+ *
1354
+ * XXX would it be better to take the result type from the pg_proc tuple,
1355
+ * rather than the Oper or Func node?
1344
1356
*/
1345
1357
if (expr -> opType == OP_EXPR )
1346
1358
{
@@ -1373,6 +1385,31 @@ simplify_op_or_func(Expr *expr, List *args)
1373
1385
if (funcform -> proretset )
1374
1386
return NULL ;
1375
1387
1388
+ /*
1389
+ * Now that we know if the function is strict, we can finish the
1390
+ * checks for simplifiable inputs that we started above.
1391
+ */
1392
+ if (funcform -> proisstrict && has_null_input )
1393
+ {
1394
+ /*
1395
+ * It's strict and has NULL input, so must produce NULL output.
1396
+ * Return a NULL constant of the right type.
1397
+ */
1398
+ resultType = typeidType (result_typeid );
1399
+ return (Expr * )makeConst (result_typeid ,typeLen (resultType ),
1400
+ (Datum )0 , true,
1401
+ typeByVal (resultType ),
1402
+ false, false);
1403
+ }
1404
+
1405
+ /*
1406
+ * Otherwise, can simplify only if all inputs are constants.
1407
+ * (For a non-strict function, constant NULL inputs are treated
1408
+ * the same as constant non-NULL inputs.)
1409
+ */
1410
+ if (has_nonconst_input )
1411
+ return NULL ;
1412
+
1376
1413
/*
1377
1414
* OK, looks like we can simplify this operator/function.
1378
1415
*
@@ -1402,9 +1439,6 @@ simplify_op_or_func(Expr *expr, List *args)
1402
1439
1403
1440
/*
1404
1441
* Make the constant result node.
1405
- *
1406
- * XXX would it be better to take the result type from the pg_proc tuple,
1407
- * rather than the Oper or Func node?
1408
1442
*/
1409
1443
resultType = typeidType (result_typeid );
1410
1444
return (Expr * )makeConst (result_typeid ,typeLen (resultType ),