@tanstack/db
Version:
A reactive client store for building super fast apps on sync
142 lines (141 loc) • 5.15 kB
JavaScript
import { map, join, consolidate, filter } from "@electric-sql/d2mini";
import { evaluateConditionOnNamespacedRow } from "./evaluators.js";
import { extractJoinKey } from "./extractors.js";
function processJoinClause(pipeline, query, tables, mainTableAlias, allInputs) {
if (!query.join) return pipeline;
const input = allInputs[query.from];
for (const joinClause of query.join) {
const joinedTableAlias = joinClause.as || joinClause.from;
const joinType = joinClause.type === `cross` ? `inner` : joinClause.type;
const [mainKeyRef, , joinedKeyRefs] = joinClause.on;
const mainPipeline = pipeline.pipe(
map(([currentKey, namespacedRow]) => {
const mainRow = namespacedRow[mainTableAlias];
const key = extractJoinKey(mainRow, mainKeyRef, mainTableAlias);
return [key, [currentKey, namespacedRow]];
})
);
let joinedTableInput;
if (allInputs[joinClause.from]) {
joinedTableInput = allInputs[joinClause.from];
} else {
joinedTableInput = input.graph.newInput();
}
tables[joinedTableAlias] = joinedTableInput;
const joinedPipeline = joinedTableInput.pipe(
map(([currentKey, row]) => {
const namespacedRow = { [joinedTableAlias]: row };
const key = extractJoinKey(row, joinedKeyRefs, joinedTableAlias);
return [key, [currentKey, namespacedRow]];
})
);
switch (joinType) {
case `inner`:
pipeline = mainPipeline.pipe(
join(joinedPipeline, `inner`),
consolidate(),
processJoinResults(mainTableAlias, joinedTableAlias, joinClause)
);
break;
case `left`:
pipeline = mainPipeline.pipe(
join(joinedPipeline, `left`),
consolidate(),
processJoinResults(mainTableAlias, joinedTableAlias, joinClause)
);
break;
case `right`:
pipeline = mainPipeline.pipe(
join(joinedPipeline, `right`),
consolidate(),
processJoinResults(mainTableAlias, joinedTableAlias, joinClause)
);
break;
case `full`:
pipeline = mainPipeline.pipe(
join(joinedPipeline, `full`),
consolidate(),
processJoinResults(mainTableAlias, joinedTableAlias, joinClause)
);
break;
default:
pipeline = mainPipeline.pipe(
join(joinedPipeline, `inner`),
consolidate(),
processJoinResults(mainTableAlias, joinedTableAlias, joinClause)
);
}
}
return pipeline;
}
function processJoinResults(mainTableAlias, joinedTableAlias, joinClause) {
return function(pipeline) {
return pipeline.pipe(
// Process the join result and handle nulls in the same step
map((result) => {
const [_key, [main, joined]] = result;
const mainKey = main == null ? void 0 : main[0];
const mainNamespacedRow = main == null ? void 0 : main[1];
const joinedKey = joined == null ? void 0 : joined[0];
const joinedNamespacedRow = joined == null ? void 0 : joined[1];
if (joinClause.type === `inner` || joinClause.type === `cross`) {
if (!mainNamespacedRow || !joinedNamespacedRow) {
return void 0;
}
}
if (joinClause.type === `left` && !mainNamespacedRow) {
return void 0;
}
if (joinClause.type === `right` && !joinedNamespacedRow) {
return void 0;
}
const mergedNamespacedRow = {};
if (mainNamespacedRow) {
Object.entries(mainNamespacedRow).forEach(
([tableAlias, tableData]) => {
mergedNamespacedRow[tableAlias] = tableData;
}
);
}
if (joinedNamespacedRow) {
Object.entries(joinedNamespacedRow).forEach(
([tableAlias, tableData]) => {
mergedNamespacedRow[tableAlias] = tableData;
}
);
} else if (joinClause.type === `left` || joinClause.type === `full`) ;
if (!mainNamespacedRow && (joinClause.type === `right` || joinClause.type === `full`)) ;
const newKey = `[${mainKey},${joinedKey}]`;
return [newKey, mergedNamespacedRow];
}),
// Filter out undefined results
filter((value) => value !== void 0),
// Process the ON condition
filter(([_key, namespacedRow]) => {
if (!joinClause.on || joinClause.type === `cross`) {
return true;
}
if (joinClause.type === `left` && namespacedRow[joinedTableAlias] === void 0) {
return true;
}
if (joinClause.type === `right` && namespacedRow[mainTableAlias] === void 0) {
return true;
}
if (joinClause.type === `full` && (namespacedRow[mainTableAlias] === void 0 || namespacedRow[joinedTableAlias] === void 0)) {
return true;
}
return evaluateConditionOnNamespacedRow(
namespacedRow,
joinClause.on,
mainTableAlias,
joinedTableAlias
);
})
);
};
}
export {
processJoinClause,
processJoinResults
};
//# sourceMappingURL=joins.js.map