Skip to main content

Atlas Schema Rule

predicate

A predicate is composed of multiple condition blocks, operators, and quantifiers. A condition can be applied to one or more attributes of the object, such as checking column nullability and type. Additionally, a condition can be negated, combined with other conditions using logical operators, and quantified to check if the condition holds for all or some attributes.

predicate table

The predicate table consists of a set of condition blocks that apply to a table. The block has the following attributes:

AttributeDescription
nameThe name of the table. Supports the eq, eq_fold, contains, contains_fold, ne, in, and match operators for comparison.
commentThe comment of the table. Supports the eq, eq_fold, contains, contains_fold, ne, in, and match operators for comparison.
selfThe table itself. Supports the eq and ne operators for comparison.
primary_keyThe primary key of the table. Can be checked using the condition or predicate attribute.
schemaThe schema of the table. Can be checked using the condition or predicate attribute.
schema.rule.hcl
predicate "table" "not_audit" {
not {
name {
match = ".+_audit$"
}
}
}

predicate "table" "has_sibling_audit" {
schema {
predicate = predicate.schema.has_table
vars = {
has_table = "${self.name}_audit"
}
}
}

predicate "schema" "has_table" {
variable "table_name" {
type = string
}
any {
table {
condition = self.name == var.table_name
}
}
}

Driver specific attributes:

AttributeDescription
row_security_enabledThe row security status of the table. Supports the eq and ne operators for comparison.
row_security_enforcedThe row security enforcement status of the table. Supports the eq and ne operators for comparison.

In addition to the or, and, and not logical operators, the block supports the following quantifiers for child objects:

  • any: Checks if the condition holds for at least one child object.
  • all: Checks if the condition holds for all child objects.
  • exists: Checks if the condition holds for at least one child object.
  • count: Checks if the condition holds for a specific number of child objects.

The child objects can be of the following types:

TypeDescription
columnA column of the table.
indexAn index of the table.
foreign_keyA foreign key of the table.
checkA check constraint of the table.
triggerA trigger of the table.
attrAn attribute of the table.
policy (PostgreSQL)A policy of the table.
schema.rule.hcl
predicate "table" "has_timestamp_columns" {
any {
column {
predicate = predicate.column.not_null
vars = {
name = "created_at"
type = "timestamp"
}
}
}
}

predicate column

The predicate column consists of a set of condition blocks that apply to a column. The block has the following attributes:

AttributeDescription
nullThe nullability of the column. Supports the eq and ne operators for comparison.
nameThe name of the column. Supports the eq, eq_fold, contains, contains_fold, ne, in, and match operators for comparison.
typeThe data type of the column. Supports the eq, eq_fold, contains, contains_fold, ne, in, and match operators for comparison.
defaultThe default value of the column. Supports the eq, eq_fold, contains, contains_fold, ne, in, and match operators for comparison.
commentThe comment of the column. Supports the eq, eq_fold, contains, contains_fold, ne, in, and match operators for comparison.
primary_keyThe primary key status of the column. Supports the eq and ne operators for comparison.
selfThe column itself. Supports the eq and ne operators for comparison.
predicate "column" "not_null_or_have_default" {
or {
default {
ne = null
}
null {
eq = false
}
}
}

In addition to the or, and, and not logical operators, the block supports the following quantifiers for child objects:

  • any: Checks if the condition holds for at least one child object.
  • all: Checks if the condition holds for all child objects.
  • exists: Checks if the condition holds for at least one child object.
  • count: Checks if the condition holds for a specific number of child objects.

predicate schema

The predicate schema consists of a set of condition blocks that apply to a schema. The block has the following attributes:

AttributeDescription
nameThe name of the schema. Supports the eq, eq_fold, contains, contains_fold, ne, in, and match operators for comparison.
commentThe comment of the schema. Supports the eq, eq_fold, contains, contains_fold, ne, in, and match operators for comparison.
selfThe schema itself. Supports the eq and ne operators for comparison.

In addition to the or, and, and not logical operators, the block supports the following quantifiers for child objects:

  • any: Checks if the condition holds for at least one child object.
  • all: Checks if the condition holds for all child objects.
  • exists: Checks if the condition holds for at least one child object.
  • count: Checks if the condition holds for a specific number of child objects.

The child objects can be of the following types:

