1// Copyright 2022 Google LLC 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15syntax = "proto3"; 16 17package google.spanner.v1; 18 19import "google/protobuf/struct.proto"; 20import "google/spanner/v1/query_plan.proto"; 21import "google/spanner/v1/transaction.proto"; 22import "google/spanner/v1/type.proto"; 23 24option cc_enable_arenas = true; 25option csharp_namespace = "Google.Cloud.Spanner.V1"; 26option go_package = "cloud.google.com/go/spanner/apiv1/spannerpb;spannerpb"; 27option java_multiple_files = true; 28option java_outer_classname = "ResultSetProto"; 29option java_package = "com.google.spanner.v1"; 30option php_namespace = "Google\\Cloud\\Spanner\\V1"; 31option ruby_package = "Google::Cloud::Spanner::V1"; 32 33// Results from [Read][google.spanner.v1.Spanner.Read] or 34// [ExecuteSql][google.spanner.v1.Spanner.ExecuteSql]. 35message ResultSet { 36 // Metadata about the result set, such as row type information. 37 ResultSetMetadata metadata = 1; 38 39 // Each element in `rows` is a row whose format is defined by 40 // [metadata.row_type][google.spanner.v1.ResultSetMetadata.row_type]. The ith element 41 // in each row matches the ith field in 42 // [metadata.row_type][google.spanner.v1.ResultSetMetadata.row_type]. Elements are 43 // encoded based on type as described 44 // [here][google.spanner.v1.TypeCode]. 45 repeated google.protobuf.ListValue rows = 2; 46 47 // Query plan and execution statistics for the SQL statement that 48 // produced this result set. These can be requested by setting 49 // [ExecuteSqlRequest.query_mode][google.spanner.v1.ExecuteSqlRequest.query_mode]. 50 // DML statements always produce stats containing the number of rows 51 // modified, unless executed using the 52 // [ExecuteSqlRequest.QueryMode.PLAN][google.spanner.v1.ExecuteSqlRequest.QueryMode.PLAN] [ExecuteSqlRequest.query_mode][google.spanner.v1.ExecuteSqlRequest.query_mode]. 53 // Other fields may or may not be populated, based on the 54 // [ExecuteSqlRequest.query_mode][google.spanner.v1.ExecuteSqlRequest.query_mode]. 55 ResultSetStats stats = 3; 56} 57 58// Partial results from a streaming read or SQL query. Streaming reads and 59// SQL queries better tolerate large result sets, large rows, and large 60// values, but are a little trickier to consume. 61message PartialResultSet { 62 // Metadata about the result set, such as row type information. 63 // Only present in the first response. 64 ResultSetMetadata metadata = 1; 65 66 // A streamed result set consists of a stream of values, which might 67 // be split into many `PartialResultSet` messages to accommodate 68 // large rows and/or large values. Every N complete values defines a 69 // row, where N is equal to the number of entries in 70 // [metadata.row_type.fields][google.spanner.v1.StructType.fields]. 71 // 72 // Most values are encoded based on type as described 73 // [here][google.spanner.v1.TypeCode]. 74 // 75 // It is possible that the last value in values is "chunked", 76 // meaning that the rest of the value is sent in subsequent 77 // `PartialResultSet`(s). This is denoted by the [chunked_value][google.spanner.v1.PartialResultSet.chunked_value] 78 // field. Two or more chunked values can be merged to form a 79 // complete value as follows: 80 // 81 // * `bool/number/null`: cannot be chunked 82 // * `string`: concatenate the strings 83 // * `list`: concatenate the lists. If the last element in a list is a 84 // `string`, `list`, or `object`, merge it with the first element in 85 // the next list by applying these rules recursively. 86 // * `object`: concatenate the (field name, field value) pairs. If a 87 // field name is duplicated, then apply these rules recursively 88 // to merge the field values. 89 // 90 // Some examples of merging: 91 // 92 // # Strings are concatenated. 93 // "foo", "bar" => "foobar" 94 // 95 // # Lists of non-strings are concatenated. 96 // [2, 3], [4] => [2, 3, 4] 97 // 98 // # Lists are concatenated, but the last and first elements are merged 99 // # because they are strings. 100 // ["a", "b"], ["c", "d"] => ["a", "bc", "d"] 101 // 102 // # Lists are concatenated, but the last and first elements are merged 103 // # because they are lists. Recursively, the last and first elements 104 // # of the inner lists are merged because they are strings. 105 // ["a", ["b", "c"]], [["d"], "e"] => ["a", ["b", "cd"], "e"] 106 // 107 // # Non-overlapping object fields are combined. 108 // {"a": "1"}, {"b": "2"} => {"a": "1", "b": 2"} 109 // 110 // # Overlapping object fields are merged. 111 // {"a": "1"}, {"a": "2"} => {"a": "12"} 112 // 113 // # Examples of merging objects containing lists of strings. 114 // {"a": ["1"]}, {"a": ["2"]} => {"a": ["12"]} 115 // 116 // For a more complete example, suppose a streaming SQL query is 117 // yielding a result set whose rows contain a single string 118 // field. The following `PartialResultSet`s might be yielded: 119 // 120 // { 121 // "metadata": { ... } 122 // "values": ["Hello", "W"] 123 // "chunked_value": true 124 // "resume_token": "Af65..." 125 // } 126 // { 127 // "values": ["orl"] 128 // "chunked_value": true 129 // "resume_token": "Bqp2..." 130 // } 131 // { 132 // "values": ["d"] 133 // "resume_token": "Zx1B..." 134 // } 135 // 136 // This sequence of `PartialResultSet`s encodes two rows, one 137 // containing the field value `"Hello"`, and a second containing the 138 // field value `"World" = "W" + "orl" + "d"`. 139 repeated google.protobuf.Value values = 2; 140 141 // If true, then the final value in [values][google.spanner.v1.PartialResultSet.values] is chunked, and must 142 // be combined with more values from subsequent `PartialResultSet`s 143 // to obtain a complete field value. 144 bool chunked_value = 3; 145 146 // Streaming calls might be interrupted for a variety of reasons, such 147 // as TCP connection loss. If this occurs, the stream of results can 148 // be resumed by re-sending the original request and including 149 // `resume_token`. Note that executing any other transaction in the 150 // same session invalidates the token. 151 bytes resume_token = 4; 152 153 // Query plan and execution statistics for the statement that produced this 154 // streaming result set. These can be requested by setting 155 // [ExecuteSqlRequest.query_mode][google.spanner.v1.ExecuteSqlRequest.query_mode] and are sent 156 // only once with the last response in the stream. 157 // This field will also be present in the last response for DML 158 // statements. 159 ResultSetStats stats = 5; 160} 161 162// Metadata about a [ResultSet][google.spanner.v1.ResultSet] or [PartialResultSet][google.spanner.v1.PartialResultSet]. 163message ResultSetMetadata { 164 // Indicates the field names and types for the rows in the result 165 // set. For example, a SQL query like `"SELECT UserId, UserName FROM 166 // Users"` could return a `row_type` value like: 167 // 168 // "fields": [ 169 // { "name": "UserId", "type": { "code": "INT64" } }, 170 // { "name": "UserName", "type": { "code": "STRING" } }, 171 // ] 172 StructType row_type = 1; 173 174 // If the read or SQL query began a transaction as a side-effect, the 175 // information about the new transaction is yielded here. 176 Transaction transaction = 2; 177 178 // A SQL query can be parameterized. In PLAN mode, these parameters can be 179 // undeclared. This indicates the field names and types for those undeclared 180 // parameters in the SQL query. For example, a SQL query like `"SELECT * FROM 181 // Users where UserId = @userId and UserName = @userName "` could return a 182 // `undeclared_parameters` value like: 183 // 184 // "fields": [ 185 // { "name": "UserId", "type": { "code": "INT64" } }, 186 // { "name": "UserName", "type": { "code": "STRING" } }, 187 // ] 188 StructType undeclared_parameters = 3; 189} 190 191// Additional statistics about a [ResultSet][google.spanner.v1.ResultSet] or [PartialResultSet][google.spanner.v1.PartialResultSet]. 192message ResultSetStats { 193 // [QueryPlan][google.spanner.v1.QueryPlan] for the query associated with this result. 194 QueryPlan query_plan = 1; 195 196 // Aggregated statistics from the execution of the query. Only present when 197 // the query is profiled. For example, a query could return the statistics as 198 // follows: 199 // 200 // { 201 // "rows_returned": "3", 202 // "elapsed_time": "1.22 secs", 203 // "cpu_time": "1.19 secs" 204 // } 205 google.protobuf.Struct query_stats = 2; 206 207 // The number of rows modified by the DML statement. 208 oneof row_count { 209 // Standard DML returns an exact count of rows that were modified. 210 int64 row_count_exact = 3; 211 212 // Partitioned DML does not offer exactly-once semantics, so it 213 // returns a lower bound of the rows modified. 214 int64 row_count_lower_bound = 4; 215 } 216} 217