|
6 | 6 | "errors" |
7 | 7 | "github.com/apstndb/execspansql/internal" |
8 | 8 | "github.com/apstndb/execspansql/params" |
9 | | - "google.golang.org/api/iterator" |
10 | 9 | "io" |
11 | | - "iter" |
12 | 10 | "regexp" |
13 | 11 | "slices" |
14 | 12 | "spheric.cloud/xiter" |
@@ -36,9 +34,10 @@ import ( |
36 | 34 |
|
37 | 35 | "cloud.google.com/go/spanner" |
38 | 36 | sppb "cloud.google.com/go/spanner/apiv1/spannerpb" |
| 37 | + "github.com/apstndb/execspansql/jqresult" |
| 38 | + "github.com/apstndb/spaniter" |
39 | 39 | "github.com/apstndb/spannerotel/interceptor" |
40 | 40 | svwriter "github.com/apstndb/spanvalue/writer" |
41 | | - "github.com/apstndb/execspansql/jqresult" |
42 | 41 | "github.com/jessevdk/go-flags" |
43 | 42 | "github.com/wader/gojq" |
44 | 43 | "google.golang.org/protobuf/types/known/structpb" |
@@ -568,56 +567,28 @@ func newEncoder(writer io.Writer, format string, compactOutput bool, rawOutput b |
568 | 567 | // consumeRowIterIntoResultSet construct *spannerpb.ResultSet using *spanner.RowIterator. |
569 | 568 | // rowIter must be passed without calling any method, and it will be closed by this function. |
570 | 569 | func consumeRowIterIntoResultSet(rowIter *spanner.RowIterator, redactRows bool) (*sppb.ResultSet, error) { |
571 | | - defer rowIter.Stop() |
572 | | - |
573 | | - var rows []*structpb.ListValue |
574 | | - var err error |
575 | | - |
576 | 570 | if redactRows { |
577 | | - err = skipRowIter(rowIter) |
578 | | - } else { |
579 | | - rows, err = consumeRowIterIntoListValues(rowIter) |
| 571 | + result, err := spaniter.DrainRowIterator(rowIter) |
| 572 | + if err != nil { |
| 573 | + return nil, err |
| 574 | + } |
| 575 | + return jqresult.BuildResultSetFromParts(nil, result.Metadata, result.Stats.QueryPlan, result.Stats.QueryStats, result.Stats.RowCount) |
580 | 576 | } |
581 | 577 |
|
| 578 | + var result spaniter.RowIteratorResult |
| 579 | + rows, err := consumeRowIterIntoListValues(rowIter, |
| 580 | + spaniter.WithResult(&result), |
| 581 | + ) |
582 | 582 | if err != nil { |
583 | 583 | return nil, err |
584 | 584 | } |
585 | | - |
586 | | - return convertToResultSet(rows, rowIter) |
587 | | -} |
588 | | - |
589 | | -// convertToResultSet convert rows and rowIter into sppb.ResultSet. |
590 | | -// rowIter must be consumed with iterator.Done, and not Stop()-ed. |
591 | | -func convertToResultSet(rows []*structpb.ListValue, rowIter *spanner.RowIterator) (*sppb.ResultSet, error) { |
592 | | - return jqresult.BuildResultSet(rows, rowIter) |
593 | | -} |
594 | | - |
595 | | -func rowIterSeq(rowIter *spanner.RowIterator) iter.Seq2[*spanner.Row, error] { |
596 | | - return func(yield func(*spanner.Row, error) bool) { |
597 | | - for { |
598 | | - r, err := rowIter.Next() |
599 | | - if errors.Is(err, iterator.Done) { |
600 | | - return |
601 | | - } |
602 | | - if err != nil { |
603 | | - _ = yield(nil, err) |
604 | | - return |
605 | | - } |
606 | | - if !yield(r, nil) { |
607 | | - return |
608 | | - } |
609 | | - } |
610 | | - } |
| 585 | + return jqresult.BuildResultSetFromParts(rows, result.Metadata, result.Stats.QueryPlan, result.Stats.QueryStats, result.Stats.RowCount) |
611 | 586 | } |
612 | 587 |
|
613 | 588 | func rowToListValue(r *spanner.Row) *structpb.ListValue { |
614 | 589 | return &structpb.ListValue{Values: slices.Collect(xiter.Map(xiter.Range(0, r.Size()), r.ColumnValue))} |
615 | 590 | } |
616 | 591 |
|
617 | | -func consumeRowIterIntoListValues(rowIter *spanner.RowIterator) ([]*structpb.ListValue, error) { |
618 | | - return xiter.TryCollect(internal.MapNonError(rowIterSeq(rowIter), rowToListValue)) |
619 | | -} |
620 | | - |
621 | | -func skipRowIter(rowIter *spanner.RowIterator) error { |
622 | | - return rowIter.Do(func(r *spanner.Row) error { return nil }) |
| 592 | +func consumeRowIterIntoListValues(rowIter *spanner.RowIterator, opts ...spaniter.Option) ([]*structpb.ListValue, error) { |
| 593 | + return xiter.TryCollect(internal.MapNonError(spaniter.RowIteratorSeq(rowIter, opts...), rowToListValue)) |
623 | 594 | } |
0 commit comments