TypeDescription
tableA table in the schema.
viewA view in the schema.
attrAn attribute of the schema.
functionA function in the schema.
procedureA procedure in the schema.
attrAn attribute of the table.
policy (PostgreSQL)A policy of the table.
schema.rule.hcl
predicate "schema" "has_tenant_policy" {
exists {
policy {
predicate = predicate.policy.tenant
}
}
}

predicate view

The predicate view consists of a set of condition blocks that apply to a view. The block has the following attributes:

AttributeDescription
nameThe name of the view. Supports the eq, eq_fold, contains, contains_fold, ne, in, and match operators for comparison.
queryThe query of the view. Supports the eq, eq_fold, contains, contains_fold, ne, in, and match operators for comparison.
commentThe comment of the view. Supports the eq, eq_fold, contains, contains_fold, ne, in, and match operators for comparison.
selfThe view itself. Supports the eq and ne operators for comparison.
schema.rule.hcl
predicate "view" "check_option" {
variable "value" {
type = string
}
check_option {
eq_fold = var.value
}
}

rule "schema" "view-check-option" {
description = "require all views to have a specific check option"
view {
assert {
predicate = predicate.view.check_option
vars = {
value = "CASCADED"
}
message = "view \"${self.name}\" must have check option CASCADED"
}
}
}

Driver specific attributes:

AttributeDescription
security_barrierSupports the eq and ne operators for comparison.
security_invokerSupports the eq and ne operators for comparison.
security_invokerSupports the eq and ne operators for comparison.

In addition to the or, and, and not logical operators, the block supports the following quantifiers for child objects:

  • any: Checks if the condition holds for at least one child object.
  • all: Checks if the condition holds for all child objects.
  • exists: Checks if the condition holds for at least one child object.
  • count: Checks if the condition holds for a specific number of child objects.

The child objects can be of the following types:

TypeDescription
columnA column of the view.
indexAn index of the view.
triggerA trigger of the view.
attrAn attribute of the view.

predicate index

The predicate index consists of a set of condition blocks that apply to an index. The block has the following attributes:

AttributeDescription
nameThe name of the index. Supports the eq, eq_fold, contains, contains_fold, ne, in, and match operators for comparison.
commentThe comment of the index. Supports the eq, eq_fold, contains, contains_fold, ne, in, and match operators for comparison.
uniqueSupports the eq and ne operators for comparison.
schema.rule.hcl
predicate "index" "type" {
variable "type" {
type = string
}
type {
eq = var.type
}
}

rule "schema" "all-indexes-btree" {
description = "Require all indexes to be BTREE."
table {
index {
assert {
predicate = predicate.index.type
vars = { type = "BTREE" }
message = "Table ${self.table.name} index ${self.name} must be BTREE"
}
}
}
}

Driver specific attributes:

AttributeDescription
typeSupports the eq, eq_fold, contains, contains_fold, ne, in, and match operators for comparison.
whereSupports the eq, eq_fold, contains, contains_fold, ne, in, and match operators for comparison.
nulls_distinctSupports the eq and ne operators for comparison.

In addition to the or, and, and not logical operators, the block supports the following quantifiers for child objects:

  • any: Checks if the condition holds for at least one child object.
  • all: Checks if the condition holds for all child objects.
  • exists: Checks if the condition holds for at least one child object.
  • count: Checks if the condition holds for a specific number of child objects.

The child objects can be of the following types:

TypeDescription
partA part of the index (e.g., column or an expression).
attrAn attribute of the index.
schema.rule.hcl
predicate "index" "max_length_parts" {
variable "len" {
type = number
}
all {
part {
predicate = predicate.index_part.max_length
vars = { len = var.len }
}
}
}

predicate "index_part" "max_length" {
variable "len" {
type = number
}
or {
prefix {
eq = null
}
prefix {
le = var.len
}
}
}

predicate index_part

The predicate index_part consists of a set of condition blocks that apply to an index/key part (e.g., a column or an expression together with its attributes). Each block includes the following attributes:

AttributeDescription
colummNot-empty if the index-part is set on a column. Supports the eq, eq_fold, contains, contains_fold, ne, in, and match operators for comparison.
exprNot-empty if the index-part is set on an expression. Supports the eq, eq_fold, contains, contains_fold, ne, in, and match operators for comparison.
descSupports the eq and ne operators for comparison.
schema.rule.hcl
predicate "index_part" "max_length" {
variable "len" {
type = number
}
or {
prefix {
eq = null
}
prefix {
le = var.len
}
}
}

Driver specific attributes:

