> ## Documentation Index
> Fetch the complete documentation index at: https://docs.adriel.com/llms.txt
> Use this file to discover all available pages before exploring further.

# FAQs

> Common questions, expected behaviors, and troubleshooting for the Postgres data source.

## Why can I only see tables from the public schema?

Table discovery is scoped to the `public` schema on purpose. When a table is picked for a data source, Adriel lists every table in `public` for which the connecting database user holds `SELECT` privilege, and it hides everything else. Tables in other schemas, and tables the user cannot read, do not appear in the list.

To report on a table that lives in another schema, expose it in `public` as a view and bind the view. Because a view behaves like a table to the connector, its columns are discovered and typed the same way. One Adriel data source binds to exactly one table (or view), so a view is also the way to combine several tables into a single reportable object. Full discovery rules are in the [Postgres data reference](/data-sources/o-z/postgres/data-reference).

## Do I need to allowlist Adriel's IP addresses for my database?

Yes. Queries reach the database through Adriel's database proxy rather than from a rotating set of servers, so the database only needs to accept connections from the proxy's egress address, `52.79.160.224`. That address has to be permitted by the network firewall (or the cloud provider's security group) and by the host-based rules in `pg_hba.conf`. When direct exposure is not an option, an SSH tunnel to the database works as well.

A read-only role is recommended: the connector only issues `SELECT` statements, so granting `SELECT` on the target table (or view) is enough. Step-by-step connection setup lives in [How to connect Postgres](/data-sources/o-z/postgres/how-to-connect).

## Why does my widget show "Unknown" as a breakdown value?

When a column used as a breakdown contains `NULL` (or empty values), those rows are grouped under the literal label `Unknown` rather than being dropped. This keeps the group visible instead of silently removing rows from the widget, so an `Unknown` bucket usually means the underlying column has missing values for those records.

Filtering on `Unknown` matches those same missing rows: a filter value of `Unknown` also matches `IS NULL`. To remove the bucket, populate the column in the source database, or filter the widget to the values that should appear.

## Why are my Postgres numbers not adding up?

The most common cause is a column that looks numeric but is treated as text. Any column whose name ends in `_id` or `ID` is forced to text so it behaves as a breakdown rather than a metric, even when its native type is a number. Identifier columns are meant for grouping, not for summing, so placing one in a metric slot will not produce a total.

Field roles otherwise follow the column's native type. Numeric types (integer, decimal, and similar) map to Number and can be summed; dates map to Date; every other type — including `boolean`, `uuid`, and `text` — maps to Text and is combined with string aggregation instead of arithmetic. To count records rather than sum a value, use the built-in **Row count** field. The full type-mapping and aggregation rules are in the [Postgres data reference](/data-sources/o-z/postgres/data-reference).

## Why don't columns I just added to my table show up?

The connector remembers each table's column list, so a column added on the Postgres side is not visible the instant it is created — it appears once the field-metadata cache next refreshes. The same refresh removes columns that no longer exist in the table. This affects only which columns are selectable; row values are read live on every widget load and are never cached. For the exact caching schedule, see the [Postgres data reference](/data-sources/o-z/postgres/data-reference).

## How do I filter by a numeric range, or combine multiple tables?

Widget filters on Postgres data sources use a fixed operator set — `EQUAL`, `IN`, `LIKE`, `STARTS_WITH`, `ENDS_WITH`, `REGEXP`, and `EXIST`, which can be combined with `AND`, `OR`, and `NOT`. Greater-than and less-than comparisons are not available as widget filters, and one data source binds to exactly one table. Both gaps are handled the same way, with a Postgres **view**:

* For a numeric or date range, define a view that applies the range predicate, then bind the view as the data source.
* For data that spans several tables, pre-join the tables into a view and bind that view.

Because a view is discovered and typed like a table, keeping the heavier logic in the database runs it closest to the data. For a database that uses a form-driven column pre-filter instead of a view-based approach, see the [MongoDB data source](/data-sources/g-n/mongodb/data-reference).

## Related

<CardGroup cols={2}>
  <Card title="How to connect Postgres" href="/data-sources/o-z/postgres/how-to-connect">
    Credentials, IP allowlisting, and connection setup for a PostgreSQL database.
  </Card>

  <Card title="Postgres data reference" href="/data-sources/o-z/postgres/data-reference">
    Query model, field type mapping, caching, and limits for the Postgres data source.
  </Card>

  <Card title="MySQL data reference" href="/data-sources/g-n/mysql/data-reference">
    The sibling SQL database connector, with the same view-based patterns.
  </Card>

  <Card title="Redshift data reference" href="/data-sources/o-z/redshift/data-reference">
    The cloud data warehouse alternative for large SQL datasets.
  </Card>
</CardGroup>
