1- use pgt_schema_cache:: SchemaCache ;
2- use pgt_treesitter:: { TreesitterContext , WrappingClause } ;
1+ use pgt_schema_cache:: { Column , SchemaCache } ;
2+ use pgt_treesitter:: TreesitterContext ;
33
44use crate :: {
5- CompletionItemKind ,
5+ CompletionItemKind , CompletionText ,
66 builder:: { CompletionBuilder , PossibleCompletionItem } ,
7+ providers:: helper:: { get_range_to_replace, with_closed_quote} ,
78 relevance:: { CompletionRelevanceData , filtering:: CompletionFilter , scoring:: CompletionScore } ,
89} ;
910
10- use super :: helper:: { find_matching_alias_for_table, get_completion_text_with_schema_or_alias } ;
11+ use super :: helper:: { find_matching_alias_for_table, with_schema_or_alias } ;
1112
1213pub fn complete_columns < ' a > (
1314 ctx : & TreesitterContext < ' a > ,
@@ -19,33 +20,34 @@ pub fn complete_columns<'a>(
1920 for col in available_columns {
2021 let relevance = CompletionRelevanceData :: Column ( col) ;
2122
22- let mut item = PossibleCompletionItem {
23+ let item = PossibleCompletionItem {
2324 label : col. name . clone ( ) ,
2425 score : CompletionScore :: from ( relevance. clone ( ) ) ,
2526 filter : CompletionFilter :: from ( relevance) ,
2627 description : format ! ( "{}.{}" , col. schema_name, col. table_name) ,
2728 kind : CompletionItemKind :: Column ,
28- completion_text : None ,
29+ completion_text : Some ( get_completion_text ( ctx , col ) ) ,
2930 detail : col. type_name . as_ref ( ) . map ( |t| t. to_string ( ) ) ,
3031 } ;
3132
32- // autocomplete with the alias in a join clause if we find one
33- if matches ! (
34- ctx. wrapping_clause_type,
35- Some ( WrappingClause :: Join { .. } )
36- | Some ( WrappingClause :: Where )
37- | Some ( WrappingClause :: Select )
38- ) {
39- item. completion_text = find_matching_alias_for_table ( ctx, col. table_name . as_str ( ) )
40- . and_then ( |alias| {
41- get_completion_text_with_schema_or_alias ( ctx, col. name . as_str ( ) , alias. as_str ( ) )
42- } ) ;
43- }
44-
4533 builder. add_item ( item) ;
4634 }
4735}
4836
37+ fn get_completion_text ( ctx : & TreesitterContext , col : & Column ) -> CompletionText {
38+ let range = get_range_to_replace ( ctx) ;
39+ let col_name = with_closed_quote ( ctx, col. name . as_str ( ) ) ;
40+ let alias = find_matching_alias_for_table ( ctx, col. table_name . as_str ( ) ) ;
41+ let with_schema_or_alias =
42+ with_schema_or_alias ( ctx, col_name. as_str ( ) , alias. as_ref ( ) . map ( |s| s. as_str ( ) ) ) ;
43+
44+ CompletionText {
45+ is_snippet : false ,
46+ range,
47+ text : with_schema_or_alias,
48+ }
49+ }
50+
4951#[ cfg( test) ]
5052mod tests {
5153 use std:: vec;
@@ -932,4 +934,89 @@ mod tests {
932934 . await ;
933935 }
934936 }
937+
938+ #[ sqlx:: test( migrator = "pgt_test_utils::MIGRATIONS" ) ]
939+ async fn completes_quoted_columns ( pool : PgPool ) {
940+ let setup = r#"
941+ create schema if not exists auth;
942+ drop table if exists auth.quote_test_users;
943+
944+ create table auth.quote_test_users (
945+ id serial primary key,
946+ email text unique not null,
947+ name text not null,
948+ "quoted_column" text
949+ );
950+ "# ;
951+
952+ pool. execute ( setup) . await . unwrap ( ) ;
953+
954+ // test completion inside quoted column name
955+ assert_complete_results (
956+ format ! (
957+ r#"select "em{}" from "auth"."quote_test_users""# ,
958+ QueryWithCursorPosition :: cursor_marker( )
959+ )
960+ . as_str ( ) ,
961+ vec ! [ CompletionAssertion :: LabelAndDesc (
962+ "email" . to_string( ) ,
963+ "auth.quote_test_users" . to_string( ) ,
964+ ) ] ,
965+ None ,
966+ & pool,
967+ )
968+ . await ;
969+
970+ // test completion for already quoted column
971+ assert_complete_results (
972+ format ! (
973+ r#"select "quoted_col{}" from "auth"."quote_test_users""# ,
974+ QueryWithCursorPosition :: cursor_marker( )
975+ )
976+ . as_str ( ) ,
977+ vec ! [ CompletionAssertion :: LabelAndDesc (
978+ "quoted_column" . to_string( ) ,
979+ "auth.quote_test_users" . to_string( ) ,
980+ ) ] ,
981+ None ,
982+ & pool,
983+ )
984+ . await ;
985+
986+ // test completion with empty quotes
987+ assert_complete_results (
988+ format ! (
989+ r#"select "{}" from "auth"."quote_test_users""# ,
990+ QueryWithCursorPosition :: cursor_marker( )
991+ )
992+ . as_str ( ) ,
993+ vec ! [
994+ CompletionAssertion :: Label ( "email" . to_string( ) ) ,
995+ CompletionAssertion :: Label ( "id" . to_string( ) ) ,
996+ CompletionAssertion :: Label ( "name" . to_string( ) ) ,
997+ CompletionAssertion :: Label ( "quoted_column" . to_string( ) ) ,
998+ ] ,
999+ None ,
1000+ & pool,
1001+ )
1002+ . await ;
1003+
1004+ // test completion with partially opened quote
1005+ assert_complete_results (
1006+ format ! (
1007+ r#"select "{} from "auth"."quote_test_users""# ,
1008+ QueryWithCursorPosition :: cursor_marker( )
1009+ )
1010+ . as_str ( ) ,
1011+ vec ! [
1012+ CompletionAssertion :: Label ( "email" . to_string( ) ) ,
1013+ CompletionAssertion :: Label ( "id" . to_string( ) ) ,
1014+ CompletionAssertion :: Label ( "name" . to_string( ) ) ,
1015+ CompletionAssertion :: Label ( "quoted_column" . to_string( ) ) ,
1016+ ] ,
1017+ None ,
1018+ & pool,
1019+ )
1020+ . await ;
1021+ }
9351022}
0 commit comments