Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Categorize built-in rules documentation #347

Merged
merged 3 commits into from
Feb 22, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 49 additions & 41 deletions src/rules/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
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.

## name-casing
## Naming Conventions

### name-casing

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 ](https://wiki.postgresql.org/wiki/Don't_Do_This#Don.27t_use_upper_case_table_or_column_names).
Expand All @@ -18,29 +20,31 @@ At the moment, this rule checks tables, views and columns.
},
```

## prefer-text-to-varchar
### name-inflection

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](https://wiki.postgresql.org/wiki/Don't_Do_This#Don.27t_use_varchar.28n.29_by_default)
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'`.

```js
rules: {
'prefer-text-to-varchar': ['error'],
'name-inflection': ['error', 'singular'],
},
```

## name-inflection
## Data Types

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'`.
### prefer-text-to-varchar

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](https://wiki.postgresql.org/wiki/Don't_Do_This#Don.27t_use_varchar.28n.29_by_default)

```js
rules: {
'name-inflection': ['error', 'singular'],
'prefer-text-to-varchar': ['error'],
},
```

## prefer-timestamptz-to-timestamp
### prefer-timestamptz-to-timestamp

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
Expand All @@ -52,7 +56,7 @@ timezone data. You can learn more here: [Understanding PostgreSQL Timestamp Data
},
```

## prefer-jsonb-to-json
### prefer-jsonb-to-json

`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.

Expand All @@ -68,7 +72,7 @@ You can learn more here: [JSON types](https://www.postgresql.org/docs/current/da
},
```

## prefer-identity-to-serial
### prefer-identity-to-serial

Identity columns are a SQL standard-conforming variant of PostgreSQL's serial columns. They fix a few usability
issues that serial columns have:
Expand All @@ -87,19 +91,21 @@ You can learn more here: [Identity Columns Explained](https://www.2ndquadrant.co
},
```

## require-primary-key
## Table Structures

Identity tables that do not have a primary key defined. Tables can be ignored by passing the `ignorePattern` rule argument.
### require-primary-key

Identify tables that do not have a primary key defined. Tables can be ignored by passing the `ignorePattern` rule argument.
Copy link
Sponsor Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I replaced Identity with Identify. I am not sure, but I think it is a typo.


```js
rules: {
rules: {
'require-primary-key': ['error', {
ignorePattern: 'information_schema.*'
}],
},
```

## index-referencing-column
### index-referencing-column

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.

Expand All @@ -110,45 +116,47 @@ As the official PostgreSQL documentation states, it is not always needed to inde
You can learn more here: [Foreign Keys](https://www.postgresql.org/docs/current/ddl-constraints.html#DDL-CONSTRAINTS-FK)

```js
rules: {
'index-referencing-column': ['error'],
}
rules: {
'index-referencing-column': ['error'],
}
```

## reference-actions
### reference-actions

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.

```js
rules: {
'reference-actions': ['error', {
onUpdate: 'NO ACTION',
onDelete: 'CASCADE',
}],
}
rules: {
'reference-actions': ['error', {
onUpdate: 'NO ACTION',
onDelete: 'CASCADE',
}],
}
```

## row-level-security
### mandatory-columns

[Row-level security](https://www.postgresql.org/docs/current/ddl-rowsecurity.html) (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`.
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](https://kristiandupont.github.io/extract-pg-schema/api/extract-pg-schema.tablecolumn.html) 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.

```js
rules: {
'row-level-security': ['error', {enforced: true}],
}
rules: {
'mandatory-columns': ['error', {
created_at: {
expandedType: 'pg_catalog.timestamptz',
isNullable: false,
}
}],
}
```

## mandatory-columns
## Security

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](https://kristiandupont.github.io/extract-pg-schema/api/extract-pg-schema.tablecolumn.html) 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.
### row-level-security

[Row-level security](https://www.postgresql.org/docs/current/ddl-rowsecurity.html) (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`.

```js
rules: {
'mandatory-columns': ['error', {
created_at: {
expandedType: 'pg_catalog.timestamptz',
isNullable: false,
}
}],
}
rules: {
'row-level-security': ['error', {enforced: true}],
}
```