Skip to content

Commit 610acc2

Browse files
authored
feature: support using path for JSON_CONTAINS (#271)
* feat: support using path for JSON_CONTAINS * chore: add function description for contains
1 parent a602643 commit 610acc2

File tree

2 files changed

+22
-3
lines changed

2 files changed

+22
-3
lines changed

json.go

+11-3
Original file line numberDiff line numberDiff line change
@@ -451,11 +451,14 @@ func JSONArrayQuery(column string) *JSONArrayExpression {
451451

452452
type JSONArrayExpression struct {
453453
column string
454+
keys []string
454455
equalsValue interface{}
455456
}
456457

457-
func (json *JSONArrayExpression) Contains(value interface{}) *JSONArrayExpression {
458+
// Contains checks if the column[keys] has contains the value given. The keys parameter is only supported for MySQL.
459+
func (json *JSONArrayExpression) Contains(value interface{}, keys ...string) *JSONArrayExpression {
458460
json.equalsValue = value
461+
json.keys = keys
459462
return json
460463
}
461464

@@ -464,9 +467,14 @@ func (json *JSONArrayExpression) Build(builder clause.Builder) {
464467
if stmt, ok := builder.(*gorm.Statement); ok {
465468
switch stmt.Dialector.Name() {
466469
case "mysql":
467-
builder.WriteString("JSON_CONTAINS (" + stmt.Quote(json.column) + ", JSON_ARRAY(")
470+
builder.WriteString("JSON_CONTAINS(" + stmt.Quote(json.column) + ",JSON_ARRAY(")
468471
builder.AddVar(stmt, json.equalsValue)
469-
builder.WriteString("))")
472+
builder.WriteByte(')')
473+
if len(json.keys) > 0 {
474+
builder.WriteByte(',')
475+
builder.AddVar(stmt, jsonQueryJoin(json.keys))
476+
}
477+
builder.WriteByte(')')
470478
case "sqlite":
471479
builder.WriteString("exists(SELECT 1 FROM json_each(" + stmt.Quote(json.column) + ") WHERE value = ")
472480
builder.AddVar(stmt, json.equalsValue)

json_test.go

+11
Original file line numberDiff line numberDiff line change
@@ -468,13 +468,20 @@ func TestJSONArrayQuery(t *testing.T) {
468468
DisplayName: "JSONArray-2",
469469
Config: datatypes.JSON("[\"c\", \"a\"]"),
470470
}
471+
cmp3 := Param{
472+
DisplayName: "JSONArray-3",
473+
Config: datatypes.JSON("{\"test\": [\"a\", \"b\"]}"),
474+
}
471475

472476
if err := DB.Create(&cmp1).Error; err != nil {
473477
t.Errorf("Failed to create param %v", err)
474478
}
475479
if err := DB.Create(&cmp2).Error; err != nil {
476480
t.Errorf("Failed to create param %v", err)
477481
}
482+
if err := DB.Create(&cmp3).Error; err != nil {
483+
t.Errorf("Failed to create param %v", err)
484+
}
478485

479486
var retSingle1 Param
480487
if err := DB.Where("id = ?", cmp2.ID).First(&retSingle1).Error; err != nil {
@@ -496,5 +503,9 @@ func TestJSONArrayQuery(t *testing.T) {
496503
}
497504
AssertEqual(t, len(retMultiple), 1)
498505

506+
if err := DB.Where(datatypes.JSONArrayQuery("config").Contains("a", "test")).Find(&retMultiple).Error; err != nil {
507+
t.Fatalf("failed to find params with json value and keys, got error %v", err)
508+
}
509+
AssertEqual(t, len(retMultiple), 1)
499510
}
500511
}

0 commit comments

Comments
 (0)