mirror of
https://github.com/hanzoai/sqlbuilder.git
synced 2026-10-01 00:37:42 +00:00
ignore empty values and expressions to prevent syntax error
This commit is contained in:
@@ -186,7 +186,7 @@ func (c *Cond) LTE(field string, value interface{}) string {
|
||||
|
||||
// In is used to construct the expression "field IN (value...)".
|
||||
func (c *Cond) In(field string, values ...interface{}) string {
|
||||
if len(field) == 0 {
|
||||
if len(field) == 0 || len(values) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
@@ -202,7 +202,7 @@ func (c *Cond) In(field string, values ...interface{}) string {
|
||||
|
||||
// NotIn is used to construct the expression "field NOT IN (value...)".
|
||||
func (c *Cond) NotIn(field string, values ...interface{}) string {
|
||||
if len(field) == 0 {
|
||||
if len(field) == 0 || len(values) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
@@ -369,6 +369,8 @@ func (c *Cond) NotBetween(field string, lower, upper interface{}) string {
|
||||
|
||||
// Or is used to construct the expression OR logic like "expr1 OR expr2 OR expr3".
|
||||
func (c *Cond) Or(orExpr ...string) string {
|
||||
orExpr = filterEmptyStrings(orExpr)
|
||||
|
||||
if len(orExpr) == 0 {
|
||||
return ""
|
||||
}
|
||||
@@ -392,6 +394,8 @@ func (c *Cond) Or(orExpr ...string) string {
|
||||
|
||||
// And is used to construct the expression AND logic like "expr1 AND expr2 AND expr3".
|
||||
func (c *Cond) And(andExpr ...string) string {
|
||||
andExpr = filterEmptyStrings(andExpr)
|
||||
|
||||
if len(andExpr) == 0 {
|
||||
return ""
|
||||
}
|
||||
@@ -453,7 +457,7 @@ func (c *Cond) NotExists(subquery interface{}) string {
|
||||
|
||||
// Any is used to construct the expression "field op ANY (value...)".
|
||||
func (c *Cond) Any(field, op string, values ...interface{}) string {
|
||||
if len(field) == 0 || len(op) == 0 {
|
||||
if len(field) == 0 || len(op) == 0 || len(values) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
@@ -471,7 +475,7 @@ func (c *Cond) Any(field, op string, values ...interface{}) string {
|
||||
|
||||
// All is used to construct the expression "field op ALL (value...)".
|
||||
func (c *Cond) All(field, op string, values ...interface{}) string {
|
||||
if len(field) == 0 || len(op) == 0 {
|
||||
if len(field) == 0 || len(op) == 0 || len(values) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
@@ -489,7 +493,7 @@ func (c *Cond) All(field, op string, values ...interface{}) string {
|
||||
|
||||
// Some is used to construct the expression "field op SOME (value...)".
|
||||
func (c *Cond) Some(field, op string, values ...interface{}) string {
|
||||
if len(field) == 0 || len(op) == 0 {
|
||||
if len(field) == 0 || len(op) == 0 || len(values) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
|
||||
@@ -123,7 +123,9 @@ func TestEmptyCond(t *testing.T) {
|
||||
func(cond *Cond) string { return cond.LessThan("", 123) },
|
||||
func(cond *Cond) string { return cond.LessEqualThan("", 123) },
|
||||
func(cond *Cond) string { return cond.In("", 1, 2, 3) },
|
||||
func(cond *Cond) string { return cond.In("a") },
|
||||
func(cond *Cond) string { return cond.NotIn("", 1, 2, 3) },
|
||||
func(cond *Cond) string { return cond.NotIn("a") },
|
||||
func(cond *Cond) string { return cond.Like("", "%Huan%") },
|
||||
func(cond *Cond) string { return cond.ILike("", "%Huan%") },
|
||||
func(cond *Cond) string { return cond.NotLike("", "%Huan%") },
|
||||
@@ -137,14 +139,17 @@ func TestEmptyCond(t *testing.T) {
|
||||
func(cond *Cond) string { return cond.Any("", "", 1, 2) },
|
||||
func(cond *Cond) string { return cond.Any("", ">", 1, 2) },
|
||||
func(cond *Cond) string { return cond.Any("$a", "", 1, 2) },
|
||||
func(cond *Cond) string { return cond.Any("$a", ">") },
|
||||
|
||||
func(cond *Cond) string { return cond.All("", "", 1) },
|
||||
func(cond *Cond) string { return cond.All("", ">", 1) },
|
||||
func(cond *Cond) string { return cond.All("$a", "", 1) },
|
||||
func(cond *Cond) string { return cond.All("$a", ">") },
|
||||
|
||||
func(cond *Cond) string { return cond.Some("", "", 1, 2, 3) },
|
||||
func(cond *Cond) string { return cond.Some("", ">", 1, 2, 3) },
|
||||
func(cond *Cond) string { return cond.Some("$a", "", 1, 2, 3) },
|
||||
func(cond *Cond) string { return cond.Some("$a", ">") },
|
||||
|
||||
func(cond *Cond) string { return cond.IsDistinctFrom("", 1) },
|
||||
func(cond *Cond) string { return cond.IsNotDistinctFrom("", 1) },
|
||||
|
||||
@@ -172,7 +172,6 @@ func (db *DeleteBuilder) Build() (sql string, args []interface{}) {
|
||||
// BuildWithFlavor returns compiled DELETE string and args with flavor and initial args.
|
||||
// They can be used in `DB#Query` of package `database/sql` directly.
|
||||
func (db *DeleteBuilder) BuildWithFlavor(flavor Flavor, initialArg ...interface{}) (sql string, args []interface{}) {
|
||||
|
||||
buf := newStringBuilder()
|
||||
db.injection.WriteTo(buf, deleteMarkerInit)
|
||||
|
||||
|
||||
@@ -390,9 +390,9 @@ func (sb *SelectBuilder) BuildWithFlavor(flavor Flavor, initialArg ...interface{
|
||||
buf.WriteLeadingString("JOIN ")
|
||||
buf.WriteString(sb.joinTables[i])
|
||||
|
||||
if exprs := sb.joinExprs[i]; len(exprs) > 0 {
|
||||
if exprs := filterEmptyStrings(sb.joinExprs[i]); len(exprs) > 0 {
|
||||
buf.WriteString(" ON ")
|
||||
buf.WriteStrings(sb.joinExprs[i], " AND ")
|
||||
buf.WriteStrings(exprs, " AND ")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -414,9 +414,9 @@ func (sb *SelectBuilder) BuildWithFlavor(flavor Flavor, initialArg ...interface{
|
||||
buf.WriteLeadingString("GROUP BY ")
|
||||
buf.WriteStrings(sb.groupByCols, ", ")
|
||||
|
||||
if len(sb.havingExprs) > 0 {
|
||||
if havingExprs := filterEmptyStrings(sb.havingExprs); len(havingExprs) > 0 {
|
||||
buf.WriteString(" HAVING ")
|
||||
buf.WriteStrings(sb.havingExprs, " AND ")
|
||||
buf.WriteStrings(havingExprs, " AND ")
|
||||
}
|
||||
|
||||
sb.injection.WriteTo(buf, selectMarkerAfterGroupBy)
|
||||
|
||||
@@ -75,3 +75,29 @@ func (sb *stringBuilder) Reset() {
|
||||
func (sb *stringBuilder) Grow(n int) {
|
||||
sb.builder.Grow(n)
|
||||
}
|
||||
|
||||
// filterEmptyStrings removes empty strings from ss.
|
||||
// As ss rarely contains empty strings, filterEmptyStrings tries to avoid allocation if possible.
|
||||
func filterEmptyStrings(ss []string) []string {
|
||||
emptyStrings := 0
|
||||
|
||||
for _, s := range ss {
|
||||
if len(s) == 0 {
|
||||
emptyStrings++
|
||||
}
|
||||
}
|
||||
|
||||
if emptyStrings == 0 {
|
||||
return ss
|
||||
}
|
||||
|
||||
filtered := make([]string, 0, len(ss)-emptyStrings)
|
||||
|
||||
for _, s := range ss {
|
||||
if len(s) != 0 {
|
||||
filtered = append(filtered, s)
|
||||
}
|
||||
}
|
||||
|
||||
return filtered
|
||||
}
|
||||
|
||||
@@ -260,9 +260,9 @@ func (ub *UpdateBuilder) BuildWithFlavor(flavor Flavor, initialArg ...interface{
|
||||
|
||||
ub.injection.WriteTo(buf, updateMarkerAfterUpdate)
|
||||
|
||||
if len(ub.assignments) > 0 {
|
||||
if assignments := filterEmptyStrings(ub.assignments); len(assignments) > 0 {
|
||||
buf.WriteLeadingString("SET ")
|
||||
buf.WriteStrings(ub.assignments, ", ")
|
||||
buf.WriteStrings(assignments, ", ")
|
||||
}
|
||||
|
||||
ub.injection.WriteTo(buf, updateMarkerAfterSet)
|
||||
|
||||
+7
-1
@@ -38,8 +38,14 @@ type clause struct {
|
||||
}
|
||||
|
||||
func (c *clause) Build(flavor Flavor, initialArg ...interface{}) (sql string, args []interface{}) {
|
||||
exprs := filterEmptyStrings(c.andExprs)
|
||||
|
||||
if len(exprs) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
buf := newStringBuilder()
|
||||
buf.WriteStrings(c.andExprs, " AND ")
|
||||
buf.WriteStrings(exprs, " AND ")
|
||||
sql, args = c.args.CompileWithFlavor(buf.String(), flavor, initialArg...)
|
||||
return
|
||||
}
|
||||
|
||||
+4
-4
@@ -245,10 +245,10 @@ func TestWhereClauseSharedInstances(t *testing.T) {
|
||||
|
||||
func TestEmptyWhereExpr(t *testing.T) {
|
||||
a := assert.New(t)
|
||||
var emptyExpr []string
|
||||
sb := Select("*").From("t").Where(emptyExpr...)
|
||||
ub := Update("t").Set("foo = 1").Where(emptyExpr...)
|
||||
db := DeleteFrom("t").Where(emptyExpr...)
|
||||
blankExprs := []string{"", ""}
|
||||
sb := Select("*").From("t").Where(blankExprs...)
|
||||
ub := Update("t").Set("foo = 1").Where(blankExprs...)
|
||||
db := DeleteFrom("t").Where(blankExprs...)
|
||||
|
||||
a.Equal(sb.String(), "SELECT * FROM t")
|
||||
a.Equal(ub.String(), "UPDATE t SET foo = 1")
|
||||
|
||||
Reference in New Issue
Block a user