Implement complete collection persistence with database-backed survival across server restarts
• Add full multi-table schema for collections with normalized design (collections, collection_templates, collection_items, collection_item_versions) • Implement collection detection and processing in enhancement pipeline for .insertr-add elements • Add template extraction and storage from existing HTML children with multi-variant support • Enable collection reconstruction from database on server restart with proper DOM rebuilding • Extend ContentClient interface with collection operations and full database integration • Update enhance command to use engine.DatabaseClient for collection persistence support
This commit is contained in:
197
internal/db/postgresql/collection_item_versions.sql.go
Normal file
197
internal/db/postgresql/collection_item_versions.sql.go
Normal file
@@ -0,0 +1,197 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.30.0
|
||||
// source: collection_item_versions.sql
|
||||
|
||||
package postgresql
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
)
|
||||
|
||||
const createCollectionItemVersion = `-- name: CreateCollectionItemVersion :exec
|
||||
|
||||
INSERT INTO collection_item_versions (item_id, collection_id, site_id, html_content, template_id, position, created_by)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
||||
`
|
||||
|
||||
type CreateCollectionItemVersionParams struct {
|
||||
ItemID string `json:"item_id"`
|
||||
CollectionID string `json:"collection_id"`
|
||||
SiteID string `json:"site_id"`
|
||||
HtmlContent string `json:"html_content"`
|
||||
TemplateID int32 `json:"template_id"`
|
||||
Position int32 `json:"position"`
|
||||
CreatedBy string `json:"created_by"`
|
||||
}
|
||||
|
||||
// Collection item versions table queries
|
||||
func (q *Queries) CreateCollectionItemVersion(ctx context.Context, arg CreateCollectionItemVersionParams) error {
|
||||
_, err := q.db.ExecContext(ctx, createCollectionItemVersion,
|
||||
arg.ItemID,
|
||||
arg.CollectionID,
|
||||
arg.SiteID,
|
||||
arg.HtmlContent,
|
||||
arg.TemplateID,
|
||||
arg.Position,
|
||||
arg.CreatedBy,
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
const deleteOldCollectionItemVersions = `-- name: DeleteOldCollectionItemVersions :exec
|
||||
DELETE FROM collection_item_versions
|
||||
WHERE created_at < $1 AND site_id = $2
|
||||
`
|
||||
|
||||
type DeleteOldCollectionItemVersionsParams struct {
|
||||
CreatedBefore int64 `json:"created_before"`
|
||||
SiteID string `json:"site_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) DeleteOldCollectionItemVersions(ctx context.Context, arg DeleteOldCollectionItemVersionsParams) error {
|
||||
_, err := q.db.ExecContext(ctx, deleteOldCollectionItemVersions, arg.CreatedBefore, arg.SiteID)
|
||||
return err
|
||||
}
|
||||
|
||||
const getAllCollectionItemVersionsForSite = `-- name: GetAllCollectionItemVersionsForSite :many
|
||||
SELECT
|
||||
civ.version_id, civ.item_id, civ.collection_id, civ.site_id, civ.html_content, civ.template_id, civ.position, civ.created_at, civ.created_by,
|
||||
ci.html_content as current_html_content, ci.position as current_position
|
||||
FROM collection_item_versions civ
|
||||
LEFT JOIN collection_items ci ON civ.item_id = ci.item_id AND civ.collection_id = ci.collection_id AND civ.site_id = ci.site_id
|
||||
WHERE civ.site_id = $1
|
||||
ORDER BY civ.created_at DESC
|
||||
LIMIT $2
|
||||
`
|
||||
|
||||
type GetAllCollectionItemVersionsForSiteParams struct {
|
||||
SiteID string `json:"site_id"`
|
||||
LimitCount int32 `json:"limit_count"`
|
||||
}
|
||||
|
||||
type GetAllCollectionItemVersionsForSiteRow struct {
|
||||
VersionID int32 `json:"version_id"`
|
||||
ItemID string `json:"item_id"`
|
||||
CollectionID string `json:"collection_id"`
|
||||
SiteID string `json:"site_id"`
|
||||
HtmlContent string `json:"html_content"`
|
||||
TemplateID int32 `json:"template_id"`
|
||||
Position int32 `json:"position"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
CreatedBy string `json:"created_by"`
|
||||
CurrentHtmlContent sql.NullString `json:"current_html_content"`
|
||||
CurrentPosition sql.NullInt32 `json:"current_position"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetAllCollectionItemVersionsForSite(ctx context.Context, arg GetAllCollectionItemVersionsForSiteParams) ([]GetAllCollectionItemVersionsForSiteRow, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getAllCollectionItemVersionsForSite, arg.SiteID, arg.LimitCount)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []GetAllCollectionItemVersionsForSiteRow
|
||||
for rows.Next() {
|
||||
var i GetAllCollectionItemVersionsForSiteRow
|
||||
if err := rows.Scan(
|
||||
&i.VersionID,
|
||||
&i.ItemID,
|
||||
&i.CollectionID,
|
||||
&i.SiteID,
|
||||
&i.HtmlContent,
|
||||
&i.TemplateID,
|
||||
&i.Position,
|
||||
&i.CreatedAt,
|
||||
&i.CreatedBy,
|
||||
&i.CurrentHtmlContent,
|
||||
&i.CurrentPosition,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getCollectionItemVersion = `-- name: GetCollectionItemVersion :one
|
||||
SELECT version_id, item_id, collection_id, site_id, html_content, template_id, position, created_at, created_by
|
||||
FROM collection_item_versions
|
||||
WHERE version_id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetCollectionItemVersion(ctx context.Context, versionID int32) (CollectionItemVersion, error) {
|
||||
row := q.db.QueryRowContext(ctx, getCollectionItemVersion, versionID)
|
||||
var i CollectionItemVersion
|
||||
err := row.Scan(
|
||||
&i.VersionID,
|
||||
&i.ItemID,
|
||||
&i.CollectionID,
|
||||
&i.SiteID,
|
||||
&i.HtmlContent,
|
||||
&i.TemplateID,
|
||||
&i.Position,
|
||||
&i.CreatedAt,
|
||||
&i.CreatedBy,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getCollectionItemVersionHistory = `-- name: GetCollectionItemVersionHistory :many
|
||||
SELECT version_id, item_id, collection_id, site_id, html_content, template_id, position, created_at, created_by
|
||||
FROM collection_item_versions
|
||||
WHERE item_id = $1 AND collection_id = $2 AND site_id = $3
|
||||
ORDER BY created_at DESC
|
||||
LIMIT $4
|
||||
`
|
||||
|
||||
type GetCollectionItemVersionHistoryParams struct {
|
||||
ItemID string `json:"item_id"`
|
||||
CollectionID string `json:"collection_id"`
|
||||
SiteID string `json:"site_id"`
|
||||
LimitCount int32 `json:"limit_count"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetCollectionItemVersionHistory(ctx context.Context, arg GetCollectionItemVersionHistoryParams) ([]CollectionItemVersion, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getCollectionItemVersionHistory,
|
||||
arg.ItemID,
|
||||
arg.CollectionID,
|
||||
arg.SiteID,
|
||||
arg.LimitCount,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []CollectionItemVersion
|
||||
for rows.Next() {
|
||||
var i CollectionItemVersion
|
||||
if err := rows.Scan(
|
||||
&i.VersionID,
|
||||
&i.ItemID,
|
||||
&i.CollectionID,
|
||||
&i.SiteID,
|
||||
&i.HtmlContent,
|
||||
&i.TemplateID,
|
||||
&i.Position,
|
||||
&i.CreatedAt,
|
||||
&i.CreatedBy,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
327
internal/db/postgresql/collection_items.sql.go
Normal file
327
internal/db/postgresql/collection_items.sql.go
Normal file
@@ -0,0 +1,327 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.30.0
|
||||
// source: collection_items.sql
|
||||
|
||||
package postgresql
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
const createCollectionItem = `-- name: CreateCollectionItem :one
|
||||
INSERT INTO collection_items (item_id, collection_id, site_id, template_id, html_content, position, last_edited_by)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
||||
RETURNING item_id, collection_id, site_id, template_id, html_content, position, created_at, updated_at, last_edited_by
|
||||
`
|
||||
|
||||
type CreateCollectionItemParams struct {
|
||||
ItemID string `json:"item_id"`
|
||||
CollectionID string `json:"collection_id"`
|
||||
SiteID string `json:"site_id"`
|
||||
TemplateID int32 `json:"template_id"`
|
||||
HtmlContent string `json:"html_content"`
|
||||
Position int32 `json:"position"`
|
||||
LastEditedBy string `json:"last_edited_by"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateCollectionItem(ctx context.Context, arg CreateCollectionItemParams) (CollectionItem, error) {
|
||||
row := q.db.QueryRowContext(ctx, createCollectionItem,
|
||||
arg.ItemID,
|
||||
arg.CollectionID,
|
||||
arg.SiteID,
|
||||
arg.TemplateID,
|
||||
arg.HtmlContent,
|
||||
arg.Position,
|
||||
arg.LastEditedBy,
|
||||
)
|
||||
var i CollectionItem
|
||||
err := row.Scan(
|
||||
&i.ItemID,
|
||||
&i.CollectionID,
|
||||
&i.SiteID,
|
||||
&i.TemplateID,
|
||||
&i.HtmlContent,
|
||||
&i.Position,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.LastEditedBy,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const deleteCollectionItem = `-- name: DeleteCollectionItem :exec
|
||||
DELETE FROM collection_items
|
||||
WHERE item_id = $1 AND collection_id = $2 AND site_id = $3
|
||||
`
|
||||
|
||||
type DeleteCollectionItemParams struct {
|
||||
ItemID string `json:"item_id"`
|
||||
CollectionID string `json:"collection_id"`
|
||||
SiteID string `json:"site_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) DeleteCollectionItem(ctx context.Context, arg DeleteCollectionItemParams) error {
|
||||
_, err := q.db.ExecContext(ctx, deleteCollectionItem, arg.ItemID, arg.CollectionID, arg.SiteID)
|
||||
return err
|
||||
}
|
||||
|
||||
const deleteCollectionItems = `-- name: DeleteCollectionItems :exec
|
||||
DELETE FROM collection_items
|
||||
WHERE collection_id = $1 AND site_id = $2
|
||||
`
|
||||
|
||||
type DeleteCollectionItemsParams struct {
|
||||
CollectionID string `json:"collection_id"`
|
||||
SiteID string `json:"site_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) DeleteCollectionItems(ctx context.Context, arg DeleteCollectionItemsParams) error {
|
||||
_, err := q.db.ExecContext(ctx, deleteCollectionItems, arg.CollectionID, arg.SiteID)
|
||||
return err
|
||||
}
|
||||
|
||||
const getCollectionItem = `-- name: GetCollectionItem :one
|
||||
|
||||
SELECT item_id, collection_id, site_id, template_id, html_content, position, created_at, updated_at, last_edited_by
|
||||
FROM collection_items
|
||||
WHERE item_id = $1 AND collection_id = $2 AND site_id = $3
|
||||
`
|
||||
|
||||
type GetCollectionItemParams struct {
|
||||
ItemID string `json:"item_id"`
|
||||
CollectionID string `json:"collection_id"`
|
||||
SiteID string `json:"site_id"`
|
||||
}
|
||||
|
||||
// Collection items table queries
|
||||
func (q *Queries) GetCollectionItem(ctx context.Context, arg GetCollectionItemParams) (CollectionItem, error) {
|
||||
row := q.db.QueryRowContext(ctx, getCollectionItem, arg.ItemID, arg.CollectionID, arg.SiteID)
|
||||
var i CollectionItem
|
||||
err := row.Scan(
|
||||
&i.ItemID,
|
||||
&i.CollectionID,
|
||||
&i.SiteID,
|
||||
&i.TemplateID,
|
||||
&i.HtmlContent,
|
||||
&i.Position,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.LastEditedBy,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getCollectionItems = `-- name: GetCollectionItems :many
|
||||
SELECT item_id, collection_id, site_id, template_id, html_content, position, created_at, updated_at, last_edited_by
|
||||
FROM collection_items
|
||||
WHERE collection_id = $1 AND site_id = $2
|
||||
ORDER BY position ASC
|
||||
`
|
||||
|
||||
type GetCollectionItemsParams struct {
|
||||
CollectionID string `json:"collection_id"`
|
||||
SiteID string `json:"site_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetCollectionItems(ctx context.Context, arg GetCollectionItemsParams) ([]CollectionItem, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getCollectionItems, arg.CollectionID, arg.SiteID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []CollectionItem
|
||||
for rows.Next() {
|
||||
var i CollectionItem
|
||||
if err := rows.Scan(
|
||||
&i.ItemID,
|
||||
&i.CollectionID,
|
||||
&i.SiteID,
|
||||
&i.TemplateID,
|
||||
&i.HtmlContent,
|
||||
&i.Position,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.LastEditedBy,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getCollectionItemsWithTemplate = `-- name: GetCollectionItemsWithTemplate :many
|
||||
SELECT
|
||||
ci.item_id, ci.collection_id, ci.site_id, ci.template_id, ci.html_content, ci.position, ci.created_at, ci.updated_at, ci.last_edited_by,
|
||||
ct.name as template_name, ct.html_template, ct.is_default
|
||||
FROM collection_items ci
|
||||
JOIN collection_templates ct ON ci.template_id = ct.template_id
|
||||
WHERE ci.collection_id = $1 AND ci.site_id = $2
|
||||
ORDER BY ci.position ASC
|
||||
`
|
||||
|
||||
type GetCollectionItemsWithTemplateParams struct {
|
||||
CollectionID string `json:"collection_id"`
|
||||
SiteID string `json:"site_id"`
|
||||
}
|
||||
|
||||
type GetCollectionItemsWithTemplateRow struct {
|
||||
ItemID string `json:"item_id"`
|
||||
CollectionID string `json:"collection_id"`
|
||||
SiteID string `json:"site_id"`
|
||||
TemplateID int32 `json:"template_id"`
|
||||
HtmlContent string `json:"html_content"`
|
||||
Position int32 `json:"position"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
UpdatedAt int64 `json:"updated_at"`
|
||||
LastEditedBy string `json:"last_edited_by"`
|
||||
TemplateName string `json:"template_name"`
|
||||
HtmlTemplate string `json:"html_template"`
|
||||
IsDefault bool `json:"is_default"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetCollectionItemsWithTemplate(ctx context.Context, arg GetCollectionItemsWithTemplateParams) ([]GetCollectionItemsWithTemplateRow, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getCollectionItemsWithTemplate, arg.CollectionID, arg.SiteID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []GetCollectionItemsWithTemplateRow
|
||||
for rows.Next() {
|
||||
var i GetCollectionItemsWithTemplateRow
|
||||
if err := rows.Scan(
|
||||
&i.ItemID,
|
||||
&i.CollectionID,
|
||||
&i.SiteID,
|
||||
&i.TemplateID,
|
||||
&i.HtmlContent,
|
||||
&i.Position,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.LastEditedBy,
|
||||
&i.TemplateName,
|
||||
&i.HtmlTemplate,
|
||||
&i.IsDefault,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getMaxPosition = `-- name: GetMaxPosition :one
|
||||
SELECT COALESCE(MAX(position), 0) as max_position
|
||||
FROM collection_items
|
||||
WHERE collection_id = $1 AND site_id = $2
|
||||
`
|
||||
|
||||
type GetMaxPositionParams struct {
|
||||
CollectionID string `json:"collection_id"`
|
||||
SiteID string `json:"site_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetMaxPosition(ctx context.Context, arg GetMaxPositionParams) (interface{}, error) {
|
||||
row := q.db.QueryRowContext(ctx, getMaxPosition, arg.CollectionID, arg.SiteID)
|
||||
var max_position interface{}
|
||||
err := row.Scan(&max_position)
|
||||
return max_position, err
|
||||
}
|
||||
|
||||
const reorderCollectionItems = `-- name: ReorderCollectionItems :exec
|
||||
UPDATE collection_items
|
||||
SET position = position + $1
|
||||
WHERE collection_id = $2 AND site_id = $3
|
||||
AND position >= $4
|
||||
`
|
||||
|
||||
type ReorderCollectionItemsParams struct {
|
||||
PositionDelta int32 `json:"position_delta"`
|
||||
CollectionID string `json:"collection_id"`
|
||||
SiteID string `json:"site_id"`
|
||||
StartPosition int32 `json:"start_position"`
|
||||
}
|
||||
|
||||
func (q *Queries) ReorderCollectionItems(ctx context.Context, arg ReorderCollectionItemsParams) error {
|
||||
_, err := q.db.ExecContext(ctx, reorderCollectionItems,
|
||||
arg.PositionDelta,
|
||||
arg.CollectionID,
|
||||
arg.SiteID,
|
||||
arg.StartPosition,
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
const updateCollectionItem = `-- name: UpdateCollectionItem :one
|
||||
UPDATE collection_items
|
||||
SET html_content = $1, last_edited_by = $2
|
||||
WHERE item_id = $3 AND collection_id = $4 AND site_id = $5
|
||||
RETURNING item_id, collection_id, site_id, template_id, html_content, position, created_at, updated_at, last_edited_by
|
||||
`
|
||||
|
||||
type UpdateCollectionItemParams struct {
|
||||
HtmlContent string `json:"html_content"`
|
||||
LastEditedBy string `json:"last_edited_by"`
|
||||
ItemID string `json:"item_id"`
|
||||
CollectionID string `json:"collection_id"`
|
||||
SiteID string `json:"site_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateCollectionItem(ctx context.Context, arg UpdateCollectionItemParams) (CollectionItem, error) {
|
||||
row := q.db.QueryRowContext(ctx, updateCollectionItem,
|
||||
arg.HtmlContent,
|
||||
arg.LastEditedBy,
|
||||
arg.ItemID,
|
||||
arg.CollectionID,
|
||||
arg.SiteID,
|
||||
)
|
||||
var i CollectionItem
|
||||
err := row.Scan(
|
||||
&i.ItemID,
|
||||
&i.CollectionID,
|
||||
&i.SiteID,
|
||||
&i.TemplateID,
|
||||
&i.HtmlContent,
|
||||
&i.Position,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.LastEditedBy,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const updateCollectionItemPosition = `-- name: UpdateCollectionItemPosition :exec
|
||||
UPDATE collection_items
|
||||
SET position = $1
|
||||
WHERE item_id = $2 AND collection_id = $3 AND site_id = $4
|
||||
`
|
||||
|
||||
type UpdateCollectionItemPositionParams struct {
|
||||
Position int32 `json:"position"`
|
||||
ItemID string `json:"item_id"`
|
||||
CollectionID string `json:"collection_id"`
|
||||
SiteID string `json:"site_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateCollectionItemPosition(ctx context.Context, arg UpdateCollectionItemPositionParams) error {
|
||||
_, err := q.db.ExecContext(ctx, updateCollectionItemPosition,
|
||||
arg.Position,
|
||||
arg.ItemID,
|
||||
arg.CollectionID,
|
||||
arg.SiteID,
|
||||
)
|
||||
return err
|
||||
}
|
||||
217
internal/db/postgresql/collection_templates.sql.go
Normal file
217
internal/db/postgresql/collection_templates.sql.go
Normal file
@@ -0,0 +1,217 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.30.0
|
||||
// source: collection_templates.sql
|
||||
|
||||
package postgresql
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
const createCollectionTemplate = `-- name: CreateCollectionTemplate :one
|
||||
INSERT INTO collection_templates (collection_id, site_id, name, html_template, is_default)
|
||||
VALUES ($1, $2, $3, $4, $5)
|
||||
RETURNING template_id, collection_id, site_id, name, html_template, is_default, created_at
|
||||
`
|
||||
|
||||
type CreateCollectionTemplateParams struct {
|
||||
CollectionID string `json:"collection_id"`
|
||||
SiteID string `json:"site_id"`
|
||||
Name string `json:"name"`
|
||||
HtmlTemplate string `json:"html_template"`
|
||||
IsDefault bool `json:"is_default"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateCollectionTemplate(ctx context.Context, arg CreateCollectionTemplateParams) (CollectionTemplate, error) {
|
||||
row := q.db.QueryRowContext(ctx, createCollectionTemplate,
|
||||
arg.CollectionID,
|
||||
arg.SiteID,
|
||||
arg.Name,
|
||||
arg.HtmlTemplate,
|
||||
arg.IsDefault,
|
||||
)
|
||||
var i CollectionTemplate
|
||||
err := row.Scan(
|
||||
&i.TemplateID,
|
||||
&i.CollectionID,
|
||||
&i.SiteID,
|
||||
&i.Name,
|
||||
&i.HtmlTemplate,
|
||||
&i.IsDefault,
|
||||
&i.CreatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const deleteCollectionTemplate = `-- name: DeleteCollectionTemplate :exec
|
||||
DELETE FROM collection_templates
|
||||
WHERE template_id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) DeleteCollectionTemplate(ctx context.Context, templateID int32) error {
|
||||
_, err := q.db.ExecContext(ctx, deleteCollectionTemplate, templateID)
|
||||
return err
|
||||
}
|
||||
|
||||
const deleteCollectionTemplates = `-- name: DeleteCollectionTemplates :exec
|
||||
DELETE FROM collection_templates
|
||||
WHERE collection_id = $1 AND site_id = $2
|
||||
`
|
||||
|
||||
type DeleteCollectionTemplatesParams struct {
|
||||
CollectionID string `json:"collection_id"`
|
||||
SiteID string `json:"site_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) DeleteCollectionTemplates(ctx context.Context, arg DeleteCollectionTemplatesParams) error {
|
||||
_, err := q.db.ExecContext(ctx, deleteCollectionTemplates, arg.CollectionID, arg.SiteID)
|
||||
return err
|
||||
}
|
||||
|
||||
const getCollectionTemplate = `-- name: GetCollectionTemplate :one
|
||||
|
||||
SELECT template_id, collection_id, site_id, name, html_template, is_default, created_at
|
||||
FROM collection_templates
|
||||
WHERE template_id = $1
|
||||
`
|
||||
|
||||
// Collection templates table queries
|
||||
func (q *Queries) GetCollectionTemplate(ctx context.Context, templateID int32) (CollectionTemplate, error) {
|
||||
row := q.db.QueryRowContext(ctx, getCollectionTemplate, templateID)
|
||||
var i CollectionTemplate
|
||||
err := row.Scan(
|
||||
&i.TemplateID,
|
||||
&i.CollectionID,
|
||||
&i.SiteID,
|
||||
&i.Name,
|
||||
&i.HtmlTemplate,
|
||||
&i.IsDefault,
|
||||
&i.CreatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getCollectionTemplates = `-- name: GetCollectionTemplates :many
|
||||
SELECT template_id, collection_id, site_id, name, html_template, is_default, created_at
|
||||
FROM collection_templates
|
||||
WHERE collection_id = $1 AND site_id = $2
|
||||
ORDER BY is_default DESC, created_at ASC
|
||||
`
|
||||
|
||||
type GetCollectionTemplatesParams struct {
|
||||
CollectionID string `json:"collection_id"`
|
||||
SiteID string `json:"site_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetCollectionTemplates(ctx context.Context, arg GetCollectionTemplatesParams) ([]CollectionTemplate, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getCollectionTemplates, arg.CollectionID, arg.SiteID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []CollectionTemplate
|
||||
for rows.Next() {
|
||||
var i CollectionTemplate
|
||||
if err := rows.Scan(
|
||||
&i.TemplateID,
|
||||
&i.CollectionID,
|
||||
&i.SiteID,
|
||||
&i.Name,
|
||||
&i.HtmlTemplate,
|
||||
&i.IsDefault,
|
||||
&i.CreatedAt,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getDefaultTemplate = `-- name: GetDefaultTemplate :one
|
||||
SELECT template_id, collection_id, site_id, name, html_template, is_default, created_at
|
||||
FROM collection_templates
|
||||
WHERE collection_id = $1 AND site_id = $2 AND is_default = TRUE
|
||||
LIMIT 1
|
||||
`
|
||||
|
||||
type GetDefaultTemplateParams struct {
|
||||
CollectionID string `json:"collection_id"`
|
||||
SiteID string `json:"site_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetDefaultTemplate(ctx context.Context, arg GetDefaultTemplateParams) (CollectionTemplate, error) {
|
||||
row := q.db.QueryRowContext(ctx, getDefaultTemplate, arg.CollectionID, arg.SiteID)
|
||||
var i CollectionTemplate
|
||||
err := row.Scan(
|
||||
&i.TemplateID,
|
||||
&i.CollectionID,
|
||||
&i.SiteID,
|
||||
&i.Name,
|
||||
&i.HtmlTemplate,
|
||||
&i.IsDefault,
|
||||
&i.CreatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const setTemplateAsDefault = `-- name: SetTemplateAsDefault :exec
|
||||
UPDATE collection_templates
|
||||
SET is_default = CASE
|
||||
WHEN template_id = $1 THEN TRUE
|
||||
ELSE FALSE
|
||||
END
|
||||
WHERE collection_id = $2 AND site_id = $3
|
||||
`
|
||||
|
||||
type SetTemplateAsDefaultParams struct {
|
||||
TemplateID int32 `json:"template_id"`
|
||||
CollectionID string `json:"collection_id"`
|
||||
SiteID string `json:"site_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) SetTemplateAsDefault(ctx context.Context, arg SetTemplateAsDefaultParams) error {
|
||||
_, err := q.db.ExecContext(ctx, setTemplateAsDefault, arg.TemplateID, arg.CollectionID, arg.SiteID)
|
||||
return err
|
||||
}
|
||||
|
||||
const updateCollectionTemplate = `-- name: UpdateCollectionTemplate :one
|
||||
UPDATE collection_templates
|
||||
SET name = $1, html_template = $2, is_default = $3
|
||||
WHERE template_id = $4
|
||||
RETURNING template_id, collection_id, site_id, name, html_template, is_default, created_at
|
||||
`
|
||||
|
||||
type UpdateCollectionTemplateParams struct {
|
||||
Name string `json:"name"`
|
||||
HtmlTemplate string `json:"html_template"`
|
||||
IsDefault bool `json:"is_default"`
|
||||
TemplateID int32 `json:"template_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateCollectionTemplate(ctx context.Context, arg UpdateCollectionTemplateParams) (CollectionTemplate, error) {
|
||||
row := q.db.QueryRowContext(ctx, updateCollectionTemplate,
|
||||
arg.Name,
|
||||
arg.HtmlTemplate,
|
||||
arg.IsDefault,
|
||||
arg.TemplateID,
|
||||
)
|
||||
var i CollectionTemplate
|
||||
err := row.Scan(
|
||||
&i.TemplateID,
|
||||
&i.CollectionID,
|
||||
&i.SiteID,
|
||||
&i.Name,
|
||||
&i.HtmlTemplate,
|
||||
&i.IsDefault,
|
||||
&i.CreatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
199
internal/db/postgresql/collections.sql.go
Normal file
199
internal/db/postgresql/collections.sql.go
Normal file
@@ -0,0 +1,199 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.30.0
|
||||
// source: collections.sql
|
||||
|
||||
package postgresql
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
const createCollection = `-- name: CreateCollection :one
|
||||
INSERT INTO collections (id, site_id, container_html, last_edited_by)
|
||||
VALUES ($1, $2, $3, $4)
|
||||
RETURNING id, site_id, container_html, created_at, updated_at, last_edited_by
|
||||
`
|
||||
|
||||
type CreateCollectionParams struct {
|
||||
ID string `json:"id"`
|
||||
SiteID string `json:"site_id"`
|
||||
ContainerHtml string `json:"container_html"`
|
||||
LastEditedBy string `json:"last_edited_by"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateCollection(ctx context.Context, arg CreateCollectionParams) (Collection, error) {
|
||||
row := q.db.QueryRowContext(ctx, createCollection,
|
||||
arg.ID,
|
||||
arg.SiteID,
|
||||
arg.ContainerHtml,
|
||||
arg.LastEditedBy,
|
||||
)
|
||||
var i Collection
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.SiteID,
|
||||
&i.ContainerHtml,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.LastEditedBy,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const deleteAllSiteCollections = `-- name: DeleteAllSiteCollections :exec
|
||||
DELETE FROM collections
|
||||
WHERE site_id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) DeleteAllSiteCollections(ctx context.Context, siteID string) error {
|
||||
_, err := q.db.ExecContext(ctx, deleteAllSiteCollections, siteID)
|
||||
return err
|
||||
}
|
||||
|
||||
const deleteCollection = `-- name: DeleteCollection :exec
|
||||
DELETE FROM collections
|
||||
WHERE id = $1 AND site_id = $2
|
||||
`
|
||||
|
||||
type DeleteCollectionParams struct {
|
||||
ID string `json:"id"`
|
||||
SiteID string `json:"site_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) DeleteCollection(ctx context.Context, arg DeleteCollectionParams) error {
|
||||
_, err := q.db.ExecContext(ctx, deleteCollection, arg.ID, arg.SiteID)
|
||||
return err
|
||||
}
|
||||
|
||||
const getAllCollections = `-- name: GetAllCollections :many
|
||||
SELECT id, site_id, container_html, created_at, updated_at, last_edited_by
|
||||
FROM collections
|
||||
WHERE site_id = $1
|
||||
ORDER BY updated_at DESC
|
||||
`
|
||||
|
||||
func (q *Queries) GetAllCollections(ctx context.Context, siteID string) ([]Collection, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getAllCollections, siteID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []Collection
|
||||
for rows.Next() {
|
||||
var i Collection
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.SiteID,
|
||||
&i.ContainerHtml,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.LastEditedBy,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getCollection = `-- name: GetCollection :one
|
||||
|
||||
SELECT id, site_id, container_html, created_at, updated_at, last_edited_by
|
||||
FROM collections
|
||||
WHERE id = $1 AND site_id = $2
|
||||
`
|
||||
|
||||
type GetCollectionParams struct {
|
||||
ID string `json:"id"`
|
||||
SiteID string `json:"site_id"`
|
||||
}
|
||||
|
||||
// Collections table queries
|
||||
func (q *Queries) GetCollection(ctx context.Context, arg GetCollectionParams) (Collection, error) {
|
||||
row := q.db.QueryRowContext(ctx, getCollection, arg.ID, arg.SiteID)
|
||||
var i Collection
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.SiteID,
|
||||
&i.ContainerHtml,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.LastEditedBy,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const updateCollection = `-- name: UpdateCollection :one
|
||||
UPDATE collections
|
||||
SET container_html = $1, last_edited_by = $2
|
||||
WHERE id = $3 AND site_id = $4
|
||||
RETURNING id, site_id, container_html, created_at, updated_at, last_edited_by
|
||||
`
|
||||
|
||||
type UpdateCollectionParams struct {
|
||||
ContainerHtml string `json:"container_html"`
|
||||
LastEditedBy string `json:"last_edited_by"`
|
||||
ID string `json:"id"`
|
||||
SiteID string `json:"site_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateCollection(ctx context.Context, arg UpdateCollectionParams) (Collection, error) {
|
||||
row := q.db.QueryRowContext(ctx, updateCollection,
|
||||
arg.ContainerHtml,
|
||||
arg.LastEditedBy,
|
||||
arg.ID,
|
||||
arg.SiteID,
|
||||
)
|
||||
var i Collection
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.SiteID,
|
||||
&i.ContainerHtml,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.LastEditedBy,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const upsertCollection = `-- name: UpsertCollection :one
|
||||
INSERT INTO collections (id, site_id, container_html, last_edited_by)
|
||||
VALUES ($1, $2, $3, $4)
|
||||
ON CONFLICT(id, site_id) DO UPDATE SET
|
||||
container_html = EXCLUDED.container_html,
|
||||
last_edited_by = EXCLUDED.last_edited_by
|
||||
RETURNING id, site_id, container_html, created_at, updated_at, last_edited_by
|
||||
`
|
||||
|
||||
type UpsertCollectionParams struct {
|
||||
ID string `json:"id"`
|
||||
SiteID string `json:"site_id"`
|
||||
ContainerHtml string `json:"container_html"`
|
||||
LastEditedBy string `json:"last_edited_by"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpsertCollection(ctx context.Context, arg UpsertCollectionParams) (Collection, error) {
|
||||
row := q.db.QueryRowContext(ctx, upsertCollection,
|
||||
arg.ID,
|
||||
arg.SiteID,
|
||||
arg.ContainerHtml,
|
||||
arg.LastEditedBy,
|
||||
)
|
||||
var i Collection
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.SiteID,
|
||||
&i.ContainerHtml,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.LastEditedBy,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
@@ -8,6 +8,49 @@ import (
|
||||
"database/sql"
|
||||
)
|
||||
|
||||
type Collection struct {
|
||||
ID string `json:"id"`
|
||||
SiteID string `json:"site_id"`
|
||||
ContainerHtml string `json:"container_html"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
UpdatedAt int64 `json:"updated_at"`
|
||||
LastEditedBy string `json:"last_edited_by"`
|
||||
}
|
||||
|
||||
type CollectionItem struct {
|
||||
ItemID string `json:"item_id"`
|
||||
CollectionID string `json:"collection_id"`
|
||||
SiteID string `json:"site_id"`
|
||||
TemplateID int32 `json:"template_id"`
|
||||
HtmlContent string `json:"html_content"`
|
||||
Position int32 `json:"position"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
UpdatedAt int64 `json:"updated_at"`
|
||||
LastEditedBy string `json:"last_edited_by"`
|
||||
}
|
||||
|
||||
type CollectionItemVersion struct {
|
||||
VersionID int32 `json:"version_id"`
|
||||
ItemID string `json:"item_id"`
|
||||
CollectionID string `json:"collection_id"`
|
||||
SiteID string `json:"site_id"`
|
||||
HtmlContent string `json:"html_content"`
|
||||
TemplateID int32 `json:"template_id"`
|
||||
Position int32 `json:"position"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
CreatedBy string `json:"created_by"`
|
||||
}
|
||||
|
||||
type CollectionTemplate struct {
|
||||
TemplateID int32 `json:"template_id"`
|
||||
CollectionID string `json:"collection_id"`
|
||||
SiteID string `json:"site_id"`
|
||||
Name string `json:"name"`
|
||||
HtmlTemplate string `json:"html_template"`
|
||||
IsDefault bool `json:"is_default"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
}
|
||||
|
||||
type Content struct {
|
||||
ID string `json:"id"`
|
||||
SiteID string `json:"site_id"`
|
||||
|
||||
@@ -9,24 +9,70 @@ import (
|
||||
)
|
||||
|
||||
type Querier interface {
|
||||
CreateCollection(ctx context.Context, arg CreateCollectionParams) (Collection, error)
|
||||
CreateCollectionItem(ctx context.Context, arg CreateCollectionItemParams) (CollectionItem, error)
|
||||
// Collection item versions table queries
|
||||
CreateCollectionItemVersion(ctx context.Context, arg CreateCollectionItemVersionParams) error
|
||||
CreateCollectionItemVersionsLookupIndex(ctx context.Context) error
|
||||
CreateCollectionItemsLookupIndex(ctx context.Context) error
|
||||
CreateCollectionItemsTemplateIndex(ctx context.Context) error
|
||||
CreateCollectionTemplate(ctx context.Context, arg CreateCollectionTemplateParams) (CollectionTemplate, error)
|
||||
CreateCollectionTemplatesDefaultIndex(ctx context.Context) error
|
||||
CreateCollectionTemplatesLookupIndex(ctx context.Context) error
|
||||
CreateCollectionTemplatesOneDefaultIndex(ctx context.Context) error
|
||||
CreateCollectionsSiteIndex(ctx context.Context) error
|
||||
CreateCollectionsUpdatedAtIndex(ctx context.Context) error
|
||||
CreateContent(ctx context.Context, arg CreateContentParams) (Content, error)
|
||||
CreateContentSiteIndex(ctx context.Context) error
|
||||
CreateContentUpdatedAtIndex(ctx context.Context) error
|
||||
CreateContentVersion(ctx context.Context, arg CreateContentVersionParams) error
|
||||
CreateUpdateFunction(ctx context.Context) error
|
||||
CreateVersionsLookupIndex(ctx context.Context) error
|
||||
DeleteAllSiteCollections(ctx context.Context, siteID string) error
|
||||
DeleteAllSiteContent(ctx context.Context, siteID string) error
|
||||
DeleteCollection(ctx context.Context, arg DeleteCollectionParams) error
|
||||
DeleteCollectionItem(ctx context.Context, arg DeleteCollectionItemParams) error
|
||||
DeleteCollectionItems(ctx context.Context, arg DeleteCollectionItemsParams) error
|
||||
DeleteCollectionTemplate(ctx context.Context, templateID int32) error
|
||||
DeleteCollectionTemplates(ctx context.Context, arg DeleteCollectionTemplatesParams) error
|
||||
DeleteContent(ctx context.Context, arg DeleteContentParams) error
|
||||
DeleteOldCollectionItemVersions(ctx context.Context, arg DeleteOldCollectionItemVersionsParams) error
|
||||
DeleteOldVersions(ctx context.Context, arg DeleteOldVersionsParams) error
|
||||
GetAllCollectionItemVersionsForSite(ctx context.Context, arg GetAllCollectionItemVersionsForSiteParams) ([]GetAllCollectionItemVersionsForSiteRow, error)
|
||||
GetAllCollections(ctx context.Context, siteID string) ([]Collection, error)
|
||||
GetAllContent(ctx context.Context, siteID string) ([]Content, error)
|
||||
GetAllVersionsForSite(ctx context.Context, arg GetAllVersionsForSiteParams) ([]GetAllVersionsForSiteRow, error)
|
||||
GetBulkContent(ctx context.Context, arg GetBulkContentParams) ([]Content, error)
|
||||
// Collections table queries
|
||||
GetCollection(ctx context.Context, arg GetCollectionParams) (Collection, error)
|
||||
// Collection items table queries
|
||||
GetCollectionItem(ctx context.Context, arg GetCollectionItemParams) (CollectionItem, error)
|
||||
GetCollectionItemVersion(ctx context.Context, versionID int32) (CollectionItemVersion, error)
|
||||
GetCollectionItemVersionHistory(ctx context.Context, arg GetCollectionItemVersionHistoryParams) ([]CollectionItemVersion, error)
|
||||
GetCollectionItems(ctx context.Context, arg GetCollectionItemsParams) ([]CollectionItem, error)
|
||||
GetCollectionItemsWithTemplate(ctx context.Context, arg GetCollectionItemsWithTemplateParams) ([]GetCollectionItemsWithTemplateRow, error)
|
||||
// Collection templates table queries
|
||||
GetCollectionTemplate(ctx context.Context, templateID int32) (CollectionTemplate, error)
|
||||
GetCollectionTemplates(ctx context.Context, arg GetCollectionTemplatesParams) ([]CollectionTemplate, error)
|
||||
GetContent(ctx context.Context, arg GetContentParams) (Content, error)
|
||||
GetContentVersion(ctx context.Context, versionID int32) (ContentVersion, error)
|
||||
GetContentVersionHistory(ctx context.Context, arg GetContentVersionHistoryParams) ([]ContentVersion, error)
|
||||
GetDefaultTemplate(ctx context.Context, arg GetDefaultTemplateParams) (CollectionTemplate, error)
|
||||
GetMaxPosition(ctx context.Context, arg GetMaxPositionParams) (interface{}, error)
|
||||
InitializeCollectionItemVersionsTable(ctx context.Context) error
|
||||
InitializeCollectionItemsTable(ctx context.Context) error
|
||||
InitializeCollectionTemplatesTable(ctx context.Context) error
|
||||
InitializeCollectionsTable(ctx context.Context) error
|
||||
InitializeSchema(ctx context.Context) error
|
||||
InitializeVersionsTable(ctx context.Context) error
|
||||
ReorderCollectionItems(ctx context.Context, arg ReorderCollectionItemsParams) error
|
||||
SetTemplateAsDefault(ctx context.Context, arg SetTemplateAsDefaultParams) error
|
||||
UpdateCollection(ctx context.Context, arg UpdateCollectionParams) (Collection, error)
|
||||
UpdateCollectionItem(ctx context.Context, arg UpdateCollectionItemParams) (CollectionItem, error)
|
||||
UpdateCollectionItemPosition(ctx context.Context, arg UpdateCollectionItemPositionParams) error
|
||||
UpdateCollectionTemplate(ctx context.Context, arg UpdateCollectionTemplateParams) (CollectionTemplate, error)
|
||||
UpdateContent(ctx context.Context, arg UpdateContentParams) (Content, error)
|
||||
UpsertCollection(ctx context.Context, arg UpsertCollectionParams) (Collection, error)
|
||||
UpsertContent(ctx context.Context, arg UpsertContentParams) (Content, error)
|
||||
}
|
||||
|
||||
|
||||
@@ -22,11 +22,78 @@ CREATE TABLE content_versions (
|
||||
created_by TEXT DEFAULT 'system' NOT NULL
|
||||
);
|
||||
|
||||
-- Collections table - manages .insertr-add containers
|
||||
CREATE TABLE collections (
|
||||
id TEXT NOT NULL,
|
||||
site_id TEXT NOT NULL,
|
||||
container_html TEXT NOT NULL,
|
||||
created_at BIGINT DEFAULT EXTRACT(EPOCH FROM NOW()) NOT NULL,
|
||||
updated_at BIGINT DEFAULT EXTRACT(EPOCH FROM NOW()) NOT NULL,
|
||||
last_edited_by TEXT DEFAULT 'system' NOT NULL,
|
||||
PRIMARY KEY (id, site_id)
|
||||
);
|
||||
|
||||
-- Collection templates - multiple template variants per collection
|
||||
CREATE TABLE collection_templates (
|
||||
template_id SERIAL PRIMARY KEY,
|
||||
collection_id TEXT NOT NULL,
|
||||
site_id TEXT NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
html_template TEXT NOT NULL,
|
||||
is_default BOOLEAN DEFAULT FALSE NOT NULL,
|
||||
created_at BIGINT DEFAULT EXTRACT(EPOCH FROM NOW()) NOT NULL,
|
||||
FOREIGN KEY (collection_id, site_id) REFERENCES collections(id, site_id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
-- Collection items - individual items within collections
|
||||
CREATE TABLE collection_items (
|
||||
item_id TEXT NOT NULL,
|
||||
collection_id TEXT NOT NULL,
|
||||
site_id TEXT NOT NULL,
|
||||
template_id INTEGER NOT NULL,
|
||||
html_content TEXT NOT NULL,
|
||||
position INTEGER NOT NULL,
|
||||
created_at BIGINT DEFAULT EXTRACT(EPOCH FROM NOW()) NOT NULL,
|
||||
updated_at BIGINT DEFAULT EXTRACT(EPOCH FROM NOW()) NOT NULL,
|
||||
last_edited_by TEXT DEFAULT 'system' NOT NULL,
|
||||
PRIMARY KEY (item_id, collection_id, site_id),
|
||||
FOREIGN KEY (collection_id, site_id) REFERENCES collections(id, site_id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (template_id) REFERENCES collection_templates(template_id) ON DELETE RESTRICT
|
||||
);
|
||||
|
||||
-- Collection item version history
|
||||
CREATE TABLE collection_item_versions (
|
||||
version_id SERIAL PRIMARY KEY,
|
||||
item_id TEXT NOT NULL,
|
||||
collection_id TEXT NOT NULL,
|
||||
site_id TEXT NOT NULL,
|
||||
html_content TEXT NOT NULL,
|
||||
template_id INTEGER NOT NULL,
|
||||
position INTEGER NOT NULL,
|
||||
created_at BIGINT DEFAULT EXTRACT(EPOCH FROM NOW()) NOT NULL,
|
||||
created_by TEXT DEFAULT 'system' NOT NULL,
|
||||
FOREIGN KEY (item_id, collection_id, site_id) REFERENCES collection_items(item_id, collection_id, site_id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
-- Indexes for performance
|
||||
CREATE INDEX IF NOT EXISTS idx_content_site_id ON content(site_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_content_updated_at ON content(updated_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_content_versions_lookup ON content_versions(content_id, site_id, created_at DESC);
|
||||
|
||||
-- Collection indexes for performance
|
||||
CREATE INDEX IF NOT EXISTS idx_collections_site_id ON collections(site_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_collections_updated_at ON collections(updated_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_collection_templates_lookup ON collection_templates(collection_id, site_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_collection_templates_default ON collection_templates(collection_id, site_id, is_default DESC);
|
||||
CREATE INDEX IF NOT EXISTS idx_collection_items_lookup ON collection_items(collection_id, site_id, position);
|
||||
CREATE INDEX IF NOT EXISTS idx_collection_items_template ON collection_items(template_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_collection_item_versions_lookup ON collection_item_versions(item_id, collection_id, site_id, created_at DESC);
|
||||
|
||||
-- Constraint to ensure only one default template per collection
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_collection_templates_one_default
|
||||
ON collection_templates(collection_id, site_id)
|
||||
WHERE is_default = TRUE;
|
||||
|
||||
-- Function and trigger to automatically update updated_at timestamp
|
||||
CREATE OR REPLACE FUNCTION update_updated_at_column()
|
||||
RETURNS TRIGGER AS $$
|
||||
@@ -39,4 +106,15 @@ $$ language 'plpgsql';
|
||||
CREATE TRIGGER update_content_updated_at
|
||||
BEFORE UPDATE ON content
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION update_updated_at_column();
|
||||
|
||||
-- Triggers for collection timestamps
|
||||
CREATE TRIGGER update_collections_updated_at
|
||||
BEFORE UPDATE ON collections
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION update_updated_at_column();
|
||||
|
||||
CREATE TRIGGER update_collection_items_updated_at
|
||||
BEFORE UPDATE ON collection_items
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION update_updated_at_column();
|
||||
@@ -21,6 +21,59 @@ CREATE TABLE IF NOT EXISTS content_versions (
|
||||
created_by TEXT DEFAULT 'system' NOT NULL
|
||||
);
|
||||
|
||||
-- name: InitializeCollectionsTable :exec
|
||||
CREATE TABLE IF NOT EXISTS collections (
|
||||
id TEXT NOT NULL,
|
||||
site_id TEXT NOT NULL,
|
||||
container_html TEXT NOT NULL,
|
||||
created_at BIGINT DEFAULT (EXTRACT(EPOCH FROM NOW())) NOT NULL,
|
||||
updated_at BIGINT DEFAULT (EXTRACT(EPOCH FROM NOW())) NOT NULL,
|
||||
last_edited_by TEXT DEFAULT 'system' NOT NULL,
|
||||
PRIMARY KEY (id, site_id)
|
||||
);
|
||||
|
||||
-- name: InitializeCollectionTemplatesTable :exec
|
||||
CREATE TABLE IF NOT EXISTS collection_templates (
|
||||
template_id SERIAL PRIMARY KEY,
|
||||
collection_id TEXT NOT NULL,
|
||||
site_id TEXT NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
html_template TEXT NOT NULL,
|
||||
is_default BOOLEAN DEFAULT FALSE NOT NULL,
|
||||
created_at BIGINT DEFAULT (EXTRACT(EPOCH FROM NOW())) NOT NULL,
|
||||
FOREIGN KEY (collection_id, site_id) REFERENCES collections(id, site_id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
-- name: InitializeCollectionItemsTable :exec
|
||||
CREATE TABLE IF NOT EXISTS collection_items (
|
||||
item_id TEXT NOT NULL,
|
||||
collection_id TEXT NOT NULL,
|
||||
site_id TEXT NOT NULL,
|
||||
template_id INTEGER NOT NULL,
|
||||
html_content TEXT NOT NULL,
|
||||
position INTEGER NOT NULL,
|
||||
created_at BIGINT DEFAULT (EXTRACT(EPOCH FROM NOW())) NOT NULL,
|
||||
updated_at BIGINT DEFAULT (EXTRACT(EPOCH FROM NOW())) NOT NULL,
|
||||
last_edited_by TEXT DEFAULT 'system' NOT NULL,
|
||||
PRIMARY KEY (item_id, collection_id, site_id),
|
||||
FOREIGN KEY (collection_id, site_id) REFERENCES collections(id, site_id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (template_id) REFERENCES collection_templates(template_id) ON DELETE RESTRICT
|
||||
);
|
||||
|
||||
-- name: InitializeCollectionItemVersionsTable :exec
|
||||
CREATE TABLE IF NOT EXISTS collection_item_versions (
|
||||
version_id SERIAL PRIMARY KEY,
|
||||
item_id TEXT NOT NULL,
|
||||
collection_id TEXT NOT NULL,
|
||||
site_id TEXT NOT NULL,
|
||||
html_content TEXT NOT NULL,
|
||||
template_id INTEGER NOT NULL,
|
||||
position INTEGER NOT NULL,
|
||||
created_at BIGINT DEFAULT (EXTRACT(EPOCH FROM NOW())) NOT NULL,
|
||||
created_by TEXT DEFAULT 'system' NOT NULL,
|
||||
FOREIGN KEY (item_id, collection_id, site_id) REFERENCES collection_items(item_id, collection_id, site_id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
-- name: CreateContentSiteIndex :exec
|
||||
CREATE INDEX IF NOT EXISTS idx_content_site_id ON content(site_id);
|
||||
|
||||
@@ -30,6 +83,32 @@ CREATE INDEX IF NOT EXISTS idx_content_updated_at ON content(updated_at);
|
||||
-- name: CreateVersionsLookupIndex :exec
|
||||
CREATE INDEX IF NOT EXISTS idx_content_versions_lookup ON content_versions(content_id, site_id, created_at DESC);
|
||||
|
||||
-- name: CreateCollectionsSiteIndex :exec
|
||||
CREATE INDEX IF NOT EXISTS idx_collections_site_id ON collections(site_id);
|
||||
|
||||
-- name: CreateCollectionsUpdatedAtIndex :exec
|
||||
CREATE INDEX IF NOT EXISTS idx_collections_updated_at ON collections(updated_at);
|
||||
|
||||
-- name: CreateCollectionTemplatesLookupIndex :exec
|
||||
CREATE INDEX IF NOT EXISTS idx_collection_templates_lookup ON collection_templates(collection_id, site_id);
|
||||
|
||||
-- name: CreateCollectionTemplatesDefaultIndex :exec
|
||||
CREATE INDEX IF NOT EXISTS idx_collection_templates_default ON collection_templates(collection_id, site_id, is_default DESC);
|
||||
|
||||
-- name: CreateCollectionItemsLookupIndex :exec
|
||||
CREATE INDEX IF NOT EXISTS idx_collection_items_lookup ON collection_items(collection_id, site_id, position);
|
||||
|
||||
-- name: CreateCollectionItemsTemplateIndex :exec
|
||||
CREATE INDEX IF NOT EXISTS idx_collection_items_template ON collection_items(template_id);
|
||||
|
||||
-- name: CreateCollectionItemVersionsLookupIndex :exec
|
||||
CREATE INDEX IF NOT EXISTS idx_collection_item_versions_lookup ON collection_item_versions(item_id, collection_id, site_id, created_at DESC);
|
||||
|
||||
-- name: CreateCollectionTemplatesOneDefaultIndex :exec
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_collection_templates_one_default
|
||||
ON collection_templates(collection_id, site_id)
|
||||
WHERE is_default = TRUE;
|
||||
|
||||
-- name: CreateUpdateFunction :exec
|
||||
CREATE OR REPLACE FUNCTION update_content_timestamp()
|
||||
RETURNS TRIGGER AS $$
|
||||
@@ -44,4 +123,18 @@ DROP TRIGGER IF EXISTS update_content_updated_at ON content;
|
||||
CREATE TRIGGER update_content_updated_at
|
||||
BEFORE UPDATE ON content
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION update_content_timestamp();
|
||||
|
||||
-- name: CreateCollectionsUpdateTrigger :exec
|
||||
DROP TRIGGER IF EXISTS update_collections_updated_at ON collections;
|
||||
CREATE TRIGGER update_collections_updated_at
|
||||
BEFORE UPDATE ON collections
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION update_content_timestamp();
|
||||
|
||||
-- name: CreateCollectionItemsUpdateTrigger :exec
|
||||
DROP TRIGGER IF EXISTS update_collection_items_updated_at ON collection_items;
|
||||
CREATE TRIGGER update_collection_items_updated_at
|
||||
BEFORE UPDATE ON collection_items
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION update_content_timestamp();
|
||||
@@ -9,6 +9,80 @@ import (
|
||||
"context"
|
||||
)
|
||||
|
||||
const createCollectionItemVersionsLookupIndex = `-- name: CreateCollectionItemVersionsLookupIndex :exec
|
||||
CREATE INDEX IF NOT EXISTS idx_collection_item_versions_lookup ON collection_item_versions(item_id, collection_id, site_id, created_at DESC)
|
||||
`
|
||||
|
||||
func (q *Queries) CreateCollectionItemVersionsLookupIndex(ctx context.Context) error {
|
||||
_, err := q.db.ExecContext(ctx, createCollectionItemVersionsLookupIndex)
|
||||
return err
|
||||
}
|
||||
|
||||
const createCollectionItemsLookupIndex = `-- name: CreateCollectionItemsLookupIndex :exec
|
||||
CREATE INDEX IF NOT EXISTS idx_collection_items_lookup ON collection_items(collection_id, site_id, position)
|
||||
`
|
||||
|
||||
func (q *Queries) CreateCollectionItemsLookupIndex(ctx context.Context) error {
|
||||
_, err := q.db.ExecContext(ctx, createCollectionItemsLookupIndex)
|
||||
return err
|
||||
}
|
||||
|
||||
const createCollectionItemsTemplateIndex = `-- name: CreateCollectionItemsTemplateIndex :exec
|
||||
CREATE INDEX IF NOT EXISTS idx_collection_items_template ON collection_items(template_id)
|
||||
`
|
||||
|
||||
func (q *Queries) CreateCollectionItemsTemplateIndex(ctx context.Context) error {
|
||||
_, err := q.db.ExecContext(ctx, createCollectionItemsTemplateIndex)
|
||||
return err
|
||||
}
|
||||
|
||||
const createCollectionTemplatesDefaultIndex = `-- name: CreateCollectionTemplatesDefaultIndex :exec
|
||||
CREATE INDEX IF NOT EXISTS idx_collection_templates_default ON collection_templates(collection_id, site_id, is_default DESC)
|
||||
`
|
||||
|
||||
func (q *Queries) CreateCollectionTemplatesDefaultIndex(ctx context.Context) error {
|
||||
_, err := q.db.ExecContext(ctx, createCollectionTemplatesDefaultIndex)
|
||||
return err
|
||||
}
|
||||
|
||||
const createCollectionTemplatesLookupIndex = `-- name: CreateCollectionTemplatesLookupIndex :exec
|
||||
CREATE INDEX IF NOT EXISTS idx_collection_templates_lookup ON collection_templates(collection_id, site_id)
|
||||
`
|
||||
|
||||
func (q *Queries) CreateCollectionTemplatesLookupIndex(ctx context.Context) error {
|
||||
_, err := q.db.ExecContext(ctx, createCollectionTemplatesLookupIndex)
|
||||
return err
|
||||
}
|
||||
|
||||
const createCollectionTemplatesOneDefaultIndex = `-- name: CreateCollectionTemplatesOneDefaultIndex :exec
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_collection_templates_one_default
|
||||
ON collection_templates(collection_id, site_id)
|
||||
WHERE is_default = TRUE
|
||||
`
|
||||
|
||||
func (q *Queries) CreateCollectionTemplatesOneDefaultIndex(ctx context.Context) error {
|
||||
_, err := q.db.ExecContext(ctx, createCollectionTemplatesOneDefaultIndex)
|
||||
return err
|
||||
}
|
||||
|
||||
const createCollectionsSiteIndex = `-- name: CreateCollectionsSiteIndex :exec
|
||||
CREATE INDEX IF NOT EXISTS idx_collections_site_id ON collections(site_id)
|
||||
`
|
||||
|
||||
func (q *Queries) CreateCollectionsSiteIndex(ctx context.Context) error {
|
||||
_, err := q.db.ExecContext(ctx, createCollectionsSiteIndex)
|
||||
return err
|
||||
}
|
||||
|
||||
const createCollectionsUpdatedAtIndex = `-- name: CreateCollectionsUpdatedAtIndex :exec
|
||||
CREATE INDEX IF NOT EXISTS idx_collections_updated_at ON collections(updated_at)
|
||||
`
|
||||
|
||||
func (q *Queries) CreateCollectionsUpdatedAtIndex(ctx context.Context) error {
|
||||
_, err := q.db.ExecContext(ctx, createCollectionsUpdatedAtIndex)
|
||||
return err
|
||||
}
|
||||
|
||||
const createContentSiteIndex = `-- name: CreateContentSiteIndex :exec
|
||||
CREATE INDEX IF NOT EXISTS idx_content_site_id ON content(site_id)
|
||||
`
|
||||
@@ -51,6 +125,83 @@ func (q *Queries) CreateVersionsLookupIndex(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
const initializeCollectionItemVersionsTable = `-- name: InitializeCollectionItemVersionsTable :exec
|
||||
CREATE TABLE IF NOT EXISTS collection_item_versions (
|
||||
version_id SERIAL PRIMARY KEY,
|
||||
item_id TEXT NOT NULL,
|
||||
collection_id TEXT NOT NULL,
|
||||
site_id TEXT NOT NULL,
|
||||
html_content TEXT NOT NULL,
|
||||
template_id INTEGER NOT NULL,
|
||||
position INTEGER NOT NULL,
|
||||
created_at BIGINT DEFAULT (EXTRACT(EPOCH FROM NOW())) NOT NULL,
|
||||
created_by TEXT DEFAULT 'system' NOT NULL,
|
||||
FOREIGN KEY (item_id, collection_id, site_id) REFERENCES collection_items(item_id, collection_id, site_id) ON DELETE CASCADE
|
||||
)
|
||||
`
|
||||
|
||||
func (q *Queries) InitializeCollectionItemVersionsTable(ctx context.Context) error {
|
||||
_, err := q.db.ExecContext(ctx, initializeCollectionItemVersionsTable)
|
||||
return err
|
||||
}
|
||||
|
||||
const initializeCollectionItemsTable = `-- name: InitializeCollectionItemsTable :exec
|
||||
CREATE TABLE IF NOT EXISTS collection_items (
|
||||
item_id TEXT NOT NULL,
|
||||
collection_id TEXT NOT NULL,
|
||||
site_id TEXT NOT NULL,
|
||||
template_id INTEGER NOT NULL,
|
||||
html_content TEXT NOT NULL,
|
||||
position INTEGER NOT NULL,
|
||||
created_at BIGINT DEFAULT (EXTRACT(EPOCH FROM NOW())) NOT NULL,
|
||||
updated_at BIGINT DEFAULT (EXTRACT(EPOCH FROM NOW())) NOT NULL,
|
||||
last_edited_by TEXT DEFAULT 'system' NOT NULL,
|
||||
PRIMARY KEY (item_id, collection_id, site_id),
|
||||
FOREIGN KEY (collection_id, site_id) REFERENCES collections(id, site_id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (template_id) REFERENCES collection_templates(template_id) ON DELETE RESTRICT
|
||||
)
|
||||
`
|
||||
|
||||
func (q *Queries) InitializeCollectionItemsTable(ctx context.Context) error {
|
||||
_, err := q.db.ExecContext(ctx, initializeCollectionItemsTable)
|
||||
return err
|
||||
}
|
||||
|
||||
const initializeCollectionTemplatesTable = `-- name: InitializeCollectionTemplatesTable :exec
|
||||
CREATE TABLE IF NOT EXISTS collection_templates (
|
||||
template_id SERIAL PRIMARY KEY,
|
||||
collection_id TEXT NOT NULL,
|
||||
site_id TEXT NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
html_template TEXT NOT NULL,
|
||||
is_default BOOLEAN DEFAULT FALSE NOT NULL,
|
||||
created_at BIGINT DEFAULT (EXTRACT(EPOCH FROM NOW())) NOT NULL,
|
||||
FOREIGN KEY (collection_id, site_id) REFERENCES collections(id, site_id) ON DELETE CASCADE
|
||||
)
|
||||
`
|
||||
|
||||
func (q *Queries) InitializeCollectionTemplatesTable(ctx context.Context) error {
|
||||
_, err := q.db.ExecContext(ctx, initializeCollectionTemplatesTable)
|
||||
return err
|
||||
}
|
||||
|
||||
const initializeCollectionsTable = `-- name: InitializeCollectionsTable :exec
|
||||
CREATE TABLE IF NOT EXISTS collections (
|
||||
id TEXT NOT NULL,
|
||||
site_id TEXT NOT NULL,
|
||||
container_html TEXT NOT NULL,
|
||||
created_at BIGINT DEFAULT (EXTRACT(EPOCH FROM NOW())) NOT NULL,
|
||||
updated_at BIGINT DEFAULT (EXTRACT(EPOCH FROM NOW())) NOT NULL,
|
||||
last_edited_by TEXT DEFAULT 'system' NOT NULL,
|
||||
PRIMARY KEY (id, site_id)
|
||||
)
|
||||
`
|
||||
|
||||
func (q *Queries) InitializeCollectionsTable(ctx context.Context) error {
|
||||
_, err := q.db.ExecContext(ctx, initializeCollectionsTable)
|
||||
return err
|
||||
}
|
||||
|
||||
const initializeSchema = `-- name: InitializeSchema :exec
|
||||
CREATE TABLE IF NOT EXISTS content (
|
||||
id TEXT NOT NULL,
|
||||
|
||||
Reference in New Issue
Block a user