gokselk commented on code in PR #14111: URL: https://github.com/apache/datafusion/pull/14111#discussion_r1916736891
########## datafusion/physical-expr/src/equivalence/properties.rs: ########## @@ -548,6 +570,88 @@ impl EquivalenceProperties { true } + /// Checks if the sort requirements are satisfied by any of the table constraints (primary key or unique). + /// Returns true if any constraint fully satisfies the requirements. + fn satisfied_by_constraints( + &self, + normalized_reqs: &[PhysicalSortRequirement], + ) -> bool { + self.constraints.iter().any(|constraint| match constraint { + Constraint::PrimaryKey(indices) | Constraint::Unique(indices) => self + .satisfied_by_constraint( + normalized_reqs, + indices, + matches!(constraint, Constraint::Unique(_)), + ), + }) + } + + /// Checks if sort requirements are satisfied by a constraint (primary key or unique). + /// Returns true if the constraint indices form a valid prefix of an existing ordering + /// that matches the requirements. For unique constraints, also verifies nullable columns. + fn satisfied_by_constraint( + &self, + normalized_reqs: &[PhysicalSortRequirement], + indices: &[usize], + check_null: bool, + ) -> bool { + // Requirements must contain indices + if indices.len() > normalized_reqs.len() { + return false; + } + + // Find orderings that contain all required indices + let prefix_candidates = self + .oeq_class + .iter() + .filter(|&ordering| { + if indices.len() > ordering.len() { + return false; + } + + // Check if all constraint indices appear in this ordering + indices.iter().all(|&idx| { Review Comment: Resolved in 726737b. ########## datafusion/physical-expr/src/equivalence/properties.rs: ########## @@ -548,6 +570,88 @@ impl EquivalenceProperties { true } + /// Checks if the sort requirements are satisfied by any of the table constraints (primary key or unique). + /// Returns true if any constraint fully satisfies the requirements. + fn satisfied_by_constraints( + &self, + normalized_reqs: &[PhysicalSortRequirement], + ) -> bool { + self.constraints.iter().any(|constraint| match constraint { + Constraint::PrimaryKey(indices) | Constraint::Unique(indices) => self + .satisfied_by_constraint( + normalized_reqs, + indices, + matches!(constraint, Constraint::Unique(_)), + ), + }) + } + + /// Checks if sort requirements are satisfied by a constraint (primary key or unique). + /// Returns true if the constraint indices form a valid prefix of an existing ordering + /// that matches the requirements. For unique constraints, also verifies nullable columns. + fn satisfied_by_constraint( + &self, + normalized_reqs: &[PhysicalSortRequirement], + indices: &[usize], + check_null: bool, + ) -> bool { + // Requirements must contain indices + if indices.len() > normalized_reqs.len() { + return false; + } + + // Find orderings that contain all required indices + let prefix_candidates = self + .oeq_class + .iter() + .filter(|&ordering| { + if indices.len() > ordering.len() { + return false; + } + + // Check if all constraint indices appear in this ordering + indices.iter().all(|&idx| { + ordering.iter().enumerate().any(|(pos, req)| { + // Only handle Column expressions + let Some(col) = req.expr.as_any().downcast_ref::<Column>() else { + return false; + }; + + // Column index must match + if col.index() != idx { + return false; + } + + // For unique constraints, verify column is not nullable if it's first/last + if check_null && (pos == 0 || pos == ordering.len() - 1) { + return !col.nullable(&self.schema).unwrap_or(true); + } + + true + }) + }) + }) + .collect::<Vec<_>>(); + + if prefix_candidates.is_empty() { + return false; + } + + // Check if any candidate ordering matches requirements prefix + prefix_candidates.iter().any(|&ordering| { Review Comment: Resolved in 726737b. -- 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: github-unsubscr...@datafusion.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org --------------------------------------------------------------------- To unsubscribe, e-mail: github-unsubscr...@datafusion.apache.org For additional commands, e-mail: github-h...@datafusion.apache.org