From 573517565da10993ae9d3fad643eafaee983adaf Mon Sep 17 00:00:00 2001 From: Leon Mika Date: Sun, 16 Feb 2025 14:06:45 +1100 Subject: [PATCH] Made some changes to how index pages are made --- gen/sqlc/dbq/bundles.sql.go | 35 +++++++++++++++++++++++ gen/sqlc/dbq/models.go | 48 +++++++++++++++++++++++++++++-- gen/sqlc/dbq/pages.sql.go | 45 +++++++++++++++++------------ gen/sqlc/dbq/posts.sql.go | 12 ++++---- models/{bundle.go => page.go} | 16 ++++++++++- providers/db/bundles.go | 15 ++++++++++ providers/db/page.go | 9 ++++++ services/pages/services.go | 2 +- services/sitebuilder/pages.go | 54 +++++++++++++++++++++++++++++++---- services/sitebuilder/posts.go | 32 +++++++++++++++++---- services/sites/create.go | 1 + sql/queries/bundles.sql | 10 ++++++- sql/queries/pages.sql | 20 +++++++------ sql/schema/1_init.up.sql | 16 +++++++---- 14 files changed, 259 insertions(+), 56 deletions(-) rename models/{bundle.go => page.go} (78%) diff --git a/gen/sqlc/dbq/bundles.sql.go b/gen/sqlc/dbq/bundles.sql.go index d6f11d8..d98eb37 100644 --- a/gen/sqlc/dbq/bundles.sql.go +++ b/gen/sqlc/dbq/bundles.sql.go @@ -28,6 +28,41 @@ func (q *Queries) GetBundleWithID(ctx context.Context, id int64) (Bundle, error) return i, err } +const getSiteBundleInfo = `-- name: GetSiteBundleInfo :many +WITH page_counts AS ( + SELECT b.bundle_id, count(*) AS page_count FROM pages b WHERE b.site_id = $1 GROUP BY bundle_id +), index_pages AS ( + SELECT p.id AS index_page_id, p.bundle_id FROM pages p WHERE p.site_id = $1 AND p.role = 'index' +) +SELECT b.bundle_id, b.page_count, p.index_page_id FROM page_counts b LEFT OUTER JOIN index_pages p ON b.bundle_id = p.bundle_id +` + +type GetSiteBundleInfoRow struct { + BundleID int64 + PageCount int64 + IndexPageID pgtype.Int8 +} + +func (q *Queries) GetSiteBundleInfo(ctx context.Context, siteID int64) ([]GetSiteBundleInfoRow, error) { + rows, err := q.db.Query(ctx, getSiteBundleInfo, siteID) + if err != nil { + return nil, err + } + defer rows.Close() + var items []GetSiteBundleInfoRow + for rows.Next() { + var i GetSiteBundleInfoRow + if err := rows.Scan(&i.BundleID, &i.PageCount, &i.IndexPageID); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + const insertBundle = `-- name: InsertBundle :one INSERT INTO bundles ( site_id, diff --git a/gen/sqlc/dbq/models.go b/gen/sqlc/dbq/models.go index 9a3d13b..e027f2d 100644 --- a/gen/sqlc/dbq/models.go +++ b/gen/sqlc/dbq/models.go @@ -54,6 +54,47 @@ func (ns NullPageNameProvenance) Value() (driver.Value, error) { return string(ns.PageNameProvenance), nil } +type PageRole string + +const ( + PageRoleIndex PageRole = "index" +) + +func (e *PageRole) Scan(src interface{}) error { + switch s := src.(type) { + case []byte: + *e = PageRole(s) + case string: + *e = PageRole(s) + default: + return fmt.Errorf("unsupported scan type for PageRole: %T", src) + } + return nil +} + +type NullPageRole struct { + PageRole PageRole + Valid bool // Valid is true if PageRole is not NULL +} + +// Scan implements the Scanner interface. +func (ns *NullPageRole) Scan(value interface{}) error { + if value == nil { + ns.PageRole, ns.Valid = "", false + return nil + } + ns.Valid = true + return ns.PageRole.Scan(value) +} + +// Value implements the driver Valuer interface. +func (ns NullPageRole) Value() (driver.Value, error) { + if !ns.Valid { + return nil, nil + } + return string(ns.PageRole), nil +} + type PostState string const ( @@ -193,10 +234,11 @@ type Page struct { Name string NameProvenance PageNameProvenance Title pgtype.Text - Role pgtype.Int8 + PostTypeID pgtype.Int8 Body string State PostState Props []byte + Role NullPageRole PublishDate pgtype.Timestamptz CreatedAt pgtype.Timestamp UpdatedAt pgtype.Timestamp @@ -206,7 +248,7 @@ type Post struct { ID int64 SiteID int64 Title pgtype.Text - Role pgtype.Int8 + PostTypeID pgtype.Int8 Body string State PostState Props []byte @@ -215,7 +257,7 @@ type Post struct { UpdatedAt pgtype.Timestamp } -type PostRole struct { +type PostType struct { ID int64 SiteID int64 LayoutName string diff --git a/gen/sqlc/dbq/pages.sql.go b/gen/sqlc/dbq/pages.sql.go index 20d4023..89c3376 100644 --- a/gen/sqlc/dbq/pages.sql.go +++ b/gen/sqlc/dbq/pages.sql.go @@ -21,7 +21,7 @@ func (q *Queries) DeletePageWithID(ctx context.Context, id int64) error { } const getPageWithID = `-- name: GetPageWithID :one -SELECT id, site_id, bundle_id, name, name_provenance, title, role, body, state, props, publish_date, created_at, updated_at FROM pages WHERE id = $1 +SELECT id, site_id, bundle_id, name, name_provenance, title, post_type_id, body, state, props, role, publish_date, created_at, updated_at FROM pages WHERE id = $1 ` func (q *Queries) GetPageWithID(ctx context.Context, id int64) (Page, error) { @@ -34,10 +34,11 @@ func (q *Queries) GetPageWithID(ctx context.Context, id int64) (Page, error) { &i.Name, &i.NameProvenance, &i.Title, - &i.Role, + &i.PostTypeID, &i.Body, &i.State, &i.Props, + &i.Role, &i.PublishDate, &i.CreatedAt, &i.UpdatedAt, @@ -52,14 +53,15 @@ INSERT INTO pages ( name, name_provenance, title, - role, + post_type_id, body, state, props, + role, publish_date, created_at, updated_at -) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $11) +) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $12) RETURNING id ` @@ -69,10 +71,11 @@ type InsertPageParams struct { Name string NameProvenance PageNameProvenance Title pgtype.Text - Role pgtype.Int8 + PostTypeID pgtype.Int8 Body string State PostState Props []byte + Role NullPageRole PublishDate pgtype.Timestamptz CreatedAt pgtype.Timestamp } @@ -84,10 +87,11 @@ func (q *Queries) InsertPage(ctx context.Context, arg InsertPageParams) (int64, arg.Name, arg.NameProvenance, arg.Title, - arg.Role, + arg.PostTypeID, arg.Body, arg.State, arg.Props, + arg.Role, arg.PublishDate, arg.CreatedAt, ) @@ -97,7 +101,7 @@ func (q *Queries) InsertPage(ctx context.Context, arg InsertPageParams) (int64, } const listPages = `-- name: ListPages :many -SELECT id, site_id, bundle_id, name, name_provenance, title, role, body, state, props, publish_date, created_at, updated_at FROM pages WHERE site_id = $1 ORDER BY name ASC LIMIT 25 +SELECT id, site_id, bundle_id, name, name_provenance, title, post_type_id, body, state, props, role, publish_date, created_at, updated_at FROM pages WHERE site_id = $1 ORDER BY name ASC LIMIT 25 ` func (q *Queries) ListPages(ctx context.Context, siteID int64) ([]Page, error) { @@ -116,10 +120,11 @@ func (q *Queries) ListPages(ctx context.Context, siteID int64) ([]Page, error) { &i.Name, &i.NameProvenance, &i.Title, - &i.Role, + &i.PostTypeID, &i.Body, &i.State, &i.Props, + &i.Role, &i.PublishDate, &i.CreatedAt, &i.UpdatedAt, @@ -135,7 +140,7 @@ func (q *Queries) ListPages(ctx context.Context, siteID int64) ([]Page, error) { } const listPublishablePages = `-- name: ListPublishablePages :many -SELECT id, site_id, bundle_id, name, name_provenance, title, role, body, state, props, publish_date, created_at, updated_at +SELECT id, site_id, bundle_id, name, name_provenance, title, post_type_id, body, state, props, role, publish_date, created_at, updated_at FROM pages WHERE id > $1 AND site_id = $2 AND state = 'published' ORDER BY id LIMIT 100 @@ -162,10 +167,11 @@ func (q *Queries) ListPublishablePages(ctx context.Context, arg ListPublishableP &i.Name, &i.NameProvenance, &i.Title, - &i.Role, + &i.PostTypeID, &i.Body, &i.State, &i.Props, + &i.Role, &i.PublishDate, &i.CreatedAt, &i.UpdatedAt, @@ -187,13 +193,14 @@ UPDATE pages SET name = $4, name_provenance = $5, title = $6, - role = $7, - body = $8, - state = $9, - props = $10, - publish_date = $11, - created_at = $12, - updated_at = $13 + post_type_id = $7, + role = $8, + body = $9, + state = $10, + props = $11, + publish_date = $12, + created_at = $13, + updated_at = $14 WHERE id = $1 ` @@ -204,7 +211,8 @@ type UpdatePageParams struct { Name string NameProvenance PageNameProvenance Title pgtype.Text - Role pgtype.Int8 + PostTypeID pgtype.Int8 + Role NullPageRole Body string State PostState Props []byte @@ -221,6 +229,7 @@ func (q *Queries) UpdatePage(ctx context.Context, arg UpdatePageParams) error { arg.Name, arg.NameProvenance, arg.Title, + arg.PostTypeID, arg.Role, arg.Body, arg.State, diff --git a/gen/sqlc/dbq/posts.sql.go b/gen/sqlc/dbq/posts.sql.go index 2f55e3a..0500cce 100644 --- a/gen/sqlc/dbq/posts.sql.go +++ b/gen/sqlc/dbq/posts.sql.go @@ -21,7 +21,7 @@ func (q *Queries) DeletePost(ctx context.Context, id int64) error { } const getPostWithID = `-- name: GetPostWithID :one -SELECT id, site_id, title, role, body, state, props, publish_date, created_at, updated_at FROM posts WHERE id = $1 LIMIT 1 +SELECT id, site_id, title, post_type_id, body, state, props, publish_date, created_at, updated_at FROM posts WHERE id = $1 LIMIT 1 ` func (q *Queries) GetPostWithID(ctx context.Context, id int64) (Post, error) { @@ -31,7 +31,7 @@ func (q *Queries) GetPostWithID(ctx context.Context, id int64) (Post, error) { &i.ID, &i.SiteID, &i.Title, - &i.Role, + &i.PostTypeID, &i.Body, &i.State, &i.Props, @@ -84,7 +84,7 @@ func (q *Queries) InsertPost(ctx context.Context, arg InsertPostParams) (int64, } const listPosts = `-- name: ListPosts :many -SELECT id, site_id, title, role, body, state, props, publish_date, created_at, updated_at FROM posts WHERE site_id = $1 ORDER BY publish_date DESC LIMIT 25 +SELECT id, site_id, title, post_type_id, body, state, props, publish_date, created_at, updated_at FROM posts WHERE site_id = $1 ORDER BY publish_date DESC LIMIT 25 ` func (q *Queries) ListPosts(ctx context.Context, siteID int64) ([]Post, error) { @@ -100,7 +100,7 @@ func (q *Queries) ListPosts(ctx context.Context, siteID int64) ([]Post, error) { &i.ID, &i.SiteID, &i.Title, - &i.Role, + &i.PostTypeID, &i.Body, &i.State, &i.Props, @@ -119,7 +119,7 @@ func (q *Queries) ListPosts(ctx context.Context, siteID int64) ([]Post, error) { } const listPublishablePosts = `-- name: ListPublishablePosts :many -SELECT id, site_id, title, role, body, state, props, publish_date, created_at, updated_at +SELECT id, site_id, title, post_type_id, body, state, props, publish_date, created_at, updated_at FROM posts WHERE id > $1 AND site_id = $2 AND state = 'published' AND publish_date <= $3 ORDER BY id LIMIT 100 @@ -144,7 +144,7 @@ func (q *Queries) ListPublishablePosts(ctx context.Context, arg ListPublishableP &i.ID, &i.SiteID, &i.Title, - &i.Role, + &i.PostTypeID, &i.Body, &i.State, &i.Props, diff --git a/models/bundle.go b/models/page.go similarity index 78% rename from models/bundle.go rename to models/page.go index 2d6a1b1..d0bb592 100644 --- a/models/bundle.go +++ b/models/page.go @@ -15,6 +15,13 @@ const ( DateNameProvenance NameProvenance = iota ) +type PageRole int + +const ( + NormalPageRole PageRole = iota + IndexPageRole +) + type Bundle struct { ID int64 SiteID int64 @@ -30,11 +37,18 @@ type Page struct { Name string NameProvenance NameProvenance Title string - Role int64 + Role PageRole Body string State PostState + PageTypeID int64 Props []byte PublishDate time.Time CreatedAt time.Time UpdatedAt time.Time } + +type BundleInfo struct { + BundleID int64 + PageCount int + IndexPageID int64 +} diff --git a/providers/db/bundles.go b/providers/db/bundles.go index 5b724c1..730a29e 100644 --- a/providers/db/bundles.go +++ b/providers/db/bundles.go @@ -5,6 +5,7 @@ import ( "github.com/jackc/pgx/v5/pgtype" "lmika.dev/lmika/hugo-cms/gen/sqlc/dbq" "lmika.dev/lmika/hugo-cms/models" + "lmika.dev/pkg/modash/momap" "lmika.dev/pkg/modash/moslice" ) @@ -39,6 +40,20 @@ func (db *DB) GetBundleWithID(ctx context.Context, id int64) (models.Bundle, err return dbBundleToBundle(res), nil } +func (db *DB) GetSiteBundleInfo(ctx context.Context, siteID int64) (map[int64]models.BundleInfo, error) { + res, err := db.q.GetSiteBundleInfo(ctx, siteID) + if err != nil { + return nil, err + } + return momap.FromSlice(res, func(bi dbq.GetSiteBundleInfoRow) (int64, models.BundleInfo) { + return bi.BundleID, models.BundleInfo{ + BundleID: bi.BundleID, + PageCount: int(bi.PageCount), + IndexPageID: bi.IndexPageID.Int64, + } + }), nil +} + func dbBundleToBundle(b dbq.Bundle) models.Bundle { return models.Bundle{ ID: b.ID, diff --git a/providers/db/page.go b/providers/db/page.go index 4b209d4..788e157 100644 --- a/providers/db/page.go +++ b/providers/db/page.go @@ -16,6 +16,12 @@ var nameProvenanceToDBNameProvenance = map[models.NameProvenance]dbq.PageNamePro } var dbNameProvenanceToNameProvenance = momap.ReverseMap(nameProvenanceToDBNameProvenance) +var pageRoleToDBPageRole = map[models.PageRole]dbq.NullPageRole{ + models.NormalPageRole: {}, + models.IndexPageRole: {PageRole: dbq.PageRoleIndex, Valid: true}, +} +var dbPageRoleToPageRole = momap.ReverseMap(pageRoleToDBPageRole) + func (db *DB) InsertPage(ctx context.Context, page *models.Page) error { id, err := db.q.InsertPage(ctx, dbq.InsertPageParams{ @@ -23,6 +29,7 @@ func (db *DB) InsertPage(ctx context.Context, page *models.Page) error { BundleID: page.BundleID, Name: page.Name, NameProvenance: nameProvenanceToDBNameProvenance[page.NameProvenance], + Role: pageRoleToDBPageRole[page.Role], Title: pgtype.Text{String: page.Title, Valid: page.Title != ""}, Body: page.Body, State: dbq.PostState(page.State), @@ -43,6 +50,7 @@ func (db *DB) UpdatePage(ctx context.Context, page *models.Page) error { SiteID: page.SiteID, BundleID: page.BundleID, Name: page.Name, + Role: pageRoleToDBPageRole[page.Role], NameProvenance: nameProvenanceToDBNameProvenance[page.NameProvenance], Title: pgtype.Text{String: page.Title, Valid: page.Title != ""}, Body: page.Body, @@ -95,6 +103,7 @@ func dbPageToPage(p dbq.Page) models.Page { SiteID: p.SiteID, BundleID: p.BundleID, Name: p.Name, + Role: dbPageRoleToPageRole[p.Role], NameProvenance: dbNameProvenanceToNameProvenance[p.NameProvenance], Title: p.Title.String, Body: p.Body, diff --git a/services/pages/services.go b/services/pages/services.go index 82df64d..c289946 100644 --- a/services/pages/services.go +++ b/services/pages/services.go @@ -85,7 +85,7 @@ func (s *Service) Create(ctx context.Context, site models.Site, req NewPost) (mo post := models.Page{ SiteID: site.ID, BundleID: rootBundle.ID, - Name: s.normalizePageName(req.Title), + Name: name, NameProvenance: nameProvenance, Title: req.Title, Body: req.Body, diff --git a/services/sitebuilder/pages.go b/services/sitebuilder/pages.go index f551d76..7acb5a6 100644 --- a/services/sitebuilder/pages.go +++ b/services/sitebuilder/pages.go @@ -27,7 +27,17 @@ func (s *Service) WritePage(site models.Site, bundle models.Bundle, page models. return fmt.Errorf("theme %s not found in themes", site.Theme) } - if err := s.writePage(site, themeMeta, bundle, page); err != nil { + bundleInfo, err := s.db.GetSiteBundleInfo(ctx, site.ID) + if err != nil { + return err + } + + if err := s.writePage(pageBuildInfo{ + site: site, + themeMeta: themeMeta, + bundle: bundle, + bundleInfo: bundleInfo, + }, page); err != nil { return err } return s.publish(ctx, site) @@ -45,8 +55,23 @@ func (s *Service) DeletePage(site models.Site, page models.Page) models.Job { if err != nil { return err } + + themeMeta, ok := s.themes.Lookup(site.Theme) + if !ok { + return fmt.Errorf("theme %s not found in themes", site.Theme) + } - postFilename := s.pageFilename(site, bundle, page) + bundleInfo, err := s.db.GetSiteBundleInfo(ctx, site.ID) + if err != nil { + return err + } + + postFilename := s.pageFilename(pageBuildInfo{ + site: site, + themeMeta: themeMeta, + bundle: bundle, + bundleInfo: bundleInfo, + }, page) if os.Remove(postFilename) != nil { return nil @@ -71,6 +96,11 @@ func (s *Service) writeAllPages(ctx context.Context, site models.Site) error { bundlesByID := momap.FromSlice(bundles, func(b models.Bundle) (int64, models.Bundle) { return b.ID, b }) + bundleInfo, err := s.db.GetSiteBundleInfo(ctx, site.ID) + if err != nil { + return err + } + var startId int64 for { pages, err := s.db.ListPublishablePages(ctx, int64(startId), site.ID) @@ -81,7 +111,12 @@ func (s *Service) writeAllPages(ctx context.Context, site models.Site) error { } for _, page := range pages { - if err := s.writePage(site, themeMeta, bundlesByID[page.BundleID], page); err != nil { + if err := s.writePage(pageBuildInfo{ + site: site, + themeMeta: themeMeta, + bundle: bundlesByID[page.BundleID], + bundleInfo: bundleInfo, + }, page); err != nil { return err } } @@ -89,17 +124,24 @@ func (s *Service) writeAllPages(ctx context.Context, site models.Site) error { } } -func (s *Service) writePage(site models.Site, themeMeta models.ThemeMeta, bundle models.Bundle, page models.Page) error { - postFilename := s.pageFilename(site, bundle, page) +func (s *Service) writePage(bi pageBuildInfo, page models.Page) error { + postFilename := s.pageFilename(bi, page) frontMatter := map[string]any{ "date": page.PublishDate.Format(time.RFC3339), } if page.Title != "" { frontMatter["title"] = page.Title - } else if themeMeta.PreferTitle { + } else if bi.themeMeta.PreferTitle { frontMatter["title"] = page.PublishDate.Format(time.ANSIC) } return s.writeMarkdownFile(postFilename, frontMatter, page.Body) } + +type pageBuildInfo struct { + site models.Site + themeMeta models.ThemeMeta + bundle models.Bundle + bundleInfo map[int64]models.BundleInfo +} diff --git a/services/sitebuilder/posts.go b/services/sitebuilder/posts.go index 9789092..52a5d17 100644 --- a/services/sitebuilder/posts.go +++ b/services/sitebuilder/posts.go @@ -151,12 +151,32 @@ func (s *Service) postFilename(site models.Site, themeMeta models.ThemeMeta, pos return filepath.Join(s.hugo.SiteStagingDir(site, hugo.ContentSiteDir), themeMeta.BlogPostBundle, post.CreatedAt.Format("2006-01-02-150405.md")) } -func (s *Service) pageFilename(site models.Site, bundle models.Bundle, page models.Page) string { - bundleDir := "" - if bundle.Name != models.RootBundleName { - bundleDir = bundle.Name +func (s *Service) pageFilename(bi pageBuildInfo, page models.Page) string { + isIndex := false + isLeafBundle := true + + thisBundleInfo := bi.bundleInfo[bi.bundle.ID] + if thisBundleInfo.PageCount > 1 { + isLeafBundle = false + isIndex = thisBundleInfo.IndexPageID == page.ID + } else { + isIndex = true } - pageName := page.Name + ".md" - return filepath.Join(s.hugo.SiteStagingDir(site, hugo.ContentSiteDir), bundleDir, pageName) + bundleDir := "" + if bi.bundle.Name != models.RootBundleName { + bundleDir = bi.bundle.Name + } + + pageName := page.Name + if isIndex { + if isLeafBundle { + pageName = "index" + } else { + pageName = "_index" + } + } + + pageName += ".md" + return filepath.Join(s.hugo.SiteStagingDir(bi.site, hugo.ContentSiteDir), bundleDir, pageName) } diff --git a/services/sites/create.go b/services/sites/create.go index b8a679d..4c3cb31 100644 --- a/services/sites/create.go +++ b/services/sites/create.go @@ -43,6 +43,7 @@ func (s *Service) CreateSite(ctx context.Context, user models.User, name string) Title: "Welcome to the home page", Body: "This is the home page", State: models.PostStatePublished, + Role: models.IndexPageRole, PublishDate: time.Now(), CreatedAt: time.Now(), UpdatedAt: time.Now(), diff --git a/sql/queries/bundles.sql b/sql/queries/bundles.sql index 6d2a497..d11c9bd 100644 --- a/sql/queries/bundles.sql +++ b/sql/queries/bundles.sql @@ -10,4 +10,12 @@ INSERT INTO bundles ( SELECT * FROM bundles WHERE site_id = $1; -- name: GetBundleWithID :one -SELECT * FROM bundles WHERE id = $1; \ No newline at end of file +SELECT * FROM bundles WHERE id = $1; + +-- name: GetSiteBundleInfo :many +WITH page_counts AS ( + SELECT b.bundle_id, count(*) AS page_count FROM pages b WHERE b.site_id = $1 GROUP BY bundle_id +), index_pages AS ( + SELECT p.id AS index_page_id, p.bundle_id FROM pages p WHERE p.site_id = $1 AND p.role = 'index' +) +SELECT b.bundle_id, b.page_count, p.index_page_id FROM page_counts b LEFT OUTER JOIN index_pages p ON b.bundle_id = p.bundle_id; diff --git a/sql/queries/pages.sql b/sql/queries/pages.sql index d3b77db..db5fe71 100644 --- a/sql/queries/pages.sql +++ b/sql/queries/pages.sql @@ -5,14 +5,15 @@ INSERT INTO pages ( name, name_provenance, title, - role, + post_type_id, body, state, props, + role, publish_date, created_at, updated_at -) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $11) +) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $12) RETURNING id; -- name: UpdatePage :exec @@ -22,13 +23,14 @@ UPDATE pages SET name = $4, name_provenance = $5, title = $6, - role = $7, - body = $8, - state = $9, - props = $10, - publish_date = $11, - created_at = $12, - updated_at = $13 + post_type_id = $7, + role = $8, + body = $9, + state = $10, + props = $11, + publish_date = $12, + created_at = $13, + updated_at = $14 WHERE id = $1; -- name: ListPublishablePages :many diff --git a/sql/schema/1_init.up.sql b/sql/schema/1_init.up.sql index 6524422..772df25 100644 --- a/sql/schema/1_init.up.sql +++ b/sql/schema/1_init.up.sql @@ -17,6 +17,10 @@ CREATE TYPE page_name_provenance AS ENUM ( 'date' ); +CREATE TYPE page_role AS ENUM ( + 'index' +); + CREATE TABLE users ( id BIGSERIAL NOT NULL PRIMARY KEY, email TEXT NOT NULL UNIQUE, @@ -36,7 +40,7 @@ CREATE TABLE sites ( -- Post role is used to describe a specific kind of post, such as a link. -- When set, it specifies the layout to use for the page -CREATE TABLE post_roles ( +CREATE TABLE post_types ( id BIGSERIAL NOT NULL PRIMARY KEY, site_id BIGINT NOT NULL, layout_name TEXT NOT NULL, @@ -48,7 +52,7 @@ CREATE TABLE posts ( id BIGSERIAL NOT NULL PRIMARY KEY, site_id BIGINT NOT NULL, title TEXT, - role BIGINT, + post_type_id BIGINT, body TEXT NOT NULL, state post_state NOT NULL, props JSON NOT NULL, @@ -56,7 +60,7 @@ CREATE TABLE posts ( created_at TIMESTAMP NOT NULL, updated_at TIMESTAMP NOT NULL, - FOREIGN KEY (role) REFERENCES post_roles (id) ON DELETE CASCADE, + FOREIGN KEY (post_type_id) REFERENCES post_types (id) ON DELETE CASCADE, FOREIGN KEY (site_id) REFERENCES sites (id) ON DELETE CASCADE ); @@ -77,19 +81,21 @@ CREATE TABLE pages ( name TEXT NOT NULL, name_provenance page_name_provenance NOT NULL, title TEXT, - role BIGINT, + post_type_id BIGINT, body TEXT NOT NULL, state post_state NOT NULL, props JSON NOT NULL, + role page_role, publish_date TIMESTAMP WITH TIME ZONE, created_at TIMESTAMP NOT NULL, updated_at TIMESTAMP NOT NULL, UNIQUE (bundle_id, name), FOREIGN KEY (site_id) REFERENCES sites (id) ON DELETE CASCADE, - FOREIGN KEY (role) REFERENCES post_roles (id) ON DELETE CASCADE, + FOREIGN KEY (post_type_id) REFERENCES post_types (id) ON DELETE CASCADE, FOREIGN KEY (bundle_id) REFERENCES sites (id) ON DELETE CASCADE ); +CREATE UNIQUE INDEX page_bundle_id_role ON pages (bundle_id, role) WHERE (role is NOT null); CREATE TABLE publish_targets ( id BIGSERIAL NOT NULL PRIMARY KEY,