Skip to main content
Column-level security (CLS) lets you restrict which columns of a table a given role can read. You grant or revoke SELECT on specific columns using PostgreSQL-style syntax:
A user who has not been granted access to a column cannot read it in queries. SELECT * expands only to their permitted columns, explicit references to unpermitted columns are rejected, and catalog views like information_schema.columns hide those columns from view.

How column-level security works

CLS extends Firebolt’s existing Role-Based Access Control (RBAC) model. A table-level SELECT grant (no column list) continues to mean “access to all columns.” Column-level grants add a finer level of control within a table. Key rules:
  • Table-level SELECT grants all columns. If a role has GRANT SELECT ON TABLE t, it can read every column regardless of any column-scoped grants. To restrict the role to specific columns, you must first REVOKE SELECT ON TABLE and then grant column-level access.
  • Column grants are additive. Granting (col_a) and then (col_b) is equivalent to granting (col_a, col_b) — the sets are merged.
  • Union across roles. A user sees the union of columns granted across all their roles. If role_a grants SELECT (col1) and role_b grants SELECT (col2), a user with both roles can read both columns.
  • Column identity is stable. Privileges are stored using internal column IDs, not column names. Renaming a column does not affect access. Dropping and re-adding a column with the same name creates a new ID, so old grants do not apply to the new column.
  • Unauthorized columns are invisible. Referencing an unauthorized column produces the same error as referencing a column that does not exist.

Prerequisites

Before configuring column-level security, make sure:
  • You have a user with GRANT privileges (typically an account_admin or a role with the relevant permissions).
  • You understand RBAC basics and table permissions.
  • The target database and schema exist, and you have USAGE on both.

Grant SELECT on specific columns

Use GRANT with a column list to restrict a role to specific columns:
If the role already has a table-level SELECT grant (that is, GRANT SELECT ON TABLE without a column list), it can read all columns regardless of any column-scoped grants. You must first revoke the table-level grant before column-level restrictions take effect:
Column-list syntax is only valid for SELECT on TABLE objects. You cannot use column lists with other privileges (such as INSERT or DELETE) or on views.

Example

Suppose you have an employees table with sensitive salary and SSN data:
Grant an analyst_role access to only the non-sensitive columns:
Verify access:

Revoke SELECT on specific columns

Use REVOKE with a column list to remove access to specific columns:
Column-list REVOKE subtracts from the column-scoped grant only. It does not affect table-level SELECT grants.

Example

Remove access to the department column:
The role retains access to employee_id and name.

Interaction with table-level grants

Column-level and table-level SELECT grants follow an OR rule, consistent with PostgreSQL:

Moving from full table access to column-scoped access

You cannot “punch holes” in table-level access with a column-list REVOKE. To restrict a role from full table access to a subset of columns:
  1. Revoke the table-level SELECT:
  2. Grant access to only the desired columns:

Table-level REVOKE removes column-scoped grants

REVOKE SELECT ON TABLE (without a column list) removes all SELECT on that table for the role, including any column-scoped grants. This matches PostgreSQL behavior.

Schema evolution

Column-level privileges use stable column IDs. When the table schema changes:
  • ADD COLUMN: The new column is not included in any existing column-scoped grant. Roles with column-scoped SELECT cannot read the new column until an administrator explicitly grants it.
  • DROP and re-add column: Dropping and re-adding a column with the same name creates a new internal column ID. Previous grants do not apply to the new column.
  • RENAME COLUMN: Renaming a column does not affect access. The grant follows the column’s stable internal ID, not its name.

STRUCT columns

CLS operates at the top-level column granularity. A STRUCT column is granted or denied as a whole. Individual sub-fields cannot be independently granted or revoked.

Catalog visibility

Views and column-level security

When a query references a view, column-level access on the underlying table is evaluated using the view owner’s privileges, not the querying user’s. This is the same owner rights model that Firebolt applies to all views. For example, if a view owner has SELECT (a, b) on a table and a view is defined as SELECT a, b FROM t, any user with SELECT on the view can see both columns through the view, even if their own direct table grants are narrower.
For scenarios that require data masking (exposing columns in a transformed or redacted form) or row-level security (filtering which rows a user can see), use secure views. Column-level security and secure views complement each other as part of Firebolt’s layered security model.

Example: multi-role column access

The following example sets up two roles with different column access on the same table, then shows the effective access for a user with both roles: