diff --git a/store/db/postgres/activity.go b/store/db/postgres/activity.go index 9b453927..11f0b334 100644 --- a/store/db/postgres/activity.go +++ b/store/db/postgres/activity.go @@ -2,7 +2,6 @@ package postgres import ( "context" - "time" "github.com/Masterminds/squirrel" "github.com/pkg/errors" @@ -35,7 +34,7 @@ func (d *DB) CreateActivity(ctx context.Context, create *store.Activity) (*store if create.CreatedTs != 0 { qb = qb.Columns("created_ts") - values = append(values, squirrel.Expr("TO_TIMESTAMP(?)", create.CreatedTs)) + values = append(values, create.CreatedTs) } qb = qb.Values(values...).Suffix("RETURNING id") @@ -60,7 +59,7 @@ func (d *DB) CreateActivity(ctx context.Context, create *store.Activity) (*store } func (d *DB) ListActivities(ctx context.Context, find *store.FindActivity) ([]*store.Activity, error) { - qb := squirrel.Select("id", "creator_id", "type", "level", "payload", "created_ts"). + qb := squirrel.Select("id", "created_ts", "creator_id", "type", "level", "payload"). From("activity"). Where("1 = 1"). PlaceholderFormat(squirrel.Dollar) @@ -87,20 +86,17 @@ func (d *DB) ListActivities(ctx context.Context, find *store.FindActivity) ([]*s for rows.Next() { activity := &store.Activity{} var payloadBytes []byte - createdTsPlaceHolder := time.Time{} if err := rows.Scan( &activity.ID, + &activity.CreatedTs, &activity.CreatorID, &activity.Type, &activity.Level, &payloadBytes, - &createdTsPlaceHolder, ); err != nil { return nil, err } - activity.CreatedTs = createdTsPlaceHolder.Unix() - payload := &storepb.ActivityPayload{} if err := protojson.Unmarshal(payloadBytes, payload); err != nil { return nil, err diff --git a/store/db/postgres/inbox.go b/store/db/postgres/inbox.go index 88463c7c..5decb3c9 100644 --- a/store/db/postgres/inbox.go +++ b/store/db/postgres/inbox.go @@ -2,7 +2,6 @@ package postgres import ( "context" - "time" "github.com/Masterminds/squirrel" "github.com/pkg/errors" @@ -76,13 +75,10 @@ func (d *DB) ListInboxes(ctx context.Context, find *store.FindInbox) ([]*store.I for rows.Next() { inbox := &store.Inbox{} var messageBytes []byte - createdTsPlaceHolder := time.Time{} - if err := rows.Scan(&inbox.ID, &createdTsPlaceHolder, &inbox.SenderID, &inbox.ReceiverID, &inbox.Status, &messageBytes); err != nil { + if err := rows.Scan(&inbox.ID, &inbox.CreatedTs, &inbox.SenderID, &inbox.ReceiverID, &inbox.Status, &messageBytes); err != nil { return nil, err } - inbox.CreatedTs = createdTsPlaceHolder.Unix() - message := &storepb.InboxMessage{} if err := protojsonUnmarshaler.Unmarshal(messageBytes, message); err != nil { return nil, err diff --git a/store/db/postgres/memo.go b/store/db/postgres/memo.go index 938e9962..cf5fd46a 100644 --- a/store/db/postgres/memo.go +++ b/store/db/postgres/memo.go @@ -3,7 +3,6 @@ package postgres import ( "context" "database/sql" - "encoding/binary" "fmt" "strings" @@ -30,12 +29,12 @@ func (d *DB) CreateMemo(ctx context.Context, create *store.Memo) (*store.Memo, e if create.CreatedTs != 0 { builder = builder.Columns("created_ts") - values = append(values, squirrel.Expr("to_timestamp(?)", create.CreatedTs)) + values = append(values, create.CreatedTs) } if create.UpdatedTs != 0 { builder = builder.Columns("updated_ts") - values = append(values, squirrel.Expr("to_timestamp(?)", create.UpdatedTs)) + values = append(values, create.UpdatedTs) } if create.RowStatus != "" { @@ -78,8 +77,8 @@ func (d *DB) ListMemos(ctx context.Context, find *store.FindMemo) ([]*store.Memo builder := squirrel.Select( "memo.id AS id", "memo.creator_id AS creator_id", - "EXTRACT(EPOCH FROM memo.created_ts) AS created_ts", - "EXTRACT(EPOCH FROM memo.updated_ts) AS updated_ts", + "memo.created_ts AS created_ts", + "memo.updated_ts AS updated_ts", "memo.row_status AS row_status", "memo.content AS content", "memo.visibility AS visibility", @@ -101,10 +100,10 @@ func (d *DB) ListMemos(ctx context.Context, find *store.FindMemo) ([]*store.Memo builder = builder.Where("memo.row_status = ?", *v) } if v := find.CreatedTsBefore; v != nil { - builder = builder.Where("EXTRACT(EPOCH FROM memo.created_ts) < ?", *v) + builder = builder.Where("memo.created_ts < ?", *v) } if v := find.CreatedTsAfter; v != nil { - builder = builder.Where("EXTRACT(EPOCH FROM memo.created_ts) > ?", *v) + builder = builder.Where("memo.created_ts > ?", *v) } if v := find.Pinned; v != nil { builder = builder.Where("memo_organizer.pinned = 1") @@ -158,14 +157,13 @@ func (d *DB) ListMemos(ctx context.Context, find *store.FindMemo) ([]*store.Memo // Process the result set list := make([]*store.Memo, 0) - updatedTsPlaceHolder, createdTsPlaceHolder := make([]uint8, 8), make([]uint8, 8) for rows.Next() { var memo store.Memo if err := rows.Scan( &memo.ID, &memo.CreatorID, - &createdTsPlaceHolder, - &updatedTsPlaceHolder, + &memo.CreatedTs, + &memo.UpdatedTs, &memo.RowStatus, &memo.Content, &memo.Visibility, @@ -174,10 +172,6 @@ func (d *DB) ListMemos(ctx context.Context, find *store.FindMemo) ([]*store.Memo return nil, err } - // Convert the timestamps from Postgres to Go - memo.CreatedTs = int64(binary.BigEndian.Uint64(createdTsPlaceHolder)) - memo.UpdatedTs = int64(binary.BigEndian.Uint64(updatedTsPlaceHolder)) - list = append(list, &memo) } @@ -209,10 +203,10 @@ func (d *DB) UpdateMemo(ctx context.Context, update *store.UpdateMemo) error { // Conditionally add set clauses if v := update.CreatedTs; v != nil { - builder = builder.Set("created_ts", squirrel.Expr("to_timestamp(?)", *v)) + builder = builder.Set("created_ts", *v) } if v := update.UpdatedTs; v != nil { - builder = builder.Set("updated_ts", squirrel.Expr("to_timestamp(?)", *v)) + builder = builder.Set("updated_ts", *v) } if v := update.RowStatus; v != nil { builder = builder.Set("row_status", *v) diff --git a/store/db/postgres/migration/dev/LATEST__SCHEMA.sql b/store/db/postgres/migration/dev/LATEST__SCHEMA.sql index 1a52b493..8d62b0e2 100644 --- a/store/db/postgres/migration/dev/LATEST__SCHEMA.sql +++ b/store/db/postgres/migration/dev/LATEST__SCHEMA.sql @@ -17,7 +17,7 @@ DROP TABLE IF EXISTS webhook CASCADE; -- migration_history CREATE TABLE migration_history ( version TEXT NOT NULL PRIMARY KEY, - created_ts TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP + created_ts BIGINT NOT NULL DEFAULT EXTRACT(EPOCH FROM NOW()) ); -- system_setting @@ -30,8 +30,8 @@ CREATE TABLE system_setting ( -- user CREATE TABLE "user" ( id SERIAL PRIMARY KEY, - created_ts TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, - updated_ts TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, + created_ts BIGINT NOT NULL DEFAULT EXTRACT(EPOCH FROM NOW()), + updated_ts BIGINT NOT NULL DEFAULT EXTRACT(EPOCH FROM NOW()), row_status TEXT NOT NULL DEFAULT 'NORMAL', username TEXT NOT NULL UNIQUE, role TEXT NOT NULL DEFAULT 'USER', @@ -53,8 +53,8 @@ CREATE TABLE user_setting ( CREATE TABLE memo ( id SERIAL PRIMARY KEY, creator_id INTEGER NOT NULL, - created_ts TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, - updated_ts TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, + created_ts BIGINT NOT NULL DEFAULT EXTRACT(EPOCH FROM NOW()), + updated_ts BIGINT NOT NULL DEFAULT EXTRACT(EPOCH FROM NOW()), row_status TEXT NOT NULL DEFAULT 'NORMAL', content TEXT NOT NULL, visibility TEXT NOT NULL DEFAULT 'PRIVATE' @@ -80,8 +80,8 @@ CREATE TABLE memo_relation ( CREATE TABLE resource ( id SERIAL PRIMARY KEY, creator_id INTEGER NOT NULL, - created_ts TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, - updated_ts TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, + created_ts BIGINT NOT NULL DEFAULT EXTRACT(EPOCH FROM NOW()), + updated_ts BIGINT NOT NULL DEFAULT EXTRACT(EPOCH FROM NOW()), filename TEXT NOT NULL, blob BYTEA, external_link TEXT NOT NULL, @@ -102,7 +102,7 @@ CREATE TABLE tag ( CREATE TABLE activity ( id SERIAL PRIMARY KEY, creator_id INTEGER NOT NULL, - created_ts TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, + created_ts BIGINT NOT NULL DEFAULT EXTRACT(EPOCH FROM NOW()), type TEXT NOT NULL DEFAULT '', level TEXT NOT NULL DEFAULT 'INFO', payload JSONB NOT NULL DEFAULT '{}' @@ -128,7 +128,7 @@ CREATE TABLE idp ( -- inbox CREATE TABLE inbox ( id SERIAL PRIMARY KEY, - created_ts TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, + created_ts BIGINT NOT NULL DEFAULT EXTRACT(EPOCH FROM NOW()), sender_id INTEGER NOT NULL, receiver_id INTEGER NOT NULL, status TEXT NOT NULL, @@ -138,8 +138,8 @@ CREATE TABLE inbox ( -- webhook CREATE TABLE webhook ( id SERIAL PRIMARY KEY, - created_ts TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, - updated_ts TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, + created_ts BIGINT NOT NULL DEFAULT EXTRACT(EPOCH FROM NOW()), + updated_ts BIGINT NOT NULL DEFAULT EXTRACT(EPOCH FROM NOW()), row_status TEXT NOT NULL DEFAULT 'NORMAL', creator_id INTEGER NOT NULL, name TEXT NOT NULL, diff --git a/store/db/postgres/migration/prod/LATEST__SCHEMA.sql b/store/db/postgres/migration/prod/LATEST__SCHEMA.sql index 1a52b493..8d62b0e2 100644 --- a/store/db/postgres/migration/prod/LATEST__SCHEMA.sql +++ b/store/db/postgres/migration/prod/LATEST__SCHEMA.sql @@ -17,7 +17,7 @@ DROP TABLE IF EXISTS webhook CASCADE; -- migration_history CREATE TABLE migration_history ( version TEXT NOT NULL PRIMARY KEY, - created_ts TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP + created_ts BIGINT NOT NULL DEFAULT EXTRACT(EPOCH FROM NOW()) ); -- system_setting @@ -30,8 +30,8 @@ CREATE TABLE system_setting ( -- user CREATE TABLE "user" ( id SERIAL PRIMARY KEY, - created_ts TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, - updated_ts TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, + created_ts BIGINT NOT NULL DEFAULT EXTRACT(EPOCH FROM NOW()), + updated_ts BIGINT NOT NULL DEFAULT EXTRACT(EPOCH FROM NOW()), row_status TEXT NOT NULL DEFAULT 'NORMAL', username TEXT NOT NULL UNIQUE, role TEXT NOT NULL DEFAULT 'USER', @@ -53,8 +53,8 @@ CREATE TABLE user_setting ( CREATE TABLE memo ( id SERIAL PRIMARY KEY, creator_id INTEGER NOT NULL, - created_ts TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, - updated_ts TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, + created_ts BIGINT NOT NULL DEFAULT EXTRACT(EPOCH FROM NOW()), + updated_ts BIGINT NOT NULL DEFAULT EXTRACT(EPOCH FROM NOW()), row_status TEXT NOT NULL DEFAULT 'NORMAL', content TEXT NOT NULL, visibility TEXT NOT NULL DEFAULT 'PRIVATE' @@ -80,8 +80,8 @@ CREATE TABLE memo_relation ( CREATE TABLE resource ( id SERIAL PRIMARY KEY, creator_id INTEGER NOT NULL, - created_ts TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, - updated_ts TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, + created_ts BIGINT NOT NULL DEFAULT EXTRACT(EPOCH FROM NOW()), + updated_ts BIGINT NOT NULL DEFAULT EXTRACT(EPOCH FROM NOW()), filename TEXT NOT NULL, blob BYTEA, external_link TEXT NOT NULL, @@ -102,7 +102,7 @@ CREATE TABLE tag ( CREATE TABLE activity ( id SERIAL PRIMARY KEY, creator_id INTEGER NOT NULL, - created_ts TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, + created_ts BIGINT NOT NULL DEFAULT EXTRACT(EPOCH FROM NOW()), type TEXT NOT NULL DEFAULT '', level TEXT NOT NULL DEFAULT 'INFO', payload JSONB NOT NULL DEFAULT '{}' @@ -128,7 +128,7 @@ CREATE TABLE idp ( -- inbox CREATE TABLE inbox ( id SERIAL PRIMARY KEY, - created_ts TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, + created_ts BIGINT NOT NULL DEFAULT EXTRACT(EPOCH FROM NOW()), sender_id INTEGER NOT NULL, receiver_id INTEGER NOT NULL, status TEXT NOT NULL, @@ -138,8 +138,8 @@ CREATE TABLE inbox ( -- webhook CREATE TABLE webhook ( id SERIAL PRIMARY KEY, - created_ts TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, - updated_ts TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, + created_ts BIGINT NOT NULL DEFAULT EXTRACT(EPOCH FROM NOW()), + updated_ts BIGINT NOT NULL DEFAULT EXTRACT(EPOCH FROM NOW()), row_status TEXT NOT NULL DEFAULT 'NORMAL', creator_id INTEGER NOT NULL, name TEXT NOT NULL, diff --git a/store/db/postgres/migration_history.go b/store/db/postgres/migration_history.go index 1a7d2039..83279ec8 100644 --- a/store/db/postgres/migration_history.go +++ b/store/db/postgres/migration_history.go @@ -2,7 +2,6 @@ package postgres import ( "context" - "time" "github.com/Masterminds/squirrel" @@ -28,11 +27,9 @@ func (d *DB) FindMigrationHistoryList(ctx context.Context, _ *store.FindMigratio list := make([]*store.MigrationHistory, 0) for rows.Next() { var migrationHistory store.MigrationHistory - var createdTs time.Time - if err := rows.Scan(&migrationHistory.Version, &createdTs); err != nil { + if err := rows.Scan(&migrationHistory.Version, &migrationHistory.CreatedTs); err != nil { return nil, err } - migrationHistory.CreatedTs = createdTs.UnixNano() list = append(list, &migrationHistory) } @@ -60,7 +57,6 @@ func (d *DB) UpsertMigrationHistory(ctx context.Context, upsert *store.UpsertMig } var migrationHistory store.MigrationHistory - var createdTs time.Time query, args, err = squirrel.Select("version", "created_ts"). From("migration_history"). Where(squirrel.Eq{"version": upsert.Version}). @@ -70,10 +66,9 @@ func (d *DB) UpsertMigrationHistory(ctx context.Context, upsert *store.UpsertMig return nil, err } - if err := d.db.QueryRowContext(ctx, query, args...).Scan(&migrationHistory.Version, &createdTs); err != nil { + if err := d.db.QueryRowContext(ctx, query, args...).Scan(&migrationHistory.Version, &migrationHistory.CreatedTs); err != nil { return nil, err } - migrationHistory.CreatedTs = createdTs.UnixNano() return &migrationHistory, nil } diff --git a/store/db/postgres/resource.go b/store/db/postgres/resource.go index 802c104c..d1db73f1 100644 --- a/store/db/postgres/resource.go +++ b/store/db/postgres/resource.go @@ -23,12 +23,12 @@ func (d *DB) CreateResource(ctx context.Context, create *store.Resource) (*store if create.CreatedTs != 0 { qb = qb.Columns("created_ts") - values = append(values, time.Unix(0, create.CreatedTs)) + values = append(values, create.CreatedTs) } if create.UpdatedTs != 0 { qb = qb.Columns("updated_ts") - values = append(values, time.Unix(0, create.UpdatedTs)) + values = append(values, create.UpdatedTs) } if create.MemoID != nil { @@ -105,7 +105,6 @@ func (d *DB) ListResources(ctx context.Context, find *store.FindResource) ([]*st for rows.Next() { resource := store.Resource{} var memoID sql.NullInt32 - var createdTs, updatedTs time.Time dests := []any{ &resource.ID, &resource.Filename, @@ -113,8 +112,8 @@ func (d *DB) ListResources(ctx context.Context, find *store.FindResource) ([]*st &resource.Type, &resource.Size, &resource.CreatorID, - &createdTs, - &updatedTs, + &resource.CreatedTs, + &resource.UpdatedTs, &resource.InternalPath, &memoID, } @@ -125,9 +124,6 @@ func (d *DB) ListResources(ctx context.Context, find *store.FindResource) ([]*st return nil, err } - resource.CreatedTs = createdTs.UnixNano() - resource.UpdatedTs = updatedTs.UnixNano() - if memoID.Valid { resource.MemoID = &memoID.Int32 } diff --git a/store/db/postgres/user.go b/store/db/postgres/user.go index d6553a77..b301cb48 100644 --- a/store/db/postgres/user.go +++ b/store/db/postgres/user.go @@ -11,7 +11,7 @@ import ( func (d *DB) CreateUser(ctx context.Context, create *store.User) (*store.User, error) { // Start building the insert statement - builder := squirrel.Insert("\"user\"").PlaceholderFormat(squirrel.Dollar) + builder := squirrel.Insert(`"user"`).PlaceholderFormat(squirrel.Dollar) columns := []string{"username", "role", "email", "nickname", "password_hash", "avatar_url"} builder = builder.Columns(columns...) @@ -25,12 +25,12 @@ func (d *DB) CreateUser(ctx context.Context, create *store.User) (*store.User, e if create.CreatedTs != 0 { builder = builder.Columns("created_ts") - values = append(values, squirrel.Expr("TO_TIMESTAMP(?)", create.CreatedTs)) + values = append(values, create.CreatedTs) } if create.UpdatedTs != 0 { builder = builder.Columns("updated_ts") - values = append(values, squirrel.Expr("TO_TIMESTAMP(?)", create.UpdatedTs)) + values = append(values, create.UpdatedTs) } if create.ID != 0 { @@ -66,7 +66,7 @@ func (d *DB) CreateUser(ctx context.Context, create *store.User) (*store.User, e func (d *DB) UpdateUser(ctx context.Context, update *store.UpdateUser) (*store.User, error) { // Start building the update statement - builder := squirrel.Update("\"user\"").PlaceholderFormat(squirrel.Dollar) + builder := squirrel.Update(`"user"`).PlaceholderFormat(squirrel.Dollar) // Conditionally add set clauses if v := update.UpdatedTs; v != nil { @@ -115,9 +115,8 @@ func (d *DB) UpdateUser(ctx context.Context, update *store.UpdateUser) (*store.U func (d *DB) ListUsers(ctx context.Context, find *store.FindUser) ([]*store.User, error) { // Start building the SELECT statement - builder := squirrel.Select("id", "username", "role", "email", "nickname", "password_hash", "avatar_url", - "FLOOR(EXTRACT(EPOCH FROM created_ts)) AS created_ts", "FLOOR(EXTRACT(EPOCH FROM updated_ts)) AS updated_ts", "row_status"). - From("\"user\""). + builder := squirrel.Select("id", "username", "role", "email", "nickname", "password_hash", "avatar_url", "created_ts", "updated_ts", "row_status"). + From(`"user"`). PlaceholderFormat(squirrel.Dollar) // 1 = 1 is often used as a no-op in SQL, ensuring there's always a WHERE clause @@ -196,7 +195,7 @@ func (d *DB) GetUser(ctx context.Context, find *store.FindUser) (*store.User, er func (d *DB) DeleteUser(ctx context.Context, delete *store.DeleteUser) error { // Start building the DELETE statement - builder := squirrel.Delete("\"user\""). + builder := squirrel.Delete(`"user"`). PlaceholderFormat(squirrel.Dollar). Where(squirrel.Eq{"id": delete.ID}) diff --git a/store/db/postgres/webhook.go b/store/db/postgres/webhook.go index 38d2e2b9..6ebb7c09 100644 --- a/store/db/postgres/webhook.go +++ b/store/db/postgres/webhook.go @@ -2,7 +2,6 @@ package postgres import ( "context" - "time" "github.com/Masterminds/squirrel" @@ -63,12 +62,10 @@ func (d *DB) ListWebhooks(ctx context.Context, find *store.FindWebhook) ([]*stor for rows.Next() { webhook := &storepb.Webhook{} var rowStatus string - var createdTs, updatedTs time.Time - if err := rows.Scan( &webhook.Id, - &createdTs, - &updatedTs, + &webhook.CreatedTs, + &webhook.UpdatedTs, &rowStatus, &webhook.CreatorId, &webhook.Name, @@ -77,8 +74,6 @@ func (d *DB) ListWebhooks(ctx context.Context, find *store.FindWebhook) ([]*stor return nil, err } - webhook.CreatedTs = createdTs.UnixNano() - webhook.UpdatedTs = updatedTs.UnixNano() webhook.RowStatus = storepb.RowStatus(storepb.RowStatus_value[rowStatus]) list = append(list, webhook)