Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import (
"time"

"cloud.google.com/go/spanner"
pb "cloud.google.com/go/spanner/apiv1/spannerpb"
sppb "cloud.google.com/go/spanner/apiv1/spannerpb"
"github.com/chzyer/readline"
"github.com/olekukonko/tablewriter"
"google.golang.org/api/option"
Expand Down Expand Up @@ -66,7 +66,7 @@ type Cli struct {
OutStream io.Writer
ErrStream io.Writer
Verbose bool
Priority pb.RequestOptions_Priority
Priority sppb.RequestOptions_Priority
Endpoint string
}

Expand All @@ -75,7 +75,7 @@ type command struct {
Vertical bool
}

func NewCli(projectId, instanceId, databaseId, prompt, historyFile string, credential []byte, inStream io.ReadCloser, outStream io.Writer, errStream io.Writer, verbose bool, priority pb.RequestOptions_Priority, role string, endpoint string, directedRead *pb.DirectedReadOptions) (*Cli, error) {
func NewCli(projectId, instanceId, databaseId, prompt, historyFile string, credential []byte, inStream io.ReadCloser, outStream io.Writer, errStream io.Writer, verbose bool, priority sppb.RequestOptions_Priority, role string, endpoint string, directedRead *sppb.DirectedReadOptions) (*Cli, error) {
session, err := createSession(projectId, instanceId, databaseId, credential, priority, role, endpoint, directedRead)
if err != nil {
return nil, err
Expand Down Expand Up @@ -310,7 +310,7 @@ func (c *Cli) getInterpolatedPrompt() string {
return prompt
}

func createSession(projectId string, instanceId string, databaseId string, credential []byte, priority pb.RequestOptions_Priority, role string, endpoint string, directedRead *pb.DirectedReadOptions) (*Session, error) {
func createSession(projectId string, instanceId string, databaseId string, credential []byte, priority sppb.RequestOptions_Priority, role string, endpoint string, directedRead *sppb.DirectedReadOptions) (*Session, error) {
var opts []option.ClientOption
if credential != nil {
opts = append(opts, option.WithCredentialsJSON(credential))
Expand Down
7 changes: 3 additions & 4 deletions cli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import (
"bytes"
"fmt"
"io"
"io/ioutil"
"strings"
"testing"
"time"
Expand Down Expand Up @@ -164,9 +163,9 @@ func TestReadInteractiveInput(t *testing.T) {
} {
t.Run(tt.desc, func(t *testing.T) {
rl, err := readline.NewEx(&readline.Config{
Stdin: ioutil.NopCloser(strings.NewReader(tt.input)),
Stdout: ioutil.Discard,
Stderr: ioutil.Discard,
Stdin: io.NopCloser(strings.NewReader(tt.input)),
Stdout: io.Discard,
Stderr: io.Discard,
})
if err != nil {
t.Fatalf("unexpected readline.NewEx() error: %v", err)
Expand Down
4 changes: 2 additions & 2 deletions integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import (
"google.golang.org/api/option"

adminpb "cloud.google.com/go/spanner/admin/database/apiv1/databasepb"
pb "cloud.google.com/go/spanner/apiv1/spannerpb"
sppb "cloud.google.com/go/spanner/apiv1/spannerpb"
)

const (
Expand Down Expand Up @@ -85,7 +85,7 @@ func setup(t *testing.T, ctx context.Context, dmls []string) (*Session, string,
if testCredential != "" {
options = append(options, option.WithCredentialsJSON([]byte(testCredential)))
}
session, err := NewSession(testProjectId, testInstanceId, testDatabaseId, pb.RequestOptions_PRIORITY_UNSPECIFIED, "", nil, options...)
session, err := NewSession(testProjectId, testInstanceId, testDatabaseId, sppb.RequestOptions_PRIORITY_UNSPECIFIED, "", nil, options...)
if err != nil {
t.Fatalf("failed to create test session: err=%s", err)
}
Expand Down
16 changes: 8 additions & 8 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ package main

import (
"fmt"
"io/ioutil"
"io"
"os"
"os/user"
"path/filepath"

pb "cloud.google.com/go/spanner/apiv1/spannerpb"
sppb "cloud.google.com/go/spanner/apiv1/spannerpb"
flags "github.com/jessevdk/go-flags"
)

Expand Down Expand Up @@ -78,7 +78,7 @@ func main() {
}
}

var priority pb.RequestOptions_Priority
var priority sppb.RequestOptions_Priority
if opts.Priority != "" {
var err error
priority, err = parsePriority(opts.Priority)
Expand All @@ -87,7 +87,7 @@ func main() {
}
}

var directedRead *pb.DirectedReadOptions
var directedRead *sppb.DirectedReadOptions
if opts.DirectedRead != "" {
var err error
directedRead, err = parseDirectedReadOption(opts.DirectedRead)
Expand All @@ -105,13 +105,13 @@ func main() {
if opts.Execute != "" {
input = opts.Execute
} else if opts.File == "-" {
b, err := ioutil.ReadAll(os.Stdin)
b, err := io.ReadAll(os.Stdin)
if err != nil {
exitf("Read from stdin failed: %v", err)
}
input = string(b)
} else if opts.File != "" {
b, err := ioutil.ReadFile(opts.File)
b, err := os.ReadFile(opts.File)
if err != nil {
exitf("Read from file %v failed: %v", opts.File, err)
}
Expand Down Expand Up @@ -168,13 +168,13 @@ func readCredentialFile(filepath string) ([]byte, error) {
if err != nil {
return nil, err
}
return ioutil.ReadAll(f)
return io.ReadAll(f)
}

func readStdin() (string, error) {
stat, _ := os.Stdin.Stat()
if (stat.Mode() & os.ModeCharDevice) == 0 {
b, err := ioutil.ReadAll(os.Stdin)
b, err := io.ReadAll(os.Stdin)
if err != nil {
return "", err
}
Expand Down
18 changes: 9 additions & 9 deletions query_plan.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import (
"sort"
"strings"

pb "cloud.google.com/go/spanner/apiv1/spannerpb"
sppb "cloud.google.com/go/spanner/apiv1/spannerpb"
"github.com/xlab/treeprint"
"google.golang.org/protobuf/types/known/structpb"
)
Expand All @@ -42,7 +42,7 @@ type Link struct {
}

type Node struct {
PlanNode *pb.PlanNode
PlanNode *sppb.PlanNode
Children []*Link
}

Expand Down Expand Up @@ -80,12 +80,12 @@ type queryPlanNodeWithStatsTyped struct {
LinkType string `json:"link_type"`
}

func BuildQueryPlanTree(plan *pb.QueryPlan, idx int32) *Node {
func BuildQueryPlanTree(plan *sppb.QueryPlan, idx int32) *Node {
if len(plan.PlanNodes) == 0 {
return &Node{}
}

nodeMap := map[int32]*pb.PlanNode{}
nodeMap := map[int32]*sppb.PlanNode{}
for _, node := range plan.PlanNodes {
nodeMap[node.Index] = node
}
Expand Down Expand Up @@ -120,7 +120,7 @@ type QueryPlanRow struct {
Predicates []string
}

func isPredicate(planNodes []*pb.PlanNode, childLink *pb.PlanNode_ChildLink) bool {
func isPredicate(planNodes []*sppb.PlanNode, childLink *sppb.PlanNode_ChildLink) bool {
// Known predicates are Condition(Filter/Hash Join) or Seek Condition/Residual Condition(FilterScan) or Split Range(Distributed Union).
// Agg is a Function but not a predicate.
child := planNodes[childLink.ChildIndex]
Expand All @@ -133,7 +133,7 @@ func isPredicate(planNodes []*pb.PlanNode, childLink *pb.PlanNode_ChildLink) boo
return false
}

func (n *Node) RenderTreeWithStats(planNodes []*pb.PlanNode) ([]QueryPlanRow, error) {
func (n *Node) RenderTreeWithStats(planNodes []*sppb.PlanNode) ([]QueryPlanRow, error) {
tree := treeprint.New()
renderTreeWithStats(tree, "", n)
var result []QueryPlanRow
Expand Down Expand Up @@ -239,7 +239,7 @@ func (n *Node) String() string {

func renderTreeWithStats(tree treeprint.Tree, linkType string, node *Node) {
// Scalar operator is rendered if and only if it is linked as Scalar type(Scalar/Array Subquery)
if node.PlanNode.GetKind() == pb.PlanNode_SCALAR && linkType != "Scalar" {
if node.PlanNode.GetKind() == sppb.PlanNode_SCALAR && linkType != "Scalar" {
return
}

Expand Down Expand Up @@ -274,13 +274,13 @@ func renderTreeWithStats(tree treeprint.Tree, linkType string, node *Node) {
}
}

func getMaxRelationalNodeID(plan *pb.QueryPlan) int32 {
func getMaxRelationalNodeID(plan *sppb.QueryPlan) int32 {
var maxRelationalNodeID int32
// We assume that plan_nodes[] is pre-sorted in ascending order.
// See QueryPlan.plan_nodes[] in the document.
// https://cloud.google.com/spanner/docs/reference/rpc/google.spanner.v1?hl=en#google.spanner.v1.QueryPlan.FIELDS.repeated.google.spanner.v1.PlanNode.google.spanner.v1.QueryPlan.plan_nodes
for _, planNode := range plan.GetPlanNodes() {
if planNode.GetKind() == pb.PlanNode_RELATIONAL {
if planNode.GetKind() == sppb.PlanNode_RELATIONAL {
maxRelationalNodeID = planNode.Index
}
}
Expand Down
59 changes: 29 additions & 30 deletions query_plan_test.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
package main

import (
"io/ioutil"
"os"
"testing"

"github.com/google/go-cmp/cmp"
"google.golang.org/genproto/googleapis/spanner/v1"
"google.golang.org/protobuf/encoding/protojson"
"google.golang.org/protobuf/types/known/structpb"

pb "cloud.google.com/go/spanner/apiv1/spannerpb"
sppb "cloud.google.com/go/spanner/apiv1/spannerpb"
)

func mustNewStruct(m map[string]interface{}) *structpb.Struct {
Expand Down Expand Up @@ -367,11 +366,11 @@ func TestRenderTreeUsingTestdataPlans(t *testing.T) {
},
} {
t.Run(test.title, func(t *testing.T) {
b, err := ioutil.ReadFile(test.file)
b, err := os.ReadFile(test.file)
if err != nil {
t.Fatal(err)
}
var plan pb.QueryPlan
var plan sppb.QueryPlan
err = protojson.Unmarshal(b, &plan)
if err != nil {
t.Fatal(err)
Expand All @@ -391,20 +390,20 @@ func TestRenderTreeUsingTestdataPlans(t *testing.T) {
func TestRenderTreeWithStats(t *testing.T) {
for _, test := range []struct {
title string
plan *spanner.QueryPlan
plan *sppb.QueryPlan
want []QueryPlanRow
}{
{
title: "Simple Query",
plan: &spanner.QueryPlan{
PlanNodes: []*spanner.PlanNode{
plan: &sppb.QueryPlan{
PlanNodes: []*sppb.PlanNode{
{
Index: 0,
ChildLinks: []*spanner.PlanNode_ChildLink{
ChildLinks: []*sppb.PlanNode_ChildLink{
{ChildIndex: 1},
},
DisplayName: "Distributed Union",
Kind: spanner.PlanNode_RELATIONAL,
Kind: sppb.PlanNode_RELATIONAL,
ExecutionStats: mustNewStruct(map[string]interface{}{
"latency": map[string]interface{}{"total": "1", "unit": "msec"},
"rows": map[string]interface{}{"total": "9"},
Expand All @@ -413,11 +412,11 @@ func TestRenderTreeWithStats(t *testing.T) {
},
{
Index: 1,
ChildLinks: []*spanner.PlanNode_ChildLink{
ChildLinks: []*sppb.PlanNode_ChildLink{
{ChildIndex: 2},
},
DisplayName: "Distributed Union",
Kind: spanner.PlanNode_RELATIONAL,
Kind: sppb.PlanNode_RELATIONAL,
Metadata: mustNewStruct(map[string]interface{}{"call_type": "Local"}),
ExecutionStats: mustNewStruct(map[string]interface{}{
"latency": map[string]interface{}{"total": "1", "unit": "msec"},
Expand All @@ -427,11 +426,11 @@ func TestRenderTreeWithStats(t *testing.T) {
},
{
Index: 2,
ChildLinks: []*spanner.PlanNode_ChildLink{
ChildLinks: []*sppb.PlanNode_ChildLink{
{ChildIndex: 3},
},
DisplayName: "Serialize Result",
Kind: spanner.PlanNode_RELATIONAL,
Kind: sppb.PlanNode_RELATIONAL,
ExecutionStats: mustNewStruct(map[string]interface{}{
"latency": map[string]interface{}{"total": "1", "unit": "msec"},
"rows": map[string]interface{}{"total": "9"},
Expand All @@ -441,7 +440,7 @@ func TestRenderTreeWithStats(t *testing.T) {
{
Index: 3,
DisplayName: "Scan",
Kind: spanner.PlanNode_RELATIONAL,
Kind: sppb.PlanNode_RELATIONAL,
Metadata: mustNewStruct(map[string]interface{}{"scan_type": "IndexScan", "scan_target": "SongsBySingerAlbumSongNameDesc", "Full scan": "true"}),
ExecutionStats: mustNewStruct(map[string]interface{}{
"latency": map[string]interface{}{"total": "1", "unit": "msec"},
Expand Down Expand Up @@ -501,7 +500,7 @@ func TestNodeString(t *testing.T) {
want string
}{
{"Distributed Union with call_type=Local",
&Node{PlanNode: &spanner.PlanNode{
&Node{PlanNode: &sppb.PlanNode{
DisplayName: "Distributed Union",
Metadata: mustNewStruct(map[string]interface{}{
"call_type": "Local",
Expand All @@ -510,7 +509,7 @@ func TestNodeString(t *testing.T) {
}}, "Local Distributed Union",
},
{"Scan with scan_type=IndexScan and Full scan=true",
&Node{PlanNode: &spanner.PlanNode{
&Node{PlanNode: &sppb.PlanNode{
DisplayName: "Scan",
Metadata: mustNewStruct(map[string]interface{}{
"scan_type": "IndexScan",
Expand All @@ -519,37 +518,37 @@ func TestNodeString(t *testing.T) {
}),
}}, "Index Scan (Full scan: true, Index: SongsBySongName)"},
{"Scan with scan_type=TableScan",
&Node{PlanNode: &spanner.PlanNode{
&Node{PlanNode: &sppb.PlanNode{
DisplayName: "Scan",
Metadata: mustNewStruct(map[string]interface{}{
"scan_type": "TableScan",
"scan_target": "Songs",
}),
}}, "Table Scan (Table: Songs)"},
{"Scan with scan_type=BatchScan",
&Node{PlanNode: &spanner.PlanNode{
&Node{PlanNode: &sppb.PlanNode{
DisplayName: "Scan",
Metadata: mustNewStruct(map[string]interface{}{
"scan_type": "BatchScan",
"scan_target": "$v2",
}),
}}, "Batch Scan (Batch: $v2)"},
{"Sort Limit with call_type=Local",
&Node{PlanNode: &spanner.PlanNode{
&Node{PlanNode: &sppb.PlanNode{
DisplayName: "Sort Limit",
Metadata: mustNewStruct(map[string]interface{}{
"call_type": "Local",
}),
}}, "Local Sort Limit"},
{"Sort Limit with call_type=Global",
&Node{PlanNode: &spanner.PlanNode{
&Node{PlanNode: &sppb.PlanNode{
DisplayName: "Sort Limit",
Metadata: mustNewStruct(map[string]interface{}{
"call_type": "Global",
}),
}}, "Global Sort Limit"},
{"Aggregate with iterator_type=Stream",
&Node{PlanNode: &spanner.PlanNode{
&Node{PlanNode: &sppb.PlanNode{
DisplayName: "Aggregate",
Metadata: mustNewStruct(map[string]interface{}{
"iterator_type": "Stream",
Expand All @@ -565,18 +564,18 @@ func TestNodeString(t *testing.T) {
func TestGetMaxRelationalNodeID(t *testing.T) {
for _, tt := range []struct {
desc string
input *pb.QueryPlan
input *sppb.QueryPlan
want int32
}{
{
desc: "pre-sorted order",
input: &pb.QueryPlan{
PlanNodes: []*pb.PlanNode{
{Index: 0, DisplayName: "Scalar Subquery", Kind: pb.PlanNode_SCALAR},
{Index: 1, DisplayName: "Index Scan", Kind: pb.PlanNode_RELATIONAL},
{Index: 2, DisplayName: "Index Scan", Kind: pb.PlanNode_RELATIONAL},
{Index: 3, DisplayName: "Index Scan", Kind: pb.PlanNode_RELATIONAL},
{Index: 4, DisplayName: "Constant", Kind: pb.PlanNode_SCALAR}, // This is not visible
input: &sppb.QueryPlan{
PlanNodes: []*sppb.PlanNode{
{Index: 0, DisplayName: "Scalar Subquery", Kind: sppb.PlanNode_SCALAR},
{Index: 1, DisplayName: "Index Scan", Kind: sppb.PlanNode_RELATIONAL},
{Index: 2, DisplayName: "Index Scan", Kind: sppb.PlanNode_RELATIONAL},
{Index: 3, DisplayName: "Index Scan", Kind: sppb.PlanNode_RELATIONAL},
{Index: 4, DisplayName: "Constant", Kind: sppb.PlanNode_SCALAR}, // This is not visible
},
},
want: 3,
Expand Down
Loading