You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When we run a query, each column method on the query object is actually an instance of Criteria. In this Criteria object, we know the name of the column, and the query object class, as well as the value to query for. The thing we don't know is what type that column is.
For example:
PostQuery.new.posted(true)
In this example, posted() is basically
defpostedBool.adapter.criteria(self, "posts.posted")
enddefposted(value)
posted.eq(value)
end
The criteria method here is basically
defcriteriaCriteria(PostQuery, Bool).new(post_query, "posts.posted")
end
We can infer that posted is Bool within the Criteria by checking that in Criteria(T, V), V is Bool. However, if we use an Array...
PostQuery.new.tags(["crystal", "lucky"])
deftagsArray(String).adapter.criteria(self, "posts.tags")
enddefcriteriaCriteria(PostQuery, String).new(post_query, "posts.tags")
end
It ends up looking like this. We run everything through the String adapter for Array(String), so now we don't really know that tags is an Array. We also have Enum, and JSON::Any which are a bit complex. If we want to start having special query methods that can only be ran on these complex types, then the Criteria needs to understand what they are, but at compile-time.
One option I tried, was to pass in "optional" generics, but it gets pretty messy.
classCriteria(T, V, *R)
defspecial_array_method
check_array(R[0]?)
enddefcheck_array(is_array : Array.class)
enddefcheck_array(is_anything_else : Nil)
{%raise"compile-time error"%}
endend# `R` is a Tuple so R[0] is `nil`Criteria(PostQuery, String)
# `R[0]` here is `Array(String)`Critera(PostQuery, String, Array(String))
The issue I ran in to here was within macro land, things got quite messy, and I was fighting the compiler the entire time when some classes said they needed the methods when they didn't.
I'm not sure if this is the right path, or if there's a better one, but if we want to start really flexing what postgres can do in queries, we will need to have a bit more control.
The text was updated successfully, but these errors were encountered:
Related: #733
Also sort of related: luckyframework/lucky#1583 (comment)
When we run a query, each column method on the query object is actually an instance of
Criteria
. In this Criteria object, we know the name of the column, and the query object class, as well as the value to query for. The thing we don't know is what type that column is.For example:
In this example,
posted()
is basicallyThe
criteria
method here is basicallyWe can infer that
posted
isBool
within the Criteria by checking that inCriteria(T, V)
,V
isBool
. However, if we use anArray
...It ends up looking like this. We run everything through the
String
adapter forArray(String)
, so now we don't really know thattags
is an Array. We also haveEnum
, andJSON::Any
which are a bit complex. If we want to start having special query methods that can only be ran on these complex types, then the Criteria needs to understand what they are, but at compile-time.One option I tried, was to pass in "optional" generics, but it gets pretty messy.
The issue I ran in to here was within macro land, things got quite messy, and I was fighting the compiler the entire time when some classes said they needed the methods when they didn't.
I'm not sure if this is the right path, or if there's a better one, but if we want to start really flexing what postgres can do in queries, we will need to have a bit more control.
The text was updated successfully, but these errors were encountered: