Skip to content

Commit

Permalink
feature: add Mysql&Postgres Json Like (#225)
Browse files Browse the repository at this point in the history
  • Loading branch information
wave2way authored Oct 26, 2023
1 parent 84327a5 commit aa60862
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 0 deletions.
40 changes: 40 additions & 0 deletions json.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ type JSONQueryExpression struct {
keys []string
hasKeys bool
equals bool
likes bool
equalsValue interface{}
extract bool
path string
Expand Down Expand Up @@ -142,6 +143,14 @@ func (jsonQuery *JSONQueryExpression) Equals(value interface{}, keys ...string)
return jsonQuery
}

// Likes return clause.Expression
func (jsonQuery *JSONQueryExpression) Likes(value interface{}, keys ...string) *JSONQueryExpression {
jsonQuery.keys = keys
jsonQuery.likes = true
jsonQuery.equalsValue = value
return jsonQuery
}

// Build implements clause.Expression
func (jsonQuery *JSONQueryExpression) Build(builder clause.Builder) {
if stmt, ok := builder.(*gorm.Statement); ok {
Expand Down Expand Up @@ -175,6 +184,19 @@ func (jsonQuery *JSONQueryExpression) Build(builder clause.Builder) {
stmt.AddVar(builder, jsonQuery.equalsValue)
}
}
case jsonQuery.likes:
if len(jsonQuery.keys) > 0 {
builder.WriteString("JSON_EXTRACT(")
builder.WriteQuoted(jsonQuery.column)
builder.WriteByte(',')
builder.AddVar(stmt, jsonQueryJoin(jsonQuery.keys))
builder.WriteString(") LIKE ")
if value, ok := jsonQuery.equalsValue.(bool); ok {
builder.WriteString(strconv.FormatBool(value))
} else {
stmt.AddVar(builder, jsonQuery.equalsValue)
}
}
}
case "postgres":
switch {
Expand Down Expand Up @@ -206,6 +228,24 @@ func (jsonQuery *JSONQueryExpression) Build(builder clause.Builder) {
}
builder.WriteString(") = ")

if _, ok := jsonQuery.equalsValue.(string); ok {
stmt.AddVar(builder, jsonQuery.equalsValue)
} else {
stmt.AddVar(builder, fmt.Sprint(jsonQuery.equalsValue))
}
}
case jsonQuery.likes:
if len(jsonQuery.keys) > 0 {
builder.WriteString(fmt.Sprintf("json_extract_path_text(%v::json,", stmt.Quote(jsonQuery.column)))

for idx, key := range jsonQuery.keys {
if idx > 0 {
builder.WriteByte(',')
}
stmt.AddVar(builder, key)
}
builder.WriteString(") LIKE ")

if _, ok := jsonQuery.equalsValue.(string); ok {
stmt.AddVar(builder, jsonQuery.equalsValue)
} else {
Expand Down
6 changes: 6 additions & 0 deletions json_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,12 @@ func TestJSON(t *testing.T) {
}
AssertEqual(t, results9[0].Name, users[1].Name)

var result10 UserWithJSON
if err := DB.First(&result10, datatypes.JSONQuery("attributes").Likes("%dmi%", "role")).Error; err != nil {
t.Fatalf("failed to find user with json value, got error %v", err)
}
AssertEqual(t, result10.Name, users[1].Name)

// not support for sqlite
// JSONOverlaps
//var result9 UserWithJSON
Expand Down

0 comments on commit aa60862

Please sign in to comment.