# Row-Level Policies

## Policy logic

Immuta row-level policies compare data values with user metadata at query-time to determine whether or not the querying user should have access to the individual rows of data.

### Referencing data values

The values contained in one or many columns in the table in question (or a [separate joined table](https://documentation.immuta.com/2024.3/secure-your-data/authoring-policies-in-secure/data-policies/..#leveraging-lookup-tables)) need to be referenced by the policy for its logic to take effect.

For example, consider the policy below:

> **Only show rows where user** is a member of a group that matches the value in the column tagged `Department`.

The data values (the values in the column tagged `Department`) are matched against the user attribute (their groups) to determine whether or not rows will be visible to the user accessing the data.

The policy targets columns tagged `Department`; this means that this policy can be applied globally across all tables and data platforms that have that tag with this single policy rather than having to build a separate policy for individual tables and columns.

### Leveraging custom functions

It is also possible to use custom functions in [custom WHERE](https://documentation.immuta.com/2024.3/secure-your-data/authoring-policies-in-secure/data-policies/reference-guides/custom-where-clause-functions) row-level policies for more complex use cases.

These wrap Immuta context into free-form SQL logic for the row-level policy. That context can be things like the attributes (`@attributeValuesContains()`) or groups (`@groupsContains()`) possessed by the user or the username (`@username`) - injected into the SQL at runtime.

Avoid referencing explicit column names in custom functions and instead use the `@columnTagged('tag name')` function in SQL. In doing so, you can avoid having to reference the physical database world with the custom SQL policies and instead continue to target the metadata/tag world.
