Skip to content

Commit

Permalink
test: add enable_ddl_instant option test (#674)
Browse files Browse the repository at this point in the history
* test: add enable_ddl_instant option test
  • Loading branch information
hanchuanchuan authored Aug 25, 2024
1 parent 4cffeba commit 2f06c61
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 38 deletions.
66 changes: 66 additions & 0 deletions session/session_base_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// Copyright 2015 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

package session

import (
"testing"

"github.com/hanchuanchuan/goInception/ast"
"github.com/hanchuanchuan/goInception/parser"
"github.com/hanchuanchuan/goInception/sessionctx/variable"
)

func Test_checkDDLInstantMySQL(t *testing.T) {
parser := parser.New()
sessionVars := variable.NewSessionVars()
parser.SetSQLMode(sessionVars.SQLMode)

table := &TableInfo{Name: "t1",
Fields: []FieldInfo{
{Field: "c1", Extra: ""},
{Field: "c2", Extra: "VIRTUAL"},
{Field: "c3", Extra: "STORED"}}}

tests := []struct {
sql string
mysql57 bool
mysql80 bool
}{
{"alter table t1 add column c1 int;", false, true},
{"ALTER TABLE t1 ADD COLUMN c2 INT GENERATED ALWAYS AS (c1 + 1) VIRTUAL;", true, true},
{"ALTER TABLE t1 ADD COLUMN c4 INT AFTER c1;", false, false},
{"ALTER TABLE t1 ADD COLUMN c3 INT GENERATED ALWAYS AS (c1 + 1) STORED;", false, false},
}

for _, test := range tests {
stmts, _, err := parser.Parse(test.sql, "", "")
if err != nil {
t.Error(err)
}
for _, stmtNode := range stmts {
switch node := stmtNode.(type) {
case *ast.AlterTableStmt:
canInstant := checkDDLInstantMySQL57(node)
if canInstant != test.mysql57 {
t.Errorf("canInstant is %v, but excepted %v: sql: %v", canInstant, test.mysql57, test.sql)
}

canInstant = checkDDLInstantMySQL80(node, table, 80000)
if canInstant != test.mysql80 {
t.Errorf("canInstant is %v, but excepted %v: sql: %v", canInstant, test.mysql57, test.sql)
}
}
}
}
}
93 changes: 55 additions & 38 deletions session/session_inception.go
Original file line number Diff line number Diff line change
Expand Up @@ -3682,58 +3682,56 @@ func (s *session) checkAlterTable(node *ast.AlterTableStmt, sql string, mergeOnl
}
}

// checkDDLInstant 检查是否支持 ALGORITHM=INSTANT, 当支持时自动关闭pt-osc/gh-ost.
func (s *session) checkDDLInstant(node *ast.AlterTableStmt, t *TableInfo) {
if !s.inc.EnableDDLInstant || !s.myRecord.useOsc || s.dbVersion < 50700 {
return
}

if s.dbVersion < 80000 {
// 如果mysql版本小于8.0,只有VIRTUAL column支持Only Modifies Metadata
for _, alter := range node.Specs {
switch alter.Tp {
case ast.AlterTableAddColumns:
newColumns := len(alter.NewColumns)
virtualColumns := 0
for _, nc := range alter.NewColumns {
isPrimary := false
isUnique := false
var isStore *bool
for _, op := range nc.Options {
switch op.Tp {
case ast.ColumnOptionPrimaryKey:
isPrimary = true
case ast.ColumnOptionUniqKey:
isUnique = true
case ast.ColumnOptionGenerated:
isStore = &op.Stored
}
// checkDDLInstantMySQL57
func checkDDLInstantMySQL57(node *ast.AlterTableStmt) (canInstant bool) {
// 如果mysql版本小于8.0,只有VIRTUAL column支持Only Modifies Metadata
for _, alter := range node.Specs {
switch alter.Tp {
case ast.AlterTableAddColumns:
newColumns := len(alter.NewColumns)
virtualColumns := 0
for _, nc := range alter.NewColumns {
isPrimary := false
isUnique := false
var isStore *bool
for _, op := range nc.Options {
switch op.Tp {
case ast.ColumnOptionPrimaryKey:
isPrimary = true
case ast.ColumnOptionUniqKey:
isUnique = true
case ast.ColumnOptionGenerated:
isStore = &op.Stored
}
}

if !isPrimary && !isUnique {
if s.dbVersion < 80000 && isStore != nil && !*isStore {
virtualColumns++
}
if !isPrimary && !isUnique {
if isStore != nil && !*isStore {
virtualColumns++
}
}
if virtualColumns == newColumns {
s.myRecord.useOsc = false
return
}
default:
}
if virtualColumns == newColumns {
canInstant = true
return
}
default:
return
}
return
}
return false
}

// checkDDLInstantMySQL80
func checkDDLInstantMySQL80(node *ast.AlterTableStmt, t *TableInfo, dbVersion int) (canInstant bool) {
canInstantSpecs := 0
for _, alter := range node.Specs {
// 当用户指定了 ALGORITHM=INSTANT 时,忽略检查并关闭osc
if alter.Algorithm == ast.AlgorithmTypeInstant {
s.myRecord.useOsc = false
canInstant = true
return
}

switch alter.Tp {
case ast.AlterTableAddColumns:
newColumns := len(alter.NewColumns)
Expand Down Expand Up @@ -3762,7 +3760,7 @@ func (s *session) checkDDLInstant(node *ast.AlterTableStmt, t *TableInfo) {
}
}
if alter.Position.Tp != ast.ColumnPositionNone {
if s.dbVersion < 80029 {
if dbVersion < 80029 {
return
} else {
canInstantSpecs++
Expand Down Expand Up @@ -3795,6 +3793,25 @@ func (s *session) checkDDLInstant(node *ast.AlterTableStmt, t *TableInfo) {
}
}
if canInstantSpecs == len(node.Specs) {
canInstant = true
}
return canInstant
}

// checkDDLInstant 检查是否支持 ALGORITHM=INSTANT, 当支持时自动关闭pt-osc/gh-ost.
func (s *session) checkDDLInstant(node *ast.AlterTableStmt, t *TableInfo) {
if !s.inc.EnableDDLInstant || !s.myRecord.useOsc || s.dbVersion < 50700 {
return
}

if s.dbVersion < 80000 {
if checkDDLInstantMySQL57(node) {
s.myRecord.useOsc = false
}
return
}

if checkDDLInstantMySQL80(node, t, s.dbVersion) {
s.myRecord.useOsc = false
}
}
Expand Down

0 comments on commit 2f06c61

Please sign in to comment.