Skip to content

Commit

Permalink
Add basic vector support for MySQL 9.x (vitessio#16464)
Browse files Browse the repository at this point in the history
Signed-off-by: Dirkjan Bussink <[email protected]>
  • Loading branch information
dbussink authored Jul 24, 2024
1 parent be8f9f4 commit 134a7dc
Show file tree
Hide file tree
Showing 30 changed files with 9,572 additions and 9,492 deletions.
3 changes: 3 additions & 0 deletions go/mysql/binlog/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ const (
// TypeTime2 is MYSQL_TYPE_TIME2
TypeTime2 = 19

// TypeVector is MYSQL_TYPE_VECTOR
TypeVector = 242

// TypeJSON is MYSQL_TYPE_JSON
TypeJSON = 245

Expand Down
6 changes: 3 additions & 3 deletions go/mysql/binlog/rbr.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ func CellLength(data []byte, pos int, typ byte, metadata uint16) (int, error) {
return intg0*4 + dig2bytes[intg0x] + frac0*4 + dig2bytes[frac0x], nil
case TypeEnum, TypeSet:
return int(metadata & 0xff), nil
case TypeJSON, TypeTinyBlob, TypeMediumBlob, TypeLongBlob, TypeBlob, TypeGeometry:
case TypeJSON, TypeTinyBlob, TypeMediumBlob, TypeLongBlob, TypeBlob, TypeGeometry, TypeVector:
// Of the Blobs, only TypeBlob is used in binary logs,
// but supports others just in case.
switch metadata {
Expand Down Expand Up @@ -652,8 +652,8 @@ func CellValue(data []byte, pos int, typ byte, metadata uint16, field *querypb.F
return sqltypes.MakeTrusted(querypb.Type_SET,
data[pos:pos+l]), l, nil

case TypeJSON, TypeTinyBlob, TypeMediumBlob, TypeLongBlob, TypeBlob:
// Only TypeBlob is used in binary logs,
case TypeJSON, TypeTinyBlob, TypeMediumBlob, TypeLongBlob, TypeBlob, TypeVector:
// Only TypeBlob and TypeVector is used in binary logs,
// but supports others just in case.
l := 0
switch metadata {
Expand Down
7 changes: 4 additions & 3 deletions go/mysql/binlog_event_rbr.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ const (
tableMapEnumAndSetDefaultCharset
tableMapEnumAndSetColumnCharset
tableMapColumnVisibility
tableMapVectorDimensionality
)

// This byte in the optional metadata indicates that we should
Expand Down Expand Up @@ -136,7 +137,7 @@ func metadataLength(typ byte) int {
// No data here.
return 0

case binlog.TypeFloat, binlog.TypeDouble, binlog.TypeTimestamp2, binlog.TypeDateTime2, binlog.TypeTime2, binlog.TypeJSON, binlog.TypeTinyBlob, binlog.TypeMediumBlob, binlog.TypeLongBlob, binlog.TypeBlob, binlog.TypeGeometry:
case binlog.TypeFloat, binlog.TypeDouble, binlog.TypeTimestamp2, binlog.TypeDateTime2, binlog.TypeTime2, binlog.TypeJSON, binlog.TypeTinyBlob, binlog.TypeMediumBlob, binlog.TypeLongBlob, binlog.TypeBlob, binlog.TypeGeometry, binlog.TypeVector:
// One byte.
return 1

Expand Down Expand Up @@ -172,7 +173,7 @@ func metadataRead(data []byte, pos int, typ byte) (uint16, int, error) {
// No data here.
return 0, pos, nil

case binlog.TypeFloat, binlog.TypeDouble, binlog.TypeTimestamp2, binlog.TypeDateTime2, binlog.TypeTime2, binlog.TypeJSON, binlog.TypeTinyBlob, binlog.TypeMediumBlob, binlog.TypeLongBlob, binlog.TypeBlob, binlog.TypeGeometry:
case binlog.TypeFloat, binlog.TypeDouble, binlog.TypeTimestamp2, binlog.TypeDateTime2, binlog.TypeTime2, binlog.TypeJSON, binlog.TypeTinyBlob, binlog.TypeMediumBlob, binlog.TypeLongBlob, binlog.TypeBlob, binlog.TypeGeometry, binlog.TypeVector:
// One byte.
return uint16(data[pos]), pos + 1, nil

Expand All @@ -198,7 +199,7 @@ func metadataWrite(data []byte, pos int, typ byte, value uint16) int {
// No data here.
return pos

case binlog.TypeFloat, binlog.TypeDouble, binlog.TypeTimestamp2, binlog.TypeDateTime2, binlog.TypeTime2, binlog.TypeJSON, binlog.TypeTinyBlob, binlog.TypeMediumBlob, binlog.TypeLongBlob, binlog.TypeBlob, binlog.TypeGeometry:
case binlog.TypeFloat, binlog.TypeDouble, binlog.TypeTimestamp2, binlog.TypeDateTime2, binlog.TypeTime2, binlog.TypeJSON, binlog.TypeTinyBlob, binlog.TypeMediumBlob, binlog.TypeLongBlob, binlog.TypeBlob, binlog.TypeGeometry, binlog.TypeVector:
// One byte.
data[pos] = byte(value)
return pos + 1
Expand Down
2 changes: 1 addition & 1 deletion go/mysql/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -891,7 +891,7 @@ func (c *Conn) parseStmtArgs(data []byte, typ querypb.Type, pos int) (sqltypes.V
return sqltypes.NULL, 0, false
}
case sqltypes.Decimal, sqltypes.Text, sqltypes.Blob, sqltypes.VarChar, sqltypes.VarBinary, sqltypes.Year, sqltypes.Char,
sqltypes.Bit, sqltypes.Enum, sqltypes.Set, sqltypes.Geometry, sqltypes.Binary, sqltypes.TypeJSON:
sqltypes.Bit, sqltypes.Enum, sqltypes.Set, sqltypes.Geometry, sqltypes.Binary, sqltypes.TypeJSON, sqltypes.Vector:
val, pos, ok := readLenEncStringAsBytesCopy(data, pos)
return sqltypes.MakeTrusted(sqltypes.VarBinary, val), pos, ok
default:
Expand Down
3 changes: 3 additions & 0 deletions go/mysql/query_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,7 @@ func TestQueries(t *testing.T) {
// Skip TUPLE, not possible in Result.
{Name: "Type_GEOMETRY ", Type: querypb.Type_GEOMETRY, Charset: collations.CollationBinaryID, Flags: uint32(querypb.MySqlFlag_BINARY_FLAG | querypb.MySqlFlag_BLOB_FLAG)},
{Name: "Type_JSON ", Type: querypb.Type_JSON, Charset: collations.CollationUtf8mb4ID},
{Name: "Type_VECTOR ", Type: querypb.Type_VECTOR, Charset: collations.CollationBinaryID},
},
Rows: [][]sqltypes.Value{
{
Expand Down Expand Up @@ -492,6 +493,7 @@ func TestQueries(t *testing.T) {
sqltypes.MakeTrusted(querypb.Type_SET, []byte("Type_SET")),
sqltypes.MakeTrusted(querypb.Type_GEOMETRY, []byte("Type_GEOMETRY")),
sqltypes.MakeTrusted(querypb.Type_JSON, []byte("Type_JSON")),
sqltypes.MakeTrusted(querypb.Type_VECTOR, []byte("Type_VECTOR")),
},
{
sqltypes.NULL,
Expand Down Expand Up @@ -523,6 +525,7 @@ func TestQueries(t *testing.T) {
sqltypes.NULL,
sqltypes.NULL,
sqltypes.NULL,
sqltypes.NULL,
},
},
})
Expand Down
2 changes: 2 additions & 0 deletions go/mysql/sqlerror/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ const (
ERDupIndex = ErrorCode(1831)
ERInnodbReadOnly = ErrorCode(1874)

ERVectorConversion = ErrorCode(6138)

// already exists
ERDbCreateExists = ErrorCode(1007)
ERTableExists = ErrorCode(1050)
Expand Down
1 change: 1 addition & 0 deletions go/mysql/sqlerror/sql_error.go
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@ var stateToMysqlCode = map[vterrors.State]mysqlCode{
vterrors.KillDeniedError: {num: ERKillDenied, state: SSUnknownSQLState},
vterrors.BadNullError: {num: ERBadNullError, state: SSConstraintViolation},
vterrors.InvalidGroupFuncUse: {num: ERInvalidGroupFuncUse, state: SSUnknownSQLState},
vterrors.VectorConversion: {num: ERVectorConversion, state: SSUnknownSQLState},
}

func getStateToMySQLState(state vterrors.State) mysqlCode {
Expand Down
3 changes: 3 additions & 0 deletions go/sqltypes/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ const (
HexVal = querypb.Type_HEXVAL
Tuple = querypb.Type_TUPLE
BitNum = querypb.Type_BITNUM
Vector = querypb.Type_VECTOR
)

// bit-shift the mysql flags by two byte so we
Expand Down Expand Up @@ -219,6 +220,7 @@ var mysqlToType = map[byte]querypb.Type{
17: Timestamp,
18: Datetime,
19: Time,
242: Vector,
245: TypeJSON,
246: Decimal,
247: Enum,
Expand Down Expand Up @@ -331,6 +333,7 @@ var typeToMySQL = map[querypb.Type]struct {
Datetime: {typ: 12, flags: mysqlBinary},
Year: {typ: 13, flags: mysqlUnsigned},
Bit: {typ: 16, flags: mysqlUnsigned},
Vector: {typ: 242},
TypeJSON: {typ: 245},
Decimal: {typ: 246},
Text: {typ: 252},
Expand Down
34 changes: 20 additions & 14 deletions go/vt/proto/query/query.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions go/vt/sqlparser/ast_funcs.go
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,8 @@ func SQLTypeToQueryType(typeName string, unsigned bool) querypb.Type {
return sqltypes.Set
case JSON:
return sqltypes.TypeJSON
case VECTOR:
return sqltypes.Vector
case GEOMETRY:
return sqltypes.Geometry
case POINT:
Expand Down
1 change: 1 addition & 0 deletions go/vt/sqlparser/keywords.go
Original file line number Diff line number Diff line change
Expand Up @@ -752,6 +752,7 @@ var keywords = []keyword{
{"varcharacter", UNUSED},
{"variance", VARIANCE},
{"varying", UNUSED},
{"vector", VECTOR},
{"vexplain", VEXPLAIN},
{"vgtid_executed", VGTID_EXECUTED},
{"virtual", VIRTUAL},
Expand Down
7 changes: 7 additions & 0 deletions go/vt/sqlparser/parse_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1228,6 +1228,9 @@ var (
input: "select /* bool in order by */ * from t order by a is null or b asc",
}, {
input: "select /* string in case statement */ if(max(case a when 'foo' then 1 else 0 end) = 1, 'foo', 'bar') as foobar from t",
}, {
input: "select 1 as vector",
output: "select 1 as `vector` from dual",
}, {
input: "/*!show databases*/",
output: "show databases",
Expand Down Expand Up @@ -5924,6 +5927,10 @@ partition by range (YEAR(purchased)) subpartition by hash (TO_DAYS(purchased))
input: "create table t (id int, s varchar(255) default 'foo\"bar')",
output: "create table t (\n\tid int,\n\ts varchar(255) default 'foo\"bar'\n)",
},
{
input: "create table t (id int, vec VECTOR(4))",
output: "create table t (\n\tid int,\n\tvec VECTOR(4)\n)",
},
}
parser := NewTestParser()
for _, test := range createTableQueries {
Expand Down
Loading

0 comments on commit 134a7dc

Please sign in to comment.