sqlite3-fiddle 1.0.0

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.
@@ -0,0 +1,115 @@
1
+ require 'fiddle'
2
+ require 'fiddle/import'
3
+
4
+ module SQLite3
5
+ module Driver
6
+ extend Fiddle::Importer
7
+
8
+ if path = $LIBSQLITE3 || ENV['LIBSQLITE3']
9
+ dlload path
10
+ else
11
+ dlload 'libsqlite3.dylib' rescue begin
12
+ dlload 'libsqlite3.so' rescue begin
13
+ dlload 'libsqlite3.dll' rescue fail('Unable to find libsqlite3, set ' +
14
+ 'the global $LIBSQLITE3 or the environment variable LIBSQLITE3')
15
+ end
16
+ end
17
+ end
18
+
19
+ extern 'const char *sqlite3_libversion()'
20
+ extern 'int sqlite3_busy_timeout(void*, int)'
21
+ extern 'int sqlite3_open_v2(const char *, sqlite3 **, int, const char *)'
22
+ extern 'int sqlite3_open16(const void *,sqlite3 **)'
23
+ extern 'int sqlite3_close(sqlite3*)'
24
+ extern 'int sqlite3_changes(void*)'
25
+ extern 'int sqlite3_total_changes(sqlite3*)'
26
+ extern 'long long sqlite3_last_insert_rowid(void*)'
27
+ extern 'int sqlite3_prepare_v2(void*, void*, int, void*, void*)'
28
+ extern 'int sqlite3_step(void*)'
29
+ extern 'int sqlite3_finalize(void*)'
30
+ extern 'int sqlite3_reset(void *)'
31
+ extern 'int sqlite3_clear_bindings(void*)'
32
+ extern 'int sqlite3_bind_parameter_count(void*)'
33
+ extern 'int sqlite3_column_count(void*)'
34
+ extern 'const char *sqlite3_column_name(void*, int)' rescue nil
35
+ extern 'const char *sqlite3_column_decltype(void*, int)'
36
+ extern 'const char *sqlite3_column_database_name(void*,int)' rescue nil
37
+ extern 'const char *sqlite3_column_table_name(void*,int)' rescue nil
38
+ extern 'const char *sqlite3_column_origin_name(void*,int)' rescue nil
39
+ extern 'int sqlite3_column_type(void*, int)'
40
+ extern 'const void *sqlite3_column_blob(void*, int)'
41
+ extern 'int sqlite3_column_bytes(void*, int)'
42
+ extern 'double sqlite3_column_double(void*, int)'
43
+ extern 'long long sqlite3_column_int64(void*, int)'
44
+ extern 'const unsigned char *sqlite3_column_text(void*, int)'
45
+ extern 'int sqlite3_bind_blob(void*, int, const void*, int, void*)'
46
+ extern 'int sqlite3_bind_double(void*, int, double)'
47
+ extern 'int sqlite3_bind_int64(void*, int, long long)'
48
+ extern 'int sqlite3_bind_null(void*, int)'
49
+ extern 'int sqlite3_bind_text(void*,int,const char*,int,void*)'
50
+ extern 'int sqlite3_bind_text16(void*,int,const char*,int,void*)'
51
+ extern 'int sqlite3_bind_parameter_index(sqlite3_stmt*, const char *)'
52
+ extern 'int sqlite3_errcode(sqlite3 *)'
53
+ extern 'int sqlite3_complete(const char *)'
54
+ extern 'int sqlite3_get_autocommit(sqlite3*)'
55
+ extern 'int sqlite3_db_readonly(sqlite3 *, const char *)'
56
+ extern 'const char *sqlite3_errmsg(sqlite3*)'
57
+ extern 'void *sqlite3_trace(void*, void*, void*)'
58
+ extern 'int sqlite3_set_authorizer(sqlite3*, void*, void*)'
59
+ extern 'const void *sqlite3_value_blob(sqlite3_value*)'
60
+ extern 'int sqlite3_value_bytes(sqlite3_value*)'
61
+ extern 'int sqlite3_value_bytes16(sqlite3_value*)'
62
+ extern 'double sqlite3_value_double(sqlite3_value*)'
63
+ extern 'int sqlite3_value_int(sqlite3_value*)'
64
+ extern 'long long sqlite3_value_int64(sqlite3_value*)'
65
+ extern 'const unsigned char *sqlite3_value_text(sqlite3_value*)'
66
+ extern 'const void *sqlite3_value_text16(sqlite3_value*)'
67
+ extern 'const void *sqlite3_value_text16le(sqlite3_value*)'
68
+ extern 'const void *sqlite3_value_text16be(sqlite3_value*)'
69
+ extern 'int sqlite3_value_type(sqlite3_value*)'
70
+ extern 'int sqlite3_value_numeric_type(sqlite3_value*)'
71
+ extern 'void sqlite3_result_blob(sqlite3_context*, const void*, int, void*)'
72
+ extern 'void sqlite3_result_double(sqlite3_context*, double)'
73
+ extern 'void sqlite3_result_error(sqlite3_context*, const char*, int)'
74
+ extern 'void sqlite3_result_int(sqlite3_context*, int)'
75
+ extern 'void sqlite3_result_int64(sqlite3_context*, long long)'
76
+ extern 'void sqlite3_result_null(sqlite3_context*)'
77
+ extern 'void sqlite3_result_text(sqlite3_context*, const char*, int, void*)'
78
+ extern 'void sqlite3_result_text16(sqlite3_context*, const char*, int, void*)'
79
+ extern 'int sqlite3_create_function(sqlite3 *,const char *,int,int,void*,void*,void*,void*)'
80
+ extern 'void *sqlite3_user_data(sqlite3_context*)'
81
+ extern 'void sqlite3_interrupt(sqlite3*)'
82
+ extern 'int sqlite3_busy_handler(sqlite3*, void*, void*)'
83
+ extern 'int sqlite3_create_collation(sqlite3*,const char *,int,void *,void*)'
84
+ extern 'const char *sqlite3_errmsg(sqlite3*)'
85
+ extern 'sqlite3_backup *sqlite3_backup_init(sqlite3 *, const char *, sqlite3 *, const char *)'
86
+ extern 'int sqlite3_backup_step(sqlite3_backup *, int)'
87
+ extern 'int sqlite3_backup_finish(sqlite3_backup *)'
88
+ extern 'int sqlite3_backup_remaining(sqlite3_backup *)'
89
+ extern 'int sqlite3_backup_pagecount(sqlite3_backup *)'
90
+
91
+ def self.set_context_result(ctx, var)
92
+ case var
93
+ when Blob
94
+ Driver.sqlite3_result_blob(ctx, var.to_s, var.to_s.size, nil)
95
+ when String
96
+ if var.encoding == Encoding::UTF_16LE ||
97
+ var.encoding == Encoding::UTF_16BE
98
+ Driver.sqlite3_result_text16(ctx, var, -1, nil)
99
+ else
100
+ Driver.sqlite3_result_text(ctx, var.encode(Encoding::UTF_8), -1, nil)
101
+ end
102
+ when Fixnum, Bignum
103
+ Driver.sqlite3_result_int64(ctx, var)
104
+ when Float
105
+ Driver.sqlite3_result_double(ctx, var)
106
+ when NilClass
107
+ Driver.sqlite3_result_null(ctx)
108
+ when TrueClass, FalseClass
109
+ Driver.sqlite3_result_int(ctx, var ? 1 : 0)
110
+ else
111
+ raise RuntimeError, "can't return #{var.class}"
112
+ end
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,280 @@
1
+ require 'sqlite3/constants'
2
+
3
+ module SQLite3
4
+
5
+ # This module is intended for inclusion solely by the Database class. It
6
+ # defines convenience methods for the various pragmas supported by SQLite3.
7
+ #
8
+ # For a detailed description of these pragmas, see the SQLite3 documentation
9
+ # at http://sqlite.org/pragma.html.
10
+ module Pragmas
11
+
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
62
+
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
225
+
226
+ result = [] unless block_given?
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
234
+ end
235
+
236
+ tweak_default(new_row) if needs_tweak_default
237
+
238
+ if block_given?
239
+ yield new_row
240
+ else
241
+ result << new_row
242
+ end
243
+ end
244
+ stmt.close
245
+
246
+ result
247
+ end
248
+
249
+ private
250
+
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
263
+ end
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 /^'(.*)'$/m
273
+ hash["dflt_value"] = $1.gsub(/''/, "'")
274
+ when /^"(.*)"$/m
275
+ hash["dflt_value"] = $1.gsub(/""/, '"')
276
+ end
277
+ end
278
+ end
279
+
280
+ end
@@ -0,0 +1,158 @@
1
+ module SQLite3
2
+
3
+ # The ResultSet object encapsulates the enumerability of a query's output.
4
+ # It is a simple cursor over the data that the query returns. It will
5
+ # very rarely (if ever) be instantiated directly. Instead, clients should
6
+ # obtain a ResultSet instance via Statement#execute.
7
+ class ResultSet
8
+ include Enumerable
9
+
10
+ class ArrayWithTypes < Array # :nodoc:
11
+ attr_accessor :types
12
+ end
13
+
14
+ class ArrayWithTypesAndFields < Array # :nodoc:
15
+ attr_writer :types
16
+ attr_writer :fields
17
+
18
+ def types
19
+ @types
20
+ end
21
+
22
+ def fields
23
+ @fields
24
+ end
25
+ end
26
+
27
+ # The class of which we return an object in case we want a Hash as
28
+ # result.
29
+ class HashWithTypesAndFields < Hash # :nodoc:
30
+ attr_writer :types
31
+ attr_writer :fields
32
+
33
+ def types
34
+ @types
35
+ end
36
+
37
+ def fields
38
+ @fields
39
+ end
40
+
41
+ def [] key
42
+ key = fields[key] if key.is_a? Numeric
43
+ super key
44
+ end
45
+ end
46
+
47
+ # Create a new ResultSet attached to the given database, using the
48
+ # given sql text.
49
+ def initialize db, stmt
50
+ @db = db
51
+ @stmt = stmt
52
+ end
53
+
54
+ # Reset the cursor, so that a result set which has reached end-of-file
55
+ # can be rewound and reiterated.
56
+ def reset( *bind_params )
57
+ must_be_open!
58
+ @stmt.reset!
59
+ @stmt.bind_params( *bind_params )
60
+ @eof = false
61
+ end
62
+
63
+ # Query whether the cursor has reached the end of the result set or not.
64
+ def eof?
65
+ @stmt.done?
66
+ end
67
+
68
+ # Obtain the next row from the cursor. If there are no more rows to be
69
+ # had, this will return +nil+. If type translation is active on the
70
+ # corresponding database, the values in the row will be translated
71
+ # according to their types.
72
+ #
73
+ # The returned value will be an array, unless Database#results_as_hash has
74
+ # been set to +true+, in which case the returned value will be a hash.
75
+ #
76
+ # For arrays, the column names are accessible via the +fields+ property,
77
+ # and the column types are accessible via the +types+ property.
78
+ #
79
+ # For hashes, the column names are the keys of the hash, and the column
80
+ # types are accessible via the +types+ property.
81
+ def next
82
+ must_be_open!
83
+ if @db.results_as_hash
84
+ return next_hash
85
+ end
86
+
87
+ row = @stmt.step
88
+ return nil if @stmt.done?
89
+ row = ArrayWithTypesAndFields.new(row)
90
+ row.fields = @stmt.columns
91
+ row.types = @stmt.types
92
+ row
93
+ end
94
+
95
+ # Required by the Enumerable mixin. Provides an internal iterator over the
96
+ # rows of the result set.
97
+ def each
98
+ must_be_open!
99
+ while node = self.next
100
+ yield node
101
+ end
102
+ end
103
+
104
+ # Provides an internal iterator over the rows of the result set where
105
+ # each row is yielded as a hash.
106
+ def each_hash
107
+ while node = next_hash
108
+ yield node
109
+ end
110
+ end
111
+
112
+ # Closes the statement that spawned this result set.
113
+ # <em>Use with caution!</em> Closing a result set will automatically
114
+ # close any other result sets that were spawned from the same statement.
115
+ def close
116
+ @stmt.close
117
+ end
118
+
119
+ # Queries whether the underlying statement has been closed or not.
120
+ def closed?
121
+ @stmt.closed?
122
+ end
123
+
124
+ # Returns the types of the columns returned by this result set.
125
+ def types
126
+ must_be_open!
127
+ @stmt.types
128
+ end
129
+
130
+ # Returns the names of the columns returned by this result set.
131
+ def columns
132
+ must_be_open!
133
+ @stmt.columns
134
+ end
135
+
136
+ # Return the next row as a hash
137
+ def next_hash
138
+ must_be_open!
139
+ row = @stmt.step
140
+ return nil if @stmt.done?
141
+
142
+ # FIXME: this can be switched to a regular hash in 2.0
143
+ row = HashWithTypesAndFields[*@stmt.columns.zip(row).flatten]
144
+
145
+ # FIXME: these methods are deprecated for version 2.0, so we can remove
146
+ # this code in 2.0
147
+ row.fields = @stmt.columns
148
+ row.types = @stmt.types
149
+ row
150
+ end
151
+
152
+ private
153
+
154
+ def must_be_open!
155
+ raise Exception, "#{self.class} is closed!" if closed?
156
+ end
157
+ end
158
+ end