Merge branch 'master' into fClose-Fix
This commit is contained in:
commit
46bead0369
@ -94,7 +94,7 @@ Please see [Coding gh-ost](doc/coding-ghost.md) for a guide to getting started d
|
|||||||
|
|
||||||
[Download latest release here](https://github.com/github/gh-ost/releases/latest)
|
[Download latest release here](https://github.com/github/gh-ost/releases/latest)
|
||||||
|
|
||||||
`gh-ost` is a Go project; it is built with Go `1.8` (though `1.7` should work as well). To build on your own, use either:
|
`gh-ost` is a Go project; it is built with Go `1.9` and above. To build on your own, use either:
|
||||||
- [script/build](https://github.com/github/gh-ost/blob/master/script/build) - this is the same build script used by CI hence the authoritative; artifact is `./bin/gh-ost` binary.
|
- [script/build](https://github.com/github/gh-ost/blob/master/script/build) - this is the same build script used by CI hence the authoritative; artifact is `./bin/gh-ost` binary.
|
||||||
- [build.sh](https://github.com/github/gh-ost/blob/master/build.sh) for building `tar.gz` artifacts in `/tmp/gh-ost`
|
- [build.sh](https://github.com/github/gh-ost/blob/master/build.sh) for building `tar.gz` artifacts in `/tmp/gh-ost`
|
||||||
|
|
||||||
|
2
build.sh
2
build.sh
@ -10,7 +10,7 @@ function build {
|
|||||||
GOOS=$3
|
GOOS=$3
|
||||||
GOARCH=$4
|
GOARCH=$4
|
||||||
|
|
||||||
if [[ $(go version | egrep "go1[.][012345678]") ]]; then
|
if ! go version | egrep -q 'go(1[.]9|1[.]1[0-9])' ; then
|
||||||
echo "go version is too low. Must use 1.9 or above"
|
echo "go version is too low. Must use 1.9 or above"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
@ -28,23 +28,23 @@ type RowsEstimateMethod string
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
TableStatusRowsEstimate RowsEstimateMethod = "TableStatusRowsEstimate"
|
TableStatusRowsEstimate RowsEstimateMethod = "TableStatusRowsEstimate"
|
||||||
ExplainRowsEstimate = "ExplainRowsEstimate"
|
ExplainRowsEstimate RowsEstimateMethod = "ExplainRowsEstimate"
|
||||||
CountRowsEstimate = "CountRowsEstimate"
|
CountRowsEstimate RowsEstimateMethod = "CountRowsEstimate"
|
||||||
)
|
)
|
||||||
|
|
||||||
type CutOver int
|
type CutOver int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
CutOverAtomic CutOver = iota
|
CutOverAtomic CutOver = iota
|
||||||
CutOverTwoStep = iota
|
CutOverTwoStep
|
||||||
)
|
)
|
||||||
|
|
||||||
type ThrottleReasonHint string
|
type ThrottleReasonHint string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
NoThrottleReasonHint ThrottleReasonHint = "NoThrottleReasonHint"
|
NoThrottleReasonHint ThrottleReasonHint = "NoThrottleReasonHint"
|
||||||
UserCommandThrottleReasonHint = "UserCommandThrottleReasonHint"
|
UserCommandThrottleReasonHint ThrottleReasonHint = "UserCommandThrottleReasonHint"
|
||||||
LeavingHibernationThrottleReasonHint = "LeavingHibernationThrottleReasonHint"
|
LeavingHibernationThrottleReasonHint ThrottleReasonHint = "LeavingHibernationThrottleReasonHint"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -7,17 +7,18 @@ package binlog
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/github/gh-ost/go/sql"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/github/gh-ost/go/sql"
|
||||||
)
|
)
|
||||||
|
|
||||||
type EventDML string
|
type EventDML string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
NotDML EventDML = "NoDML"
|
NotDML EventDML = "NoDML"
|
||||||
InsertDML = "Insert"
|
InsertDML EventDML = "Insert"
|
||||||
UpdateDML = "Update"
|
UpdateDML EventDML = "Update"
|
||||||
DeleteDML = "Delete"
|
DeleteDML EventDML = "Delete"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ToEventDML(description string) EventDML {
|
func ToEventDML(description string) EventDML {
|
||||||
|
@ -255,7 +255,11 @@ func (this *Migrator) listenOnPanicAbort() {
|
|||||||
// validateStatement validates the `alter` statement meets criteria.
|
// validateStatement validates the `alter` statement meets criteria.
|
||||||
// At this time this means:
|
// At this time this means:
|
||||||
// - column renames are approved
|
// - column renames are approved
|
||||||
|
// - no table rename allowed
|
||||||
func (this *Migrator) validateStatement() (err error) {
|
func (this *Migrator) validateStatement() (err error) {
|
||||||
|
if this.parser.IsRenameTable() {
|
||||||
|
return fmt.Errorf("ALTER statement seems to RENAME the table. This is not supported, and you should run your RENAME outside gh-ost.")
|
||||||
|
}
|
||||||
if this.parser.HasNonTrivialRenames() && !this.migrationContext.SkipRenamedColumns {
|
if this.parser.HasNonTrivialRenames() && !this.migrationContext.SkipRenamedColumns {
|
||||||
this.migrationContext.ColumnRenameMap = this.parser.GetNonTrivialRenames()
|
this.migrationContext.ColumnRenameMap = this.parser.GetNonTrivialRenames()
|
||||||
if !this.migrationContext.ApproveRenamedColumns {
|
if !this.migrationContext.ApproveRenamedColumns {
|
||||||
|
@ -15,11 +15,11 @@ type ValueComparisonSign string
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
LessThanComparisonSign ValueComparisonSign = "<"
|
LessThanComparisonSign ValueComparisonSign = "<"
|
||||||
LessThanOrEqualsComparisonSign = "<="
|
LessThanOrEqualsComparisonSign ValueComparisonSign = "<="
|
||||||
EqualsComparisonSign = "="
|
EqualsComparisonSign ValueComparisonSign = "="
|
||||||
GreaterThanOrEqualsComparisonSign = ">="
|
GreaterThanOrEqualsComparisonSign ValueComparisonSign = ">="
|
||||||
GreaterThanComparisonSign = ">"
|
GreaterThanComparisonSign ValueComparisonSign = ">"
|
||||||
NotEqualsComparisonSign = "!="
|
NotEqualsComparisonSign ValueComparisonSign = "!="
|
||||||
)
|
)
|
||||||
|
|
||||||
// EscapeName will escape a db/table/column/... name by wrapping with backticks.
|
// EscapeName will escape a db/table/column/... name by wrapping with backticks.
|
||||||
|
@ -15,11 +15,13 @@ var (
|
|||||||
sanitizeQuotesRegexp = regexp.MustCompile("('[^']*')")
|
sanitizeQuotesRegexp = regexp.MustCompile("('[^']*')")
|
||||||
renameColumnRegexp = regexp.MustCompile(`(?i)\bchange\s+(column\s+|)([\S]+)\s+([\S]+)\s+`)
|
renameColumnRegexp = regexp.MustCompile(`(?i)\bchange\s+(column\s+|)([\S]+)\s+([\S]+)\s+`)
|
||||||
dropColumnRegexp = regexp.MustCompile(`(?i)\bdrop\s+(column\s+|)([\S]+)$`)
|
dropColumnRegexp = regexp.MustCompile(`(?i)\bdrop\s+(column\s+|)([\S]+)$`)
|
||||||
|
renameTableRegexp = regexp.MustCompile(`(?i)\brename\s+(to|as)\s+`)
|
||||||
)
|
)
|
||||||
|
|
||||||
type Parser struct {
|
type Parser struct {
|
||||||
columnRenameMap map[string]string
|
columnRenameMap map[string]string
|
||||||
droppedColumns map[string]bool
|
droppedColumns map[string]bool
|
||||||
|
isRenameTable bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewParser() *Parser {
|
func NewParser() *Parser {
|
||||||
@ -86,6 +88,12 @@ func (this *Parser) parseAlterToken(alterToken string) (err error) {
|
|||||||
this.droppedColumns[submatch[2]] = true
|
this.droppedColumns[submatch[2]] = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
// rename table
|
||||||
|
if renameTableRegexp.MatchString(alterToken) {
|
||||||
|
this.isRenameTable = true
|
||||||
|
}
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,3 +123,7 @@ func (this *Parser) HasNonTrivialRenames() bool {
|
|||||||
func (this *Parser) DroppedColumnsMap() map[string]bool {
|
func (this *Parser) DroppedColumnsMap() map[string]bool {
|
||||||
return this.droppedColumns
|
return this.droppedColumns
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (this *Parser) IsRenameTable() bool {
|
||||||
|
return this.isRenameTable
|
||||||
|
}
|
||||||
|
@ -159,3 +159,42 @@ func TestParseAlterStatementDroppedColumns(t *testing.T) {
|
|||||||
test.S(t).ExpectTrue(parser.droppedColumns["b"])
|
test.S(t).ExpectTrue(parser.droppedColumns["b"])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestParseAlterStatementRenameTable(t *testing.T) {
|
||||||
|
|
||||||
|
{
|
||||||
|
parser := NewParser()
|
||||||
|
statement := "drop column b"
|
||||||
|
err := parser.ParseAlterStatement(statement)
|
||||||
|
test.S(t).ExpectNil(err)
|
||||||
|
test.S(t).ExpectFalse(parser.isRenameTable)
|
||||||
|
}
|
||||||
|
{
|
||||||
|
parser := NewParser()
|
||||||
|
statement := "rename as something_else"
|
||||||
|
err := parser.ParseAlterStatement(statement)
|
||||||
|
test.S(t).ExpectNil(err)
|
||||||
|
test.S(t).ExpectTrue(parser.isRenameTable)
|
||||||
|
}
|
||||||
|
{
|
||||||
|
parser := NewParser()
|
||||||
|
statement := "drop column b, rename as something_else"
|
||||||
|
err := parser.ParseAlterStatement(statement)
|
||||||
|
test.S(t).ExpectNil(err)
|
||||||
|
test.S(t).ExpectTrue(parser.isRenameTable)
|
||||||
|
}
|
||||||
|
{
|
||||||
|
parser := NewParser()
|
||||||
|
statement := "engine=innodb rename as something_else"
|
||||||
|
err := parser.ParseAlterStatement(statement)
|
||||||
|
test.S(t).ExpectNil(err)
|
||||||
|
test.S(t).ExpectTrue(parser.isRenameTable)
|
||||||
|
}
|
||||||
|
{
|
||||||
|
parser := NewParser()
|
||||||
|
statement := "rename as something_else, engine=innodb"
|
||||||
|
err := parser.ParseAlterStatement(statement)
|
||||||
|
test.S(t).ExpectNil(err)
|
||||||
|
test.S(t).ExpectTrue(parser.isRenameTable)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -16,12 +16,12 @@ type ColumnType int
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
UnknownColumnType ColumnType = iota
|
UnknownColumnType ColumnType = iota
|
||||||
TimestampColumnType = iota
|
TimestampColumnType
|
||||||
DateTimeColumnType = iota
|
DateTimeColumnType
|
||||||
EnumColumnType = iota
|
EnumColumnType
|
||||||
MediumIntColumnType = iota
|
MediumIntColumnType
|
||||||
JSONColumnType = iota
|
JSONColumnType
|
||||||
FloatColumnType = iota
|
FloatColumnType
|
||||||
)
|
)
|
||||||
|
|
||||||
const maxMediumintUnsigned int32 = 16777215
|
const maxMediumintUnsigned int32 = 16777215
|
||||||
|
22
localtests/fail-rename-table/create.sql
Normal file
22
localtests/fail-rename-table/create.sql
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
drop table if exists gh_ost_test;
|
||||||
|
create table gh_ost_test (
|
||||||
|
id int auto_increment,
|
||||||
|
i int not null,
|
||||||
|
ts timestamp,
|
||||||
|
primary key(id)
|
||||||
|
) auto_increment=1;
|
||||||
|
|
||||||
|
drop event if exists gh_ost_test;
|
||||||
|
delimiter ;;
|
||||||
|
create event gh_ost_test
|
||||||
|
on schedule every 1 second
|
||||||
|
starts current_timestamp
|
||||||
|
ends current_timestamp + interval 60 second
|
||||||
|
on completion not preserve
|
||||||
|
enable
|
||||||
|
do
|
||||||
|
begin
|
||||||
|
insert into gh_ost_test values (null, 11, now());
|
||||||
|
insert into gh_ost_test values (null, 13, now());
|
||||||
|
insert into gh_ost_test values (null, 17, now());
|
||||||
|
end ;;
|
1
localtests/fail-rename-table/expect_failure
Normal file
1
localtests/fail-rename-table/expect_failure
Normal file
@ -0,0 +1 @@
|
|||||||
|
ALTER statement seems to RENAME the table
|
1
localtests/fail-rename-table/extra_args
Normal file
1
localtests/fail-rename-table/extra_args
Normal file
@ -0,0 +1 @@
|
|||||||
|
--alter="rename as something_else"
|
Loading…
Reference in New Issue
Block a user