AttributeDescription
prefixNot-zero if the index-part was set on a column prefix. Supports the eq, ne, lt, le, gt, and ge operators for comparison.

predicate check

The predicate check consists of a set of condition blocks that apply to a check constraint. Each block includes the following attributes:

AttributeDescription
nameSupports the eq, eq_fold, contains, contains_fold, ne, in, and match operators for comparison.
exprSupports the eq, eq_fold, contains, contains_fold, ne, in, and match operators for comparison.
commentSupports the eq, eq_fold, contains, contains_fold, ne, in, and match operators for comparison.

predicate foreign_key

The predicate foreign_key consists of a set of condition blocks that apply to a foreign key constraint. Each block includes the following attributes:

AttributeDescription
nameSupports the eq, eq_fold, contains, contains_fold, ne, in, and match operators for comparison.
commentSupports the eq, eq_fold, contains, contains_fold, ne, in, and match operators for comparison.
on_updateSupports the eq, eq_fold, contains, contains_fold, ne, in, and match operators for comparison.
on_deleteSupports the eq, eq_fold, contains, contains_fold, ne, in, and match operators for comparison.
tableCan be checked using the condition or predicate attribute.
ref_tableCan be checked using the condition or predicate attribute.
schema.rule.hcl
predicate "foreign_key" "on_delete_cascade" {
on_delete {
eq = "CASCADE"
}
}

In addition to the or, and, and not logical operators, the block supports the following quantifiers for child objects (columns, ref-columns, and attributes):

  • any: Checks if the condition holds for at least one child object.
  • all: Checks if the condition holds for all child objects.
  • exists: Checks if the condition holds for at least one child object.
  • count: Checks if the condition holds for a specific number of child objects.

The child objects can be of the following types:

TypeDescription
columnA column of the foreign key.
ref_columnA column of the referenced table.
attrAn attribute of the foreign key.
schema.rule.hcl
predicate "foreign_key" "on_delete_cascade" {
on_delete {
eq = "CASCADE"
}
all {
ref_column {
predicate = predicate.column.is_pk
}
}
}

predicate "column" "is_pk" {
primary_key {
eq = true
}
}

rule "schema" "fk-action-cascade" {
description = "All foreign keys must reference primary keys of the target table and use ON DELETE CASCADE"
table {
foreign_key {
assert {
predicate = predicate.foreign_key.on_delete_cascade
message = "foreign key ${self.name} must reference primary key of target table and use ON DELETE CASCADE"
}
}
}
}

predicate trigger

The predicate trigger consists of a set of condition blocks that apply to a trigger. Each block includes the following attributes:

AttributeDescription
nameSupports the eq, eq_fold, contains, contains_fold, ne, in, and match operators for comparison.
forSupports the eq, eq_fold, contains, contains_fold, ne, in, and match operators for comparison.
commentSupports the eq, eq_fold, contains, contains_fold, ne, in, and match operators for comparison.
bodySupports the eq, eq_fold, contains, contains_fold, ne, in, and match operators for comparison.
tableCan be checked using the condition or predicate attribute.
viewCan be checked using the condition or predicate attribute.

Driver specific attributes:

AttributeDescription
deferrableSupports the eq and the ne operators for comparison.
initially_deferredSupports the eq and the ne operators for comparison.

predicate function

The predicate function consists of a set of condition blocks that apply to a function. Each block includes the following attributes:

AttributeDescription
nameSupports the eq, eq_fold, contains, contains_fold, ne, in, and match operators for comparison.
langSupports the eq, eq_fold, contains, contains_fold, ne, in, and match operators for comparison.
returnSupports the eq, eq_fold, contains, contains_fold, ne, in, and match operators for comparison.
commentSupports the eq, eq_fold, contains, contains_fold, ne, in, and match operators for comparison.
bodySupports the eq, eq_fold, contains, contains_fold, ne, in, and match operators for comparison.
schemaCan be checked using the condition or predicate attribute.
schema.rule.hcl
predicate "function" "match_name" {
variable "pattern" {
type = string
}
name {
match = var.pattern
}
}

Driver specific attributes:

AttributeDescription
leakproofSupports the eq and the ne operators for comparison.
strictSupports the eq and the ne operators for comparison.
parallelSupports the eq, eq_fold, contains, contains_fold, ne, in, and match operators for comparison.
securitySupports the eq, eq_fold, contains, contains_fold, ne, in, and match operators for comparison.
volatilitySupports the eq, eq_fold, contains, contains_fold, ne, in, and match operators for comparison.
schema.rule.hcl
predicate "function" "security_invoker" {
security {
eq = "INVOKER"
}
}

