mirror of
https://gitea.invidious.io/iv-org/shard-crystal-db.git
synced 2024-08-15 00:53:32 +00:00
Statement#exec and #query require named argument for array values
This change allows to use an array as single argument for #exec and #query methods. Before it was shadowed by the *args splat overload.
This commit is contained in:
parent
1ce5d7f890
commit
550e867937
3 changed files with 263 additions and 12 deletions
|
@ -227,14 +227,14 @@ describe DB do
|
|||
db.query "query", 1, "string" { }
|
||||
db.query("query", Bytes.new(4)) { }
|
||||
db.query("query", 1, "string", FooValue.new(5)) { }
|
||||
db.query "query", [1, "string", FooValue.new(5)] { }
|
||||
db.query "query", args: [1, "string", FooValue.new(5)] { }
|
||||
|
||||
db.query("query").close
|
||||
db.query("query", 1).close
|
||||
db.query("query", 1, "string").close
|
||||
db.query("query", Bytes.new(4)).close
|
||||
db.query("query", 1, "string", FooValue.new(5)).close
|
||||
db.query("query", [1, "string", FooValue.new(5)]).close
|
||||
db.query("query", args: [1, "string", FooValue.new(5)]).close
|
||||
end
|
||||
|
||||
DB.open("bar://host") do |db|
|
||||
|
@ -244,14 +244,14 @@ describe DB do
|
|||
db.query "query", 1, "string" { }
|
||||
db.query("query", Bytes.new(4)) { }
|
||||
db.query("query", 1, "string", BarValue.new(5)) { }
|
||||
db.query "query", [1, "string", BarValue.new(5)] { }
|
||||
db.query "query", args: [1, "string", BarValue.new(5)] { }
|
||||
|
||||
db.query("query").close
|
||||
db.query("query", 1).close
|
||||
db.query("query", 1, "string").close
|
||||
db.query("query", Bytes.new(4)).close
|
||||
db.query("query", 1, "string", BarValue.new(5)).close
|
||||
db.query("query", [1, "string", BarValue.new(5)]).close
|
||||
db.query("query", args: [1, "string", BarValue.new(5)]).close
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -263,7 +263,7 @@ describe DB do
|
|||
db.exec("query", 1, "string")
|
||||
db.exec("query", Bytes.new(4))
|
||||
db.exec("query", 1, "string", FooValue.new(5))
|
||||
db.exec("query", [1, "string", FooValue.new(5)])
|
||||
db.exec("query", args: [1, "string", FooValue.new(5)])
|
||||
end
|
||||
|
||||
DB.open("bar://host") do |db|
|
||||
|
@ -273,20 +273,20 @@ describe DB do
|
|||
db.exec("query", 1, "string")
|
||||
db.exec("query", Bytes.new(4))
|
||||
db.exec("query", 1, "string", BarValue.new(5))
|
||||
db.exec("query", [1, "string", BarValue.new(5)])
|
||||
db.exec("query", args: [1, "string", BarValue.new(5)])
|
||||
end
|
||||
end
|
||||
|
||||
it "Foo and Bar drivers should not implement each other params" do
|
||||
DB.open("foo://host") do |db|
|
||||
expect_raises Exception, "FooDriver::FooStatement does not support BarValue params" do
|
||||
db.exec("query", [BarValue.new(5)])
|
||||
db.exec("query", args: [BarValue.new(5)])
|
||||
end
|
||||
end
|
||||
|
||||
DB.open("bar://host") do |db|
|
||||
expect_raises Exception, "BarDriver::BarStatement does not support FooValue params" do
|
||||
db.exec("query", [FooValue.new(5)])
|
||||
db.exec("query", args: [FooValue.new(5)])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -20,8 +20,8 @@ module DB
|
|||
end
|
||||
|
||||
# See `QueryMethods#exec`
|
||||
def exec(args : Array) : ExecResult
|
||||
statement_with_retry &.exec(args)
|
||||
def exec(*, args : Array) : ExecResult
|
||||
statement_with_retry &.exec(args: args)
|
||||
end
|
||||
|
||||
# See `QueryMethods#query`
|
||||
|
@ -35,8 +35,8 @@ module DB
|
|||
end
|
||||
|
||||
# See `QueryMethods#query`
|
||||
def query(args : Array) : ResultSet
|
||||
statement_with_retry &.query(args)
|
||||
def query(*, args : Array) : ResultSet
|
||||
statement_with_retry &.query(args: args)
|
||||
end
|
||||
|
||||
# See `QueryMethods#scalar`
|
||||
|
|
|
@ -271,5 +271,256 @@ module DB
|
|||
def scalar(query, *args)
|
||||
build(query).scalar(*args)
|
||||
end
|
||||
|
||||
# Executes a *query* and returns a `ResultSet` with the results.
|
||||
# The `ResultSet` must be closed manually.
|
||||
#
|
||||
# ```
|
||||
# result = db.query "select name from contacts where id = ?", 10
|
||||
# begin
|
||||
# if result.move_next
|
||||
# id = result.read(Int32)
|
||||
# end
|
||||
# ensure
|
||||
# result.close
|
||||
# end
|
||||
# ```
|
||||
def query(query, *, args : Array)
|
||||
build(query).query(args: args)
|
||||
end
|
||||
|
||||
# Executes a *query* and yields a `ResultSet` with the results.
|
||||
# The `ResultSet` is closed automatically.
|
||||
#
|
||||
# ```
|
||||
# db.query("select name from contacts where age > ?", 18) do |rs|
|
||||
# rs.each do
|
||||
# name = rs.read(String)
|
||||
# end
|
||||
# end
|
||||
# ```
|
||||
def query(query, *, args : Array)
|
||||
# CHECK build(query).query(args: args, &block)
|
||||
rs = query(query, args: args)
|
||||
yield rs ensure rs.close
|
||||
end
|
||||
|
||||
# Executes a *query* that expects a single row and yields a `ResultSet`
|
||||
# positioned at that first row.
|
||||
#
|
||||
# The given block must not invoke `move_next` on the yielded result set.
|
||||
#
|
||||
# Raises `DB::Error` if there were no rows, or if there were more than one row.
|
||||
#
|
||||
# ```
|
||||
# name = db.query_one "select name from contacts where id = ?", 18, &.read(String)
|
||||
# ```
|
||||
def query_one(query, *, args : Array, &block : ResultSet -> U) : U forall U
|
||||
query(query, args: args) do |rs|
|
||||
raise DB::Error.new("no rows") unless rs.move_next
|
||||
|
||||
value = yield rs
|
||||
raise DB::Error.new("more than one row") if rs.move_next
|
||||
return value
|
||||
end
|
||||
end
|
||||
|
||||
# Executes a *query* that expects a single row and returns it
|
||||
# as a tuple of the given *types*.
|
||||
#
|
||||
# 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: {String, Int32}
|
||||
# ```
|
||||
def query_one(query, *, args : Array, as types : Tuple)
|
||||
query_one(query, args: args) do |rs|
|
||||
rs.read(*types)
|
||||
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 : Array, as types : NamedTuple)
|
||||
query_one(query, args: 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*.
|
||||
#
|
||||
# Raises `DB::Error` if there were no rows, or if there were more than one row.
|
||||
#
|
||||
# ```
|
||||
# db.query_one "select name from contacts where id = ?", 1, as: String
|
||||
# ```
|
||||
def query_one(query, *, args : Array, as type : Class)
|
||||
query_one(query, args: args) do |rs|
|
||||
rs.read(type)
|
||||
end
|
||||
end
|
||||
|
||||
# Executes a *query* that expects at most a single row and yields a `ResultSet`
|
||||
# positioned at that first row.
|
||||
#
|
||||
# Returns `nil`, not invoking the block, if there were no rows.
|
||||
#
|
||||
# Raises `DB::Error` if there were more than one row
|
||||
# (this ends up invoking the block once).
|
||||
#
|
||||
# ```
|
||||
# name = db.query_one? "select name from contacts where id = ?", 18, &.read(String)
|
||||
# typeof(name) # => String | Nil
|
||||
# ```
|
||||
def query_one?(query, *, args : Array, &block : ResultSet -> U) : U? forall U
|
||||
query(query, args: args) do |rs|
|
||||
return nil unless rs.move_next
|
||||
|
||||
value = yield rs
|
||||
raise DB::Error.new("more than one row") if rs.move_next
|
||||
return value
|
||||
end
|
||||
end
|
||||
|
||||
# Executes a *query* that expects a single row and returns it
|
||||
# as a tuple of the given *types*.
|
||||
#
|
||||
# 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: {String, Int32}
|
||||
# typeof(result) # => Tuple(String, Int32) | Nil
|
||||
# ```
|
||||
def query_one?(query, *, args : Array, as types : Tuple)
|
||||
query_one?(query, args: args) do |rs|
|
||||
rs.read(*types)
|
||||
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 : Array, as types : NamedTuple)
|
||||
query_one?(query, args: 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*.
|
||||
#
|
||||
# Returns `nil` if there were no rows.
|
||||
#
|
||||
# Raises `DB::Error` if there were more than one row.
|
||||
#
|
||||
# ```
|
||||
# name = db.query_one? "select name from contacts where id = ?", 1, as: String
|
||||
# typeof(name) # => String?
|
||||
# ```
|
||||
def query_one?(query, *, args : Array, as type : Class)
|
||||
query_one?(query, args: args) do |rs|
|
||||
rs.read(type)
|
||||
end
|
||||
end
|
||||
|
||||
# Executes a *query* and yield a `ResultSet` positioned at the beginning
|
||||
# of each row, returning an array of the values of the blocks.
|
||||
#
|
||||
# ```
|
||||
# names = db.query_all "select name from contacts", &.read(String)
|
||||
# ```
|
||||
def query_all(query, *, args : Array, &block : ResultSet -> U) : Array(U) forall U
|
||||
ary = [] of U
|
||||
query_each(query, args: args) do |rs|
|
||||
ary.push(yield rs)
|
||||
end
|
||||
ary
|
||||
end
|
||||
|
||||
# Executes a *query* and returns an array where each row is
|
||||
# read as a tuple of the given *types*.
|
||||
#
|
||||
# ```
|
||||
# contacts = db.query_all "select name, age from contacts", as: {String, Int32}
|
||||
# ```
|
||||
def query_all(query, *, args : Array, as types : Tuple)
|
||||
query_all(query, args: args) do |rs|
|
||||
rs.read(*types)
|
||||
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 : Array, as types : NamedTuple)
|
||||
query_all(query, args: 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*.
|
||||
#
|
||||
# ```
|
||||
# names = db.query_all "select name from contacts", as: String
|
||||
# ```
|
||||
def query_all(query, *, args : Array, as type : Class)
|
||||
query_all(query, args: args) do |rs|
|
||||
rs.read(type)
|
||||
end
|
||||
end
|
||||
|
||||
# Executes a *query* and yields the `ResultSet` once per each row.
|
||||
# The `ResultSet` is closed automatically.
|
||||
#
|
||||
# ```
|
||||
# db.query_each "select name from contacts" do |rs|
|
||||
# puts rs.read(String)
|
||||
# end
|
||||
# ```
|
||||
def query_each(query, *, args : Array)
|
||||
query(query, args: args) do |rs|
|
||||
rs.each do
|
||||
yield rs
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Performs the `query` and returns an `ExecResult`
|
||||
def exec(query, *, args : Array)
|
||||
build(query).exec(args: args)
|
||||
end
|
||||
|
||||
# Performs the `query` and returns a single scalar value
|
||||
#
|
||||
# ```
|
||||
# puts db.scalar("SELECT MAX(name)").as(String) # => (a String)
|
||||
# ```
|
||||
def scalar(query, *, args : Array)
|
||||
build(query).scalar(args: args)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue