Skip to content

Commit

Permalink
feature: implement in for sqlite databases (#276)
Browse files Browse the repository at this point in the history
* feat: implement in for sqlite databases

* chore: update method description for Contains and In
  • Loading branch information
jiazheng2 authored Nov 14, 2024
1 parent e2e91b3 commit e503f10
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 11 deletions.
32 changes: 30 additions & 2 deletions json.go
Original file line number Diff line number Diff line change
Expand Up @@ -457,15 +457,15 @@ type JSONArrayExpression struct {
equalsValue interface{}
}

// Contains checks if the column[keys] contains the value given. The keys parameter is only supported for MySQL.
// Contains checks if column[keys] contains the value given. The keys parameter is only supported for MySQL and SQLite.
func (json *JSONArrayExpression) Contains(value interface{}, keys ...string) *JSONArrayExpression {
json.contains = true
json.equalsValue = value
json.keys = keys
return json
}

// In checks if columns[keys] is in the array value given. This method is only supported for MySQL.
// In checks if columns[keys] is in the array value given. This method is only supported for MySQL and SQLite.
func (json *JSONArrayExpression) In(value interface{}, keys ...string) *JSONArrayExpression {
json.in = true
json.keys = keys
Expand Down Expand Up @@ -521,6 +521,34 @@ func (json *JSONArrayExpression) Build(builder clause.Builder) {
builder.AddVar(stmt, jsonQueryJoin(json.keys))
}
builder.WriteString(") > 0")
case json.in:
builder.WriteString("CASE WHEN json_type(")
builder.WriteQuoted(json.column)
if len(json.keys) > 0 {
builder.WriteByte(',')
builder.AddVar(stmt, jsonQueryJoin(json.keys))
}
builder.WriteString(") = 'array' THEN NOT EXISTS(SELECT 1 FROM json_each(")
builder.WriteQuoted(json.column)
if len(json.keys) > 0 {
builder.WriteByte(',')
builder.AddVar(stmt, jsonQueryJoin(json.keys))
}
builder.WriteString(") WHERE value NOT IN ")
builder.AddVar(stmt, json.equalsValue)
builder.WriteString(") ELSE ")
if len(json.keys) > 0 {
builder.WriteString("json_extract(")
}
builder.WriteQuoted(json.column)
if len(json.keys) > 0 {
builder.WriteByte(',')
builder.AddVar(stmt, jsonQueryJoin(json.keys))
builder.WriteByte(')')
}
builder.WriteString(" IN ")
builder.AddVar(stmt, json.equalsValue)
builder.WriteString(" END")
}
case "postgres":
switch {
Expand Down
16 changes: 7 additions & 9 deletions json_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -514,16 +514,14 @@ func TestJSONArrayQuery(t *testing.T) {
}
AssertEqual(t, len(retMultiple), 1)

if SupportedDriver("mysql") {
if err := DB.Where(datatypes.JSONArrayQuery("config").In([]string{"c", "a"})).Find(&retMultiple).Error; err != nil {
t.Fatalf("failed to find params with json value, got error %v", err)
}
AssertEqual(t, len(retMultiple), 1)
if err := DB.Where(datatypes.JSONArrayQuery("config").In([]string{"c", "a"})).Find(&retMultiple).Error; err != nil {
t.Fatalf("failed to find params with json value, got error %v", err)
}
AssertEqual(t, len(retMultiple), 1)

if err := DB.Where(datatypes.JSONArrayQuery("config").In([]string{"c", "d"}, "test")).Find(&retMultiple).Error; err != nil {
t.Fatalf("failed to find params with json value and keys, got error %v", err)
}
AssertEqual(t, len(retMultiple), 1)
if err := DB.Where(datatypes.JSONArrayQuery("config").In([]string{"c", "d"}, "test")).Find(&retMultiple).Error; err != nil {
t.Fatalf("failed to find params with json value and keys, got error %v", err)
}
AssertEqual(t, len(retMultiple), 1)
}
}

0 comments on commit e503f10

Please sign in to comment.