├── .cargo └── config.toml ├── .eslintignore ├── .eslintrc.js ├── .gitattributes ├── .github └── workflows │ ├── js.yml │ ├── python.yml │ └── rust.yml ├── .gitignore ├── .kodiak.toml ├── .npmignore ├── .pre-commit-hooks.yaml ├── .prettierignore ├── .prettierrc.js ├── .python-version ├── .vscode ├── extensions.json ├── extensions │ └── squawk-dev │ │ ├── .npmrc │ │ ├── .vscode-test.mjs │ │ ├── .vscode │ │ ├── extensions.json │ │ ├── launch.json │ │ ├── settings.json │ │ └── tasks.json │ │ ├── .vscodeignore │ │ ├── README.md │ │ ├── esbuild.js │ │ ├── eslint.config.mjs │ │ ├── package.json │ │ ├── pnpm-lock.yaml │ │ ├── src │ │ ├── definitionProviders.ts │ │ └── extension.ts │ │ └── tsconfig.json ├── launch.json ├── linter.code-snippets ├── settings.json └── syntax.code-snippets ├── CHANGELOG.md ├── CONTRIBUTING.md ├── Cargo.lock ├── Cargo.toml ├── Dockerfile ├── LICENSE ├── PLAN.md ├── README.md ├── crates ├── squawk │ ├── Cargo.toml │ ├── pyproject.toml │ └── src │ │ ├── config.rs │ │ ├── debug.rs │ │ ├── file.rs │ │ ├── file_finding.rs │ │ ├── github.rs │ │ ├── main.rs │ │ ├── reporter.rs │ │ └── snapshots │ │ ├── squawk__config__test_config__load_assume_in_transaction.snap │ │ ├── squawk__config__test_config__load_cfg_full.snap │ │ ├── squawk__config__test_config__load_excluded_paths.snap │ │ ├── squawk__config__test_config__load_excluded_rules.snap │ │ ├── squawk__config__test_config__load_fail_on_violations.snap │ │ ├── squawk__config__test_config__load_pg_version.snap │ │ ├── squawk__debug__test__dump_ast_basic_output.snap │ │ ├── squawk__github__test_github_comment__generating_comment_multiple_files.snap │ │ ├── squawk__github__test_github_comment__generating_comment_no_violations.snap │ │ ├── squawk__github__test_github_comment__generating_no_violations_no_files.snap │ │ ├── squawk__reporter__test_check_files__check_files_invalid_syntax.snap │ │ ├── squawk__reporter__test_reporter__display_no_violations_tty.snap │ │ ├── squawk__reporter__test_reporter__display_violations_tty.snap │ │ └── squawk__reporter__test_reporter__span_offsets.snap ├── squawk_github │ ├── Cargo.toml │ ├── README.md │ └── src │ │ ├── actions.rs │ │ ├── app.rs │ │ └── lib.rs ├── squawk_lexer │ ├── Cargo.toml │ ├── README.md │ └── src │ │ ├── LICENSE-MIT │ │ ├── cursor.rs │ │ ├── lib.rs │ │ ├── snapshots │ │ ├── squawk_lexer__tests__bitstring.snap │ │ ├── squawk_lexer__tests__block_comment.snap │ │ ├── squawk_lexer__tests__block_comment_unterminated.snap │ │ ├── squawk_lexer__tests__dollar_quote_mismatch_tags_complex.snap │ │ ├── squawk_lexer__tests__dollar_quote_mismatch_tags_simple.snap │ │ ├── squawk_lexer__tests__dollar_quoting.snap │ │ ├── squawk_lexer__tests__dollar_strings_part2.snap │ │ ├── squawk_lexer__tests__lex_statement.snap │ │ ├── squawk_lexer__tests__line_comment.snap │ │ ├── squawk_lexer__tests__line_comment_whitespace.snap │ │ ├── squawk_lexer__tests__numeric.snap │ │ ├── squawk_lexer__tests__numeric_non_decimal.snap │ │ ├── squawk_lexer__tests__numeric_with_seperators.snap │ │ ├── squawk_lexer__tests__params.snap │ │ ├── squawk_lexer__tests__quoted_ident.snap │ │ ├── squawk_lexer__tests__quoted_ident_with_escape_quote.snap │ │ ├── squawk_lexer__tests__select_with_period.snap │ │ ├── squawk_lexer__tests__string.snap │ │ ├── squawk_lexer__tests__string_unicode_escape.snap │ │ └── squawk_lexer__tests__string_with_escapes.snap │ │ └── token.rs ├── squawk_linter │ ├── Cargo.toml │ ├── README.md │ └── src │ │ ├── ignore.rs │ │ ├── ignore_index.rs │ │ ├── lib.rs │ │ ├── rules │ │ ├── adding_field_with_default.rs │ │ ├── adding_foreign_key_constraint.rs │ │ ├── adding_not_null_field.rs │ │ ├── adding_primary_key_constraint.rs │ │ ├── adding_required_field.rs │ │ ├── ban_alter_domain_with_add_constraint.rs │ │ ├── ban_char_field.rs │ │ ├── ban_concurrent_index_creation_in_transaction.rs │ │ ├── ban_create_domain_with_constraint.rs │ │ ├── ban_drop_column.rs │ │ ├── ban_drop_database.rs │ │ ├── ban_drop_not_null.rs │ │ ├── ban_drop_table.rs │ │ ├── ban_truncate_cascade.rs │ │ ├── changing_column_type.rs │ │ ├── constraint_missing_not_valid.rs │ │ ├── disallow_unique_constraint.rs │ │ ├── mod.rs │ │ ├── non_volatile_built_in_functions.txt │ │ ├── prefer_bigint_over_int.rs │ │ ├── prefer_bigint_over_smallint.rs │ │ ├── prefer_identity.rs │ │ ├── prefer_robust_stmts.rs │ │ ├── prefer_text_field.rs │ │ ├── prefer_timestamptz.rs │ │ ├── renaming_column.rs │ │ ├── renaming_table.rs │ │ ├── require_concurrent_index_creation.rs │ │ ├── require_concurrent_index_deletion.rs │ │ ├── snapshots │ │ │ ├── squawk_linter__rules__adding_field_with_default__test__add_numbers_ok.snap │ │ │ ├── squawk_linter__rules__adding_field_with_default__test__arbitrary_func_err.snap │ │ │ ├── squawk_linter__rules__adding_field_with_default__test__default_bool_ok.snap │ │ │ ├── squawk_linter__rules__adding_field_with_default__test__default_enum_ok.snap │ │ │ ├── squawk_linter__rules__adding_field_with_default__test__default_func_now_ok.snap │ │ │ ├── squawk_linter__rules__adding_field_with_default__test__default_jsonb_ok.snap │ │ │ ├── squawk_linter__rules__adding_field_with_default__test__default_random_with_args_err.snap │ │ │ ├── squawk_linter__rules__adding_field_with_default__test__default_str_ok.snap │ │ │ ├── squawk_linter__rules__adding_field_with_default__test__default_uuid_error.snap │ │ │ ├── squawk_linter__rules__adding_field_with_default__test__default_uuid_error_multi_stmt.snap │ │ │ ├── squawk_linter__rules__adding_field_with_default__test__default_volatile_func_err.snap │ │ │ ├── squawk_linter__rules__adding_field_with_default__test__docs_example_ok.snap │ │ │ ├── squawk_linter__rules__adding_field_with_default__test__docs_example_ok_post_pg_11.snap │ │ │ ├── squawk_linter__rules__adding_field_with_default__test__generated_stored_err.snap │ │ │ ├── squawk_linter__rules__adding_not_null_field__test__regression_gh_issue_519.snap │ │ │ ├── squawk_linter__rules__adding_not_null_field__test__set_not_null.snap │ │ │ ├── squawk_linter__rules__adding_primary_key_constraint__test__plain_primary_key.snap │ │ │ ├── squawk_linter__rules__adding_primary_key_constraint__test__serial_primary_key.snap │ │ │ ├── squawk_linter__rules__adding_required_field__test__not_null_without_default.snap │ │ │ ├── squawk_linter__rules__ban_alter_domain_with_add_constraint__test__err.snap │ │ │ ├── squawk_linter__rules__ban_char_field__test__all_the_types.snap │ │ │ ├── squawk_linter__rules__ban_char_field__test__alter_table_err.snap │ │ │ ├── squawk_linter__rules__ban_char_field__test__array_char_type_err.snap │ │ │ ├── squawk_linter__rules__ban_char_field__test__creating_table_with_char_errors.snap │ │ │ ├── squawk_linter__rules__ban_concurrent_index_creation_in_transaction__test__assuming_in_transaction_err.snap │ │ │ ├── squawk_linter__rules__ban_concurrent_index_creation_in_transaction__test__ban_concurrent_index_creation_in_transaction_err.snap │ │ │ ├── squawk_linter__rules__ban_create_domain_with_constraint__test__err.snap │ │ │ ├── squawk_linter__rules__ban_create_domain_with_constraint__test__err_with_multiple_constraints.snap │ │ │ ├── squawk_linter__rules__ban_drop_column__test__err.snap │ │ │ ├── squawk_linter__rules__ban_drop_database__test__ban_drop_database.snap │ │ │ ├── squawk_linter__rules__ban_drop_not_null__test__err.snap │ │ │ ├── squawk_linter__rules__ban_drop_table__test__err.snap │ │ │ ├── squawk_linter__rules__ban_truncate_cascade__test__err.snap │ │ │ ├── squawk_linter__rules__changing_column_type__test__another_err.snap │ │ │ ├── squawk_linter__rules__changing_column_type__test__err.snap │ │ │ ├── squawk_linter__rules__constraint_missing_not_valid__test__adding_check_constraint_err.snap │ │ │ ├── squawk_linter__rules__constraint_missing_not_valid__test__adding_fk_err.snap │ │ │ ├── squawk_linter__rules__constraint_missing_not_valid__test__not_valid_validate_assume_transaction_err.snap │ │ │ ├── squawk_linter__rules__constraint_missing_not_valid__test__not_valid_validate_transaction_err.snap │ │ │ ├── squawk_linter__rules__constraint_missing_not_valid__test__not_valid_validate_with_assume_in_transaction_with_explicit_commit_err.snap │ │ │ ├── squawk_linter__rules__disallow_unique_constraint__test__adding_unique_constraint_err.snap │ │ │ ├── squawk_linter__rules__disallow_unique_constraint__test__unique_constraint_inline_add_column_err.snap │ │ │ ├── squawk_linter__rules__disallow_unique_constraint__test__unique_constraint_inline_add_column_unique_err.snap │ │ │ ├── squawk_linter__rules__prefer_bigint_over_int__test__err.snap │ │ │ ├── squawk_linter__rules__prefer_bigint_over_smallint__test__err.snap │ │ │ ├── squawk_linter__rules__prefer_identity__test__err.snap │ │ │ ├── squawk_linter__rules__prefer_robust_stmts__test__alter_column_set_not_null.snap │ │ │ ├── squawk_linter__rules__prefer_robust_stmts__test__alter_table_drop_column_err.snap │ │ │ ├── squawk_linter__rules__prefer_robust_stmts__test__alter_table_drop_constraint_err.snap │ │ │ ├── squawk_linter__rules__prefer_robust_stmts__test__alter_table_err.snap │ │ │ ├── squawk_linter__rules__prefer_robust_stmts__test__create_index_concurrently_err.snap │ │ │ ├── squawk_linter__rules__prefer_robust_stmts__test__create_index_concurrently_muli_stmts_err.snap │ │ │ ├── squawk_linter__rules__prefer_robust_stmts__test__create_index_concurrently_unnamed_err.snap │ │ │ ├── squawk_linter__rules__prefer_robust_stmts__test__create_table_err.snap │ │ │ ├── squawk_linter__rules__prefer_robust_stmts__test__disable_row_level_security_err.snap │ │ │ ├── squawk_linter__rules__prefer_robust_stmts__test__double_add_after_drop_err.snap │ │ │ ├── squawk_linter__rules__prefer_robust_stmts__test__drop_index_err.snap │ │ │ ├── squawk_linter__rules__prefer_robust_stmts__test__enable_row_level_security_err.snap │ │ │ ├── squawk_linter__rules__prefer_robust_stmts__test__enable_row_level_security_without_exists_check_err.snap │ │ │ ├── squawk_linter__rules__prefer_text_field__test__adding_column_non_text_err.snap │ │ │ ├── squawk_linter__rules__prefer_text_field__test__create_table_with_pgcatalog_varchar_err.snap │ │ │ ├── squawk_linter__rules__prefer_text_field__test__create_table_with_varchar_err.snap │ │ │ ├── squawk_linter__rules__prefer_text_field__test__increase_varchar_size_err.snap │ │ │ ├── squawk_linter__rules__prefer_timestamptz__test__alter_table_with_timestamp_err.snap │ │ │ ├── squawk_linter__rules__prefer_timestamptz__test__create_table_with_timestamp_err.snap │ │ │ ├── squawk_linter__rules__renaming_column__test__err.snap │ │ │ ├── squawk_linter__rules__renaming_table__test__err.snap │ │ │ ├── squawk_linter__rules__require_concurrent_index_creation__test__adding_index_non_concurrently_err.snap │ │ │ ├── squawk_linter__rules__require_concurrent_index_deletion__test__drop_index_missing_concurrently_err.snap │ │ │ ├── squawk_linter__rules__transaction_nesting__test__begin_assume_transaction_err.snap │ │ │ ├── squawk_linter__rules__transaction_nesting__test__begin_repeated_err.snap │ │ │ ├── squawk_linter__rules__transaction_nesting__test__commit_repeated_err.snap │ │ │ ├── squawk_linter__rules__transaction_nesting__test__commit_with_assume_in_transaction_err.snap │ │ │ └── squawk_linter__rules__transaction_nesting__test__rollback_with_assume_in_transaction_err.snap │ │ └── transaction_nesting.rs │ │ ├── snapshots │ │ └── squawk_linter__version__test_pg_version__parse.snap │ │ ├── text.rs │ │ ├── version.rs │ │ └── visitors.rs ├── squawk_parser │ ├── Cargo.toml │ ├── README.md │ ├── src │ │ ├── event.rs │ │ ├── generated │ │ │ ├── mod.rs │ │ │ ├── syntax_kind.rs │ │ │ └── token_sets.rs │ │ ├── grammar.rs │ │ ├── input.rs │ │ ├── lexed_str.rs │ │ ├── lib.rs │ │ ├── output.rs │ │ ├── shortcuts.rs │ │ ├── syntax_kind.rs │ │ └── token_set.rs │ └── tests │ │ ├── data │ │ ├── err │ │ │ ├── alter_foreign_data_wrapper.sql │ │ │ ├── alter_sequence.sql │ │ │ ├── alter_server.sql │ │ │ ├── alter_table.sql │ │ │ ├── create_function.sql │ │ │ ├── create_table.sql │ │ │ ├── insert.sql │ │ │ ├── select.sql │ │ │ ├── select_cte.sql │ │ │ └── values.sql │ │ ├── ok │ │ │ ├── alter_aggregate.sql │ │ │ ├── alter_collation.sql │ │ │ ├── alter_conversion.sql │ │ │ ├── alter_database.sql │ │ │ ├── alter_default_privileges.sql │ │ │ ├── alter_domain.sql │ │ │ ├── alter_event_trigger.sql │ │ │ ├── alter_extension.sql │ │ │ ├── alter_foreign_data_wrapper.sql │ │ │ ├── alter_foreign_table.sql │ │ │ ├── alter_function.sql │ │ │ ├── alter_group.sql │ │ │ ├── alter_index.sql │ │ │ ├── alter_language.sql │ │ │ ├── alter_large_object.sql │ │ │ ├── alter_materialized_view.sql │ │ │ ├── alter_operator.sql │ │ │ ├── alter_operator_class.sql │ │ │ ├── alter_operator_family.sql │ │ │ ├── alter_policy.sql │ │ │ ├── alter_procedure.sql │ │ │ ├── alter_publication.sql │ │ │ ├── alter_role.sql │ │ │ ├── alter_routine.sql │ │ │ ├── alter_rule.sql │ │ │ ├── alter_schema.sql │ │ │ ├── alter_sequence.sql │ │ │ ├── alter_server.sql │ │ │ ├── alter_statistics.sql │ │ │ ├── alter_subscription.sql │ │ │ ├── alter_system.sql │ │ │ ├── alter_table.sql │ │ │ ├── alter_table_pg17.sql │ │ │ ├── alter_tablespace.sql │ │ │ ├── alter_text_search_configuration.sql │ │ │ ├── alter_text_search_dictionary.sql │ │ │ ├── alter_text_search_parser.sql │ │ │ ├── alter_text_search_template.sql │ │ │ ├── alter_trigger.sql │ │ │ ├── alter_type.sql │ │ │ ├── alter_user.sql │ │ │ ├── alter_user_mapping.sql │ │ │ ├── alter_view.sql │ │ │ ├── analyze.sql │ │ │ ├── call.sql │ │ │ ├── checkpoint.sql │ │ │ ├── close.sql │ │ │ ├── cluster.sql │ │ │ ├── comment.sql │ │ │ ├── copy.sql │ │ │ ├── create_access_method.sql │ │ │ ├── create_aggregate.sql │ │ │ ├── create_cast.sql │ │ │ ├── create_collation.sql │ │ │ ├── create_conversion.sql │ │ │ ├── create_database.sql │ │ │ ├── create_domain.sql │ │ │ ├── create_event_trigger.sql │ │ │ ├── create_ext.sql │ │ │ ├── create_foreign_data_wrapper.sql │ │ │ ├── create_foreign_table.sql │ │ │ ├── create_function.sql │ │ │ ├── create_group.sql │ │ │ ├── create_index.sql │ │ │ ├── create_language.sql │ │ │ ├── create_materialized_view.sql │ │ │ ├── create_operator.sql │ │ │ ├── create_operator_class.sql │ │ │ ├── create_operator_family.sql │ │ │ ├── create_policy.sql │ │ │ ├── create_procedure.sql │ │ │ ├── create_publication.sql │ │ │ ├── create_role.sql │ │ │ ├── create_rule.sql │ │ │ ├── create_sequence.sql │ │ │ ├── create_server.sql │ │ │ ├── create_statistics.sql │ │ │ ├── create_subscription.sql │ │ │ ├── create_table.sql │ │ │ ├── create_table_as.sql │ │ │ ├── create_table_pg17.sql │ │ │ ├── create_tablespace.sql │ │ │ ├── create_text_search_config.sql │ │ │ ├── create_text_search_dict.sql │ │ │ ├── create_text_search_parser.sql │ │ │ ├── create_text_search_template.sql │ │ │ ├── create_transform.sql │ │ │ ├── create_trigger.sql │ │ │ ├── create_type.sql │ │ │ ├── create_user.sql │ │ │ ├── create_view.sql │ │ │ ├── create_view_extra_parens.sql │ │ │ ├── deallocate.sql │ │ │ ├── declare.sql │ │ │ ├── delete.sql │ │ │ ├── discard.sql │ │ │ ├── do.sql │ │ │ ├── drop_access_method.sql │ │ │ ├── drop_aggregate.sql │ │ │ ├── drop_cast.sql │ │ │ ├── drop_collation.sql │ │ │ ├── drop_conversion.sql │ │ │ ├── drop_database.sql │ │ │ ├── drop_domain.sql │ │ │ ├── drop_event_trigger.sql │ │ │ ├── drop_extension.sql │ │ │ ├── drop_foreign_data.sql │ │ │ ├── drop_foreign_table.sql │ │ │ ├── drop_function.sql │ │ │ ├── drop_group.sql │ │ │ ├── drop_index.sql │ │ │ ├── drop_language.sql │ │ │ ├── drop_materialized_view.sql │ │ │ ├── drop_operator.sql │ │ │ ├── drop_operator_class.sql │ │ │ ├── drop_operator_family.sql │ │ │ ├── drop_owned.sql │ │ │ ├── drop_policy.sql │ │ │ ├── drop_procedure.sql │ │ │ ├── drop_publication.sql │ │ │ ├── drop_role.sql │ │ │ ├── drop_routine.sql │ │ │ ├── drop_rule.sql │ │ │ ├── drop_sequence.sql │ │ │ ├── drop_server.sql │ │ │ ├── drop_statistics.sql │ │ │ ├── drop_subscription.sql │ │ │ ├── drop_table.sql │ │ │ ├── drop_tablespace.sql │ │ │ ├── drop_text_search_config.sql │ │ │ ├── drop_text_search_dict.sql │ │ │ ├── drop_text_search_parser.sql │ │ │ ├── drop_text_search_template.sql │ │ │ ├── drop_transform.sql │ │ │ ├── drop_trigger.sql │ │ │ ├── drop_type.sql │ │ │ ├── drop_user.sql │ │ │ ├── drop_user_mapping.sql │ │ │ ├── drop_view.sql │ │ │ ├── execute.sql │ │ │ ├── explain.sql │ │ │ ├── fetch.sql │ │ │ ├── grant.sql │ │ │ ├── import_foreign_schema.sql │ │ │ ├── insert.sql │ │ │ ├── listen.sql │ │ │ ├── load.sql │ │ │ ├── lock.sql │ │ │ ├── merge.sql │ │ │ ├── merge_pg17.sql │ │ │ ├── misc.sql │ │ │ ├── move.sql │ │ │ ├── notify.sql │ │ │ ├── precedence.sql │ │ │ ├── prepare.sql │ │ │ ├── reassign.sql │ │ │ ├── refresh.sql │ │ │ ├── reindex.sql │ │ │ ├── reset.sql │ │ │ ├── revoke.sql │ │ │ ├── schemas.sql │ │ │ ├── security_label.sql │ │ │ ├── select.sql │ │ │ ├── select_casts.sql │ │ │ ├── select_compound_union_select.sql │ │ │ ├── select_cte.sql │ │ │ ├── select_funcs.sql │ │ │ ├── select_funcs_pg17.sql │ │ │ ├── select_into.sql │ │ │ ├── select_operators.sql │ │ │ ├── set_constraints.sql │ │ │ ├── set_role.sql │ │ │ ├── set_session_auth.sql │ │ │ ├── set_transaction.sql │ │ │ ├── transaction.sql │ │ │ ├── truncate.sql │ │ │ ├── unlisten.sql │ │ │ ├── update.sql │ │ │ ├── vacuum.sql │ │ │ └── values.sql │ │ └── regression_suite │ │ │ ├── LICENSE │ │ │ ├── advisory_lock.sql │ │ │ ├── aggregates.sql │ │ │ ├── alter_generic.sql │ │ │ ├── alter_operator.sql │ │ │ ├── alter_table.sql │ │ │ ├── amutils.sql │ │ │ ├── arrays.sql │ │ │ ├── async.sql │ │ │ ├── bit.sql │ │ │ ├── bitmapops.sql │ │ │ ├── boolean.sql │ │ │ ├── box.sql │ │ │ ├── brin.sql │ │ │ ├── brin_bloom.sql │ │ │ ├── brin_multi.sql │ │ │ ├── btree_index.sql │ │ │ ├── case.sql │ │ │ ├── char.sql │ │ │ ├── circle.sql │ │ │ ├── cluster.sql │ │ │ ├── collate.icu.utf8.sql │ │ │ ├── collate.linux.utf8.sql │ │ │ ├── collate.sql │ │ │ ├── collate.utf8.sql │ │ │ ├── combocid.sql │ │ │ ├── comments.sql │ │ │ ├── compression.sql │ │ │ ├── constraints.sql │ │ │ ├── conversion.sql │ │ │ ├── copy.sql │ │ │ ├── copy2.sql │ │ │ ├── copydml.sql │ │ │ ├── copyencoding.sql │ │ │ ├── copyselect.sql │ │ │ ├── create_aggregate.sql │ │ │ ├── create_am.sql │ │ │ ├── create_cast.sql │ │ │ ├── create_function_c.sql │ │ │ ├── create_function_sql.sql │ │ │ ├── create_index.sql │ │ │ ├── create_index_spgist.sql │ │ │ ├── create_misc.sql │ │ │ ├── create_operator.sql │ │ │ ├── create_procedure.sql │ │ │ ├── create_role.sql │ │ │ ├── create_schema.sql │ │ │ ├── create_table.sql │ │ │ ├── create_table_like.sql │ │ │ ├── create_type.sql │ │ │ ├── create_view.sql │ │ │ ├── database.sql │ │ │ ├── date.sql │ │ │ ├── dbsize.sql │ │ │ ├── delete.sql │ │ │ ├── dependency.sql │ │ │ ├── domain.sql │ │ │ ├── drop_if_exists.sql │ │ │ ├── drop_operator.sql │ │ │ ├── enum.sql │ │ │ ├── equivclass.sql │ │ │ ├── errors.sql │ │ │ ├── event_trigger.sql │ │ │ ├── event_trigger_login.sql │ │ │ ├── explain.sql │ │ │ ├── expressions.sql │ │ │ ├── fast_default.sql │ │ │ ├── float4.sql │ │ │ ├── float8.sql │ │ │ ├── foreign_data.sql │ │ │ ├── foreign_key.sql │ │ │ ├── functional_deps.sql │ │ │ ├── generated_stored.sql │ │ │ ├── generated_virtual.sql │ │ │ ├── geometry.sql │ │ │ ├── gin.sql │ │ │ ├── gist.sql │ │ │ ├── groupingsets.sql │ │ │ ├── guc.sql │ │ │ ├── hash_func.sql │ │ │ ├── hash_index.sql │ │ │ ├── hash_part.sql │ │ │ ├── horology.sql │ │ │ ├── identity.sql │ │ │ ├── incremental_sort.sql │ │ │ ├── index_including.sql │ │ │ ├── index_including_gist.sql │ │ │ ├── indexing.sql │ │ │ ├── indirect_toast.sql │ │ │ ├── inet.sql │ │ │ ├── infinite_recurse.sql │ │ │ ├── inherit.sql │ │ │ ├── init_privs.sql │ │ │ ├── insert.sql │ │ │ ├── insert_conflict.sql │ │ │ ├── int2.sql │ │ │ ├── int4.sql │ │ │ ├── int8.sql │ │ │ ├── interval.sql │ │ │ ├── join.sql │ │ │ ├── join_hash.sql │ │ │ ├── json.sql │ │ │ ├── json_encoding.sql │ │ │ ├── jsonb.sql │ │ │ ├── jsonb_jsonpath.sql │ │ │ ├── jsonpath.sql │ │ │ ├── jsonpath_encoding.sql │ │ │ ├── largeobject.sql │ │ │ ├── limit.sql │ │ │ ├── line.sql │ │ │ ├── lock.sql │ │ │ ├── lseg.sql │ │ │ ├── macaddr.sql │ │ │ ├── macaddr8.sql │ │ │ ├── maintain_every.sql │ │ │ ├── matview.sql │ │ │ ├── md5.sql │ │ │ ├── memoize.sql │ │ │ ├── merge.sql │ │ │ ├── misc.sql │ │ │ ├── misc_functions.sql │ │ │ ├── misc_sanity.sql │ │ │ ├── money.sql │ │ │ ├── multirangetypes.sql │ │ │ ├── mvcc.sql │ │ │ ├── name.sql │ │ │ ├── namespace.sql │ │ │ ├── numa.sql │ │ │ ├── numeric.sql │ │ │ ├── numeric_big.sql │ │ │ ├── numerology.sql │ │ │ ├── object_address.sql │ │ │ ├── oid.sql │ │ │ ├── oidjoins.sql │ │ │ ├── opr_sanity.sql │ │ │ ├── partition_aggregate.sql │ │ │ ├── partition_info.sql │ │ │ ├── partition_join.sql │ │ │ ├── partition_prune.sql │ │ │ ├── password.sql │ │ │ ├── path.sql │ │ │ ├── pg_lsn.sql │ │ │ ├── plancache.sql │ │ │ ├── plpgsql.sql │ │ │ ├── point.sql │ │ │ ├── polygon.sql │ │ │ ├── polymorphism.sql │ │ │ ├── portals.sql │ │ │ ├── portals_p2.sql │ │ │ ├── predicate.sql │ │ │ ├── prepare.sql │ │ │ ├── prepared_xacts.sql │ │ │ ├── privileges.sql │ │ │ ├── publication.sql │ │ │ ├── random.sql │ │ │ ├── rangefuncs.sql │ │ │ ├── rangetypes.sql │ │ │ ├── regex.sql │ │ │ ├── regproc.sql │ │ │ ├── reindex_catalog.sql │ │ │ ├── reloptions.sql │ │ │ ├── replica_identity.sql │ │ │ ├── returning.sql │ │ │ ├── roleattributes.sql │ │ │ ├── rowsecurity.sql │ │ │ ├── rowtypes.sql │ │ │ ├── rules.sql │ │ │ ├── sanity_check.sql │ │ │ ├── security_label.sql │ │ │ ├── select.sql │ │ │ ├── select_distinct.sql │ │ │ ├── select_distinct_on.sql │ │ │ ├── select_having.sql │ │ │ ├── select_implicit.sql │ │ │ ├── select_into.sql │ │ │ ├── select_parallel.sql │ │ │ ├── select_views.sql │ │ │ ├── sequence.sql │ │ │ ├── spgist.sql │ │ │ ├── sqljson.sql │ │ │ ├── sqljson_jsontable.sql │ │ │ ├── sqljson_queryfuncs.sql │ │ │ ├── stats.sql │ │ │ ├── stats_ext.sql │ │ │ ├── stats_import.sql │ │ │ ├── strings.sql │ │ │ ├── subscription.sql │ │ │ ├── subselect.sql │ │ │ ├── sysviews.sql │ │ │ ├── tablesample.sql │ │ │ ├── tablespace.sql │ │ │ ├── temp.sql │ │ │ ├── test_setup.sql │ │ │ ├── text.sql │ │ │ ├── tid.sql │ │ │ ├── tidrangescan.sql │ │ │ ├── tidscan.sql │ │ │ ├── time.sql │ │ │ ├── timestamp.sql │ │ │ ├── timestamptz.sql │ │ │ ├── timetz.sql │ │ │ ├── transactions.sql │ │ │ ├── triggers.sql │ │ │ ├── truncate.sql │ │ │ ├── tsdicts.sql │ │ │ ├── tsearch.sql │ │ │ ├── tsrf.sql │ │ │ ├── tstypes.sql │ │ │ ├── tuplesort.sql │ │ │ ├── txid.sql │ │ │ ├── type_sanity.sql │ │ │ ├── typed_table.sql │ │ │ ├── unicode.sql │ │ │ ├── union.sql │ │ │ ├── updatable_views.sql │ │ │ ├── update.sql │ │ │ ├── uuid.sql │ │ │ ├── vacuum.sql │ │ │ ├── vacuum_parallel.sql │ │ │ ├── varchar.sql │ │ │ ├── window.sql │ │ │ ├── with.sql │ │ │ ├── without_overlaps.sql │ │ │ ├── write_parallel.sql │ │ │ ├── xid.sql │ │ │ ├── xml.sql │ │ │ └── xmlmap.sql │ │ ├── snapshots │ │ ├── tests__alter_aggregate_ok.snap │ │ ├── tests__alter_collation_ok.snap │ │ ├── tests__alter_conversion_ok.snap │ │ ├── tests__alter_database_ok.snap │ │ ├── tests__alter_default_privileges_ok.snap │ │ ├── tests__alter_domain_ok.snap │ │ ├── tests__alter_event_trigger_ok.snap │ │ ├── tests__alter_extension_ok.snap │ │ ├── tests__alter_foreign_data_wrapper_err.snap │ │ ├── tests__alter_foreign_data_wrapper_ok.snap │ │ ├── tests__alter_foreign_table_ok.snap │ │ ├── tests__alter_function_ok.snap │ │ ├── tests__alter_group_ok.snap │ │ ├── tests__alter_index_ok.snap │ │ ├── tests__alter_language_ok.snap │ │ ├── tests__alter_large_object_ok.snap │ │ ├── tests__alter_materialized_view_ok.snap │ │ ├── tests__alter_operator_class_ok.snap │ │ ├── tests__alter_operator_family_ok.snap │ │ ├── tests__alter_operator_ok.snap │ │ ├── tests__alter_policy_ok.snap │ │ ├── tests__alter_procedure_ok.snap │ │ ├── tests__alter_publication_ok.snap │ │ ├── tests__alter_role_ok.snap │ │ ├── tests__alter_routine_ok.snap │ │ ├── tests__alter_rule_ok.snap │ │ ├── tests__alter_schema_ok.snap │ │ ├── tests__alter_sequence_err.snap │ │ ├── tests__alter_sequence_ok.snap │ │ ├── tests__alter_server_err.snap │ │ ├── tests__alter_server_ok.snap │ │ ├── tests__alter_statistics_ok.snap │ │ ├── tests__alter_subscription_ok.snap │ │ ├── tests__alter_system_ok.snap │ │ ├── tests__alter_table_err.snap │ │ ├── tests__alter_table_ok.snap │ │ ├── tests__alter_table_pg17_ok.snap │ │ ├── tests__alter_tablespace_ok.snap │ │ ├── tests__alter_text_search_configuration_ok.snap │ │ ├── tests__alter_text_search_dictionary_ok.snap │ │ ├── tests__alter_text_search_parser_ok.snap │ │ ├── tests__alter_text_search_template_ok.snap │ │ ├── tests__alter_trigger_ok.snap │ │ ├── tests__alter_type_ok.snap │ │ ├── tests__alter_user_mapping_ok.snap │ │ ├── tests__alter_user_ok.snap │ │ ├── tests__alter_view_ok.snap │ │ ├── tests__analyze_ok.snap │ │ ├── tests__call_ok.snap │ │ ├── tests__checkpoint_ok.snap │ │ ├── tests__close_ok.snap │ │ ├── tests__cluster_ok.snap │ │ ├── tests__comment_ok.snap │ │ ├── tests__copy_ok.snap │ │ ├── tests__create_access_method_ok.snap │ │ ├── tests__create_aggregate_ok.snap │ │ ├── tests__create_cast_ok.snap │ │ ├── tests__create_collation_ok.snap │ │ ├── tests__create_conversion_ok.snap │ │ ├── tests__create_database_ok.snap │ │ ├── tests__create_domain_ok.snap │ │ ├── tests__create_event_trigger_ok.snap │ │ ├── tests__create_ext_ok.snap │ │ ├── tests__create_foreign_data_wrapper_ok.snap │ │ ├── tests__create_foreign_table_ok.snap │ │ ├── tests__create_function_err.snap │ │ ├── tests__create_function_ok.snap │ │ ├── tests__create_group_ok.snap │ │ ├── tests__create_index_ok.snap │ │ ├── tests__create_language_ok.snap │ │ ├── tests__create_materialized_view_ok.snap │ │ ├── tests__create_operator_class_ok.snap │ │ ├── tests__create_operator_family_ok.snap │ │ ├── tests__create_operator_ok.snap │ │ ├── tests__create_policy_ok.snap │ │ ├── tests__create_procedure_ok.snap │ │ ├── tests__create_publication_ok.snap │ │ ├── tests__create_role_ok.snap │ │ ├── tests__create_rule_ok.snap │ │ ├── tests__create_sequence_ok.snap │ │ ├── tests__create_server_ok.snap │ │ ├── tests__create_statistics_ok.snap │ │ ├── tests__create_subscription_ok.snap │ │ ├── tests__create_table_as_ok.snap │ │ ├── tests__create_table_err.snap │ │ ├── tests__create_table_ok.snap │ │ ├── tests__create_table_pg17_ok.snap │ │ ├── tests__create_tablespace_ok.snap │ │ ├── tests__create_text_search_config_ok.snap │ │ ├── tests__create_text_search_dict_ok.snap │ │ ├── tests__create_text_search_parser_ok.snap │ │ ├── tests__create_text_search_template_ok.snap │ │ ├── tests__create_transform_ok.snap │ │ ├── tests__create_trigger_ok.snap │ │ ├── tests__create_type_ok.snap │ │ ├── tests__create_user_ok.snap │ │ ├── tests__create_view_extra_parens_ok.snap │ │ ├── tests__create_view_ok.snap │ │ ├── tests__deallocate_ok.snap │ │ ├── tests__declare_ok.snap │ │ ├── tests__delete_ok.snap │ │ ├── tests__discard_ok.snap │ │ ├── tests__do_ok.snap │ │ ├── tests__drop_access_method_ok.snap │ │ ├── tests__drop_aggregate_ok.snap │ │ ├── tests__drop_cast_ok.snap │ │ ├── tests__drop_collation_ok.snap │ │ ├── tests__drop_conversion_ok.snap │ │ ├── tests__drop_database_ok.snap │ │ ├── tests__drop_domain_ok.snap │ │ ├── tests__drop_event_trigger_ok.snap │ │ ├── tests__drop_extension_ok.snap │ │ ├── tests__drop_foreign_data_ok.snap │ │ ├── tests__drop_foreign_table_ok.snap │ │ ├── tests__drop_function_ok.snap │ │ ├── tests__drop_group_ok.snap │ │ ├── tests__drop_index_ok.snap │ │ ├── tests__drop_language_ok.snap │ │ ├── tests__drop_materialized_view_ok.snap │ │ ├── tests__drop_operator_class_ok.snap │ │ ├── tests__drop_operator_family_ok.snap │ │ ├── tests__drop_operator_ok.snap │ │ ├── tests__drop_owned_ok.snap │ │ ├── tests__drop_policy_ok.snap │ │ ├── tests__drop_procedure_ok.snap │ │ ├── tests__drop_publication_ok.snap │ │ ├── tests__drop_role_ok.snap │ │ ├── tests__drop_routine_ok.snap │ │ ├── tests__drop_rule_ok.snap │ │ ├── tests__drop_sequence_ok.snap │ │ ├── tests__drop_server_ok.snap │ │ ├── tests__drop_statistics_ok.snap │ │ ├── tests__drop_subscription_ok.snap │ │ ├── tests__drop_table_ok.snap │ │ ├── tests__drop_tablespace_ok.snap │ │ ├── tests__drop_text_search_config_ok.snap │ │ ├── tests__drop_text_search_dict_ok.snap │ │ ├── tests__drop_text_search_parser_ok.snap │ │ ├── tests__drop_text_search_template_ok.snap │ │ ├── tests__drop_transform_ok.snap │ │ ├── tests__drop_trigger_ok.snap │ │ ├── tests__drop_type_ok.snap │ │ ├── tests__drop_user_mapping_ok.snap │ │ ├── tests__drop_user_ok.snap │ │ ├── tests__drop_view_ok.snap │ │ ├── tests__execute_ok.snap │ │ ├── tests__explain_ok.snap │ │ ├── tests__fetch_ok.snap │ │ ├── tests__grant_ok.snap │ │ ├── tests__import_foreign_schema_ok.snap │ │ ├── tests__insert_err.snap │ │ ├── tests__insert_ok.snap │ │ ├── tests__listen_ok.snap │ │ ├── tests__load_ok.snap │ │ ├── tests__lock_ok.snap │ │ ├── tests__merge_ok.snap │ │ ├── tests__merge_pg17_ok.snap │ │ ├── tests__misc_ok.snap │ │ ├── tests__move_ok.snap │ │ ├── tests__notify_ok.snap │ │ ├── tests__precedence_ok.snap │ │ ├── tests__prepare_ok.snap │ │ ├── tests__reassign_ok.snap │ │ ├── tests__refresh_ok.snap │ │ ├── tests__regression_errors.snap │ │ ├── tests__regression_foreign_data.snap │ │ ├── tests__regression_foreign_key.snap │ │ ├── tests__regression_groupingsets.snap │ │ ├── tests__regression_horology.snap │ │ ├── tests__regression_inherit.snap │ │ ├── tests__regression_insert_conflict.snap │ │ ├── tests__regression_join.snap │ │ ├── tests__regression_merge.snap │ │ ├── tests__regression_partition_prune.snap │ │ ├── tests__regression_privileges.snap │ │ ├── tests__regression_publication.snap │ │ ├── tests__regression_rangefuncs.snap │ │ ├── tests__regression_returning.snap │ │ ├── tests__regression_rules.snap │ │ ├── tests__regression_sqljson.snap │ │ ├── tests__regression_sqljson_jsontable.snap │ │ ├── tests__regression_sqljson_queryfuncs.snap │ │ ├── tests__regression_strings.snap │ │ ├── tests__regression_subselect.snap │ │ ├── tests__regression_suite_errors.snap │ │ ├── tests__regression_timestamp.snap │ │ ├── tests__regression_timestamptz.snap │ │ ├── tests__regression_transactions.snap │ │ ├── tests__regression_tuplesort.snap │ │ ├── tests__regression_union.snap │ │ ├── tests__regression_update.snap │ │ ├── tests__regression_window.snap │ │ ├── tests__regression_with.snap │ │ ├── tests__regression_xml.snap │ │ ├── tests__reindex_ok.snap │ │ ├── tests__reset_ok.snap │ │ ├── tests__revoke_ok.snap │ │ ├── tests__schemas_ok.snap │ │ ├── tests__security_label_ok.snap │ │ ├── tests__select_casts_ok.snap │ │ ├── tests__select_compound_union_select_ok.snap │ │ ├── tests__select_cte_err.snap │ │ ├── tests__select_cte_ok.snap │ │ ├── tests__select_err.snap │ │ ├── tests__select_funcs_ok.snap │ │ ├── tests__select_funcs_pg17_ok.snap │ │ ├── tests__select_into_ok.snap │ │ ├── tests__select_ok.snap │ │ ├── tests__select_operators_ok.snap │ │ ├── tests__set_constraints_ok.snap │ │ ├── tests__set_role_ok.snap │ │ ├── tests__set_session_auth_ok.snap │ │ ├── tests__set_transaction_ok.snap │ │ ├── tests__transaction_ok.snap │ │ ├── tests__truncate_ok.snap │ │ ├── tests__unlisten_ok.snap │ │ ├── tests__update_ok.snap │ │ ├── tests__vacuum_ok.snap │ │ ├── tests__values_err.snap │ │ └── tests__values_ok.snap │ │ └── tests.rs ├── squawk_syntax │ ├── Cargo.toml │ ├── README.md │ ├── src │ │ ├── ast.rs │ │ ├── ast │ │ │ ├── generated │ │ │ │ ├── mod.rs │ │ │ │ ├── nodes.rs │ │ │ │ └── tokens.rs │ │ │ ├── node_ext.rs │ │ │ ├── nodes.rs │ │ │ ├── support.rs │ │ │ └── traits.rs │ │ ├── lib.rs │ │ ├── parsing.rs │ │ ├── postgresql.ungram │ │ ├── snapshots │ │ │ ├── squawk_syntax__test__alter_aggregate_params_validation.snap │ │ │ ├── squawk_syntax__test__array_exprs_validation.snap │ │ │ ├── squawk_syntax__test__create_aggregate_params_validation.snap │ │ │ ├── squawk_syntax__test__custom_operators_validation.snap │ │ │ ├── squawk_syntax__test__drop_aggregate_params_validation.snap │ │ │ └── squawk_syntax__test__validate_string_continuation_validation.snap │ │ ├── syntax_error.rs │ │ ├── syntax_node.rs │ │ ├── test.rs │ │ ├── token_text.rs │ │ └── validation.rs │ └── test_data │ │ └── validation │ │ ├── alter_aggregate_params.sql │ │ ├── array_exprs.sql │ │ ├── create_aggregate_params.sql │ │ ├── custom_operators.sql │ │ ├── drop_aggregate_params.sql │ │ └── validate_string_continuation.sql ├── squawk_wasm │ ├── Cargo.toml │ ├── README.md │ └── src │ │ └── lib.rs └── xtask │ ├── Cargo.toml │ ├── README.md │ └── src │ ├── codegen.rs │ ├── download_regression_tests.rs │ ├── keywords.rs │ ├── main.rs │ ├── new_rule.rs │ ├── path.rs │ └── sync_kwlist.rs ├── docs ├── .gitignore ├── README.md ├── babel.config.js ├── docs │ ├── adding-field-with-default.md │ ├── adding-foreign-key-constraint.md │ ├── adding-not-nullable-field.md │ ├── adding-required-field.md │ ├── adding-serial-primary-key-field.md │ ├── ban-alter-domain-with-add-constraint.md │ ├── ban-char-field.md │ ├── ban-concurrent-index-creation-in-transaction.md │ ├── ban-create-domain-with-constraint.md │ ├── ban-drop-column.md │ ├── ban-drop-database.md │ ├── ban-drop-not-null.md │ ├── ban-drop-table.md │ ├── ban-truncate-cascade.md │ ├── changing-column-type.md │ ├── cli.md │ ├── constraint-missing-not-valid.md │ ├── disallowed-unique-constraint.md │ ├── github_app.md │ ├── locks.md │ ├── prefer-bigint-over-int.md │ ├── prefer-bigint-over-smallint.md │ ├── prefer-identity.md │ ├── prefer-robust-stmts.md │ ├── prefer-text-field.md │ ├── prefer-timestamptz.md │ ├── quick_start.md │ ├── renaming-column.md │ ├── renaming-table.md │ ├── require-concurrent-index-creation.md │ ├── require-concurrent-index-deletion.md │ ├── rules-overview.md │ ├── safe_migrations.md │ ├── transaction-nesting.md │ ├── troubleshooting.md │ └── web-frameworks.md ├── docusaurus.config.js ├── package.json ├── sidebars.js ├── src │ ├── css │ │ └── custom.css │ └── pages │ │ ├── index.js │ │ └── styles.module.css ├── static │ ├── .nojekyll │ └── img │ │ ├── owl.png │ │ ├── squawk-pr-comment.png │ │ └── squawk-wordmark.png └── yarn.lock ├── example.sql ├── flake.lock ├── flake.nix ├── js ├── bin │ └── squawk ├── binaries │ └── .gitignore ├── helpers.js └── install.js ├── package.json ├── playground ├── .gitignore ├── .netlify │ └── state.json ├── README.md ├── eslint.config.js ├── index.html ├── package.json ├── pnpm-lock.yaml ├── prettier.config.js ├── public │ └── owl.png ├── src │ ├── App.tsx │ ├── index.css │ ├── main.tsx │ ├── monacoWorker.tsx │ ├── squawk.tsx │ └── vite-env.d.ts ├── tsconfig.app.json ├── tsconfig.json ├── tsconfig.node.json └── vite.config.ts ├── postgres ├── LICENSE └── kwlist.h ├── rust-toolchain.toml ├── s ├── check-version ├── ci-install ├── eslint ├── fmt ├── lint ├── pin-actions-versions ├── prettier ├── test ├── tsc └── update-version ├── tsconfig.json └── yarn.lock /.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [alias] 2 | xtask = "run --package xtask --" 3 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | # don't ever lint node_modules 2 | node_modules 3 | .eslintrc.js 4 | docs 5 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | parser: "@typescript-eslint/parser", 4 | parserOptions: { 5 | sourceType: "module", 6 | project: "./tsconfig.json", 7 | }, 8 | plugins: ["@typescript-eslint", "import"], 9 | settings: {}, 10 | env: { 11 | node: true, 12 | }, 13 | rules: { 14 | "import/no-duplicates": "error", 15 | "no-unneeded-ternary": ["error", { defaultAssignment: false }], 16 | "@typescript-eslint/no-non-null-assertion": "error", 17 | "@typescript-eslint/no-explicit-any": "error", 18 | "init-declarations": ["error", "always"], 19 | "no-lonely-if": "error", 20 | "object-shorthand": ["error", "always"], 21 | "@typescript-eslint/consistent-type-assertions": [ 22 | "error", 23 | { 24 | assertionStyle: "never", 25 | }, 26 | ], 27 | eqeqeq: ["error", "smart"], 28 | }, 29 | } 30 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | crates/squawk_parser/src/generated/* linguist-generated=true 2 | crates/squawk_syntax/src/ast/generated/* linguist-generated=true 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | *.pending-snap 4 | *.tgz 5 | *.pem 6 | 7 | # IntelliJ IDE users 8 | .idea 9 | dist 10 | 11 | .DS_Store 12 | -------------------------------------------------------------------------------- /.kodiak.toml: -------------------------------------------------------------------------------- 1 | version = 1 2 | 3 | [merge] 4 | method = "squash" 5 | delete_branch_on_merge = true 6 | 7 | [merge.message] 8 | title = "pull_request_title" 9 | body = "pull_request_body" 10 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # ignore everything 2 | /* 3 | 4 | # unignore desired files 5 | !package.json 6 | !README.md 7 | !LICENSE 8 | !js 9 | .DS_Store 10 | -------------------------------------------------------------------------------- /.pre-commit-hooks.yaml: -------------------------------------------------------------------------------- 1 | - id: squawk 2 | name: squawk 3 | description: 'Linter for Postgres migrations' 4 | entry: squawk 5 | language: node 6 | types: 7 | - text 8 | additional_dependencies: 9 | - squawk-cli 10 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | build/ 2 | node_modules/ 3 | playground/ 4 | coverage/ 5 | .venv/ 6 | .mypy_cache/ 7 | .terraform/ 8 | .pytest_cache/ 9 | target/ 10 | docs 11 | -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | // https://prettier.io/docs/en/options.html 2 | module.exports = { 3 | semi: false, 4 | useTabs: false, 5 | tabWidth: 2, 6 | singleQuote: false, 7 | trailingComma: "es5", 8 | bracketSpacing: true, 9 | jsxBracketSameLine: true, 10 | arrowParens: "avoid", 11 | } 12 | -------------------------------------------------------------------------------- /.python-version: -------------------------------------------------------------------------------- 1 | 3.10.4 2 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "ckolkman.vscode-postgres", 4 | "rust-lang.rust-analyzer", 5 | "usernamehw.errorlens", 6 | "dbaeumer.vscode-eslint", 7 | "mitsuhiko.insta", 8 | "esbenp.prettier-vscode", 9 | "vitest.explorer", 10 | "binhtran432k.ungrammar-language-features", 11 | "sleistner.vscode-fileutils", 12 | "tamasfe.even-better-toml" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /.vscode/extensions/squawk-dev/.npmrc: -------------------------------------------------------------------------------- 1 | enable-pre-post-scripts = true -------------------------------------------------------------------------------- /.vscode/extensions/squawk-dev/.vscode-test.mjs: -------------------------------------------------------------------------------- 1 | import { defineConfig } from '@vscode/test-cli'; 2 | 3 | export default defineConfig({ 4 | files: 'out/test/**/*.test.js', 5 | }); 6 | -------------------------------------------------------------------------------- /.vscode/extensions/squawk-dev/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | // See http://go.microsoft.com/fwlink/?LinkId=827846 3 | // for the documentation about the extensions.json format 4 | "recommendations": [ 5 | "dbaeumer.vscode-eslint", 6 | "connor4312.esbuild-problem-matchers", 7 | "ms-vscode.extension-test-runner" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /.vscode/extensions/squawk-dev/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | // A launch configuration that compiles the extension and then opens it inside a new window 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | { 6 | "version": "0.2.0", 7 | "configurations": [ 8 | { 9 | "name": "Run Extension", 10 | "type": "extensionHost", 11 | "request": "launch", 12 | "args": ["--extensionDevelopmentPath=${workspaceFolder}"], 13 | "outFiles": ["${workspaceFolder}/dist/**/*.js"], 14 | "preLaunchTask": "${defaultBuildTask}" 15 | } 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /.vscode/extensions/squawk-dev/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | // Place your settings in this file to overwrite default and user settings. 2 | { 3 | "files.exclude": { 4 | "out": false, // set this to true to hide the "out" folder with the compiled JS files 5 | "dist": false // set this to true to hide the "dist" folder with the compiled JS files 6 | }, 7 | "search.exclude": { 8 | "out": true, // set this to false to include "out" folder in search results 9 | "dist": true // set this to false to include "dist" folder in search results 10 | }, 11 | // Turn off tsc task auto detection since we have the necessary tasks as npm scripts 12 | "typescript.tsc.autoDetect": "off" 13 | } 14 | -------------------------------------------------------------------------------- /.vscode/extensions/squawk-dev/.vscodeignore: -------------------------------------------------------------------------------- 1 | .vscode/** 2 | .vscode-test/** 3 | out/** 4 | node_modules/** 5 | src/** 6 | .gitignore 7 | .yarnrc 8 | esbuild.js 9 | vsc-extension-quickstart.md 10 | **/tsconfig.json 11 | **/eslint.config.mjs 12 | **/*.map 13 | **/*.ts 14 | **/.vscode-test.* 15 | -------------------------------------------------------------------------------- /.vscode/extensions/squawk-dev/README.md: -------------------------------------------------------------------------------- 1 | # squawk-dev 2 | 3 | Extension to make developing squawk a little nicer. 4 | 5 | ## Install 6 | 7 | 1. install deps and build 8 | 9 | ```sh 10 | cd .vscode/extensions/squawk-dev 11 | pnpm install 12 | pnpm run compile 13 | ``` 14 | 15 | 2. enable extension in vscode 16 | 17 | In the command palette run: 18 | 19 | ``` 20 | Extensions: Show Recommended Extensions 21 | ``` 22 | 23 | You should then see the `recipeyak-dev` extension in the results. 24 | 25 | Press the `Install Workspace Extension` button. 26 | 27 | Done! 28 | 29 | ## Features 30 | 31 | ### Jump from snapshot to source file 32 | 33 | ### Jump from soruce file to snapshot 34 | -------------------------------------------------------------------------------- /.vscode/extensions/squawk-dev/eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import typescriptEslint from "@typescript-eslint/eslint-plugin" 2 | import tsParser from "@typescript-eslint/parser" 3 | 4 | export default [ 5 | { 6 | files: ["**/*.ts"], 7 | }, 8 | { 9 | plugins: { 10 | "@typescript-eslint": typescriptEslint, 11 | }, 12 | 13 | languageOptions: { 14 | parser: tsParser, 15 | ecmaVersion: 2022, 16 | sourceType: "module", 17 | }, 18 | 19 | rules: { 20 | "@typescript-eslint/naming-convention": [ 21 | "warn", 22 | { 23 | selector: "import", 24 | format: ["camelCase", "PascalCase"], 25 | }, 26 | ], 27 | 28 | curly: "warn", 29 | eqeqeq: ["warn", "smart"], 30 | "no-throw-literal": "warn", 31 | semi: ["warn", "never"], 32 | }, 33 | }, 34 | ] 35 | -------------------------------------------------------------------------------- /.vscode/extensions/squawk-dev/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "Node16", 4 | "target": "ES2022", 5 | "lib": ["ES2022"], 6 | "sourceMap": true, 7 | "rootDir": "src", 8 | "strict": true /* enable all strict type-checking options */ 9 | /* Additional Checks */ 10 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 11 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 12 | // "noUnusedParameters": true, /* Report errors on unused parameters. */ 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "lldb", 9 | "request": "launch", 10 | "name": "Debug executable 'squawk'", 11 | "cargo": { 12 | "args": ["build", "--bin=squawk", "--package=squawk"], 13 | "filter": { 14 | "name": "squawk", 15 | "kind": "bin" 16 | } 17 | }, 18 | "args": ["example.sql"], 19 | "cwd": "${workspaceFolder}" 20 | }, 21 | { 22 | "type": "lldb", 23 | "request": "launch", 24 | "name": "Debug unit tests in executable 'squawk'", 25 | "cargo": { 26 | "args": ["test", "--no-run", "--bin=squawk", "--package=squawk"], 27 | "filter": { 28 | "name": "squawk", 29 | "kind": "bin" 30 | } 31 | }, 32 | "args": [], 33 | "cwd": "${workspaceFolder}" 34 | } 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.formatOnSave": true, 3 | "editor.defaultFormatter": "esbenp.prettier-vscode", 4 | "rust-analyzer.check.command": "build", 5 | "rust-analyzer.showSyntaxTree": true, 6 | "[rust]": { 7 | "editor.defaultFormatter": "rust-lang.rust-analyzer" 8 | }, 9 | "files.associations": { 10 | "*.sql": "postgres" 11 | }, 12 | "[postgres]": { 13 | "editor.tabSize": 2 14 | }, 15 | "[ungrammar]": { 16 | "editor.tabSize": 2 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # contributing 2 | 3 | New rules welcome! 4 | 5 | If you have ideas for new rules or plan to add one, feel free to open an issue or a pull request. 6 | 7 | If you need any help contributing, please open an issue. 8 | 9 | See [the README's dev section](./README.md#dev) for development information. 10 | 11 | ## Adding new rules 12 | 13 | When adding a new rule, running `cargo xtask new-rule` will create stubs for your rule in the Rust crate and in Documentation site. 14 | 15 | ```bash 16 | cargo xtask new-rule 'prefer big serial' 17 | ``` 18 | -------------------------------------------------------------------------------- /crates/squawk/pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["maturin>=1.7,<2.0"] 3 | build-backend = "maturin" 4 | 5 | [project] 6 | name = "squawk-cli" 7 | description = "Linter for PostgreSQL migrations" 8 | requires-python = ">=3.8" 9 | classifiers = [ 10 | "License :: OSI Approved :: GNU General Public License v3 (GPLv3)", 11 | "Operating System :: MacOS", 12 | "Operating System :: Microsoft :: Windows", 13 | "Operating System :: POSIX :: Linux", 14 | "Programming Language :: Python :: 3", 15 | "Programming Language :: Rust", 16 | "Programming Language :: Python :: Implementation :: CPython", 17 | "Programming Language :: Python :: Implementation :: PyPy", 18 | ] 19 | dynamic = ["version"] 20 | 21 | [tool.maturin] 22 | bindings = "bin" 23 | -------------------------------------------------------------------------------- /crates/squawk/src/file.rs: -------------------------------------------------------------------------------- 1 | use std::{ 2 | fs::File, 3 | io::{self, Read}, 4 | path::PathBuf, 5 | }; 6 | 7 | use anyhow::Result; 8 | 9 | pub(crate) fn sql_from_stdin() -> Result { 10 | let mut buffer = String::new(); 11 | let stdin = io::stdin(); 12 | let mut handle = stdin.lock(); 13 | handle.read_to_string(&mut buffer)?; 14 | Ok(buffer) 15 | } 16 | 17 | pub(crate) fn sql_from_path(path: &PathBuf) -> Result { 18 | let mut file = File::open(path)?; 19 | let mut contents = String::new(); 20 | file.read_to_string(&mut contents)?; 21 | Ok(contents) 22 | } 23 | -------------------------------------------------------------------------------- /crates/squawk/src/snapshots/squawk__config__test_config__load_assume_in_transaction.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/cli/src/config.rs 3 | expression: "Config::parse(Some(squawk_toml.path().to_path_buf()))" 4 | --- 5 | Ok( 6 | Some( 7 | Config { 8 | excluded_paths: [], 9 | excluded_rules: [], 10 | pg_version: None, 11 | assume_in_transaction: Some( 12 | false, 13 | ), 14 | upload_to_github: UploadToGitHubConfig { 15 | fail_on_violations: None, 16 | }, 17 | }, 18 | ), 19 | ) 20 | -------------------------------------------------------------------------------- /crates/squawk/src/snapshots/squawk__config__test_config__load_cfg_full.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/cli/src/config.rs 3 | expression: "Config::parse(Some(squawk_toml.path().to_path_buf()))" 4 | --- 5 | Ok( 6 | Some( 7 | Config { 8 | excluded_paths: [ 9 | "example.sql", 10 | ], 11 | excluded_rules: [ 12 | RequireConcurrentIndexCreation, 13 | ], 14 | pg_version: Some( 15 | Version { 16 | major: 19, 17 | minor: Some( 18 | 1, 19 | ), 20 | patch: None, 21 | }, 22 | ), 23 | assume_in_transaction: Some( 24 | true, 25 | ), 26 | upload_to_github: UploadToGitHubConfig { 27 | fail_on_violations: None, 28 | }, 29 | }, 30 | ), 31 | ) 32 | -------------------------------------------------------------------------------- /crates/squawk/src/snapshots/squawk__config__test_config__load_excluded_paths.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/cli/src/config.rs 3 | expression: "Config::parse(Some(squawk_toml.path().to_path_buf()))" 4 | --- 5 | Ok( 6 | Some( 7 | Config { 8 | excluded_paths: [ 9 | "example.sql", 10 | ], 11 | excluded_rules: [], 12 | pg_version: None, 13 | assume_in_transaction: None, 14 | upload_to_github: UploadToGitHubConfig { 15 | fail_on_violations: None, 16 | }, 17 | }, 18 | ), 19 | ) 20 | -------------------------------------------------------------------------------- /crates/squawk/src/snapshots/squawk__config__test_config__load_excluded_rules.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/cli/src/config.rs 3 | expression: "Config::parse(Some(squawk_toml.path().to_path_buf()))" 4 | --- 5 | Ok( 6 | Some( 7 | Config { 8 | excluded_paths: [], 9 | excluded_rules: [ 10 | RequireConcurrentIndexCreation, 11 | ], 12 | pg_version: None, 13 | assume_in_transaction: None, 14 | upload_to_github: UploadToGitHubConfig { 15 | fail_on_violations: None, 16 | }, 17 | }, 18 | ), 19 | ) 20 | -------------------------------------------------------------------------------- /crates/squawk/src/snapshots/squawk__config__test_config__load_fail_on_violations.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/cli/src/config.rs 3 | expression: "Config::parse(Some(squawk_toml.path().to_path_buf()))" 4 | --- 5 | Ok( 6 | Some( 7 | Config { 8 | excluded_paths: [], 9 | excluded_rules: [], 10 | pg_version: None, 11 | assume_in_transaction: None, 12 | upload_to_github: UploadToGitHubConfig { 13 | fail_on_violations: Some( 14 | true, 15 | ), 16 | }, 17 | }, 18 | ), 19 | ) 20 | -------------------------------------------------------------------------------- /crates/squawk/src/snapshots/squawk__config__test_config__load_pg_version.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/cli/src/config.rs 3 | expression: "Config::parse(Some(squawk_toml.path().to_path_buf()))" 4 | --- 5 | Ok( 6 | Some( 7 | Config { 8 | excluded_paths: [], 9 | excluded_rules: [], 10 | pg_version: Some( 11 | Version { 12 | major: 19, 13 | minor: Some( 14 | 1, 15 | ), 16 | patch: None, 17 | }, 18 | ), 19 | assume_in_transaction: None, 20 | upload_to_github: UploadToGitHubConfig { 21 | fail_on_violations: None, 22 | }, 23 | }, 24 | ), 25 | ) 26 | -------------------------------------------------------------------------------- /crates/squawk/src/snapshots/squawk__debug__test__dump_ast_basic_output.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk/src/debug.rs 3 | expression: output 4 | --- 5 | { 6 | "stmts": [ 7 | { 8 | "type": "SELECT" 9 | }, 10 | { 11 | "type": "INSERT" 12 | }, 13 | { 14 | "type": "UPDATE" 15 | }, 16 | { 17 | "type": "DELETE" 18 | }, 19 | { 20 | "type": "TRUNCATE" 21 | } 22 | ], 23 | "version": "0.1" 24 | } 25 | -------------------------------------------------------------------------------- /crates/squawk/src/snapshots/squawk__github__test_github_comment__generating_comment_multiple_files.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/cli/src/github.rs 3 | expression: body 4 | --- 5 | # Squawk Report 6 | 7 | ### **🚒 1** violations across **1** file(s) 8 | 9 | --- 10 | 11 |

