From 171497e4ef363fc8a35b459edb2cff4d9505730e Mon Sep 17 00:00:00 2001 From: Johannes Knopp Date: Wed, 3 Jun 2026 00:13:57 +0200 Subject: [PATCH 1/2] fix(pretty-print): quote reserved-keyword and mixed-case identifiert across all emitters Several emitters printed identifiers as bare tokens instead of using the quote-aware helper, so names that require quoting (reserved keywords, multi-word, mixed-case) lost their qutes and produced invalid or semantically different SQL. Similar to (#749), routed them through `emit_identifier_maybe_quoted` instead of using bare `TokenKind::IDENT` tokens, and added test cases covering one statement per fixed emitter. --- crates/pgls_pretty_print/src/nodes/alias.rs | 4 +- .../nodes/alter_database_refresh_coll_stmt.rs | 2 +- .../src/nodes/alter_database_set_stmt.rs | 2 +- .../src/nodes/alter_database_stmt.rs | 2 +- .../src/nodes/alter_event_trig_stmt.rs | 2 +- .../nodes/alter_extension_contents_stmt.rs | 2 +- .../src/nodes/alter_extension_stmt.rs | 2 +- .../src/nodes/alter_fdw_stmt.rs | 2 +- .../src/nodes/alter_object_depends_stmt.rs | 2 +- .../src/nodes/alter_object_schema_stmt.rs | 2 +- .../src/nodes/alter_op_family_stmt.rs | 2 +- .../src/nodes/alter_publication_stmt.rs | 2 +- .../src/nodes/alter_role_set_stmt.rs | 2 +- .../src/nodes/alter_table_move_all_stmt.rs | 4 +- .../src/nodes/alter_user_mapping_stmt.rs | 2 +- .../src/nodes/close_portal_stmt.rs | 2 +- .../src/nodes/cluster_stmt.rs | 2 +- .../src/nodes/common_table_expr.rs | 2 +- .../pgls_pretty_print/src/nodes/constraint.rs | 2 +- .../src/nodes/create_am_stmt.rs | 2 +- .../src/nodes/create_extension_stmt.rs | 2 +- .../src/nodes/create_fdw_stmt.rs | 2 +- .../src/nodes/create_foreign_table_stmt.rs | 2 +- .../src/nodes/create_op_class_stmt.rs | 2 +- .../src/nodes/create_op_family_stmt.rs | 2 +- .../src/nodes/create_publication_stmt.rs | 2 +- .../src/nodes/create_transform_stmt.rs | 2 +- .../src/nodes/create_trig_stmt.rs | 2 +- .../src/nodes/create_user_mapping_stmt.rs | 2 +- .../src/nodes/deallocate_stmt.rs | 2 +- .../src/nodes/drop_table_space_stmt.rs | 2 +- .../src/nodes/drop_user_mapping_stmt.rs | 2 +- .../src/nodes/dropdb_stmt.rs | 2 +- .../src/nodes/execute_stmt.rs | 2 +- .../pgls_pretty_print/src/nodes/fetch_stmt.rs | 2 +- .../src/nodes/import_foreign_schema_stmt.rs | 6 +- .../pgls_pretty_print/src/nodes/index_elem.rs | 2 +- .../pgls_pretty_print/src/nodes/index_stmt.rs | 4 +- .../src/nodes/listen_stmt.rs | 2 +- .../src/nodes/partition_elem.rs | 2 +- .../src/nodes/prepare_stmt.rs | 2 +- .../src/nodes/publication_obj_spec.rs | 2 +- .../src/nodes/reindex_stmt.rs | 2 +- .../src/nodes/replica_identity_stmt.rs | 2 +- .../pgls_pretty_print/src/nodes/rule_stmt.rs | 2 +- .../src/nodes/unlisten_stmt.rs | 2 +- .../data/multi/reserved_keyword_idents.sql | 83 +++++++++++ .../single/index_elem_reserved_keyword_0.sql | 1 + .../tests__reserved_keyword_idents_100.snap | 133 ++++++++++++++++++ .../tests__reserved_keyword_idents_80.snap | 133 ++++++++++++++++++ ...ts__index_elem_reserved_keyword_0_100.snap | 14 ++ ...sts__index_elem_reserved_keyword_0_80.snap | 14 ++ 52 files changed, 429 insertions(+), 51 deletions(-) create mode 100644 crates/pgls_pretty_print/tests/data/multi/reserved_keyword_idents.sql create mode 100644 crates/pgls_pretty_print/tests/data/single/index_elem_reserved_keyword_0.sql create mode 100644 crates/pgls_pretty_print/tests/snapshots/multi/tests__reserved_keyword_idents_100.snap create mode 100644 crates/pgls_pretty_print/tests/snapshots/multi/tests__reserved_keyword_idents_80.snap create mode 100644 crates/pgls_pretty_print/tests/snapshots/single/tests__index_elem_reserved_keyword_0_100.snap create mode 100644 crates/pgls_pretty_print/tests/snapshots/single/tests__index_elem_reserved_keyword_0_80.snap diff --git a/crates/pgls_pretty_print/src/nodes/alias.rs b/crates/pgls_pretty_print/src/nodes/alias.rs index a1e1a906c..0718e43a0 100644 --- a/crates/pgls_pretty_print/src/nodes/alias.rs +++ b/crates/pgls_pretty_print/src/nodes/alias.rs @@ -15,7 +15,7 @@ pub(super) fn emit_alias(e: &mut EventEmitter, n: &Alias) { e.token(TokenKind::AS_KW); e.space(); - e.token(TokenKind::IDENT(n.aliasname.clone())); + super::emit_identifier_maybe_quoted(e, &n.aliasname); // Add column aliases if present if !n.colnames.is_empty() { @@ -24,7 +24,7 @@ pub(super) fn emit_alias(e: &mut EventEmitter, n: &Alias) { emit_comma_separated_list(e, &n.colnames, |node, e| { // Column names in alias are String nodes if let Some(pgls_query::NodeEnum::String(s)) = node.node.as_ref() { - e.token(TokenKind::IDENT(s.sval.clone())); + super::emit_identifier_maybe_quoted(e, &s.sval); } else { super::emit_node(node, e); } diff --git a/crates/pgls_pretty_print/src/nodes/alter_database_refresh_coll_stmt.rs b/crates/pgls_pretty_print/src/nodes/alter_database_refresh_coll_stmt.rs index 76285cb3e..ead501907 100644 --- a/crates/pgls_pretty_print/src/nodes/alter_database_refresh_coll_stmt.rs +++ b/crates/pgls_pretty_print/src/nodes/alter_database_refresh_coll_stmt.rs @@ -14,7 +14,7 @@ pub(super) fn emit_alter_database_refresh_coll_stmt( e.space(); if !n.dbname.is_empty() { - e.token(TokenKind::IDENT(n.dbname.clone())); + super::emit_identifier_maybe_quoted(e, &n.dbname); } e.line(LineType::SoftOrSpace); diff --git a/crates/pgls_pretty_print/src/nodes/alter_database_set_stmt.rs b/crates/pgls_pretty_print/src/nodes/alter_database_set_stmt.rs index d44f51b46..25dbc6ff9 100644 --- a/crates/pgls_pretty_print/src/nodes/alter_database_set_stmt.rs +++ b/crates/pgls_pretty_print/src/nodes/alter_database_set_stmt.rs @@ -11,7 +11,7 @@ pub(super) fn emit_alter_database_set_stmt(e: &mut EventEmitter, n: &AlterDataba e.space(); if !n.dbname.is_empty() { - e.token(TokenKind::IDENT(n.dbname.clone())); + super::emit_identifier_maybe_quoted(e, &n.dbname); } if let Some(ref setstmt) = n.setstmt { diff --git a/crates/pgls_pretty_print/src/nodes/alter_database_stmt.rs b/crates/pgls_pretty_print/src/nodes/alter_database_stmt.rs index 0f6b25382..fee0d6f5e 100644 --- a/crates/pgls_pretty_print/src/nodes/alter_database_stmt.rs +++ b/crates/pgls_pretty_print/src/nodes/alter_database_stmt.rs @@ -13,7 +13,7 @@ pub(super) fn emit_alter_database_stmt(e: &mut EventEmitter, n: &AlterDatabaseSt e.space(); if !n.dbname.is_empty() { - e.token(TokenKind::IDENT(n.dbname.clone())); + super::emit_identifier_maybe_quoted(e, &n.dbname); } if !n.options.is_empty() { diff --git a/crates/pgls_pretty_print/src/nodes/alter_event_trig_stmt.rs b/crates/pgls_pretty_print/src/nodes/alter_event_trig_stmt.rs index 35edba6bd..92b95a5b9 100644 --- a/crates/pgls_pretty_print/src/nodes/alter_event_trig_stmt.rs +++ b/crates/pgls_pretty_print/src/nodes/alter_event_trig_stmt.rs @@ -13,7 +13,7 @@ pub(super) fn emit_alter_event_trig_stmt(e: &mut EventEmitter, n: &AlterEventTri e.space(); if !n.trigname.is_empty() { - e.token(TokenKind::IDENT(n.trigname.clone())); + super::emit_identifier_maybe_quoted(e, &n.trigname); } e.space(); diff --git a/crates/pgls_pretty_print/src/nodes/alter_extension_contents_stmt.rs b/crates/pgls_pretty_print/src/nodes/alter_extension_contents_stmt.rs index 06202e72a..03537f618 100644 --- a/crates/pgls_pretty_print/src/nodes/alter_extension_contents_stmt.rs +++ b/crates/pgls_pretty_print/src/nodes/alter_extension_contents_stmt.rs @@ -14,7 +14,7 @@ pub(super) fn emit_alter_extension_contents_stmt( e.space(); if !n.extname.is_empty() { - e.token(TokenKind::IDENT(n.extname.clone())); + super::emit_identifier_maybe_quoted(e, &n.extname); } e.line(LineType::SoftOrSpace); diff --git a/crates/pgls_pretty_print/src/nodes/alter_extension_stmt.rs b/crates/pgls_pretty_print/src/nodes/alter_extension_stmt.rs index 6660f4fd0..66fee4d8e 100644 --- a/crates/pgls_pretty_print/src/nodes/alter_extension_stmt.rs +++ b/crates/pgls_pretty_print/src/nodes/alter_extension_stmt.rs @@ -13,7 +13,7 @@ pub(super) fn emit_alter_extension_stmt(e: &mut EventEmitter, n: &AlterExtension e.space(); if !n.extname.is_empty() { - e.token(TokenKind::IDENT(n.extname.clone())); + super::emit_identifier_maybe_quoted(e, &n.extname); } if !n.options.is_empty() { diff --git a/crates/pgls_pretty_print/src/nodes/alter_fdw_stmt.rs b/crates/pgls_pretty_print/src/nodes/alter_fdw_stmt.rs index f1ca2dcf3..598424775 100644 --- a/crates/pgls_pretty_print/src/nodes/alter_fdw_stmt.rs +++ b/crates/pgls_pretty_print/src/nodes/alter_fdw_stmt.rs @@ -17,7 +17,7 @@ pub(super) fn emit_alter_fdw_stmt(e: &mut EventEmitter, n: &AlterFdwStmt) { e.space(); if !n.fdwname.is_empty() { - e.token(TokenKind::IDENT(n.fdwname.clone())); + super::emit_identifier_maybe_quoted(e, &n.fdwname); } // Handler/validator functions in func_options - space-separated, not comma-separated diff --git a/crates/pgls_pretty_print/src/nodes/alter_object_depends_stmt.rs b/crates/pgls_pretty_print/src/nodes/alter_object_depends_stmt.rs index b44c1a500..09e358ece 100644 --- a/crates/pgls_pretty_print/src/nodes/alter_object_depends_stmt.rs +++ b/crates/pgls_pretty_print/src/nodes/alter_object_depends_stmt.rs @@ -37,7 +37,7 @@ pub(super) fn emit_alter_object_depends_stmt(e: &mut EventEmitter, n: &AlterObje if let Some(ref extname) = n.extname { e.space(); - e.token(TokenKind::IDENT(extname.sval.clone())); + super::emit_identifier_maybe_quoted(e, &extname.sval); } e.token(TokenKind::SEMICOLON); diff --git a/crates/pgls_pretty_print/src/nodes/alter_object_schema_stmt.rs b/crates/pgls_pretty_print/src/nodes/alter_object_schema_stmt.rs index 37f9190e9..a9cfa4179 100644 --- a/crates/pgls_pretty_print/src/nodes/alter_object_schema_stmt.rs +++ b/crates/pgls_pretty_print/src/nodes/alter_object_schema_stmt.rs @@ -123,7 +123,7 @@ pub(super) fn emit_alter_object_schema_stmt(e: &mut EventEmitter, n: &AlterObjec e.space(); e.token(TokenKind::SCHEMA_KW); e.space(); - e.token(TokenKind::IDENT(n.newschema.clone())); + super::emit_identifier_maybe_quoted(e, &n.newschema); } e.token(TokenKind::SEMICOLON); diff --git a/crates/pgls_pretty_print/src/nodes/alter_op_family_stmt.rs b/crates/pgls_pretty_print/src/nodes/alter_op_family_stmt.rs index e7ffb3406..8c29960c5 100644 --- a/crates/pgls_pretty_print/src/nodes/alter_op_family_stmt.rs +++ b/crates/pgls_pretty_print/src/nodes/alter_op_family_stmt.rs @@ -23,7 +23,7 @@ pub(super) fn emit_alter_op_family_stmt(e: &mut EventEmitter, n: &AlterOpFamilyS e.space(); if !n.amname.is_empty() { - e.token(TokenKind::IDENT(n.amname.clone())); + super::emit_identifier_maybe_quoted(e, &n.amname); } // Use indent and soft line break for ADD/DROP clause diff --git a/crates/pgls_pretty_print/src/nodes/alter_publication_stmt.rs b/crates/pgls_pretty_print/src/nodes/alter_publication_stmt.rs index 0852a89da..5cd833ae1 100644 --- a/crates/pgls_pretty_print/src/nodes/alter_publication_stmt.rs +++ b/crates/pgls_pretty_print/src/nodes/alter_publication_stmt.rs @@ -14,7 +14,7 @@ pub(super) fn emit_alter_publication_stmt(e: &mut EventEmitter, n: &AlterPublica // Publication name if !n.pubname.is_empty() { - e.token(TokenKind::IDENT(n.pubname.clone())); + super::emit_identifier_maybe_quoted(e, &n.pubname); } // action: 0=Undefined, 1=AP_AddObjects, 2=AP_DropObjects, 3=AP_SetObjects diff --git a/crates/pgls_pretty_print/src/nodes/alter_role_set_stmt.rs b/crates/pgls_pretty_print/src/nodes/alter_role_set_stmt.rs index 78cb15b48..ecfe6e458 100644 --- a/crates/pgls_pretty_print/src/nodes/alter_role_set_stmt.rs +++ b/crates/pgls_pretty_print/src/nodes/alter_role_set_stmt.rs @@ -23,7 +23,7 @@ pub(super) fn emit_alter_role_set_stmt(e: &mut EventEmitter, n: &AlterRoleSetStm e.space(); e.token(TokenKind::DATABASE_KW); e.space(); - e.token(TokenKind::IDENT(n.database.clone())); + super::emit_identifier_maybe_quoted(e, &n.database); } // The SET/RESET statement diff --git a/crates/pgls_pretty_print/src/nodes/alter_table_move_all_stmt.rs b/crates/pgls_pretty_print/src/nodes/alter_table_move_all_stmt.rs index 3acf12c76..aaee193cd 100644 --- a/crates/pgls_pretty_print/src/nodes/alter_table_move_all_stmt.rs +++ b/crates/pgls_pretty_print/src/nodes/alter_table_move_all_stmt.rs @@ -29,7 +29,7 @@ pub(super) fn emit_alter_table_move_all_stmt(e: &mut EventEmitter, n: &AlterTabl e.space(); e.token(TokenKind::TABLESPACE_KW); e.space(); - e.token(TokenKind::IDENT(n.orig_tablespacename.clone())); + super::emit_identifier_maybe_quoted(e, &n.orig_tablespacename); // Emit OWNED BY roles if specified if !n.roles.is_empty() { @@ -49,7 +49,7 @@ pub(super) fn emit_alter_table_move_all_stmt(e: &mut EventEmitter, n: &AlterTabl e.space(); e.token(TokenKind::TABLESPACE_KW); e.space(); - e.token(TokenKind::IDENT(n.new_tablespacename.clone())); + super::emit_identifier_maybe_quoted(e, &n.new_tablespacename); if n.nowait { e.space(); diff --git a/crates/pgls_pretty_print/src/nodes/alter_user_mapping_stmt.rs b/crates/pgls_pretty_print/src/nodes/alter_user_mapping_stmt.rs index 735b87e80..cae958097 100644 --- a/crates/pgls_pretty_print/src/nodes/alter_user_mapping_stmt.rs +++ b/crates/pgls_pretty_print/src/nodes/alter_user_mapping_stmt.rs @@ -26,7 +26,7 @@ pub(super) fn emit_alter_user_mapping_stmt(e: &mut EventEmitter, n: &AlterUserMa e.space(); e.token(TokenKind::SERVER_KW); e.space(); - e.token(TokenKind::IDENT(n.servername.clone())); + super::emit_identifier_maybe_quoted(e, &n.servername); // Options if !n.options.is_empty() { diff --git a/crates/pgls_pretty_print/src/nodes/close_portal_stmt.rs b/crates/pgls_pretty_print/src/nodes/close_portal_stmt.rs index da1ab1b63..4da528110 100644 --- a/crates/pgls_pretty_print/src/nodes/close_portal_stmt.rs +++ b/crates/pgls_pretty_print/src/nodes/close_portal_stmt.rs @@ -13,7 +13,7 @@ pub(super) fn emit_close_portal_stmt(e: &mut EventEmitter, n: &ClosePortalStmt) if n.portalname.is_empty() { e.token(TokenKind::ALL_KW); } else { - e.token(TokenKind::IDENT(n.portalname.clone())); + super::emit_identifier_maybe_quoted(e, &n.portalname); } e.token(TokenKind::SEMICOLON); diff --git a/crates/pgls_pretty_print/src/nodes/cluster_stmt.rs b/crates/pgls_pretty_print/src/nodes/cluster_stmt.rs index 26133a17b..c568fe16a 100644 --- a/crates/pgls_pretty_print/src/nodes/cluster_stmt.rs +++ b/crates/pgls_pretty_print/src/nodes/cluster_stmt.rs @@ -25,7 +25,7 @@ pub(super) fn emit_cluster_stmt(e: &mut EventEmitter, n: &ClusterStmt) { e.line(LineType::SoftOrSpace); e.token(TokenKind::USING_KW); e.space(); - e.token(TokenKind::IDENT(n.indexname.clone())); + super::emit_identifier_maybe_quoted(e, &n.indexname); } } diff --git a/crates/pgls_pretty_print/src/nodes/common_table_expr.rs b/crates/pgls_pretty_print/src/nodes/common_table_expr.rs index 3b81fe0da..390c982f6 100644 --- a/crates/pgls_pretty_print/src/nodes/common_table_expr.rs +++ b/crates/pgls_pretty_print/src/nodes/common_table_expr.rs @@ -14,7 +14,7 @@ pub(super) fn emit_common_table_expr(e: &mut EventEmitter, n: &CommonTableExpr) e.group_start(GroupKind::CommonTableExpr); // CTE name - e.token(TokenKind::IDENT(n.ctename.clone())); + super::emit_identifier_maybe_quoted(e, &n.ctename); // Optional column aliases if !n.aliascolnames.is_empty() { diff --git a/crates/pgls_pretty_print/src/nodes/constraint.rs b/crates/pgls_pretty_print/src/nodes/constraint.rs index 699529406..841de695c 100644 --- a/crates/pgls_pretty_print/src/nodes/constraint.rs +++ b/crates/pgls_pretty_print/src/nodes/constraint.rs @@ -303,7 +303,7 @@ pub(super) fn emit_constraint(e: &mut EventEmitter, n: &Constraint) { e.space(); e.token(TokenKind::USING_KW); e.space(); - e.token(TokenKind::IDENT(n.access_method.clone())); + super::emit_identifier_maybe_quoted(e, &n.access_method); } if !n.exclusions.is_empty() { diff --git a/crates/pgls_pretty_print/src/nodes/create_am_stmt.rs b/crates/pgls_pretty_print/src/nodes/create_am_stmt.rs index ebf4cd344..f25f022ff 100644 --- a/crates/pgls_pretty_print/src/nodes/create_am_stmt.rs +++ b/crates/pgls_pretty_print/src/nodes/create_am_stmt.rs @@ -16,7 +16,7 @@ pub(super) fn emit_create_am_stmt(e: &mut EventEmitter, n: &CreateAmStmt) { if !n.amname.is_empty() { e.space(); - e.token(TokenKind::IDENT(n.amname.clone())); + super::emit_identifier_maybe_quoted(e, &n.amname); } // TYPE diff --git a/crates/pgls_pretty_print/src/nodes/create_extension_stmt.rs b/crates/pgls_pretty_print/src/nodes/create_extension_stmt.rs index b70c47e8d..92a52de14 100644 --- a/crates/pgls_pretty_print/src/nodes/create_extension_stmt.rs +++ b/crates/pgls_pretty_print/src/nodes/create_extension_stmt.rs @@ -21,7 +21,7 @@ pub(super) fn emit_create_extension_stmt(e: &mut EventEmitter, n: &CreateExtensi e.space(); } - e.token(TokenKind::IDENT(n.extname.clone())); + super::emit_identifier_maybe_quoted(e, &n.extname); if !n.options.is_empty() { e.line(LineType::SoftOrSpace); diff --git a/crates/pgls_pretty_print/src/nodes/create_fdw_stmt.rs b/crates/pgls_pretty_print/src/nodes/create_fdw_stmt.rs index 48d9cd9e5..b00b7dd59 100644 --- a/crates/pgls_pretty_print/src/nodes/create_fdw_stmt.rs +++ b/crates/pgls_pretty_print/src/nodes/create_fdw_stmt.rs @@ -16,7 +16,7 @@ pub(super) fn emit_create_fdw_stmt(e: &mut EventEmitter, n: &CreateFdwStmt) { e.space(); e.token(TokenKind::WRAPPER_KW); e.space(); - e.token(TokenKind::IDENT(n.fdwname.clone())); + super::emit_identifier_maybe_quoted(e, &n.fdwname); // Handler and validator functions if !n.func_options.is_empty() { diff --git a/crates/pgls_pretty_print/src/nodes/create_foreign_table_stmt.rs b/crates/pgls_pretty_print/src/nodes/create_foreign_table_stmt.rs index 34877ade6..3c25e86b0 100644 --- a/crates/pgls_pretty_print/src/nodes/create_foreign_table_stmt.rs +++ b/crates/pgls_pretty_print/src/nodes/create_foreign_table_stmt.rs @@ -61,7 +61,7 @@ pub(super) fn emit_create_foreign_table_stmt(e: &mut EventEmitter, n: &CreateFor e.space(); e.token(TokenKind::SERVER_KW); e.space(); - e.token(TokenKind::IDENT(n.servername.clone())); + super::emit_identifier_maybe_quoted(e, &n.servername); // OPTIONS clause if !n.options.is_empty() { diff --git a/crates/pgls_pretty_print/src/nodes/create_op_class_stmt.rs b/crates/pgls_pretty_print/src/nodes/create_op_class_stmt.rs index 6f8fb4c6b..7b19b664f 100644 --- a/crates/pgls_pretty_print/src/nodes/create_op_class_stmt.rs +++ b/crates/pgls_pretty_print/src/nodes/create_op_class_stmt.rs @@ -39,7 +39,7 @@ pub(super) fn emit_create_op_class_stmt(e: &mut EventEmitter, n: &CreateOpClassS e.line(LineType::SoftOrSpace); e.token(TokenKind::USING_KW); e.space(); - e.token(TokenKind::IDENT(n.amname.clone())); + super::emit_identifier_maybe_quoted(e, &n.amname); // FAMILY if !n.opfamilyname.is_empty() { diff --git a/crates/pgls_pretty_print/src/nodes/create_op_family_stmt.rs b/crates/pgls_pretty_print/src/nodes/create_op_family_stmt.rs index 5c93520a5..71122e7d3 100644 --- a/crates/pgls_pretty_print/src/nodes/create_op_family_stmt.rs +++ b/crates/pgls_pretty_print/src/nodes/create_op_family_stmt.rs @@ -22,7 +22,7 @@ pub(super) fn emit_create_op_family_stmt(e: &mut EventEmitter, n: &CreateOpFamil e.line(LineType::SoftOrSpace); e.token(TokenKind::USING_KW); e.space(); - e.token(TokenKind::IDENT(n.amname.clone())); + super::emit_identifier_maybe_quoted(e, &n.amname); e.token(TokenKind::SEMICOLON); diff --git a/crates/pgls_pretty_print/src/nodes/create_publication_stmt.rs b/crates/pgls_pretty_print/src/nodes/create_publication_stmt.rs index 56cacc4de..058a28cec 100644 --- a/crates/pgls_pretty_print/src/nodes/create_publication_stmt.rs +++ b/crates/pgls_pretty_print/src/nodes/create_publication_stmt.rs @@ -12,7 +12,7 @@ pub(super) fn emit_create_publication_stmt(e: &mut EventEmitter, n: &CreatePubli e.space(); e.token(TokenKind::PUBLICATION_KW); e.space(); - e.token(TokenKind::IDENT(n.pubname.clone())); + super::emit_identifier_maybe_quoted(e, &n.pubname); if n.for_all_tables { e.space(); diff --git a/crates/pgls_pretty_print/src/nodes/create_transform_stmt.rs b/crates/pgls_pretty_print/src/nodes/create_transform_stmt.rs index 2f2e943cc..cc948a979 100644 --- a/crates/pgls_pretty_print/src/nodes/create_transform_stmt.rs +++ b/crates/pgls_pretty_print/src/nodes/create_transform_stmt.rs @@ -29,7 +29,7 @@ pub(super) fn emit_create_transform_stmt(e: &mut EventEmitter, n: &CreateTransfo e.space(); e.token(TokenKind::LANGUAGE_KW); e.space(); - e.token(TokenKind::IDENT(n.lang.clone())); + super::emit_identifier_maybe_quoted(e, &n.lang); e.line(LineType::SoftOrSpace); e.token(TokenKind::L_PAREN); diff --git a/crates/pgls_pretty_print/src/nodes/create_trig_stmt.rs b/crates/pgls_pretty_print/src/nodes/create_trig_stmt.rs index 1fb1521cb..2d96e35a1 100644 --- a/crates/pgls_pretty_print/src/nodes/create_trig_stmt.rs +++ b/crates/pgls_pretty_print/src/nodes/create_trig_stmt.rs @@ -27,7 +27,7 @@ pub(super) fn emit_create_trig_stmt(e: &mut EventEmitter, n: &CreateTrigStmt) { e.token(TokenKind::TRIGGER_KW); e.space(); - e.token(TokenKind::IDENT(n.trigname.clone())); + super::emit_identifier_maybe_quoted(e, &n.trigname); // Timing: BEFORE (2), AFTER (4), INSTEAD OF (16) // After trigger name, break to new line for timing + events + ON table diff --git a/crates/pgls_pretty_print/src/nodes/create_user_mapping_stmt.rs b/crates/pgls_pretty_print/src/nodes/create_user_mapping_stmt.rs index e8444dca8..463cb899d 100644 --- a/crates/pgls_pretty_print/src/nodes/create_user_mapping_stmt.rs +++ b/crates/pgls_pretty_print/src/nodes/create_user_mapping_stmt.rs @@ -34,7 +34,7 @@ pub(super) fn emit_create_user_mapping_stmt(e: &mut EventEmitter, n: &CreateUser e.line(LineType::SoftOrSpace); e.token(TokenKind::SERVER_KW); e.space(); - e.token(TokenKind::IDENT(n.servername.clone())); + super::emit_identifier_maybe_quoted(e, &n.servername); } if !n.options.is_empty() { diff --git a/crates/pgls_pretty_print/src/nodes/deallocate_stmt.rs b/crates/pgls_pretty_print/src/nodes/deallocate_stmt.rs index 4b2ed3bba..bdcbdc7f5 100644 --- a/crates/pgls_pretty_print/src/nodes/deallocate_stmt.rs +++ b/crates/pgls_pretty_print/src/nodes/deallocate_stmt.rs @@ -14,7 +14,7 @@ pub(super) fn emit_deallocate_stmt(e: &mut EventEmitter, n: &DeallocateStmt) { if n.name.is_empty() || n.name == "ALL" { e.token(TokenKind::ALL_KW); } else { - e.token(TokenKind::IDENT(n.name.clone())); + super::emit_identifier_maybe_quoted(e, &n.name); } e.token(TokenKind::SEMICOLON); diff --git a/crates/pgls_pretty_print/src/nodes/drop_table_space_stmt.rs b/crates/pgls_pretty_print/src/nodes/drop_table_space_stmt.rs index e7cc3b8a9..dea185412 100644 --- a/crates/pgls_pretty_print/src/nodes/drop_table_space_stmt.rs +++ b/crates/pgls_pretty_print/src/nodes/drop_table_space_stmt.rs @@ -21,7 +21,7 @@ pub(super) fn emit_drop_table_space_stmt(e: &mut EventEmitter, n: &DropTableSpac if !n.tablespacename.is_empty() { e.space(); - e.token(TokenKind::IDENT(n.tablespacename.clone())); + super::emit_identifier_maybe_quoted(e, &n.tablespacename); } e.token(TokenKind::SEMICOLON); diff --git a/crates/pgls_pretty_print/src/nodes/drop_user_mapping_stmt.rs b/crates/pgls_pretty_print/src/nodes/drop_user_mapping_stmt.rs index 58009ad04..9765f0e0c 100644 --- a/crates/pgls_pretty_print/src/nodes/drop_user_mapping_stmt.rs +++ b/crates/pgls_pretty_print/src/nodes/drop_user_mapping_stmt.rs @@ -33,7 +33,7 @@ pub(super) fn emit_drop_user_mapping_stmt(e: &mut EventEmitter, n: &DropUserMapp e.line(LineType::SoftOrSpace); e.token(TokenKind::SERVER_KW); e.space(); - e.token(TokenKind::IDENT(n.servername.clone())); + super::emit_identifier_maybe_quoted(e, &n.servername); } e.token(TokenKind::SEMICOLON); diff --git a/crates/pgls_pretty_print/src/nodes/dropdb_stmt.rs b/crates/pgls_pretty_print/src/nodes/dropdb_stmt.rs index a750e17b3..3c5b02773 100644 --- a/crates/pgls_pretty_print/src/nodes/dropdb_stmt.rs +++ b/crates/pgls_pretty_print/src/nodes/dropdb_stmt.rs @@ -22,7 +22,7 @@ pub(super) fn emit_dropdb_stmt(e: &mut EventEmitter, n: &DropdbStmt) { if !n.dbname.is_empty() { e.space(); - e.token(TokenKind::IDENT(n.dbname.clone())); + super::emit_identifier_maybe_quoted(e, &n.dbname); } // DROP DATABASE options like (FORCE) diff --git a/crates/pgls_pretty_print/src/nodes/execute_stmt.rs b/crates/pgls_pretty_print/src/nodes/execute_stmt.rs index 5b695f27a..ed1047908 100644 --- a/crates/pgls_pretty_print/src/nodes/execute_stmt.rs +++ b/crates/pgls_pretty_print/src/nodes/execute_stmt.rs @@ -20,7 +20,7 @@ fn emit_execute_stmt_impl(e: &mut EventEmitter, n: &ExecuteStmt, with_semicolon: e.token(TokenKind::EXECUTE_KW); e.space(); - e.token(TokenKind::IDENT(n.name.clone())); + super::emit_identifier_maybe_quoted(e, &n.name); if !n.params.is_empty() { e.line(LineType::SoftOrSpace); diff --git a/crates/pgls_pretty_print/src/nodes/fetch_stmt.rs b/crates/pgls_pretty_print/src/nodes/fetch_stmt.rs index 965468d75..14adf0bef 100644 --- a/crates/pgls_pretty_print/src/nodes/fetch_stmt.rs +++ b/crates/pgls_pretty_print/src/nodes/fetch_stmt.rs @@ -88,7 +88,7 @@ pub(super) fn emit_fetch_stmt(e: &mut EventEmitter, n: &FetchStmt) { e.line(LineType::SoftOrSpace); e.token(TokenKind::FROM_KW); e.space(); - e.token(TokenKind::IDENT(n.portalname.clone())); + super::emit_identifier_maybe_quoted(e, &n.portalname); } e.token(TokenKind::SEMICOLON); diff --git a/crates/pgls_pretty_print/src/nodes/import_foreign_schema_stmt.rs b/crates/pgls_pretty_print/src/nodes/import_foreign_schema_stmt.rs index 7b14814f0..9567a5ee9 100644 --- a/crates/pgls_pretty_print/src/nodes/import_foreign_schema_stmt.rs +++ b/crates/pgls_pretty_print/src/nodes/import_foreign_schema_stmt.rs @@ -16,7 +16,7 @@ pub(super) fn emit_import_foreign_schema_stmt(e: &mut EventEmitter, n: &ImportFo if !n.remote_schema.is_empty() { e.space(); - e.token(TokenKind::IDENT(n.remote_schema.clone())); + super::emit_identifier_maybe_quoted(e, &n.remote_schema); } // LIMIT TO / EXCEPT @@ -45,7 +45,7 @@ pub(super) fn emit_import_foreign_schema_stmt(e: &mut EventEmitter, n: &ImportFo e.space(); e.token(TokenKind::SERVER_KW); e.space(); - e.token(TokenKind::IDENT(n.server_name.clone())); + super::emit_identifier_maybe_quoted(e, &n.server_name); } // INTO schema @@ -53,7 +53,7 @@ pub(super) fn emit_import_foreign_schema_stmt(e: &mut EventEmitter, n: &ImportFo e.line(LineType::SoftOrSpace); e.token(TokenKind::INTO_KW); e.space(); - e.token(TokenKind::IDENT(n.local_schema.clone())); + super::emit_identifier_maybe_quoted(e, &n.local_schema); } // OPTIONS diff --git a/crates/pgls_pretty_print/src/nodes/index_elem.rs b/crates/pgls_pretty_print/src/nodes/index_elem.rs index d90d4893f..db7cdfce9 100644 --- a/crates/pgls_pretty_print/src/nodes/index_elem.rs +++ b/crates/pgls_pretty_print/src/nodes/index_elem.rs @@ -15,7 +15,7 @@ pub(super) fn emit_index_elem(e: &mut EventEmitter, n: &IndexElem) { super::emit_node(expr, e); e.token(TokenKind::R_PAREN); } else if !n.name.is_empty() { - e.token(TokenKind::IDENT(n.name.clone())); + super::emit_identifier_maybe_quoted(e, &n.name); } // Optional collation diff --git a/crates/pgls_pretty_print/src/nodes/index_stmt.rs b/crates/pgls_pretty_print/src/nodes/index_stmt.rs index 97ef08c47..a97ff7a32 100644 --- a/crates/pgls_pretty_print/src/nodes/index_stmt.rs +++ b/crates/pgls_pretty_print/src/nodes/index_stmt.rs @@ -57,7 +57,7 @@ pub(super) fn emit_index_stmt(e: &mut EventEmitter, n: &IndexStmt) { e.line(crate::emitter::LineType::SoftOrSpace); e.token(TokenKind::USING_KW); e.space(); - e.token(TokenKind::IDENT(n.access_method.clone())); + super::emit_identifier_maybe_quoted(e, &n.access_method); } // Index columns/expressions @@ -106,7 +106,7 @@ pub(super) fn emit_index_stmt(e: &mut EventEmitter, n: &IndexStmt) { e.line(crate::emitter::LineType::Hard); e.token(TokenKind::TABLESPACE_KW); e.space(); - e.token(TokenKind::IDENT(n.table_space.clone())); + super::emit_identifier_maybe_quoted(e, &n.table_space); } // WHERE clause (partial index) diff --git a/crates/pgls_pretty_print/src/nodes/listen_stmt.rs b/crates/pgls_pretty_print/src/nodes/listen_stmt.rs index b964e54bc..3c759063a 100644 --- a/crates/pgls_pretty_print/src/nodes/listen_stmt.rs +++ b/crates/pgls_pretty_print/src/nodes/listen_stmt.rs @@ -10,7 +10,7 @@ pub(super) fn emit_listen_stmt(e: &mut EventEmitter, n: &ListenStmt) { e.token(TokenKind::LISTEN_KW); e.space(); - e.token(TokenKind::IDENT(n.conditionname.clone())); + super::emit_identifier_maybe_quoted(e, &n.conditionname); e.token(TokenKind::SEMICOLON); diff --git a/crates/pgls_pretty_print/src/nodes/partition_elem.rs b/crates/pgls_pretty_print/src/nodes/partition_elem.rs index 5c7f481da..dcd018ba8 100644 --- a/crates/pgls_pretty_print/src/nodes/partition_elem.rs +++ b/crates/pgls_pretty_print/src/nodes/partition_elem.rs @@ -10,7 +10,7 @@ pub(super) fn emit_partition_elem(e: &mut EventEmitter, n: &PartitionElem) { // Emit column name if present if !n.name.is_empty() { - e.token(TokenKind::IDENT(n.name.clone())); + super::emit_identifier_maybe_quoted(e, &n.name); } else if let Some(ref expr) = n.expr { // Emit expression wrapped in parentheses (required by PostgreSQL syntax) e.token(TokenKind::L_PAREN); diff --git a/crates/pgls_pretty_print/src/nodes/prepare_stmt.rs b/crates/pgls_pretty_print/src/nodes/prepare_stmt.rs index b0b07ec84..a34d3af2e 100644 --- a/crates/pgls_pretty_print/src/nodes/prepare_stmt.rs +++ b/crates/pgls_pretty_print/src/nodes/prepare_stmt.rs @@ -14,7 +14,7 @@ pub(super) fn emit_prepare_stmt(e: &mut EventEmitter, n: &PrepareStmt) { // Statement name if !n.name.is_empty() { e.space(); - e.token(TokenKind::IDENT(n.name.clone())); + super::emit_identifier_maybe_quoted(e, &n.name); } // Argument types diff --git a/crates/pgls_pretty_print/src/nodes/publication_obj_spec.rs b/crates/pgls_pretty_print/src/nodes/publication_obj_spec.rs index d908b21d7..9c1380951 100644 --- a/crates/pgls_pretty_print/src/nodes/publication_obj_spec.rs +++ b/crates/pgls_pretty_print/src/nodes/publication_obj_spec.rs @@ -16,7 +16,7 @@ pub(super) fn emit_publication_obj_spec(e: &mut EventEmitter, n: &PublicationObj e.token(TokenKind::SCHEMA_KW); if !n.name.is_empty() { e.space(); - e.token(TokenKind::IDENT(n.name.clone())); + super::emit_identifier_maybe_quoted(e, &n.name); } } 3 => { diff --git a/crates/pgls_pretty_print/src/nodes/reindex_stmt.rs b/crates/pgls_pretty_print/src/nodes/reindex_stmt.rs index f45c08267..b39d219b5 100644 --- a/crates/pgls_pretty_print/src/nodes/reindex_stmt.rs +++ b/crates/pgls_pretty_print/src/nodes/reindex_stmt.rs @@ -55,7 +55,7 @@ pub(super) fn emit_reindex_stmt(e: &mut EventEmitter, n: &ReindexStmt) { if let Some(ref relation) = n.relation { super::emit_range_var(e, relation); } else if !n.name.is_empty() { - e.token(TokenKind::IDENT(n.name.clone())); + super::emit_identifier_maybe_quoted(e, &n.name); } e.token(TokenKind::SEMICOLON); diff --git a/crates/pgls_pretty_print/src/nodes/replica_identity_stmt.rs b/crates/pgls_pretty_print/src/nodes/replica_identity_stmt.rs index b8a0cd19f..6cce34ad8 100644 --- a/crates/pgls_pretty_print/src/nodes/replica_identity_stmt.rs +++ b/crates/pgls_pretty_print/src/nodes/replica_identity_stmt.rs @@ -31,7 +31,7 @@ pub(super) fn emit_replica_identity_stmt(e: &mut EventEmitter, n: &ReplicaIdenti e.token(TokenKind::INDEX_KW); if !n.name.is_empty() { e.line(LineType::SoftOrSpace); - e.token(TokenKind::IDENT(n.name.clone())); + super::emit_identifier_maybe_quoted(e, &n.name); } } _ => { diff --git a/crates/pgls_pretty_print/src/nodes/rule_stmt.rs b/crates/pgls_pretty_print/src/nodes/rule_stmt.rs index a194ab33b..684165106 100644 --- a/crates/pgls_pretty_print/src/nodes/rule_stmt.rs +++ b/crates/pgls_pretty_print/src/nodes/rule_stmt.rs @@ -22,7 +22,7 @@ pub(super) fn emit_rule_stmt(e: &mut EventEmitter, n: &RuleStmt) { e.space(); e.token(TokenKind::RULE_KW); e.space(); - e.token(TokenKind::IDENT(n.rulename.clone())); + super::emit_identifier_maybe_quoted(e, &n.rulename); e.line(LineType::Hard); e.token(TokenKind::AS_KW); diff --git a/crates/pgls_pretty_print/src/nodes/unlisten_stmt.rs b/crates/pgls_pretty_print/src/nodes/unlisten_stmt.rs index 72dba31b2..99b7b4302 100644 --- a/crates/pgls_pretty_print/src/nodes/unlisten_stmt.rs +++ b/crates/pgls_pretty_print/src/nodes/unlisten_stmt.rs @@ -14,7 +14,7 @@ pub(super) fn emit_unlisten_stmt(e: &mut EventEmitter, n: &UnlistenStmt) { if n.conditionname.is_empty() || n.conditionname == "*" { e.token(TokenKind::IDENT("*".to_string())); } else { - e.token(TokenKind::IDENT(n.conditionname.clone())); + super::emit_identifier_maybe_quoted(e, &n.conditionname); } e.token(TokenKind::SEMICOLON); diff --git a/crates/pgls_pretty_print/tests/data/multi/reserved_keyword_idents.sql b/crates/pgls_pretty_print/tests/data/multi/reserved_keyword_idents.sql new file mode 100644 index 000000000..0ed39ac72 --- /dev/null +++ b/crates/pgls_pretty_print/tests/data/multi/reserved_keyword_idents.sql @@ -0,0 +1,83 @@ +-- Regression coverage: identifiers that require quoting (reserved keywords like +-- "primary", or multi-word/mixed-case names) must keep their quotes through the +-- formatter. Each statement exercises a different emitter that previously emitted +-- the name as a bare token, producing invalid SQL. + +-- tables / columns / constraints / schema +CREATE TABLE "primary" (x int); +CREATE TABLE t1 ("primary" int); +CREATE TABLE t2 (x int CONSTRAINT "primary" CHECK (x > 0)); +ALTER TABLE t1 SET SCHEMA "primary"; + +-- view / sequence / domain / collation +CREATE VIEW "primary" AS SELECT 1; +CREATE SEQUENCE "primary"; +CREATE DOMAIN "primary" AS int; +CREATE COLLATION "primary" FROM "default"; + +-- index (index name, indexed column, tablespace) +CREATE INDEX "primary" ON t1 (x); +CREATE UNIQUE INDEX i1 ON t1 USING btree (x, "primary") TABLESPACE "primary" WHERE "primary"; +CLUSTER t1 USING "primary"; + +-- CTE / table alias / column alias +WITH "primary" AS (SELECT 1 AS a) SELECT * FROM "primary"; +SELECT * FROM t1 AS "primary"; +SELECT * FROM t1 "Mixed Case"; +SELECT * FROM (SELECT 1) AS x("primary"); + +-- trigger / event trigger / rule +CREATE TRIGGER "primary" BEFORE INSERT ON t1 FOR EACH ROW EXECUTE FUNCTION f(); +CREATE EVENT TRIGGER "primary" ON ddl_command_start EXECUTE FUNCTION f(); +ALTER EVENT TRIGGER "primary" ENABLE; +CREATE RULE "primary" AS ON INSERT TO t1 DO NOTHING; + +-- prepared statements / cursors / notifications +PREPARE "primary" AS SELECT 1; +EXECUTE "primary"; +DEALLOCATE "primary"; +LISTEN "primary"; +UNLISTEN "primary"; +NOTIFY "primary"; +CLOSE "primary"; +FETCH 1 FROM "primary"; + +-- extensions / publications +CREATE EXTENSION "primary"; +ALTER EXTENSION "primary" ADD TABLE t1; +CREATE PUBLICATION "primary"; +ALTER PUBLICATION "primary" ADD TABLE t1; + +-- foreign data wrappers / servers / user mappings / foreign tables +CREATE FOREIGN DATA WRAPPER "primary"; +CREATE USER MAPPING FOR u SERVER "primary"; +DROP USER MAPPING FOR u SERVER "primary"; +CREATE FOREIGN TABLE ft1 (x int) SERVER "primary"; +IMPORT FOREIGN SCHEMA "primary" FROM SERVER s INTO "select"; + +-- databases / roles / tablespaces +DROP DATABASE "primary"; +ALTER DATABASE "primary" SET work_mem = '1MB'; +ALTER ROLE r IN DATABASE "primary" SET work_mem = '1MB'; +DROP TABLESPACE "primary"; +ALTER TABLE ALL IN TABLESPACE "primary" SET TABLESPACE "select"; + +-- access methods / operator classes & families / exclusion constraints +CREATE INDEX i2 ON t1 USING "primary" (x); +CREATE ACCESS METHOD "primary" TYPE INDEX HANDLER h; +CREATE OPERATOR FAMILY of1 USING "primary"; +ALTER OPERATOR FAMILY of1 USING "primary" ADD OPERATOR 1 = (int, int); +CREATE OPERATOR CLASS oc1 FOR TYPE int USING "primary" AS OPERATOR 1 =; +ALTER TABLE t1 ADD CONSTRAINT e1 EXCLUDE USING "primary" (x WITH =); + +-- procedural languages / transforms / partitioning / replica identity / reindex +CREATE TRANSFORM FOR int LANGUAGE "primary" (FROM SQL WITH FUNCTION f(internal), TO SQL WITH FUNCTION g(int)); +CREATE TABLE t3 (x int) PARTITION BY LIST ("primary"); +ALTER TABLE t1 REPLICA IDENTITY USING INDEX "primary"; +REINDEX SCHEMA "primary"; +ALTER FUNCTION f() DEPENDS ON EXTENSION "primary"; +ALTER PUBLICATION p1 ADD TABLES IN SCHEMA "primary"; + +-- mixed-case identifiers (must keep quotes to preserve case) +REINDEX SCHEMA "MySchema"; +SELECT * FROM t1 AS "MyAlias" ("MyCol"); diff --git a/crates/pgls_pretty_print/tests/data/single/index_elem_reserved_keyword_0.sql b/crates/pgls_pretty_print/tests/data/single/index_elem_reserved_keyword_0.sql new file mode 100644 index 000000000..b5823b4aa --- /dev/null +++ b/crates/pgls_pretty_print/tests/data/single/index_elem_reserved_keyword_0.sql @@ -0,0 +1 @@ +CREATE UNIQUE INDEX index_user_emails_on_user_id_and_primary ON public.user_emails USING btree (user_id, "primary") WHERE "primary"; diff --git a/crates/pgls_pretty_print/tests/snapshots/multi/tests__reserved_keyword_idents_100.snap b/crates/pgls_pretty_print/tests/snapshots/multi/tests__reserved_keyword_idents_100.snap new file mode 100644 index 000000000..725d7bdd2 --- /dev/null +++ b/crates/pgls_pretty_print/tests/snapshots/multi/tests__reserved_keyword_idents_100.snap @@ -0,0 +1,133 @@ +--- +source: crates/pgls_pretty_print/tests/tests.rs +input_file: crates/pgls_pretty_print/tests/data/multi/reserved_keyword_idents.sql +--- +create table "primary" (x int); + +create table t1 ("primary" int); + +create table t2 (x int constraint "primary" check (x > 0)); + +alter table t1 set schema "primary"; + +create view "primary" +as select 1; + +create sequence "primary"; + +create domain "primary" as int; + +create collation "primary" from "default"; + +create index "primary" on t1 using btree (x); + +create unique index "i1" +on t1 +using btree +( + x, + "primary" +) +tablespace "primary" +where + "primary"; + +cluster t1 using "primary"; + +with "primary" as (select 1 as a) select * from "primary"; + +select * from t1 as "primary"; + +select * from t1 as "Mixed Case"; + +select * from (select 1) as x ("primary"); + +create trigger "primary" before insert on t1 for each row execute function f(); + +create event trigger "primary" on ddl_command_start execute function f(); + +alter event trigger "primary" enable; + +create rule "primary" +as on insert to t1 +do + nothing; + +prepare "primary" as select 1;; + +execute "primary"; + +deallocate "primary"; + +listen "primary"; + +unlisten "primary"; + +notify "primary"; + +close "primary"; + +fetch next from "primary"; + +create extension "primary"; + +alter extension "primary" add table t1; + +create publication "primary"; + +alter publication "primary" add table t1; + +create foreign data wrapper "primary"; + +create user mapping for u server "primary"; + +drop user mapping for u server "primary"; + +create foreign table ft1 ( x int ) server "primary"; + +import foreign schema "primary" from server s into "select"; + +drop database "primary"; + +alter database "primary" set work_mem = '1MB'; + +alter role r in database "primary" set work_mem = '1MB'; + +drop tablespace "primary"; + +alter table all in tablespace "primary" set tablespace "select"; + +create index "i2" on t1 using "primary" (x); + +create access method "primary" type index handler h; + +create operator family of1 using "primary"; + +alter operator family of1 using "primary" add operator 1 = (int, int); + +create operator class oc1 for type int using "primary" as operator 1 =; + +alter table t1 + add constraint "e1" exclude using "primary" (x with =); + +create transform for int language "primary" +( + from sql with function f(internal), + to sql with function g(int) +); + +create table t3 (x int) +partition by LIST("primary"); + +alter table t1 + replica identity using index "primary"; + +reindex schema "primary"; + +alter function f() depends on extension "primary"; + +alter publication p1 add tables in schema "primary"; + +reindex schema "MySchema"; + +select * from t1 as "MyAlias" ("MyCol"); diff --git a/crates/pgls_pretty_print/tests/snapshots/multi/tests__reserved_keyword_idents_80.snap b/crates/pgls_pretty_print/tests/snapshots/multi/tests__reserved_keyword_idents_80.snap new file mode 100644 index 000000000..725d7bdd2 --- /dev/null +++ b/crates/pgls_pretty_print/tests/snapshots/multi/tests__reserved_keyword_idents_80.snap @@ -0,0 +1,133 @@ +--- +source: crates/pgls_pretty_print/tests/tests.rs +input_file: crates/pgls_pretty_print/tests/data/multi/reserved_keyword_idents.sql +--- +create table "primary" (x int); + +create table t1 ("primary" int); + +create table t2 (x int constraint "primary" check (x > 0)); + +alter table t1 set schema "primary"; + +create view "primary" +as select 1; + +create sequence "primary"; + +create domain "primary" as int; + +create collation "primary" from "default"; + +create index "primary" on t1 using btree (x); + +create unique index "i1" +on t1 +using btree +( + x, + "primary" +) +tablespace "primary" +where + "primary"; + +cluster t1 using "primary"; + +with "primary" as (select 1 as a) select * from "primary"; + +select * from t1 as "primary"; + +select * from t1 as "Mixed Case"; + +select * from (select 1) as x ("primary"); + +create trigger "primary" before insert on t1 for each row execute function f(); + +create event trigger "primary" on ddl_command_start execute function f(); + +alter event trigger "primary" enable; + +create rule "primary" +as on insert to t1 +do + nothing; + +prepare "primary" as select 1;; + +execute "primary"; + +deallocate "primary"; + +listen "primary"; + +unlisten "primary"; + +notify "primary"; + +close "primary"; + +fetch next from "primary"; + +create extension "primary"; + +alter extension "primary" add table t1; + +create publication "primary"; + +alter publication "primary" add table t1; + +create foreign data wrapper "primary"; + +create user mapping for u server "primary"; + +drop user mapping for u server "primary"; + +create foreign table ft1 ( x int ) server "primary"; + +import foreign schema "primary" from server s into "select"; + +drop database "primary"; + +alter database "primary" set work_mem = '1MB'; + +alter role r in database "primary" set work_mem = '1MB'; + +drop tablespace "primary"; + +alter table all in tablespace "primary" set tablespace "select"; + +create index "i2" on t1 using "primary" (x); + +create access method "primary" type index handler h; + +create operator family of1 using "primary"; + +alter operator family of1 using "primary" add operator 1 = (int, int); + +create operator class oc1 for type int using "primary" as operator 1 =; + +alter table t1 + add constraint "e1" exclude using "primary" (x with =); + +create transform for int language "primary" +( + from sql with function f(internal), + to sql with function g(int) +); + +create table t3 (x int) +partition by LIST("primary"); + +alter table t1 + replica identity using index "primary"; + +reindex schema "primary"; + +alter function f() depends on extension "primary"; + +alter publication p1 add tables in schema "primary"; + +reindex schema "MySchema"; + +select * from t1 as "MyAlias" ("MyCol"); diff --git a/crates/pgls_pretty_print/tests/snapshots/single/tests__index_elem_reserved_keyword_0_100.snap b/crates/pgls_pretty_print/tests/snapshots/single/tests__index_elem_reserved_keyword_0_100.snap new file mode 100644 index 000000000..1cadc3cc7 --- /dev/null +++ b/crates/pgls_pretty_print/tests/snapshots/single/tests__index_elem_reserved_keyword_0_100.snap @@ -0,0 +1,14 @@ +--- +source: crates/pgls_pretty_print/tests/tests.rs +input_file: crates/pgls_pretty_print/tests/data/single/index_elem_reserved_keyword_0.sql +--- +create unique +index "index_user_emails_on_user_id_and_primary" +on public.user_emails +using btree +( + user_id, + "primary" +) +where + "primary"; diff --git a/crates/pgls_pretty_print/tests/snapshots/single/tests__index_elem_reserved_keyword_0_80.snap b/crates/pgls_pretty_print/tests/snapshots/single/tests__index_elem_reserved_keyword_0_80.snap new file mode 100644 index 000000000..1cadc3cc7 --- /dev/null +++ b/crates/pgls_pretty_print/tests/snapshots/single/tests__index_elem_reserved_keyword_0_80.snap @@ -0,0 +1,14 @@ +--- +source: crates/pgls_pretty_print/tests/tests.rs +input_file: crates/pgls_pretty_print/tests/data/single/index_elem_reserved_keyword_0.sql +--- +create unique +index "index_user_emails_on_user_id_and_primary" +on public.user_emails +using btree +( + user_id, + "primary" +) +where + "primary"; From 0cc65cb6c5d4c67d3420ee09fa81fadad66ebd9e Mon Sep 17 00:00:00 2001 From: Johannes Knopp Date: Wed, 3 Jun 2026 15:46:56 +0200 Subject: [PATCH 2/2] add further test cases and fixes for potentially quoted reserved keywords --- .../src/nodes/alter_domain_stmt.rs | 4 +- .../src/nodes/alter_table_stmt.rs | 60 +++++++++---------- .../nodes/alter_tablespace_options_stmt.rs | 2 +- .../pgls_pretty_print/src/nodes/column_def.rs | 2 +- .../src/nodes/create_plang_stmt.rs | 2 +- .../src/nodes/create_publication_stmt.rs | 2 +- .../src/nodes/create_stmt.rs | 2 +- .../src/nodes/create_table_as_stmt.rs | 4 +- .../src/nodes/create_trig_stmt.rs | 2 +- .../src/nodes/current_of_expr.rs | 2 +- .../src/nodes/drop_subscription_stmt.rs | 2 +- .../pgls_pretty_print/src/nodes/json_expr.rs | 2 +- .../data/multi/reserved_keyword_idents.sql | 13 ++++ .../multi/tests__publication_100.snap | 6 +- .../multi/tests__publication_80.snap | 6 +- .../tests__reserved_keyword_idents_100.snap | 31 ++++++++++ .../tests__reserved_keyword_idents_80.snap | 31 ++++++++++ 17 files changed, 124 insertions(+), 49 deletions(-) diff --git a/crates/pgls_pretty_print/src/nodes/alter_domain_stmt.rs b/crates/pgls_pretty_print/src/nodes/alter_domain_stmt.rs index d3336c283..36b278e5d 100644 --- a/crates/pgls_pretty_print/src/nodes/alter_domain_stmt.rs +++ b/crates/pgls_pretty_print/src/nodes/alter_domain_stmt.rs @@ -72,7 +72,7 @@ pub(super) fn emit_alter_domain_stmt(e: &mut EventEmitter, n: &AlterDomainStmt) } if !n.name.is_empty() { e.space(); - e.token(TokenKind::IDENT(n.name.clone())); + super::emit_identifier_maybe_quoted(e, &n.name); } // behavior: 0=Undefined, 1=DropRestrict, 2=DropCascade // Only emit CASCADE explicitly; RESTRICT is the default @@ -87,7 +87,7 @@ pub(super) fn emit_alter_domain_stmt(e: &mut EventEmitter, n: &AlterDomainStmt) e.token(TokenKind::CONSTRAINT_KW); if !n.name.is_empty() { e.space(); - e.token(TokenKind::IDENT(n.name.clone())); + super::emit_identifier_maybe_quoted(e, &n.name); } } _ => { diff --git a/crates/pgls_pretty_print/src/nodes/alter_table_stmt.rs b/crates/pgls_pretty_print/src/nodes/alter_table_stmt.rs index 42982f9d5..f28b039fb 100644 --- a/crates/pgls_pretty_print/src/nodes/alter_table_stmt.rs +++ b/crates/pgls_pretty_print/src/nodes/alter_table_stmt.rs @@ -127,7 +127,7 @@ fn emit_alter_table_cmd_impl(e: &mut EventEmitter, cmd: &AlterTableCmd, for_type } if !cmd.name.is_empty() { e.space(); - e.token(TokenKind::IDENT(cmd.name.clone())); + super::emit_identifier_maybe_quoted(e, &cmd.name); } if matches!(cmd.behavior(), DropBehavior::DropCascade) { e.space(); @@ -145,7 +145,7 @@ fn emit_alter_table_cmd_impl(e: &mut EventEmitter, cmd: &AlterTableCmd, for_type } if !cmd.name.is_empty() { e.space(); - e.token(TokenKind::IDENT(cmd.name.clone())); + super::emit_identifier_maybe_quoted(e, &cmd.name); } e.space(); e.token(TokenKind::TYPE_KW); @@ -164,7 +164,7 @@ fn emit_alter_table_cmd_impl(e: &mut EventEmitter, cmd: &AlterTableCmd, for_type e.space(); e.token(TokenKind::COMPRESSION_KW); e.space(); - e.token(TokenKind::IDENT(column_def.compression.clone())); + super::emit_identifier_maybe_quoted(e, &column_def.compression); } // Emit storage clause if specified @@ -195,7 +195,7 @@ fn emit_alter_table_cmd_impl(e: &mut EventEmitter, cmd: &AlterTableCmd, for_type e.token(TokenKind::COLUMN_KW); if !cmd.name.is_empty() { e.space(); - e.token(TokenKind::IDENT(cmd.name.clone())); + super::emit_identifier_maybe_quoted(e, &cmd.name); } e.space(); if let Some(ref def) = cmd.def { @@ -216,7 +216,7 @@ fn emit_alter_table_cmd_impl(e: &mut EventEmitter, cmd: &AlterTableCmd, for_type e.token(TokenKind::COLUMN_KW); if !cmd.name.is_empty() { e.space(); - e.token(TokenKind::IDENT(cmd.name.clone())); + super::emit_identifier_maybe_quoted(e, &cmd.name); } e.space(); e.token(TokenKind::SET_KW); @@ -231,7 +231,7 @@ fn emit_alter_table_cmd_impl(e: &mut EventEmitter, cmd: &AlterTableCmd, for_type e.token(TokenKind::COLUMN_KW); if !cmd.name.is_empty() { e.space(); - e.token(TokenKind::IDENT(cmd.name.clone())); + super::emit_identifier_maybe_quoted(e, &cmd.name); } e.space(); e.token(TokenKind::DROP_KW); @@ -247,7 +247,7 @@ fn emit_alter_table_cmd_impl(e: &mut EventEmitter, cmd: &AlterTableCmd, for_type e.token(TokenKind::COLUMN_KW); if !cmd.name.is_empty() { e.space(); - e.token(TokenKind::IDENT(cmd.name.clone())); + super::emit_identifier_maybe_quoted(e, &cmd.name); } e.space(); e.token(TokenKind::SET_KW); @@ -269,7 +269,7 @@ fn emit_alter_table_cmd_impl(e: &mut EventEmitter, cmd: &AlterTableCmd, for_type e.token(TokenKind::COLUMN_KW); if !cmd.name.is_empty() { e.space(); - e.token(TokenKind::IDENT(cmd.name.clone())); + super::emit_identifier_maybe_quoted(e, &cmd.name); } e.space(); e.token(TokenKind::DROP_KW); @@ -301,7 +301,7 @@ fn emit_alter_table_cmd_impl(e: &mut EventEmitter, cmd: &AlterTableCmd, for_type } if !cmd.name.is_empty() { e.space(); - e.token(TokenKind::IDENT(cmd.name.clone())); + super::emit_identifier_maybe_quoted(e, &cmd.name); } // behavior: 0=Undefined, 1=DropRestrict, 2=DropCascade if cmd.behavior == 2 { @@ -315,7 +315,7 @@ fn emit_alter_table_cmd_impl(e: &mut EventEmitter, cmd: &AlterTableCmd, for_type e.token(TokenKind::CONSTRAINT_KW); if !cmd.name.is_empty() { e.space(); - e.token(TokenKind::IDENT(cmd.name.clone())); + super::emit_identifier_maybe_quoted(e, &cmd.name); } } AlterTableType::AtSetTableSpace => { @@ -324,7 +324,7 @@ fn emit_alter_table_cmd_impl(e: &mut EventEmitter, cmd: &AlterTableCmd, for_type e.token(TokenKind::TABLESPACE_KW); if !cmd.name.is_empty() { e.space(); - e.token(TokenKind::IDENT(cmd.name.clone())); + super::emit_identifier_maybe_quoted(e, &cmd.name); } } AlterTableType::AtChangeOwner => { @@ -342,7 +342,7 @@ fn emit_alter_table_cmd_impl(e: &mut EventEmitter, cmd: &AlterTableCmd, for_type e.token(TokenKind::TRIGGER_KW); if !cmd.name.is_empty() { e.space(); - e.token(TokenKind::IDENT(cmd.name.clone())); + super::emit_identifier_maybe_quoted(e, &cmd.name); } } AlterTableType::AtDisableTrig => { @@ -351,7 +351,7 @@ fn emit_alter_table_cmd_impl(e: &mut EventEmitter, cmd: &AlterTableCmd, for_type e.token(TokenKind::TRIGGER_KW); if !cmd.name.is_empty() { e.space(); - e.token(TokenKind::IDENT(cmd.name.clone())); + super::emit_identifier_maybe_quoted(e, &cmd.name); } } AlterTableType::AtSetLogged => { @@ -395,7 +395,7 @@ fn emit_alter_table_cmd_impl(e: &mut EventEmitter, cmd: &AlterTableCmd, for_type e.token(TokenKind::COLUMN_KW); if !cmd.name.is_empty() { e.space(); - e.token(TokenKind::IDENT(cmd.name.clone())); + super::emit_identifier_maybe_quoted(e, &cmd.name); } e.space(); e.token(TokenKind::SET_KW); @@ -413,7 +413,7 @@ fn emit_alter_table_cmd_impl(e: &mut EventEmitter, cmd: &AlterTableCmd, for_type e.token(TokenKind::COLUMN_KW); if !cmd.name.is_empty() { e.space(); - e.token(TokenKind::IDENT(cmd.name.clone())); + super::emit_identifier_maybe_quoted(e, &cmd.name); } e.space(); e.token(TokenKind::RESET_KW); @@ -431,7 +431,7 @@ fn emit_alter_table_cmd_impl(e: &mut EventEmitter, cmd: &AlterTableCmd, for_type e.token(TokenKind::COLUMN_KW); if !cmd.name.is_empty() { e.space(); - e.token(TokenKind::IDENT(cmd.name.clone())); + super::emit_identifier_maybe_quoted(e, &cmd.name); } else if cmd.num != 0 { // Column specified by number (for indexes) e.space(); @@ -453,7 +453,7 @@ fn emit_alter_table_cmd_impl(e: &mut EventEmitter, cmd: &AlterTableCmd, for_type e.token(TokenKind::COLUMN_KW); if !cmd.name.is_empty() { e.space(); - e.token(TokenKind::IDENT(cmd.name.clone())); + super::emit_identifier_maybe_quoted(e, &cmd.name); } e.space(); e.token(TokenKind::SET_KW); @@ -471,7 +471,7 @@ fn emit_alter_table_cmd_impl(e: &mut EventEmitter, cmd: &AlterTableCmd, for_type e.token(TokenKind::COLUMN_KW); if !cmd.name.is_empty() { e.space(); - e.token(TokenKind::IDENT(cmd.name.clone())); + super::emit_identifier_maybe_quoted(e, &cmd.name); } e.space(); e.token(TokenKind::SET_KW); @@ -488,7 +488,7 @@ fn emit_alter_table_cmd_impl(e: &mut EventEmitter, cmd: &AlterTableCmd, for_type e.token(TokenKind::ON_KW); if !cmd.name.is_empty() { e.space(); - e.token(TokenKind::IDENT(cmd.name.clone())); + super::emit_identifier_maybe_quoted(e, &cmd.name); } } AlterTableType::AtDropCluster => { @@ -506,7 +506,7 @@ fn emit_alter_table_cmd_impl(e: &mut EventEmitter, cmd: &AlterTableCmd, for_type e.token(TokenKind::METHOD_KW); e.space(); if !cmd.name.is_empty() { - e.token(TokenKind::IDENT(cmd.name.clone())); + super::emit_identifier_maybe_quoted(e, &cmd.name); } else { // Empty name means DEFAULT e.token(TokenKind::DEFAULT_KW); @@ -632,7 +632,7 @@ fn emit_alter_table_cmd_impl(e: &mut EventEmitter, cmd: &AlterTableCmd, for_type e.token(TokenKind::TRIGGER_KW); if !cmd.name.is_empty() { e.space(); - e.token(TokenKind::IDENT(cmd.name.clone())); + super::emit_identifier_maybe_quoted(e, &cmd.name); } } AlterTableType::AtEnableReplicaTrig => { @@ -643,7 +643,7 @@ fn emit_alter_table_cmd_impl(e: &mut EventEmitter, cmd: &AlterTableCmd, for_type e.token(TokenKind::TRIGGER_KW); if !cmd.name.is_empty() { e.space(); - e.token(TokenKind::IDENT(cmd.name.clone())); + super::emit_identifier_maybe_quoted(e, &cmd.name); } } AlterTableType::AtEnableRule => { @@ -652,7 +652,7 @@ fn emit_alter_table_cmd_impl(e: &mut EventEmitter, cmd: &AlterTableCmd, for_type e.token(TokenKind::RULE_KW); if !cmd.name.is_empty() { e.space(); - e.token(TokenKind::IDENT(cmd.name.clone())); + super::emit_identifier_maybe_quoted(e, &cmd.name); } } AlterTableType::AtDisableRule => { @@ -661,7 +661,7 @@ fn emit_alter_table_cmd_impl(e: &mut EventEmitter, cmd: &AlterTableCmd, for_type e.token(TokenKind::RULE_KW); if !cmd.name.is_empty() { e.space(); - e.token(TokenKind::IDENT(cmd.name.clone())); + super::emit_identifier_maybe_quoted(e, &cmd.name); } } AlterTableType::AtEnableAlwaysRule => { @@ -672,7 +672,7 @@ fn emit_alter_table_cmd_impl(e: &mut EventEmitter, cmd: &AlterTableCmd, for_type e.token(TokenKind::RULE_KW); if !cmd.name.is_empty() { e.space(); - e.token(TokenKind::IDENT(cmd.name.clone())); + super::emit_identifier_maybe_quoted(e, &cmd.name); } } AlterTableType::AtEnableReplicaRule => { @@ -683,7 +683,7 @@ fn emit_alter_table_cmd_impl(e: &mut EventEmitter, cmd: &AlterTableCmd, for_type e.token(TokenKind::RULE_KW); if !cmd.name.is_empty() { e.space(); - e.token(TokenKind::IDENT(cmd.name.clone())); + super::emit_identifier_maybe_quoted(e, &cmd.name); } } AlterTableType::AtAddIdentity => { @@ -694,7 +694,7 @@ fn emit_alter_table_cmd_impl(e: &mut EventEmitter, cmd: &AlterTableCmd, for_type e.token(TokenKind::COLUMN_KW); if !cmd.name.is_empty() { e.space(); - e.token(TokenKind::IDENT(cmd.name.clone())); + super::emit_identifier_maybe_quoted(e, &cmd.name); } e.line(LineType::SoftOrSpace); e.token(TokenKind::ADD_KW); @@ -712,7 +712,7 @@ fn emit_alter_table_cmd_impl(e: &mut EventEmitter, cmd: &AlterTableCmd, for_type e.token(TokenKind::COLUMN_KW); if !cmd.name.is_empty() { e.space(); - e.token(TokenKind::IDENT(cmd.name.clone())); + super::emit_identifier_maybe_quoted(e, &cmd.name); } e.space(); e.token(TokenKind::SET_KW); @@ -756,7 +756,7 @@ fn emit_alter_table_cmd_impl(e: &mut EventEmitter, cmd: &AlterTableCmd, for_type e.token(TokenKind::COLUMN_KW); if !cmd.name.is_empty() { e.space(); - e.token(TokenKind::IDENT(cmd.name.clone())); + super::emit_identifier_maybe_quoted(e, &cmd.name); } e.space(); e.token(TokenKind::DROP_KW); @@ -822,7 +822,7 @@ fn emit_alter_table_cmd_impl(e: &mut EventEmitter, cmd: &AlterTableCmd, for_type e.token(TokenKind::COLUMN_KW); if !cmd.name.is_empty() { e.space(); - e.token(TokenKind::IDENT(cmd.name.clone())); + super::emit_identifier_maybe_quoted(e, &cmd.name); } e.space(); e.token(TokenKind::OPTIONS_KW); diff --git a/crates/pgls_pretty_print/src/nodes/alter_tablespace_options_stmt.rs b/crates/pgls_pretty_print/src/nodes/alter_tablespace_options_stmt.rs index 6a3679463..a84929696 100644 --- a/crates/pgls_pretty_print/src/nodes/alter_tablespace_options_stmt.rs +++ b/crates/pgls_pretty_print/src/nodes/alter_tablespace_options_stmt.rs @@ -15,7 +15,7 @@ pub(super) fn emit_alter_tablespace_options_stmt( e.space(); e.token(TokenKind::TABLESPACE_KW); e.space(); - e.token(TokenKind::IDENT(n.tablespacename.clone())); + super::emit_identifier_maybe_quoted(e, &n.tablespacename); e.line(LineType::SoftOrSpace); if n.is_reset { diff --git a/crates/pgls_pretty_print/src/nodes/column_def.rs b/crates/pgls_pretty_print/src/nodes/column_def.rs index 380afba33..bad3564be 100644 --- a/crates/pgls_pretty_print/src/nodes/column_def.rs +++ b/crates/pgls_pretty_print/src/nodes/column_def.rs @@ -22,7 +22,7 @@ pub(super) fn emit_column_def(e: &mut EventEmitter, n: &ColumnDef) { e.space(); e.token(TokenKind::COMPRESSION_KW); e.space(); - e.token(TokenKind::IDENT(n.compression.clone())); + super::emit_identifier_maybe_quoted(e, &n.compression); } // Add storage clause if specified diff --git a/crates/pgls_pretty_print/src/nodes/create_plang_stmt.rs b/crates/pgls_pretty_print/src/nodes/create_plang_stmt.rs index bdca31fbf..cac1559a7 100644 --- a/crates/pgls_pretty_print/src/nodes/create_plang_stmt.rs +++ b/crates/pgls_pretty_print/src/nodes/create_plang_stmt.rs @@ -25,7 +25,7 @@ pub(super) fn emit_create_plang_stmt(e: &mut EventEmitter, n: &CreatePLangStmt) e.token(TokenKind::LANGUAGE_KW); e.space(); - e.token(TokenKind::IDENT(n.plname.clone())); + super::emit_identifier_maybe_quoted(e, &n.plname); if !n.plhandler.is_empty() { e.space(); diff --git a/crates/pgls_pretty_print/src/nodes/create_publication_stmt.rs b/crates/pgls_pretty_print/src/nodes/create_publication_stmt.rs index 058a28cec..d132f45dc 100644 --- a/crates/pgls_pretty_print/src/nodes/create_publication_stmt.rs +++ b/crates/pgls_pretty_print/src/nodes/create_publication_stmt.rs @@ -66,7 +66,7 @@ pub(super) fn emit_create_publication_stmt(e: &mut EventEmitter, n: &CreatePubli e.token(TokenKind::SCHEMA_KW); e.space(); if !obj.name.is_empty() { - e.token(TokenKind::IDENT(obj.name.clone())); + super::emit_identifier_maybe_quoted(e, &obj.name); } } 3 => { diff --git a/crates/pgls_pretty_print/src/nodes/create_stmt.rs b/crates/pgls_pretty_print/src/nodes/create_stmt.rs index 54f95227a..c412faee2 100644 --- a/crates/pgls_pretty_print/src/nodes/create_stmt.rs +++ b/crates/pgls_pretty_print/src/nodes/create_stmt.rs @@ -296,7 +296,7 @@ pub(super) fn emit_create_stmt(e: &mut EventEmitter, n: &CreateStmt) { e.line(LineType::SoftOrSpace); e.token(TokenKind::TABLESPACE_KW); e.space(); - e.token(TokenKind::IDENT(n.tablespacename.clone())); + super::emit_identifier_maybe_quoted(e, &n.tablespacename); } e.token(TokenKind::SEMICOLON); diff --git a/crates/pgls_pretty_print/src/nodes/create_table_as_stmt.rs b/crates/pgls_pretty_print/src/nodes/create_table_as_stmt.rs index e5ecdf5c1..a521d708b 100644 --- a/crates/pgls_pretty_print/src/nodes/create_table_as_stmt.rs +++ b/crates/pgls_pretty_print/src/nodes/create_table_as_stmt.rs @@ -73,7 +73,7 @@ pub(super) fn emit_create_table_as_stmt(e: &mut EventEmitter, n: &CreateTableAsS e.space(); e.token(TokenKind::USING_KW); e.space(); - e.token(TokenKind::IDENT(into.access_method.clone())); + super::emit_identifier_maybe_quoted(e, &into.access_method); } // WITH (options) - like fillfactor @@ -140,7 +140,7 @@ pub(super) fn emit_create_table_as_stmt(e: &mut EventEmitter, n: &CreateTableAsS e.line(LineType::SoftOrSpace); e.token(TokenKind::TABLESPACE_KW); e.space(); - e.token(TokenKind::IDENT(into.table_space_name.clone())); + super::emit_identifier_maybe_quoted(e, &into.table_space_name); } } diff --git a/crates/pgls_pretty_print/src/nodes/create_trig_stmt.rs b/crates/pgls_pretty_print/src/nodes/create_trig_stmt.rs index 2d96e35a1..08d4c3ee1 100644 --- a/crates/pgls_pretty_print/src/nodes/create_trig_stmt.rs +++ b/crates/pgls_pretty_print/src/nodes/create_trig_stmt.rs @@ -184,6 +184,6 @@ fn emit_trigger_transitions(e: &mut EventEmitter, rels: &[pgls_query::Node]) { e.space(); e.token(TokenKind::AS_KW); e.space(); - e.token(TokenKind::IDENT(transition.name.clone())); + super::emit_identifier_maybe_quoted(e, &transition.name); }); } diff --git a/crates/pgls_pretty_print/src/nodes/current_of_expr.rs b/crates/pgls_pretty_print/src/nodes/current_of_expr.rs index 581b4b9ee..ca47237e5 100644 --- a/crates/pgls_pretty_print/src/nodes/current_of_expr.rs +++ b/crates/pgls_pretty_print/src/nodes/current_of_expr.rs @@ -14,7 +14,7 @@ pub(super) fn emit_current_of_expr(e: &mut EventEmitter, n: &CurrentOfExpr) { if !n.cursor_name.is_empty() { e.space(); - e.token(TokenKind::IDENT(n.cursor_name.clone())); + super::emit_identifier_maybe_quoted(e, &n.cursor_name); } e.group_end(); diff --git a/crates/pgls_pretty_print/src/nodes/drop_subscription_stmt.rs b/crates/pgls_pretty_print/src/nodes/drop_subscription_stmt.rs index b0c504719..c73b3afbe 100644 --- a/crates/pgls_pretty_print/src/nodes/drop_subscription_stmt.rs +++ b/crates/pgls_pretty_print/src/nodes/drop_subscription_stmt.rs @@ -21,7 +21,7 @@ pub(super) fn emit_drop_subscription_stmt(e: &mut EventEmitter, n: &DropSubscrip if !n.subname.is_empty() { e.space(); - e.token(TokenKind::IDENT(n.subname.clone())); + super::emit_identifier_maybe_quoted(e, &n.subname); } // Add CASCADE or RESTRICT if specified diff --git a/crates/pgls_pretty_print/src/nodes/json_expr.rs b/crates/pgls_pretty_print/src/nodes/json_expr.rs index 084b8a4a1..1ee6ce974 100644 --- a/crates/pgls_pretty_print/src/nodes/json_expr.rs +++ b/crates/pgls_pretty_print/src/nodes/json_expr.rs @@ -37,7 +37,7 @@ pub(super) fn emit_json_expr(e: &mut EventEmitter, n: &JsonExpr) { e.token(TokenKind::COMMA); e.space(); } - e.token(TokenKind::IDENT(n.column_name.clone())); + super::emit_identifier_maybe_quoted(e, &n.column_name); wrote_value = true; } diff --git a/crates/pgls_pretty_print/tests/data/multi/reserved_keyword_idents.sql b/crates/pgls_pretty_print/tests/data/multi/reserved_keyword_idents.sql index 0ed39ac72..62d3e4069 100644 --- a/crates/pgls_pretty_print/tests/data/multi/reserved_keyword_idents.sql +++ b/crates/pgls_pretty_print/tests/data/multi/reserved_keyword_idents.sql @@ -81,3 +81,16 @@ ALTER PUBLICATION p1 ADD TABLES IN SCHEMA "primary"; -- mixed-case identifiers (must keep quotes to preserve case) REINDEX SCHEMA "MySchema"; SELECT * FROM t1 AS "MyAlias" ("MyCol"); + +ALTER TABLE t1 DROP COLUMN "primary"; +ALTER TABLE t1 ALTER COLUMN "primary" SET NOT NULL; +ALTER DOMAIN dom DROP CONSTRAINT "primary"; +ALTER TABLESPACE "primary" SET (seq_page_cost = 1.0); +CREATE TABLE t1 (c text COMPRESSION "primary"); +CREATE PUBLICATION p1 FOR TABLES IN SCHEMA "primary"; +CREATE TABLE t1 (x int) TABLESPACE "primary"; +CREATE TABLE t1 USING "primary" AS SELECT 1 AS a; +CREATE TABLE t2 TABLESPACE "primary" AS SELECT 1 AS a; +CREATE TRIGGER tr1 AFTER UPDATE ON t1 REFERENCING OLD TABLE AS "primary" FOR EACH STATEMENT EXECUTE FUNCTION f(); +UPDATE t1 SET x = 1 WHERE CURRENT OF "primary"; +DROP SUBSCRIPTION "primary"; diff --git a/crates/pgls_pretty_print/tests/snapshots/multi/tests__publication_100.snap b/crates/pgls_pretty_print/tests/snapshots/multi/tests__publication_100.snap index df5c75958..8ad38b88d 100644 --- a/crates/pgls_pretty_print/tests/snapshots/multi/tests__publication_100.snap +++ b/crates/pgls_pretty_print/tests/snapshots/multi/tests__publication_100.snap @@ -1280,14 +1280,14 @@ tables in schema pub_test3; create publication testpub3_forschema for tables in schema current_schema; -create publication testpub4_forschema for tables in schema CURRENT_SCHEMA; +create publication testpub4_forschema for tables in schema "CURRENT_SCHEMA"; create publication testpub5_forschema for tables in schema current_schema, -tables in schema CURRENT_SCHEMA; +tables in schema "CURRENT_SCHEMA"; create publication testpub6_forschema -for tables in schema CURRENT_SCHEMA, +for tables in schema "CURRENT_SCHEMA", tables in schema current_schema; create publication testpub_fortable for table "CURRENT_SCHEMA"."CURRENT_SCHEMA"; diff --git a/crates/pgls_pretty_print/tests/snapshots/multi/tests__publication_80.snap b/crates/pgls_pretty_print/tests/snapshots/multi/tests__publication_80.snap index 656ea8f95..5ceb35a11 100644 --- a/crates/pgls_pretty_print/tests/snapshots/multi/tests__publication_80.snap +++ b/crates/pgls_pretty_print/tests/snapshots/multi/tests__publication_80.snap @@ -1396,14 +1396,14 @@ tables in schema pub_test3; create publication testpub3_forschema for tables in schema current_schema; -create publication testpub4_forschema for tables in schema CURRENT_SCHEMA; +create publication testpub4_forschema for tables in schema "CURRENT_SCHEMA"; create publication testpub5_forschema for tables in schema current_schema, -tables in schema CURRENT_SCHEMA; +tables in schema "CURRENT_SCHEMA"; create publication testpub6_forschema -for tables in schema CURRENT_SCHEMA, +for tables in schema "CURRENT_SCHEMA", tables in schema current_schema; create publication testpub_fortable for table "CURRENT_SCHEMA"."CURRENT_SCHEMA"; diff --git a/crates/pgls_pretty_print/tests/snapshots/multi/tests__reserved_keyword_idents_100.snap b/crates/pgls_pretty_print/tests/snapshots/multi/tests__reserved_keyword_idents_100.snap index 725d7bdd2..18de13a20 100644 --- a/crates/pgls_pretty_print/tests/snapshots/multi/tests__reserved_keyword_idents_100.snap +++ b/crates/pgls_pretty_print/tests/snapshots/multi/tests__reserved_keyword_idents_100.snap @@ -131,3 +131,34 @@ alter publication p1 add tables in schema "primary"; reindex schema "MySchema"; select * from t1 as "MyAlias" ("MyCol"); + +alter table t1 + drop column "primary"; + +alter table t1 + alter column "primary" set not null; + +alter domain dom drop constraint "primary"; + +alter tablespace "primary" set (seq_page_cost = 1.0); + +create table t1 (c text compression "primary"); + +create publication p1 for tables in schema "primary"; + +create table t1 (x int) tablespace "primary"; + +create table t1 using "primary" as select 1 as a; + +create table t2 tablespace "primary" as select 1 as a; + +create trigger tr1 +after update +on t1 +referencing old table as "primary" +for each statement +execute function f(); + +update t1 set x = 1 where current of "primary"; + +drop subscription "primary" restrict; diff --git a/crates/pgls_pretty_print/tests/snapshots/multi/tests__reserved_keyword_idents_80.snap b/crates/pgls_pretty_print/tests/snapshots/multi/tests__reserved_keyword_idents_80.snap index 725d7bdd2..18de13a20 100644 --- a/crates/pgls_pretty_print/tests/snapshots/multi/tests__reserved_keyword_idents_80.snap +++ b/crates/pgls_pretty_print/tests/snapshots/multi/tests__reserved_keyword_idents_80.snap @@ -131,3 +131,34 @@ alter publication p1 add tables in schema "primary"; reindex schema "MySchema"; select * from t1 as "MyAlias" ("MyCol"); + +alter table t1 + drop column "primary"; + +alter table t1 + alter column "primary" set not null; + +alter domain dom drop constraint "primary"; + +alter tablespace "primary" set (seq_page_cost = 1.0); + +create table t1 (c text compression "primary"); + +create publication p1 for tables in schema "primary"; + +create table t1 (x int) tablespace "primary"; + +create table t1 using "primary" as select 1 as a; + +create table t2 tablespace "primary" as select 1 as a; + +create trigger tr1 +after update +on t1 +referencing old table as "primary" +for each statement +execute function f(); + +update t1 set x = 1 where current of "primary"; + +drop subscription "primary" restrict;