import type { Change } from './change.ts';
import type { Node } from './data.ts';
import type { InputBase, Output } from './operator.ts';
import type { SourceSchema } from './schema.ts';
import type { Stream } from './stream.ts';
/**
 * # pushAccumulatedChanges
 *
 * Pushes the changes that were accumulated by
 * [fan-out, fan-in] or [ufo, ufi] sub-graphs.
 *
 * This function is called at the end of the sub-graph.
 *
 * The sub-graphs represents `OR`s.
 *
 * Changes that can enter the subgraphs:
 * 1. child (due to exist joins being above the sub-graph)
 * 2. add
 * 3. remove
 * 4. edit
 *
 * # Changes that can exit into `pushAccumulatedChanges`:
 *
 * ## Child
 * If a `child` change enters a sub-graph, it will flow to all branches.
 * Each branch will either:
 * - preserve the `child` change
 * - stop the `child` change (e.g., filter)
 * - convert it to an `add` or `remove` (e.g., exists filter)
 *
 * ## Add
 * If an `add` change enters a sub-graph, it will flow to all branches.
 * Each branch will either:
 * - preserve the `add` change
 * - hide the change (e.g., filter)
 *
 * ## Remove
 * If a `remove` change enters a sub-graph, it will flow to all branches.
 * Each branch will either:
 * - preserve the `remove` change
 * - hide the change (e.g., filter)
 *
 * ## Edit
 * If an `edit` change enters a sub-graph, it will flow to all branches.
 * Each branch will either:
 * - preserve the `edit` change
 * - convert it to an `add` (e.g., filter where old didn't match but new does)
 * - convert it to a `remove` (e.g., filter where old matched but new doesn't)
 *
 * This results in some invariants:
 * - an add coming in will only create adds coming out
 * - a remove coming in will only create removes coming out
 * - an edit coming in can create adds, removes, and edits coming out
 * - a child coming in can create adds, removes, and children coming out
 *
 * # Return of `pushAccumulatedChanges`
 *
 * This function will only push a single change.
 * Given the above invariants, how is this possible?
 *
 * An add that becomes many `adds` results in a single add
 * as the `add` is the same row across all adds. Branches do not change the row.
 *
 * A remove that becomes many `removes` results in a single remove
 * for the same reason.
 *
 * If a child enters and exits, it takes precedence over all other changes.
 * If a child enters and is converted only to add and remove it exits as an edit.
 * If a child enters and is converted to only add or only remove, it exits as that change.
 *
 * If an edit enters and is converted to add and remove it exits as an edit.
 * If an edit enters and is converted to only add or only remove, it exits as that change.
 * If an edit enters and exits as edits only, it exits as a single edit.
 */
export declare function pushAccumulatedChanges(accumulatedPushes: Change[], output: Output, pusher: InputBase, fanOutChangeType: Change['type'], mergeRelationships: (existing: Change, incoming: Change) => Change, addEmptyRelationships: (change: Change) => Change): Stream<'yield'>;
/**
 * Puts relationships from `right` into `left` if they don't already exist in `left`.
 */
export declare function mergeRelationships(left: Change, right: Change): Change;
export declare function makeAddEmptyRelationships(schema: SourceSchema): (change: Change) => Change;
/**
 * For each relationship in `schema` that does not exist
 * in `relationships`, add it with an empty stream.
 *
 * This modifies the `relationships` object in place.
 */
export declare function mergeEmpty(relationships: Record<string, () => Stream<Node | 'yield'>>, relationshipNames: string[]): void;
//# sourceMappingURL=push-accumulated.d.ts.map