Class: RDBI::Result
- Inherits:
-
Object
- Object
- RDBI::Result
- Extended by:
- MethLab
- Includes:
- Enumerable
- Defined in:
- lib/rdbi/result.rb
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
-
#affected_count ⇒ Object
readonly
The count of affected rows by a DML statement (see RDBI::Result main documentation).
-
#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.
-
#result_count ⇒ Object
readonly
The count of results (see RDBI::Result main documentation).
-
#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
-
#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.
-
#each ⇒ Object
Iterator for Enumerable methods.
-
#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 and the RDBI::Statement handle, scheduling any unpreserved data for garbage collection.
-
#has_data ⇒ Object
:attr_reader: has_data?.
-
#initialize(sth, binds, data, schema, type_hash) ⇒ Result
constructor
Creates a new RDBI::Result.
-
#raw_fetch(row_count) ⇒ Object
raw_fetch is a straight array fetch without driver interaction.
-
#reload ⇒ Object
Reload the result.
-
#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.
81 82 83 84 85 86 87 88 89 90 91 92 93 |
# File 'lib/rdbi/result.rb', line 81 def initialize(sth, binds, data, schema, type_hash) @schema = schema @data = data @result_count = data.size @affected_count = data.affected_count @sth = sth @binds = binds @type_hash = type_hash @mutex = Mutex.new @driver = RDBI::Result::Driver::Array @fetch_handle = nil as(@driver) end |
Instance Attribute Details
#affected_count ⇒ Object (readonly)
The count of affected rows by a DML statement (see RDBI::Result main documentation)
54 55 56 |
# File 'lib/rdbi/result.rb', line 54 def affected_count @affected_count end |
#binds ⇒ Object (readonly)
The binds used in the statement that yielded this Result.
60 61 62 |
# File 'lib/rdbi/result.rb', line 60 def binds @binds end |
#driver ⇒ Object (readonly)
The RDBI::Result::Driver currently associated with this Result.
48 49 50 |
# File 'lib/rdbi/result.rb', line 48 def driver @driver end |
#result_count ⇒ Object (readonly)
The count of results (see RDBI::Result main documentation)
51 52 53 |
# File 'lib/rdbi/result.rb', line 51 def result_count @result_count end |
#schema ⇒ Object (readonly)
The RDBI::Schema structure associated with this result.
42 43 44 |
# File 'lib/rdbi/result.rb', line 42 def schema @schema end |
#sth ⇒ Object (readonly)
The RDBI::Statement that yielded this result.
45 46 47 |
# File 'lib/rdbi/result.rb', line 45 def sth @sth end |
#type_hash ⇒ Object (readonly)
The mapping of types for each positional argument in the Result.
57 58 59 |
# File 'lib/rdbi/result.rb', line 57 def type_hash @type_hash end |
Instance Method Details
#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.
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.
156 157 158 159 160 161 162 163 |
# File 'lib/rdbi/result.rb', line 156 def as(driver_klass, *args) driver_klass = RDBI::Util.class_from_class_or_symbol(driver_klass, RDBI::Result::Driver) @data.rewind @driver = driver_klass @fetch_handle = driver_klass.new(self, *args) end |
#coerce_to_array ⇒ Object
Coerce the underlying result to an array, fetching all values.
130 131 132 |
# File 'lib/rdbi/result.rb', line 130 def coerce_to_array @data.coerce_to_array end |
#each ⇒ Object
Iterator for Enumerable methods. Yields a row at a time.
114 115 116 117 118 |
# File 'lib/rdbi/result.rb', line 114 def each @data.each do |row| yield(row) end 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.
208 209 210 211 212 213 214 |
# File 'lib/rdbi/result.rb', line 208 def fetch(row_count=1, driver_klass=nil, *args) if driver_klass as(driver_klass, *args) end @fetch_handle.fetch(row_count) end |
#finish ⇒ Object
This call finishes the result and the RDBI::Statement handle, scheduling any unpreserved data for garbage collection.
245 246 247 248 249 250 251 252 253 |
# File 'lib/rdbi/result.rb', line 245 def finish @sth.finish @data.finish @data = nil @sth = nil @driver = nil @binds = nil @schema = nil end |
#has_data ⇒ Object
:attr_reader: has_data?
Does this result have data?
74 |
# File 'lib/rdbi/result.rb', line 74 inline(:has_data, :has_data?) { @data.size > 0 } |
#raw_fetch(row_count) ⇒ Object
raw_fetch is a straight array fetch without driver interaction. If you think you need this, please still read the fetch documentation as there is a considerable amount of overlap.
This is generally used by Result Drivers to transform results.
225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 |
# File 'lib/rdbi/result.rb', line 225 def raw_fetch(row_count) final_res = case row_count when :all @data.all when :rest @data.rest when :first [@data.first] when :last [@data.last] else @data.fetch(row_count) end RDBI::Util.deep_copy(final_res) 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.
101 102 103 104 105 106 107 108 109 |
# File 'lib/rdbi/result.rb', line 101 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) @result_count = res.instance_variable_get(:@result_count) @affected_count = res.instance_variable_get(:@affected_count) end |
#rewind ⇒ Object
Reset the index.
123 124 125 |
# File 'lib/rdbi/result.rb', line 123 def rewind @data.rewind end |