diff --git a/.github/workflows/check_make_parser.yml b/.github/workflows/check_make_parser.yml index c46f5bffc5f..efc6c737e73 100644 --- a/.github/workflows/check_make_parser.yml +++ b/.github/workflows/check_make_parser.yml @@ -17,7 +17,7 @@ jobs: - name: Get dependencies run: | - sudo apt-get update + sudo apt-get update || echo "update failed" sudo apt-get install -y mysql-server mysql-client make unzip g++ etcd curl git wget sudo service mysql stop sudo service etcd stop diff --git a/.github/workflows/cluster_endtoend.yml b/.github/workflows/cluster_endtoend.yml index 448622241a1..5d31167f707 100644 --- a/.github/workflows/cluster_endtoend.yml +++ b/.github/workflows/cluster_endtoend.yml @@ -17,7 +17,7 @@ jobs: - name: Get dependencies run: | - sudo apt-get update + sudo apt-get update || echo "update failed" sudo apt-get install -y mysql-server mysql-client make unzip g++ etcd curl git wget sudo service mysql stop sudo service etcd stop diff --git a/.github/workflows/e2e_race.yml b/.github/workflows/e2e_race.yml index 040639d96b6..2e6fb4f4938 100644 --- a/.github/workflows/e2e_race.yml +++ b/.github/workflows/e2e_race.yml @@ -17,7 +17,7 @@ jobs: - name: Get dependencies run: | - sudo apt-get update + sudo apt-get update || echo "update failed" sudo apt-get install -y mysql-server mysql-client make unzip g++ etcd curl git wget sudo service mysql stop sudo service etcd stop diff --git a/.github/workflows/endtoend.yml b/.github/workflows/endtoend.yml index 7a0c594ee35..b10977d4860 100644 --- a/.github/workflows/endtoend.yml +++ b/.github/workflows/endtoend.yml @@ -17,7 +17,7 @@ jobs: - name: Get dependencies run: | - sudo apt-get update + sudo apt-get update || echo "update failed" sudo apt-get install -y mysql-server mysql-client make unzip g++ etcd curl git wget sudo service mysql stop sudo service etcd stop diff --git a/.github/workflows/local_example.yml b/.github/workflows/local_example.yml index 496229ade18..b08ce73f886 100644 --- a/.github/workflows/local_example.yml +++ b/.github/workflows/local_example.yml @@ -17,7 +17,7 @@ jobs: - name: Get dependencies run: | - sudo apt-get update + sudo apt-get update || echo "update failed" sudo apt-get install -y mysql-server mysql-client make unzip g++ etcd curl git wget sudo service mysql stop sudo service etcd stop diff --git a/.github/workflows/unit.yml b/.github/workflows/unit.yml index 6cfc4d77967..37df2da855a 100644 --- a/.github/workflows/unit.yml +++ b/.github/workflows/unit.yml @@ -19,7 +19,7 @@ jobs: - name: Get dependencies run: | - sudo apt-get update + sudo apt-get update || echo "update failed" if [ ${{matrix.name}} = "mysql57" ]; then sudo apt-get install -y mysql-server mysql-client @@ -29,7 +29,7 @@ jobs: wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.14-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* - sudo apt-get update + sudo apt-get update || echo "update failed" sudo DEBIAN_FRONTEND="noninteractive" apt-get install -y mysql-server mysql-client elif [ ${{matrix.name}} = "mariadb101" ]; then sudo apt-get remove -y mysql-server mysql-client diff --git a/.github/workflows/unit_race.yml b/.github/workflows/unit_race.yml index 7da452685d8..6f065bf2737 100644 --- a/.github/workflows/unit_race.yml +++ b/.github/workflows/unit_race.yml @@ -17,7 +17,7 @@ jobs: - name: Get dependencies run: | - sudo apt-get update + sudo apt-get update || echo "update failed" sudo apt-get install -y mysql-server mysql-client make unzip g++ etcd curl git wget sudo service mysql stop sudo service etcd stop diff --git a/go.mod b/go.mod index 44d8c461dd1..af52af73134 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f // indirect github.com/dchest/safefile v0.0.0-20151022103144-855e8d98f185 // indirect github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect - github.com/evanphx/json-patch v4.5.0+incompatible // indirect + github.com/evanphx/json-patch v4.5.0+incompatible github.com/ghodss/yaml v0.0.0-20161207003320-04f313413ffd // indirect github.com/go-ini/ini v1.12.0 // indirect github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b @@ -45,7 +45,7 @@ require ( github.com/klauspost/crc32 v1.2.0 // indirect github.com/klauspost/pgzip v1.2.0 github.com/kr/pretty v0.1.0 // indirect - github.com/krishicks/yaml-patch v0.0.10 // indirect + github.com/krishicks/yaml-patch v0.0.10 github.com/mattn/go-runewidth v0.0.1 // indirect github.com/minio/minio-go v0.0.0-20190131015406-c8a261de75c1 github.com/mitchellh/go-testing-interface v1.0.0 // indirect diff --git a/go/mysql/encoding.go b/go/mysql/encoding.go index c9333522cdf..53b9e2efc73 100644 --- a/go/mysql/encoding.go +++ b/go/mysql/encoding.go @@ -281,3 +281,17 @@ func readLenEncStringAsBytes(data []byte, pos int) ([]byte, int, bool) { } return data[pos : pos+s], pos + s, true } + +func readLenEncStringAsBytesCopy(data []byte, pos int) ([]byte, int, bool) { + size, pos, ok := readLenEncInt(data, pos) + if !ok { + return nil, 0, false + } + s := int(size) + if pos+s-1 >= len(data) { + return nil, 0, false + } + result := make([]byte, size) + copy(result, data[pos:pos+s]) + return result, pos + s, true +} diff --git a/go/mysql/encoding_test.go b/go/mysql/encoding_test.go index 2ca9a84c934..ac38b5c7db0 100644 --- a/go/mysql/encoding_test.go +++ b/go/mysql/encoding_test.go @@ -303,6 +303,24 @@ func TestEncString(t *testing.T) { t.Errorf("readLenEncStringAsBytes returned ok=true for empty value %v", test.value) } + // Check successful decoding as bytes. + gotbcopy, posCopy, ok := readLenEncStringAsBytesCopy(test.lenEncoded, 0) + if !ok || string(gotb) != test.value || pos != len(test.lenEncoded) { + t.Errorf("readLenEncString returned %v/%v/%v but expected %v/%v/%v", gotbcopy, posCopy, ok, test.value, len(test.lenEncoded), true) + } + + // Check failed decoding as bytes with shorter data. + _, _, ok = readLenEncStringAsBytesCopy(test.lenEncoded[:len(test.lenEncoded)-1], 0) + if ok { + t.Errorf("readLenEncStringAsBytes returned ok=true for shorter value %v", test.value) + } + + // Check failed decoding as bytes with no data. + _, _, ok = readLenEncStringAsBytesCopy([]byte{}, 0) + if ok { + t.Errorf("readLenEncStringAsBytes returned ok=true for empty value %v", test.value) + } + // null encoded tests. // Check successful encoding. diff --git a/go/mysql/query.go b/go/mysql/query.go index 6ff9d1e9bc0..f6435bf4b64 100644 --- a/go/mysql/query.go +++ b/go/mysql/query.go @@ -261,7 +261,7 @@ func (c *Conn) parseRow(data []byte, fields []*querypb.Field) ([]sqltypes.Value, } var s []byte var ok bool - s, pos, ok = readLenEncStringAsBytes(data, pos) + s, pos, ok = readLenEncStringAsBytesCopy(data, pos) if !ok { return nil, NewSQLError(CRMalformedPacket, SSUnknownSQLState, "decoding string failed") } @@ -823,7 +823,7 @@ func (c *Conn) parseStmtArgs(data []byte, typ querypb.Type, pos int) (sqltypes.V } case sqltypes.Decimal, sqltypes.Text, sqltypes.Blob, sqltypes.VarChar, sqltypes.VarBinary, sqltypes.Char, sqltypes.Bit, sqltypes.Enum, sqltypes.Set, sqltypes.Geometry, sqltypes.Binary, sqltypes.TypeJSON: - val, pos, ok := readLenEncStringAsBytes(data, pos) + val, pos, ok := readLenEncStringAsBytesCopy(data, pos) return sqltypes.MakeTrusted(sqltypes.VarBinary, val), pos, ok default: return sqltypes.NULL, pos, false diff --git a/go/vt/discovery/healthcheck_test.go b/go/vt/discovery/healthcheck_flaky_test.go similarity index 100% rename from go/vt/discovery/healthcheck_test.go rename to go/vt/discovery/healthcheck_flaky_test.go diff --git a/go/vt/logutil/logutil_test.go b/go/vt/logutil/logutil_flaky_test.go similarity index 100% rename from go/vt/logutil/logutil_test.go rename to go/vt/logutil/logutil_flaky_test.go diff --git a/go/vt/vtgate/executor.go b/go/vt/vtgate/executor.go index 7a91df5e65e..63e3a0bdfb2 100644 --- a/go/vt/vtgate/executor.go +++ b/go/vt/vtgate/executor.go @@ -845,6 +845,14 @@ func (e *Executor) handleShow(ctx context.Context, safeSession *SafeSession, sql } } } + case sqlparser.KeywordString(sqlparser.COLUMNS): + if !show.OnTable.Qualifier.IsEmpty() { + destKeyspace = show.OnTable.Qualifier.String() + show.OnTable.Qualifier = sqlparser.NewTableIdent("") + } else { + break + } + sql = sqlparser.String(show) case sqlparser.KeywordString(sqlparser.TABLES): if show.ShowTablesOpt != nil && show.ShowTablesOpt.DbName != "" { if destKeyspace == "" { diff --git a/go/vt/vtgate/executor_test.go b/go/vt/vtgate/executor_test.go index 8767cd0928c..8a42e884bc6 100644 --- a/go/vt/vtgate/executor_test.go +++ b/go/vt/vtgate/executor_test.go @@ -890,6 +890,13 @@ func TestExecutorShow(t *testing.T) { if err != nil { t.Error(err) } + + // Test SHOW FULL COLUMNS FROM where query has a qualifier + _, err = executor.Execute(context.Background(), "TestExecute", session, fmt.Sprintf("show full columns from %v.table1", KsTestUnsharded), nil) + if err != nil { + t.Errorf("Unexpected error: %v", err) + } + // Just test for first & last. qr.Rows = [][]sqltypes.Value{qr.Rows[0], qr.Rows[len(qr.Rows)-1]} wantqr = &sqltypes.Result{ diff --git a/go/vt/vttablet/tabletmanager/vreplication/vcopier_test.go b/go/vt/vttablet/tabletmanager/vreplication/vcopier_flaky_test.go similarity index 100% rename from go/vt/vttablet/tabletmanager/vreplication/vcopier_test.go rename to go/vt/vttablet/tabletmanager/vreplication/vcopier_flaky_test.go diff --git a/tools/unit_test_runner.sh b/tools/unit_test_runner.sh index 4cffb3eb913..879626d7bf7 100755 --- a/tools/unit_test_runner.sh +++ b/tools/unit_test_runner.sh @@ -55,6 +55,8 @@ if [ $? -ne 0 ]; then exit 1 fi +echo '# Flaky tests (3 attempts permitted)' + # Run flaky tests sequentially. Retry when necessary. for pkg in $flaky_tests; do max_attempts=3