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

Namespaces mysql #1386

Merged
merged 13 commits into from
Mar 8, 2023
1 change: 1 addition & 0 deletions config/migrations/mysql/4_create_namespaces.down.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DROP TABLE IF EXISTS namespaces;
12 changes: 12 additions & 0 deletions config/migrations/mysql/4_create_namespaces.up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/* Create namespaces table */
CREATE TABLE IF NOT EXISTS namespaces (
`key` VARCHAR(255) PRIMARY KEY UNIQUE NOT NULL,
name VARCHAR(255) NOT NULL,
description TEXT NOT NULL,
protected BOOLEAN DEFAULT FALSE NOT NULL,
created_at TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP(6) NOT NULL,
updated_at TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP(6) NOT NULL
);

/* Create default namespace */
INSERT INTO namespaces (`key`, name, description, protected) VALUES ('default', 'Default', 'Default namespace', true);
10 changes: 10 additions & 0 deletions config/migrations/mysql/5_namespaces_flags.up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
ALTER TABLE flags ADD COLUMN namespace_key VARCHAR(255) NOT NULL DEFAULT 'default';
ALTER TABLE flags DROP INDEX `key`, ADD INDEX `key` (`key`) USING BTREE; /* drop previously created unique index */
ALTER TABLE flags ADD FOREIGN KEY (namespace_key) REFERENCES namespaces(`key`) ON DELETE CASCADE;
ALTER TABLE flags DROP PRIMARY KEY, ADD PRIMARY KEY (`namespace_key`, `key`);

ALTER TABLE variants ADD COLUMN namespace_key VARCHAR(255) NOT NULL DEFAULT 'default';
ALTER TABLE variants DROP FOREIGN KEY `variants_ibfk_1`; /* drop previously created foreign key */
ALTER TABLE variants DROP INDEX `variants_flag_key_key`, ADD UNIQUE INDEX `variants_namespace_flag_key` (`namespace_key`, `flag_key`, `key`) USING BTREE; /* drop previously created unique index */
ALTER TABLE variants ADD FOREIGN KEY (namespace_key) REFERENCES namespaces(`key`) ON DELETE CASCADE;
ALTER TABLE variants ADD FOREIGN KEY (namespace_key, flag_key) REFERENCES flags(`namespace_key`, `key`) ON DELETE CASCADE;
10 changes: 10 additions & 0 deletions config/migrations/mysql/6_namespaces_segments.up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
ALTER TABLE segments ADD COLUMN namespace_key VARCHAR(255) NOT NULL DEFAULT 'default';
ALTER TABLE segments DROP INDEX `key`, ADD INDEX `key` (`key`) USING BTREE; /* drop previously created unique index */
ALTER TABLE segments ADD FOREIGN KEY (namespace_key) REFERENCES namespaces(`key`) ON DELETE CASCADE;
ALTER TABLE segments DROP PRIMARY KEY, ADD PRIMARY KEY (`namespace_key`, `key`);

