Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tests for numeric_precision and numeric_scale columns in information_schema #7763

Merged
merged 6 commits into from
Mar 31, 2021
Merged
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
47 changes: 46 additions & 1 deletion go/mysql/endtoend/query_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@ limitations under the License.
package endtoend

import (
"context"
"fmt"
"math/rand"
"strings"
"testing"

"context"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"vitess.io/vitess/go/mysql"
"vitess.io/vitess/go/sqltypes"
Expand Down Expand Up @@ -285,3 +287,46 @@ func TestWarningsDeprecateEOF(t *testing.T) {
func TestWarningsNoDeprecateEOF(t *testing.T) {
doTestWarnings(t, true)
}

func TestSysInfo(t *testing.T) {
ctx := context.Background()
conn, err := mysql.Connect(ctx, &connParams)
require.NoError(t, err)
defer conn.Close()

_, err = conn.ExecuteFetch("drop table if exists `a`", 1000, true)
require.NoError(t, err)

_, err = conn.ExecuteFetch("CREATE TABLE `a` (`one` int NOT NULL,`two` int NOT NULL,PRIMARY KEY (`one`,`two`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", 1000, true)
require.NoError(t, err)
defer conn.ExecuteFetch("drop table `a`", 1000, true)

qr, err := conn.ExecuteFetch(`SELECT
column_name column_name,
data_type data_type,
column_type full_data_type,
character_maximum_length character_maximum_length,
numeric_precision numeric_precision,
numeric_scale numeric_scale,
datetime_precision datetime_precision,
column_default column_default,
is_nullable is_nullable,
extra extra,
table_name table_name
FROM information_schema.columns
WHERE table_schema = 'vttest' and table_name = 'a'
ORDER BY ordinal_position`, 1000, true)
require.NoError(t, err)
require.Equal(t, 2, len(qr.Rows))

// is_nullable
assert.Equal(t, `VARCHAR("NO")`, qr.Rows[0][8].String())
assert.Equal(t, `VARCHAR("NO")`, qr.Rows[1][8].String())

// table_name
assert.Equal(t, `VARCHAR("a")`, qr.Rows[0][10].String())
assert.Equal(t, `VARCHAR("a")`, qr.Rows[1][10].String())

assert.EqualValues(t, sqltypes.Uint64, qr.Fields[4].Type)
assert.EqualValues(t, querypb.Type_UINT64, qr.Rows[0][4].Type())
}
2 changes: 1 addition & 1 deletion go/test/endtoend/vtgate/misc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -592,7 +592,7 @@ func TestSubQueryOnTopOfSubQuery(t *testing.T) {
exec(t, conn, `insert into t1(id1, id2) values (1, 1), (2, 2), (3, 3), (4, 4), (5, 5)`)
exec(t, conn, `insert into t2(id3, id4) values (1, 3), (2, 4)`)

assertMatches(t, conn, "select id1 from t1 where id1 not in (select id3 from t2) and id2 in (select id4 from t2)", `[[INT64(3)] [INT64(4)]]`)
assertMatches(t, conn, "select id1 from t1 where id1 not in (select id3 from t2) and id2 in (select id4 from t2) order by id1", `[[INT64(3)] [INT64(4)]]`)
}

func assertMatches(t *testing.T, conn *mysql.Conn, query, expected string) {
Expand Down
40 changes: 40 additions & 0 deletions go/test/endtoend/vtgate/unsharded/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"time"

"vitess.io/vitess/go/vt/log"
querypb "vitess.io/vitess/go/vt/proto/query"

"github.com/google/go-cmp/cmp"
"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -396,6 +397,45 @@ func TestReservedConnDML(t *testing.T) {
exec(t, conn, `commit`)
}

func TestNumericPrecisionScale(t *testing.T) {
defer cluster.PanicHandler(t)
ctx := context.Background()
vtParams := mysql.ConnParams{
Host: "localhost",
Port: clusterInstance.VtgateMySQLPort,
}
conn, err := mysql.Connect(ctx, &vtParams)
require.NoError(t, err)
defer conn.Close()

_ = exec(t, conn, "CREATE TABLE `a` (`one` bigint NOT NULL PRIMARY KEY) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4")
require.NoError(t, err)
defer exec(t, conn, "drop table `a`")

qr := exec(t, conn, "select numeric_precision, numeric_scale from information_schema.columns where table_name = 'a'")
require.Equal(t, 1, len(qr.Rows))

/*
We expect UINT64 to be returned as type for field and rows from VTGate to client.

require.Equal(t, querypb.Type_UINT64, qr.Fields[0].Type)
require.Equal(t, querypb.Type_UINT64, qr.Fields[1].Type)
require.Equal(t, sqltypes.Uint64, qr.Rows[0][0].Type())
require.Equal(t, sqltypes.Uint64, qr.Rows[0][1].Type())

But, the field query from mysql returns field at UINT32 and row types as UINT64.
Our conversion on VTGate on receiving data from VTTablet the Rows are converted to Field Types.
So, we see UINT32 for both fields and rows.

This issue is only with MySQL 8.0. In CI we use 5.7 as well. So asserting with both the values.
*/

assert.True(t, qr.Fields[0].Type == querypb.Type_UINT64 || qr.Fields[0].Type == querypb.Type_UINT32)
assert.True(t, qr.Fields[1].Type == querypb.Type_UINT64 || qr.Fields[1].Type == querypb.Type_UINT32)
assert.True(t, qr.Rows[0][0].Type() == sqltypes.Uint64 || qr.Rows[0][0].Type() == sqltypes.Uint32)
assert.True(t, qr.Rows[0][1].Type() == sqltypes.Uint64 || qr.Rows[0][1].Type() == sqltypes.Uint32)
}

func exec(t *testing.T, conn *mysql.Conn, query string) *sqltypes.Result {
t.Helper()
qr, err := conn.ExecuteFetch(query, 1000, true)
Expand Down
2 changes: 1 addition & 1 deletion go/vt/vttablet/endtoend/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ var tableACLConfig = `{
},
{
"name": "sys_table",
"table_names_or_prefixes": ["tables", "user", "processlist", "mutex_instances"],
"table_names_or_prefixes": ["tables", "user", "processlist", "mutex_instances", "columns", "a"],
"readers": ["dev"],
"writers": ["dev"],
"admins": ["dev"]
Expand Down
65 changes: 65 additions & 0 deletions go/vt/vttablet/endtoend/misc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -779,3 +779,68 @@ func TestSelectBooleanSystemVariables(t *testing.T) {
require.Equal(t, tc.Type, qr.Fields[0].Type, fmt.Sprintf("invalid type, wants: %+v, but got: %+v\n", tc.Type, qr.Fields[0].Type))
}
}

func TestSysSchema(t *testing.T) {
client := framework.NewClient()
_, err := client.Execute("drop table if exists `a`", nil)
require.NoError(t, err)

_, err = client.Execute("CREATE TABLE `a` (`one` int NOT NULL,`two` int NOT NULL,PRIMARY KEY (`one`,`two`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", nil)
require.NoError(t, err)
defer client.Execute("drop table `a`", nil)

qr, err := client.Execute(`SELECT
column_name column_name,
data_type data_type,
column_type full_data_type,
character_maximum_length character_maximum_length,
numeric_precision numeric_precision,
numeric_scale numeric_scale,
datetime_precision datetime_precision,
column_default column_default,
is_nullable is_nullable,
extra extra,
table_name table_name
FROM information_schema.columns
WHERE 1 != 1
ORDER BY ordinal_position`, nil)
require.NoError(t, err)

// This is mysql behaviour that we are receiving Uint32 on field query even though the column is Uint64.
// assert.EqualValues(t, sqltypes.Uint64, qr.Fields[4].Type) - ideally this should be received
// The issue is only in MySQL 8.0 , As CI is on MySQL 5.7 need to check with Uint64
assert.True(t, qr.Fields[4].Type == sqltypes.Uint64 || qr.Fields[4].Type == sqltypes.Uint32)

qr, err = client.Execute(`SELECT
column_name column_name,
data_type data_type,
column_type full_data_type,
character_maximum_length character_maximum_length,
numeric_precision numeric_precision,
numeric_scale numeric_scale,
datetime_precision datetime_precision,
column_default column_default,
is_nullable is_nullable,
extra extra,
table_name table_name
FROM information_schema.columns
WHERE table_schema = 'vttest' and table_name = 'a'
ORDER BY ordinal_position`, nil)
require.NoError(t, err)
require.Equal(t, 2, len(qr.Rows))

// is_nullable
assert.Equal(t, `VARCHAR("NO")`, qr.Rows[0][8].String())
assert.Equal(t, `VARCHAR("NO")`, qr.Rows[1][8].String())

// table_name
assert.Equal(t, `VARCHAR("a")`, qr.Rows[0][10].String())
assert.Equal(t, `VARCHAR("a")`, qr.Rows[1][10].String())

// The field Type and the row value type are not matching and because of this wrong packet is send regarding the data of bigint unsigned to the client on vttestserver.
// On, Vitess cluster using protobuf we are doing the row conversion to field type and so the final row type send to client is same as field type.
// assert.EqualValues(t, sqltypes.Uint64, qr.Fields[4].Type) - We would have received this but because of field caching we are receiving Uint32.
// The issue is only in MySQL 8.0 , As CI is on MySQL 5.7 need to check with Uint64
assert.True(t, qr.Fields[4].Type == sqltypes.Uint64 || qr.Fields[4].Type == sqltypes.Uint32)
assert.Equal(t, querypb.Type_UINT64, qr.Rows[0][4].Type())
}