Repository: polarsignals/frostdb
Pull request #537 (2023-09-19 15:51:23)

remove hashed optimization regexp compile step
Saves cpu and memory to compile the optimization once


Patch:
diff --git a/query/logicalplan/expr.go b/query/logicalplan/expr.go
index 2af76d8..b7d5e47 100644
--- a/query/logicalplan/expr.go
+++ b/query/logicalplan/expr.go
@@ -692,27 +692,27 @@ func (a *AverageExpr) Accept(visitor Visitor) bool {
 	return visitor.PostVisit(a)
 }
 
-func RegExpColumnMatch(regexp string) *RegexpColumnMatch {
+func RegExpColumnMatch(match *regexp.Regexp) *RegexpColumnMatch {
 	return &RegexpColumnMatch{
-		regexp: regexp,
+		match: match,
 	}
 }
 
-func RegExpNotColumnMatch(regexp string) *RegexpColumnMatch {
+func RegExpNotColumnMatch(match *regexp.Regexp) *RegexpColumnMatch {
 	return &RegexpColumnMatch{
 		inverse: true,
-		regexp:  regexp,
+		match:   match,
 	}
 }
 
 type RegexpColumnMatch struct {
 	inverse bool
-	regexp  string
+	match   *regexp.Regexp
 }
 
 func (a *RegexpColumnMatch) Clone() Expr {
 	return &RegexpColumnMatch{
-		regexp: a.regexp,
+		match: a.match,
 	}
 }
 
@@ -721,7 +721,7 @@ func (a *RegexpColumnMatch) DataType(s *parquet.Schema) (arrow.DataType, error)
 }
 
 func (a *RegexpColumnMatch) Name() string {
-	return a.regexp
+	return a.match.String()
 }
 
 func (a *RegexpColumnMatch) ColumnsUsedExprs() []Expr {
@@ -729,13 +729,11 @@ func (a *RegexpColumnMatch) ColumnsUsedExprs() []Expr {
 }
 
 func (a *RegexpColumnMatch) MatchPath(path string) bool {
-	match, err := regexp.MatchString(a.regexp, path)
-	return err == nil && match != a.inverse
+	return a.match.MatchString(path) != a.inverse
 }
 
 func (a *RegexpColumnMatch) MatchColumn(name string) bool {
-	match, err := regexp.MatchString(a.regexp, name)
-	return err == nil && match != a.inverse
+	return a.match.MatchString(name) != a.inverse
 }
 
 func (a *RegexpColumnMatch) Computed() bool {
diff --git a/query/logicalplan/optimize.go b/query/logicalplan/optimize.go
index 494ec5d..8d3e2ed 100644
--- a/query/logicalplan/optimize.go
+++ b/query/logicalplan/optimize.go
@@ -1,9 +1,13 @@
 package logicalplan
 
 import (
+	"regexp"
+
 	"golang.org/x/exp/slices"
 )
 
+var hashedMatch = regexp.MustCompile("^hashed.")
+
 type Optimizer interface {
 	Optimize(plan *LogicalPlan) *LogicalPlan
 }
@@ -13,7 +17,7 @@ func DefaultOptimizers() []Optimizer {
 		&AverageAggregationPushDown{},
 		&PhysicalProjectionPushDown{
 			defaultProjections: []Expr{
-				RegExpNotColumnMatch("^hashed."),
+				RegExpNotColumnMatch(hashedMatch),
 			},
 		},
 		&FilterPushDown{},
@@ -122,7 +126,7 @@ func (p *PhysicalProjectionPushDown) optimize(plan *LogicalPlan, columnsUsedExpr
 			columnsUsedExprs = append(columnsUsedExprs, expr.ColumnsUsedExprs()...)
 		}
 		p.defaultProjections = []Expr{}
-		columnsUsedExprs = append(columnsUsedExprs, RegExpColumnMatch("^hashed."))
+		columnsUsedExprs = append(columnsUsedExprs, RegExpColumnMatch(hashedMatch))
 	}
 
 	if plan.Input != nil {


Test patch:
diff --git a/query/logicalplan/optimize_test.go b/query/logicalplan/optimize_test.go
index 4cedd1f..3835eb4 100644
--- a/query/logicalplan/optimize_test.go
+++ b/query/logicalplan/optimize_test.go
@@ -35,7 +35,7 @@ func TestOptimizePhysicalProjectionPushDown(t *testing.T) {
 			&Column{ColumnName: "stacktrace"},
 			&Column{ColumnName: "stacktrace"},
 			&Column{ColumnName: "value"},
-			RegExpColumnMatch("^hashed."),
+			RegExpColumnMatch(hashedMatch),
 			&Column{ColumnName: "labels.test"},
 		},
 	},
@@ -205,7 +205,7 @@ func TestAllOptimizers(t *testing.T) {
 			&Column{ColumnName: "stacktrace"},
 			&Column{ColumnName: "stacktrace"},
 			&Column{ColumnName: "value"},
-			RegExpColumnMatch("^hashed."),
+			RegExpColumnMatch(hashedMatch),
 			&Column{ColumnName: "labels.test"},
 		},
 		Filter: &BinaryExpr{