sqlite3 0.1.1 → 1.3.3.beta.1
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/API_CHANGES.rdoc +50 -0
- data/CHANGELOG.rdoc +177 -0
- data/ChangeLog.cvs +88 -0
- data/LICENSE +24 -17
- data/Manifest.txt +50 -0
- data/README.rdoc +100 -4
- data/Rakefile +10 -0
- data/ext/sqlite3/backup.c +164 -0
- data/ext/sqlite3/backup.h +15 -0
- data/ext/sqlite3/database.c +762 -0
- data/ext/sqlite3/database.h +15 -0
- data/ext/sqlite3/exception.c +94 -0
- data/ext/sqlite3/exception.h +8 -0
- data/ext/sqlite3/extconf.rb +47 -0
- data/ext/sqlite3/sqlite3.c +36 -0
- data/ext/sqlite3/sqlite3_ruby.h +44 -0
- data/ext/sqlite3/statement.c +419 -0
- data/ext/sqlite3/statement.h +16 -0
- data/faq/faq.rb +145 -0
- data/faq/faq.yml +426 -0
- data/lib/sqlite3.rb +9 -12
- data/lib/sqlite3/constants.rb +46 -72
- data/lib/sqlite3/database.rb +415 -140
- data/lib/sqlite3/errors.rb +1 -56
- data/lib/sqlite3/pragmas.rb +246 -63
- data/lib/sqlite3/resultset.rb +30 -112
- data/lib/sqlite3/statement.rb +42 -108
- data/lib/sqlite3/translator.rb +118 -0
- data/lib/sqlite3/value.rb +57 -0
- data/lib/sqlite3/version.rb +23 -1
- data/setup.rb +1333 -0
- data/tasks/faq.rake +9 -0
- data/tasks/gem.rake +31 -0
- data/tasks/native.rake +61 -0
- data/tasks/vendor_sqlite3.rake +104 -0
- data/test/helper.rb +3 -0
- data/test/test_backup.rb +33 -0
- data/test/test_collation.rb +82 -0
- data/test/test_database.rb +312 -0
- data/test/test_database_readonly.rb +29 -0
- data/test/test_deprecated.rb +37 -0
- data/test/test_encoding.rb +119 -0
- data/test/test_integration.rb +544 -0
- data/test/test_integration_open_close.rb +30 -0
- data/test/test_integration_pending.rb +115 -0
- data/test/test_integration_resultset.rb +156 -0
- data/test/test_integration_statement.rb +194 -0
- data/test/test_sqlite3.rb +9 -0
- data/test/test_statement.rb +207 -0
- data/test/test_statement_execute.rb +35 -0
- metadata +124 -67
- data/lib/sqlite3/api.rb +0 -52
- data/lib/sqlite3/driver.rb +0 -138
- data/lib/sqlite3/encoding.rb +0 -43
- data/lib/sqlite3/extensions.rb +0 -27
data/lib/sqlite3/errors.rb
CHANGED
@@ -1,37 +1,6 @@
|
|
1
|
-
|
2
|
-
# All rights reserved.
|
3
|
-
|
4
|
-
# Redistribution and use in source and binary forms, with or without
|
5
|
-
# modification, are permitted provided that the following conditions
|
6
|
-
# are met:
|
7
|
-
|
8
|
-
# * Redistributions of source code must retain the above copyright
|
9
|
-
# notice, this list of conditions and the following disclaimer.
|
10
|
-
|
11
|
-
# * Redistributions in binary form must reproduce the above copyright
|
12
|
-
# notice, this list of conditions and the following disclaimer in
|
13
|
-
# the documentation and/or other materials provided with the
|
14
|
-
# distribution.
|
15
|
-
|
16
|
-
# * The names of its contributors may not be used to endorse or
|
17
|
-
# promote products derived from this software without specific prior
|
18
|
-
# written permission.
|
19
|
-
|
20
|
-
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
21
|
-
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
22
|
-
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
23
|
-
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
24
|
-
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
25
|
-
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
26
|
-
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
27
|
-
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
28
|
-
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
29
|
-
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
30
|
-
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
31
|
-
# POSSIBILITY OF SUCH DAMAGE.
|
1
|
+
require 'sqlite3/constants'
|
32
2
|
|
33
3
|
module SQLite3
|
34
|
-
|
35
4
|
class Exception < ::StandardError
|
36
5
|
@code = 0
|
37
6
|
|
@@ -72,28 +41,4 @@ module SQLite3
|
|
72
41
|
class FormatException < Exception; end
|
73
42
|
class RangeException < Exception; end
|
74
43
|
class NotADatabaseException < Exception; end
|
75
|
-
|
76
|
-
EXCEPTIONS =
|
77
|
-
[
|
78
|
-
nil, SQLException, InternalException,
|
79
|
-
PermissionException, AbortException, BusyException,
|
80
|
-
LockedException, MemoryException, ReadOnlyException,
|
81
|
-
InterruptException, IOException, CorruptException,
|
82
|
-
NotFoundException, FullException, CantOpenException,
|
83
|
-
ProtocolException, EmptyException, SchemaChangedException,
|
84
|
-
TooBigException, ConstraintException, MismatchException,
|
85
|
-
MisuseException, UnsupportedException, AuthorizationException,
|
86
|
-
FormatException, RangeException, NotADatabaseException
|
87
|
-
].each_with_index { |e,i| e.instance_variable_set(:@code, i ) if e }
|
88
|
-
|
89
|
-
module Error
|
90
|
-
def check( result, db=nil, msg=nil )
|
91
|
-
unless result == Constants::ErrorCode::OK
|
92
|
-
msg = ( msg ? msg + ": " : "" ) + db.errmsg if db
|
93
|
-
raise(( EXCEPTIONS[result] || SQLite3::Exception ), msg)
|
94
|
-
end
|
95
|
-
end
|
96
|
-
module_function :check
|
97
|
-
end
|
98
|
-
|
99
44
|
end
|
data/lib/sqlite3/pragmas.rb
CHANGED
@@ -1,34 +1,4 @@
|
|
1
|
-
|
2
|
-
# All rights reserved.
|
3
|
-
|
4
|
-
# Redistribution and use in source and binary forms, with or without
|
5
|
-
# modification, are permitted provided that the following conditions
|
6
|
-
# are met:
|
7
|
-
|
8
|
-
# * Redistributions of source code must retain the above copyright
|
9
|
-
# notice, this list of conditions and the following disclaimer.
|
10
|
-
|
11
|
-
# * Redistributions in binary form must reproduce the above copyright
|
12
|
-
# notice, this list of conditions and the following disclaimer in
|
13
|
-
# the documentation and/or other materials provided with the
|
14
|
-
# distribution.
|
15
|
-
|
16
|
-
# * The names of its contributors may not be used to endorse or
|
17
|
-
# promote products derived from this software without specific prior
|
18
|
-
# written permission.
|
19
|
-
|
20
|
-
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
21
|
-
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
22
|
-
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
23
|
-
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
24
|
-
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
25
|
-
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
26
|
-
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
27
|
-
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
28
|
-
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
29
|
-
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
30
|
-
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
31
|
-
# POSSIBILITY OF SUCH DAMAGE.
|
1
|
+
require 'sqlite3/errors'
|
32
2
|
|
33
3
|
module SQLite3
|
34
4
|
|
@@ -39,16 +9,228 @@ module SQLite3
|
|
39
9
|
# at http://sqlite.org/pragma.html.
|
40
10
|
module Pragmas
|
41
11
|
|
42
|
-
|
43
|
-
|
12
|
+
# Returns +true+ or +false+ depending on the value of the named pragma.
|
13
|
+
def get_boolean_pragma( name )
|
14
|
+
get_first_value( "PRAGMA #{name}" ) != "0"
|
15
|
+
end
|
16
|
+
private :get_boolean_pragma
|
17
|
+
|
18
|
+
# Sets the given pragma to the given boolean value. The value itself
|
19
|
+
# may be +true+ or +false+, or any other commonly used string or
|
20
|
+
# integer that represents truth.
|
21
|
+
def set_boolean_pragma( name, mode )
|
22
|
+
case mode
|
23
|
+
when String
|
24
|
+
case mode.downcase
|
25
|
+
when "on", "yes", "true", "y", "t"; mode = "'ON'"
|
26
|
+
when "off", "no", "false", "n", "f"; mode = "'OFF'"
|
27
|
+
else
|
28
|
+
raise Exception,
|
29
|
+
"unrecognized pragma parameter #{mode.inspect}"
|
30
|
+
end
|
31
|
+
when true, 1
|
32
|
+
mode = "ON"
|
33
|
+
when false, 0, nil
|
34
|
+
mode = "OFF"
|
35
|
+
else
|
36
|
+
raise Exception,
|
37
|
+
"unrecognized pragma parameter #{mode.inspect}"
|
38
|
+
end
|
39
|
+
|
40
|
+
execute( "PRAGMA #{name}=#{mode}" )
|
41
|
+
end
|
42
|
+
private :set_boolean_pragma
|
43
|
+
|
44
|
+
# Requests the given pragma (and parameters), and if the block is given,
|
45
|
+
# each row of the result set will be yielded to it. Otherwise, the results
|
46
|
+
# are returned as an array.
|
47
|
+
def get_query_pragma( name, *parms, &block ) # :yields: row
|
48
|
+
if parms.empty?
|
49
|
+
execute( "PRAGMA #{name}", &block )
|
50
|
+
else
|
51
|
+
args = "'" + parms.join("','") + "'"
|
52
|
+
execute( "PRAGMA #{name}( #{args} )", &block )
|
53
|
+
end
|
54
|
+
end
|
55
|
+
private :get_query_pragma
|
56
|
+
|
57
|
+
# Return the value of the given pragma.
|
58
|
+
def get_enum_pragma( name )
|
59
|
+
get_first_value( "PRAGMA #{name}" )
|
60
|
+
end
|
61
|
+
private :get_enum_pragma
|
44
62
|
|
45
|
-
|
63
|
+
# Set the value of the given pragma to +mode+. The +mode+ parameter must
|
64
|
+
# conform to one of the values in the given +enum+ array. Each entry in
|
65
|
+
# the array is another array comprised of elements in the enumeration that
|
66
|
+
# have duplicate values. See #synchronous, #default_synchronous,
|
67
|
+
# #temp_store, and #default_temp_store for usage examples.
|
68
|
+
def set_enum_pragma( name, mode, enums )
|
69
|
+
match = enums.find { |p| p.find { |i| i.to_s.downcase == mode.to_s.downcase } }
|
70
|
+
raise Exception,
|
71
|
+
"unrecognized #{name} #{mode.inspect}" unless match
|
72
|
+
execute( "PRAGMA #{name}='#{match.first.upcase}'" )
|
73
|
+
end
|
74
|
+
private :set_enum_pragma
|
75
|
+
|
76
|
+
# Returns the value of the given pragma as an integer.
|
77
|
+
def get_int_pragma( name )
|
78
|
+
get_first_value( "PRAGMA #{name}" ).to_i
|
79
|
+
end
|
80
|
+
private :get_int_pragma
|
81
|
+
|
82
|
+
# Set the value of the given pragma to the integer value of the +value+
|
83
|
+
# parameter.
|
84
|
+
def set_int_pragma( name, value )
|
85
|
+
execute( "PRAGMA #{name}=#{value.to_i}" )
|
86
|
+
end
|
87
|
+
private :set_int_pragma
|
88
|
+
|
89
|
+
# The enumeration of valid synchronous modes.
|
90
|
+
SYNCHRONOUS_MODES = [ [ 'full', 2 ], [ 'normal', 1 ], [ 'off', 0 ] ]
|
91
|
+
|
92
|
+
# The enumeration of valid temp store modes.
|
93
|
+
TEMP_STORE_MODES = [ [ 'default', 0 ], [ 'file', 1 ], [ 'memory', 2 ] ]
|
94
|
+
|
95
|
+
# Does an integrity check on the database. If the check fails, a
|
96
|
+
# SQLite3::Exception will be raised. Otherwise it
|
97
|
+
# returns silently.
|
98
|
+
def integrity_check
|
99
|
+
execute( "PRAGMA integrity_check" ) do |row|
|
100
|
+
raise Exception, row[0] if row[0] != "ok"
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def auto_vacuum
|
105
|
+
get_boolean_pragma "auto_vacuum"
|
106
|
+
end
|
107
|
+
|
108
|
+
def auto_vacuum=( mode )
|
109
|
+
set_boolean_pragma "auto_vacuum", mode
|
110
|
+
end
|
111
|
+
|
112
|
+
def schema_cookie
|
113
|
+
get_int_pragma "schema_cookie"
|
114
|
+
end
|
115
|
+
|
116
|
+
def schema_cookie=( cookie )
|
117
|
+
set_int_pragma "schema_cookie", cookie
|
118
|
+
end
|
119
|
+
|
120
|
+
def user_cookie
|
121
|
+
get_int_pragma "user_cookie"
|
122
|
+
end
|
123
|
+
|
124
|
+
def user_cookie=( cookie )
|
125
|
+
set_int_pragma "user_cookie", cookie
|
126
|
+
end
|
127
|
+
|
128
|
+
def cache_size
|
129
|
+
get_int_pragma "cache_size"
|
130
|
+
end
|
131
|
+
|
132
|
+
def cache_size=( size )
|
133
|
+
set_int_pragma "cache_size", size
|
134
|
+
end
|
135
|
+
|
136
|
+
def default_cache_size
|
137
|
+
get_int_pragma "default_cache_size"
|
138
|
+
end
|
139
|
+
|
140
|
+
def default_cache_size=( size )
|
141
|
+
set_int_pragma "default_cache_size", size
|
142
|
+
end
|
143
|
+
|
144
|
+
def default_synchronous
|
145
|
+
get_enum_pragma "default_synchronous"
|
146
|
+
end
|
147
|
+
|
148
|
+
def default_synchronous=( mode )
|
149
|
+
set_enum_pragma "default_synchronous", mode, SYNCHRONOUS_MODES
|
150
|
+
end
|
151
|
+
|
152
|
+
def synchronous
|
153
|
+
get_enum_pragma "synchronous"
|
154
|
+
end
|
155
|
+
|
156
|
+
def synchronous=( mode )
|
157
|
+
set_enum_pragma "synchronous", mode, SYNCHRONOUS_MODES
|
158
|
+
end
|
159
|
+
|
160
|
+
def default_temp_store
|
161
|
+
get_enum_pragma "default_temp_store"
|
162
|
+
end
|
163
|
+
|
164
|
+
def default_temp_store=( mode )
|
165
|
+
set_enum_pragma "default_temp_store", mode, TEMP_STORE_MODES
|
166
|
+
end
|
167
|
+
|
168
|
+
def temp_store
|
169
|
+
get_enum_pragma "temp_store"
|
170
|
+
end
|
171
|
+
|
172
|
+
def temp_store=( mode )
|
173
|
+
set_enum_pragma "temp_store", mode, TEMP_STORE_MODES
|
174
|
+
end
|
175
|
+
|
176
|
+
def full_column_names
|
177
|
+
get_boolean_pragma "full_column_names"
|
178
|
+
end
|
179
|
+
|
180
|
+
def full_column_names=( mode )
|
181
|
+
set_boolean_pragma "full_column_names", mode
|
182
|
+
end
|
183
|
+
|
184
|
+
def parser_trace
|
185
|
+
get_boolean_pragma "parser_trace"
|
186
|
+
end
|
187
|
+
|
188
|
+
def parser_trace=( mode )
|
189
|
+
set_boolean_pragma "parser_trace", mode
|
190
|
+
end
|
191
|
+
|
192
|
+
def vdbe_trace
|
193
|
+
get_boolean_pragma "vdbe_trace"
|
194
|
+
end
|
195
|
+
|
196
|
+
def vdbe_trace=( mode )
|
197
|
+
set_boolean_pragma "vdbe_trace", mode
|
198
|
+
end
|
199
|
+
|
200
|
+
def database_list( &block ) # :yields: row
|
201
|
+
get_query_pragma "database_list", &block
|
202
|
+
end
|
203
|
+
|
204
|
+
def foreign_key_list( table, &block ) # :yields: row
|
205
|
+
get_query_pragma "foreign_key_list", table, &block
|
206
|
+
end
|
207
|
+
|
208
|
+
def index_info( index, &block ) # :yields: row
|
209
|
+
get_query_pragma "index_info", index, &block
|
210
|
+
end
|
211
|
+
|
212
|
+
def index_list( table, &block ) # :yields: row
|
213
|
+
get_query_pragma "index_list", table, &block
|
214
|
+
end
|
215
|
+
|
216
|
+
###
|
217
|
+
# Returns information about +table+. Yields each row of table information
|
218
|
+
# if a block is provided.
|
219
|
+
def table_info table
|
220
|
+
stmt = prepare "PRAGMA table_info(#{table})"
|
221
|
+
columns = stmt.columns
|
222
|
+
|
223
|
+
needs_tweak_default =
|
224
|
+
version_compare(SQLite3.libversion.to_s, "3.3.7") > 0
|
46
225
|
|
47
226
|
result = [] unless block_given?
|
48
|
-
|
49
|
-
new_row =
|
50
|
-
|
51
|
-
|
227
|
+
stmt.each do |row|
|
228
|
+
new_row = Hash[columns.zip(row)]
|
229
|
+
|
230
|
+
# FIXME: This should be removed but is required for older versions
|
231
|
+
# of rails
|
232
|
+
if(Object.const_defined?(:ActiveRecord))
|
233
|
+
new_row['notnull'] = new_row['notnull'].to_s
|
52
234
|
end
|
53
235
|
|
54
236
|
tweak_default(new_row) if needs_tweak_default
|
@@ -59,39 +241,40 @@ module SQLite3
|
|
59
241
|
result << new_row
|
60
242
|
end
|
61
243
|
end
|
244
|
+
stmt.close
|
62
245
|
|
63
246
|
result
|
64
247
|
end
|
65
248
|
|
66
249
|
private
|
67
250
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
251
|
+
# Compares two version strings
|
252
|
+
def version_compare(v1, v2)
|
253
|
+
v1 = v1.split(".").map { |i| i.to_i }
|
254
|
+
v2 = v2.split(".").map { |i| i.to_i }
|
255
|
+
parts = [v1.length, v2.length].max
|
256
|
+
v1.push 0 while v1.length < parts
|
257
|
+
v2.push 0 while v2.length < parts
|
258
|
+
v1.zip(v2).each do |a,b|
|
259
|
+
return -1 if a < b
|
260
|
+
return 1 if a > b
|
261
|
+
end
|
262
|
+
return 0
|
78
263
|
end
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
hash["dflt_value"] = $1.gsub(/""/, '"')
|
264
|
+
|
265
|
+
# Since SQLite 3.3.8, the table_info pragma has returned the default
|
266
|
+
# value of the row as a quoted SQL value. This method essentially
|
267
|
+
# unquotes those values.
|
268
|
+
def tweak_default(hash)
|
269
|
+
case hash["dflt_value"]
|
270
|
+
when /^null$/i
|
271
|
+
hash["dflt_value"] = nil
|
272
|
+
when /^'(.*)'$/
|
273
|
+
hash["dflt_value"] = $1.gsub(/''/, "'")
|
274
|
+
when /^"(.*)"$/
|
275
|
+
hash["dflt_value"] = $1.gsub(/""/, '"')
|
276
|
+
end
|
93
277
|
end
|
94
|
-
end
|
95
278
|
end
|
96
279
|
|
97
280
|
end
|
data/lib/sqlite3/resultset.rb
CHANGED
@@ -1,34 +1,5 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
# Redistribution and use in source and binary forms, with or without
|
5
|
-
# modification, are permitted provided that the following conditions
|
6
|
-
# are met:
|
7
|
-
|
8
|
-
# * Redistributions of source code must retain the above copyright
|
9
|
-
# notice, this list of conditions and the following disclaimer.
|
10
|
-
|
11
|
-
# * Redistributions in binary form must reproduce the above copyright
|
12
|
-
# notice, this list of conditions and the following disclaimer in
|
13
|
-
# the documentation and/or other materials provided with the
|
14
|
-
# distribution.
|
15
|
-
|
16
|
-
# * The names of its contributors may not be used to endorse or
|
17
|
-
# promote products derived from this software without specific prior
|
18
|
-
# written permission.
|
19
|
-
|
20
|
-
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
21
|
-
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
22
|
-
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
23
|
-
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
24
|
-
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
25
|
-
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
26
|
-
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
27
|
-
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
28
|
-
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
29
|
-
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
30
|
-
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
31
|
-
# POSSIBILITY OF SUCH DAMAGE.
|
1
|
+
require 'sqlite3/constants'
|
2
|
+
require 'sqlite3/errors'
|
32
3
|
|
33
4
|
module SQLite3
|
34
5
|
|
@@ -60,47 +31,22 @@ module SQLite3
|
|
60
31
|
|
61
32
|
# Create a new ResultSet attached to the given database, using the
|
62
33
|
# given sql text.
|
63
|
-
def initialize
|
64
|
-
@db
|
65
|
-
@driver = @db.driver
|
34
|
+
def initialize db, stmt
|
35
|
+
@db = db
|
66
36
|
@stmt = stmt
|
67
|
-
@utf_16 = utf_16
|
68
|
-
commence
|
69
37
|
end
|
70
38
|
|
71
|
-
# A convenience method for compiling the virtual machine and stepping
|
72
|
-
# to the first row of the result set.
|
73
|
-
def commence
|
74
|
-
result = @driver.step(@stmt.handle)
|
75
|
-
if result == Constants::ErrorCode::ERROR
|
76
|
-
@driver.reset(@stmt.handle)
|
77
|
-
end
|
78
|
-
check result
|
79
|
-
@first_row = true
|
80
|
-
end
|
81
|
-
private :commence
|
82
|
-
|
83
|
-
def check(result)
|
84
|
-
@eof = (result == Constants::ErrorCode::DONE)
|
85
|
-
found = (result == Constants::ErrorCode::ROW)
|
86
|
-
Error.check(result, @db) unless @eof || found
|
87
|
-
end
|
88
|
-
private :check
|
89
|
-
|
90
39
|
# Reset the cursor, so that a result set which has reached end-of-file
|
91
40
|
# can be rewound and reiterated.
|
92
|
-
def reset(*bind_params)
|
93
|
-
@stmt.
|
94
|
-
@stmt.
|
95
|
-
@driver.reset(@stmt.handle)
|
96
|
-
@stmt.bind_params(*bind_params)
|
41
|
+
def reset( *bind_params )
|
42
|
+
@stmt.reset!
|
43
|
+
@stmt.bind_params( *bind_params )
|
97
44
|
@eof = false
|
98
|
-
commence
|
99
45
|
end
|
100
46
|
|
101
47
|
# Query whether the cursor has reached the end of the result set or not.
|
102
48
|
def eof?
|
103
|
-
@
|
49
|
+
@stmt.done?
|
104
50
|
end
|
105
51
|
|
106
52
|
# Obtain the next row from the cursor. If there are no more rows to be
|
@@ -117,67 +63,39 @@ module SQLite3
|
|
117
63
|
# For hashes, the column names are the keys of the hash, and the column
|
118
64
|
# types are accessible via the +types+ property.
|
119
65
|
def next
|
120
|
-
|
121
|
-
|
122
|
-
@stmt.must_be_open!
|
66
|
+
row = @stmt.step
|
67
|
+
return nil if @stmt.done?
|
123
68
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
end
|
128
|
-
|
129
|
-
@first_row = false
|
130
|
-
|
131
|
-
unless @eof
|
132
|
-
row = []
|
133
|
-
@driver.data_count(@stmt.handle).times do |column|
|
134
|
-
type = @driver.column_type(@stmt.handle, column)
|
135
|
-
|
136
|
-
if type == Constants::ColumnType::NULL
|
137
|
-
row << nil
|
138
|
-
elsif type == Constants::ColumnType::BLOB
|
139
|
-
row << @driver.column_blob(@stmt.handle, column)
|
140
|
-
elsif type == Constants::ColumnType::INTEGER
|
141
|
-
row << @driver.column_int64(@stmt.handle, column)
|
142
|
-
elsif type == Constants::ColumnType::FLOAT
|
143
|
-
row << @driver.column_double(@stmt.handle, column)
|
144
|
-
else
|
145
|
-
row << @driver.column_text(@stmt.handle, column, @utf_16)
|
146
|
-
end
|
69
|
+
if @db.type_translation
|
70
|
+
row = @stmt.types.zip(row).map do |type, value|
|
71
|
+
@db.translator.translate( type, value )
|
147
72
|
end
|
73
|
+
end
|
148
74
|
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
row
|
158
|
-
row = new_row
|
75
|
+
if @db.results_as_hash
|
76
|
+
new_row = HashWithTypes[*@stmt.columns.zip(row).flatten]
|
77
|
+
row.each_with_index { |value,idx|
|
78
|
+
new_row[idx] = value
|
79
|
+
}
|
80
|
+
row = new_row
|
81
|
+
else
|
82
|
+
if row.respond_to?(:fields)
|
83
|
+
row = ArrayWithTypes.new(row)
|
159
84
|
else
|
160
|
-
|
161
|
-
row = ArrayWithTypes.new(row)
|
162
|
-
else
|
163
|
-
row = ArrayWithTypesAndFields.new(row)
|
164
|
-
end
|
165
|
-
row.fields = @stmt.columns
|
85
|
+
row = ArrayWithTypesAndFields.new(row)
|
166
86
|
end
|
167
|
-
|
168
|
-
# row.types = @stmt.types
|
169
|
-
|
170
|
-
return row
|
87
|
+
row.fields = @stmt.columns
|
171
88
|
end
|
172
89
|
|
173
|
-
|
90
|
+
row.types = @stmt.types
|
91
|
+
row
|
174
92
|
end
|
175
93
|
|
176
94
|
# Required by the Enumerable mixin. Provides an internal iterator over the
|
177
95
|
# rows of the result set.
|
178
|
-
def each
|
179
|
-
while
|
180
|
-
yield
|
96
|
+
def each( &block )
|
97
|
+
while node = self.next
|
98
|
+
yield node
|
181
99
|
end
|
182
100
|
end
|
183
101
|
|