Merge branch 'carry-every-date-through-an-adjustment'
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
commit
cb9f98f551
19
CLAUDE.md
19
CLAUDE.md
@ -408,6 +408,18 @@ Turning a region back into slices re-derives, per cell, the same filters Perspec
|
|||||||
|
|
||||||
All three operations follow the same structure: insert a `pf.log` row in a CTE, then insert forecast rows referencing its id. `{{where_clause}}` is built from the slice; `{{exclude_clause}}` blocks `exclude_iters` rows.
|
All three operations follow the same structure: insert a `pf.log` row in a CTE, then insert forecast rows referencing its id. `{{where_clause}}` is built from the slice; `{{exclude_clause}}` blocks `exclude_iters` rows.
|
||||||
|
|
||||||
|
**Every date column travels, not just the first.** `dataCols` is
|
||||||
|
`[...dims, ...dateCols, value, units]`. It used to be `dateCols[0]`, so on a
|
||||||
|
source with order, requested and ship dates, scale and recode wrote rows whose
|
||||||
|
`rdate` and `sdate_e` were **null** — and because the derived period dimensions
|
||||||
|
(`rseas`, `smon_e`) are dimensions and were copied with the rest, the labels
|
||||||
|
read correctly while the dates under them were gone. Both columns are
|
||||||
|
`role = 'date'` and therefore sliceable, so an adjustment scoped to a ship date
|
||||||
|
matched no adjustment row that had ever been written. Clone and the loads were
|
||||||
|
always right. The wider GROUP BY costs almost nothing on `osm_skinny`
|
||||||
|
(971,185 → 971,352 groups) because `ordnum`/`ordline` already make a row
|
||||||
|
near-unique.
|
||||||
|
|
||||||
- **Scale** — distributes `value_incr`/`units_incr` proportionally across rows in the slice using window functions
|
- **Scale** — distributes `value_incr`/`units_incr` proportionally across rows in the slice using window functions
|
||||||
- **Recode** — inserts negative rows (zero out original) + positive rows with `{{set_clause}}` dimension overrides; both share the same logid
|
- **Recode** — inserts negative rows (zero out original) + positive rows with `{{set_clause}}` dimension overrides; both share the same logid
|
||||||
- **Clone** — copies the slice with `{{set_clause}}` overrides and `{{scale_factor}}` multiplier; original untouched
|
- **Clone** — copies the slice with `{{set_clause}}` overrides and `{{scale_factor}}` multiplier; original untouched
|
||||||
@ -539,6 +551,13 @@ column.
|
|||||||
|
|
||||||
## Known issues / active work
|
## Known issues / active work
|
||||||
|
|
||||||
|
- **Rows written before 2026-09-21 have null `rdate`/`sdate_e`.** The generator
|
||||||
|
fix above changes what gets written from here on; it does not repair what is
|
||||||
|
there. On `fc_osm_skinny_29` that is ~270k scale and recode rows. A backfill
|
||||||
|
would have to re-derive each from the baseline rows at the same coordinate,
|
||||||
|
which is possible but is inference, not recovery — deleting and replaying
|
||||||
|
those log entries is the honest repair
|
||||||
|
|
||||||
- **Zero-row operations report success.** Scale refuses with "Nothing to
|
- **Zero-row operations report success.** Scale refuses with "Nothing to
|
||||||
scale…" when its slice matches nothing; recode and clone commit an empty log
|
scale…" when its slice matches nothing; recode and clone commit an empty log
|
||||||
entry and return `rows_affected: 0`. A recode of a rep whose rows are all
|
entry and return `rows_affected: 0`. A recode of a rep whose rows are all
|
||||||
|
|||||||
@ -198,19 +198,31 @@ function generateSQL(source, colMeta) {
|
|||||||
|
|
||||||
const valueCol = valueCols[0];
|
const valueCol = valueCols[0];
|
||||||
const unitsCol = unitsCols[0];
|
const unitsCol = unitsCols[0];
|
||||||
const dateCol = dateCols[0];
|
|
||||||
|
|
||||||
if (!valueCol) throw new Error('No value column defined in col_meta');
|
if (!valueCol) throw new Error('No value column defined in col_meta');
|
||||||
if (!dateCol) throw new Error('No date column defined in col_meta');
|
if (!dateCols.length) throw new Error('No date column defined in col_meta');
|
||||||
if (dims.length === 0) throw new Error('No dimension columns defined in col_meta');
|
if (dims.length === 0) throw new Error('No dimension columns defined in col_meta');
|
||||||
|
|
||||||
const srcTable = `"${source.schema}"."${source.tname}"`;
|
const srcTable = `"${source.schema}"."${source.tname}"`;
|
||||||
const dataCols = [...dims, dateCol, valueCol, unitsCol].filter(Boolean);
|
// Every date column, not just the primary one. Scale and recode used to
|
||||||
|
// carry dateCols[0] alone, so a source with order, requested and ship dates
|
||||||
|
// wrote adjustment rows whose rdate and sdate_e were *null* -- not stale,
|
||||||
|
// absent. Those columns are role 'date' and therefore sliceable, so a later
|
||||||
|
// adjustment scoped to a ship date matched no adjustment row ever written,
|
||||||
|
// and any reader that dated the forecast by ship date lost every
|
||||||
|
// adjustment silently. The derived period dimensions (rseas, smon_e) were
|
||||||
|
// fine throughout, being dimensions and copied with the rest -- which is
|
||||||
|
// what made it invisible: the labels were right and the dates underneath
|
||||||
|
// them were gone.
|
||||||
|
const dataCols = [...dims, ...dateCols, valueCol, unitsCol].filter(Boolean);
|
||||||
const effectiveValue = dataCols.includes(valueCol) ? valueCol : null;
|
const effectiveValue = dataCols.includes(valueCol) ? valueCol : null;
|
||||||
const effectiveUnits = dataCols.includes(unitsCol) ? unitsCol : null;
|
const effectiveUnits = dataCols.includes(unitsCol) ? unitsCol : null;
|
||||||
const insertCols = [...dataCols.map(q), 'pf_iter', 'pf_logid', 'pf_user', 'pf_created_at'].join(', ');
|
const insertCols = [...dataCols.map(q), 'pf_iter', 'pf_logid', 'pf_user', 'pf_created_at'].join(', ');
|
||||||
const selectData = dataCols.map(q).join(', ');
|
const selectData = dataCols.map(q).join(', ');
|
||||||
const dimsJoined = dims.map(q).join(', ');
|
const dimsJoined = dims.map(q).join(', ');
|
||||||
|
// The date columns as a select list, in the same order dataCols lists them,
|
||||||
|
// so it lines up with insertCols positionally.
|
||||||
|
const datesJoined = dateCols.map(q).join(', ');
|
||||||
|
|
||||||
// Baseline and reference copy the source row wholesale, so they carry every
|
// Baseline and reference copy the source row wholesale, so they carry every
|
||||||
// measure and every date — not just the primary one the operations act on.
|
// measure and every date — not just the primary one the operations act on.
|
||||||
@ -410,7 +422,7 @@ SELECT count(*) AS rows_affected, (SELECT id FROM ilog) AS log_id FROM ins`.trim
|
|||||||
// comes to the same figure the ungrouped window produced.
|
// comes to the same figure the ungrouped window produced.
|
||||||
const baseSelectParts = [
|
const baseSelectParts = [
|
||||||
...dimsJoined ? [dimsJoined] : [],
|
...dimsJoined ? [dimsJoined] : [],
|
||||||
q(dateCol),
|
datesJoined,
|
||||||
effectiveValue ? `sum(${q(effectiveValue)}) AS ${q(effectiveValue)}` : null,
|
effectiveValue ? `sum(${q(effectiveValue)}) AS ${q(effectiveValue)}` : null,
|
||||||
effectiveUnits ? `sum(${q(effectiveUnits)}) AS ${q(effectiveUnits)}` : null,
|
effectiveUnits ? `sum(${q(effectiveUnits)}) AS ${q(effectiveUnits)}` : null,
|
||||||
effectiveValue ? `sum(sum(${q(effectiveValue)})) OVER () AS total_value` : null,
|
effectiveValue ? `sum(sum(${q(effectiveValue)})) OVER () AS total_value` : null,
|
||||||
@ -430,12 +442,12 @@ ilog AS (
|
|||||||
WHERE {{where_clause}}
|
WHERE {{where_clause}}
|
||||||
{{exclude_clause}}
|
{{exclude_clause}}
|
||||||
GROUP BY
|
GROUP BY
|
||||||
${groupCols([...dims, dateCol])}
|
${groupCols([...dims, ...dateCols])}
|
||||||
)
|
)
|
||||||
,ins AS (
|
,ins AS (
|
||||||
INSERT INTO {{fc_table}} (${insertCols})
|
INSERT INTO {{fc_table}} (${insertCols})
|
||||||
SELECT
|
SELECT
|
||||||
${[dimsJoined, q(dateCol), ...(effectiveValue ? [vSel] : []), ...(effectiveUnits ? [uSel] : [])].join(',\n ')},
|
${[dimsJoined, datesJoined, ...(effectiveValue ? [vSel] : []), ...(effectiveUnits ? [uSel] : [])].join(',\n ')},
|
||||||
'scale', (SELECT id FROM ilog), '{{pf_user}}', now()
|
'scale', (SELECT id FROM ilog), '{{pf_user}}', now()
|
||||||
FROM base
|
FROM base
|
||||||
RETURNING *
|
RETURNING *
|
||||||
@ -454,23 +466,23 @@ ilog AS (
|
|||||||
,src AS (
|
,src AS (
|
||||||
SELECT
|
SELECT
|
||||||
${dimsJoined},
|
${dimsJoined},
|
||||||
${q(dateCol)}${effectiveValue ? `,\n sum(${q(effectiveValue)}) AS ${q(effectiveValue)}` : ''}${effectiveUnits ? `,\n sum(${q(effectiveUnits)}) AS ${q(effectiveUnits)}` : ''}
|
${datesJoined}${effectiveValue ? `,\n sum(${q(effectiveValue)}) AS ${q(effectiveValue)}` : ''}${effectiveUnits ? `,\n sum(${q(effectiveUnits)}) AS ${q(effectiveUnits)}` : ''}
|
||||||
FROM {{fc_table}}
|
FROM {{fc_table}}
|
||||||
WHERE {{where_clause}}
|
WHERE {{where_clause}}
|
||||||
{{exclude_clause}}
|
{{exclude_clause}}
|
||||||
GROUP BY
|
GROUP BY
|
||||||
${groupCols([...dims, dateCol])}
|
${groupCols([...dims, ...dateCols])}
|
||||||
)
|
)
|
||||||
,neg AS (
|
,neg AS (
|
||||||
INSERT INTO {{fc_table}} (${insertCols})
|
INSERT INTO {{fc_table}} (${insertCols})
|
||||||
SELECT ${dimsJoined}, ${q(dateCol)}, ${effectiveValue ? `-${q(effectiveValue)}` : '0'}${effectiveUnits ? `, -${q(effectiveUnits)}` : ''},
|
SELECT ${dimsJoined}, ${datesJoined}, ${effectiveValue ? `-${q(effectiveValue)}` : '0'}${effectiveUnits ? `, -${q(effectiveUnits)}` : ''},
|
||||||
'recode', (SELECT id FROM ilog), '{{pf_user}}', now()
|
'recode', (SELECT id FROM ilog), '{{pf_user}}', now()
|
||||||
FROM src
|
FROM src
|
||||||
RETURNING *
|
RETURNING *
|
||||||
)
|
)
|
||||||
,ins AS (
|
,ins AS (
|
||||||
INSERT INTO {{fc_table}} (${insertCols})
|
INSERT INTO {{fc_table}} (${insertCols})
|
||||||
SELECT {{set_clause}}, ${q(dateCol)}, ${effectiveValue ? q(effectiveValue) : '0'}${effectiveUnits ? `, ${q(effectiveUnits)}` : ''},
|
SELECT {{set_clause}}, ${datesJoined}, ${effectiveValue ? q(effectiveValue) : '0'}${effectiveUnits ? `, ${q(effectiveUnits)}` : ''},
|
||||||
'recode', (SELECT id FROM ilog), '{{pf_user}}', now()
|
'recode', (SELECT id FROM ilog), '{{pf_user}}', now()
|
||||||
FROM src
|
FROM src
|
||||||
RETURNING *
|
RETURNING *
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user