Skip to content

Commit

Permalink
Fix handling of resjunk TargetEntry (used in GROUP BY) of subqueries
Browse files Browse the repository at this point in the history
  • Loading branch information
PierreSenellart committed Jul 26, 2024
1 parent be0edb1 commit b006580
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 7 deletions.
51 changes: 45 additions & 6 deletions src/provsql.c
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ static List *get_provenance_attributes(const constants_t *constants, Query *q)
if(new_subquery != NULL) {
int i=0;
int *offset = (int *)palloc(old_targetlist_length * sizeof(int));
unsigned varattnoprovsql;

r->subquery = new_subquery;

Expand All @@ -229,8 +230,16 @@ static List *get_provenance_attributes(const constants_t *constants, Query *q)
reduce_varattno_by_offset(q->targetList, rteid, offset);
}

varattnoprovsql=0;
for(ListCell *cell = list_head(new_subquery->targetList); cell!=NULL; cell=my_lnext(new_subquery->targetList, cell)) {
TargetEntry *te = (TargetEntry*) lfirst(cell);
++varattnoprovsql;
if(!strcmp(te->resname,PROVSQL_COLUMN_NAME))
break;
}

r->eref->colnames = lappend(r->eref->colnames, makeString(pstrdup(PROVSQL_COLUMN_NAME)));
prov_atts=lappend(prov_atts,make_provenance_attribute(constants, q, r, rteid, list_length(new_subquery->targetList)));
prov_atts=lappend(prov_atts,make_provenance_attribute(constants, q, r, rteid, varattnoprovsql));
fix_type_of_aggregation_result(constants, q, rteid, r->subquery->targetList);
}
}
Expand Down Expand Up @@ -583,6 +592,7 @@ static Expr *make_aggregation_expression(
agg->args=list_make1(te_inner);
agg->aggkind=AGGKIND_NORMAL;
agg->location=-1;
agg->aggno=agg->aggtransno=-1;

agg->aggargtypes = list_make1_oid(constants->OID_TYPE_UUID);

Expand Down Expand Up @@ -959,11 +969,40 @@ static void add_to_select(
Query *q,
Expr *provenance)
{
TargetEntry *te = makeNode(TargetEntry);
te->expr = provenance;
te->resno = list_length(q->targetList) + 1;
te->resname = (char *)PROVSQL_COLUMN_NAME;
q->targetList = lappend(q->targetList, te);
TargetEntry *newte = makeNode(TargetEntry);
bool inserted=false;
unsigned resno=0;

newte->expr = provenance;
newte->resname = (char *)PROVSQL_COLUMN_NAME;

/* Make sure to insert before all resjunk Target Entry */
for (ListCell *cell = list_head(q->targetList); cell != NULL;)
{
TargetEntry *te = (TargetEntry*) lfirst(cell);

if(!inserted)
++resno;

if(te->resjunk) {
if(!inserted) {
newte->resno=resno;
q->targetList = list_insert_nth(q->targetList, resno-1, newte);
cell=list_nth_cell(q->targetList, resno);
te = (TargetEntry*) lfirst(cell);
inserted=true;
}

++te->resno;
}

cell = my_lnext(q->targetList, cell);
}

if(!inserted) {
newte->resno = resno+1;
q->targetList = lappend(q->targetList, newte);
}
}

typedef struct provenance_mutator_context
Expand Down
13 changes: 13 additions & 0 deletions test/expected/resjunk.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
\set ECHO none
remove_provenance

(1 row)
city
Berlin
Berlin
New York
New York
Paris
Paris
Paris
(7 rows)
2 changes: 1 addition & 1 deletion test/schedule.common
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ test: provenance_in_from identify_token subquery create_provenance_mapping
test: security formula counting

# Test of various ProvSQL features and SQL language capabilities
test: deterministic union_all union nested_union union_nary distinct group_by_provenance except null unsupported_features no_attribute
test: deterministic union_all union nested_union union_nary distinct group_by_provenance except null unsupported_features no_attribute resjunk
test: aggregation
test: agg_distinct agg_order_by
test: create_as
Expand Down
33 changes: 33 additions & 0 deletions test/sql/resjunk.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
\set ECHO none
\pset format unaligned
SET search_path TO provsql_test, provsql;

CREATE TABLE resjunk AS
SELECT
city,
provenance ()
FROM (
SELECT
p1.city
FROM
personnel p1
JOIN personnel p2 ON p1.city = p2.city
GROUP BY
p1.city,
p2.name,
p2.id) t;

SELECT
remove_provenance ('resjunk');

ALTER TABLE resjunk
DROP COLUMN provenance;

SELECT
*
FROM
resjunk
ORDER BY
city;

DROP TABLE resjunk;

0 comments on commit b006580

Please sign in to comment.