Avoid useless "x = ANY(ARRAY[])" test for empty partition list.
authorTom Lane <[email protected]>
Mon, 26 Jun 2017 14:43:20 +0000 (10:43 -0400)
committerTom Lane <[email protected]>
Mon, 26 Jun 2017 14:43:20 +0000 (10:43 -0400)
This arises in practice if the partition only admits NULL values.

Jeevan Ladhe

Discussion: https://postgr.es/m/CAOgcT0OChrN--uuqH6wG6Z8+nxnCWJ+2Q-uhnK4KOANdRRxuAw@mail.gmail.com

src/backend/catalog/partition.c

index af07cd06aa8b8163aa9a0e98479c5a54c947ce39..f8c55b1fe775186a0f5d5db1b433fe8d09c1d1af 100644 (file)
@@ -1311,6 +1311,12 @@ get_qual_for_list(PartitionKey key, PartitionBoundSpec *spec)
    List       *arrelems = NIL;
    bool        list_has_null = false;
 
+   /*
+    * Only single-column list partitioning is supported, so we are worried
+    * only about the partition key with index 0.
+    */
+   Assert(key->partnatts == 1);
+
    /* Construct Var or expression representing the partition column */
    if (key->partattrs[0] != 0)
        keyCol = (Expr *) makeVar(1,
@@ -1333,20 +1339,28 @@ get_qual_for_list(PartitionKey key, PartitionBoundSpec *spec)
            arrelems = lappend(arrelems, copyObject(val));
    }
 
-   /* Construct an ArrayExpr for the non-null partition values */
-   arr = makeNode(ArrayExpr);
-   arr->array_typeid = !type_is_array(key->parttypid[0])
-       ? get_array_type(key->parttypid[0])
-       : key->parttypid[0];
-   arr->array_collid = key->parttypcoll[0];
-   arr->element_typeid = key->parttypid[0];
-   arr->elements = arrelems;
-   arr->multidims = false;
-   arr->location = -1;
-
-   /* Generate the main expression, i.e., keyCol = ANY (arr) */
-   opexpr = make_partition_op_expr(key, 0, BTEqualStrategyNumber,
-                                   keyCol, (Expr *) arr);
+   if (arrelems)
+   {
+       /* Construct an ArrayExpr for the non-null partition values */
+       arr = makeNode(ArrayExpr);
+       arr->array_typeid = !type_is_array(key->parttypid[0])
+           ? get_array_type(key->parttypid[0])
+           : key->parttypid[0];
+       arr->array_collid = key->parttypcoll[0];
+       arr->element_typeid = key->parttypid[0];
+       arr->elements = arrelems;
+       arr->multidims = false;
+       arr->location = -1;
+
+       /* Generate the main expression, i.e., keyCol = ANY (arr) */
+       opexpr = make_partition_op_expr(key, 0, BTEqualStrategyNumber,
+                                       keyCol, (Expr *) arr);
+   }
+   else
+   {
+       /* If there are no partition values, we don't need an = ANY expr */
+       opexpr = NULL;
+   }
 
    if (!list_has_null)
    {
@@ -1361,7 +1375,7 @@ get_qual_for_list(PartitionKey key, PartitionBoundSpec *spec)
        nulltest->argisrow = false;
        nulltest->location = -1;
 
-       result = list_make2(nulltest, opexpr);
+       result = opexpr ? list_make2(nulltest, opexpr) : list_make1(nulltest);
    }
    else
    {
@@ -1369,16 +1383,21 @@ get_qual_for_list(PartitionKey key, PartitionBoundSpec *spec)
         * Gin up a "col IS NULL" test that will be OR'd with the main
         * expression.
         */
-       Expr       *or;
-
        nulltest = makeNode(NullTest);
        nulltest->arg = keyCol;
        nulltest->nulltesttype = IS_NULL;
        nulltest->argisrow = false;
        nulltest->location = -1;
 
-       or = makeBoolExpr(OR_EXPR, list_make2(nulltest, opexpr), -1);
-       result = list_make1(or);
+       if (opexpr)
+       {
+           Expr       *or;
+
+           or = makeBoolExpr(OR_EXPR, list_make2(nulltest, opexpr), -1);
+           result = list_make1(or);
+       }
+       else
+           result = list_make1(nulltest);
    }
 
    return result;