sqlite3-ruby 1.3.2 → 1.3.3.beta.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. metadata +25 -100
  2. data/API_CHANGES.rdoc +0 -50
  3. data/CHANGELOG.rdoc +0 -171
  4. data/ChangeLog.cvs +0 -88
  5. data/LICENSE +0 -27
  6. data/Manifest.txt +0 -50
  7. data/README.rdoc +0 -74
  8. data/Rakefile +0 -10
  9. data/ext/sqlite3/backup.c +0 -164
  10. data/ext/sqlite3/backup.h +0 -15
  11. data/ext/sqlite3/database.c +0 -762
  12. data/ext/sqlite3/database.h +0 -15
  13. data/ext/sqlite3/exception.c +0 -94
  14. data/ext/sqlite3/exception.h +0 -8
  15. data/ext/sqlite3/extconf.rb +0 -43
  16. data/ext/sqlite3/sqlite3.c +0 -36
  17. data/ext/sqlite3/sqlite3_ruby.h +0 -44
  18. data/ext/sqlite3/statement.c +0 -419
  19. data/ext/sqlite3/statement.h +0 -16
  20. data/faq/faq.rb +0 -145
  21. data/faq/faq.yml +0 -426
  22. data/lib/sqlite3.rb +0 -10
  23. data/lib/sqlite3/constants.rb +0 -49
  24. data/lib/sqlite3/database.rb +0 -587
  25. data/lib/sqlite3/errors.rb +0 -44
  26. data/lib/sqlite3/pragmas.rb +0 -280
  27. data/lib/sqlite3/resultset.rb +0 -126
  28. data/lib/sqlite3/statement.rb +0 -148
  29. data/lib/sqlite3/translator.rb +0 -118
  30. data/lib/sqlite3/value.rb +0 -57
  31. data/lib/sqlite3/version.rb +0 -25
  32. data/setup.rb +0 -1333
  33. data/tasks/faq.rake +0 -9
  34. data/tasks/gem.rake +0 -31
  35. data/tasks/native.rake +0 -61
  36. data/tasks/vendor_sqlite3.rake +0 -104
  37. data/test/helper.rb +0 -3
  38. data/test/test_backup.rb +0 -33
  39. data/test/test_collation.rb +0 -82
  40. data/test/test_database.rb +0 -312
  41. data/test/test_database_readonly.rb +0 -29
  42. data/test/test_deprecated.rb +0 -33
  43. data/test/test_encoding.rb +0 -119
  44. data/test/test_integration.rb +0 -544
  45. data/test/test_integration_open_close.rb +0 -30
  46. data/test/test_integration_pending.rb +0 -115
  47. data/test/test_integration_resultset.rb +0 -156
  48. data/test/test_integration_statement.rb +0 -194
  49. data/test/test_sqlite3.rb +0 -9
  50. data/test/test_statement.rb +0 -207
  51. data/test/test_statement_execute.rb +0 -35
