From 1e8de9a2b47e26acba38b072d3e8b42df9e9b602 Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Tue, 28 Jun 2016 14:04:27 -0300 Subject: [PATCH] Implement https://github.com/crystal-lang/crystal-db/pull/9 --- spec/driver_spec.cr | 31 +--------------- src/sqlite3/result_set.cr | 75 +++++++++++---------------------------- 2 files changed, 22 insertions(+), 84 deletions(-) diff --git a/spec/driver_spec.cr b/spec/driver_spec.cr index f966213..b42a7ce 100644 --- a/spec/driver_spec.cr +++ b/spec/driver_spec.cr @@ -25,12 +25,6 @@ def assert_single_read(rs, value_type, value) rs.move_next.should be_false end -def assert_single_read?(rs, value_type, value) - rs.move_next.should be_true - rs.read?(value_type).should eq(value) - rs.move_next.should be_false -end - def assert_filename(uri, filename) SQLite3::Connection.filename(URI.parse(uri)).should eq(filename) end @@ -77,7 +71,7 @@ describe Driver do db.scalar("select null").should be_nil db.query "select null" do |rs| - assert_single_read? rs, typeof({{value}}), nil + assert_single_read rs, typeof({{value}} || nil), nil end end end @@ -137,24 +131,6 @@ describe Driver do end end - it "gets column types" do - with_mem_db do |db| - db.exec "create table table1 (aText text, anInteger integer, aReal real, aBlob blob)" - db.exec "insert into table1 (aText, anInteger, aReal, aBlob) values ('a', 1, 1.5, X'53')" - - # sqlite is unable to get column_type information - # from the query itself without executing and getting - # actual data. - db.query "select * from table1" do |rs| - rs.move_next - rs.column_type(0).should eq(String) - rs.column_type(1).should eq(Int64) - rs.column_type(2).should eq(Float64) - rs.column_type(3).should eq(Bytes) - end - end - end - it "gets last insert row id" do with_mem_db do |db| db.exec "create table person (name string, age integer)" @@ -199,11 +175,6 @@ describe Driver do rs.move_next rs.read(Time).should eq(value) end - - db.query "select col1 from table1" do |rs| - rs.move_next - rs.read?(Time).should eq(value) - end end end diff --git a/src/sqlite3/result_set.cr b/src/sqlite3/result_set.cr index 174c403..7de5c3d 100644 --- a/src/sqlite3/result_set.cr +++ b/src/sqlite3/result_set.cr @@ -22,56 +22,43 @@ class SQLite3::ResultSet < DB::ResultSet end end - macro nilable_read_for(t) - def read?(t : {{t}}.class) : {{t}}? - if read_nil? - moving_column { nil } + def read + col = @column_index + value = + case LibSQLite3.column_type(self, col) + when Type::INTEGER + LibSQLite3.column_int64(self, col) + when Type::FLOAT + LibSQLite3.column_double(self, col) + when Type::BLOB + blob = LibSQLite3.column_blob(self, col) + bytes = LibSQLite3.column_bytes(self, col) + ptr = Pointer(UInt8).malloc(bytes) + ptr.copy_from(blob, bytes) + Bytes.new(ptr, bytes) + when Type::TEXT + String.new(LibSQLite3.column_text(self, col)) + when Type::NULL + nil else - read(t) + raise Exception.new(@statement.connection) end - end - end - - {% for t in DB::TYPES %} - nilable_read_for({{t}}) - {% end %} - - def read(t : String.class) : String - moving_column { |col| String.new(LibSQLite3.column_text(self, col)) } + @column_index += 1 + value end def read(t : Int32.class) : Int32 read(Int64).to_i32 end - def read(t : Int64.class) : Int64 - moving_column { |col| LibSQLite3.column_int64(self, col) } - end - def read(t : Float32.class) : Float32 read(Float64).to_f32 end - def read(t : Float64.class) : Float64 - moving_column { |col| LibSQLite3.column_double(self, col) } - end - - def read(t : Bytes.class) : Bytes - moving_column do |col| - blob = LibSQLite3.column_blob(self, col) - bytes = LibSQLite3.column_bytes(self, col) - ptr = Pointer(UInt8).malloc(bytes) - ptr.copy_from(blob, bytes) - Bytes.new(ptr, bytes) - end - end - def read(t : Time.class) : Time Time.parse read(String), SQLite3::DATE_FORMAT end - nilable_read_for Time - def column_count LibSQLite3.column_count(self) end @@ -80,30 +67,10 @@ class SQLite3::ResultSet < DB::ResultSet String.new LibSQLite3.column_name(self, index) end - def column_type(index : Int32) - case LibSQLite3.column_type(self, index) - when Type::INTEGER; Int64 - when Type::FLOAT ; Float64 - when Type::BLOB ; Bytes - when Type::TEXT ; String - when Type::NULL ; Nil - else - raise Exception.new(@statement.connection) - end - end - def to_unsafe @statement.to_unsafe end - private def read_nil? - column_sqlite_type == Type::NULL - end - - private def column_sqlite_type - LibSQLite3.column_type(self, @column_index) - end - # :nodoc: private def step LibSQLite3::Code.new LibSQLite3.step(@statement)