Back to Postgres Language Server

Rules

docs/reference/rules.md

0.25.27.6 KB
Original Source

Rules

Below the list of rules supported by the Postgres Language Server, divided by group. Here's a legend of the emojis:

  • The icon ✅ indicates that the rule is part of the recommended rules.

Safety

Rules that detect potential safety issues in your code.

Rule nameDescriptionProperties
addSerialColumnAdding a column with a SERIAL type or GENERATED ALWAYS AS ... STORED causes a full table rewrite.
addingFieldWithDefaultAdding a column with a DEFAULT value may lead to a table rewrite while holding an ACCESS EXCLUSIVE lock.
addingForeignKeyConstraintAdding a foreign key constraint requires a table scan and a SHARE ROW EXCLUSIVE lock on both tables, which blocks writes.
addingNotNullFieldSetting a column NOT NULL blocks reads while the table is scanned.
addingPrimaryKeyConstraintAdding a primary key constraint results in locks and table rewrites.
addingRequiredFieldAdding a new column that is NOT NULL and has no default value to an existing table effectively makes it required.
avoidAddingExclusionConstraintAdding an exclusion constraint acquires an ACCESS EXCLUSIVE lock.
avoidAlterEnumAddValueALTER TYPE ... ADD VALUE cannot run inside a transaction block in older Postgres versions.
avoidAttachingPartitionAttaching a partition acquires an ACCESS EXCLUSIVE lock on the parent table.
avoidCreateTriggerCreating a trigger acquires a SHARE ROW EXCLUSIVE lock on the table.
avoidEnableDisableTriggerEnabling or disabling a trigger acquires a SHARE ROW EXCLUSIVE lock.
avoidWideLockWindowAcquiring ACCESS EXCLUSIVE locks on multiple tables widens the lock window.
banCharFieldUsing CHAR(n) or CHARACTER(n) types is discouraged.
banConcurrentIndexCreationInTransactionConcurrent index creation is not allowed within a transaction.
banDeleteWithoutWhereA DELETE statement without a WHERE clause will remove all rows from the table.
banDropColumnDropping a column may break existing clients.
banDropDatabaseDropping a database may break existing clients (and everything else, really).
banDropNotNullDropping a NOT NULL constraint may break existing clients.
banDropSchemaDropping a schema will remove all objects within it and may break existing clients.
banDropTableDropping a table may break existing clients.
banDropTriggerDropping a trigger acquires an ACCESS EXCLUSIVE lock on the table.
banTruncateTruncating a table removes all rows and can cause data loss in production.
banTruncateCascadeUsing TRUNCATE's CASCADE option will truncate any tables that are also foreign-keyed to the specified tables.
banUpdateWithoutWhereAn UPDATE statement without a WHERE clause will modify all rows in the table.
banVacuumFullVACUUM FULL rewrites the entire table and acquires an ACCESS EXCLUSIVE lock.
changingColumnTypeChanging a column type may require a table rewrite and break existing clients.
concurrentRefreshMatviewLockREFRESH MATERIALIZED VIEW CONCURRENTLY still acquires an EXCLUSIVE lock.
constraintMissingNotValidAdding constraints without NOT VALID blocks all reads and writes.
creatingEnumCreating enum types is not recommended for new applications.
disallowUniqueConstraintDisallow adding a UNIQUE constraint without using an existing index.
lockTimeoutWarningTaking a dangerous lock without setting a lock timeout can cause indefinite blocking.
multipleAlterTableMultiple ALTER TABLE statements on the same table should be combined into a single statement.
preferBigIntPrefer BIGINT over smaller integer types.
preferBigintOverIntPrefer BIGINT over INT/INTEGER types.
preferBigintOverSmallintPrefer BIGINT over SMALLINT types.
preferIdentityPrefer using IDENTITY columns over serial columns.
preferJsonbPrefer JSONB over JSON types.
preferRobustStmtsPrefer statements with guards for robustness in migrations.
preferTextFieldPrefer using TEXT over VARCHAR(n) types.
preferTimestamptzPrefer TIMESTAMPTZ over TIMESTAMP types.
renamingColumnRenaming columns may break existing queries and application code.
renamingTableRenaming tables may break existing queries and application code.
requireConcurrentDetachPartitionDetaching a partition without CONCURRENTLY acquires an ACCESS EXCLUSIVE lock.
requireConcurrentIndexCreationCreating indexes non-concurrently can lock the table for writes.
requireConcurrentIndexDeletionDropping indexes non-concurrently can lock the table for reads.
requireConcurrentRefreshMatviewREFRESH MATERIALIZED VIEW without CONCURRENTLY acquires an ACCESS EXCLUSIVE lock.
requireConcurrentReindexREINDEX without CONCURRENTLY acquires an ACCESS EXCLUSIVE lock on the table.
requireIdleInTransactionTimeoutDangerous lock statements should be preceded by SET idle_in_transaction_session_timeout.
requireSeparateConstraintValidationValidating a constraint in the same transaction it was added as NOT VALID defeats the purpose.
requireStatementTimeoutDangerous lock statements should be preceded by SET statement_timeout.
runningStatementWhileHoldingAccessExclusiveRunning additional statements while holding an ACCESS EXCLUSIVE lock blocks all table access.
transactionNestingDetects problematic transaction nesting that could lead to unexpected behavior.