fix: stop "." export sentinel from clobbering real post content
ReblogRecord (TraverseDirectory's .txt-export parser) and the --likes API path both default every content field to the literal "." when their source has no value for that field, then pass it straight into UpdatePost. A blog with two export folders in different field formats -- a duplicate "_2" folder, or an export whose field set changed over time -- sends one record with real Title/Tags/Slug and another with those fields "." because that format never had a line for them. Re-importing both on every run flipped the row back and forth forever: net content never changed, but DateModified moved on every pass since each write really did change a column relative to the other write, just not relative to the true value. Every content column in UpdatePost's SET list is now guarded the same way RootBlogName/RootURL already were -- a "." parameter leaves the existing value alone instead of overwriting it -- and the change-detection WHERE clause carries the same exception, so a "."-only difference no longer fires the UPDATE at all. Deliberately narrow: only the literal "." is the sentinel, so an explicit empty string from a real record still overwrites. Verified against a throwaway DB using the exact SQL text and parameter binding from UpdatePost, reproducing the an-angry-wolf/adore-blk scenario found in the live DB: re-importing conflicting "." records now writes zero rows and leaves DateModified untouched, while a genuine content change still fires and still moves it. Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
@@ -101,6 +101,29 @@ new post arriving for a known blog reopens `HasBeenOutput` but must leave `DateA
|
||||
a new post is not a new blog, and rewriting the column both destroys the registration date
|
||||
and makes every insert look like a change.
|
||||
|
||||
**`"."` in a `Posts` content field means "not supplied", not "empty".** `ReblogRecord`
|
||||
(`TraverseDirectory`'s parser for the local `.txt` export tree) and the `--likes` API path
|
||||
both default every content field to the literal string `"."` when their source has no value
|
||||
for it, then pass that straight to `UpdatePost`. A blog with two export folders in different
|
||||
field formats (a duplicate `_2` folder, or a Tumblr export whose field set changed over time)
|
||||
sends one record with a real `Title`/`Tags`/`Slug` and another with those fields `"."`
|
||||
because that format never had a line for them — and without a guard, re-importing both on
|
||||
every run flips the row back and forth forever, bumping `DateModified` on every pass even
|
||||
though the true content never changes.
|
||||
|
||||
- Every content column in `UpdatePost`'s `SET` list is guarded the same way `RootBlogName`/
|
||||
`RootURL` already were: `col = CASE WHEN @col = '.' THEN col ELSE @col END`. A `"."`
|
||||
parameter leaves the existing value alone instead of overwriting it
|
||||
- The change-detection `WHERE` clause carries the same exception —
|
||||
`(@col <> '.' AND IFNULL(col, '') <> @col) OR ...` — so a `"."`-only difference does not
|
||||
make the statement fire at all, and `DateModified` stays put
|
||||
- Deliberately narrow: only the literal `"."` is the sentinel. An explicit empty string from
|
||||
a real record still overwrites, same as before this fix. `postID`, `BlogName`, `hasImage`,
|
||||
`ByLikes` are not part of this convention and are unaffected
|
||||
- If a new content field is added to `Posts`/`UpdatePost`, decide explicitly whether its
|
||||
source can legitimately supply `"."` as "field absent" before deciding whether it needs
|
||||
the same `CASE` treatment — don't assume every column needs it
|
||||
|
||||
### Testing
|
||||
- No existing test suite; use xUnit if adding tests
|
||||
- Test critical logic: `ApiKeyPool` init, color parsing, config persistence
|
||||
|
||||
Reference in New Issue
Block a user