From 48389c5e94ce409926871afab9f3d9415056f543 Mon Sep 17 00:00:00 2001 From: Ariel Mashraki <7413593+a8m@users.noreply.github.com> Date: Wed, 26 Aug 2020 18:20:45 +0300 Subject: [PATCH] dialect/sql: add the basic operators to WriteOp (#700) * dialect/sql: add the basic operators to WriteOp --- dialect/sql/builder.go | 61 +++++++++++++++++++++++++++++++------ dialect/sql/builder_test.go | 12 ++++---- 2 files changed, 57 insertions(+), 16 deletions(-) diff --git a/dialect/sql/builder.go b/dialect/sql/builder.go index 8abc27982..01d79aaf3 100644 --- a/dialect/sql/builder.go +++ b/dialect/sql/builder.go @@ -891,7 +891,8 @@ func EQ(col string, value interface{}) *Predicate { // EQ appends a "=" predicate. func (p *Predicate) EQ(col string, arg interface{}) *Predicate { return p.Append(func(b *Builder) { - b.Ident(col).WriteString(" = ") + b.Ident(col) + b.WriteOp(OpEQ) b.Arg(arg) }) } @@ -904,7 +905,8 @@ func NEQ(col string, value interface{}) *Predicate { // NEQ appends a "<>" predicate. func (p *Predicate) NEQ(col string, arg interface{}) *Predicate { return p.Append(func(b *Builder) { - b.Ident(col).WriteString(" <> ") + b.Ident(col) + b.WriteOp(OpNEQ) b.Arg(arg) }) } @@ -917,7 +919,8 @@ func LT(col string, value interface{}) *Predicate { // LT appends a "<" predicate. func (p *Predicate) LT(col string, arg interface{}) *Predicate { return p.Append(func(b *Builder) { - b.Ident(col).WriteString(" < ") + b.Ident(col) + p.WriteOp(OpLT) b.Arg(arg) }) } @@ -930,7 +933,8 @@ func LTE(col string, value interface{}) *Predicate { // LTE appends a "<=" predicate. func (p *Predicate) LTE(col string, arg interface{}) *Predicate { return p.Append(func(b *Builder) { - b.Ident(col).WriteString(" <= ") + b.Ident(col) + p.WriteOp(OpLTE) b.Arg(arg) }) } @@ -943,7 +947,8 @@ func GT(col string, value interface{}) *Predicate { // GT appends a ">" predicate. func (p *Predicate) GT(col string, arg interface{}) *Predicate { return p.Append(func(b *Builder) { - b.Ident(col).WriteString(" > ") + b.Ident(col) + p.WriteOp(OpGT) b.Arg(arg) }) } @@ -956,7 +961,8 @@ func GTE(col string, value interface{}) *Predicate { // GTE appends a ">=" predicate. func (p *Predicate) GTE(col string, arg interface{}) *Predicate { return p.Append(func(b *Builder) { - b.Ident(col).WriteString(" >= ") + b.Ident(col) + p.WriteOp(OpGTE) b.Arg(arg) }) } @@ -996,7 +1002,7 @@ func (p *Predicate) In(col string, args ...interface{}) *Predicate { return p } return p.Append(func(b *Builder) { - b.Ident(col).WriteString(" IN ") + b.Ident(col).WriteOp(OpIn) b.Nested(func(b *Builder) { if s, ok := args[0].(*Selector); ok { b.Join(s) @@ -1043,7 +1049,7 @@ func NotIn(col string, args ...interface{}) *Predicate { // NotIn appends the `Not IN` predicate. func (p *Predicate) NotIn(col string, args ...interface{}) *Predicate { return p.Append(func(b *Builder) { - b.Ident(col).WriteString(" NOT IN ") + b.Ident(col).WriteOp(OpNotIn) b.Nested(func(b *Builder) { b.Args(args...) }) @@ -1058,7 +1064,7 @@ func Like(col, pattern string) *Predicate { // Like appends the `LIKE` predicate. func (p *Predicate) Like(col, pattern string) *Predicate { return p.Append(func(b *Builder) { - b.Ident(col).WriteString(" LIKE ") + b.Ident(col).WriteOp(OpLike) b.Arg(pattern) }) } @@ -1089,7 +1095,8 @@ func (p *Predicate) EqualFold(col, sub string) *Predicate { return p.Append(func(b *Builder) { f := &Func{} f.SetDialect(b.dialect) - b.Ident(f.Lower(col)).WriteString(" = ") + b.Ident(f.Lower(col)) + b.WriteOp(OpEQ) b.Arg(strings.ToLower(sub)) }) } @@ -1880,6 +1887,40 @@ func (b *Builder) WriteString(s string) *Builder { return b } +// An Op represents a predicate operator. +type Op int + +const ( + OpEQ Op = iota // logical and. + OpNEQ // <> + OpGT // > + OpGTE // >= + OpLT // < + OpLTE // <= + OpIn // IN + OpNotIn // NOT IN + OpLike // LIKE +) + +var ops = [...]string{ + OpEQ: "=", + OpNEQ: "<>", + OpGT: ">", + OpGTE: ">=", + OpLT: "<", + OpLTE: "<=", + OpIn: "IN", + OpNotIn: "NOT IN", + OpLike: "LIKE", +} + +// WriteOp writes an operator to the builder. +func (b *Builder) WriteOp(op Op) { + if op >= OpEQ && op <= OpLike { + b.Pad().WriteString(ops[op]).Pad() + } +} + // JSONOption allows for calling database JSON paths with functional options. type JSONOption func(*JSONPath) diff --git a/dialect/sql/builder_test.go b/dialect/sql/builder_test.go index b2ced1713..cc9ef5041 100644 --- a/dialect/sql/builder_test.go +++ b/dialect/sql/builder_test.go @@ -1217,9 +1217,9 @@ WHERE input: Dialect(dialect.MySQL). Select("*"). From(Table("users")). - Where(P().Append(func(b *Builder) { + Where(P(func(b *Builder) { b.JSONPath("a", Path("b", "c", "[1]", "d"), Unquote(true)) - b.WriteString(" = ") + b.WriteOp(OpEQ) b.Arg("a") })), wantQuery: "SELECT * FROM `users` WHERE JSON_UNQUOTE(JSON_EXTRACT(`a`, \"$.b.c[1].d\")) = ?", @@ -1229,9 +1229,9 @@ WHERE input: Dialect(dialect.Postgres). Select("*"). From(Table("users")). - Where(P().Append(func(b *Builder) { + Where(P(func(b *Builder) { b.JSONPath("a", Path("b", "c", "[1]", "d"), Unquote(true)) - b.WriteString(" = ") + b.WriteOp(OpEQ) b.Arg("a") })), wantQuery: `SELECT * FROM "users" WHERE "a"->'b'->'c'->1->>'d' = $1`, @@ -1241,9 +1241,9 @@ WHERE input: Dialect(dialect.Postgres). Select("*"). From(Table("users")). - Where(P().Append(func(b *Builder) { + Where(P(func(b *Builder) { b.JSONPath("a", Path("b", "c", "[1]", "d"), Cast("int")) - b.WriteString(" = ") + b.WriteOp(OpEQ) b.Arg(1) })), wantQuery: `SELECT * FROM "users" WHERE CAST("a"->'b'->'c'->1->'d' AS int) = $1`,