ALTER TABLE constraints ADD COLUMN namespace_key VARCHAR(255) NOT NULL DEFAULT 'default';
ALTER TABLE constraints DROP FOREIGN KEY `constraints_ibfk_1`; /* drop previously created foreign key */
ALTER TABLE constraints DROP INDEX `segment_key`, ADD INDEX `constraints_namespace_segment_key` (`namespace_key`, `segment_key`) USING BTREE; /* drop previously created index */
ALTER TABLE constraints ADD FOREIGN KEY (namespace_key) REFERENCES namespaces(`key`) ON DELETE CASCADE;
ALTER TABLE constraints ADD FOREIGN KEY (namespace_key, segment_key) REFERENCES segments(`namespace_key`, `key`) ON DELETE CASCADE;
Empty file.
8 changes: 8 additions & 0 deletions config/migrations/mysql/7_namespaces_rules.up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
ALTER TABLE rules ADD COLUMN namespace_key VARCHAR(255) NOT NULL DEFAULT 'default';
ALTER TABLE rules DROP FOREIGN KEY `rules_ibfk_1`; /* drop previously created foreign key */
ALTER TABLE rules DROP FOREIGN KEY `rules_ibfk_2`; /* drop previously created foreign key */
ALTER TABLE rules DROP INDEX `flag_key`, ADD INDEX `rules_namespace_flag_key` (`namespace_key`, `flag_key`) USING BTREE; /* drop previously created index */
ALTER TABLE rules DROP INDEX `segment_key`, ADD INDEX `rules_namespace_segment_key` (`namespace_key`, `segment_key`) USING BTREE; /* drop previously created index */
ALTER TABLE rules ADD FOREIGN KEY (namespace_key) REFERENCES namespaces(`key`) ON DELETE CASCADE;
ALTER TABLE rules ADD FOREIGN KEY (namespace_key, flag_key) REFERENCES flags(`namespace_key`, `key`) ON DELETE CASCADE;
ALTER TABLE rules ADD FOREIGN KEY (namespace_key, segment_key) REFERENCES segments(`namespace_key`, `key`) ON DELETE CASCADE;
1 change: 1 addition & 0 deletions config/migrations/sqlite3/7_namespaces_flags.down.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/* TODO */
1 change: 1 addition & 0 deletions config/migrations/sqlite3/8_namespaces_segments.down.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/* TODO */
2 changes: 1 addition & 1 deletion internal/storage/sql/common/namespace.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func (s *Store) GetNamespace(ctx context.Context, key string) (*flipt.Namespace,

err = s.builder.Select("\"key\", name, description, protected, created_at, updated_at").
From("namespaces").
Where(sq.Eq{"key": key}).
Where(sq.Eq{"\"key\"": key}).
QueryRowContext(ctx).
Scan(
&namespace.Key,
Expand Down
2 changes: 1 addition & 1 deletion internal/storage/sql/migrator.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import (
var expectedVersions = map[Driver]uint{
SQLite: 8,
Postgres: 5,
MySQL: 3,
MySQL: 7,
CockroachDB: 2,
}

Expand Down
42 changes: 34 additions & 8 deletions internal/storage/sql/mysql/mysql.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,35 @@ func (s *Store) String() string {
return "mysql"
}

func (s *Store) CreateNamespace(ctx context.Context, r *flipt.CreateNamespaceRequest) (*flipt.Namespace, error) {
namespace, err := s.Store.CreateNamespace(ctx, r)

if err != nil {
var merr *mysql.MySQLError

if errors.As(err, &merr) && merr.Number == constraintUniqueErrCode {
return nil, errs.ErrInvalidf("namespace %q is not unique", r.Key)
}

return nil, err
}

return namespace, nil
}

func (s *Store) CreateFlag(ctx context.Context, r *flipt.CreateFlagRequest) (*flipt.Flag, error) {
flag, err := s.Store.CreateFlag(ctx, r)

if err != nil {
var merr *mysql.MySQLError

if errors.As(err, &merr) && merr.Number == constraintUniqueErrCode {
return nil, errs.ErrInvalidf("flag %q is not unique for the namespace %q", r.Key, r.NamespaceKey)
if errors.As(err, &merr) {
switch merr.Number {
case constraintForeignKeyErrCode:
return nil, errs.ErrNotFoundf("namespace %q", r.NamespaceKey)
case constraintUniqueErrCode:
return nil, errs.ErrInvalidf(`flag "%s/%s" is not unique`, r.NamespaceKey, r.Key)
}
}

return nil, err
Expand All @@ -63,9 +84,9 @@ func (s *Store) CreateVariant(ctx context.Context, r *flipt.CreateVariantRequest
if errors.As(err, &merr) {
switch merr.Number {
case constraintForeignKeyErrCode:
return nil, errs.ErrNotFoundf("flag %q", r.FlagKey)
return nil, errs.ErrNotFoundf(`flag "%s/%s"`, r.NamespaceKey, r.FlagKey)
case constraintUniqueErrCode:
return nil, errs.ErrInvalidf("variant %q is not unique for the flag %q", r.Key, r.FlagKey)
return nil, errs.ErrInvalidf(`variant %q is not unique for flag "%s/%s"`, r.Key, r.NamespaceKey, r.FlagKey)
}
}

Expand All @@ -82,7 +103,7 @@ func (s *Store) UpdateVariant(ctx context.Context, r *flipt.UpdateVariantRequest
var merr *mysql.MySQLError

if errors.As(err, &merr) && merr.Number == constraintUniqueErrCode {
return nil, errs.ErrInvalidf("variant %q is not unique for the flag %q", r.Key, r.FlagKey)
return nil, errs.ErrInvalidf(`variant %q is not unique for flag "%s/%s"`, r.Key, r.NamespaceKey, r.FlagKey)
}

return nil, err
Expand All @@ -97,8 +118,13 @@ func (s *Store) CreateSegment(ctx context.Context, r *flipt.CreateSegmentRequest
if err != nil {
var merr *mysql.MySQLError

if errors.As(err, &merr) && merr.Number == constraintUniqueErrCode {
return nil, errs.ErrInvalidf("segment %q is not unique", r.Key)
if errors.As(err, &merr) {
switch merr.Number {
case constraintForeignKeyErrCode:
return nil, errs.ErrNotFoundf("namespace %q", r.NamespaceKey)
case constraintUniqueErrCode:
return nil, errs.ErrInvalidf(`segment "%s/%s" is not unique`, r.NamespaceKey, r.Key)
}
}

return nil, err
Expand All @@ -114,7 +140,7 @@ func (s *Store) CreateConstraint(ctx context.Context, r *flipt.CreateConstraintR
var merr *mysql.MySQLError

if errors.As(err, &merr) && merr.Number == constraintForeignKeyErrCode {
return nil, errs.ErrNotFoundf("segment %q", r.SegmentKey)
return nil, errs.ErrNotFoundf(`segment "%s/%s"`, r.NamespaceKey, r.SegmentKey)
}

return nil, err
Expand Down
1 change: 1 addition & 0 deletions internal/storage/sql/sqlite/sqlite.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ func (s *Store) CreateSegment(ctx context.Context, r *flipt.CreateSegmentRequest
return nil, errs.ErrInvalidf(`segment "%s/%s" is not unique`, r.NamespaceKey, r.Key)
}
}

return nil, err
}

Expand Down