alpha.sql

12 | 13 | ```sql 14 | 15 | SELECT 1; 16 | 17 | ``` 18 | 19 |

🚒 Rule Violations (1)

20 | 21 | 22 | ``` 23 | warning[adding-not-nullable-field]: Adding a NOT NULL field requires exclusive locks and table rewrites. 24 | --> alpha.sql:1:1 25 | | 26 | | 27 | = help: Make the field nullable. 28 | ``` 29 | 30 | --- 31 | 32 | 33 | [📚 More info on rules](https://github.com/sbdchd/squawk#rules) 34 | 35 | ⚡️ Powered by [`Squawk`](https://github.com/sbdchd/squawk) (0.2.3), a linter for PostgreSQL, focused on migrations 36 | -------------------------------------------------------------------------------- /crates/squawk/src/snapshots/squawk__github__test_github_comment__generating_comment_no_violations.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/cli/src/github.rs 3 | expression: body 4 | --- 5 | # Squawk Report 6 | 7 | ### **✅ 0** violations across **2** file(s) 8 | 9 | --- 10 | 11 |

alpha.sql

12 | 13 | ```sql 14 | 15 | BEGIN; 16 | -- 17 | -- Create model Bar 18 | -- 19 | CREATE TABLE "core_bar" ( 20 | "id" serial NOT NULL PRIMARY KEY, 21 | "alpha" varchar(100) NOT NULL 22 | ); 23 | 24 | ``` 25 | 26 |

✅ Rule Violations (0)

27 | 28 | No violations found. 29 | 30 | --- 31 | 32 | 33 |

bravo.sql

34 | 35 | ```sql 36 | 37 | ALTER TABLE "core_recipe" ADD COLUMN "foo" integer DEFAULT 10; 38 | 39 | ``` 40 | 41 |

✅ Rule Violations (0)

42 | 43 | No violations found. 44 | 45 | --- 46 | 47 | 48 | [📚 More info on rules](https://github.com/sbdchd/squawk#rules) 49 | 50 | ⚡️ Powered by [`Squawk`](https://github.com/sbdchd/squawk) (0.2.3), a linter for PostgreSQL, focused on migrations 51 | -------------------------------------------------------------------------------- /crates/squawk/src/snapshots/squawk__github__test_github_comment__generating_no_violations_no_files.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/cli/src/github.rs 3 | expression: body 4 | --- 5 | # Squawk Report 6 | 7 | ### **✅ 0** violations across **0** file(s) 8 | 9 | --- 10 | 11 | 12 | [📚 More info on rules](https://github.com/sbdchd/squawk#rules) 13 | 14 | ⚡️ Powered by [`Squawk`](https://github.com/sbdchd/squawk) (0.2.3), a linter for PostgreSQL, focused on migrations 15 | -------------------------------------------------------------------------------- /crates/squawk/src/snapshots/squawk__reporter__test_check_files__check_files_invalid_syntax.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/cli/src/reporter.rs 3 | expression: val 4 | --- 5 | [{"column":6,"file":"test.sql","help":null,"level":"Error","line":1,"message":"expected SEMICOLON","rule_name":"syntax-error"},{"column":7,"file":"test.sql","help":null,"level":"Error","line":1,"message":"expected command, found ERROR","rule_name":"syntax-error"}] 6 | -------------------------------------------------------------------------------- /crates/squawk/src/snapshots/squawk__reporter__test_reporter__display_no_violations_tty.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/cli/src/reporter.rs 3 | expression: "strip_ansi_codes(&String::from_utf8_lossy(&buff))" 4 | --- 5 | Found 0 issues in 1 file 🎉 6 | -------------------------------------------------------------------------------- /crates/squawk_github/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "squawk_github" 3 | version = "0.0.0" 4 | authors = ["Steve Dignam "] 5 | edition = "2018" 6 | license = "GPL-3.0" 7 | description = "Postgres SQL linter Github APIs used in Squawk" 8 | repository = "https://github.com/sbdchd/squawk" 9 | readme = "README.md" 10 | keywords = ["bot", "github", "linter"] 11 | 12 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 13 | 14 | [dependencies] 15 | jsonwebtoken.workspace = true 16 | serde_json.workspace = true 17 | serde.workspace = true 18 | reqwest.workspace = true 19 | log.workspace = true 20 | -------------------------------------------------------------------------------- /crates/squawk_github/README.md: -------------------------------------------------------------------------------- 1 | # squawk_github 2 | 3 | A small wrapper around the GitHub API to allow [`squawk`](https://github.com/sbdchd/squawk) to comment on PRs. 4 | -------------------------------------------------------------------------------- /crates/squawk_lexer/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "squawk_lexer" 3 | version = "0.0.0" 4 | description = "TBD" 5 | 6 | authors.workspace = true 7 | edition.workspace = true 8 | license = "MIT" 9 | rust-version.workspace = true 10 | 11 | [lib] 12 | doctest = false 13 | 14 | [dependencies] 15 | 16 | [dev-dependencies] 17 | insta.workspace = true 18 | 19 | [lints] 20 | workspace = true 21 | -------------------------------------------------------------------------------- /crates/squawk_lexer/README.md: -------------------------------------------------------------------------------- 1 | # lexer 2 | 3 | > Adapted from the Rust lexer. 4 | -------------------------------------------------------------------------------- /crates/squawk_lexer/src/snapshots/squawk_lexer__tests__bitstring.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_lexer/src/lib.rs 3 | expression: "lex(r#\"\nB'1001'\nb'1001'\nX'1FF'\nx'1FF'\n\"#)" 4 | --- 5 | [ 6 | "\n" @ Whitespace, 7 | "B'1001'" @ Literal { kind: BitStr { terminated: true } }, 8 | "\n" @ Whitespace, 9 | "b'1001'" @ Literal { kind: BitStr { terminated: true } }, 10 | "\n" @ Whitespace, 11 | "X'1FF'" @ Literal { kind: ByteStr { terminated: true } }, 12 | "\n" @ Whitespace, 13 | "x'1FF'" @ Literal { kind: ByteStr { terminated: true } }, 14 | "\n" @ Whitespace, 15 | ] 16 | -------------------------------------------------------------------------------- /crates/squawk_lexer/src/snapshots/squawk_lexer__tests__block_comment.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_lexer/src/lib.rs 3 | expression: result 4 | --- 5 | [ 6 | "\n" @ Whitespace, 7 | "/*\n * foo\n * bar\n*/" @ BlockComment { terminated: true }, 8 | ] 9 | -------------------------------------------------------------------------------- /crates/squawk_lexer/src/snapshots/squawk_lexer__tests__block_comment_unterminated.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_lexer/src/lib.rs 3 | expression: result 4 | --- 5 | [ 6 | "\n" @ Whitespace, 7 | "/*\n * foo\n * bar\n /*\n*/" @ BlockComment { terminated: false }, 8 | ] 9 | -------------------------------------------------------------------------------- /crates/squawk_lexer/src/snapshots/squawk_lexer__tests__dollar_quote_mismatch_tags_complex.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_lexer/src/lib.rs 3 | expression: "lex(r#\"\n-- with dollar inside but mismatched tags\n$foo$hello$world$bar$\n\"#)" 4 | --- 5 | [ 6 | "\n" @ Whitespace, 7 | "-- with dollar inside but mismatched tags" @ LineComment, 8 | "\n" @ Whitespace, 9 | "$foo$hello$world$bar$\n" @ Literal { kind: DollarQuotedString { terminated: false } }, 10 | ] 11 | -------------------------------------------------------------------------------- /crates/squawk_lexer/src/snapshots/squawk_lexer__tests__dollar_quote_mismatch_tags_simple.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_lexer/src/lib.rs 3 | expression: "lex(r#\"\n-- dollar quoting with mismatched tags\n$foo$hello world$bar$\n\"#)" 4 | --- 5 | [ 6 | "\n" @ Whitespace, 7 | "-- dollar quoting with mismatched tags" @ LineComment, 8 | "\n" @ Whitespace, 9 | "$foo$hello world$bar$\n" @ Literal { kind: DollarQuotedString { terminated: false } }, 10 | ] 11 | -------------------------------------------------------------------------------- /crates/squawk_lexer/src/snapshots/squawk_lexer__tests__dollar_quoting.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_lexer/src/lib.rs 3 | expression: "lex(r#\"\n$$Dianne's horse$$\n$SomeTag$Dianne's horse$SomeTag$\n\n-- with dollar inside and matching tags\n$foo$hello$world$bar$\n\"#)" 4 | --- 5 | [ 6 | "\n" @ Whitespace, 7 | "$$Dianne's horse$$" @ Literal { kind: DollarQuotedString { terminated: true } }, 8 | "\n" @ Whitespace, 9 | "$SomeTag$Dianne's horse$SomeTag$" @ Literal { kind: DollarQuotedString { terminated: true } }, 10 | "\n\n" @ Whitespace, 11 | "-- with dollar inside and matching tags" @ LineComment, 12 | "\n" @ Whitespace, 13 | "$foo$hello$world$bar$\n" @ Literal { kind: DollarQuotedString { terminated: false } }, 14 | ] 15 | -------------------------------------------------------------------------------- /crates/squawk_lexer/src/snapshots/squawk_lexer__tests__dollar_strings_part2.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_lexer/src/lib.rs 3 | expression: "lex(r#\"\nDO $doblock$\nend\n$doblock$;\"#)" 4 | --- 5 | [ 6 | "\n" @ Whitespace, 7 | "DO" @ Ident, 8 | " " @ Whitespace, 9 | "$doblock$\nend\n$doblock$" @ Literal { kind: DollarQuotedString { terminated: true } }, 10 | ";" @ Semi, 11 | ] 12 | -------------------------------------------------------------------------------- /crates/squawk_lexer/src/snapshots/squawk_lexer__tests__lex_statement.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_lexer/src/lib.rs 3 | expression: result 4 | --- 5 | [ 6 | "select" @ Ident, 7 | " " @ Whitespace, 8 | "1" @ Literal { kind: Int { base: Decimal, empty_int: false } }, 9 | ";" @ Semi, 10 | ] 11 | -------------------------------------------------------------------------------- /crates/squawk_lexer/src/snapshots/squawk_lexer__tests__line_comment.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_lexer/src/lib.rs 3 | expression: result 4 | --- 5 | [ 6 | "\n" @ Whitespace, 7 | "-- foooooooooooo bar buzz" @ LineComment, 8 | "\n" @ Whitespace, 9 | ] 10 | -------------------------------------------------------------------------------- /crates/squawk_lexer/src/snapshots/squawk_lexer__tests__line_comment_whitespace.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_lexer/src/lib.rs 3 | expression: "lex(r#\"\nselect 'Hello' -- This is a comment\n' World';\"#)" 4 | --- 5 | [ 6 | "\n" @ Whitespace, 7 | "select" @ Ident, 8 | " " @ Whitespace, 9 | "'Hello'" @ Literal { kind: Str { terminated: true } }, 10 | " " @ Whitespace, 11 | "-- This is a comment" @ LineComment, 12 | "\n" @ Whitespace, 13 | "' World'" @ Literal { kind: Str { terminated: true } }, 14 | ";" @ Semi, 15 | ] 16 | -------------------------------------------------------------------------------- /crates/squawk_lexer/src/snapshots/squawk_lexer__tests__numeric_non_decimal.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_lexer/src/lib.rs 3 | expression: "lex(r#\"\n0b100101\n0B10011001\n0o273\n0O755\n0x42f\n0XFFFF\n\"#)" 4 | --- 5 | [ 6 | "\n" @ Whitespace, 7 | "0b100101" @ Literal { kind: Int { base: Binary, empty_int: false } }, 8 | "\n" @ Whitespace, 9 | "0B10011001" @ Literal { kind: Int { base: Binary, empty_int: false } }, 10 | "\n" @ Whitespace, 11 | "0o273" @ Literal { kind: Int { base: Octal, empty_int: false } }, 12 | "\n" @ Whitespace, 13 | "0O755" @ Literal { kind: Int { base: Octal, empty_int: false } }, 14 | "\n" @ Whitespace, 15 | "0x42f" @ Literal { kind: Int { base: Hexadecimal, empty_int: false } }, 16 | "\n" @ Whitespace, 17 | "0XFFFF" @ Literal { kind: Int { base: Hexadecimal, empty_int: false } }, 18 | "\n" @ Whitespace, 19 | ] 20 | -------------------------------------------------------------------------------- /crates/squawk_lexer/src/snapshots/squawk_lexer__tests__numeric_with_seperators.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_lexer/src/lib.rs 3 | expression: "lex(r#\"\n1_500_000_000\n0b10001000_00000000\n0o_1_755\n0xFFFF_FFFF\n1.618_034\n\"#)" 4 | --- 5 | [ 6 | "\n" @ Whitespace, 7 | "1_500_000_000" @ Literal { kind: Int { base: Decimal, empty_int: false } }, 8 | "\n" @ Whitespace, 9 | "0b10001000_00000000" @ Literal { kind: Int { base: Binary, empty_int: false } }, 10 | "\n" @ Whitespace, 11 | "0o_1_755" @ Literal { kind: Int { base: Octal, empty_int: false } }, 12 | "\n" @ Whitespace, 13 | "0xFFFF_FFFF" @ Literal { kind: Int { base: Hexadecimal, empty_int: false } }, 14 | "\n" @ Whitespace, 15 | "1.618_034" @ Literal { kind: Float { base: Decimal, empty_exponent: false } }, 16 | "\n" @ Whitespace, 17 | ] 18 | -------------------------------------------------------------------------------- /crates/squawk_lexer/src/snapshots/squawk_lexer__tests__params.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_lexer/src/lib.rs 3 | expression: "lex(r#\"\nselect $1 + $2;\n\nselect $1123123123123;\n\nselect $;\n\"#)" 4 | --- 5 | [ 6 | "\n" @ Whitespace, 7 | "select" @ Ident, 8 | " " @ Whitespace, 9 | "$1" @ PositionalParam, 10 | " " @ Whitespace, 11 | "+" @ Plus, 12 | " " @ Whitespace, 13 | "$2" @ PositionalParam, 14 | ";" @ Semi, 15 | "\n\n" @ Whitespace, 16 | "select" @ Ident, 17 | " " @ Whitespace, 18 | "$1123123123123" @ PositionalParam, 19 | ";" @ Semi, 20 | "\n\n" @ Whitespace, 21 | "select" @ Ident, 22 | " " @ Whitespace, 23 | "$" @ PositionalParam, 24 | ";" @ Semi, 25 | "\n" @ Whitespace, 26 | ] 27 | -------------------------------------------------------------------------------- /crates/squawk_lexer/src/snapshots/squawk_lexer__tests__quoted_ident.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_lexer/src/lib.rs 3 | expression: "lex(r#\"\n\"hello &1 -world\";\n\n\n\"hello-world\n\"#)" 4 | --- 5 | [ 6 | "\n" @ Whitespace, 7 | "\"hello &1 -world\"" @ QuotedIdent { terminated: true }, 8 | ";" @ Semi, 9 | "\n\n\n" @ Whitespace, 10 | "\"hello-world\n" @ QuotedIdent { terminated: false }, 11 | ] 12 | -------------------------------------------------------------------------------- /crates/squawk_lexer/src/snapshots/squawk_lexer__tests__quoted_ident_with_escape_quote.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_lexer/src/lib.rs 3 | expression: "lex(r#\"\n\"foo \"\" bar\"\n\"#)" 4 | --- 5 | [ 6 | "\n" @ Whitespace, 7 | "\"foo \"\" bar\"" @ QuotedIdent { terminated: true }, 8 | "\n" @ Whitespace, 9 | ] 10 | -------------------------------------------------------------------------------- /crates/squawk_lexer/src/snapshots/squawk_lexer__tests__select_with_period.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_lexer/src/lib.rs 3 | expression: "lex(r#\"\nselect public.users;\n\"#)" 4 | --- 5 | [ 6 | "\n" @ Whitespace, 7 | "select" @ Ident, 8 | " " @ Whitespace, 9 | "public" @ Ident, 10 | "." @ Dot, 11 | "users" @ Ident, 12 | ";" @ Semi, 13 | "\n" @ Whitespace, 14 | ] 15 | -------------------------------------------------------------------------------- /crates/squawk_lexer/src/snapshots/squawk_lexer__tests__string.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_lexer/src/lib.rs 3 | expression: "lex(r#\"\n'Dianne''s horse'\n\nselect 'foo ''\nbar';\n\nselect 'foooo' \n 'bar';\n\n\n'foo \\\\ \\n \\tbar'\n\n'forgot to close the string\n\"#)" 4 | --- 5 | [ 6 | "\n" @ Whitespace, 7 | "'Dianne''s horse'" @ Literal { kind: Str { terminated: true } }, 8 | "\n\n" @ Whitespace, 9 | "select" @ Ident, 10 | " " @ Whitespace, 11 | "'foo ''\nbar'" @ Literal { kind: Str { terminated: true } }, 12 | ";" @ Semi, 13 | "\n\n" @ Whitespace, 14 | "select" @ Ident, 15 | " " @ Whitespace, 16 | "'foooo'" @ Literal { kind: Str { terminated: true } }, 17 | " \n " @ Whitespace, 18 | "'bar'" @ Literal { kind: Str { terminated: true } }, 19 | ";" @ Semi, 20 | "\n\n\n" @ Whitespace, 21 | "'foo \\\\ \\n \\tbar'" @ Literal { kind: Str { terminated: true } }, 22 | "\n\n" @ Whitespace, 23 | "'forgot to close the string\n" @ Literal { kind: Str { terminated: false } }, 24 | ] 25 | -------------------------------------------------------------------------------- /crates/squawk_lexer/src/snapshots/squawk_lexer__tests__string_unicode_escape.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_lexer/src/lib.rs 3 | expression: "lex(r#\"\nU&\"d\\0061t\\+000061\"\n\nU&\"\\0441\\043B\\043E\\043D\"\n\nu&'\\0441\\043B'\n\nU&\"d!0061t!+000061\" UESCAPE '!'\n\"#)" 4 | --- 5 | [ 6 | "\n" @ Whitespace, 7 | "U&\"d\\0061t\\+000061\"" @ QuotedIdent { terminated: true }, 8 | "\n\n" @ Whitespace, 9 | "U&\"\\0441\\043B\\043E\\043D\"" @ QuotedIdent { terminated: true }, 10 | "\n\n" @ Whitespace, 11 | "u&'\\0441\\043B'" @ Literal { kind: UnicodeEscStr { terminated: true } }, 12 | "\n\n" @ Whitespace, 13 | "U&\"d!0061t!+000061\"" @ QuotedIdent { terminated: true }, 14 | " " @ Whitespace, 15 | "UESCAPE" @ Ident, 16 | " " @ Whitespace, 17 | "'!'" @ Literal { kind: Str { terminated: true } }, 18 | "\n" @ Whitespace, 19 | ] 20 | -------------------------------------------------------------------------------- /crates/squawk_lexer/src/snapshots/squawk_lexer__tests__string_with_escapes.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_lexer/src/lib.rs 3 | expression: "lex(r#\"\nE'foo'\n\ne'bar'\n\ne'\\b\\f\\n\\r\\t'\n\ne'\\0\\11\\777'\n\ne'\\x0\\x11\\xFF'\n\ne'\\uAAAA \\UFFFFFFFF'\n\n\"#)" 4 | --- 5 | [ 6 | "\n" @ Whitespace, 7 | "E'foo'" @ Literal { kind: EscStr { terminated: true } }, 8 | "\n\n" @ Whitespace, 9 | "e'bar'" @ Literal { kind: EscStr { terminated: true } }, 10 | "\n\n" @ Whitespace, 11 | "e'\\b\\f\\n\\r\\t'" @ Literal { kind: EscStr { terminated: true } }, 12 | "\n\n" @ Whitespace, 13 | "e'\\0\\11\\777'" @ Literal { kind: EscStr { terminated: true } }, 14 | "\n\n" @ Whitespace, 15 | "e'\\x0\\x11\\xFF'" @ Literal { kind: EscStr { terminated: true } }, 16 | "\n\n" @ Whitespace, 17 | "e'\\uAAAA \\UFFFFFFFF'" @ Literal { kind: EscStr { terminated: true } }, 18 | "\n\n" @ Whitespace, 19 | ] 20 | -------------------------------------------------------------------------------- /crates/squawk_linter/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "squawk_linter" 3 | version = "0.0.0" 4 | edition.workspace = true 5 | rust-version.workspace = true 6 | authors.workspace = true 7 | license.workspace = true 8 | 9 | [dependencies] 10 | squawk_syntax.workspace = true 11 | 12 | rowan.workspace = true 13 | serde.workspace = true 14 | lazy_static.workspace = true 15 | insta.workspace = true 16 | enum-iterator.workspace = true 17 | line-index.workspace = true 18 | serde_plain.workspace = true 19 | 20 | 21 | [lints] 22 | workspace = true 23 | -------------------------------------------------------------------------------- /crates/squawk_linter/README.md: -------------------------------------------------------------------------------- 1 | # linter 2 | 3 | ## Error message style guide 4 | 5 | ### Lock messages 6 | 7 | Each lock name should be: 8 | 9 | - accompanied by an explanation of its meaning in simple terms 10 | - tables that are affected 11 | 12 | Instead of: 13 | 14 | ``` 15 | Changing the size of a `varchar` field requires an `ACCESS EXCLUSIVE` lock. 16 | ``` 17 | 18 | include a lock description & table name: 19 | 20 | ``` 21 | Changing the size of a `varchar` field requires an `ACCESS EXCLUSIVE` lock, which prevents reads and writes to `users`. 22 | ``` 23 | 24 | ### Help 25 | 26 | A help message should be short an actionable. 27 | 28 | Instead of: 29 | 30 | ``` 31 | You can remove the `CASCADE` keyword and then specify exactly which tables you want to truncate directly. 32 | ``` 33 | 34 | tell the user what to change (add, update, remove): 35 | 36 | ``` 37 | Remove the `CASCADE` and specify exactly which tables you want to truncate. 38 | ``` 39 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_field_with_default__test__add_numbers_ok.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/adding_field_with_default.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: AddingFieldWithDefault, 8 | message: "Adding a generated column requires a table rewrite with an `ACCESS EXCLUSIVE` lock.", 9 | text_range: 62..67, 10 | help: Some( 11 | "Add the column as nullable, backfill existing rows, and add a trigger to update the column on write instead.", 12 | ), 13 | }, 14 | ] 15 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_field_with_default__test__arbitrary_func_err.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/adding_field_with_default.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: AddingFieldWithDefault, 8 | message: "Adding a generated column requires a table rewrite with an `ACCESS EXCLUSIVE` lock.", 9 | text_range: 74..83, 10 | help: Some( 11 | "Add the column as nullable, backfill existing rows, and add a trigger to update the column on write instead.", 12 | ), 13 | }, 14 | ] 15 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_field_with_default__test__default_bool_ok.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/adding_field_with_default.rs 3 | expression: errors 4 | --- 5 | [] 6 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_field_with_default__test__default_enum_ok.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/adding_field_with_default.rs 3 | expression: errors 4 | --- 5 | [] 6 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_field_with_default__test__default_func_now_ok.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/adding_field_with_default.rs 3 | expression: errors 4 | --- 5 | [] 6 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_field_with_default__test__default_jsonb_ok.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/adding_field_with_default.rs 3 | expression: errors 4 | --- 5 | [] 6 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_field_with_default__test__default_random_with_args_err.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/adding_field_with_default.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: AddingFieldWithDefault, 8 | message: "Adding a generated column requires a table rewrite with an `ACCESS EXCLUSIVE` lock.", 9 | text_range: 80..88, 10 | help: Some( 11 | "Add the column as nullable, backfill existing rows, and add a trigger to update the column on write instead.", 12 | ), 13 | }, 14 | ] 15 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_field_with_default__test__default_str_ok.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/adding_field_with_default.rs 3 | expression: errors 4 | --- 5 | [] 6 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_field_with_default__test__default_uuid_error.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/adding_field_with_default.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: AddingFieldWithDefault, 8 | message: "Adding a generated column requires a table rewrite with an `ACCESS EXCLUSIVE` lock.", 9 | text_range: 60..66, 10 | help: Some( 11 | "Add the column as nullable, backfill existing rows, and add a trigger to update the column on write instead.", 12 | ), 13 | }, 14 | ] 15 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_field_with_default__test__default_uuid_error_multi_stmt.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/adding_field_with_default.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: AddingFieldWithDefault, 8 | message: "Adding a generated column requires a table rewrite with an `ACCESS EXCLUSIVE` lock.", 9 | text_range: 56..62, 10 | help: Some( 11 | "Add the column as nullable, backfill existing rows, and add a trigger to update the column on write instead.", 12 | ), 13 | }, 14 | ] 15 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_field_with_default__test__default_volatile_func_err.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/adding_field_with_default.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: AddingFieldWithDefault, 8 | message: "Adding a generated column requires a table rewrite with an `ACCESS EXCLUSIVE` lock.", 9 | text_range: 76..84, 10 | help: Some( 11 | "Add the column as nullable, backfill existing rows, and add a trigger to update the column on write instead.", 12 | ), 13 | }, 14 | ] 15 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_field_with_default__test__docs_example_ok.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/adding_field_with_default.rs 3 | expression: errors 4 | --- 5 | [] 6 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_field_with_default__test__docs_example_ok_post_pg_11.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/adding_field_with_default.rs 3 | expression: errors 4 | --- 5 | [] 6 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_field_with_default__test__generated_stored_err.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/adding_field_with_default.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: AddingFieldWithDefault, 8 | message: "Adding a generated column requires a table rewrite with an `ACCESS EXCLUSIVE` lock.", 9 | text_range: 40..78, 10 | help: Some( 11 | "Add the column as nullable, backfill existing rows, and add a trigger to update the column on write instead.", 12 | ), 13 | }, 14 | ] 15 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_not_null_field__test__regression_gh_issue_519.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/adding_not_null_field.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: AddingNotNullableField, 8 | message: "Setting a column `NOT NULL` blocks reads while the table is scanned.", 9 | text_range: 78..90, 10 | help: Some( 11 | "Make the field nullable and use a `CHECK` constraint instead.", 12 | ), 13 | }, 14 | ] 15 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_not_null_field__test__set_not_null.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/adding_not_null_field.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: AddingNotNullableField, 8 | message: "Setting a column `NOT NULL` blocks reads while the table is scanned.", 9 | text_range: 46..58, 10 | help: Some( 11 | "Make the field nullable and use a `CHECK` constraint instead.", 12 | ), 13 | }, 14 | ] 15 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_primary_key_constraint__test__plain_primary_key.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/adding_primary_key_constraint.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: AddingSerialPrimaryKeyField, 8 | message: "Adding a primary key constraint requires an `ACCESS EXCLUSIVE` lock that will block all reads and writes to the table while the primary key index is built.", 9 | text_range: 23..39, 10 | help: Some( 11 | "Add the `PRIMARY KEY` constraint `USING` an index.", 12 | ), 13 | }, 14 | ] 15 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_primary_key_constraint__test__serial_primary_key.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/adding_primary_key_constraint.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: AddingSerialPrimaryKeyField, 8 | message: "Adding a primary key constraint requires an `ACCESS EXCLUSIVE` lock that will block all reads and writes to the table while the primary key index is built.", 9 | text_range: 43..54, 10 | help: Some( 11 | "Add the `PRIMARY KEY` constraint `USING` an index.", 12 | ), 13 | }, 14 | ] 15 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_required_field__test__not_null_without_default.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/adding_required_field.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: AddingRequiredField, 8 | message: "Adding a new column that is `NOT NULL` and has no default value to an existing table effectively makes it required.", 9 | text_range: 22..58, 10 | help: Some( 11 | "Make the field nullable or add a non-VOLATILE DEFAULT", 12 | ), 13 | }, 14 | ] 15 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__ban_alter_domain_with_add_constraint__test__err.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/ban_alter_domain_with_add_constraint.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: BanAlterDomainWithAddConstraint, 8 | message: "Domains with constraints have poor support for online migrations. Use table and column constraints instead.", 9 | text_range: 31..79, 10 | help: None, 11 | }, 12 | ] 13 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__ban_char_field__test__alter_table_err.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/ban_char_field.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: BanCharField, 8 | message: "Using `character` is likey a mistake and should almost always be replaced by `text` or `varchar`.", 9 | text_range: 28..32, 10 | help: None, 11 | }, 12 | ] 13 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__ban_char_field__test__array_char_type_err.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/ban_char_field.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: BanCharField, 8 | message: "Using `character` is likey a mistake and should almost always be replaced by `text` or `varchar`.", 9 | text_range: 22..26, 10 | help: None, 11 | }, 12 | ] 13 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__ban_concurrent_index_creation_in_transaction__test__assuming_in_transaction_err.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/ban_concurrent_index_creation_in_transaction.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: BanConcurrentIndexCreationInTransaction, 8 | message: "While regular index creation can happen inside a transaction, this is not allowed when the `CONCURRENTLY` option is used.", 9 | text_range: 39..51, 10 | help: Some( 11 | "Build the index outside any transactions.", 12 | ), 13 | }, 14 | ] 15 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__ban_concurrent_index_creation_in_transaction__test__ban_concurrent_index_creation_in_transaction_err.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/ban_concurrent_index_creation_in_transaction.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: BanConcurrentIndexCreationInTransaction, 8 | message: "While regular index creation can happen inside a transaction, this is not allowed when the `CONCURRENTLY` option is used.", 9 | text_range: 59..71, 10 | help: Some( 11 | "Build the index outside any transactions.", 12 | ), 13 | }, 14 | ] 15 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__ban_create_domain_with_constraint__test__err.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/ban_create_domain_with_constraint.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: BanCreateDomainWithConstraint, 8 | message: "Domains with constraints have poor support for online migrations. Use table and column constraints instead.", 9 | text_range: 46..63, 10 | help: None, 11 | }, 12 | ] 13 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__ban_create_domain_with_constraint__test__err_with_multiple_constraints.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/ban_create_domain_with_constraint.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: BanCreateDomainWithConstraint, 8 | message: "Domains with constraints have poor support for online migrations. Use table and column constraints instead.", 9 | text_range: 22..48, 10 | help: None, 11 | }, 12 | ] 13 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__ban_drop_column__test__err.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/ban_drop_column.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: BanDropColumn, 8 | message: "Dropping a column may break existing clients.", 9 | text_range: 23..52, 10 | help: None, 11 | }, 12 | ] 13 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__ban_drop_database__test__ban_drop_database.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/ban_drop_database.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: BanDropDatabase, 8 | message: "Dropping a database may break existing clients.", 9 | text_range: 9..35, 10 | help: None, 11 | }, 12 | Violation { 13 | code: BanDropDatabase, 14 | message: "Dropping a database may break existing clients.", 15 | text_range: 45..81, 16 | help: None, 17 | }, 18 | Violation { 19 | code: BanDropDatabase, 20 | message: "Dropping a database may break existing clients.", 21 | text_range: 91..127, 22 | help: None, 23 | }, 24 | ] 25 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__ban_drop_not_null__test__err.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/ban_drop_not_null.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: BanDropNotNull, 8 | message: "Dropping a `NOT NULL` constraint may break existing clients.", 9 | text_range: 46..59, 10 | help: None, 11 | }, 12 | ] 13 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__ban_drop_table__test__err.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/ban_drop_table.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: BanDropTable, 8 | message: "Dropping a table may break existing clients.", 9 | text_range: 1..24, 10 | help: None, 11 | }, 12 | Violation { 13 | code: BanDropTable, 14 | message: "Dropping a table may break existing clients.", 15 | text_range: 26..59, 16 | help: None, 17 | }, 18 | Violation { 19 | code: BanDropTable, 20 | message: "Dropping a table may break existing clients.", 21 | text_range: 61..94, 22 | help: None, 23 | }, 24 | ] 25 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__ban_truncate_cascade__test__err.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/ban_truncate_cascade.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: BanTruncateCascade, 8 | message: "Using `CASCADE` will recursively truncate any tables that foreign key to the referenced tables! So if you had foreign keys setup as `a <- b <- c` and truncated `a`, then `b` & `c` would also be truncated!", 9 | text_range: 26..33, 10 | help: Some( 11 | "Remove the `CASCADE` and specify exactly which tables you want to truncate.", 12 | ), 13 | }, 14 | ] 15 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__changing_column_type__test__another_err.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/changing_column_type.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: ChangingColumnType, 8 | message: "Changing a column type requires an `ACCESS EXCLUSIVE` lock on the table which blocks reads and writes while the table is rewritten. Changing the type of the column may also break other clients reading from the table.", 9 | text_range: 88..131, 10 | help: None, 11 | }, 12 | Violation { 13 | code: ChangingColumnType, 14 | message: "Changing a column type requires an `ACCESS EXCLUSIVE` lock on the table which blocks reads and writes while the table is rewritten. Changing the type of the column may also break other clients reading from the table.", 15 | text_range: 178..205, 16 | help: None, 17 | }, 18 | ] 19 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__changing_column_type__test__err.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/changing_column_type.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: ChangingColumnType, 8 | message: "Changing a column type requires an `ACCESS EXCLUSIVE` lock on the table which blocks reads and writes while the table is rewritten. Changing the type of the column may also break other clients reading from the table.", 9 | text_range: 92..121, 10 | help: None, 11 | }, 12 | ] 13 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__constraint_missing_not_valid__test__adding_check_constraint_err.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/constraint_missing_not_valid.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: ConstraintMissingNotValid, 8 | message: "By default new constraints require a table scan and block writes to the table while that scan occurs.", 9 | text_range: 38..94, 10 | help: Some( 11 | "Use `NOT VALID` with a later `VALIDATE CONSTRAINT` call.", 12 | ), 13 | }, 14 | ] 15 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__constraint_missing_not_valid__test__adding_fk_err.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/constraint_missing_not_valid.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: ConstraintMissingNotValid, 8 | message: "By default new constraints require a table scan and block writes to the table while that scan occurs.", 9 | text_range: 40..114, 10 | help: Some( 11 | "Use `NOT VALID` with a later `VALIDATE CONSTRAINT` call.", 12 | ), 13 | }, 14 | ] 15 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__constraint_missing_not_valid__test__not_valid_validate_assume_transaction_err.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/constraint_missing_not_valid.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: ConstraintMissingNotValid, 8 | message: "Using `NOT VALID` and `VALIDATE CONSTRAINT` in the same transaction will block all reads while the constraint is validated.", 9 | text_range: 134..163, 10 | help: Some( 11 | "Add constraint as `NOT VALID` in one transaction and `VALIDATE CONSTRAINT` in a separate transaction.", 12 | ), 13 | }, 14 | ] 15 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__constraint_missing_not_valid__test__not_valid_validate_transaction_err.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/constraint_missing_not_valid.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: ConstraintMissingNotValid, 8 | message: "Using `NOT VALID` and `VALIDATE CONSTRAINT` in the same transaction will block all reads while the constraint is validated.", 9 | text_range: 141..170, 10 | help: Some( 11 | "Add constraint as `NOT VALID` in one transaction and `VALIDATE CONSTRAINT` in a separate transaction.", 12 | ), 13 | }, 14 | ] 15 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__constraint_missing_not_valid__test__not_valid_validate_with_assume_in_transaction_with_explicit_commit_err.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/constraint_missing_not_valid.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: ConstraintMissingNotValid, 8 | message: "Using `NOT VALID` and `VALIDATE CONSTRAINT` in the same transaction will block all reads while the constraint is validated.", 9 | text_range: 134..163, 10 | help: Some( 11 | "Add constraint as `NOT VALID` in one transaction and `VALIDATE CONSTRAINT` in a separate transaction.", 12 | ), 13 | }, 14 | ] 15 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__disallow_unique_constraint__test__adding_unique_constraint_err.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/disallow_unique_constraint.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: DisallowedUniqueConstraint, 8 | message: "Adding a `UNIQUE` constraint requires an `ACCESS EXCLUSIVE` lock which blocks reads and writes to the table while the index is built.", 9 | text_range: 28..80, 10 | help: Some( 11 | "Create an index `CONCURRENTLY` and create the constraint using the index.", 12 | ), 13 | }, 14 | ] 15 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__disallow_unique_constraint__test__unique_constraint_inline_add_column_err.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/disallow_unique_constraint.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: DisallowedUniqueConstraint, 8 | message: "Adding a `UNIQUE` constraint requires an `ACCESS EXCLUSIVE` lock which blocks reads and writes to the table while the index is built.", 9 | text_range: 37..69, 10 | help: Some( 11 | "Create an index `CONCURRENTLY` and create the constraint using the index.", 12 | ), 13 | }, 14 | ] 15 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__disallow_unique_constraint__test__unique_constraint_inline_add_column_unique_err.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/disallow_unique_constraint.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: DisallowedUniqueConstraint, 8 | message: "Adding a `UNIQUE` constraint requires an `ACCESS EXCLUSIVE` lock which blocks reads and writes to the table while the index is built.", 9 | text_range: 37..43, 10 | help: Some( 11 | "Create an index `CONCURRENTLY` and create the constraint using the index.", 12 | ), 13 | }, 14 | ] 15 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__prefer_robust_stmts__test__alter_column_set_not_null.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/prefer_robust_stmts.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: PreferRobustStmts, 8 | message: "Missing transaction, the migration can't be rerun if it fails part way through.", 9 | text_range: 54..81, 10 | help: None, 11 | }, 12 | ] 13 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__prefer_robust_stmts__test__alter_table_drop_column_err.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/prefer_robust_stmts.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: PreferRobustStmts, 8 | message: "Missing `IF EXISTS`, the migration can't be rerun if it fails part way through.", 9 | text_range: 54..75, 10 | help: None, 11 | }, 12 | ] 13 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__prefer_robust_stmts__test__alter_table_drop_constraint_err.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/prefer_robust_stmts.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: PreferRobustStmts, 8 | message: "Missing `IF EXISTS`, the migration can't be rerun if it fails part way through.", 9 | text_range: 63..93, 10 | help: None, 11 | }, 12 | ] 13 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__prefer_robust_stmts__test__alter_table_err.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/prefer_robust_stmts.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: PreferRobustStmts, 8 | message: "Missing `IF NOT EXISTS`, the migration can't be rerun if it fails part way through.", 9 | text_range: 63..98, 10 | help: None, 11 | }, 12 | ] 13 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__prefer_robust_stmts__test__create_index_concurrently_err.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/prefer_robust_stmts.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: PreferRobustStmts, 8 | message: "Missing `IF NOT EXISTS`, the migration can't be rerun if it fails part way through.", 9 | text_range: 40..108, 10 | help: Some( 11 | "Use an explicit name for a concurrently created index", 12 | ), 13 | }, 14 | ] 15 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__prefer_robust_stmts__test__create_index_concurrently_muli_stmts_err.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/prefer_robust_stmts.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: PreferRobustStmts, 8 | message: "Missing `IF NOT EXISTS`, the migration can't be rerun if it fails part way through.", 9 | text_range: 1..57, 10 | help: Some( 11 | "Use an explicit name for a concurrently created index", 12 | ), 13 | }, 14 | Violation { 15 | code: PreferRobustStmts, 16 | message: "Missing `IF NOT EXISTS`, the migration can't be rerun if it fails part way through.", 17 | text_range: 59..115, 18 | help: Some( 19 | "Use an explicit name for a concurrently created index", 20 | ), 21 | }, 22 | ] 23 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__prefer_robust_stmts__test__create_index_concurrently_unnamed_err.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/prefer_robust_stmts.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: PreferRobustStmts, 8 | message: "Missing `IF NOT EXISTS`, the migration can't be rerun if it fails part way through.", 9 | text_range: 40..96, 10 | help: Some( 11 | "Use an explicit name for a concurrently created index", 12 | ), 13 | }, 14 | ] 15 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__prefer_robust_stmts__test__create_table_err.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/prefer_robust_stmts.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: PreferRobustStmts, 8 | message: "Missing `IF NOT EXISTS`, the migration can't be rerun if it fails part way through.", 9 | text_range: 11..122, 10 | help: None, 11 | }, 12 | ] 13 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__prefer_robust_stmts__test__disable_row_level_security_err.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/prefer_robust_stmts.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: PreferRobustStmts, 8 | message: "Missing transaction, the migration can't be rerun if it fails part way through.", 9 | text_range: 63..89, 10 | help: None, 11 | }, 12 | ] 13 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__prefer_robust_stmts__test__double_add_after_drop_err.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/prefer_robust_stmts.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: PreferRobustStmts, 8 | message: "Missing `IF NOT EXISTS`, the migration can't be rerun if it fails part way through.", 9 | text_range: 240..297, 10 | help: None, 11 | }, 12 | ] 13 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__prefer_robust_stmts__test__drop_index_err.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/prefer_robust_stmts.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: PreferRobustStmts, 8 | message: "Missing `IF NOT EXISTS`, the migration can't be rerun if it fails part way through.", 9 | text_range: 40..75, 10 | help: None, 11 | }, 12 | ] 13 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__prefer_robust_stmts__test__enable_row_level_security_err.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/prefer_robust_stmts.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: PreferRobustStmts, 8 | message: "Missing transaction, the migration can't be rerun if it fails part way through.", 9 | text_range: 63..88, 10 | help: None, 11 | }, 12 | ] 13 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__prefer_robust_stmts__test__enable_row_level_security_without_exists_check_err.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/prefer_robust_stmts.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: PreferRobustStmts, 8 | message: "Missing transaction, the migration can't be rerun if it fails part way through.", 9 | text_range: 53..78, 10 | help: None, 11 | }, 12 | ] 13 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__prefer_text_field__test__adding_column_non_text_err.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/prefer_text_field.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: PreferTextField, 8 | message: "Changing the size of a `varchar` field requires an `ACCESS EXCLUSIVE` lock, that will prevent all reads and writes to the table.", 9 | text_range: 56..68, 10 | help: Some( 11 | "Use a `TEXT` field with a `CHECK` constraint.", 12 | ), 13 | }, 14 | ] 15 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__prefer_text_field__test__create_table_with_pgcatalog_varchar_err.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/prefer_text_field.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: PreferTextField, 8 | message: "Changing the size of a `varchar` field requires an `ACCESS EXCLUSIVE` lock, that will prevent all reads and writes to the table.", 9 | text_range: 69..92, 10 | help: Some( 11 | "Use a `TEXT` field with a `CHECK` constraint.", 12 | ), 13 | }, 14 | ] 15 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__prefer_text_field__test__create_table_with_varchar_err.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/prefer_text_field.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: PreferTextField, 8 | message: "Changing the size of a `varchar` field requires an `ACCESS EXCLUSIVE` lock, that will prevent all reads and writes to the table.", 9 | text_range: 111..123, 10 | help: Some( 11 | "Use a `TEXT` field with a `CHECK` constraint.", 12 | ), 13 | }, 14 | ] 15 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__prefer_text_field__test__increase_varchar_size_err.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/prefer_text_field.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: PreferTextField, 8 | message: "Changing the size of a `varchar` field requires an `ACCESS EXCLUSIVE` lock, that will prevent all reads and writes to the table.", 9 | text_range: 89..102, 10 | help: Some( 11 | "Use a `TEXT` field with a `CHECK` constraint.", 12 | ), 13 | }, 14 | ] 15 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__renaming_column__test__err.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/renaming_column.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: RenamingColumn, 8 | message: "Renaming a column may break existing clients.", 9 | text_range: 26..74, 10 | help: None, 11 | }, 12 | ] 13 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__renaming_table__test__err.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/renaming_table.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: RenamingTable, 8 | message: "Renaming a table may break existing clients.", 9 | text_range: 26..52, 10 | help: None, 11 | }, 12 | ] 13 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__require_concurrent_index_creation__test__adding_index_non_concurrently_err.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/require_concurrent_index_creation.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: RequireConcurrentIndexCreation, 8 | message: "During normal index creation, table updates are blocked, but reads are still allowed.", 9 | text_range: 15..75, 10 | help: Some( 11 | "Use `CONCURRENTLY` to avoid blocking writes.", 12 | ), 13 | }, 14 | ] 15 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__require_concurrent_index_deletion__test__drop_index_missing_concurrently_err.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/require_concurrent_index_deletion.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: RequireConcurrentIndexDeletion, 8 | message: "A normal `DROP INDEX` acquires an `ACCESS EXCLUSIVE` lock on the table, blocking other accesses until the index drop can complete.", 9 | text_range: 19..56, 10 | help: Some( 11 | "Drop the index `CONCURRENTLY`.", 12 | ), 13 | }, 14 | ] 15 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__transaction_nesting__test__begin_repeated_err.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/transaction_nesting.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: TransactionNesting, 8 | message: "There is an existing transaction already in progress.", 9 | text_range: 8..13, 10 | help: Some( 11 | "Put migration statements in separate files to have them be in separate transactions or don't use the assume-in-transaction setting.", 12 | ), 13 | }, 14 | ] 15 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__transaction_nesting__test__commit_repeated_err.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/transaction_nesting.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: TransactionNesting, 8 | message: "There is no transaction to `COMMIT` or `ROLLBACK`.", 9 | text_range: 26..32, 10 | help: Some( 11 | "`BEGIN` a transaction at an earlier point in the migration or remove this statement.", 12 | ), 13 | }, 14 | ] 15 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__transaction_nesting__test__commit_with_assume_in_transaction_err.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/transaction_nesting.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: TransactionNesting, 8 | message: "Attempting to end the transaction that is managed by your migration tool", 9 | text_range: 11..17, 10 | help: Some( 11 | "Put migration statements in separate files to have them be in separate transactions or don't use the assume-in-transaction setting.", 12 | ), 13 | }, 14 | ] 15 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__transaction_nesting__test__rollback_with_assume_in_transaction_err.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/rules/transaction_nesting.rs 3 | expression: errors 4 | --- 5 | [ 6 | Violation { 7 | code: TransactionNesting, 8 | message: "Attempting to end the transaction that is managed by your migration tool", 9 | text_range: 92..100, 10 | help: Some( 11 | "Put migration statements in separate files to have them be in separate transactions or don't use the assume-in-transaction setting.", 12 | ), 13 | }, 14 | ] 15 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/snapshots/squawk_linter__version__test_pg_version__parse.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_linter/src/version.rs 3 | expression: "Version::from_str(\"test\").unwrap_err()" 4 | --- 5 | InvalidNumber( 6 | InvalidNumber { 7 | version: "test", 8 | e: ParseIntError { 9 | kind: InvalidDigit, 10 | }, 11 | }, 12 | ) 13 | -------------------------------------------------------------------------------- /crates/squawk_linter/src/text.rs: -------------------------------------------------------------------------------- 1 | // TODO: figure out a better way to handle quoted and unquoted idents 2 | pub(crate) fn trim_quotes(s: &str) -> &str { 3 | if s.starts_with('"') && s.ends_with('"') { 4 | &s[1..s.len() - 1] 5 | } else { 6 | s 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /crates/squawk_parser/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "squawk_parser" 3 | version = "0.0.0" 4 | description = "TBD" 5 | 6 | authors.workspace = true 7 | edition.workspace = true 8 | license.workspace = true 9 | rust-version.workspace = true 10 | 11 | [lib] 12 | doctest = false 13 | 14 | [dependencies] 15 | squawk_lexer.workspace = true 16 | drop_bomb.workspace = true 17 | 18 | [dev-dependencies] 19 | insta.workspace = true 20 | dir-test.workspace = true 21 | camino.workspace = true 22 | pg_query.workspace = true 23 | xshell.workspace = true 24 | 25 | [lints] 26 | workspace = true 27 | -------------------------------------------------------------------------------- /crates/squawk_parser/src/generated/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod syntax_kind; 2 | pub(crate) mod token_sets; 3 | -------------------------------------------------------------------------------- /crates/squawk_parser/src/syntax_kind.rs: -------------------------------------------------------------------------------- 1 | // based on https://github.com/rust-lang/rust-analyzer/blob/d8887c0758bbd2d5f752d5bd405d4491e90e7ed6/crates/parser/src/syntax_kind.rs 2 | 3 | pub use crate::generated::syntax_kind::SyntaxKind; 4 | 5 | impl From for SyntaxKind { 6 | #[inline] 7 | fn from(d: u16) -> SyntaxKind { 8 | assert!(d <= (SyntaxKind::__LAST as u16)); 9 | unsafe { std::mem::transmute::(d) } 10 | } 11 | } 12 | 13 | impl From for u16 { 14 | #[inline] 15 | fn from(k: SyntaxKind) -> u16 { 16 | k as u16 17 | } 18 | } 19 | 20 | impl SyntaxKind { 21 | #[inline] 22 | pub fn is_trivia(self) -> bool { 23 | matches!(self, SyntaxKind::WHITESPACE | SyntaxKind::COMMENT) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/err/alter_foreign_data_wrapper.sql: -------------------------------------------------------------------------------- 1 | -- missing option 2 | alter foreign data wrapper w; 3 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/err/alter_sequence.sql: -------------------------------------------------------------------------------- 1 | -- missing option 2 | alter sequence s; 3 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/err/alter_server.sql: -------------------------------------------------------------------------------- 1 | -- missing option 2 | alter server s; 3 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/err/alter_table.sql: -------------------------------------------------------------------------------- 1 | -- missing alter_table 2 | add column foo boolean; 3 | 4 | -- mismatch options 5 | alter table t alter constraint c not deferrable initially deferred; 6 | 7 | -- pg 18 only, via: https://www.depesz.com/2025/05/01/waiting-for-postgresql-18-allow-not-null-constraints-to-be-added-as-not-valid/ 8 | alter table public.copy_2 add constraint id_not_null not null id not valid; 9 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/err/create_function.sql: -------------------------------------------------------------------------------- 1 | -- regression partial definition 2 | create function 3 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/err/insert.sql: -------------------------------------------------------------------------------- 1 | -- missing comma in column list 2 | insert into t (a, b c) 3 | values (1, 2, 3) 4 | on conflict do nothing; 5 | 6 | -- missing column in column list & trailing comma 7 | insert into t (a,,c,) 8 | values (1, 2, 3) 9 | on conflict do nothing; 10 | 11 | -- missing comma in values & trailing comma 12 | insert into t (a, b, c) 13 | values (4, 5 6,) 14 | on conflict do nothing; 15 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/err/select.sql: -------------------------------------------------------------------------------- 1 | --- via https://duckdb.org/docs/stable/sql/dialect/friendly_sql.html#trailing-commas 2 | select 3 | 42 as x, 4 | array['a', 'b', 'c',] as y, 5 | 'hello world' as z, 6 | ; 7 | 8 | -- trailing comma in column list 9 | select * from t as u(a,); 10 | 11 | -- missing comma 12 | select a, b c d, e from t; 13 | -- ^ ^ comma missing 14 | -- \-- this is a label 15 | 16 | -- trailing comma in args 17 | select f(1,); 18 | 19 | -- missing args 20 | select f(a,,,,,); 21 | 22 | -- in can only be used with tuples / sub queries 23 | select 1 in c; 24 | 25 | -- type cast must use a string literal 26 | select numeric 1234; 27 | 28 | -- regression test: this would cause the parser to get stuck & panic, now it 29 | -- warns about a missing semicolon 30 | select select; 31 | 32 | -- trailing comma at EOF 33 | select 1, 34 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/err/select_cte.sql: -------------------------------------------------------------------------------- 1 | with t as ( 2 | select 1 3 | ), -- <--- extra comma! 4 | select * from t; 5 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/err/values.sql: -------------------------------------------------------------------------------- 1 | 2 | -- trailing comma and missing comma between value lists 3 | values (1,) (1); 4 | 5 | -- extra comma, aka missing tuple 6 | values (1),, (2); 7 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/alter_aggregate.sql: -------------------------------------------------------------------------------- 1 | -- star 2 | alter aggregate a (*) rename to b; 3 | 4 | -- simple_args 5 | alter aggregate a (t) set schema s; 6 | 7 | -- complex_args 8 | alter aggregate a (in x text, y numeric) 9 | owner to current_user; 10 | 11 | -- with_order_by 12 | alter aggregate a (x order by y) 13 | rename to b; 14 | 15 | -- qualified_names 16 | alter aggregate foo.bar (in t, u) 17 | set schema new_schema; 18 | 19 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/alter_collation.sql: -------------------------------------------------------------------------------- 1 | -- refresh 2 | alter collation c 3 | refresh version; 4 | 5 | -- rename 6 | alter collation c 7 | rename to d; 8 | 9 | -- owner 10 | alter collation c 11 | owner to u; 12 | alter collation s.c 13 | owner to current_role; 14 | 15 | -- set_schema 16 | alter collation c 17 | set schema s; 18 | 19 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/alter_conversion.sql: -------------------------------------------------------------------------------- 1 | -- rename 2 | alter conversion c rename to n; 3 | 4 | -- owner 5 | alter conversion c owner to u; 6 | alter conversion c owner to current_user; 7 | 8 | -- set_schema 9 | alter conversion c set schema s; 10 | 11 | -- qualified_name 12 | alter conversion a.c set schema s; 13 | 14 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/alter_database.sql: -------------------------------------------------------------------------------- 1 | -- rename 2 | alter database d rename to n; 3 | 4 | -- owner 5 | alter database d owner to u; 6 | alter database d owner to current_user; 7 | 8 | -- tablespace 9 | alter database d set tablespace t; 10 | 11 | -- refresh 12 | alter database d refresh collation version; 13 | 14 | -- set_param 15 | alter database d set p to v; 16 | alter database d set p = v; 17 | alter database d set p = default; 18 | alter database d set p from current; 19 | 20 | -- reset 21 | alter database d reset p; 22 | alter database d reset all; 23 | 24 | -- with_option 25 | alter database d with allow_connections true; 26 | 27 | -- option_connection_limit 28 | alter database d connection limit 10; 29 | 30 | -- option_is_template 31 | alter database d is_template false; 32 | 33 | -- with_multiple_options 34 | alter database d with allow_connections true connection limit 10 is_template false; 35 | 36 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/alter_domain.sql: -------------------------------------------------------------------------------- 1 | -- set_default 2 | alter domain d 3 | set default 42; 4 | 5 | -- drop_default 6 | alter domain foo.d 7 | drop default; 8 | 9 | -- set_not_null 10 | alter domain d 11 | set not null; 12 | 13 | -- drop_not_null 14 | alter domain d 15 | drop not null; 16 | 17 | -- add_constraint 18 | alter domain d 19 | add constraint c check (value > 0); 20 | alter domain d 21 | add check (value > 0) not valid; 22 | alter domain d 23 | add constraint a check (a > b); 24 | 25 | -- drop_constraint 26 | alter domain d 27 | drop constraint c cascade; 28 | alter domain d 29 | drop constraint if exists c restrict; 30 | 31 | -- rename_constraint 32 | alter domain d 33 | rename constraint c to n; 34 | 35 | -- validate_constraint 36 | alter domain d 37 | validate constraint c; 38 | 39 | -- owner_to 40 | alter domain d 41 | owner to u; 42 | alter domain d 43 | owner to current_user; 44 | 45 | -- rename_to 46 | alter domain d 47 | rename to n; 48 | 49 | -- set_schema 50 | alter domain d 51 | set schema s; 52 | 53 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/alter_event_trigger.sql: -------------------------------------------------------------------------------- 1 | -- disable 2 | alter event trigger t disable; 3 | 4 | -- enable 5 | alter event trigger t enable; 6 | 7 | -- enable_replica 8 | alter event trigger t enable replica; 9 | 10 | -- enable_always 11 | alter event trigger t enable always; 12 | 13 | -- owner 14 | alter event trigger t owner to u; 15 | 16 | -- owner_current_role 17 | alter event trigger t owner to current_role; 18 | 19 | -- rename 20 | alter event trigger t rename to u; 21 | 22 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/alter_foreign_data_wrapper.sql: -------------------------------------------------------------------------------- 1 | -- handler 2 | alter foreign data wrapper w 3 | handler h; 4 | 5 | -- no_handler 6 | alter foreign data wrapper w 7 | no handler; 8 | 9 | -- validator 10 | alter foreign data wrapper w 11 | validator v; 12 | 13 | -- no_validator 14 | alter foreign data wrapper w 15 | no validator; 16 | 17 | -- options 18 | alter foreign data wrapper w 19 | options (add o 'v', set o 'v', drop o); 20 | 21 | -- multiple 22 | alter foreign data wrapper w 23 | handler s.h 24 | no handler 25 | validator s.v 26 | no validator 27 | options (add o 'v', set o '', drop d); 28 | 29 | -- owner 30 | alter foreign data wrapper w 31 | owner to u; 32 | 33 | -- rename 34 | alter foreign data wrapper w 35 | rename to n; 36 | 37 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/alter_function.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | alter function f stable; 3 | 4 | -- rename 5 | alter function f rename to g; 6 | alter function s.f rename to g; 7 | 8 | -- action_with_params 9 | alter function f(int, text) strict; 10 | 11 | -- owner 12 | alter function f owner to current_user; 13 | 14 | -- schema 15 | alter function f set schema s; 16 | 17 | -- multiple_actions 18 | alter function f 19 | called on null input 20 | returns null on null input 21 | strict 22 | immutable 23 | stable 24 | volatile 25 | not leakproof 26 | leakproof 27 | external security invoker 28 | security invoker 29 | external security definer 30 | security definer 31 | parallel unsafe 32 | parallel restricted 33 | parallel safe 34 | cost 100 35 | rows 10 36 | support f 37 | set c to 1 38 | set c = 1 39 | set c = default 40 | set c from current 41 | reset c 42 | reset all 43 | restrict; 44 | 45 | -- depends 46 | alter function f depends on extension e; 47 | alter function f no depends on extension e; 48 | 49 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/alter_group.sql: -------------------------------------------------------------------------------- 1 | -- add 2 | alter group g add user u; 3 | 4 | -- add_multiple 5 | alter group g add user u, v, w; 6 | 7 | -- drop 8 | alter group g drop user u; 9 | 10 | -- drop_multiple 11 | alter group g drop user u, v, w; 12 | 13 | -- rename 14 | alter group g rename to n; 15 | 16 | -- current_role 17 | alter group current_role add user u; 18 | 19 | -- current_user 20 | alter group current_user drop user u; 21 | 22 | -- session_user 23 | alter group session_user add user u; 24 | 25 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/alter_index.sql: -------------------------------------------------------------------------------- 1 | -- rename 2 | alter index i rename to j; 3 | alter index if exists s.i rename to j; 4 | 5 | -- set_tablespace 6 | alter index i set tablespace t; 7 | alter index if exists s.i set tablespace t; 8 | 9 | -- set_params 10 | alter index i set (a); 11 | alter index if exists s.i set (a=1, b='v'); 12 | 13 | -- reset_params 14 | alter index i reset (a); 15 | alter index if exists s.i reset (a, b); 16 | 17 | -- attach 18 | alter index i attach partition p; 19 | alter index s.i attach partition s.p; 20 | 21 | -- depends 22 | alter index i no depends on extension e; 23 | alter index s.i depends on extension e; 24 | 25 | -- alter_column 26 | alter index i alter 1 set statistics 100; 27 | alter index if exists s.i alter column 1 set statistics 100; 28 | 29 | -- all_tablespace 30 | alter index all in tablespace t 31 | set tablespace n; 32 | alter index all in tablespace t 33 | owned by r, s 34 | set tablespace n 35 | nowait; 36 | 37 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/alter_language.sql: -------------------------------------------------------------------------------- 1 | -- rename 2 | alter language x rename to y; 3 | alter procedural language x rename to y; 4 | 5 | -- owner 6 | alter language x owner to u; 7 | alter procedural language x owner to current_user; 8 | 9 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/alter_large_object.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | alter large object 12345 owner to u; 3 | 4 | -- current_role 5 | alter large object 12345 owner to current_role; 6 | 7 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/alter_operator.sql: -------------------------------------------------------------------------------- 1 | -- owner 2 | alter operator p.+ (int4, int4) 3 | owner to u; 4 | 5 | -- schema 6 | alter operator + (none, text) 7 | set schema s; 8 | 9 | -- options 10 | alter operator & (bool, bool) 11 | set ( 12 | restrict = r, 13 | join = j, 14 | commutator = c, 15 | negator = n, 16 | hashes = enabled, 17 | merges = enabled 18 | ); 19 | 20 | -- none_options 21 | alter operator % (int, int) 22 | set (restrict = none, join = none); 23 | 24 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/alter_operator_class.sql: -------------------------------------------------------------------------------- 1 | -- rename 2 | alter operator class c using m 3 | rename to n; 4 | 5 | alter operator class s.c using m 6 | rename to n; 7 | 8 | -- owner 9 | alter operator class c using m 10 | owner to u; 11 | 12 | alter operator class c using m 13 | owner to current_user; 14 | 15 | -- schema 16 | alter operator class c using m 17 | set schema s; 18 | 19 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/alter_policy.sql: -------------------------------------------------------------------------------- 1 | -- rename 2 | alter policy p on t 3 | rename to q; 4 | 5 | -- to_role 6 | alter policy p on t 7 | to r; 8 | 9 | -- to_multiple_roles 10 | alter policy p on t 11 | to r, public, current_user; 12 | 13 | -- using_expr 14 | alter policy p on t 15 | using (a = b); 16 | 17 | -- with_check 18 | alter policy p on t 19 | with check (c > d); 20 | 21 | -- full 22 | alter policy p on t 23 | to r, s 24 | using (a = b) 25 | with check (c > d); 26 | 27 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/alter_procedure.sql: -------------------------------------------------------------------------------- 1 | -- rename 2 | alter procedure p 3 | rename to q; 4 | alter procedure foo.p(int, text) 5 | rename to q; 6 | 7 | -- owner 8 | alter procedure p 9 | owner to u; 10 | alter procedure p 11 | owner to current_user; 12 | 13 | -- set_schema 14 | alter procedure p 15 | set schema s; 16 | 17 | -- security 18 | alter procedure p 19 | security invoker 20 | external security invoker 21 | security definer 22 | external security definer 23 | restrict; 24 | 25 | -- actions 26 | alter procedure p 27 | security invoker 28 | set c = 1 29 | set d from current 30 | reset z 31 | reset all 32 | restrict; 33 | 34 | -- set_param 35 | alter procedure p 36 | set c to v; 37 | alter procedure p 38 | set c = v; 39 | alter procedure p 40 | set c = default; 41 | alter procedure p 42 | set c from current; 43 | 44 | -- reset_param 45 | alter procedure p 46 | reset c; 47 | alter procedure p 48 | reset all; 49 | 50 | -- depends 51 | alter procedure p 52 | depends on extension e; 53 | alter procedure p 54 | no depends on extension e; 55 | 56 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/alter_publication.sql: -------------------------------------------------------------------------------- 1 | -- add_table 2 | alter publication p add table t; 3 | alter publication p add table t1, table t2 where (a > b), table only t, table t (a, b); 4 | 5 | -- add_tables_in_schema 6 | alter publication p add tables in schema s; 7 | alter publication p add tables in schema current_schema; 8 | 9 | -- set_table 10 | alter publication p set table t; 11 | alter publication p set table t1, table t2 where (a > b), table only t, table t (a, b); 12 | 13 | -- set_parameters 14 | alter publication p set (param1, param2 = value); 15 | 16 | -- drop_table 17 | alter publication p drop table t; 18 | alter publication p drop table t1, table t2 where (a > b), table only t, table t (a, b); 19 | 20 | -- owner_to 21 | alter publication p owner to u; 22 | alter publication p owner to current_user; 23 | 24 | -- rename 25 | alter publication p rename to q; 26 | 27 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/alter_role.sql: -------------------------------------------------------------------------------- 1 | -- with_options 2 | alter role r with superuser; 3 | 4 | -- all_options 5 | alter role r 6 | with superuser 7 | nosuperuser 8 | nosuperuser 9 | createdb 10 | nocreatedb 11 | createrole 12 | nocreaterole 13 | inherit 14 | noinherit 15 | login 16 | nologin 17 | replication 18 | noreplication 19 | bypassrls 20 | nobypassrls 21 | connection limit 100 22 | encrypted password 'foo' 23 | password 'bar' password null 24 | valid until '2042-02-22'; 25 | 26 | -- rename 27 | alter role r rename to newname; 28 | 29 | -- set_config 30 | alter role r set param = 'value'; 31 | alter role r set param to 'value'; 32 | alter role r set param to default; 33 | 34 | -- set_config_from_current 35 | alter role r set param from current; 36 | 37 | -- reset_config 38 | alter role r reset param; 39 | 40 | -- reset_all 41 | alter role r reset all; 42 | 43 | -- in_database 44 | alter role r in database d set param to 'value'; 45 | 46 | -- using_current_user 47 | alter role current_user with nologin; 48 | 49 | -- for_all_roles 50 | alter role all reset all; 51 | 52 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/alter_routine.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | alter routine r 3 | stable; 4 | 5 | -- rename 6 | alter routine r 7 | rename to n; 8 | 9 | -- owner 10 | alter routine r 11 | owner to current_user; 12 | 13 | -- schema 14 | alter routine r 15 | set schema s; 16 | 17 | -- depends 18 | alter routine r 19 | depends on extension e; 20 | 21 | alter routine r 22 | no depends on extension e; 23 | 24 | -- no_depends 25 | alter routine r 26 | no depends on extension e; 27 | 28 | -- with_params 29 | alter routine f(in a text, out b int) 30 | parallel safe; 31 | 32 | -- all_actions 33 | alter routine r 34 | immutable 35 | stable 36 | volatile 37 | not leakproof 38 | leakproof 39 | external security invoker 40 | security invoker 41 | security definer 42 | external security definer 43 | parallel unsafe 44 | parallel restricted 45 | parallel safe 46 | cost 10 47 | rows 10 48 | set c = 1 49 | set c = default 50 | set c to true 51 | reset c 52 | reset all 53 | restrict; 54 | 55 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/alter_rule.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | alter rule r on t rename to n; 3 | 4 | -- with_schema 5 | alter rule r on schema.t rename to n; 6 | 7 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/alter_schema.sql: -------------------------------------------------------------------------------- 1 | -- rename 2 | alter schema s rename to n; 3 | 4 | -- owner 5 | alter schema s owner to u; 6 | alter schema s owner to current_user; 7 | 8 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/alter_sequence.sql: -------------------------------------------------------------------------------- 1 | -- full 2 | alter sequence if exists foo.s 3 | as varchar(100) 4 | increment by 2 5 | minvalue 1 6 | no minvalue 7 | maxvalue 100 8 | no maxvalue 9 | start 10 10 | start with 10 11 | restart 12 | restart 10 13 | restart with 10 14 | cache 10 15 | no cycle 16 | cycle 17 | owned by foo.c 18 | owned by none; 19 | 20 | -- set_logged 21 | alter sequence s 22 | set logged; 23 | 24 | alter sequence s 25 | set unlogged; 26 | 27 | -- owner_to 28 | alter sequence s 29 | owner to u; 30 | 31 | alter sequence s 32 | owner to current_user; 33 | 34 | -- rename 35 | alter sequence s 36 | rename to t; 37 | 38 | -- schema 39 | alter sequence s 40 | set schema x; 41 | 42 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/alter_server.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | alter server s 3 | version 'v1'; 4 | 5 | -- full 6 | alter server s 7 | version 'v1' 8 | options (add o 'val', drop p); 9 | 10 | -- owner 11 | alter server s 12 | owner to u; 13 | alter server s 14 | owner to current_user; 15 | 16 | -- rename 17 | alter server s 18 | rename to t; 19 | 20 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/alter_statistics.sql: -------------------------------------------------------------------------------- 1 | -- owner 2 | alter statistics s owner to u; 3 | alter statistics foo.s owner to current_user; 4 | 5 | -- rename 6 | alter statistics s rename to n; 7 | 8 | -- schema 9 | alter statistics s set schema n; 10 | 11 | -- statistics_value 12 | alter statistics s set statistics 100; 13 | alter statistics s set statistics default; 14 | 15 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/alter_subscription.sql: -------------------------------------------------------------------------------- 1 | -- connection 2 | alter subscription s connection 'host=localhost port=5432'; 3 | 4 | -- set_publication 5 | alter subscription s set publication p; 6 | alter subscription s set publication p, q, r with (a, b = true); 7 | 8 | -- add_publication 9 | alter subscription s add publication p; 10 | alter subscription s add publication a, b, c with (a, b = 1); 11 | 12 | -- drop_publication 13 | alter subscription s drop publication p; 14 | alter subscription s drop publication a, b, c with (a, b = 1); 15 | 16 | -- refresh 17 | alter subscription s refresh publication with (copy_data = false); 18 | 19 | -- enable 20 | alter subscription s enable; 21 | 22 | -- disable 23 | alter subscription s disable; 24 | 25 | -- set_parameters 26 | alter subscription s set (slot_name = 'new_slot', synchronous_commit = 'off'); 27 | 28 | -- skip 29 | alter subscription s skip (lsn = '0/12345678'); 30 | 31 | -- owner 32 | alter subscription s owner to u; 33 | alter subscription s owner to current_user; 34 | 35 | -- rename 36 | alter subscription s rename to t; 37 | 38 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/alter_system.sql: -------------------------------------------------------------------------------- 1 | -- set_to 2 | alter system set p to 'v'; 3 | 4 | -- set_equals 5 | alter system set p = 'v'; 6 | 7 | -- schema 8 | alter system set foo.p = 'v'; 9 | alter system reset foo.p; 10 | 11 | -- set_multiple 12 | alter system set p to 'v1', 'v2', 'v3'; 13 | 14 | -- set_default 15 | alter system set p to default; 16 | 17 | -- reset_param 18 | alter system reset p; 19 | 20 | -- reset_all 21 | alter system reset all; 22 | 23 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/alter_table_pg17.sql: -------------------------------------------------------------------------------- 1 | 2 | alter table t alter c set expression as ( a > b ); 3 | 4 | alter table t set access method default; 5 | 6 | alter table t add foreign key (a, b) references t1 match partial; 7 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/alter_tablespace.sql: -------------------------------------------------------------------------------- 1 | -- rename 2 | alter tablespace t rename to u; 3 | 4 | -- owner 5 | alter tablespace t owner to u; 6 | alter tablespace t owner to current_user; 7 | 8 | -- set_option 9 | alter tablespace t set (o = v); 10 | 11 | -- set_multiple_options 12 | alter tablespace t set (o1 = v1, o2 = v2); 13 | 14 | -- reset_option 15 | alter tablespace t reset (o); 16 | 17 | -- reset_multiple_options 18 | alter tablespace t reset (o1, o2); 19 | 20 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/alter_text_search_dictionary.sql: -------------------------------------------------------------------------------- 1 | -- options 2 | alter text search dictionary foo.d ( 3 | a = 1, 4 | b 5 | ); 6 | 7 | -- rename 8 | alter text search dictionary d rename to n; 9 | 10 | -- owner 11 | alter text search dictionary d owner to u; 12 | alter text search dictionary d owner to current_user; 13 | 14 | -- schema 15 | alter text search dictionary d set schema s; 16 | 17 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/alter_text_search_parser.sql: -------------------------------------------------------------------------------- 1 | -- rename 2 | alter text search parser p rename to q; 3 | 4 | -- set_schema 5 | alter text search parser p set schema s; 6 | 7 | alter text search parser foo.p set schema s; 8 | 9 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/alter_text_search_template.sql: -------------------------------------------------------------------------------- 1 | -- rename 2 | alter text search template t rename to u; 3 | 4 | -- set_schema 5 | alter text search template foo.t set schema s; 6 | 7 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/alter_trigger.sql: -------------------------------------------------------------------------------- 1 | -- rename 2 | alter trigger t on x rename to u; 3 | 4 | -- depends_on 5 | alter trigger t on x depends on extension e; 6 | 7 | -- full 8 | alter trigger t on s.t no depends on extension e; 9 | 10 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/alter_user.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | alter user u superuser; 3 | 4 | -- full 5 | alter user u with 6 | superuser 7 | nosuperuser 8 | createdb 9 | nocreatedb 10 | createrole 11 | nocreaterole 12 | inherit 13 | noinherit 14 | login 15 | nologin 16 | replication 17 | noreplication 18 | bypassrls 19 | nobypassrls 20 | connection limit 10 21 | encrypted password '' 22 | password null 23 | password 'foo' 24 | valid until '2025-01-01'; 25 | 26 | -- rename_user 27 | alter user u rename to v; 28 | 29 | -- set 30 | alter user u set p = 'value'; 31 | alter user u set p to 'value'; 32 | alter user u set p to default; 33 | 34 | alter user u in database d set p to 'value'; 35 | alter user u set p from current; 36 | 37 | -- reset 38 | alter user u reset p; 39 | alter user u reset all; 40 | alter user u in database d reset p; 41 | 42 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/alter_user_mapping.sql: -------------------------------------------------------------------------------- 1 | -- full 2 | alter user mapping for current_role 3 | server s 4 | options (add a 'v', set b 'w', drop c); 5 | 6 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/alter_view.sql: -------------------------------------------------------------------------------- 1 | -- column_set_default 2 | alter view v alter c set default 42; 3 | 4 | alter view if exists v alter column c set default current_timestamp; 5 | 6 | -- column_drop_default 7 | alter view v alter column c drop default; 8 | 9 | -- owner_to 10 | alter view v owner to u; 11 | 12 | -- owner_to_current_role 13 | alter view if exists s.v owner to current_role; 14 | 15 | -- owner_to_current_user 16 | alter view v owner to current_user; 17 | 18 | -- owner_to_session_user 19 | alter view v owner to session_user; 20 | 21 | -- rename_to 22 | alter view v rename to n; 23 | 24 | -- rename_column 25 | alter view v rename column a to b; 26 | alter view v rename a to b; 27 | 28 | -- set_schema 29 | alter view v set schema s; 30 | 31 | -- set_options 32 | alter view v set (a = 'x', b = 100, c, d = true); 33 | 34 | -- reset_options 35 | alter view v reset (a, b, c); 36 | 37 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/analyze.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | analyze; 3 | analyse; 4 | 5 | -- full 6 | analyze verbose foo.bar, foo.bar(a, b, c), foo; 7 | 8 | -- full_parens 9 | analyze (verbose false, skip_locked, buffer_usage_limit 10) foo.bar(a, b, c); 10 | 11 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/call.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | CALL do_db_maintenance(); 3 | 4 | -- with_schema 5 | CALL partman.partition_data_proc('partman_test.time_taptest_table'); 6 | 7 | -- with_named_args 8 | CALL do_db_maintenance(x => '1', null, b => 'd'); 9 | 10 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/checkpoint.sql: -------------------------------------------------------------------------------- 1 | -- checkpoint 2 | checkpoint; 3 | 4 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/close.sql: -------------------------------------------------------------------------------- 1 | -- pg_docs 2 | close foo; 3 | close all; 4 | 5 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/cluster.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | cluster; 3 | 4 | -- full 5 | cluster (verbose false) foo.bar using idx; 6 | 7 | -- options_only 8 | cluster (verbose false); 9 | 10 | -- pre_14 11 | cluster verbose foo.bar using idx; 12 | 13 | -- pre_17 14 | cluster verbose; 15 | 16 | -- pre_8_3 17 | cluster verbose f on foo.bar; 18 | 19 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/create_access_method.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | create access method m 3 | type table 4 | handler f; 5 | 6 | -- full 7 | create access method m 8 | type index 9 | handler bar.f; 10 | 11 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/create_cast.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | create cast (t as u) 3 | without function; 4 | 5 | -- inout 6 | create cast (t as u) 7 | with inout 8 | as implicit; 9 | 10 | -- full 11 | create cast (foo.t as bar.u) 12 | with function foo.bar(in a text, out b bigint, text) 13 | as assignment; 14 | 15 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/create_collation.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | create collation c from d; 3 | 4 | -- from_full 5 | create collation if not exists foo.c from bar.d; 6 | 7 | -- with_options 8 | create collation if not exists foo.c ( 9 | locale = 'foo', 10 | lc_collate = 1, 11 | lc_ctype = false, 12 | provider = 'foo', 13 | deterministic = false, 14 | rules = r, 15 | version = '100' 16 | ); 17 | 18 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/create_conversion.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | create conversion c 3 | for '' 4 | to '' 5 | from f; 6 | 7 | -- full 8 | create default conversion foo.bar.c 9 | for '' 10 | to '' 11 | from foo.bar; 12 | 13 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/create_database.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | create database d; 3 | 4 | -- full 5 | create database d 6 | with owner 'foo' 7 | template = 'foo' 8 | encoding = 'utf-8' 9 | strategy = 10 10 | locale = 'fr_FR' 11 | lc_collate = 'fr_FR' 12 | lc_ctyep = 10 13 | builtin_locale = 'en' 14 | icu_locale = 'en' 15 | icu_rules = '' 16 | locale_provider = './foo/bar' 17 | collation_version = 10 18 | tablespace = full 19 | allow_connections = false 20 | connection limit = 1000 21 | is_template = false 22 | oid 1010; 23 | 24 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/create_domain.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | create domain d int; 3 | 4 | -- full 5 | create domain d as varchar(100) 6 | collate "fr_FR" 7 | default 'fooooo' 8 | constraint c check (a > b) 9 | not null 10 | null; 11 | 12 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/create_event_trigger.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | create event trigger t on e 3 | execute function f(); 4 | 5 | -- full 6 | create event trigger t on e 7 | when x in ('foo', 'bar', 'buzz') 8 | and real in ('a') 9 | execute function foo.f(); 10 | 11 | -- doc_example_1 12 | CREATE EVENT TRIGGER abort_ddl ON ddl_command_start 13 | EXECUTE FUNCTION abort_any_command(); 14 | 15 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/create_ext.sql: -------------------------------------------------------------------------------- 1 | -- create_extension 2 | create extension foo; 3 | create extension if not exists foo; 4 | 5 | create extension hstore schema addons; 6 | 7 | create extension foo 8 | with schema bar 9 | version foo 10 | cascade; 11 | 12 | create extension foo 13 | schema bar 14 | version 'buzz'; 15 | 16 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/create_foreign_data_wrapper.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | create foreign data wrapper w; 3 | 4 | -- full 5 | create foreign data wrapper w 6 | handler foo.bar 7 | no handler 8 | validator f.bar 9 | no validator 10 | options (a 'foo', b 'bar'); 11 | 12 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/create_group.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | create group g; 3 | 4 | -- full 5 | create group g 6 | with superuser 7 | nosuperuser 8 | nosuperuser 9 | createdb 10 | nocreatedb 11 | createrole 12 | nocreaterole 13 | inherit 14 | noinherit 15 | login 16 | nologin 17 | replication 18 | noreplication 19 | bypassrls 20 | nobypassrls 21 | connection limit 100 22 | encrypted password 'foo' 23 | password 'bar' 24 | password null 25 | valid until '2042-02-22' 26 | in role foo, bar, buzz 27 | in group foo 28 | role r, current_user 29 | admin foo, bar, buzz 30 | sysid 100; 31 | 32 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/create_language.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | create language l; 3 | 4 | -- full 5 | create or replace trusted procedural language l 6 | handler foo.bar 7 | inline f.b 8 | validator x.y; 9 | 10 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/create_materialized_view.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | create materialized view t 3 | as select 1; 4 | 5 | -- full 6 | create materialized view if not exists foo.bar 7 | (a, b, c) 8 | using u 9 | with (x = 10, bar, buzz = true) 10 | tablespace t 11 | as select 1, 2, 3 12 | with no data; 13 | 14 | -- table 15 | create materialized view t 16 | as table u; 17 | 18 | -- values 19 | create materialized view t 20 | as values (1), (2, 2); 21 | 22 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/create_operator.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | create operator > ( 3 | function = f 4 | ); 5 | 6 | -- procedure 7 | create operator # ( 8 | procedure = p 9 | ); 10 | 11 | -- full 12 | create operator foo.bar.>>-# ( 13 | function = foo.bar.f, 14 | leftarg = varchar(100), 15 | rightarg = foo.bigint, 16 | commutator = &&&&, 17 | negator = <->, 18 | restrict = r, 19 | join = j, 20 | hashes, 21 | merges 22 | ); 23 | 24 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/create_operator_class.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | create operator class c for type t 3 | using i as storage s; 4 | 5 | -- full 6 | create operator class foo.c for type varchar(100) 7 | using i family foo.f as 8 | storage s, 9 | operator 1 &&, 10 | operator 100 <<<< (text, foo.bigint) for search, 11 | operator 100 # (varchar(100), varchar(10)) for order by foo.bar, 12 | function 1010 foo, 13 | function 1010 (bigint) foo.bar(in b text, out a text, text), 14 | function 1010 (bigint, smallint) foo.bar(text, text); 15 | 16 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/create_operator_family.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | create operator family f using i; 3 | 4 | -- full 5 | create operator family a.b using i; 6 | 7 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/create_policy.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | create policy p on t; 3 | 4 | -- as_ 5 | create policy p on t 6 | as permissive; 7 | 8 | create policy p on t 9 | as restrictive; 10 | 11 | -- full 12 | create policy p on foo.t 13 | as permissive 14 | for all 15 | to public, current_role, current_user, session_user 16 | using (x > b and 1 < 2) 17 | with check ( x < 1); 18 | 19 | -- for_ 20 | create policy p on t 21 | for all; 22 | 23 | create policy p on t 24 | for select; 25 | 26 | create policy p on t 27 | for insert; 28 | 29 | create policy p on t 30 | for update; 31 | 32 | create policy p on t 33 | for delete; 34 | 35 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/create_procedure.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | create procedure p() 3 | language sql; 4 | 5 | -- full 6 | create or replace procedure p( 7 | in a text DEFAULT 'foo', 8 | out b bigint = 10, 9 | bigint = 1 10 | ) 11 | language sql 12 | transform for type foo.t, for type text 13 | external security invoker 14 | security invoker 15 | external security definer 16 | security definer 17 | set foo to true 18 | set bar = false 19 | set buzz from current 20 | as 'foo' 21 | as 'foo', 'bar' 22 | return 10 + 1; 23 | 24 | -- with_select_body 25 | create or replace procedure p() 26 | language sql 27 | begin atomic 28 | select 1; 29 | select 2; 30 | end; 31 | 32 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/create_publication.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | create publication p; 3 | 4 | -- all_tables 5 | create publication p 6 | for all tables 7 | with (foo = bar, bar); 8 | 9 | -- table 10 | create publication p for 11 | table only foo.bar, 12 | table foo.bar.buzz *, 13 | table foo, 14 | table foo(a, b, c) where (x > 10 or a != b), 15 | table only (foo) 16 | with (foo = bar, bar); 17 | 18 | -- table_in_schema 19 | create publication p 20 | for tables in schema a, b, c, current_schema; 21 | 22 | -- multiple tables 23 | create publication pub for table chats, users; 24 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/create_role.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | create role u; 3 | 4 | -- full 5 | create role u 6 | with superuser 7 | nosuperuser 8 | nosuperuser 9 | createdb 10 | nocreatedb 11 | createrole 12 | nocreaterole 13 | inherit 14 | noinherit 15 | login 16 | nologin 17 | replication 18 | noreplication 19 | bypassrls 20 | nobypassrls 21 | connection limit 100 22 | encrypted password 'foo' 23 | password 'bar' password null 24 | valid until '2042-02-22' 25 | in role foo, bar, buzz 26 | in group foo 27 | admin foo 28 | sysid 100; 29 | 30 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/create_rule.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | create rule r as on select 3 | to t 4 | do nothing; 5 | 6 | -- full 7 | create or replace rule r as on select 8 | to foo.t 9 | where new.foo = old.foo or old.id != new.id 10 | do ( 11 | select 1; 12 | insert into t values (1, 2); 13 | delete from t; 14 | values (1, 2); 15 | update t set foo = 1; 16 | notify f; 17 | ); 18 | 19 | -- doc_1 20 | CREATE RULE "_RETURN" AS 21 | ON SELECT TO t1 22 | DO INSTEAD 23 | SELECT * FROM t2; 24 | 25 | CREATE RULE "_RETURN" AS 26 | ON SELECT TO t2 27 | DO INSTEAD 28 | SELECT * FROM t1; 29 | 30 | SELECT * FROM t1; 31 | 32 | -- doc_2 33 | CREATE RULE notify_me AS ON UPDATE TO mytable DO ALSO NOTIFY mytable; 34 | 35 | UPDATE mytable SET name = 'foo' WHERE id = 42; 36 | 37 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/create_sequence.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | create sequence s; 3 | 4 | -- full 5 | create temporary sequence if not exists s 6 | as varchar(100) 7 | increment by 10 8 | minvalue 1 9 | no minvalue 10 | maxvalue 100 11 | no maxvalue 12 | start with 10 13 | cache 10 14 | no cycle 15 | owned by foo.bar; 16 | 17 | -- unlogged 18 | create unlogged sequence s; 19 | 20 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/create_server.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | create server s foreign data wrapper f; 3 | 4 | -- full 5 | create server if not exists s 6 | type 'bar' 7 | version 'foo' 8 | foreign data wrapper f 9 | options (a 'foo', bar 'b'); 10 | 11 | -- docs_1 12 | CREATE SERVER myserver FOREIGN DATA WRAPPER postgres_fdw OPTIONS (host 'foo', dbname 'foodb', port '5432'); 13 | 14 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/create_statistics.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | create statistics on (a) from t; 3 | 4 | -- full 5 | create statistics if not exists foo.s(mcv, ndistinct, dependencies) 6 | on (foo), bar, buzz, (a + b) 7 | from foo.t; 8 | 9 | -- docs_1 10 | CREATE STATISTICS s1 (dependencies) ON a, b FROM t1; 11 | 12 | -- docs_2 13 | CREATE STATISTICS s2 (mcv) ON a, b FROM t2; 14 | 15 | -- docs_3 16 | CREATE STATISTICS s3 (ndistinct) ON date_trunc('month', a), date_trunc('day', a) FROM t3; 17 | 18 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/create_subscription.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | create subscription s 3 | connection '' 4 | publication a; 5 | 6 | -- full 7 | create subscription s 8 | connection 'host=10.0.0.1 port=5432 user=u dbname=d' 9 | publication a, b, c 10 | with ( 11 | connect = false, 12 | create_slot = true, 13 | enabled = false, 14 | slot_name = 'bar', 15 | binary = true, 16 | copy_data = true, 17 | synchronous_commit = off, 18 | two_phase = false, 19 | disable_on_error = true, 20 | password_required = false, 21 | run_as_owner = true, 22 | origin = 'foo', 23 | failover = false 24 | ); 25 | 26 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/create_table_as.sql: -------------------------------------------------------------------------------- 1 | -- execute 2 | create temp table t on commit drop as 3 | execute f(a); 4 | 5 | -- select 6 | create table t as 7 | select * from u where c >= b; 8 | 9 | -- table 10 | create table t as 11 | table u; 12 | 13 | -- values 14 | create temporary table t as 15 | values (1); 16 | 17 | create temporary table t as 18 | values (1, 3), (a, 5); 19 | 20 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/create_table_pg17.sql: -------------------------------------------------------------------------------- 1 | -- match partial not implemented yet 2 | create table t ( 3 | a int, 4 | b int references foo.bar ( bar ) match partial 5 | on delete no action 6 | on update set null ( a, b ) 7 | ); 8 | 9 | 10 | -- temporal_foreign_key 11 | CREATE TABLE orders ( 12 | id int8 generated BY DEFAULT AS IDENTITY, 13 | address_id int8 NOT NULL, 14 | address_valid_at tstzrange NOT NULL, 15 | content text, 16 | CONSTRAINT order_address FOREIGN KEY ( address_id, PERIOD address_valid_at ) REFERENCES addresses ( id, PERIOD valid_range ) 17 | ); 18 | 19 | -- unique_constraint_without_overlaps 20 | create table t ( 21 | a int, 22 | b text, 23 | unique (a without overlaps) 24 | ); 25 | 26 | -- temporal_primary_key 27 | CREATE TABLE addresses ( 28 | id int8 generated BY DEFAULT AS IDENTITY, 29 | valid_range tstzrange NOT NULL DEFAULT tstzrange(now(), 'infinity', '[)'), 30 | recipient text NOT NULL, 31 | PRIMARY KEY (id, valid_range WITHOUT OVERLAPS) 32 | ); 33 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/create_tablespace.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | create tablespace t location ''; 3 | 4 | -- full 5 | create tablespace t 6 | owner current_role 7 | location '' 8 | with ( 9 | seq_page_cost = 10, 10 | random_page_cost = 1, 11 | effective_io_concurrency = 0, 12 | maintenance_io_concurrency = 4 13 | ); 14 | 15 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/create_text_search_config.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | create text search configuration name ( 3 | parser = parser_name 4 | ); 5 | 6 | -- full 7 | create text search configuration foo.name ( 8 | config = source_config 9 | ); 10 | 11 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/create_text_search_dict.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | create text search dictionary name ( 3 | template = t 4 | ); 5 | 6 | -- full 7 | create text search dictionary foo.name ( 8 | template = t, 9 | foo = bar, 10 | a = b 11 | ); 12 | 13 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/create_text_search_parser.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | create text search parser name ( 3 | start = start_function, 4 | gettoken = gettoken_function, 5 | end = end_function, 6 | lextypes = lextypes_function 7 | ); 8 | 9 | -- full 10 | create text search parser foo.name ( 11 | start = start_function, 12 | gettoken = gettoken_function, 13 | end = end_function, 14 | lextypes = lextypes_function, 15 | headline = headline_function 16 | ); 17 | 18 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/create_text_search_template.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | create text search template name ( 3 | lexize = f 4 | ); 5 | 6 | -- full 7 | create text search template foo.name ( 8 | INIT = init_function, 9 | lexize = lexize_function 10 | ); 11 | 12 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/create_transform.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | create transform for t language l ( 3 | from sql with function t, 4 | to sql with function g 5 | ); 6 | 7 | -- full 8 | create or replace transform for foo.t(10231) language l ( 9 | from sql with function bar.foo.f(a text), 10 | to sql with function g 11 | ); 12 | 13 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/create_trigger.sql: -------------------------------------------------------------------------------- 1 | -- create_trigger 2 | CREATE TRIGGER update_foo_column 3 | BEFORE INSERT ON core_recipe 4 | FOR EACH ROW 5 | EXECUTE PROCEDURE foo_update_trigger(); 6 | 7 | -- with_most_fields 8 | create or replace trigger buzz instead of insert or delete 9 | on foo.bar.buzz 10 | referencing 11 | old table as foo 12 | new table as bar 13 | for each statement 14 | when (x > 10 and b is not null) 15 | execute function x.y.z(1,2,'3'); 16 | 17 | -- constraint 18 | create constraint trigger t after insert or delete 19 | on f 20 | for each row 21 | execute function f(); 22 | 23 | -- with_most_fields_part2 24 | create trigger bar after update of a, b, c 25 | on foo 26 | referencing 27 | new table bar 28 | old table foo 29 | for row 30 | execute procedure foo('bar'); 31 | 32 | -- simple 33 | create trigger bar before truncate or delete or insert 34 | on buzz 35 | execute function a(); 36 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/create_user.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | create user u; 3 | 4 | -- full 5 | create user u 6 | with superuser 7 | nosuperuser 8 | nosuperuser 9 | createdb 10 | nocreatedb 11 | createrole 12 | nocreaterole 13 | inherit 14 | noinherit 15 | login 16 | nologin 17 | replication 18 | noreplication 19 | bypassrls 20 | nobypassrls 21 | connection limit 100 22 | encrypted password 'foo' 23 | password 'bar' 24 | password null 25 | valid until '2042-02-22' 26 | in role foo, bar, buzz 27 | in group foo 28 | role foo 29 | admin foo 30 | user foo 31 | sysid 100; 32 | 33 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/create_view_extra_parens.sql: -------------------------------------------------------------------------------- 1 | create view foo as 2 | select b.y from (( select y from bar )) as b 3 | order by y desc; 4 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/deallocate.sql: -------------------------------------------------------------------------------- 1 | -- pg_docs 2 | deallocate prepare all; 3 | 4 | deallocate all; 5 | 6 | deallocate foo; 7 | 8 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/declare.sql: -------------------------------------------------------------------------------- 1 | -- pg_docs 2 | DECLARE cursor_name CURSOR FOR SELECT * FROM t; 3 | 4 | -- full 5 | declare c binary insensitive no scroll cursor without hold for select 1; 6 | 7 | declare c 8 | binary 9 | asensitive 10 | scroll 11 | cursor 12 | with hold 13 | for select 2; 14 | 15 | declare c cursor for select 1; 16 | 17 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/discard.sql: -------------------------------------------------------------------------------- 1 | -- pg_docs 2 | DISCARD ALL; 3 | DISCARD PLANS; 4 | DISCARD SEQUENCES; 5 | DISCARD TEMPORARY; 6 | DISCARD TEMP; 7 | 8 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/do.sql: -------------------------------------------------------------------------------- 1 | -- pg_docs 2 | DO $$DECLARE r record; 3 | BEGIN 4 | FOR r IN SELECT table_schema, table_name FROM information_schema.tables 5 | WHERE table_type = 'VIEW' AND table_schema = 'public' 6 | LOOP 7 | EXECUTE 'GRANT ALL ON ' || quote_ident(r.table_schema) || '.' || quote_ident(r.table_name) || ' TO webuser'; 8 | END LOOP; 9 | END$$; 10 | 11 | -- do_with_language 12 | do language plpgsql 'select 1'; 13 | 14 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/drop_access_method.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | drop access method s; 3 | 4 | -- full 5 | drop access method if exists a cascade; 6 | drop access method if exists a restrict; 7 | 8 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/drop_aggregate.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | drop aggregate a(*); 3 | 4 | -- full 5 | drop aggregate 6 | if exists 7 | a(*), 8 | foo.bar(*), 9 | foo.bar( 10 | in foo integer, 11 | bar integer, 12 | text 13 | ), 14 | c(*) 15 | cascade; 16 | 17 | -- aggregate 18 | drop aggregate a( 19 | integer, 20 | text, 21 | numeric 22 | order by 23 | in a timestamp, 24 | b numeric, 25 | text 26 | ) restrict; 27 | 28 | drop aggregate foo.bar( 29 | order by 30 | in a timestamp, 31 | b numeric, 32 | text 33 | ); 34 | 35 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/drop_cast.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | drop cast (text as int); 3 | 4 | -- full 5 | drop cast if exists (a as b) cascade; 6 | drop cast if exists (foo.a as bar.b) restrict; 7 | 8 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/drop_collation.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | drop collation s; 3 | 4 | -- full 5 | drop collation if exists foo.b cascade; 6 | drop collation if exists a restrict; 7 | 8 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/drop_conversion.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | drop conversion s; 3 | 4 | -- full 5 | drop conversion if exists foo.b cascade; 6 | drop conversion if exists buzz.b restrict; 7 | 8 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/drop_database.sql: -------------------------------------------------------------------------------- 1 | -- drop_database 2 | drop database d; 3 | 4 | drop database d ( force); 5 | drop database d with ( force, force ); 6 | 7 | drop database "table_name"; 8 | 9 | drop database if exists "table_name"; 10 | 11 | drop database if exists "table_name" 12 | 13 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/drop_domain.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | drop domain s; 3 | 4 | -- full 5 | drop domain if exists a, foo.b, c cascade; 6 | drop domain if exists a, b, c restrict; 7 | 8 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/drop_event_trigger.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | drop event trigger s; 3 | 4 | -- full 5 | drop event trigger if exists a cascade; 6 | drop event trigger if exists a restrict; 7 | 8 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/drop_extension.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | drop extension s; 3 | 4 | -- full 5 | drop extension if exists a, b, c cascade; 6 | drop extension if exists a, b, c restrict; 7 | 8 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/drop_foreign_data.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | drop foreign data wrapper s; 3 | 4 | -- full 5 | drop foreign data wrapper if exists a, b, c cascade; 6 | drop foreign data wrapper if exists a, b, c restrict; 7 | 8 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/drop_foreign_table.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | drop foreign table s; 3 | 4 | -- full 5 | drop foreign table if exists a, foo.b, c cascade; 6 | drop foreign table if exists a, b, c restrict; 7 | 8 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/drop_function.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | drop function s; 3 | 4 | -- full 5 | drop function if exists a, b(text), foo.c(in f int), b(out text) cascade; 6 | drop function if exists a restrict; 7 | 8 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/drop_group.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | drop group s; 3 | 4 | -- full 5 | drop group if exists a, b, c; 6 | 7 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/drop_index.sql: -------------------------------------------------------------------------------- 1 | -- drop_index 2 | drop index i; 3 | 4 | drop index foo.i; 5 | 6 | drop index concurrently if exists a, b, c cascade; 7 | 8 | drop index if exists d restrict; 9 | 10 | drop index if exists "field_name_idx"; 11 | 12 | drop index concurrently if exists "field_name_idx"; 13 | 14 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/drop_language.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | drop language s; 3 | 4 | -- full 5 | drop language if exists a cascade; 6 | drop procedural language if exists a restrict; 7 | 8 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/drop_materialized_view.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | drop materialized view s; 3 | 4 | -- full 5 | drop materialized view if exists a, foo.b, c cascade; 6 | drop materialized view if exists a, b, c restrict; 7 | 8 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/drop_operator.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | drop operator ^ (integer, integer); 3 | 4 | -- schema 5 | drop operator foo.foo.^ (f.smallint, bar.smallint); 6 | 7 | -- unary 8 | drop operator ~ (none, bit); 9 | 10 | -- multiple 11 | drop operator ~ (none, bit), ^ (integer, integer); 12 | 13 | -- full 14 | drop operator if exists # (NONE, bigint), @ (text, text), ## (none, integer) cascade; 15 | drop operator if exists ! (int, int) restrict; 16 | 17 | -- non_default_operator 18 | drop operator if exists !!!!!!!!!!!!!!!!!!! (int, int) restrict; 19 | 20 | drop operator bar.bar.@@@@@@@@@@@@@@@@@ (int, int) restrict; 21 | 22 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/drop_operator_class.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | drop operator class n using i; 3 | 4 | -- full 5 | drop operator class if exists foo.f using i cascade; 6 | drop operator class if exists bar.b using i restrict; 7 | 8 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/drop_operator_family.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | drop operator family n using i; 3 | 4 | -- full 5 | drop operator family if exists foo.f using i cascade; 6 | drop operator family if exists bar.b using i restrict; 7 | 8 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/drop_owned.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | drop owned by s; 3 | 4 | -- full 5 | drop owned by a, current_role, c cascade; 6 | drop owned by session_user, current_user restrict; 7 | 8 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/drop_policy.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | drop policy s on t; 3 | 4 | -- full 5 | drop policy if exists r on foo.t_name cascade; 6 | drop policy if exists r on a restrict; 7 | 8 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/drop_procedure.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | drop procedure s; 3 | 4 | -- full 5 | drop procedure if exists a, b(text), foo.c(in f int), b(out text) cascade; 6 | drop procedure if exists a restrict; 7 | 8 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/drop_publication.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | drop publication s; 3 | 4 | -- full 5 | drop publication if exists a, b, c cascade; 6 | drop publication if exists a, b, c restrict; 7 | 8 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/drop_role.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | drop role s; 3 | 4 | -- full 5 | drop role if exists a, b, c; 6 | drop role if exists a, b, c; 7 | 8 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/drop_routine.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | drop routine s; 3 | 4 | -- full 5 | drop routine if exists a, b(text), foo.c(in f int), b(out text) cascade; 6 | drop routine if exists a restrict; 7 | 8 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/drop_rule.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | drop rule s on t;; 3 | 4 | -- full 5 | drop rule if exists r on foo.t_name cascade; 6 | drop rule if exists r on a restrict; 7 | 8 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/drop_sequence.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | drop sequence s; 3 | 4 | -- full 5 | drop sequence if exists a, foo.b, c cascade; 6 | drop sequence if exists a, b, c restrict; 7 | 8 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/drop_server.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | drop server s; 3 | 4 | -- full 5 | drop server if exists a, b, c cascade; 6 | drop server if exists a, b, c restrict; 7 | 8 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/drop_statistics.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | drop statistics s; 3 | 4 | -- full 5 | drop statistics if exists a, foo.b, c cascade; 6 | 7 | drop statistics if exists a, b, c restrict; 8 | 9 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/drop_subscription.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | drop subscription s; 3 | 4 | -- full 5 | drop subscription if exists a cascade; 6 | drop subscription if exists a restrict; 7 | 8 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/drop_table.sql: -------------------------------------------------------------------------------- 1 | drop table if exists some_table; 2 | 3 | -- schema 4 | drop table if exists foo.some_table; 5 | 6 | -- simple 7 | drop table t; 8 | 9 | -- duo 10 | drop table a, b; 11 | 12 | -- schema 13 | drop table foo.t; 14 | 15 | -- if exists 16 | drop table if exists t; 17 | 18 | -- cascade 19 | drop table foo, bar cascade; 20 | 21 | -- restrict 22 | drop table t restrict; 23 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/drop_tablespace.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | drop tablespace foo; 3 | 4 | -- full 5 | drop tablespace if exists t; 6 | 7 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/drop_text_search_config.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | drop text search configuration foo; 3 | 4 | -- full 5 | drop text search configuration if exists bar cascade; 6 | 7 | -- restrict 8 | drop text search configuration bar restrict; 9 | 10 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/drop_text_search_dict.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | drop text search dictionary foo; 3 | 4 | -- full 5 | drop text search dictionary if exists bar cascade; 6 | 7 | -- restrict 8 | drop text search dictionary bar restrict; 9 | 10 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/drop_text_search_parser.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | drop text search parser foo; 3 | 4 | -- full 5 | drop text search parser if exists bar cascade; 6 | 7 | -- restrict 8 | drop text search parser bar restrict; 9 | 10 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/drop_text_search_template.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | drop text search template foo; 3 | 4 | -- full 5 | drop text search template if exists bar cascade; 6 | 7 | -- restrict 8 | drop text search template bar restrict; 9 | 10 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/drop_transform.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | drop transform for text language foo; 3 | 4 | -- full 5 | drop transform if exists for t language l cascade; 6 | 7 | -- type_args 8 | drop transform for varchar(100) language l restrict; 9 | 10 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/drop_trigger.sql: -------------------------------------------------------------------------------- 1 | drop trigger tr on t; 2 | 3 | drop trigger tr on bar.t; 4 | 5 | drop trigger if exists tr on t; 6 | 7 | drop trigger if exists tr on t cascade; 8 | 9 | drop trigger tr on t restrict; 10 | 11 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/drop_type.sql: -------------------------------------------------------------------------------- 1 | -- drop_type 2 | drop type t; 3 | drop type foo.t; 4 | drop type a, b, c; 5 | drop type if exists a, b, c; 6 | 7 | drop type if exists a cascade; 8 | drop type a restrict; 9 | 10 | drop type if exists foo; 11 | 12 | 13 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/drop_user.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | drop user foo; 3 | 4 | -- full 5 | drop user if exists a, b, c; 6 | 7 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/drop_user_mapping.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | drop user mapping for user server s; 3 | 4 | -- full 5 | drop user mapping if exists for current_role server some_server_name; 6 | 7 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/drop_view.sql: -------------------------------------------------------------------------------- 1 | -- pg_docs 2 | DROP VIEW kinds; 3 | 4 | -- full 5 | drop view if exists foo, bar, buzz cascade; 6 | 7 | drop view foo restrict; 8 | 9 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/execute.sql: -------------------------------------------------------------------------------- 1 | -- execute 2 | EXECUTE fooplan(1, 'Hunter Valley', 't', 200.00); 3 | 4 | EXECUTE usrrptplan(1, current_date); 5 | 6 | EXECUTE foo; 7 | 8 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/fetch.sql: -------------------------------------------------------------------------------- 1 | -- pg_docs 2 | fetch next from cursor_name; 3 | fetch prior from cursor_name; 4 | fetch prior in cursor_name; 5 | fetch prior cursor_name; 6 | 7 | FETCH NEXT FROM cursor_name; 8 | FETCH PRIOR FROM cursor_name; 9 | FETCH FIRST FROM cursor_name; 10 | FETCH LAST FROM cursor_name; 11 | FETCH ABSOLUTE 10 FROM cursor_name; 12 | FETCH RELATIVE 10 FROM cursor_name; 13 | FETCH 10 FROM cursor_name; 14 | FETCH ALL FROM cursor_name; 15 | FETCH FORWARD FROM cursor_name; 16 | FETCH FORWARD 10 FROM cursor_name; 17 | FETCH FORWARD ALL FROM cursor_name; 18 | FETCH BACKWARD FROM cursor_name; 19 | FETCH BACKWARD 10 FROM cursor_name; 20 | FETCH BACKWARD ALL FROM cursor_name; 21 | 22 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/import_foreign_schema.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | import foreign schema s 3 | from server a 4 | into b; 5 | 6 | -- except 7 | import foreign schema some_schema_name 8 | EXCEPT (t1, t2) 9 | FROM SERVER server_name 10 | INTO local_schema; 11 | 12 | -- options 13 | import foreign schema a 14 | from server b 15 | into c 16 | options (foo 'bar'); 17 | 18 | -- options_multi 19 | import foreign schema a 20 | from server b 21 | into c 22 | options (foo 'bar', a 'b'); 23 | 24 | -- doc_example_1 25 | IMPORT FOREIGN SCHEMA foreign_films 26 | FROM SERVER film_server INTO films; 27 | 28 | -- doc_example_2 29 | IMPORT FOREIGN SCHEMA foreign_films LIMIT TO (actors, directors) 30 | FROM SERVER film_server INTO films; 31 | 32 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/listen.sql: -------------------------------------------------------------------------------- 1 | -- pg_docs 2 | listen foo; 3 | 4 | LISTEN virtual; 5 | 6 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/load.sql: -------------------------------------------------------------------------------- 1 | -- pg_docs 2 | load 'foo'; 3 | 4 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/lock.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | lock t; 3 | 4 | -- table_names 5 | lock table t, only b, c *; 6 | 7 | -- lock_mode 8 | lock t in access share mode; 9 | lock t in row share mode; 10 | lock t in row exclusive mode; 11 | lock t in share update exclusive mode; 12 | lock t in share mode; 13 | lock t in share row exclusive mode; 14 | lock t in exclusive mode; 15 | lock t in access exclusive mode; 16 | 17 | -- all 18 | lock table t, a *, only c in row exclusive mode nowait; 19 | 20 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/move.sql: -------------------------------------------------------------------------------- 1 | -- pg_docs 2 | move next from cursor_name; 3 | move prior from cursor_name; 4 | move prior in cursor_name; 5 | move prior cursor_name; 6 | 7 | move NEXT FROM cursor_name; 8 | move PRIOR FROM cursor_name; 9 | move FIRST FROM cursor_name; 10 | move LAST FROM cursor_name; 11 | move ABSOLUTE 10 FROM cursor_name; 12 | move RELATIVE 10 FROM cursor_name; 13 | move 10 FROM cursor_name; 14 | move ALL FROM cursor_name; 15 | move FORWARD FROM cursor_name; 16 | move FORWARD 10 FROM cursor_name; 17 | move FORWARD ALL FROM cursor_name; 18 | move BACKWARD FROM cursor_name; 19 | move BACKWARD 10 FROM cursor_name; 20 | move BACKWARD ALL FROM cursor_name; 21 | 22 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/notify.sql: -------------------------------------------------------------------------------- 1 | -- notify_stmt 2 | NOTIFY foo; 3 | NOTIFY virtual, 'This is the payload'; 4 | 5 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/precedence.sql: -------------------------------------------------------------------------------- 1 | -- see: https://github.com/postgres/postgres/blob/028b4b21df26fee67b3ce75c6f14fcfd3c7cf2ee/src/backend/parser/gram.y#L12699 2 | SELECT (((SELECT 2)) + 3); 3 | SELECT (((SELECT 2)) UNION SELECT 2); 4 | 5 | 6 | -- TODO! 7 | SELECT foo UNION SELECT bar ORDER BY baz; 8 | -- equal to: 9 | (SELECT foo UNION SELECT bar) ORDER BY baz; 10 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/prepare.sql: -------------------------------------------------------------------------------- 1 | -- insert 2 | PREPARE fooplan (int, text, bool, numeric) AS 3 | INSERT INTO foo VALUES($1, $2, $3, $4); 4 | 5 | 6 | 7 | -- select 8 | PREPARE usrrptplan (int) AS 9 | SELECT * FROM users u, logs l WHERE u.usrid=$1 AND u.usrid=l.usrid 10 | AND l.date = $2; 11 | 12 | PREPARE foo AS 13 | with t as (select 1) 14 | select * from t; 15 | 16 | -- update 17 | prepare foo as 18 | update foo set x = 1 where x > 10; 19 | 20 | -- delete 21 | prepare foo as 22 | delete from foo where x = 1; 23 | 24 | -- merge 25 | prepare foo as 26 | merge into t1 27 | using t2 on t2.id = t1.id 28 | when matched then do nothing 29 | when not matched by source then do nothing 30 | when not matched then do nothing; 31 | 32 | -- values 33 | prepare foo as 34 | values (1, 'one'), (2, 'two'); 35 | 36 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/reassign.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | reassign owned by set, current_role, current_user, foo to session_user; 3 | 4 | reassign owned by current_user to current_role; 5 | 6 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/refresh.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | REFRESH MATERIALIZED VIEW order_summary; 3 | 4 | REFRESH MATERIALIZED VIEW annual_statistics_basis WITH NO DATA; 5 | 6 | refresh materialized view concurrently v with data; 7 | 8 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/reindex.sql: -------------------------------------------------------------------------------- 1 | -- pg_docs 2 | REINDEX INDEX my_index; 3 | 4 | REINDEX TABLE my_table; 5 | 6 | REINDEX TABLE CONCURRENTLY my_broken_table; 7 | 8 | -- complete_syntax 9 | reindex (concurrently true, tablespace fooo, verbose false) database concurrently foo; 10 | 11 | reindex system foo; 12 | 13 | reindex index foo; 14 | reindex table foo; 15 | reindex schema foo; 16 | 17 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/reset.sql: -------------------------------------------------------------------------------- 1 | -- pg_docs 2 | reset some_config_param; 3 | reset all; 4 | 5 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/select_compound_union_select.sql: -------------------------------------------------------------------------------- 1 | SELECT ( 2 | (SELECT id FROM code_categories WHERE "language" = @language::char(4) ORDER BY "id" ASC LIMIT 1) 3 | UNION 4 | (SELECT id FROM code_categories WHERE "language" = 'nl-NL' ORDER BY "id" ASC LIMIT 1) 5 | ) LIMIT 1; 6 | 7 | -- version without parentheses. 8 | SELECT ( 9 | (SELECT id FROM code_categories WHERE "language" = @language::char(4) ORDER BY "id" ASC LIMIT 1) 10 | UNION 11 | SELECT id FROM code_categories WHERE "language" = 'nl-NL' ORDER BY "id" ASC LIMIT 1 12 | ) LIMIT 1; 13 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/select_into.sql: -------------------------------------------------------------------------------- 1 | -- docs 2 | SELECT * INTO films_recent FROM films WHERE date_prod >= '2002-01-01'; 3 | 4 | -- more_schema 5 | select a, b, c into t from t2; 6 | 7 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/set_constraints.sql: -------------------------------------------------------------------------------- 1 | -- docs 2 | set constraints all deferred; 3 | 4 | set constraints all immediate; 5 | 6 | set constraints foo, bar, a.b immediate; 7 | 8 | set constraints bar immediate; 9 | 10 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/set_role.sql: -------------------------------------------------------------------------------- 1 | -- docs 2 | SET ROLE 'paul'; 3 | 4 | SET ROLE NONE; 5 | 6 | SET LOCAL ROLE NONE; 7 | 8 | SET SESSION ROLE foo; 9 | 10 | RESET ROLE; 11 | 12 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/set_session_auth.sql: -------------------------------------------------------------------------------- 1 | -- docs 2 | SET SESSION AUTHORIZATION decimal; 3 | SET SESSION SESSION AUTHORIZATION 'foo'; 4 | SET LOCAL SESSION AUTHORIZATION DEFAULT; 5 | RESET SESSION AUTHORIZATION; 6 | 7 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/set_transaction.sql: -------------------------------------------------------------------------------- 1 | -- docs 2 | SET TRANSACTION SNAPSHOT '00000003-0000001B-1'; 3 | 4 | SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL READ COMMITTED, read write; 5 | 6 | SET TRANSACTION ISOLATION LEVEL SERIALIZABLE, READ WRITE, NOT DEFERRABLE; 7 | 8 | 9 | -- no commas is postgres historical according to gram.y 10 | SET TRANSACTION ISOLATION LEVEL SERIALIZABLE READ WRITE NOT DEFERRABLE; 11 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/truncate.sql: -------------------------------------------------------------------------------- 1 | -- pg_grammar 2 | truncate table only t 3 | restart identity 4 | cascade; 5 | 6 | -- multiple_tables 7 | TRUNCATE only a, b *, c; 8 | 9 | -- rest 10 | truncate t; 11 | truncate a continue identity; 12 | truncate a continue identity restrict; 13 | 14 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/unlisten.sql: -------------------------------------------------------------------------------- 1 | -- pg_docs 2 | unlisten virtual; 3 | 4 | unlisten *; 5 | 6 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/ok/vacuum.sql: -------------------------------------------------------------------------------- 1 | -- simple 2 | vacuum; 3 | 4 | -- pg_docs 5 | VACUUM (VERBOSE, ANALYZE) onek; 6 | 7 | -- full 8 | VACUUM ( 9 | full, 10 | full true, 11 | full false, 12 | analyze, 13 | analyze true, 14 | analyze false, 15 | disable_page_skipping, 16 | disable_page_skipping true, 17 | disable_page_skipping false, 18 | skip_locked, 19 | skip_locked true, 20 | skip_locked false, 21 | index_cleanup auto, 22 | index_cleanup on, 23 | index_cleanup off, 24 | process_main, 25 | process_main true, 26 | process_main false, 27 | truncate, 28 | truncate true, 29 | truncate false, 30 | parallel 100, 31 | skip_database_stats, 32 | skip_database_stats true, 33 | skip_database_stats false, 34 | only_database_stats, 35 | only_database_stats true, 36 | only_database_stats false, 37 | buffer_usage_limit 10, 38 | buffer_usage_limit '10 TB' 39 | ) t1; 40 | 41 | -- pre_pg_9_syntax 42 | vacuum full freeze verbose analyze foo, bar(a, b), c; 43 | 44 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/regression_suite/async.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- ASYNC 3 | -- 4 | 5 | --Should work. Send a valid message via a valid channel name 6 | SELECT pg_notify('notify_async1','sample message1'); 7 | SELECT pg_notify('notify_async1',''); 8 | SELECT pg_notify('notify_async1',NULL); 9 | 10 | -- Should fail. Send a valid message via an invalid channel name 11 | SELECT pg_notify('','sample message1'); 12 | SELECT pg_notify(NULL,'sample message1'); 13 | SELECT pg_notify('notify_async_channel_name_too_long______________________________','sample_message1'); 14 | 15 | --Should work. Valid NOTIFY/LISTEN/UNLISTEN commands 16 | NOTIFY notify_async2; 17 | LISTEN notify_async2; 18 | UNLISTEN notify_async2; 19 | UNLISTEN *; 20 | 21 | -- Should return zero while there are no pending notifications. 22 | -- src/test/isolation/specs/async-notify.spec tests for actual usage. 23 | SELECT pg_notification_queue_usage(); 24 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/regression_suite/database.sql: -------------------------------------------------------------------------------- 1 | CREATE DATABASE regression_tbd 2 | ENCODING utf8 LC_COLLATE "C" LC_CTYPE "C" TEMPLATE template0; 3 | ALTER DATABASE regression_tbd RENAME TO regression_utf8; 4 | ALTER DATABASE regression_utf8 SET TABLESPACE regress_tblspace; 5 | ALTER DATABASE regression_utf8 RESET TABLESPACE; 6 | ALTER DATABASE regression_utf8 CONNECTION_LIMIT 123; 7 | 8 | -- Test PgDatabaseToastTable. Doing this with GRANT would be slow. 9 | BEGIN; 10 | UPDATE pg_database 11 | SET datacl = array_fill(makeaclitem(10, 10, 'USAGE', false), ARRAY[5e5::int]) 12 | WHERE datname = 'regression_utf8'; 13 | -- load catcache entry, if nothing else does 14 | ALTER DATABASE regression_utf8 RESET TABLESPACE; 15 | ROLLBACK; 16 | 17 | CREATE ROLE regress_datdba_before; 18 | CREATE ROLE regress_datdba_after; 19 | ALTER DATABASE regression_utf8 OWNER TO regress_datdba_before; 20 | REASSIGN OWNED BY regress_datdba_before TO regress_datdba_after; 21 | 22 | DROP DATABASE regression_utf8; 23 | DROP ROLE regress_datdba_before; 24 | DROP ROLE regress_datdba_after; 25 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/regression_suite/delete.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE delete_test ( 2 | id SERIAL PRIMARY KEY, 3 | a INT, 4 | b text 5 | ); 6 | 7 | INSERT INTO delete_test (a) VALUES (10); 8 | INSERT INTO delete_test (a, b) VALUES (50, repeat('x', 10000)); 9 | INSERT INTO delete_test (a) VALUES (100); 10 | 11 | -- allow an alias to be specified for DELETE's target table 12 | DELETE FROM delete_test AS dt WHERE dt.a > 75; 13 | 14 | -- if an alias is specified, don't allow the original table name 15 | -- to be referenced 16 | DELETE FROM delete_test dt WHERE delete_test.a > 25; 17 | 18 | SELECT id, a, char_length(b) FROM delete_test; 19 | 20 | -- delete a row with a TOASTed value 21 | DELETE FROM delete_test WHERE a > 25; 22 | 23 | SELECT id, a, char_length(b) FROM delete_test; 24 | 25 | DROP TABLE delete_test; 26 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/regression_suite/event_trigger_login.sql: -------------------------------------------------------------------------------- 1 | -- Login event triggers 2 | CREATE TABLE user_logins(id serial, who text); 3 | GRANT SELECT ON user_logins TO public; 4 | CREATE FUNCTION on_login_proc() RETURNS event_trigger AS $$ 5 | BEGIN 6 | INSERT INTO user_logins (who) VALUES (SESSION_USER); 7 | RAISE NOTICE 'You are welcome!'; 8 | END; 9 | $$ LANGUAGE plpgsql; 10 | CREATE EVENT TRIGGER on_login_trigger ON login EXECUTE PROCEDURE on_login_proc(); 11 | ALTER EVENT TRIGGER on_login_trigger ENABLE ALWAYS; 12 | SELECT COUNT(*) FROM user_logins; 13 | SELECT COUNT(*) FROM user_logins; 14 | 15 | -- Check dathasloginevt in system catalog 16 | SELECT dathasloginevt FROM pg_database WHERE datname= 'DBNAME'; 17 | 18 | -- Cleanup 19 | DROP TABLE user_logins; 20 | DROP EVENT TRIGGER on_login_trigger; 21 | DROP FUNCTION on_login_proc(); 22 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/regression_suite/infinite_recurse.sql: -------------------------------------------------------------------------------- 1 | -- Check that stack depth detection mechanism works and 2 | -- max_stack_depth is not set too high. 3 | 4 | create function infinite_recurse() returns int as 5 | 'select infinite_recurse()' language sql; 6 | 7 | -- Unfortunately, up till mid 2020 the Linux kernel had a bug in PPC64 8 | -- signal handling that would cause this test to crash if it happened 9 | -- to receive an sinval catchup interrupt while the stack is deep: 10 | -- https://bugzilla.kernel.org/show_bug.cgi?id=205183 11 | -- It is likely to be many years before that bug disappears from all 12 | -- production kernels, so disable this test on such platforms. 13 | -- (We still create the function, so as not to have a cross-platform 14 | -- difference in the end state of the regression database.) 15 | 16 | SELECT version() ~ 'powerpc64[^,]*-linux-gnu' 17 | AS skip_test ; 18 | 19 | -- The full error report is not very stable, so we show only SQLSTATE 20 | -- and primary error message. 21 | 22 | 23 | select infinite_recurse(); 24 | 25 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/regression_suite/init_privs.sql: -------------------------------------------------------------------------------- 1 | -- Test initial privileges 2 | 3 | -- There should always be some initial privileges, set up by initdb 4 | SELECT count(*) > 0 FROM pg_init_privs; 5 | 6 | -- Intentionally include some non-initial privs for pg_dump to dump out 7 | GRANT SELECT ON pg_proc TO CURRENT_USER; 8 | GRANT SELECT (prosrc) ON pg_proc TO CURRENT_USER; 9 | 10 | GRANT SELECT (rolname, rolsuper) ON pg_authid TO CURRENT_USER; 11 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/regression_suite/lseg.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- LSEG 3 | -- Line segments 4 | -- 5 | 6 | --DROP TABLE LSEG_TBL; 7 | CREATE TABLE LSEG_TBL (s lseg); 8 | 9 | INSERT INTO LSEG_TBL VALUES ('[(1,2),(3,4)]'); 10 | INSERT INTO LSEG_TBL VALUES ('(0,0),(6,6)'); 11 | INSERT INTO LSEG_TBL VALUES ('10,-10 ,-3,-4'); 12 | INSERT INTO LSEG_TBL VALUES ('[-1e6,2e2,3e5, -4e1]'); 13 | INSERT INTO LSEG_TBL VALUES (lseg(point(11, 22), point(33,44))); 14 | INSERT INTO LSEG_TBL VALUES ('[(-10,2),(-10,3)]'); -- vertical 15 | INSERT INTO LSEG_TBL VALUES ('[(0,-20),(30,-20)]'); -- horizontal 16 | INSERT INTO LSEG_TBL VALUES ('[(NaN,1),(NaN,90)]'); -- NaN 17 | 18 | -- bad values for parser testing 19 | INSERT INTO LSEG_TBL VALUES ('(3asdf,2 ,3,4r2)'); 20 | INSERT INTO LSEG_TBL VALUES ('[1,2,3, 4'); 21 | INSERT INTO LSEG_TBL VALUES ('[(,2),(3,4)]'); 22 | INSERT INTO LSEG_TBL VALUES ('[(1,2),(3,4)'); 23 | 24 | select * from LSEG_TBL; 25 | 26 | -- test non-error-throwing API for some core types 27 | SELECT pg_input_is_valid('[(1,2),(3)]', 'lseg'); 28 | SELECT * FROM pg_input_error_info('[(1,2),(3)]', 'lseg'); 29 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/regression_suite/numa.sql: -------------------------------------------------------------------------------- 1 | SELECT NOT(pg_numa_available()) AS skip_test ; 2 | SELECT COUNT(*) = 0 AS ok FROM pg_shmem_allocations_numa; 3 | 4 | -- switch to superuser 5 | 6 | SELECT COUNT(*) >= 0 AS ok FROM pg_shmem_allocations_numa; 7 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/data/regression_suite/sanity_check.sql: -------------------------------------------------------------------------------- 1 | VACUUM; 2 | 3 | -- 4 | -- Sanity check: every system catalog that has OIDs should have 5 | -- a unique index on OID. This ensures that the OIDs will be unique, 6 | -- even after the OID counter wraps around. 7 | -- We exclude non-system tables from the check by looking at nspname. 8 | -- 9 | SELECT relname, nspname 10 | FROM pg_class c LEFT JOIN pg_namespace n ON n.oid = relnamespace JOIN pg_attribute a ON (attrelid = c.oid AND attname = 'oid') 11 | WHERE relkind = 'r' and c.oid < 16384 12 | AND ((nspname ~ '^pg_') IS NOT FALSE) 13 | AND NOT EXISTS (SELECT 1 FROM pg_index i WHERE indrelid = c.oid 14 | AND indkey[0] = a.attnum AND indnatts = 1 15 | AND indisunique AND indimmediate); 16 | 17 | -- check that relations without storage don't have relfilenode 18 | SELECT relname, relkind 19 | FROM pg_class 20 | WHERE relkind IN ('v', 'c', 'f', 'p', 'I') 21 | AND relfilenode <> 0; 22 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/snapshots/tests__alter_foreign_data_wrapper_err.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_parser/tests/tests.rs 3 | input_file: crates/squawk_parser/tests/data/err/alter_foreign_data_wrapper.sql 4 | --- 5 | SOURCE_FILE 6 | COMMENT "-- missing option" 7 | WHITESPACE "\n" 8 | ALTER_FOREIGN_DATA_WRAPPER 9 | ALTER_KW "alter" 10 | WHITESPACE " " 11 | FOREIGN_KW "foreign" 12 | WHITESPACE " " 13 | DATA_KW "data" 14 | WHITESPACE " " 15 | WRAPPER_KW "wrapper" 16 | WHITESPACE " " 17 | NAME_REF 18 | IDENT "w" 19 | SEMICOLON ";" 20 | WHITESPACE "\n" 21 | --- 22 | ERROR@46: Missing alter foreign data wrapper option or action. 23 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/snapshots/tests__alter_large_object_ok.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_parser/tests/tests.rs 3 | input_file: crates/squawk_parser/tests/data/ok/alter_large_object.sql 4 | --- 5 | SOURCE_FILE 6 | COMMENT "-- simple" 7 | WHITESPACE "\n" 8 | ALTER_LARGE_OBJECT 9 | ALTER_KW "alter" 10 | WHITESPACE " " 11 | LARGE_KW "large" 12 | WHITESPACE " " 13 | OBJECT_KW "object" 14 | WHITESPACE " " 15 | LITERAL 16 | INT_NUMBER "12345" 17 | WHITESPACE " " 18 | OWNER_KW "owner" 19 | WHITESPACE " " 20 | TO_KW "to" 21 | WHITESPACE " " 22 | IDENT "u" 23 | SEMICOLON ";" 24 | WHITESPACE "\n\n" 25 | COMMENT "-- current_role" 26 | WHITESPACE "\n" 27 | ALTER_LARGE_OBJECT 28 | ALTER_KW "alter" 29 | WHITESPACE " " 30 | LARGE_KW "large" 31 | WHITESPACE " " 32 | OBJECT_KW "object" 33 | WHITESPACE " " 34 | LITERAL 35 | INT_NUMBER "12345" 36 | WHITESPACE " " 37 | OWNER_KW "owner" 38 | WHITESPACE " " 39 | TO_KW "to" 40 | WHITESPACE " " 41 | CURRENT_ROLE_KW "current_role" 42 | SEMICOLON ";" 43 | WHITESPACE "\n\n" 44 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/snapshots/tests__alter_sequence_err.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_parser/tests/tests.rs 3 | input_file: crates/squawk_parser/tests/data/err/alter_sequence.sql 4 | --- 5 | SOURCE_FILE 6 | COMMENT "-- missing option" 7 | WHITESPACE "\n" 8 | ALTER_SEQUENCE 9 | ALTER_KW "alter" 10 | WHITESPACE " " 11 | SEQUENCE_KW "sequence" 12 | WHITESPACE " " 13 | PATH 14 | PATH_SEGMENT 15 | NAME_REF 16 | IDENT "s" 17 | SEMICOLON ";" 18 | WHITESPACE "\n" 19 | --- 20 | ERROR@34: expected ALTER SEQUENCE option 21 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/snapshots/tests__alter_server_err.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_parser/tests/tests.rs 3 | input_file: crates/squawk_parser/tests/data/err/alter_server.sql 4 | --- 5 | SOURCE_FILE 6 | COMMENT "-- missing option" 7 | WHITESPACE "\n" 8 | ALTER_SERVER 9 | ALTER_KW "alter" 10 | WHITESPACE " " 11 | SERVER_KW "server" 12 | WHITESPACE " " 13 | NAME_REF 14 | IDENT "s" 15 | SEMICOLON ";" 16 | WHITESPACE "\n" 17 | --- 18 | ERROR@32: expected ALTER SERVER option 19 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/snapshots/tests__checkpoint_ok.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_parser/tests/tests.rs 3 | input_file: crates/squawk_parser/tests/data/ok/checkpoint.sql 4 | --- 5 | SOURCE_FILE 6 | COMMENT "-- checkpoint" 7 | WHITESPACE "\n" 8 | CHECKPOINT 9 | CHECKPOINT_KW "checkpoint" 10 | SEMICOLON ";" 11 | WHITESPACE "\n\n" 12 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/snapshots/tests__close_ok.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_parser/tests/tests.rs 3 | input_file: crates/squawk_parser/tests/data/ok/close.sql 4 | --- 5 | SOURCE_FILE 6 | COMMENT "-- pg_docs" 7 | WHITESPACE "\n" 8 | CLOSE 9 | CLOSE_KW "close" 10 | WHITESPACE " " 11 | NAME 12 | IDENT "foo" 13 | SEMICOLON ";" 14 | WHITESPACE "\n" 15 | CLOSE 16 | CLOSE_KW "close" 17 | WHITESPACE " " 18 | ALL_KW "all" 19 | SEMICOLON ";" 20 | WHITESPACE "\n\n" 21 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/snapshots/tests__create_function_err.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_parser/tests/tests.rs 3 | input_file: crates/squawk_parser/tests/data/err/create_function.sql 4 | snapshot_kind: text 5 | --- 6 | SOURCE_FILE 7 | COMMENT "-- regression partial definition" 8 | WHITESPACE "\n" 9 | CREATE_FUNCTION 10 | CREATE_KW "create" 11 | WHITESPACE " " 12 | FUNCTION_KW "function" 13 | WHITESPACE "\n" 14 | --- 15 | ERROR@48: expected path name 16 | ERROR@48: expected L_PAREN 17 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/snapshots/tests__deallocate_ok.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_parser/tests/tests.rs 3 | input_file: crates/squawk_parser/tests/data/ok/deallocate.sql 4 | --- 5 | SOURCE_FILE 6 | COMMENT "-- pg_docs" 7 | WHITESPACE "\n" 8 | DEALLOCATE 9 | DEALLOCATE_KW "deallocate" 10 | WHITESPACE " " 11 | PREPARE_KW "prepare" 12 | WHITESPACE " " 13 | ALL_KW "all" 14 | SEMICOLON ";" 15 | WHITESPACE "\n\n" 16 | DEALLOCATE 17 | DEALLOCATE_KW "deallocate" 18 | WHITESPACE " " 19 | ALL_KW "all" 20 | SEMICOLON ";" 21 | WHITESPACE "\n\n" 22 | DEALLOCATE 23 | DEALLOCATE_KW "deallocate" 24 | WHITESPACE " " 25 | NAME 26 | IDENT "foo" 27 | SEMICOLON ";" 28 | WHITESPACE "\n\n" 29 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/snapshots/tests__discard_ok.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_parser/tests/tests.rs 3 | input_file: crates/squawk_parser/tests/data/ok/discard.sql 4 | --- 5 | SOURCE_FILE 6 | COMMENT "-- pg_docs" 7 | WHITESPACE "\n" 8 | DISCARD 9 | DISCARD_KW "DISCARD" 10 | WHITESPACE " " 11 | ALL_KW "ALL" 12 | SEMICOLON ";" 13 | WHITESPACE "\n" 14 | DISCARD 15 | DISCARD_KW "DISCARD" 16 | WHITESPACE " " 17 | PLANS_KW "PLANS" 18 | SEMICOLON ";" 19 | WHITESPACE "\n" 20 | DISCARD 21 | DISCARD_KW "DISCARD" 22 | WHITESPACE " " 23 | SEQUENCES_KW "SEQUENCES" 24 | SEMICOLON ";" 25 | WHITESPACE "\n" 26 | DISCARD 27 | DISCARD_KW "DISCARD" 28 | WHITESPACE " " 29 | TEMPORARY_KW "TEMPORARY" 30 | SEMICOLON ";" 31 | WHITESPACE "\n" 32 | DISCARD 33 | DISCARD_KW "DISCARD" 34 | WHITESPACE " " 35 | TEMP_KW "TEMP" 36 | SEMICOLON ";" 37 | WHITESPACE "\n\n" 38 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/snapshots/tests__do_ok.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_parser/tests/tests.rs 3 | input_file: crates/squawk_parser/tests/data/ok/do.sql 4 | --- 5 | SOURCE_FILE 6 | COMMENT "-- pg_docs" 7 | WHITESPACE "\n" 8 | DO 9 | DO_KW "DO" 10 | WHITESPACE " " 11 | LITERAL 12 | DOLLAR_QUOTED_STRING "$$DECLARE r record;\nBEGIN\n FOR r IN SELECT table_schema, table_name FROM information_schema.tables\n WHERE table_type = 'VIEW' AND table_schema = 'public'\n LOOP\n EXECUTE 'GRANT ALL ON ' || quote_ident(r.table_schema) || '.' || quote_ident(r.table_name) || ' TO webuser';\n END LOOP;\nEND$$" 13 | SEMICOLON ";" 14 | WHITESPACE "\n\n" 15 | COMMENT "-- do_with_language" 16 | WHITESPACE "\n" 17 | DO 18 | DO_KW "do" 19 | WHITESPACE " " 20 | LANGUAGE_KW "language" 21 | WHITESPACE " " 22 | IDENT "plpgsql" 23 | WHITESPACE " " 24 | LITERAL 25 | STRING "'select 1'" 26 | SEMICOLON ";" 27 | WHITESPACE "\n\n" 28 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/snapshots/tests__drop_group_ok.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_parser/tests/tests.rs 3 | input_file: crates/squawk_parser/tests/data/ok/drop_group.sql 4 | --- 5 | SOURCE_FILE 6 | COMMENT "-- simple" 7 | WHITESPACE "\n" 8 | DROP_GROUP 9 | DROP_KW "drop" 10 | WHITESPACE " " 11 | GROUP_KW "group" 12 | WHITESPACE " " 13 | NAME_REF 14 | IDENT "s" 15 | SEMICOLON ";" 16 | WHITESPACE "\n\n" 17 | COMMENT "-- full" 18 | WHITESPACE "\n" 19 | DROP_GROUP 20 | DROP_KW "drop" 21 | WHITESPACE " " 22 | GROUP_KW "group" 23 | WHITESPACE " " 24 | IF_EXISTS 25 | IF_KW "if" 26 | WHITESPACE " " 27 | EXISTS_KW "exists" 28 | WHITESPACE " " 29 | NAME_REF 30 | IDENT "a" 31 | COMMA "," 32 | WHITESPACE " " 33 | NAME_REF 34 | IDENT "b" 35 | COMMA "," 36 | WHITESPACE " " 37 | NAME_REF 38 | IDENT "c" 39 | SEMICOLON ";" 40 | WHITESPACE "\n\n" 41 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/snapshots/tests__drop_tablespace_ok.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_parser/tests/tests.rs 3 | input_file: crates/squawk_parser/tests/data/ok/drop_tablespace.sql 4 | --- 5 | SOURCE_FILE 6 | COMMENT "-- simple" 7 | WHITESPACE "\n" 8 | DROP_TABLESPACE 9 | DROP_KW "drop" 10 | WHITESPACE " " 11 | TABLESPACE_KW "tablespace" 12 | WHITESPACE " " 13 | NAME_REF 14 | IDENT "foo" 15 | SEMICOLON ";" 16 | WHITESPACE "\n\n" 17 | COMMENT "-- full" 18 | WHITESPACE "\n" 19 | DROP_TABLESPACE 20 | DROP_KW "drop" 21 | WHITESPACE " " 22 | TABLESPACE_KW "tablespace" 23 | WHITESPACE " " 24 | IF_EXISTS 25 | IF_KW "if" 26 | WHITESPACE " " 27 | EXISTS_KW "exists" 28 | WHITESPACE " " 29 | NAME_REF 30 | IDENT "t" 31 | SEMICOLON ";" 32 | WHITESPACE "\n\n" 33 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/snapshots/tests__drop_user_ok.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_parser/tests/tests.rs 3 | input_file: crates/squawk_parser/tests/data/ok/drop_user.sql 4 | --- 5 | SOURCE_FILE 6 | COMMENT "-- simple" 7 | WHITESPACE "\n" 8 | DROP_USER 9 | DROP_KW "drop" 10 | WHITESPACE " " 11 | USER_KW "user" 12 | WHITESPACE " " 13 | NAME_REF 14 | IDENT "foo" 15 | SEMICOLON ";" 16 | WHITESPACE "\n\n" 17 | COMMENT "-- full" 18 | WHITESPACE "\n" 19 | DROP_USER 20 | DROP_KW "drop" 21 | WHITESPACE " " 22 | USER_KW "user" 23 | WHITESPACE " " 24 | IF_EXISTS 25 | IF_KW "if" 26 | WHITESPACE " " 27 | EXISTS_KW "exists" 28 | WHITESPACE " " 29 | NAME_REF 30 | IDENT "a" 31 | COMMA "," 32 | WHITESPACE " " 33 | NAME_REF 34 | IDENT "b" 35 | COMMA "," 36 | WHITESPACE " " 37 | NAME_REF 38 | IDENT "c" 39 | SEMICOLON ";" 40 | WHITESPACE "\n\n" 41 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/snapshots/tests__listen_ok.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_parser/tests/tests.rs 3 | input_file: crates/squawk_parser/tests/data/ok/listen.sql 4 | --- 5 | SOURCE_FILE 6 | COMMENT "-- pg_docs" 7 | WHITESPACE "\n" 8 | LISTEN 9 | LISTEN_KW "listen" 10 | WHITESPACE " " 11 | NAME 12 | IDENT "foo" 13 | SEMICOLON ";" 14 | WHITESPACE "\n\n" 15 | LISTEN 16 | LISTEN_KW "LISTEN" 17 | WHITESPACE " " 18 | NAME 19 | VIRTUAL_KW "virtual" 20 | SEMICOLON ";" 21 | WHITESPACE "\n\n" 22 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/snapshots/tests__load_ok.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_parser/tests/tests.rs 3 | input_file: crates/squawk_parser/tests/data/ok/load.sql 4 | --- 5 | SOURCE_FILE 6 | COMMENT "-- pg_docs" 7 | WHITESPACE "\n" 8 | LOAD 9 | LOAD_KW "load" 10 | WHITESPACE " " 11 | LITERAL 12 | STRING "'foo'" 13 | SEMICOLON ";" 14 | WHITESPACE "\n\n" 15 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/snapshots/tests__notify_ok.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_parser/tests/tests.rs 3 | input_file: crates/squawk_parser/tests/data/ok/notify.sql 4 | --- 5 | SOURCE_FILE 6 | COMMENT "-- notify_stmt" 7 | WHITESPACE "\n" 8 | NOTIFY 9 | NOTIFY_KW "NOTIFY" 10 | WHITESPACE " " 11 | NAME 12 | IDENT "foo" 13 | SEMICOLON ";" 14 | WHITESPACE "\n" 15 | NOTIFY 16 | NOTIFY_KW "NOTIFY" 17 | WHITESPACE " " 18 | NAME 19 | VIRTUAL_KW "virtual" 20 | COMMA "," 21 | WHITESPACE " " 22 | LITERAL 23 | STRING "'This is the payload'" 24 | SEMICOLON ";" 25 | WHITESPACE "\n\n" 26 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/snapshots/tests__regression_join.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_parser/tests/tests.rs 3 | input_file: crates/squawk_parser/tests/data/regression_suite/join.sql 4 | --- 5 | ERROR@93160: expected R_PAREN 6 | ERROR@93186: expected SEMICOLON 7 | ERROR@93186: expected command, found R_PAREN 8 | ERROR@93188: expected command, found AS_KW 9 | ERROR@93191: expected command, found IDENT 10 | ERROR@93196: expected command, found CROSS_KW 11 | ERROR@93202: expected command, found JOIN_KW 12 | ERROR@93207: expected command, found LATERAL_KW 13 | ERROR@93255: expected R_PAREN 14 | ERROR@93282: expected R_PAREN 15 | ERROR@93282: expected SEMICOLON 16 | ERROR@93283: expected command, found AS_KW 17 | ERROR@93286: expected command, found IDENT 18 | ERROR@93288: expected command, found R_PAREN 19 | ERROR@93293: expected command, found UNION_KW 20 | ERROR@93299: expected command, found ALL_KW 21 | ERROR@93319: expected SEMICOLON 22 | ERROR@93322: expected command, found R_PAREN 23 | ERROR@93324: expected command, found AS_KW 24 | ERROR@93327: expected command, found IDENT 25 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/snapshots/tests__regression_timestamptz.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_parser/tests/tests.rs 3 | input_file: crates/squawk_parser/tests/data/regression_suite/timestamptz.sql 4 | --- 5 | ERROR@28897: expected COMMA 6 | ERROR@28900: expected COMMA 7 | ERROR@29074: expected COMMA 8 | ERROR@29077: expected COMMA 9 | ERROR@29280: missing comma 10 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/snapshots/tests__regression_union.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_parser/tests/tests.rs 3 | input_file: crates/squawk_parser/tests/data/regression_suite/union.sql 4 | --- 5 | ERROR@996: expected SEMICOLON 6 | ERROR@997: expected command, found ORDER_KW 7 | ERROR@1003: expected command, found BY_KW 8 | ERROR@1006: expected command, found INT_NUMBER 9 | ERROR@10339: expected SEMICOLON 10 | ERROR@10340: expected command, found ORDER_KW 11 | ERROR@10346: expected command, found BY_KW 12 | ERROR@10349: expected command, found INT_NUMBER 13 | ERROR@11233: expected SEMICOLON 14 | ERROR@11234: expected command, found ORDER_KW 15 | ERROR@11240: expected command, found BY_KW 16 | ERROR@11243: expected command, found INT_NUMBER 17 | ERROR@18725: expected SEMICOLON 18 | ERROR@18726: expected command, found LIMIT_KW 19 | ERROR@18732: expected command, found INT_NUMBER 20 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/snapshots/tests__regression_with.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_parser/tests/tests.rs 3 | input_file: crates/squawk_parser/tests/data/regression_suite/with.sql 4 | --- 5 | ERROR@23242: expected command, found L_PAREN 6 | ERROR@23243: expected SELECT, TABLE, VALUES, INSERT, UPDATE, DELETE, or MERGE statement 7 | ERROR@23243: expected R_PAREN 8 | ERROR@23243: expected DELETE, SELECT, TABLE, UPDATE, VALUES, or MERGE, got: WITH_KW 9 | ERROR@23288: expected SEMICOLON 10 | ERROR@23288: expected command, found R_PAREN 11 | ERROR@23292: expected command, found UNION_KW 12 | ERROR@23308: expected SEMICOLON 13 | ERROR@23308: expected command, found R_PAREN 14 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/snapshots/tests__reset_ok.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_parser/tests/tests.rs 3 | input_file: crates/squawk_parser/tests/data/ok/reset.sql 4 | --- 5 | SOURCE_FILE 6 | COMMENT "-- pg_docs" 7 | WHITESPACE "\n" 8 | RESET 9 | RESET_KW "reset" 10 | WHITESPACE " " 11 | PATH 12 | PATH_SEGMENT 13 | NAME_REF 14 | IDENT "some_config_param" 15 | SEMICOLON ";" 16 | WHITESPACE "\n" 17 | RESET 18 | RESET_KW "reset" 19 | WHITESPACE " " 20 | ALL_KW "all" 21 | SEMICOLON ";" 22 | WHITESPACE "\n\n" 23 | -------------------------------------------------------------------------------- /crates/squawk_parser/tests/snapshots/tests__unlisten_ok.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/squawk_parser/tests/tests.rs 3 | input_file: crates/squawk_parser/tests/data/ok/unlisten.sql 4 | --- 5 | SOURCE_FILE 6 | COMMENT "-- pg_docs" 7 | WHITESPACE "\n" 8 | UNLISTEN 9 | UNLISTEN_KW "unlisten" 10 | WHITESPACE " " 11 | NAME 12 | VIRTUAL_KW "virtual" 13 | SEMICOLON ";" 14 | WHITESPACE "\n\n" 15 | UNLISTEN 16 | UNLISTEN_KW "unlisten" 17 | WHITESPACE " " 18 | STAR "*" 19 | SEMICOLON ";" 20 | WHITESPACE "\n\n" 21 | -------------------------------------------------------------------------------- /crates/squawk_syntax/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "squawk_syntax" 3 | version = "0.0.0" 4 | edition.workspace = true 5 | rust-version.workspace = true 6 | authors.workspace = true 7 | license.workspace = true 8 | 9 | [dependencies] 10 | squawk_parser.workspace = true 11 | rowan.workspace = true 12 | smol_str.workspace = true 13 | 14 | [dev-dependencies] 15 | insta.workspace = true 16 | dir-test.workspace = true 17 | camino.workspace = true 18 | 19 | [lints] 20 | workspace = true 21 | -------------------------------------------------------------------------------- /crates/squawk_syntax/README.md: -------------------------------------------------------------------------------- 1 | # squawk_syntax 2 | 3 | ## related 4 | 5 | - https://github.com/rust-lang/rust-analyzer/blob/d2f17873ff19786a121fb3302f91779c1a1b957f/docs/book/src/contributing/syntax.md 6 | -------------------------------------------------------------------------------- /crates/squawk_syntax/src/ast/generated/mod.rs: -------------------------------------------------------------------------------- 1 | pub(crate) mod nodes; 2 | pub(crate) mod tokens; 3 | -------------------------------------------------------------------------------- /crates/squawk_syntax/src/ast/nodes.rs: -------------------------------------------------------------------------------- 1 | pub use crate::ast::generated::nodes::*; 2 | -------------------------------------------------------------------------------- /crates/squawk_syntax/src/ast/traits.rs: -------------------------------------------------------------------------------- 1 | // based on rust-analyzer's ast traits 2 | // https://github.com/rust-lang/rust-analyzer/blob/d8887c0758bbd2d5f752d5bd405d4491e90e7ed6/crates/syntax/src/ast/traits.rs 3 | use crate::ast; 4 | use crate::ast::{support, AstNode}; 5 | 6 | pub trait HasName: AstNode { 7 | fn name(&self) -> Option { 8 | support::child(self.syntax()) 9 | } 10 | } 11 | 12 | pub trait HasArgList: AstNode { 13 | fn arg_list(&self) -> Option { 14 | support::child(self.syntax()) 15 | } 16 | } 17 | 18 | pub trait HasIfExists: AstNode { 19 | fn if_exists(&self) -> Option { 20 | support::child(self.syntax()) 21 | } 22 | } 23 | 24 | pub trait HasIfNotExists: AstNode { 25 | fn if_not_exists(&self) -> Option { 26 | support::child(self.syntax()) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /crates/squawk_syntax/test_data/validation/alter_aggregate_params.sql: -------------------------------------------------------------------------------- 1 | -- can't have out params in aggregates 2 | create aggregate a(in x, out y) ( 3 | sfunc = f, 4 | stype = t 5 | ); 6 | -------------------------------------------------------------------------------- /crates/squawk_syntax/test_data/validation/array_exprs.sql: -------------------------------------------------------------------------------- 1 | select ['a', 'b', 'c']; 2 | 3 | select [[1, 2]]; 4 | -------------------------------------------------------------------------------- /crates/squawk_syntax/test_data/validation/create_aggregate_params.sql: -------------------------------------------------------------------------------- 1 | -- can't have out params in aggregates 2 | alter aggregate a (in t, out u) 3 | set schema s; 4 | 5 | -------------------------------------------------------------------------------- /crates/squawk_syntax/test_data/validation/custom_operators.sql: -------------------------------------------------------------------------------- 1 | -- disallowed prefix operators 2 | select *c; 3 | select /d; 4 | select f; 6 | select =g; 7 | select %l; 8 | select ^m; 9 | -------------------------------------------------------------------------------- /crates/squawk_syntax/test_data/validation/drop_aggregate_params.sql: -------------------------------------------------------------------------------- 1 | 2 | -- full 3 | drop aggregate 4 | if exists 5 | a(*), 6 | foo.bar(*), 7 | foo.bar( 8 | in foo integer, 9 | out bar integer, 10 | text 11 | ), 12 | c(*) 13 | cascade; 14 | 15 | -- aggregate 16 | drop aggregate a( 17 | integer, 18 | text, 19 | numeric 20 | order by 21 | in a timestamp, 22 | out b numeric, 23 | text 24 | ) restrict; 25 | 26 | drop aggregate foo.bar( 27 | order by 28 | in a timestamp, 29 | out b numeric, 30 | text 31 | ); 32 | 33 | -------------------------------------------------------------------------------- /crates/squawk_syntax/test_data/validation/validate_string_continuation.sql: -------------------------------------------------------------------------------- 1 | select 'foo' 'bar'; 2 | select 'foo' /* comment */ 'bar'; 3 | select 'hello' /* comment */ 'bar' /* another comment */ ' world'; 4 | 5 | select 'hello' -- comment 6 | 'world'; 7 | -------------------------------------------------------------------------------- /crates/squawk_wasm/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "squawk_wasm" 3 | version = "0.1.0" 4 | edition.workspace = true 5 | rust-version.workspace = true 6 | authors.workspace = true 7 | license.workspace = true 8 | 9 | [lib] 10 | crate-type = ["cdylib", "rlib"] 11 | 12 | [features] 13 | default = ["console_error_panic_hook"] 14 | 15 | [dependencies] 16 | 17 | squawk_syntax.workspace = true 18 | squawk_linter.workspace = true 19 | squawk_lexer.workspace = true 20 | 21 | wasm-bindgen.workspace = true 22 | serde-wasm-bindgen.workspace = true 23 | serde.workspace = true 24 | console_error_panic_hook = { workspace = true, optional = true } 25 | web-sys = { workspace = true, features = ["Window"] } 26 | console_log.workspace = true 27 | log.workspace = true 28 | line-index.workspace = true 29 | 30 | [dev-dependencies] 31 | wasm-bindgen-test.workspace = true 32 | 33 | [lints] 34 | workspace = true 35 | -------------------------------------------------------------------------------- /crates/squawk_wasm/README.md: -------------------------------------------------------------------------------- 1 | # squak_wasm 2 | 3 | ```shell 4 | wasm-pack build --target web crates/squawk_wasm 5 | ``` 6 | -------------------------------------------------------------------------------- /crates/xtask/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "xtask" 3 | version = "0.1.0" 4 | 5 | authors.workspace = true 6 | edition.workspace = true 7 | license.workspace = true 8 | rust-version.workspace = true 9 | 10 | [dependencies] 11 | anyhow.workspace = true 12 | clap.workspace = true 13 | enum-iterator.workspace = true 14 | reqwest = { version = "0.12.9", features = ["blocking", "json"] } 15 | serde.workspace = true 16 | serde_json.workspace = true 17 | convert_case.workspace = true 18 | camino.workspace = true 19 | ungrammar.workspace = true 20 | quote.workspace = true 21 | xshell.workspace = true 22 | proc-macro2.workspace = true 23 | regex.workspace = true 24 | 25 | [lints] 26 | workspace = true 27 | -------------------------------------------------------------------------------- /crates/xtask/README.md: -------------------------------------------------------------------------------- 1 | # xtask 2 | 3 | > see 4 | 5 | Run via: 6 | 7 | ```sh 8 | cargo xtask --help 9 | ``` 10 | -------------------------------------------------------------------------------- /crates/xtask/src/path.rs: -------------------------------------------------------------------------------- 1 | use camino::Utf8PathBuf; 2 | 3 | pub(crate) fn project_root() -> Utf8PathBuf { 4 | let binding = Utf8PathBuf::from(env!("CARGO_MANIFEST_DIR")); 5 | Utf8PathBuf::from(binding.parent().unwrap().parent().unwrap()) 6 | } 7 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | /node_modules 3 | 4 | # Production 5 | /build 6 | 7 | # Generated files 8 | .docusaurus 9 | .cache-loader 10 | 11 | # Misc 12 | .DS_Store 13 | .env.local 14 | .env.development.local 15 | .env.test.local 16 | .env.production.local 17 | 18 | npm-debug.log* 19 | yarn-debug.log* 20 | yarn-error.log* 21 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # Website 2 | 3 | This website is built using [Docusaurus 2](https://v2.docusaurus.io/), a modern static website generator. 4 | 5 | ## Installation 6 | 7 | ```console 8 | yarn install 9 | ``` 10 | 11 | ## Local Development 12 | 13 | ```console 14 | yarn start 15 | ``` 16 | 17 | This command starts a local development server and open up a browser window. Most changes are reflected live without having to restart the server. 18 | 19 | ## Build 20 | 21 | ```console 22 | yarn build 23 | ``` 24 | 25 | This command generates static content into the `build` directory and can be served using any static contents hosting service. 26 | 27 | ## Deployment 28 | 29 | This site is deployed on Netlify. We configure our Algolia index settings in the deploy settings there. 30 | -------------------------------------------------------------------------------- /docs/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [require.resolve('@docusaurus/core/lib/babel/preset')], 3 | }; 4 | -------------------------------------------------------------------------------- /docs/docs/ban-drop-column.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: ban-drop-column 3 | title: ban-drop-column 4 | --- 5 | 6 | ## problem 7 | 8 | Dropping a column may break existing clients. 9 | 10 | ## solution 11 | 12 | Update your application code to no longer read or write the column. 13 | 14 | You can leave the column as nullable or delete the column once queries no longer select or modify the column. -------------------------------------------------------------------------------- /docs/docs/ban-drop-database.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: ban-drop-database 3 | title: ban-drop-database 4 | --- 5 | 6 | ## problem 7 | 8 | Dropping a database may break existing clients. 9 | 10 | ## solution 11 | 12 | You probably don't want to drop your database. -------------------------------------------------------------------------------- /docs/docs/ban-drop-not-null.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: ban-drop-not-null 3 | title: ban-drop-not-null 4 | --- 5 | 6 | ## problem 7 | 8 | Dropping a NOT NULL constraint may break existing clients. 9 | 10 | Application code or code written in procedural languages like PL/SQL or PL/pgSQL may not expect NULL values for the column that was previously guaranteed to be NOT NULL and therefore may fail to process them correctly. 11 | 12 | ## solution 13 | 14 | Consider using a marker value that represents a "null" value and using that throughout application code. If NULL is truly desired, consider creating a new table similiar to the current one but that doesn't have the NOT NULL constraint, copy data to that, and create a view to replace the old table that either filters out NULL values or substitutes an appropriate marker value. 15 | -------------------------------------------------------------------------------- /docs/docs/ban-drop-table.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: ban-drop-table 3 | title: ban-drop-table 4 | --- 5 | 6 | ## problem 7 | 8 | Dropping a table may break existing clients. 9 | 10 | ## solution 11 | 12 | Update your application code to no longer read or write the table. 13 | 14 | Once the table is no longer needed, you can delete it by running the command "DROP TABLE mytable;". 15 | 16 | This command will permanently remove the table from the database and all its contents. 17 | 18 | Be sure to back up the table before deleting it, just in case you need to restore it in the future. 19 | -------------------------------------------------------------------------------- /docs/docs/prefer-bigint-over-int.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: prefer-bigint-over-int 3 | title: prefer-bigint-over-int 4 | --- 5 | 6 | 7 | ## problem 8 | 9 | Using 32 bit integer fields can result in hitting the max int limit. 10 | 11 | ## solution 12 | 13 | Use 64 bit integer field instead, like `BIGSERIAL` or `BIGINT`. 14 | 15 | 16 | ### serial 17 | 18 | Instead of: 19 | 20 | ```sql 21 | CREATE TABLE posts ( 22 | id serial primary key 23 | ) 24 | ``` 25 | 26 | Use: 27 | 28 | ```sql 29 | CREATE TABLE posts ( 30 | id bigserial primary key 31 | ) 32 | ``` 33 | 34 | 35 | ### int 36 | 37 | Instead of: 38 | 39 | ```sql 40 | CREATE TABLE posts ( 41 | id int primary key 42 | ) 43 | ``` 44 | 45 | Use: 46 | 47 | ```sql 48 | CREATE TABLE posts ( 49 | id bigint primary key 50 | ) 51 | ``` 52 | 53 | ## related 54 | 55 | See ["prefer-bigint-over-smallint"](./prefer-bigint-over-smallint.md)for a simliar lint rule against 16 bit integers. 56 | -------------------------------------------------------------------------------- /docs/docs/prefer-bigint-over-smallint.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: prefer-bigint-over-smallint 3 | title: prefer-bigint-over-smallint 4 | --- 5 | 6 | 7 | ## problem 8 | 9 | Using 16 bit integer fields can result in hitting the max int limit. 10 | 11 | ## solution 12 | 13 | Use 64 bit integer field instead, like `BIGSERIAL` or `BIGINT`. 14 | 15 | 16 | ### smallserial 17 | 18 | Instead of: 19 | 20 | ```sql 21 | CREATE TABLE posts ( 22 | id smallserial primary key 23 | ) 24 | ``` 25 | 26 | Use: 27 | 28 | ```sql 29 | CREATE TABLE posts ( 30 | id bigserial primary key 31 | ) 32 | ``` 33 | 34 | 35 | ### smallint 36 | 37 | Instead of: 38 | 39 | ```sql 40 | CREATE TABLE posts ( 41 | id smallint primary key 42 | ) 43 | ``` 44 | 45 | Use: 46 | 47 | ```sql 48 | CREATE TABLE posts ( 49 | id bigint primary key 50 | ) 51 | ``` 52 | 53 | ## related 54 | 55 | See ["prefer-bigint-over-int"](./prefer-bigint-over-int.md) for a simliar lint rule against 32 bit integers. 56 | -------------------------------------------------------------------------------- /docs/docs/renaming-column.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: renaming-column 3 | title: renaming-column 4 | --- 5 | 6 | ## problem 7 | 8 | Renaming a column may break existing clients. 9 | 10 | ## solution 11 | 12 | There isn't an easy way to rename a column. 13 | 14 | If you're using an ORM (object relational mapper), you can rename the field in your application level struct while leaving the column name unchanged. 15 | 16 | A more complicated solution using a new column with triggers and backfill to sync the two columns may work. -------------------------------------------------------------------------------- /docs/docs/rules-overview.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: rules 3 | title: Rules Overview 4 | --- 5 | 6 | Squawk's rules focus on ensuring safe migrations and warn about statements that could block reads / writes or break existing clients. See the sidebar for documentation for each rule. 7 | 8 | The rule docs should provide actionable, user friendly error messages. If you find a rule, error message, or docs page lacking, please [open an issue](https://github.com/sbdchd/squawk/issues/new). 9 | 10 | 11 | :::note Reminder 12 | 13 | Read ["Running Migrations](./safe_migrations.md) to learn about safely applying migrations after linting. 14 | ::: 15 | 16 | ## index 17 | import sidebar from '../sidebars.js' 18 | 19 |
    20 | {sidebar.someSidebar.Rules.map(ruleName =>
  • {ruleName}
  • )} 21 |
22 | -------------------------------------------------------------------------------- /docs/docs/troubleshooting.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: troubleshooting 3 | title: Troubleshooting 4 | --- 5 | 6 | If you encounter an issue using Squawk that can't be resolved with these docs, please [open an issue](https://github.com/sbdchd/squawk/issues/new). 7 | -------------------------------------------------------------------------------- /docs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "squawk", 3 | "version": "0.7.2", 4 | "private": true, 5 | "scripts": { 6 | "docusaurus": "docusaurus", 7 | "start": "ALGOLIA_APP_ID=empty ALGOLIA_API_KEY=empty ALGOLIA_INDEX_NAME=empty docusaurus start", 8 | "build": "docusaurus build", 9 | "swizzle": "docusaurus swizzle", 10 | "deploy": "docusaurus deploy", 11 | "serve": "docusaurus serve", 12 | "clear": "docusaurus clear" 13 | }, 14 | "dependencies": { 15 | "@docusaurus/core": "2.0.0-alpha.70", 16 | "@docusaurus/preset-classic": "2.0.0-alpha.70", 17 | "@mdx-js/react": "^1.6.21", 18 | "clsx": "^1.1.1", 19 | "react": "^16.8.4", 20 | "react-dom": "^16.8.4" 21 | }, 22 | "browserslist": { 23 | "production": [ 24 | ">0.5%", 25 | "not dead", 26 | "not op_mini all" 27 | ], 28 | "development": [ 29 | "last 1 chrome version", 30 | "last 1 firefox version", 31 | "last 1 safari version" 32 | ] 33 | }, 34 | "volta": { 35 | "node": "12.18.0" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /docs/src/css/custom.css: -------------------------------------------------------------------------------- 1 | /* stylelint-disable docusaurus/copyright-header */ 2 | /** 3 | * Any CSS included here will be global. The classic template 4 | * bundles Infima by default. Infima is a CSS framework designed to 5 | * work well for content-centric websites. 6 | */ 7 | 8 | /* 9 | template: https://github.com/facebook/docusaurus/blob/ac28dc70917e2746b5229b1717f21dbe0acdba6e/packages/docusaurus-init/templates/classic/src/css/custom.css */ 10 | 11 | .docusaurus-highlight-code-line { 12 | background-color: rgb(72, 77, 91); 13 | display: block; 14 | margin: 0 calc(-1 * var(--ifm-pre-padding)); 15 | padding: 0 var(--ifm-pre-padding); 16 | } 17 | -------------------------------------------------------------------------------- /docs/src/pages/styles.module.css: -------------------------------------------------------------------------------- 1 | /* stylelint-disable docusaurus/copyright-header */ 2 | 3 | /** 4 | * CSS files with the .module.css suffix will be treated as CSS modules 5 | * and scoped locally. 6 | */ 7 | 8 | .heroBanner { 9 | padding: 4rem 0; 10 | text-align: center; 11 | position: relative; 12 | overflow: hidden; 13 | } 14 | 15 | @media screen and (max-width: 966px) { 16 | .heroBanner { 17 | padding: 2rem; 18 | } 19 | } 20 | 21 | .buttons { 22 | display: flex; 23 | align-items: center; 24 | justify-content: center; 25 | } 26 | 27 | .features { 28 | display: flex; 29 | align-items: center; 30 | padding: 2rem 0; 31 | width: 100%; 32 | } 33 | 34 | .featureImage { 35 | height: 200px; 36 | width: 200px; 37 | } 38 | -------------------------------------------------------------------------------- /docs/static/.nojekyll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sbdchd/squawk/061710b1fa47c300f44cda49586a39fd8a2a535b/docs/static/.nojekyll -------------------------------------------------------------------------------- /docs/static/img/owl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sbdchd/squawk/061710b1fa47c300f44cda49586a39fd8a2a535b/docs/static/img/owl.png -------------------------------------------------------------------------------- /docs/static/img/squawk-pr-comment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sbdchd/squawk/061710b1fa47c300f44cda49586a39fd8a2a535b/docs/static/img/squawk-pr-comment.png -------------------------------------------------------------------------------- /docs/static/img/squawk-wordmark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sbdchd/squawk/061710b1fa47c300f44cda49586a39fd8a2a535b/docs/static/img/squawk-wordmark.png -------------------------------------------------------------------------------- /example.sql: -------------------------------------------------------------------------------- 1 | BEGIN; 2 | -- 3 | -- Create model Bar 4 | -- 5 | CREATE TABLE "core_bar" ( 6 | "id" serial NOT NULL PRIMARY KEY, 7 | "alpha" varchar(100) NOT NULL 8 | ); 9 | 10 | CREATE INDEX "field_name_idx" ON "table_name" ("field_name"); 11 | 12 | ALTER TABLE table_name ADD CONSTRAINT field_name_constraint UNIQUE (field_name); 13 | 14 | COMMIT; 15 | -------------------------------------------------------------------------------- /js/binaries/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /js/helpers.js: -------------------------------------------------------------------------------- 1 | "use strict" 2 | 3 | const path = require("path") 4 | const binaryPath = path.resolve(__dirname, "binaries", "squawk") 5 | 6 | module.exports = { 7 | binaryPath, 8 | } 9 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "squawk-cli", 3 | "version": "2.11.0", 4 | "description": "linter for PostgreSQL, focused on migrations", 5 | "repository": "git@github.com:sbdchd/squawk.git", 6 | "author": "Steve Dignam ", 7 | "license": "GPL-3.0", 8 | "keywords": [ 9 | "postgres", 10 | "postgresql", 11 | "linter", 12 | "SQL", 13 | "migrations" 14 | ], 15 | "bin": { 16 | "squawk": "js/bin/squawk" 17 | }, 18 | "scripts": { 19 | "install": "node js/install.js" 20 | }, 21 | "devDependencies": { 22 | "@types/node": "^14.0.13", 23 | "@types/node-fetch": "^2.5.7", 24 | "@typescript-eslint/eslint-plugin": "^3.3.0", 25 | "@typescript-eslint/parser": "^3.3.0", 26 | "eslint": "^7.2.0", 27 | "eslint-plugin-import": "^2.21.2", 28 | "prettier": "^2.0.5", 29 | "typescript": "^3.9.5" 30 | }, 31 | "dependencies": { 32 | "node-fetch": "^2.6.0" 33 | }, 34 | "volta": { 35 | "node": "18.15.0" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /playground/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | 26 | # Sentry Config File 27 | .env.sentry-build-plugin 28 | -------------------------------------------------------------------------------- /playground/.netlify/state.json: -------------------------------------------------------------------------------- 1 | { 2 | "siteId": "34768e35-903f-4f55-807d-916f993f368e" 3 | } 4 | -------------------------------------------------------------------------------- /playground/README.md: -------------------------------------------------------------------------------- 1 | # playground 2 | 3 | > 4 | 5 | ## dev 6 | 7 | ```shell 8 | pnpm dev 9 | ``` 10 | 11 | ```shell 12 | cargo install wasm-pack 13 | ``` 14 | 15 | ## deploy 16 | 17 | ```shell 18 | npm run build 19 | 20 | # deploy to preview 21 | netlify deploy 22 | 23 | # check it looks good, then deploy to prod 24 | netlify deploy --prod 25 | ``` 26 | -------------------------------------------------------------------------------- /playground/eslint.config.js: -------------------------------------------------------------------------------- 1 | import js from "@eslint/js" 2 | import globals from "globals" 3 | import reactHooks from "eslint-plugin-react-hooks" 4 | import reactRefresh from "eslint-plugin-react-refresh" 5 | import tseslint from "typescript-eslint" 6 | 7 | export default tseslint.config( 8 | { ignores: ["dist"] }, 9 | { 10 | extends: [js.configs.recommended, ...tseslint.configs.recommended], 11 | files: ["**/*.{ts,tsx}"], 12 | languageOptions: { 13 | ecmaVersion: 2020, 14 | globals: globals.browser, 15 | }, 16 | plugins: { 17 | "react-hooks": reactHooks, 18 | "react-refresh": reactRefresh, 19 | }, 20 | rules: { 21 | ...reactHooks.configs.recommended.rules, 22 | "react-refresh/only-export-components": [ 23 | "warn", 24 | { allowConstantExport: true }, 25 | ], 26 | }, 27 | }, 28 | ) 29 | -------------------------------------------------------------------------------- /playground/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Squawk Playground 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /playground/prettier.config.js: -------------------------------------------------------------------------------- 1 | // https://prettier.io/docs/en/options.html 2 | /** @type {import("prettier").Config} */ 3 | export default { 4 | semi: false, 5 | useTabs: false, 6 | tabWidth: 2, 7 | singleQuote: false, 8 | trailingComma: "all", 9 | bracketSpacing: true, 10 | } 11 | -------------------------------------------------------------------------------- /playground/public/owl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sbdchd/squawk/061710b1fa47c300f44cda49586a39fd8a2a535b/playground/public/owl.png -------------------------------------------------------------------------------- /playground/src/index.css: -------------------------------------------------------------------------------- 1 | @import "tailwindcss"; 2 | -------------------------------------------------------------------------------- /playground/src/monacoWorker.tsx: -------------------------------------------------------------------------------- 1 | import editorWorker from "monaco-editor/esm/vs/editor/editor.worker?worker" 2 | 3 | self.MonacoEnvironment = { 4 | // eslint-disable-next-line @typescript-eslint/no-unused-vars 5 | getWorker(_: unknown, _label: string) { 6 | return new editorWorker() 7 | }, 8 | } 9 | -------------------------------------------------------------------------------- /playground/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /playground/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", 4 | "target": "ES2020", 5 | "useDefineForClassFields": true, 6 | "lib": ["ES2020", "DOM", "DOM.Iterable"], 7 | "module": "ESNext", 8 | "skipLibCheck": true, 9 | 10 | /* Bundler mode */ 11 | "moduleResolution": "bundler", 12 | "allowImportingTsExtensions": true, 13 | "isolatedModules": true, 14 | "moduleDetection": "force", 15 | "noEmit": true, 16 | "jsx": "react-jsx", 17 | 18 | /* Linting */ 19 | "strict": true, 20 | "noUnusedLocals": true, 21 | "noUnusedParameters": true, 22 | "noFallthroughCasesInSwitch": true, 23 | "noUncheckedSideEffectImports": true 24 | }, 25 | "include": ["src"] 26 | } 27 | -------------------------------------------------------------------------------- /playground/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [], 3 | "references": [ 4 | { "path": "./tsconfig.app.json" }, 5 | { "path": "./tsconfig.node.json" } 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /playground/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", 4 | "target": "ES2022", 5 | "lib": ["ES2023"], 6 | "module": "ESNext", 7 | "skipLibCheck": true, 8 | 9 | /* Bundler mode */ 10 | "moduleResolution": "bundler", 11 | "allowImportingTsExtensions": true, 12 | "isolatedModules": true, 13 | "moduleDetection": "force", 14 | "noEmit": true, 15 | 16 | /* Linting */ 17 | "strict": true, 18 | "noUnusedLocals": true, 19 | "noUnusedParameters": true, 20 | "noFallthroughCasesInSwitch": true, 21 | "noUncheckedSideEffectImports": true 22 | }, 23 | "include": ["vite.config.ts"] 24 | } 25 | -------------------------------------------------------------------------------- /playground/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite" 2 | import { sentryVitePlugin } from "@sentry/vite-plugin" 3 | import react from "@vitejs/plugin-react" 4 | import tailwindcss from "@tailwindcss/vite" 5 | 6 | const ReactCompilerConfig = {} 7 | 8 | // https://vite.dev/config/ 9 | export default defineConfig({ 10 | plugins: [ 11 | react({ 12 | babel: { 13 | plugins: [["babel-plugin-react-compiler", ReactCompilerConfig]], 14 | }, 15 | }), 16 | tailwindcss(), 17 | sentryVitePlugin({ 18 | org: "magnus-montis", 19 | project: "squawk-playground-ui", 20 | }), 21 | ], 22 | build: { 23 | sourcemap: true, 24 | }, 25 | }) 26 | -------------------------------------------------------------------------------- /rust-toolchain.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | targets = ["x86_64-unknown-linux-gnu", "x86_64-apple-darwin", "aarch64-apple-darwin"] 3 | channel = "1.84.0" 4 | -------------------------------------------------------------------------------- /s/ci-install: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec yarn --frozen-lockfile --ignore-scripts 3 | -------------------------------------------------------------------------------- /s/eslint: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -ex 4 | 5 | ./node_modules/.bin/eslint 'js/*.js' 6 | -------------------------------------------------------------------------------- /s/fmt: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -eu 3 | 4 | cargo fmt 5 | -------------------------------------------------------------------------------- /s/lint: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -eu 3 | 4 | cargo fmt -- --check 5 | cargo clippy --all-targets --all-features -- -D warnings 6 | -------------------------------------------------------------------------------- /s/pin-actions-versions: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -ex 3 | 4 | main() { 5 | pin-github-action --allow='actions/*' ./github/workflows/* 6 | } 7 | 8 | main "$@" 9 | -------------------------------------------------------------------------------- /s/prettier: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -ex 4 | 5 | main() { 6 | if [ "$CI" ]; then 7 | ./node_modules/.bin/prettier --check '**/*.{js,md,yml,json}' 8 | else 9 | ./node_modules/.bin/prettier '**/*.{js,md,yml,json}' --write 10 | fi 11 | } 12 | 13 | main "$@" 14 | 15 | -------------------------------------------------------------------------------- /s/test: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | cargo test 4 | -------------------------------------------------------------------------------- /s/tsc: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -ex 4 | 5 | ./node_modules/.bin/tsc --noEmit --project tsconfig.json 6 | -------------------------------------------------------------------------------- /s/update-version: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # This script requires fastmod to be installed 3 | # fastmod: https://github.com/facebookincubator/fastmod 4 | 5 | 6 | function main { 7 | NEW_VERSION="$1" 8 | echo "updating version to '$NEW_VERSION'..." 9 | fastmod --accept-all '^version = ".*"' 'version = "'$NEW_VERSION'"' crates/squawk/Cargo.toml 10 | fastmod --accept-all -m '(name = "squawk"\n)version = ".*?"' '${1}version = "'$NEW_VERSION'"' Cargo.lock 11 | fastmod --accept-all '"version": ".*"' '"version": "'$NEW_VERSION'"' package.json 12 | fastmod --accept-all -m '(pname = "squawk";.*?)version = ".*?"' '${1}version = "'$NEW_VERSION'"' flake.nix 13 | } 14 | 15 | 16 | main $@ 17 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "sourceMap": true, 4 | "allowJs": true, 5 | "checkJs": true, 6 | "target": "es2017", 7 | "module": "commonjs", 8 | "moduleResolution": "node", 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "noUnusedLocals": true, 12 | "noUnusedParameters": true, 13 | "skipLibCheck": true, 14 | "esModuleInterop": true, 15 | "resolveJsonModule": true, 16 | "jsx": "react", 17 | "noEmit": true 18 | }, 19 | "include": ["js/**/*.js"], 20 | "exclude": ["build", "node_modules", "docs", "plopfile.js", "playground"] 21 | } 22 | --------------------------------------------------------------------------------