sqlite-ruby 2.2.0-mswin32 → 2.2.1-mswin32

Sign up to get free protection for your applications and to get access to all the features.
@@ -62,25 +62,25 @@
62
62
  <ul>
63
63
  <li>How do I do a database query?
64
64
  <ul>
65
- <li><a href='#538840882'>I just want an array of the rows&#8230;</a></li>
66
- <li><a href='#538840832'>I&#8217;d like to use a block to iterate through the rows&#8230;</a></li>
67
- <li><a href='#538840792'>I need to get the column names as well as the rows&#8230;</a></li>
68
- <li><a href='#538840732'>I need the result set object itself&#8230;</a></li>
69
- <li><a href='#538840692'>I just want the first row of the result set&#8230;</a></li>
70
- <li><a href='#538840632'>I just want the first value of the first row of the result set&#8230;</a></li>
65
+ <li><a href='#538599180'>I just want an array of the rows&#8230;</a></li>
66
+ <li><a href='#538599140'>I&#8217;d like to use a block to iterate through the rows&#8230;</a></li>
67
+ <li><a href='#538599100'>I need to get the column names as well as the rows&#8230;</a></li>
68
+ <li><a href='#538599060'>I need the result set object itself&#8230;</a></li>
69
+ <li><a href='#538599020'>I just want the first row of the result set&#8230;</a></li>
70
+ <li><a href='#538598980'>I just want the first value of the first row of the result set&#8230;</a></li>
71
71
  </ul>
72
72
  </li>
73
- <li><a href='#538840552'>How do I prepare a statement for repeated execution?</a></li>
74
- <li><a href='#538840502'>How do I use placeholders in an <span class="caps">SQL</span> statement?</a></li>
75
- <li><a href='#538840462'>How do I discover metadata about a query?</a></li>
76
- <li><a href='#538840402'>I&#8217;d like the rows to be indexible by column name.</a></li>
77
- <li><a href='#538840362'>I&#8217;d like the values from a query to be the correct types, instead of String.</a></li>
78
- <li><a href='#538840302'>How do I do a <span class="caps">DDL </span>(insert, update, delete) statement?</a></li>
79
- <li><a href='#538840262'>How do I execute multiple statements in a single string?</a></li>
80
- <li><a href='#538840212'>How do I begin/end a transaction?</a></li>
73
+ <li><a href='#538598910'>How do I prepare a statement for repeated execution?</a></li>
74
+ <li><a href='#538598870'>How do I use placeholders in an <span class="caps">SQL</span> statement?</a></li>
75
+ <li><a href='#538598830'>How do I discover metadata about a query?</a></li>
76
+ <li><a href='#538598790'>I&#8217;d like the rows to be indexible by column name.</a></li>
77
+ <li><a href='#538598750'>I&#8217;d like the values from a query to be the correct types, instead of String.</a></li>
78
+ <li><a href='#538598710'>How do I do a <span class="caps">DDL </span>(insert, update, delete) statement?</a></li>
79
+ <li><a href='#538598670'>How do I execute multiple statements in a single string?</a></li>
80
+ <li><a href='#538598630'>How do I begin/end a transaction?</a></li>
81
81
  </ul>
82
82
  </div>
83
- <a name='538840882'></a>
83
+ <a name='538599180'></a>
84
84
  <div class='faq-title'>How do I do a database query? I just want an array of the rows&#8230;</div>
85
85
  <div class='faq-answer'><p>Use the <a href='http://sqlite-ruby.rubyforge.org/classes/SQLite/Database.html'>Database#execute</a> method. If you don&#8217;t give it a block, it will return an array of all the rows:</p>
86
86
 
@@ -90,7 +90,7 @@
90
90
  db = SQLite::<a href='http://sqlite-ruby.rubyforge.org/classes/SQLite/Database.html'>Database</a>.new( "test.db" )
91
91
  rows = db.execute( "select * from test" )
92
92
  </pre></div>
93
- <a name='538840832'></a>
93
+ <a name='538599140'></a>
94
94
  <div class='faq-title'>How do I do a database query? I&#8217;d like to use a block to iterate through the rows&#8230;</div>
95
95
  <div class='faq-answer'><p>Use the <a href='http://sqlite-ruby.rubyforge.org/classes/SQLite/Database.html'>Database#execute</a> method. If you give it a block, each row of the result will be yielded to the block:</p>
96
96
 
@@ -102,7 +102,7 @@
102
102
  ...
103
103
  end
104
104
  </pre></div>
105
- <a name='538840792'></a>
105
+ <a name='538599100'></a>
106
106
  <div class='faq-title'>How do I do a database query? I need to get the column names as well as the rows&#8230;</div>
107
107
  <div class='faq-answer'><p>Use the <a href='http://sqlite-ruby.rubyforge.org/classes/SQLite/Database.html'>Database#execute2</a> method. This works just like <a href='http://sqlite-ruby.rubyforge.org/classes/SQLite/Database.html'>Database#execute</a>; if you don&#8217;t give it a block, it returns an array of rows; otherwise, it will yield each row to the block. <em>However</em>, the first row returned is always an array of the column names from the query:</p>
