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:
Attribute | Description |
---|---|
name | The name of the table. Supports the eq , eq_fold , contains , contains_fold , ne , in , and match operators for comparison. |
comment | The comment of the table. Supports the eq , eq_fold , contains , contains_fold , ne , in , and match operators for comparison. |
self | The table itself. Supports the eq and ne operators for comparison. |
primary_key | The primary key of the table. Can be checked using the condition or predicate attribute. |
schema | The schema of the table. Can be checked using the condition or predicate attribute. |
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:
- PostgreSQL
- SQLite
Attribute | Description |
---|---|
row_security_enabled | The row security status of the table. Supports the eq and ne operators for comparison. |
row_security_enforced | The row security enforcement status of the table. Supports the eq and ne operators for comparison. |
Attribute | Description |
---|---|
strict | The strict mode status of the table. Supports the eq and ne operators for comparison. |
without_rowid | The without rowid 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:
Type | Description |
---|---|
column | A column of the table. |
index | An index of the table. |
foreign_key | A foreign key of the table. |
check | A check constraint of the table. |
trigger | A trigger of the table. |
attr | An attribute of the table. |
policy (PostgreSQL) | A policy of the table. |
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:
Attribute | Description |
---|---|
null | The nullability of the column. Supports the eq and ne operators for comparison. |
name | The name of the column. Supports the eq , eq_fold , contains , contains_fold , ne , in , and match operators for comparison. |
type | The data type of the column. Supports the eq , eq_fold , contains , contains_fold , ne , in , and match operators for comparison. |
default | The default value of the column. Supports the eq , eq_fold , contains , contains_fold , ne , in , and match operators for comparison. |
comment | The comment of the column. Supports the eq , eq_fold , contains , contains_fold , ne , in , and match operators for comparison. |
primary_key | The primary key status of the column. Supports the eq and ne operators for comparison. |
self | The 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:
Attribute | Description |
---|---|
name | The name of the schema. Supports the eq , eq_fold , contains , contains_fold , ne , in , and match operators for comparison. |
comment | The comment of the schema. Supports the eq , eq_fold , contains , contains_fold , ne , in , and match operators for comparison. |
self | The 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:
Type | Description |
---|---|
table | A table in the schema. |
view | A view in the schema. |
attr | An attribute of the schema. |
function | A function in the schema. |
procedure | A procedure in the schema. |
attr | An attribute of the table. |
policy (PostgreSQL) | A policy of the table. |
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:
Attribute | Description |
---|---|
name | The name of the view. Supports the eq , eq_fold , contains , contains_fold , ne , in , and match operators for comparison. |
query | The query of the view. Supports the eq , eq_fold , contains , contains_fold , ne , in , and match operators for comparison. |
comment | The comment of the view. Supports the eq , eq_fold , contains , contains_fold , ne , in , and match operators for comparison. |
self | The view itself. Supports the eq and ne operators for comparison. |
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:
- PostgreSQL
- MySQL
Attribute | Description |
---|---|
security_barrier | Supports the eq and ne operators for comparison. |
security_invoker | Supports the eq and ne operators for comparison. |
security_invoker | Supports the eq and ne operators for comparison. |
Attribute | Description |
---|---|
security | Supports the eq , eq_fold , contains , contains_fold , ne , in , and match 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:
Type | Description |
---|---|
column | A column of the view. |
index | An index of the view. |
trigger | A trigger of the view. |
attr | An 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:
Attribute | Description |
---|---|
name | The name of the index. Supports the eq , eq_fold , contains , contains_fold , ne , in , and match operators for comparison. |
comment | The comment of the index. Supports the eq , eq_fold , contains , contains_fold , ne , in , and match operators for comparison. |
unique | Supports the eq and ne operators for comparison. |
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:
- PostgreSQL
- MySQL
Attribute | Description |
---|---|
type | Supports the eq , eq_fold , contains , contains_fold , ne , in , and match operators for comparison. |
where | Supports the eq , eq_fold , contains , contains_fold , ne , in , and match operators for comparison. |
nulls_distinct | Supports the eq and ne operators for comparison. |
Attribute | Description |
---|---|
type | Supports the eq , eq_fold , contains , contains_fold , ne , in , and match 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:
Type | Description |
---|---|
part | A part of the index (e.g., column or an expression). |
attr | An attribute of the index. |
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:
Attribute | Description |
---|---|
columm | Not-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. |
expr | Not-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. |
desc | Supports the eq and ne operators for comparison. |
predicate "index_part" "max_length" {
variable "len" {
type = number
}
or {
prefix {
eq = null
}
prefix {
le = var.len
}
}
}
Driver specific attributes:
- MySQL
Attribute | Description |
---|---|
prefix | Not-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:
Attribute | Description |
---|---|
name | Supports the eq , eq_fold , contains , contains_fold , ne , in , and match operators for comparison. |
expr | Supports the eq , eq_fold , contains , contains_fold , ne , in , and match operators for comparison. |
comment | Supports 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:
Attribute | Description |
---|---|
name | Supports the eq , eq_fold , contains , contains_fold , ne , in , and match operators for comparison. |
comment | Supports the eq , eq_fold , contains , contains_fold , ne , in , and match operators for comparison. |
on_update | Supports the eq , eq_fold , contains , contains_fold , ne , in , and match operators for comparison. |
on_delete | Supports the eq , eq_fold , contains , contains_fold , ne , in , and match operators for comparison. |
table | Can be checked using the condition or predicate attribute. |
ref_table | Can be checked using the condition or predicate attribute. |
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:
Type | Description |
---|---|
column | A column of the foreign key. |
ref_column | A column of the referenced table. |
attr | An attribute of the foreign key. |
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:
Attribute | Description |
---|---|
name | Supports the eq , eq_fold , contains , contains_fold , ne , in , and match operators for comparison. |
for | Supports the eq , eq_fold , contains , contains_fold , ne , in , and match operators for comparison. |
comment | Supports the eq , eq_fold , contains , contains_fold , ne , in , and match operators for comparison. |
body | Supports the eq , eq_fold , contains , contains_fold , ne , in , and match operators for comparison. |
table | Can be checked using the condition or predicate attribute. |
view | Can be checked using the condition or predicate attribute. |
Driver specific attributes:
- PostreSQL
Attribute | Description |
---|---|
deferrable | Supports the eq and the ne operators for comparison. |
initially_deferred | Supports 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:
Attribute | Description |
---|---|
name | Supports the eq , eq_fold , contains , contains_fold , ne , in , and match operators for comparison. |
lang | Supports the eq , eq_fold , contains , contains_fold , ne , in , and match operators for comparison. |
return | Supports the eq , eq_fold , contains , contains_fold , ne , in , and match operators for comparison. |
comment | Supports the eq , eq_fold , contains , contains_fold , ne , in , and match operators for comparison. |
body | Supports the eq , eq_fold , contains , contains_fold , ne , in , and match operators for comparison. |
schema | Can be checked using the condition or predicate attribute. |
predicate "function" "match_name" {
variable "pattern" {
type = string
}
name {
match = var.pattern
}
}
Driver specific attributes:
- PostreSQL
- MySQL
Attribute | Description |
---|---|
leakproof | Supports the eq and the ne operators for comparison. |
strict | Supports the eq and the ne operators for comparison. |
parallel | Supports the eq , eq_fold , contains , contains_fold , ne , in , and match operators for comparison. |
security | Supports the eq , eq_fold , contains , contains_fold , ne , in , and match operators for comparison. |
volatility | Supports the eq , eq_fold , contains , contains_fold , ne , in , and match operators for comparison. |
predicate "function" "security_invoker" {
security {
eq = "INVOKER"
}
}
Attribute | Description |
---|---|
deterministic | Supports the eq and the ne operators for comparison. |
security | Supports the eq , eq_fold , contains , contains_fold , ne , in , and match operators for comparison. |
data_access | Supports the eq , eq_fold , contains , contains_fold , ne , in , and match operators for comparison. |
predicate "function" "deterministic" {
deterministic {
eq = true
}
}
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:
Type | Description |
---|---|
arg | An argument of the function. |
attr | An 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:
Attribute | Description |
---|---|
name | Supports the eq , eq_fold , contains , contains_fold , ne , in , and match operators for comparison. |
lang | Supports the eq , eq_fold , contains , contains_fold , ne , in , and match operators for comparison. |
comment | Supports the eq , eq_fold , contains , contains_fold , ne , in , and match operators for comparison. |
body | Supports the eq , eq_fold , contains , contains_fold , ne , in , and match operators for comparison. |
schema | Can be checked using the condition or predicate attribute. |
predicate "procedure" "is_sql" {
lang {
eq = "SQL"
}
}
Driver specific attributes:
- PostreSQL
- MySQL
Attribute | Description |
---|---|
security | Supports the eq , eq_fold , contains , contains_fold , ne , in , and match operators for comparison. |
predicate "function" "security_invoker" {
security {
eq = "INVOKER"
}
}
Attribute | Description |
---|---|
deterministic | Supports the eq and the ne operators for comparison. |
security | Supports the eq , eq_fold , contains , contains_fold , ne , in , and match operators for comparison. |
data_access | Supports the eq , eq_fold , contains , contains_fold , ne , in , and match operators for comparison. |
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:
Type | Description |
---|---|
arg | An argument of the procedure. |
attr | An 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:
Attribute | Description |
---|---|
name | Supports the eq , eq_fold , contains , contains_fold , ne , in , and match operators for comparison. |
type | Supports the eq , eq_fold , contains , contains_fold , ne , in , and match operators for comparison. |
default | Supports the eq , eq_fold , contains , contains_fold , ne , in , and match operators for comparison. |
mode | Supports the eq , eq_fold , contains , contains_fold , ne , in , and match operators for comparison. |
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
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
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
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
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"
}
}
}
}