dialect/sql: add pattern matching predicates for json values

This commit is contained in:
Gerardo Reyes
2021-08-02 17:33:13 +02:00
parent 1586d50f94
commit f9e2609e95
3 changed files with 121 additions and 0 deletions

View File

@@ -142,6 +142,39 @@ func ValueContains(column string, arg interface{}, opts ...Option) *sql.Predicat
})
}
// StrValueContains return a predicate for checking that a JSON string value
// (returned by the path) contains the given substring
func StrValueContains(column string, arg string, opts ...Option) *sql.Predicate {
return sql.P(func(b *sql.Builder) {
opts = append(opts, Unquote(true))
ValuePath(b, column, opts...)
argWithWildCard := "%" + arg + "%"
b.WriteOp(sql.OpLike).Arg(argWithWildCard)
})
}
// StrValueHasPrefix return a predicate for checking that a JSON string value
// (returned by the path) has the given substring as prefix
func StrValueHasPrefix(column string, arg string, opts ...Option) *sql.Predicate {
return sql.P(func(b *sql.Builder) {
opts = append(opts, Unquote(true))
ValuePath(b, column, opts...)
argWithWildCard := arg + "%"
b.WriteOp(sql.OpLike).Arg(argWithWildCard)
})
}
// StrValueHasSuffix return a predicate for checking that a JSON string value
// (returned by the path) has the given substring as suffix
func StrValueHasSuffix(column string, arg string, opts ...Option) *sql.Predicate {
return sql.P(func(b *sql.Builder) {
opts = append(opts, Unquote(true))
ValuePath(b, column, opts...)
argWithWildCard := "%" + arg
b.WriteOp(sql.OpLike).Arg(argWithWildCard)
})
}
// LenEQ return a predicate for checking that an array length
// of a JSON (returned by the path) is equal to the given argument.
//

View File

@@ -195,6 +195,62 @@ func TestWritePath(t *testing.T) {
wantQuery: "SELECT * FROM \"users\" WHERE (\"tags\"->'a')::jsonb @> $1",
wantArgs: []interface{}{"1"},
},
{
input: sql.Dialect(dialect.Postgres).
Select("*").
From(sql.Table("users")).
Where(sqljson.StrValueContains("a", "substr", sqljson.Path("b", "c", "[1]", "d"))),
wantQuery: `SELECT * FROM "users" WHERE "a"->'b'->'c'->1->>'d' LIKE $1`,
wantArgs: []interface{}{"%substr%"},
},
{
input: sql.Dialect(dialect.MySQL).
Select("*").
From(sql.Table("users")).
Where(sqljson.StrValueContains("a", "substr", sqljson.Path("b", "c", "[1]", "d"))),
wantQuery: "SELECT * FROM `users` WHERE JSON_UNQUOTE(JSON_EXTRACT(`a`, \"$.b.c[1].d\")) LIKE ?",
wantArgs: []interface{}{"%substr%"},
},
{
input: sql.Dialect(dialect.SQLite).
Select("*").
From(sql.Table("users")).
Where(sqljson.StrValueContains("a", "substr", sqljson.Path("b", "c", "[1]", "d"))),
wantQuery: "SELECT * FROM `users` WHERE JSON_EXTRACT(`a`, \"$.b.c[1].d\") LIKE ?",
wantArgs: []interface{}{"%substr%"},
},
{
input: sql.Dialect(dialect.Postgres).
Select("*").
From(sql.Table("users")).
Where(sqljson.StrValueHasPrefix("a", "substr", sqljson.Path("b", "c", "[1]", "d"))),
wantQuery: `SELECT * FROM "users" WHERE "a"->'b'->'c'->1->>'d' LIKE $1`,
wantArgs: []interface{}{"substr%"},
},
{
input: sql.Dialect(dialect.MySQL).
Select("*").
From(sql.Table("users")).
Where(sqljson.StrValueHasPrefix("a", "substr", sqljson.Path("b", "c", "[1]", "d"))),
wantQuery: "SELECT * FROM `users` WHERE JSON_UNQUOTE(JSON_EXTRACT(`a`, \"$.b.c[1].d\")) LIKE ?",
wantArgs: []interface{}{"substr%"},
},
{
input: sql.Dialect(dialect.Postgres).
Select("*").
From(sql.Table("users")).
Where(sqljson.StrValueHasSuffix("a", "substr", sqljson.Path("b", "c", "[1]", "d"))),
wantQuery: `SELECT * FROM "users" WHERE "a"->'b'->'c'->1->>'d' LIKE $1`,
wantArgs: []interface{}{"%substr"},
},
{
input: sql.Dialect(dialect.MySQL).
Select("*").
From(sql.Table("users")).
Where(sqljson.StrValueHasSuffix("a", "substr", sqljson.Path("b", "c", "[1]", "d"))),
wantQuery: "SELECT * FROM `users` WHERE JSON_UNQUOTE(JSON_EXTRACT(`a`, \"$.b.c[1].d\")) LIKE ?",
wantArgs: []interface{}{"%substr"},
},
}
for i, tt := range tests {
t.Run(strconv.Itoa(i), func(t *testing.T) {