diff options
| author | JP Appel <jeanpierre.appel01@gmail.com> | 2025-07-28 01:20:01 -0400 |
|---|---|---|
| committer | JP Appel <jeanpierre.appel01@gmail.com> | 2025-07-28 01:20:01 -0400 |
| commit | 3b8dcd30f5aca7624a22cff85a2f767d8d1fb583 (patch) | |
| tree | db01e57776ef9a8bc104403cd038e303c6831500 /pkg/query/optimizer.go | |
| parent | 7b5cd075161bd4e1a05070d51cc64b38882ae74b (diff) | |
Add regex operator
Implemented regex operator using go flavored regular expressions.
Added optimization to combine regex's in `OR` clauses.
Diffstat (limited to 'pkg/query/optimizer.go')
| -rw-r--r-- | pkg/query/optimizer.go | 63 |
1 files changed, 62 insertions, 1 deletions
diff --git a/pkg/query/optimizer.go b/pkg/query/optimizer.go index 3c435e8..2cc610a 100644 --- a/pkg/query/optimizer.go +++ b/pkg/query/optimizer.go @@ -1,6 +1,7 @@ package query import ( + "bytes" "slices" "strings" "sync" @@ -52,7 +53,6 @@ func (o Optimizer) Optimize(level int) { if level < 0 { return } else if level == 0 { - // TODO: determine smarter level determination strategy level = o.root.Depth() } @@ -63,6 +63,7 @@ func (o Optimizer) Optimize(level int) { o.StrictEquality() o.Tighten() o.Contradictions() + o.MergeRegex() // parallel + serial o.Tidy() // purely serial @@ -326,6 +327,66 @@ func (o Optimizer) StrictEquality() { }) } +// Merge regular within a clause +func (o *Optimizer) MergeRegex() { + if !o.isSorted { + o.SortStatements() + } + + pool := &sync.Pool{} + pool.New = func() any { + return &bytes.Buffer{} + } + + o.parallel(func(c *Clause) { + if c.Operator != COP_OR { + return + } + + buf := pool.Get().(*bytes.Buffer) + defer pool.Put(buf) + defer buf.Reset() + sortChanged := false + for _, catStmts := range c.Statements.CategoryPartition() { + for op, opStmts := range catStmts.OperatorPartition() { + if op != OP_RE { + continue + } + + for _, stmts := range opStmts.NegatedPartition() { + if len(stmts) <= 1 { + continue + } + sortChanged = true + + for i, stmt := range stmts { + if i == 0 { + buf.WriteByte('(') + buf.WriteString(stmt.Value.(StringValue).S) + buf.WriteByte('|') + } else if i == len(stmts)-1 { + buf.WriteString(stmt.Value.(StringValue).S) + buf.WriteByte(')') + stmts[i] = Statement{} + } else { + buf.WriteString(stmt.Value.(StringValue).S) + buf.WriteByte('|') + stmts[i] = Statement{} + } + } + stmts[0].Value = StringValue{S: buf.String()} + buf.Reset() + } + + break + } + } + if sortChanged { + o.isSorted = false + } + }) +} + // Shrink approximate statements and ranges // // Examples: |
