-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathexecution.go
More file actions
68 lines (62 loc) · 2.26 KB
/
Copy pathexecution.go
File metadata and controls
68 lines (62 loc) · 2.26 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
package main
import (
"context"
"fmt"
"cloud.google.com/go/spanner"
sppb "cloud.google.com/go/spanner/apiv1/spannerpb"
"github.com/apstndb/execspansql/resultset"
)
// queryResult owns either a live read-only iterator or a completed ResultSet.
// Write results are exposed only after commit, so output code never participates
// in transaction retries and cannot change the outcome of a successful write.
type queryResult struct {
rowIter *spanner.RowIterator
resultSet *sppb.ResultSet
committed bool
}
func executeQuery(ctx context.Context, client *spanner.Client, command *preparedCommand) (*queryResult, error) {
result := &queryResult{}
switch mode := command.mode.(type) {
case single:
result.rowIter = client.Single().WithTimestampBound(mode.TimestampBound).QueryWithOptions(ctx, command.statement, command.queryOptions)
case readWrite:
_, err := client.ReadWriteTransaction(ctx, func(ctx context.Context, tx *spanner.ReadWriteTransaction) (err error) {
// Each attempt replaces the previous result. In particular, no rows from
// an aborted attempt can reach stdout or a file destination.
result.resultSet, err = resultset.Materialize(tx.QueryWithOptions(ctx, command.statement, command.queryOptions),
materializeWithoutRows(command.opts), spaniterStatsOpts(mode, command.queryOptions)...)
return err
})
if err != nil {
return nil, err
}
result.committed = true
case partitionedDML:
count, err := client.PartitionedUpdateWithOptions(ctx, command.statement, command.queryOptions)
if err != nil {
return nil, err
}
result.resultSet = &sppb.ResultSet{
Metadata: &sppb.ResultSetMetadata{RowType: &sppb.StructType{}},
Stats: &sppb.ResultSetStats{RowCount: &sppb.ResultSetStats_RowCountLowerBound{RowCountLowerBound: count}},
}
result.committed = true
default:
return nil, fmt.Errorf("unknown query mode: %T", mode)
}
return result, nil
}
func (r *queryResult) materialize(redact bool) (*sppb.ResultSet, error) {
if r.resultSet != nil {
return r.resultSet, nil
}
var err error
r.resultSet, err = resultset.Materialize(r.rowIter, redact)
r.rowIter = nil // Materialize owns and stops the iterator, including on error.
return r.resultSet, err
}
func (r *queryResult) Close() {
if r.rowIter != nil {
r.rowIter.Stop()
}
}