Skip to content

Commit

Permalink
Add support for MySQL 5.5
Browse files Browse the repository at this point in the history
  • Loading branch information
evanelias committed Jul 4, 2018
1 parent a9cb684 commit dd14442
Show file tree
Hide file tree
Showing 61 changed files with 404 additions and 16 deletions.
2 changes: 1 addition & 1 deletion Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions ddlstatement_test.go
Expand Up @@ -8,6 +8,9 @@ import (
)

func (s *SkeemaIntegrationSuite) TestNewDDLStatement(t *testing.T) {
major, minor, _ := s.d.Version()
is55 := major == 5 && minor == 5

// Setup: init files and then change the DB so that we have some
// differences to generate. We first add a default value to domain col
// to later test that quoting rules are working properly for shellouts.
Expand All @@ -26,6 +29,10 @@ func (s *SkeemaIntegrationSuite) TestNewDDLStatement(t *testing.T) {
"alter-algorithm": "INPLACE",
"alter-lock": "NONE",
})
if is55 {
delete(fakeFileSource, "alter-algorithm")
delete(fakeFileSource, "alter-lock")
}
cfg := mybase.ParseFakeCLI(t, CommandSuite, "skeema diff ", fakeFileSource)
AddGlobalConfigFiles(cfg)
dir, err := NewDir(".", cfg)
Expand All @@ -52,6 +59,9 @@ func (s *SkeemaIntegrationSuite) TestNewDDLStatement(t *testing.T) {
LockClause: "NONE",
AlgorithmClause: "INPLACE",
}
if is55 {
mods = tengo.StatementModifiers{AllowUnsafe: true}
}
for _, diff := range sd.TableDiffs {
ddl := NewDDLStatement(diff, mods, target)
if ddl.Err != nil {
Expand All @@ -67,6 +77,9 @@ func (s *SkeemaIntegrationSuite) TestNewDDLStatement(t *testing.T) {
// no rows, so ddl-wrapper used. verify the statement separately.
expected = "/bin/echo ddl-wrapper analytics.rollups ALTER"
expectedStmt := "ALTER TABLE `rollups` ALGORITHM=INPLACE, LOCK=NONE, ADD COLUMN `value` bigint(20) DEFAULT NULL"
if is55 {
expectedStmt = "ALTER TABLE `rollups` ADD COLUMN `value` bigint(20) DEFAULT NULL"
}
if ddl.stmt != expectedStmt {
t.Errorf("Expected statement:\n%s\nActual statement:\n%s\n", expectedStmt, ddl.stmt)
}
Expand Down
13 changes: 10 additions & 3 deletions skeema_cmd_test.go
Expand Up @@ -414,9 +414,13 @@ func (s *SkeemaIntegrationSuite) TestIndexOrdering(t *testing.T) {
}

// Edit posts.sql to put the new indexes first again, and ensure
// push --exact-match actually reorders them
// push --exact-match actually reorders them.
writeFile(t, "mydb/product/posts.sql", contentsIndexesFirst)
s.handleCommand(t, CodeSuccess, "", "skeema push --exact-match --alter-algorithm=COPY")
if major, minor, _ := s.d.Version(); major == 5 && minor == 5 {
s.handleCommand(t, CodeSuccess, "", "skeema push --exact-match")
} else {
s.handleCommand(t, CodeSuccess, "", "skeema push --exact-match --alter-algorithm=COPY")
}
s.handleCommand(t, CodeSuccess, "", "skeema diff")
s.handleCommand(t, CodeSuccess, "", "skeema diff --exact-match")
s.handleCommand(t, CodeSuccess, "", "skeema pull")
Expand Down Expand Up @@ -679,9 +683,12 @@ func (s *SkeemaIntegrationSuite) TestDirEdgeCases(t *testing.T) {
// information_schema. Skeema ignores/strips these clauses so that they do not
// trip up its "unsupported table" validation logic.
func (s *SkeemaIntegrationSuite) TestNonInnoClauses(t *testing.T) {
// MariaDB does not consider STORAGE or COLUMN_FORMAT clauses as valid SQL
// MariaDB does not consider STORAGE or COLUMN_FORMAT clauses as valid SQL.
// Ditto for MySQL 5.5.
if s.d.Flavor() == tengo.FlavorMariaDB {
t.Skip("Test not relevant for MariaDB-based image", s.d.Image)
} else if major, minor, _ := s.d.Version(); major == 5 && minor == 5 {
t.Skip("Test not relevant for 5.5-based image", s.d.Image)
}

withClauses := "CREATE TABLE `problems` (\n" +
Expand Down
16 changes: 11 additions & 5 deletions skeema_test.go
Expand Up @@ -168,13 +168,19 @@ func (s *SkeemaIntegrationSuite) handleCommand(t *testing.T, expectedExitCode in
func (s *SkeemaIntegrationSuite) verifyFiles(t *testing.T, cfg *mybase.Config, dirExpectedBase string) {
t.Helper()

// MariaDB 10.2+ changes a few aspects of SHOW CREATE TABLE: default values are
// no longer quoted if non-strings; the blob and text types now permit default
// values; partitions are formatted differently. We must maintain a different
// set of golden files for comparing to MariaDB, so hackily manipulate the
// dirExpectedBase if needed.
// Hackily manipulate dirExpectedBase if testing against a database backend
// with different SHOW CREATE TABLE rules:
// In MariaDB 10.2+, default values are no longer quoted if non-strings; the
// blob and text types now permit default values; partitions are formatted
// differently; default values and on-update rules for CURRENT_TIMESTAMP always
// include parens and lowercase the function name.
// In MySQL 5.5, DATETIME columns cannot have default or on-update of
// CURRENT_TIMESTAMP; only one TIMESTAMP column can have on-update;
// CURRENT_TIMESTAMP does not take an arg for specifying sub-second precision
if s.d.IsNewMariaFormat() {
dirExpectedBase = strings.Replace(dirExpectedBase, "golden", "golden-mariadb102", 1)
} else if major, minor, _ := s.d.Version(); major == 5 && minor == 5 {
dirExpectedBase = strings.Replace(dirExpectedBase, "golden", "golden-mysql55", 1)
}

var compareDirs func(*Dir, *Dir)
Expand Down
12 changes: 8 additions & 4 deletions target.go
Expand Up @@ -255,10 +255,14 @@ func (t *Target) verifyDiff(diff *tengo.SchemaDiff) (err error) {
}
mods := tengo.StatementModifiers{
NextAutoInc: tengo.NextAutoIncIgnore,
StrictIndexOrder: true, // needed since we must get the SHOW CREATE TABLEs to match
StrictForeignKeyNaming: true, // ditto
AllowUnsafe: true, // needed since we're just running against the temp schema
AlgorithmClause: "COPY", // needed to avoid having MySQL ignore index changes that are simply reordered
StrictIndexOrder: true, // needed since we must get the SHOW CREATE TABLEs to match
StrictForeignKeyNaming: true, // ditto
AllowUnsafe: true, // needed since we're just running against the temp schema
}
if major, minor, _ := t.Instance.Version(); major != 5 || minor != 5 {
// avoid having MySQL ignore index changes that are simply reordered, but only
// legal syntax in 5.6+
mods.AlgorithmClause = "COPY"
}

// Iterate over the ALTER-type TableDiffs in the SchemaDiff and index by table
Expand Down
3 changes: 3 additions & 0 deletions testdata/golden-mysql55/autoinc/mydb/.skeema
@@ -0,0 +1,3 @@
[production]
host=127.0.0.1
port={DYNAMICALLY INSERTED BY TEST}
1 change: 1 addition & 0 deletions testdata/golden-mysql55/autoinc/mydb/analytics/.skeema
@@ -0,0 +1 @@
schema=analytics
9 changes: 9 additions & 0 deletions testdata/golden-mysql55/autoinc/mydb/analytics/activity.sql
@@ -0,0 +1,9 @@
CREATE TABLE `activity` (
`user_id` bigint(20) unsigned NOT NULL,
`action_id` int(10) unsigned NOT NULL,
`ts` int(10) unsigned NOT NULL,
`target_type` varchar(20) DEFAULT NULL,
`target_id` bigint(20) unsigned DEFAULT NULL,
PRIMARY KEY (`user_id`,`action_id`,`ts`),
KEY `by_target` (`target_id`,`target_type`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
8 changes: 8 additions & 0 deletions testdata/golden-mysql55/autoinc/mydb/analytics/pageviews.sql
@@ -0,0 +1,8 @@
CREATE TABLE `pageviews` (
`url` varchar(200) NOT NULL,
`start_ts` int(10) unsigned NOT NULL,
`end_ts` int(10) unsigned NOT NULL,
`views` bigint(20) unsigned DEFAULT NULL,
`domain` varchar(40) NOT NULL,
PRIMARY KEY (`url`,`start_ts`,`end_ts`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
5 changes: 5 additions & 0 deletions testdata/golden-mysql55/autoinc/mydb/analytics/rollups.sql
@@ -0,0 +1,5 @@
CREATE TABLE `rollups` (
`metric_id` int(10) unsigned NOT NULL,
`value` bigint(20) DEFAULT NULL,
PRIMARY KEY (`metric_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
1 change: 1 addition & 0 deletions testdata/golden-mysql55/autoinc/mydb/product/.skeema
@@ -0,0 +1 @@
schema=product
8 changes: 8 additions & 0 deletions testdata/golden-mysql55/autoinc/mydb/product/comments.sql
@@ -0,0 +1,8 @@
CREATE TABLE `comments` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`post_id` bigint(20) unsigned NOT NULL,
`user_id` bigint(20) unsigned NOT NULL,
`created_at` datetime DEFAULT NULL,
`body` text,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
9 changes: 9 additions & 0 deletions testdata/golden-mysql55/autoinc/mydb/product/posts.sql
@@ -0,0 +1,9 @@
CREATE TABLE `posts` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`user_id` bigint(20) unsigned NOT NULL,
`body` text,
`created_at` datetime DEFAULT NULL,
`edited_at` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `user_created` (`user_id`,`created_at`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
@@ -0,0 +1,7 @@
CREATE TABLE `subscriptions` (
`user_id` bigint(20) unsigned NOT NULL,
`post_id` bigint(20) unsigned NOT NULL,
`subscribed_at` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`post_id`,`user_id`),
KEY `user_post` (`user_id`,`post_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
8 changes: 8 additions & 0 deletions testdata/golden-mysql55/autoinc/mydb/product/users.sql
@@ -0,0 +1,8 @@
CREATE TABLE `users` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(30) NOT NULL,
`credits` decimal(9,2) DEFAULT '10.00',
`last_modified` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1;
5 changes: 5 additions & 0 deletions testdata/golden-mysql55/ignore/mydb/.skeema
@@ -0,0 +1,5 @@
[production]
host=127.0.0.1
port={DYNAMICALLY INSERTED BY TEST}
ignore-schema=^archives$
ignore-table=^_
1 change: 1 addition & 0 deletions testdata/golden-mysql55/ignore/mydb/analytics/.skeema
@@ -0,0 +1 @@
schema=analytics
9 changes: 9 additions & 0 deletions testdata/golden-mysql55/ignore/mydb/analytics/activity.sql
@@ -0,0 +1,9 @@
CREATE TABLE `activity` (
`user_id` bigint(20) unsigned NOT NULL,
`action_id` int(10) unsigned NOT NULL,
`ts` int(10) unsigned NOT NULL,
`target_type` varchar(20) DEFAULT NULL,
`target_id` bigint(20) unsigned DEFAULT NULL,
PRIMARY KEY (`user_id`,`action_id`,`ts`),
KEY `by_target` (`target_id`,`target_type`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
8 changes: 8 additions & 0 deletions testdata/golden-mysql55/ignore/mydb/analytics/pageviews.sql
@@ -0,0 +1,8 @@
CREATE TABLE `pageviews` (
`url` varchar(200) NOT NULL,
`start_ts` int(10) unsigned NOT NULL,
`end_ts` int(10) unsigned NOT NULL,
`views` bigint(20) unsigned DEFAULT NULL,
`domain` varchar(40) NOT NULL,
PRIMARY KEY (`url`,`start_ts`,`end_ts`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
5 changes: 5 additions & 0 deletions testdata/golden-mysql55/ignore/mydb/analytics/rollups.sql
@@ -0,0 +1,5 @@
CREATE TABLE `rollups` (
`metric_id` int(10) unsigned NOT NULL,
`value` bigint(20) DEFAULT NULL,
PRIMARY KEY (`metric_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
1 change: 1 addition & 0 deletions testdata/golden-mysql55/ignore/mydb/product/.skeema
@@ -0,0 +1 @@
schema=product
8 changes: 8 additions & 0 deletions testdata/golden-mysql55/ignore/mydb/product/comments.sql
@@ -0,0 +1,8 @@
CREATE TABLE `comments` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`post_id` bigint(20) unsigned NOT NULL,
`user_id` bigint(20) unsigned NOT NULL,
`created_at` datetime DEFAULT NULL,
`body` text,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
9 changes: 9 additions & 0 deletions testdata/golden-mysql55/ignore/mydb/product/posts.sql
@@ -0,0 +1,9 @@
CREATE TABLE `posts` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`user_id` bigint(20) unsigned NOT NULL,
`body` text,
`created_at` datetime DEFAULT NULL,
`edited_at` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `user_created` (`user_id`,`created_at`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
7 changes: 7 additions & 0 deletions testdata/golden-mysql55/ignore/mydb/product/subscriptions.sql
@@ -0,0 +1,7 @@
CREATE TABLE `subscriptions` (
`user_id` bigint(20) unsigned NOT NULL,
`post_id` bigint(20) unsigned NOT NULL,
`subscribed_at` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`post_id`,`user_id`),
KEY `user_post` (`user_id`,`post_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
8 changes: 8 additions & 0 deletions testdata/golden-mysql55/ignore/mydb/product/users.sql
@@ -0,0 +1,8 @@
CREATE TABLE `users` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(30) NOT NULL,
`credits` decimal(9,2) DEFAULT '10.00',
`last_modified` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
3 changes: 3 additions & 0 deletions testdata/golden-mysql55/init/mydb/.skeema
@@ -0,0 +1,3 @@
[production]
host=127.0.0.1
port={DYNAMICALLY INSERTED BY TEST}
1 change: 1 addition & 0 deletions testdata/golden-mysql55/init/mydb/analytics/.skeema
@@ -0,0 +1 @@
schema=analytics
9 changes: 9 additions & 0 deletions testdata/golden-mysql55/init/mydb/analytics/activity.sql
@@ -0,0 +1,9 @@
CREATE TABLE `activity` (
`user_id` bigint(20) unsigned NOT NULL,
`action_id` int(10) unsigned NOT NULL,
`ts` int(10) unsigned NOT NULL,
`target_type` varchar(20) DEFAULT NULL,
`target_id` bigint(20) unsigned DEFAULT NULL,
PRIMARY KEY (`user_id`,`action_id`,`ts`),
KEY `by_target` (`target_id`,`target_type`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
8 changes: 8 additions & 0 deletions testdata/golden-mysql55/init/mydb/analytics/pageviews.sql
@@ -0,0 +1,8 @@
CREATE TABLE `pageviews` (
`url` varchar(200) NOT NULL,
`start_ts` int(10) unsigned NOT NULL,
`end_ts` int(10) unsigned NOT NULL,
`views` bigint(20) unsigned DEFAULT NULL,
`domain` varchar(40) NOT NULL,
PRIMARY KEY (`url`,`start_ts`,`end_ts`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
5 changes: 5 additions & 0 deletions testdata/golden-mysql55/init/mydb/analytics/rollups.sql
@@ -0,0 +1,5 @@
CREATE TABLE `rollups` (
`metric_id` int(10) unsigned NOT NULL,
`value` bigint(20) DEFAULT NULL,
PRIMARY KEY (`metric_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
1 change: 1 addition & 0 deletions testdata/golden-mysql55/init/mydb/product/.skeema
@@ -0,0 +1 @@
schema=product
8 changes: 8 additions & 0 deletions testdata/golden-mysql55/init/mydb/product/comments.sql
@@ -0,0 +1,8 @@
CREATE TABLE `comments` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`post_id` bigint(20) unsigned NOT NULL,
`user_id` bigint(20) unsigned NOT NULL,
`created_at` datetime DEFAULT NULL,
`body` text,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
9 changes: 9 additions & 0 deletions testdata/golden-mysql55/init/mydb/product/posts.sql
@@ -0,0 +1,9 @@
CREATE TABLE `posts` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`user_id` bigint(20) unsigned NOT NULL,
`body` text,
`created_at` datetime DEFAULT NULL,
`edited_at` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `user_created` (`user_id`,`created_at`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
7 changes: 7 additions & 0 deletions testdata/golden-mysql55/init/mydb/product/subscriptions.sql
@@ -0,0 +1,7 @@
CREATE TABLE `subscriptions` (
`user_id` bigint(20) unsigned NOT NULL,
`post_id` bigint(20) unsigned NOT NULL,
`subscribed_at` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`post_id`,`user_id`),
KEY `user_post` (`user_id`,`post_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
8 changes: 8 additions & 0 deletions testdata/golden-mysql55/init/mydb/product/users.sql
@@ -0,0 +1,8 @@
CREATE TABLE `users` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(30) NOT NULL,
`credits` decimal(9,2) DEFAULT '10.00',
`last_modified` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
3 changes: 3 additions & 0 deletions testdata/golden-mysql55/pull1/mydb/.skeema
@@ -0,0 +1,3 @@
[production]
host=127.0.0.1
port={DYNAMICALLY INSERTED BY TEST}
3 changes: 3 additions & 0 deletions testdata/golden-mysql55/pull1/mydb/analytics/.skeema
@@ -0,0 +1,3 @@
schema=analytics
default-character-set=utf8
default-collation=utf8_swedish_ci
9 changes: 9 additions & 0 deletions testdata/golden-mysql55/pull1/mydb/analytics/activity.sql
@@ -0,0 +1,9 @@
CREATE TABLE `activity` (
`user_id` bigint(20) unsigned NOT NULL,
`action_id` int(10) unsigned NOT NULL,
`ts` int(10) unsigned NOT NULL,
`target_type` varchar(20) DEFAULT NULL,
`target_id` bigint(20) unsigned DEFAULT NULL,
PRIMARY KEY (`user_id`,`action_id`,`ts`),
KEY `by_target` (`target_id`,`target_type`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
8 changes: 8 additions & 0 deletions testdata/golden-mysql55/pull1/mydb/analytics/pageviews.sql
@@ -0,0 +1,8 @@
CREATE TABLE `pageviews` (
`url` varchar(200) NOT NULL,
`start_ts` int(10) unsigned NOT NULL,
`end_ts` int(10) unsigned NOT NULL,
`views` bigint(20) unsigned DEFAULT NULL,
`domain` varchar(40) NOT NULL,
PRIMARY KEY (`url`,`start_ts`,`end_ts`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
5 changes: 5 additions & 0 deletions testdata/golden-mysql55/pull1/mydb/analytics/rollups.sql
@@ -0,0 +1,5 @@
CREATE TABLE `rollups` (
`metric_id` int(10) unsigned NOT NULL,
`value` bigint(20) DEFAULT NULL,
PRIMARY KEY (`metric_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
@@ -0,0 +1,5 @@
CREATE TABLE `widget_counts` (
`name` varchar(40) NOT NULL,
`cnt` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
3 changes: 3 additions & 0 deletions testdata/golden-mysql55/pull1/mydb/archives/.skeema
@@ -0,0 +1,3 @@
schema=archives
default-character-set=utf8mb4
default-collation=utf8mb4_general_ci
4 changes: 4 additions & 0 deletions testdata/golden-mysql55/pull1/mydb/archives/foo.sql
@@ -0,0 +1,4 @@
CREATE TABLE `foo` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
1 change: 1 addition & 0 deletions testdata/golden-mysql55/pull1/mydb/product/.skeema
@@ -0,0 +1 @@
schema=product
10 changes: 10 additions & 0 deletions testdata/golden-mysql55/pull1/mydb/product/posts.sql
@@ -0,0 +1,10 @@
CREATE TABLE `posts` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`user_id` bigint(20) unsigned NOT NULL,
`body` text,
`created_at` datetime DEFAULT NULL,
`edited_at` datetime DEFAULT NULL,
`status` varchar(20) DEFAULT 'published',
PRIMARY KEY (`id`),
KEY `user_created` (`user_id`,`created_at`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

0 comments on commit dd14442

Please sign in to comment.