1use crate::classify::{NameClass, NameRefClass, classify_name, classify_name_ref};
2use crate::column_name::ColumnName;
3use crate::offsets::token_from_offset;
4use crate::resolve;
5use crate::{
6 binder,
7 symbols::{Name, Schema},
8};
9use rowan::TextSize;
10use squawk_syntax::SyntaxNode;
11use squawk_syntax::{
12 SyntaxKind,
13 ast::{self, AstNode},
14};
15
16pub fn hover(file: &ast::SourceFile, offset: TextSize) -> Option<String> {
17 let token = token_from_offset(file, offset)?;
18 let parent = token.parent()?;
19
20 let root = file.syntax();
21 let binder = binder::bind(file);
22
23 if token.kind() == SyntaxKind::STAR {
24 if let Some(field_expr) = ast::FieldExpr::cast(parent.clone())
25 && field_expr.star_token().is_some()
26 && let Some(result) = hover_qualified_star(root, &field_expr, &binder)
27 {
28 return Some(result);
29 }
30
31 if let Some(arg_list) = ast::ArgList::cast(parent.clone())
32 && let Some(result) = hover_unqualified_star_in_arg_list(root, &arg_list, &binder)
33 {
34 return Some(result);
35 }
36
37 if let Some(target) = ast::Target::cast(parent.clone())
38 && target.star_token().is_some()
39 && let Some(result) = hover_unqualified_star(root, &target, &binder)
40 {
41 return Some(result);
42 }
43 }
44
45 if let Some(name_ref) = ast::NameRef::cast(parent.clone()) {
46 let context = classify_name_ref(&name_ref)?;
47 match context {
48 NameRefClass::CreateIndexColumn
49 | NameRefClass::InsertColumn
50 | NameRefClass::DeleteWhereColumn
51 | NameRefClass::UpdateWhereColumn
52 | NameRefClass::UpdateSetColumn
53 | NameRefClass::UpdateReturningColumn
54 | NameRefClass::InsertReturningColumn
55 | NameRefClass::DeleteReturningColumn
56 | NameRefClass::MergeReturningColumn
57 | NameRefClass::MergeWhenColumn
58 | NameRefClass::MergeOnColumn
59 | NameRefClass::CheckConstraintColumn
60 | NameRefClass::GeneratedColumn
61 | NameRefClass::UniqueConstraintColumn
62 | NameRefClass::PrimaryKeyConstraintColumn
63 | NameRefClass::NotNullConstraintColumn
64 | NameRefClass::ExcludeConstraintColumn
65 | NameRefClass::PartitionByColumn
66 | NameRefClass::JoinUsingColumn
67 | NameRefClass::ForeignKeyColumn
68 | NameRefClass::ForeignKeyLocalColumn
69 | NameRefClass::SequenceOwnedByColumn
70 | NameRefClass::AlterTableColumn
71 | NameRefClass::AlterTableDropColumn => {
72 return hover_column(root, &name_ref, &binder);
73 }
74 NameRefClass::TypeReference | NameRefClass::DropType => {
75 return hover_type(root, &name_ref, &binder);
76 }
77 NameRefClass::CompositeTypeField => {
78 return hover_composite_type_field(root, &name_ref, &binder);
79 }
80 NameRefClass::SelectColumn | NameRefClass::SelectQualifiedColumn => {
81 if let Some(result) = hover_column(root, &name_ref, &binder) {
83 return Some(result);
84 }
85 if let Some(result) = hover_function(root, &name_ref, &binder) {
87 return Some(result);
88 }
89 return hover_table(root, &name_ref, &binder);
91 }
92 NameRefClass::Table
93 | NameRefClass::DropTable
94 | NameRefClass::DropForeignTable
95 | NameRefClass::DropView
96 | NameRefClass::DropMaterializedView
97 | NameRefClass::CreateIndex
98 | NameRefClass::InsertTable
99 | NameRefClass::InsertQualifiedColumnTable
100 | NameRefClass::DeleteTable
101 | NameRefClass::DeleteQualifiedColumnTable
102 | NameRefClass::DeleteUsingTable
103 | NameRefClass::MergeUsingTable
104 | NameRefClass::UpdateTable
105 | NameRefClass::SelectFromTable
106 | NameRefClass::UpdateFromTable
107 | NameRefClass::SelectQualifiedColumnTable
108 | NameRefClass::UpdateSetQualifiedColumnTable
109 | NameRefClass::MergeQualifiedColumnTable
110 | NameRefClass::UpdateReturningQualifiedColumnTable
111 | NameRefClass::InsertReturningQualifiedColumnTable
112 | NameRefClass::DeleteReturningQualifiedColumnTable
113 | NameRefClass::MergeReturningQualifiedColumnTable
114 | NameRefClass::MergeTable
115 | NameRefClass::ForeignKeyTable
116 | NameRefClass::LikeTable
117 | NameRefClass::InheritsTable
118 | NameRefClass::PartitionOfTable
119 | NameRefClass::TruncateTable
120 | NameRefClass::LockTable
121 | NameRefClass::VacuumTable
122 | NameRefClass::AlterTable
123 | NameRefClass::ReindexTable
124 | NameRefClass::RefreshMaterializedView
125 | NameRefClass::AttachPartition => {
126 return hover_table(root, &name_ref, &binder);
127 }
128 NameRefClass::DropSequence => return hover_sequence(root, &name_ref, &binder),
129 NameRefClass::DropTrigger => return hover_trigger(root, &name_ref, &binder),
130 NameRefClass::DropEventTrigger | NameRefClass::AlterEventTrigger => {
131 return hover_event_trigger(root, &name_ref, &binder);
132 }
133 NameRefClass::DropDatabase
134 | NameRefClass::ReindexDatabase
135 | NameRefClass::ReindexSystem => return hover_database(root, &name_ref, &binder),
136 NameRefClass::DropServer
137 | NameRefClass::AlterServer
138 | NameRefClass::CreateServer
139 | NameRefClass::ForeignTableServerName => {
140 return hover_server(root, &name_ref, &binder);
141 }
142 NameRefClass::DropExtension | NameRefClass::AlterExtension => {
143 return hover_extension(root, &name_ref, &binder);
144 }
145 NameRefClass::AlterRole
146 | NameRefClass::DropRole
147 | NameRefClass::SetRole
148 | NameRefClass::Role => {
149 return hover_role(root, &name_ref, &binder);
150 }
151 NameRefClass::Tablespace => return hover_tablespace(root, &name_ref, &binder),
152 NameRefClass::DropIndex | NameRefClass::ReindexIndex => {
153 return hover_index(root, &name_ref, &binder);
154 }
155 NameRefClass::DropFunction
156 | NameRefClass::DefaultConstraintFunctionCall
157 | NameRefClass::TriggerFunctionCall => {
158 return hover_function(root, &name_ref, &binder);
159 }
160 NameRefClass::DropAggregate => return hover_aggregate(root, &name_ref, &binder),
161 NameRefClass::DropProcedure
162 | NameRefClass::CallProcedure
163 | NameRefClass::TriggerProcedureCall => {
164 return hover_procedure(root, &name_ref, &binder);
165 }
166 NameRefClass::DropRoutine => return hover_routine(root, &name_ref, &binder),
167 NameRefClass::SelectFunctionCall => {
168 if let Some(result) = hover_function(root, &name_ref, &binder) {
171 return Some(result);
172 }
173 return hover_column(root, &name_ref, &binder);
174 }
175 NameRefClass::SchemaQualifier
176 | NameRefClass::DropSchema
177 | NameRefClass::ReindexSchema => {
178 return hover_schema(root, &name_ref, &binder);
179 }
180 NameRefClass::NamedArgParameter => {
181 return hover_named_arg_parameter(root, &name_ref, &binder);
182 }
183 NameRefClass::Cursor => {
184 return hover_cursor(root, &name_ref, &binder);
185 }
186 NameRefClass::PreparedStatement => {
187 return hover_prepared_statement(root, &name_ref, &binder);
188 }
189 NameRefClass::NotifyChannel | NameRefClass::UnlistenChannel => {
190 return hover_channel(root, &name_ref, &binder);
191 }
192 }
193 }
194
195 if let Some(name) = ast::Name::cast(parent) {
196 let context = classify_name(&name)?;
197 match context {
198 NameClass::ColumnDefinition {
199 create_table,
200 column,
201 } => return hover_column_definition(&create_table, &column, &binder),
202 NameClass::CreateTable(create_table) => {
203 return format_create_table(&create_table, &binder);
204 }
205 NameClass::WithTable(with_table) => return format_with_table(&with_table),
206 NameClass::CreateIndex(create_index) => {
207 return format_create_index(&create_index, &binder);
208 }
209 NameClass::CreateSequence(create_sequence) => {
210 return format_create_sequence(&create_sequence, &binder);
211 }
212 NameClass::CreateTrigger(create_trigger) => {
213 return format_create_trigger(&create_trigger, &binder);
214 }
215 NameClass::CreateEventTrigger(create_event_trigger) => {
216 return format_create_event_trigger(&create_event_trigger);
217 }
218 NameClass::CreateTablespace(create_tablespace) => {
219 return format_create_tablespace(&create_tablespace);
220 }
221 NameClass::CreateDatabase(create_database) => {
222 return format_create_database(&create_database);
223 }
224 NameClass::CreateServer(create_server) => {
225 return format_create_server(&create_server);
226 }
227 NameClass::CreateExtension(create_extension) => {
228 return format_create_extension(&create_extension);
229 }
230 NameClass::CreateRole(create_role) => {
231 return format_create_role(&create_role);
232 }
233 NameClass::CreateType(create_type) => {
234 return format_create_type(&create_type, &binder);
235 }
236 NameClass::CreateFunction(create_function) => {
237 return format_create_function(&create_function, &binder);
238 }
239 NameClass::CreateAggregate(create_aggregate) => {
240 return format_create_aggregate(&create_aggregate, &binder);
241 }
242 NameClass::CreateProcedure(create_procedure) => {
243 return format_create_procedure(&create_procedure, &binder);
244 }
245 NameClass::CreateSchema(create_schema) => {
246 return format_create_schema(&create_schema);
247 }
248 NameClass::ViewColumnList { create_view, name } => {
249 return format_view_column(&create_view, Name::from_node(&name), &binder);
250 }
251 NameClass::CreateView(create_view) => {
252 return format_create_view(&create_view, &binder);
253 }
254 NameClass::DeclareCursor(declare) => {
255 return format_declare_cursor(&declare);
256 }
257 NameClass::PrepareStatement(prepare) => {
258 return format_prepare(&prepare);
259 }
260 NameClass::Listen(listen) => {
261 return format_listen(&listen);
262 }
263 }
264 }
265
266 None
267}
268
269struct ColumnHover {}
270impl ColumnHover {
271 fn table_column(table_name: &str, column_name: &str) -> String {
272 format!("column {table_name}.{column_name}")
273 }
274 fn schema_table_column_type(
275 schema: &str,
276 table_name: &str,
277 column_name: &str,
278 ty: &str,
279 ) -> String {
280 format!("column {schema}.{table_name}.{column_name} {ty}")
281 }
282 fn schema_table_column(schema: &str, table_name: &str, column_name: &str) -> String {
283 format!("column {schema}.{table_name}.{column_name}")
284 }
285
286 fn anon_column(col_name: &str) -> String {
287 format!("column {}", col_name)
288 }
289}
290
291fn hover_column(
292 root: &SyntaxNode,
293 name_ref: &ast::NameRef,
294 binder: &binder::Binder,
295) -> Option<String> {
296 let column_ptrs = resolve::resolve_name_ref_ptrs(binder, root, name_ref)?;
297
298 let results: Vec<String> = column_ptrs
299 .iter()
300 .filter_map(|column_ptr| {
301 let column_name_node = column_ptr.to_node(root);
302 format_hover_for_column_node(binder, &column_name_node, name_ref)
303 })
304 .collect();
305
306 if results.is_empty() {
307 return None;
308 }
309
310 Some(results.join("\n"))
311}
312
313fn format_hover_for_column_node(
314 binder: &binder::Binder,
315 column_name_node: &squawk_syntax::SyntaxNode,
316 name_ref: &ast::NameRef,
317) -> Option<String> {
318 for a in column_name_node.ancestors() {
319 if let Some(with_table) = ast::WithTable::cast(a.clone()) {
320 let cte_name = with_table.name()?;
321 let column_name = if column_name_node
322 .ancestors()
323 .any(|a| ast::Values::can_cast(a.kind()))
324 {
325 Name::from_node(name_ref)
326 } else {
327 Name::from_string(column_name_node.text().to_string())
328 };
329 let table_name = Name::from_node(&cte_name);
330 return Some(ColumnHover::table_column(
331 &table_name.to_string(),
332 &column_name.to_string(),
333 ));
334 }
335 if ast::ParenSelect::can_cast(a.kind())
336 && let Some(field_expr) = name_ref.syntax().parent().and_then(ast::FieldExpr::cast)
337 && let Some(base) = field_expr.base()
338 && let ast::Expr::NameRef(table_name_ref) = base
339 {
340 let table_name = Name::from_node(&table_name_ref);
341 let column_name = Name::from_string(column_name_node.text().to_string());
342 return Some(ColumnHover::table_column(
343 &table_name.to_string(),
344 &column_name.to_string(),
345 ));
346 }
347
348 if let Some(create_view) = ast::CreateView::cast(a.clone())
352 && let Some(column_name) =
353 ast::Name::cast(column_name_node.clone()).map(|name| Name::from_node(&name))
354 {
355 return format_view_column(&create_view, column_name, binder);
356 }
357 }
358
359 let column = column_name_node.ancestors().find_map(ast::Column::cast)?;
360 let column_name = column.name()?;
361 let ty = column.ty()?;
362
363 let create_table = column
364 .syntax()
365 .ancestors()
366 .find_map(ast::CreateTableLike::cast)?;
367 let path = create_table.path()?;
368 let (schema, table_name) = resolve::resolve_table_info(binder, &path)?;
369
370 let schema = schema.to_string();
371 let column_name = Name::from_node(&column_name);
372 let ty = &ty.syntax().text().to_string();
373 Some(ColumnHover::schema_table_column_type(
374 &schema,
375 &table_name,
376 &column_name.to_string(),
377 ty,
378 ))
379}
380
381fn hover_composite_type_field(
382 root: &SyntaxNode,
383 name_ref: &ast::NameRef,
384 binder: &binder::Binder,
385) -> Option<String> {
386 let field_ptr = resolve::resolve_name_ref_ptrs(binder, root, name_ref)?
387 .into_iter()
388 .next()?;
389 let field_name_node = field_ptr.to_node(root);
390
391 let column = field_name_node.ancestors().find_map(ast::Column::cast)?;
392 let field_name = column.name()?.syntax().text().to_string();
393 let ty = column.ty()?;
394
395 let create_type = column
396 .syntax()
397 .ancestors()
398 .find_map(ast::CreateType::cast)?;
399 let type_path = create_type.path()?;
400 let (schema, type_name) = resolve::resolve_type_info(binder, &type_path)?;
401
402 Some(format!(
403 "field {}.{}.{} {}",
404 schema,
405 type_name,
406 field_name,
407 ty.syntax().text()
408 ))
409}
410
411fn hover_column_definition(
412 create_table: &impl ast::HasCreateTable,
413 column: &ast::Column,
414 binder: &binder::Binder,
415) -> Option<String> {
416 let column_name = column.name()?.syntax().text().to_string();
417 let ty = column.ty()?;
418 let path = create_table.path()?;
419 let (schema, table_name) = resolve::resolve_table_info(binder, &path)?;
420 let ty = ty.syntax().text().to_string();
421 Some(ColumnHover::schema_table_column_type(
422 &schema.to_string(),
423 &table_name,
424 &column_name,
425 &ty,
426 ))
427}
428
429fn hover_table(
430 root: &SyntaxNode,
431 name_ref: &ast::NameRef,
432 binder: &binder::Binder,
433) -> Option<String> {
434 if let Some(result) = hover_subquery_table(name_ref) {
435 return Some(result);
436 }
437
438 let table_ptr = resolve::resolve_name_ref_ptrs(binder, root, name_ref)?
439 .into_iter()
440 .next()?;
441
442 hover_table_from_ptr(root, &table_ptr, binder)
443}
444
445fn hover_table_from_ptr(
446 root: &SyntaxNode,
447 table_ptr: &squawk_syntax::SyntaxNodePtr,
448 binder: &binder::Binder,
449) -> Option<String> {
450 let table_name_node = table_ptr.to_node(root);
451
452 match resolve::find_table_source(&table_name_node)? {
453 resolve::TableSource::WithTable(with_table) => format_with_table(&with_table),
454 resolve::TableSource::CreateView(create_view) => format_create_view(&create_view, binder),
455 resolve::TableSource::CreateMaterializedView(create_materialized_view) => {
456 format_create_materialized_view(&create_materialized_view, binder)
457 }
458 resolve::TableSource::CreateTable(create_table) => {
459 format_create_table(&create_table, binder)
460 }
461 }
462}
463
464fn hover_qualified_star(
465 root: &SyntaxNode,
466 field_expr: &ast::FieldExpr,
467 binder: &binder::Binder,
468) -> Option<String> {
469 let table_ptr = resolve::resolve_qualified_star_table_ptr(binder, field_expr)?;
470 hover_qualified_star_columns(root, &table_ptr, binder)
471}
472
473fn hover_unqualified_star(
474 root: &SyntaxNode,
475 target: &ast::Target,
476 binder: &binder::Binder,
477) -> Option<String> {
478 let table_ptrs = resolve::resolve_unqualified_star_table_ptrs(binder, target)?;
479 let mut results = vec![];
480 for table_ptr in table_ptrs {
481 if let Some(columns) = hover_qualified_star_columns(root, &table_ptr, binder) {
482 results.push(columns);
483 }
484 }
485
486 if results.is_empty() {
487 return None;
488 }
489
490 Some(results.join("\n"))
491}
492
493fn hover_unqualified_star_in_arg_list(
494 root: &SyntaxNode,
495 arg_list: &ast::ArgList,
496 binder: &binder::Binder,
497) -> Option<String> {
498 let table_ptrs = resolve::resolve_unqualified_star_in_arg_list_ptrs(binder, arg_list)?;
499 let mut results = vec![];
500 for table_ptr in table_ptrs {
501 if let Some(columns) = hover_qualified_star_columns(root, &table_ptr, binder) {
502 results.push(columns);
503 }
504 }
505
506 if results.is_empty() {
507 return None;
508 }
509
510 Some(results.join("\n"))
511}
512
513fn hover_subquery_table(name_ref: &ast::NameRef) -> Option<String> {
514 let select = name_ref.syntax().ancestors().find_map(ast::Select::cast)?;
515 let from_clause = select.from_clause()?;
516 let qualifier = Name::from_node(name_ref);
517 let from_item = resolve::find_from_item_in_from_clause(&from_clause, &qualifier)?;
518 let paren_select = from_item.paren_select()?;
519 format_subquery_table(name_ref, &paren_select)
520}
521
522fn format_subquery_table(
523 name_ref: &ast::NameRef,
524 paren_select: &ast::ParenSelect,
525) -> Option<String> {
526 let name = name_ref.syntax().text().to_string();
527 let query = paren_select.syntax().text().to_string();
528 Some(format!("subquery {} as {}", name, query))
529}
530
531fn hover_qualified_star_columns(
532 root: &SyntaxNode,
533 table_ptr: &squawk_syntax::SyntaxNodePtr,
534 binder: &binder::Binder,
535) -> Option<String> {
536 let table_name_node = table_ptr.to_node(root);
537
538 if let Some(paren_select) = ast::ParenSelect::cast(table_name_node.clone()) {
539 return hover_qualified_star_columns_from_subquery(root, &paren_select, binder);
540 }
541
542 match resolve::find_table_source(&table_name_node)? {
543 resolve::TableSource::WithTable(with_table) => {
544 hover_qualified_star_columns_from_cte(&with_table)
545 }
546 resolve::TableSource::CreateTable(create_table) => {
547 hover_qualified_star_columns_from_table(root, &create_table, binder)
548 }
549 resolve::TableSource::CreateView(create_view) => {
550 hover_qualified_star_columns_from_view(&create_view, binder)
551 }
552 resolve::TableSource::CreateMaterializedView(create_materialized_view) => {
553 hover_qualified_star_columns_from_materialized_view(&create_materialized_view, binder)
554 }
555 }
556}
557
558fn hover_qualified_star_columns_from_table(
559 root: &SyntaxNode,
560 create_table: &impl ast::HasCreateTable,
561 binder: &binder::Binder,
562) -> Option<String> {
563 let path = create_table.path()?;
564 let (schema, table_name) = resolve::resolve_table_info(binder, &path)?;
565 let schema = schema.to_string();
566 let results: Vec<String> = resolve::collect_table_columns(binder, root, create_table)
567 .into_iter()
568 .filter_map(|column| {
569 let column_name = Name::from_node(&column.name()?);
570 let ty = column.ty()?;
571 let ty = &ty.syntax().text().to_string();
572 Some(ColumnHover::schema_table_column_type(
573 &schema,
574 &table_name,
575 &column_name.to_string(),
576 ty,
577 ))
578 })
579 .collect();
580
581 if results.is_empty() {
582 return None;
583 }
584
585 Some(results.join("\n"))
586}
587
588fn hover_qualified_star_columns_from_cte(with_table: &ast::WithTable) -> Option<String> {
589 let cte_name = Name::from_node(&with_table.name()?);
590 let column_names = resolve::collect_with_table_column_names(with_table);
591 let results: Vec<String> = column_names
592 .iter()
593 .map(|column_name| {
594 ColumnHover::table_column(&cte_name.to_string(), &column_name.to_string())
595 })
596 .collect();
597
598 if results.is_empty() {
599 return None;
600 }
601
602 Some(results.join("\n"))
603}
604
605fn hover_qualified_star_columns_from_view(
606 create_view: &ast::CreateView,
607 binder: &binder::Binder,
608) -> Option<String> {
609 let path = create_view.path()?;
610 let (schema, view_name) = resolve::resolve_view_info(binder, &path)?;
611
612 let schema_str = schema.to_string();
613 let column_names = resolve::collect_view_column_names(create_view);
614 let results: Vec<String> = column_names
615 .iter()
616 .map(|column_name| {
617 ColumnHover::schema_table_column(&schema_str, &view_name, &column_name.to_string())
618 })
619 .collect();
620
621 if results.is_empty() {
622 return None;
623 }
624
625 Some(results.join("\n"))
626}
627
628fn hover_qualified_star_columns_from_materialized_view(
629 create_materialized_view: &ast::CreateMaterializedView,
630 binder: &binder::Binder,
631) -> Option<String> {
632 let path = create_materialized_view.path()?;
633 let (schema, view_name) = resolve::resolve_view_info(binder, &path)?;
634
635 let schema_str = schema.to_string();
636 let column_names = resolve::collect_materialized_view_column_names(create_materialized_view);
637 let results: Vec<String> = column_names
638 .iter()
639 .map(|column_name| {
640 ColumnHover::schema_table_column(&schema_str, &view_name, &column_name.to_string())
641 })
642 .collect();
643
644 if results.is_empty() {
645 return None;
646 }
647
648 Some(results.join("\n"))
649}
650
651fn hover_qualified_star_columns_from_subquery(
652 root: &SyntaxNode,
653 paren_select: &ast::ParenSelect,
654 binder: &binder::Binder,
655) -> Option<String> {
656 let ast::SelectVariant::Select(select) = paren_select.select()? else {
657 return None;
658 };
659
660 let select_clause = select.select_clause()?;
661 let target_list = select_clause.target_list()?;
662
663 let mut results = vec![];
664 let subquery_alias = subquery_alias_name(paren_select);
665
666 for target in target_list.targets() {
667 if target.star_token().is_some() {
668 let table_ptrs = resolve::resolve_unqualified_star_table_ptrs(binder, &target)?;
669 for table_ptr in table_ptrs {
670 if let Some(columns) = hover_qualified_star_columns(root, &table_ptr, binder) {
671 results.push(columns)
672 }
673 }
674 continue;
675 }
676
677 if let Some(result) =
678 hover_subquery_target_column(root, &target, subquery_alias.as_ref(), binder)
679 {
680 results.push(result);
681 }
682 }
683
684 if results.is_empty() {
685 return None;
686 }
687
688 Some(results.join("\n"))
689}
690
691fn subquery_alias_name(paren_select: &ast::ParenSelect) -> Option<Name> {
692 let from_item = paren_select
693 .syntax()
694 .ancestors()
695 .find_map(ast::FromItem::cast)?;
696 let alias_name = from_item.alias()?.name()?;
697 Some(Name::from_node(&alias_name))
698}
699
700fn hover_subquery_target_column(
701 root: &SyntaxNode,
702 target: &ast::Target,
703 subquery_alias: Option<&Name>,
704 binder: &binder::Binder,
705) -> Option<String> {
706 if let Some(alias) = subquery_alias
707 && let Some((col_name, _node)) = ColumnName::from_target(target.clone())
708 && let Some(col_name) = col_name.to_string()
709 {
710 return Some(ColumnHover::table_column(&alias.to_string(), &col_name));
711 }
712
713 let result = match target.expr()? {
714 ast::Expr::NameRef(name_ref) => hover_column(root, &name_ref, binder),
715 ast::Expr::FieldExpr(field_expr) => {
716 let field = field_expr.field()?;
717 hover_column(root, &field, binder)
718 }
719 _ => None,
720 };
721
722 if result.is_some() {
723 return result;
724 }
725
726 if let Some((col_name, _node)) = ColumnName::from_target(target.clone())
727 && let Some(col_name) = col_name.to_string()
728 {
729 return Some(ColumnHover::anon_column(&col_name));
730 }
731
732 None
733}
734
735fn hover_index(
736 root: &SyntaxNode,
737 name_ref: &ast::NameRef,
738 binder: &binder::Binder,
739) -> Option<String> {
740 let index_ptr = resolve::resolve_name_ref_ptrs(binder, root, name_ref)?
741 .into_iter()
742 .next()?;
743
744 let index_name_node = index_ptr.to_node(root);
745
746 let create_index = index_name_node
747 .ancestors()
748 .find_map(ast::CreateIndex::cast)?;
749
750 format_create_index(&create_index, binder)
751}
752
753fn hover_sequence(
754 root: &SyntaxNode,
755 name_ref: &ast::NameRef,
756 binder: &binder::Binder,
757) -> Option<String> {
758 let sequence_ptr = resolve::resolve_name_ref_ptrs(binder, root, name_ref)?
759 .into_iter()
760 .next()?;
761
762 let sequence_name_node = sequence_ptr.to_node(root);
763
764 let create_sequence = sequence_name_node
765 .ancestors()
766 .find_map(ast::CreateSequence::cast)?;
767
768 format_create_sequence(&create_sequence, binder)
769}
770
771fn hover_trigger(
772 root: &SyntaxNode,
773 name_ref: &ast::NameRef,
774 binder: &binder::Binder,
775) -> Option<String> {
776 let trigger_ptr = resolve::resolve_name_ref_ptrs(binder, root, name_ref)?
777 .into_iter()
778 .next()?;
779
780 let trigger_name_node = trigger_ptr.to_node(root);
781
782 let create_trigger = trigger_name_node
783 .ancestors()
784 .find_map(ast::CreateTrigger::cast)?;
785
786 format_create_trigger(&create_trigger, binder)
787}
788
789fn hover_event_trigger(
790 root: &SyntaxNode,
791 name_ref: &ast::NameRef,
792 binder: &binder::Binder,
793) -> Option<String> {
794 let event_trigger_ptr = resolve::resolve_name_ref_ptrs(binder, root, name_ref)?
795 .into_iter()
796 .next()?;
797
798 let event_trigger_name_node = event_trigger_ptr.to_node(root);
799
800 let create_event_trigger = event_trigger_name_node
801 .ancestors()
802 .find_map(ast::CreateEventTrigger::cast)?;
803
804 format_create_event_trigger(&create_event_trigger)
805}
806
807fn hover_tablespace(
808 root: &SyntaxNode,
809 name_ref: &ast::NameRef,
810 binder: &binder::Binder,
811) -> Option<String> {
812 let tablespace_ptr = resolve::resolve_name_ref_ptrs(binder, root, name_ref)?
813 .into_iter()
814 .next()?;
815 let tablespace_name_node = tablespace_ptr.to_node(root);
816 Some(format!("tablespace {}", tablespace_name_node.text()))
817}
818
819fn hover_database(
820 root: &SyntaxNode,
821 name_ref: &ast::NameRef,
822 binder: &binder::Binder,
823) -> Option<String> {
824 let database_ptr = resolve::resolve_name_ref_ptrs(binder, root, name_ref)?
825 .into_iter()
826 .next()?;
827 let database_name_node = database_ptr.to_node(root);
828 Some(format!("database {}", database_name_node.text()))
829}
830
831fn hover_server(
832 root: &SyntaxNode,
833 name_ref: &ast::NameRef,
834 binder: &binder::Binder,
835) -> Option<String> {
836 let server_ptr = resolve::resolve_name_ref_ptrs(binder, root, name_ref)?
837 .into_iter()
838 .next()?;
839 let server_name_node = server_ptr.to_node(root);
840 Some(format!("server {}", server_name_node.text()))
841}
842
843fn hover_extension(
844 root: &SyntaxNode,
845 name_ref: &ast::NameRef,
846 binder: &binder::Binder,
847) -> Option<String> {
848 let extension_ptr = resolve::resolve_name_ref_ptrs(binder, root, name_ref)?
849 .into_iter()
850 .next()?;
851 let extension_name_node = extension_ptr.to_node(root);
852 Some(format!("extension {}", extension_name_node.text()))
853}
854
855fn hover_role(
856 root: &SyntaxNode,
857 name_ref: &ast::NameRef,
858 binder: &binder::Binder,
859) -> Option<String> {
860 let role_ptr = resolve::resolve_name_ref_ptrs(binder, root, name_ref)?
861 .into_iter()
862 .next()?;
863 let role_name_node = role_ptr.to_node(root);
864 Some(format!("role {}", role_name_node.text()))
865}
866
867fn hover_cursor(
868 root: &SyntaxNode,
869 name_ref: &ast::NameRef,
870 binder: &binder::Binder,
871) -> Option<String> {
872 let cursor_ptr = resolve::resolve_name_ref_ptrs(binder, root, name_ref)?
873 .into_iter()
874 .next()?;
875 let cursor_name_node = cursor_ptr.to_node(root);
876 let declare = cursor_name_node.ancestors().find_map(ast::Declare::cast)?;
877 format_declare_cursor(&declare)
878}
879
880fn hover_prepared_statement(
881 root: &SyntaxNode,
882 name_ref: &ast::NameRef,
883 binder: &binder::Binder,
884) -> Option<String> {
885 let statement_ptr = resolve::resolve_name_ref_ptrs(binder, root, name_ref)?
886 .into_iter()
887 .next()?;
888 let statement_name_node = statement_ptr.to_node(root);
889 let prepare = statement_name_node
890 .ancestors()
891 .find_map(ast::Prepare::cast)?;
892 format_prepare(&prepare)
893}
894
895fn hover_channel(
896 root: &SyntaxNode,
897 name_ref: &ast::NameRef,
898 binder: &binder::Binder,
899) -> Option<String> {
900 let channel_ptr = resolve::resolve_name_ref_ptrs(binder, root, name_ref)?
901 .into_iter()
902 .next()?;
903 let channel_name_node = channel_ptr.to_node(root);
904 let listen = channel_name_node.ancestors().find_map(ast::Listen::cast)?;
905 format_listen(&listen)
906}
907
908fn hover_type(
909 root: &SyntaxNode,
910 name_ref: &ast::NameRef,
911 binder: &binder::Binder,
912) -> Option<String> {
913 let type_ptr = resolve::resolve_name_ref_ptrs(binder, root, name_ref)?
914 .into_iter()
915 .next()?;
916
917 let type_name_node = type_ptr.to_node(root);
918
919 let create_type = type_name_node.ancestors().find_map(ast::CreateType::cast)?;
920
921 format_create_type(&create_type, binder)
922}
923
924fn format_declare_cursor(declare: &ast::Declare) -> Option<String> {
925 let name = declare.name()?;
926 let query = declare.query()?;
927 Some(format!(
928 "cursor {} for {}",
929 name.syntax().text(),
930 query.syntax().text()
931 ))
932}
933
934fn format_prepare(prepare: &ast::Prepare) -> Option<String> {
935 let name = prepare.name()?;
936 let stmt = prepare.preparable_stmt()?;
937 Some(format!(
938 "prepare {} as {}",
939 name.syntax().text(),
940 stmt.syntax().text()
941 ))
942}
943
944fn format_listen(listen: &ast::Listen) -> Option<String> {
945 let name = listen.name()?;
946 Some(format!("listen {}", name.syntax().text()))
947}
948
949fn format_create_table(
950 create_table: &impl ast::HasCreateTable,
951 binder: &binder::Binder,
952) -> Option<String> {
953 let path = create_table.path()?;
954 let (schema, table_name) = resolve::resolve_table_info(binder, &path)?;
955 let schema = schema.to_string();
956 let args = create_table.table_arg_list()?.syntax().text().to_string();
957
958 let foreign = if create_table.syntax().kind() == SyntaxKind::CREATE_FOREIGN_TABLE {
959 "foreign "
960 } else {
961 ""
962 };
963
964 Some(format!("{foreign}table {schema}.{table_name}{args}"))
965}
966
967fn format_create_view(create_view: &ast::CreateView, binder: &binder::Binder) -> Option<String> {
968 let path = create_view.path()?;
969 let (schema, view_name) = resolve::resolve_view_info(binder, &path)?;
970 let schema = schema.to_string();
971
972 let column_list = create_view
973 .column_list()
974 .map(|cl| cl.syntax().text().to_string())
975 .unwrap_or_default();
976
977 let query = create_view.query()?.syntax().text().to_string();
978
979 Some(format!(
980 "view {}.{}{} as {}",
981 schema, view_name, column_list, query
982 ))
983}
984
985fn format_create_materialized_view(
986 create_materialized_view: &ast::CreateMaterializedView,
987 binder: &binder::Binder,
988) -> Option<String> {
989 let path = create_materialized_view.path()?;
990 let (schema, view_name) = resolve::resolve_view_info(binder, &path)?;
991 let schema = schema.to_string();
992
993 let column_list = create_materialized_view
994 .column_list()
995 .map(|cl| cl.syntax().text().to_string())
996 .unwrap_or_default();
997
998 let query = create_materialized_view
999 .query()?
1000 .syntax()
1001 .text()
1002 .to_string();
1003
1004 Some(format!(
1005 "materialized view {}.{}{} as {}",
1006 schema, view_name, column_list, query
1007 ))
1008}
1009
1010fn format_view_column(
1011 create_view: &ast::CreateView,
1012 column_name: Name,
1013 binder: &binder::Binder,
1014) -> Option<String> {
1015 let path = create_view.path()?;
1016 let (schema, view_name) = resolve::resolve_view_info(binder, &path)?;
1017 Some(ColumnHover::schema_table_column(
1018 &schema.to_string(),
1019 &view_name,
1020 &column_name.to_string(),
1021 ))
1022}
1023
1024fn format_with_table(with_table: &ast::WithTable) -> Option<String> {
1025 let name = with_table.name()?.syntax().text().to_string();
1026 let query = with_table.query()?.syntax().text().to_string();
1027 Some(format!("with {} as ({})", name, query))
1028}
1029
1030fn format_create_index(create_index: &ast::CreateIndex, binder: &binder::Binder) -> Option<String> {
1031 let index_name = create_index.name()?.syntax().text().to_string();
1032
1033 let index_schema = index_schema(create_index, binder)?;
1034
1035 let relation_name = create_index.relation_name()?;
1036 let path = relation_name.path()?;
1037 let (table_schema, table_name) = resolve::resolve_table_info(binder, &path)?;
1038
1039 let partition_item_list = create_index.partition_item_list()?;
1040 let columns = partition_item_list.syntax().text().to_string();
1041
1042 Some(format!(
1043 "index {}.{} on {}.{}{}",
1044 index_schema, index_name, table_schema, table_name, columns
1045 ))
1046}
1047
1048fn format_create_sequence(
1049 create_sequence: &ast::CreateSequence,
1050 binder: &binder::Binder,
1051) -> Option<String> {
1052 let path = create_sequence.path()?;
1053 let (schema, sequence_name) = resolve::resolve_sequence_info(binder, &path)?;
1054
1055 Some(format!("sequence {}.{}", schema, sequence_name))
1056}
1057
1058fn format_create_trigger(
1059 create_trigger: &ast::CreateTrigger,
1060 binder: &binder::Binder,
1061) -> Option<String> {
1062 let trigger_name = create_trigger.name()?.syntax().text().to_string();
1063 let on_table_path = create_trigger.on_table()?.path()?;
1064
1065 let (schema, table_name) = resolve::resolve_table_info(binder, &on_table_path)?;
1066 Some(format!(
1067 "trigger {}.{} on {}.{}",
1068 schema, trigger_name, schema, table_name
1069 ))
1070}
1071
1072fn format_create_event_trigger(create_event_trigger: &ast::CreateEventTrigger) -> Option<String> {
1073 let name = create_event_trigger.name()?.syntax().text().to_string();
1074 Some(format!("event trigger {}", name))
1075}
1076
1077fn format_create_tablespace(create_tablespace: &ast::CreateTablespace) -> Option<String> {
1078 let name = create_tablespace.name()?.syntax().text().to_string();
1079 Some(format!("tablespace {}", name))
1080}
1081
1082fn format_create_database(create_database: &ast::CreateDatabase) -> Option<String> {
1083 let name = create_database.name()?.syntax().text().to_string();
1084 Some(format!("database {}", name))
1085}
1086
1087fn format_create_server(create_server: &ast::CreateServer) -> Option<String> {
1088 let name = create_server.name()?.syntax().text().to_string();
1089 Some(format!("server {}", name))
1090}
1091
1092fn format_create_extension(create_extension: &ast::CreateExtension) -> Option<String> {
1093 let name = create_extension.name()?.syntax().text().to_string();
1094 Some(format!("extension {}", name))
1095}
1096
1097fn format_create_role(create_role: &ast::CreateRole) -> Option<String> {
1098 let name = create_role.name()?.syntax().text().to_string();
1099 Some(format!("role {}", name))
1100}
1101
1102fn index_schema(create_index: &ast::CreateIndex, binder: &binder::Binder) -> Option<String> {
1103 let position = create_index.syntax().text_range().start();
1104 let search_path = binder.search_path_at(position);
1105 search_path.first().map(|s| s.to_string())
1106}
1107
1108fn format_create_type(create_type: &ast::CreateType, binder: &binder::Binder) -> Option<String> {
1109 let path = create_type.path()?;
1110 let (schema, type_name) = resolve::resolve_type_info(binder, &path)?;
1111
1112 if let Some(variant_list) = create_type.variant_list() {
1113 let variants = variant_list.syntax().text().to_string();
1114 return Some(format!(
1115 "type {}.{} as enum {}",
1116 schema, type_name, variants
1117 ));
1118 }
1119
1120 if let Some(column_list) = create_type.column_list() {
1121 let columns = column_list.syntax().text().to_string();
1122 return Some(format!("type {}.{} as {}", schema, type_name, columns));
1123 }
1124
1125 if let Some(attribute_list) = create_type.attribute_list() {
1126 let attributes = attribute_list.syntax().text().to_string();
1127 return Some(format!("type {}.{} {}", schema, type_name, attributes));
1128 }
1129
1130 Some(format!("type {}.{}", schema, type_name))
1131}
1132
1133fn hover_schema(
1134 root: &SyntaxNode,
1135 name_ref: &ast::NameRef,
1136 binder: &binder::Binder,
1137) -> Option<String> {
1138 let schema_ptr = resolve::resolve_name_ref_ptrs(binder, root, name_ref)?
1139 .into_iter()
1140 .next()?;
1141
1142 let schema_name_node = schema_ptr.to_node(root);
1143
1144 let create_schema = schema_name_node
1145 .ancestors()
1146 .find_map(ast::CreateSchema::cast)?;
1147
1148 format_create_schema(&create_schema)
1149}
1150
1151fn create_schema_name(create_schema: &ast::CreateSchema) -> Option<String> {
1152 if let Some(schema_name) = create_schema.name() {
1153 return Some(schema_name.syntax().text().to_string());
1154 }
1155
1156 create_schema
1157 .role()
1158 .and_then(|r| r.name())
1159 .map(|n| n.syntax().text().to_string())
1160}
1161
1162fn format_create_schema(create_schema: &ast::CreateSchema) -> Option<String> {
1163 let schema_name = create_schema_name(create_schema)?;
1164 Some(format!("schema {}", schema_name))
1165}
1166
1167fn hover_function(
1168 root: &SyntaxNode,
1169 name_ref: &ast::NameRef,
1170 binder: &binder::Binder,
1171) -> Option<String> {
1172 let function_ptr = resolve::resolve_name_ref_ptrs(binder, root, name_ref)?
1173 .into_iter()
1174 .next()?;
1175
1176 let function_name_node = function_ptr.to_node(root);
1177
1178 let create_function = function_name_node
1179 .ancestors()
1180 .find_map(ast::CreateFunction::cast)?;
1181
1182 format_create_function(&create_function, binder)
1183}
1184
1185fn hover_named_arg_parameter(
1186 root: &SyntaxNode,
1187 name_ref: &ast::NameRef,
1188 binder: &binder::Binder,
1189) -> Option<String> {
1190 let param_ptr = resolve::resolve_name_ref_ptrs(binder, root, name_ref)?
1191 .into_iter()
1192 .next()?;
1193 let param_name_node = param_ptr.to_node(root);
1194 let param = param_name_node.ancestors().find_map(ast::Param::cast)?;
1195 let param_name = param.name().map(|name| Name::from_node(&name))?;
1196 let param_type = param.ty().map(|ty| ty.syntax().text().to_string());
1197
1198 for ancestor in param_name_node.ancestors() {
1199 if let Some(create_function) = ast::CreateFunction::cast(ancestor.clone()) {
1200 let path = create_function.path()?;
1201 let (schema, function_name) = resolve::resolve_function_info(binder, &path)?;
1202 return Some(format_param_hover(
1203 schema,
1204 function_name,
1205 param_name,
1206 param_type,
1207 ));
1208 }
1209 if let Some(create_procedure) = ast::CreateProcedure::cast(ancestor.clone()) {
1210 let path = create_procedure.path()?;
1211 let (schema, procedure_name) = resolve::resolve_procedure_info(binder, &path)?;
1212 return Some(format_param_hover(
1213 schema,
1214 procedure_name,
1215 param_name,
1216 param_type,
1217 ));
1218 }
1219 if let Some(create_aggregate) = ast::CreateAggregate::cast(ancestor) {
1220 let path = create_aggregate.path()?;
1221 let (schema, aggregate_name) = resolve::resolve_aggregate_info(binder, &path)?;
1222 return Some(format_param_hover(
1223 schema,
1224 aggregate_name,
1225 param_name,
1226 param_type,
1227 ));
1228 }
1229 }
1230
1231 None
1232}
1233
1234fn format_param_hover(
1235 schema: Schema,
1236 routine_name: String,
1237 param_name: Name,
1238 param_type: Option<String>,
1239) -> String {
1240 if let Some(param_type) = param_type {
1241 return format!(
1242 "parameter {}.{}.{} {}",
1243 schema, routine_name, param_name, param_type
1244 );
1245 }
1246
1247 format!("parameter {}.{}.{}", schema, routine_name, param_name)
1248}
1249
1250fn format_create_function(
1251 create_function: &ast::CreateFunction,
1252 binder: &binder::Binder,
1253) -> Option<String> {
1254 let path = create_function.path()?;
1255 let (schema, function_name) = resolve::resolve_function_info(binder, &path)?;
1256
1257 let param_list = create_function.param_list()?;
1258 let params = param_list.syntax().text().to_string();
1259
1260 let ret_type = create_function.ret_type()?;
1261 let return_type = ret_type.syntax().text().to_string();
1262
1263 Some(format!(
1264 "function {}.{}{} {}",
1265 schema, function_name, params, return_type
1266 ))
1267}
1268
1269fn hover_aggregate(
1270 root: &SyntaxNode,
1271 name_ref: &ast::NameRef,
1272 binder: &binder::Binder,
1273) -> Option<String> {
1274 let aggregate_ptr = resolve::resolve_name_ref_ptrs(binder, root, name_ref)?
1275 .into_iter()
1276 .next()?;
1277
1278 let aggregate_name_node = aggregate_ptr.to_node(root);
1279
1280 let create_aggregate = aggregate_name_node
1281 .ancestors()
1282 .find_map(ast::CreateAggregate::cast)?;
1283
1284 format_create_aggregate(&create_aggregate, binder)
1285}
1286
1287fn format_create_aggregate(
1288 create_aggregate: &ast::CreateAggregate,
1289 binder: &binder::Binder,
1290) -> Option<String> {
1291 let path = create_aggregate.path()?;
1292 let (schema, aggregate_name) = resolve::resolve_aggregate_info(binder, &path)?;
1293
1294 let param_list = create_aggregate.param_list()?;
1295 let params = param_list.syntax().text().to_string();
1296
1297 Some(format!("aggregate {}.{}{}", schema, aggregate_name, params))
1298}
1299
1300fn hover_procedure(
1301 root: &SyntaxNode,
1302 name_ref: &ast::NameRef,
1303 binder: &binder::Binder,
1304) -> Option<String> {
1305 let procedure_ptr = resolve::resolve_name_ref_ptrs(binder, root, name_ref)?
1306 .into_iter()
1307 .next()?;
1308
1309 let procedure_name_node = procedure_ptr.to_node(root);
1310
1311 let create_procedure = procedure_name_node
1312 .ancestors()
1313 .find_map(ast::CreateProcedure::cast)?;
1314
1315 format_create_procedure(&create_procedure, binder)
1316}
1317
1318fn format_create_procedure(
1319 create_procedure: &ast::CreateProcedure,
1320 binder: &binder::Binder,
1321) -> Option<String> {
1322 let path = create_procedure.path()?;
1323 let (schema, procedure_name) = resolve::resolve_procedure_info(binder, &path)?;
1324
1325 let param_list = create_procedure.param_list()?;
1326 let params = param_list.syntax().text().to_string();
1327
1328 Some(format!("procedure {}.{}{}", schema, procedure_name, params))
1329}
1330
1331fn hover_routine(
1332 root: &SyntaxNode,
1333 name_ref: &ast::NameRef,
1334 binder: &binder::Binder,
1335) -> Option<String> {
1336 let routine_ptr = resolve::resolve_name_ref_ptrs(binder, root, name_ref)?
1337 .into_iter()
1338 .next()?;
1339 let routine_name = routine_ptr.to_node(root);
1340
1341 for a in routine_name.ancestors() {
1342 if let Some(create_function) = ast::CreateFunction::cast(a.clone()) {
1343 return format_create_function(&create_function, binder);
1344 }
1345 if let Some(create_aggregate) = ast::CreateAggregate::cast(a.clone()) {
1346 return format_create_aggregate(&create_aggregate, binder);
1347 }
1348 if let Some(create_procedure) = ast::CreateProcedure::cast(a) {
1349 return format_create_procedure(&create_procedure, binder);
1350 }
1351 }
1352
1353 None
1354}
1355
1356#[cfg(test)]
1357mod test {
1358 use crate::hover::hover;
1359 use crate::test_utils::fixture;
1360 use annotate_snippets::{AnnotationKind, Level, Renderer, Snippet, renderer::DecorStyle};
1361 use insta::assert_snapshot;
1362 use squawk_syntax::ast;
1363
1364 #[track_caller]
1365 fn check_hover(sql: &str) -> String {
1366 check_hover_(sql).expect("should find hover information")
1367 }
1368
1369 #[track_caller]
1370 fn check_hover_(sql: &str) -> Option<String> {
1371 let (mut offset, sql) = fixture(sql);
1372 offset = offset.checked_sub(1.into()).unwrap_or_default();
1373 let parse = ast::SourceFile::parse(&sql);
1374 assert_eq!(parse.errors(), vec![]);
1375 let file: ast::SourceFile = parse.tree();
1376
1377 if let Some(type_info) = hover(&file, offset) {
1378 let offset_usize: usize = offset.into();
1379 let title = format!("hover: {}", type_info);
1380 let group = Level::INFO.primary_title(&title).element(
1381 Snippet::source(&sql).fold(true).annotation(
1382 AnnotationKind::Context
1383 .span(offset_usize..offset_usize + 1)
1384 .label("hover"),
1385 ),
1386 );
1387 let renderer = Renderer::plain().decor_style(DecorStyle::Unicode);
1388 return Some(
1389 renderer
1390 .render(&[group])
1391 .to_string()
1392 .replace("info: hover:", "hover:"),
1394 );
1395 }
1396 None
1397 }
1398
1399 #[test]
1400 fn hover_column_in_create_index() {
1401 assert_snapshot!(check_hover("
1402create table users(id int, email text);
1403create index idx_email on users(email$0);
1404"), @r"
1405 hover: column public.users.email text
1406 ╭▸
1407 3 │ create index idx_email on users(email);
1408 ╰╴ ─ hover
1409 ");
1410 }
1411
1412 #[test]
1413 fn hover_column_int_type() {
1414 assert_snapshot!(check_hover("
1415create table users(id int, email text);
1416create index idx_id on users(id$0);
1417"), @r"
1418 hover: column public.users.id int
1419 ╭▸
1420 3 │ create index idx_id on users(id);
1421 ╰╴ ─ hover
1422 ");
1423 }
1424
1425 #[test]
1426 fn hover_column_with_schema() {
1427 assert_snapshot!(check_hover("
1428create table public.users(id int, email text);
1429create index idx_email on public.users(email$0);
1430"), @r"
1431 hover: column public.users.email text
1432 ╭▸
1433 3 │ create index idx_email on public.users(email);
1434 ╰╴ ─ hover
1435 ");
1436 }
1437
1438 #[test]
1439 fn hover_column_temp_table() {
1440 assert_snapshot!(check_hover("
1441create temp table users(id int, email text);
1442create index idx_email on users(email$0);
1443"), @r"
1444 hover: column pg_temp.users.email text
1445 ╭▸
1446 3 │ create index idx_email on users(email);
1447 ╰╴ ─ hover
1448 ");
1449 }
1450
1451 #[test]
1452 fn hover_column_multiple_columns() {
1453 assert_snapshot!(check_hover("
1454create table users(id int, email text, name varchar(100));
1455create index idx_users on users(id, email$0, name);
1456"), @r"
1457 hover: column public.users.email text
1458 ╭▸
1459 3 │ create index idx_users on users(id, email, name);
1460 ╰╴ ─ hover
1461 ");
1462 }
1463
1464 #[test]
1465 fn hover_column_varchar() {
1466 assert_snapshot!(check_hover("
1467create table users(id int, name varchar(100));
1468create index idx_name on users(name$0);
1469"), @r"
1470 hover: column public.users.name varchar(100)
1471 ╭▸
1472 3 │ create index idx_name on users(name);
1473 ╰╴ ─ hover
1474 ");
1475 }
1476
1477 #[test]
1478 fn hover_column_bigint() {
1479 assert_snapshot!(check_hover("
1480create table metrics(value bigint);
1481create index idx_value on metrics(value$0);
1482"), @r"
1483 hover: column public.metrics.value bigint
1484 ╭▸
1485 3 │ create index idx_value on metrics(value);
1486 ╰╴ ─ hover
1487 ");
1488 }
1489
1490 #[test]
1491 fn hover_column_timestamp() {
1492 assert_snapshot!(check_hover("
1493create table events(created_at timestamp with time zone);
1494create index idx_created on events(created_at$0);
1495"), @r"
1496 hover: column public.events.created_at timestamp with time zone
1497 ╭▸
1498 3 │ create index idx_created on events(created_at);
1499 ╰╴ ─ hover
1500 ");
1501 }
1502
1503 #[test]
1504 fn hover_column_with_search_path() {
1505 assert_snapshot!(check_hover(r#"
1506set search_path to myschema;
1507create table myschema.users(id int, email text);
1508create index idx_email on users(email$0);
1509"#), @r"
1510 hover: column myschema.users.email text
1511 ╭▸
1512 4 │ create index idx_email on users(email);
1513 ╰╴ ─ hover
1514 ");
1515 }
1516
1517 #[test]
1518 fn hover_column_explicit_schema_overrides_search_path() {
1519 assert_snapshot!(check_hover(r#"
1520set search_path to myschema;
1521create table public.users(id int, email text);
1522create table myschema.users(value bigint);
1523create index idx_email on public.users(email$0);
1524"#), @r"
1525 hover: column public.users.email text
1526 ╭▸
1527 5 │ create index idx_email on public.users(email);
1528 ╰╴ ─ hover
1529 ");
1530 }
1531
1532 #[test]
1533 fn hover_on_table_name() {
1534 assert_snapshot!(check_hover("
1535create table t(id int);
1536create index idx on t$0(id);
1537"), @r"
1538 hover: table public.t(id int)
1539 ╭▸
1540 3 │ create index idx on t(id);
1541 ╰╴ ─ hover
1542 ");
1543 }
1544
1545 #[test]
1546 fn hover_on_index_name_in_create() {
1547 assert_snapshot!(check_hover("
1548create table users(id int);
1549create index idx$0 on users(id);
1550"), @r"
1551 hover: index public.idx on public.users(id)
1552 ╭▸
1553 3 │ create index idx on users(id);
1554 ╰╴ ─ hover
1555 ");
1556 }
1557
1558 #[test]
1559 fn hover_table_in_create_index() {
1560 assert_snapshot!(check_hover("
1561create table users(id int, email text);
1562create index idx_email on users$0(email);
1563"), @r"
1564 hover: table public.users(id int, email text)
1565 ╭▸
1566 3 │ create index idx_email on users(email);
1567 ╰╴ ─ hover
1568 ");
1569 }
1570
1571 #[test]
1572 fn hover_table_with_schema() {
1573 assert_snapshot!(check_hover("
1574create table public.users(id int, email text);
1575create index idx on public.users$0(id);
1576"), @r"
1577 hover: table public.users(id int, email text)
1578 ╭▸
1579 3 │ create index idx on public.users(id);
1580 ╰╴ ─ hover
1581 ");
1582 }
1583
1584 #[test]
1585 fn hover_table_temp() {
1586 assert_snapshot!(check_hover("
1587create temp table users(id int, email text);
1588create index idx on users$0(id);
1589"), @r"
1590 hover: table pg_temp.users(id int, email text)
1591 ╭▸
1592 3 │ create index idx on users(id);
1593 ╰╴ ─ hover
1594 ");
1595 }
1596
1597 #[test]
1598 fn hover_table_multiline() {
1599 assert_snapshot!(check_hover("
1600create table users(
1601 id int,
1602 email text,
1603 name varchar(100)
1604);
1605create index idx on users$0(id);
1606"), @r"
1607 hover: table public.users(
1608 id int,
1609 email text,
1610 name varchar(100)
1611 )
1612 ╭▸
1613 7 │ create index idx on users(id);
1614 ╰╴ ─ hover
1615 ");
1616 }
1617
1618 #[test]
1619 fn hover_table_with_search_path() {
1620 assert_snapshot!(check_hover(r#"
1621set search_path to myschema;
1622create table users(id int, email text);
1623create index idx on users$0(id);
1624"#), @r"
1625 hover: table myschema.users(id int, email text)
1626 ╭▸
1627 4 │ create index idx on users(id);
1628 ╰╴ ─ hover
1629 ");
1630 }
1631
1632 #[test]
1633 fn hover_table_search_path_at_definition() {
1634 assert_snapshot!(check_hover(r#"
1635set search_path to myschema;
1636create table users(id int, email text);
1637set search_path to myschema, otherschema;
1638create index idx on users$0(id);
1639"#), @r"
1640 hover: table myschema.users(id int, email text)
1641 ╭▸
1642 5 │ create index idx on users(id);
1643 ╰╴ ─ hover
1644 ");
1645 }
1646
1647 #[test]
1648 fn hover_on_create_table_definition() {
1649 assert_snapshot!(check_hover("
1650create table t$0(x bigint);
1651"), @r"
1652 hover: table public.t(x bigint)
1653 ╭▸
1654 2 │ create table t(x bigint);
1655 ╰╴ ─ hover
1656 ");
1657 }
1658
1659 #[test]
1660 fn hover_on_create_table_definition_with_schema() {
1661 assert_snapshot!(check_hover("
1662create table myschema.users$0(id int);
1663"), @r"
1664 hover: table myschema.users(id int)
1665 ╭▸
1666 2 │ create table myschema.users(id int);
1667 ╰╴ ─ hover
1668 ");
1669 }
1670
1671 #[test]
1672 fn hover_on_create_temp_table_definition() {
1673 assert_snapshot!(check_hover("
1674create temp table t$0(x bigint);
1675"), @r"
1676 hover: table pg_temp.t(x bigint)
1677 ╭▸
1678 2 │ create temp table t(x bigint);
1679 ╰╴ ─ hover
1680 ");
1681 }
1682
1683 #[test]
1684 fn hover_on_column_in_create_table() {
1685 assert_snapshot!(check_hover("
1686create table t(id$0 int);
1687"), @r"
1688 hover: column public.t.id int
1689 ╭▸
1690 2 │ create table t(id int);
1691 ╰╴ ─ hover
1692 ");
1693 }
1694
1695 #[test]
1696 fn hover_on_column_in_create_table_with_schema() {
1697 assert_snapshot!(check_hover("
1698create table myschema.users(id$0 int, name text);
1699"), @r"
1700 hover: column myschema.users.id int
1701 ╭▸
1702 2 │ create table myschema.users(id int, name text);
1703 ╰╴ ─ hover
1704 ");
1705 }
1706
1707 #[test]
1708 fn hover_on_column_in_temp_table() {
1709 assert_snapshot!(check_hover("
1710create temp table t(x$0 bigint);
1711"), @r"
1712 hover: column pg_temp.t.x bigint
1713 ╭▸
1714 2 │ create temp table t(x bigint);
1715 ╰╴ ─ hover
1716 ");
1717 }
1718
1719 #[test]
1720 fn hover_on_multiple_columns() {
1721 assert_snapshot!(check_hover("
1722create table t(id int, email$0 text, name varchar(100));
1723"), @r"
1724 hover: column public.t.email text
1725 ╭▸
1726 2 │ create table t(id int, email text, name varchar(100));
1727 ╰╴ ─ hover
1728 ");
1729 }
1730
1731 #[test]
1732 fn hover_on_drop_table() {
1733 assert_snapshot!(check_hover("
1734create table users(id int, email text);
1735drop table users$0;
1736"), @r"
1737 hover: table public.users(id int, email text)
1738 ╭▸
1739 3 │ drop table users;
1740 ╰╴ ─ hover
1741 ");
1742 }
1743
1744 #[test]
1745 fn hover_on_drop_table_with_schema() {
1746 assert_snapshot!(check_hover("
1747create table myschema.users(id int);
1748drop table myschema.users$0;
1749"), @r"
1750 hover: table myschema.users(id int)
1751 ╭▸
1752 3 │ drop table myschema.users;
1753 ╰╴ ─ hover
1754 ");
1755 }
1756
1757 #[test]
1758 fn hover_on_drop_temp_table() {
1759 assert_snapshot!(check_hover("
1760create temp table t(x bigint);
1761drop table t$0;
1762"), @r"
1763 hover: table pg_temp.t(x bigint)
1764 ╭▸
1765 3 │ drop table t;
1766 ╰╴ ─ hover
1767 ");
1768 }
1769
1770 #[test]
1771 fn hover_on_create_index_definition() {
1772 assert_snapshot!(check_hover("
1773create table t(x bigint);
1774create index idx$0 on t(x);
1775"), @r"
1776 hover: index public.idx on public.t(x)
1777 ╭▸
1778 3 │ create index idx on t(x);
1779 ╰╴ ─ hover
1780 ");
1781 }
1782
1783 #[test]
1784 fn hover_on_drop_index() {
1785 assert_snapshot!(check_hover("
1786create table t(x bigint);
1787create index idx_x on t(x);
1788drop index idx_x$0;
1789"), @r"
1790 hover: index public.idx_x on public.t(x)
1791 ╭▸
1792 4 │ drop index idx_x;
1793 ╰╴ ─ hover
1794 ");
1795 }
1796
1797 #[test]
1798 fn hover_on_create_type_definition() {
1799 assert_snapshot!(check_hover("
1800create type status$0 as enum ('active', 'inactive');
1801"), @r"
1802 hover: type public.status as enum ('active', 'inactive')
1803 ╭▸
1804 2 │ create type status as enum ('active', 'inactive');
1805 ╰╴ ─ hover
1806 ");
1807 }
1808
1809 #[test]
1810 fn hover_on_create_type_definition_with_schema() {
1811 assert_snapshot!(check_hover("
1812create type myschema.status$0 as enum ('active', 'inactive');
1813"), @r"
1814 hover: type myschema.status as enum ('active', 'inactive')
1815 ╭▸
1816 2 │ create type myschema.status as enum ('active', 'inactive');
1817 ╰╴ ─ hover
1818 ");
1819 }
1820
1821 #[test]
1822 fn hover_on_drop_type() {
1823 assert_snapshot!(check_hover("
1824create type status as enum ('active', 'inactive');
1825drop type status$0;
1826"), @r"
1827 hover: type public.status as enum ('active', 'inactive')
1828 ╭▸
1829 3 │ drop type status;
1830 ╰╴ ─ hover
1831 ");
1832 }
1833
1834 #[test]
1835 fn hover_on_drop_type_with_schema() {
1836 assert_snapshot!(check_hover("
1837create type myschema.status as enum ('active', 'inactive');
1838drop type myschema.status$0;
1839"), @r"
1840 hover: type myschema.status as enum ('active', 'inactive')
1841 ╭▸
1842 3 │ drop type myschema.status;
1843 ╰╴ ─ hover
1844 ");
1845 }
1846
1847 #[test]
1848 fn hover_on_create_type_composite() {
1849 assert_snapshot!(check_hover("
1850create type person$0 as (name text, age int);
1851"), @r"
1852 hover: type public.person as (name text, age int)
1853 ╭▸
1854 2 │ create type person as (name text, age int);
1855 ╰╴ ─ hover
1856 ");
1857 }
1858
1859 #[test]
1860 fn hover_on_drop_type_composite() {
1861 assert_snapshot!(check_hover("
1862create type person as (name text, age int);
1863drop type person$0;
1864"), @r"
1865 hover: type public.person as (name text, age int)
1866 ╭▸
1867 3 │ drop type person;
1868 ╰╴ ─ hover
1869 ");
1870 }
1871
1872 #[test]
1873 fn hover_on_create_type_range() {
1874 assert_snapshot!(check_hover("
1875create type int4_range$0 as range (subtype = int4);
1876"), @r"
1877 hover: type public.int4_range (subtype = int4)
1878 ╭▸
1879 2 │ create type int4_range as range (subtype = int4);
1880 ╰╴ ─ hover
1881 ");
1882 }
1883
1884 #[test]
1885 fn hover_on_drop_type_range() {
1886 assert_snapshot!(check_hover("
1887create type int4_range as range (subtype = int4);
1888drop type int4_range$0;
1889"), @r"
1890 hover: type public.int4_range (subtype = int4)
1891 ╭▸
1892 3 │ drop type int4_range;
1893 ╰╴ ─ hover
1894 ");
1895 }
1896
1897 #[test]
1898 fn hover_on_cast_operator() {
1899 assert_snapshot!(check_hover("
1900create type foo as enum ('a', 'b');
1901select x::foo$0;
1902"), @r"
1903 hover: type public.foo as enum ('a', 'b')
1904 ╭▸
1905 3 │ select x::foo;
1906 ╰╴ ─ hover
1907 ");
1908 }
1909
1910 #[test]
1911 fn hover_on_cast_function() {
1912 assert_snapshot!(check_hover("
1913create type bar as enum ('x', 'y');
1914select cast(x as bar$0);
1915"), @r"
1916 hover: type public.bar as enum ('x', 'y')
1917 ╭▸
1918 3 │ select cast(x as bar);
1919 ╰╴ ─ hover
1920 ");
1921 }
1922
1923 #[test]
1924 fn hover_on_cast_with_schema() {
1925 assert_snapshot!(check_hover("
1926create type myschema.baz as enum ('m', 'n');
1927select x::myschema.baz$0;
1928"), @r"
1929 hover: type myschema.baz as enum ('m', 'n')
1930 ╭▸
1931 3 │ select x::myschema.baz;
1932 ╰╴ ─ hover
1933 ");
1934 }
1935
1936 #[test]
1937 fn hover_on_drop_function() {
1938 assert_snapshot!(check_hover("
1939create function foo() returns int as $$ select 1 $$ language sql;
1940drop function foo$0();
1941"), @r"
1942 hover: function public.foo() returns int
1943 ╭▸
1944 3 │ drop function foo();
1945 ╰╴ ─ hover
1946 ");
1947 }
1948
1949 #[test]
1950 fn hover_on_drop_function_with_schema() {
1951 assert_snapshot!(check_hover("
1952create function myschema.foo() returns int as $$ select 1 $$ language sql;
1953drop function myschema.foo$0();
1954"), @r"
1955 hover: function myschema.foo() returns int
1956 ╭▸
1957 3 │ drop function myschema.foo();
1958 ╰╴ ─ hover
1959 ");
1960 }
1961
1962 #[test]
1963 fn hover_on_create_function_definition() {
1964 assert_snapshot!(check_hover("
1965create function foo$0() returns int as $$ select 1 $$ language sql;
1966"), @r"
1967 hover: function public.foo() returns int
1968 ╭▸
1969 2 │ create function foo() returns int as $$ select 1 $$ language sql;
1970 ╰╴ ─ hover
1971 ");
1972 }
1973
1974 #[test]
1975 fn hover_on_create_function_with_explicit_schema() {
1976 assert_snapshot!(check_hover("
1977create function myschema.foo$0() returns int as $$ select 1 $$ language sql;
1978"), @r"
1979 hover: function myschema.foo() returns int
1980 ╭▸
1981 2 │ create function myschema.foo() returns int as $$ select 1 $$ language sql;
1982 ╰╴ ─ hover
1983 ");
1984 }
1985
1986 #[test]
1987 fn hover_on_drop_function_with_search_path() {
1988 assert_snapshot!(check_hover(r#"
1989set search_path to myschema;
1990create function foo() returns int as $$ select 1 $$ language sql;
1991drop function foo$0();
1992"#), @r"
1993 hover: function myschema.foo() returns int
1994 ╭▸
1995 4 │ drop function foo();
1996 ╰╴ ─ hover
1997 ");
1998 }
1999
2000 #[test]
2001 fn hover_on_drop_function_overloaded() {
2002 assert_snapshot!(check_hover("
2003create function add(complex) returns complex as $$ select null $$ language sql;
2004create function add(bigint) returns bigint as $$ select 1 $$ language sql;
2005drop function add$0(complex);
2006"), @r"
2007 hover: function public.add(complex) returns complex
2008 ╭▸
2009 4 │ drop function add(complex);
2010 ╰╴ ─ hover
2011 ");
2012 }
2013
2014 #[test]
2015 fn hover_on_drop_function_second_overload() {
2016 assert_snapshot!(check_hover("
2017create function add(complex) returns complex as $$ select null $$ language sql;
2018create function add(bigint) returns bigint as $$ select 1 $$ language sql;
2019drop function add$0(bigint);
2020"), @r"
2021 hover: function public.add(bigint) returns bigint
2022 ╭▸
2023 4 │ drop function add(bigint);
2024 ╰╴ ─ hover
2025 ");
2026 }
2027
2028 #[test]
2029 fn hover_on_drop_aggregate() {
2030 assert_snapshot!(check_hover("
2031create aggregate myavg(int) (sfunc = int4_avg_accum, stype = _int8);
2032drop aggregate myavg$0(int);
2033"), @r"
2034 hover: aggregate public.myavg(int)
2035 ╭▸
2036 3 │ drop aggregate myavg(int);
2037 ╰╴ ─ hover
2038 ");
2039 }
2040
2041 #[test]
2042 fn hover_on_drop_aggregate_with_schema() {
2043 assert_snapshot!(check_hover("
2044create aggregate myschema.myavg(int) (sfunc = int4_avg_accum, stype = _int8);
2045drop aggregate myschema.myavg$0(int);
2046"), @r"
2047 hover: aggregate myschema.myavg(int)
2048 ╭▸
2049 3 │ drop aggregate myschema.myavg(int);
2050 ╰╴ ─ hover
2051 ");
2052 }
2053
2054 #[test]
2055 fn hover_on_create_aggregate_definition() {
2056 assert_snapshot!(check_hover("
2057create aggregate myavg$0(int) (sfunc = int4_avg_accum, stype = _int8);
2058"), @r"
2059 hover: aggregate public.myavg(int)
2060 ╭▸
2061 2 │ create aggregate myavg(int) (sfunc = int4_avg_accum, stype = _int8);
2062 ╰╴ ─ hover
2063 ");
2064 }
2065
2066 #[test]
2067 fn hover_on_drop_aggregate_with_search_path() {
2068 assert_snapshot!(check_hover(r#"
2069set search_path to myschema;
2070create aggregate myavg(int) (sfunc = int4_avg_accum, stype = _int8);
2071drop aggregate myavg$0(int);
2072"#), @r"
2073 hover: aggregate myschema.myavg(int)
2074 ╭▸
2075 4 │ drop aggregate myavg(int);
2076 ╰╴ ─ hover
2077 ");
2078 }
2079
2080 #[test]
2081 fn hover_on_drop_aggregate_overloaded() {
2082 assert_snapshot!(check_hover("
2083create aggregate sum(complex) (sfunc = complex_add, stype = complex, initcond = '(0,0)');
2084create aggregate sum(bigint) (sfunc = bigint_add, stype = bigint, initcond = '0');
2085drop aggregate sum$0(complex);
2086"), @r"
2087 hover: aggregate public.sum(complex)
2088 ╭▸
2089 4 │ drop aggregate sum(complex);
2090 ╰╴ ─ hover
2091 ");
2092 }
2093
2094 #[test]
2095 fn hover_on_drop_aggregate_second_overload() {
2096 assert_snapshot!(check_hover("
2097create aggregate sum(complex) (sfunc = complex_add, stype = complex, initcond = '(0,0)');
2098create aggregate sum(bigint) (sfunc = bigint_add, stype = bigint, initcond = '0');
2099drop aggregate sum$0(bigint);
2100"), @r"
2101 hover: aggregate public.sum(bigint)
2102 ╭▸
2103 4 │ drop aggregate sum(bigint);
2104 ╰╴ ─ hover
2105 ");
2106 }
2107
2108 #[test]
2109 fn hover_on_select_function_call() {
2110 assert_snapshot!(check_hover("
2111create function foo() returns int as $$ select 1 $$ language sql;
2112select foo$0();
2113"), @r"
2114 hover: function public.foo() returns int
2115 ╭▸
2116 3 │ select foo();
2117 ╰╴ ─ hover
2118 ");
2119 }
2120
2121 #[test]
2122 fn hover_on_select_function_call_with_schema() {
2123 assert_snapshot!(check_hover("
2124create function public.foo() returns int as $$ select 1 $$ language sql;
2125select public.foo$0();
2126"), @r"
2127 hover: function public.foo() returns int
2128 ╭▸
2129 3 │ select public.foo();
2130 ╰╴ ─ hover
2131 ");
2132 }
2133
2134 #[test]
2135 fn hover_on_select_function_call_with_search_path() {
2136 assert_snapshot!(check_hover(r#"
2137set search_path to myschema;
2138create function foo() returns int as $$ select 1 $$ language sql;
2139select foo$0();
2140"#), @r"
2141 hover: function myschema.foo() returns int
2142 ╭▸
2143 4 │ select foo();
2144 ╰╴ ─ hover
2145 ");
2146 }
2147
2148 #[test]
2149 fn hover_on_select_function_call_with_params() {
2150 assert_snapshot!(check_hover("
2151create function add(a int, b int) returns int as $$ select a + b $$ language sql;
2152select add$0(1, 2);
2153"), @r"
2154 hover: function public.add(a int, b int) returns int
2155 ╭▸
2156 3 │ select add(1, 2);
2157 ╰╴ ─ hover
2158 ");
2159 }
2160
2161 #[test]
2162 fn hover_on_named_arg_param() {
2163 assert_snapshot!(check_hover("
2164create function foo(bar_param int) returns int as $$ select 1 $$ language sql;
2165select foo(bar_param$0 := 5);
2166"), @r"
2167 hover: parameter public.foo.bar_param int
2168 ╭▸
2169 3 │ select foo(bar_param := 5);
2170 ╰╴ ─ hover
2171 ");
2172 }
2173
2174 #[test]
2175 fn hover_on_named_arg_param_schema_qualified() {
2176 assert_snapshot!(check_hover("
2177create schema s;
2178create function s.foo(my_param int) returns int as $$ select 1 $$ language sql;
2179select s.foo(my_param$0 := 10);
2180"), @r"
2181 hover: parameter s.foo.my_param int
2182 ╭▸
2183 4 │ select s.foo(my_param := 10);
2184 ╰╴ ─ hover
2185 ");
2186 }
2187
2188 #[test]
2189 fn hover_on_named_arg_param_procedure() {
2190 assert_snapshot!(check_hover("
2191create procedure proc(param_x int) as 'select 1' language sql;
2192call proc(param_x$0 := 42);
2193"), @r"
2194 hover: parameter public.proc.param_x int
2195 ╭▸
2196 3 │ call proc(param_x := 42);
2197 ╰╴ ─ hover
2198 ");
2199 }
2200
2201 #[test]
2202 fn hover_on_function_call_style_column_access() {
2203 assert_snapshot!(check_hover("
2204create table t(a int, b int);
2205select a$0(t) from t;
2206"), @r"
2207 hover: column public.t.a int
2208 ╭▸
2209 3 │ select a(t) from t;
2210 ╰╴ ─ hover
2211 ");
2212 }
2213
2214 #[test]
2215 fn hover_on_function_call_style_column_access_with_function_precedence() {
2216 assert_snapshot!(check_hover("
2217create table t(a int, b int);
2218create function b(t) returns int as 'select 1' LANGUAGE sql;
2219select b$0(t) from t;
2220"), @r"
2221 hover: function public.b(t) returns int
2222 ╭▸
2223 4 │ select b(t) from t;
2224 ╰╴ ─ hover
2225 ");
2226 }
2227
2228 #[test]
2229 fn hover_on_function_call_style_table_arg() {
2230 assert_snapshot!(check_hover("
2231create table t(a int, b int);
2232select a(t$0) from t;
2233"), @r"
2234 hover: table public.t(a int, b int)
2235 ╭▸
2236 3 │ select a(t) from t;
2237 ╰╴ ─ hover
2238 ");
2239 }
2240
2241 #[test]
2242 fn hover_on_function_call_style_table_arg_with_function() {
2243 assert_snapshot!(check_hover("
2244create table t(a int, b int);
2245create function b(t) returns int as 'select 1' LANGUAGE sql;
2246select b(t$0) from t;
2247"), @r"
2248 hover: table public.t(a int, b int)
2249 ╭▸
2250 4 │ select b(t) from t;
2251 ╰╴ ─ hover
2252 ");
2253 }
2254
2255 #[test]
2256 fn hover_on_function_call_style_table_arg_in_where() {
2257 assert_snapshot!(check_hover("
2258create table t(a int);
2259select * from t where a(t$0) > 2;
2260"), @r"
2261 hover: table public.t(a int)
2262 ╭▸
2263 3 │ select * from t where a(t) > 2;
2264 ╰╴ ─ hover
2265 ");
2266 }
2267
2268 #[test]
2269 fn hover_on_qualified_table_ref_in_where() {
2270 assert_snapshot!(check_hover("
2271create table t(a int);
2272create function b(t) returns int as 'select 1' language sql;
2273select * from t where t$0.b > 2;
2274"), @r"
2275 hover: table public.t(a int)
2276 ╭▸
2277 4 │ select * from t where t.b > 2;
2278 ╰╴ ─ hover
2279 ");
2280 }
2281
2282 #[test]
2283 fn hover_on_field_style_function_call() {
2284 assert_snapshot!(check_hover("
2285create table t(a int);
2286create function b(t) returns int as 'select 1' language sql;
2287select t.b$0 from t;
2288"), @r"
2289 hover: function public.b(t) returns int
2290 ╭▸
2291 4 │ select t.b from t;
2292 ╰╴ ─ hover
2293 ");
2294 }
2295
2296 #[test]
2297 fn hover_on_field_style_function_call_column_precedence() {
2298 assert_snapshot!(check_hover("
2299create table t(a int, b int);
2300create function b(t) returns int as 'select 1' language sql;
2301select t.b$0 from t;
2302"), @r"
2303 hover: column public.t.b int
2304 ╭▸
2305 4 │ select t.b from t;
2306 ╰╴ ─ hover
2307 ");
2308 }
2309
2310 #[test]
2311 fn hover_on_field_style_function_call_table_ref() {
2312 assert_snapshot!(check_hover("
2313create table t(a int);
2314create function b(t) returns int as 'select 1' language sql;
2315select t$0.b from t;
2316"), @r"
2317 hover: table public.t(a int)
2318 ╭▸
2319 4 │ select t.b from t;
2320 ╰╴ ─ hover
2321 ");
2322 }
2323
2324 #[test]
2325 fn hover_on_select_from_table() {
2326 assert_snapshot!(check_hover("
2327create table users(id int, email text);
2328select * from users$0;
2329"), @r"
2330 hover: table public.users(id int, email text)
2331 ╭▸
2332 3 │ select * from users;
2333 ╰╴ ─ hover
2334 ");
2335 }
2336
2337 #[test]
2338 fn hover_on_subquery_qualified_table_ref() {
2339 assert_snapshot!(check_hover("
2340select t$0.a from (select 1 a) t;
2341"), @r"
2342 hover: subquery t as (select 1 a)
2343 ╭▸
2344 2 │ select t.a from (select 1 a) t;
2345 ╰╴ ─ hover
2346 ");
2347 }
2348
2349 #[test]
2350 fn hover_on_subquery_qualified_column_ref() {
2351 assert_snapshot!(check_hover("
2352select t.a$0 from (select 1 a) t;
2353"), @r"
2354 hover: column t.a
2355 ╭▸
2356 2 │ select t.a from (select 1 a) t;
2357 ╰╴ ─ hover
2358 ");
2359 }
2360
2361 #[test]
2362 fn hover_on_select_from_table_with_schema() {
2363 assert_snapshot!(check_hover("
2364create table public.users(id int, email text);
2365select * from public.users$0;
2366"), @r"
2367 hover: table public.users(id int, email text)
2368 ╭▸
2369 3 │ select * from public.users;
2370 ╰╴ ─ hover
2371 ");
2372 }
2373
2374 #[test]
2375 fn hover_on_select_from_table_with_search_path() {
2376 assert_snapshot!(check_hover("
2377set search_path to foo;
2378create table foo.users(id int, email text);
2379select * from users$0;
2380"), @r"
2381 hover: table foo.users(id int, email text)
2382 ╭▸
2383 4 │ select * from users;
2384 ╰╴ ─ hover
2385 ");
2386 }
2387
2388 #[test]
2389 fn hover_on_select_from_temp_table() {
2390 assert_snapshot!(check_hover("
2391create temp table users(id int, email text);
2392select * from users$0;
2393"), @r"
2394 hover: table pg_temp.users(id int, email text)
2395 ╭▸
2396 3 │ select * from users;
2397 ╰╴ ─ hover
2398 ");
2399 }
2400
2401 #[test]
2402 fn hover_on_select_from_multiline_table() {
2403 assert_snapshot!(check_hover("
2404create table users(
2405 id int,
2406 email text,
2407 name varchar(100)
2408);
2409select * from users$0;
2410"), @r"
2411 hover: table public.users(
2412 id int,
2413 email text,
2414 name varchar(100)
2415 )
2416 ╭▸
2417 7 │ select * from users;
2418 ╰╴ ─ hover
2419 ");
2420 }
2421
2422 #[test]
2423 fn hover_on_select_column() {
2424 assert_snapshot!(check_hover("
2425create table users(id int, email text);
2426select id$0 from users;
2427"), @r"
2428 hover: column public.users.id int
2429 ╭▸
2430 3 │ select id from users;
2431 ╰╴ ─ hover
2432 ");
2433 }
2434
2435 #[test]
2436 fn hover_on_select_column_second() {
2437 assert_snapshot!(check_hover("
2438create table users(id int, email text);
2439select id, email$0 from users;
2440"), @r"
2441 hover: column public.users.email text
2442 ╭▸
2443 3 │ select id, email from users;
2444 ╰╴ ─ hover
2445 ");
2446 }
2447
2448 #[test]
2449 fn hover_on_select_column_with_schema() {
2450 assert_snapshot!(check_hover("
2451create table public.users(id int, email text);
2452select email$0 from public.users;
2453"), @r"
2454 hover: column public.users.email text
2455 ╭▸
2456 3 │ select email from public.users;
2457 ╰╴ ─ hover
2458 ");
2459 }
2460
2461 #[test]
2462 fn hover_on_select_column_with_search_path() {
2463 assert_snapshot!(check_hover("
2464set search_path to foo;
2465create table foo.users(id int, email text);
2466select id$0 from users;
2467"), @r"
2468 hover: column foo.users.id int
2469 ╭▸
2470 4 │ select id from users;
2471 ╰╴ ─ hover
2472 ");
2473 }
2474
2475 #[test]
2476 fn hover_on_select_qualified_star() {
2477 assert_snapshot!(check_hover("
2478create table u(id int, b int);
2479select u.*$0 from u;
2480"), @r"
2481 hover: column public.u.id int
2482 column public.u.b int
2483 ╭▸
2484 3 │ select u.* from u;
2485 ╰╴ ─ hover
2486 ");
2487 }
2488
2489 #[test]
2490 fn hover_on_select_unqualified_star() {
2491 assert_snapshot!(check_hover("
2492create table u(id int, b int);
2493select *$0 from u;
2494"), @r"
2495 hover: column public.u.id int
2496 column public.u.b int
2497 ╭▸
2498 3 │ select * from u;
2499 ╰╴ ─ hover
2500 ");
2501 }
2502
2503 #[test]
2504 fn hover_on_select_count_star() {
2505 assert_snapshot!(check_hover("
2506create table u(id int, b int);
2507select count(*$0) from u;
2508"), @r"
2509 hover: column public.u.id int
2510 column public.u.b int
2511 ╭▸
2512 3 │ select count(*) from u;
2513 ╰╴ ─ hover
2514 ");
2515 }
2516
2517 #[test]
2518 fn hover_on_insert_table() {
2519 assert_snapshot!(check_hover("
2520create table users(id int, email text);
2521insert into users$0(id, email) values (1, 'test');
2522"), @r"
2523 hover: table public.users(id int, email text)
2524 ╭▸
2525 3 │ insert into users(id, email) values (1, 'test');
2526 ╰╴ ─ hover
2527 ");
2528 }
2529
2530 #[test]
2531 fn hover_on_insert_table_with_schema() {
2532 assert_snapshot!(check_hover("
2533create table public.users(id int, email text);
2534insert into public.users$0(id, email) values (1, 'test');
2535"), @r"
2536 hover: table public.users(id int, email text)
2537 ╭▸
2538 3 │ insert into public.users(id, email) values (1, 'test');
2539 ╰╴ ─ hover
2540 ");
2541 }
2542
2543 #[test]
2544 fn hover_on_insert_column() {
2545 assert_snapshot!(check_hover("
2546create table users(id int, email text);
2547insert into users(id$0, email) values (1, 'test');
2548"), @r"
2549 hover: column public.users.id int
2550 ╭▸
2551 3 │ insert into users(id, email) values (1, 'test');
2552 ╰╴ ─ hover
2553 ");
2554 }
2555
2556 #[test]
2557 fn hover_on_insert_column_second() {
2558 assert_snapshot!(check_hover("
2559create table users(id int, email text);
2560insert into users(id, email$0) values (1, 'test');
2561"), @r"
2562 hover: column public.users.email text
2563 ╭▸
2564 3 │ insert into users(id, email) values (1, 'test');
2565 ╰╴ ─ hover
2566 ");
2567 }
2568
2569 #[test]
2570 fn hover_on_insert_column_with_schema() {
2571 assert_snapshot!(check_hover("
2572create table public.users(id int, email text);
2573insert into public.users(email$0) values ('test');
2574"), @r"
2575 hover: column public.users.email text
2576 ╭▸
2577 3 │ insert into public.users(email) values ('test');
2578 ╰╴ ─ hover
2579 ");
2580 }
2581
2582 #[test]
2583 fn hover_on_delete_table() {
2584 assert_snapshot!(check_hover("
2585create table users(id int, email text);
2586delete from users$0 where id = 1;
2587"), @r"
2588 hover: table public.users(id int, email text)
2589 ╭▸
2590 3 │ delete from users where id = 1;
2591 ╰╴ ─ hover
2592 ");
2593 }
2594
2595 #[test]
2596 fn hover_on_delete_table_with_schema() {
2597 assert_snapshot!(check_hover("
2598create table public.users(id int, email text);
2599delete from public.users$0 where id = 1;
2600"), @r"
2601 hover: table public.users(id int, email text)
2602 ╭▸
2603 3 │ delete from public.users where id = 1;
2604 ╰╴ ─ hover
2605 ");
2606 }
2607
2608 #[test]
2609 fn hover_on_delete_where_column() {
2610 assert_snapshot!(check_hover("
2611create table users(id int, email text);
2612delete from users where id$0 = 1;
2613"), @r"
2614 hover: column public.users.id int
2615 ╭▸
2616 3 │ delete from users where id = 1;
2617 ╰╴ ─ hover
2618 ");
2619 }
2620
2621 #[test]
2622 fn hover_on_delete_where_column_second() {
2623 assert_snapshot!(check_hover("
2624create table users(id int, email text, active boolean);
2625delete from users where id = 1 and email$0 = 'test';
2626"), @r"
2627 hover: column public.users.email text
2628 ╭▸
2629 3 │ delete from users where id = 1 and email = 'test';
2630 ╰╴ ─ hover
2631 ");
2632 }
2633
2634 #[test]
2635 fn hover_on_delete_where_column_with_schema() {
2636 assert_snapshot!(check_hover("
2637create table public.users(id int, email text);
2638delete from public.users where email$0 = 'test';
2639"), @r"
2640 hover: column public.users.email text
2641 ╭▸
2642 3 │ delete from public.users where email = 'test';
2643 ╰╴ ─ hover
2644 ");
2645 }
2646
2647 #[test]
2648 fn hover_on_select_table_as_column() {
2649 assert_snapshot!(check_hover("
2650create table t(x bigint, y bigint);
2651select t$0 from t;
2652"), @r"
2653 hover: table public.t(x bigint, y bigint)
2654 ╭▸
2655 3 │ select t from t;
2656 ╰╴ ─ hover
2657 ");
2658 }
2659
2660 #[test]
2661 fn hover_on_select_table_as_column_with_schema() {
2662 assert_snapshot!(check_hover("
2663create table public.t(x bigint, y bigint);
2664select t$0 from public.t;
2665"), @r"
2666 hover: table public.t(x bigint, y bigint)
2667 ╭▸
2668 3 │ select t from public.t;
2669 ╰╴ ─ hover
2670 ");
2671 }
2672
2673 #[test]
2674 fn hover_on_select_table_as_column_with_search_path() {
2675 assert_snapshot!(check_hover("
2676set search_path to foo;
2677create table foo.users(id int, email text);
2678select users$0 from users;
2679"), @r"
2680 hover: table foo.users(id int, email text)
2681 ╭▸
2682 4 │ select users from users;
2683 ╰╴ ─ hover
2684 ");
2685 }
2686
2687 #[test]
2688 fn hover_on_select_column_with_same_name_as_table() {
2689 assert_snapshot!(check_hover("
2690create table t(t int);
2691select t$0 from t;
2692"), @r"
2693 hover: column public.t.t int
2694 ╭▸
2695 3 │ select t from t;
2696 ╰╴ ─ hover
2697 ");
2698 }
2699
2700 #[test]
2701 fn hover_on_create_schema() {
2702 assert_snapshot!(check_hover("
2703create schema foo$0;
2704"), @r"
2705 hover: schema foo
2706 ╭▸
2707 2 │ create schema foo;
2708 ╰╴ ─ hover
2709 ");
2710 }
2711
2712 #[test]
2713 fn hover_on_create_schema_authorization() {
2714 assert_snapshot!(check_hover("
2715create schema authorization foo$0;
2716"), @r"
2717 hover: schema foo
2718 ╭▸
2719 2 │ create schema authorization foo;
2720 ╰╴ ─ hover
2721 ");
2722 }
2723
2724 #[test]
2725 fn hover_on_drop_schema_authorization() {
2726 assert_snapshot!(check_hover("
2727create schema authorization foo;
2728drop schema foo$0;
2729"), @r"
2730 hover: schema foo
2731 ╭▸
2732 3 │ drop schema foo;
2733 ╰╴ ─ hover
2734 ");
2735 }
2736
2737 #[test]
2738 fn hover_on_drop_schema() {
2739 assert_snapshot!(check_hover("
2740create schema foo;
2741drop schema foo$0;
2742"), @r"
2743 hover: schema foo
2744 ╭▸
2745 3 │ drop schema foo;
2746 ╰╴ ─ hover
2747 ");
2748 }
2749
2750 #[test]
2751 fn hover_on_schema_after_definition() {
2752 assert_snapshot!(check_hover("
2753drop schema foo$0;
2754create schema foo;
2755"), @r"
2756 hover: schema foo
2757 ╭▸
2758 2 │ drop schema foo;
2759 ╰╴ ─ hover
2760 ");
2761 }
2762
2763 #[test]
2764 fn hover_on_cte_table() {
2765 assert_snapshot!(check_hover("
2766with t as (select 1 a)
2767select a from t$0;
2768"), @r"
2769 hover: with t as (select 1 a)
2770 ╭▸
2771 3 │ select a from t;
2772 ╰╴ ─ hover
2773 ");
2774 }
2775
2776 #[test]
2777 fn hover_on_cte_column() {
2778 assert_snapshot!(check_hover("
2779with t as (select 1 a)
2780select a$0 from t;
2781"), @r"
2782 hover: column t.a
2783 ╭▸
2784 3 │ select a from t;
2785 ╰╴ ─ hover
2786 ");
2787 }
2788
2789 #[test]
2790 fn hover_on_cte_with_multiple_columns() {
2791 assert_snapshot!(check_hover("
2792with t as (select 1 a, 2 b)
2793select b$0 from t;
2794"), @r"
2795 hover: column t.b
2796 ╭▸
2797 3 │ select b from t;
2798 ╰╴ ─ hover
2799 ");
2800 }
2801
2802 #[test]
2803 fn hover_on_cte_with_column_list() {
2804 assert_snapshot!(check_hover("
2805with t(a) as (select 1)
2806select a$0 from t;
2807"), @r"
2808 hover: column t.a
2809 ╭▸
2810 3 │ select a from t;
2811 ╰╴ ─ hover
2812 ");
2813 }
2814
2815 #[test]
2816 fn hover_on_nested_cte() {
2817 assert_snapshot!(check_hover("
2818with x as (select 1 a),
2819 y as (select a from x)
2820select a$0 from y;
2821"), @r"
2822 hover: column y.a
2823 ╭▸
2824 4 │ select a from y;
2825 ╰╴ ─ hover
2826 ");
2827 }
2828
2829 #[test]
2830 fn hover_on_cte_shadowing_table_with_star() {
2831 assert_snapshot!(check_hover("
2832create table t(a bigint);
2833with t as (select * from t)
2834select a$0 from t;
2835"), @r"
2836 hover: column public.t.a bigint
2837 ╭▸
2838 4 │ select a from t;
2839 ╰╴ ─ hover
2840 ");
2841 }
2842
2843 #[test]
2844 fn hover_on_cte_definition() {
2845 assert_snapshot!(check_hover("
2846with t$0 as (select 1 a)
2847select a from t;
2848"), @r"
2849 hover: with t as (select 1 a)
2850 ╭▸
2851 2 │ with t as (select 1 a)
2852 ╰╴ ─ hover
2853 ");
2854 }
2855
2856 #[test]
2857 fn hover_on_cte_values_column1() {
2858 assert_snapshot!(check_hover("
2859with t as (
2860 values (1, 2), (3, 4)
2861)
2862select column1$0, column2 from t;
2863"), @r"
2864 hover: column t.column1
2865 ╭▸
2866 5 │ select column1, column2 from t;
2867 ╰╴ ─ hover
2868 ");
2869 }
2870
2871 #[test]
2872 fn hover_on_cte_values_column2() {
2873 assert_snapshot!(check_hover("
2874with t as (
2875 values (1, 2), (3, 4)
2876)
2877select column1, column2$0 from t;
2878"), @r"
2879 hover: column t.column2
2880 ╭▸
2881 5 │ select column1, column2 from t;
2882 ╰╴ ─ hover
2883 ");
2884 }
2885
2886 #[test]
2887 fn hover_on_cte_values_single_column() {
2888 assert_snapshot!(check_hover("
2889with t as (
2890 values (1), (2), (3)
2891)
2892select column1$0 from t;
2893"), @r"
2894 hover: column t.column1
2895 ╭▸
2896 5 │ select column1 from t;
2897 ╰╴ ─ hover
2898 ");
2899 }
2900
2901 #[test]
2902 fn hover_on_cte_values_uppercase_column_names() {
2903 assert_snapshot!(check_hover("
2904with t as (
2905 values (1, 2), (3, 4)
2906)
2907select COLUMN1$0, COLUMN2 from t;
2908"), @r"
2909 hover: column t.column1
2910 ╭▸
2911 5 │ select COLUMN1, COLUMN2 from t;
2912 ╰╴ ─ hover
2913 ");
2914 }
2915
2916 #[test]
2917 fn hover_on_cte_qualified_star() {
2918 assert_snapshot!(check_hover("
2919with u as (select 1 id, 2 b)
2920select u.*$0 from u;
2921"), @r"
2922 hover: column u.id
2923 column u.b
2924 ╭▸
2925 3 │ select u.* from u;
2926 ╰╴ ─ hover
2927 ");
2928 }
2929
2930 #[test]
2931 fn hover_on_cte_values_qualified_star() {
2932 assert_snapshot!(check_hover("
2933with t as (values (1, 2), (3, 4))
2934select t.*$0 from t;
2935"), @r"
2936 hover: column t.column1
2937 column t.column2
2938 ╭▸
2939 3 │ select t.* from t;
2940 ╰╴ ─ hover
2941 ");
2942 }
2943
2944 #[test]
2945 fn hover_on_star_with_subquery_from_cte() {
2946 assert_snapshot!(check_hover("
2947with u as (select 1 id, 2 b)
2948select *$0 from (select *, *, * from u);
2949"), @r"
2950 hover: column u.id
2951 column u.b
2952 column u.id
2953 column u.b
2954 column u.id
2955 column u.b
2956 ╭▸
2957 3 │ select * from (select *, *, * from u);
2958 ╰╴ ─ hover
2959 ");
2960 }
2961
2962 #[test]
2963 fn hover_on_star_with_subquery_from_table() {
2964 assert_snapshot!(check_hover("
2965create table t(a int, b int);
2966select *$0 from (select a from t);
2967"), @r"
2968 hover: column public.t.a int
2969 ╭▸
2970 3 │ select * from (select a from t);
2971 ╰╴ ─ hover
2972 ");
2973 }
2974
2975 #[test]
2976 fn hover_on_star_with_subquery_literal() {
2977 assert_snapshot!(check_hover("
2978select *$0 from (select 1);
2979"), @r"
2980 hover: column ?column?
2981 ╭▸
2982 2 │ select * from (select 1);
2983 ╰╴ ─ hover
2984 ");
2985 }
2986
2987 #[test]
2988 fn hover_on_star_with_subquery_literal_with_alias() {
2989 assert_snapshot!(check_hover("
2990select *$0 from (select 1) as sub;
2991"), @r"
2992 hover: column sub.?column?
2993 ╭▸
2994 2 │ select * from (select 1) as sub;
2995 ╰╴ ─ hover
2996 ");
2997 }
2998
2999 #[test]
3000 fn hover_on_view_qualified_star() {
3001 assert_snapshot!(check_hover("
3002create view v as select 1 id, 2 b;
3003select v.*$0 from v;
3004"), @r"
3005 hover: column public.v.id
3006 column public.v.b
3007 ╭▸
3008 3 │ select v.* from v;
3009 ╰╴ ─ hover
3010 ");
3011 }
3012
3013 #[test]
3014 fn hover_on_drop_procedure() {
3015 assert_snapshot!(check_hover("
3016create procedure foo() language sql as $$ select 1 $$;
3017drop procedure foo$0();
3018"), @r"
3019 hover: procedure public.foo()
3020 ╭▸
3021 3 │ drop procedure foo();
3022 ╰╴ ─ hover
3023 ");
3024 }
3025
3026 #[test]
3027 fn hover_on_drop_procedure_with_schema() {
3028 assert_snapshot!(check_hover("
3029create procedure myschema.foo() language sql as $$ select 1 $$;
3030drop procedure myschema.foo$0();
3031"), @r"
3032 hover: procedure myschema.foo()
3033 ╭▸
3034 3 │ drop procedure myschema.foo();
3035 ╰╴ ─ hover
3036 ");
3037 }
3038
3039 #[test]
3040 fn hover_on_create_procedure_definition() {
3041 assert_snapshot!(check_hover("
3042create procedure foo$0() language sql as $$ select 1 $$;
3043"), @r"
3044 hover: procedure public.foo()
3045 ╭▸
3046 2 │ create procedure foo() language sql as $$ select 1 $$;
3047 ╰╴ ─ hover
3048 ");
3049 }
3050
3051 #[test]
3052 fn hover_on_create_procedure_with_explicit_schema() {
3053 assert_snapshot!(check_hover("
3054create procedure myschema.foo$0() language sql as $$ select 1 $$;
3055"), @r"
3056 hover: procedure myschema.foo()
3057 ╭▸
3058 2 │ create procedure myschema.foo() language sql as $$ select 1 $$;
3059 ╰╴ ─ hover
3060 ");
3061 }
3062
3063 #[test]
3064 fn hover_on_drop_procedure_with_search_path() {
3065 assert_snapshot!(check_hover(r#"
3066set search_path to myschema;
3067create procedure foo() language sql as $$ select 1 $$;
3068drop procedure foo$0();
3069"#), @r"
3070 hover: procedure myschema.foo()
3071 ╭▸
3072 4 │ drop procedure foo();
3073 ╰╴ ─ hover
3074 ");
3075 }
3076
3077 #[test]
3078 fn hover_on_drop_procedure_overloaded() {
3079 assert_snapshot!(check_hover("
3080create procedure add(complex) language sql as $$ select null $$;
3081create procedure add(bigint) language sql as $$ select 1 $$;
3082drop procedure add$0(complex);
3083"), @r"
3084 hover: procedure public.add(complex)
3085 ╭▸
3086 4 │ drop procedure add(complex);
3087 ╰╴ ─ hover
3088 ");
3089 }
3090
3091 #[test]
3092 fn hover_on_drop_procedure_second_overload() {
3093 assert_snapshot!(check_hover("
3094create procedure add(complex) language sql as $$ select null $$;
3095create procedure add(bigint) language sql as $$ select 1 $$;
3096drop procedure add$0(bigint);
3097"), @r"
3098 hover: procedure public.add(bigint)
3099 ╭▸
3100 4 │ drop procedure add(bigint);
3101 ╰╴ ─ hover
3102 ");
3103 }
3104
3105 #[test]
3106 fn hover_on_call_procedure() {
3107 assert_snapshot!(check_hover("
3108create procedure foo() language sql as $$ select 1 $$;
3109call foo$0();
3110"), @r"
3111 hover: procedure public.foo()
3112 ╭▸
3113 3 │ call foo();
3114 ╰╴ ─ hover
3115 ");
3116 }
3117
3118 #[test]
3119 fn hover_on_call_procedure_with_schema() {
3120 assert_snapshot!(check_hover("
3121create procedure public.foo() language sql as $$ select 1 $$;
3122call public.foo$0();
3123"), @r"
3124 hover: procedure public.foo()
3125 ╭▸
3126 3 │ call public.foo();
3127 ╰╴ ─ hover
3128 ");
3129 }
3130
3131 #[test]
3132 fn hover_on_call_procedure_with_search_path() {
3133 assert_snapshot!(check_hover(r#"
3134set search_path to myschema;
3135create procedure foo() language sql as $$ select 1 $$;
3136call foo$0();
3137"#), @r"
3138 hover: procedure myschema.foo()
3139 ╭▸
3140 4 │ call foo();
3141 ╰╴ ─ hover
3142 ");
3143 }
3144
3145 #[test]
3146 fn hover_on_call_procedure_with_params() {
3147 assert_snapshot!(check_hover("
3148create procedure add(a int, b int) language sql as $$ select a + b $$;
3149call add$0(1, 2);
3150"), @r"
3151 hover: procedure public.add(a int, b int)
3152 ╭▸
3153 3 │ call add(1, 2);
3154 ╰╴ ─ hover
3155 ");
3156 }
3157
3158 #[test]
3159 fn hover_on_drop_routine_function() {
3160 assert_snapshot!(check_hover("
3161create function foo() returns int as $$ select 1 $$ language sql;
3162drop routine foo$0();
3163"), @r"
3164 hover: function public.foo() returns int
3165 ╭▸
3166 3 │ drop routine foo();
3167 ╰╴ ─ hover
3168 ");
3169 }
3170
3171 #[test]
3172 fn hover_on_drop_routine_aggregate() {
3173 assert_snapshot!(check_hover("
3174create aggregate myavg(int) (sfunc = int4_avg_accum, stype = _int8);
3175drop routine myavg$0(int);
3176"), @r"
3177 hover: aggregate public.myavg(int)
3178 ╭▸
3179 3 │ drop routine myavg(int);
3180 ╰╴ ─ hover
3181 ");
3182 }
3183
3184 #[test]
3185 fn hover_on_drop_routine_procedure() {
3186 assert_snapshot!(check_hover("
3187create procedure foo() language sql as $$ select 1 $$;
3188drop routine foo$0();
3189"), @r"
3190 hover: procedure public.foo()
3191 ╭▸
3192 3 │ drop routine foo();
3193 ╰╴ ─ hover
3194 ");
3195 }
3196
3197 #[test]
3198 fn hover_on_drop_routine_with_schema() {
3199 assert_snapshot!(check_hover("
3200set search_path to public;
3201create function foo() returns int as $$ select 1 $$ language sql;
3202drop routine public.foo$0();
3203"), @r"
3204 hover: function public.foo() returns int
3205 ╭▸
3206 4 │ drop routine public.foo();
3207 ╰╴ ─ hover
3208 ");
3209 }
3210
3211 #[test]
3212 fn hover_on_drop_routine_with_search_path() {
3213 assert_snapshot!(check_hover(r#"
3214set search_path to myschema;
3215create function foo() returns int as $$ select 1 $$ language sql;
3216drop routine foo$0();
3217"#), @r"
3218 hover: function myschema.foo() returns int
3219 ╭▸
3220 4 │ drop routine foo();
3221 ╰╴ ─ hover
3222 ");
3223 }
3224
3225 #[test]
3226 fn hover_on_drop_routine_overloaded() {
3227 assert_snapshot!(check_hover("
3228create function add(complex) returns complex as $$ select null $$ language sql;
3229create function add(bigint) returns bigint as $$ select 1 $$ language sql;
3230drop routine add$0(complex);
3231"), @r"
3232 hover: function public.add(complex) returns complex
3233 ╭▸
3234 4 │ drop routine add(complex);
3235 ╰╴ ─ hover
3236 ");
3237 }
3238
3239 #[test]
3240 fn hover_on_drop_routine_prefers_function_over_procedure() {
3241 assert_snapshot!(check_hover("
3242create function foo() returns int as $$ select 1 $$ language sql;
3243create procedure foo() language sql as $$ select 1 $$;
3244drop routine foo$0();
3245"), @r"
3246 hover: function public.foo() returns int
3247 ╭▸
3248 4 │ drop routine foo();
3249 ╰╴ ─ hover
3250 ");
3251 }
3252
3253 #[test]
3254 fn hover_on_drop_routine_prefers_aggregate_over_procedure() {
3255 assert_snapshot!(check_hover("
3256create aggregate foo(int) (sfunc = int4_avg_accum, stype = _int8);
3257create procedure foo(int) language sql as $$ select 1 $$;
3258drop routine foo$0(int);
3259"), @r"
3260 hover: aggregate public.foo(int)
3261 ╭▸
3262 4 │ drop routine foo(int);
3263 ╰╴ ─ hover
3264 ");
3265 }
3266
3267 #[test]
3268 fn hover_on_update_table() {
3269 assert_snapshot!(check_hover("
3270create table users(id int, email text);
3271update users$0 set email = 'new@example.com';
3272"), @r"
3273 hover: table public.users(id int, email text)
3274 ╭▸
3275 3 │ update users set email = 'new@example.com';
3276 ╰╴ ─ hover
3277 ");
3278 }
3279
3280 #[test]
3281 fn hover_on_update_table_with_schema() {
3282 assert_snapshot!(check_hover("
3283create table public.users(id int, email text);
3284update public.users$0 set email = 'new@example.com';
3285"), @r"
3286 hover: table public.users(id int, email text)
3287 ╭▸
3288 3 │ update public.users set email = 'new@example.com';
3289 ╰╴ ─ hover
3290 ");
3291 }
3292
3293 #[test]
3294 fn hover_on_update_set_column() {
3295 assert_snapshot!(check_hover("
3296create table users(id int, email text);
3297update users set email$0 = 'new@example.com' where id = 1;
3298"), @r"
3299 hover: column public.users.email text
3300 ╭▸
3301 3 │ update users set email = 'new@example.com' where id = 1;
3302 ╰╴ ─ hover
3303 ");
3304 }
3305
3306 #[test]
3307 fn hover_on_update_set_column_with_schema() {
3308 assert_snapshot!(check_hover("
3309create table public.users(id int, email text);
3310update public.users set email$0 = 'new@example.com' where id = 1;
3311"), @r"
3312 hover: column public.users.email text
3313 ╭▸
3314 3 │ update public.users set email = 'new@example.com' where id = 1;
3315 ╰╴ ─ hover
3316 ");
3317 }
3318
3319 #[test]
3320 fn hover_on_update_where_column() {
3321 assert_snapshot!(check_hover("
3322create table users(id int, email text);
3323update users set email = 'new@example.com' where id$0 = 1;
3324"), @r"
3325 hover: column public.users.id int
3326 ╭▸
3327 3 │ update users set email = 'new@example.com' where id = 1;
3328 ╰╴ ─ hover
3329 ");
3330 }
3331
3332 #[test]
3333 fn hover_on_update_where_column_with_schema() {
3334 assert_snapshot!(check_hover("
3335create table public.users(id int, email text);
3336update public.users set email = 'new@example.com' where id$0 = 1;
3337"), @r"
3338 hover: column public.users.id int
3339 ╭▸
3340 3 │ update public.users set email = 'new@example.com' where id = 1;
3341 ╰╴ ─ hover
3342 ");
3343 }
3344
3345 #[test]
3346 fn hover_on_update_from_table() {
3347 assert_snapshot!(check_hover("
3348create table users(id int, email text);
3349create table messages(id int, user_id int, email text);
3350update users set email = messages.email from messages$0 where users.id = messages.user_id;
3351"), @r"
3352 hover: table public.messages(id int, user_id int, email text)
3353 ╭▸
3354 4 │ update users set email = messages.email from messages where users.id = messages.user_id;
3355 ╰╴ ─ hover
3356 ");
3357 }
3358
3359 #[test]
3360 fn hover_on_update_from_table_with_schema() {
3361 assert_snapshot!(check_hover("
3362create table users(id int, email text);
3363create table public.messages(id int, user_id int, email text);
3364update users set email = messages.email from public.messages$0 where users.id = messages.user_id;
3365"), @r"
3366 hover: table public.messages(id int, user_id int, email text)
3367 ╭▸
3368 4 │ update users set email = messages.email from public.messages where users.id = messages.user_id;
3369 ╰╴ ─ hover
3370 ");
3371 }
3372
3373 #[test]
3374 fn hover_on_update_with_cte_table() {
3375 assert_snapshot!(check_hover("
3376create table users(id int, email text);
3377with new_data as (
3378 select 1 as id, 'new@example.com' as email
3379)
3380update users set email = new_data.email from new_data$0 where users.id = new_data.id;
3381"), @r"
3382 hover: with new_data as (select 1 as id, 'new@example.com' as email)
3383 ╭▸
3384 6 │ update users set email = new_data.email from new_data where users.id = new_data.id;
3385 ╰╴ ─ hover
3386 ");
3387 }
3388
3389 #[test]
3390 fn hover_on_update_with_cte_column_in_set() {
3391 assert_snapshot!(check_hover("
3392create table users(id int, email text);
3393with new_data as (
3394 select 1 as id, 'new@example.com' as email
3395)
3396update users set email = new_data.email$0 from new_data where users.id = new_data.id;
3397"), @r"
3398 hover: column new_data.email
3399 ╭▸
3400 6 │ update users set email = new_data.email from new_data where users.id = new_data.id;
3401 ╰╴ ─ hover
3402 ");
3403 }
3404
3405 #[test]
3406 fn hover_on_update_with_cte_column_in_where() {
3407 assert_snapshot!(check_hover("
3408create table users(id int, email text);
3409with new_data as (
3410 select 1 as id, 'new@example.com' as email
3411)
3412update users set email = new_data.email from new_data where new_data.id$0 = users.id;
3413"), @r"
3414 hover: column new_data.id
3415 ╭▸
3416 6 │ update users set email = new_data.email from new_data where new_data.id = users.id;
3417 ╰╴ ─ hover
3418 ");
3419 }
3420
3421 #[test]
3422 fn hover_on_create_view_definition() {
3423 assert_snapshot!(check_hover("
3424create view v$0 as select 1;
3425"), @r"
3426 hover: view public.v as select 1
3427 ╭▸
3428 2 │ create view v as select 1;
3429 ╰╴ ─ hover
3430 ");
3431 }
3432
3433 #[test]
3434 fn hover_on_create_view_definition_with_schema() {
3435 assert_snapshot!(check_hover("
3436create view myschema.v$0 as select 1;
3437"), @r"
3438 hover: view myschema.v as select 1
3439 ╭▸
3440 2 │ create view myschema.v as select 1;
3441 ╰╴ ─ hover
3442 ");
3443 }
3444
3445 #[test]
3446 fn hover_on_create_temp_view_definition() {
3447 assert_snapshot!(check_hover("
3448create temp view v$0 as select 1;
3449"), @r"
3450 hover: view pg_temp.v as select 1
3451 ╭▸
3452 2 │ create temp view v as select 1;
3453 ╰╴ ─ hover
3454 ");
3455 }
3456
3457 #[test]
3458 fn hover_on_create_view_with_column_list() {
3459 assert_snapshot!(check_hover("
3460create view v(col1$0) as select 1;
3461"), @r"
3462 hover: column public.v.col1
3463 ╭▸
3464 2 │ create view v(col1) as select 1;
3465 ╰╴ ─ hover
3466 ");
3467 }
3468
3469 #[test]
3470 fn hover_on_select_from_view() {
3471 assert_snapshot!(check_hover("
3472create view v as select 1;
3473select * from v$0;
3474"), @r"
3475 hover: view public.v as select 1
3476 ╭▸
3477 3 │ select * from v;
3478 ╰╴ ─ hover
3479 ");
3480 }
3481
3482 #[test]
3483 fn hover_on_select_column_from_view_column_list() {
3484 assert_snapshot!(check_hover("
3485create view v(a) as select 1;
3486select a$0 from v;
3487"), @r"
3488 hover: column public.v.a
3489 ╭▸
3490 3 │ select a from v;
3491 ╰╴ ─ hover
3492 ");
3493 }
3494
3495 #[test]
3496 fn hover_on_select_column_from_view_column_list_overrides_target() {
3497 assert_snapshot!(check_hover("
3498create view v(a) as select 1, 2 b;
3499select a, b$0 from v;
3500"), @r"
3501 hover: column public.v.b
3502 ╭▸
3503 3 │ select a, b from v;
3504 ╰╴ ─ hover
3505 ");
3506 }
3507
3508 #[test]
3509 fn hover_on_select_column_from_view_target_list() {
3510 assert_snapshot!(check_hover("
3511create view v as select 1 a, 2 b;
3512select a$0, b from v;
3513"), @r"
3514 hover: column public.v.a
3515 ╭▸
3516 3 │ select a, b from v;
3517 ╰╴ ─ hover
3518 ");
3519 }
3520
3521 #[test]
3522 fn hover_on_select_from_view_with_schema() {
3523 assert_snapshot!(check_hover("
3524create view myschema.v as select 1;
3525select * from myschema.v$0;
3526"), @r"
3527 hover: view myschema.v as select 1
3528 ╭▸
3529 3 │ select * from myschema.v;
3530 ╰╴ ─ hover
3531 ");
3532 }
3533
3534 #[test]
3535 fn hover_on_drop_view() {
3536 assert_snapshot!(check_hover("
3537create view v as select 1;
3538drop view v$0;
3539"), @r"
3540 hover: view public.v as select 1
3541 ╭▸
3542 3 │ drop view v;
3543 ╰╴ ─ hover
3544 ");
3545 }
3546
3547 #[test]
3548 fn hover_composite_type_field() {
3549 assert_snapshot!(check_hover("
3550create type person_info as (name varchar(50), age int);
3551with team as (
3552 select 1 as id, ('Alice', 30)::person_info as member
3553)
3554select (member).name$0, (member).age from team;
3555"), @r"
3556 hover: field public.person_info.name varchar(50)
3557 ╭▸
3558 6 │ select (member).name, (member).age from team;
3559 ╰╴ ─ hover
3560 ");
3561 }
3562
3563 #[test]
3564 fn hover_composite_type_field_age() {
3565 assert_snapshot!(check_hover("
3566create type person_info as (name varchar(50), age int);
3567with team as (
3568 select 1 as id, ('Alice', 30)::person_info as member
3569)
3570select (member).name, (member).age$0 from team;
3571"), @r"
3572 hover: field public.person_info.age int
3573 ╭▸
3574 6 │ select (member).name, (member).age from team;
3575 ╰╴ ─ hover
3576 ");
3577 }
3578
3579 #[test]
3580 fn hover_composite_type_field_nested_parens() {
3581 assert_snapshot!(check_hover("
3582create type person_info as (name varchar(50), age int);
3583with team as (
3584 select 1 as id, ('Alice', 30)::person_info as member
3585)
3586select ((((member))).name$0) from team;
3587"), @r"
3588 hover: field public.person_info.name varchar(50)
3589 ╭▸
3590 6 │ select ((((member))).name) from team;
3591 ╰╴ ─ hover
3592 ");
3593 }
3594
3595 #[test]
3596 fn hover_on_join_using_column() {
3597 assert_snapshot!(check_hover("
3598create table t(id int);
3599create table u(id int);
3600select * from t join u using (id$0);
3601"), @r"
3602 hover: column public.t.id int
3603 column public.u.id int
3604 ╭▸
3605 4 │ select * from t join u using (id);
3606 ╰╴ ─ hover
3607 ");
3608 }
3609
3610 #[test]
3611 fn hover_on_truncate_table() {
3612 assert_snapshot!(check_hover("
3613create table users(id int, email text);
3614truncate table users$0;
3615"), @r"
3616 hover: table public.users(id int, email text)
3617 ╭▸
3618 3 │ truncate table users;
3619 ╰╴ ─ hover
3620 ");
3621 }
3622
3623 #[test]
3624 fn hover_on_truncate_table_without_table_keyword() {
3625 assert_snapshot!(check_hover("
3626create table users(id int, email text);
3627truncate users$0;
3628"), @r"
3629 hover: table public.users(id int, email text)
3630 ╭▸
3631 3 │ truncate users;
3632 ╰╴ ─ hover
3633 ");
3634 }
3635
3636 #[test]
3637 fn hover_on_lock_table() {
3638 assert_snapshot!(check_hover("
3639create table users(id int, email text);
3640lock table users$0;
3641"), @r"
3642 hover: table public.users(id int, email text)
3643 ╭▸
3644 3 │ lock table users;
3645 ╰╴ ─ hover
3646 ");
3647 }
3648
3649 #[test]
3650 fn hover_on_lock_table_without_table_keyword() {
3651 assert_snapshot!(check_hover("
3652create table users(id int, email text);
3653lock users$0;
3654"), @r"
3655 hover: table public.users(id int, email text)
3656 ╭▸
3657 3 │ lock users;
3658 ╰╴ ─ hover
3659 ");
3660 }
3661
3662 #[test]
3663 fn hover_on_vacuum_table() {
3664 assert_snapshot!(check_hover("
3665create table users(id int, email text);
3666vacuum users$0;
3667"), @r"
3668 hover: table public.users(id int, email text)
3669 ╭▸
3670 3 │ vacuum users;
3671 ╰╴ ─ hover
3672 ");
3673 }
3674
3675 #[test]
3676 fn hover_on_vacuum_with_analyze() {
3677 assert_snapshot!(check_hover("
3678create table users(id int, email text);
3679vacuum analyze users$0;
3680"), @r"
3681 hover: table public.users(id int, email text)
3682 ╭▸
3683 3 │ vacuum analyze users;
3684 ╰╴ ─ hover
3685 ");
3686 }
3687
3688 #[test]
3689 fn hover_on_alter_table() {
3690 assert_snapshot!(check_hover("
3691create table users(id int, email text);
3692alter table users$0 alter email set not null;
3693"), @r"
3694 hover: table public.users(id int, email text)
3695 ╭▸
3696 3 │ alter table users alter email set not null;
3697 ╰╴ ─ hover
3698 ");
3699 }
3700
3701 #[test]
3702 fn hover_on_alter_table_column() {
3703 assert_snapshot!(check_hover("
3704create table users(id int, email text);
3705alter table users alter email$0 set not null;
3706"), @r"
3707 hover: column public.users.email text
3708 ╭▸
3709 3 │ alter table users alter email set not null;
3710 ╰╴ ─ hover
3711 ");
3712 }
3713
3714 #[test]
3715 fn hover_on_refresh_materialized_view() {
3716 assert_snapshot!(check_hover("
3717create materialized view mv as select 1;
3718refresh materialized view mv$0;
3719"), @r"
3720 hover: materialized view public.mv as select 1
3721 ╭▸
3722 3 │ refresh materialized view mv;
3723 ╰╴ ─ hover
3724 ");
3725 }
3726
3727 #[test]
3728 fn hover_on_reindex_table() {
3729 assert_snapshot!(check_hover("
3730create table users(id int);
3731reindex table users$0;
3732"), @r"
3733 hover: table public.users(id int)
3734 ╭▸
3735 3 │ reindex table users;
3736 ╰╴ ─ hover
3737 ");
3738 }
3739
3740 #[test]
3741 fn hover_on_reindex_index() {
3742 assert_snapshot!(check_hover("
3743create table t(c int);
3744create index idx on t(c);
3745reindex index idx$0;
3746"), @r"
3747 hover: index public.idx on public.t(c)
3748 ╭▸
3749 4 │ reindex index idx;
3750 ╰╴ ─ hover
3751 ");
3752 }
3753
3754 #[test]
3755 fn hover_merge_returning_star_from_cte() {
3756 assert_snapshot!(check_hover("
3757create table t(a int, b int);
3758with u(x, y) as (
3759 select 1, 2
3760),
3761merged as (
3762 merge into t
3763 using u
3764 on t.a = u.x
3765 when matched then
3766 do nothing
3767 when not matched then
3768 do nothing
3769 returning a as x, b as y
3770)
3771select *$0 from merged;
3772"), @r"
3773 hover: column merged.x
3774 column merged.y
3775 ╭▸
3776 16 │ select * from merged;
3777 ╰╴ ─ hover
3778 ");
3779 }
3780
3781 #[test]
3782 fn hover_update_returning_star() {
3783 assert_snapshot!(check_hover("
3784create table t(a int, b int);
3785update t set a = 1
3786returning *$0;
3787"), @r"
3788 hover: column public.t.a int
3789 column public.t.b int
3790 ╭▸
3791 4 │ returning *;
3792 ╰╴ ─ hover
3793 ");
3794 }
3795
3796 #[test]
3797 fn hover_insert_returning_star() {
3798 assert_snapshot!(check_hover("
3799create table t(a int, b int);
3800insert into t values (1, 2)
3801returning *$0;
3802"), @r"
3803 hover: column public.t.a int
3804 column public.t.b int
3805 ╭▸
3806 4 │ returning *;
3807 ╰╴ ─ hover
3808 ");
3809 }
3810
3811 #[test]
3812 fn hover_delete_returning_star() {
3813 assert_snapshot!(check_hover("
3814create table t(a int, b int);
3815delete from t
3816returning *$0;
3817"), @r"
3818 hover: column public.t.a int
3819 column public.t.b int
3820 ╭▸
3821 4 │ returning *;
3822 ╰╴ ─ hover
3823 ");
3824 }
3825
3826 #[test]
3827 fn hover_merge_returning_star() {
3828 assert_snapshot!(check_hover("
3829create table t(a int, b int);
3830merge into t
3831 using (select 1 as x, 2 as y) u
3832 on t.a = u.x
3833 when matched then
3834 do nothing
3835returning *$0;
3836"), @r"
3837 hover: column public.t.a int
3838 column public.t.b int
3839 ╭▸
3840 8 │ returning *;
3841 ╰╴ ─ hover
3842 ");
3843 }
3844
3845 #[test]
3846 fn hover_merge_returning_qualified_star_old() {
3847 assert_snapshot!(check_hover("
3848create table t(a int, b int);
3849merge into t
3850 using (select 1 as x, 2 as y) u
3851 on t.a = u.x
3852 when matched then
3853 update set a = 99
3854returning old$0.*;
3855"), @r"
3856 hover: table public.t(a int, b int)
3857 ╭▸
3858 8 │ returning old.*;
3859 ╰╴ ─ hover
3860 ");
3861 }
3862
3863 #[test]
3864 fn hover_merge_returning_qualified_star_new() {
3865 assert_snapshot!(check_hover("
3866create table t(a int, b int);
3867merge into t
3868 using (select 1 as x, 2 as y) u
3869 on t.a = u.x
3870 when matched then
3871 update set a = 99
3872returning new$0.*;
3873"), @r"
3874 hover: table public.t(a int, b int)
3875 ╭▸
3876 8 │ returning new.*;
3877 ╰╴ ─ hover
3878 ");
3879 }
3880
3881 #[test]
3882 fn hover_merge_returning_qualified_star_table() {
3883 assert_snapshot!(check_hover("
3884create table t(a int, b int);
3885merge into t
3886 using (select 1 as x, 2 as y) u
3887 on t.a = u.x
3888 when matched then
3889 update set a = 99
3890returning t$0.*;
3891"), @r"
3892 hover: table public.t(a int, b int)
3893 ╭▸
3894 8 │ returning t.*;
3895 ╰╴ ─ hover
3896 ");
3897 }
3898
3899 #[test]
3900 fn hover_merge_returning_qualified_star_old_on_star() {
3901 assert_snapshot!(check_hover("
3902create table t(a int, b int);
3903merge into t
3904 using (select 1 as x, 2 as y) u
3905 on t.a = u.x
3906 when matched then
3907 update set a = 99
3908returning old.*$0;
3909"), @r"
3910 hover: column public.t.a int
3911 column public.t.b int
3912 ╭▸
3913 8 │ returning old.*;
3914 ╰╴ ─ hover
3915 ");
3916 }
3917
3918 #[test]
3919 fn hover_merge_returning_qualified_star_new_on_star() {
3920 assert_snapshot!(check_hover("
3921create table t(a int, b int);
3922merge into t
3923 using (select 1 as x, 2 as y) u
3924 on t.a = u.x
3925 when matched then
3926 update set a = 99
3927returning new.*$0;
3928"), @r"
3929 hover: column public.t.a int
3930 column public.t.b int
3931 ╭▸
3932 8 │ returning new.*;
3933 ╰╴ ─ hover
3934 ");
3935 }
3936
3937 #[test]
3938 fn hover_merge_returning_qualified_star_table_on_star() {
3939 assert_snapshot!(check_hover("
3940create table t(a int, b int);
3941merge into t
3942 using (select 1 as x, 2 as y) u
3943 on t.a = u.x
3944 when matched then
3945 update set a = 99
3946returning t.*$0;
3947"), @r"
3948 hover: column public.t.a int
3949 column public.t.b int
3950 ╭▸
3951 8 │ returning t.*;
3952 ╰╴ ─ hover
3953 ");
3954 }
3955
3956 #[test]
3957 fn hover_partition_table_column() {
3958 assert_snapshot!(check_hover("
3959create table part (
3960 a int,
3961 inserted_at timestamptz not null default now()
3962) partition by range (inserted_at);
3963create table part_2026_01_02 partition of part
3964 for values from ('2026-01-02') to ('2026-01-03');
3965select a$0 from part_2026_01_02;
3966"), @r"
3967 hover: column public.part.a int
3968 ╭▸
3969 8 │ select a from part_2026_01_02;
3970 ╰╴ ─ hover
3971 ");
3972 }
3973
3974 #[test]
3975 fn hover_create_table_like_multi_star() {
3976 assert_snapshot!(check_hover("
3977create table t(a int, b int);
3978create table u(x int, y int);
3979create table k(like t, like u, c int);
3980select *$0 from k;
3981"), @r"
3982 hover: column public.k.a int
3983 column public.k.b int
3984 column public.k.x int
3985 column public.k.y int
3986 column public.k.c int
3987 ╭▸
3988 5 │ select * from k;
3989 ╰╴ ─ hover
3990 ");
3991 }
3992
3993 #[test]
3994 fn hover_create_table_inherits_star() {
3995 assert_snapshot!(check_hover("
3996create table t (
3997 a int, b text
3998);
3999create table u (
4000 c int
4001) inherits (t);
4002select *$0 from u;
4003"), @r"
4004 hover: column public.u.a int
4005 column public.u.b text
4006 column public.u.c int
4007 ╭▸
4008 8 │ select * from u;
4009 ╰╴ ─ hover
4010 ");
4011 }
4012
4013 #[test]
4014 fn hover_create_table_inherits_column() {
4015 assert_snapshot!(check_hover("
4016create table t (
4017 a int, b text
4018);
4019create table u (
4020 c int
4021) inherits (t);
4022select a$0 from u;
4023"), @r"
4024 hover: column public.t.a int
4025 ╭▸
4026 8 │ select a from u;
4027 ╰╴ ─ hover
4028 ");
4029 }
4030
4031 #[test]
4032 fn hover_create_table_inherits_local_column() {
4033 assert_snapshot!(check_hover("
4034create table t (
4035 a int, b text
4036);
4037create table u (
4038 c int
4039) inherits (t);
4040select c$0 from u;
4041"), @r"
4042 hover: column public.u.c int
4043 ╭▸
4044 8 │ select c from u;
4045 ╰╴ ─ hover
4046 ");
4047 }
4048
4049 #[test]
4050 fn hover_create_table_inherits_multiple_parents() {
4051 assert_snapshot!(check_hover("
4052create table t1 (
4053 a int
4054);
4055create table t2 (
4056 b text
4057);
4058create table u (
4059 c int
4060) inherits (t1, t2);
4061select b$0 from u;
4062"), @r"
4063 hover: column public.t2.b text
4064 ╭▸
4065 11 │ select b from u;
4066 ╰╴ ─ hover
4067 ");
4068 }
4069
4070 #[test]
4071 fn hover_create_foreign_table_inherits_column() {
4072 assert_snapshot!(check_hover("
4073create server myserver foreign data wrapper postgres_fdw;
4074create table t (
4075 a int, b text
4076);
4077create foreign table u (
4078 c int
4079) inherits (t) server myserver;
4080select a$0 from u;
4081"), @r"
4082 hover: column public.t.a int
4083 ╭▸
4084 9 │ select a from u;
4085 ╰╴ ─ hover
4086 ");
4087 }
4088
4089 #[test]
4090 fn hover_extension_on_create() {
4091 assert_snapshot!(check_hover("
4092create extension my$0ext;
4093"), @r"
4094 hover: extension myext
4095 ╭▸
4096 2 │ create extension myext;
4097 ╰╴ ─ hover
4098 ");
4099 }
4100
4101 #[test]
4102 fn hover_extension_on_drop() {
4103 assert_snapshot!(check_hover("
4104create extension myext;
4105drop extension my$0ext;
4106"), @r"
4107 hover: extension myext
4108 ╭▸
4109 3 │ drop extension myext;
4110 ╰╴ ─ hover
4111 ");
4112 }
4113
4114 #[test]
4115 fn hover_extension_on_alter() {
4116 assert_snapshot!(check_hover("
4117create extension myext;
4118alter extension my$0ext update to '2.0';
4119"), @r"
4120 hover: extension myext
4121 ╭▸
4122 3 │ alter extension myext update to '2.0';
4123 ╰╴ ─ hover
4124 ");
4125 }
4126
4127 #[test]
4128 fn hover_role_on_create() {
4129 assert_snapshot!(check_hover("
4130create role read$0er;
4131"), @r"
4132 hover: role reader
4133 ╭▸
4134 2 │ create role reader;
4135 ╰╴ ─ hover
4136 ");
4137 }
4138
4139 #[test]
4140 fn hover_role_on_alter() {
4141 assert_snapshot!(check_hover("
4142create role reader;
4143alter role read$0er rename to writer;
4144"), @r"
4145 hover: role reader
4146 ╭▸
4147 3 │ alter role reader rename to writer;
4148 ╰╴ ─ hover
4149 ");
4150 }
4151
4152 #[test]
4153 fn hover_role_on_drop() {
4154 assert_snapshot!(check_hover("
4155create role reader;
4156drop role read$0er;
4157"), @r"
4158 hover: role reader
4159 ╭▸
4160 3 │ drop role reader;
4161 ╰╴ ─ hover
4162 ");
4163 }
4164
4165 #[test]
4166 fn hover_role_on_set() {
4167 assert_snapshot!(check_hover("
4168create role reader;
4169set role read$0er;
4170"), @r"
4171 hover: role reader
4172 ╭▸
4173 3 │ set role reader;
4174 ╰╴ ─ hover
4175 ");
4176 }
4177
4178 #[test]
4179 fn hover_role_on_create_tablespace_owner() {
4180 assert_snapshot!(check_hover("
4181create role reader;
4182create tablespace t owner read$0er location 'foo';
4183"), @r"
4184 hover: role reader
4185 ╭▸
4186 3 │ create tablespace t owner reader location 'foo';
4187 ╰╴ ─ hover
4188 ");
4189 }
4190
4191 #[test]
4192 fn hover_on_fetch_cursor() {
4193 assert_snapshot!(check_hover("
4194declare c scroll cursor for select * from t;
4195fetch forward 5 from c$0;
4196"), @r"
4197 hover: cursor c for select * from t
4198 ╭▸
4199 3 │ fetch forward 5 from c;
4200 ╰╴ ─ hover
4201 ");
4202 }
4203
4204 #[test]
4205 fn hover_on_close_cursor() {
4206 assert_snapshot!(check_hover("
4207declare c scroll cursor for select * from t;
4208close c$0;
4209"), @r"
4210 hover: cursor c for select * from t
4211 ╭▸
4212 3 │ close c;
4213 ╰╴ ─ hover
4214 ");
4215 }
4216
4217 #[test]
4218 fn hover_on_move_cursor() {
4219 assert_snapshot!(check_hover("
4220declare c scroll cursor for select * from t;
4221move forward 10 from c$0;
4222"), @r"
4223 hover: cursor c for select * from t
4224 ╭▸
4225 3 │ move forward 10 from c;
4226 ╰╴ ─ hover
4227 ");
4228 }
4229
4230 #[test]
4231 fn hover_on_prepare_statement() {
4232 assert_snapshot!(check_hover("
4233prepare stmt$0 as select 1;
4234"), @r"
4235 hover: prepare stmt as select 1
4236 ╭▸
4237 2 │ prepare stmt as select 1;
4238 ╰╴ ─ hover
4239 ");
4240 }
4241
4242 #[test]
4243 fn hover_on_execute_prepared_statement() {
4244 assert_snapshot!(check_hover("
4245prepare stmt as select 1;
4246execute stmt$0;
4247"), @r"
4248 hover: prepare stmt as select 1
4249 ╭▸
4250 3 │ execute stmt;
4251 ╰╴ ─ hover
4252 ");
4253 }
4254
4255 #[test]
4256 fn hover_on_deallocate_prepared_statement() {
4257 assert_snapshot!(check_hover("
4258prepare stmt as select 1;
4259deallocate stmt$0;
4260"), @r"
4261 hover: prepare stmt as select 1
4262 ╭▸
4263 3 │ deallocate stmt;
4264 ╰╴ ─ hover
4265 ");
4266 }
4267
4268 #[test]
4269 fn hover_on_listen_definition() {
4270 assert_snapshot!(check_hover("
4271listen updates$0;
4272"), @r"
4273 hover: listen updates
4274 ╭▸
4275 2 │ listen updates;
4276 ╰╴ ─ hover
4277 ");
4278 }
4279
4280 #[test]
4281 fn hover_on_notify_channel() {
4282 assert_snapshot!(check_hover("
4283listen updates;
4284notify updates$0;
4285"), @r"
4286 hover: listen updates
4287 ╭▸
4288 3 │ notify updates;
4289 ╰╴ ─ hover
4290 ");
4291 }
4292
4293 #[test]
4294 fn hover_on_unlisten_channel() {
4295 assert_snapshot!(check_hover("
4296listen updates;
4297unlisten updates$0;
4298"), @r"
4299 hover: listen updates
4300 ╭▸
4301 3 │ unlisten updates;
4302 ╰╴ ─ hover
4303 ");
4304 }
4305}