108
108
 
@@ -123,7 +123,7 @@
123
123
  end
124
124
  end
125
125
  </pre></div>
126
- <a name='538840732'></a>
126
+ <a name='538599060'></a>
127
127
  <div class='faq-title'>How do I do a database query? I need the result set object itself&#8230;</div>
128
128
  <div class='faq-answer'><p>Sometimes you don&#8217;t want all the rows at once, and yet you&#8217;d like to be able to iterate through the results. For instance, you may want to pass the results to some other function (or series of functions) and have them pull rows from the results on demand. This is more effecient for very large queries.</p>
129
129
 
@@ -167,7 +167,7 @@
167
167
  </pre>
168
168
 
169
169
  <p>In general, <a href='http://sqlite-ruby.rubyforge.org/classes/SQLite/Database.html'>Database#query</a> is not a very good choice for such operations&#8230;</p></div>
170
- <a name='538840692'></a>
170
+ <a name='538599020'></a>
171
171
  <div class='faq-title'>How do I do a database query? I just want the first row of the result set&#8230;</div>
172
172
  <div class='faq-answer'><p>Easy. Just call <a href='http://sqlite-ruby.rubyforge.org/classes/SQLite/Database.html'>Database#get_first_row</a>:</p>
173
173
 
@@ -176,7 +176,7 @@
176
176
  </pre>
177
177
 
178
178
  <p>This also supports bind variables, just like <a href='http://sqlite-ruby.rubyforge.org/classes/SQLite/Database.html'>Database#execute</a> and friends.</p></div>
179
- <a name='538840632'></a>
179
+ <a name='538598980'></a>
180
180
  <div class='faq-title'>How do I do a database query? I just want the first value of the first row of the result set&#8230;</div>
181
181
  <div class='faq-answer'><p>Also easy. Just call <a href='http://sqlite-ruby.rubyforge.org/classes/SQLite/Database.html'>Database#get_first_value</a>:</p>
182
182
 
@@ -185,7 +185,7 @@
185
185
  </pre>
186
186
 
187
187
  <p>This also supports bind variables, just like <a href='http://sqlite-ruby.rubyforge.org/classes/SQLite/Database.html'>Database#execute</a> and friends.</p></div>
188
- <a name='538840552'></a>
188
+ <a name='538598910'></a>
189
189
  <div class='faq-title'>How do I prepare a statement for repeated execution?</div>
190
190
  <div class='faq-answer'><p>If the same statement is going to be executed repeatedly, you can speed things up a bit by <em>preparing</em> the statement. You do this via the <a href='http://sqlite-ruby.rubyforge.org/classes/SQLite/Database.html'>Database#prepare</a> method. It returns a <a href='http://sqlite-ruby.rubyforge.org/classes/SQLite/Statement.html'>Statement</a> object, and you can then invoke #execute on that to get the <a href='http://sqlite-ruby.rubyforge.org/classes/SQLite/ResultSet.html'>ResultSet</a>:</p>
191
191
 
@@ -200,7 +200,7 @@
200
200
  </pre>
201
201
 
202
202
  <p>This is made more useful by the ability to bind variables to placeholders via the <a href='http://sqlite-ruby.rubyforge.org/classes/SQLite/Statement.html'>Statement#bind_param</a> and <a href='http://sqlite-ruby.rubyforge.org/classes/SQLite/Statement.html'>Statement#bind_params</a> methods. (See the next <span class="caps">FAQ</span> for details.)</p></div>
203
- <a name='538840502'></a>
203
+ <a name='538598870'></a>
204
204
  <div class='faq-title'>How do I use placeholders in an <span class="caps">SQL</span> statement?</div>
205
205
  <div class='faq-answer'><p>Placeholders in an <span class="caps">SQL</span> statement take any of the following formats:</p>
206
206
 
@@ -258,7 +258,7 @@
258
258
 
259
259
  stmt.bind_params( "value", "name" =&gt; "bob" )
260
260
  </pre></div>
261
- <a name='538840462'></a>
261
+ <a name='538598830'></a>
262
262
  <div class='faq-title'>How do I discover metadata about a query?</div>
263
263
  <div class='faq-answer'><p>If you ever want to know the names or types of the columns in a result set, you can do it in several ways.</p>
264
264
 
@@ -287,7 +287,7 @@
287
287
  p stmt.columns
288
288
  p stmt.types
289
289
  </pre></div>
290
- <a name='538840402'></a>
290
+ <a name='538598790'></a>
291
291
  <div class='faq-title'>I&#8217;d like the rows to be indexible by column name.</div>
292
292
  <div class='faq-answer'><p>By default, each row from a query is returned as an Array of values. This means that you can only obtain values by their index. Sometimes, however, you would like to obtain values by their column name.</p>
293
293
 
@@ -312,7 +312,7 @@
312
312
  p row[1] == row['column2']
313
313
  end
314
314
  </pre></div>
315
- <a name='538840362'></a>
315
+ <a name='538598750'></a>
316
316
  <div class='faq-title'>I&#8217;d like the values from a query to be the correct types, instead of String.</div>
