Queryer: an explicit archived filter overrides the active-only default, per node
Filter keys arrive as "path/field:$op", so the override check that compared the key to the bare "archived" never matched: the hidden NOT archived clause was always added and an explicit archived filter could not return archived rows. The match is on the node's own archived path, so a root filter lifts the default for the root only — nested includes the filter never mentioned keep hiding archived rows. The two queryer fixtures that filter on archived had snapshotted the contradiction (NOT archived AND archived = $1); they now expect the filter alone. 1286 library tests pass. Pinned by api's TestArchive_CascadesDownTheTree (test/punc/lineage_test.go). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AvkGU4kQ4wsqxHFpXtZKZM
This commit is contained in:
@ -1246,8 +1246,7 @@
|
|||||||
" )",
|
" )",
|
||||||
" FROM agreego.entity entity_1",
|
" FROM agreego.entity entity_1",
|
||||||
" WHERE",
|
" WHERE",
|
||||||
" NOT entity_1.archived",
|
" entity_1.archived = ($1 #>> '{}')::BOOLEAN",
|
||||||
" AND entity_1.archived = ($1 #>> '{}')::BOOLEAN",
|
|
||||||
" AND entity_1.archived <> ($2 #>> '{}')::BOOLEAN",
|
" AND entity_1.archived <> ($2 #>> '{}')::BOOLEAN",
|
||||||
" AND entity_1.created_at = ($3 #>> '{}')::TIMESTAMPTZ",
|
" AND entity_1.created_at = ($3 #>> '{}')::TIMESTAMPTZ",
|
||||||
" AND entity_1.created_at > ($4 #>> '{}')::TIMESTAMPTZ",
|
" AND entity_1.created_at > ($4 #>> '{}')::TIMESTAMPTZ",
|
||||||
@ -1718,8 +1717,7 @@
|
|||||||
" JOIN agreego.organization organization_2 ON organization_2.id = entity_1.id",
|
" JOIN agreego.organization organization_2 ON organization_2.id = entity_1.id",
|
||||||
" JOIN agreego.person person_3 ON person_3.id = organization_2.id",
|
" JOIN agreego.person person_3 ON person_3.id = organization_2.id",
|
||||||
" WHERE",
|
" WHERE",
|
||||||
" NOT entity_1.archived",
|
" person_3.age = ($1 #>> '{}')::NUMERIC",
|
||||||
" AND person_3.age = ($1 #>> '{}')::NUMERIC",
|
|
||||||
" AND person_3.age > ($2 #>> '{}')::NUMERIC",
|
" AND person_3.age > ($2 #>> '{}')::NUMERIC",
|
||||||
" AND person_3.age >= ($3 #>> '{}')::NUMERIC",
|
" AND person_3.age >= ($3 #>> '{}')::NUMERIC",
|
||||||
" AND person_3.age < ($4 #>> '{}')::NUMERIC",
|
" AND person_3.age < ($4 #>> '{}')::NUMERIC",
|
||||||
|
|||||||
@ -578,8 +578,20 @@ impl<'a> Compiler<'a> {
|
|||||||
let mut where_clauses = Vec::new();
|
let mut where_clauses = Vec::new();
|
||||||
|
|
||||||
// Dynamically apply the 'active-only' default ONLY if the client
|
// Dynamically apply the 'active-only' default ONLY if the client
|
||||||
// didn't explicitly request to filter on 'archived' themselves!
|
// didn't explicitly request to filter on 'archived' themselves — for THIS node.
|
||||||
let has_archived_override = self.filter_keys.iter().any(|k| k == "archived");
|
// Keys arrive as "path/field:$op" (extract_filters), so match this node's own archived
|
||||||
|
// path, never the bare name: compared to "archived" alone it never matched (an explicit
|
||||||
|
// archived filter could not return archived rows), and matched on any key it would lift
|
||||||
|
// the default from every nested include the filter never mentioned.
|
||||||
|
let archived_path = if node.ast_path.is_empty() {
|
||||||
|
"archived".to_string()
|
||||||
|
} else {
|
||||||
|
format!("{}/archived", node.ast_path)
|
||||||
|
};
|
||||||
|
let has_archived_override = self
|
||||||
|
.filter_keys
|
||||||
|
.iter()
|
||||||
|
.any(|k| k.split(':').next().unwrap_or(k) == archived_path);
|
||||||
|
|
||||||
if !has_archived_override {
|
if !has_archived_override {
|
||||||
where_clauses.push(format!("NOT {}.archived", entity_alias));
|
where_clauses.push(format!("NOT {}.archived", entity_alias));
|
||||||
|
|||||||
Reference in New Issue
Block a user