Skip to content

Commit

Permalink
fix sticky parent tables
Browse files Browse the repository at this point in the history
Fixes parent tables being sticky when a lateral query is re-used by making a defensive copy of the lateral query.
  • Loading branch information
rosettaroberts-impact committed Apr 9, 2024
1 parent b4314f5 commit 6e64759
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 4 deletions.
22 changes: 22 additions & 0 deletions src/db/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,28 @@ export class SQLFragment<RunResult = pg.QueryResult['rows'], Constraint = never>

constructor(protected literals: string[], protected expressions: SQL[]) { }

/**
* Performs a shallow copy of this SQLFragment, optionally overriding some of its properties.
* @param override The properties to override
*/
copy(override?: {
literals?: string[];
expressions?: SQL[];
parentTable?: string;
preparedName?: string;
noop?: boolean;
noopResult?: any;
}): SQLFragment<RunResult, Constraint> {
const { literals = this.literals, expressions = this.expressions, ...overrideRest } = override ?? {};
const copy = new SQLFragment<RunResult, Constraint>(literals, expressions);
return Object.assign(copy, {
parentTable: this.parentTable,
preparedName: this.preparedName,
noop: this.noop,
noopResult: this.noopResult
}, overrideRest);
}

/**
* Instruct Postgres to treat this as a prepared statement: see
* https://node-postgres.com/features/queries#prepared-statements
Expand Down
7 changes: 3 additions & 4 deletions src/db/shortcuts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -542,12 +542,11 @@ export const select: SelectSignatures = function (
}),
lateralSQL = lateral === undefined ? [] :
lateral instanceof SQLFragment ? (() => {
lateral.parentTable = alias;
return sql` LEFT JOIN LATERAL (${lateral}) AS "lateral_passthru" ON true`;
return sql` LEFT JOIN LATERAL (${lateral.copy({ parentTable: alias })}) AS "lateral_passthru" ON true`;
})() :
Object.keys(lateral).sort().map(k => {
const subQ = lateral[k];
subQ.parentTable = alias; // enables `parent('column')` in subquery's Whereables
/// enables `parent('column')` in subquery's Whereables
const subQ = lateral[k].copy({ parentTable: alias });
return sql` LEFT JOIN LATERAL (${subQ}) AS "lateral_${raw(k)}" ON true`;
});

Expand Down

0 comments on commit 6e64759

Please sign in to comment.