Class: RDBI::Result
Overview
RDBI::Result encapsulates results from a statement.
Results in RDBI::Result are row-oriented and may be transformable by Result Drivers (RDBI::Result::Driver). They are fetched as a unit or in order.
The RDBI::Result API is deliberately architected to loosely resemble that of IO or File.
Just give me the data!
Have a peek at RDBI::Result#fetch.
Result Counts
Multiple kinds of counts are represented in each result:
-
A count of the results provided
-
A count of the affected rows.
To elaborate, the “affected rows” is a count of rows that were altered by the statement from a DML result such as INSERT
or UPDATE
. In some cases, statements will both alter rows and yield results, which is why this value is not switched depending on the kind of statement.
Result Drivers
Result drivers are subclasses of RDBI::Result::Driver that take the result as input and yield a transformed input: data structures such a hashes, or even wilder results such as CSV or JSON or YAML. Given the ability to sanely transform row-oriented input, result drivers effectively have the power to do anything.
Accessing result drivers is as easy as using a secondary form of RDBI::Result#fetch or more explicitly with the RDBI::Result#as call.
Defined Under Namespace
Classes: Driver
Instance Attribute Summary collapse
-
#binds ⇒ Object
readonly
The binds used in the statement that yielded this Result.
-
#driver ⇒ Object
readonly
The RDBI::Result::Driver currently associated with this Result.
-
#rewindable_result ⇒ Object
readonly
See RDBI::Statement#rewindable_result.
-
#schema ⇒ Object
readonly
The RDBI::Schema structure associated with this result.
-
#sth ⇒ Object
readonly
The RDBI::Statement that yielded this result.
-
#type_hash ⇒ Object
readonly
The mapping of types for each positional argument in the Result.
Instance Method Summary collapse
-
#affected_count ⇒ Object
The count of affected rows by a DML statement (see RDBI::Result main documentation).
-
#as(driver_klass, *args) ⇒ Object
:call-seq: as(String) as(Symbol) as(Class) as([Class, String, or Symbol], *driver_arguments).
-
#coerce_to_array ⇒ Object
Coerce the underlying result to an array, fetching all values.
-
#complete ⇒ Object
(also: #complete?)
:nodoc: FIXME async.
-
#each ⇒ Object
Iterator for Enumerable methods.
-
#empty? ⇒ Boolean
Is this result empty?.
-
#fetch(row_count = 1, driver_klass = nil, *args) ⇒ Object
(also: #read)
:call-seq: fetch() fetch(Integer) fetch(:first) fetch(:last) fetch(:all) fetch(:rest) fetch(amount, [Class, String, or Symbol], *driver_arguments).
-
#finish ⇒ Object
This call finishes the result, scheduling any unpreserved data for garbage collection.
-
#first ⇒ Object
Returns the first result in the set.
-
#has_data ⇒ Object
(also: #has_data?)
Does this result have data?.
-
#initialize(sth, binds, data, schema, type_hash) ⇒ Result
constructor
Creates a new RDBI::Result.
-
#last ⇒ Object
Returns the last result in the set.
-
#reload ⇒ Object
Reload the result.
-
#result_count ⇒ Object
The count of results (see RDBI::Result main documentation).
-
#rewind ⇒ Object
Reset the index.
Constructor Details
#initialize(sth, binds, data, schema, type_hash) ⇒ Result
Creates a new RDBI::Result. Please refer to RDBI::Statement#new_execution for instructions on how this is typically used and how the contents are passed to the constructor.
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/rdbi/result.rb', line 78 def initialize(sth, binds, data, schema, type_hash) @schema = schema @data = data @affected_count = nil # computed on demand @sth = sth @binds = binds @type_hash = type_hash @driver = RDBI::Result::Driver::Array @result_driver = nil configure_rewindable configure_driver(@driver) RDBI::Util.upon_finalize!(self, @data, :finish) end |
Instance Attribute Details
#binds ⇒ Object (readonly)
The binds used in the statement that yielded this Result.
53 54 55 |
# File 'lib/rdbi/result.rb', line 53 def binds @binds end |
#driver ⇒ Object (readonly)
The RDBI::Result::Driver currently associated with this Result.
47 48 49 |
# File 'lib/rdbi/result.rb', line 47 def driver @driver end |
#rewindable_result ⇒ Object (readonly)
See RDBI::Statement#rewindable_result.
56 57 58 |
# File 'lib/rdbi/result.rb', line 56 def rewindable_result @rewindable_result end |
#schema ⇒ Object (readonly)
The RDBI::Schema structure associated with this result.
41 42 43 |
# File 'lib/rdbi/result.rb', line 41 def schema @schema end |
#sth ⇒ Object (readonly)
The RDBI::Statement that yielded this result.
44 45 46 |
# File 'lib/rdbi/result.rb', line 44 def sth @sth end |
#type_hash ⇒ Object (readonly)
The mapping of types for each positional argument in the Result.
50 51 52 |
# File 'lib/rdbi/result.rb', line 50 def type_hash @type_hash end |
Instance Method Details
#affected_count ⇒ Object
The count of affected rows by a DML statement (see RDBI::Result main documentation)
102 103 104 |
# File 'lib/rdbi/result.rb', line 102 def affected_count @affected_count ||= @data.affected_count end |
#as(driver_klass, *args) ⇒ Object
:call-seq:
as(String)
as(Symbol)
as(Class)
as([Class, String, or Symbol], *driver_arguments)
Replace the Result Driver. See RDBI::Result’s main docs and RDBI::Result::Driver for more information on Result Drivers. Returns its receiver, permitting method chaining.
You may pass:
-
A Symbol or String which is shorthand for loading from the RDBI::Result::Driver namespace – for example: “CSV” will result in the class RDBI::Result::Driver::CSV.
-
A full class name.
There are no naming requirements; the String/Symbol form is just shorthand for convention.
Any additional arguments will be passed to the driver’s constructor.
This will force a rewind even if rewindable_result
is false.
181 182 183 184 185 186 187 188 189 190 191 192 |
# File 'lib/rdbi/result.rb', line 181 def as(driver_klass, *args) driver_klass = RDBI::Util.class_from_class_or_symbol(driver_klass, RDBI::Result::Driver) rr = @data.rewindable_result @data.rewindable_result = true @data.rewind @data.rewindable_result = rr @driver = driver_klass configure_driver(@driver, *args) self end |
#coerce_to_array ⇒ Object
Coerce the underlying result to an array, fetching all values. Same as setting RDBI::Result#rewindable_result.
152 153 154 |
# File 'lib/rdbi/result.rb', line 152 def coerce_to_array @data.coerce_to_array end |
#complete ⇒ Object Also known as: complete?
:nodoc: FIXME async
60 61 62 |
# File 'lib/rdbi/result.rb', line 60 def complete true end |
#each ⇒ Object
Iterator for Enumerable methods. Yields a row at a time as translated by the current driver
.
128 129 130 131 132 |
# File 'lib/rdbi/result.rb', line 128 def each while row = fetch(:next_row) yield(row) end end |
#empty? ⇒ Boolean
Is this result empty?
144 145 146 |
# File 'lib/rdbi/result.rb', line 144 def empty? @data.empty? end |
#fetch(row_count = 1, driver_klass = nil, *args) ⇒ Object Also known as: read
:call-seq:
fetch()
fetch(Integer)
fetch(:first)
fetch(:last)
fetch(:all)
fetch(:rest)
fetch(amount, [Class, String, or Symbol], *driver_arguments)
fetch is the way people will typically interact with this class. It yields some or all of the results depending on the arguments given. Additionally, it can be supplemented with the arguments passed to RDBI::Result#as to one-off select a result driver.
The initial argument can be none or one of many options:
-
An Integer n requests n rows from the result and increments the index.
-
No argument uses an Integer count of 1.
-
:first yields the first row of the result, regardless of the index.
-
:last yields the last row of the result, regardless of the index.
-
:all yields the whole set of rows, regardless of the index.
-
:rest yields all the items that have not been fetched, determined by the index.
-
:first and :last return nil if there are no results. All others will return an empty array.
The index
I bet you’re wondering what that is now, right? Well, the index is essentially a running row count that is altered by certain fetch operations. This makes sequential fetches much simpler.
The index is largely implemented by RDBI::Cursor (and Database Driver subclasses)
Items that do not use the index do not affect it.
Result Drivers will always rewind the index, as this implicates a “point of no return” state change. You may always return to the original driver you were using, but the index position will be lost.
The default result driver is RDBI::Result::Driver::Array.
237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 |
# File 'lib/rdbi/result.rb', line 237 def fetch(row_count=1, driver_klass=nil, *args) if driver_klass as(driver_klass, *args) end # fetch() has two significantly different return signatures: # # Returning a single row is nil upon EOF (:first, :last, inside #each) # Returning a set of rows is [] upon EOF (all others) raw, multiple_rows = case row_count when :first, :last, :next_row [@data.__send__(row_count), false] when :all, :rest [@data.__send__(row_count), true] else [@data.fetch(row_count), true] end return @result_driver.format_multiple_rows(raw) if multiple_rows @result_driver.format_single_row(raw) if raw # else nil -- :first, :last or #each at EOF end |
#finish ⇒ Object
This call finishes the result, scheduling any unpreserved data for garbage collection.
286 287 288 289 290 291 292 293 |
# File 'lib/rdbi/result.rb', line 286 def finish @data.finish @data = nil @sth = nil @driver = nil @binds = nil @schema = nil end |
#first ⇒ Object
Returns the first result in the set. Note that this may force an advance of the underlying cursor for non-rewindable ResultSets.
267 268 269 |
# File 'lib/rdbi/result.rb', line 267 def first fetch(:first) end |
#has_data ⇒ Object Also known as: has_data?
Does this result have data?
67 68 69 |
# File 'lib/rdbi/result.rb', line 67 def has_data @data.size > 0 end |
#last ⇒ Object
Returns the last result in the set. Note that this may exhaust the underlying cursor for non-rewindable ResultSets, as the driver advances to the end of the results to fetch the last row.
276 277 278 |
# File 'lib/rdbi/result.rb', line 276 def last fetch(:last) end |
#reload ⇒ Object
Reload the result. This will:
-
Execute the statement that yielded this result again, with the original binds
-
Replace the results and other attributes with the new results.
113 114 115 116 117 118 119 120 121 122 |
# File 'lib/rdbi/result.rb', line 113 def reload @data.finish res = @sth.execute(*@binds) @data = res.instance_variable_get(:@data) @type_hash = res.instance_variable_get(:@type_hash) @schema = res.instance_variable_get(:@schema) @affected_count = nil # recomputed on demand configure_rewindable end |
#result_count ⇒ Object
The count of results (see RDBI::Result main documentation)
95 96 97 98 99 |
# File 'lib/rdbi/result.rb', line 95 def result_count # Non-rewindable cursors typically will give the number of rows # fetched so far... @data.size end |
#rewind ⇒ Object
Reset the index.
137 138 139 |
# File 'lib/rdbi/result.rb', line 137 def rewind @data.rewind end |