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