In addition to the or, and, and not logical operators, the block supports the following quantifiers for child objects (function arguments and attributes):

  • any: Checks if the condition holds for at least one child object.
  • all: Checks if the condition holds for all child objects.
  • exists: Checks if the condition holds for at least one child object.
  • count: Checks if the condition holds for a specific number of child objects.

The child objects can be of the following types:

TypeDescription
argAn argument of the function.
attrAn attribute of the function.

predicate procedure

The predicate procedure consists of a set of condition blocks that apply to a procedure. Each block includes the following attributes:

AttributeDescription
nameSupports the eq, eq_fold, contains, contains_fold, ne, in, and match operators for comparison.
langSupports the eq, eq_fold, contains, contains_fold, ne, in, and match operators for comparison.
commentSupports the eq, eq_fold, contains, contains_fold, ne, in, and match operators for comparison.
bodySupports the eq, eq_fold, contains, contains_fold, ne, in, and match operators for comparison.
schemaCan be checked using the condition or predicate attribute.
schema.rule.hcl
predicate "procedure" "is_sql" {
lang {
eq = "SQL"
}
}

Driver specific attributes:

AttributeDescription
securitySupports the eq, eq_fold, contains, contains_fold, ne, in, and match operators for comparison.
schema.rule.hcl
predicate "function" "security_invoker" {
security {
eq = "INVOKER"
}
}

In addition to the or, and, and not logical operators, the block supports the following quantifiers for child objects (procedure arguments and attributes):

  • any: Checks if the condition holds for at least one child object.
  • all: Checks if the condition holds for all child objects.
  • exists: Checks if the condition holds for at least one child object.
  • count: Checks if the condition holds for a specific number of child objects.

The child objects can be of the following types:

TypeDescription
argAn argument of the procedure.
attrAn attribute of the procedure.

predicate arg

The predicate arg consists of a set of condition blocks that apply to a function argument. Each block includes the following attributes:

AttributeDescription
nameSupports the eq, eq_fold, contains, contains_fold, ne, in, and match operators for comparison.
typeSupports the eq, eq_fold, contains, contains_fold, ne, in, and match operators for comparison.
defaultSupports the eq, eq_fold, contains, contains_fold, ne, in, and match operators for comparison.
modeSupports the eq, eq_fold, contains, contains_fold, ne, in, and match operators for comparison.
schema.rule.hcl
predicate "arg" "not_out" {
mode {
ne = "OUT"
}
}
predicate "function" "no_out_arg" {
not {
exists {
arg {
predicate = predicate.arg.not_out
}
}
}
}

rule

The rule "schema" block defines a rule applied to the schema. It requires a name label and a description attribute that provides a human-readable explanation of the rule (it is used in the linting output).

When traversing a schema element, two blocks can be used: match and assert. The match block filters the elements the rule should apply to, and the assert block applies the predicate to the matched elements. If the predicate evaluates to false, an assertion is raised with the provided message attribute.

Example schema check

schema.rule.hcl
rule "schema" "disallow-circular-table-references" {
description = "Disallow circular table references"
schema {
assert {
predicate = predicate.schema.not_circular_ref
message = "schema ${self.name} has circular table references"
}
}
}

Example foreign_key check

schema.rule.hcl
rule "schema" "fk-action-cascade" {
description = "All foreign keys must reference primary keys of the target table and use ON DELETE CASCADE"
table {
foreign_key {
assert {
predicate = predicate.foreign_key.on_delete_cascade
message = "foreign key ${self.name} must reference primary key of target table and use ON DELETE CASCADE"
}
}
}
}

Example primary_key check

schema.rule.hcl
rule "schema" "pk-column-uuid" {
description = "require primary key columns to be of type UUID"
table {
primary_key {
match {
predicate = predicate.index.is_set
}
assert {
predicate = predicate.index.uuid_columns_only
message = "primary key must be set on UUID columns only"
}
}
}
}

Example column check

schema.rule.hcl
rule "schema" "column-pii" {
description = "require all PII columns to have a specific comment"
table {
column {
match {
predicate = predicate.column.is_pii
}
assert {
predicate = predicate.column.comment_match
vars = {
pattern = ".*PII.*"
}
message = "column ${self.name} must have a comment PII"
}
}
}
}