Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

schemadiff: temporal range partition rotation analysis and operation #17426

Open
wants to merge 25 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
45bb85a
FromSeconds for DateTime
shlomi-noach Dec 24, 2024
be61768
A 8.4 test env
shlomi-noach Dec 24, 2024
fc21c82
schemadiff: range partition analysis, rotation and retention
shlomi-noach Dec 24, 2024
fd9f964
do not reverse-compute temporal functions. Always compute forward
shlomi-noach Dec 24, 2024
26beaa4
remove FromSeconds
shlomi-noach Dec 24, 2024
709815a
stricter checks
shlomi-noach Dec 24, 2024
38d710e
minor test refactoring
shlomi-noach Dec 24, 2024
21f9cb7
optionally create distinct DROP statements
shlomi-noach Dec 24, 2024
d4fb9f9
simplify
shlomi-noach Dec 24, 2024
1087acb
test YearWeek function
shlomi-noach Jan 2, 2025
b1d4715
refactor code into supportedPartitioningScheme() function
shlomi-noach Jan 2, 2025
087af5f
support weekly rotations, support YEARWEEK function, support 'mode' a…
shlomi-noach Jan 2, 2025
eef1157
rename mode->weekMode
shlomi-noach Jan 2, 2025
85f8588
retention test for week rotation
shlomi-noach Jan 2, 2025
1e9f490
ParseIntervalType()
shlomi-noach Jan 6, 2025
f708b8a
rename as 'IntervalTypeFromString'
shlomi-noach Jan 6, 2025
64b53c9
Merge branch 'main' into schemadiff-range-rotation
shlomi-noach Jan 13, 2025
5157097
convert 'switch' statement to map
shlomi-noach Jan 13, 2025
e269ccf
version agnostic doc link
shlomi-noach Jan 13, 2025
9883c6e
copyright: new year
shlomi-noach Jan 13, 2025
812ee79
fix pascal case
shlomi-noach Jan 13, 2025
0e66f36
more cannonical code
shlomi-noach Jan 13, 2025
fa11194
decapitalize error strings
shlomi-noach Jan 13, 2025
bfc8d07
Adapt tests to decapitalization
shlomi-noach Jan 13, 2025
5a2cb5f
more switch->map conversion
shlomi-noach Jan 13, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions go/mysql/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ package config
const DefaultSQLMode = "ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION"
const DefaultMySQLVersion = "8.0.30"
const LegacyMySQLVersion = "5.7.31"
const Lts84MySQLVersion = "8.4.3"
48 changes: 48 additions & 0 deletions go/mysql/datetime/interval.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,54 @@ func (itv IntervalType) ToString() string {
}
}

// IntervalTypeFromString parses a string into an IntervalType. This is the inverse function of IntervalType.ToString().
func IntervalTypeFromString(s string) IntervalType {
switch strings.ToLower(s) {
case "year":
return IntervalYear
case "quarter":
return IntervalQuarter
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like this might be worth a map in the package?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

case "month":
return IntervalMonth
case "week":
return IntervalWeek
case "day":
return IntervalDay
case "hour":
return IntervalHour
case "minute":
return IntervalMinute
case "second":
return IntervalSecond
case "microsecond":
return IntervalMicrosecond
case "year_month":
return IntervalYearMonth
case "day_hour":
return IntervalDayHour
case "day_minute":
return IntervalDayMinute
case "day_second":
return IntervalDaySecond
case "hour_minute":
return IntervalHourMinute
case "hour_second":
return IntervalHourSecond
case "minute_second":
return IntervalMinuteSecond
case "day_microsecond":
return IntervalDayMicrosecond
case "hour_microsecond":
return IntervalHourMicrosecond
case "minute_microsecond":
return IntervalMinuteMicrosecond
case "second_microsecond":
return IntervalSecondMicrosecond
default:
return IntervalNone
}
}

func intervalSetYear(tp *Interval, val int) {
tp.year = val
}
Expand Down
47 changes: 47 additions & 0 deletions go/mysql/datetime/interval_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,12 @@ limitations under the License.
package datetime

import (
"math"
"strings"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"vitess.io/vitess/go/mysql/decimal"
)
Expand Down Expand Up @@ -367,3 +370,47 @@ func TestInRange(t *testing.T) {
assert.Equal(t, tc.wantInRange, got)
}
}

func TestIntervalTypeFromString(t *testing.T) {
intervals := []IntervalType{
IntervalMicrosecond,
IntervalSecond,
IntervalMinute,
IntervalHour,
IntervalDay,
IntervalWeek,
IntervalMonth,
IntervalQuarter,
IntervalYear,
IntervalSecondMicrosecond,
IntervalMinuteMicrosecond,
IntervalMinuteSecond,
IntervalHourMicrosecond,
IntervalHourSecond,
IntervalHourMinute,
IntervalDayMicrosecond,
IntervalDaySecond,
IntervalDayMinute,
IntervalDayHour,
IntervalYearMonth,
}
for _, interval := range intervals {
s := interval.ToString()
t.Run(s, func(t *testing.T) {
require.NotEmpty(t, s)
require.NotEqual(t, "[unknown IntervalType]", s)
parsed := IntervalTypeFromString(s)
assert.NotEqual(t, IntervalNone, parsed)
assert.Equal(t, interval, parsed)

parsed = IntervalTypeFromString(strings.ToUpper(s))
assert.NotEqual(t, IntervalNone, parsed)
assert.Equal(t, interval, parsed)
})
}
interval := IntervalType(math.MaxUint8)
s := interval.ToString()
assert.Equal(t, "[unknown IntervalType]", s)
parsed := IntervalTypeFromString(s)
assert.Equal(t, IntervalNone, parsed)
}
68 changes: 0 additions & 68 deletions go/vt/schemadiff/analysis.go
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed as partitioning_analysis.go

This file was deleted.

83 changes: 0 additions & 83 deletions go/vt/schemadiff/analysis_test.go
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed as partitioning_analysis_test.go

This file was deleted.

34 changes: 33 additions & 1 deletion go/vt/schemadiff/diff_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -587,9 +587,11 @@ func TestDiffSchemas(t *testing.T) {
diffs []string
cdiffs []string
expectError string
tableRename int
annotated []string
// hints:
tableRename int
fkStrategy int
rotation int
}{
{
name: "identical tables",
Expand Down Expand Up @@ -922,6 +924,35 @@ func TestDiffSchemas(t *testing.T) {
"ALTER TABLE `t` RENAME INDEX `i_idx` TO `i_alternative`",
},
},
// Partitions
{
name: "change partitioning range: statements, add",
from: "create table t1 (id int primary key) partition by range (id) (partition p1 values less than (10), partition p2 values less than (20))",
to: "create table t1 (id int primary key) partition by range (id) (partition p1 values less than (10), partition p2 values less than (20), partition p3 values less than (30))",
rotation: RangeRotationDistinctStatements,
diffs: []string{
"alter table t1 add partition (partition p3 values less than (30))",
},
cdiffs: []string{
"ALTER TABLE `t1` ADD PARTITION (PARTITION `p3` VALUES LESS THAN (30))",
},
},
{
name: "change partitioning range: statements, multiple drops, distinct",
from: "create table t1 (id int primary key) partition by range (id) (partition p1 values less than (10), partition p2 values less than (20), partition p3 values less than (30))",
to: "create table t1 (id int primary key) partition by range (id) (partition p3 values less than (30))",
rotation: RangeRotationDistinctStatements,
diffs: []string{"alter table t1 drop partition p1, p2"},
cdiffs: []string{"ALTER TABLE `t1` DROP PARTITION `p1`, `p2`"},
},
{
name: "change partitioning range: statements, multiple, assorted",
from: "create table t1 (id int primary key) partition by range (id) (partition p1 values less than (10), partition p2 values less than (20), partition p3 values less than (30))",
to: "create table t1 (id int primary key) partition by range (id) (partition p2 values less than (20), partition p3 values less than (30), partition p4 values less than (40))",
rotation: RangeRotationDistinctStatements,
diffs: []string{"alter table t1 drop partition p1", "alter table t1 add partition (partition p4 values less than (40))"},
cdiffs: []string{"ALTER TABLE `t1` DROP PARTITION `p1`", "ALTER TABLE `t1` ADD PARTITION (PARTITION `p4` VALUES LESS THAN (40))"},
},
// Views
{
name: "identical views",
Expand Down Expand Up @@ -1043,6 +1074,7 @@ func TestDiffSchemas(t *testing.T) {
hints := &DiffHints{
TableRenameStrategy: ts.tableRename,
ForeignKeyCheckStrategy: ts.fkStrategy,
RangeRotationStrategy: ts.rotation,
}
diff, err := DiffSchemasSQL(env, ts.from, ts.to, hints)
if ts.expectError != "" {
Expand Down
7 changes: 7 additions & 0 deletions go/vt/schemadiff/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@ func NewTestEnv() *Environment {
}
}

func New84TestEnv() *Environment {
return &Environment{
Environment: vtenv.New84TestEnv(),
DefaultColl: collations.MySQL8().DefaultConnectionCharset(),
}
}

func NewEnv(env *vtenv.Environment, defaultColl collations.ID) *Environment {
return &Environment{
Environment: env,
Expand Down
10 changes: 10 additions & 0 deletions go/vt/schemadiff/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,16 @@ func (e *InvalidColumnInPartitionError) Error() string {
sqlescape.EscapeID(e.Column), sqlescape.EscapeID(e.Table))
}

type UnsupportedRangeColumnsTypeError struct {
Table string
Column string
Type string
}

func (e *UnsupportedRangeColumnsTypeError) Error() string {
return fmt.Sprintf("unsupported column type %s for column %s indicated by RANGE COLUMNS in table %s", e.Type, e.Column, e.Table)
}

type MissingPartitionColumnInUniqueKeyError struct {
Table string
Column string
Expand Down
Loading
Loading