sqlite3 2.0.0-x86_64-linux-musl

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,701 @@
1
+ require "sqlite3/constants"
2
+ require "sqlite3/errors"
3
+ require "sqlite3/pragmas"
4
+ require "sqlite3/statement"
5
+ require "sqlite3/value"
6
+
7
+ module SQLite3
8
+ # The Database class encapsulates a single connection to a SQLite3 database.
9
+ # Its usage is very straightforward:
10
+ #
11
+ # require 'sqlite3'
12
+ #
13
+ # SQLite3::Database.new( "data.db" ) do |db|
14
+ # db.execute( "select * from table" ) do |row|
15
+ # p row
16
+ # end
17
+ # end
18
+ #
19
+ # It wraps the lower-level methods provided by the selected driver, and
20
+ # includes the Pragmas module for access to various pragma convenience
21
+ # methods.
22
+ #
23
+ # The Database class provides type translation services as well, by which
24
+ # the SQLite3 data types (which are all represented as strings) may be
25
+ # converted into their corresponding types (as defined in the schemas
26
+ # for their tables). This translation only occurs when querying data from
27
+ # the database--insertions and updates are all still typeless.
28
+ #
29
+ # Furthermore, the Database class has been designed to work well with the
30
+ # ArrayFields module from Ara Howard. If you require the ArrayFields
31
+ # module before performing a query, and if you have not enabled results as
32
+ # hashes, then the results will all be indexible by field name.
33
+ #
34
+ # Thread safety:
35
+ #
36
+ # When `SQLite3.threadsafe?` returns true, it is safe to share instances of
37
+ # the database class among threads without adding specific locking. Other
38
+ # object instances may require applications to provide their own locks if
39
+ # they are to be shared among threads. Please see the README.md for more
40
+ # information.
41
+ class Database
42
+ attr_reader :collations
43
+
44
+ include Pragmas
45
+
46
+ class << self
47
+ # Without block works exactly as new.
48
+ # With block, like new closes the database at the end, but unlike new
49
+ # returns the result of the block instead of the database instance.
50
+ def open(*args)
51
+ database = new(*args)
52
+
53
+ if block_given?
54
+ begin
55
+ yield database
56
+ ensure
57
+ database.close
58
+ end
59
+ else
60
+ database
61
+ end
62
+ end
63
+
64
+ # Quotes the given string, making it safe to use in an SQL statement.
65
+ # It replaces all instances of the single-quote character with two
66
+ # single-quote characters. The modified string is returned.
67
+ def quote(string)
68
+ string.gsub("'", "''")
69
+ end
70
+ end
71
+
72
+ # A boolean that indicates whether rows in result sets should be returned
73
+ # as hashes or not. By default, rows are returned as arrays.
74
+ attr_accessor :results_as_hash
75
+
76
+ # call-seq: SQLite3::Database.new(file, options = {})
77
+ #
78
+ # Create a new Database object that opens the given file.
79
+ #
80
+ # Supported permissions +options+:
81
+ # - the default mode is <tt>READWRITE | CREATE</tt>
82
+ # - +:readonly+: boolean (default false), true to set the mode to +READONLY+
83
+ # - +:readwrite+: boolean (default false), true to set the mode to +READWRITE+
84
+ # - +:flags+: set the mode to a combination of SQLite3::Constants::Open flags.
85
+ #
86
+ # Supported encoding +options+:
87
+ # - +:utf16+: boolean (default false), is the filename's encoding UTF-16 (only needed if the filename encoding is not UTF_16LE or BE)
88
+ #
89
+ # Other supported +options+:
90
+ # - +:strict+: boolean (default false), disallow the use of double-quoted string literals (see https://www.sqlite.org/quirks.html#double_quoted_string_literals_are_accepted)
91
+ # - +:results_as_hash+: boolean (default false), return rows as hashes instead of arrays
92
+ # - +:default_transaction_mode+: one of +:deferred+ (default), +:immediate+, or +:exclusive+. If a mode is not specified in a call to #transaction, this will be the default transaction mode.
93
+ #
94
+ def initialize file, options = {}, zvfs = nil
95
+ mode = Constants::Open::READWRITE | Constants::Open::CREATE
96
+
97
+ file = file.to_path if file.respond_to? :to_path
98
+ if file.encoding == ::Encoding::UTF_16LE || file.encoding == ::Encoding::UTF_16BE || options[:utf16]
99
+ open16 file
100
+ else
101
+ # The three primary flag values for sqlite3_open_v2 are:
102
+ # SQLITE_OPEN_READONLY
103
+ # SQLITE_OPEN_READWRITE
104
+ # SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE -- always used for sqlite3_open and sqlite3_open16
105
+ mode = Constants::Open::READONLY if options[:readonly]
106
+
107
+ if options[:readwrite]
108
+ raise "conflicting options: readonly and readwrite" if options[:readonly]
109
+ mode = Constants::Open::READWRITE
110
+ end
111
+
112
+ if options[:flags]
113
+ if options[:readonly] || options[:readwrite]
114
+ raise "conflicting options: flags with readonly and/or readwrite"
115
+ end
116
+ mode = options[:flags]
117
+ end
118
+
119
+ open_v2 file.encode("utf-8"), mode, zvfs
120
+
121
+ if options[:strict]
122
+ disable_quirk_mode
123
+ end
124
+ end
125
+
126
+ @tracefunc = nil
127
+ @authorizer = nil
128
+ @busy_handler = nil
129
+ @progress_handler = nil
130
+ @collations = {}
131
+ @functions = {}
132
+ @results_as_hash = options[:results_as_hash]
133
+ @readonly = mode & Constants::Open::READONLY != 0
134
+ @default_transaction_mode = options[:default_transaction_mode] || :deferred
135
+
136
+ if block_given?
137
+ begin
138
+ yield self
139
+ ensure
140
+ close
141
+ end
142
+ end
143
+ end
144
+
145
+ # call-seq: db.encoding
146
+ #
147
+ # Fetch the encoding set on this database
148
+ def encoding
149
+ prepare("PRAGMA encoding") { |stmt| Encoding.find(stmt.first.first) }
150
+ end
151
+
152
+ # Installs (or removes) a block that will be invoked for every access
153
+ # to the database. If the block returns 0 (or +nil+), the statement
154
+ # is allowed to proceed. Returning 1 causes an authorization error to
155
+ # occur, and returning 2 causes the access to be silently denied.
156
+ def authorizer(&block)
157
+ self.authorizer = block
158
+ end
159
+
160
+ # Returns a Statement object representing the given SQL. This does not
161
+ # execute the statement; it merely prepares the statement for execution.
162
+ #
163
+ # The Statement can then be executed using Statement#execute.
164
+ #
165
+ def prepare sql
166
+ stmt = SQLite3::Statement.new(self, sql)
167
+ return stmt unless block_given?
168
+
169
+ begin
170
+ yield stmt
171
+ ensure
172
+ stmt.close unless stmt.closed?
173
+ end
174
+ end
175
+
176
+ # Returns the filename for the database named +db_name+. +db_name+ defaults
177
+ # to "main". Main return `nil` or an empty string if the database is
178
+ # temporary or in-memory.
179
+ def filename db_name = "main"
180
+ db_filename db_name
181
+ end
182
+
183
+ # Executes the given SQL statement. If additional parameters are given,
184
+ # they are treated as bind variables, and are bound to the placeholders in
185
+ # the query.
186
+ #
187
+ # Note that if any of the values passed to this are hashes, then the
188
+ # key/value pairs are each bound separately, with the key being used as
189
+ # the name of the placeholder to bind the value to.
190
+ #
191
+ # The block is optional. If given, it will be invoked for each row returned
192
+ # by the query. Otherwise, any results are accumulated into an array and
193
+ # returned wholesale.
194
+ #
195
+ # See also #execute2, #query, and #execute_batch for additional ways of
196
+ # executing statements.
197
+ def execute sql, bind_vars = [], *args, &block
198
+ prepare(sql) do |stmt|
199
+ stmt.bind_params(bind_vars)
200
+ stmt = build_result_set stmt
201
+
202
+ if block
203
+ stmt.each do |row|
204
+ yield row
205
+ end
206
+ else
207
+ stmt.to_a.freeze
208
+ end
209
+ end
210
+ end
211
+
212
+ # Executes the given SQL statement, exactly as with #execute. However, the
213
+ # first row returned (either via the block, or in the returned array) is
214
+ # always the names of the columns. Subsequent rows correspond to the data
215
+ # from the result set.
216
+ #
217
+ # Thus, even if the query itself returns no rows, this method will always
218
+ # return at least one row--the names of the columns.
219
+ #
220
+ # See also #execute, #query, and #execute_batch for additional ways of
221
+ # executing statements.
222
+ def execute2(sql, *bind_vars)
223
+ prepare(sql) do |stmt|
224
+ result = stmt.execute(*bind_vars)
225
+ if block_given?
226
+ yield stmt.columns
227
+ result.each { |row| yield row }
228
+ else
229
+ return result.each_with_object([stmt.columns]) { |row, arr|
230
+ arr << row
231
+ }
232
+ end
233
+ end
234
+ end
235
+
236
+ # Executes all SQL statements in the given string. By contrast, the other
237
+ # means of executing queries will only execute the first statement in the
238
+ # string, ignoring all subsequent statements. This will execute each one
239
+ # in turn. The same bind parameters, if given, will be applied to each
240
+ # statement.
241
+ #
242
+ # This always returns the result of the last statement.
243
+ #
244
+ # See also #execute_batch2 for additional ways of
245
+ # executing statements.
246
+ def execute_batch(sql, bind_vars = [], *args)
247
+ sql = sql.strip
248
+ result = nil
249
+ until sql.empty?
250
+ prepare(sql) do |stmt|
251
+ unless stmt.closed?
252
+ # FIXME: this should probably use sqlite3's api for batch execution
253
+ # This implementation requires stepping over the results.
254
+ if bind_vars.length == stmt.bind_parameter_count
255
+ stmt.bind_params(bind_vars)
256
+ end
257
+ result = stmt.step
258
+ end
259
+ sql = stmt.remainder.strip
260
+ end
261
+ end
262
+
263
+ result
264
+ end
265
+
266
+ # Executes all SQL statements in the given string. By contrast, the other
267
+ # means of executing queries will only execute the first statement in the
268
+ # string, ignoring all subsequent statements. This will execute each one
269
+ # in turn. Bind parameters cannot be passed to #execute_batch2.
270
+ #
271
+ # If a query is made, all values will be returned as strings.
272
+ # If no query is made, an empty array will be returned.
273
+ #
274
+ # Because all values except for 'NULL' are returned as strings,
275
+ # a block can be passed to parse the values accordingly.
276
+ #
277
+ # See also #execute_batch for additional ways of
278
+ # executing statements.
279
+ def execute_batch2(sql, &block)
280
+ if block
281
+ result = exec_batch(sql, @results_as_hash)
282
+ result.map do |val|
283
+ yield val
284
+ end
285
+ else
286
+ exec_batch(sql, @results_as_hash)
287
+ end
288
+ end
289
+
290
+ # This is a convenience method for creating a statement, binding
291
+ # parameters to it, and calling execute:
292
+ #
293
+ # result = db.query( "select * from foo where a=?", [5])
294
+ # # is the same as
295
+ # result = db.prepare( "select * from foo where a=?" ).execute( 5 )
296
+ #
297
+ # You must be sure to call +close+ on the ResultSet instance that is
298
+ # returned, or you could have problems with locks on the table. If called
299
+ # with a block, +close+ will be invoked implicitly when the block
300
+ # terminates.
301
+ def query(sql, bind_vars = [], *args)
302
+ result = prepare(sql).execute(bind_vars)
303
+ if block_given?
304
+ begin
305
+ yield result
306
+ ensure
307
+ result.close
308
+ end
309
+ else
310
+ result
311
+ end
312
+ end
313
+
314
+ # A convenience method for obtaining the first row of a result set, and
315
+ # discarding all others. It is otherwise identical to #execute.
316
+ #
317
+ # See also #get_first_value.
318
+ def get_first_row(sql, *bind_vars)
319
+ execute(sql, *bind_vars).first
320
+ end
321
+
322
+ # A convenience method for obtaining the first value of the first row of a
323
+ # result set, and discarding all other values and rows. It is otherwise
324
+ # identical to #execute.
325
+ #
326
+ # See also #get_first_row.
327
+ def get_first_value(sql, *bind_vars)
328
+ query(sql, bind_vars) do |rs|
329
+ if (row = rs.next)
330
+ return @results_as_hash ? row[rs.columns[0]] : row[0]
331
+ end
332
+ end
333
+ nil
334
+ end
335
+
336
+ alias_method :busy_timeout, :busy_timeout=
337
+
338
+ # Creates a new function for use in SQL statements. It will be added as
339
+ # +name+, with the given +arity+. (For variable arity functions, use
340
+ # -1 for the arity.)
341
+ #
342
+ # The block should accept at least one parameter--the FunctionProxy
343
+ # instance that wraps this function invocation--and any other
344
+ # arguments it needs (up to its arity).
345
+ #
346
+ # The block does not return a value directly. Instead, it will invoke
347
+ # the FunctionProxy#result= method on the +func+ parameter and
348
+ # indicate the return value that way.
349
+ #
350
+ # Example:
351
+ #
352
+ # db.create_function( "maim", 1 ) do |func, value|
353
+ # if value.nil?
354
+ # func.result = nil
355
+ # else
356
+ # func.result = value.split(//).sort.join
357
+ # end
358
+ # end
359
+ #
360
+ # puts db.get_first_value( "select maim(name) from table" )
361
+ def create_function name, arity, text_rep = Constants::TextRep::UTF8, &block
362
+ define_function_with_flags(name, text_rep) do |*args|
363
+ fp = FunctionProxy.new
364
+ block.call(fp, *args)
365
+ fp.result
366
+ end
367
+ self
368
+ end
369
+
370
+ # Creates a new aggregate function for use in SQL statements. Aggregate
371
+ # functions are functions that apply over every row in the result set,
372
+ # instead of over just a single row. (A very common aggregate function
373
+ # is the "count" function, for determining the number of rows that match
374
+ # a query.)
375
+ #
376
+ # The new function will be added as +name+, with the given +arity+. (For
377
+ # variable arity functions, use -1 for the arity.)
378
+ #
379
+ # The +step+ parameter must be a proc object that accepts as its first
380
+ # parameter a FunctionProxy instance (representing the function
381
+ # invocation), with any subsequent parameters (up to the function's arity).
382
+ # The +step+ callback will be invoked once for each row of the result set.
383
+ #
384
+ # The +finalize+ parameter must be a +proc+ object that accepts only a
385
+ # single parameter, the FunctionProxy instance representing the current
386
+ # function invocation. It should invoke FunctionProxy#result= to
387
+ # store the result of the function.
388
+ #
389
+ # Example:
390
+ #
391
+ # db.create_aggregate( "lengths", 1 ) do
392
+ # step do |func, value|
393
+ # func[ :total ] ||= 0
394
+ # func[ :total ] += ( value ? value.length : 0 )
395
+ # end
396
+ #
397
+ # finalize do |func|
398
+ # func.result = func[ :total ] || 0
399
+ # end
400
+ # end
401
+ #
402
+ # puts db.get_first_value( "select lengths(name) from table" )
403
+ #
404
+ # See also #create_aggregate_handler for a more object-oriented approach to
405
+ # aggregate functions.
406
+ def create_aggregate(name, arity, step = nil, finalize = nil,
407
+ text_rep = Constants::TextRep::ANY, &block)
408
+
409
+ proxy = Class.new do
410
+ def self.step(&block)
411
+ define_method(:step_with_ctx, &block)
412
+ end
413
+
414
+ def self.finalize(&block)
415
+ define_method(:finalize_with_ctx, &block)
416
+ end
417
+ end
418
+
419
+ if block
420
+ proxy.instance_eval(&block)
421
+ else
422
+ proxy.class_eval do
423
+ define_method(:step_with_ctx, step)
424
+ define_method(:finalize_with_ctx, finalize)
425
+ end
426
+ end
427
+
428
+ proxy.class_eval do
429
+ # class instance variables
430
+ @name = name
431
+ @arity = arity
432
+
433
+ def self.name
434
+ @name
435
+ end
436
+
437
+ def self.arity
438
+ @arity
439
+ end
440
+
441
+ def initialize
442
+ @ctx = FunctionProxy.new
443
+ end
444
+
445
+ def step(*args)
446
+ step_with_ctx(@ctx, *args)
447
+ end
448
+
449
+ def finalize
450
+ finalize_with_ctx(@ctx)
451
+ @ctx.result
452
+ end
453
+ end
454
+ define_aggregator2(proxy, name)
455
+ end
456
+
457
+ # This is another approach to creating an aggregate function (see
458
+ # #create_aggregate). Instead of explicitly specifying the name,
459
+ # callbacks, arity, and type, you specify a factory object
460
+ # (the "handler") that knows how to obtain all of that information. The
461
+ # handler should respond to the following messages:
462
+ #
463
+ # +arity+:: corresponds to the +arity+ parameter of #create_aggregate. This
464
+ # message is optional, and if the handler does not respond to it,
465
+ # the function will have an arity of -1.
466
+ # +name+:: this is the name of the function. The handler _must_ implement
467
+ # this message.
468
+ # +new+:: this must be implemented by the handler. It should return a new
469
+ # instance of the object that will handle a specific invocation of
470
+ # the function.
471
+ #
472
+ # The handler instance (the object returned by the +new+ message, described
473
+ # above), must respond to the following messages:
474
+ #
475
+ # +step+:: this is the method that will be called for each step of the
476
+ # aggregate function's evaluation. It should implement the same
477
+ # signature as the +step+ callback for #create_aggregate.
478
+ # +finalize+:: this is the method that will be called to finalize the
479
+ # aggregate function's evaluation. It should implement the
480
+ # same signature as the +finalize+ callback for
481
+ # #create_aggregate.
482
+ #
483
+ # Example:
484
+ #
485
+ # class LengthsAggregateHandler
486
+ # def self.arity; 1; end
487
+ # def self.name; 'lengths'; end
488
+ #
489
+ # def initialize
490
+ # @total = 0
491
+ # end
492
+ #
493
+ # def step( ctx, name )
494
+ # @total += ( name ? name.length : 0 )
495
+ # end
496
+ #
497
+ # def finalize( ctx )
498
+ # ctx.result = @total
499
+ # end
500
+ # end
501
+ #
502
+ # db.create_aggregate_handler( LengthsAggregateHandler )
503
+ # puts db.get_first_value( "select lengths(name) from A" )
504
+ def create_aggregate_handler(handler)
505
+ # This is a compatibility shim so the (basically pointless) FunctionProxy
506
+ # "ctx" object is passed as first argument to both step() and finalize().
507
+ # Now its up to the library user whether he prefers to store his
508
+ # temporaries as instance variables or fields in the FunctionProxy.
509
+ # The library user still must set the result value with
510
+ # FunctionProxy.result= as there is no backwards compatible way to
511
+ # change this.
512
+ proxy = Class.new(handler) do
513
+ def initialize
514
+ super
515
+ @fp = FunctionProxy.new
516
+ end
517
+
518
+ def step(*args)
519
+ super(@fp, *args)
520
+ end
521
+
522
+ def finalize
523
+ super(@fp)
524
+ @fp.result
525
+ end
526
+ end
527
+ define_aggregator2(proxy, proxy.name)
528
+ self
529
+ end
530
+
531
+ # Define an aggregate function named +name+ using a object template
532
+ # object +aggregator+. +aggregator+ must respond to +step+ and +finalize+.
533
+ # +step+ will be called with row information and +finalize+ must return the
534
+ # return value for the aggregator function.
535
+ #
536
+ # _API Change:_ +aggregator+ must also implement +clone+. The provided
537
+ # +aggregator+ object will serve as template that is cloned to provide the
538
+ # individual instances of the aggregate function. Regular ruby objects
539
+ # already provide a suitable +clone+.
540
+ # The functions arity is the arity of the +step+ method.
541
+ def define_aggregator(name, aggregator)
542
+ # Previously, this has been implemented in C. Now this is just yet
543
+ # another compatibility shim
544
+ proxy = Class.new do
545
+ @template = aggregator
546
+ @name = name
547
+
548
+ def self.template
549
+ @template
550
+ end
551
+
552
+ def self.name
553
+ @name
554
+ end
555
+
556
+ def self.arity
557
+ # this is what sqlite3_obj_method_arity did before
558
+ @template.method(:step).arity
559
+ end
560
+
561
+ def initialize
562
+ @klass = self.class.template.clone
563
+ end
564
+
565
+ def step(*args)
566
+ @klass.step(*args)
567
+ end
568
+
569
+ def finalize
570
+ @klass.finalize
571
+ end
572
+ end
573
+ define_aggregator2(proxy, name)
574
+ self
575
+ end
576
+
577
+ # Begins a new transaction. Note that nested transactions are not allowed
578
+ # by SQLite, so attempting to nest a transaction will result in a runtime
579
+ # exception.
580
+ #
581
+ # The +mode+ parameter may be either <tt>:deferred</tt>,
582
+ # <tt>:immediate</tt>, or <tt>:exclusive</tt>.
583
+ # If `nil` is specified, the default transaction mode, which was
584
+ # passed to #initialize, is used.
585
+ #
586
+ # If a block is given, the database instance is yielded to it, and the
587
+ # transaction is committed when the block terminates. If the block
588
+ # raises an exception, a rollback will be performed instead. Note that if
589
+ # a block is given, #commit and #rollback should never be called
590
+ # explicitly or you'll get an error when the block terminates.
591
+ #
592
+ # If a block is not given, it is the caller's responsibility to end the
593
+ # transaction explicitly, either by calling #commit, or by calling
594
+ # #rollback.
595
+ def transaction(mode = nil)
596
+ mode = @default_transaction_mode if mode.nil?
597
+ execute "begin #{mode} transaction"
598
+
599
+ if block_given?
600
+ abort = false
601
+ begin
602
+ yield self
603
+ rescue
604
+ abort = true
605
+ raise
606
+ ensure
607
+ abort and rollback or commit
608
+ end
609
+ else
610
+ true
611
+ end
612
+ end
613
+
614
+ # Commits the current transaction. If there is no current transaction,
615
+ # this will cause an error to be raised. This returns +true+, in order
616
+ # to allow it to be used in idioms like
617
+ # <tt>abort? and rollback or commit</tt>.
618
+ def commit
619
+ execute "commit transaction"
620
+ true
621
+ end
622
+
623
+ # Rolls the current transaction back. If there is no current transaction,
624
+ # this will cause an error to be raised. This returns +true+, in order
625
+ # to allow it to be used in idioms like
626
+ # <tt>abort? and rollback or commit</tt>.
627
+ def rollback
628
+ execute "rollback transaction"
629
+ true
630
+ end
631
+
632
+ # Returns +true+ if the database has been open in readonly mode
633
+ # A helper to check before performing any operation
634
+ def readonly?
635
+ @readonly
636
+ end
637
+
638
+ # Sets a #busy_handler that releases the GVL between retries,
639
+ # but only retries up to the indicated number of +milliseconds+.
640
+ # This is an alternative to #busy_timeout, which holds the GVL
641
+ # while SQLite sleeps and retries.
642
+ def busy_handler_timeout=(milliseconds)
643
+ timeout_seconds = milliseconds.fdiv(1000)
644
+
645
+ busy_handler do |count|
646
+ now = Process.clock_gettime(Process::CLOCK_MONOTONIC)
647
+ if count.zero?
648
+ @timeout_deadline = now + timeout_seconds
649
+ elsif now > @timeout_deadline
650
+ next false
651
+ else
652
+ sleep(0.001)
653
+ end
654
+ end
655
+ end
656
+
657
+ # A helper class for dealing with custom functions (see #create_function,
658
+ # #create_aggregate, and #create_aggregate_handler). It encapsulates the
659
+ # opaque function object that represents the current invocation. It also
660
+ # provides more convenient access to the API functions that operate on
661
+ # the function object.
662
+ #
663
+ # This class will almost _always_ be instantiated indirectly, by working
664
+ # with the create methods mentioned above.
665
+ class FunctionProxy
666
+ attr_accessor :result
667
+
668
+ # Create a new FunctionProxy that encapsulates the given +func+ object.
669
+ # If context is non-nil, the functions context will be set to that. If
670
+ # it is non-nil, it must quack like a Hash. If it is nil, then none of
671
+ # the context functions will be available.
672
+ def initialize
673
+ @result = nil
674
+ @context = {}
675
+ end
676
+
677
+ # Returns the value with the given key from the context. This is only
678
+ # available to aggregate functions.
679
+ def [](key)
680
+ @context[key]
681
+ end
682
+
683
+ # Sets the value with the given key in the context. This is only
684
+ # available to aggregate functions.
685
+ def []=(key, value)
686
+ @context[key] = value
687
+ end
688
+ end
689
+
690
+ # Given a statement, return a result set.
691
+ # This is not intended for general consumption
692
+ # :nodoc:
693
+ def build_result_set stmt
694
+ if results_as_hash
695
+ HashResultSet.new(self, stmt)
696
+ else
697
+ ResultSet.new(self, stmt)
698
+ end
699
+ end
700
+ end
701
+ end