vitess.io/vitess@v0.16.2/go/vt/vtgate/mysql_protocol_test.go (about) 1 /* 2 Copyright 2019 The Vitess Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package vtgate 18 19 import ( 20 "net" 21 "strconv" 22 "testing" 23 24 "vitess.io/vitess/go/test/utils" 25 26 "github.com/stretchr/testify/assert" 27 "github.com/stretchr/testify/require" 28 29 "context" 30 31 "google.golang.org/protobuf/proto" 32 33 "vitess.io/vitess/go/mysql" 34 "vitess.io/vitess/go/vt/vttablet/sandboxconn" 35 36 querypb "vitess.io/vitess/go/vt/proto/query" 37 topodatapb "vitess.io/vitess/go/vt/proto/topodata" 38 ) 39 40 func TestMySQLProtocolExecute(t *testing.T) { 41 createSandbox(KsTestUnsharded) 42 hcVTGateTest.Reset() 43 sbc := hcVTGateTest.AddTestTablet("aa", "1.1.1.1", 1001, KsTestUnsharded, "0", topodatapb.TabletType_PRIMARY, true, 1, nil) 44 45 c, err := mysqlConnect(&mysql.ConnParams{}) 46 if err != nil { 47 t.Fatal(err) 48 } 49 defer c.Close() 50 51 qr, err := c.ExecuteFetch("select id from t1", 10, true /* wantfields */) 52 require.NoError(t, err) 53 utils.MustMatch(t, sandboxconn.SingleRowResult, qr, "mismatch in rows") 54 55 options := &querypb.ExecuteOptions{ 56 IncludedFields: querypb.ExecuteOptions_ALL, 57 Workload: querypb.ExecuteOptions_OLTP, 58 } 59 if !proto.Equal(sbc.Options[0], options) { 60 t.Errorf("got ExecuteOptions \n%+v, want \n%+v", sbc.Options[0], options) 61 } 62 } 63 64 func TestMySQLProtocolStreamExecute(t *testing.T) { 65 createSandbox(KsTestUnsharded) 66 hcVTGateTest.Reset() 67 sbc := hcVTGateTest.AddTestTablet("aa", "1.1.1.1", 1001, KsTestUnsharded, "0", topodatapb.TabletType_PRIMARY, true, 1, nil) 68 69 c, err := mysqlConnect(&mysql.ConnParams{}) 70 if err != nil { 71 t.Fatal(err) 72 } 73 defer c.Close() 74 75 _, err = c.ExecuteFetch("set workload='olap'", 1, true /* wantfields */) 76 require.NoError(t, err) 77 78 qr, err := c.ExecuteFetch("select id from t1", 10, true /* wantfields */) 79 require.NoError(t, err) 80 utils.MustMatch(t, sandboxconn.SingleRowResult, qr, "mismatch in rows") 81 82 options := &querypb.ExecuteOptions{ 83 IncludedFields: querypb.ExecuteOptions_ALL, 84 Workload: querypb.ExecuteOptions_OLAP, 85 } 86 if !proto.Equal(sbc.Options[0], options) { 87 t.Errorf("got ExecuteOptions \n%+v, want \n%+v", sbc.Options[0], options) 88 } 89 } 90 91 func TestMySQLProtocolExecuteUseStatement(t *testing.T) { 92 createSandbox(KsTestUnsharded) 93 hcVTGateTest.Reset() 94 hcVTGateTest.AddTestTablet("aa", "1.1.1.1", 1001, KsTestUnsharded, "0", topodatapb.TabletType_PRIMARY, true, 1, nil) 95 96 c, err := mysqlConnect(&mysql.ConnParams{DbName: "@primary"}) 97 if err != nil { 98 t.Fatal(err) 99 } 100 defer c.Close() 101 102 qr, err := c.ExecuteFetch("select id from t1", 10, true /* wantfields */) 103 require.NoError(t, err) 104 utils.MustMatch(t, sandboxconn.SingleRowResult, qr) 105 106 qr, err = c.ExecuteFetch("show vitess_target", 1, false) 107 require.NoError(t, err) 108 assert.Equal(t, "VARCHAR(\"@primary\")", qr.Rows[0][0].String()) 109 110 _, err = c.ExecuteFetch("use TestUnsharded", 0, false) 111 require.NoError(t, err) 112 113 qr, err = c.ExecuteFetch("select id from t1", 10, true /* wantfields */) 114 require.NoError(t, err) 115 utils.MustMatch(t, sandboxconn.SingleRowResult, qr) 116 117 // No such keyspace this will fail 118 _, err = c.ExecuteFetch("use InvalidKeyspace", 0, false) 119 require.Error(t, err) 120 assert.Contains(t, err.Error(), "VT05003: unknown database 'InvalidKeyspace' in vschema (errno 1049) (sqlstate 42000)") 121 122 // That doesn't reset the vitess_target 123 qr, err = c.ExecuteFetch("show vitess_target", 1, false) 124 require.NoError(t, err) 125 assert.Equal(t, "VARCHAR(\"TestUnsharded\")", qr.Rows[0][0].String()) 126 127 _, err = c.ExecuteFetch("use @replica", 0, false) 128 require.NoError(t, err) 129 130 // No replica tablets, this should also fail 131 _, err = c.ExecuteFetch("select id from t1", 10, true /* wantfields */) 132 require.Error(t, err) 133 assert.Contains(t, err.Error(), `no healthy tablet available for 'keyspace:"TestUnsharded" shard:"0" tablet_type:REPLICA`) 134 } 135 136 func TestMysqlProtocolInvalidDB(t *testing.T) { 137 _, err := mysqlConnect(&mysql.ConnParams{DbName: "invalidDB"}) 138 require.EqualError(t, err, "VT05003: unknown database 'invalidDB' in vschema (errno 1049) (sqlstate 42000)") 139 } 140 141 func TestMySQLProtocolClientFoundRows(t *testing.T) { 142 createSandbox(KsTestUnsharded) 143 hcVTGateTest.Reset() 144 sbc := hcVTGateTest.AddTestTablet("aa", "1.1.1.1", 1001, KsTestUnsharded, "0", topodatapb.TabletType_PRIMARY, true, 1, nil) 145 146 c, err := mysqlConnect(&mysql.ConnParams{Flags: mysql.CapabilityClientFoundRows}) 147 if err != nil { 148 t.Fatal(err) 149 } 150 defer c.Close() 151 152 qr, err := c.ExecuteFetch("select id from t1", 10, true /* wantfields */) 153 require.NoError(t, err) 154 utils.MustMatch(t, sandboxconn.SingleRowResult, qr) 155 156 options := &querypb.ExecuteOptions{ 157 IncludedFields: querypb.ExecuteOptions_ALL, 158 ClientFoundRows: true, 159 Workload: querypb.ExecuteOptions_OLTP, 160 } 161 162 if !proto.Equal(sbc.Options[0], options) { 163 t.Errorf("got ExecuteOptions \n%+v, want \n%+v", sbc.Options[0], options) 164 } 165 } 166 167 // mysqlConnect fills the host & port into params and connects 168 // to the mysql protocol port. 169 func mysqlConnect(params *mysql.ConnParams) (*mysql.Conn, error) { 170 host, port, err := net.SplitHostPort(mysqlListener.Addr().String()) 171 if err != nil { 172 return nil, err 173 } 174 portnum, _ := strconv.Atoi(port) 175 params.Host = host 176 params.Port = portnum 177 return mysql.Connect(context.Background(), params) 178 }