Class: Google::Cloud::Spanner::Results

Inherits:
Object
  • Object
show all
Defined in:
lib/google/cloud/spanner/results.rb

Overview

Results

Represents the result set from an operation returning data.

See Client#execute_query and Client#read.

Examples:

require "google/cloud/spanner"

spanner = Google::Cloud::Spanner.new

db = spanner.client "my-instance", "my-database"

results = db.execute_query "SELECT * FROM users"

results.fields.pairs.each do |name, type|
  puts "Column #{name} is type #{type}"
end

Instance Method Summary collapse

Instance Method Details

#fieldsFields

Returns the configuration object (Fields) of the names and types of the rows in the returned data.

Examples:

require "google/cloud/spanner"

spanner = Google::Cloud::Spanner.new

db = spanner.client "my-instance", "my-database"

results = db.execute_query "SELECT * FROM users"

results.fields.pairs.each do |name, type|
  puts "Column #{name} is type #{type}"
end

Returns:

  • (Fields)

    The fields of the returned data.



72
73
74
# File 'lib/google/cloud/spanner/results.rb', line 72

def fields
  @fields ||= Fields.from_grpc @metadata.row_type.fields
end

#rows {|row| ... } ⇒ Object

The values returned from the request.

Examples:

require "google/cloud/spanner"

spanner = Google::Cloud::Spanner.new

db = spanner.client "my-instance", "my-database"

results = db.execute_query "SELECT * FROM users"

results.rows.each do |row|
  puts "User #{row[:id]} is #{row[:name]}"
end

Yields:

  • (row)

    An enumerator for the rows.

Yield Parameters:

  • row (Data)

    object that contains the data values.



97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
# File 'lib/google/cloud/spanner/results.rb', line 97

def rows
  return nil if @closed

  unless block_given?
    return enum_for(:rows)
  end

  fields = @metadata.row_type.fields
  values = []
  buffered_responses = []
  buffer_upper_bound = 10
  chunked_value = nil
  resume_token = nil

  # Cannot call Enumerator#each because it won't return the first
  # value that was already identified when calling Enumerator#peek.
  # Iterate only using Enumerator#next and break on StopIteration.
  loop do
    begin
      grpc = @enum.next
      # metadata should be set before the first iteration...
      @metadata ||= grpc.
      @stats ||= grpc.stats

      buffered_responses << grpc

      if (grpc.resume_token && grpc.resume_token != "") ||
        buffered_responses.size >= buffer_upper_bound
        # This can set the resume_token to nil
        resume_token = grpc.resume_token

        if fields.count > 0
          buffered_responses.each do |resp|
            if chunked_value
              resp.values.unshift merge(chunked_value, resp.values.shift)
              chunked_value = nil
            end
            to_iterate = values + Array(resp.values)
            chunked_value = to_iterate.pop if resp.chunked_value
            values = to_iterate.pop(to_iterate.count % fields.count)
            to_iterate.each_slice(fields.count) do |slice|
              yield Data.from_grpc(slice, fields)
            end
          end
        end

        # Flush the buffered responses now that they are all handled
        buffered_responses = []
      end
    rescue GRPC::Cancelled, GRPC::DeadlineExceeded, GRPC::Internal,
           GRPC::ResourceExhausted, GRPC::Unauthenticated,
           GRPC::Unavailable, GRPC::Core::CallError => err
      if resume_token.nil? || resume_token.empty?
        # Re-raise if the resume_token is not a valid value.
        # This can happen if the buffer was flushed.
        raise Google::Cloud::Error.from_error(err)
      end

      # Resume the stream from the last known resume_token
      if @execute_query_options
        @enum = @service.execute_streaming_sql \
          @session_path, @sql,
          @execute_query_options.merge(resume_token: resume_token)
      else
        @enum = @service.streaming_read_table \
          @session_path, @table, @columns,
          @read_options.merge(resume_token: resume_token)
      end

      # Flush the buffered responses to reset to the resume_token
      buffered_responses = []
    rescue GRPC::BadStatus => err
      raise Google::Cloud::Error.from_error(err)
    rescue StopIteration
      break
    end
  end

  # clear out any remaining values left over
  if fields.count > 0
    buffered_responses.each do |resp|
      if chunked_value
        resp.values.unshift merge(chunked_value, resp.values.shift)
        chunked_value = nil
      end
      to_iterate = values + Array(resp.values)
      chunked_value = to_iterate.pop if resp.chunked_value
      values = to_iterate.pop(to_iterate.count % fields.count)
      to_iterate.each_slice(fields.count) do |slice|
        yield Data.from_grpc(slice, fields)
      end
    end
    values.each_slice(fields.count) do |slice|
      yield Data.from_grpc(slice, fields)
    end
  end

  # If we get this far then we can release the session
  @closed = true
  nil
end

#timestampTime

The read timestamp chosen for single-use snapshots (read-only transactions).

Returns:

  • (Time)

    The chosen timestamp.



48
49
50
51
# File 'lib/google/cloud/spanner/results.rb', line 48

def timestamp
  return nil if @metadata.nil? || @metadata.transaction.nil?
  Convert.timestamp_to_time @metadata.transaction.read_timestamp
end