Skip to content

Commit

Permalink
Adds new JSON::Any criteria methods for querying jsonb columns that c…
Browse files Browse the repository at this point in the history
…ontain the ? character. Ref #197 (#1015)
  • Loading branch information
jwoertink authored Mar 23, 2024
1 parent e0ca6de commit 4dd49ea
Show file tree
Hide file tree
Showing 3 changed files with 131 additions and 0 deletions.
45 changes: 45 additions & 0 deletions spec/avram/json_criteria_spec.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
require "../spec_helper"

private class QueryMe < BaseModel
COLUMN_SQL = "users.id, users.created_at, users.updated_at, users.preferences"

table users do
column preferences : JSON::Any
end
end

describe JSON::Any::Lucky::Criteria do
describe "has_key" do
it "?" do
preferences.has_key("theme").to_sql.should eq ["SELECT #{QueryMe::COLUMN_SQL} FROM users WHERE users.preferences ? $1", "theme"]
end

it "negates with NOT()" do
preferences.not.has_key("theme").to_sql.should eq ["SELECT #{QueryMe::COLUMN_SQL} FROM users WHERE NOT(users.preferences ? $1)", "theme"]
end
end

describe "has_any_keys" do
it "?|" do
preferences.has_any_keys(["theme", "style"]).to_sql.should eq ["SELECT #{QueryMe::COLUMN_SQL} FROM users WHERE users.preferences ?| $1", ["theme", "style"]]
end

it "negates with NOT()" do
preferences.not.has_any_keys(["theme", "style"]).to_sql.should eq ["SELECT #{QueryMe::COLUMN_SQL} FROM users WHERE NOT(users.preferences ?| $1)", ["theme", "style"]]
end
end

describe "has_all_keys" do
it "?&" do
preferences.has_all_keys(["theme", "style"]).to_sql.should eq ["SELECT #{QueryMe::COLUMN_SQL} FROM users WHERE users.preferences ?& $1", ["theme", "style"]]
end

it "negates with NOT()" do
preferences.not.has_all_keys(["theme", "style"]).to_sql.should eq ["SELECT #{QueryMe::COLUMN_SQL} FROM users WHERE NOT(users.preferences ?& $1)", ["theme", "style"]]
end
end
end

private def preferences
QueryMe::BaseQuery.new.preferences
end
14 changes: 14 additions & 0 deletions src/avram/charms/json_extensions.cr
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,20 @@ struct JSON::Any
end

class Criteria(T, V) < Avram::Criteria(T, V)
# performs `WHERE jsonb ? string`
def has_key(value : String) : T
add_clause(Avram::Where::JSONHasKey.new(column, value))
end

# performs `WHERE jsonb ?| array`
def has_any_keys(keys : Array(String)) : T
add_clause(Avram::Where::JSONHasAnyKeys.new(column, keys))
end

# performs `WHERE jsonb ?& array`
def has_all_keys(keys : Array(String)) : T
add_clause(Avram::Where::JSONHasAllKeys.new(column, keys))
end
end
end
end
72 changes: 72 additions & 0 deletions src/avram/where.cr
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,78 @@ module Avram::Where
end
end

class JSONHasKey < ValueHoldingSqlClause
def operator : String
"?"
end

def negated : NotJSONHasKey
NotJSONHasKey.new(column, value)
end
end

class NotJSONHasKey < ValueHoldingSqlClause
def operator : String
"?"
end

def negated : JSONHasKey
JSONHasKey.new(column, value)
end

def prepare(placeholder_supplier : Proc(String)) : String
"NOT(#{column} #{operator} #{placeholder_supplier.call})"
end
end

class JSONHasAnyKeys < ValueHoldingSqlClause
def operator : String
"?|"
end

def negated : NotJSONHasAnyKeys
NotJSONHasAnyKeys.new(column, value)
end
end

class NotJSONHasAnyKeys < ValueHoldingSqlClause
def operator : String
"?|"
end

def negated : JSONHasAnyKeys
JSONHasAnyKeys.new(column, value)
end

def prepare(placeholder_supplier : Proc(String)) : String
"NOT(#{column} #{operator} #{placeholder_supplier.call})"
end
end

class JSONHasAllKeys < ValueHoldingSqlClause
def operator : String
"?&"
end

def negated : NotJSONHasAllKeys
NotJSONHasAllKeys.new(column, value)
end
end

class NotJSONHasAllKeys < ValueHoldingSqlClause
def operator : String
"?&"
end

def negated : JSONHasAllKeys
JSONHasAllKeys.new(column, value)
end

def prepare(placeholder_supplier : Proc(String)) : String
"NOT(#{column} #{operator} #{placeholder_supplier.call})"
end
end

class Raw < Condition
@clause : String

Expand Down

0 comments on commit 4dd49ea

Please sign in to comment.