diff --git a/ast/ddl.go b/ast/ddl.go index ab75ccb..12f668b 100644 --- a/ast/ddl.go +++ b/ast/ddl.go @@ -527,6 +527,7 @@ const ( ColumnOptionStorage ColumnOptionAutoRandom ColumnOptionSecondaryEngineAttribute + ColumnOptionSrid ) var ( @@ -564,6 +565,8 @@ type ColumnOption struct { ConstraintName string PrimaryKeyTp PrimaryKeyType SecondaryEngineAttr string + // UintValue is only for ColumnOptionSrid. + UintValue uint64 } // Restore implements Node interface. @@ -686,6 +689,9 @@ func (n *ColumnOption) Restore(ctx *format.RestoreCtx) error { ctx.WriteKeyWord("SECONDARY_ENGINE_ATTRIBUTE") ctx.WritePlain(" = ") ctx.WriteString(n.StrValue) + case ColumnOptionSrid: + ctx.WriteKeyWord("SRID ") + ctx.WritePlainf("%d", n.UintValue) default: return errors.New("An error occurred while splicing ColumnOption") } @@ -933,6 +939,8 @@ const ( // It will be rewritten into ConstraintColumnar after preprocessor phase. ConstraintVector ConstraintColumnar + // ConstraintSpatial is only used in AST. + ConstraintSpatial ) // Constraint is constraint for table definition. @@ -987,6 +995,8 @@ func (n *Constraint) Restore(ctx *format.RestoreCtx) error { ctx.WriteKeyWord("UNIQUE INDEX") case ConstraintFulltext: ctx.WriteKeyWord("FULLTEXT") + case ConstraintSpatial: + ctx.WriteKeyWord("SPATIAL") case ConstraintCheck: if n.Name != "" { ctx.WriteKeyWord("CONSTRAINT ") diff --git a/mysql/type.go b/mysql/type.go index 6f1ace0..2158626 100644 --- a/mysql/type.go +++ b/mysql/type.go @@ -47,6 +47,17 @@ const ( TypeGeometry byte = 0xff TypeTiDBVectorFloat32 byte = 0xe1 + + // MySQL reports every spatial column as TypeGeometry on the wire; these + // bytes exist only so the parser can keep the declared spatial subtype + // (following the TypeTiDBVectorFloat32 precedent for non-wire types). + TypePoint byte = 0xe2 + TypeLineString byte = 0xe3 + TypePolygon byte = 0xe4 + TypeMultiPoint byte = 0xe5 + TypeMultiLineString byte = 0xe6 + TypeMultiPolygon byte = 0xe7 + TypeGeometryCollection byte = 0xe8 ) // Flag information. diff --git a/parser/keyword_classes.go b/parser/keyword_classes.go index 9e3e08f..1a993dc 100644 --- a/parser/keyword_classes.go +++ b/parser/keyword_classes.go @@ -122,6 +122,14 @@ var unReservedKeywordNames = []string{ "STATUS", "OPEN", "POINT", + "GEOMETRY", + "GEOMETRYCOLLECTION", + "LINESTRING", + "MULTILINESTRING", + "MULTIPOINT", + "MULTIPOLYGON", + "POLYGON", + "SRID", "SUBPARTITIONS", "SUBPARTITION", "TABLES", diff --git a/parser/keywords.go b/parser/keywords.go index 25f3b14..b0f38c5 100644 --- a/parser/keywords.go +++ b/parser/keywords.go @@ -429,6 +429,8 @@ var Keywords = []KeywordsType{ {"FULL", false, "unreserved"}, {"FUNCTION", false, "unreserved"}, {"GENERAL", false, "unreserved"}, + {"GEOMETRY", false, "unreserved"}, + {"GEOMETRYCOLLECTION", false, "unreserved"}, {"GLOBAL", false, "unreserved"}, {"GRANTS", false, "unreserved"}, {"GROUP_REPLICATION", false, "unreserved"}, @@ -471,6 +473,7 @@ var Keywords = []KeywordsType{ {"LESS", false, "unreserved"}, {"LEVEL", false, "unreserved"}, {"LIBRARY", false, "unreserved"}, + {"LINESTRING", false, "unreserved"}, {"LIST", false, "unreserved"}, {"LOAD_STATS", false, "unreserved"}, {"LOCAL", false, "unreserved"}, @@ -500,6 +503,9 @@ var Keywords = []KeywordsType{ {"MODE", false, "unreserved"}, {"MODIFY", false, "unreserved"}, {"MONTH", false, "unreserved"}, + {"MULTILINESTRING", false, "unreserved"}, + {"MULTIPOINT", false, "unreserved"}, + {"MULTIPOLYGON", false, "unreserved"}, {"MUTEX", false, "unreserved"}, {"NAMES", false, "unreserved"}, {"NATIONAL", false, "unreserved"}, @@ -553,6 +559,7 @@ var Keywords = []KeywordsType{ {"PLUGINS", false, "unreserved"}, {"POINT", false, "unreserved"}, {"POLICY", false, "unreserved"}, + {"POLYGON", false, "unreserved"}, {"PRECEDES", false, "unreserved"}, {"PRECEDING", false, "unreserved"}, {"PREPARE", false, "unreserved"}, @@ -647,6 +654,7 @@ var Keywords = []KeywordsType{ {"SQL_TSI_SECOND", false, "unreserved"}, {"SQL_TSI_WEEK", false, "unreserved"}, {"SQL_TSI_YEAR", false, "unreserved"}, + {"SRID", false, "unreserved"}, {"STACKED", false, "unreserved"}, {"START", false, "unreserved"}, {"STARTS", false, "unreserved"}, diff --git a/parser/keywords_test.go b/parser/keywords_test.go index a5f4b4f..81fbaf6 100644 --- a/parser/keywords_test.go +++ b/parser/keywords_test.go @@ -43,8 +43,8 @@ func TestKeywords(t *testing.T) { } func TestKeywordsLength(t *testing.T) { - if !reflect.DeepEqual(751, len(parser.Keywords)) { - t.Fatalf("got %v, want %v", len(parser.Keywords), 751) + if !reflect.DeepEqual(759, len(parser.Keywords)) { + t.Fatalf("got %v, want %v", len(parser.Keywords), 759) } reservedNr := 0 diff --git a/parser/misc.go b/parser/misc.go index d01329a..646af7d 100644 --- a/parser/misc.go +++ b/parser/misc.go @@ -450,6 +450,9 @@ var tokenMap = map[string]int{ "GC_TTL": gcTTL, "GENERAL": general, "GENERATED": generated, + "GEOMCOLLECTION": geometryCollectionType, + "GEOMETRY": geometryType, + "GEOMETRYCOLLECTION": geometryCollectionType, "GET": get, "GET_FORMAT": getFormat, "GLOBAL": global, @@ -557,6 +560,7 @@ var tokenMap = map[string]int{ "LITE": lite, "LINEAR": linear, "LINES": lines, + "LINESTRING": linestringType, "LIST": list, "LOAD": load, "LOCAL": local, @@ -608,6 +612,9 @@ var tokenMap = map[string]int{ "MODIFY": modify, "MONITOR": monitor, "MONTH": month, + "MULTILINESTRING": multilinestringType, + "MULTIPOINT": multipointType, + "MULTIPOLYGON": multipolygonType, "MUTEX": mutex, "NAMES": names, "NATIONAL": national, @@ -688,6 +695,7 @@ var tokenMap = map[string]int{ "POINT": point, "POLICIES": policies, "POLICY": policy, + "POLYGON": polygonType, "POSITION": position, "PRE_SPLIT_REGIONS": preSplitRegions, "PRECEDES": precedes, @@ -847,6 +855,7 @@ var tokenMap = map[string]int{ "SQLEXCEPTION": sqlexception, "SQLSTATE": sqlstate, "SQLWARNING": sqlwarning, + "SRID": srid, "SSL": ssl, "STACKED": stacked, "STALENESS": staleness, @@ -1087,10 +1096,11 @@ var windowFuncTokenMap = map[string]int{ // aliases are strings directly map to another string and use the same token. var aliases = map[string]string{ - "SCHEMA": "DATABASE", - "SCHEMAS": "DATABASES", - "DEC": "DECIMAL", - "SUBSTR": "SUBSTRING", + "SCHEMA": "DATABASE", + "SCHEMAS": "DATABASES", + "DEC": "DECIMAL", + "GEOMCOLLECTION": "GEOMETRYCOLLECTION", + "SUBSTR": "SUBSTRING", } // hintedTokens is a set of tokens which recognizes a hint. diff --git a/parser/parse_alter.go b/parser/parse_alter.go index 70f175a..256d63d 100644 --- a/parser/parse_alter.go +++ b/parser/parse_alter.go @@ -732,7 +732,7 @@ func (r *rdParser) parseAlterTableSpec() *ast.AlterTableSpec { func (r *rdParser) parseAlterTableSpecAdd() *ast.AlterTableSpec { r.expect(add) switch r.tok() { - case constraint, primary, unique, fulltext, foreign, check, key, index: + case constraint, primary, unique, fulltext, spatial, foreign, check, key, index: // "ADD" ConstraintWithColumnarIndex (the Constraint alternative) return &ast.AlterTableSpec{ Tp: ast.AlterTableAddConstraint, diff --git a/parser/parse_column.go b/parser/parse_column.go index cf22b24..9565502 100644 --- a/parser/parse_column.go +++ b/parser/parse_column.go @@ -58,7 +58,8 @@ func (r *rdParser) isColumnOptionStart() bool { switch r.tok() { case not, not2, null, autoIncrement, primary, key, unique, defaultKwd, serial, on, comment, check, constraint, generated, as, references, - collate, columnFormat, storage, autoRandom, secondaryEngineAttribute: + collate, columnFormat, storage, autoRandom, secondaryEngineAttribute, + srid: return true } return false @@ -262,6 +263,14 @@ func (r *rdParser) parseColumnOption() interface{} { Tp: ast.ColumnOptionSecondaryEngineAttribute, StrValue: r.expect(stringLit).lit, } + case srid: + // ColumnOption: "SRID" LengthNum — the spatial column attribute + // (MySQL 26.7 §13.1.20.10); postdates the goyacc grammar. + r.advance() + return &ast.ColumnOption{ + Tp: ast.ColumnOptionSrid, + UintValue: r.parseLengthNum(), + } } r.syntaxError() return nil @@ -748,6 +757,32 @@ func (r *rdParser) parseConstraintElem() *ast.Constraint { c.Option = &ast.IndexOption{} } return c + case spatial: + // "SPATIAL" KeyOrIndexOpt IndexName '(' IndexPartSpecificationList ')' IndexOptionList + // — the MySQL 26.7 §15.1.20 table-constraint form, which postdates + // the goyacc grammar (it only had CREATE SPATIAL INDEX). Mirrors + // the FULLTEXT alternative. + r.advance() + if r.tok() == key || r.tok() == index { + r.advance() + } + name := r.parseIndexName() + r.expect(int('(')) + keys := r.parseIndexPartSpecificationList() + r.expect(int(')')) + option := r.parseIndexOptionList() + c := &ast.Constraint{ + Tp: ast.ConstraintSpatial, + Keys: keys, + Name: name.String, + IsEmptyIndex: name.Empty, + } + if option != nil { + c.Option = option + } else { + c.Option = &ast.IndexOption{} + } + return c case key, index: // KeyOrIndex IfNotExists IndexNameAndTypeOpt '(' IndexPartSpecificationList ')' IndexOptionList r.advance() diff --git a/parser/parse_create_table.go b/parser/parse_create_table.go index c01122a..017a861 100644 --- a/parser/parse_create_table.go +++ b/parser/parse_create_table.go @@ -331,7 +331,7 @@ func (r *rdParser) parseTableElementList() []interface{} { // ConstraintWithColumnarIndex. func (r *rdParser) parseTableElement() interface{} { switch r.tok() { - case constraint, primary, unique, fulltext, foreign, check, key, index: + case constraint, primary, unique, fulltext, spatial, foreign, check, key, index: // Constraint: ConstraintKeywordOpt ConstraintElem return r.parseConstraint() case vectorType, columnar: diff --git a/parser/parse_func.go b/parser/parse_func.go index 8051151..97b4a8e 100644 --- a/parser/parse_func.go +++ b/parser/parse_func.go @@ -1428,6 +1428,17 @@ func (r *rdParser) parseCastType() *types.FieldType { tp.SetCharset(charset.CharsetBin) tp.SetCollate(charset.CollationBin) return tp + case geometryType, point, linestringType, polygonType, multipointType, + multilinestringType, multipolygonType, geometryCollectionType: + // CastType: the spatial types — castable since MySQL 8.0.24 + // (MySQL 26.7 §14.10); postdates the goyacc grammar. + b := spatialTypeByte(r.tok()) + r.advance() + tp := types.NewFieldType(b) + tp.SetCharset(charset.CharsetBin) + tp.SetCollate(charset.CollationBin) + tp.AddFlag(mysql.BinaryFlag) + return tp case vectorType: // "VECTOR" OptVectorElementType OptFieldLen r.advance() diff --git a/parser/parse_types.go b/parser/parse_types.go index 30f2ca5..6620a89 100644 --- a/parser/parse_types.go +++ b/parser/parse_types.go @@ -320,6 +320,20 @@ func (r *rdParser) parseStringOrDateAndTimeType() *types.FieldType { tp.SetCharset(charset.CharsetBin) tp.SetCollate(charset.CollationBin) return tp + case geometryType, point, linestringType, polygonType, multipointType, + multilinestringType, multipolygonType, geometryCollectionType: + // SpatialType: "GEOMETRY" | "POINT" | "LINESTRING" | "POLYGON" + // | "MULTIPOINT" | "MULTILINESTRING" | "MULTIPOLYGON" + // | "GEOMETRYCOLLECTION" — MySQL 26.7 §13.4.1. The spatial types + // postdate the goyacc grammar; GEOMCOLLECTION lexes as its + // GEOMETRYCOLLECTION synonym. Spatial values are stored in a + // binary format, like JSON. + b := spatialTypeByte(r.tok()) + r.advance() + tp := types.NewFieldType(b) + tp.SetCharset(charset.CharsetBin) + tp.SetCollate(charset.CollationBin) + return tp case long: return r.parseLongType() case vectorType: @@ -390,15 +404,50 @@ func (r *rdParser) parseStringOrDateAndTimeType() *types.FieldType { return nil } +// spatialTypeByte maps a spatial type keyword token to its type byte. +func spatialTypeByte(tok int) byte { + switch tok { + case geometryType: + return mysql.TypeGeometry + case point: + return mysql.TypePoint + case linestringType: + return mysql.TypeLineString + case polygonType: + return mysql.TypePolygon + case multipointType: + return mysql.TypeMultiPoint + case multilinestringType: + return mysql.TypeMultiLineString + case multipolygonType: + return mysql.TypeMultiPolygon + case geometryCollectionType: + return mysql.TypeGeometryCollection + } + return 0 +} + // parseCharTail finishes `Char/NChar FieldLen OptBinary` and // `Char/NChar OptBinary` after the type keyword(s) have been consumed. +// Deviation from the goyacc grammar: the attribute is parsed as +// OptCharsetWithOptBinary, whose extra leading tokens admit the MySQL +// 26.7 §13.3.1 ASCII/UNICODE/BYTE attributes (`CHAR BYTE` is the +// documented alias for BINARY); goyacc allowed them only on TEXT, +// ENUM, SET, and LONG. func (r *rdParser) parseCharTail() *types.FieldType { tp := types.NewFieldType(mysql.TypeString) if r.tok() == int('(') { tp.SetFlen(r.parseFieldLen()) } - opt := r.parseOptBinary() + opt := r.parseOptCharsetWithOptBinary() tp.SetCharset(opt.Charset) + if opt.Charset == charset.CharsetBin { + // The binary charset (spelled BYTE or CHARACTER SET binary) makes + // the column BINARY(n); normalize like the TextType action so the + // result matches what parsing BINARY(n) produces. + tp.AddFlag(mysql.BinaryFlag) + tp.SetCollate(charset.CollationBin) + } if opt.IsBinary { tp.AddFlag(mysql.BinaryFlag) } @@ -406,13 +455,19 @@ func (r *rdParser) parseCharTail() *types.FieldType { } // parseVarcharTail finishes `Varchar/NVarchar FieldLen OptBinary` after -// the type keyword(s) have been consumed. +// the type keyword(s) have been consumed, with the same +// OptCharsetWithOptBinary deviation and binary-charset normalization as +// parseCharTail. func (r *rdParser) parseVarcharTail() *types.FieldType { flen := r.parseFieldLen() - opt := r.parseOptBinary() + opt := r.parseOptCharsetWithOptBinary() tp := types.NewFieldType(mysql.TypeVarchar) tp.SetFlen(flen) tp.SetCharset(opt.Charset) + if opt.Charset == charset.CharsetBin { + tp.AddFlag(mysql.BinaryFlag) + tp.SetCollate(charset.CollationBin) + } if opt.IsBinary { tp.AddFlag(mysql.BinaryFlag) } diff --git a/parser/testdata/parser/compat_types/input.sql b/parser/testdata/parser/compat_types/input.sql index 1810b90..a532170 100644 --- a/parser/testdata/parser/compat_types/input.sql +++ b/parser/testdata/parser/compat_types/input.sql @@ -29,3 +29,15 @@ CREATE TABLE t(id INT PRIMARY KEY, c1 LONG) CREATE TABLE t(id INT PRIMARY KEY, c1 MIDDLEINT) -- case CREATE TABLE t(id INT PRIMARY KEY, c1 NUMERIC) +-- case +CREATE TABLE t(id INT PRIMARY KEY, c1 CHAR(5) BYTE) +-- case +CREATE TABLE t(id INT PRIMARY KEY, c1 CHAR(5) ASCII) +-- case +CREATE TABLE t(id INT PRIMARY KEY, c1 CHAR(5) UNICODE) +-- case +CREATE TABLE t(id INT PRIMARY KEY, c1 VARCHAR(10) BYTE) +-- case +CREATE TABLE t(id INT PRIMARY KEY, c1 VARCHAR(10) ASCII) +-- case +CREATE TABLE t(id INT PRIMARY KEY, c1 VARCHAR(10) UNICODE) diff --git a/parser/testdata/parser/compat_types/output.sql b/parser/testdata/parser/compat_types/output.sql index 959aeb1..ffe609a 100644 --- a/parser/testdata/parser/compat_types/output.sql +++ b/parser/testdata/parser/compat_types/output.sql @@ -29,3 +29,15 @@ CREATE TABLE `t` (`id` INT PRIMARY KEY,`c1` MEDIUMTEXT) CREATE TABLE `t` (`id` INT PRIMARY KEY,`c1` MEDIUMINT) -- case CREATE TABLE `t` (`id` INT PRIMARY KEY,`c1` DECIMAL) +-- case +CREATE TABLE `t` (`id` INT PRIMARY KEY,`c1` BINARY(5)) +-- case +CREATE TABLE `t` (`id` INT PRIMARY KEY,`c1` CHAR(5) CHARACTER SET LATIN1) +-- case +-- error: [parser:1115]Unknown character set: 'ucs2' +-- case +CREATE TABLE `t` (`id` INT PRIMARY KEY,`c1` VARBINARY(10)) +-- case +CREATE TABLE `t` (`id` INT PRIMARY KEY,`c1` VARCHAR(10) CHARACTER SET LATIN1) +-- case +-- error: [parser:1115]Unknown character set: 'ucs2' diff --git a/parser/testdata/parser/spatial_types/input.sql b/parser/testdata/parser/spatial_types/input.sql new file mode 100644 index 0000000..af755df --- /dev/null +++ b/parser/testdata/parser/spatial_types/input.sql @@ -0,0 +1,51 @@ +CREATE TABLE t (g GEOMETRY) +-- case +CREATE TABLE t (pt POINT) +-- case +CREATE TABLE t (ls LINESTRING) +-- case +CREATE TABLE t (pg POLYGON) +-- case +CREATE TABLE t (mpt MULTIPOINT) +-- case +CREATE TABLE t (mls MULTILINESTRING) +-- case +CREATE TABLE t (mpg MULTIPOLYGON) +-- case +CREATE TABLE t (gc GEOMETRYCOLLECTION) +-- case +CREATE TABLE t (gc GEOMCOLLECTION) +-- case +CREATE TABLE t (g GEOMETRY NOT NULL) +-- case +CREATE TABLE t (g GEOMETRY NOT NULL SRID 4326) +-- case +CREATE TABLE t (pt POINT SRID 0) +-- case +CREATE TABLE t (g GEOMETRY NOT NULL SRID 4326, SPATIAL INDEX idx_g (g)) +-- case +CREATE TABLE t (g GEOMETRY NOT NULL, SPATIAL KEY (g)) +-- case +CREATE TABLE t (g GEOMETRY NOT NULL, SPATIAL (g)) +-- case +ALTER TABLE t ADD SPATIAL INDEX idx_g (g) +-- case +CREATE SPATIAL INDEX idx_g ON t (g) +-- case +CREATE TABLE geom (g GEOMETRY, p POINT NOT NULL SRID 4326, ll LINESTRING COMMENT 'path') +-- case +ALTER TABLE t ADD COLUMN g GEOMETRY NOT NULL SRID 4326 +-- case +ALTER TABLE t MODIFY COLUMN pt POINT SRID 4326 +-- case +CREATE TABLE t (geometry INT, point INT, linestring INT, polygon INT, multipoint INT, multilinestring INT, multipolygon INT, geometrycollection INT, srid INT) +-- case +SELECT geometry, point, srid FROM polygon +-- case +CREATE TABLE t (g GEOMETRY SRID 4326 COMMENT 'geo column' NOT NULL) +-- case +SELECT CAST(g AS POINT) FROM t +-- case +SELECT CAST(x AS GEOMETRY), CAST(x AS GEOMETRYCOLLECTION), CAST(x AS GEOMCOLLECTION) FROM t +-- case +SELECT CONVERT(x, MULTIPOLYGON), CONVERT(x, LINESTRING) FROM t diff --git a/parser/testdata/parser/spatial_types/output.sql b/parser/testdata/parser/spatial_types/output.sql new file mode 100644 index 0000000..8ccb9f4 --- /dev/null +++ b/parser/testdata/parser/spatial_types/output.sql @@ -0,0 +1,51 @@ +CREATE TABLE `t` (`g` GEOMETRY) +-- case +CREATE TABLE `t` (`pt` POINT) +-- case +CREATE TABLE `t` (`ls` LINESTRING) +-- case +CREATE TABLE `t` (`pg` POLYGON) +-- case +CREATE TABLE `t` (`mpt` MULTIPOINT) +-- case +CREATE TABLE `t` (`mls` MULTILINESTRING) +-- case +CREATE TABLE `t` (`mpg` MULTIPOLYGON) +-- case +CREATE TABLE `t` (`gc` GEOMETRYCOLLECTION) +-- case +CREATE TABLE `t` (`gc` GEOMETRYCOLLECTION) +-- case +CREATE TABLE `t` (`g` GEOMETRY NOT NULL) +-- case +CREATE TABLE `t` (`g` GEOMETRY NOT NULL SRID 4326) +-- case +CREATE TABLE `t` (`pt` POINT SRID 0) +-- case +CREATE TABLE `t` (`g` GEOMETRY NOT NULL SRID 4326,SPATIAL `idx_g`(`g`)) +-- case +CREATE TABLE `t` (`g` GEOMETRY NOT NULL,SPATIAL(`g`)) +-- case +CREATE TABLE `t` (`g` GEOMETRY NOT NULL,SPATIAL(`g`)) +-- case +ALTER TABLE `t` ADD SPATIAL `idx_g`(`g`) +-- case +CREATE SPATIAL INDEX `idx_g` ON `t` (`g`) +-- case +CREATE TABLE `geom` (`g` GEOMETRY,`p` POINT NOT NULL SRID 4326,`ll` LINESTRING COMMENT 'path') +-- case +ALTER TABLE `t` ADD COLUMN `g` GEOMETRY NOT NULL SRID 4326 +-- case +ALTER TABLE `t` MODIFY COLUMN `pt` POINT SRID 4326 +-- case +CREATE TABLE `t` (`geometry` INT,`point` INT,`linestring` INT,`polygon` INT,`multipoint` INT,`multilinestring` INT,`multipolygon` INT,`geometrycollection` INT,`srid` INT) +-- case +SELECT `geometry`,`point`,`srid` FROM `polygon` +-- case +CREATE TABLE `t` (`g` GEOMETRY SRID 4326 COMMENT 'geo column' NOT NULL) +-- case +SELECT CAST(`g` AS POINT) FROM `t` +-- case +SELECT CAST(`x` AS GEOMETRY),CAST(`x` AS GEOMETRYCOLLECTION),CAST(`x` AS GEOMETRYCOLLECTION) FROM `t` +-- case +SELECT CONVERT(`x`, MULTIPOLYGON),CONVERT(`x`, LINESTRING) FROM `t` diff --git a/parser/token_kinds.go b/parser/token_kinds.go index df0ff3a..a6b7bfe 100644 --- a/parser/token_kinds.go +++ b/parser/token_kinds.go @@ -379,6 +379,8 @@ const ( ge = 58209 general = 57733 generated = 57436 + geometryCollectionType = 58320 + geometryType = 58321 get = 58254 getFormat = 58030 global = 57734 @@ -500,6 +502,7 @@ const ( limit = 57478 linear = 57479 lines = 57480 + linestringType = 58322 list = 57769 lite = 58171 load = 57481 @@ -577,6 +580,9 @@ const ( modify = 57793 monitor = 57794 month = 57795 + multilinestringType = 58323 + multipointType = 58324 + multipolygonType = 58325 mutex = 58277 names = 57796 national = 57797 @@ -674,6 +680,7 @@ const ( point = 57840 policies = 58177 policy = 57841 + polygonType = 58326 position = 58060 preSplitRegions = 57845 precedes = 58311 @@ -837,6 +844,7 @@ const ( sqlexception = 57547 sqlstate = 57548 sqlwarning = 57549 + srid = 58327 ssl = 57553 stacked = 58257 staleness = 58078 diff --git a/types/etc.go b/types/etc.go index 109cd9a..e3f6247 100644 --- a/types/etc.go +++ b/types/etc.go @@ -46,65 +46,79 @@ func IsTypeVector(tp byte) bool { } var type2Str = map[byte]string{ - mysql.TypeBit: "bit", - mysql.TypeBlob: "text", - mysql.TypeDate: "date", - mysql.TypeDatetime: "datetime", - mysql.TypeUnspecified: "unspecified", - mysql.TypeNewDecimal: "decimal", - mysql.TypeDouble: "double", - mysql.TypeEnum: "enum", - mysql.TypeFloat: "float", - mysql.TypeGeometry: "geometry", - mysql.TypeTiDBVectorFloat32: "vector", - mysql.TypeInt24: "mediumint", - mysql.TypeJSON: "json", - mysql.TypeLong: "int", - mysql.TypeLonglong: "bigint", - mysql.TypeLongBlob: "longtext", - mysql.TypeMediumBlob: "mediumtext", - mysql.TypeNull: "null", - mysql.TypeSet: "set", - mysql.TypeShort: "smallint", - mysql.TypeString: "char", - mysql.TypeDuration: "time", - mysql.TypeTimestamp: "timestamp", - mysql.TypeTiny: "tinyint", - mysql.TypeTinyBlob: "tinytext", - mysql.TypeVarchar: "varchar", - mysql.TypeVarString: "var_string", - mysql.TypeYear: "year", + mysql.TypeBit: "bit", + mysql.TypeBlob: "text", + mysql.TypeDate: "date", + mysql.TypeDatetime: "datetime", + mysql.TypeUnspecified: "unspecified", + mysql.TypeNewDecimal: "decimal", + mysql.TypeDouble: "double", + mysql.TypeEnum: "enum", + mysql.TypeFloat: "float", + mysql.TypeGeometry: "geometry", + mysql.TypePoint: "point", + mysql.TypeLineString: "linestring", + mysql.TypePolygon: "polygon", + mysql.TypeMultiPoint: "multipoint", + mysql.TypeMultiLineString: "multilinestring", + mysql.TypeMultiPolygon: "multipolygon", + mysql.TypeGeometryCollection: "geometrycollection", + mysql.TypeTiDBVectorFloat32: "vector", + mysql.TypeInt24: "mediumint", + mysql.TypeJSON: "json", + mysql.TypeLong: "int", + mysql.TypeLonglong: "bigint", + mysql.TypeLongBlob: "longtext", + mysql.TypeMediumBlob: "mediumtext", + mysql.TypeNull: "null", + mysql.TypeSet: "set", + mysql.TypeShort: "smallint", + mysql.TypeString: "char", + mysql.TypeDuration: "time", + mysql.TypeTimestamp: "timestamp", + mysql.TypeTiny: "tinyint", + mysql.TypeTinyBlob: "tinytext", + mysql.TypeVarchar: "varchar", + mysql.TypeVarString: "var_string", + mysql.TypeYear: "year", } var str2Type = map[string]byte{ - "bit": mysql.TypeBit, - "text": mysql.TypeBlob, - "date": mysql.TypeDate, - "datetime": mysql.TypeDatetime, - "unspecified": mysql.TypeUnspecified, - "decimal": mysql.TypeNewDecimal, - "double": mysql.TypeDouble, - "enum": mysql.TypeEnum, - "float": mysql.TypeFloat, - "geometry": mysql.TypeGeometry, - "vector": mysql.TypeTiDBVectorFloat32, - "mediumint": mysql.TypeInt24, - "json": mysql.TypeJSON, - "int": mysql.TypeLong, - "bigint": mysql.TypeLonglong, - "longtext": mysql.TypeLongBlob, - "mediumtext": mysql.TypeMediumBlob, - "null": mysql.TypeNull, - "set": mysql.TypeSet, - "smallint": mysql.TypeShort, - "char": mysql.TypeString, - "time": mysql.TypeDuration, - "timestamp": mysql.TypeTimestamp, - "tinyint": mysql.TypeTiny, - "tinytext": mysql.TypeTinyBlob, - "varchar": mysql.TypeVarchar, - "var_string": mysql.TypeVarString, - "year": mysql.TypeYear, + "bit": mysql.TypeBit, + "text": mysql.TypeBlob, + "date": mysql.TypeDate, + "datetime": mysql.TypeDatetime, + "unspecified": mysql.TypeUnspecified, + "decimal": mysql.TypeNewDecimal, + "double": mysql.TypeDouble, + "enum": mysql.TypeEnum, + "float": mysql.TypeFloat, + "geometry": mysql.TypeGeometry, + "point": mysql.TypePoint, + "linestring": mysql.TypeLineString, + "polygon": mysql.TypePolygon, + "multipoint": mysql.TypeMultiPoint, + "multilinestring": mysql.TypeMultiLineString, + "multipolygon": mysql.TypeMultiPolygon, + "geometrycollection": mysql.TypeGeometryCollection, + "vector": mysql.TypeTiDBVectorFloat32, + "mediumint": mysql.TypeInt24, + "json": mysql.TypeJSON, + "int": mysql.TypeLong, + "bigint": mysql.TypeLonglong, + "longtext": mysql.TypeLongBlob, + "mediumtext": mysql.TypeMediumBlob, + "null": mysql.TypeNull, + "set": mysql.TypeSet, + "smallint": mysql.TypeShort, + "char": mysql.TypeString, + "time": mysql.TypeDuration, + "timestamp": mysql.TypeTimestamp, + "tinyint": mysql.TypeTiny, + "tinytext": mysql.TypeTinyBlob, + "varchar": mysql.TypeVarchar, + "var_string": mysql.TypeVarString, + "year": mysql.TypeYear, } // TypeStr converts tp to a string. diff --git a/types/field_type.go b/types/field_type.go index 055f521..8b26235 100644 --- a/types/field_type.go +++ b/types/field_type.go @@ -678,6 +678,10 @@ func (ft *FieldType) RestoreAsCastType(ctx *format.RestoreCtx, explicitCharset b ctx.WriteKeyWord("YEAR") case mysql.TypeTiDBVectorFloat32: ctx.WriteKeyWord("VECTOR") + case mysql.TypeGeometry, mysql.TypePoint, mysql.TypeLineString, + mysql.TypePolygon, mysql.TypeMultiPoint, mysql.TypeMultiLineString, + mysql.TypeMultiPolygon, mysql.TypeGeometryCollection: + ctx.WriteKeyWord(TypeStr(ft.tp)) } if ft.array { ctx.WritePlain(" ")