Mercurial > gemma
diff pkg/controllers/common.go @ 3194:eeff2cc4ff9d
controllers: re-factored the SQL filter to a tree like structure to be of more general use.
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Wed, 08 May 2019 13:11:30 +0200 |
parents | 54a3e40cfbed |
children | 4c254651d80b |
line wrap: on
line diff
--- a/pkg/controllers/common.go Wed May 08 12:45:21 2019 +0200 +++ b/pkg/controllers/common.go Wed May 08 13:11:30 2019 +0200 @@ -18,26 +18,61 @@ "strings" ) -type filterBuilder struct { - stmt strings.Builder - args []interface{} - hasCond bool +type ( + filterNode interface { + serialize(*strings.Builder, *[]interface{}) + } + + filterTerm struct { + format string + args []interface{} + } + + filterNot struct { + filterNode + } + + filterAnd []filterNode + filterOr []filterNode +) + +func (ft *filterTerm) serialize(stmt *strings.Builder, args *[]interface{}) { + indices := make([]interface{}, len(ft.args)) + for i := range indices { + indices[i] = len(*args) + i + 1 + } + fmt.Fprintf(stmt, ft.format, indices...) + *args = append(*args, (*ft).args...) } -func (fb *filterBuilder) arg(format string, v ...interface{}) { - indices := make([]interface{}, len(v)) - for i := range indices { - indices[i] = len(fb.args) + i + 1 +func buildFilterTerm(format string, args ...interface{}) *filterTerm { + return &filterTerm{format: format, args: args} +} + +func (fa filterAnd) serialize(stmt *strings.Builder, args *[]interface{}) { + for i, node := range fa { + if i > 0 { + stmt.WriteString(" AND ") + } + stmt.WriteByte('(') + node.serialize(stmt, args) + stmt.WriteByte(')') } - fmt.Fprintf(&fb.stmt, format, indices...) - fb.args = append(fb.args, v...) } -func (fb *filterBuilder) and(format string, v ...interface{}) { - if fb.hasCond { - fb.stmt.WriteString(" AND ") - } else { - fb.hasCond = true +func (fo filterOr) serialize(stmt *strings.Builder, args *[]interface{}) { + for i, node := range fo { + if i > 0 { + stmt.WriteString(" OR ") + } + stmt.WriteByte('(') + node.serialize(stmt, args) + stmt.WriteByte(')') } - fb.arg(format, v...) } + +func (fn *filterNot) serialize(stmt *strings.Builder, args *[]interface{}) { + stmt.WriteString("NOT (") + fn.filterNode.serialize(stmt, args) + stmt.WriteByte(')') +}