# `Electric.Shapes.Filter`
[🔗](https://github.com/electric-sql/electric/tree/%40core/sync-service%401.6.2/packages/sync-service/lib/electric/shapes/filter.ex#L1)

Responsible for knowing which shapes are affected by a change.

`affected_shapes(filter, change)` will return a set of IDs for the shapes that are affected by the change
considering all the shapes that have been added to the filter using `add_shape/3`.

The `Filter` module keeps track of what tables are referenced by the shapes and changes and delegates
the table specific logic to the `Filter.WhereCondition` module.

Data is stored in ETS tables (outside the process heap) to avoid GC pressure with large numbers of shapes.

# `shape_id`

```elixir
@type shape_id() :: any()
```

# `t`

```elixir
@type t() :: %Electric.Shapes.Filter{
  eq_index_table: term(),
  incl_index_table: term(),
  shapes_table: term(),
  subquery_index: term(),
  tables_table: term(),
  where_cond_table: term()
}
```

# `active_shapes`

```elixir
@spec active_shapes(t()) :: [shape_id()]
```

# `add_shape`

```elixir
@spec add_shape(t(), shape_id(), Electric.Shapes.Shape.t()) :: t()
```

Add a shape for the filter to track.

The `shape_id` can be any term you like to identify the shape. Whatever you use will be returned
by `affected_shapes/2` when the shape is affected by a change.

# `affected_shapes`

```elixir
@spec affected_shapes(
  t(),
  Electric.Replication.Changes.change()
  | Electric.Replication.Changes.Relation.t()
) :: MapSet.t(shape_id())
```

Returns the shape IDs for all shapes that have been added to the filter
that are affected by the given change.

# `get_shape`

Get a shape by its ID. Used internally for where clause evaluation.

# `has_shape?`

```elixir
@spec has_shape?(t(), shape_id()) :: boolean()
```

# `indexed_shape?`

```elixir
@spec indexed_shape?(Electric.Shapes.Shape.t()) :: boolean()
```

Returns `true` when ShapeLogCollector can route the shape through any of its
indexes instead of relying exclusively on `other_shapes` scans.

# `new`

```elixir
@spec new(keyword()) :: t()
```

# `remove_shape`

```elixir
@spec remove_shape(t(), shape_id()) :: t()
```

Remove a shape from the filter.

# `subquery_index`

Get the subquery index. Used by consumers to seed/update membership.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
