Skip to content

Commit e049a6c

Browse files
authored
Merge pull request #1 from xtrimf/support_for_triggers
Support for triggers
2 parents d291bf6 + 0a271d0 commit e049a6c

File tree

7 files changed

+43
-46
lines changed

7 files changed

+43
-46
lines changed

go/base/context.go

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import (
2121
"github.com/github/gh-ost/go/mysql"
2222
"github.com/github/gh-ost/go/sql"
2323
"github.com/openark/golib/log"
24-
"github.com/openark/golib/sqlutils"
2524

2625
"github.com/go-ini/ini"
2726
)
@@ -229,7 +228,7 @@ type MigrationContext struct {
229228
IncludeTriggers bool
230229
RemoveTriggerSuffix bool
231230
TriggerSuffix string
232-
Triggers []*sqlutils.RowMap
231+
Triggers []mysql.Trigger
233232

234233
recentBinlogCoordinates mysql.BinlogCoordinates
235234

@@ -864,22 +863,21 @@ func (this *MigrationContext) ReadConfigFile() error {
864863
// getGhostTriggerName generates the name of a ghost trigger, based on original trigger name
865864
// or a given trigger name
866865
func (this *MigrationContext) GetGhostTriggerName(triggerName string) string {
867-
// var triggerName string
868-
if this.RemoveTriggerSuffix && strings.HasSuffix(triggerName, this.TriggerSuffix) {
866+
if this.RemoveTriggerSuffix {
869867
return strings.TrimSuffix(triggerName, this.TriggerSuffix)
870868
}
871869

872870
return triggerName + this.TriggerSuffix
873871
}
874872

875873
// validateGhostTriggerLength check if the ghost trigger name length is not more than 64 characters
876-
func (this *MigrationContext) ValidateGhostTriggerLengthBelow65chars(triggerName string) bool {
874+
func (this *MigrationContext) ValidateGhostTriggerLengthBelowMaxLength(triggerName string) bool {
877875
var ghostTriggerName string
878-
if this.RemoveTriggerSuffix && strings.HasSuffix(triggerName, this.TriggerSuffix) {
876+
if this.RemoveTriggerSuffix {
879877
ghostTriggerName = strings.TrimSuffix(triggerName, this.TriggerSuffix)
880878
} else {
881879
ghostTriggerName = triggerName + this.TriggerSuffix
882880
}
883881

884-
return utf8.RuneCountInString(ghostTriggerName) < 65
882+
return utf8.RuneCountInString(ghostTriggerName) <= mysql.MaxTableNameLength
885883
}

go/base/context_test.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -87,39 +87,39 @@ func TestGetTriggerNames(t *testing.T) {
8787
}
8888

8989
}
90-
func TestValidateGhostTriggerLengthBelow65chars(t *testing.T) {
90+
func TestValidateGhostTriggerLengthBelowMaxLength(t *testing.T) {
9191
{
9292
context := NewMigrationContext()
9393
context.TriggerSuffix = "_gho"
94-
test.S(t).ExpectEquals(context.ValidateGhostTriggerLengthBelow65chars("my_trigger"), true)
94+
test.S(t).ExpectEquals(context.ValidateGhostTriggerLengthBelowMaxLength("my_trigger"), true)
9595
}
9696
{
9797
context := NewMigrationContext()
9898
context.TriggerSuffix = "_ghost"
99-
test.S(t).ExpectEquals(context.ValidateGhostTriggerLengthBelow65chars(strings.Repeat("my_trigger_ghost", 4)), false) // 64 characters + "_ghost"
99+
test.S(t).ExpectEquals(context.ValidateGhostTriggerLengthBelowMaxLength(strings.Repeat("my_trigger_ghost", 4)), false) // 64 characters + "_ghost"
100100
}
101101
{
102102
context := NewMigrationContext()
103103
context.TriggerSuffix = "_ghost"
104-
test.S(t).ExpectEquals(context.ValidateGhostTriggerLengthBelow65chars(strings.Repeat("my_trigger_ghost", 3)), true) // 48 characters + "_ghost"
104+
test.S(t).ExpectEquals(context.ValidateGhostTriggerLengthBelowMaxLength(strings.Repeat("my_trigger_ghost", 3)), true) // 48 characters + "_ghost"
105105
}
106106
{
107107
context := NewMigrationContext()
108108
context.TriggerSuffix = "_ghost"
109109
context.RemoveTriggerSuffix = true
110-
test.S(t).ExpectEquals(context.ValidateGhostTriggerLengthBelow65chars(strings.Repeat("my_trigger_ghost", 4)), true) // 64 characters + "_ghost" removed
110+
test.S(t).ExpectEquals(context.ValidateGhostTriggerLengthBelowMaxLength(strings.Repeat("my_trigger_ghost", 4)), true) // 64 characters + "_ghost" removed
111111
}
112112
{
113113
context := NewMigrationContext()
114114
context.TriggerSuffix = "_ghost"
115115
context.RemoveTriggerSuffix = true
116-
test.S(t).ExpectEquals(context.ValidateGhostTriggerLengthBelow65chars(strings.Repeat("my_trigger_ghost", 4)+"X"), false) // 65 characters + "_ghost" not removed
116+
test.S(t).ExpectEquals(context.ValidateGhostTriggerLengthBelowMaxLength(strings.Repeat("my_trigger_ghost", 4)+"X"), false) // 65 characters + "_ghost" not removed
117117
}
118118
{
119119
context := NewMigrationContext()
120120
context.TriggerSuffix = "_ghost"
121121
context.RemoveTriggerSuffix = true
122-
test.S(t).ExpectEquals(context.ValidateGhostTriggerLengthBelow65chars(strings.Repeat("my_trigger_ghost", 4)+"_ghost"), true) // 70 characters + last "_ghost" removed
122+
test.S(t).ExpectEquals(context.ValidateGhostTriggerLengthBelowMaxLength(strings.Repeat("my_trigger_ghost", 4)+"_ghost"), true) // 70 characters + last "_ghost" removed
123123
}
124124
}
125125

go/cmd/gh-ost/main.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -129,8 +129,8 @@ func main() {
129129
flag.UintVar(&migrationContext.ReplicaServerId, "replica-server-id", 99999, "server id used by gh-ost process. Default: 99999")
130130

131131
flag.BoolVar(&migrationContext.IncludeTriggers, "include-triggers", false, "When true, the triggers (if exist) will be created on the new table")
132-
flag.StringVar(&migrationContext.TriggerSuffix, "trigger-suffix", "", "have to be used with '--include-triggers'")
133-
flag.BoolVar(&migrationContext.RemoveTriggerSuffix, "remove-trigger-suffix-if-exists", false, "Removal (instead of addition) of trigger suffix if it exists at the end of the original triger name. Have to be used with '--include-triggers' and '--TriggerSuffix'")
132+
flag.StringVar(&migrationContext.TriggerSuffix, "trigger-suffix", "", "Add a suffix to the trigger name (i.e '_v2'). Requires '--include-triggers'")
133+
flag.BoolVar(&migrationContext.RemoveTriggerSuffix, "remove-trigger-suffix-if-exists", false, "Remove given suffix from name of trigger. Requires '--include-triggers' and '--trigger-suffix'")
134134

135135
maxLoad := flag.String("max-load", "", "Comma delimited status-name=threshold. e.g: 'Threads_running=100,Threads_connected=500'. When status exceeds threshold, app throttles writes")
136136
criticalLoad := flag.String("critical-load", "", "Comma delimited status-name=threshold, same format as --max-load. When status exceeds threshold, app panics and quits")
@@ -247,9 +247,9 @@ func main() {
247247
migrationContext.Log.Fatalf("--trigger-suffix cannot be be used without --include-triggers")
248248
}
249249
if migrationContext.TriggerSuffix != "" {
250-
regex, err := regexp.Compile(`^[\da-zA-Z_]+$`)
250+
regex := regexp.MustCompile(`^[\da-zA-Z_]+$`)
251251

252-
if err != nil || !regex.Match([]byte(migrationContext.TriggerSuffix)) {
252+
if !regex.Match([]byte(migrationContext.TriggerSuffix)) {
253253
migrationContext.Log.Fatalf("--trigger-suffix must contain only alpha numeric characters and underscore (0-9,a-z,A-Z,_)")
254254
}
255255
}

go/logic/applier.go

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ func (this *Applier) dropTable(tableName string) error {
276276
func (this *Applier) DropTriggersFromGhost() error {
277277
if len(this.migrationContext.Triggers) > 0 {
278278
for _, trigger := range this.migrationContext.Triggers {
279-
triggerName := this.migrationContext.GetGhostTriggerName((*trigger).GetString("name"))
279+
triggerName := this.migrationContext.GetGhostTriggerName(trigger.Name)
280280
query := fmt.Sprintf("drop trigger if exists %s", sql.EscapeName(triggerName))
281281
_, err := sqlutils.ExecNoPrepare(this.db, query)
282282
if err != nil {
@@ -292,15 +292,15 @@ func (this *Applier) DropTriggersFromGhost() error {
292292
func (this *Applier) createTriggers(tableName string) error {
293293
if len(this.migrationContext.Triggers) > 0 {
294294
for _, trigger := range this.migrationContext.Triggers {
295-
triggerName := this.migrationContext.GetGhostTriggerName((*trigger).GetString("name"))
295+
triggerName := this.migrationContext.GetGhostTriggerName(trigger.Name)
296296
query := fmt.Sprintf(`create /* gh-ost */ trigger %s %s %s on %s.%s for each row
297297
%s`,
298298
sql.EscapeName(triggerName),
299-
(*trigger).GetString("timing"),
300-
(*trigger).GetString("event"),
299+
trigger.Timing,
300+
trigger.Event,
301301
sql.EscapeName(this.migrationContext.DatabaseName),
302302
sql.EscapeName(tableName),
303-
(*trigger).GetString("statement"),
303+
trigger.Statement,
304304
)
305305
this.migrationContext.Log.Infof("Createing trigger %s on %s.%s",
306306
sql.EscapeName(triggerName),
@@ -316,14 +316,7 @@ func (this *Applier) createTriggers(tableName string) error {
316316
return nil
317317
}
318318

319-
// ReCreateTriggers creates the original triggers on applier host
320-
func (this *Applier) CreateTriggersOnGhostAtomic(tableLocked chan<- error) error {
321-
err := this.createTriggers(this.migrationContext.GetGhostTableName())
322-
tableLocked <- err
323-
return err
324-
}
325-
326-
// ReCreateTriggers creates the original triggers on applier host
319+
// CreateTriggers creates the original triggers on applier host
327320
func (this *Applier) CreateTriggersOnGhost() error {
328321
err := this.createTriggers(this.migrationContext.GetGhostTableName())
329322
return err

go/logic/inspect.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -531,7 +531,7 @@ func (this *Inspector) validateGhostTriggersDontExist() error {
531531
if len(this.migrationContext.Triggers) > 0 {
532532
var foundTriggers []string
533533
for _, trigger := range this.migrationContext.Triggers {
534-
triggerName := this.migrationContext.GetGhostTriggerName((*trigger).GetString("name"))
534+
triggerName := this.migrationContext.GetGhostTriggerName(trigger.Name)
535535
query := "select 1 from information_schema.triggers where trigger_name = ? and trigger_schema = ?"
536536
err := sqlutils.QueryRowsMap(this.db, query, func(rowMap sqlutils.RowMap) error {
537537
triggerExists := rowMap.GetInt("1")
@@ -559,14 +559,14 @@ func (this *Inspector) validateGhostTriggersLength() error {
559559
if len(this.migrationContext.Triggers) > 0 {
560560
var foundTriggers []string
561561
for _, trigger := range this.migrationContext.Triggers {
562-
triggerName := this.migrationContext.GetGhostTriggerName((*trigger).GetString("name"))
563-
if ok := this.migrationContext.ValidateGhostTriggerLengthBelow65chars(triggerName); !ok {
562+
triggerName := this.migrationContext.GetGhostTriggerName(trigger.Name)
563+
if ok := this.migrationContext.ValidateGhostTriggerLengthBelowMaxLength(triggerName); !ok {
564564
foundTriggers = append(foundTriggers, triggerName)
565565
}
566566

567567
}
568568
if len(foundTriggers) > 0 {
569-
return this.migrationContext.Log.Errorf("Gh-ost triggers (%s) length > 64 characters. Bailing out", strings.Join(foundTriggers, ","))
569+
return this.migrationContext.Log.Errorf("Gh-ost triggers (%s) length > %d characters. Bailing out", strings.Join(foundTriggers, ","),mysql.MaxTableNameLength)
570570
}
571571
}
572572

go/logic/migrator.go

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -671,14 +671,8 @@ func (this *Migrator) atomicCutOver() (err error) {
671671

672672
// If we need to create triggers we need to do it here (only create part)
673673
if this.migrationContext.IncludeTriggers && len(this.migrationContext.Triggers) > 0 {
674-
triggersCreated := make(chan error, 2)
675-
go func() {
676-
if err := this.applier.CreateTriggersOnGhostAtomic(triggersCreated); err != nil {
677-
this.migrationContext.Log.Errore(err)
678-
}
679-
}()
680-
if err := <-triggersCreated; err != nil {
681-
return this.migrationContext.Log.Errore(err)
674+
if err := this.applier.CreateTriggersOnGhost(); err != nil {
675+
this.migrationContext.Log.Errore(err)
682676
}
683677
}
684678

go/mysql/utils.go

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,13 @@ type ReplicationLagResult struct {
3030
Err error
3131
}
3232

33+
type Trigger struct {
34+
Name string
35+
Event string
36+
Statement string
37+
Timing string
38+
}
39+
3340
func NewNoReplicationLagResult() *ReplicationLagResult {
3441
return &ReplicationLagResult{Lag: 0, Err: nil}
3542
}
@@ -207,13 +214,18 @@ func GetTableColumns(db *gosql.DB, databaseName, tableName string) (*sql.ColumnL
207214
}
208215

209216
// GetTriggers reads trigger list from given table
210-
func GetTriggers(db *gosql.DB, databaseName, tableName string) (triggers []*sqlutils.RowMap, err error) {
217+
func GetTriggers(db *gosql.DB, databaseName, tableName string) (triggers []Trigger, err error) {
211218
query := fmt.Sprintf(`select trigger_name as name, event_manipulation as event, action_statement as statement, action_timing as timing
212219
from information_schema.triggers
213220
where trigger_schema = '%s' and event_object_table = '%s'`, databaseName, tableName)
214-
221+
215222
err = sqlutils.QueryRowsMap(db, query, func(rowMap sqlutils.RowMap) error {
216-
triggers = append(triggers, &rowMap)
223+
triggers = append(triggers, Trigger{
224+
Name: rowMap.GetString("name"),
225+
Event: rowMap.GetString("event"),
226+
Statement: rowMap.GetString("statement"),
227+
Timing: rowMap.GetString("timing"),
228+
})
217229
return nil
218230
})
219231
if err != nil {

0 commit comments

Comments
 (0)