317
317
  <div class='faq-answer'><p>You can turn on &#8220;type translation&#8221; by setting <a href='http://sqlite-ruby.rubyforge.org/classes/SQLite/Database.html'>Database#type_translation</a> to true:</p>
318
318
 
@@ -347,14 +347,14 @@
347
347
  obj = db.get_first_value( "select thing from objects where name='bob'" )
348
348
  p obj == h
349
349
  </pre></div>
350
- <a name='538840302'></a>
350
+ <a name='538598710'></a>
351
351
  <div class='faq-title'>How do I do a <span class="caps">DDL </span>(insert, update, delete) statement?</div>
352
352
  <div class='faq-answer'><p>You can actually do inserts, updates, and deletes in exactly the same way as selects, but in general the <a href='http://sqlite-ruby.rubyforge.org/classes/SQLite/Database.html'>Database#execute</a> method will be most convenient:</p>
353
353
 
354
354
  <pre>
355
355
  db.execute( "insert into table values ( ?, ? )", *bind_vars )
356
356
  </pre></div>
357
- <a name='538840262'></a>
357
+ <a name='538598670'></a>
358
358
  <div class='faq-title'>How do I execute multiple statements in a single string?</div>
359
359
  <div class='faq-answer'><p>The standard query methods (<a href='http://sqlite-ruby.rubyforge.org/classes/SQLite/Database.html'>Database#execute</a>, <a href='http://sqlite-ruby.rubyforge.org/classes/SQLite/Database.html'>Database#execute2</a>, <a href='http://sqlite-ruby.rubyforge.org/classes/SQLite/Database.html'>Database#query</a>, and <a href='http://sqlite-ruby.rubyforge.org/classes/SQLite/Statement.html'>Statement#execute</a>) will only execute the first statement in the string that is given to them. Thus, if you have a string with multiple <span class="caps">SQL</span> statements, each separated by a string, you can&#8217;t use those methods to execute them all at once.</p>
360
360
 
@@ -376,7 +376,7 @@
376
376
  </pre>
377
377
 
378
378
  <p>Unlike the other query methods, <a href='http://sqlite-ruby.rubyforge.org/classes/SQLite/Database.html'>Database#execute_batch</a> accepts no block. It will also only ever return <ins>nil</ins>. Thus, it is really only suitable for batch processing of <span class="caps">DDL</span> statements.</p></div>
379
- <a name='538840212'></a>
379
+ <a name='538598630'></a>
380
380
  <div class='faq-title'>How do I begin/end a transaction?</div>
381
381
  <div class='faq-answer'><p>Use <a href='http://sqlite-ruby.rubyforge.org/classes/SQLite/Database.html'>Database#transaction</a> to start a transaction. If you give it a block, the block will be automatically committed at the end of the block, unless an exception was raised, in which case the transaction will be rolled back. (Never explicitly call <a href='http://sqlite-ruby.rubyforge.org/classes/SQLite/Database.html'>Database#commit</a> or <a href='http://sqlite-ruby.rubyforge.org/classes/SQLite/Database.html'>Database#rollback</a> inside of a transaction block&#8212;you&#8217;ll get errors when the block terminates!)</p>
382
382
 
@@ -57,8 +57,8 @@ module SQLite
57
57
  # An array of the column types for this result set (may be empty)
58
58
  attr_reader :types
59
59
 
60
- # Create a new ResultSet attached to the given database and virtual
61
- # machine instances.
60
+ # Create a new ResultSet attached to the given database, using the
61
+ # given sql text.
62
62
  def initialize( db, sql )
63
63
  @db = db
64
64
  @sql = sql
@@ -53,7 +53,7 @@ module SQLite
53
53
  def initialize( db, sql )
54
54
  @db = db
55
55
  @statement = ParsedStatement.new( sql )
56
- @remainder = @statement.trailing
56
+ @remainder = @statement.trailing.strip
57
57
  @sql = @statement.to_s
58
58
  end
59
59
 
@@ -36,7 +36,7 @@ module SQLite
36
36
 
37
37
  MAJOR = 2
38
38
  MINOR = 2
39
- TINY = 0
39
+ TINY = 1
40
40
 
41
41
  STRING = [ MAJOR, MINOR, TINY ].join( "." )
42
42
 
Binary file
@@ -0,0 +1,34 @@
1
+ #--
2
+ # =============================================================================
3
+ # Copyright (c) 2004, Jamis Buck (jgb3@email.byu.edu)
4
+ # All rights reserved.
5
+ #
6
+ # Redistribution and use in source and binary forms, with or without
7
+ # modification, are permitted provided that the following conditions are met:
8
+ #
9
+ # * Redistributions of source code must retain the above copyright notice,
10
+ # this list of conditions and the following disclaimer.
11
+ #
12
+ # * Redistributions in binary form must reproduce the above copyright
13
+ # notice, this list of conditions and the following disclaimer in the
14
+ # documentation and/or other materials provided with the distribution.
15
+ #
16
+ # * The names of its contributors may not be used to endorse or promote
17
+ # products derived from this software without specific prior written
18
+ # permission.
19
+ #
20
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
24
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
+ # =============================================================================
31
+ #++
32
+
33
+ require 'sqlite/database'
34
+ require 'sqlite/version'
@@ -0,0 +1,682 @@
1
+ #--
2
+ # =============================================================================
3
+ # Copyright (c) 2004, Jamis Buck (jgb3@email.byu.edu)
4
+ # All rights reserved.
5
+ #
6
+ # Redistribution and use in source and binary forms, with or without
7
+ # modification, are permitted provided that the following conditions are met:
8
+ #
9
+ # * Redistributions of source code must retain the above copyright notice,
10
+ # this list of conditions and the following disclaimer.
11
+ #
12
+ # * Redistributions in binary form must reproduce the above copyright
13
+ # notice, this list of conditions and the following disclaimer in the
14
+ # documentation and/or other materials provided with the distribution.
15
+ #
16
+ # * The names of its contributors may not be used to endorse or promote
17
+ # products derived from this software without specific prior written
18
+ # permission.
19
+ #
20
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
24
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
+ # =============================================================================
31
+ #++
32
+
33
+ require 'base64'
34
+ require 'sqlite_api'
35
+ require 'sqlite/pragmas'
36
+ require 'sqlite/statement'
37
+ require 'sqlite/translator'
38
+
39
+ module SQLite
40
+
41
+ # The Database class encapsulates a single connection to a SQLite database.
42
+ # Its usage is very straightforward:
43
+ #
44
+ # require 'sqlite'
45
+ #
46
+ # db = SQLite::Database.new( "data.db" )
47
+ #
48
+ # db.execute( "select * from table" ) do |row|
49
+ # p row
50
+ # end
51
+ #
52
+ # db.close
53
+ #
54
+ # It wraps the lower-level methods provides by the API module, include
55
+ # includes the Pragmas module for access to various pragma convenience
56
+ # methods.
57
+ #
58
+ # The Database class provides type translation services as well, by which
59
+ # the SQLite data types (which are all represented as strings) may be
60
+ # converted into their corresponding types (as defined in the schemas
61
+ # for their tables). This translation only occurs when querying data from
62
+ # the database--insertions and updates are all still typeless.
63
+ #
64
+ # Furthermore, the Database class has been designed to work well with the
65
+ # ArrayFields module from Ara Howard. If you require the ArrayFields
66
+ # module before performing a query, and if you have not enabled results as
67
+ # hashes, then the results will all be indexible by field name.
68
+ class Database
69
+ include SQLite::Pragmas
70
+
71
+ # Opens the database contained in the given file. This just calls #new,
72
+ # passing 0 as the mode parameter. This returns the new Database
73
+ # instance.
74
+ def self.open( file_name )
75
+ new( file_name, 0 )
76
+ end
77
+
78
+ # Quotes the given string, making it safe to use in an SQL statement.
79
+ # It replaces all instances of the single-quote character with two
80
+ # single-quote characters. The modified string is returned.
81
+ def self.quote( string )
82
+ string.gsub( /'/, "''" )
83
+ end
84
+
85
+ # Returns a string that represents the serialization of the given object.
86
+ # The string may safely be used in an SQL statement.
87
+ def self.encode( object )
88
+ Base64.encode64( Marshal.dump( object ) ).strip
89
+ end
90
+
91
+ # Unserializes the object contained in the given string. The string must be
92
+ # one that was returned by #encode.
93
+ def self.decode( string )
94
+ Marshal.load( Base64.decode64( string ) )
95
+ end
96
+
97
+ # Return +true+ if the string is a valid (ie, parsable) SQL statement, and
98
+ # +false+ otherwise.
99
+ def self.complete?( string )
100
+ SQLite::API.complete( string )
101
+ end
102
+
103
+ # The low-level opaque database handle that this object wraps.
104
+ attr_reader :handle
105
+
106
+ # A boolean that indicates whether rows in result sets should be returned
107
+ # as hashes or not. By default, rows are returned as arrays.
108
+ attr_accessor :results_as_hash
109
+
110
+ # Create a new Database object that opens the given file. The mode
111
+ # parameter has no meaning yet, and may be omitted. If the file does not
112
+ # exist, it will be created if possible.
113
+ #
114
+ # By default, the new database will return result rows as arrays
115
+ # (#results_as_hash) and has type translation disabled (#type_translation=).
116
+ def initialize( file_name, mode=0 )
117
+ @handle = SQLite::API.open( file_name, mode )
118
+ @closed = false
119
+ @results_as_hash = false
120
+ @type_translation = false
121
+ @translator = nil
122
+ end
123
+
124
+ # Return the type translator employed by this database instance. Each
125
+ # database instance has its own type translator; this allows for different
126
+ # type handlers to be installed in each instance without affecting other
127
+ # instances. Furthermore, the translators are instantiated lazily, so that
128
+ # if a database does not use type translation, it will not be burdened by
129
+ # the overhead of a useless type translator. (See the Translator class.)
130
+ def translator
131
+ @translator ||= Translator.new
132
+ end
133
+
134
+ # Returns +true+ if type translation is enabled for this database, or
135
+ # +false+ otherwise.
136
+ def type_translation
137
+ @type_translation
138
+ end
139
+
140
+ # Enable or disable type translation for this database.
141
+ def type_translation=( mode )
142
+ @type_translation = mode
143
+ end
144
+
145
+ # Closes this database. No checks are done to ensure that a database is not
146
+ # closed more than once, and closing a database more than once can be
147
+ # catastrophic.
148
+ def close
149
+ SQLite::API.close( @handle )
150
+ @closed = true
151
+ end
152
+
153
+ # Returns +true+ if this database instance has been closed (see #close).
154
+ def closed?
155
+ @closed
156
+ end
157
+
158
+ # Returns a Statement object representing the given SQL. This does not
159
+ # execute the statement; it merely prepares the statement for execution.
160
+ def prepare( sql )
161
+ Statement.new( self, sql )
162
+ end
163
+
164
+ # Executes the given SQL statement. If additional parameters are given,
165
+ # they are treated as bind variables, and are bound to the placeholders in
166
+ # the query.
167
+ #
168
+ # Each placeholder must match one of the following formats:
169
+ #
170
+ # * <tt>?</tt>
171
+ # * <tt>?nnn</tt>
172
+ # * <tt>:word</tt>
173
+ # * <tt>:word:</tt>
174
+ #
175
+ # where _nnn_ is an integer value indicating the index of the bind
176
+ # variable to be bound at that position, and _word_ is an alphanumeric
177
+ # identifier for that placeholder. For "<tt>?</tt>", an index is
178
+ # automatically assigned of one greater than the previous index used
179
+ # (or 1, if it is the first).
180
+ #
181
+ # Note that if any of the values passed to this are hashes, then the
182
+ # key/value pairs are each bound separately, with the key being used as
183
+ # the name of the placeholder to bind the value to.
184
+ #
185
+ # The block is optional. If given, it will be invoked for each row returned
186
+ # by the query. Otherwise, any results are accumulated into an array and
187
+ # returned wholesale.
188
+ #
189
+ # See also #execute2, #execute_batch and #query for additional ways of
190
+ # executing statements.
191
+ def execute( sql, *bind_vars )
192
+ stmt = prepare( sql )
193
+ stmt.bind_params( *bind_vars )
194
+ result = stmt.execute
195
+ begin
196
+ if block_given?
197
+ result.each { |row| yield row }
198
+ else
199
+ return result.inject( [] ) { |arr,row| arr << row; arr }
200
+ end
201
+ ensure
202
+ result.close
203
+ end
204
+ end
205
+
206
+ # Executes the given SQL statement, exactly as with #execute. However, the
207
+ # first row returned (either via the block, or in the returned array) is
208
+ # always the names of the columns. Subsequent rows correspond to the data
209
+ # from the result set.
210
+ #
211
+ # Thus, even if the query itself returns no rows, this method will always
212
+ # return at least one row--the names of the columns.
213
+ #
214
+ # See also #execute, #execute_batch and #query for additional ways of
215
+ # executing statements.
216
+ def execute2( sql, *bind_vars )
217
+ stmt = prepare( sql )
218
+ stmt.bind_params( *bind_vars )
219
+ result = stmt.execute
220
+ begin
221
+ if block_given?
222
+ yield result.columns
223
+ result.each { |row| yield row }
224
+ else
225
+ return result.inject( [ result.columns ] ) { |arr,row| arr << row; arr }
226
+ end
227
+ ensure
228
+ result.close
229
+ end
230
+ end
231
+
232
+ # Executes all SQL statements in the given string. By contrast, the other
233
+ # means of executing queries will only execute the first statement in the
234
+ # string, ignoring all subsequent statements. This will execute each one
235
+ # in turn. The same bind parameters, if given, will be applied to each
236
+ # statement.
237
+ #
238
+ # This always returns +nil+, making it unsuitable for queries that return
239
+ # rows.
240
+ def execute_batch( sql, *bind_vars )
241
+ loop do
242
+ stmt = prepare( sql )
243
+ stmt.bind_params *bind_vars
244
+ stmt.execute
245
+ sql = stmt.remainder
246
+ break if sql.length < 1
247
+ end
248
+ nil
249
+ end
250
+
251
+ # This does like #execute and #execute2 (binding variables and so forth),
252
+ # but instead of yielding each row from the result set, this will yield the
253
+ # ResultSet instance itself (q.v.). If no block is given, the ResultSet
254
+ # instance will be returned.
255
+ def query( sql, *bind_vars, &block ) # :yields: result_set
256
+ stmt = prepare( sql )
257
+ stmt.bind_params( *bind_vars )
258
+ stmt.execute( &block )
259
+ end
260
+
261
+ # A convenience method for obtaining the first row of a result set, and
262
+ # discarding all others. It is otherwise identical to #execute.
263
+ #
264
+ # See also #get_first_value.
265
+ def get_first_row( sql, *bind_vars )
266
+ execute( sql, *bind_vars ) { |row| return row }
267
+ nil
268
+ end
269
+
270
+ # A convenience method for obtaining the first value of the first row of a
271
+ # result set, and discarding all other values and rows. It is otherwise
272
+ # identical to #execute.
273
+ #
274
+ # See also #get_first_row.
275
+ def get_first_value( sql, *bind_vars )
276
+ execute( sql, *bind_vars ) { |row| return row[0] }
277
+ nil
278
+ end
279
+
280
+ # Obtains the unique row ID of the last row to be inserted by this Database
281
+ # instance.
282
+ def last_insert_row_id
283
+ SQLite::API.last_insert_row_id( @handle )
284
+ end
285
+
286
+ # Returns the number of changes made to this database instance by the last
287
+ # operation performed. Note that a "delete from table" without a where
288
+ # clause will not affect this value.
289
+ def changes
290
+ SQLite::API.changes( @handle )
291
+ end
292
+
293
+ # Interrupts the currently executing operation, causing it to abort.
294
+ def interrupt
295
+ SQLite::API.interrupt( @handle )
296
+ end
297
+
298
+ # Register a busy handler with this database instance. When a requested
299
+ # resource is busy, this handler will be invoked. If the handler returns
300
+ # +false+, the operation will be aborted; otherwise, the resource will
301
+ # be requested again.
302
+ #
303
+ # The handler will be invoked with the name of the resource that was
304
+ # busy, and the number of times it has been retried.
305
+ #
306
+ # See also #busy_timeout.
307
+ def busy_handler( &block ) # :yields: resource, retries
308
+ SQLite::API.busy_handler( @handle, block )
309
+ end
310
+
311
+ # Indicates that if a request for a resource terminates because that
312
+ # resource is busy, SQLite should wait for the indicated number of
313
+ # milliseconds before trying again. By default, SQLite does not retry
314
+ # busy resources. To restore the default behavior, send 0 as the
315
+ # +ms+ parameter.
316
+ #
317
+ # See also #busy_handler.
318
+ def busy_timeout( ms )
319
+ SQLite::API.busy_timeout( @handle, ms )
320
+ end
321
+
322
+ # Creates a new function for use in SQL statements. It will be added as
323
+ # +name+, with the given +arity+. (For variable arity functions, use
324
+ # -1 for the arity.) If +type+ is non-nil, it should either be an
325
+ # integer (indicating that the type of the function is always the
326
+ # type of the argument at that index), or one of the symbols
327
+ # <tt>:numeric</tt>, <tt>:text</tt>, <tt>:args</tt> (in which case
328
+ # the function is, respectively, numeric, textual, or the same type as
329
+ # its arguments).
330
+ #
331
+ # The block should accept at least one parameter--the FunctionProxy
332
+ # instance that wraps this function invocation--and any other
333
+ # arguments it needs (up to its arity).
334
+ #
335
+ # The block does not return a value directly. Instead, it will invoke
336
+ # the FunctionProxy#set_result method on the +func+ parameter and
337
+ # indicate the return value that way.
338
+ #
339
+ # Example:
340
+ #
341
+ # db.create_function( "maim", 1, :text ) do |func, value|
342
+ # if value.nil?
343
+ # func.set_value nil
344
+ # else
345
+ # func.set_value value.split(//).sort.join
346
+ # end
347
+ # end
348
+ #
349
+ # puts db.get_first_value( "select maim(name) from table" )
350
+ def create_function( name, arity, type=nil, &block ) # :yields: func, *args
351
+ case type
352
+ when :numeric
353
+ type = SQLite::API::NUMERIC
354
+ when :text
355
+ type = SQLite::API::TEXT
356
+ when :args
357
+ type = SQLite::API::ARGS
358
+ end
359
+
360
+ callback = proc do |func,*args|
361
+ begin
362
+ block.call( FunctionProxy.new( func ), *args )
363
+ rescue Exception => e
364
+ SQLite::API.set_result_error( func, "#{e.message} (#{e.class})" )
365
+ end
366
+ end
367
+
368
+ SQLite::API.create_function( @handle, name, arity, callback )
369
+ SQLite::API.function_type( @handle, name, type ) if type
370
+
371
+ self
372
+ end
373
+
374
+ # Creates a new aggregate function for use in SQL statements. Aggregate
375
+ # functions are functions that apply over every row in the result set,
376
+ # instead of over just a single row. (A very common aggregate function
377
+ # is the "count" function, for determining the number of rows that match
378
+ # a query.)
379
+ #
380
+ # The new function will be added as +name+, with the given +arity+. (For
381
+ # variable arity functions, use -1 for the arity.) If +type+ is non-nil,
382
+ # it should be a value as described in #create_function.
383
+ #
384
+ # The +step+ parameter must be a proc object that accepts as its first
385
+ # parameter a FunctionProxy instance (representing the function
386
+ # invocation), with any subsequent parameters (up to the function's arity).
387
+ # The +step+ callback will be invoked once for each row of the result set.
388
+ #
389
+ # The +finalize+ parameter must be a +proc+ object that accepts only a
390
+ # single parameter, the FunctionProxy instance representing the current
391
+ # function invocation. It should invoke FunctionProxy#set_result to
392
+ # store the result of the function.
393
+ #
394
+ # Example:
395
+ #
396
+ # step = proc do |func, value|
397
+ # func[ :total ] ||= 0
398
+ # func[ :total ] += ( value ? value.length : 0 )
399
+ # end
400
+ #
401
+ # finalize = proc do |func|
402
+ # func.set_result( func[ :total ] || 0 )
403
+ # end
404
+ #
405
+ # db.create_aggregate( "lengths", 1, step, finalize, :numeric )
406
+ #
407
+ # puts db.get_first_value( "select lengths(name) from table" )
408
+ #
409
+ # See also #create_aggregate_handler for a more object-oriented approach to
410
+ # aggregate functions.
411
+ def create_aggregate( name, arity, step, finalize, type=nil )
412
+ case type
413
+ when :numeric
414
+ type = SQLite::API::NUMERIC
415
+ when :text
416
+ type = SQLite::API::TEXT
417
+ when :args
418
+ type = SQLite::API::ARGS
419
+ end
420
+
421
+ step_callback = proc do |func,*args|
422
+ ctx = SQLite::API.aggregate_context( func )
423
+ unless ctx[:__error]
424
+ begin
425
+ step.call( FunctionProxy.new( func, ctx ), *args )
426
+ rescue Exception => e
427
+ ctx[:__error] = e
428
+ end
429
+ end
430
+ end
431
+
432
+ finalize_callback = proc do |func|
433
+ ctx = SQLite::API.aggregate_context( func )
434
+ unless ctx[:__error]
435
+ begin
436
+ finalize.call( FunctionProxy.new( func, ctx ) )
437
+ rescue Exception => e
438
+ SQLite::API.set_result_error( func, "#{e.message} (#{e.class})" )
439
+ end
440
+ else
441
+ e = ctx[:__error]
442
+ SQLite::API.set_result_error( func, "#{e.message} (#{e.class})" )
443
+ end
444
+ end
445
+
446
+ SQLite::API.create_aggregate( @handle, name, arity,
447
+ step_callback, finalize_callback )
448
+
449
+ SQLite::API.function_type( @handle, name, type ) if type
450
+
451
+ self
452
+ end
453
+
454
+ # This is another approach to creating an aggregate function (see
455
+ # #create_aggregate). Instead of explicitly specifying the name,
456
+ # callbacks, arity, and type, you specify a factory object
457
+ # (the "handler") that knows how to obtain all of that information. The
458
+ # handler should respond to the following messages:
459
+ #
460
+ # +function_type+:: corresponds to the +type+ parameter of
461
+ # #create_aggregate. This is an optional message, and if
462
+ # the handler does not respond to it, the function type
463
+ # will not be set for this function.
464
+ # +arity+:: corresponds to the +arity+ parameter of #create_aggregate. This
465
+ # message is optional, and if the handler does not respond to it,
466
+ # the function will have an arity of -1.
467
+ # +name+:: this is the name of the function. The handler _must_ implement
468
+ # this message.
469
+ # +new+:: this must be implemented by the handler. It should return a new
470
+ # instance of the object that will handle a specific invocation of
471
+ # the function.
472
+ #
473
+ # The handler instance (the object returned by the +new+ message, described
474
+ # above), must respond to the following messages:
475
+ #
476
+ # +step+:: this is the method that will be called for each step of the
477
+ # aggregate function's evaluation. It should implement the same
478
+ # signature as the +step+ callback for #create_aggregate.
479
+ # +finalize+:: this is the method that will be called to finalize the
480
+ # aggregate function's evaluation. It should implement the
481
+ # same signature as the +finalize+ callback for
482
+ # #create_aggregate.
483
+ #
484
+ # Example:
485
+ #
486
+ # class LengthsAggregateHandler
487
+ # def self.function_type; :numeric; end
488
+ # def self.arity; 1; end
489
+ #
490
+ # def initialize
491
+ # @total = 0
492
+ # end
493
+ #
494
+ # def step( ctx, name )
495
+ # @total += ( name ? name.length : 0 )
496
+ # end
497
+ #
498
+ # def finalize( ctx )
499
+ # ctx.set_result( @total )
500
+ # end
501
+ # end
502
+ #
503
+ # db.create_aggregate_handler( LengthsAggregateHandler )
504
+ # puts db.get_first_value( "select lengths(name) from A" )
505
+ def create_aggregate_handler( handler )
506
+ type = nil
507
+ arity = -1
508
+
509
+ type = handler.function_type if handler.respond_to?(:function_type)
510
+ arity = handler.arity if handler.respond_to?(:arity)
511
+ name = handler.name
512
+
513
+ case type
514
+ when :numeric
515
+ type = SQLite::API::NUMERIC
516
+ when :text
517
+ type = SQLite::API::TEXT
518
+ when :args
519
+ type = SQLite::API::ARGS
520
+ end
521
+
522
+ step = proc do |func,*args|
523
+ ctx = SQLite::API.aggregate_context( func )
524
+ unless ctx[ :__error ]
525
+ ctx[ :handler ] ||= handler.new
526
+ begin
527
+ ctx[ :handler ].step( FunctionProxy.new( func, ctx ), *args )
528
+ rescue Exception => e
529
+ ctx[ :__error ] = e
530
+ end
531
+ end
532
+ end
533
+
534
+ finalize = proc do |func|
535
+ ctx = SQLite::API.aggregate_context( func )
536
+ unless ctx[ :__error ]
537
+ ctx[ :handler ] ||= handler.new
538
+ begin
539
+ ctx[ :handler ].finalize( FunctionProxy.new( func, ctx ) )
540
+ rescue Exception => e
541
+ ctx[ :__error ] = e
542
+ end
543
+ end
544
+
545
+ if ctx[ :__error ]
546
+ e = ctx[ :__error ]
547
+ SQLite::API.set_result_error( func, "#{e.message} (#{e.class})" )
548
+ end
549
+ end
550
+
551
+ SQLite::API.create_aggregate( @handle, name, arity, step, finalize )
552
+ SQLite::API.function_type( @handle, name, type ) if type
553
+
554
+ self
555
+ end
556
+
557
+ # Begins a new transaction. Note that nested transactions are not allowed
558
+ # by SQLite, so attempting to nest a transaction will result in a runtime
559
+ # exception.
560
+ #
561
+ # If a block is given, the database instance is yielded to it, and the
562
+ # transaction is committed when the block terminates. If the block
563
+ # raises an exception, a rollback will be performed instead. Note that if
564
+ # a block is given, #commit and #rollback should never be called
565
+ # explicitly or you'll get an error when the block terminates.
566
+ #
567
+ # If a block is not given, it is the caller's responsibility to end the
568
+ # transaction explicitly, either by calling #commit, or by calling
569
+ # #rollback.
570
+ def transaction
571
+ execute "begin transaction"
572
+ @transaction_active = true
573
+
574
+ if block_given?
575
+ abort = false
576
+ begin
577
+ yield self
578
+ rescue Exception
579
+ abort = true
580
+ raise
581
+ ensure
582
+ abort and rollback or commit
583
+ end
584
+ end
585
+
586
+ true
587
+ end
588
+
589
+ # Commits the current transaction. If there is no current transaction,
590
+ # this will cause an error to be raised. This returns +true+, in order
591
+ # to allow it to be used in idioms like
592
+ # <tt>abort? and rollback or commit</tt>.
593
+ def commit
594
+ execute "commit transaction"
595
+ @transaction_active = false
596
+ true
597
+ end
598
+
599
+ # Rolls the current transaction back. If there is no current transaction,
600
+ # this will cause an error to be raised. This returns +true+, in order
601
+ # to allow it to be used in idioms like
602
+ # <tt>abort? and rollback or commit</tt>.
603
+ def rollback
604
+ execute "rollback transaction"
605
+ @transaction_active = false
606
+ true
607
+ end
608
+
609
+ # Returns +true+ if there is a transaction active, and +false+ otherwise.
610
+ def transaction_active?
611
+ @transaction_active
612
+ end
613
+
614
+ # A helper class for dealing with custom functions (see #create_function,
615
+ # #create_aggregate, and #create_aggregate_handler). It encapsulates the
616
+ # opaque function object that represents the current invocation. It also
617
+ # provides more convenient access to the API functions that operate on
618
+ # the function object.
619
+ #
620
+ # This class will almost _always_ be instantiated indirectly, by working
621
+ # with the create methods mentioned above.
622
+ class FunctionProxy
623
+
624
+ # Create a new FunctionProxy that encapsulates the given +func+ object.
625
+ # If context is non-nil, the functions context will be set to that. If
626
+ # it is non-nil, it must quack like a Hash. If it is nil, then none of
627
+ # the context functions will be available.
628
+ def initialize( func, context=nil )
629
+ @func = func
630
+ @context = context
631
+ end
632
+
633
+ # Set the result of the function to the given value. The function will
634
+ # then return this value.
635
+ def set_result( result )
636
+ SQLite::API.set_result( @func, result )
637
+ end
638
+
639
+ # Set the result of the function to the given error message, which must
640
+ # be a string. The function will then return that error.
641
+ def set_error( error )
642
+ SQLite::API.set_result_error( @func, error )
643
+ end
644
+
645
+ # (Only available to aggregate functions.) Returns the number of rows
646
+ # that the aggregate has processed so far. This will include the current
647
+ # row, and so will always return at least 1.
648
+ def count
649
+ ensure_aggregate!
650
+ SQLite::API.aggregate_count( @func )
651
+ end
652
+
653
+ # Returns the value with the given key from the context. This is only
654
+ # available to aggregate functions.
655
+ def []( key )
656
+ ensure_aggregate!
657
+ @context[ key ]
658
+ end
659
+
660
+ # Sets the value with the given key in the context. This is only
661
+ # available to aggregate functions.
662
+ def []=( key, value )
663
+ ensure_aggregate!
664
+ @context[ key ] = value
665
+ end
666
+
667
+ # A function for performing a sanity check, to ensure that the function
668
+ # being invoked is an aggregate function. This is implied by the
669
+ # existence of the context variable.
670
+ def ensure_aggregate!
671
+ unless @context
672
+ raise Exceptions::MisuseException, "function is not an aggregate"
673
+ end
674
+ end
675
+ private :ensure_aggregate!
676
+
677
+ end
678
+
679
+ end
680
+
681
+ end
682
+