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

Add alias support for: "as: Type" syntax #98

Open
girng opened this issue Feb 23, 2019 · 2 comments
Open

Add alias support for: "as: Type" syntax #98

girng opened this issue Feb 23, 2019 · 2 comments

Comments

@girng
Copy link

girng commented Feb 23, 2019

Example Code:

alias ItemTuple = {Int64, Int32, String, Int16, Int8, Int8, Int8, Int16, Int16, Float64, Float64, Int8, Int16}
db.query_all "select #{ItemQuery} from rpg_user_items where rpg_character_id = ? and user_id = ? and in_stash = 0", client.selected_characterid, client.user_id, as: ItemTuple

Result:

MySql::ResultSet#read returned a Int64. A Tuple(Int64, Int32, String, Int16, Int8, Int8, Int8, Int16, Int16, Float64, Float64, Int8, Int16) was expected.

The docs mention Class, Tuple, &.read(Type) and NamedTuple can be used:
http://crystal-lang.github.io/crystal-db/api/0.5.1/DB/QueryMethods.html#query_all%28query%2C%2Aargs%2Castypes%3ATuple%29-instance-method

def query_all(query, *args, as types : Tuple)

That error message doesn't make any sense to me because ItemTuple is a Tuple 🌊

A couple of ways around this (that might be cumbersome / redundant):

  • Just copy and paste the line and remove alias, and then use ItemTuple2
ItemTuple2 = {Int64, Int32, String, Int16, Int8, Int8, Int8, Int16, Int16, Float64, Float64, Int8, Int16}
  • Copy the Tuple literal and replace it in the query method itself..
db.query_all "select #{ItemQuery} from rpg_user_items where rpg_character_id = ? and user_id = ? and in_stash = 0", client.selected_characterid, client.user_id, as: {Int64, Int32, String, Int16, Int8, Int8, Int8, Int16, Int16, Float64, Float64, Int8, Int16}

This means now, the developer must manage/add another type in this section of code whenever they add a new column for their table (highly annoying)

  • Or, the developer can do:
db.query_all "select #{ItemQuery} from rpg_user_items where rpg_character_id = ? and user_id = ? and in_stash = 0", client.selected_characterid, client.user_id, as: ItemTuple.types

Why does the developer need to use ItemTuple.types, when ItemTuple is already an alias for the Tuple itself? It would be so much more simpler if we could just do as: ItemTuple

@straight-shoota
Copy link
Member

The difference is that #query_all expects a tuple of types. But the alias defines a tuple type instead. This is not directly obvious, because the curly braces literal can be used both and its meaning depends on the context. With the alias, ItemType is expected to be a type and thus its value is interpreted according to the type grammar.

Looking at the normalized expression and types of ItemTuple and ItemTuple2 should help explaining the difference:

alias ItemTuple = Tuple(Int64, Int32, String, Int16, Int8, Int8, Int8, Int16, Int16, Float64, Float64, Int8, Int16)
ItemTuple2      = {Int64, Int32, String, Int16, Int8, Int8, Int8, Int16, Int16, Float64, Float64, Int8, Int16}
typeof(ItemTuple)  # => Tuple(Int64, Int32, String, Int16, Int8, Int8, Int8, Int16, Int16, Float64, Float64, Int8, Int16).class
typeof(ItemTuple2) # => Tuple(Int64.class, Int32.class, String.class, Int16.class, Int8.class, Int8.class, Int8.class, Int16.class, Int16.class, Float64.class, Float64.class, Int8.class, Int16.class)

@girng
Copy link
Author

girng commented Feb 23, 2019

My mind is blown after reading the first 2 sentences, but nonetheless thanks for explaining the differences.

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

2 participants