Do not add broken compressed join clauses

We used to add join clauses that referenced a compressed column at the
level of the compressed scan, and later remove them. This is wrong and
useless, just don't add them.
This commit is contained in:
Alexander Kuzmenkov 2023-08-15 23:18:13 +02:00
parent 22a2f49a2f
commit d088b3a5d9
3 changed files with 60 additions and 61 deletions

View File

@ -1170,6 +1170,49 @@ chunk_joininfo_mutator(Node *node, CompressionInfo *context)
return expression_tree_mutator(node, chunk_joininfo_mutator, context);
}
/* Check if the expression references a compressed column in compressed chunk. */
static bool
has_compressed_vars_walker(Node *node, CompressionInfo *info)
{
if (node == NULL)
{
return false;
}
if (IsA(node, Var))
{
Var *var = castNode(Var, node);
if ((Index) var->varno != (Index) info->compressed_rel->relid)
{
return false;
}
if (var->varattno <= 0)
{
/*
* Shouldn't see a system var here, might be a whole row var?
* In any case, we can't push it down to the compressed scan level.
*/
return true;
}
if (bms_is_member(var->varattno, info->compressed_attnos_in_compressed_chunk))
{
return true;
}
return false;
}
return expression_tree_walker(node, has_compressed_vars_walker, info);
}
static bool
has_compressed_vars(RestrictInfo *ri, CompressionInfo *info)
{
return expression_tree_walker((Node *) ri->clause, has_compressed_vars_walker, info);
}
/* translate chunk_rel->joininfo for compressed_rel
* this is necessary for create_index_path which gets join clauses from
* rel->joininfo and sets up parameterized paths (in rel->ppilist).
@ -1186,12 +1229,21 @@ compressed_rel_setup_joininfo(RelOptInfo *compressed_rel, CompressionInfo *info)
List *compress_joininfo = NIL;
foreach (lc, chunk_rel->joininfo)
{
RestrictInfo *compress_ri;
RestrictInfo *ri = (RestrictInfo *) lfirst(lc);
Node *result = chunk_joininfo_mutator((Node *) ri, info);
Assert(IsA(result, RestrictInfo));
compress_ri = (RestrictInfo *) result;
compress_joininfo = lappend(compress_joininfo, compress_ri);
RestrictInfo *adjusted = (RestrictInfo *) chunk_joininfo_mutator((Node *) ri, info);
Assert(IsA(adjusted, RestrictInfo));
if (has_compressed_vars(adjusted, info))
{
/*
* We can't check clauses that refer to compressed columns during
* the compressed scan.
*/
continue;
}
compress_joininfo = lappend(compress_joininfo, adjusted);
}
compressed_rel->joininfo = compress_joininfo;
}
@ -1481,8 +1533,8 @@ decompress_chunk_add_plannerinfo(PlannerInfo *root, CompressionInfo *info, Chunk
/* store attnos for the compressed chunk here */
AttrNumber compressed_chunk_attno =
get_attnum(info->compressed_rte->relid, NameStr(fd->attname));
info->compressed_chunk_compressed_attnos =
bms_add_member(info->compressed_chunk_compressed_attnos, compressed_chunk_attno);
info->compressed_attnos_in_compressed_chunk =
bms_add_member(info->compressed_attnos_in_compressed_chunk, compressed_chunk_attno);
}
}
compressed_rel_setup_reltarget(compressed_rel, info, needs_sequence_num);

View File

@ -35,7 +35,7 @@ typedef struct CompressionInfo
*/
Bitmapset *chunk_const_segmentby;
/* compressed chunk attribute numbers for columns that are compressed */
Bitmapset *compressed_chunk_compressed_attnos;
Bitmapset *compressed_attnos_in_compressed_chunk;
bool single_chunk; /* query on explicit chunk */

View File

@ -322,33 +322,6 @@ replace_compressed_vars(Node *node, CompressionInfo *info)
return expression_tree_mutator(node, replace_compressed_vars, (void *) info);
}
typedef struct CompressedAttnoContext
{
Bitmapset *compressed_attnos;
Index compress_relid;
} CompressedAttnoContext;
/* check if the clause refers to any attributes that are in compressed
* form.
*/
static bool
clause_has_compressed_attrs(Node *node, void *context)
{
if (node == NULL)
return true;
if (IsA(node, Var))
{
CompressedAttnoContext *cxt = (CompressedAttnoContext *) context;
Var *var = (Var *) node;
if ((Index) var->varno == cxt->compress_relid)
{
if (bms_is_member(var->varattno, cxt->compressed_attnos))
return true;
}
}
return expression_tree_walker(node, clause_has_compressed_attrs, context);
}
/*
* Find the resno of the given attribute in the provided target list
*/
@ -410,8 +383,6 @@ decompress_chunk_plan_create(PlannerInfo *root, RelOptInfo *rel, CustomPath *pat
* IndexClause's, so we use some custom code based on it.
*/
IndexPath *ipath = castNode(IndexPath, compressed_path);
List *indexqual = NIL;
Plan *indexplan;
foreach (lc, clauses)
{
RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc);
@ -443,30 +414,6 @@ decompress_chunk_plan_create(PlannerInfo *root, RelOptInfo *rel, CustomPath *pat
decompress_plan->scan.plan.qual =
lappend(decompress_plan->scan.plan.qual, rinfo->clause);
}
/* joininfo clauses on the compressed chunk rel have to
* contain clauses on both compressed and
* decompressed attnos. joininfo clauses get translated into
* ParamPathInfo for the indexpath. But the index scans can't
* handle compressed attributes, so remove them from the
* indexscans here. (these are included in the `clauses` passed in
* to the function and so were added as filters
* for decompress_plan->scan.plan.qual in the loop above. )
*/
indexplan = linitial(custom_plans);
Assert(IsA(indexplan, IndexScan) || IsA(indexplan, IndexOnlyScan));
foreach (lc, indexplan->qual)
{
Node *expr = (Node *) lfirst(lc);
CompressedAttnoContext cxt;
Index compress_relid = dcpath->info->compressed_rel->relid;
cxt.compress_relid = compress_relid;
cxt.compressed_attnos = dcpath->info->compressed_chunk_compressed_attnos;
if (!clause_has_compressed_attrs((Node *) expr, &cxt))
indexqual = lappend(indexqual, expr);
}
indexplan->qual = indexqual;
}
else
{