]> granicus.if.org Git - postgresql/commitdiff
Refactor ON CONFLICT index inference parse tree representation.
authorAndres Freund <andres@anarazel.de>
Tue, 19 May 2015 19:17:52 +0000 (21:17 +0200)
committerAndres Freund <andres@anarazel.de>
Tue, 19 May 2015 19:21:27 +0000 (21:21 +0200)
Defer lookup of opfamily and input type of a of a user specified opclass
until the optimizer selects among available unique indexes; and store
the opclass in the parse analyzed tree instead.  The primary reason for
doing this is that for rule deparsing it's easier to use the opclass
than the previous representation.

While at it also rename a variable in the inference code to better fit
it's purpose.

This is separate from the actual fixes for deparsing to make review
easier.

contrib/pg_stat_statements/pg_stat_statements.c
src/backend/nodes/copyfuncs.c
src/backend/nodes/equalfuncs.c
src/backend/nodes/outfuncs.c
src/backend/nodes/readfuncs.c
src/backend/optimizer/util/plancat.c
src/backend/parser/parse_clause.c
src/include/nodes/primnodes.h

index c4d3ee50148efd0455bbf1e9edc1f340264645da..3cc687bdb70eb3607793569274745183057ce0a4 100644 (file)
@@ -2645,8 +2645,7 @@ JumbleExpr(pgssJumbleState *jstate, Node *node)
                                InferenceElem *ie = (InferenceElem *) node;
 
                                APP_JUMB(ie->infercollid);
-                               APP_JUMB(ie->inferopfamily);
-                               APP_JUMB(ie->inferopcinputtype);
+                               APP_JUMB(ie->inferopclass);
                                JumbleExpr(jstate, ie->expr);
                        }
                        break;
index d36be3c80685ab698be8ffe724eecd64611ee6af..2d9bf419bdb57844e25d07b900f4eee5573f94c2 100644 (file)
@@ -1839,8 +1839,7 @@ _copyInferenceElem(const InferenceElem *from)
 
        COPY_NODE_FIELD(expr);
        COPY_SCALAR_FIELD(infercollid);
-       COPY_SCALAR_FIELD(inferopfamily);
-       COPY_SCALAR_FIELD(inferopcinputtype);
+       COPY_SCALAR_FIELD(inferopclass);
 
        return newnode;
 }
index d7928a99176609ae83c5da20f695492576721055..f19251e7c415fb3a92b83a2f1e086fb1ea29a8f7 100644 (file)
@@ -702,8 +702,7 @@ _equalInferenceElem(const InferenceElem *a, const InferenceElem *b)
 {
        COMPARE_NODE_FIELD(expr);
        COMPARE_SCALAR_FIELD(infercollid);
-       COMPARE_SCALAR_FIELD(inferopfamily);
-       COMPARE_SCALAR_FIELD(inferopcinputtype);
+       COMPARE_SCALAR_FIELD(inferopclass);
 
        return true;
 }
index fdd6032b4cb227b39d6fbb04e170671352962d48..54464f8c656096175f1c3e89f9dd0535d6d5c9b5 100644 (file)
@@ -1474,8 +1474,7 @@ _outInferenceElem(StringInfo str, const InferenceElem *node)
 
        WRITE_NODE_FIELD(expr);
        WRITE_OID_FIELD(infercollid);
-       WRITE_OID_FIELD(inferopfamily);
-       WRITE_OID_FIELD(inferopcinputtype);
+       WRITE_OID_FIELD(inferopclass);
 }
 
 static void
index 6fd9d46ee7963f72d9b49b3f9a857aa013e7a8db..f5a40fbfb44b8d648a9aa32c1089055c4d3c70a6 100644 (file)
@@ -1214,8 +1214,7 @@ _readInferenceElem(void)
 
        READ_NODE_FIELD(expr);
        READ_OID_FIELD(infercollid);
-       READ_OID_FIELD(inferopfamily);
-       READ_OID_FIELD(inferopcinputtype);
+       READ_OID_FIELD(inferopclass);
 
        READ_DONE();
 }
index b425680f47647f19eaa89da02cfac8d3c8d9f765..a857ba3526484f675ed9b165b5d53ff2ee9a9e81 100644 (file)
@@ -438,8 +438,8 @@ infer_arbiter_indexes(PlannerInfo *root)
        Bitmapset  *inferAttrs = NULL;
        List       *inferElems = NIL;
 
