# Copyright (c) 2004, Jamis Buck (jamis@jamisbuck.org)# All rights reserved.# Redistribution and use in source and binary forms, with or without# modification, are permitted provided that the following conditions# are met:# * Redistributions of source code must retain the above copyright# notice, this list of conditions and the following disclaimer.# * Redistributions in binary form must reproduce the above copyright# notice, this list of conditions and the following disclaimer in# the documentation and/or other materials provided with the# distribution.# * The names of its contributors may not be used to endorse or# promote products derived from this software without specific prior# written permission.# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE# POSSIBILITY OF SUCH DAMAGE.moduleSQLite3# The ResultSet object encapsulates the enumerability of a query's output.# It is a simple cursor over the data that the query returns. It will# very rarely (if ever) be instantiated directly. Instead, client's should# obtain a ResultSet instance via Statement#execute.classResultSetincludeEnumerable# The class of which we return an object in case we want an Array as# result. (ArrayFields is installed.)classArrayWithTypes<Arrayattr_accessor:typesend# The class of which we return an object in case we want an Array as# result. (ArrayFields is not installed.)classArrayWithTypesAndFields<Arrayattr_accessor:typesattr_accessor:fieldsend# The class of which we return an object in case we want a Hash as# result.classHashWithTypes<Hashattr_accessor:typesend# Create a new ResultSet attached to the given database, using the# given sql text.definitialize(db,stmt,utf_16=false)@db=db@driver=@db.driver@stmt=stmt@utf_16=utf_16commenceend# A convenience method for compiling the virtual machine and stepping# to the first row of the result set.defcommenceresult=@driver.step(@stmt.handle)ifresult==Constants::ErrorCode::ERROR@driver.reset(@stmt.handle)endcheckresult@first_row=trueendprivate:commencedefcheck(result)@eof=(result==Constants::ErrorCode::DONE)found=(result==Constants::ErrorCode::ROW)Error.check(result,@db)unless@eof||foundendprivate:check# Reset the cursor, so that a result set which has reached end-of-file# can be rewound and reiterated.defreset(*bind_params)@stmt.must_be_open!@stmt.reset!(false)@driver.reset(@stmt.handle)@stmt.bind_params(*bind_params)@eof=falsecommenceend# Query whether the cursor has reached the end of the result set or not.defeof?@eofend# Obtain the next row from the cursor. If there are no more rows to be# had, this will return +nil+. If type translation is active on the# corresponding database, the values in the row will be translated# according to their types.## The returned value will be an array, unless Database#results_as_hash has# been set to +true+, in which case the returned value will be a hash.## For arrays, the column names are accessible via the +fields+ property,# and the column types are accessible via the +types+ property.## For hashes, the column names are the keys of the hash, and the column# types are accessible via the +types+ property.defnextreturnnilif@eof@stmt.must_be_open!unless@first_rowresult=@driver.step(@stmt.handle)checkresultend@first_row=falseunless@eofrow=[]@driver.data_count(@stmt.handle).timesdo|column|type=@driver.column_type(@stmt.handle,column)iftype==Constants::ColumnType::NULLrow<<nilelsiftype==Constants::ColumnType::BLOBrow<<@driver.column_blob(@stmt.handle,column)elsiftype==Constants::ColumnType::INTEGERrow<<@driver.column_int64(@stmt.handle,column)elsiftype==Constants::ColumnType::FLOATrow<<@driver.column_double(@stmt.handle,column)elserow<<@driver.column_text(@stmt.handle,column,@utf_16)endend# if @db.type_translation# row = @stmt.types.zip(row).map do |type, value|# @db.translator.translate(type, value)# end# endif@db.results_as_hashnew_row=HashWithTypes[*(@stmt.columns.zip(row).to_a.flatten)]row.each_with_index{|value,idx|new_row[idx]=value}row=new_rowelseifrow.respond_to?(:fields)row=ArrayWithTypes.new(row)elserow=ArrayWithTypesAndFields.new(row)endrow.fields=@stmt.columnsend# row.types = @stmt.typesreturnrowendnilend# Required by the Enumerable mixin. Provides an internal iterator over the# rows of the result set.defeachwhilerow=self.nextyieldrowendend# Closes the statement that spawned this result set.# <em>Use with caution!</em> Closing a result set will automatically# close any other result sets that were spawned from the same statement.defclose@stmt.closeend# Queries whether the underlying statement has been closed or not.defclosed?@stmt.closed?end# Returns the types of the columns returned by this result set.deftypes@stmt.typesend# Returns the names of the columns returned by this result set.defcolumns@stmt.columnsendendend