From 82f68ed6cfb9ec79bfff242ce52b7b24cf0bbd28 Mon Sep 17 00:00:00 2001 From: "Brian J. Cardiff" Date: Fri, 29 Jan 2016 17:13:22 -0300 Subject: [PATCH] arguments support --- spec/database_spec.cr | 1 + spec/driver_spec.cr | 70 ++++++++++++++++++++++++++++++--------- src/sqlite3/statement2.cr | 40 +++++++++++++++++++++- 3 files changed, 95 insertions(+), 16 deletions(-) diff --git a/spec/database_spec.cr b/spec/database_spec.cr index b37d14b..b6f2702 100644 --- a/spec/database_spec.cr +++ b/spec/database_spec.cr @@ -27,6 +27,7 @@ describe Database do end end + # pending it "executes and selects blob" do rows = with_db_old(&.execute(%(select X'53514C697465'))) row = rows[0] diff --git a/spec/driver_spec.cr b/spec/driver_spec.cr index 72bb6f1..ee6fe4a 100644 --- a/spec/driver_spec.cr +++ b/spec/driver_spec.cr @@ -14,6 +14,18 @@ def sql(s) "#{s}" end +def assert_single_read(result_set, value_type, value) + result_set.move_next.should be_true + result_set.read(value_type).should eq(value) + result_set.move_next.should be_false +end + +def assert_single_read?(result_set, value_type, value) + result_set.move_next.should be_true + result_set.read?(value_type).should eq(value) + result_set.move_next.should be_false +end + describe Driver do it "should register sqlite3 name" do DB.driver_class("sqlite3").should eq(SQLite3::Driver) @@ -30,36 +42,64 @@ describe Driver do it "executes and select {{value.id}}" do with_db do |db| result_set = db.exec("select #{sql({{value}})}") - result_set.move_next.should be_true - result_set.read(typeof({{value}})).should eq({{value}}) - result_set.move_next.should be_false + assert_single_read result_set, typeof({{value}}), {{value}} end end it "executes and select {{value.id}} as nillable" do with_db do |db| result_set = db.exec("select #{sql({{value}})}") - result_set.move_next.should be_true - result_set.read?(typeof({{value}})).should eq({{value}}) - result_set.move_next.should be_false + assert_single_read? result_set, typeof({{value}}), {{value}} end end it "executes and select nil as type of {{value.id}}" do with_db do |db| result_set = db.exec("select null") - result_set.move_next.should be_true - result_set.read?(typeof({{value}})).should be_nil - result_set.move_next.should be_false + assert_single_read? result_set, typeof({{value}}), nil end end - # it "executes with bind #{value}" do - # with_db(&.execute(%(select ?), value)).should eq([[value]]) - # end + it "executes with bind {{value.id}}" do + with_db do |db| + result_set = db.exec(%(select ?), {{value}}) + assert_single_read result_set, typeof({{value}}), {{value}} + end + end - # it "executes with bind #{value} as array" do - # with_db(&.execute(%(select ?), [value])).should eq([[value]]) - # end + it "executes with bind {{value.id}} read as nillable" do + with_db do |db| + result_set = db.exec(%(select ?), {{value}}) + assert_single_read? result_set, typeof({{value}}), {{value}} + end + end + + it "executes with bind nil as typeof {{value.id}}" do + with_db do |db| + result_set = db.exec(%(select ?), nil) + assert_single_read? result_set, typeof({{value}}), nil + end + end + + it "executes with bind {{value.id}} as array" do + with_db do |db| + result_set = db.exec(%(select ?), [{{value}}]) + assert_single_read result_set, typeof({{value}}), {{value}} + end + end {% end %} + + it "executes with named bind using symbol" do + with_db do |db| + result_set = db.exec(%(select :value), {value: "hello"}) + assert_single_read result_set, String, "hello" + end + end + + it "executes with named bind using string" do + with_db do |db| + result_set = db.exec(%(select :value), {"value": "hello"}) + assert_single_read result_set, String, "hello" + end + end end diff --git a/src/sqlite3/statement2.cr b/src/sqlite3/statement2.cr index cd4fc5f..1cb8feb 100644 --- a/src/sqlite3/statement2.cr +++ b/src/sqlite3/statement2.cr @@ -4,11 +4,49 @@ class SQLite3::Statement2 < DB::Statement # @closed = false end - def exec(*args) + protected def before_execute LibSQLite3.reset(self) + end + + protected def add_parameter(index : Int32, value) + bind_arg(index, value) + end + + protected def add_parameter(name : String, value) + converted_name = ":#{name}" + index = LibSQLite3.bind_parameter_index(self, converted_name) + raise "Unknown parameter: #{name}" if index == 0 + bind_arg(index, value) + end + + protected def execute ResultSet2.new(self) end + private def bind_arg(index, value : Nil) + check LibSQLite3.bind_null(self, index) + end + + private def bind_arg(index, value : Int32) + check LibSQLite3.bind_int(self, index, value) + end + + private def bind_arg(index, value : Int64) + check LibSQLite3.bind_int64(self, index, value) + end + + private def bind_arg(index, value : Float32) + check LibSQLite3.bind_double(self, index, value.to_f64) + end + + private def bind_arg(index, value : Float64) + check LibSQLite3.bind_double(self, index, value) + end + + private def bind_arg(index, value : String) + check LibSQLite3.bind_text(self, index, value, value.bytesize, nil) + end + private def check(code) raise Exception.new(@driver) unless code == 0 end