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

A DNF sidecar plan compiled from a shape's WHERE clause.

Decomposes the WHERE clause into Disjunctive Normal Form and enriches each
position with dependency metadata needed by downstream modules.

Not stored on the Shape struct itself and compiled at runtime when needed.

# `position_info`

```elixir
@type position_info() :: %{
  ast: term(),
  sql: String.t(),
  is_subquery: boolean(),
  negated: boolean(),
  dependency_index: non_neg_integer() | nil,
  subquery_ref: [String.t()] | nil,
  tag_columns: tag_columns() | nil
}
```

# `t`

```elixir
@type t() :: %Electric.Shapes.DnfPlan{
  dependency_disjuncts: %{required(non_neg_integer()) =&gt; [non_neg_integer()]},
  dependency_polarities: %{required(non_neg_integer()) =&gt; :positive | :negated},
  dependency_positions: %{
    required(non_neg_integer()) =&gt; [
      Electric.Replication.Eval.Decomposer.position()
    ]
  },
  disjuncts: Electric.Replication.Eval.Decomposer.dnf(),
  disjuncts_positions: [[Electric.Replication.Eval.Decomposer.position()]],
  position_count: non_neg_integer(),
  positions: %{
    required(Electric.Replication.Eval.Decomposer.position()) =&gt; position_info()
  }
}
```

# `tag_columns`

```elixir
@type tag_columns() :: [String.t()] | {:hash_together, [String.t()]}
```

# `compile`

```elixir
@spec compile(Electric.Shapes.Shape.t()) ::
  {:ok, t()} | :no_subqueries | {:error, term()}
```

Compile a DNF plan from a shape.

Returns `{:ok, plan}` for shapes with subquery dependencies,
`:no_subqueries` for shapes without, or `{:error, reason}` if
decomposition fails.

---

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