fix(selfhost): translate SQLite julianday() for the Postgres dialect - #9838
Conversation
`translateFunctions` rewrote date()/strftime()/json_extract() for self-host Postgres but not `julianday()`, so submitter-reputation.ts's avgMergeMs column (`(julianday(merged_at) - julianday(created_at)) * 86400000`) reached Postgres as a "function julianday does not exist" error, swallowed by the fail-safe read. Add a rule mapping `julianday(<expr>)` to its Julian Day NUMBER, `(EXTRACT(EPOCH FROM (<expr>)::timestamptz) / 86400.0 + 2440587.5)`, using ::timestamptz like the sibling date()/strftime() rules so the TEXT ISO timestamps the app writes are read identically. The +2440587.5 offset cancels in the subtraction, so the `(a - b) * 86400000` still yields milliseconds. Add a drift guard: a test that scans every src/** SQL string literal (comments stripped) for the ten SQLite-only scalar functions (julianday, unixepoch, json_group_array, json_array_length, group_concat, printf, iif, glob, randomblob, total) and fails if any survives translateSql untranslated — plus a positive test that its detection helper flags a synthetic untranslated call, so the guard is not trivially green. Closes JSONbored#9648
|
Warning ⏸️ LoopOver review result - manual review recommendedReview updated: 2026-07-29 13:02:50 UTC
Review summary Nits — 3 non-blocking
Decision drivers
Context & advisory signals — never blocks the verdict
Linked issue satisfactionAddressed Review context
Contributor next steps
Signal definitions
🧪 Chat with LoopOverAsk LoopOver a question about this PR directly in a comment — grounded only in the same cached, public-safe facts shown above, never a new claim.
Full command reference: https://loopover.ai/docs/loopover-commands 🧪 Experimental — new and may change. 🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed 💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →. Checked by LoopOver, a quiet PR intelligence layer for OSS maintainers.
|
|
Superagent didn't find any vulnerabilities or security issues in this PR. |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #9838 +/- ##
==========================================
+ Coverage 79.03% 79.06% +0.02%
==========================================
Files 280 281 +1
Lines 58366 58445 +79
Branches 6697 6714 +17
==========================================
+ Hits 46128 46207 +79
Misses 11955 11955
Partials 283 283
Flags with carried forward coverage won't be shown. Click here to find out more.
|
What & why
translateFunctions(src/selfhost/pg-dialect.ts) rewritesdate(),strftime(),datetime(),json_extract()and more for the self-host Postgres dialect — but notjulianday(). Sosubmitter-reputation.ts'savgMergeMscolumn,reached Postgres as a
function julianday(...) does not existerror, swallowed by the fail-safe read — the same class of silent self-host gap #8171 kept closing.The fix
Map
julianday(<expr>)to its Julian Day number:::timestamptzmatches the siblingdate()/strftime()rules, so the TEXT ISO timestamps the app writes are read identically.+ 2440587.5offset cancels in the subtraction, so(julianday(a) - julianday(b)) * 86400000still yields milliseconds exactly as before.Drift guard
A new test scans every
src/**SQL string literal (TS comments stripped first, so English prose like "…their total (…)" or areview.exclude_pathsglob isn't mistaken for SQL) for the ten SQLite-only scalar functions —julianday, unixepoch, json_group_array, json_array_length, group_concat, printf, iif, glob, randomblob, total— and fails if any survivestranslateSqluntranslated. A companion positive test asserts the detection helper flags a synthetic untranslated call (unixepoch(...)), so the guard is not trivially green.Tests (
test/unit/selfhost-pg-dialect.test.ts)julianday()translates (single, whitespaced, and the exactavgMergeMstwo-call expression → nojuliandayleft, ms arithmetic preserved) — fails onmain.listSubmitterCohortRowsstatement text has no remainingjuliandayaftertranslateSql— fails onmain.src/**SQL literal uses an untranslated SQLite-only function (flagssubmitter-reputation.ts: juliandayonmain), and its helper catches a syntheticunixepoch(.Validation
npm run typecheckgreen; the pg-dialect suite green.pg-dialect.tsis 100% (the added rule).git diff --check <base> HEADclean; diff is two files, no schema/migration change.Closes #9648