Allow query results to be read as named tuples directly (#56)
This commit is contained in:
parent
28b17b7dba
commit
d55a34e851
|
@ -138,6 +138,12 @@ describe DummyDriver do
|
|||
end
|
||||
end
|
||||
|
||||
it "with a named tuple" do
|
||||
with_dummy do |db|
|
||||
db.query_one("3,4", as: {a: Int64, b: Int64}).should eq({a: 3i64, b: 4i64})
|
||||
end
|
||||
end
|
||||
|
||||
it "with as, just one" do
|
||||
with_dummy do |db|
|
||||
db.query_one("3", as: Int64).should eq(3i64)
|
||||
|
@ -176,6 +182,14 @@ describe DummyDriver do
|
|||
end
|
||||
end
|
||||
|
||||
it "with as" do
|
||||
with_dummy do |db|
|
||||
value = db.query_one?("3,4", as: {a: Int64, b: Int64})
|
||||
value.should be_a(NamedTuple(a: Int64, b: Int64)?)
|
||||
value.should eq({a: 3i64, b: 4i64})
|
||||
end
|
||||
end
|
||||
|
||||
it "with as, just one" do
|
||||
with_dummy do |db|
|
||||
value = db.query_one?("3", as: Int64)
|
||||
|
@ -200,6 +214,13 @@ describe DummyDriver do
|
|||
end
|
||||
end
|
||||
|
||||
it "queries with a named tuple" do
|
||||
with_dummy do |db|
|
||||
ary = db.query_all "3,4 1,2", as: {a: Int64, b: Int64}
|
||||
ary.should eq([{a: 3, b: 4}, {a: 1, b: 2}])
|
||||
end
|
||||
end
|
||||
|
||||
it "queries with as, just one" do
|
||||
with_dummy do |db|
|
||||
ary = db.query_all "3 1", as: Int64
|
||||
|
|
|
@ -88,6 +88,21 @@ module DB
|
|||
end
|
||||
end
|
||||
|
||||
# Executes a *query* that expects a single row and returns it
|
||||
# as a named tuple of the given *types* (the keys of the named tuple
|
||||
# are not necessarily the column names).
|
||||
#
|
||||
# Raises `DB::Error` if there were no rows, or if there were more than one row.
|
||||
#
|
||||
# ```
|
||||
# db.query_one "select name, age from contacts where id = ?", 1, as: {name: String, age: Int32}
|
||||
# ```
|
||||
def query_one(query, *args, as types : NamedTuple)
|
||||
query_one(query, *args) do |rs|
|
||||
rs.read(**types)
|
||||
end
|
||||
end
|
||||
|
||||
# Executes a *query* that expects a single row
|
||||
# and returns the first column's value as the given *type*.
|
||||
#
|
||||
|
@ -141,6 +156,24 @@ module DB
|
|||
end
|
||||
end
|
||||
|
||||
# Executes a *query* that expects a single row and returns it
|
||||
# as a named tuple of the given *types* (the keys of the named tuple
|
||||
# are not necessarily the column names).
|
||||
#
|
||||
# Returns `nil` if there were no rows.
|
||||
#
|
||||
# Raises `DB::Error` if there were more than one row.
|
||||
#
|
||||
# ```
|
||||
# result = db.query_one? "select name, age from contacts where id = ?", 1, as: {age: String, name: Int32}
|
||||
# typeof(result) # => NamedTuple(age: String, name: Int32) | Nil
|
||||
# ```
|
||||
def query_one?(query, *args, as types : NamedTuple)
|
||||
query_one(query, *args) do |rs|
|
||||
rs.read(**types)
|
||||
end
|
||||
end
|
||||
|
||||
# Executes a *query* that expects a single row
|
||||
# and returns the first column's value as the given *type*.
|
||||
#
|
||||
|
@ -184,6 +217,19 @@ module DB
|
|||
end
|
||||
end
|
||||
|
||||
# Executes a *query* and returns an array where each row is
|
||||
# read as a named tuple of the given *types* (the keys of the named tuple
|
||||
# are not necessarily the column names).
|
||||
#
|
||||
# ```
|
||||
# contacts = db.query_all "select name, age from contacts", as: {name: String, age: Int32}
|
||||
# ```
|
||||
def query_all(query, *args, as types : NamedTuple)
|
||||
query_all(query, *args) do |rs|
|
||||
rs.read(**types)
|
||||
end
|
||||
end
|
||||
|
||||
# Executes a *query* and returns an array where the
|
||||
# value of each row is read as the given *type*.
|
||||
#
|
||||
|
|
|
@ -89,6 +89,11 @@ module DB
|
|||
internal_read(*types)
|
||||
end
|
||||
|
||||
# Reads the next columns and returns a named tuple of the values.
|
||||
def read(**types : Class)
|
||||
internal_read(**types)
|
||||
end
|
||||
|
||||
private def internal_read(*types : *T) forall T
|
||||
{% begin %}
|
||||
Tuple.new(
|
||||
|
@ -99,6 +104,16 @@ module DB
|
|||
{% end %}
|
||||
end
|
||||
|
||||
private def internal_read(**types : **T) forall T
|
||||
{% begin %}
|
||||
NamedTuple.new(
|
||||
{% for name, type in T %}
|
||||
{{ name }}: read({{type.instance}}),
|
||||
{% end %}
|
||||
)
|
||||
{% end %}
|
||||
end
|
||||
|
||||
# def read_blob
|
||||
# yield ... io ....
|
||||
# end
|
||||
|
|
Loading…
Reference in New Issue