Skip to content

Commit baafd97

Browse files
committed
Experimenting with switching on MySQL/PostgreSQL behavior
1 parent 07dfd6f commit baafd97

File tree

3 files changed

+51
-27
lines changed

3 files changed

+51
-27
lines changed

sql/analyzer/analyzer.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,7 @@ func (ab *Builder) Build() *Analyzer {
274274
Parallelism: ab.parallelism,
275275
Coster: memo.NewDefaultCoster(),
276276
ExecBuilder: rowexec.DefaultBuilder,
277+
DatabaseType: sql.EngineType_MySql,
277278
}
278279
}
279280

@@ -298,6 +299,9 @@ type Analyzer struct {
298299
// EventScheduler is used to communiate with the event scheduler
299300
// for any EVENT related statements. It can be nil if EventScheduler is not defined.
300301
EventScheduler sql.EventScheduler
302+
// DatabaseType indicates whether the analyzer's behavior is compatible with a MySQL
303+
// database or a PostgreSQL database.
304+
DatabaseType sql.EngineType
301305
}
302306

303307
// NewDefault creates a default Analyzer instance with all default Rules and configuration.

sql/analyzer/validate_create_table.go

Lines changed: 38 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ func validateCreateTable(ctx *sql.Context, a *Analyzer, n sql.Node, scope *plan.
4444
if err != nil {
4545
return nil, transform.SameTree, err
4646
}
47-
err = validateIndexes(ctx, sch, idxs, strictMySQLCompat)
47+
validatePrefixLengths := a.DatabaseType == sql.EngineType_MySql
48+
err = validateIndexes(ctx, sch, idxs, strictMySQLCompat, validatePrefixLengths)
4849
if err != nil {
4950
return nil, transform.SameTree, err
5051
}
@@ -226,6 +227,7 @@ func resolveAlterColumn(ctx *sql.Context, a *Analyzer, n sql.Node, scope *plan.S
226227
initialSch := sch
227228

228229
addedColumn := false
230+
validatePrefixLengths := a.DatabaseType == sql.EngineType_MySql
229231

230232
// Need a TransformUp here because multiple of these statement types can be nested under a Block node.
231233
// It doesn't look it, but this is actually an iterative loop over all the independent clauses in an ALTER statement
@@ -237,7 +239,7 @@ func resolveAlterColumn(ctx *sql.Context, a *Analyzer, n sql.Node, scope *plan.S
237239
return nil, transform.SameTree, err
238240
}
239241

240-
sch, err = validateModifyColumn(ctx, initialSch, sch, n.(*plan.ModifyColumn), keyedColumns)
242+
sch, err = validateModifyColumn(ctx, initialSch, sch, n.(*plan.ModifyColumn), keyedColumns, validatePrefixLengths)
241243
if err != nil {
242244
return nil, transform.SameTree, err
243245
}
@@ -282,7 +284,7 @@ func resolveAlterColumn(ctx *sql.Context, a *Analyzer, n sql.Node, scope *plan.S
282284
if err != nil {
283285
return nil, transform.SameTree, err
284286
}
285-
indexes, err = validateAlterIndex(ctx, initialSch, sch, n.(*plan.AlterIndex), indexes)
287+
indexes, err = validateAlterIndex(ctx, sch, n.(*plan.AlterIndex), indexes, validatePrefixLengths)
286288
if err != nil {
287289
return nil, transform.SameTree, err
288290
}
@@ -294,7 +296,7 @@ func resolveAlterColumn(ctx *sql.Context, a *Analyzer, n sql.Node, scope *plan.S
294296
if err != nil {
295297
return nil, transform.SameTree, err
296298
}
297-
sch, err = validatePrimaryKey(ctx, initialSch, sch, n.(*plan.AlterPK))
299+
sch, err = validatePrimaryKey(ctx, sch, n.(*plan.AlterPK), validatePrefixLengths)
298300
if err != nil {
299301
return nil, transform.SameTree, err
300302
}
@@ -446,7 +448,9 @@ func isStrictMysqlCompatibilityEnabled(ctx *sql.Context) (bool, error) {
446448
return i == 1, nil
447449
}
448450

449-
func validateModifyColumn(ctx *sql.Context, initialSch sql.Schema, schema sql.Schema, mc *plan.ModifyColumn, keyedColumns map[string]bool) (sql.Schema, error) {
451+
// validateModifyColumn validates the |mc| ModifyColumn node and returns the updated schema. If
452+
// |validatePrefixLengths| is true, then prefix lengths on TEXT/BLOB columns will also be validated.
453+
func validateModifyColumn(ctx *sql.Context, initialSch sql.Schema, schema sql.Schema, mc *plan.ModifyColumn, keyedColumns map[string]bool, validatePrefixLengths bool) (sql.Schema, error) {
450454
table := mc.Table
451455
tableName := table.(sql.Nameable).Name()
452456

@@ -496,7 +500,6 @@ func validateModifyColumn(ctx *sql.Context, initialSch sql.Schema, schema sql.Sc
496500
if index.IsFullText() {
497501
continue
498502
}
499-
prefixLengths := index.PrefixLengths()
500503
for i, expr := range index.Expressions() {
501504
col := plan.GetColumnFromIndexExpr(expr, tbl)
502505
if !strings.EqualFold(col.Name, oldColName) {
@@ -505,13 +508,16 @@ func validateModifyColumn(ctx *sql.Context, initialSch sql.Schema, schema sql.Sc
505508
if types.IsJSON(newCol.Type) {
506509
return nil, sql.ErrJSONIndex.New(col.Name)
507510
}
508-
var prefixLen int64
509-
if i < len(prefixLengths) {
510-
prefixLen = int64(prefixLengths[i])
511-
}
512-
err = validatePrefixLength(ctx, oldColName, prefixLen, newCol.Type, strictMySQLCompat, index.IsUnique())
513-
if err != nil {
514-
return nil, err
511+
512+
if validatePrefixLengths {
513+
var prefixLen int64
514+
if i < len(index.PrefixLengths()) {
515+
prefixLen = int64(index.PrefixLengths()[i])
516+
}
517+
err = validatePrefixLength(ctx, oldColName, prefixLen, newCol.Type, strictMySQLCompat, index.IsUnique())
518+
if err != nil {
519+
return nil, err
520+
}
515521
}
516522
}
517523
}
@@ -619,8 +625,9 @@ func validateColumnSafeToDropWithCheckConstraint(columnName string, checks sql.C
619625
}
620626

621627
// validateAlterIndex validates the specified column can have an index added, dropped, or renamed. Returns an updated
622-
// list of index name given the add, drop, or rename operations.
623-
func validateAlterIndex(ctx *sql.Context, initialSch, sch sql.Schema, ai *plan.AlterIndex, indexes []string) ([]string, error) {
628+
// list of index name given the add, drop, or rename operations. If |validatePrefixLengths| is true, then index prefix
629+
// lengths on TEXT and BLOB columns will also be validated.
630+
func validateAlterIndex(ctx *sql.Context, sch sql.Schema, ai *plan.AlterIndex, indexes []string, validatePrefixLengths bool) ([]string, error) {
624631
switch ai.Action {
625632
case plan.IndexAction_Create:
626633
err := validateIdentifier(ai.IndexName)
@@ -640,7 +647,7 @@ func validateAlterIndex(ctx *sql.Context, initialSch, sch sql.Schema, ai *plan.A
640647
Storage: ai.Using,
641648
Comment: ai.Comment,
642649
}
643-
err = validateIndex(ctx, colMap, indexDef, strictMySQLCompat)
650+
err = validateIndex(ctx, colMap, indexDef, strictMySQLCompat, validatePrefixLengths)
644651
if err != nil {
645652
return nil, err
646653
}
@@ -839,14 +846,14 @@ func schToColMap(sch sql.Schema) map[string]*sql.Column {
839846
}
840847

841848
// validateIndexes prevents creating tables with blob/text primary keys and indexes without a specified length
842-
func validateIndexes(ctx *sql.Context, sch sql.Schema, idxDefs sql.IndexDefs, strictMySQLCompat bool) error {
849+
func validateIndexes(ctx *sql.Context, sch sql.Schema, idxDefs sql.IndexDefs, strictMySQLCompat bool, validatePrefixLengths bool) error {
843850
colMap := schToColMap(sch)
844851
var hasPkIndexDef bool
845852
for _, idxDef := range idxDefs {
846853
if idxDef.IsPrimary() {
847854
hasPkIndexDef = true
848855
}
849-
if err := validateIndex(ctx, colMap, idxDef, strictMySQLCompat); err != nil {
856+
if err := validateIndex(ctx, colMap, idxDef, strictMySQLCompat, validatePrefixLengths); err != nil {
850857
return err
851858
}
852859
}
@@ -865,13 +872,14 @@ func validateIndexes(ctx *sql.Context, sch sql.Schema, idxDefs sql.IndexDefs, st
865872
}
866873

867874
// validateIndex ensures that the Index Definition is valid for the table schema.
868-
// This function will throw errors and warnings as needed.
869-
// All columns in the index must be:
875+
// This function will throw errors and warnings as needed. If |validatePrefixLengths| is
876+
// true, then TEXT and BLOB columns included in the index will also be checked to ensure
877+
// they include a valid prefix length. All columns in the index must be:
870878
// - in the schema
871879
// - not duplicated
872880
// - not JSON Type
873881
// - have the proper prefix length
874-
func validateIndex(ctx *sql.Context, colMap map[string]*sql.Column, idxDef *sql.IndexDef, strictMySQLCompat bool) error {
882+
func validateIndex(ctx *sql.Context, colMap map[string]*sql.Column, idxDef *sql.IndexDef, strictMySQLCompat, validatePrefixLengths bool) error {
875883
seenCols := make(map[string]struct{})
876884
for _, idxCol := range idxDef.Columns {
877885
schCol, exists := colMap[strings.ToLower(idxCol.Name)]
@@ -890,9 +898,11 @@ func validateIndex(ctx *sql.Context, colMap map[string]*sql.Column, idxDef *sql.
890898
continue
891899
}
892900

893-
err := validatePrefixLength(ctx, idxCol.Name, idxCol.Length, schCol.Type, strictMySQLCompat, idxDef.IsUnique())
894-
if err != nil {
895-
return err
901+
if validatePrefixLengths {
902+
err := validatePrefixLength(ctx, idxCol.Name, idxCol.Length, schCol.Type, strictMySQLCompat, idxDef.IsUnique())
903+
if err != nil {
904+
return err
905+
}
896906
}
897907
}
898908

@@ -957,8 +967,9 @@ func getTableIndexNames(ctx *sql.Context, _ *Analyzer, table sql.Node) ([]string
957967
return names, nil
958968
}
959969

960-
// validatePrimaryKey validates a primary key add or drop operation.
961-
func validatePrimaryKey(ctx *sql.Context, initialSch, sch sql.Schema, ai *plan.AlterPK) (sql.Schema, error) {
970+
// validatePrimaryKey validates a primary key add or drop operation. If |validatePrefixLengths| is true, then
971+
// TEXT and BLOB columns will be checked for a valid prefix length.
972+
func validatePrimaryKey(ctx *sql.Context, sch sql.Schema, ai *plan.AlterPK, validatePrefixLengths bool) (sql.Schema, error) {
962973
tableName := getTableName(ai.Table)
963974
switch ai.Action {
964975
case plan.PrimaryKeyAction_Create:
@@ -976,7 +987,7 @@ func validatePrimaryKey(ctx *sql.Context, initialSch, sch sql.Schema, ai *plan.A
976987
if err != nil {
977988
return nil, err
978989
}
979-
err = validateIndex(ctx, colMap, idxDef, strictMySQLCompat)
990+
err = validateIndex(ctx, colMap, idxDef, strictMySQLCompat, validatePrefixLengths)
980991
if err != nil {
981992
return nil, err
982993
}

sql/engines.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,15 @@ package sql
1616

1717
import "fmt"
1818

19+
// EngineType indicates which type of database is being emulated. This is used to switch
20+
// between MySQL behavior and PostgreSQL behavior.
21+
type EngineType byte
22+
23+
const (
24+
EngineType_MySql EngineType = iota
25+
EngineType_Postgres
26+
)
27+
1928
// Engine represents a sql engine.
2029
type Engine struct {
2130
Name string

0 commit comments

Comments
 (0)