diff --git a/routes/operations.js b/routes/operations.js index 1b4385c..2c97cbb 100644 --- a/routes/operations.js +++ b/routes/operations.js @@ -32,6 +32,22 @@ module.exports = function(pool) { return clean; } + // How a multi-slice request is split into statements. + // + // 'each' — one statement per slice, so every slice reaches its target on + // its own and gets its own log entry + // 'prorate' — a single statement over all of them, letting the SQL's + // sum() OVER () distribute across the whole pool + // + // Only scale has a target to prorate towards; recode and clone rewrite rows + // rather than distribute an amount, so for them this only decides whether the + // work lands as one log entry or several. + function sliceUnits(slices, ctx, applyMode) { + return applyMode === 'each' + ? slices.map(sl => ({ slices: [sl], where: buildWhere(sl, ctx.filterCols) })) + : [{ slices, where: buildWhereAny(slices, ctx.filterCols) }]; + } + // A slice is only meaningful if at least one of its keys is a filterable // column. buildWhere silently drops unknown keys, so {"typo": "x"} would // otherwise reduce to TRUE and apply the operation to the whole version. @@ -572,9 +588,7 @@ module.exports = function(pool) { // sum() OVER () distribute the increment across the whole pool. // 'each' runs the same statement once per slice, so every slice // reaches the target on its own and gets its own log entry. - const units = applyMode === 'each' - ? slices.map(sl => ({ slices: [sl], where: buildWhere(sl, ctx.filterCols) })) - : [{ slices, where: buildWhereAny(slices, ctx.filterCols) }]; + const units = sliceUnits(slices, ctx, applyMode); const client = await pool.connect(); let committed = false; @@ -656,7 +670,7 @@ module.exports = function(pool) { const excludeClause = buildExcludeClause(ctx.version.exclude_iters); const setClause = buildSetClause(ctx.dimCols, set); - const units = sliceUnits(slices, ctx, apply_mode); + const units = sliceUnits(slices, ctx, apply_mode === 'each' ? 'each' : 'prorate'); const client = await pool.connect(); let committed = false; @@ -712,7 +726,7 @@ module.exports = function(pool) { const scaleFactor = (scale != null) ? parseFloat(scale) : 1.0; const excludeClause = buildExcludeClause(ctx.version.exclude_iters); const setClause = buildSetClause(ctx.dimCols, set); - const units = sliceUnits(slices, ctx, apply_mode); + const units = sliceUnits(slices, ctx, apply_mode === 'each' ? 'each' : 'prorate'); const client = await pool.connect(); let committed = false;