@@ -26,6 +26,10 @@ import (
2626
2727const MaxBytePrefix = 3072
2828
29+ // defaultPrefixLength is used for PostgreSQL compatibility. We don't support secondary indexes including address
30+ // encoded types such as TEXT/BLOB, so we must apply an implicit prefix length.
31+ const defaultPrefixLength = 200
32+
2933// validateCreateTable validates various constraints about CREATE TABLE statements.
3034func validateCreateTable (ctx * sql.Context , a * Analyzer , n sql.Node , scope * plan.Scope , sel RuleSelector , qFlags * sql.QueryFlags ) (sql.Node , transform.TreeIdentity , error ) {
3135 ct , ok := n .(* plan.CreateTable )
@@ -44,7 +48,10 @@ func validateCreateTable(ctx *sql.Context, a *Analyzer, n sql.Node, scope *plan.
4448 if err != nil {
4549 return nil , transform .SameTree , err
4650 }
47- validatePrefixLengths := a .DatabaseType == sql .EngineType_MySql
51+
52+ // For MySQL compatibility, users must specify a prefix length for any TEXT or BLOB columns used in an index,
53+ // otherwise we will apply an implicit prefix length.
54+ validatePrefixLengths := a .EngineType == sql .EngineType_MySql
4855 err = validateIndexes (ctx , sch , idxs , strictMySQLCompat , validatePrefixLengths )
4956 if err != nil {
5057 return nil , transform .SameTree , err
@@ -225,9 +232,11 @@ func resolveAlterColumn(ctx *sql.Context, a *Analyzer, n sql.Node, scope *plan.S
225232
226233 sch = sch .Copy () // Make a copy of the original schema to deal with any references to the original table.
227234 initialSch := sch
228-
229235 addedColumn := false
230- validatePrefixLengths := a .DatabaseType == sql .EngineType_MySql
236+
237+ // For MySQL compatibility, users must specify a prefix length for any TEXT or BLOB columns used in an index,
238+ // otherwise we will apply an implicit prefix length.
239+ validatePrefixLengths := a .EngineType == sql .EngineType_MySql
231240
232241 // Need a TransformUp here because multiple of these statement types can be nested under a Block node.
233242 // It doesn't look it, but this is actually an iterative loop over all the independent clauses in an ALTER statement
@@ -520,6 +529,24 @@ func validateModifyColumn(ctx *sql.Context, initialSch sql.Schema, schema sql.Sc
520529 }
521530 }
522531 }
532+
533+ // If we aren't validating user-specified prefix lengths, then apply an implicit prefix length for TEXT columns
534+ if ! validatePrefixLengths {
535+ prefixLengths := make ([]uint16 , len (index .Expressions ()))
536+ for i , expr := range index .Expressions () {
537+ col := plan .GetColumnFromIndexExpr (expr , tbl )
538+ if ! strings .EqualFold (col .Name , oldColName ) {
539+ continue
540+ }
541+ if types .IsJSON (newCol .Type ) {
542+ return nil , sql .ErrJSONIndex .New (col .Name )
543+ }
544+ if types .IsText (newCol .Type ) {
545+ prefixLengths [i ] = defaultPrefixLength
546+ }
547+ }
548+ index .SetPrefixLengths (prefixLengths )
549+ }
523550 }
524551
525552 return newSch , nil
@@ -906,6 +933,25 @@ func validateIndex(ctx *sql.Context, colMap map[string]*sql.Column, idxDef *sql.
906933 }
907934 }
908935
936+ // If we aren't validating user-specified prefix lengths, then we need to apply implicit prefix lengths for
937+ // any TEXT columns.
938+ if ! validatePrefixLengths {
939+ prefixLengths := make ([]uint16 , len (idxDef .Columns ))
940+ for i , idxCol := range idxDef .Columns {
941+ schCol , exists := colMap [strings .ToLower (idxCol .Name )]
942+ if ! exists {
943+ return sql .ErrKeyColumnDoesNotExist .New (idxCol .Name )
944+ }
945+ if types .IsJSON (schCol .Type ) {
946+ return sql .ErrJSONIndex .New (schCol .Name )
947+ }
948+ if types .IsText (schCol .Type ) {
949+ prefixLengths [i ] = defaultPrefixLength
950+ }
951+ idxDef .Columns [i ].Length = int64 (prefixLengths [i ])
952+ }
953+ }
954+
909955 if idxDef .IsSpatial () {
910956 if len (idxDef .Columns ) != 1 {
911957 return sql .ErrTooManyKeyParts .New (1 )
0 commit comments