sqlite3 2.0.0-aarch64-linux-musl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,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