Skip to content

Commit d74b570

Browse files
fix subscription plan caching for client-specific views
1 parent 31a8d5f commit d74b570

2 files changed

Lines changed: 36 additions & 2 deletions

File tree

crates/physical-plan/src/plan.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,13 @@ impl ProjectPlan {
115115
pub fn returns_view_table(&self) -> bool {
116116
self.return_table().is_some_and(|schema| schema.is_view())
117117
}
118+
119+
/// Does this plan read from an (anonymous) view?
120+
pub fn reads_from_view(&self, anonymous: bool) -> bool {
121+
match self {
122+
Self::None(plan) | Self::Name(plan, ..) => plan.reads_from_view(anonymous),
123+
}
124+
}
118125
}
119126

120127
/// Physical plans always terminate with a projection.
@@ -213,6 +220,15 @@ impl ProjectListPlan {
213220
pub fn returns_view_table(&self) -> bool {
214221
self.return_table().is_some_and(|schema| schema.is_view())
215222
}
223+
224+
/// Does this plan read from an (anonymous) view?
225+
pub fn reads_from_view(&self, anonymous: bool) -> bool {
226+
match self {
227+
Self::Limit(plan, _) => plan.reads_from_view(anonymous),
228+
Self::Name(plans) => plans.iter().any(|plan| plan.reads_from_view(anonymous)),
229+
Self::List(plans, ..) | Self::Agg(plans, ..) => plans.iter().any(|plan| plan.reads_from_view(anonymous)),
230+
}
231+
}
216232
}
217233

218234
/// Query operators return tuples of rows.
@@ -1124,6 +1140,19 @@ impl PhysicalPlan {
11241140
pub fn returns_view_table(&self) -> bool {
11251141
self.return_table().is_some_and(|schema| schema.is_view())
11261142
}
1143+
1144+
/// Does this plan read from an (anonymous) view?
1145+
pub fn reads_from_view(&self, anonymous: bool) -> bool {
1146+
self.any(&|plan| match plan {
1147+
Self::TableScan(scan, _) if anonymous => scan.schema.is_anonymous_view(),
1148+
Self::TableScan(scan, _) => scan.schema.is_view() && !scan.schema.is_anonymous_view(),
1149+
Self::IxScan(scan, _) if anonymous => scan.schema.is_anonymous_view(),
1150+
Self::IxScan(scan, _) => scan.schema.is_view() && !scan.schema.is_anonymous_view(),
1151+
Self::IxJoin(join, _) if anonymous => join.rhs.is_anonymous_view(),
1152+
Self::IxJoin(join, _) => join.rhs.is_view() && !join.rhs.is_anonymous_view(),
1153+
_ => false,
1154+
})
1155+
}
11271156
}
11281157

11291158
/// Scan a table row by row, returning row ids

crates/query/src/lib.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,14 @@ pub fn compile_subscription(
4545
let plan_fragments = resolve_views_for_sub(tx, plan, auth, &mut has_param)?
4646
.into_iter()
4747
.map(compile_select)
48-
.collect();
48+
.collect::<Vec<_>>();
4949

50-
Ok((plan_fragments, return_id, return_name, has_param))
50+
// Does this subscription read from a client-specific view?
51+
// If so, it is as if the view is parameterized by `:sender`.
52+
// We must know this in order to generate the correct query hash.
53+
let reads_view = plan_fragments.iter().any(|plan| plan.reads_from_view(false));
54+
55+
Ok((plan_fragments, return_id, return_name, has_param || reads_view))
5156
}
5257

5358
/// A utility for parsing and type checking a sql statement

0 commit comments

Comments
 (0)