sqlite3-fiddle 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,290 @@
1
+ module SQLite3
2
+ class Statement
3
+ include Enumerable
4
+
5
+ # This is any text that followed the first valid SQL statement in the text
6
+ # with which the statement was initialized. If there was no trailing text,
7
+ # this will be the empty string.
8
+ attr_reader :remainder
9
+
10
+ def initialize(db, sql)
11
+ raise TypeError, 'sql has to be a string' unless sql.is_a? String
12
+ raise ArgumentError, 'db has to be open' if db.closed?
13
+ @db = db
14
+ sql = sql.strip.encode(Encoding::UTF_8)
15
+ @prepared_stmt = Fiddle::Pointer.malloc(Fiddle::SIZEOF_VOIDP)
16
+ remainder = Fiddle::Pointer.malloc(Fiddle::SIZEOF_VOIDP)
17
+ @db.check Driver.sqlite3_prepare_v2(db.handle, sql, -1,
18
+ @prepared_stmt.ref,
19
+ remainder.ref)
20
+ @remainder = remainder.to_s
21
+ @sql = sql
22
+ @done = false
23
+ remainder.free
24
+ end
25
+
26
+ def column_count
27
+ Driver.sqlite3_column_count(@prepared_stmt)
28
+ end
29
+
30
+ def column_name(index)
31
+ column = Driver.sqlite3_column_name(@prepared_stmt, index.to_i)
32
+ column.to_s unless column.null?
33
+ end
34
+
35
+ def column_decltype(index)
36
+ column = Driver.sqlite3_column_decltype(@prepared_stmt, index.to_i)
37
+ column.to_s unless column.null?
38
+ end
39
+
40
+ def database_name(index)
41
+ name = Driver.sqlite3_column_database_name(@prepared_stmt, index.to_i)
42
+ name.to_s unless name.null?
43
+ end
44
+
45
+ def table_name(index)
46
+ name = Driver.sqlite3_column_table_name(@prepared_stmt, index.to_i)
47
+ name.to_s unless name.null?
48
+ end
49
+
50
+ def origin_name(index)
51
+ name = Driver.sqlite3_column_origin_name(@prepared_stmt, index.to_i)
52
+ name.to_s unless name.null?
53
+ end
54
+
55
+ def bind_parameter_count
56
+ Driver.sqlite3_bind_parameter_count(@prepared_stmt)
57
+ end
58
+
59
+ # Binds the given variables to the corresponding placeholders in the SQL
60
+ # text.
61
+ #
62
+ # See Database#execute for a description of the valid placeholder
63
+ # syntaxes.
64
+ #
65
+ # Example:
66
+ #
67
+ # stmt = db.prepare( "select * from table where a=? and b=?" )
68
+ # stmt.bind_params( 15, "hello" )
69
+ #
70
+ # See also #execute, #bind_param, Statement#bind_param, and
71
+ # Statement#bind_params.
72
+ def bind_params( *bind_vars )
73
+ index = 1
74
+ bind_vars.flatten.each do |var|
75
+ if Hash === var
76
+ var.each { |key, val| bind_param key, val }
77
+ else
78
+ bind_param index, var
79
+ index += 1
80
+ end
81
+ end
82
+ end
83
+
84
+ def bind_param(index, var)
85
+ must_be_open!
86
+ unless index.is_a? Fixnum
87
+ name = index.to_s
88
+ name = ":#{name}" unless name.start_with? ':'
89
+ # if name !=~ /^[:@?$].*/
90
+ index = Driver.sqlite3_bind_parameter_index(@prepared_stmt, name)
91
+ if index == 0
92
+ raise Exception, "index #{name} unknown for [#{@sql}]"
93
+ end
94
+ end
95
+ @db.check case var
96
+ when Blob
97
+ var = var.force_encoding(Encoding::ASCII_8BIT)
98
+ Driver.sqlite3_bind_blob(@prepared_stmt, index, var.to_s,
99
+ var.size, nil)
100
+ when String
101
+ # if UTF_16BE was passed we have to convert it anyway, than we use
102
+ # the UTF-8 conversion much like the c implementation does.
103
+ # TODO: check if this is slow because the sqlite than has to convert to?
104
+ if var.encoding == Encoding::UTF_16LE
105
+ Driver.sqlite3_bind_text16(@prepared_stmt, index, var, -1, nil)
106
+ else # this string behaves like a blob, so we bind it as such
107
+ if var.encoding == Encoding::ASCII_8BIT
108
+ Driver.sqlite3_bind_blob(@prepared_stmt, index, var.to_s,
109
+ var.size, nil)
110
+ else
111
+ unless var.encoding == Encoding::UTF_8
112
+ var = var.encode(Encoding::UTF_8)
113
+ end
114
+ Driver.sqlite3_bind_text(@prepared_stmt, index, var, -1, nil)
115
+ end
116
+ end
117
+ when Fixnum, Bignum
118
+ Driver.sqlite3_bind_int64(@prepared_stmt, index, var)
119
+ when Float
120
+ Driver.sqlite3_bind_double(@prepared_stmt, index, var)
121
+ when NilClass
122
+ Driver.sqlite3_bind_null(@prepared_stmt, index)
123
+ when TrueClass, FalseClass
124
+ Driver.sqlite3_bind_int(@prepared_stmt, index, var ? 1 : 0)
125
+ else
126
+ Driver.sqlite3_bind_blob(@prepared_stmt, index, var.to_s,
127
+ var.to_s.size, nil)
128
+ end
129
+ end
130
+
131
+ def clear_bindings!
132
+ @db.check Driver.sqlite3_clear_bindings(@prepared_stmt)
133
+ end
134
+
135
+ def reset!
136
+ @db.check Driver.sqlite3_reset(@prepared_stmt)
137
+ @done = false
138
+ end
139
+ #
140
+ # def execute(*bind_vars, &handler)
141
+ # must_be_open!
142
+ # reset! if active? || done?
143
+ # bind_params *bind_vars unless bind_vars.empty?
144
+ # if block_given?
145
+ # each &handler
146
+ # else
147
+ # ResultSet.new(@db, self)
148
+ # end
149
+ # end
150
+ def execute( *bind_vars )
151
+ reset! if active? || done?
152
+
153
+ bind_params(*bind_vars) unless bind_vars.empty?
154
+ @results = ResultSet.new(@db, self)
155
+
156
+ step if 0 == column_count
157
+
158
+ yield @results if block_given?
159
+ @results
160
+ end
161
+
162
+ def each
163
+ loop do
164
+ val = step
165
+ break self if done?
166
+ yield val
167
+ end
168
+ end
169
+
170
+ def step
171
+ must_be_open!
172
+ case Driver.sqlite3_step(@prepared_stmt)
173
+ when SQLITE_ROW
174
+ row = []
175
+ column_count.times do |i|
176
+ case Driver.sqlite3_column_type(@prepared_stmt, i)
177
+ when SQLITE_INTEGER
178
+ row << Driver.sqlite3_column_int64(@prepared_stmt, i)
179
+ when SQLITE_FLOAT
180
+ row << Driver.sqlite3_column_double(@prepared_stmt, i)
181
+ when SQLITE_TEXT
182
+ text = (Driver.sqlite3_column_text(@prepared_stmt, i)[
183
+ 0, Driver.sqlite3_column_bytes(@prepared_stmt, i)
184
+ ])
185
+ default = Encoding.default_internal || Encoding::UTF_8
186
+ row << text.encode(default, Encoding::UTF_8)
187
+ when SQLITE_BLOB
188
+ data = Driver.sqlite3_column_blob(@prepared_stmt, i)[
189
+ 0, Driver.sqlite3_column_bytes(@prepared_stmt, i)
190
+ ]
191
+ row << Blob.new(data.force_encoding(Encoding::ASCII_8BIT))
192
+ when SQLITE_NULL
193
+ row << nil
194
+ else
195
+ fail Exception, "bad type"
196
+ end
197
+ end
198
+ return row
199
+ when SQLITE_DONE
200
+ @done = true
201
+ return nil
202
+ else
203
+ reset!
204
+ @done = false
205
+ end
206
+ end
207
+
208
+ # Execute the statement. If no block was given, this returns an array of
209
+ # rows returned by executing the statement. Otherwise, each row will be
210
+ # yielded to the block.
211
+ #
212
+ # Any parameters will be bound to the statement using #bind_params.
213
+ #
214
+ # Example:
215
+ #
216
+ # stmt = db.prepare( "select * from table" )
217
+ # stmt.execute! do |row|
218
+ # ...
219
+ # end
220
+ #
221
+ # See also #bind_params, #execute.
222
+ def execute!( *bind_vars, &block )
223
+ execute(*bind_vars)
224
+ block_given? ? each(&block) : to_a
225
+ end
226
+
227
+ # Returns true if the statement has been closed.
228
+ def closed?
229
+ @prepared_stmt.nil?
230
+ end
231
+
232
+ # returns true if all rows have been returned.
233
+ def done?
234
+ @done
235
+ end
236
+
237
+ def close
238
+ must_be_open!
239
+ @db.check Driver.sqlite3_finalize(@prepared_stmt)
240
+ @prepared_stmt.free
241
+ @prepared_stmt = nil
242
+ end
243
+
244
+
245
+ # Return an array of the data types for each column in this statement. Note
246
+ # that this may execute the statement in order to obtain the metadata; this
247
+ # makes it a (potentially) expensive operation.
248
+ def types
249
+ must_be_open!
250
+ get_metadata unless @types
251
+ @types
252
+ end
253
+
254
+ # Return an array of the column names for this statement. Note that this
255
+ # may execute the statement in order to obtain the metadata; this makes it
256
+ # a (potentially) expensive operation.
257
+ def columns
258
+ must_be_open!
259
+ get_metadata unless @columns
260
+ return @columns
261
+ end
262
+
263
+ # Returns true if the statement is currently active, meaning it has an
264
+ # open result set.
265
+ def active?
266
+ !done?
267
+ end
268
+
269
+ # Performs a sanity check to ensure that the statement is not
270
+ # closed. If it is, an exception is raised.
271
+ def must_be_open! # :nodoc:
272
+ if closed?
273
+ raise Exception, "cannot use a closed statement"
274
+ end
275
+ end
276
+
277
+ private
278
+ # A convenience method for obtaining the metadata about the query. Note
279
+ # that this will actually execute the SQL, which means it can be a
280
+ # (potentially) expensive operation.
281
+ def get_metadata
282
+ @columns = Array.new(column_count) do |column|
283
+ column_name column
284
+ end
285
+ @types = Array.new(column_count) do |column|
286
+ column_decltype column
287
+ end
288
+ end
289
+ end
290
+ end
@@ -0,0 +1,71 @@
1
+ require 'sqlite3/constants'
2
+
3
+ module SQLite3
4
+
5
+ class Value
6
+ attr_reader :handle
7
+
8
+ def initialize(db, handle)
9
+ @handle = handle
10
+ end
11
+
12
+ def null?
13
+ type == :null
14
+ end
15
+
16
+ def to_blob
17
+ bytes = size
18
+ Blob.new(Driver.sqlite3_value_blob(@handle).to_s(bytes))
19
+ end
20
+
21
+ def length(utf16=false)
22
+ if utf16
23
+ Driver.sqlite3_value_bytes16(@handle)
24
+ else
25
+ Driver.sqlite3_value_bytes(@handle)
26
+ end
27
+ end
28
+
29
+ alias_method :size, :length
30
+
31
+ def to_f
32
+ Driver.sqlite3_value_double(@handle)
33
+ end
34
+
35
+ def to_i
36
+ Driver.sqlite3_value_int(@handle)
37
+ end
38
+
39
+ def to_int64
40
+ Driver.sqlite3_value_int64(@handle)
41
+ end
42
+
43
+ def to_s(utf16=false)
44
+ if utf16
45
+ Driver.sqlite3_result_text16(@handle).to_s
46
+ else
47
+ Driver.sqlite3_value_text(@handle).to_s
48
+ end
49
+ end
50
+
51
+ def type
52
+ case Driver.sqlite3_value_type(@handle)
53
+ when SQLITE_INTEGER then :int
54
+ when SQLITE_FLOAT then :float
55
+ when SQLITE_TEXT then :text
56
+ when SQLITE_BLOB then :blob
57
+ when SQLITE_NULL then :null
58
+ end
59
+ end
60
+
61
+ def native
62
+ case Driver.sqlite3_value_type(@handle)
63
+ when SQLITE_INTEGER then to_int64
64
+ when SQLITE_FLOAT then to_f
65
+ when SQLITE_TEXT then to_s
66
+ when SQLITE_BLOB then to_blob
67
+ when SQLITE_NULL then nil
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,10 @@
1
+ module SQLite3
2
+ MAJOR = 1
3
+ MINOR = 0
4
+ PATCH = 0
5
+ VERSION = [MAJOR, MINOR, PATCH].join('.')
6
+
7
+ def self.libversion
8
+ Driver.sqlite3_libversion().to_s
9
+ end
10
+ end
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'sqlite3/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "sqlite3-fiddle"
8
+ spec.version = SQLite3::VERSION
9
+ spec.authors = ["Vincent Landgraf"]
10
+ spec.email = ["vilandgr+sqlite@googlemail.com"]
11
+
12
+ spec.summary = %q{Ruby bindings for the SQLite3 embedded database - without compiling}
13
+ spec.description = %q{Ruby bindings for the SQLite3 embedded database - without compiling}
14
+ spec.homepage = "https://github.com/threez/sqlite3-fiddle"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.bindir = "exe"
19
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_development_dependency "bundler", "~> 1.7"
23
+ spec.add_development_dependency "rake", "~> 10.0"
24
+ spec.add_development_dependency "minitest", "~> 5.0"
25
+ end
metadata ADDED
@@ -0,0 +1,105 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sqlite3-fiddle
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Vincent Landgraf
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2015-03-09 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.7'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '5.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '5.0'
55
+ description: Ruby bindings for the SQLite3 embedded database - without compiling
56
+ email:
57
+ - vilandgr+sqlite@googlemail.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - ".gitignore"
63
+ - ".ruby-version"
64
+ - ".travis.yml"
65
+ - Gemfile
66
+ - LICENSE
67
+ - README.md
68
+ - Rakefile
69
+ - lib/.DS_Store
70
+ - lib/sqlite3.rb
71
+ - lib/sqlite3/backup.rb
72
+ - lib/sqlite3/constants.rb
73
+ - lib/sqlite3/database.rb
74
+ - lib/sqlite3/driver.rb
75
+ - lib/sqlite3/pragmas.rb
76
+ - lib/sqlite3/resultset.rb
77
+ - lib/sqlite3/statement.rb
78
+ - lib/sqlite3/value.rb
79
+ - lib/sqlite3/version.rb
80
+ - sqlite3-fiddle.gemspec
81
+ homepage: https://github.com/threez/sqlite3-fiddle
82
+ licenses:
83
+ - MIT
84
+ metadata: {}
85
+ post_install_message:
86
+ rdoc_options: []
87
+ require_paths:
88
+ - lib
89
+ required_ruby_version: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ required_rubygems_version: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ requirements: []
100
+ rubyforge_project:
101
+ rubygems_version: 2.4.3
102
+ signing_key:
103
+ specification_version: 4
104
+ summary: Ruby bindings for the SQLite3 embedded database - without compiling
105
+ test_files: []