Browse Source

Foreign key constraint from parameters to posts

master
Jan-Lukas Else 4 weeks ago
parent
commit
33000461de
  1. 16
      dbmigrations/00028.sql
  2. 1
      docs/storage.md
  3. 20
      postsDb.go
  4. 46
      postsDb_test.go
  5. 4
      utils.go

16
dbmigrations/00028.sql

@ -0,0 +1,16 @@
-- Add foreign key constraint to post_parameters table
create table post_parameters_new (
id integer primary key autoincrement,
path text not null,
parameter text not null,
value text not null default '',
foreign key (path) references posts(path) on update cascade on delete cascade
);
drop view posts_fts_view;
create view posts_fts_view as select p.rowid as id, p.path as path, coalesce(pp.value, '') as title, p.content as content from posts p left outer join (select * from post_parameters_new pp where pp.parameter = 'title') pp on p.path = pp.path;
insert into post_parameters_new select * from post_parameters;
drop table post_parameters;
alter table post_parameters_new rename to post_parameters;
create index index_post_parameters on post_parameters (path, parameter, value);
create index index_post_parameters_par_val_pat on post_parameters (parameter, value, path);
insert into posts_fts(posts_fts) values ('rebuild');

1
docs/storage.md

@ -21,6 +21,7 @@ post_parameters
posts
posts_fts
queue
reactions
sessions
shortpath
webmentions

20
postsDb.go

@ -182,20 +182,18 @@ func (db *database) savePost(p *post, o *postCreationOptions) error {
sqlBuilder.WriteString("insert into posts (path, content, published, updated, blog, section, status, priority) values (?, ?, ?, ?, ?, ?, ?, ?);")
sqlArgs = append(sqlArgs, p.Path, p.Content, toUTCSafe(p.Published), toUTCSafe(p.Updated), p.Blog, p.Section, p.Status, p.Priority)
} else {
// Update old post
sqlBuilder.WriteString("update posts set path = ?, content = ?, published = ?, updated = ?, blog = ?, section = ?, status = ?, priority = ? where path = ?;")
sqlArgs = append(sqlArgs, p.Path, p.Content, toUTCSafe(p.Published), toUTCSafe(p.Updated), p.Blog, p.Section, p.Status, p.Priority, o.oldPath)
// Delete post parameters
sqlBuilder.WriteString("delete from post_parameters where path = ?;")
sqlArgs = append(sqlArgs, o.oldPath)
// Update old post
sqlBuilder.WriteString("update posts set path = ?, content = ?, published = ?, updated = ?, blog = ?, section = ?, status = ?, priority = ? where path = ?;")
sqlArgs = append(sqlArgs, p.Path, p.Content, toUTCSafe(p.Published), toUTCSafe(p.Updated), p.Blog, p.Section, p.Status, p.Priority, o.oldPath)
}
// Insert post parameters
for param, value := range p.Parameters {
for _, value := range value {
if value != "" {
sqlBuilder.WriteString("insert into post_parameters (path, parameter, value) values (?, ?, ?);")
sqlArgs = append(sqlArgs, p.Path, param, value)
}
for _, value := range lo.Filter(value, loStringNotEmpty) {
sqlBuilder.WriteString("insert into post_parameters (path, parameter, value) values (?, ?, ?);")
sqlArgs = append(sqlArgs, p.Path, param, value)
}
}
// Commit transaction
@ -228,7 +226,7 @@ func (a *goBlog) deletePost(path string) error {
if strings.HasSuffix(string(p.Status), statusDeletedSuffix) {
// Post is already marked as deleted, delete it from database
if _, err = a.db.exec(
`begin; delete from posts where path = ?; delete from post_parameters where path = ?; insert or ignore into deleted (path) values (?); commit;`,
`begin; delete from posts where path = ?; insert or ignore into deleted (path) values (?); commit;`,
dbNoCache, p.Path, p.Path, p.Path,
); err != nil {
return err
@ -249,7 +247,7 @@ func (a *goBlog) deletePost(path string) error {
p.Parameters["deleted"] = []string{deletedTime}
// Mark post as deleted
if _, err = a.db.exec(
`begin; update posts set status = ? where path = ?; delete from post_parameters where path = ? and value = 'deleted'; insert into post_parameters (path, parameter, value) values (?, 'deleted', ?); commit;`,
`begin; update posts set status = ? where path = ?; delete from post_parameters where path = ? and parameter = 'deleted'; insert into post_parameters (path, parameter, value) values (?, 'deleted', ?); commit;`,
dbNoCache, p.Status, p.Path, p.Path, p.Path, deletedTime,
); err != nil {
return err
@ -298,7 +296,7 @@ func (a *goBlog) undeletePost(path string) error {
func (db *database) replacePostParam(path, param string, values []string) error {
// Filter empty values
values = lo.Filter(values, func(v string, _ int) bool { return v != "" })
values = lo.Filter(values, loStringNotEmpty)
// Lock post creation
db.pcm.Lock()
defer db.pcm.Unlock()

46
postsDb_test.go

@ -394,3 +394,49 @@ func Test_replaceParams(t *testing.T) {
assert.Len(t, union, 3)
}
}
func Test_postDeletesParams(t *testing.T) {
app := &goBlog{
cfg: createDefaultTestConfig(t),
}
_ = app.initConfig()
_ = app.initDatabase(false)
defer app.db.close()
app.initComponents(false)
err := app.createPost(&post{
Path: "/test/abc",
Content: "ABC",
Parameters: map[string][]string{
"test": {
"ABC", "DEF", "GHI",
},
},
})
require.NoError(t, err)
// Delete the first time (mark as delete)
err = app.deletePost("/test/abc")
require.NoError(t, err)
row, err := app.db.queryRow("select count(*) from post_parameters where path = ? and parameter = ?", "/test/abc", "test")
require.NoError(t, err)
var count int
err = row.Scan(&count)
require.NoError(t, err)
assert.Equal(t, 3, count)
// Delete the second time (actually delete)
err = app.deletePost("/test/abc")
require.NoError(t, err)
row, err = app.db.queryRow("select count(*) from post_parameters where path = ? and parameter = ?", "/test/abc", "test")
require.NoError(t, err)
err = row.Scan(&count)
require.NoError(t, err)
assert.Equal(t, 0, count)
}

4
utils.go

@ -396,3 +396,7 @@ func stringToInt(s string) int {
i, _ := strconv.Atoi(s)
return i
}
func loStringNotEmpty(s string, _ int) bool {
return s != ""
}

Loading…
Cancel
Save