do_sqlite3 0.2.5 → 0.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +2 -2
- data/Rakefile +46 -25
- data/TODO +4 -0
- data/ext/do_sqlite3_ext.c +538 -0
- data/ext/extconf.rb +28 -4
- data/lib/do_sqlite3.rb +4 -209
- data/lib/do_sqlite3/transaction.rb +36 -0
- data/spec/integration/do_sqlite3_spec.rb +244 -0
- data/spec/integration/logging_spec.rb +47 -0
- data/spec/integration/quoting_spec.rb +19 -0
- data/spec/spec_helper.rb +47 -0
- data/spec/unit/transaction_spec.rb +34 -0
- metadata +60 -48
- data/ext/sqlite3_c.c +0 -4725
- data/ext/sqlite_c.i +0 -168
data/ext/extconf.rb
CHANGED
@@ -1,11 +1,35 @@
|
|
1
|
-
ENV["RC_ARCHS"] = `uname -m`.chomp if `uname -sr` =~ /^Darwin/
|
1
|
+
# ENV["RC_ARCHS"] = `uname -m`.chomp if `uname -sr` =~ /^Darwin/
|
2
|
+
#
|
3
|
+
# require 'mkmf'
|
4
|
+
#
|
5
|
+
# SWIG_WRAP = "sqlite3_api_wrap.c"
|
6
|
+
#
|
7
|
+
# dir_config( "sqlite3", "/usr/local" )
|
8
|
+
#
|
9
|
+
# if have_header( "sqlite3.h" ) && have_library( "sqlite3", "sqlite3_open" )
|
10
|
+
# create_makefile( "sqlite3_c" )
|
11
|
+
# end
|
2
12
|
|
13
|
+
if RUBY_PLATFORM =~ /darwin/
|
14
|
+
ENV["RC_ARCHS"] = `uname -m`.chomp if `uname -sr` =~ /^Darwin/
|
15
|
+
|
16
|
+
# On PowerPC the defaults are fine
|
17
|
+
ENV["RC_ARCHS"] = '' if `uname -m` =~ /^Power Macintosh/
|
18
|
+
end
|
19
|
+
|
20
|
+
# Loads mkmf which is used to make makefiles for Ruby extensions
|
3
21
|
require 'mkmf'
|
4
22
|
|
5
|
-
|
23
|
+
# Give it a name
|
24
|
+
extension_name = 'do_sqlite3_ext'
|
25
|
+
|
26
|
+
dir_config("sqlite3")
|
6
27
|
|
7
|
-
|
28
|
+
# NOTE: use GCC flags unless Visual C compiler is used
|
29
|
+
$CFLAGS << ' -Wall ' unless RUBY_PLATFORM =~ /mswin/
|
8
30
|
|
31
|
+
# Do the work
|
32
|
+
# create_makefile(extension_name)
|
9
33
|
if have_header( "sqlite3.h" ) && have_library( "sqlite3", "sqlite3_open" )
|
10
|
-
create_makefile(
|
34
|
+
create_makefile(extension_name)
|
11
35
|
end
|
data/lib/do_sqlite3.rb
CHANGED
@@ -1,210 +1,5 @@
|
|
1
|
-
require 'sqlite3_c'
|
2
|
-
require 'data_objects'
|
3
|
-
|
4
|
-
module DataObject
|
5
|
-
module Sqlite3
|
6
|
-
|
7
|
-
QUOTE_STRING = "\""
|
8
|
-
QUOTE_COLUMN = "'"
|
9
|
-
|
10
|
-
class Connection < DataObject::Connection
|
11
|
-
|
12
|
-
attr_reader :db
|
13
|
-
|
14
|
-
def initialize(connection_string)
|
15
|
-
@state = STATE_CLOSED
|
16
|
-
@connection_string = connection_string
|
17
|
-
@conn = Hash[*connection_string.split(" ").map {|x| x.split("=")}.flatten]["dbname"]
|
18
|
-
end
|
19
|
-
|
20
|
-
def open
|
21
|
-
r, d = Sqlite3_c.sqlite3_open(@conn)
|
22
|
-
unless r == Sqlite3_c::SQLITE_OK
|
23
|
-
raise ConnectionFailed, "Unable to connect to database with provided connection string. \n#{Sqlite3_c.sqlite3_errmsg(d)}"
|
24
|
-
else
|
25
|
-
@db = d
|
26
|
-
end
|
27
|
-
@state = STATE_OPEN
|
28
|
-
true
|
29
|
-
end
|
30
|
-
|
31
|
-
def close
|
32
|
-
Sqlite3_c.sqlite3_close(@db)
|
33
|
-
@state = STATE_CLOSED
|
34
|
-
true
|
35
|
-
end
|
36
|
-
|
37
|
-
def create_command(text)
|
38
|
-
Command.new(self, text)
|
39
|
-
end
|
40
|
-
|
41
|
-
def begin_transaction
|
42
|
-
Transaction.new(self)
|
43
|
-
end
|
44
|
-
|
45
|
-
end
|
46
|
-
|
47
|
-
class Transaction < DataObject::Transaction
|
48
|
-
|
49
|
-
attr_reader :connection
|
50
|
-
|
51
|
-
def initialize(conn)
|
52
|
-
@connection = conn
|
53
|
-
exec_sql("BEGIN")
|
54
|
-
end
|
55
1
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
# Rolls back the transaction
|
62
|
-
def rollback(savepoint = nil)
|
63
|
-
raise NotImplementedError, "SQLite3 does not support savepoints" if savepoint
|
64
|
-
exec_sql("ROLLBACK")
|
65
|
-
end
|
66
|
-
|
67
|
-
# Creates a savepoint for rolling back later (not commonly supported)
|
68
|
-
def save(name)
|
69
|
-
raise NotImplementedError, "SQLite3 does not support savepoints"
|
70
|
-
end
|
71
|
-
|
72
|
-
def create_command(*args)
|
73
|
-
@connection.create_command(*args)
|
74
|
-
end
|
75
|
-
|
76
|
-
protected
|
77
|
-
|
78
|
-
def exec_sql(sql)
|
79
|
-
@connection.logger.debug { sql }
|
80
|
-
result, reader = Sqlite3_c.sqlite3_prepare_v2(@connection.db, sql, sql.size + 1)
|
81
|
-
exec_result = Sqlite3_c.sqlite3_step(reader)
|
82
|
-
Sqlite3_c.sqlite3_finalize(reader)
|
83
|
-
exec_result
|
84
|
-
end
|
85
|
-
|
86
|
-
end
|
87
|
-
|
88
|
-
class Reader < DataObject::Reader
|
89
|
-
|
90
|
-
def initialize(db, reader)
|
91
|
-
@reader = reader
|
92
|
-
result = Sqlite3_c.sqlite3_step(reader)
|
93
|
-
rows_affected, field_count = Sqlite3_c.sqlite3_changes(db), Sqlite3_c.sqlite3_column_count(reader)
|
94
|
-
if field_count == 0
|
95
|
-
@records_affected = rows_affected
|
96
|
-
close
|
97
|
-
else
|
98
|
-
@field_count = field_count
|
99
|
-
@fields, @field_types = [], []
|
100
|
-
i = 0
|
101
|
-
while(i < @field_count)
|
102
|
-
@field_types.push(Sqlite3_c.sqlite3_column_type(reader, i))
|
103
|
-
@fields.push(Sqlite3_c.sqlite3_column_name(reader, i))
|
104
|
-
i += 1
|
105
|
-
end
|
106
|
-
case result
|
107
|
-
when Sqlite3_c::SQLITE_BUSY, Sqlite3_c::SQLITE_ERROR, Sqlite3_c::SQLITE_MISUSE
|
108
|
-
raise ReaderError, "An error occurred while trying to get the next row\n#{Sqlite3_c.sqlite3_errmsg(db)}"
|
109
|
-
else
|
110
|
-
@has_rows = result == Sqlite3_c::SQLITE_ROW
|
111
|
-
@state = STATE_OPEN
|
112
|
-
close unless @has_rows
|
113
|
-
end
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
def real_close
|
118
|
-
Sqlite3_c.sqlite3_finalize(@reader)
|
119
|
-
end
|
120
|
-
|
121
|
-
def name(idx)
|
122
|
-
super
|
123
|
-
@fields[idx]
|
124
|
-
end
|
125
|
-
|
126
|
-
def get_index(name)
|
127
|
-
super
|
128
|
-
@fields.index(name)
|
129
|
-
end
|
130
|
-
|
131
|
-
def null?(idx)
|
132
|
-
super
|
133
|
-
item(idx).nil?
|
134
|
-
end
|
135
|
-
|
136
|
-
def item(idx)
|
137
|
-
super
|
138
|
-
case @field_types[idx]
|
139
|
-
when 1 # SQLITE_INTEGER
|
140
|
-
Sqlite3_c.sqlite3_column_int(@reader, idx).to_i
|
141
|
-
when 2 # SQLITE_FLOAT
|
142
|
-
Sqlite3_c.sqlite3_column_double(@reader, idx)
|
143
|
-
else
|
144
|
-
Sqlite3_c.sqlite3_column_text(@reader, idx)
|
145
|
-
end
|
146
|
-
end
|
147
|
-
|
148
|
-
def each
|
149
|
-
return unless has_rows?
|
150
|
-
|
151
|
-
while(true) do
|
152
|
-
yield
|
153
|
-
break unless Sqlite3_c.sqlite3_step(@reader) == Sqlite3_c::SQLITE_ROW
|
154
|
-
end
|
155
|
-
end
|
156
|
-
|
157
|
-
end
|
158
|
-
|
159
|
-
class Command < DataObject::Command
|
160
|
-
|
161
|
-
def execute_reader(*args)
|
162
|
-
super
|
163
|
-
sql = escape_sql(args)
|
164
|
-
@connection.logger.debug { sql }
|
165
|
-
result, ptr = Sqlite3_c.sqlite3_prepare_v2(@connection.db, sql, sql.size + 1)
|
166
|
-
unless result == Sqlite3_c::SQLITE_OK
|
167
|
-
raise QueryError, "Your query failed.\n#{Sqlite3_c.sqlite3_errmsg(@connection.db)}\nQUERY: \"#{sql}\""
|
168
|
-
else
|
169
|
-
reader = Reader.new(@connection.db, ptr)
|
170
|
-
|
171
|
-
if block_given?
|
172
|
-
return_value = yield(reader)
|
173
|
-
reader.close
|
174
|
-
return_value
|
175
|
-
else
|
176
|
-
reader
|
177
|
-
end
|
178
|
-
end
|
179
|
-
end
|
180
|
-
|
181
|
-
def execute_non_query(*args)
|
182
|
-
super
|
183
|
-
sql = escape_sql(args)
|
184
|
-
@connection.logger.debug { sql }
|
185
|
-
result, reader = Sqlite3_c.sqlite3_prepare_v2(@connection.db, sql, -1)
|
186
|
-
unless result == Sqlite3_c::SQLITE_OK
|
187
|
-
Sqlite3_c.sqlite3_finalize(reader)
|
188
|
-
raise QueryError, "Your query failed.\n#{Sqlite3_c.sqlite3_errmsg(@connection.db)}\nQUERY: \"#{sql}\""
|
189
|
-
else
|
190
|
-
exec_result = Sqlite3_c.sqlite3_step(reader)
|
191
|
-
Sqlite3_c.sqlite3_finalize(reader)
|
192
|
-
if exec_result == Sqlite3_c::SQLITE_DONE
|
193
|
-
ResultData.new(@connection, Sqlite3_c.sqlite3_changes(@connection.db), Sqlite3_c.sqlite3_last_insert_rowid(@connection.db))
|
194
|
-
else
|
195
|
-
raise QueryError, "Your query failed or you tried to execute a SELECT query through execute_non_reader\n#{Sqlite3_c.sqlite3_errmsg(@connection.db)}\nQUERY: \"#{@text}\""
|
196
|
-
end
|
197
|
-
end
|
198
|
-
end
|
199
|
-
|
200
|
-
def quote_symbol(value)
|
201
|
-
value.to_s
|
202
|
-
end
|
203
|
-
|
204
|
-
def quote_boolean(value)
|
205
|
-
value ? '1' : '0'
|
206
|
-
end
|
207
|
-
end
|
208
|
-
|
209
|
-
end
|
210
|
-
end
|
2
|
+
require 'rubygems'
|
3
|
+
require 'data_objects'
|
4
|
+
require 'do_sqlite3_ext'
|
5
|
+
require 'do_sqlite3/transaction'
|
@@ -0,0 +1,36 @@
|
|
1
|
+
|
2
|
+
module DataObjects
|
3
|
+
|
4
|
+
module Sqlite3
|
5
|
+
|
6
|
+
class Transaction < DataObjects::Transaction
|
7
|
+
|
8
|
+
def begin
|
9
|
+
cmd = "BEGIN"
|
10
|
+
connection.create_command(cmd).execute_non_query
|
11
|
+
end
|
12
|
+
|
13
|
+
def commit
|
14
|
+
cmd = "COMMIT"
|
15
|
+
connection.create_command(cmd).execute_non_query
|
16
|
+
end
|
17
|
+
|
18
|
+
def rollback
|
19
|
+
cmd = "ROLLBACK"
|
20
|
+
connection.create_command(cmd).execute_non_query
|
21
|
+
end
|
22
|
+
|
23
|
+
def rollback_prepared
|
24
|
+
cmd = "ROLLBACK"
|
25
|
+
connection.create_command(cmd).execute_non_query
|
26
|
+
end
|
27
|
+
|
28
|
+
def prepare
|
29
|
+
# Eek, I don't know how to do this. Lets hope a commit arrives soon...
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
@@ -0,0 +1,244 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require Pathname(__FILE__).dirname.expand_path.parent + 'spec_helper'
|
3
|
+
|
4
|
+
describe "DataObjects::Sqlite3" do
|
5
|
+
include Sqlite3SpecHelpers
|
6
|
+
|
7
|
+
it "should raise error on bad connection string" do
|
8
|
+
lambda { DataObjects::Connection.new("sqlite3:///ac0d9iopalmsdcasd/asdc9pomasd/test.db") }.should raise_error("unable to open database file")
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
NOW = DateTime.now
|
13
|
+
|
14
|
+
describe "DataObjects::Sqlite3::Result" do
|
15
|
+
include Sqlite3SpecHelpers
|
16
|
+
|
17
|
+
before(:all) do
|
18
|
+
@connection = DataObjects::Connection.new("sqlite3://#{File.expand_path(File.dirname(__FILE__))}/test.db")
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should raise an error for a bad query" do
|
22
|
+
command = @connection.create_command("INSER INTO table_which_doesnt_exist (id) VALUES (1)")
|
23
|
+
lambda { command.execute_non_query }.should raise_error('near "INSER": syntax error')
|
24
|
+
|
25
|
+
command = @connection.create_command("INSERT INTO table_which_doesnt_exist (id) VALUES (1)")
|
26
|
+
lambda { command.execute_non_query }.should raise_error("no such table: table_which_doesnt_exist")
|
27
|
+
|
28
|
+
command = @connection.create_command("SELECT * FROM table_which_doesnt_exist")
|
29
|
+
lambda { command.execute_reader }.should raise_error("no such table: table_which_doesnt_exist")
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should return the affected rows and insert_id" do
|
33
|
+
command = @connection.create_command("DROP TABLE users")
|
34
|
+
command.execute_non_query rescue nil
|
35
|
+
command = @connection.create_command("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, type TEXT, age INTEGER, created_at DATETIME, balance DECIMAL default '0.00')")
|
36
|
+
result = command.execute_non_query
|
37
|
+
command = @connection.create_command("INSERT INTO users (name) VALUES ('test')")
|
38
|
+
result = command.execute_non_query
|
39
|
+
result.insert_id.should == 1
|
40
|
+
result.to_i.should == 1
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should do a reader query" do
|
44
|
+
command = @connection.create_command("SELECT * FROM users")
|
45
|
+
reader = command.execute_reader
|
46
|
+
|
47
|
+
lambda { reader.values }.should raise_error
|
48
|
+
|
49
|
+
while ( reader.next! )
|
50
|
+
lambda { reader.values }.should_not raise_error
|
51
|
+
reader.values.should be_a_kind_of(Array)
|
52
|
+
end
|
53
|
+
|
54
|
+
lambda { reader.values }.should raise_error
|
55
|
+
|
56
|
+
reader.close
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should do a paramaterized reader query" do
|
60
|
+
command = @connection.create_command("SELECT * FROM users WHERE id = ?")
|
61
|
+
reader = command.execute_reader(1)
|
62
|
+
reader.next!
|
63
|
+
|
64
|
+
reader.values[0].should == 1
|
65
|
+
|
66
|
+
reader.next!
|
67
|
+
|
68
|
+
lambda { reader.values }.should raise_error
|
69
|
+
|
70
|
+
reader.close
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should do a custom typecast reader" do
|
74
|
+
command = @connection.create_command("SELECT name, id FROM users")
|
75
|
+
command.set_types [String, String]
|
76
|
+
reader = command.execute_reader
|
77
|
+
|
78
|
+
while ( reader.next! )
|
79
|
+
reader.fields.should == ["name", "id"]
|
80
|
+
reader.values.each { |v| v.should be_a_kind_of(String) }
|
81
|
+
end
|
82
|
+
|
83
|
+
reader.close
|
84
|
+
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should handle a null value" do
|
88
|
+
id = insert("INSERT INTO users (name) VALUES (NULL)")
|
89
|
+
select("SELECT name from users WHERE name is null") do |reader|
|
90
|
+
reader.values[0].should == nil
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should not convert empty strings to null" do
|
95
|
+
id = insert("INSERT INTO users (name) VALUES ('')")
|
96
|
+
select("SELECT name FROM users WHERE id = ?", [String], id) do |reader|
|
97
|
+
reader.values.first.should == ''
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
it "should raise an error when you pass too many or too few types for the expected result set" do
|
102
|
+
lambda { select("SELECT name, id FROM users", [String, Integer, String]) }.should raise_error(Sqlite3Error)
|
103
|
+
end
|
104
|
+
|
105
|
+
it "should do a custom typecast reader with Class" do
|
106
|
+
class Person; end
|
107
|
+
|
108
|
+
id = insert("INSERT INTO users (name, age, type) VALUES (?, ?, ?)", 'Sam', 30, Person)
|
109
|
+
|
110
|
+
select("SELECT name, age, type FROM users WHERE id = ?", [String, Integer, Class], id) do |reader|
|
111
|
+
reader.fields.should == ["name", "age", "type"]
|
112
|
+
reader.values.should == ["Sam", 30, Person]
|
113
|
+
end
|
114
|
+
|
115
|
+
exec("DELETE FROM users WHERE id = ?", id)
|
116
|
+
end
|
117
|
+
|
118
|
+
[
|
119
|
+
NOW.strftime('%Y-%m-%dT%H:%M:%S'),
|
120
|
+
NOW.strftime('%Y-%m-%d %H:%M:%S')
|
121
|
+
].each do |raw_value|
|
122
|
+
it "should return #{NOW.to_s} using the LOCAL timezone when typecasting '#{raw_value}'" do
|
123
|
+
|
124
|
+
# Insert a timezone-less DateTime into the DB
|
125
|
+
id = insert("INSERT INTO users (name, age, type, created_at) VALUES (?, ?, ?, ?)", 'Sam', 30, Person, raw_value)
|
126
|
+
|
127
|
+
select("SELECT created_at FROM users WHERE id = ?", [DateTime], id) do |reader|
|
128
|
+
reader.values.last.to_s.should == NOW.to_s
|
129
|
+
end
|
130
|
+
|
131
|
+
exec("DELETE FROM users WHERE id = ?", id)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
it "should return DateTimes using the same timezone that was used to insert it" do
|
136
|
+
pending "improved support for timezone checking"
|
137
|
+
|
138
|
+
dates = [
|
139
|
+
NOW,
|
140
|
+
NOW.new_offset( (-11 * 3600).to_r / 86400), # GMT -11:00
|
141
|
+
NOW.new_offset( (-9 * 3600 + 10 * 60).to_r / 86400), # GMT -9:10
|
142
|
+
NOW.new_offset( (-8 * 3600).to_r / 86400), # GMT -08:00
|
143
|
+
NOW.new_offset( (+3 * 3600).to_r / 86400), # GMT +03:00
|
144
|
+
NOW.new_offset( (+5 * 3600 + 30 * 60).to_r / 86400) # GMT +05:30 (New Delhi)
|
145
|
+
]
|
146
|
+
|
147
|
+
dates.each do |date|
|
148
|
+
id = insert("INSERT INTO users (name, age, type, created_at) VALUES (?, ?, ?, ?)", 'Sam', 30, Person, date)
|
149
|
+
|
150
|
+
select("SELECT created_at FROM users WHERE id = ?", [DateTime], id) do |reader|
|
151
|
+
reader.values.last.year.should == date.year
|
152
|
+
reader.values.last.month.should == date.month
|
153
|
+
reader.values.last.day.should == date.day
|
154
|
+
reader.values.last.hour.should == date.hour
|
155
|
+
reader.values.last.min.should == date.min
|
156
|
+
reader.values.last.sec.should == date.sec
|
157
|
+
reader.values.last.zone.should == date.zone
|
158
|
+
end
|
159
|
+
|
160
|
+
exec("DELETE FROM users WHERE id = ?", id)
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
it "should return a BigDecimal" do
|
165
|
+
balance = BigDecimal.new('10000000000.00')
|
166
|
+
|
167
|
+
id = insert("INSERT INTO users (name, age, type, created_at, balance) VALUES (?, ?, ?, ?, ?)", 'Scott', 27, Person, DateTime.now, balance)
|
168
|
+
|
169
|
+
select("SELECT balance FROM users WHERE id = ?", [BigDecimal], id) do |reader|
|
170
|
+
reader.values.last.should == balance
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
describe "quoting" do
|
175
|
+
|
176
|
+
before do
|
177
|
+
@connection.create_command("DROP TABLE IF EXISTS sail_boats").execute_non_query
|
178
|
+
@connection.create_command("CREATE TABLE sail_boats ( id INTEGER PRIMARY KEY, name VARCHAR(50), port VARCHAR(50), notes VARCHAR(50), vintage BOOLEAN )").execute_non_query
|
179
|
+
command = @connection.create_command("INSERT INTO sail_boats (id, name, port, name, vintage) VALUES (?, ?, ?, ?, ?)")
|
180
|
+
command.execute_non_query(1, "A", "C", "Fortune Pig!", false)
|
181
|
+
command.execute_non_query(2, "B", "B", "Happy Cow!", true)
|
182
|
+
command.execute_non_query(3, "C", "A", "Spoon", true)
|
183
|
+
end
|
184
|
+
|
185
|
+
it "should quote a String" do
|
186
|
+
command = @connection.create_command("INSERT INTO users (name) VALUES (?)")
|
187
|
+
result = command.execute_non_query("John Doe")
|
188
|
+
result.to_i.should == 1
|
189
|
+
end
|
190
|
+
|
191
|
+
it "should quote multiple values" do
|
192
|
+
command = @connection.create_command("INSERT INTO users (name, age) VALUES (?, ?)")
|
193
|
+
result = command.execute_non_query("Sam Smoot", 1)
|
194
|
+
result.to_i.should == 1
|
195
|
+
end
|
196
|
+
|
197
|
+
|
198
|
+
it "should handle boolean columns gracefully" do
|
199
|
+
command = @connection.create_command("INSERT INTO sail_boats (id, name, port, name, vintage) VALUES (?, ?, ?, ?, ?)")
|
200
|
+
result = command.execute_non_query(4, "Scooner", "Port au Prince", "This is one gangster boat!", true)
|
201
|
+
result.to_i.should == 1
|
202
|
+
end
|
203
|
+
|
204
|
+
it "should quote an Array" do
|
205
|
+
command = @connection.create_command("SELECT id, notes FROM sail_boats WHERE (id IN ?)")
|
206
|
+
reader = command.execute_reader([1, 2, 3])
|
207
|
+
|
208
|
+
i = 1
|
209
|
+
while(reader.next!)
|
210
|
+
reader.values[0].should == i
|
211
|
+
i += 1
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
it "should quote an Array with NULL values returned" do
|
216
|
+
command = @connection.create_command("SELECT id, NULL AS notes FROM sail_boats WHERE (id IN ?)")
|
217
|
+
reader = command.execute_reader([1, 2, 3])
|
218
|
+
|
219
|
+
i = 1
|
220
|
+
while(reader.next!)
|
221
|
+
reader.values[0].should == i
|
222
|
+
i += 1
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
it "should quote an Array with NULL values returned AND set_types called" do
|
227
|
+
command = @connection.create_command("SELECT id, NULL AS notes FROM sail_boats WHERE (id IN ?)")
|
228
|
+
command.set_types [ Integer, String ]
|
229
|
+
|
230
|
+
reader = command.execute_reader([1, 2, 3])
|
231
|
+
|
232
|
+
i = 1
|
233
|
+
while(reader.next!)
|
234
|
+
reader.values[0].should == i
|
235
|
+
i += 1
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
after do
|
240
|
+
@connection.create_command("DROP TABLE sail_boats").execute_non_query
|
241
|
+
end
|
242
|
+
|
243
|
+
end # describe "quoting"
|
244
|
+
end
|