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