@@ -1,10 +0,0 @@
1
- # support multiple ruby version (fat binaries under windows)
2
- begin
3
- RUBY_VERSION =~ /(\d+.\d+)/
4
- require "sqlite3/#{$1}/sqlite3_native"
5
- rescue LoadError
6
- require 'sqlite3/sqlite3_native'
7
- end
8
-
9
- require 'sqlite3/database'
10
- require 'sqlite3/version'
@@ -1,49 +0,0 @@
1
- module SQLite3 ; module Constants
2
-
3
- module TextRep
4
- UTF8 = 1
5
- UTF16LE = 2
6
- UTF16BE = 3
7
- UTF16 = 4
8
- ANY = 5
9
- end
10
-
11
- module ColumnType
12
- INTEGER = 1
13
- FLOAT = 2
14
- TEXT = 3
15
- BLOB = 4
16
- NULL = 5
17
- end
18
-
19
- module ErrorCode
20
- OK = 0 # Successful result
21
- ERROR = 1 # SQL error or missing database
22
- INTERNAL = 2 # An internal logic error in SQLite
23
- PERM = 3 # Access permission denied
24
- ABORT = 4 # Callback routine requested an abort
25
- BUSY = 5 # The database file is locked
26
- LOCKED = 6 # A table in the database is locked
27
- NOMEM = 7 # A malloc() failed
28
- READONLY = 8 # Attempt to write a readonly database
29
- INTERRUPT = 9 # Operation terminated by sqlite_interrupt()
30
- IOERR = 10 # Some kind of disk I/O error occurred
31
- CORRUPT = 11 # The database disk image is malformed
32
- NOTFOUND = 12 # (Internal Only) Table or record not found
33
- FULL = 13 # Insertion failed because database is full
34
- CANTOPEN = 14 # Unable to open the database file
35
- PROTOCOL = 15 # Database lock protocol error
36
- EMPTY = 16 # (Internal Only) Database table is empty
37
- SCHEMA = 17 # The database schema changed
38
- TOOBIG = 18 # Too much data for one row of a table
39
- CONSTRAINT = 19 # Abort due to contraint violation
40
- MISMATCH = 20 # Data type mismatch
41
- MISUSE = 21 # Library used incorrectly
42
- NOLFS = 22 # Uses OS features not supported on host
43
- AUTH = 23 # Authorization denied
44
-
45
- ROW = 100 # sqlite_step() has another row ready
46
- DONE = 101 # sqlite_step() has finished executing
47
- end
48
-
49
- end ; end
@@ -1,587 +0,0 @@
1
- require 'sqlite3/constants'
2
- require 'sqlite3/errors'
3
- require 'sqlite3/pragmas'
4
- require 'sqlite3/statement'
5
- require 'sqlite3/translator'
6
- require 'sqlite3/value'
7
-
8
- module SQLite3
9
-
10
- # The Database class encapsulates a single connection to a SQLite3 database.
11
- # Its usage is very straightforward:
12
- #
13
- # require 'sqlite3'
14
- #
15
- # SQLite3::Database.new( "data.db" ) do |db|
16
- # db.execute( "select * from table" ) do |row|
17
- # p row
18
- # end
19
- # end
20
- #
21
- # It wraps the lower-level methods provides by the selected driver, and
22
- # includes the Pragmas module for access to various pragma convenience
23
- # methods.
24
- #
25
- # The Database class provides type translation services as well, by which
26
- # the SQLite3 data types (which are all represented as strings) may be
27
- # converted into their corresponding types (as defined in the schemas
28
- # for their tables). This translation only occurs when querying data from
29
- # the database--insertions and updates are all still typeless.
30
- #
31
- # Furthermore, the Database class has been designed to work well with the
32
- # ArrayFields module from Ara Howard. If you require the ArrayFields
33
- # module before performing a query, and if you have not enabled results as
34
- # hashes, then the results will all be indexible by field name.
35
- class Database
36
- attr_reader :collations
37
-
38
- include Pragmas
39
-
40
- class << self
41
-
42
- alias :open :new
43
-
44
- # Quotes the given string, making it safe to use in an SQL statement.
45
- # It replaces all instances of the single-quote character with two
46
- # single-quote characters. The modified string is returned.
47
- def quote( string )
48
- string.gsub( /'/, "''" )
49
- end
50
-
51
- end
52
-
53
- # A boolean that indicates whether rows in result sets should be returned
54
- # as hashes or not. By default, rows are returned as arrays.
55
- attr_accessor :results_as_hash
56
-
57
- def type_translation= value # :nodoc:
58
- warn(<<-eowarn) if $VERBOSE
59
- #{caller[0]} is calling SQLite3::Database#type_translation=
60
- SQLite3::Database#type_translation= is deprecated and will be removed
61
- in version 2.0.0.
62
- eowarn
63
- @type_translation = value
64
- end
65
- attr_reader :type_translation # :nodoc:
66
-
67
- # Return the type translator employed by this database instance. Each
68
- # database instance has its own type translator; this allows for different
69
- # type handlers to be installed in each instance without affecting other
70
- # instances. Furthermore, the translators are instantiated lazily, so that
71
- # if a database does not use type translation, it will not be burdened by
72
- # the overhead of a useless type translator. (See the Translator class.)
73
- def translator
74
- @translator ||= Translator.new
75
- end
76
-
77
- # Installs (or removes) a block that will be invoked for every access
78
- # to the database. If the block returns 0 (or +nil+), the statement
79
- # is allowed to proceed. Returning 1 causes an authorization error to
80
- # occur, and returning 2 causes the access to be silently denied.
81
- def authorizer( &block )
82
- self.authorizer = block
83
- end
84
-
85
- # Returns a Statement object representing the given SQL. This does not
86
- # execute the statement; it merely prepares the statement for execution.
87
- #
88
- # The Statement can then be executed using Statement#execute.
89
- #
90
- def prepare sql
91
- stmt = SQLite3::Statement.new( self, sql )
92
- return stmt unless block_given?
93
-
94
- begin
95
- yield stmt
96
- ensure
97
- stmt.close
98
- end
99
- end
100
-
101
- # Executes the given SQL statement. If additional parameters are given,
102
- # they are treated as bind variables, and are bound to the placeholders in
103
- # the query.
104
- #
105
- # Note that if any of the values passed to this are hashes, then the
106
- # key/value pairs are each bound separately, with the key being used as
107
- # the name of the placeholder to bind the value to.
108
- #
109
- # The block is optional. If given, it will be invoked for each row returned
110
- # by the query. Otherwise, any results are accumulated into an array and
111
- # returned wholesale.
112
- #
113
- # See also #execute2, #query, and #execute_batch for additional ways of
114
- # executing statements.
115
- def execute sql, bind_vars = [], *args, &block
116
- # FIXME: This is a terrible hack and should be removed but is required
117
- # for older versions of rails
118
- hack = Object.const_defined?(:ActiveRecord) && sql =~ /^PRAGMA index_list/
119
-
120
- if bind_vars.nil? || !args.empty?
121
- if args.empty?
122
- bind_vars = []
123
- else
124
- bind_vars = [nil] + args
125
- end
126
-
127
- warn(<<-eowarn) if $VERBOSE
128
- #{caller[0]} is calling SQLite3::Database#execute with nil or multiple bind params
129
- without using an array. Please switch to passing bind parameters as an array.
130
- Support for bind parameters as *args will be removed in 2.0.0.
131
- eowarn
132
- end
133
-
134
- prepare( sql ) do |stmt|
135
- stmt.bind_params(bind_vars)
136
- columns = stmt.columns
137
- stmt = ResultSet.new(self, stmt).to_a if type_translation
138
-
139
- if block_given?
140
- stmt.each do |row|
141
- if @results_as_hash
142
- yield type_translation ? row : ordered_map_for(columns, row)
143
- else
144
- yield row
145
- end
146
- end
147
- else
148
- if @results_as_hash
149
- stmt.map { |row|
150
- h = type_translation ? row : ordered_map_for(columns, row)
151
-
152
- # FIXME UGH TERRIBLE HACK!
153
- h['unique'] = h['unique'].to_s if hack
154
-
155
- h
156
- }
157
- else
158
- stmt.to_a
159
- end
160
- end
161
- end
162
- end
163
-
164
- # Executes the given SQL statement, exactly as with #execute. However, the
165
- # first row returned (either via the block, or in the returned array) is
166
- # always the names of the columns. Subsequent rows correspond to the data
167
- # from the result set.
168
- #
169
- # Thus, even if the query itself returns no rows, this method will always
170
- # return at least one row--the names of the columns.
171
- #
172
- # See also #execute, #query, and #execute_batch for additional ways of
173
- # executing statements.
174
- def execute2( sql, *bind_vars )
175
- prepare( sql ) do |stmt|
176
- result = stmt.execute( *bind_vars )
177
- if block_given?
178
- yield stmt.columns
179
- result.each { |row| yield row }
180
- else
181
- return result.inject( [ stmt.columns ] ) { |arr,row|
182
- arr << row; arr }
183
- end
184
- end
185
- end
186
-
187
- # Executes all SQL statements in the given string. By contrast, the other
188
- # means of executing queries will only execute the first statement in the
189
- # string, ignoring all subsequent statements. This will execute each one
190
- # in turn. The same bind parameters, if given, will be applied to each
191
- # statement.
192
- #
193
- # This always returns +nil+, making it unsuitable for queries that return
194
- # rows.
195
- def execute_batch( sql, bind_vars = [], *args )
196
- # FIXME: remove this stuff later
197
- unless [Array, Hash].include?(bind_vars.class)
198
- bind_vars = [bind_vars]
199
- warn(<<-eowarn) if $VERBOSE
200
- #{caller[0]} is calling SQLite3::Database#execute_batch with bind parameters
201
- that are not a list of a hash. Please switch to passing bind parameters as an
202
- array or hash. Support for this behavior will be removed in version 2.0.0.
203
- eowarn
204
- end
205
-
206
- # FIXME: remove this stuff later
207
- if bind_vars.nil? || !args.empty?
208
- if args.empty?
209
- bind_vars = []
210
- else
211
- bind_vars = [nil] + args
212
- end
213
-
214
- warn(<<-eowarn) if $VERBOSE
215
- #{caller[0]} is calling SQLite3::Database#execute_batch with nil or multiple bind params
216
- without using an array. Please switch to passing bind parameters as an array.
217
- Support for this behavior will be removed in version 2.0.0.
218
- eowarn
219
- end
220
-
221
- sql = sql.strip
222
- until sql.empty? do
223
- prepare( sql ) do |stmt|
224
- # FIXME: this should probably use sqlite3's api for batch execution
225
- # This implementation requires stepping over the results.
226
- if bind_vars.length == stmt.bind_parameter_count
227
- stmt.bind_params(bind_vars)
228
- end
229
- stmt.step
230
- sql = stmt.remainder.strip
231
- end
232
- end
233
- nil
234
- end
235
-
236
- # This is a convenience method for creating a statement, binding
237
- # paramters to it, and calling execute:
238
- #
239
- # result = db.query( "select * from foo where a=?", 5 )
240
- # # is the same as
241
- # result = db.prepare( "select * from foo where a=?" ).execute( 5 )
242
- #
243
- # You must be sure to call +close+ on the ResultSet instance that is
244
- # returned, or you could have problems with locks on the table. If called
245
- # with a block, +close+ will be invoked implicitly when the block
246
- # terminates.
247
- def query( sql, bind_vars = [], *args )
248
-
249
- if bind_vars.nil? || !args.empty?
250
- if args.empty?
251
- bind_vars = []
252
- else
253
- bind_vars = [nil] + args
254
- end
255
-
256
- warn(<<-eowarn) if $VERBOSE
257
- #{caller[0]} is calling SQLite3::Database#query with nil or multiple bind params
258
- without using an array. Please switch to passing bind parameters as an array.
259
- Support for this will be removed in version 2.0.0.
260
- eowarn
261
- end
262
-
263
- result = prepare( sql ).execute( bind_vars )
264
- if block_given?
265
- begin
266
- yield result
267
- ensure
268
- result.close
269
- end
270
- else
271
- return result
272
- end
273
- end
274
-
275
- # A convenience method for obtaining the first row of a result set, and
276
- # discarding all others. It is otherwise identical to #execute.
277
- #
278
- # See also #get_first_value.
279
- def get_first_row( sql, *bind_vars )
280
- execute( sql, *bind_vars ).first
281
- end
282
-
283
- # A convenience method for obtaining the first value of the first row of a
284
- # result set, and discarding all other values and rows. It is otherwise
285
- # identical to #execute.
286
- #
287
- # See also #get_first_row.
288
- def get_first_value( sql, *bind_vars )
289
- execute( sql, *bind_vars ) { |row| return row[0] }
290
- nil
291
- end
292
-
293
- alias :busy_timeout :busy_timeout=
294
-
295
- # Creates a new function for use in SQL statements. It will be added as
296
- # +name+, with the given +arity+. (For variable arity functions, use
297
- # -1 for the arity.)
298
- #
299
- # The block should accept at least one parameter--the FunctionProxy
300
- # instance that wraps this function invocation--and any other
301
- # arguments it needs (up to its arity).
302
- #
303
- # The block does not return a value directly. Instead, it will invoke
304
- # the FunctionProxy#result= method on the +func+ parameter and
305
- # indicate the return value that way.
306
- #
307
- # Example:
308
- #
309
- # db.create_function( "maim", 1 ) do |func, value|
310
- # if value.nil?
311
- # func.result = nil
312
- # else
313
- # func.result = value.split(//).sort.join
314
- # end
315
- # end
316
- #
317
- # puts db.get_first_value( "select maim(name) from table" )
318
- def create_function name, arity, text_rep=Constants::TextRep::ANY, &block
319
- define_function(name) do |*args|
320
- fp = FunctionProxy.new
321
- block.call(fp, *args)
322
- fp.result
323
- end
324
- self
325
- end
326
-
327
- # Creates a new aggregate function for use in SQL statements. Aggregate
328
- # functions are functions that apply over every row in the result set,
329
- # instead of over just a single row. (A very common aggregate function
330
- # is the "count" function, for determining the number of rows that match
331
- # a query.)
332
- #
333
- # The new function will be added as +name+, with the given +arity+. (For
334
- # variable arity functions, use -1 for the arity.)
335
- #
336
- # The +step+ parameter must be a proc object that accepts as its first
337
- # parameter a FunctionProxy instance (representing the function
338
- # invocation), with any subsequent parameters (up to the function's arity).
339
- # The +step+ callback will be invoked once for each row of the result set.
340
- #
341
- # The +finalize+ parameter must be a +proc+ object that accepts only a
342
- # single parameter, the FunctionProxy instance representing the current
343
- # function invocation. It should invoke FunctionProxy#result= to
344
- # store the result of the function.
345
- #
346
- # Example:
347
- #
348
- # db.create_aggregate( "lengths", 1 ) do
349
- # step do |func, value|
350
- # func[ :total ] ||= 0
351
- # func[ :total ] += ( value ? value.length : 0 )
352
- # end
353
- #
354
- # finalize do |func|
355
- # func.result = func[ :total ] || 0
356
- # end
357
- # end
358
- #
359
- # puts db.get_first_value( "select lengths(name) from table" )
360
- #
361
- # See also #create_aggregate_handler for a more object-oriented approach to
362
- # aggregate functions.
363
- def create_aggregate( name, arity, step=nil, finalize=nil,
364
- text_rep=Constants::TextRep::ANY, &block )
365
-
366
- factory = Class.new do
367
- def self.step( &block )
368
- define_method(:step, &block)
369
- end
370
-
371
- def self.finalize( &block )
372
- define_method(:finalize, &block)
373
- end
374
- end
375
-
376
- if block_given?
377
- factory.instance_eval(&block)
378
- else
379
- factory.class_eval do
380
- define_method(:step, step)
381
- define_method(:finalize, finalize)
382
- end
383
- end
384
-
385
- proxy = factory.new
386
- proxy.extend(Module.new {
387
- attr_accessor :ctx
388
-
389
- def step( *args )
390
- super(@ctx, *args)
391
- end
392
-
393
- def finalize
394
- super(@ctx)
395
- end
396
- })
397
- proxy.ctx = FunctionProxy.new
398
- define_aggregator(name, proxy)
399
- end
400
-
401
- # This is another approach to creating an aggregate function (see
402
- # #create_aggregate). Instead of explicitly specifying the name,
403
- # callbacks, arity, and type, you specify a factory object
404
- # (the "handler") that knows how to obtain all of that information. The
405
- # handler should respond to the following messages:
406
- #
407
- # +arity+:: corresponds to the +arity+ parameter of #create_aggregate. This
408
- # message is optional, and if the handler does not respond to it,
409
- # the function will have an arity of -1.
410
- # +name+:: this is the name of the function. The handler _must_ implement
411
- # this message.
412
- # +new+:: this must be implemented by the handler. It should return a new
413
- # instance of the object that will handle a specific invocation of
414
- # the function.
415
- #
416
- # The handler instance (the object returned by the +new+ message, described
417
- # above), must respond to the following messages:
418
- #
419
- # +step+:: this is the method that will be called for each step of the
420
- # aggregate function's evaluation. It should implement the same
421
- # signature as the +step+ callback for #create_aggregate.
422
- # +finalize+:: this is the method that will be called to finalize the
423
- # aggregate function's evaluation. It should implement the
424
- # same signature as the +finalize+ callback for
425
- # #create_aggregate.
426
- #
427
- # Example:
428
- #
429
- # class LengthsAggregateHandler
430
- # def self.arity; 1; end
431
- #
432
- # def initialize
433
- # @total = 0
434
- # end
435
- #
436
- # def step( ctx, name )
437
- # @total += ( name ? name.length : 0 )
438
- # end
439
- #
440
- # def finalize( ctx )
441
- # ctx.result = @total
442
- # end
443
- # end
444
- #
445
- # db.create_aggregate_handler( LengthsAggregateHandler )
446
- # puts db.get_first_value( "select lengths(name) from A" )
447
- def create_aggregate_handler( handler )
448
- proxy = Class.new do
449
- def initialize handler
450
- @handler = handler
451
- @fp = FunctionProxy.new
452
- end
453
-
454
- def step( *args )
455
- @handler.step(@fp, *args)
456
- end
457
-
458
- def finalize
459
- @handler.finalize @fp
460
- @fp.result
461
- end
462
- end
463
- define_aggregator(handler.name, proxy.new(handler.new))
464
- self
465
- end
466
-
467
- # Begins a new transaction. Note that nested transactions are not allowed
468
- # by SQLite, so attempting to nest a transaction will result in a runtime
469
- # exception.
470
- #
471
- # The +mode+ parameter may be either <tt>:deferred</tt> (the default),
472
- # <tt>:immediate</tt>, or <tt>:exclusive</tt>.
473
- #
474
- # If a block is given, the database instance is yielded to it, and the
475
- # transaction is committed when the block terminates. If the block
476
- # raises an exception, a rollback will be performed instead. Note that if
477
- # a block is given, #commit and #rollback should never be called
478
- # explicitly or you'll get an error when the block terminates.
479
- #
480
- # If a block is not given, it is the caller's responsibility to end the
481
- # transaction explicitly, either by calling #commit, or by calling
482
- # #rollback.
483
- def transaction( mode = :deferred )
484
- execute "begin #{mode.to_s} transaction"
485
- @transaction_active = true
486
-
487
- if block_given?
488
- abort = false
489
- begin
490
- yield self
491
- rescue ::Object
492
- abort = true
493
- raise
494
- ensure
495
- abort and rollback or commit
496
- end
497
- end
498
-
499
- true
500
- end
501
-
502
- # Commits the current transaction. If there is no current transaction,
503
- # this will cause an error to be raised. This returns +true+, in order
504
- # to allow it to be used in idioms like
505
- # <tt>abort? and rollback or commit</tt>.
506
- def commit
507
- execute "commit transaction"
508
- @transaction_active = false
509
- true
510
- end
511
-
512
- # Rolls the current transaction back. If there is no current transaction,
513
- # this will cause an error to be raised. This returns +true+, in order
514
- # to allow it to be used in idioms like
515
- # <tt>abort? and rollback or commit</tt>.
516
- def rollback
517
- execute "rollback transaction"
518
- @transaction_active = false
519
- true
520
- end
521
-
522
- # Returns +true+ if there is a transaction active, and +false+ otherwise.
523
- def transaction_active?
524
- @transaction_active
525
- end
526
-
527
- # Returns +true+ if the database has been open in readonly mode
528
- # A helper to check before performing any operation
529
- def readonly?
530
- @readonly
531
- end
532
-
533
- # A helper class for dealing with custom functions (see #create_function,
534
- # #create_aggregate, and #create_aggregate_handler). It encapsulates the
535
- # opaque function object that represents the current invocation. It also
536
- # provides more convenient access to the API functions that operate on
537
- # the function object.
538
- #
539
- # This class will almost _always_ be instantiated indirectly, by working
540
- # with the create methods mentioned above.
541
- class FunctionProxy
542
- attr_accessor :result
543
-
544
- # Create a new FunctionProxy that encapsulates the given +func+ object.
545
- # If context is non-nil, the functions context will be set to that. If
546
- # it is non-nil, it must quack like a Hash. If it is nil, then none of
547
- # the context functions will be available.
548
- def initialize
549
- @result = nil
550
- @context = {}
551
- end
552
-
553
- # Set the result of the function to the given error message.
554
- # The function will then return that error.
555
- def set_error( error )
556
- @driver.result_error( @func, error.to_s, -1 )
557
- end
558
-
559
- # (Only available to aggregate functions.) Returns the number of rows
560
- # that the aggregate has processed so far. This will include the current
561
- # row, and so will always return at least 1.
562
- def count
563
- @driver.aggregate_count( @func )
564
- end
565
-
566
- # Returns the value with the given key from the context. This is only
567
- # available to aggregate functions.
568
- def []( key )
569
- @context[ key ]
570
- end
571
-
572
- # Sets the value with the given key in the context. This is only
573
- # available to aggregate functions.
574
- def []=( key, value )
575
- @context[ key ] = value
576
- end
577
- end
578
-
579
- private
580
-
581
- def ordered_map_for columns, row
582
- h = Hash[*columns.zip(row).flatten]
583
- row.each_with_index { |r, i| h[i] = r }
584
- h
585
- end
586
- end
587
- end