Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Query Criteria need more information on the column #734

Open
jwoertink opened this issue Sep 30, 2021 · 0 comments
Open

Query Criteria need more information on the column #734

jwoertink opened this issue Sep 30, 2021 · 0 comments

Comments

@jwoertink
Copy link
Member

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:

PostQuery.new.posted(true)

In this example, posted() is basically

def posted
  Bool.adapter.criteria(self, "posts.posted")
end
def posted(value)
  posted.eq(value)
end

The criteria method here is basically

def criteria
  Criteria(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"])

def tags
  Array(String).adapter.criteria(self, "posts.tags")
end

def criteria
  Criteria(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.

class Criteria(T, V, *R)
  def special_array_method
    check_array(R[0]?)
  end

  def check_array(is_array : Array.class)
  end
  def check_array(is_anything_else : Nil)
    {%  raise "compile-time error" %}
  end
end

# `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.

@jwoertink jwoertink added the hacktoberfest Valid Issue for Hacktoberfest label Oct 1, 2021
@jwoertink jwoertink removed the hacktoberfest Valid Issue for Hacktoberfest label Nov 1, 2021
@jwoertink jwoertink added the hacktoberfest Valid Issue for Hacktoberfest label Oct 1, 2022
@jwoertink jwoertink removed the hacktoberfest Valid Issue for Hacktoberfest label Nov 6, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant