@tanstack/db-ivm
Version:
Incremental View Maintenance for TanStack DB based on Differential Dataflow
146 lines (145 loc) • 4.7 kB
JavaScript
;
var __typeError = (msg) => {
throw TypeError(msg);
};
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
var _indexA, _indexB;
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const graph = require("../graph.cjs");
const d2 = require("../d2.cjs");
const multiset = require("../multiset.cjs");
const indexes = require("../indexes.cjs");
const negate = require("./negate.cjs");
const map = require("./map.cjs");
const concat = require("./concat.cjs");
class JoinOperator extends graph.BinaryOperator {
constructor(id, inputA, inputB, output) {
super(id, inputA, inputB, output);
__privateAdd(this, _indexA, new indexes.Index());
__privateAdd(this, _indexB, new indexes.Index());
}
run() {
const deltaA = new indexes.Index();
const deltaB = new indexes.Index();
const messagesA = this.inputAMessages();
for (const message of messagesA) {
const multiSetMessage = message;
for (const [item, multiplicity] of multiSetMessage.getInner()) {
const [key, value] = item;
deltaA.addValue(key, [value, multiplicity]);
}
}
const messagesB = this.inputBMessages();
for (const message of messagesB) {
const multiSetMessage = message;
for (const [item, multiplicity] of multiSetMessage.getInner()) {
const [key, value] = item;
deltaB.addValue(key, [value, multiplicity]);
}
}
const results = new multiset.MultiSet();
results.extend(deltaA.join(__privateGet(this, _indexB)));
__privateGet(this, _indexA).append(deltaA);
results.extend(__privateGet(this, _indexA).join(deltaB));
if (results.getInner().length > 0) {
this.output.sendData(results);
}
__privateGet(this, _indexB).append(deltaB);
}
}
_indexA = new WeakMap();
_indexB = new WeakMap();
function join(other, type = `inner`) {
switch (type) {
case `inner`:
return innerJoin(other);
case `anti`:
return antiJoin(other);
case `left`:
return leftJoin(other);
case `right`:
return rightJoin(other);
case `full`:
return fullJoin(other);
default:
throw new Error(`Join type ${type} is invalid`);
}
}
function innerJoin(other) {
return (stream) => {
if (stream.graph !== other.graph) {
throw new Error(`Cannot join streams from different graphs`);
}
const output = new d2.StreamBuilder(
stream.graph,
new graph.DifferenceStreamWriter()
);
const operator = new JoinOperator(
stream.graph.getNextOperatorId(),
stream.connectReader(),
other.connectReader(),
output.writer
);
stream.graph.addOperator(operator);
stream.graph.addStream(output.connectReader());
return output;
};
}
function antiJoin(other) {
return (stream) => {
const matchedLeft = stream.pipe(
innerJoin(other),
map.map(([key, [valueLeft, _valueRight]]) => [key, valueLeft])
);
const anti = stream.pipe(
concat.concat(matchedLeft.pipe(negate.negate())),
// @ts-ignore TODO: fix this
map.map(([key, value]) => [key, [value, null]])
);
return anti;
};
}
function leftJoin(other) {
return (stream) => {
const left = stream;
const right = other;
const inner = left.pipe(innerJoin(right));
const anti = left.pipe(antiJoin(right));
return inner.pipe(concat.concat(anti));
};
}
function rightJoin(other) {
return (stream) => {
const left = stream;
const right = other;
const inner = left.pipe(innerJoin(right));
const anti = right.pipe(
antiJoin(left),
map.map(([key, [a, b]]) => [key, [b, a]])
);
return inner.pipe(concat.concat(anti));
};
}
function fullJoin(other) {
return (stream) => {
const left = stream;
const right = other;
const inner = left.pipe(innerJoin(right));
const antiLeft = left.pipe(antiJoin(right));
const antiRight = right.pipe(
antiJoin(left),
map.map(([key, [a, b]]) => [key, [b, a]])
);
return inner.pipe(concat.concat(antiLeft), concat.concat(antiRight));
};
}
exports.JoinOperator = JoinOperator;
exports.antiJoin = antiJoin;
exports.fullJoin = fullJoin;
exports.innerJoin = innerJoin;
exports.join = join;
exports.leftJoin = leftJoin;
exports.rightJoin = rightJoin;
//# sourceMappingURL=join.cjs.map