JingsongLi commented on code in PR #760:
URL: https://github.com/apache/paimon-rust/pull/760#discussion_r3901245270


##########
crates/paimon/src/table/vector_search_builder.rs:
##########
@@ -1217,11 +1270,30 @@ impl<'a> BatchVectorSearchBuilder<'a> {
     pub async fn execute(&self) -> crate::Result<Vec<SearchResult>> {
         let timing_enabled = vector_search_timing_enabled();
         let total_start = timing_enabled.then(Instant::now);
+        if let Some(prepared) = &self.prepared_filter {
+            if !same_vector_search_table(self.table, prepared.table()) {
+                return Err(crate::Error::DataInvalid {
+                    message: format!(
+                        "Prepared vector search filter belongs to a different 
table: builder target is '{}@{}', prepared filter target is '{}@{}'",
+                        self.table.location(),
+                        self.table.branch(),
+                        prepared.table().location(),
+                        prepared.table().branch(),
+                    ),
+                    source: None,
+                });
+            }
+        }
         // Fail closed: like `execute_read` and the single-query builder, this
         // returns data-derived row ids/scores outside `TableScan`/`TableRead`,
         // so it must refuse a `query-auth.enabled` table before any fast path
         // (an empty snapshot would otherwise return empty results and bypass 
it).
-        let core = CoreOptions::new(self.table.schema().options());
+        let execution_table = self
+            .prepared_filter
+            .as_ref()
+            .map(PreparedVectorSearchFilter::table)
+            .unwrap_or(self.table);
+        let core = CoreOptions::new(execution_table.schema().options());

Review Comment:
   [P1] Authorize the builder target before switching to the prepared snapshot
   
   The lineage check still permits different schema/option copies of the same 
physical table, but this guard now checks only `execution_table`. A prepared 
filter created before `query-auth.enabled` was enabled carries the old 
auth-disabled schema; after the catalog reloads the table with auth enabled 
(the same catalog FileIO clone keeps the same lineage), attaching that prepared 
value passes `same_vector_search_table`, replaces the builder target here, and 
bypasses the fail-closed guard. I reproduced the minimal public-API form with 
`source.prepare_vector_search_filter(...)`, `target = 
source.copy_with_options({query-auth.enabled: true})`, and 
`target.new_batch_vector_search_builder().with_prepared_filter(prepared).execute()`:
 it returns `Ok([empty SearchResult])` instead of `Unsupported`. This 
contradicts the existing time-travel rule that current stored auth cannot be 
disabled by a historical/dynamic copy. Please call `ensure_read_authorized` on 
`self.table` before selecting the pi
 nned prepared table (and keep the prepared-table check as defense in depth), 
with a stale-prepared -> auth-enabled-target regression.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to