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.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.ruby-version +1 -0
- data/.travis.yml +6 -0
- data/Gemfile +4 -0
- data/LICENSE +28 -0
- data/README.md +46 -0
- data/Rakefile +9 -0
- data/lib/.DS_Store +0 -0
- data/lib/sqlite3.rb +9 -0
- data/lib/sqlite3/backup.rb +26 -0
- data/lib/sqlite3/constants.rb +140 -0
- data/lib/sqlite3/database.rb +823 -0
- data/lib/sqlite3/driver.rb +115 -0
- data/lib/sqlite3/pragmas.rb +280 -0
- data/lib/sqlite3/resultset.rb +158 -0
- data/lib/sqlite3/statement.rb +290 -0
- data/lib/sqlite3/value.rb +71 -0
- data/lib/sqlite3/version.rb +10 -0
- data/sqlite3-fiddle.gemspec +25 -0
- metadata +105 -0
@@ -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,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: []
|