xref: /aosp_15_r20/external/googleapis/google/spanner/v1/result_set.proto (revision d5c09012810ac0c9f33fe448fb6da8260d444cc9)
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