Re: Making Vars outer-join aware

Anton A. Melnikov <aamelnikov@inbox.ru>

From: "Anton A. Melnikov" <aamelnikov@inbox.ru>
To: Justin Pryzby <pryzby@telsasoft.com>, Richard Guo <guofenglinux@gmail.com>
Cc: Tom Lane <tgl@sss.pgh.pa.us>, pgsql-hackers@lists.postgresql.org, "Finnerty, Jim" <jfinnert@amazon.com>
Date: 2023-05-04T07:22:36Z
Lists: pgsql-hackers

Commits

Same data as JSON: GET /api/v1/messages/:b64id/commits the thread's linked commits as JSON, with link sources. API reference →
  1. Re-allow INDEX_VAR as rt_index in ChangeVarNodes().

  2. Fix thinkos in have_unsafe_outer_join_ref; reduce to Assert check.

  3. Invent "join domains" to replace the below_outer_join hack.

  4. Do assorted mop-up in the planner.

  5. Make Vars be outer-join-aware.

  6. Invent "multibitmapsets", and use them to speed up antijoin detection.

  7. Add basic regression tests for semi/antijoin recognition.

  8. Improve performance of adjust_appendrel_attrs_multilevel.

  9. Refactor addition of PlaceHolderVars to joinrel targetlists.

  10. Use an explicit state flag to control PlaceHolderInfo creation.

  11. Make PlaceHolderInfo lookup O(1).

Hello!

I'm having doubts about this fix but most likely i don't understand something.
Could you help me to figure it out, please.

The thing is that for custom scan nodes as readme says:
"INDEX_VAR is abused to signify references to columns of a custom scan tuple type"
But INDEX_VAR has a negative value, so it can not be used in varnullingrels bitmapset.
And therefore this improvement seems will not work with custom scan nodes and some
extensions that use such nodes.

If i'm wrong in my doubts and bitmapset for varnullingrels is ok, may be add a check before
adjust_relid_set() call like this:

@@ -569,9 +569,10 @@ ChangeVarNodes_walker(Node *node, ChangeVarNodes_context *context)
                 {
                         if (var->varno == context->rt_index)
                                 var->varno = context->new_index;
-                       var->varnullingrels = adjust_relid_set(var->varnullingrels,
-                                                              context->rt_index,
-                                                              context->new_index);
+                       if (context->rt_index >= 0 && context->new_index >= 0)
+                               var->varnullingrels = adjust_relid_set(var->varnullingrels,
+                                                                      context->rt_index,
+

With the best wishes,

-- 
Anton A. Melnikov
Postgres Professional: http://www.postgrespro.com
The Russian Postgres Company