-       /* Result */
-       List       *candidates = NIL;
+       /* Results */
+       List       *results = NIL;
 
        /*
         * Quickly return NIL for ON CONFLICT DO NOTHING without an inference
@@ -565,11 +565,11 @@ infer_arbiter_indexes(PlannerInfo *root)
                                                (errcode(ERRCODE_WRONG_OBJECT_TYPE),
                                                 errmsg("ON CONFLICT DO UPDATE not supported with exclusion constraints")));
 
-                       candidates = lappend_oid(candidates, idxForm->indexrelid);
+                       results = lappend_oid(results, idxForm->indexrelid);
                        list_free(indexList);
                        index_close(idxRel, NoLock);
                        heap_close(relation, NoLock);
-                       return candidates;
+                       return results;
                }
                else if (indexOidFromConstraint != InvalidOid)
                {
@@ -633,7 +633,7 @@ infer_arbiter_indexes(PlannerInfo *root)
                         * index definition.
                         */
                        if (elem->infercollid != InvalidOid ||
-                               elem->inferopfamily != InvalidOid ||
+                               elem->inferopclass != InvalidOid ||
                                list_member(idxExprs, elem->expr))
                                continue;
 
@@ -660,7 +660,7 @@ infer_arbiter_indexes(PlannerInfo *root)
                if (!predicate_implied_by(predExprs, whereExplicit))
                        goto next;
 
-               candidates = lappend_oid(candidates, idxForm->indexrelid);
+               results = lappend_oid(results, idxForm->indexrelid);
 next:
                index_close(idxRel, NoLock);
        }
@@ -668,12 +668,12 @@ next:
        list_free(indexList);
        heap_close(relation, NoLock);
 
-       if (candidates == NIL)
+       if (results == NIL)
                ereport(ERROR,
                                (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
                                 errmsg("there is no unique or exclusion constraint matching the ON CONFLICT specification")));
 
-       return candidates;
+       return results;
 }
 
 /*
@@ -709,23 +709,33 @@ infer_collation_opclass_match(InferenceElem *elem, Relation idxRel,
                                                          Bitmapset *inferAttrs, List *idxExprs)
 {
        AttrNumber      natt;
+       Oid                     inferopfamily = InvalidOid;             /* OID of att opfamily */
+       Oid                     inferopcinputtype = InvalidOid;         /* OID of att opfamily */
 
        /*
         * If inference specification element lacks collation/opclass, then no
         * need to check for exact match.
         */
-       if (elem->infercollid == InvalidOid && elem->inferopfamily == InvalidOid)
+       if (elem->infercollid == InvalidOid && elem->inferopclass == InvalidOid)
                return true;
 
+       /*
+        * Lookup opfamily and input type, for matching indexes
+        */
+       if (elem->inferopclass)
+       {
+               inferopfamily = get_opclass_family(elem->inferopclass);
+               inferopcinputtype = get_opclass_input_type(elem->inferopclass);
+       }
+
        for (natt = 1; natt <= idxRel->rd_att->natts; natt++)
        {
                Oid             opfamily = idxRel->rd_opfamily[natt - 1];
                Oid             opcinputtype = idxRel->rd_opcintype[natt - 1];
                Oid             collation = idxRel->rd_indcollation[natt - 1];
 
-               if (elem->inferopfamily != InvalidOid &&
-                       (elem->inferopfamily != opfamily ||
-                        elem->inferopcinputtype != opcinputtype))
+               if (elem->inferopclass != InvalidOid &&
+                       (inferopfamily != opfamily || inferopcinputtype != opcinputtype))
                {
                        /* Attribute needed to match opclass, but didn't */
                        continue;
index a90bcf40c9d948f8cad385672fda9e459d0035b2..c8af5ab1d050d40002bebf4643926cd776d86fce 100644 (file)
@@ -2730,18 +2730,10 @@ resolve_unique_index_expr(ParseState *pstate, InferClause *infer,
                                                                                                  exprLocation(pInfer->expr));
 
                if (!ielem->opclass)
-               {
-                       pInfer->inferopfamily = InvalidOid;
-                       pInfer->inferopcinputtype = InvalidOid;
-               }
+                       pInfer->inferopclass = InvalidOid;
                else
-               {
-                       Oid             opclass = get_opclass_oid(BTREE_AM_OID, ielem->opclass,
-                                                                                         false);
-
-                       pInfer->inferopfamily = get_opclass_family(opclass);
-                       pInfer->inferopcinputtype = get_opclass_input_type(opclass);
-               }
+                       pInfer->inferopclass = get_opclass_oid(BTREE_AM_OID,
+                                                                                                  ielem->opclass, false);
 
                result = lappend(result, pInfer);
        }
index a5467c5379918b3eb5abc01c5a1c13a4395e8d11..9f3a7267a27c486989813aea9fab870c328c99ef 100644 (file)
@@ -1198,8 +1198,7 @@ typedef struct InferenceElem
        Expr            xpr;
        Node       *expr;                               /* expression to infer from, or NULL */
        Oid                     infercollid;            /* OID of collation, or InvalidOid */
-       Oid                     inferopfamily;          /* OID of att opfamily, or InvalidOid */
-       Oid                     inferopcinputtype;      /* OID of att input type, or InvalidOid */
+       Oid                     inferopclass;           /* OID of att opclass, or InvalidOid */
 } InferenceElem;
 
 /*--------------------