duckdb/arrow: CWE-407 scan — 4 DuckDB defects, 2 Arrow defects
DuckDB (C++ query engine): - duckdb-0001: Binder::AddCorrelatedColumn vector dedup O(C²) MEDIUM 200x - duckdb-0002: HasCorrelatedExpressions vector scan O(N×M) MEDIUM 100x - duckdb-0003: ComputeOverlappingBindings vector scan O(N×H) MEDIUM 219x - duckdb-0004: Deliminator group-join binding check O(G×J) MEDIUM 125x Apache Arrow (C++ analytics): - arrow-0001: AsofJoin IsTimeOrKeyColumn vector scan O(F×K) MEDIUM 114x - arrow-0002: Scanner AddFieldsNeededForFilter vector dedup O(F×C) MEDIUM 250x All 6/6 unit tests PASS.
This commit is contained in:
parent
0772cf539a
commit
6b975a3b9e
13 changed files with 959 additions and 184 deletions
|
|
@ -0,0 +1,39 @@
|
|||
# UNDF: (leave blank)
|
||||
--- a/pkg/planner/core/rule/rule_predicate_simplification.go
|
||||
+++ b/pkg/planner/core/rule/rule_predicate_simplification.go
|
||||
@@ -228,7 +228,6 @@ func mergeInAndNotEQLists(sctx base.PlanContext, predicates []expression.Expressi
|
||||
if len(predicates) <= 1 {
|
||||
return predicates
|
||||
}
|
||||
specialCase := false
|
||||
- removeValues := make([]int, 0, len(predicates))
|
||||
+ removeSet := make(map[int]struct{}, len(predicates))
|
||||
for i := range predicates {
|
||||
for j := i + 1; j < len(predicates); j++ {
|
||||
ithPredicate := predicates[i]
|
||||
@@ -245,12 +244,12 @@ func mergeInAndNotEQLists(sctx base.PlanContext, predicates []expression.Expressi
|
||||
if !specialCase {
|
||||
- removeValues = append(removeValues, i)
|
||||
+ removeSet[i] = struct{}{}
|
||||
}
|
||||
} else if iType == inListPredicate && jType == notEqualPredicate {
|
||||
predicates[i], specialCase = updateInPredicate(sctx, ithPredicate, jthPredicate)
|
||||
if maybeOverOptimized4PlanCache {
|
||||
sctx.GetSessionVars().StmtCtx.SetSkipPlanCache("NE/INList simplification is triggered")
|
||||
}
|
||||
if !specialCase {
|
||||
- removeValues = append(removeValues, j)
|
||||
+ removeSet[j] = struct{}{}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
newValues := make([]expression.Expression, 0, len(predicates))
|
||||
for i, value := range predicates {
|
||||
- if !(slices.Contains(removeValues, i)) {
|
||||
+ if _, remove := removeSet[i]; !remove {
|
||||
newValues = append(newValues, value)
|
||||
}
|
||||
}
|
||||
return newValues
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
# UNDF: (leave blank)
|
||||
--- a/pkg/table/tables/partition.go
|
||||
+++ b/pkg/table/tables/partition.go
|
||||
@@ -640,13 +640,18 @@ func (pg *ListPartitionGroup) intersect(otherPg ListPartitionGroup) bool {
|
||||
if pg.PartIdx != otherPg.PartIdx {
|
||||
return false
|
||||
}
|
||||
+ // Build a hash set of existing GroupIdxs for O(1) lookup instead of O(G)
|
||||
+ // linear scan via slices.Contains, making the overall intersect O(G) not O(G²).
|
||||
+ existing := make(map[int]struct{}, len(pg.GroupIdxs))
|
||||
+ for _, gidx := range pg.GroupIdxs {
|
||||
+ existing[gidx] = struct{}{}
|
||||
+ }
|
||||
var groupIdxs []int
|
||||
for _, gidx := range otherPg.GroupIdxs {
|
||||
- if pg.findGroupIdx(gidx) {
|
||||
+ if _, ok := existing[gidx]; ok {
|
||||
groupIdxs = append(groupIdxs, gidx)
|
||||
}
|
||||
}
|
||||
pg.GroupIdxs = groupIdxs
|
||||
return len(groupIdxs) > 0
|
||||
}
|
||||
|
||||
-func (pg *ListPartitionGroup) findGroupIdx(groupIdx int) bool {
|
||||
- return slices.Contains(pg.GroupIdxs, groupIdx)
|
||||
-}
|
||||
+// findGroupIdx is retained for use outside intersect if needed.
|
||||
+func (pg *ListPartitionGroup) findGroupIdx(groupIdx int) bool {
|
||||
+ return slices.Contains(pg.GroupIdxs, groupIdx)
|
||||
+}
|
||||
Loading…
Add table
Add a link
Reference in a new issue