mirror of
https://gitea.invidious.io/iv-org/shard-crystal-sqlite3.git
synced 2024-08-15 00:53:26 +00:00
remove old code
This commit is contained in:
parent
503868f434
commit
1d52f93879
8 changed files with 26 additions and 436 deletions
27
README.md
27
README.md
|
@ -17,11 +17,30 @@ dependencies:
|
|||
### Usage
|
||||
|
||||
```crystal
|
||||
require "db"
|
||||
require "sqlite3"
|
||||
|
||||
db = SQLite3::Database.new( "data.db" )
|
||||
db.execute("select * from table") do |row|
|
||||
p row
|
||||
DB.open "sqlite3://./data.db" do |db|
|
||||
db.exec "create table contacts (name string, age integer)"
|
||||
db.exec "insert into contacts values (?, ?)", "John Doe", 30
|
||||
|
||||
args = [] of DB::Any
|
||||
args << "Sarah"
|
||||
args << 33
|
||||
db.exec "insert into contacts values (?, ?)", args
|
||||
|
||||
puts "max age:"
|
||||
puts db.scalar "select max(age) from contacts" # => 33
|
||||
|
||||
puts "contacts:"
|
||||
db.query "select name, age from contacts order by age desc" do |rs|
|
||||
puts "#{rs.column_name(0)} (#{rs.column_name(1)})"
|
||||
# => name (age)
|
||||
rs.each do
|
||||
puts "#{rs.read(String)} (#{rs.read(Int32)})"
|
||||
# => Sarah (33)
|
||||
# => John Doe (30)
|
||||
end
|
||||
end
|
||||
end
|
||||
db.close
|
||||
```
|
||||
|
|
|
@ -3,4 +3,5 @@ version: 0.1.0
|
|||
|
||||
authors:
|
||||
- Ary Borenszweig <aborenszweig@manas.com.ar>
|
||||
- Brian J. Cardiff <bcardiff@manas.com.ar>
|
||||
|
||||
|
|
|
@ -1,140 +0,0 @@
|
|||
require "./spec_helper"
|
||||
|
||||
private def with_db_old
|
||||
yield Database.new DB_FILENAME
|
||||
ensure
|
||||
File.delete(DB_FILENAME)
|
||||
end
|
||||
|
||||
describe Database do
|
||||
it "opens a database" do
|
||||
with_db_old do |db|
|
||||
File.exists?(DB_FILENAME).should be_true
|
||||
end
|
||||
end
|
||||
|
||||
[nil, 1, 1_i64, "hello", 1.5, 1.5_f32].each do |value|
|
||||
it "executes and select #{value}" do
|
||||
with_db_old(&.execute("select #{value ? value.inspect : "null"}")).should eq([[value]])
|
||||
end
|
||||
|
||||
it "executes with bind #{value}" do
|
||||
with_db_old(&.execute(%(select ?), value)).should eq([[value]])
|
||||
end
|
||||
|
||||
it "executes with bind #{value} as array" do
|
||||
with_db_old(&.execute(%(select ?), [value])).should eq([[value]])
|
||||
end
|
||||
end
|
||||
|
||||
it "executes and selects blob" do
|
||||
rows = with_db_old(&.execute(%(select X'53514C697465')))
|
||||
row = rows[0]
|
||||
cell = row[0] as Slice(UInt8)
|
||||
cell.to_a.should eq([0x53, 0x51, 0x4C, 0x69, 0x74, 0x65])
|
||||
end
|
||||
|
||||
it "executes with named bind using symbol" do
|
||||
with_db_old(&.execute(%(select :value), {value: "hello"})).should eq([["hello"]])
|
||||
end
|
||||
|
||||
it "executes with named bind using string" do
|
||||
with_db_old(&.execute(%(select :value), {"value": "hello"})).should eq([["hello"]])
|
||||
end
|
||||
|
||||
it "executes with bind blob" do
|
||||
ary = UInt8[0x53, 0x51, 0x4C, 0x69, 0x74, 0x65]
|
||||
rows = with_db_old(&.execute(%(select cast(? as BLOB)), Slice.new(ary.to_unsafe, ary.size)))
|
||||
row = rows[0]
|
||||
cell = row[0] as Slice(UInt8)
|
||||
cell.to_a.should eq(ary)
|
||||
end
|
||||
|
||||
it "gets column names" do
|
||||
Database.new(":memory:") do |db|
|
||||
db.execute "create table person (name string, age integer)"
|
||||
stmt = db.prepare("select * from person")
|
||||
stmt.columns.should eq(%w(name age))
|
||||
stmt.close
|
||||
end
|
||||
end
|
||||
|
||||
# pending
|
||||
it "gets column types" do
|
||||
Database.new(":memory:") do |db|
|
||||
db.execute "create table person (name string, age integer)"
|
||||
db.execute %(insert into person values ("foo", 10))
|
||||
stmt = db.prepare("select * from person")
|
||||
stmt.execute
|
||||
stmt.step
|
||||
stmt.types.should eq([Type::TEXT, Type::INTEGER])
|
||||
stmt.close
|
||||
end
|
||||
end
|
||||
|
||||
it "gets column by name" do
|
||||
Database.new(":memory:") do |db|
|
||||
db.execute "create table person (name string, age integer)"
|
||||
db.execute %(insert into person values ("foo", 10))
|
||||
db.query("select * from person") do |result_set|
|
||||
result_set.next.should be_true
|
||||
result_set["name"].should eq("foo")
|
||||
result_set["age"].should eq(10)
|
||||
expect_raises { result_set["lala"] }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it "gets last insert row id" do
|
||||
Database.new(":memory:") do |db|
|
||||
db.execute "create table person (name string, age integer)"
|
||||
|
||||
db.last_insert_row_id.should eq(0)
|
||||
db.execute %(insert into person values ("foo", 10))
|
||||
db.last_insert_row_id.should eq(1)
|
||||
end
|
||||
end
|
||||
|
||||
it "quotes" do
|
||||
db = Database.new(":memory:")
|
||||
db.quote("'hello'").should eq("''hello''")
|
||||
end
|
||||
|
||||
it "gets first row" do
|
||||
with_db_old(&.get_first_row(%(select 1))).should eq([1])
|
||||
end
|
||||
|
||||
it "gets first value" do
|
||||
with_db_old(&.get_first_value(%(select 1))).should eq(1)
|
||||
end
|
||||
|
||||
it "ensures statements are closed" do
|
||||
begin
|
||||
Database.new(DB_FILENAME) do |db|
|
||||
db.execute(%(create table if not exists a (i int not null, str text not null);))
|
||||
db.execute(%(insert into a (i, str) values (23, "bai bai");))
|
||||
end
|
||||
|
||||
2.times do |i|
|
||||
Database.new(DB_FILENAME) do |db|
|
||||
begin
|
||||
db.query("SELECT i, str FROM a WHERE i = ?", 23) do |rs|
|
||||
rs.next
|
||||
break
|
||||
end
|
||||
rescue e : SQLite3::Exception
|
||||
fail("Expected no exception, but got \"#{e.message}\"")
|
||||
end
|
||||
|
||||
begin
|
||||
db.execute("UPDATE a SET i = ? WHERE i = ?", 23, 23)
|
||||
rescue e : SQLite3::Exception
|
||||
fail("Expected no exception, but got \"#{e.message}\"")
|
||||
end
|
||||
end
|
||||
end
|
||||
ensure
|
||||
File.delete(DB_FILENAME)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,5 +1,7 @@
|
|||
require "./spec_helper"
|
||||
|
||||
DB_FILENAME = "./test.db"
|
||||
|
||||
def with_db(&block : DB::Database ->)
|
||||
DB.open "sqlite3:#{DB_FILENAME}", &block
|
||||
ensure
|
||||
|
|
|
@ -2,5 +2,3 @@ require "spec"
|
|||
require "../src/sqlite3"
|
||||
|
||||
include SQLite3
|
||||
|
||||
DB_FILENAME = "./test.db"
|
||||
|
|
|
@ -1,71 +0,0 @@
|
|||
# The ResultSet object encapsulates the enumerability of a query’s output.
|
||||
# It is a simple cursor over the data that the query returns.
|
||||
#
|
||||
# Typical usage is:
|
||||
#
|
||||
# ```
|
||||
# require "sqlite3"
|
||||
#
|
||||
# db = SQLite3::Database.new("foo.db")
|
||||
# stmt = db.prepare("select * from person")
|
||||
# result_set = stmt.execute
|
||||
# while result_set.next
|
||||
# p result_set.to_a
|
||||
# end
|
||||
# stmt.close
|
||||
# db.close
|
||||
# ```
|
||||
class SQLite3::ResultSet
|
||||
# :nodoc:
|
||||
def initialize(@statement)
|
||||
end
|
||||
|
||||
# Returns the number of columns.
|
||||
def column_count
|
||||
@statement.column_count
|
||||
end
|
||||
|
||||
# Returns the value of a column by index or name.
|
||||
def [](index_or_name)
|
||||
@statement[index_or_name]
|
||||
end
|
||||
|
||||
# Returns the types of the columns, an `Array(Type)`.
|
||||
def types
|
||||
@statement.types
|
||||
end
|
||||
|
||||
# Returns the names of the columns, an `Array(String)`.
|
||||
def columns
|
||||
@statement.columns
|
||||
end
|
||||
|
||||
# Advances to the next row. Returns `true` if there's a next row,
|
||||
# `false` otherwise. Must be called at least once to advance to the first
|
||||
# row.
|
||||
def next
|
||||
case @statement.step
|
||||
when LibSQLite3::Code::ROW
|
||||
true
|
||||
when LibSQLite3::Code::DONE
|
||||
false
|
||||
else
|
||||
raise Exception.new(@db)
|
||||
end
|
||||
end
|
||||
|
||||
# Closes this result set, closing the associated statement.
|
||||
def close
|
||||
@statement.close
|
||||
end
|
||||
|
||||
# Returns `true` if the associated statement is closed.
|
||||
def closed?
|
||||
@statement.closed?
|
||||
end
|
||||
|
||||
# Return the current row's value as an `Array(Value)`.
|
||||
def to_a
|
||||
Array(Value).new(column_count) { |i| self[i] }
|
||||
end
|
||||
end
|
|
@ -1,215 +0,0 @@
|
|||
# A statement represents a prepared-but-unexecuted SQL query.
|
||||
class SQLite3::Statement
|
||||
# :nodoc:
|
||||
def initialize(@db, sql)
|
||||
check LibSQLite3.prepare_v2(@db, sql, sql.bytesize + 1, out @stmt, nil)
|
||||
@closed = false
|
||||
end
|
||||
|
||||
# :nodoc:
|
||||
def self.new(db, sql)
|
||||
statement = new db, sql
|
||||
begin
|
||||
yield statement
|
||||
ensure
|
||||
statement.close
|
||||
end
|
||||
end
|
||||
|
||||
# :nodoc:
|
||||
def step
|
||||
LibSQLite3::Code.new LibSQLite3.step(self)
|
||||
end
|
||||
|
||||
# Returns the number of columns in this statement.
|
||||
def column_count
|
||||
LibSQLite3.column_count(self)
|
||||
end
|
||||
|
||||
# Returns the `Type` of the column at the given index.
|
||||
def column_type(index : Int)
|
||||
LibSQLite3.column_type(self, index)
|
||||
end
|
||||
|
||||
# Returns the name of the column at the given index.
|
||||
def column_name(index)
|
||||
String.new LibSQLite3.column_name(self, index)
|
||||
end
|
||||
|
||||
# Executes this statement with the given binds and returns a `ResultSet`.
|
||||
def execute(*binds)
|
||||
execute binds
|
||||
end
|
||||
|
||||
# Executes this statement with the given binds and yields a `ResultSet` that
|
||||
# will be closed at the end of the block.
|
||||
def execute(*binds)
|
||||
execute(binds) do |row|
|
||||
yield row
|
||||
end
|
||||
end
|
||||
|
||||
# Executes this statement with a single BLOB bind and returns a `ResultSet`.
|
||||
def execute(binds : Slice(UInt8))
|
||||
reset
|
||||
self[1] = binds
|
||||
ResultSet.new self
|
||||
end
|
||||
|
||||
# Executes this statement with the given binds and returns a `ResultSet`.
|
||||
def execute(binds : Enumerable)
|
||||
reset
|
||||
# TODO use offset after Crystal 0.6.2
|
||||
binds.each_with_index do |bind_value, index|
|
||||
self[index + 1] = bind_value
|
||||
end
|
||||
ResultSet.new self
|
||||
end
|
||||
|
||||
# Executes this statement with the given binds and yields a `ResultSet` that
|
||||
# will be closed at the end of the block.
|
||||
def execute(binds : Enumerable | Slice(UInt8), &block)
|
||||
result_set = execute(binds)
|
||||
yield result_set
|
||||
ensure
|
||||
close
|
||||
end
|
||||
|
||||
# Returns the value of the given column by index (1-based).
|
||||
def [](index : Int)
|
||||
case type = column_type(index)
|
||||
when Type::INTEGER
|
||||
column_int64(index)
|
||||
when Type::FLOAT
|
||||
column_double(index)
|
||||
when Type::TEXT
|
||||
String.new(column_text(index))
|
||||
when Type::BLOB
|
||||
blob = column_blob(index)
|
||||
bytes = column_bytes(index)
|
||||
ptr = Pointer(UInt8).malloc(bytes)
|
||||
ptr.copy_from(blob, bytes)
|
||||
Slice.new(ptr, bytes)
|
||||
when Type::NULL
|
||||
nil
|
||||
else
|
||||
raise "Unknown column type: #{type}"
|
||||
end
|
||||
end
|
||||
|
||||
# Returns the value of the given column by name.
|
||||
def [](name : String)
|
||||
column_count.times do |i|
|
||||
if column_name(i) == name
|
||||
return self[i]
|
||||
end
|
||||
end
|
||||
raise "Unknown column: #{name}"
|
||||
end
|
||||
|
||||
# Binds the parameter at the given index to an Int.
|
||||
def []=(index : Int, value : Nil)
|
||||
check LibSQLite3.bind_null(self, index)
|
||||
end
|
||||
|
||||
# Binds the parameter at the given index to an Int32.
|
||||
def []=(index : Int, value : Int32)
|
||||
check LibSQLite3.bind_int(self, index, value)
|
||||
end
|
||||
|
||||
# Binds the parameter at the given index to an Int64.
|
||||
def []=(index : Int, value : Int64)
|
||||
check LibSQLite3.bind_int64(self, index, value)
|
||||
end
|
||||
|
||||
# Binds the parameter at the given index to a Float.
|
||||
def []=(index : Int, value : Float)
|
||||
check LibSQLite3.bind_double(self, index, value.to_f64)
|
||||
end
|
||||
|
||||
# Binds the parameter at the given index to a String.
|
||||
def []=(index : Int, value : String)
|
||||
check LibSQLite3.bind_text(self, index, value, value.bytesize, nil)
|
||||
end
|
||||
|
||||
# Binds the parameter at the given index to a BLOB.
|
||||
def []=(index : Int, value : Slice(UInt8))
|
||||
check LibSQLite3.bind_blob(self, index, value, value.size, nil)
|
||||
end
|
||||
|
||||
# Binds a named parameter, using the `:AAAA` naming scheme for parameters.
|
||||
def []=(name : String | Symbol, value)
|
||||
converted_name = ":#{name}"
|
||||
index = LibSQLite3.bind_parameter_index(self, converted_name)
|
||||
if index == 0
|
||||
raise "Unknown parameter: #{name}"
|
||||
end
|
||||
self[index] = value
|
||||
end
|
||||
|
||||
# Binds a hash to this statement (the `index` is ignored).
|
||||
def []=(index : Int, hash : Hash)
|
||||
hash.each do |key, value|
|
||||
self[key] = value
|
||||
end
|
||||
end
|
||||
|
||||
# Returns the column names of this statement.
|
||||
def columns
|
||||
Array.new(column_count) { |i| column_name(i) }
|
||||
end
|
||||
|
||||
# Returns an `Array(Type)` of this statement's columns. Note that the statement
|
||||
# must be executed in order for this to return sensible values, otherwise all types
|
||||
# will be NULL.
|
||||
def types
|
||||
Array.new(column_count) { |i| column_type(i) }
|
||||
end
|
||||
|
||||
# Reset this statment, allowing to re-execute it with new binds.
|
||||
def reset
|
||||
LibSQLite3.reset(self)
|
||||
end
|
||||
|
||||
# Closes this statement.
|
||||
def close
|
||||
raise "Statement already closed" if @closed
|
||||
@closed = true
|
||||
|
||||
check LibSQLite3.finalize(self)
|
||||
end
|
||||
|
||||
# Returns `true` if this statement is closed. See `#close`.
|
||||
def closed?
|
||||
@closed
|
||||
end
|
||||
|
||||
# :nodoc:
|
||||
def to_unsafe
|
||||
@stmt
|
||||
end
|
||||
|
||||
private def column_int64(index)
|
||||
LibSQLite3.column_int64(self, index)
|
||||
end
|
||||
|
||||
private def column_double(index)
|
||||
LibSQLite3.column_double(self, index)
|
||||
end
|
||||
|
||||
private def column_text(index)
|
||||
LibSQLite3.column_text(self, index)
|
||||
end
|
||||
|
||||
private def column_blob(index)
|
||||
LibSQLite3.column_blob(self, index)
|
||||
end
|
||||
|
||||
private def column_bytes(index)
|
||||
LibSQLite3.column_bytes(self, index)
|
||||
end
|
||||
|
||||
private def check(code)
|
||||
raise Exception.new(@db) unless code == 0
|
||||
end
|
||||
end
|
|
@ -1,4 +0,0 @@
|
|||
module SQLite3
|
||||
# All possible values of each column of a row returned by `Database#execute`.
|
||||
alias Value = Nil | Int64 | Float64 | String | Slice(UInt8)
|
||||
end
|
Loading…
Reference in a new issue