From 477a47897e403c499c6199f6f9c0961d28a88500 Mon Sep 17 00:00:00 2001 From: Michael Gaffney Date: Wed, 13 May 2020 10:40:57 -0400 Subject: [PATCH] Add wt_timestamp type to database (#52) * Add wt_timestamp type to database * Swap the order of domains and oplog migrations All migrations should use the new 'wt_timestamp' domain type for timestamps. * Remove dead code * Add down migration for wt_timestamp --- internal/db/domains_test.go | 41 ++++++++- internal/db/migrations/postgres.gen.go | 92 ++++++++++--------- ...ypes.down.sql => 01_domain_types.down.sql} | 1 + ...in_types.up.sql => 01_domain_types.up.sql} | 6 ++ .../{01_oplog.up.sql => 02_oplog.up.sql} | 12 +-- internal/db/migrations/postgres/03_db.up.sql | 14 +-- internal/db/migrations/postgres/04_iam.up.sql | 6 +- 7 files changed, 114 insertions(+), 58 deletions(-) rename internal/db/migrations/postgres/{02_domain_types.down.sql => 01_domain_types.down.sql} (62%) rename internal/db/migrations/postgres/{02_domain_types.up.sql => 01_domain_types.up.sql} (51%) rename internal/db/migrations/postgres/{01_oplog.up.sql => 02_oplog.up.sql} (74%) diff --git a/internal/db/domains_test.go b/internal/db/domains_test.go index f08df92fd..55052cbb1 100644 --- a/internal/db/domains_test.go +++ b/internal/db/domains_test.go @@ -6,7 +6,7 @@ import ( _ "github.com/jackc/pgx/v4" ) -func TestPublicIdDomain(t *testing.T) { +func TestDomain_PublicId(t *testing.T) { const ( createTable = ` create table if not exists test_table ( @@ -63,3 +63,42 @@ returning id; }) } } + +func TestDomain_Timestamp(t *testing.T) { + const ( + createTable = ` +create table if not exists test_table ( + id bigint generated always as identity primary key, + name text, + good_time wt_timestamp, + bad_time timestamp default current_timestamp +); +` + insert = ` +insert into test_table (name) +values ($1) +returning id; +` + ) + + cleanup, conn, _ := TestSetup(t, "postgres") + defer cleanup() + defer conn.Close() + + db := conn.DB() + if _, err := db.Exec(createTable); err != nil { + t.Fatalf("query: \n%s\n error: %s", createTable, err) + } + + if _, err := db.Exec(insert, "foo"); err != nil { + t.Fatalf("want no error, got error %v", err) + } + + if _, err := db.Query("select extract(timezone from good_time) from test_table;"); err != nil { + t.Errorf("want no error, got error %v", err) + } + + if _, err := db.Query("select extract(timezone from bad_time) from test_table;"); err == nil { + t.Errorf("want error, got no error") + } +} diff --git a/internal/db/migrations/postgres.gen.go b/internal/db/migrations/postgres.gen.go index debdcbea1..f58781e74 100644 --- a/internal/db/migrations/postgres.gen.go +++ b/internal/db/migrations/postgres.gen.go @@ -5,27 +5,61 @@ var postgresMigrations = map[string]*fakeFile{ "migrations": { name: "migrations", }, - "migrations/01_oplog.up.sql": { - name: "01_oplog.up.sql", + "migrations/01_domain_types.down.sql": { + name: "01_domain_types.down.sql", + bytes: []byte(` +begin; + +drop domain wt_timestamp; +drop domain wt_public_id; + +commit; + +`), + }, + "migrations/01_domain_types.up.sql": { + name: "01_domain_types.up.sql", + bytes: []byte(` +begin; + +create domain wt_public_id as text +check( + length(trim(value)) > 10 +); +comment on domain wt_public_id is +'Random ID generated with github.com/hashicorp/vault/sdk/helper/base62'; + +create domain wt_timestamp as + timestamp with time zone + default current_timestamp; +comment on domain wt_timestamp is +'Standard timestamp for all create_time and update_time columns'; + +commit; + +`), + }, + "migrations/02_oplog.up.sql": { + name: "02_oplog.up.sql", bytes: []byte(` CREATE TABLE if not exists oplog_entry ( id bigint generated always as identity primary key, - create_time timestamp with time zone default current_timestamp, - update_time timestamp with time zone default current_timestamp, + create_time wt_timestamp, + update_time wt_timestamp, version text NOT NULL, aggregate_name text NOT NULL, "data" bytea NOT NULL ); CREATE TABLE if not exists oplog_ticket ( id bigint generated always as identity primary key, - create_time timestamp with time zone default current_timestamp, - update_time timestamp with time zone default current_timestamp, + create_time wt_timestamp, + update_time wt_timestamp, "name" text NOT NULL UNIQUE, "version" bigint NOT NULL ); CREATE TABLE if not exists oplog_metadata ( id bigint generated always as identity primary key, - create_time timestamp with time zone default current_timestamp, + create_time wt_timestamp, entry_id bigint NOT NULL REFERENCES oplog_entry(id) ON DELETE CASCADE ON UPDATE CASCADE, "key" text NOT NULL, value text NULL @@ -47,32 +81,6 @@ values ('db_test_user', 1), ('db_test_car', 1), ('db_test_rental', 1); -`), - }, - "migrations/02_domain_types.down.sql": { - name: "02_domain_types.down.sql", - bytes: []byte(` -begin; - -drop domain wt_public_id; - -commit; - -`), - }, - "migrations/02_domain_types.up.sql": { - name: "02_domain_types.up.sql", - bytes: []byte(` -begin; - -create domain wt_public_id as text -check( - length(trim(value)) > 10 -); -comment on domain wt_public_id is -'Random ID generated with github.com/hashicorp/vault/sdk/helper/base62'; - -commit; `), }, @@ -92,8 +100,8 @@ drop table if exists db_test_rental; -- of the Watchtower domain model... they are simply used for testing the internal/db package CREATE TABLE if not exists db_test_user ( id bigint generated always as identity primary key, - create_time timestamp with time zone default current_timestamp, - update_time timestamp with time zone default current_timestamp, + create_time wt_timestamp, + update_time wt_timestamp, public_id text NOT NULL UNIQUE, name text UNIQUE, phone_number text, @@ -101,8 +109,8 @@ CREATE TABLE if not exists db_test_user ( ); CREATE TABLE if not exists db_test_car ( id bigint generated always as identity primary key, - create_time timestamp with time zone default current_timestamp, - update_time timestamp with time zone default current_timestamp, + create_time wt_timestamp, + update_time wt_timestamp, public_id text NOT NULL UNIQUE, name text UNIQUE, model text, @@ -110,13 +118,14 @@ CREATE TABLE if not exists db_test_car ( ); CREATE TABLE if not exists db_test_rental ( id bigint generated always as identity primary key, - create_time timestamp with time zone default current_timestamp, - update_time timestamp with time zone default current_timestamp, + create_time wt_timestamp, + update_time wt_timestamp, public_id text NOT NULL UNIQUE, name text UNIQUE, user_id bigint not null REFERENCES db_test_user(id), car_id bigint not null REFERENCES db_test_car(id) ); + `), }, "migrations/04_iam.down.sql": { @@ -148,8 +157,8 @@ values CREATE TABLE if not exists iam_scope ( public_id wt_public_id primary key, - create_time timestamp with time zone default current_timestamp, - update_time timestamp with time zone default current_timestamp, + create_time wt_timestamp, + update_time wt_timestamp, name text, type text NOT NULL REFERENCES iam_scope_type_enm(string) CHECK( ( @@ -220,6 +229,7 @@ BEFORE update ON iam_scope FOR EACH ROW EXECUTE PROCEDURE iam_immutable_scope_type_func(); COMMIT; + `), }, } diff --git a/internal/db/migrations/postgres/02_domain_types.down.sql b/internal/db/migrations/postgres/01_domain_types.down.sql similarity index 62% rename from internal/db/migrations/postgres/02_domain_types.down.sql rename to internal/db/migrations/postgres/01_domain_types.down.sql index 5381eaa23..41adb0fc9 100644 --- a/internal/db/migrations/postgres/02_domain_types.down.sql +++ b/internal/db/migrations/postgres/01_domain_types.down.sql @@ -1,5 +1,6 @@ begin; +drop domain wt_timestamp; drop domain wt_public_id; commit; diff --git a/internal/db/migrations/postgres/02_domain_types.up.sql b/internal/db/migrations/postgres/01_domain_types.up.sql similarity index 51% rename from internal/db/migrations/postgres/02_domain_types.up.sql rename to internal/db/migrations/postgres/01_domain_types.up.sql index 0d6a3d95b..45e63e5ff 100644 --- a/internal/db/migrations/postgres/02_domain_types.up.sql +++ b/internal/db/migrations/postgres/01_domain_types.up.sql @@ -7,4 +7,10 @@ check( comment on domain wt_public_id is 'Random ID generated with github.com/hashicorp/vault/sdk/helper/base62'; +create domain wt_timestamp as + timestamp with time zone + default current_timestamp; +comment on domain wt_timestamp is +'Standard timestamp for all create_time and update_time columns'; + commit; diff --git a/internal/db/migrations/postgres/01_oplog.up.sql b/internal/db/migrations/postgres/02_oplog.up.sql similarity index 74% rename from internal/db/migrations/postgres/01_oplog.up.sql rename to internal/db/migrations/postgres/02_oplog.up.sql index 76c7b2628..c2634e697 100644 --- a/internal/db/migrations/postgres/01_oplog.up.sql +++ b/internal/db/migrations/postgres/02_oplog.up.sql @@ -1,21 +1,21 @@ CREATE TABLE if not exists oplog_entry ( id bigint generated always as identity primary key, - create_time timestamp with time zone default current_timestamp, - update_time timestamp with time zone default current_timestamp, + create_time wt_timestamp, + update_time wt_timestamp, version text NOT NULL, aggregate_name text NOT NULL, "data" bytea NOT NULL ); CREATE TABLE if not exists oplog_ticket ( id bigint generated always as identity primary key, - create_time timestamp with time zone default current_timestamp, - update_time timestamp with time zone default current_timestamp, + create_time wt_timestamp, + update_time wt_timestamp, "name" text NOT NULL UNIQUE, "version" bigint NOT NULL ); CREATE TABLE if not exists oplog_metadata ( id bigint generated always as identity primary key, - create_time timestamp with time zone default current_timestamp, + create_time wt_timestamp, entry_id bigint NOT NULL REFERENCES oplog_entry(id) ON DELETE CASCADE ON UPDATE CASCADE, "key" text NOT NULL, value text NULL @@ -36,4 +36,4 @@ values ('iam_role_user', 1), ('db_test_user', 1), ('db_test_car', 1), - ('db_test_rental', 1); \ No newline at end of file + ('db_test_rental', 1); diff --git a/internal/db/migrations/postgres/03_db.up.sql b/internal/db/migrations/postgres/03_db.up.sql index fb79ebe0d..e984e22f2 100644 --- a/internal/db/migrations/postgres/03_db.up.sql +++ b/internal/db/migrations/postgres/03_db.up.sql @@ -3,8 +3,8 @@ -- of the Watchtower domain model... they are simply used for testing the internal/db package CREATE TABLE if not exists db_test_user ( id bigint generated always as identity primary key, - create_time timestamp with time zone default current_timestamp, - update_time timestamp with time zone default current_timestamp, + create_time wt_timestamp, + update_time wt_timestamp, public_id text NOT NULL UNIQUE, name text UNIQUE, phone_number text, @@ -12,8 +12,8 @@ CREATE TABLE if not exists db_test_user ( ); CREATE TABLE if not exists db_test_car ( id bigint generated always as identity primary key, - create_time timestamp with time zone default current_timestamp, - update_time timestamp with time zone default current_timestamp, + create_time wt_timestamp, + update_time wt_timestamp, public_id text NOT NULL UNIQUE, name text UNIQUE, model text, @@ -21,10 +21,10 @@ CREATE TABLE if not exists db_test_car ( ); CREATE TABLE if not exists db_test_rental ( id bigint generated always as identity primary key, - create_time timestamp with time zone default current_timestamp, - update_time timestamp with time zone default current_timestamp, + create_time wt_timestamp, + update_time wt_timestamp, public_id text NOT NULL UNIQUE, name text UNIQUE, user_id bigint not null REFERENCES db_test_user(id), car_id bigint not null REFERENCES db_test_car(id) -); \ No newline at end of file +); diff --git a/internal/db/migrations/postgres/04_iam.up.sql b/internal/db/migrations/postgres/04_iam.up.sql index a7fc1508c..9564f0850 100644 --- a/internal/db/migrations/postgres/04_iam.up.sql +++ b/internal/db/migrations/postgres/04_iam.up.sql @@ -12,8 +12,8 @@ values CREATE TABLE if not exists iam_scope ( public_id wt_public_id primary key, - create_time timestamp with time zone default current_timestamp, - update_time timestamp with time zone default current_timestamp, + create_time wt_timestamp, + update_time wt_timestamp, name text, type text NOT NULL REFERENCES iam_scope_type_enm(string) CHECK( ( @@ -83,4 +83,4 @@ CREATE TRIGGER iam_scope_update BEFORE update ON iam_scope FOR EACH ROW EXECUTE PROCEDURE iam_immutable_scope_type_func(); -COMMIT; \ No newline at end of file +COMMIT;