This folder contains the built-in rules for Schemalint. While there is value in these, the true benefit is achieved by writing custom rules that enforce the specific architecture that you are aiming for.
Check that your names are cased correctly. The default setting is "snake"
(i.e. tables should be named with underscores as word boundaries: member_profile
).
The reasoning for this is outlined in the Postgres wiki: Don't use upper case table or column names .
If, for some reason or other, you want to use a different naming scheme, you can configure the rule to use one of snake
, dash
(member-profile
), camel
(memberProfile
) or pascal
(MemberProfile
).
At the moment, this rule checks tables, views and columns.
rules: {
'name-casing': ['error', 'snake'],
},
If you want to enforce singular or plural naming for your tables, this rule can enforce it.
Which one to choose is a matter of great debate but in the end it comes down to personal preference. You can choose 'singular'
(default) or 'plural'
.
rules: {
'name-inflection': ['error', 'singular'],
},
In Postgres there is no performance penalty on using the text
type which has no maximum length, so you will generally want to choose that over varchar
.
The reasoning for this is outlined in the Postgres wiki: Don't use varchar(n) by default
rules: {
'prefer-text-to-varchar': ['error'],
},
In Postgres when you insert a value into a timestamptz
column, PostgreSQL converts the timestamptz
value into a UTC value and stores the UTC value in the table, and when you query timestamptz
from the database, PostgreSQL converts the UTC value back to the time value of the timezone set by the database server, the user, or the current database connection, whereas timestamp
does not save any
timezone data. You can learn more here: Understanding PostgreSQL Timestamp Data Types
rules: {
'prefer-timestamptz-to-timestamp': ['error'],
},
json
data is stored as a copy of the input text which processing functions need to reparse on each execution. jsonb
data is stored in a binary format which is faster to process, and also supports indexing.
While there are some caveats, the official PostgreSQL documentation states:
In general, most applications should prefer to store JSON data as jsonb, unless there are quite specialized needs, such as legacy assumptions about ordering of object keys.
You can learn more here: JSON types
rules: {
'prefer-jsonb-to-json': ['error'],
},
Identity columns are a SQL standard-conforming variant of PostgreSQL's serial columns. They fix a few usability issues that serial columns have:
- CREATE TABLE / LIKE copies default but refers to same sequence
- cannot add/drop serialness with ALTER TABLE
- dropping default does not drop sequence
- need to grant separate privileges to sequence
- other slight weirdnesses because serial is some kind of special macro
You can learn more here: Identity Columns Explained
rules: {
'prefer-identity-to-serial': ['error'],
},
Identify tables that do not have a primary key defined. Tables can be ignored by passing the ignorePattern
rule argument.
rules: {
'require-primary-key': ['error', {
ignorePattern: 'information_schema.*'
}],
},
PostgreSQL does not automatically create an index on the referencing column (not the referenced column) of a foreign key constraint. This rule can enforce that you create an index on the referencing column.
As the official PostgreSQL documentation states, it is not always needed to index the referencing columns, but it is often a good idea to do so.
Since a DELETE of a row from the referenced table or an UPDATE of a referenced column will require a scan of the referencing table for rows matching the old value, it is often a good idea to index the referencing columns too. Because this is not always needed, and there are many choices available on how to index, the declaration of a foreign key constraint does not automatically create an index on the referencing columns.
You can learn more here: Foreign Keys
rules: {
'index-referencing-column': ['error'],
}
This rule enforces that foreign key constraints have specific ON UPDATE
and ON DELETE
actions. Available actions are: NO ACTION
, RESTRICT
, CASCADE
, SET NULL
, SET DEFAULT
. When onUpdate
or onDelete
is not specified, the rule allows any action for the unspecified action.
rules: {
'reference-actions': ['error', {
onUpdate: 'NO ACTION',
onDelete: 'CASCADE',
}],
}
This rule enforces that a table has certain columns. The option is an object, where the key is the column name and the value is the object representing the required properties. Any property of the TableColumn object can be used as a required property. For example, you can specify ordinalPosition
to ensure that the column is in the expected position, but note that PostgreSQL always adds a new column to the very back.
rules: {
'mandatory-columns': ['error', {
created_at: {
expandedType: 'pg_catalog.timestamptz',
isNullable: false,
}
}],
}
Row-level security (RLS) is a feature that enables you to control which rows in a table are visible to different users. This rule checks that tables have row-level security enabled. You can also check that it is enforced by setting the enforced
option to true
.
rules: {
'row-level-security': ['error', {enforced: true}],
}